diff --git a/Cargo.lock b/Cargo.lock index c903b1a44ec..43f948d7cf1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3237,7 +3237,7 @@ dependencies = [ [[package]] name = "grovedb" version = "6.1.1" -source = "git+https://github.com/dashpay/grovedb?rev=12adbd357522a03efad4ae609499c93fe8cc3e2c#12adbd357522a03efad4ae609499c93fe8cc3e2c" +source = "git+https://github.com/dashpay/grovedb?rev=0ea327d7260692bda575fd208b30be5fc2f511df#0ea327d7260692bda575fd208b30be5fc2f511df" dependencies = [ "axum 0.8.9", "blake3", @@ -3296,7 +3296,7 @@ dependencies = [ [[package]] name = "grovedb-bulk-append-tree" version = "6.1.1" -source = "git+https://github.com/dashpay/grovedb?rev=12adbd357522a03efad4ae609499c93fe8cc3e2c#12adbd357522a03efad4ae609499c93fe8cc3e2c" +source = "git+https://github.com/dashpay/grovedb?rev=0ea327d7260692bda575fd208b30be5fc2f511df#0ea327d7260692bda575fd208b30be5fc2f511df" dependencies = [ "blake3", "grovedb-bincode", @@ -3314,7 +3314,7 @@ dependencies = [ [[package]] name = "grovedb-commitment-tree" version = "6.1.1" -source = "git+https://github.com/dashpay/grovedb?rev=12adbd357522a03efad4ae609499c93fe8cc3e2c#12adbd357522a03efad4ae609499c93fe8cc3e2c" +source = "git+https://github.com/dashpay/grovedb?rev=0ea327d7260692bda575fd208b30be5fc2f511df#0ea327d7260692bda575fd208b30be5fc2f511df" dependencies = [ "blake3", "grovedb-bulk-append-tree", @@ -3331,7 +3331,7 @@ dependencies = [ [[package]] name = "grovedb-costs" version = "6.1.1" -source = "git+https://github.com/dashpay/grovedb?rev=12adbd357522a03efad4ae609499c93fe8cc3e2c#12adbd357522a03efad4ae609499c93fe8cc3e2c" +source = "git+https://github.com/dashpay/grovedb?rev=0ea327d7260692bda575fd208b30be5fc2f511df#0ea327d7260692bda575fd208b30be5fc2f511df" dependencies = [ "integer-encoding", "intmap", @@ -3341,7 +3341,7 @@ dependencies = [ [[package]] name = "grovedb-dense-fixed-sized-merkle-tree" version = "6.1.1" -source = "git+https://github.com/dashpay/grovedb?rev=12adbd357522a03efad4ae609499c93fe8cc3e2c#12adbd357522a03efad4ae609499c93fe8cc3e2c" +source = "git+https://github.com/dashpay/grovedb?rev=0ea327d7260692bda575fd208b30be5fc2f511df#0ea327d7260692bda575fd208b30be5fc2f511df" dependencies = [ "blake3", "grovedb-bincode", @@ -3355,7 +3355,7 @@ dependencies = [ [[package]] name = "grovedb-element" version = "6.1.1" -source = "git+https://github.com/dashpay/grovedb?rev=12adbd357522a03efad4ae609499c93fe8cc3e2c#12adbd357522a03efad4ae609499c93fe8cc3e2c" +source = "git+https://github.com/dashpay/grovedb?rev=0ea327d7260692bda575fd208b30be5fc2f511df#0ea327d7260692bda575fd208b30be5fc2f511df" dependencies = [ "grovedb-bincode", "grovedb-bincode-derive", @@ -3371,7 +3371,7 @@ dependencies = [ [[package]] name = "grovedb-epoch-based-storage-flags" version = "6.1.1" -source = "git+https://github.com/dashpay/grovedb?rev=12adbd357522a03efad4ae609499c93fe8cc3e2c#12adbd357522a03efad4ae609499c93fe8cc3e2c" +source = "git+https://github.com/dashpay/grovedb?rev=0ea327d7260692bda575fd208b30be5fc2f511df#0ea327d7260692bda575fd208b30be5fc2f511df" dependencies = [ "grovedb-costs", "hex", @@ -3383,7 +3383,7 @@ dependencies = [ [[package]] name = "grovedb-merk" version = "6.1.1" -source = "git+https://github.com/dashpay/grovedb?rev=12adbd357522a03efad4ae609499c93fe8cc3e2c#12adbd357522a03efad4ae609499c93fe8cc3e2c" +source = "git+https://github.com/dashpay/grovedb?rev=0ea327d7260692bda575fd208b30be5fc2f511df#0ea327d7260692bda575fd208b30be5fc2f511df" dependencies = [ "blake3", "byteorder", @@ -3409,7 +3409,7 @@ dependencies = [ [[package]] name = "grovedb-merkle-mountain-range" version = "6.1.1" -source = "git+https://github.com/dashpay/grovedb?rev=12adbd357522a03efad4ae609499c93fe8cc3e2c#12adbd357522a03efad4ae609499c93fe8cc3e2c" +source = "git+https://github.com/dashpay/grovedb?rev=0ea327d7260692bda575fd208b30be5fc2f511df#0ea327d7260692bda575fd208b30be5fc2f511df" dependencies = [ "blake3", "grovedb-bincode", @@ -3422,7 +3422,7 @@ dependencies = [ [[package]] name = "grovedb-path" version = "6.1.1" -source = "git+https://github.com/dashpay/grovedb?rev=12adbd357522a03efad4ae609499c93fe8cc3e2c#12adbd357522a03efad4ae609499c93fe8cc3e2c" +source = "git+https://github.com/dashpay/grovedb?rev=0ea327d7260692bda575fd208b30be5fc2f511df#0ea327d7260692bda575fd208b30be5fc2f511df" dependencies = [ "hex", ] @@ -3430,7 +3430,7 @@ dependencies = [ [[package]] name = "grovedb-private-document-store" version = "6.1.1" -source = "git+https://github.com/dashpay/grovedb?rev=12adbd357522a03efad4ae609499c93fe8cc3e2c#12adbd357522a03efad4ae609499c93fe8cc3e2c" +source = "git+https://github.com/dashpay/grovedb?rev=0ea327d7260692bda575fd208b30be5fc2f511df#0ea327d7260692bda575fd208b30be5fc2f511df" dependencies = [ "blake3", "grovedb-bulk-append-tree", @@ -3443,7 +3443,7 @@ dependencies = [ [[package]] name = "grovedb-query" version = "6.1.1" -source = "git+https://github.com/dashpay/grovedb?rev=12adbd357522a03efad4ae609499c93fe8cc3e2c#12adbd357522a03efad4ae609499c93fe8cc3e2c" +source = "git+https://github.com/dashpay/grovedb?rev=0ea327d7260692bda575fd208b30be5fc2f511df#0ea327d7260692bda575fd208b30be5fc2f511df" dependencies = [ "byteorder", "ed", @@ -3459,7 +3459,7 @@ dependencies = [ [[package]] name = "grovedb-storage" version = "6.1.1" -source = "git+https://github.com/dashpay/grovedb?rev=12adbd357522a03efad4ae609499c93fe8cc3e2c#12adbd357522a03efad4ae609499c93fe8cc3e2c" +source = "git+https://github.com/dashpay/grovedb?rev=0ea327d7260692bda575fd208b30be5fc2f511df#0ea327d7260692bda575fd208b30be5fc2f511df" dependencies = [ "blake3", "grovedb-costs", @@ -3478,7 +3478,7 @@ dependencies = [ [[package]] name = "grovedb-version" version = "6.1.1" -source = "git+https://github.com/dashpay/grovedb?rev=12adbd357522a03efad4ae609499c93fe8cc3e2c#12adbd357522a03efad4ae609499c93fe8cc3e2c" +source = "git+https://github.com/dashpay/grovedb?rev=0ea327d7260692bda575fd208b30be5fc2f511df#0ea327d7260692bda575fd208b30be5fc2f511df" dependencies = [ "thiserror 2.0.18", "versioned-feature-core", @@ -3487,7 +3487,7 @@ dependencies = [ [[package]] name = "grovedb-visualize" version = "6.1.1" -source = "git+https://github.com/dashpay/grovedb?rev=12adbd357522a03efad4ae609499c93fe8cc3e2c#12adbd357522a03efad4ae609499c93fe8cc3e2c" +source = "git+https://github.com/dashpay/grovedb?rev=0ea327d7260692bda575fd208b30be5fc2f511df#0ea327d7260692bda575fd208b30be5fc2f511df" dependencies = [ "hex", "itertools 0.14.0", @@ -3496,7 +3496,7 @@ dependencies = [ [[package]] name = "grovedbg-types" version = "6.1.1" -source = "git+https://github.com/dashpay/grovedb?rev=12adbd357522a03efad4ae609499c93fe8cc3e2c#12adbd357522a03efad4ae609499c93fe8cc3e2c" +source = "git+https://github.com/dashpay/grovedb?rev=0ea327d7260692bda575fd208b30be5fc2f511df#0ea327d7260692bda575fd208b30be5fc2f511df" dependencies = [ "serde", "serde_with 3.21.0", diff --git a/Cargo.toml b/Cargo.toml index 6da85829926..153a356fb65 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,15 +61,15 @@ members = [ [workspace.dependencies] secp256k1 = { version = "=0.33.1", features = ["rand", "serde", "recovery"] } bincode = { package = "grovedb-bincode", version = "=2.1.0" } -grovedb = { git = "https://github.com/dashpay/grovedb", rev = "12adbd357522a03efad4ae609499c93fe8cc3e2c", default-features = false } -grovedb-costs = { git = "https://github.com/dashpay/grovedb", rev = "12adbd357522a03efad4ae609499c93fe8cc3e2c" } -grovedb-merk = { git = "https://github.com/dashpay/grovedb", rev = "12adbd357522a03efad4ae609499c93fe8cc3e2c", default-features = false } -grovedb-path = { git = "https://github.com/dashpay/grovedb", rev = "12adbd357522a03efad4ae609499c93fe8cc3e2c" } -grovedb-query = { git = "https://github.com/dashpay/grovedb", rev = "12adbd357522a03efad4ae609499c93fe8cc3e2c" } -grovedb-storage = { git = "https://github.com/dashpay/grovedb", rev = "12adbd357522a03efad4ae609499c93fe8cc3e2c" } -grovedb-version = { git = "https://github.com/dashpay/grovedb", rev = "12adbd357522a03efad4ae609499c93fe8cc3e2c" } -grovedb-epoch-based-storage-flags = { git = "https://github.com/dashpay/grovedb", rev = "12adbd357522a03efad4ae609499c93fe8cc3e2c" } -grovedb-commitment-tree = { git = "https://github.com/dashpay/grovedb", rev = "12adbd357522a03efad4ae609499c93fe8cc3e2c" } +grovedb = { git = "https://github.com/dashpay/grovedb", rev = "0ea327d7260692bda575fd208b30be5fc2f511df", default-features = false } +grovedb-costs = { git = "https://github.com/dashpay/grovedb", rev = "0ea327d7260692bda575fd208b30be5fc2f511df" } +grovedb-merk = { git = "https://github.com/dashpay/grovedb", rev = "0ea327d7260692bda575fd208b30be5fc2f511df", default-features = false } +grovedb-path = { git = "https://github.com/dashpay/grovedb", rev = "0ea327d7260692bda575fd208b30be5fc2f511df" } +grovedb-query = { git = "https://github.com/dashpay/grovedb", rev = "0ea327d7260692bda575fd208b30be5fc2f511df" } +grovedb-storage = { git = "https://github.com/dashpay/grovedb", rev = "0ea327d7260692bda575fd208b30be5fc2f511df" } +grovedb-version = { git = "https://github.com/dashpay/grovedb", rev = "0ea327d7260692bda575fd208b30be5fc2f511df" } +grovedb-epoch-based-storage-flags = { git = "https://github.com/dashpay/grovedb", rev = "0ea327d7260692bda575fd208b30be5fc2f511df" } +grovedb-commitment-tree = { git = "https://github.com/dashpay/grovedb", rev = "0ea327d7260692bda575fd208b30be5fc2f511df" } dashcore = { git = "https://github.com/dashpay/rust-dashcore", rev = "c9aeac0d0dcbd4b91d780a70d61b9bb693199ca4" } dash-network-seeds = { git = "https://github.com/dashpay/rust-dashcore", rev = "c9aeac0d0dcbd4b91d780a70d61b9bb693199ca4" } dash-spv = { git = "https://github.com/dashpay/rust-dashcore", rev = "c9aeac0d0dcbd4b91d780a70d61b9bb693199ca4" } diff --git a/book/src/contract-keywords/history.md b/book/src/contract-keywords/history.md index 3129ea4f7c9..633aea129a9 100644 --- a/book/src/contract-keywords/history.md +++ b/book/src/contract-keywords/history.md @@ -1,6 +1,6 @@ # History -Platform can keep two kinds of history for a document type. `documentsKeepHistory` keeps every version of each document in Drive, under the document itself, so an application can read what a document said at any earlier time. The three `keeps*History` flags record events instead: each transfer, purchase or price update of a document becomes a record in the document history system contract, where it can be queried by document, by contract, by identity and by time. +Platform can keep two kinds of history for a document type. `documentsKeepHistory` keeps every version of each document in Drive, so an application can read what a document said at any earlier time. The three `keeps*History` flags record events instead: each transfer, purchase or price update of a document becomes a record in the document history system contract, where it can be queried by document, by contract, by identity and by time. ## `documentsKeepHistory` @@ -35,13 +35,28 @@ Every edit of a profile adds a version, and every earlier version stays readable ### How it works -- Each document is stored as a small tree of its own: every version the document has had, keyed by the block time it was written at, and a pointer to the current one. A query by id or through an index sees the current version. +- Through protocol version 14, each document is stored as a small tree of its own, with versions keyed by block time and a pointer to the current one. From protocol version 15, versions live in a separate history tree for the document type and retain both time and revision, including edits sharing a block time. A query by id or through an index sees the current version. - Every write that changes the document adds a version: a replace, and also a transfer, a price update or a purchase. - Nothing is ever removed. Drive refuses to delete a document whose type keeps history, so its owner's delete is refused (10404 from protocol version 14; before it, the delete failed inside Drive as an internal error), and the type can have neither moderator deletion nor a `ttl`. - The `getDocumentHistory` query returns a document's versions from a given time on, each with the block time it was written at, at most 10 per request, and with a proof when asked. - Every version stays stored, paid for by the write that added it. - A doctype-level sum or average (`documentsSummable`, `documentsAverageable`) counts only each document's current version. See [Counts, Sums and Averages](aggregates.md). +`getDocumentHistory` uses request and response version 0 through protocol version +14. Its `start_at_ms` is exclusive, `offset` skips entries, and response entries +contain `date` and document `value` bytes. Proved requests require an absent or +zero offset. + +From protocol version 15, the query accepts version 1 only. It requires exactly +one filter: inclusive `start_at_ms`, exclusive `start_after` with both time and +revision, inclusive `start_at_revision`, or exact `revision`. Unproved responses +carry entries with time, revision and document bytes, plus lifecycle metadata; +proved responses carry one signed proof object containing one GroveDB proof of +the page and lifecycle. +The Rust SDK and its WASM/JavaScript bindings send version 1 and require proofs. +On an updated node running protocol version 14 this returns the standard +unsupported-query-version error; the SDK does not fall back to version 0. + ### Rules at registration All refusals below are `InvalidContractStructure` (10231). diff --git a/packages/dapi-grpc/build.rs b/packages/dapi-grpc/build.rs index 21e2cf25e26..5c492638a04 100644 --- a/packages/dapi-grpc/build.rs +++ b/packages/dapi-grpc/build.rs @@ -291,11 +291,13 @@ fn configure_platform(mut platform: MappingConfig) -> MappingConfig { // - Bumping the matching `FeatureVersionBounds.max_version` // to 1 in `rs-platform-version`. // - Implementing the v1 dispatch arm in `drive-abci`. - const VERSIONED_AT_V1_REQUESTS: [&str; 2] = [ + const VERSIONED_AT_V1_REQUESTS: [&str; 3] = [ "GetDocumentsRequest", + "GetDocumentHistoryRequest", "GetIdentityByNonUniquePublicKeyHashRequest", ]; - const VERSIONED_AT_V1_RESPONSES: [&str; 1] = ["GetDocumentsResponse"]; + const VERSIONED_AT_V1_RESPONSES: [&str; 2] = + ["GetDocumentsResponse", "GetDocumentHistoryResponse"]; // Derive VersionedGrpcMessage on requests for msg in VERSIONED_REQUESTS { 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 1a25257c154..3ab379dc642 100644 --- a/packages/dapi-grpc/clients/drive/v0/nodejs/drive_pbjs.js +++ b/packages/dapi-grpc/clients/drive/v0/nodejs/drive_pbjs.js @@ -52394,6 +52394,7 @@ $root.org = (function() { * @memberof org.dash.platform.dapi.v0 * @interface IGetDocumentHistoryRequest * @property {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.IGetDocumentHistoryRequestV0|null} [v0] GetDocumentHistoryRequest v0 + * @property {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.IGetDocumentHistoryRequestV1|null} [v1] GetDocumentHistoryRequest v1 */ /** @@ -52419,17 +52420,25 @@ $root.org = (function() { */ GetDocumentHistoryRequest.prototype.v0 = null; + /** + * GetDocumentHistoryRequest v1. + * @member {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.IGetDocumentHistoryRequestV1|null|undefined} v1 + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest + * @instance + */ + GetDocumentHistoryRequest.prototype.v1 = null; + // OneOf field names bound to virtual getters and setters var $oneOfFields; /** * GetDocumentHistoryRequest version. - * @member {"v0"|undefined} version + * @member {"v0"|"v1"|undefined} version * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest * @instance */ Object.defineProperty(GetDocumentHistoryRequest.prototype, "version", { - get: $util.oneOfGetter($oneOfFields = ["v0"]), + get: $util.oneOfGetter($oneOfFields = ["v0", "v1"]), set: $util.oneOfSetter($oneOfFields) }); @@ -52459,6 +52468,8 @@ $root.org = (function() { writer = $Writer.create(); if (message.v0 != null && Object.hasOwnProperty.call(message, "v0")) $root.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0.encode(message.v0, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); + if (message.v1 != null && Object.hasOwnProperty.call(message, "v1")) + $root.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.encode(message.v1, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); return writer; }; @@ -52496,6 +52507,9 @@ $root.org = (function() { case 1: message.v0 = $root.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0.decode(reader, reader.uint32()); break; + case 2: + message.v1 = $root.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.decode(reader, reader.uint32()); + break; default: reader.skipType(tag & 7); break; @@ -52540,6 +52554,16 @@ $root.org = (function() { return "v0." + error; } } + if (message.v1 != null && message.hasOwnProperty("v1")) { + if (properties.version === 1) + return "version: multiple values"; + properties.version = 1; + { + var error = $root.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.verify(message.v1); + if (error) + return "v1." + error; + } + } return null; }; @@ -52560,6 +52584,11 @@ $root.org = (function() { throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryRequest.v0: object expected"); message.v0 = $root.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0.fromObject(object.v0); } + if (object.v1 != null) { + if (typeof object.v1 !== "object") + throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryRequest.v1: object expected"); + message.v1 = $root.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.fromObject(object.v1); + } return message; }; @@ -52581,6 +52610,11 @@ $root.org = (function() { if (options.oneofs) object.version = "v0"; } + if (message.v1 != null && message.hasOwnProperty("v1")) { + object.v1 = $root.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.toObject(message.v1, options); + if (options.oneofs) + object.version = "v1"; + } return object; }; @@ -52957,237 +52991,32 @@ $root.org = (function() { return GetDocumentHistoryRequestV0; })(); - return GetDocumentHistoryRequest; - })(); - - v0.GetDocumentHistoryResponse = (function() { - - /** - * Properties of a GetDocumentHistoryResponse. - * @memberof org.dash.platform.dapi.v0 - * @interface IGetDocumentHistoryResponse - * @property {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.IGetDocumentHistoryResponseV0|null} [v0] GetDocumentHistoryResponse v0 - */ - - /** - * Constructs a new GetDocumentHistoryResponse. - * @memberof org.dash.platform.dapi.v0 - * @classdesc Represents a GetDocumentHistoryResponse. - * @implements IGetDocumentHistoryResponse - * @constructor - * @param {org.dash.platform.dapi.v0.IGetDocumentHistoryResponse=} [properties] Properties to set - */ - function GetDocumentHistoryResponse(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * GetDocumentHistoryResponse v0. - * @member {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.IGetDocumentHistoryResponseV0|null|undefined} v0 - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse - * @instance - */ - GetDocumentHistoryResponse.prototype.v0 = null; - - // OneOf field names bound to virtual getters and setters - var $oneOfFields; - - /** - * GetDocumentHistoryResponse version. - * @member {"v0"|undefined} version - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse - * @instance - */ - Object.defineProperty(GetDocumentHistoryResponse.prototype, "version", { - get: $util.oneOfGetter($oneOfFields = ["v0"]), - set: $util.oneOfSetter($oneOfFields) - }); - - /** - * Creates a new GetDocumentHistoryResponse instance using the specified properties. - * @function create - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse - * @static - * @param {org.dash.platform.dapi.v0.IGetDocumentHistoryResponse=} [properties] Properties to set - * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse} GetDocumentHistoryResponse instance - */ - GetDocumentHistoryResponse.create = function create(properties) { - return new GetDocumentHistoryResponse(properties); - }; - - /** - * Encodes the specified GetDocumentHistoryResponse message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.verify|verify} messages. - * @function encode - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse - * @static - * @param {org.dash.platform.dapi.v0.IGetDocumentHistoryResponse} message GetDocumentHistoryResponse message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - GetDocumentHistoryResponse.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.v0 != null && Object.hasOwnProperty.call(message, "v0")) - $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.encode(message.v0, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified GetDocumentHistoryResponse message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.verify|verify} messages. - * @function encodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse - * @static - * @param {org.dash.platform.dapi.v0.IGetDocumentHistoryResponse} message GetDocumentHistoryResponse message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - GetDocumentHistoryResponse.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a GetDocumentHistoryResponse message from the specified reader or buffer. - * @function decode - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse} GetDocumentHistoryResponse - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - GetDocumentHistoryResponse.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.v0 = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.decode(reader, reader.uint32()); - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a GetDocumentHistoryResponse message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse} GetDocumentHistoryResponse - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - GetDocumentHistoryResponse.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a GetDocumentHistoryResponse message. - * @function verify - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - GetDocumentHistoryResponse.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - var properties = {}; - if (message.v0 != null && message.hasOwnProperty("v0")) { - properties.version = 1; - { - var error = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.verify(message.v0); - if (error) - return "v0." + error; - } - } - return null; - }; - - /** - * Creates a GetDocumentHistoryResponse message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse - * @static - * @param {Object.} object Plain object - * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse} GetDocumentHistoryResponse - */ - GetDocumentHistoryResponse.fromObject = function fromObject(object) { - if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse) - return object; - var message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse(); - if (object.v0 != null) { - if (typeof object.v0 !== "object") - throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryResponse.v0: object expected"); - message.v0 = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.fromObject(object.v0); - } - return message; - }; - - /** - * Creates a plain object from a GetDocumentHistoryResponse message. Also converts values to other types if specified. - * @function toObject - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse - * @static - * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse} message GetDocumentHistoryResponse - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - GetDocumentHistoryResponse.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (message.v0 != null && message.hasOwnProperty("v0")) { - object.v0 = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.toObject(message.v0, options); - if (options.oneofs) - object.version = "v0"; - } - return object; - }; - - /** - * Converts this GetDocumentHistoryResponse to JSON. - * @function toJSON - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse - * @instance - * @returns {Object.} JSON object - */ - GetDocumentHistoryResponse.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 = (function() { + GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 = (function() { /** - * Properties of a GetDocumentHistoryResponseV0. - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse - * @interface IGetDocumentHistoryResponseV0 - * @property {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistory|null} [documentHistory] GetDocumentHistoryResponseV0 documentHistory - * @property {org.dash.platform.dapi.v0.IProof|null} [proof] GetDocumentHistoryResponseV0 proof - * @property {org.dash.platform.dapi.v0.IResponseMetadata|null} [metadata] GetDocumentHistoryResponseV0 metadata + * Properties of a GetDocumentHistoryRequestV1. + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest + * @interface IGetDocumentHistoryRequestV1 + * @property {Uint8Array|null} [dataContractId] GetDocumentHistoryRequestV1 dataContractId + * @property {string|null} [documentTypeName] GetDocumentHistoryRequestV1 documentTypeName + * @property {Uint8Array|null} [documentId] GetDocumentHistoryRequestV1 documentId + * @property {google.protobuf.IUInt32Value|null} [limit] GetDocumentHistoryRequestV1 limit + * @property {boolean|null} [prove] GetDocumentHistoryRequestV1 prove + * @property {number|Long|null} [startAtMs] GetDocumentHistoryRequestV1 startAtMs + * @property {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.ICursor|null} [startAfter] GetDocumentHistoryRequestV1 startAfter + * @property {number|Long|null} [startAtRevision] GetDocumentHistoryRequestV1 startAtRevision + * @property {number|Long|null} [revision] GetDocumentHistoryRequestV1 revision */ /** - * Constructs a new GetDocumentHistoryResponseV0. - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse - * @classdesc Represents a GetDocumentHistoryResponseV0. - * @implements IGetDocumentHistoryResponseV0 + * Constructs a new GetDocumentHistoryRequestV1. + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest + * @classdesc Represents a GetDocumentHistoryRequestV1. + * @implements IGetDocumentHistoryRequestV1 * @constructor - * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.IGetDocumentHistoryResponseV0=} [properties] Properties to set + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.IGetDocumentHistoryRequestV1=} [properties] Properties to set */ - function GetDocumentHistoryResponseV0(properties) { + function GetDocumentHistoryRequestV1(properties) { if (properties) for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) if (properties[keys[i]] != null) @@ -53195,69 +53024,1720 @@ $root.org = (function() { } /** - * GetDocumentHistoryResponseV0 documentHistory. - * @member {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistory|null|undefined} documentHistory + * GetDocumentHistoryRequestV1 dataContractId. + * @member {Uint8Array} dataContractId + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @instance + */ + GetDocumentHistoryRequestV1.prototype.dataContractId = $util.newBuffer([]); + + /** + * GetDocumentHistoryRequestV1 documentTypeName. + * @member {string} documentTypeName + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @instance + */ + GetDocumentHistoryRequestV1.prototype.documentTypeName = ""; + + /** + * GetDocumentHistoryRequestV1 documentId. + * @member {Uint8Array} documentId + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @instance + */ + GetDocumentHistoryRequestV1.prototype.documentId = $util.newBuffer([]); + + /** + * GetDocumentHistoryRequestV1 limit. + * @member {google.protobuf.IUInt32Value|null|undefined} limit + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @instance + */ + GetDocumentHistoryRequestV1.prototype.limit = null; + + /** + * GetDocumentHistoryRequestV1 prove. + * @member {boolean} prove + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @instance + */ + GetDocumentHistoryRequestV1.prototype.prove = false; + + /** + * GetDocumentHistoryRequestV1 startAtMs. + * @member {number|Long} startAtMs + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @instance + */ + GetDocumentHistoryRequestV1.prototype.startAtMs = $util.Long ? $util.Long.fromBits(0,0,true) : 0; + + /** + * GetDocumentHistoryRequestV1 startAfter. + * @member {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.ICursor|null|undefined} startAfter + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @instance + */ + GetDocumentHistoryRequestV1.prototype.startAfter = null; + + /** + * GetDocumentHistoryRequestV1 startAtRevision. + * @member {number|Long} startAtRevision + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @instance + */ + GetDocumentHistoryRequestV1.prototype.startAtRevision = $util.Long ? $util.Long.fromBits(0,0,true) : 0; + + /** + * GetDocumentHistoryRequestV1 revision. + * @member {number|Long} revision + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @instance + */ + GetDocumentHistoryRequestV1.prototype.revision = $util.Long ? $util.Long.fromBits(0,0,true) : 0; + + // OneOf field names bound to virtual getters and setters + var $oneOfFields; + + /** + * GetDocumentHistoryRequestV1 filter. + * @member {"startAtMs"|"startAfter"|"startAtRevision"|"revision"|undefined} filter + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @instance + */ + Object.defineProperty(GetDocumentHistoryRequestV1.prototype, "filter", { + get: $util.oneOfGetter($oneOfFields = ["startAtMs", "startAfter", "startAtRevision", "revision"]), + set: $util.oneOfSetter($oneOfFields) + }); + + /** + * Creates a new GetDocumentHistoryRequestV1 instance using the specified properties. + * @function create + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.IGetDocumentHistoryRequestV1=} [properties] Properties to set + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} GetDocumentHistoryRequestV1 instance + */ + GetDocumentHistoryRequestV1.create = function create(properties) { + return new GetDocumentHistoryRequestV1(properties); + }; + + /** + * Encodes the specified GetDocumentHistoryRequestV1 message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.verify|verify} messages. + * @function encode + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.IGetDocumentHistoryRequestV1} message GetDocumentHistoryRequestV1 message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + GetDocumentHistoryRequestV1.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.dataContractId != null && Object.hasOwnProperty.call(message, "dataContractId")) + writer.uint32(/* id 1, wireType 2 =*/10).bytes(message.dataContractId); + if (message.documentTypeName != null && Object.hasOwnProperty.call(message, "documentTypeName")) + writer.uint32(/* id 2, wireType 2 =*/18).string(message.documentTypeName); + if (message.documentId != null && Object.hasOwnProperty.call(message, "documentId")) + writer.uint32(/* id 3, wireType 2 =*/26).bytes(message.documentId); + if (message.limit != null && Object.hasOwnProperty.call(message, "limit")) + $root.google.protobuf.UInt32Value.encode(message.limit, writer.uint32(/* id 4, wireType 2 =*/34).fork()).ldelim(); + if (message.prove != null && Object.hasOwnProperty.call(message, "prove")) + writer.uint32(/* id 5, wireType 0 =*/40).bool(message.prove); + if (message.startAtMs != null && Object.hasOwnProperty.call(message, "startAtMs")) + writer.uint32(/* id 6, wireType 0 =*/48).uint64(message.startAtMs); + if (message.startAfter != null && Object.hasOwnProperty.call(message, "startAfter")) + $root.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.encode(message.startAfter, writer.uint32(/* id 7, wireType 2 =*/58).fork()).ldelim(); + if (message.startAtRevision != null && Object.hasOwnProperty.call(message, "startAtRevision")) + writer.uint32(/* id 8, wireType 0 =*/64).uint64(message.startAtRevision); + if (message.revision != null && Object.hasOwnProperty.call(message, "revision")) + writer.uint32(/* id 9, wireType 0 =*/72).uint64(message.revision); + return writer; + }; + + /** + * Encodes the specified GetDocumentHistoryRequestV1 message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.verify|verify} messages. + * @function encodeDelimited + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.IGetDocumentHistoryRequestV1} message GetDocumentHistoryRequestV1 message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + GetDocumentHistoryRequestV1.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a GetDocumentHistoryRequestV1 message from the specified reader or buffer. + * @function decode + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} GetDocumentHistoryRequestV1 + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + GetDocumentHistoryRequestV1.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.dataContractId = reader.bytes(); + break; + case 2: + message.documentTypeName = reader.string(); + break; + case 3: + message.documentId = reader.bytes(); + break; + case 4: + message.limit = $root.google.protobuf.UInt32Value.decode(reader, reader.uint32()); + break; + case 5: + message.prove = reader.bool(); + break; + case 6: + message.startAtMs = reader.uint64(); + break; + case 7: + message.startAfter = $root.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.decode(reader, reader.uint32()); + break; + case 8: + message.startAtRevision = reader.uint64(); + break; + case 9: + message.revision = reader.uint64(); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a GetDocumentHistoryRequestV1 message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} GetDocumentHistoryRequestV1 + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + GetDocumentHistoryRequestV1.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a GetDocumentHistoryRequestV1 message. + * @function verify + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + GetDocumentHistoryRequestV1.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + var properties = {}; + if (message.dataContractId != null && message.hasOwnProperty("dataContractId")) + if (!(message.dataContractId && typeof message.dataContractId.length === "number" || $util.isString(message.dataContractId))) + return "dataContractId: buffer expected"; + if (message.documentTypeName != null && message.hasOwnProperty("documentTypeName")) + if (!$util.isString(message.documentTypeName)) + return "documentTypeName: string expected"; + if (message.documentId != null && message.hasOwnProperty("documentId")) + if (!(message.documentId && typeof message.documentId.length === "number" || $util.isString(message.documentId))) + return "documentId: buffer expected"; + if (message.limit != null && message.hasOwnProperty("limit")) { + var error = $root.google.protobuf.UInt32Value.verify(message.limit); + if (error) + return "limit." + error; + } + if (message.prove != null && message.hasOwnProperty("prove")) + if (typeof message.prove !== "boolean") + return "prove: boolean expected"; + if (message.startAtMs != null && message.hasOwnProperty("startAtMs")) { + properties.filter = 1; + if (!$util.isInteger(message.startAtMs) && !(message.startAtMs && $util.isInteger(message.startAtMs.low) && $util.isInteger(message.startAtMs.high))) + return "startAtMs: integer|Long expected"; + } + if (message.startAfter != null && message.hasOwnProperty("startAfter")) { + if (properties.filter === 1) + return "filter: multiple values"; + properties.filter = 1; + { + var error = $root.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.verify(message.startAfter); + if (error) + return "startAfter." + error; + } + } + if (message.startAtRevision != null && message.hasOwnProperty("startAtRevision")) { + if (properties.filter === 1) + return "filter: multiple values"; + properties.filter = 1; + if (!$util.isInteger(message.startAtRevision) && !(message.startAtRevision && $util.isInteger(message.startAtRevision.low) && $util.isInteger(message.startAtRevision.high))) + return "startAtRevision: integer|Long expected"; + } + if (message.revision != null && message.hasOwnProperty("revision")) { + if (properties.filter === 1) + return "filter: multiple values"; + properties.filter = 1; + if (!$util.isInteger(message.revision) && !(message.revision && $util.isInteger(message.revision.low) && $util.isInteger(message.revision.high))) + return "revision: integer|Long expected"; + } + return null; + }; + + /** + * Creates a GetDocumentHistoryRequestV1 message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @static + * @param {Object.} object Plain object + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} GetDocumentHistoryRequestV1 + */ + GetDocumentHistoryRequestV1.fromObject = function fromObject(object) { + if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1) + return object; + var message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1(); + if (object.dataContractId != null) + if (typeof object.dataContractId === "string") + $util.base64.decode(object.dataContractId, message.dataContractId = $util.newBuffer($util.base64.length(object.dataContractId)), 0); + else if (object.dataContractId.length >= 0) + message.dataContractId = object.dataContractId; + if (object.documentTypeName != null) + message.documentTypeName = String(object.documentTypeName); + if (object.documentId != null) + if (typeof object.documentId === "string") + $util.base64.decode(object.documentId, message.documentId = $util.newBuffer($util.base64.length(object.documentId)), 0); + else if (object.documentId.length >= 0) + message.documentId = object.documentId; + if (object.limit != null) { + if (typeof object.limit !== "object") + throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.limit: object expected"); + message.limit = $root.google.protobuf.UInt32Value.fromObject(object.limit); + } + if (object.prove != null) + message.prove = Boolean(object.prove); + if (object.startAtMs != null) + if ($util.Long) + (message.startAtMs = $util.Long.fromValue(object.startAtMs)).unsigned = true; + else if (typeof object.startAtMs === "string") + message.startAtMs = parseInt(object.startAtMs, 10); + else if (typeof object.startAtMs === "number") + message.startAtMs = object.startAtMs; + else if (typeof object.startAtMs === "object") + message.startAtMs = new $util.LongBits(object.startAtMs.low >>> 0, object.startAtMs.high >>> 0).toNumber(true); + if (object.startAfter != null) { + if (typeof object.startAfter !== "object") + throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.startAfter: object expected"); + message.startAfter = $root.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.fromObject(object.startAfter); + } + if (object.startAtRevision != null) + if ($util.Long) + (message.startAtRevision = $util.Long.fromValue(object.startAtRevision)).unsigned = true; + else if (typeof object.startAtRevision === "string") + message.startAtRevision = parseInt(object.startAtRevision, 10); + else if (typeof object.startAtRevision === "number") + message.startAtRevision = object.startAtRevision; + else if (typeof object.startAtRevision === "object") + message.startAtRevision = new $util.LongBits(object.startAtRevision.low >>> 0, object.startAtRevision.high >>> 0).toNumber(true); + if (object.revision != null) + if ($util.Long) + (message.revision = $util.Long.fromValue(object.revision)).unsigned = true; + else if (typeof object.revision === "string") + message.revision = parseInt(object.revision, 10); + else if (typeof object.revision === "number") + message.revision = object.revision; + else if (typeof object.revision === "object") + message.revision = new $util.LongBits(object.revision.low >>> 0, object.revision.high >>> 0).toNumber(true); + return message; + }; + + /** + * Creates a plain object from a GetDocumentHistoryRequestV1 message. Also converts values to other types if specified. + * @function toObject + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} message GetDocumentHistoryRequestV1 + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + GetDocumentHistoryRequestV1.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.defaults) { + if (options.bytes === String) + object.dataContractId = ""; + else { + object.dataContractId = []; + if (options.bytes !== Array) + object.dataContractId = $util.newBuffer(object.dataContractId); + } + object.documentTypeName = ""; + if (options.bytes === String) + object.documentId = ""; + else { + object.documentId = []; + if (options.bytes !== Array) + object.documentId = $util.newBuffer(object.documentId); + } + object.limit = null; + object.prove = false; + } + if (message.dataContractId != null && message.hasOwnProperty("dataContractId")) + object.dataContractId = options.bytes === String ? $util.base64.encode(message.dataContractId, 0, message.dataContractId.length) : options.bytes === Array ? Array.prototype.slice.call(message.dataContractId) : message.dataContractId; + if (message.documentTypeName != null && message.hasOwnProperty("documentTypeName")) + object.documentTypeName = message.documentTypeName; + if (message.documentId != null && message.hasOwnProperty("documentId")) + object.documentId = options.bytes === String ? $util.base64.encode(message.documentId, 0, message.documentId.length) : options.bytes === Array ? Array.prototype.slice.call(message.documentId) : message.documentId; + if (message.limit != null && message.hasOwnProperty("limit")) + object.limit = $root.google.protobuf.UInt32Value.toObject(message.limit, options); + if (message.prove != null && message.hasOwnProperty("prove")) + object.prove = message.prove; + if (message.startAtMs != null && message.hasOwnProperty("startAtMs")) { + if (typeof message.startAtMs === "number") + object.startAtMs = options.longs === String ? String(message.startAtMs) : message.startAtMs; + else + object.startAtMs = options.longs === String ? $util.Long.prototype.toString.call(message.startAtMs) : options.longs === Number ? new $util.LongBits(message.startAtMs.low >>> 0, message.startAtMs.high >>> 0).toNumber(true) : message.startAtMs; + if (options.oneofs) + object.filter = "startAtMs"; + } + if (message.startAfter != null && message.hasOwnProperty("startAfter")) { + object.startAfter = $root.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.toObject(message.startAfter, options); + if (options.oneofs) + object.filter = "startAfter"; + } + if (message.startAtRevision != null && message.hasOwnProperty("startAtRevision")) { + if (typeof message.startAtRevision === "number") + object.startAtRevision = options.longs === String ? String(message.startAtRevision) : message.startAtRevision; + else + object.startAtRevision = options.longs === String ? $util.Long.prototype.toString.call(message.startAtRevision) : options.longs === Number ? new $util.LongBits(message.startAtRevision.low >>> 0, message.startAtRevision.high >>> 0).toNumber(true) : message.startAtRevision; + if (options.oneofs) + object.filter = "startAtRevision"; + } + if (message.revision != null && message.hasOwnProperty("revision")) { + if (typeof message.revision === "number") + object.revision = options.longs === String ? String(message.revision) : message.revision; + else + object.revision = options.longs === String ? $util.Long.prototype.toString.call(message.revision) : options.longs === Number ? new $util.LongBits(message.revision.low >>> 0, message.revision.high >>> 0).toNumber(true) : message.revision; + if (options.oneofs) + object.filter = "revision"; + } + return object; + }; + + /** + * Converts this GetDocumentHistoryRequestV1 to JSON. + * @function toJSON + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @instance + * @returns {Object.} JSON object + */ + GetDocumentHistoryRequestV1.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + GetDocumentHistoryRequestV1.Cursor = (function() { + + /** + * Properties of a Cursor. + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @interface ICursor + * @property {number|Long|null} [timeMs] Cursor timeMs + * @property {number|Long|null} [revision] Cursor revision + */ + + /** + * Constructs a new Cursor. + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @classdesc Represents a Cursor. + * @implements ICursor + * @constructor + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.ICursor=} [properties] Properties to set + */ + function Cursor(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * Cursor timeMs. + * @member {number|Long} timeMs + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor + * @instance + */ + Cursor.prototype.timeMs = $util.Long ? $util.Long.fromBits(0,0,true) : 0; + + /** + * Cursor revision. + * @member {number|Long} revision + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor + * @instance + */ + Cursor.prototype.revision = $util.Long ? $util.Long.fromBits(0,0,true) : 0; + + /** + * Creates a new Cursor instance using the specified properties. + * @function create + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.ICursor=} [properties] Properties to set + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor} Cursor instance + */ + Cursor.create = function create(properties) { + return new Cursor(properties); + }; + + /** + * Encodes the specified Cursor message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.verify|verify} messages. + * @function encode + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.ICursor} message Cursor message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Cursor.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.timeMs != null && Object.hasOwnProperty.call(message, "timeMs")) + writer.uint32(/* id 1, wireType 0 =*/8).uint64(message.timeMs); + if (message.revision != null && Object.hasOwnProperty.call(message, "revision")) + writer.uint32(/* id 2, wireType 0 =*/16).uint64(message.revision); + return writer; + }; + + /** + * Encodes the specified Cursor message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.verify|verify} messages. + * @function encodeDelimited + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.ICursor} message Cursor message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Cursor.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a Cursor message from the specified reader or buffer. + * @function decode + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor} Cursor + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Cursor.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.timeMs = reader.uint64(); + break; + case 2: + message.revision = reader.uint64(); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a Cursor message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor} Cursor + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Cursor.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a Cursor message. + * @function verify + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + Cursor.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.timeMs != null && message.hasOwnProperty("timeMs")) + if (!$util.isInteger(message.timeMs) && !(message.timeMs && $util.isInteger(message.timeMs.low) && $util.isInteger(message.timeMs.high))) + return "timeMs: integer|Long expected"; + if (message.revision != null && message.hasOwnProperty("revision")) + if (!$util.isInteger(message.revision) && !(message.revision && $util.isInteger(message.revision.low) && $util.isInteger(message.revision.high))) + return "revision: integer|Long expected"; + return null; + }; + + /** + * Creates a Cursor message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor + * @static + * @param {Object.} object Plain object + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor} Cursor + */ + Cursor.fromObject = function fromObject(object) { + if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor) + return object; + var message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor(); + if (object.timeMs != null) + if ($util.Long) + (message.timeMs = $util.Long.fromValue(object.timeMs)).unsigned = true; + else if (typeof object.timeMs === "string") + message.timeMs = parseInt(object.timeMs, 10); + else if (typeof object.timeMs === "number") + message.timeMs = object.timeMs; + else if (typeof object.timeMs === "object") + message.timeMs = new $util.LongBits(object.timeMs.low >>> 0, object.timeMs.high >>> 0).toNumber(true); + if (object.revision != null) + if ($util.Long) + (message.revision = $util.Long.fromValue(object.revision)).unsigned = true; + else if (typeof object.revision === "string") + message.revision = parseInt(object.revision, 10); + else if (typeof object.revision === "number") + message.revision = object.revision; + else if (typeof object.revision === "object") + message.revision = new $util.LongBits(object.revision.low >>> 0, object.revision.high >>> 0).toNumber(true); + return message; + }; + + /** + * Creates a plain object from a Cursor message. Also converts values to other types if specified. + * @function toObject + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor} message Cursor + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + Cursor.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.defaults) { + if ($util.Long) { + var long = new $util.Long(0, 0, true); + object.timeMs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else + object.timeMs = options.longs === String ? "0" : 0; + if ($util.Long) { + var long = new $util.Long(0, 0, true); + object.revision = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else + object.revision = options.longs === String ? "0" : 0; + } + if (message.timeMs != null && message.hasOwnProperty("timeMs")) + if (typeof message.timeMs === "number") + object.timeMs = options.longs === String ? String(message.timeMs) : message.timeMs; + else + object.timeMs = options.longs === String ? $util.Long.prototype.toString.call(message.timeMs) : options.longs === Number ? new $util.LongBits(message.timeMs.low >>> 0, message.timeMs.high >>> 0).toNumber(true) : message.timeMs; + if (message.revision != null && message.hasOwnProperty("revision")) + if (typeof message.revision === "number") + object.revision = options.longs === String ? String(message.revision) : message.revision; + else + object.revision = options.longs === String ? $util.Long.prototype.toString.call(message.revision) : options.longs === Number ? new $util.LongBits(message.revision.low >>> 0, message.revision.high >>> 0).toNumber(true) : message.revision; + return object; + }; + + /** + * Converts this Cursor to JSON. + * @function toJSON + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor + * @instance + * @returns {Object.} JSON object + */ + Cursor.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + return Cursor; + })(); + + return GetDocumentHistoryRequestV1; + })(); + + return GetDocumentHistoryRequest; + })(); + + v0.GetDocumentHistoryResponse = (function() { + + /** + * Properties of a GetDocumentHistoryResponse. + * @memberof org.dash.platform.dapi.v0 + * @interface IGetDocumentHistoryResponse + * @property {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.IGetDocumentHistoryResponseV0|null} [v0] GetDocumentHistoryResponse v0 + * @property {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.IGetDocumentHistoryResponseV1|null} [v1] GetDocumentHistoryResponse v1 + */ + + /** + * Constructs a new GetDocumentHistoryResponse. + * @memberof org.dash.platform.dapi.v0 + * @classdesc Represents a GetDocumentHistoryResponse. + * @implements IGetDocumentHistoryResponse + * @constructor + * @param {org.dash.platform.dapi.v0.IGetDocumentHistoryResponse=} [properties] Properties to set + */ + function GetDocumentHistoryResponse(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * GetDocumentHistoryResponse v0. + * @member {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.IGetDocumentHistoryResponseV0|null|undefined} v0 + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse + * @instance + */ + GetDocumentHistoryResponse.prototype.v0 = null; + + /** + * GetDocumentHistoryResponse v1. + * @member {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.IGetDocumentHistoryResponseV1|null|undefined} v1 + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse + * @instance + */ + GetDocumentHistoryResponse.prototype.v1 = null; + + // OneOf field names bound to virtual getters and setters + var $oneOfFields; + + /** + * GetDocumentHistoryResponse version. + * @member {"v0"|"v1"|undefined} version + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse + * @instance + */ + Object.defineProperty(GetDocumentHistoryResponse.prototype, "version", { + get: $util.oneOfGetter($oneOfFields = ["v0", "v1"]), + set: $util.oneOfSetter($oneOfFields) + }); + + /** + * Creates a new GetDocumentHistoryResponse instance using the specified properties. + * @function create + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse + * @static + * @param {org.dash.platform.dapi.v0.IGetDocumentHistoryResponse=} [properties] Properties to set + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse} GetDocumentHistoryResponse instance + */ + GetDocumentHistoryResponse.create = function create(properties) { + return new GetDocumentHistoryResponse(properties); + }; + + /** + * Encodes the specified GetDocumentHistoryResponse message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.verify|verify} messages. + * @function encode + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse + * @static + * @param {org.dash.platform.dapi.v0.IGetDocumentHistoryResponse} message GetDocumentHistoryResponse message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + GetDocumentHistoryResponse.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.v0 != null && Object.hasOwnProperty.call(message, "v0")) + $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.encode(message.v0, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); + if (message.v1 != null && Object.hasOwnProperty.call(message, "v1")) + $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.encode(message.v1, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified GetDocumentHistoryResponse message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.verify|verify} messages. + * @function encodeDelimited + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse + * @static + * @param {org.dash.platform.dapi.v0.IGetDocumentHistoryResponse} message GetDocumentHistoryResponse message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + GetDocumentHistoryResponse.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a GetDocumentHistoryResponse message from the specified reader or buffer. + * @function decode + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse} GetDocumentHistoryResponse + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + GetDocumentHistoryResponse.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.v0 = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.decode(reader, reader.uint32()); + break; + case 2: + message.v1 = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.decode(reader, reader.uint32()); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a GetDocumentHistoryResponse message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse} GetDocumentHistoryResponse + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + GetDocumentHistoryResponse.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a GetDocumentHistoryResponse message. + * @function verify + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + GetDocumentHistoryResponse.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + var properties = {}; + if (message.v0 != null && message.hasOwnProperty("v0")) { + properties.version = 1; + { + var error = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.verify(message.v0); + if (error) + return "v0." + error; + } + } + if (message.v1 != null && message.hasOwnProperty("v1")) { + if (properties.version === 1) + return "version: multiple values"; + properties.version = 1; + { + var error = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.verify(message.v1); + if (error) + return "v1." + error; + } + } + return null; + }; + + /** + * Creates a GetDocumentHistoryResponse message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse + * @static + * @param {Object.} object Plain object + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse} GetDocumentHistoryResponse + */ + GetDocumentHistoryResponse.fromObject = function fromObject(object) { + if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse) + return object; + var message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse(); + if (object.v0 != null) { + if (typeof object.v0 !== "object") + throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryResponse.v0: object expected"); + message.v0 = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.fromObject(object.v0); + } + if (object.v1 != null) { + if (typeof object.v1 !== "object") + throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryResponse.v1: object expected"); + message.v1 = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.fromObject(object.v1); + } + return message; + }; + + /** + * Creates a plain object from a GetDocumentHistoryResponse message. Also converts values to other types if specified. + * @function toObject + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse} message GetDocumentHistoryResponse + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + GetDocumentHistoryResponse.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (message.v0 != null && message.hasOwnProperty("v0")) { + object.v0 = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.toObject(message.v0, options); + if (options.oneofs) + object.version = "v0"; + } + if (message.v1 != null && message.hasOwnProperty("v1")) { + object.v1 = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.toObject(message.v1, options); + if (options.oneofs) + object.version = "v1"; + } + return object; + }; + + /** + * Converts this GetDocumentHistoryResponse to JSON. + * @function toJSON + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse + * @instance + * @returns {Object.} JSON object + */ + GetDocumentHistoryResponse.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 = (function() { + + /** + * Properties of a GetDocumentHistoryResponseV0. + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse + * @interface IGetDocumentHistoryResponseV0 + * @property {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistory|null} [documentHistory] GetDocumentHistoryResponseV0 documentHistory + * @property {org.dash.platform.dapi.v0.IProof|null} [proof] GetDocumentHistoryResponseV0 proof + * @property {org.dash.platform.dapi.v0.IResponseMetadata|null} [metadata] GetDocumentHistoryResponseV0 metadata + */ + + /** + * Constructs a new GetDocumentHistoryResponseV0. + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse + * @classdesc Represents a GetDocumentHistoryResponseV0. + * @implements IGetDocumentHistoryResponseV0 + * @constructor + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.IGetDocumentHistoryResponseV0=} [properties] Properties to set + */ + function GetDocumentHistoryResponseV0(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * GetDocumentHistoryResponseV0 documentHistory. + * @member {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistory|null|undefined} documentHistory + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @instance + */ + GetDocumentHistoryResponseV0.prototype.documentHistory = null; + + /** + * GetDocumentHistoryResponseV0 proof. + * @member {org.dash.platform.dapi.v0.IProof|null|undefined} proof + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @instance + */ + GetDocumentHistoryResponseV0.prototype.proof = null; + + /** + * GetDocumentHistoryResponseV0 metadata. + * @member {org.dash.platform.dapi.v0.IResponseMetadata|null|undefined} metadata + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @instance + */ + GetDocumentHistoryResponseV0.prototype.metadata = null; + + // OneOf field names bound to virtual getters and setters + var $oneOfFields; + + /** + * GetDocumentHistoryResponseV0 result. + * @member {"documentHistory"|"proof"|undefined} result + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @instance + */ + Object.defineProperty(GetDocumentHistoryResponseV0.prototype, "result", { + get: $util.oneOfGetter($oneOfFields = ["documentHistory", "proof"]), + set: $util.oneOfSetter($oneOfFields) + }); + + /** + * Creates a new GetDocumentHistoryResponseV0 instance using the specified properties. + * @function create + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.IGetDocumentHistoryResponseV0=} [properties] Properties to set + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} GetDocumentHistoryResponseV0 instance + */ + GetDocumentHistoryResponseV0.create = function create(properties) { + return new GetDocumentHistoryResponseV0(properties); + }; + + /** + * Encodes the specified GetDocumentHistoryResponseV0 message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.verify|verify} messages. + * @function encode + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.IGetDocumentHistoryResponseV0} message GetDocumentHistoryResponseV0 message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + GetDocumentHistoryResponseV0.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.documentHistory != null && Object.hasOwnProperty.call(message, "documentHistory")) + $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.encode(message.documentHistory, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); + if (message.proof != null && Object.hasOwnProperty.call(message, "proof")) + $root.org.dash.platform.dapi.v0.Proof.encode(message.proof, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); + if (message.metadata != null && Object.hasOwnProperty.call(message, "metadata")) + $root.org.dash.platform.dapi.v0.ResponseMetadata.encode(message.metadata, writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified GetDocumentHistoryResponseV0 message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.verify|verify} messages. + * @function encodeDelimited + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.IGetDocumentHistoryResponseV0} message GetDocumentHistoryResponseV0 message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + GetDocumentHistoryResponseV0.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a GetDocumentHistoryResponseV0 message from the specified reader or buffer. + * @function decode + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} GetDocumentHistoryResponseV0 + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + GetDocumentHistoryResponseV0.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.documentHistory = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.decode(reader, reader.uint32()); + break; + case 2: + message.proof = $root.org.dash.platform.dapi.v0.Proof.decode(reader, reader.uint32()); + break; + case 3: + message.metadata = $root.org.dash.platform.dapi.v0.ResponseMetadata.decode(reader, reader.uint32()); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a GetDocumentHistoryResponseV0 message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} GetDocumentHistoryResponseV0 + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + GetDocumentHistoryResponseV0.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a GetDocumentHistoryResponseV0 message. + * @function verify + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + GetDocumentHistoryResponseV0.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + var properties = {}; + if (message.documentHistory != null && message.hasOwnProperty("documentHistory")) { + properties.result = 1; + { + var error = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.verify(message.documentHistory); + if (error) + return "documentHistory." + error; + } + } + if (message.proof != null && message.hasOwnProperty("proof")) { + if (properties.result === 1) + return "result: multiple values"; + properties.result = 1; + { + var error = $root.org.dash.platform.dapi.v0.Proof.verify(message.proof); + if (error) + return "proof." + error; + } + } + if (message.metadata != null && message.hasOwnProperty("metadata")) { + var error = $root.org.dash.platform.dapi.v0.ResponseMetadata.verify(message.metadata); + if (error) + return "metadata." + error; + } + return null; + }; + + /** + * Creates a GetDocumentHistoryResponseV0 message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @static + * @param {Object.} object Plain object + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} GetDocumentHistoryResponseV0 + */ + GetDocumentHistoryResponseV0.fromObject = function fromObject(object) { + if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0) + return object; + var message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0(); + if (object.documentHistory != null) { + if (typeof object.documentHistory !== "object") + throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.documentHistory: object expected"); + message.documentHistory = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.fromObject(object.documentHistory); + } + if (object.proof != null) { + if (typeof object.proof !== "object") + throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.proof: object expected"); + message.proof = $root.org.dash.platform.dapi.v0.Proof.fromObject(object.proof); + } + if (object.metadata != null) { + if (typeof object.metadata !== "object") + throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.metadata: object expected"); + message.metadata = $root.org.dash.platform.dapi.v0.ResponseMetadata.fromObject(object.metadata); + } + return message; + }; + + /** + * Creates a plain object from a GetDocumentHistoryResponseV0 message. Also converts values to other types if specified. + * @function toObject + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} message GetDocumentHistoryResponseV0 + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + GetDocumentHistoryResponseV0.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.defaults) + object.metadata = null; + if (message.documentHistory != null && message.hasOwnProperty("documentHistory")) { + object.documentHistory = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.toObject(message.documentHistory, options); + if (options.oneofs) + object.result = "documentHistory"; + } + if (message.proof != null && message.hasOwnProperty("proof")) { + object.proof = $root.org.dash.platform.dapi.v0.Proof.toObject(message.proof, options); + if (options.oneofs) + object.result = "proof"; + } + if (message.metadata != null && message.hasOwnProperty("metadata")) + object.metadata = $root.org.dash.platform.dapi.v0.ResponseMetadata.toObject(message.metadata, options); + return object; + }; + + /** + * Converts this GetDocumentHistoryResponseV0 to JSON. + * @function toJSON * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 * @instance + * @returns {Object.} JSON object + */ + GetDocumentHistoryResponseV0.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + GetDocumentHistoryResponseV0.DocumentHistoryEntry = (function() { + + /** + * Properties of a DocumentHistoryEntry. + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @interface IDocumentHistoryEntry + * @property {number|Long|null} [date] DocumentHistoryEntry date + * @property {Uint8Array|null} [value] DocumentHistoryEntry value + */ + + /** + * Constructs a new DocumentHistoryEntry. + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @classdesc Represents a DocumentHistoryEntry. + * @implements IDocumentHistoryEntry + * @constructor + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistoryEntry=} [properties] Properties to set + */ + function DocumentHistoryEntry(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * DocumentHistoryEntry date. + * @member {number|Long} date + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @instance + */ + DocumentHistoryEntry.prototype.date = $util.Long ? $util.Long.fromBits(0,0,true) : 0; + + /** + * DocumentHistoryEntry value. + * @member {Uint8Array} value + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @instance + */ + DocumentHistoryEntry.prototype.value = $util.newBuffer([]); + + /** + * Creates a new DocumentHistoryEntry instance using the specified properties. + * @function create + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistoryEntry=} [properties] Properties to set + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} DocumentHistoryEntry instance + */ + DocumentHistoryEntry.create = function create(properties) { + return new DocumentHistoryEntry(properties); + }; + + /** + * Encodes the specified DocumentHistoryEntry message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.verify|verify} messages. + * @function encode + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistoryEntry} message DocumentHistoryEntry message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + DocumentHistoryEntry.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.date != null && Object.hasOwnProperty.call(message, "date")) + writer.uint32(/* id 1, wireType 0 =*/8).uint64(message.date); + if (message.value != null && Object.hasOwnProperty.call(message, "value")) + writer.uint32(/* id 2, wireType 2 =*/18).bytes(message.value); + return writer; + }; + + /** + * Encodes the specified DocumentHistoryEntry message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.verify|verify} messages. + * @function encodeDelimited + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistoryEntry} message DocumentHistoryEntry message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + DocumentHistoryEntry.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a DocumentHistoryEntry message from the specified reader or buffer. + * @function decode + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} DocumentHistoryEntry + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + DocumentHistoryEntry.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.date = reader.uint64(); + break; + case 2: + message.value = reader.bytes(); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a DocumentHistoryEntry message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} DocumentHistoryEntry + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + DocumentHistoryEntry.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a DocumentHistoryEntry message. + * @function verify + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + DocumentHistoryEntry.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.date != null && message.hasOwnProperty("date")) + if (!$util.isInteger(message.date) && !(message.date && $util.isInteger(message.date.low) && $util.isInteger(message.date.high))) + return "date: integer|Long expected"; + if (message.value != null && message.hasOwnProperty("value")) + if (!(message.value && typeof message.value.length === "number" || $util.isString(message.value))) + return "value: buffer expected"; + return null; + }; + + /** + * Creates a DocumentHistoryEntry message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @static + * @param {Object.} object Plain object + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} DocumentHistoryEntry + */ + DocumentHistoryEntry.fromObject = function fromObject(object) { + if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry) + return object; + var message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry(); + if (object.date != null) + if ($util.Long) + (message.date = $util.Long.fromValue(object.date)).unsigned = true; + else if (typeof object.date === "string") + message.date = parseInt(object.date, 10); + else if (typeof object.date === "number") + message.date = object.date; + else if (typeof object.date === "object") + message.date = new $util.LongBits(object.date.low >>> 0, object.date.high >>> 0).toNumber(true); + if (object.value != null) + if (typeof object.value === "string") + $util.base64.decode(object.value, message.value = $util.newBuffer($util.base64.length(object.value)), 0); + else if (object.value.length >= 0) + message.value = object.value; + return message; + }; + + /** + * Creates a plain object from a DocumentHistoryEntry message. Also converts values to other types if specified. + * @function toObject + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} message DocumentHistoryEntry + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + DocumentHistoryEntry.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.defaults) { + if ($util.Long) { + var long = new $util.Long(0, 0, true); + object.date = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else + object.date = options.longs === String ? "0" : 0; + if (options.bytes === String) + object.value = ""; + else { + object.value = []; + if (options.bytes !== Array) + object.value = $util.newBuffer(object.value); + } + } + if (message.date != null && message.hasOwnProperty("date")) + if (typeof message.date === "number") + object.date = options.longs === String ? String(message.date) : message.date; + else + object.date = options.longs === String ? $util.Long.prototype.toString.call(message.date) : options.longs === Number ? new $util.LongBits(message.date.low >>> 0, message.date.high >>> 0).toNumber(true) : message.date; + if (message.value != null && message.hasOwnProperty("value")) + object.value = options.bytes === String ? $util.base64.encode(message.value, 0, message.value.length) : options.bytes === Array ? Array.prototype.slice.call(message.value) : message.value; + return object; + }; + + /** + * Converts this DocumentHistoryEntry to JSON. + * @function toJSON + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @instance + * @returns {Object.} JSON object + */ + DocumentHistoryEntry.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + return DocumentHistoryEntry; + })(); + + GetDocumentHistoryResponseV0.DocumentHistory = (function() { + + /** + * Properties of a DocumentHistory. + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @interface IDocumentHistory + * @property {Array.|null} [documentEntries] DocumentHistory documentEntries + */ + + /** + * Constructs a new DocumentHistory. + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @classdesc Represents a DocumentHistory. + * @implements IDocumentHistory + * @constructor + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistory=} [properties] Properties to set + */ + function DocumentHistory(properties) { + this.documentEntries = []; + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * DocumentHistory documentEntries. + * @member {Array.} documentEntries + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * @instance + */ + DocumentHistory.prototype.documentEntries = $util.emptyArray; + + /** + * Creates a new DocumentHistory instance using the specified properties. + * @function create + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistory=} [properties] Properties to set + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} DocumentHistory instance + */ + DocumentHistory.create = function create(properties) { + return new DocumentHistory(properties); + }; + + /** + * Encodes the specified DocumentHistory message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.verify|verify} messages. + * @function encode + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistory} message DocumentHistory message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + DocumentHistory.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.documentEntries != null && message.documentEntries.length) + for (var i = 0; i < message.documentEntries.length; ++i) + $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.encode(message.documentEntries[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified DocumentHistory message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.verify|verify} messages. + * @function encodeDelimited + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistory} message DocumentHistory message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + DocumentHistory.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a DocumentHistory message from the specified reader or buffer. + * @function decode + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} DocumentHistory + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + DocumentHistory.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + if (!(message.documentEntries && message.documentEntries.length)) + message.documentEntries = []; + message.documentEntries.push($root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.decode(reader, reader.uint32())); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a DocumentHistory message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} DocumentHistory + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + DocumentHistory.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a DocumentHistory message. + * @function verify + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + DocumentHistory.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.documentEntries != null && message.hasOwnProperty("documentEntries")) { + if (!Array.isArray(message.documentEntries)) + return "documentEntries: array expected"; + for (var i = 0; i < message.documentEntries.length; ++i) { + var error = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.verify(message.documentEntries[i]); + if (error) + return "documentEntries." + error; + } + } + return null; + }; + + /** + * Creates a DocumentHistory message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * @static + * @param {Object.} object Plain object + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} DocumentHistory + */ + DocumentHistory.fromObject = function fromObject(object) { + if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory) + return object; + var message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory(); + if (object.documentEntries) { + if (!Array.isArray(object.documentEntries)) + throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.documentEntries: array expected"); + message.documentEntries = []; + for (var i = 0; i < object.documentEntries.length; ++i) { + if (typeof object.documentEntries[i] !== "object") + throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.documentEntries: object expected"); + message.documentEntries[i] = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.fromObject(object.documentEntries[i]); + } + } + return message; + }; + + /** + * Creates a plain object from a DocumentHistory message. Also converts values to other types if specified. + * @function toObject + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} message DocumentHistory + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + DocumentHistory.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.arrays || options.defaults) + object.documentEntries = []; + if (message.documentEntries && message.documentEntries.length) { + object.documentEntries = []; + for (var j = 0; j < message.documentEntries.length; ++j) + object.documentEntries[j] = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.toObject(message.documentEntries[j], options); + } + return object; + }; + + /** + * Converts this DocumentHistory to JSON. + * @function toJSON + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * @instance + * @returns {Object.} JSON object + */ + DocumentHistory.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + return DocumentHistory; + })(); + + return GetDocumentHistoryResponseV0; + })(); + + GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 = (function() { + + /** + * Properties of a GetDocumentHistoryResponseV1. + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse + * @interface IGetDocumentHistoryResponseV1 + * @property {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.IHistory|null} [history] GetDocumentHistoryResponseV1 history + * @property {org.dash.platform.dapi.v0.IProof|null} [proof] GetDocumentHistoryResponseV1 proof + * @property {org.dash.platform.dapi.v0.IResponseMetadata|null} [metadata] GetDocumentHistoryResponseV1 metadata + */ + + /** + * Constructs a new GetDocumentHistoryResponseV1. + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse + * @classdesc Represents a GetDocumentHistoryResponseV1. + * @implements IGetDocumentHistoryResponseV1 + * @constructor + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.IGetDocumentHistoryResponseV1=} [properties] Properties to set + */ + function GetDocumentHistoryResponseV1(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * GetDocumentHistoryResponseV1 history. + * @member {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.IHistory|null|undefined} history + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 + * @instance */ - GetDocumentHistoryResponseV0.prototype.documentHistory = null; + GetDocumentHistoryResponseV1.prototype.history = null; /** - * GetDocumentHistoryResponseV0 proof. + * GetDocumentHistoryResponseV1 proof. * @member {org.dash.platform.dapi.v0.IProof|null|undefined} proof - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 * @instance */ - GetDocumentHistoryResponseV0.prototype.proof = null; + GetDocumentHistoryResponseV1.prototype.proof = null; /** - * GetDocumentHistoryResponseV0 metadata. + * GetDocumentHistoryResponseV1 metadata. * @member {org.dash.platform.dapi.v0.IResponseMetadata|null|undefined} metadata - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 * @instance */ - GetDocumentHistoryResponseV0.prototype.metadata = null; + GetDocumentHistoryResponseV1.prototype.metadata = null; // OneOf field names bound to virtual getters and setters var $oneOfFields; /** - * GetDocumentHistoryResponseV0 result. - * @member {"documentHistory"|"proof"|undefined} result - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * GetDocumentHistoryResponseV1 result. + * @member {"history"|"proof"|undefined} result + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 * @instance */ - Object.defineProperty(GetDocumentHistoryResponseV0.prototype, "result", { - get: $util.oneOfGetter($oneOfFields = ["documentHistory", "proof"]), + Object.defineProperty(GetDocumentHistoryResponseV1.prototype, "result", { + get: $util.oneOfGetter($oneOfFields = ["history", "proof"]), set: $util.oneOfSetter($oneOfFields) }); /** - * Creates a new GetDocumentHistoryResponseV0 instance using the specified properties. + * Creates a new GetDocumentHistoryResponseV1 instance using the specified properties. * @function create - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 * @static - * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.IGetDocumentHistoryResponseV0=} [properties] Properties to set - * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} GetDocumentHistoryResponseV0 instance + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.IGetDocumentHistoryResponseV1=} [properties] Properties to set + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1} GetDocumentHistoryResponseV1 instance */ - GetDocumentHistoryResponseV0.create = function create(properties) { - return new GetDocumentHistoryResponseV0(properties); + GetDocumentHistoryResponseV1.create = function create(properties) { + return new GetDocumentHistoryResponseV1(properties); }; /** - * Encodes the specified GetDocumentHistoryResponseV0 message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.verify|verify} messages. + * Encodes the specified GetDocumentHistoryResponseV1 message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.verify|verify} messages. * @function encode - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 * @static - * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.IGetDocumentHistoryResponseV0} message GetDocumentHistoryResponseV0 message or plain object to encode + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.IGetDocumentHistoryResponseV1} message GetDocumentHistoryResponseV1 message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - GetDocumentHistoryResponseV0.encode = function encode(message, writer) { + GetDocumentHistoryResponseV1.encode = function encode(message, writer) { if (!writer) writer = $Writer.create(); - if (message.documentHistory != null && Object.hasOwnProperty.call(message, "documentHistory")) - $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.encode(message.documentHistory, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); + if (message.history != null && Object.hasOwnProperty.call(message, "history")) + $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.encode(message.history, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); if (message.proof != null && Object.hasOwnProperty.call(message, "proof")) $root.org.dash.platform.dapi.v0.Proof.encode(message.proof, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); if (message.metadata != null && Object.hasOwnProperty.call(message, "metadata")) @@ -53266,38 +54746,38 @@ $root.org = (function() { }; /** - * Encodes the specified GetDocumentHistoryResponseV0 message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.verify|verify} messages. + * Encodes the specified GetDocumentHistoryResponseV1 message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.verify|verify} messages. * @function encodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 * @static - * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.IGetDocumentHistoryResponseV0} message GetDocumentHistoryResponseV0 message or plain object to encode + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.IGetDocumentHistoryResponseV1} message GetDocumentHistoryResponseV1 message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - GetDocumentHistoryResponseV0.encodeDelimited = function encodeDelimited(message, writer) { + GetDocumentHistoryResponseV1.encodeDelimited = function encodeDelimited(message, writer) { return this.encode(message, writer).ldelim(); }; /** - * Decodes a GetDocumentHistoryResponseV0 message from the specified reader or buffer. + * Decodes a GetDocumentHistoryResponseV1 message from the specified reader or buffer. * @function decode - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 * @static * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from * @param {number} [length] Message length if known beforehand - * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} GetDocumentHistoryResponseV0 + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1} GetDocumentHistoryResponseV1 * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - GetDocumentHistoryResponseV0.decode = function decode(reader, length) { + GetDocumentHistoryResponseV1.decode = function decode(reader, length) { if (!(reader instanceof $Reader)) reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0(); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1(); while (reader.pos < end) { var tag = reader.uint32(); switch (tag >>> 3) { case 1: - message.documentHistory = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.decode(reader, reader.uint32()); + message.history = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.decode(reader, reader.uint32()); break; case 2: message.proof = $root.org.dash.platform.dapi.v0.Proof.decode(reader, reader.uint32()); @@ -53314,39 +54794,39 @@ $root.org = (function() { }; /** - * Decodes a GetDocumentHistoryResponseV0 message from the specified reader or buffer, length delimited. + * Decodes a GetDocumentHistoryResponseV1 message from the specified reader or buffer, length delimited. * @function decodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 * @static * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} GetDocumentHistoryResponseV0 + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1} GetDocumentHistoryResponseV1 * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - GetDocumentHistoryResponseV0.decodeDelimited = function decodeDelimited(reader) { + GetDocumentHistoryResponseV1.decodeDelimited = function decodeDelimited(reader) { if (!(reader instanceof $Reader)) reader = new $Reader(reader); return this.decode(reader, reader.uint32()); }; /** - * Verifies a GetDocumentHistoryResponseV0 message. + * Verifies a GetDocumentHistoryResponseV1 message. * @function verify - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 * @static * @param {Object.} message Plain object to verify * @returns {string|null} `null` if valid, otherwise the reason why it is not */ - GetDocumentHistoryResponseV0.verify = function verify(message) { + GetDocumentHistoryResponseV1.verify = function verify(message) { if (typeof message !== "object" || message === null) return "object expected"; var properties = {}; - if (message.documentHistory != null && message.hasOwnProperty("documentHistory")) { + if (message.history != null && message.hasOwnProperty("history")) { properties.result = 1; { - var error = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.verify(message.documentHistory); + var error = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.verify(message.history); if (error) - return "documentHistory." + error; + return "history." + error; } } if (message.proof != null && message.hasOwnProperty("proof")) { @@ -53368,54 +54848,54 @@ $root.org = (function() { }; /** - * Creates a GetDocumentHistoryResponseV0 message from a plain object. Also converts values to their respective internal types. + * Creates a GetDocumentHistoryResponseV1 message from a plain object. Also converts values to their respective internal types. * @function fromObject - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 * @static * @param {Object.} object Plain object - * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} GetDocumentHistoryResponseV0 + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1} GetDocumentHistoryResponseV1 */ - GetDocumentHistoryResponseV0.fromObject = function fromObject(object) { - if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0) + GetDocumentHistoryResponseV1.fromObject = function fromObject(object) { + if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1) return object; - var message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0(); - if (object.documentHistory != null) { - if (typeof object.documentHistory !== "object") - throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.documentHistory: object expected"); - message.documentHistory = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.fromObject(object.documentHistory); + var message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1(); + if (object.history != null) { + if (typeof object.history !== "object") + throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.history: object expected"); + message.history = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.fromObject(object.history); } if (object.proof != null) { if (typeof object.proof !== "object") - throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.proof: object expected"); + throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.proof: object expected"); message.proof = $root.org.dash.platform.dapi.v0.Proof.fromObject(object.proof); } if (object.metadata != null) { if (typeof object.metadata !== "object") - throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.metadata: object expected"); + throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.metadata: object expected"); message.metadata = $root.org.dash.platform.dapi.v0.ResponseMetadata.fromObject(object.metadata); } return message; }; /** - * Creates a plain object from a GetDocumentHistoryResponseV0 message. Also converts values to other types if specified. + * Creates a plain object from a GetDocumentHistoryResponseV1 message. Also converts values to other types if specified. * @function toObject - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 * @static - * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} message GetDocumentHistoryResponseV0 + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1} message GetDocumentHistoryResponseV1 * @param {$protobuf.IConversionOptions} [options] Conversion options * @returns {Object.} Plain object */ - GetDocumentHistoryResponseV0.toObject = function toObject(message, options) { + GetDocumentHistoryResponseV1.toObject = function toObject(message, options) { if (!options) options = {}; var object = {}; if (options.defaults) object.metadata = null; - if (message.documentHistory != null && message.hasOwnProperty("documentHistory")) { - object.documentHistory = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.toObject(message.documentHistory, options); + if (message.history != null && message.hasOwnProperty("history")) { + object.history = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.toObject(message.history, options); if (options.oneofs) - object.result = "documentHistory"; + object.result = "history"; } if (message.proof != null && message.hasOwnProperty("proof")) { object.proof = $root.org.dash.platform.dapi.v0.Proof.toObject(message.proof, options); @@ -53427,36 +54907,305 @@ $root.org = (function() { return object; }; - /** - * Converts this GetDocumentHistoryResponseV0 to JSON. - * @function toJSON - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 - * @instance - * @returns {Object.} JSON object - */ - GetDocumentHistoryResponseV0.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; + /** + * Converts this GetDocumentHistoryResponseV1 to JSON. + * @function toJSON + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 + * @instance + * @returns {Object.} JSON object + */ + GetDocumentHistoryResponseV1.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + GetDocumentHistoryResponseV1.Entry = (function() { + + /** + * Properties of an Entry. + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 + * @interface IEntry + * @property {number|Long|null} [timeMs] Entry timeMs + * @property {number|Long|null} [revision] Entry revision + * @property {Uint8Array|null} [document] Entry document + */ + + /** + * Constructs a new Entry. + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 + * @classdesc Represents an Entry. + * @implements IEntry + * @constructor + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.IEntry=} [properties] Properties to set + */ + function Entry(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * Entry timeMs. + * @member {number|Long} timeMs + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry + * @instance + */ + Entry.prototype.timeMs = $util.Long ? $util.Long.fromBits(0,0,true) : 0; + + /** + * Entry revision. + * @member {number|Long} revision + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry + * @instance + */ + Entry.prototype.revision = $util.Long ? $util.Long.fromBits(0,0,true) : 0; + + /** + * Entry document. + * @member {Uint8Array} document + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry + * @instance + */ + Entry.prototype.document = $util.newBuffer([]); + + /** + * Creates a new Entry instance using the specified properties. + * @function create + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.IEntry=} [properties] Properties to set + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry} Entry instance + */ + Entry.create = function create(properties) { + return new Entry(properties); + }; + + /** + * Encodes the specified Entry message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.verify|verify} messages. + * @function encode + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.IEntry} message Entry message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Entry.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.timeMs != null && Object.hasOwnProperty.call(message, "timeMs")) + writer.uint32(/* id 1, wireType 0 =*/8).uint64(message.timeMs); + if (message.revision != null && Object.hasOwnProperty.call(message, "revision")) + writer.uint32(/* id 2, wireType 0 =*/16).uint64(message.revision); + if (message.document != null && Object.hasOwnProperty.call(message, "document")) + writer.uint32(/* id 3, wireType 2 =*/26).bytes(message.document); + return writer; + }; + + /** + * Encodes the specified Entry message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.verify|verify} messages. + * @function encodeDelimited + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.IEntry} message Entry message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Entry.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes an Entry message from the specified reader or buffer. + * @function decode + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry} Entry + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Entry.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.timeMs = reader.uint64(); + break; + case 2: + message.revision = reader.uint64(); + break; + case 3: + message.document = reader.bytes(); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes an Entry message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry} Entry + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Entry.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies an Entry message. + * @function verify + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + Entry.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.timeMs != null && message.hasOwnProperty("timeMs")) + if (!$util.isInteger(message.timeMs) && !(message.timeMs && $util.isInteger(message.timeMs.low) && $util.isInteger(message.timeMs.high))) + return "timeMs: integer|Long expected"; + if (message.revision != null && message.hasOwnProperty("revision")) + if (!$util.isInteger(message.revision) && !(message.revision && $util.isInteger(message.revision.low) && $util.isInteger(message.revision.high))) + return "revision: integer|Long expected"; + if (message.document != null && message.hasOwnProperty("document")) + if (!(message.document && typeof message.document.length === "number" || $util.isString(message.document))) + return "document: buffer expected"; + return null; + }; + + /** + * Creates an Entry message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry + * @static + * @param {Object.} object Plain object + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry} Entry + */ + Entry.fromObject = function fromObject(object) { + if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry) + return object; + var message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry(); + if (object.timeMs != null) + if ($util.Long) + (message.timeMs = $util.Long.fromValue(object.timeMs)).unsigned = true; + else if (typeof object.timeMs === "string") + message.timeMs = parseInt(object.timeMs, 10); + else if (typeof object.timeMs === "number") + message.timeMs = object.timeMs; + else if (typeof object.timeMs === "object") + message.timeMs = new $util.LongBits(object.timeMs.low >>> 0, object.timeMs.high >>> 0).toNumber(true); + if (object.revision != null) + if ($util.Long) + (message.revision = $util.Long.fromValue(object.revision)).unsigned = true; + else if (typeof object.revision === "string") + message.revision = parseInt(object.revision, 10); + else if (typeof object.revision === "number") + message.revision = object.revision; + else if (typeof object.revision === "object") + message.revision = new $util.LongBits(object.revision.low >>> 0, object.revision.high >>> 0).toNumber(true); + if (object.document != null) + if (typeof object.document === "string") + $util.base64.decode(object.document, message.document = $util.newBuffer($util.base64.length(object.document)), 0); + else if (object.document.length >= 0) + message.document = object.document; + return message; + }; + + /** + * Creates a plain object from an Entry message. Also converts values to other types if specified. + * @function toObject + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry} message Entry + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + Entry.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.defaults) { + if ($util.Long) { + var long = new $util.Long(0, 0, true); + object.timeMs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else + object.timeMs = options.longs === String ? "0" : 0; + if ($util.Long) { + var long = new $util.Long(0, 0, true); + object.revision = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else + object.revision = options.longs === String ? "0" : 0; + if (options.bytes === String) + object.document = ""; + else { + object.document = []; + if (options.bytes !== Array) + object.document = $util.newBuffer(object.document); + } + } + if (message.timeMs != null && message.hasOwnProperty("timeMs")) + if (typeof message.timeMs === "number") + object.timeMs = options.longs === String ? String(message.timeMs) : message.timeMs; + else + object.timeMs = options.longs === String ? $util.Long.prototype.toString.call(message.timeMs) : options.longs === Number ? new $util.LongBits(message.timeMs.low >>> 0, message.timeMs.high >>> 0).toNumber(true) : message.timeMs; + if (message.revision != null && message.hasOwnProperty("revision")) + if (typeof message.revision === "number") + object.revision = options.longs === String ? String(message.revision) : message.revision; + else + object.revision = options.longs === String ? $util.Long.prototype.toString.call(message.revision) : options.longs === Number ? new $util.LongBits(message.revision.low >>> 0, message.revision.high >>> 0).toNumber(true) : message.revision; + if (message.document != null && message.hasOwnProperty("document")) + object.document = options.bytes === String ? $util.base64.encode(message.document, 0, message.document.length) : options.bytes === Array ? Array.prototype.slice.call(message.document) : message.document; + return object; + }; + + /** + * Converts this Entry to JSON. + * @function toJSON + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry + * @instance + * @returns {Object.} JSON object + */ + Entry.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; - GetDocumentHistoryResponseV0.DocumentHistoryEntry = (function() { + return Entry; + })(); + + GetDocumentHistoryResponseV1.Lifecycle = (function() { /** - * Properties of a DocumentHistoryEntry. - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 - * @interface IDocumentHistoryEntry - * @property {number|Long|null} [date] DocumentHistoryEntry date - * @property {Uint8Array|null} [value] DocumentHistoryEntry value + * Properties of a Lifecycle. + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 + * @interface ILifecycle + * @property {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.State|null} [state] Lifecycle state + * @property {number|Long|null} [remainingRevisions] Lifecycle remainingRevisions */ /** - * Constructs a new DocumentHistoryEntry. - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 - * @classdesc Represents a DocumentHistoryEntry. - * @implements IDocumentHistoryEntry + * Constructs a new Lifecycle. + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 + * @classdesc Represents a Lifecycle. + * @implements ILifecycle * @constructor - * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistoryEntry=} [properties] Properties to set + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.ILifecycle=} [properties] Properties to set */ - function DocumentHistoryEntry(properties) { + function Lifecycle(properties) { if (properties) for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) if (properties[keys[i]] != null) @@ -53464,88 +55213,88 @@ $root.org = (function() { } /** - * DocumentHistoryEntry date. - * @member {number|Long} date - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * Lifecycle state. + * @member {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.State} state + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle * @instance */ - DocumentHistoryEntry.prototype.date = $util.Long ? $util.Long.fromBits(0,0,true) : 0; + Lifecycle.prototype.state = 0; /** - * DocumentHistoryEntry value. - * @member {Uint8Array} value - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * Lifecycle remainingRevisions. + * @member {number|Long} remainingRevisions + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle * @instance */ - DocumentHistoryEntry.prototype.value = $util.newBuffer([]); + Lifecycle.prototype.remainingRevisions = $util.Long ? $util.Long.fromBits(0,0,true) : 0; /** - * Creates a new DocumentHistoryEntry instance using the specified properties. + * Creates a new Lifecycle instance using the specified properties. * @function create - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle * @static - * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistoryEntry=} [properties] Properties to set - * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} DocumentHistoryEntry instance + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.ILifecycle=} [properties] Properties to set + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle} Lifecycle instance */ - DocumentHistoryEntry.create = function create(properties) { - return new DocumentHistoryEntry(properties); + Lifecycle.create = function create(properties) { + return new Lifecycle(properties); }; /** - * Encodes the specified DocumentHistoryEntry message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.verify|verify} messages. + * Encodes the specified Lifecycle message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.verify|verify} messages. * @function encode - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle * @static - * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistoryEntry} message DocumentHistoryEntry message or plain object to encode + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.ILifecycle} message Lifecycle message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - DocumentHistoryEntry.encode = function encode(message, writer) { + Lifecycle.encode = function encode(message, writer) { if (!writer) writer = $Writer.create(); - if (message.date != null && Object.hasOwnProperty.call(message, "date")) - writer.uint32(/* id 1, wireType 0 =*/8).uint64(message.date); - if (message.value != null && Object.hasOwnProperty.call(message, "value")) - writer.uint32(/* id 2, wireType 2 =*/18).bytes(message.value); + if (message.state != null && Object.hasOwnProperty.call(message, "state")) + writer.uint32(/* id 1, wireType 0 =*/8).int32(message.state); + if (message.remainingRevisions != null && Object.hasOwnProperty.call(message, "remainingRevisions")) + writer.uint32(/* id 2, wireType 0 =*/16).uint64(message.remainingRevisions); return writer; }; /** - * Encodes the specified DocumentHistoryEntry message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.verify|verify} messages. + * Encodes the specified Lifecycle message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.verify|verify} messages. * @function encodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle * @static - * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistoryEntry} message DocumentHistoryEntry message or plain object to encode + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.ILifecycle} message Lifecycle message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - DocumentHistoryEntry.encodeDelimited = function encodeDelimited(message, writer) { + Lifecycle.encodeDelimited = function encodeDelimited(message, writer) { return this.encode(message, writer).ldelim(); }; /** - * Decodes a DocumentHistoryEntry message from the specified reader or buffer. + * Decodes a Lifecycle message from the specified reader or buffer. * @function decode - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle * @static * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from * @param {number} [length] Message length if known beforehand - * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} DocumentHistoryEntry + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle} Lifecycle * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - DocumentHistoryEntry.decode = function decode(reader, length) { + Lifecycle.decode = function decode(reader, length) { if (!(reader instanceof $Reader)) reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry(); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle(); while (reader.pos < end) { var tag = reader.uint32(); switch (tag >>> 3) { case 1: - message.date = reader.uint64(); + message.state = reader.int32(); break; case 2: - message.value = reader.bytes(); + message.remainingRevisions = reader.uint64(); break; default: reader.skipType(tag & 7); @@ -53556,140 +55305,159 @@ $root.org = (function() { }; /** - * Decodes a DocumentHistoryEntry message from the specified reader or buffer, length delimited. + * Decodes a Lifecycle message from the specified reader or buffer, length delimited. * @function decodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle * @static * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} DocumentHistoryEntry + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle} Lifecycle * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - DocumentHistoryEntry.decodeDelimited = function decodeDelimited(reader) { + Lifecycle.decodeDelimited = function decodeDelimited(reader) { if (!(reader instanceof $Reader)) reader = new $Reader(reader); return this.decode(reader, reader.uint32()); }; /** - * Verifies a DocumentHistoryEntry message. + * Verifies a Lifecycle message. * @function verify - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle * @static * @param {Object.} message Plain object to verify * @returns {string|null} `null` if valid, otherwise the reason why it is not */ - DocumentHistoryEntry.verify = function verify(message) { + Lifecycle.verify = function verify(message) { if (typeof message !== "object" || message === null) return "object expected"; - if (message.date != null && message.hasOwnProperty("date")) - if (!$util.isInteger(message.date) && !(message.date && $util.isInteger(message.date.low) && $util.isInteger(message.date.high))) - return "date: integer|Long expected"; - if (message.value != null && message.hasOwnProperty("value")) - if (!(message.value && typeof message.value.length === "number" || $util.isString(message.value))) - return "value: buffer expected"; + if (message.state != null && message.hasOwnProperty("state")) + switch (message.state) { + default: + return "state: enum value expected"; + case 0: + case 1: + break; + } + if (message.remainingRevisions != null && message.hasOwnProperty("remainingRevisions")) + if (!$util.isInteger(message.remainingRevisions) && !(message.remainingRevisions && $util.isInteger(message.remainingRevisions.low) && $util.isInteger(message.remainingRevisions.high))) + return "remainingRevisions: integer|Long expected"; return null; }; /** - * Creates a DocumentHistoryEntry message from a plain object. Also converts values to their respective internal types. + * Creates a Lifecycle message from a plain object. Also converts values to their respective internal types. * @function fromObject - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle * @static * @param {Object.} object Plain object - * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} DocumentHistoryEntry + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle} Lifecycle */ - DocumentHistoryEntry.fromObject = function fromObject(object) { - if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry) + Lifecycle.fromObject = function fromObject(object) { + if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle) return object; - var message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry(); - if (object.date != null) + var message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle(); + switch (object.state) { + case "ACTIVE": + case 0: + message.state = 0; + break; + case "ABSENT": + case 1: + message.state = 1; + break; + } + if (object.remainingRevisions != null) if ($util.Long) - (message.date = $util.Long.fromValue(object.date)).unsigned = true; - else if (typeof object.date === "string") - message.date = parseInt(object.date, 10); - else if (typeof object.date === "number") - message.date = object.date; - else if (typeof object.date === "object") - message.date = new $util.LongBits(object.date.low >>> 0, object.date.high >>> 0).toNumber(true); - if (object.value != null) - if (typeof object.value === "string") - $util.base64.decode(object.value, message.value = $util.newBuffer($util.base64.length(object.value)), 0); - else if (object.value.length >= 0) - message.value = object.value; + (message.remainingRevisions = $util.Long.fromValue(object.remainingRevisions)).unsigned = true; + else if (typeof object.remainingRevisions === "string") + message.remainingRevisions = parseInt(object.remainingRevisions, 10); + else if (typeof object.remainingRevisions === "number") + message.remainingRevisions = object.remainingRevisions; + else if (typeof object.remainingRevisions === "object") + message.remainingRevisions = new $util.LongBits(object.remainingRevisions.low >>> 0, object.remainingRevisions.high >>> 0).toNumber(true); return message; }; /** - * Creates a plain object from a DocumentHistoryEntry message. Also converts values to other types if specified. + * Creates a plain object from a Lifecycle message. Also converts values to other types if specified. * @function toObject - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle * @static - * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} message DocumentHistoryEntry + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle} message Lifecycle * @param {$protobuf.IConversionOptions} [options] Conversion options * @returns {Object.} Plain object */ - DocumentHistoryEntry.toObject = function toObject(message, options) { + Lifecycle.toObject = function toObject(message, options) { if (!options) options = {}; var object = {}; if (options.defaults) { + object.state = options.enums === String ? "ACTIVE" : 0; if ($util.Long) { var long = new $util.Long(0, 0, true); - object.date = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + object.remainingRevisions = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; } else - object.date = options.longs === String ? "0" : 0; - if (options.bytes === String) - object.value = ""; - else { - object.value = []; - if (options.bytes !== Array) - object.value = $util.newBuffer(object.value); - } + object.remainingRevisions = options.longs === String ? "0" : 0; } - if (message.date != null && message.hasOwnProperty("date")) - if (typeof message.date === "number") - object.date = options.longs === String ? String(message.date) : message.date; + if (message.state != null && message.hasOwnProperty("state")) + object.state = options.enums === String ? $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.State[message.state] : message.state; + if (message.remainingRevisions != null && message.hasOwnProperty("remainingRevisions")) + if (typeof message.remainingRevisions === "number") + object.remainingRevisions = options.longs === String ? String(message.remainingRevisions) : message.remainingRevisions; else - object.date = options.longs === String ? $util.Long.prototype.toString.call(message.date) : options.longs === Number ? new $util.LongBits(message.date.low >>> 0, message.date.high >>> 0).toNumber(true) : message.date; - if (message.value != null && message.hasOwnProperty("value")) - object.value = options.bytes === String ? $util.base64.encode(message.value, 0, message.value.length) : options.bytes === Array ? Array.prototype.slice.call(message.value) : message.value; + object.remainingRevisions = options.longs === String ? $util.Long.prototype.toString.call(message.remainingRevisions) : options.longs === Number ? new $util.LongBits(message.remainingRevisions.low >>> 0, message.remainingRevisions.high >>> 0).toNumber(true) : message.remainingRevisions; return object; }; /** - * Converts this DocumentHistoryEntry to JSON. + * Converts this Lifecycle to JSON. * @function toJSON - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle * @instance * @returns {Object.} JSON object */ - DocumentHistoryEntry.prototype.toJSON = function toJSON() { + Lifecycle.prototype.toJSON = function toJSON() { return this.constructor.toObject(this, $protobuf.util.toJSONOptions); }; - return DocumentHistoryEntry; + /** + * State enum. + * @name org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.State + * @enum {number} + * @property {number} ACTIVE=0 ACTIVE value + * @property {number} ABSENT=1 ABSENT value + */ + Lifecycle.State = (function() { + var valuesById = {}, values = Object.create(valuesById); + values[valuesById[0] = "ACTIVE"] = 0; + values[valuesById[1] = "ABSENT"] = 1; + return values; + })(); + + return Lifecycle; })(); - GetDocumentHistoryResponseV0.DocumentHistory = (function() { + GetDocumentHistoryResponseV1.History = (function() { /** - * Properties of a DocumentHistory. - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 - * @interface IDocumentHistory - * @property {Array.|null} [documentEntries] DocumentHistory documentEntries + * Properties of a History. + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 + * @interface IHistory + * @property {Array.|null} [entries] History entries + * @property {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.ILifecycle|null} [lifecycle] History lifecycle */ /** - * Constructs a new DocumentHistory. - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 - * @classdesc Represents a DocumentHistory. - * @implements IDocumentHistory + * Constructs a new History. + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 + * @classdesc Represents a History. + * @implements IHistory * @constructor - * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistory=} [properties] Properties to set + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.IHistory=} [properties] Properties to set */ - function DocumentHistory(properties) { - this.documentEntries = []; + function History(properties) { + this.entries = []; if (properties) for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) if (properties[keys[i]] != null) @@ -53697,78 +55465,91 @@ $root.org = (function() { } /** - * DocumentHistory documentEntries. - * @member {Array.} documentEntries - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * History entries. + * @member {Array.} entries + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History * @instance */ - DocumentHistory.prototype.documentEntries = $util.emptyArray; + History.prototype.entries = $util.emptyArray; /** - * Creates a new DocumentHistory instance using the specified properties. + * History lifecycle. + * @member {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.ILifecycle|null|undefined} lifecycle + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History + * @instance + */ + History.prototype.lifecycle = null; + + /** + * Creates a new History instance using the specified properties. * @function create - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History * @static - * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistory=} [properties] Properties to set - * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} DocumentHistory instance + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.IHistory=} [properties] Properties to set + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History} History instance */ - DocumentHistory.create = function create(properties) { - return new DocumentHistory(properties); + History.create = function create(properties) { + return new History(properties); }; /** - * Encodes the specified DocumentHistory message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.verify|verify} messages. + * Encodes the specified History message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.verify|verify} messages. * @function encode - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History * @static - * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistory} message DocumentHistory message or plain object to encode + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.IHistory} message History message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - DocumentHistory.encode = function encode(message, writer) { + History.encode = function encode(message, writer) { if (!writer) writer = $Writer.create(); - if (message.documentEntries != null && message.documentEntries.length) - for (var i = 0; i < message.documentEntries.length; ++i) - $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.encode(message.documentEntries[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); + if (message.entries != null && message.entries.length) + for (var i = 0; i < message.entries.length; ++i) + $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.encode(message.entries[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); + if (message.lifecycle != null && Object.hasOwnProperty.call(message, "lifecycle")) + $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.encode(message.lifecycle, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); return writer; }; /** - * Encodes the specified DocumentHistory message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.verify|verify} messages. + * Encodes the specified History message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.verify|verify} messages. * @function encodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History * @static - * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistory} message DocumentHistory message or plain object to encode + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.IHistory} message History message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - DocumentHistory.encodeDelimited = function encodeDelimited(message, writer) { + History.encodeDelimited = function encodeDelimited(message, writer) { return this.encode(message, writer).ldelim(); }; /** - * Decodes a DocumentHistory message from the specified reader or buffer. + * Decodes a History message from the specified reader or buffer. * @function decode - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History * @static * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from * @param {number} [length] Message length if known beforehand - * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} DocumentHistory + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History} History * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - DocumentHistory.decode = function decode(reader, length) { + History.decode = function decode(reader, length) { if (!(reader instanceof $Reader)) reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory(); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History(); while (reader.pos < end) { var tag = reader.uint32(); switch (tag >>> 3) { case 1: - if (!(message.documentEntries && message.documentEntries.length)) - message.documentEntries = []; - message.documentEntries.push($root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.decode(reader, reader.uint32())); + if (!(message.entries && message.entries.length)) + message.entries = []; + message.entries.push($root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.decode(reader, reader.uint32())); + break; + case 2: + message.lifecycle = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.decode(reader, reader.uint32()); break; default: reader.skipType(tag & 7); @@ -53779,107 +55560,121 @@ $root.org = (function() { }; /** - * Decodes a DocumentHistory message from the specified reader or buffer, length delimited. + * Decodes a History message from the specified reader or buffer, length delimited. * @function decodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History * @static * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} DocumentHistory + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History} History * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - DocumentHistory.decodeDelimited = function decodeDelimited(reader) { + History.decodeDelimited = function decodeDelimited(reader) { if (!(reader instanceof $Reader)) reader = new $Reader(reader); return this.decode(reader, reader.uint32()); }; /** - * Verifies a DocumentHistory message. + * Verifies a History message. * @function verify - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History * @static * @param {Object.} message Plain object to verify * @returns {string|null} `null` if valid, otherwise the reason why it is not */ - DocumentHistory.verify = function verify(message) { + History.verify = function verify(message) { if (typeof message !== "object" || message === null) return "object expected"; - if (message.documentEntries != null && message.hasOwnProperty("documentEntries")) { - if (!Array.isArray(message.documentEntries)) - return "documentEntries: array expected"; - for (var i = 0; i < message.documentEntries.length; ++i) { - var error = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.verify(message.documentEntries[i]); + if (message.entries != null && message.hasOwnProperty("entries")) { + if (!Array.isArray(message.entries)) + return "entries: array expected"; + for (var i = 0; i < message.entries.length; ++i) { + var error = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.verify(message.entries[i]); if (error) - return "documentEntries." + error; + return "entries." + error; } } + if (message.lifecycle != null && message.hasOwnProperty("lifecycle")) { + var error = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.verify(message.lifecycle); + if (error) + return "lifecycle." + error; + } return null; }; /** - * Creates a DocumentHistory message from a plain object. Also converts values to their respective internal types. + * Creates a History message from a plain object. Also converts values to their respective internal types. * @function fromObject - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History * @static * @param {Object.} object Plain object - * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} DocumentHistory + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History} History */ - DocumentHistory.fromObject = function fromObject(object) { - if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory) + History.fromObject = function fromObject(object) { + if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History) return object; - var message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory(); - if (object.documentEntries) { - if (!Array.isArray(object.documentEntries)) - throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.documentEntries: array expected"); - message.documentEntries = []; - for (var i = 0; i < object.documentEntries.length; ++i) { - if (typeof object.documentEntries[i] !== "object") - throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.documentEntries: object expected"); - message.documentEntries[i] = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.fromObject(object.documentEntries[i]); + var message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History(); + if (object.entries) { + if (!Array.isArray(object.entries)) + throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.entries: array expected"); + message.entries = []; + for (var i = 0; i < object.entries.length; ++i) { + if (typeof object.entries[i] !== "object") + throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.entries: object expected"); + message.entries[i] = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.fromObject(object.entries[i]); } } + if (object.lifecycle != null) { + if (typeof object.lifecycle !== "object") + throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.lifecycle: object expected"); + message.lifecycle = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.fromObject(object.lifecycle); + } return message; }; /** - * Creates a plain object from a DocumentHistory message. Also converts values to other types if specified. + * Creates a plain object from a History message. Also converts values to other types if specified. * @function toObject - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History * @static - * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} message DocumentHistory + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History} message History * @param {$protobuf.IConversionOptions} [options] Conversion options * @returns {Object.} Plain object */ - DocumentHistory.toObject = function toObject(message, options) { + History.toObject = function toObject(message, options) { if (!options) options = {}; var object = {}; if (options.arrays || options.defaults) - object.documentEntries = []; - if (message.documentEntries && message.documentEntries.length) { - object.documentEntries = []; - for (var j = 0; j < message.documentEntries.length; ++j) - object.documentEntries[j] = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.toObject(message.documentEntries[j], options); + object.entries = []; + if (options.defaults) + object.lifecycle = null; + if (message.entries && message.entries.length) { + object.entries = []; + for (var j = 0; j < message.entries.length; ++j) + object.entries[j] = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.toObject(message.entries[j], options); } + if (message.lifecycle != null && message.hasOwnProperty("lifecycle")) + object.lifecycle = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.toObject(message.lifecycle, options); return object; }; /** - * Converts this DocumentHistory to JSON. + * Converts this History to JSON. * @function toJSON - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History * @instance * @returns {Object.} JSON object */ - DocumentHistory.prototype.toJSON = function toJSON() { + History.prototype.toJSON = function toJSON() { return this.constructor.toObject(this, $protobuf.util.toJSONOptions); }; - return DocumentHistory; + return History; })(); - return GetDocumentHistoryResponseV0; + return GetDocumentHistoryResponseV1; })(); return GetDocumentHistoryResponse; 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 c1cb6558eab..2e5865cdcca 100644 --- a/packages/dapi-grpc/clients/platform/v0/nodejs/platform_pbjs.js +++ b/packages/dapi-grpc/clients/platform/v0/nodejs/platform_pbjs.js @@ -51886,6 +51886,7 @@ $root.org = (function() { * @memberof org.dash.platform.dapi.v0 * @interface IGetDocumentHistoryRequest * @property {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.IGetDocumentHistoryRequestV0|null} [v0] GetDocumentHistoryRequest v0 + * @property {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.IGetDocumentHistoryRequestV1|null} [v1] GetDocumentHistoryRequest v1 */ /** @@ -51911,17 +51912,25 @@ $root.org = (function() { */ GetDocumentHistoryRequest.prototype.v0 = null; + /** + * GetDocumentHistoryRequest v1. + * @member {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.IGetDocumentHistoryRequestV1|null|undefined} v1 + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest + * @instance + */ + GetDocumentHistoryRequest.prototype.v1 = null; + // OneOf field names bound to virtual getters and setters var $oneOfFields; /** * GetDocumentHistoryRequest version. - * @member {"v0"|undefined} version + * @member {"v0"|"v1"|undefined} version * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest * @instance */ Object.defineProperty(GetDocumentHistoryRequest.prototype, "version", { - get: $util.oneOfGetter($oneOfFields = ["v0"]), + get: $util.oneOfGetter($oneOfFields = ["v0", "v1"]), set: $util.oneOfSetter($oneOfFields) }); @@ -51951,6 +51960,8 @@ $root.org = (function() { writer = $Writer.create(); if (message.v0 != null && Object.hasOwnProperty.call(message, "v0")) $root.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0.encode(message.v0, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); + if (message.v1 != null && Object.hasOwnProperty.call(message, "v1")) + $root.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.encode(message.v1, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); return writer; }; @@ -51988,6 +51999,9 @@ $root.org = (function() { case 1: message.v0 = $root.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0.decode(reader, reader.uint32()); break; + case 2: + message.v1 = $root.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.decode(reader, reader.uint32()); + break; default: reader.skipType(tag & 7); break; @@ -52032,6 +52046,16 @@ $root.org = (function() { return "v0." + error; } } + if (message.v1 != null && message.hasOwnProperty("v1")) { + if (properties.version === 1) + return "version: multiple values"; + properties.version = 1; + { + var error = $root.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.verify(message.v1); + if (error) + return "v1." + error; + } + } return null; }; @@ -52052,6 +52076,11 @@ $root.org = (function() { throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryRequest.v0: object expected"); message.v0 = $root.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0.fromObject(object.v0); } + if (object.v1 != null) { + if (typeof object.v1 !== "object") + throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryRequest.v1: object expected"); + message.v1 = $root.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.fromObject(object.v1); + } return message; }; @@ -52073,6 +52102,11 @@ $root.org = (function() { if (options.oneofs) object.version = "v0"; } + if (message.v1 != null && message.hasOwnProperty("v1")) { + object.v1 = $root.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.toObject(message.v1, options); + if (options.oneofs) + object.version = "v1"; + } return object; }; @@ -52449,237 +52483,32 @@ $root.org = (function() { return GetDocumentHistoryRequestV0; })(); - return GetDocumentHistoryRequest; - })(); - - v0.GetDocumentHistoryResponse = (function() { - - /** - * Properties of a GetDocumentHistoryResponse. - * @memberof org.dash.platform.dapi.v0 - * @interface IGetDocumentHistoryResponse - * @property {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.IGetDocumentHistoryResponseV0|null} [v0] GetDocumentHistoryResponse v0 - */ - - /** - * Constructs a new GetDocumentHistoryResponse. - * @memberof org.dash.platform.dapi.v0 - * @classdesc Represents a GetDocumentHistoryResponse. - * @implements IGetDocumentHistoryResponse - * @constructor - * @param {org.dash.platform.dapi.v0.IGetDocumentHistoryResponse=} [properties] Properties to set - */ - function GetDocumentHistoryResponse(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * GetDocumentHistoryResponse v0. - * @member {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.IGetDocumentHistoryResponseV0|null|undefined} v0 - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse - * @instance - */ - GetDocumentHistoryResponse.prototype.v0 = null; - - // OneOf field names bound to virtual getters and setters - var $oneOfFields; - - /** - * GetDocumentHistoryResponse version. - * @member {"v0"|undefined} version - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse - * @instance - */ - Object.defineProperty(GetDocumentHistoryResponse.prototype, "version", { - get: $util.oneOfGetter($oneOfFields = ["v0"]), - set: $util.oneOfSetter($oneOfFields) - }); - - /** - * Creates a new GetDocumentHistoryResponse instance using the specified properties. - * @function create - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse - * @static - * @param {org.dash.platform.dapi.v0.IGetDocumentHistoryResponse=} [properties] Properties to set - * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse} GetDocumentHistoryResponse instance - */ - GetDocumentHistoryResponse.create = function create(properties) { - return new GetDocumentHistoryResponse(properties); - }; - - /** - * Encodes the specified GetDocumentHistoryResponse message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.verify|verify} messages. - * @function encode - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse - * @static - * @param {org.dash.platform.dapi.v0.IGetDocumentHistoryResponse} message GetDocumentHistoryResponse message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - GetDocumentHistoryResponse.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.v0 != null && Object.hasOwnProperty.call(message, "v0")) - $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.encode(message.v0, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified GetDocumentHistoryResponse message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.verify|verify} messages. - * @function encodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse - * @static - * @param {org.dash.platform.dapi.v0.IGetDocumentHistoryResponse} message GetDocumentHistoryResponse message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - GetDocumentHistoryResponse.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a GetDocumentHistoryResponse message from the specified reader or buffer. - * @function decode - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse} GetDocumentHistoryResponse - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - GetDocumentHistoryResponse.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.v0 = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.decode(reader, reader.uint32()); - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a GetDocumentHistoryResponse message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse} GetDocumentHistoryResponse - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - GetDocumentHistoryResponse.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a GetDocumentHistoryResponse message. - * @function verify - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - GetDocumentHistoryResponse.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - var properties = {}; - if (message.v0 != null && message.hasOwnProperty("v0")) { - properties.version = 1; - { - var error = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.verify(message.v0); - if (error) - return "v0." + error; - } - } - return null; - }; - - /** - * Creates a GetDocumentHistoryResponse message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse - * @static - * @param {Object.} object Plain object - * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse} GetDocumentHistoryResponse - */ - GetDocumentHistoryResponse.fromObject = function fromObject(object) { - if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse) - return object; - var message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse(); - if (object.v0 != null) { - if (typeof object.v0 !== "object") - throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryResponse.v0: object expected"); - message.v0 = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.fromObject(object.v0); - } - return message; - }; - - /** - * Creates a plain object from a GetDocumentHistoryResponse message. Also converts values to other types if specified. - * @function toObject - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse - * @static - * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse} message GetDocumentHistoryResponse - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - GetDocumentHistoryResponse.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (message.v0 != null && message.hasOwnProperty("v0")) { - object.v0 = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.toObject(message.v0, options); - if (options.oneofs) - object.version = "v0"; - } - return object; - }; - - /** - * Converts this GetDocumentHistoryResponse to JSON. - * @function toJSON - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse - * @instance - * @returns {Object.} JSON object - */ - GetDocumentHistoryResponse.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 = (function() { + GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 = (function() { /** - * Properties of a GetDocumentHistoryResponseV0. - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse - * @interface IGetDocumentHistoryResponseV0 - * @property {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistory|null} [documentHistory] GetDocumentHistoryResponseV0 documentHistory - * @property {org.dash.platform.dapi.v0.IProof|null} [proof] GetDocumentHistoryResponseV0 proof - * @property {org.dash.platform.dapi.v0.IResponseMetadata|null} [metadata] GetDocumentHistoryResponseV0 metadata + * Properties of a GetDocumentHistoryRequestV1. + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest + * @interface IGetDocumentHistoryRequestV1 + * @property {Uint8Array|null} [dataContractId] GetDocumentHistoryRequestV1 dataContractId + * @property {string|null} [documentTypeName] GetDocumentHistoryRequestV1 documentTypeName + * @property {Uint8Array|null} [documentId] GetDocumentHistoryRequestV1 documentId + * @property {google.protobuf.IUInt32Value|null} [limit] GetDocumentHistoryRequestV1 limit + * @property {boolean|null} [prove] GetDocumentHistoryRequestV1 prove + * @property {number|Long|null} [startAtMs] GetDocumentHistoryRequestV1 startAtMs + * @property {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.ICursor|null} [startAfter] GetDocumentHistoryRequestV1 startAfter + * @property {number|Long|null} [startAtRevision] GetDocumentHistoryRequestV1 startAtRevision + * @property {number|Long|null} [revision] GetDocumentHistoryRequestV1 revision */ /** - * Constructs a new GetDocumentHistoryResponseV0. - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse - * @classdesc Represents a GetDocumentHistoryResponseV0. - * @implements IGetDocumentHistoryResponseV0 + * Constructs a new GetDocumentHistoryRequestV1. + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest + * @classdesc Represents a GetDocumentHistoryRequestV1. + * @implements IGetDocumentHistoryRequestV1 * @constructor - * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.IGetDocumentHistoryResponseV0=} [properties] Properties to set + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.IGetDocumentHistoryRequestV1=} [properties] Properties to set */ - function GetDocumentHistoryResponseV0(properties) { + function GetDocumentHistoryRequestV1(properties) { if (properties) for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) if (properties[keys[i]] != null) @@ -52687,69 +52516,1720 @@ $root.org = (function() { } /** - * GetDocumentHistoryResponseV0 documentHistory. - * @member {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistory|null|undefined} documentHistory + * GetDocumentHistoryRequestV1 dataContractId. + * @member {Uint8Array} dataContractId + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @instance + */ + GetDocumentHistoryRequestV1.prototype.dataContractId = $util.newBuffer([]); + + /** + * GetDocumentHistoryRequestV1 documentTypeName. + * @member {string} documentTypeName + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @instance + */ + GetDocumentHistoryRequestV1.prototype.documentTypeName = ""; + + /** + * GetDocumentHistoryRequestV1 documentId. + * @member {Uint8Array} documentId + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @instance + */ + GetDocumentHistoryRequestV1.prototype.documentId = $util.newBuffer([]); + + /** + * GetDocumentHistoryRequestV1 limit. + * @member {google.protobuf.IUInt32Value|null|undefined} limit + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @instance + */ + GetDocumentHistoryRequestV1.prototype.limit = null; + + /** + * GetDocumentHistoryRequestV1 prove. + * @member {boolean} prove + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @instance + */ + GetDocumentHistoryRequestV1.prototype.prove = false; + + /** + * GetDocumentHistoryRequestV1 startAtMs. + * @member {number|Long} startAtMs + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @instance + */ + GetDocumentHistoryRequestV1.prototype.startAtMs = $util.Long ? $util.Long.fromBits(0,0,true) : 0; + + /** + * GetDocumentHistoryRequestV1 startAfter. + * @member {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.ICursor|null|undefined} startAfter + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @instance + */ + GetDocumentHistoryRequestV1.prototype.startAfter = null; + + /** + * GetDocumentHistoryRequestV1 startAtRevision. + * @member {number|Long} startAtRevision + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @instance + */ + GetDocumentHistoryRequestV1.prototype.startAtRevision = $util.Long ? $util.Long.fromBits(0,0,true) : 0; + + /** + * GetDocumentHistoryRequestV1 revision. + * @member {number|Long} revision + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @instance + */ + GetDocumentHistoryRequestV1.prototype.revision = $util.Long ? $util.Long.fromBits(0,0,true) : 0; + + // OneOf field names bound to virtual getters and setters + var $oneOfFields; + + /** + * GetDocumentHistoryRequestV1 filter. + * @member {"startAtMs"|"startAfter"|"startAtRevision"|"revision"|undefined} filter + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @instance + */ + Object.defineProperty(GetDocumentHistoryRequestV1.prototype, "filter", { + get: $util.oneOfGetter($oneOfFields = ["startAtMs", "startAfter", "startAtRevision", "revision"]), + set: $util.oneOfSetter($oneOfFields) + }); + + /** + * Creates a new GetDocumentHistoryRequestV1 instance using the specified properties. + * @function create + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.IGetDocumentHistoryRequestV1=} [properties] Properties to set + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} GetDocumentHistoryRequestV1 instance + */ + GetDocumentHistoryRequestV1.create = function create(properties) { + return new GetDocumentHistoryRequestV1(properties); + }; + + /** + * Encodes the specified GetDocumentHistoryRequestV1 message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.verify|verify} messages. + * @function encode + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.IGetDocumentHistoryRequestV1} message GetDocumentHistoryRequestV1 message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + GetDocumentHistoryRequestV1.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.dataContractId != null && Object.hasOwnProperty.call(message, "dataContractId")) + writer.uint32(/* id 1, wireType 2 =*/10).bytes(message.dataContractId); + if (message.documentTypeName != null && Object.hasOwnProperty.call(message, "documentTypeName")) + writer.uint32(/* id 2, wireType 2 =*/18).string(message.documentTypeName); + if (message.documentId != null && Object.hasOwnProperty.call(message, "documentId")) + writer.uint32(/* id 3, wireType 2 =*/26).bytes(message.documentId); + if (message.limit != null && Object.hasOwnProperty.call(message, "limit")) + $root.google.protobuf.UInt32Value.encode(message.limit, writer.uint32(/* id 4, wireType 2 =*/34).fork()).ldelim(); + if (message.prove != null && Object.hasOwnProperty.call(message, "prove")) + writer.uint32(/* id 5, wireType 0 =*/40).bool(message.prove); + if (message.startAtMs != null && Object.hasOwnProperty.call(message, "startAtMs")) + writer.uint32(/* id 6, wireType 0 =*/48).uint64(message.startAtMs); + if (message.startAfter != null && Object.hasOwnProperty.call(message, "startAfter")) + $root.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.encode(message.startAfter, writer.uint32(/* id 7, wireType 2 =*/58).fork()).ldelim(); + if (message.startAtRevision != null && Object.hasOwnProperty.call(message, "startAtRevision")) + writer.uint32(/* id 8, wireType 0 =*/64).uint64(message.startAtRevision); + if (message.revision != null && Object.hasOwnProperty.call(message, "revision")) + writer.uint32(/* id 9, wireType 0 =*/72).uint64(message.revision); + return writer; + }; + + /** + * Encodes the specified GetDocumentHistoryRequestV1 message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.verify|verify} messages. + * @function encodeDelimited + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.IGetDocumentHistoryRequestV1} message GetDocumentHistoryRequestV1 message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + GetDocumentHistoryRequestV1.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a GetDocumentHistoryRequestV1 message from the specified reader or buffer. + * @function decode + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} GetDocumentHistoryRequestV1 + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + GetDocumentHistoryRequestV1.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.dataContractId = reader.bytes(); + break; + case 2: + message.documentTypeName = reader.string(); + break; + case 3: + message.documentId = reader.bytes(); + break; + case 4: + message.limit = $root.google.protobuf.UInt32Value.decode(reader, reader.uint32()); + break; + case 5: + message.prove = reader.bool(); + break; + case 6: + message.startAtMs = reader.uint64(); + break; + case 7: + message.startAfter = $root.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.decode(reader, reader.uint32()); + break; + case 8: + message.startAtRevision = reader.uint64(); + break; + case 9: + message.revision = reader.uint64(); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a GetDocumentHistoryRequestV1 message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} GetDocumentHistoryRequestV1 + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + GetDocumentHistoryRequestV1.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a GetDocumentHistoryRequestV1 message. + * @function verify + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + GetDocumentHistoryRequestV1.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + var properties = {}; + if (message.dataContractId != null && message.hasOwnProperty("dataContractId")) + if (!(message.dataContractId && typeof message.dataContractId.length === "number" || $util.isString(message.dataContractId))) + return "dataContractId: buffer expected"; + if (message.documentTypeName != null && message.hasOwnProperty("documentTypeName")) + if (!$util.isString(message.documentTypeName)) + return "documentTypeName: string expected"; + if (message.documentId != null && message.hasOwnProperty("documentId")) + if (!(message.documentId && typeof message.documentId.length === "number" || $util.isString(message.documentId))) + return "documentId: buffer expected"; + if (message.limit != null && message.hasOwnProperty("limit")) { + var error = $root.google.protobuf.UInt32Value.verify(message.limit); + if (error) + return "limit." + error; + } + if (message.prove != null && message.hasOwnProperty("prove")) + if (typeof message.prove !== "boolean") + return "prove: boolean expected"; + if (message.startAtMs != null && message.hasOwnProperty("startAtMs")) { + properties.filter = 1; + if (!$util.isInteger(message.startAtMs) && !(message.startAtMs && $util.isInteger(message.startAtMs.low) && $util.isInteger(message.startAtMs.high))) + return "startAtMs: integer|Long expected"; + } + if (message.startAfter != null && message.hasOwnProperty("startAfter")) { + if (properties.filter === 1) + return "filter: multiple values"; + properties.filter = 1; + { + var error = $root.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.verify(message.startAfter); + if (error) + return "startAfter." + error; + } + } + if (message.startAtRevision != null && message.hasOwnProperty("startAtRevision")) { + if (properties.filter === 1) + return "filter: multiple values"; + properties.filter = 1; + if (!$util.isInteger(message.startAtRevision) && !(message.startAtRevision && $util.isInteger(message.startAtRevision.low) && $util.isInteger(message.startAtRevision.high))) + return "startAtRevision: integer|Long expected"; + } + if (message.revision != null && message.hasOwnProperty("revision")) { + if (properties.filter === 1) + return "filter: multiple values"; + properties.filter = 1; + if (!$util.isInteger(message.revision) && !(message.revision && $util.isInteger(message.revision.low) && $util.isInteger(message.revision.high))) + return "revision: integer|Long expected"; + } + return null; + }; + + /** + * Creates a GetDocumentHistoryRequestV1 message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @static + * @param {Object.} object Plain object + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} GetDocumentHistoryRequestV1 + */ + GetDocumentHistoryRequestV1.fromObject = function fromObject(object) { + if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1) + return object; + var message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1(); + if (object.dataContractId != null) + if (typeof object.dataContractId === "string") + $util.base64.decode(object.dataContractId, message.dataContractId = $util.newBuffer($util.base64.length(object.dataContractId)), 0); + else if (object.dataContractId.length >= 0) + message.dataContractId = object.dataContractId; + if (object.documentTypeName != null) + message.documentTypeName = String(object.documentTypeName); + if (object.documentId != null) + if (typeof object.documentId === "string") + $util.base64.decode(object.documentId, message.documentId = $util.newBuffer($util.base64.length(object.documentId)), 0); + else if (object.documentId.length >= 0) + message.documentId = object.documentId; + if (object.limit != null) { + if (typeof object.limit !== "object") + throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.limit: object expected"); + message.limit = $root.google.protobuf.UInt32Value.fromObject(object.limit); + } + if (object.prove != null) + message.prove = Boolean(object.prove); + if (object.startAtMs != null) + if ($util.Long) + (message.startAtMs = $util.Long.fromValue(object.startAtMs)).unsigned = true; + else if (typeof object.startAtMs === "string") + message.startAtMs = parseInt(object.startAtMs, 10); + else if (typeof object.startAtMs === "number") + message.startAtMs = object.startAtMs; + else if (typeof object.startAtMs === "object") + message.startAtMs = new $util.LongBits(object.startAtMs.low >>> 0, object.startAtMs.high >>> 0).toNumber(true); + if (object.startAfter != null) { + if (typeof object.startAfter !== "object") + throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.startAfter: object expected"); + message.startAfter = $root.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.fromObject(object.startAfter); + } + if (object.startAtRevision != null) + if ($util.Long) + (message.startAtRevision = $util.Long.fromValue(object.startAtRevision)).unsigned = true; + else if (typeof object.startAtRevision === "string") + message.startAtRevision = parseInt(object.startAtRevision, 10); + else if (typeof object.startAtRevision === "number") + message.startAtRevision = object.startAtRevision; + else if (typeof object.startAtRevision === "object") + message.startAtRevision = new $util.LongBits(object.startAtRevision.low >>> 0, object.startAtRevision.high >>> 0).toNumber(true); + if (object.revision != null) + if ($util.Long) + (message.revision = $util.Long.fromValue(object.revision)).unsigned = true; + else if (typeof object.revision === "string") + message.revision = parseInt(object.revision, 10); + else if (typeof object.revision === "number") + message.revision = object.revision; + else if (typeof object.revision === "object") + message.revision = new $util.LongBits(object.revision.low >>> 0, object.revision.high >>> 0).toNumber(true); + return message; + }; + + /** + * Creates a plain object from a GetDocumentHistoryRequestV1 message. Also converts values to other types if specified. + * @function toObject + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} message GetDocumentHistoryRequestV1 + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + GetDocumentHistoryRequestV1.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.defaults) { + if (options.bytes === String) + object.dataContractId = ""; + else { + object.dataContractId = []; + if (options.bytes !== Array) + object.dataContractId = $util.newBuffer(object.dataContractId); + } + object.documentTypeName = ""; + if (options.bytes === String) + object.documentId = ""; + else { + object.documentId = []; + if (options.bytes !== Array) + object.documentId = $util.newBuffer(object.documentId); + } + object.limit = null; + object.prove = false; + } + if (message.dataContractId != null && message.hasOwnProperty("dataContractId")) + object.dataContractId = options.bytes === String ? $util.base64.encode(message.dataContractId, 0, message.dataContractId.length) : options.bytes === Array ? Array.prototype.slice.call(message.dataContractId) : message.dataContractId; + if (message.documentTypeName != null && message.hasOwnProperty("documentTypeName")) + object.documentTypeName = message.documentTypeName; + if (message.documentId != null && message.hasOwnProperty("documentId")) + object.documentId = options.bytes === String ? $util.base64.encode(message.documentId, 0, message.documentId.length) : options.bytes === Array ? Array.prototype.slice.call(message.documentId) : message.documentId; + if (message.limit != null && message.hasOwnProperty("limit")) + object.limit = $root.google.protobuf.UInt32Value.toObject(message.limit, options); + if (message.prove != null && message.hasOwnProperty("prove")) + object.prove = message.prove; + if (message.startAtMs != null && message.hasOwnProperty("startAtMs")) { + if (typeof message.startAtMs === "number") + object.startAtMs = options.longs === String ? String(message.startAtMs) : message.startAtMs; + else + object.startAtMs = options.longs === String ? $util.Long.prototype.toString.call(message.startAtMs) : options.longs === Number ? new $util.LongBits(message.startAtMs.low >>> 0, message.startAtMs.high >>> 0).toNumber(true) : message.startAtMs; + if (options.oneofs) + object.filter = "startAtMs"; + } + if (message.startAfter != null && message.hasOwnProperty("startAfter")) { + object.startAfter = $root.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.toObject(message.startAfter, options); + if (options.oneofs) + object.filter = "startAfter"; + } + if (message.startAtRevision != null && message.hasOwnProperty("startAtRevision")) { + if (typeof message.startAtRevision === "number") + object.startAtRevision = options.longs === String ? String(message.startAtRevision) : message.startAtRevision; + else + object.startAtRevision = options.longs === String ? $util.Long.prototype.toString.call(message.startAtRevision) : options.longs === Number ? new $util.LongBits(message.startAtRevision.low >>> 0, message.startAtRevision.high >>> 0).toNumber(true) : message.startAtRevision; + if (options.oneofs) + object.filter = "startAtRevision"; + } + if (message.revision != null && message.hasOwnProperty("revision")) { + if (typeof message.revision === "number") + object.revision = options.longs === String ? String(message.revision) : message.revision; + else + object.revision = options.longs === String ? $util.Long.prototype.toString.call(message.revision) : options.longs === Number ? new $util.LongBits(message.revision.low >>> 0, message.revision.high >>> 0).toNumber(true) : message.revision; + if (options.oneofs) + object.filter = "revision"; + } + return object; + }; + + /** + * Converts this GetDocumentHistoryRequestV1 to JSON. + * @function toJSON + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @instance + * @returns {Object.} JSON object + */ + GetDocumentHistoryRequestV1.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + GetDocumentHistoryRequestV1.Cursor = (function() { + + /** + * Properties of a Cursor. + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @interface ICursor + * @property {number|Long|null} [timeMs] Cursor timeMs + * @property {number|Long|null} [revision] Cursor revision + */ + + /** + * Constructs a new Cursor. + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 + * @classdesc Represents a Cursor. + * @implements ICursor + * @constructor + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.ICursor=} [properties] Properties to set + */ + function Cursor(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * Cursor timeMs. + * @member {number|Long} timeMs + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor + * @instance + */ + Cursor.prototype.timeMs = $util.Long ? $util.Long.fromBits(0,0,true) : 0; + + /** + * Cursor revision. + * @member {number|Long} revision + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor + * @instance + */ + Cursor.prototype.revision = $util.Long ? $util.Long.fromBits(0,0,true) : 0; + + /** + * Creates a new Cursor instance using the specified properties. + * @function create + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.ICursor=} [properties] Properties to set + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor} Cursor instance + */ + Cursor.create = function create(properties) { + return new Cursor(properties); + }; + + /** + * Encodes the specified Cursor message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.verify|verify} messages. + * @function encode + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.ICursor} message Cursor message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Cursor.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.timeMs != null && Object.hasOwnProperty.call(message, "timeMs")) + writer.uint32(/* id 1, wireType 0 =*/8).uint64(message.timeMs); + if (message.revision != null && Object.hasOwnProperty.call(message, "revision")) + writer.uint32(/* id 2, wireType 0 =*/16).uint64(message.revision); + return writer; + }; + + /** + * Encodes the specified Cursor message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.verify|verify} messages. + * @function encodeDelimited + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.ICursor} message Cursor message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Cursor.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a Cursor message from the specified reader or buffer. + * @function decode + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor} Cursor + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Cursor.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.timeMs = reader.uint64(); + break; + case 2: + message.revision = reader.uint64(); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a Cursor message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor} Cursor + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Cursor.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a Cursor message. + * @function verify + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + Cursor.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.timeMs != null && message.hasOwnProperty("timeMs")) + if (!$util.isInteger(message.timeMs) && !(message.timeMs && $util.isInteger(message.timeMs.low) && $util.isInteger(message.timeMs.high))) + return "timeMs: integer|Long expected"; + if (message.revision != null && message.hasOwnProperty("revision")) + if (!$util.isInteger(message.revision) && !(message.revision && $util.isInteger(message.revision.low) && $util.isInteger(message.revision.high))) + return "revision: integer|Long expected"; + return null; + }; + + /** + * Creates a Cursor message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor + * @static + * @param {Object.} object Plain object + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor} Cursor + */ + Cursor.fromObject = function fromObject(object) { + if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor) + return object; + var message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor(); + if (object.timeMs != null) + if ($util.Long) + (message.timeMs = $util.Long.fromValue(object.timeMs)).unsigned = true; + else if (typeof object.timeMs === "string") + message.timeMs = parseInt(object.timeMs, 10); + else if (typeof object.timeMs === "number") + message.timeMs = object.timeMs; + else if (typeof object.timeMs === "object") + message.timeMs = new $util.LongBits(object.timeMs.low >>> 0, object.timeMs.high >>> 0).toNumber(true); + if (object.revision != null) + if ($util.Long) + (message.revision = $util.Long.fromValue(object.revision)).unsigned = true; + else if (typeof object.revision === "string") + message.revision = parseInt(object.revision, 10); + else if (typeof object.revision === "number") + message.revision = object.revision; + else if (typeof object.revision === "object") + message.revision = new $util.LongBits(object.revision.low >>> 0, object.revision.high >>> 0).toNumber(true); + return message; + }; + + /** + * Creates a plain object from a Cursor message. Also converts values to other types if specified. + * @function toObject + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor} message Cursor + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + Cursor.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.defaults) { + if ($util.Long) { + var long = new $util.Long(0, 0, true); + object.timeMs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else + object.timeMs = options.longs === String ? "0" : 0; + if ($util.Long) { + var long = new $util.Long(0, 0, true); + object.revision = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else + object.revision = options.longs === String ? "0" : 0; + } + if (message.timeMs != null && message.hasOwnProperty("timeMs")) + if (typeof message.timeMs === "number") + object.timeMs = options.longs === String ? String(message.timeMs) : message.timeMs; + else + object.timeMs = options.longs === String ? $util.Long.prototype.toString.call(message.timeMs) : options.longs === Number ? new $util.LongBits(message.timeMs.low >>> 0, message.timeMs.high >>> 0).toNumber(true) : message.timeMs; + if (message.revision != null && message.hasOwnProperty("revision")) + if (typeof message.revision === "number") + object.revision = options.longs === String ? String(message.revision) : message.revision; + else + object.revision = options.longs === String ? $util.Long.prototype.toString.call(message.revision) : options.longs === Number ? new $util.LongBits(message.revision.low >>> 0, message.revision.high >>> 0).toNumber(true) : message.revision; + return object; + }; + + /** + * Converts this Cursor to JSON. + * @function toJSON + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor + * @instance + * @returns {Object.} JSON object + */ + Cursor.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + return Cursor; + })(); + + return GetDocumentHistoryRequestV1; + })(); + + return GetDocumentHistoryRequest; + })(); + + v0.GetDocumentHistoryResponse = (function() { + + /** + * Properties of a GetDocumentHistoryResponse. + * @memberof org.dash.platform.dapi.v0 + * @interface IGetDocumentHistoryResponse + * @property {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.IGetDocumentHistoryResponseV0|null} [v0] GetDocumentHistoryResponse v0 + * @property {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.IGetDocumentHistoryResponseV1|null} [v1] GetDocumentHistoryResponse v1 + */ + + /** + * Constructs a new GetDocumentHistoryResponse. + * @memberof org.dash.platform.dapi.v0 + * @classdesc Represents a GetDocumentHistoryResponse. + * @implements IGetDocumentHistoryResponse + * @constructor + * @param {org.dash.platform.dapi.v0.IGetDocumentHistoryResponse=} [properties] Properties to set + */ + function GetDocumentHistoryResponse(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * GetDocumentHistoryResponse v0. + * @member {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.IGetDocumentHistoryResponseV0|null|undefined} v0 + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse + * @instance + */ + GetDocumentHistoryResponse.prototype.v0 = null; + + /** + * GetDocumentHistoryResponse v1. + * @member {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.IGetDocumentHistoryResponseV1|null|undefined} v1 + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse + * @instance + */ + GetDocumentHistoryResponse.prototype.v1 = null; + + // OneOf field names bound to virtual getters and setters + var $oneOfFields; + + /** + * GetDocumentHistoryResponse version. + * @member {"v0"|"v1"|undefined} version + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse + * @instance + */ + Object.defineProperty(GetDocumentHistoryResponse.prototype, "version", { + get: $util.oneOfGetter($oneOfFields = ["v0", "v1"]), + set: $util.oneOfSetter($oneOfFields) + }); + + /** + * Creates a new GetDocumentHistoryResponse instance using the specified properties. + * @function create + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse + * @static + * @param {org.dash.platform.dapi.v0.IGetDocumentHistoryResponse=} [properties] Properties to set + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse} GetDocumentHistoryResponse instance + */ + GetDocumentHistoryResponse.create = function create(properties) { + return new GetDocumentHistoryResponse(properties); + }; + + /** + * Encodes the specified GetDocumentHistoryResponse message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.verify|verify} messages. + * @function encode + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse + * @static + * @param {org.dash.platform.dapi.v0.IGetDocumentHistoryResponse} message GetDocumentHistoryResponse message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + GetDocumentHistoryResponse.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.v0 != null && Object.hasOwnProperty.call(message, "v0")) + $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.encode(message.v0, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); + if (message.v1 != null && Object.hasOwnProperty.call(message, "v1")) + $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.encode(message.v1, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified GetDocumentHistoryResponse message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.verify|verify} messages. + * @function encodeDelimited + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse + * @static + * @param {org.dash.platform.dapi.v0.IGetDocumentHistoryResponse} message GetDocumentHistoryResponse message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + GetDocumentHistoryResponse.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a GetDocumentHistoryResponse message from the specified reader or buffer. + * @function decode + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse} GetDocumentHistoryResponse + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + GetDocumentHistoryResponse.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.v0 = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.decode(reader, reader.uint32()); + break; + case 2: + message.v1 = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.decode(reader, reader.uint32()); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a GetDocumentHistoryResponse message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse} GetDocumentHistoryResponse + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + GetDocumentHistoryResponse.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a GetDocumentHistoryResponse message. + * @function verify + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + GetDocumentHistoryResponse.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + var properties = {}; + if (message.v0 != null && message.hasOwnProperty("v0")) { + properties.version = 1; + { + var error = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.verify(message.v0); + if (error) + return "v0." + error; + } + } + if (message.v1 != null && message.hasOwnProperty("v1")) { + if (properties.version === 1) + return "version: multiple values"; + properties.version = 1; + { + var error = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.verify(message.v1); + if (error) + return "v1." + error; + } + } + return null; + }; + + /** + * Creates a GetDocumentHistoryResponse message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse + * @static + * @param {Object.} object Plain object + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse} GetDocumentHistoryResponse + */ + GetDocumentHistoryResponse.fromObject = function fromObject(object) { + if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse) + return object; + var message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse(); + if (object.v0 != null) { + if (typeof object.v0 !== "object") + throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryResponse.v0: object expected"); + message.v0 = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.fromObject(object.v0); + } + if (object.v1 != null) { + if (typeof object.v1 !== "object") + throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryResponse.v1: object expected"); + message.v1 = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.fromObject(object.v1); + } + return message; + }; + + /** + * Creates a plain object from a GetDocumentHistoryResponse message. Also converts values to other types if specified. + * @function toObject + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse} message GetDocumentHistoryResponse + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + GetDocumentHistoryResponse.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (message.v0 != null && message.hasOwnProperty("v0")) { + object.v0 = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.toObject(message.v0, options); + if (options.oneofs) + object.version = "v0"; + } + if (message.v1 != null && message.hasOwnProperty("v1")) { + object.v1 = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.toObject(message.v1, options); + if (options.oneofs) + object.version = "v1"; + } + return object; + }; + + /** + * Converts this GetDocumentHistoryResponse to JSON. + * @function toJSON + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse + * @instance + * @returns {Object.} JSON object + */ + GetDocumentHistoryResponse.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 = (function() { + + /** + * Properties of a GetDocumentHistoryResponseV0. + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse + * @interface IGetDocumentHistoryResponseV0 + * @property {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistory|null} [documentHistory] GetDocumentHistoryResponseV0 documentHistory + * @property {org.dash.platform.dapi.v0.IProof|null} [proof] GetDocumentHistoryResponseV0 proof + * @property {org.dash.platform.dapi.v0.IResponseMetadata|null} [metadata] GetDocumentHistoryResponseV0 metadata + */ + + /** + * Constructs a new GetDocumentHistoryResponseV0. + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse + * @classdesc Represents a GetDocumentHistoryResponseV0. + * @implements IGetDocumentHistoryResponseV0 + * @constructor + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.IGetDocumentHistoryResponseV0=} [properties] Properties to set + */ + function GetDocumentHistoryResponseV0(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * GetDocumentHistoryResponseV0 documentHistory. + * @member {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistory|null|undefined} documentHistory + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @instance + */ + GetDocumentHistoryResponseV0.prototype.documentHistory = null; + + /** + * GetDocumentHistoryResponseV0 proof. + * @member {org.dash.platform.dapi.v0.IProof|null|undefined} proof + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @instance + */ + GetDocumentHistoryResponseV0.prototype.proof = null; + + /** + * GetDocumentHistoryResponseV0 metadata. + * @member {org.dash.platform.dapi.v0.IResponseMetadata|null|undefined} metadata + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @instance + */ + GetDocumentHistoryResponseV0.prototype.metadata = null; + + // OneOf field names bound to virtual getters and setters + var $oneOfFields; + + /** + * GetDocumentHistoryResponseV0 result. + * @member {"documentHistory"|"proof"|undefined} result + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @instance + */ + Object.defineProperty(GetDocumentHistoryResponseV0.prototype, "result", { + get: $util.oneOfGetter($oneOfFields = ["documentHistory", "proof"]), + set: $util.oneOfSetter($oneOfFields) + }); + + /** + * Creates a new GetDocumentHistoryResponseV0 instance using the specified properties. + * @function create + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.IGetDocumentHistoryResponseV0=} [properties] Properties to set + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} GetDocumentHistoryResponseV0 instance + */ + GetDocumentHistoryResponseV0.create = function create(properties) { + return new GetDocumentHistoryResponseV0(properties); + }; + + /** + * Encodes the specified GetDocumentHistoryResponseV0 message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.verify|verify} messages. + * @function encode + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.IGetDocumentHistoryResponseV0} message GetDocumentHistoryResponseV0 message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + GetDocumentHistoryResponseV0.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.documentHistory != null && Object.hasOwnProperty.call(message, "documentHistory")) + $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.encode(message.documentHistory, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); + if (message.proof != null && Object.hasOwnProperty.call(message, "proof")) + $root.org.dash.platform.dapi.v0.Proof.encode(message.proof, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); + if (message.metadata != null && Object.hasOwnProperty.call(message, "metadata")) + $root.org.dash.platform.dapi.v0.ResponseMetadata.encode(message.metadata, writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified GetDocumentHistoryResponseV0 message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.verify|verify} messages. + * @function encodeDelimited + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.IGetDocumentHistoryResponseV0} message GetDocumentHistoryResponseV0 message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + GetDocumentHistoryResponseV0.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a GetDocumentHistoryResponseV0 message from the specified reader or buffer. + * @function decode + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} GetDocumentHistoryResponseV0 + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + GetDocumentHistoryResponseV0.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.documentHistory = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.decode(reader, reader.uint32()); + break; + case 2: + message.proof = $root.org.dash.platform.dapi.v0.Proof.decode(reader, reader.uint32()); + break; + case 3: + message.metadata = $root.org.dash.platform.dapi.v0.ResponseMetadata.decode(reader, reader.uint32()); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a GetDocumentHistoryResponseV0 message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} GetDocumentHistoryResponseV0 + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + GetDocumentHistoryResponseV0.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a GetDocumentHistoryResponseV0 message. + * @function verify + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + GetDocumentHistoryResponseV0.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + var properties = {}; + if (message.documentHistory != null && message.hasOwnProperty("documentHistory")) { + properties.result = 1; + { + var error = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.verify(message.documentHistory); + if (error) + return "documentHistory." + error; + } + } + if (message.proof != null && message.hasOwnProperty("proof")) { + if (properties.result === 1) + return "result: multiple values"; + properties.result = 1; + { + var error = $root.org.dash.platform.dapi.v0.Proof.verify(message.proof); + if (error) + return "proof." + error; + } + } + if (message.metadata != null && message.hasOwnProperty("metadata")) { + var error = $root.org.dash.platform.dapi.v0.ResponseMetadata.verify(message.metadata); + if (error) + return "metadata." + error; + } + return null; + }; + + /** + * Creates a GetDocumentHistoryResponseV0 message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @static + * @param {Object.} object Plain object + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} GetDocumentHistoryResponseV0 + */ + GetDocumentHistoryResponseV0.fromObject = function fromObject(object) { + if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0) + return object; + var message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0(); + if (object.documentHistory != null) { + if (typeof object.documentHistory !== "object") + throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.documentHistory: object expected"); + message.documentHistory = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.fromObject(object.documentHistory); + } + if (object.proof != null) { + if (typeof object.proof !== "object") + throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.proof: object expected"); + message.proof = $root.org.dash.platform.dapi.v0.Proof.fromObject(object.proof); + } + if (object.metadata != null) { + if (typeof object.metadata !== "object") + throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.metadata: object expected"); + message.metadata = $root.org.dash.platform.dapi.v0.ResponseMetadata.fromObject(object.metadata); + } + return message; + }; + + /** + * Creates a plain object from a GetDocumentHistoryResponseV0 message. Also converts values to other types if specified. + * @function toObject + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} message GetDocumentHistoryResponseV0 + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + GetDocumentHistoryResponseV0.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.defaults) + object.metadata = null; + if (message.documentHistory != null && message.hasOwnProperty("documentHistory")) { + object.documentHistory = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.toObject(message.documentHistory, options); + if (options.oneofs) + object.result = "documentHistory"; + } + if (message.proof != null && message.hasOwnProperty("proof")) { + object.proof = $root.org.dash.platform.dapi.v0.Proof.toObject(message.proof, options); + if (options.oneofs) + object.result = "proof"; + } + if (message.metadata != null && message.hasOwnProperty("metadata")) + object.metadata = $root.org.dash.platform.dapi.v0.ResponseMetadata.toObject(message.metadata, options); + return object; + }; + + /** + * Converts this GetDocumentHistoryResponseV0 to JSON. + * @function toJSON * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 * @instance + * @returns {Object.} JSON object + */ + GetDocumentHistoryResponseV0.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + GetDocumentHistoryResponseV0.DocumentHistoryEntry = (function() { + + /** + * Properties of a DocumentHistoryEntry. + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @interface IDocumentHistoryEntry + * @property {number|Long|null} [date] DocumentHistoryEntry date + * @property {Uint8Array|null} [value] DocumentHistoryEntry value + */ + + /** + * Constructs a new DocumentHistoryEntry. + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @classdesc Represents a DocumentHistoryEntry. + * @implements IDocumentHistoryEntry + * @constructor + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistoryEntry=} [properties] Properties to set + */ + function DocumentHistoryEntry(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * DocumentHistoryEntry date. + * @member {number|Long} date + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @instance + */ + DocumentHistoryEntry.prototype.date = $util.Long ? $util.Long.fromBits(0,0,true) : 0; + + /** + * DocumentHistoryEntry value. + * @member {Uint8Array} value + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @instance + */ + DocumentHistoryEntry.prototype.value = $util.newBuffer([]); + + /** + * Creates a new DocumentHistoryEntry instance using the specified properties. + * @function create + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistoryEntry=} [properties] Properties to set + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} DocumentHistoryEntry instance + */ + DocumentHistoryEntry.create = function create(properties) { + return new DocumentHistoryEntry(properties); + }; + + /** + * Encodes the specified DocumentHistoryEntry message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.verify|verify} messages. + * @function encode + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistoryEntry} message DocumentHistoryEntry message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + DocumentHistoryEntry.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.date != null && Object.hasOwnProperty.call(message, "date")) + writer.uint32(/* id 1, wireType 0 =*/8).uint64(message.date); + if (message.value != null && Object.hasOwnProperty.call(message, "value")) + writer.uint32(/* id 2, wireType 2 =*/18).bytes(message.value); + return writer; + }; + + /** + * Encodes the specified DocumentHistoryEntry message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.verify|verify} messages. + * @function encodeDelimited + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistoryEntry} message DocumentHistoryEntry message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + DocumentHistoryEntry.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a DocumentHistoryEntry message from the specified reader or buffer. + * @function decode + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} DocumentHistoryEntry + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + DocumentHistoryEntry.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.date = reader.uint64(); + break; + case 2: + message.value = reader.bytes(); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a DocumentHistoryEntry message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} DocumentHistoryEntry + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + DocumentHistoryEntry.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a DocumentHistoryEntry message. + * @function verify + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + DocumentHistoryEntry.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.date != null && message.hasOwnProperty("date")) + if (!$util.isInteger(message.date) && !(message.date && $util.isInteger(message.date.low) && $util.isInteger(message.date.high))) + return "date: integer|Long expected"; + if (message.value != null && message.hasOwnProperty("value")) + if (!(message.value && typeof message.value.length === "number" || $util.isString(message.value))) + return "value: buffer expected"; + return null; + }; + + /** + * Creates a DocumentHistoryEntry message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @static + * @param {Object.} object Plain object + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} DocumentHistoryEntry + */ + DocumentHistoryEntry.fromObject = function fromObject(object) { + if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry) + return object; + var message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry(); + if (object.date != null) + if ($util.Long) + (message.date = $util.Long.fromValue(object.date)).unsigned = true; + else if (typeof object.date === "string") + message.date = parseInt(object.date, 10); + else if (typeof object.date === "number") + message.date = object.date; + else if (typeof object.date === "object") + message.date = new $util.LongBits(object.date.low >>> 0, object.date.high >>> 0).toNumber(true); + if (object.value != null) + if (typeof object.value === "string") + $util.base64.decode(object.value, message.value = $util.newBuffer($util.base64.length(object.value)), 0); + else if (object.value.length >= 0) + message.value = object.value; + return message; + }; + + /** + * Creates a plain object from a DocumentHistoryEntry message. Also converts values to other types if specified. + * @function toObject + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} message DocumentHistoryEntry + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + DocumentHistoryEntry.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.defaults) { + if ($util.Long) { + var long = new $util.Long(0, 0, true); + object.date = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else + object.date = options.longs === String ? "0" : 0; + if (options.bytes === String) + object.value = ""; + else { + object.value = []; + if (options.bytes !== Array) + object.value = $util.newBuffer(object.value); + } + } + if (message.date != null && message.hasOwnProperty("date")) + if (typeof message.date === "number") + object.date = options.longs === String ? String(message.date) : message.date; + else + object.date = options.longs === String ? $util.Long.prototype.toString.call(message.date) : options.longs === Number ? new $util.LongBits(message.date.low >>> 0, message.date.high >>> 0).toNumber(true) : message.date; + if (message.value != null && message.hasOwnProperty("value")) + object.value = options.bytes === String ? $util.base64.encode(message.value, 0, message.value.length) : options.bytes === Array ? Array.prototype.slice.call(message.value) : message.value; + return object; + }; + + /** + * Converts this DocumentHistoryEntry to JSON. + * @function toJSON + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @instance + * @returns {Object.} JSON object + */ + DocumentHistoryEntry.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + return DocumentHistoryEntry; + })(); + + GetDocumentHistoryResponseV0.DocumentHistory = (function() { + + /** + * Properties of a DocumentHistory. + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @interface IDocumentHistory + * @property {Array.|null} [documentEntries] DocumentHistory documentEntries + */ + + /** + * Constructs a new DocumentHistory. + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @classdesc Represents a DocumentHistory. + * @implements IDocumentHistory + * @constructor + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistory=} [properties] Properties to set + */ + function DocumentHistory(properties) { + this.documentEntries = []; + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * DocumentHistory documentEntries. + * @member {Array.} documentEntries + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * @instance + */ + DocumentHistory.prototype.documentEntries = $util.emptyArray; + + /** + * Creates a new DocumentHistory instance using the specified properties. + * @function create + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistory=} [properties] Properties to set + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} DocumentHistory instance + */ + DocumentHistory.create = function create(properties) { + return new DocumentHistory(properties); + }; + + /** + * Encodes the specified DocumentHistory message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.verify|verify} messages. + * @function encode + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistory} message DocumentHistory message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + DocumentHistory.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.documentEntries != null && message.documentEntries.length) + for (var i = 0; i < message.documentEntries.length; ++i) + $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.encode(message.documentEntries[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified DocumentHistory message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.verify|verify} messages. + * @function encodeDelimited + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistory} message DocumentHistory message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + DocumentHistory.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a DocumentHistory message from the specified reader or buffer. + * @function decode + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} DocumentHistory + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + DocumentHistory.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + if (!(message.documentEntries && message.documentEntries.length)) + message.documentEntries = []; + message.documentEntries.push($root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.decode(reader, reader.uint32())); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a DocumentHistory message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} DocumentHistory + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + DocumentHistory.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a DocumentHistory message. + * @function verify + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + DocumentHistory.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.documentEntries != null && message.hasOwnProperty("documentEntries")) { + if (!Array.isArray(message.documentEntries)) + return "documentEntries: array expected"; + for (var i = 0; i < message.documentEntries.length; ++i) { + var error = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.verify(message.documentEntries[i]); + if (error) + return "documentEntries." + error; + } + } + return null; + }; + + /** + * Creates a DocumentHistory message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * @static + * @param {Object.} object Plain object + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} DocumentHistory + */ + DocumentHistory.fromObject = function fromObject(object) { + if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory) + return object; + var message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory(); + if (object.documentEntries) { + if (!Array.isArray(object.documentEntries)) + throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.documentEntries: array expected"); + message.documentEntries = []; + for (var i = 0; i < object.documentEntries.length; ++i) { + if (typeof object.documentEntries[i] !== "object") + throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.documentEntries: object expected"); + message.documentEntries[i] = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.fromObject(object.documentEntries[i]); + } + } + return message; + }; + + /** + * Creates a plain object from a DocumentHistory message. Also converts values to other types if specified. + * @function toObject + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} message DocumentHistory + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + DocumentHistory.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.arrays || options.defaults) + object.documentEntries = []; + if (message.documentEntries && message.documentEntries.length) { + object.documentEntries = []; + for (var j = 0; j < message.documentEntries.length; ++j) + object.documentEntries[j] = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.toObject(message.documentEntries[j], options); + } + return object; + }; + + /** + * Converts this DocumentHistory to JSON. + * @function toJSON + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * @instance + * @returns {Object.} JSON object + */ + DocumentHistory.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + return DocumentHistory; + })(); + + return GetDocumentHistoryResponseV0; + })(); + + GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 = (function() { + + /** + * Properties of a GetDocumentHistoryResponseV1. + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse + * @interface IGetDocumentHistoryResponseV1 + * @property {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.IHistory|null} [history] GetDocumentHistoryResponseV1 history + * @property {org.dash.platform.dapi.v0.IProof|null} [proof] GetDocumentHistoryResponseV1 proof + * @property {org.dash.platform.dapi.v0.IResponseMetadata|null} [metadata] GetDocumentHistoryResponseV1 metadata + */ + + /** + * Constructs a new GetDocumentHistoryResponseV1. + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse + * @classdesc Represents a GetDocumentHistoryResponseV1. + * @implements IGetDocumentHistoryResponseV1 + * @constructor + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.IGetDocumentHistoryResponseV1=} [properties] Properties to set + */ + function GetDocumentHistoryResponseV1(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * GetDocumentHistoryResponseV1 history. + * @member {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.IHistory|null|undefined} history + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 + * @instance */ - GetDocumentHistoryResponseV0.prototype.documentHistory = null; + GetDocumentHistoryResponseV1.prototype.history = null; /** - * GetDocumentHistoryResponseV0 proof. + * GetDocumentHistoryResponseV1 proof. * @member {org.dash.platform.dapi.v0.IProof|null|undefined} proof - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 * @instance */ - GetDocumentHistoryResponseV0.prototype.proof = null; + GetDocumentHistoryResponseV1.prototype.proof = null; /** - * GetDocumentHistoryResponseV0 metadata. + * GetDocumentHistoryResponseV1 metadata. * @member {org.dash.platform.dapi.v0.IResponseMetadata|null|undefined} metadata - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 * @instance */ - GetDocumentHistoryResponseV0.prototype.metadata = null; + GetDocumentHistoryResponseV1.prototype.metadata = null; // OneOf field names bound to virtual getters and setters var $oneOfFields; /** - * GetDocumentHistoryResponseV0 result. - * @member {"documentHistory"|"proof"|undefined} result - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * GetDocumentHistoryResponseV1 result. + * @member {"history"|"proof"|undefined} result + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 * @instance */ - Object.defineProperty(GetDocumentHistoryResponseV0.prototype, "result", { - get: $util.oneOfGetter($oneOfFields = ["documentHistory", "proof"]), + Object.defineProperty(GetDocumentHistoryResponseV1.prototype, "result", { + get: $util.oneOfGetter($oneOfFields = ["history", "proof"]), set: $util.oneOfSetter($oneOfFields) }); /** - * Creates a new GetDocumentHistoryResponseV0 instance using the specified properties. + * Creates a new GetDocumentHistoryResponseV1 instance using the specified properties. * @function create - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 * @static - * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.IGetDocumentHistoryResponseV0=} [properties] Properties to set - * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} GetDocumentHistoryResponseV0 instance + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.IGetDocumentHistoryResponseV1=} [properties] Properties to set + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1} GetDocumentHistoryResponseV1 instance */ - GetDocumentHistoryResponseV0.create = function create(properties) { - return new GetDocumentHistoryResponseV0(properties); + GetDocumentHistoryResponseV1.create = function create(properties) { + return new GetDocumentHistoryResponseV1(properties); }; /** - * Encodes the specified GetDocumentHistoryResponseV0 message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.verify|verify} messages. + * Encodes the specified GetDocumentHistoryResponseV1 message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.verify|verify} messages. * @function encode - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 * @static - * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.IGetDocumentHistoryResponseV0} message GetDocumentHistoryResponseV0 message or plain object to encode + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.IGetDocumentHistoryResponseV1} message GetDocumentHistoryResponseV1 message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - GetDocumentHistoryResponseV0.encode = function encode(message, writer) { + GetDocumentHistoryResponseV1.encode = function encode(message, writer) { if (!writer) writer = $Writer.create(); - if (message.documentHistory != null && Object.hasOwnProperty.call(message, "documentHistory")) - $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.encode(message.documentHistory, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); + if (message.history != null && Object.hasOwnProperty.call(message, "history")) + $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.encode(message.history, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); if (message.proof != null && Object.hasOwnProperty.call(message, "proof")) $root.org.dash.platform.dapi.v0.Proof.encode(message.proof, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); if (message.metadata != null && Object.hasOwnProperty.call(message, "metadata")) @@ -52758,38 +54238,38 @@ $root.org = (function() { }; /** - * Encodes the specified GetDocumentHistoryResponseV0 message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.verify|verify} messages. + * Encodes the specified GetDocumentHistoryResponseV1 message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.verify|verify} messages. * @function encodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 * @static - * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.IGetDocumentHistoryResponseV0} message GetDocumentHistoryResponseV0 message or plain object to encode + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.IGetDocumentHistoryResponseV1} message GetDocumentHistoryResponseV1 message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - GetDocumentHistoryResponseV0.encodeDelimited = function encodeDelimited(message, writer) { + GetDocumentHistoryResponseV1.encodeDelimited = function encodeDelimited(message, writer) { return this.encode(message, writer).ldelim(); }; /** - * Decodes a GetDocumentHistoryResponseV0 message from the specified reader or buffer. + * Decodes a GetDocumentHistoryResponseV1 message from the specified reader or buffer. * @function decode - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 * @static * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from * @param {number} [length] Message length if known beforehand - * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} GetDocumentHistoryResponseV0 + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1} GetDocumentHistoryResponseV1 * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - GetDocumentHistoryResponseV0.decode = function decode(reader, length) { + GetDocumentHistoryResponseV1.decode = function decode(reader, length) { if (!(reader instanceof $Reader)) reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0(); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1(); while (reader.pos < end) { var tag = reader.uint32(); switch (tag >>> 3) { case 1: - message.documentHistory = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.decode(reader, reader.uint32()); + message.history = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.decode(reader, reader.uint32()); break; case 2: message.proof = $root.org.dash.platform.dapi.v0.Proof.decode(reader, reader.uint32()); @@ -52806,39 +54286,39 @@ $root.org = (function() { }; /** - * Decodes a GetDocumentHistoryResponseV0 message from the specified reader or buffer, length delimited. + * Decodes a GetDocumentHistoryResponseV1 message from the specified reader or buffer, length delimited. * @function decodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 * @static * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} GetDocumentHistoryResponseV0 + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1} GetDocumentHistoryResponseV1 * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - GetDocumentHistoryResponseV0.decodeDelimited = function decodeDelimited(reader) { + GetDocumentHistoryResponseV1.decodeDelimited = function decodeDelimited(reader) { if (!(reader instanceof $Reader)) reader = new $Reader(reader); return this.decode(reader, reader.uint32()); }; /** - * Verifies a GetDocumentHistoryResponseV0 message. + * Verifies a GetDocumentHistoryResponseV1 message. * @function verify - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 * @static * @param {Object.} message Plain object to verify * @returns {string|null} `null` if valid, otherwise the reason why it is not */ - GetDocumentHistoryResponseV0.verify = function verify(message) { + GetDocumentHistoryResponseV1.verify = function verify(message) { if (typeof message !== "object" || message === null) return "object expected"; var properties = {}; - if (message.documentHistory != null && message.hasOwnProperty("documentHistory")) { + if (message.history != null && message.hasOwnProperty("history")) { properties.result = 1; { - var error = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.verify(message.documentHistory); + var error = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.verify(message.history); if (error) - return "documentHistory." + error; + return "history." + error; } } if (message.proof != null && message.hasOwnProperty("proof")) { @@ -52860,54 +54340,54 @@ $root.org = (function() { }; /** - * Creates a GetDocumentHistoryResponseV0 message from a plain object. Also converts values to their respective internal types. + * Creates a GetDocumentHistoryResponseV1 message from a plain object. Also converts values to their respective internal types. * @function fromObject - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 * @static * @param {Object.} object Plain object - * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} GetDocumentHistoryResponseV0 + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1} GetDocumentHistoryResponseV1 */ - GetDocumentHistoryResponseV0.fromObject = function fromObject(object) { - if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0) + GetDocumentHistoryResponseV1.fromObject = function fromObject(object) { + if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1) return object; - var message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0(); - if (object.documentHistory != null) { - if (typeof object.documentHistory !== "object") - throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.documentHistory: object expected"); - message.documentHistory = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.fromObject(object.documentHistory); + var message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1(); + if (object.history != null) { + if (typeof object.history !== "object") + throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.history: object expected"); + message.history = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.fromObject(object.history); } if (object.proof != null) { if (typeof object.proof !== "object") - throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.proof: object expected"); + throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.proof: object expected"); message.proof = $root.org.dash.platform.dapi.v0.Proof.fromObject(object.proof); } if (object.metadata != null) { if (typeof object.metadata !== "object") - throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.metadata: object expected"); + throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.metadata: object expected"); message.metadata = $root.org.dash.platform.dapi.v0.ResponseMetadata.fromObject(object.metadata); } return message; }; /** - * Creates a plain object from a GetDocumentHistoryResponseV0 message. Also converts values to other types if specified. + * Creates a plain object from a GetDocumentHistoryResponseV1 message. Also converts values to other types if specified. * @function toObject - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 * @static - * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} message GetDocumentHistoryResponseV0 + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1} message GetDocumentHistoryResponseV1 * @param {$protobuf.IConversionOptions} [options] Conversion options * @returns {Object.} Plain object */ - GetDocumentHistoryResponseV0.toObject = function toObject(message, options) { + GetDocumentHistoryResponseV1.toObject = function toObject(message, options) { if (!options) options = {}; var object = {}; if (options.defaults) object.metadata = null; - if (message.documentHistory != null && message.hasOwnProperty("documentHistory")) { - object.documentHistory = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.toObject(message.documentHistory, options); + if (message.history != null && message.hasOwnProperty("history")) { + object.history = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.toObject(message.history, options); if (options.oneofs) - object.result = "documentHistory"; + object.result = "history"; } if (message.proof != null && message.hasOwnProperty("proof")) { object.proof = $root.org.dash.platform.dapi.v0.Proof.toObject(message.proof, options); @@ -52919,36 +54399,305 @@ $root.org = (function() { return object; }; - /** - * Converts this GetDocumentHistoryResponseV0 to JSON. - * @function toJSON - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 - * @instance - * @returns {Object.} JSON object - */ - GetDocumentHistoryResponseV0.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; + /** + * Converts this GetDocumentHistoryResponseV1 to JSON. + * @function toJSON + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 + * @instance + * @returns {Object.} JSON object + */ + GetDocumentHistoryResponseV1.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + GetDocumentHistoryResponseV1.Entry = (function() { + + /** + * Properties of an Entry. + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 + * @interface IEntry + * @property {number|Long|null} [timeMs] Entry timeMs + * @property {number|Long|null} [revision] Entry revision + * @property {Uint8Array|null} [document] Entry document + */ + + /** + * Constructs a new Entry. + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 + * @classdesc Represents an Entry. + * @implements IEntry + * @constructor + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.IEntry=} [properties] Properties to set + */ + function Entry(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * Entry timeMs. + * @member {number|Long} timeMs + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry + * @instance + */ + Entry.prototype.timeMs = $util.Long ? $util.Long.fromBits(0,0,true) : 0; + + /** + * Entry revision. + * @member {number|Long} revision + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry + * @instance + */ + Entry.prototype.revision = $util.Long ? $util.Long.fromBits(0,0,true) : 0; + + /** + * Entry document. + * @member {Uint8Array} document + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry + * @instance + */ + Entry.prototype.document = $util.newBuffer([]); + + /** + * Creates a new Entry instance using the specified properties. + * @function create + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.IEntry=} [properties] Properties to set + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry} Entry instance + */ + Entry.create = function create(properties) { + return new Entry(properties); + }; + + /** + * Encodes the specified Entry message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.verify|verify} messages. + * @function encode + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.IEntry} message Entry message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Entry.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.timeMs != null && Object.hasOwnProperty.call(message, "timeMs")) + writer.uint32(/* id 1, wireType 0 =*/8).uint64(message.timeMs); + if (message.revision != null && Object.hasOwnProperty.call(message, "revision")) + writer.uint32(/* id 2, wireType 0 =*/16).uint64(message.revision); + if (message.document != null && Object.hasOwnProperty.call(message, "document")) + writer.uint32(/* id 3, wireType 2 =*/26).bytes(message.document); + return writer; + }; + + /** + * Encodes the specified Entry message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.verify|verify} messages. + * @function encodeDelimited + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.IEntry} message Entry message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Entry.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes an Entry message from the specified reader or buffer. + * @function decode + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry} Entry + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Entry.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.timeMs = reader.uint64(); + break; + case 2: + message.revision = reader.uint64(); + break; + case 3: + message.document = reader.bytes(); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes an Entry message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry} Entry + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Entry.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies an Entry message. + * @function verify + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + Entry.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.timeMs != null && message.hasOwnProperty("timeMs")) + if (!$util.isInteger(message.timeMs) && !(message.timeMs && $util.isInteger(message.timeMs.low) && $util.isInteger(message.timeMs.high))) + return "timeMs: integer|Long expected"; + if (message.revision != null && message.hasOwnProperty("revision")) + if (!$util.isInteger(message.revision) && !(message.revision && $util.isInteger(message.revision.low) && $util.isInteger(message.revision.high))) + return "revision: integer|Long expected"; + if (message.document != null && message.hasOwnProperty("document")) + if (!(message.document && typeof message.document.length === "number" || $util.isString(message.document))) + return "document: buffer expected"; + return null; + }; + + /** + * Creates an Entry message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry + * @static + * @param {Object.} object Plain object + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry} Entry + */ + Entry.fromObject = function fromObject(object) { + if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry) + return object; + var message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry(); + if (object.timeMs != null) + if ($util.Long) + (message.timeMs = $util.Long.fromValue(object.timeMs)).unsigned = true; + else if (typeof object.timeMs === "string") + message.timeMs = parseInt(object.timeMs, 10); + else if (typeof object.timeMs === "number") + message.timeMs = object.timeMs; + else if (typeof object.timeMs === "object") + message.timeMs = new $util.LongBits(object.timeMs.low >>> 0, object.timeMs.high >>> 0).toNumber(true); + if (object.revision != null) + if ($util.Long) + (message.revision = $util.Long.fromValue(object.revision)).unsigned = true; + else if (typeof object.revision === "string") + message.revision = parseInt(object.revision, 10); + else if (typeof object.revision === "number") + message.revision = object.revision; + else if (typeof object.revision === "object") + message.revision = new $util.LongBits(object.revision.low >>> 0, object.revision.high >>> 0).toNumber(true); + if (object.document != null) + if (typeof object.document === "string") + $util.base64.decode(object.document, message.document = $util.newBuffer($util.base64.length(object.document)), 0); + else if (object.document.length >= 0) + message.document = object.document; + return message; + }; + + /** + * Creates a plain object from an Entry message. Also converts values to other types if specified. + * @function toObject + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry} message Entry + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + Entry.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.defaults) { + if ($util.Long) { + var long = new $util.Long(0, 0, true); + object.timeMs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else + object.timeMs = options.longs === String ? "0" : 0; + if ($util.Long) { + var long = new $util.Long(0, 0, true); + object.revision = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else + object.revision = options.longs === String ? "0" : 0; + if (options.bytes === String) + object.document = ""; + else { + object.document = []; + if (options.bytes !== Array) + object.document = $util.newBuffer(object.document); + } + } + if (message.timeMs != null && message.hasOwnProperty("timeMs")) + if (typeof message.timeMs === "number") + object.timeMs = options.longs === String ? String(message.timeMs) : message.timeMs; + else + object.timeMs = options.longs === String ? $util.Long.prototype.toString.call(message.timeMs) : options.longs === Number ? new $util.LongBits(message.timeMs.low >>> 0, message.timeMs.high >>> 0).toNumber(true) : message.timeMs; + if (message.revision != null && message.hasOwnProperty("revision")) + if (typeof message.revision === "number") + object.revision = options.longs === String ? String(message.revision) : message.revision; + else + object.revision = options.longs === String ? $util.Long.prototype.toString.call(message.revision) : options.longs === Number ? new $util.LongBits(message.revision.low >>> 0, message.revision.high >>> 0).toNumber(true) : message.revision; + if (message.document != null && message.hasOwnProperty("document")) + object.document = options.bytes === String ? $util.base64.encode(message.document, 0, message.document.length) : options.bytes === Array ? Array.prototype.slice.call(message.document) : message.document; + return object; + }; + + /** + * Converts this Entry to JSON. + * @function toJSON + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry + * @instance + * @returns {Object.} JSON object + */ + Entry.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; - GetDocumentHistoryResponseV0.DocumentHistoryEntry = (function() { + return Entry; + })(); + + GetDocumentHistoryResponseV1.Lifecycle = (function() { /** - * Properties of a DocumentHistoryEntry. - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 - * @interface IDocumentHistoryEntry - * @property {number|Long|null} [date] DocumentHistoryEntry date - * @property {Uint8Array|null} [value] DocumentHistoryEntry value + * Properties of a Lifecycle. + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 + * @interface ILifecycle + * @property {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.State|null} [state] Lifecycle state + * @property {number|Long|null} [remainingRevisions] Lifecycle remainingRevisions */ /** - * Constructs a new DocumentHistoryEntry. - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 - * @classdesc Represents a DocumentHistoryEntry. - * @implements IDocumentHistoryEntry + * Constructs a new Lifecycle. + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 + * @classdesc Represents a Lifecycle. + * @implements ILifecycle * @constructor - * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistoryEntry=} [properties] Properties to set + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.ILifecycle=} [properties] Properties to set */ - function DocumentHistoryEntry(properties) { + function Lifecycle(properties) { if (properties) for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) if (properties[keys[i]] != null) @@ -52956,88 +54705,88 @@ $root.org = (function() { } /** - * DocumentHistoryEntry date. - * @member {number|Long} date - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * Lifecycle state. + * @member {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.State} state + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle * @instance */ - DocumentHistoryEntry.prototype.date = $util.Long ? $util.Long.fromBits(0,0,true) : 0; + Lifecycle.prototype.state = 0; /** - * DocumentHistoryEntry value. - * @member {Uint8Array} value - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * Lifecycle remainingRevisions. + * @member {number|Long} remainingRevisions + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle * @instance */ - DocumentHistoryEntry.prototype.value = $util.newBuffer([]); + Lifecycle.prototype.remainingRevisions = $util.Long ? $util.Long.fromBits(0,0,true) : 0; /** - * Creates a new DocumentHistoryEntry instance using the specified properties. + * Creates a new Lifecycle instance using the specified properties. * @function create - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle * @static - * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistoryEntry=} [properties] Properties to set - * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} DocumentHistoryEntry instance + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.ILifecycle=} [properties] Properties to set + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle} Lifecycle instance */ - DocumentHistoryEntry.create = function create(properties) { - return new DocumentHistoryEntry(properties); + Lifecycle.create = function create(properties) { + return new Lifecycle(properties); }; /** - * Encodes the specified DocumentHistoryEntry message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.verify|verify} messages. + * Encodes the specified Lifecycle message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.verify|verify} messages. * @function encode - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle * @static - * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistoryEntry} message DocumentHistoryEntry message or plain object to encode + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.ILifecycle} message Lifecycle message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - DocumentHistoryEntry.encode = function encode(message, writer) { + Lifecycle.encode = function encode(message, writer) { if (!writer) writer = $Writer.create(); - if (message.date != null && Object.hasOwnProperty.call(message, "date")) - writer.uint32(/* id 1, wireType 0 =*/8).uint64(message.date); - if (message.value != null && Object.hasOwnProperty.call(message, "value")) - writer.uint32(/* id 2, wireType 2 =*/18).bytes(message.value); + if (message.state != null && Object.hasOwnProperty.call(message, "state")) + writer.uint32(/* id 1, wireType 0 =*/8).int32(message.state); + if (message.remainingRevisions != null && Object.hasOwnProperty.call(message, "remainingRevisions")) + writer.uint32(/* id 2, wireType 0 =*/16).uint64(message.remainingRevisions); return writer; }; /** - * Encodes the specified DocumentHistoryEntry message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.verify|verify} messages. + * Encodes the specified Lifecycle message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.verify|verify} messages. * @function encodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle * @static - * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistoryEntry} message DocumentHistoryEntry message or plain object to encode + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.ILifecycle} message Lifecycle message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - DocumentHistoryEntry.encodeDelimited = function encodeDelimited(message, writer) { + Lifecycle.encodeDelimited = function encodeDelimited(message, writer) { return this.encode(message, writer).ldelim(); }; /** - * Decodes a DocumentHistoryEntry message from the specified reader or buffer. + * Decodes a Lifecycle message from the specified reader or buffer. * @function decode - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle * @static * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from * @param {number} [length] Message length if known beforehand - * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} DocumentHistoryEntry + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle} Lifecycle * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - DocumentHistoryEntry.decode = function decode(reader, length) { + Lifecycle.decode = function decode(reader, length) { if (!(reader instanceof $Reader)) reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry(); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle(); while (reader.pos < end) { var tag = reader.uint32(); switch (tag >>> 3) { case 1: - message.date = reader.uint64(); + message.state = reader.int32(); break; case 2: - message.value = reader.bytes(); + message.remainingRevisions = reader.uint64(); break; default: reader.skipType(tag & 7); @@ -53048,140 +54797,159 @@ $root.org = (function() { }; /** - * Decodes a DocumentHistoryEntry message from the specified reader or buffer, length delimited. + * Decodes a Lifecycle message from the specified reader or buffer, length delimited. * @function decodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle * @static * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} DocumentHistoryEntry + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle} Lifecycle * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - DocumentHistoryEntry.decodeDelimited = function decodeDelimited(reader) { + Lifecycle.decodeDelimited = function decodeDelimited(reader) { if (!(reader instanceof $Reader)) reader = new $Reader(reader); return this.decode(reader, reader.uint32()); }; /** - * Verifies a DocumentHistoryEntry message. + * Verifies a Lifecycle message. * @function verify - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle * @static * @param {Object.} message Plain object to verify * @returns {string|null} `null` if valid, otherwise the reason why it is not */ - DocumentHistoryEntry.verify = function verify(message) { + Lifecycle.verify = function verify(message) { if (typeof message !== "object" || message === null) return "object expected"; - if (message.date != null && message.hasOwnProperty("date")) - if (!$util.isInteger(message.date) && !(message.date && $util.isInteger(message.date.low) && $util.isInteger(message.date.high))) - return "date: integer|Long expected"; - if (message.value != null && message.hasOwnProperty("value")) - if (!(message.value && typeof message.value.length === "number" || $util.isString(message.value))) - return "value: buffer expected"; + if (message.state != null && message.hasOwnProperty("state")) + switch (message.state) { + default: + return "state: enum value expected"; + case 0: + case 1: + break; + } + if (message.remainingRevisions != null && message.hasOwnProperty("remainingRevisions")) + if (!$util.isInteger(message.remainingRevisions) && !(message.remainingRevisions && $util.isInteger(message.remainingRevisions.low) && $util.isInteger(message.remainingRevisions.high))) + return "remainingRevisions: integer|Long expected"; return null; }; /** - * Creates a DocumentHistoryEntry message from a plain object. Also converts values to their respective internal types. + * Creates a Lifecycle message from a plain object. Also converts values to their respective internal types. * @function fromObject - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle * @static * @param {Object.} object Plain object - * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} DocumentHistoryEntry + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle} Lifecycle */ - DocumentHistoryEntry.fromObject = function fromObject(object) { - if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry) + Lifecycle.fromObject = function fromObject(object) { + if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle) return object; - var message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry(); - if (object.date != null) + var message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle(); + switch (object.state) { + case "ACTIVE": + case 0: + message.state = 0; + break; + case "ABSENT": + case 1: + message.state = 1; + break; + } + if (object.remainingRevisions != null) if ($util.Long) - (message.date = $util.Long.fromValue(object.date)).unsigned = true; - else if (typeof object.date === "string") - message.date = parseInt(object.date, 10); - else if (typeof object.date === "number") - message.date = object.date; - else if (typeof object.date === "object") - message.date = new $util.LongBits(object.date.low >>> 0, object.date.high >>> 0).toNumber(true); - if (object.value != null) - if (typeof object.value === "string") - $util.base64.decode(object.value, message.value = $util.newBuffer($util.base64.length(object.value)), 0); - else if (object.value.length >= 0) - message.value = object.value; + (message.remainingRevisions = $util.Long.fromValue(object.remainingRevisions)).unsigned = true; + else if (typeof object.remainingRevisions === "string") + message.remainingRevisions = parseInt(object.remainingRevisions, 10); + else if (typeof object.remainingRevisions === "number") + message.remainingRevisions = object.remainingRevisions; + else if (typeof object.remainingRevisions === "object") + message.remainingRevisions = new $util.LongBits(object.remainingRevisions.low >>> 0, object.remainingRevisions.high >>> 0).toNumber(true); return message; }; /** - * Creates a plain object from a DocumentHistoryEntry message. Also converts values to other types if specified. + * Creates a plain object from a Lifecycle message. Also converts values to other types if specified. * @function toObject - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle * @static - * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} message DocumentHistoryEntry + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle} message Lifecycle * @param {$protobuf.IConversionOptions} [options] Conversion options * @returns {Object.} Plain object */ - DocumentHistoryEntry.toObject = function toObject(message, options) { + Lifecycle.toObject = function toObject(message, options) { if (!options) options = {}; var object = {}; if (options.defaults) { + object.state = options.enums === String ? "ACTIVE" : 0; if ($util.Long) { var long = new $util.Long(0, 0, true); - object.date = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + object.remainingRevisions = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; } else - object.date = options.longs === String ? "0" : 0; - if (options.bytes === String) - object.value = ""; - else { - object.value = []; - if (options.bytes !== Array) - object.value = $util.newBuffer(object.value); - } + object.remainingRevisions = options.longs === String ? "0" : 0; } - if (message.date != null && message.hasOwnProperty("date")) - if (typeof message.date === "number") - object.date = options.longs === String ? String(message.date) : message.date; + if (message.state != null && message.hasOwnProperty("state")) + object.state = options.enums === String ? $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.State[message.state] : message.state; + if (message.remainingRevisions != null && message.hasOwnProperty("remainingRevisions")) + if (typeof message.remainingRevisions === "number") + object.remainingRevisions = options.longs === String ? String(message.remainingRevisions) : message.remainingRevisions; else - object.date = options.longs === String ? $util.Long.prototype.toString.call(message.date) : options.longs === Number ? new $util.LongBits(message.date.low >>> 0, message.date.high >>> 0).toNumber(true) : message.date; - if (message.value != null && message.hasOwnProperty("value")) - object.value = options.bytes === String ? $util.base64.encode(message.value, 0, message.value.length) : options.bytes === Array ? Array.prototype.slice.call(message.value) : message.value; + object.remainingRevisions = options.longs === String ? $util.Long.prototype.toString.call(message.remainingRevisions) : options.longs === Number ? new $util.LongBits(message.remainingRevisions.low >>> 0, message.remainingRevisions.high >>> 0).toNumber(true) : message.remainingRevisions; return object; }; /** - * Converts this DocumentHistoryEntry to JSON. + * Converts this Lifecycle to JSON. * @function toJSON - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle * @instance * @returns {Object.} JSON object */ - DocumentHistoryEntry.prototype.toJSON = function toJSON() { + Lifecycle.prototype.toJSON = function toJSON() { return this.constructor.toObject(this, $protobuf.util.toJSONOptions); }; - return DocumentHistoryEntry; + /** + * State enum. + * @name org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.State + * @enum {number} + * @property {number} ACTIVE=0 ACTIVE value + * @property {number} ABSENT=1 ABSENT value + */ + Lifecycle.State = (function() { + var valuesById = {}, values = Object.create(valuesById); + values[valuesById[0] = "ACTIVE"] = 0; + values[valuesById[1] = "ABSENT"] = 1; + return values; + })(); + + return Lifecycle; })(); - GetDocumentHistoryResponseV0.DocumentHistory = (function() { + GetDocumentHistoryResponseV1.History = (function() { /** - * Properties of a DocumentHistory. - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 - * @interface IDocumentHistory - * @property {Array.|null} [documentEntries] DocumentHistory documentEntries + * Properties of a History. + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 + * @interface IHistory + * @property {Array.|null} [entries] History entries + * @property {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.ILifecycle|null} [lifecycle] History lifecycle */ /** - * Constructs a new DocumentHistory. - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 - * @classdesc Represents a DocumentHistory. - * @implements IDocumentHistory + * Constructs a new History. + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 + * @classdesc Represents a History. + * @implements IHistory * @constructor - * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistory=} [properties] Properties to set + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.IHistory=} [properties] Properties to set */ - function DocumentHistory(properties) { - this.documentEntries = []; + function History(properties) { + this.entries = []; if (properties) for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) if (properties[keys[i]] != null) @@ -53189,78 +54957,91 @@ $root.org = (function() { } /** - * DocumentHistory documentEntries. - * @member {Array.} documentEntries - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * History entries. + * @member {Array.} entries + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History * @instance */ - DocumentHistory.prototype.documentEntries = $util.emptyArray; + History.prototype.entries = $util.emptyArray; /** - * Creates a new DocumentHistory instance using the specified properties. + * History lifecycle. + * @member {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.ILifecycle|null|undefined} lifecycle + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History + * @instance + */ + History.prototype.lifecycle = null; + + /** + * Creates a new History instance using the specified properties. * @function create - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History * @static - * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistory=} [properties] Properties to set - * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} DocumentHistory instance + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.IHistory=} [properties] Properties to set + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History} History instance */ - DocumentHistory.create = function create(properties) { - return new DocumentHistory(properties); + History.create = function create(properties) { + return new History(properties); }; /** - * Encodes the specified DocumentHistory message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.verify|verify} messages. + * Encodes the specified History message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.verify|verify} messages. * @function encode - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History * @static - * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistory} message DocumentHistory message or plain object to encode + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.IHistory} message History message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - DocumentHistory.encode = function encode(message, writer) { + History.encode = function encode(message, writer) { if (!writer) writer = $Writer.create(); - if (message.documentEntries != null && message.documentEntries.length) - for (var i = 0; i < message.documentEntries.length; ++i) - $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.encode(message.documentEntries[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); + if (message.entries != null && message.entries.length) + for (var i = 0; i < message.entries.length; ++i) + $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.encode(message.entries[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); + if (message.lifecycle != null && Object.hasOwnProperty.call(message, "lifecycle")) + $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.encode(message.lifecycle, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); return writer; }; /** - * Encodes the specified DocumentHistory message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.verify|verify} messages. + * Encodes the specified History message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.verify|verify} messages. * @function encodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History * @static - * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.IDocumentHistory} message DocumentHistory message or plain object to encode + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.IHistory} message History message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - DocumentHistory.encodeDelimited = function encodeDelimited(message, writer) { + History.encodeDelimited = function encodeDelimited(message, writer) { return this.encode(message, writer).ldelim(); }; /** - * Decodes a DocumentHistory message from the specified reader or buffer. + * Decodes a History message from the specified reader or buffer. * @function decode - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History * @static * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from * @param {number} [length] Message length if known beforehand - * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} DocumentHistory + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History} History * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - DocumentHistory.decode = function decode(reader, length) { + History.decode = function decode(reader, length) { if (!(reader instanceof $Reader)) reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory(); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History(); while (reader.pos < end) { var tag = reader.uint32(); switch (tag >>> 3) { case 1: - if (!(message.documentEntries && message.documentEntries.length)) - message.documentEntries = []; - message.documentEntries.push($root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.decode(reader, reader.uint32())); + if (!(message.entries && message.entries.length)) + message.entries = []; + message.entries.push($root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.decode(reader, reader.uint32())); + break; + case 2: + message.lifecycle = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.decode(reader, reader.uint32()); break; default: reader.skipType(tag & 7); @@ -53271,107 +55052,121 @@ $root.org = (function() { }; /** - * Decodes a DocumentHistory message from the specified reader or buffer, length delimited. + * Decodes a History message from the specified reader or buffer, length delimited. * @function decodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History * @static * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} DocumentHistory + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History} History * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - DocumentHistory.decodeDelimited = function decodeDelimited(reader) { + History.decodeDelimited = function decodeDelimited(reader) { if (!(reader instanceof $Reader)) reader = new $Reader(reader); return this.decode(reader, reader.uint32()); }; /** - * Verifies a DocumentHistory message. + * Verifies a History message. * @function verify - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History * @static * @param {Object.} message Plain object to verify * @returns {string|null} `null` if valid, otherwise the reason why it is not */ - DocumentHistory.verify = function verify(message) { + History.verify = function verify(message) { if (typeof message !== "object" || message === null) return "object expected"; - if (message.documentEntries != null && message.hasOwnProperty("documentEntries")) { - if (!Array.isArray(message.documentEntries)) - return "documentEntries: array expected"; - for (var i = 0; i < message.documentEntries.length; ++i) { - var error = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.verify(message.documentEntries[i]); + if (message.entries != null && message.hasOwnProperty("entries")) { + if (!Array.isArray(message.entries)) + return "entries: array expected"; + for (var i = 0; i < message.entries.length; ++i) { + var error = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.verify(message.entries[i]); if (error) - return "documentEntries." + error; + return "entries." + error; } } + if (message.lifecycle != null && message.hasOwnProperty("lifecycle")) { + var error = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.verify(message.lifecycle); + if (error) + return "lifecycle." + error; + } return null; }; /** - * Creates a DocumentHistory message from a plain object. Also converts values to their respective internal types. + * Creates a History message from a plain object. Also converts values to their respective internal types. * @function fromObject - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History * @static * @param {Object.} object Plain object - * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} DocumentHistory + * @returns {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History} History */ - DocumentHistory.fromObject = function fromObject(object) { - if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory) + History.fromObject = function fromObject(object) { + if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History) return object; - var message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory(); - if (object.documentEntries) { - if (!Array.isArray(object.documentEntries)) - throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.documentEntries: array expected"); - message.documentEntries = []; - for (var i = 0; i < object.documentEntries.length; ++i) { - if (typeof object.documentEntries[i] !== "object") - throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.documentEntries: object expected"); - message.documentEntries[i] = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.fromObject(object.documentEntries[i]); + var message = new $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History(); + if (object.entries) { + if (!Array.isArray(object.entries)) + throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.entries: array expected"); + message.entries = []; + for (var i = 0; i < object.entries.length; ++i) { + if (typeof object.entries[i] !== "object") + throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.entries: object expected"); + message.entries[i] = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.fromObject(object.entries[i]); } } + if (object.lifecycle != null) { + if (typeof object.lifecycle !== "object") + throw TypeError(".org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.lifecycle: object expected"); + message.lifecycle = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.fromObject(object.lifecycle); + } return message; }; /** - * Creates a plain object from a DocumentHistory message. Also converts values to other types if specified. + * Creates a plain object from a History message. Also converts values to other types if specified. * @function toObject - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History * @static - * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} message DocumentHistory + * @param {org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History} message History * @param {$protobuf.IConversionOptions} [options] Conversion options * @returns {Object.} Plain object */ - DocumentHistory.toObject = function toObject(message, options) { + History.toObject = function toObject(message, options) { if (!options) options = {}; var object = {}; if (options.arrays || options.defaults) - object.documentEntries = []; - if (message.documentEntries && message.documentEntries.length) { - object.documentEntries = []; - for (var j = 0; j < message.documentEntries.length; ++j) - object.documentEntries[j] = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.toObject(message.documentEntries[j], options); + object.entries = []; + if (options.defaults) + object.lifecycle = null; + if (message.entries && message.entries.length) { + object.entries = []; + for (var j = 0; j < message.entries.length; ++j) + object.entries[j] = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.toObject(message.entries[j], options); } + if (message.lifecycle != null && message.hasOwnProperty("lifecycle")) + object.lifecycle = $root.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.toObject(message.lifecycle, options); return object; }; /** - * Converts this DocumentHistory to JSON. + * Converts this History to JSON. * @function toJSON - * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory + * @memberof org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History * @instance * @returns {Object.} JSON object */ - DocumentHistory.prototype.toJSON = function toJSON() { + History.prototype.toJSON = function toJSON() { return this.constructor.toObject(this, $protobuf.util.toJSONOptions); }; - return DocumentHistory; + return History; })(); - return GetDocumentHistoryResponseV0; + return GetDocumentHistoryResponseV1; })(); return GetDocumentHistoryResponse; 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 9ffea0ab9a9..dc7db229162 100644 --- a/packages/dapi-grpc/clients/platform/v0/nodejs/platform_protoc.js +++ b/packages/dapi-grpc/clients/platform/v0/nodejs/platform_protoc.js @@ -271,12 +271,21 @@ goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDataContractsResponse.GetD goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDataContractsResponse.VersionCase', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.FilterCase', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.VersionCase', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.ResultCase', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.State', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.ResultCase', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.VersionCase', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsRequest', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsRequest.DocumentFieldValue', null, { proto }); @@ -5007,6 +5016,48 @@ if (goog.DEBUG && !COMPILED) { */ proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0.displayName = 'proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0'; } +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.oneofGroups_); +}; +goog.inherits(proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.displayName = 'proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.displayName = 'proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor'; +} /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a @@ -5091,6 +5142,90 @@ if (goog.DEBUG && !COMPILED) { */ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.displayName = 'proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory'; } +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.oneofGroups_); +}; +goog.inherits(proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.displayName = 'proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.displayName = 'proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.displayName = 'proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.repeatedFields_, null); +}; +goog.inherits(proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.displayName = 'proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History'; +} /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a @@ -56987,14 +57122,15 @@ proto.org.dash.platform.dapi.v0.GetDocumentsResponse.prototype.hasV1 = function( * @private {!Array>} * @const */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.oneofGroups_ = [[1]]; +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.oneofGroups_ = [[1,2]]; /** * @enum {number} */ proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.VersionCase = { VERSION_NOT_SET: 0, - V0: 1 + V0: 1, + V1: 2 }; /** @@ -57035,7 +57171,8 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.prototype.toObject = f */ proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.toObject = function(includeInstance, msg) { var f, obj = { - v0: (f = msg.getV0()) && proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0.toObject(includeInstance, f) + v0: (f = msg.getV0()) && proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0.toObject(includeInstance, f), + v1: (f = msg.getV1()) && proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.toObject(includeInstance, f) }; if (includeInstance) { @@ -57077,6 +57214,11 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.deserializeBinaryFromR reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0.deserializeBinaryFromReader); msg.setV0(value); break; + case 2: + var value = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.deserializeBinaryFromReader); + msg.setV1(value); + break; default: reader.skipField(); break; @@ -57114,6 +57256,14 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.serializeBinaryToWrite proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0.serializeBinaryToWriter ); } + f = message.getV1(); + if (f != null) { + writer.writeMessage( + 2, + f, + proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.serializeBinaryToWriter + ); + } }; @@ -57517,43 +57667,6 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequ }; -/** - * optional GetDocumentHistoryRequestV0 v0 = 1; - * @return {?proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0} - */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.prototype.getV0 = function() { - return /** @type{?proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0} */ ( - jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0, 1)); -}; - - -/** - * @param {?proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0|undefined} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest} returns this -*/ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.prototype.setV0 = function(value) { - return jspb.Message.setOneofWrapperField(this, 1, proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.oneofGroups_[0], value); -}; - - -/** - * Clears the message field making it undefined. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest} returns this - */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.prototype.clearV0 = function() { - return this.setV0(undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.prototype.hasV0 = function() { - return jspb.Message.getField(this, 1) != null; -}; - - /** * Oneof group definitions for this message. Each group defines the field @@ -57563,21 +57676,24 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.prototype.hasV0 = func * @private {!Array>} * @const */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.oneofGroups_ = [[1]]; +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.oneofGroups_ = [[6,7,8,9]]; /** * @enum {number} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.VersionCase = { - VERSION_NOT_SET: 0, - V0: 1 +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.FilterCase = { + FILTER_NOT_SET: 0, + START_AT_MS: 6, + START_AFTER: 7, + START_AT_REVISION: 8, + REVISION: 9 }; /** - * @return {proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.VersionCase} + * @return {proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.FilterCase} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.prototype.getVersionCase = function() { - return /** @type {proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.VersionCase} */(jspb.Message.computeOneofCase(this, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.oneofGroups_[0])); +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.getFilterCase = function() { + return /** @type {proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.FilterCase} */(jspb.Message.computeOneofCase(this, proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.oneofGroups_[0])); }; @@ -57595,8 +57711,8 @@ if (jspb.Message.GENERATE_TO_OBJECT) { * http://goto/soy-param-migration * @return {!Object} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.prototype.toObject = function(opt_includeInstance) { - return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.toObject(opt_includeInstance, this); +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.toObject = function(opt_includeInstance) { + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.toObject(opt_includeInstance, this); }; @@ -57605,13 +57721,21 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.prototype.toObject = * @param {boolean|undefined} includeInstance Deprecated. Whether to include * the JSPB instance for transitional soy proto support: * http://goto/soy-param-migration - * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse} msg The msg instance to transform. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} msg The msg instance to transform. * @return {!Object} * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.toObject = function(includeInstance, msg) { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.toObject = function(includeInstance, msg) { var f, obj = { - v0: (f = msg.getV0()) && proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.toObject(includeInstance, f) + dataContractId: msg.getDataContractId_asB64(), + documentTypeName: jspb.Message.getFieldWithDefault(msg, 2, ""), + documentId: msg.getDocumentId_asB64(), + limit: (f = msg.getLimit()) && google_protobuf_wrappers_pb.UInt32Value.toObject(includeInstance, f), + prove: jspb.Message.getBooleanFieldWithDefault(msg, 5, false), + startAtMs: jspb.Message.getFieldWithDefault(msg, 6, "0"), + startAfter: (f = msg.getStartAfter()) && proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.toObject(includeInstance, f), + startAtRevision: jspb.Message.getFieldWithDefault(msg, 8, "0"), + revision: jspb.Message.getFieldWithDefault(msg, 9, "0") }; if (includeInstance) { @@ -57625,23 +57749,23 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.toObject = function(i /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse} + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.deserializeBinary = function(bytes) { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); - var msg = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse; - return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.deserializeBinaryFromReader(msg, reader); + var msg = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1; + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. - * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse} msg The message object to deserialize into. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse} + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.deserializeBinaryFromReader = function(msg, reader) { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; @@ -57649,9 +57773,42 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.deserializeBinaryFrom var field = reader.getFieldNumber(); switch (field) { case 1: - var value = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0; - reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.deserializeBinaryFromReader); - msg.setV0(value); + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setDataContractId(value); + break; + case 2: + var value = /** @type {string} */ (reader.readString()); + msg.setDocumentTypeName(value); + break; + case 3: + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setDocumentId(value); + break; + case 4: + var value = new google_protobuf_wrappers_pb.UInt32Value; + reader.readMessage(value,google_protobuf_wrappers_pb.UInt32Value.deserializeBinaryFromReader); + msg.setLimit(value); + break; + case 5: + var value = /** @type {boolean} */ (reader.readBool()); + msg.setProve(value); + break; + case 6: + var value = /** @type {string} */ (reader.readUint64String()); + msg.setStartAtMs(value); + break; + case 7: + var value = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.deserializeBinaryFromReader); + msg.setStartAfter(value); + break; + case 8: + var value = /** @type {string} */ (reader.readUint64String()); + msg.setStartAtRevision(value); + break; + case 9: + var value = /** @type {string} */ (reader.readUint64String()); + msg.setRevision(value); break; default: reader.skipField(); @@ -57666,9 +57823,9 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.deserializeBinaryFrom * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.prototype.serializeBinary = function() { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); - proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.serializeBinaryToWriter(this, writer); + proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.serializeBinaryToWriter(this, writer); return writer.getResultBuffer(); }; @@ -57676,50 +57833,81 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.prototype.serializeBi /** * Serializes the given message to binary data (in protobuf wire * format), writing to the given BinaryWriter. - * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse} message + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} message * @param {!jspb.BinaryWriter} writer * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.serializeBinaryToWriter = function(message, writer) { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.serializeBinaryToWriter = function(message, writer) { var f = undefined; - f = message.getV0(); + f = message.getDataContractId_asU8(); + if (f.length > 0) { + writer.writeBytes( + 1, + f + ); + } + f = message.getDocumentTypeName(); + if (f.length > 0) { + writer.writeString( + 2, + f + ); + } + f = message.getDocumentId_asU8(); + if (f.length > 0) { + writer.writeBytes( + 3, + f + ); + } + f = message.getLimit(); if (f != null) { writer.writeMessage( - 1, + 4, f, - proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.serializeBinaryToWriter + google_protobuf_wrappers_pb.UInt32Value.serializeBinaryToWriter + ); + } + f = message.getProve(); + if (f) { + writer.writeBool( + 5, + f + ); + } + f = /** @type {string} */ (jspb.Message.getField(message, 6)); + if (f != null) { + writer.writeUint64String( + 6, + f + ); + } + f = message.getStartAfter(); + if (f != null) { + writer.writeMessage( + 7, + f, + proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.serializeBinaryToWriter + ); + } + f = /** @type {string} */ (jspb.Message.getField(message, 8)); + if (f != null) { + writer.writeUint64String( + 8, + f + ); + } + f = /** @type {string} */ (jspb.Message.getField(message, 9)); + if (f != null) { + writer.writeUint64String( + 9, + f ); } }; -/** - * Oneof group definitions for this message. Each group defines the field - * numbers belonging to that group. When of these fields' value is set, all - * other fields in the group are cleared. During deserialization, if multiple - * fields are encountered for a group, only the last value seen will be kept. - * @private {!Array>} - * @const - */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.oneofGroups_ = [[1,2]]; - -/** - * @enum {number} - */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.ResultCase = { - RESULT_NOT_SET: 0, - DOCUMENT_HISTORY: 1, - PROOF: 2 -}; - -/** - * @return {proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.ResultCase} - */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.getResultCase = function() { - return /** @type {proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.ResultCase} */(jspb.Message.computeOneofCase(this, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.oneofGroups_[0])); -}; - if (jspb.Message.GENERATE_TO_OBJECT) { @@ -57735,8 +57923,8 @@ if (jspb.Message.GENERATE_TO_OBJECT) { * http://goto/soy-param-migration * @return {!Object} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.toObject = function(opt_includeInstance) { - return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.toObject(opt_includeInstance, this); +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.prototype.toObject = function(opt_includeInstance) { + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.toObject(opt_includeInstance, this); }; @@ -57745,15 +57933,14 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryRes * @param {boolean|undefined} includeInstance Deprecated. Whether to include * the JSPB instance for transitional soy proto support: * http://goto/soy-param-migration - * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} msg The msg instance to transform. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor} msg The msg instance to transform. * @return {!Object} * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.toObject = function(includeInstance, msg) { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.toObject = function(includeInstance, msg) { var f, obj = { - documentHistory: (f = msg.getDocumentHistory()) && proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.toObject(includeInstance, f), - proof: (f = msg.getProof()) && proto.org.dash.platform.dapi.v0.Proof.toObject(includeInstance, f), - metadata: (f = msg.getMetadata()) && proto.org.dash.platform.dapi.v0.ResponseMetadata.toObject(includeInstance, f) + timeMs: jspb.Message.getFieldWithDefault(msg, 1, "0"), + revision: jspb.Message.getFieldWithDefault(msg, 2, "0") }; if (includeInstance) { @@ -57767,23 +57954,23 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryRes /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.deserializeBinary = function(bytes) { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); - var msg = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0; - return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.deserializeBinaryFromReader(msg, reader); + var msg = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor; + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. - * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} msg The message object to deserialize into. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.deserializeBinaryFromReader = function(msg, reader) { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; @@ -57791,19 +57978,12 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryRes var field = reader.getFieldNumber(); switch (field) { case 1: - var value = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory; - reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.deserializeBinaryFromReader); - msg.setDocumentHistory(value); + var value = /** @type {string} */ (reader.readUint64String()); + msg.setTimeMs(value); break; case 2: - var value = new proto.org.dash.platform.dapi.v0.Proof; - reader.readMessage(value,proto.org.dash.platform.dapi.v0.Proof.deserializeBinaryFromReader); - msg.setProof(value); - break; - case 3: - var value = new proto.org.dash.platform.dapi.v0.ResponseMetadata; - reader.readMessage(value,proto.org.dash.platform.dapi.v0.ResponseMetadata.deserializeBinaryFromReader); - msg.setMetadata(value); + var value = /** @type {string} */ (reader.readUint64String()); + msg.setRevision(value); break; default: reader.skipField(); @@ -57818,9 +57998,9 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryRes * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.serializeBinary = function() { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); - proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.serializeBinaryToWriter(this, writer); + proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.serializeBinaryToWriter(this, writer); return writer.getResultBuffer(); }; @@ -57828,211 +58008,935 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryRes /** * Serializes the given message to binary data (in protobuf wire * format), writing to the given BinaryWriter. - * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} message + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor} message * @param {!jspb.BinaryWriter} writer * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.serializeBinaryToWriter = function(message, writer) { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.serializeBinaryToWriter = function(message, writer) { var f = undefined; - f = message.getDocumentHistory(); - if (f != null) { - writer.writeMessage( + f = message.getTimeMs(); + if (parseInt(f, 10) !== 0) { + writer.writeUint64String( 1, - f, - proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.serializeBinaryToWriter + f ); } - f = message.getProof(); - if (f != null) { - writer.writeMessage( + f = message.getRevision(); + if (parseInt(f, 10) !== 0) { + writer.writeUint64String( 2, - f, - proto.org.dash.platform.dapi.v0.Proof.serializeBinaryToWriter - ); - } - f = message.getMetadata(); - if (f != null) { - writer.writeMessage( - 3, - f, - proto.org.dash.platform.dapi.v0.ResponseMetadata.serializeBinaryToWriter + f ); } }; +/** + * optional uint64 time_ms = 1; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.prototype.getTimeMs = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "0")); +}; - -if (jspb.Message.GENERATE_TO_OBJECT) { /** - * Creates an object representation of this proto. - * Field names that are reserved in JavaScript and will be renamed to pb_name. - * Optional fields that are not set will be set to undefined. - * To access a reserved field use, foo.pb_, eg, foo.pb_default. - * For the list of reserved names please see: - * net/proto2/compiler/js/internal/generator.cc#kKeyword. - * @param {boolean=} opt_includeInstance Deprecated. whether to include the - * JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @return {!Object} + * @param {string} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.prototype.toObject = function(opt_includeInstance) { - return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.toObject(opt_includeInstance, this); +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.prototype.setTimeMs = function(value) { + return jspb.Message.setProto3StringIntField(this, 1, value); }; /** - * Static version of the {@see toObject} method. - * @param {boolean|undefined} includeInstance Deprecated. Whether to include - * the JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages + * optional uint64 revision = 2; + * @return {string} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.toObject = function(includeInstance, msg) { - var f, obj = { - date: jspb.Message.getFieldWithDefault(msg, 1, "0"), - value: msg.getValue_asB64() - }; +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.prototype.getRevision = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "0")); +}; - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; + +/** + * @param {string} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.prototype.setRevision = function(value) { + return jspb.Message.setProto3StringIntField(this, 2, value); }; -} /** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} + * optional bytes data_contract_id = 1; + * @return {string} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry; - return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.deserializeBinaryFromReader(msg, reader); +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.getDataContractId = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); }; /** - * Deserializes binary data (in protobuf wire format) from the - * given reader into the given message object. - * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} + * optional bytes data_contract_id = 1; + * This is a type-conversion wrapper around `getDataContractId()` + * @return {string} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.deserializeBinaryFromReader = function(msg, reader) { - while (reader.nextField()) { - if (reader.isEndGroup()) { - break; - } - var field = reader.getFieldNumber(); - switch (field) { - case 1: - var value = /** @type {string} */ (reader.readUint64String()); - msg.setDate(value); - break; - case 2: - var value = /** @type {!Uint8Array} */ (reader.readBytes()); - msg.setValue(value); - break; - default: - reader.skipField(); - break; - } - } - return msg; +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.getDataContractId_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getDataContractId())); }; /** - * Serializes the message to binary data (in protobuf wire format). + * optional bytes data_contract_id = 1; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getDataContractId()` * @return {!Uint8Array} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.serializeBinaryToWriter(this, writer); - return writer.getResultBuffer(); +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.getDataContractId_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getDataContractId())); }; /** - * Serializes the given message to binary data (in protobuf wire - * format), writing to the given BinaryWriter. - * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages + * @param {!(string|Uint8Array)} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getDate(); - if (parseInt(f, 10) !== 0) { - writer.writeUint64String( - 1, - f - ); - } - f = message.getValue_asU8(); - if (f.length > 0) { - writer.writeBytes( - 2, - f - ); - } +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.setDataContractId = function(value) { + return jspb.Message.setProto3BytesField(this, 1, value); }; /** - * optional uint64 date = 1; + * optional string document_type_name = 2; * @return {string} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.prototype.getDate = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "0")); +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.getDocumentTypeName = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); }; /** * @param {string} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} returns this + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.prototype.setDate = function(value) { - return jspb.Message.setProto3StringIntField(this, 1, value); +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.setDocumentTypeName = function(value) { + return jspb.Message.setProto3StringField(this, 2, value); }; /** - * optional bytes value = 2; + * optional bytes document_id = 3; * @return {string} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.prototype.getValue = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.getDocumentId = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); }; /** - * optional bytes value = 2; - * This is a type-conversion wrapper around `getValue()` + * optional bytes document_id = 3; + * This is a type-conversion wrapper around `getDocumentId()` * @return {string} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.prototype.getValue_asB64 = function() { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.getDocumentId_asB64 = function() { return /** @type {string} */ (jspb.Message.bytesAsB64( - this.getValue())); + this.getDocumentId())); }; /** - * optional bytes value = 2; + * optional bytes document_id = 3; * Note that Uint8Array is not supported on all browsers. * @see http://caniuse.com/Uint8Array - * This is a type-conversion wrapper around `getValue()` + * This is a type-conversion wrapper around `getDocumentId()` * @return {!Uint8Array} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.prototype.getValue_asU8 = function() { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.getDocumentId_asU8 = function() { return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( - this.getValue())); + this.getDocumentId())); +}; + + +/** + * @param {!(string|Uint8Array)} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.setDocumentId = function(value) { + return jspb.Message.setProto3BytesField(this, 3, value); +}; + + +/** + * optional google.protobuf.UInt32Value limit = 4; + * @return {?proto.google.protobuf.UInt32Value} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.getLimit = function() { + return /** @type{?proto.google.protobuf.UInt32Value} */ ( + jspb.Message.getWrapperField(this, google_protobuf_wrappers_pb.UInt32Value, 4)); +}; + + +/** + * @param {?proto.google.protobuf.UInt32Value|undefined} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} returns this +*/ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.setLimit = function(value) { + return jspb.Message.setWrapperField(this, 4, value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.clearLimit = function() { + return this.setLimit(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.hasLimit = function() { + return jspb.Message.getField(this, 4) != null; +}; + + +/** + * optional bool prove = 5; + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.getProve = function() { + return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 5, false)); +}; + + +/** + * @param {boolean} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.setProve = function(value) { + return jspb.Message.setProto3BooleanField(this, 5, value); +}; + + +/** + * optional uint64 start_at_ms = 6; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.getStartAtMs = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 6, "0")); +}; + + +/** + * @param {string} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.setStartAtMs = function(value) { + return jspb.Message.setOneofField(this, 6, proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.oneofGroups_[0], value); +}; + + +/** + * Clears the field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.clearStartAtMs = function() { + return jspb.Message.setOneofField(this, 6, proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.oneofGroups_[0], undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.hasStartAtMs = function() { + return jspb.Message.getField(this, 6) != null; +}; + + +/** + * optional Cursor start_after = 7; + * @return {?proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.getStartAfter = function() { + return /** @type{?proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor} */ ( + jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor, 7)); +}; + + +/** + * @param {?proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor|undefined} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} returns this +*/ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.setStartAfter = function(value) { + return jspb.Message.setOneofWrapperField(this, 7, proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.oneofGroups_[0], value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.clearStartAfter = function() { + return this.setStartAfter(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.hasStartAfter = function() { + return jspb.Message.getField(this, 7) != null; +}; + + +/** + * optional uint64 start_at_revision = 8; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.getStartAtRevision = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 8, "0")); +}; + + +/** + * @param {string} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.setStartAtRevision = function(value) { + return jspb.Message.setOneofField(this, 8, proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.oneofGroups_[0], value); +}; + + +/** + * Clears the field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.clearStartAtRevision = function() { + return jspb.Message.setOneofField(this, 8, proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.oneofGroups_[0], undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.hasStartAtRevision = function() { + return jspb.Message.getField(this, 8) != null; +}; + + +/** + * optional uint64 revision = 9; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.getRevision = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 9, "0")); +}; + + +/** + * @param {string} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.setRevision = function(value) { + return jspb.Message.setOneofField(this, 9, proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.oneofGroups_[0], value); +}; + + +/** + * Clears the field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.clearRevision = function() { + return jspb.Message.setOneofField(this, 9, proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.oneofGroups_[0], undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.hasRevision = function() { + return jspb.Message.getField(this, 9) != null; +}; + + +/** + * optional GetDocumentHistoryRequestV0 v0 = 1; + * @return {?proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.prototype.getV0 = function() { + return /** @type{?proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0} */ ( + jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0, 1)); +}; + + +/** + * @param {?proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0|undefined} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest} returns this +*/ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.prototype.setV0 = function(value) { + return jspb.Message.setOneofWrapperField(this, 1, proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.oneofGroups_[0], value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.prototype.clearV0 = function() { + return this.setV0(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.prototype.hasV0 = function() { + return jspb.Message.getField(this, 1) != null; +}; + + +/** + * optional GetDocumentHistoryRequestV1 v1 = 2; + * @return {?proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.prototype.getV1 = function() { + return /** @type{?proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} */ ( + jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1, 2)); +}; + + +/** + * @param {?proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1|undefined} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest} returns this +*/ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.prototype.setV1 = function(value) { + return jspb.Message.setOneofWrapperField(this, 2, proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.oneofGroups_[0], value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.prototype.clearV1 = function() { + return this.setV1(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.prototype.hasV1 = function() { + return jspb.Message.getField(this, 2) != null; +}; + + + +/** + * Oneof group definitions for this message. Each group defines the field + * numbers belonging to that group. When of these fields' value is set, all + * other fields in the group are cleared. During deserialization, if multiple + * fields are encountered for a group, only the last value seen will be kept. + * @private {!Array>} + * @const + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.oneofGroups_ = [[1,2]]; + +/** + * @enum {number} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.VersionCase = { + VERSION_NOT_SET: 0, + V0: 1, + V1: 2 +}; + +/** + * @return {proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.VersionCase} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.prototype.getVersionCase = function() { + return /** @type {proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.VersionCase} */(jspb.Message.computeOneofCase(this, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.oneofGroups_[0])); +}; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.prototype.toObject = function(opt_includeInstance) { + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.toObject = function(includeInstance, msg) { + var f, obj = { + v0: (f = msg.getV0()) && proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.toObject(includeInstance, f), + v1: (f = msg.getV1()) && proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.toObject(includeInstance, f) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse; + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.deserializeBinaryFromReader); + msg.setV0(value); + break; + case 2: + var value = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.deserializeBinaryFromReader); + msg.setV1(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getV0(); + if (f != null) { + writer.writeMessage( + 1, + f, + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.serializeBinaryToWriter + ); + } + f = message.getV1(); + if (f != null) { + writer.writeMessage( + 2, + f, + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.serializeBinaryToWriter + ); + } +}; + + + +/** + * Oneof group definitions for this message. Each group defines the field + * numbers belonging to that group. When of these fields' value is set, all + * other fields in the group are cleared. During deserialization, if multiple + * fields are encountered for a group, only the last value seen will be kept. + * @private {!Array>} + * @const + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.oneofGroups_ = [[1,2]]; + +/** + * @enum {number} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.ResultCase = { + RESULT_NOT_SET: 0, + DOCUMENT_HISTORY: 1, + PROOF: 2 +}; + +/** + * @return {proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.ResultCase} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.getResultCase = function() { + return /** @type {proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.ResultCase} */(jspb.Message.computeOneofCase(this, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.oneofGroups_[0])); +}; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.toObject = function(opt_includeInstance) { + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.toObject = function(includeInstance, msg) { + var f, obj = { + documentHistory: (f = msg.getDocumentHistory()) && proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.toObject(includeInstance, f), + proof: (f = msg.getProof()) && proto.org.dash.platform.dapi.v0.Proof.toObject(includeInstance, f), + metadata: (f = msg.getMetadata()) && proto.org.dash.platform.dapi.v0.ResponseMetadata.toObject(includeInstance, f) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0; + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.deserializeBinaryFromReader); + msg.setDocumentHistory(value); + break; + case 2: + var value = new proto.org.dash.platform.dapi.v0.Proof; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.Proof.deserializeBinaryFromReader); + msg.setProof(value); + break; + case 3: + var value = new proto.org.dash.platform.dapi.v0.ResponseMetadata; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.ResponseMetadata.deserializeBinaryFromReader); + msg.setMetadata(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getDocumentHistory(); + if (f != null) { + writer.writeMessage( + 1, + f, + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.serializeBinaryToWriter + ); + } + f = message.getProof(); + if (f != null) { + writer.writeMessage( + 2, + f, + proto.org.dash.platform.dapi.v0.Proof.serializeBinaryToWriter + ); + } + f = message.getMetadata(); + if (f != null) { + writer.writeMessage( + 3, + f, + proto.org.dash.platform.dapi.v0.ResponseMetadata.serializeBinaryToWriter + ); + } +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.prototype.toObject = function(opt_includeInstance) { + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.toObject = function(includeInstance, msg) { + var f, obj = { + date: jspb.Message.getFieldWithDefault(msg, 1, "0"), + value: msg.getValue_asB64() + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry; + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readUint64String()); + msg.setDate(value); + break; + case 2: + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setValue(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getDate(); + if (parseInt(f, 10) !== 0) { + writer.writeUint64String( + 1, + f + ); + } + f = message.getValue_asU8(); + if (f.length > 0) { + writer.writeBytes( + 2, + f + ); + } +}; + + +/** + * optional uint64 date = 1; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.prototype.getDate = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "0")); +}; + + +/** + * @param {string} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.prototype.setDate = function(value) { + return jspb.Message.setProto3StringIntField(this, 1, value); +}; + + +/** + * optional bytes value = 2; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.prototype.getValue = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * optional bytes value = 2; + * This is a type-conversion wrapper around `getValue()` + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.prototype.getValue_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getValue())); +}; + + +/** + * optional bytes value = 2; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getValue()` + * @return {!Uint8Array} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.prototype.getValue_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getValue())); }; @@ -58040,8 +58944,829 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryRes * @param {!(string|Uint8Array)} value * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.prototype.setValue = function(value) { - return jspb.Message.setProto3BytesField(this, 2, value); +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.prototype.setValue = function(value) { + return jspb.Message.setProto3BytesField(this, 2, value); +}; + + + +/** + * List of repeated fields within this message type. + * @private {!Array} + * @const + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.repeatedFields_ = [1]; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.prototype.toObject = function(opt_includeInstance) { + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.toObject = function(includeInstance, msg) { + var f, obj = { + documentEntriesList: jspb.Message.toObjectList(msg.getDocumentEntriesList(), + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.toObject, includeInstance) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory; + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.deserializeBinaryFromReader); + msg.addDocumentEntries(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getDocumentEntriesList(); + if (f.length > 0) { + writer.writeRepeatedMessage( + 1, + f, + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.serializeBinaryToWriter + ); + } +}; + + +/** + * repeated DocumentHistoryEntry document_entries = 1; + * @return {!Array} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.prototype.getDocumentEntriesList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry, 1)); +}; + + +/** + * @param {!Array} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} returns this +*/ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.prototype.setDocumentEntriesList = function(value) { + return jspb.Message.setRepeatedWrapperField(this, 1, value); +}; + + +/** + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry=} opt_value + * @param {number=} opt_index + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.prototype.addDocumentEntries = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry, opt_index); +}; + + +/** + * Clears the list making it empty but non-null. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.prototype.clearDocumentEntriesList = function() { + return this.setDocumentEntriesList([]); +}; + + +/** + * optional DocumentHistory document_history = 1; + * @return {?proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.getDocumentHistory = function() { + return /** @type{?proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} */ ( + jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory, 1)); +}; + + +/** + * @param {?proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory|undefined} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} returns this +*/ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.setDocumentHistory = function(value) { + return jspb.Message.setOneofWrapperField(this, 1, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.oneofGroups_[0], value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.clearDocumentHistory = function() { + return this.setDocumentHistory(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.hasDocumentHistory = function() { + return jspb.Message.getField(this, 1) != null; +}; + + +/** + * optional Proof proof = 2; + * @return {?proto.org.dash.platform.dapi.v0.Proof} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.getProof = function() { + return /** @type{?proto.org.dash.platform.dapi.v0.Proof} */ ( + jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.Proof, 2)); +}; + + +/** + * @param {?proto.org.dash.platform.dapi.v0.Proof|undefined} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} returns this +*/ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.setProof = function(value) { + return jspb.Message.setOneofWrapperField(this, 2, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.oneofGroups_[0], value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.clearProof = function() { + return this.setProof(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.hasProof = function() { + return jspb.Message.getField(this, 2) != null; +}; + + +/** + * optional ResponseMetadata metadata = 3; + * @return {?proto.org.dash.platform.dapi.v0.ResponseMetadata} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.getMetadata = function() { + return /** @type{?proto.org.dash.platform.dapi.v0.ResponseMetadata} */ ( + jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.ResponseMetadata, 3)); +}; + + +/** + * @param {?proto.org.dash.platform.dapi.v0.ResponseMetadata|undefined} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} returns this +*/ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.setMetadata = function(value) { + return jspb.Message.setWrapperField(this, 3, value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.clearMetadata = function() { + return this.setMetadata(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.hasMetadata = function() { + return jspb.Message.getField(this, 3) != null; +}; + + + +/** + * Oneof group definitions for this message. Each group defines the field + * numbers belonging to that group. When of these fields' value is set, all + * other fields in the group are cleared. During deserialization, if multiple + * fields are encountered for a group, only the last value seen will be kept. + * @private {!Array>} + * @const + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.oneofGroups_ = [[1,2]]; + +/** + * @enum {number} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.ResultCase = { + RESULT_NOT_SET: 0, + HISTORY: 1, + PROOF: 2 +}; + +/** + * @return {proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.ResultCase} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.prototype.getResultCase = function() { + return /** @type {proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.ResultCase} */(jspb.Message.computeOneofCase(this, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.oneofGroups_[0])); +}; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.prototype.toObject = function(opt_includeInstance) { + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.toObject = function(includeInstance, msg) { + var f, obj = { + history: (f = msg.getHistory()) && proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.toObject(includeInstance, f), + proof: (f = msg.getProof()) && proto.org.dash.platform.dapi.v0.Proof.toObject(includeInstance, f), + metadata: (f = msg.getMetadata()) && proto.org.dash.platform.dapi.v0.ResponseMetadata.toObject(includeInstance, f) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1; + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.deserializeBinaryFromReader); + msg.setHistory(value); + break; + case 2: + var value = new proto.org.dash.platform.dapi.v0.Proof; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.Proof.deserializeBinaryFromReader); + msg.setProof(value); + break; + case 3: + var value = new proto.org.dash.platform.dapi.v0.ResponseMetadata; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.ResponseMetadata.deserializeBinaryFromReader); + msg.setMetadata(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getHistory(); + if (f != null) { + writer.writeMessage( + 1, + f, + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.serializeBinaryToWriter + ); + } + f = message.getProof(); + if (f != null) { + writer.writeMessage( + 2, + f, + proto.org.dash.platform.dapi.v0.Proof.serializeBinaryToWriter + ); + } + f = message.getMetadata(); + if (f != null) { + writer.writeMessage( + 3, + f, + proto.org.dash.platform.dapi.v0.ResponseMetadata.serializeBinaryToWriter + ); + } +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.prototype.toObject = function(opt_includeInstance) { + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.toObject = function(includeInstance, msg) { + var f, obj = { + timeMs: jspb.Message.getFieldWithDefault(msg, 1, "0"), + revision: jspb.Message.getFieldWithDefault(msg, 2, "0"), + document: msg.getDocument_asB64() + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry; + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readUint64String()); + msg.setTimeMs(value); + break; + case 2: + var value = /** @type {string} */ (reader.readUint64String()); + msg.setRevision(value); + break; + case 3: + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setDocument(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getTimeMs(); + if (parseInt(f, 10) !== 0) { + writer.writeUint64String( + 1, + f + ); + } + f = message.getRevision(); + if (parseInt(f, 10) !== 0) { + writer.writeUint64String( + 2, + f + ); + } + f = message.getDocument_asU8(); + if (f.length > 0) { + writer.writeBytes( + 3, + f + ); + } +}; + + +/** + * optional uint64 time_ms = 1; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.prototype.getTimeMs = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "0")); +}; + + +/** + * @param {string} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.prototype.setTimeMs = function(value) { + return jspb.Message.setProto3StringIntField(this, 1, value); +}; + + +/** + * optional uint64 revision = 2; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.prototype.getRevision = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "0")); +}; + + +/** + * @param {string} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.prototype.setRevision = function(value) { + return jspb.Message.setProto3StringIntField(this, 2, value); +}; + + +/** + * optional bytes document = 3; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.prototype.getDocument = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); +}; + + +/** + * optional bytes document = 3; + * This is a type-conversion wrapper around `getDocument()` + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.prototype.getDocument_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getDocument())); +}; + + +/** + * optional bytes document = 3; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getDocument()` + * @return {!Uint8Array} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.prototype.getDocument_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getDocument())); +}; + + +/** + * @param {!(string|Uint8Array)} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.prototype.setDocument = function(value) { + return jspb.Message.setProto3BytesField(this, 3, value); +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.prototype.toObject = function(opt_includeInstance) { + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.toObject = function(includeInstance, msg) { + var f, obj = { + state: jspb.Message.getFieldWithDefault(msg, 1, 0), + remainingRevisions: jspb.Message.getFieldWithDefault(msg, 2, "0") + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle; + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.State} */ (reader.readEnum()); + msg.setState(value); + break; + case 2: + var value = /** @type {string} */ (reader.readUint64String()); + msg.setRemainingRevisions(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getState(); + if (f !== 0.0) { + writer.writeEnum( + 1, + f + ); + } + f = message.getRemainingRevisions(); + if (parseInt(f, 10) !== 0) { + writer.writeUint64String( + 2, + f + ); + } +}; + + +/** + * @enum {number} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.State = { + ACTIVE: 0, + ABSENT: 1 +}; + +/** + * optional State state = 1; + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.State} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.prototype.getState = function() { + return /** @type {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.State} */ (jspb.Message.getFieldWithDefault(this, 1, 0)); +}; + + +/** + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.State} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.prototype.setState = function(value) { + return jspb.Message.setProto3EnumField(this, 1, value); +}; + + +/** + * optional uint64 remaining_revisions = 2; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.prototype.getRemainingRevisions = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "0")); +}; + + +/** + * @param {string} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.prototype.setRemainingRevisions = function(value) { + return jspb.Message.setProto3StringIntField(this, 2, value); }; @@ -58051,7 +59776,7 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryRes * @private {!Array} * @const */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.repeatedFields_ = [1]; +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.repeatedFields_ = [1]; @@ -58068,8 +59793,8 @@ if (jspb.Message.GENERATE_TO_OBJECT) { * http://goto/soy-param-migration * @return {!Object} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.prototype.toObject = function(opt_includeInstance) { - return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.toObject(opt_includeInstance, this); +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.prototype.toObject = function(opt_includeInstance) { + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.toObject(opt_includeInstance, this); }; @@ -58078,14 +59803,15 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryRes * @param {boolean|undefined} includeInstance Deprecated. Whether to include * the JSPB instance for transitional soy proto support: * http://goto/soy-param-migration - * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} msg The msg instance to transform. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History} msg The msg instance to transform. * @return {!Object} * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.toObject = function(includeInstance, msg) { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.toObject = function(includeInstance, msg) { var f, obj = { - documentEntriesList: jspb.Message.toObjectList(msg.getDocumentEntriesList(), - proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.toObject, includeInstance) + entriesList: jspb.Message.toObjectList(msg.getEntriesList(), + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.toObject, includeInstance), + lifecycle: (f = msg.getLifecycle()) && proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.toObject(includeInstance, f) }; if (includeInstance) { @@ -58099,23 +59825,23 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryRes /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.deserializeBinary = function(bytes) { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); - var msg = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory; - return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.deserializeBinaryFromReader(msg, reader); + var msg = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History; + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. - * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} msg The message object to deserialize into. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.deserializeBinaryFromReader = function(msg, reader) { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; @@ -58123,9 +59849,14 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryRes var field = reader.getFieldNumber(); switch (field) { case 1: - var value = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry; - reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.deserializeBinaryFromReader); - msg.addDocumentEntries(value); + var value = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.deserializeBinaryFromReader); + msg.addEntries(value); + break; + case 2: + var value = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.deserializeBinaryFromReader); + msg.setLifecycle(value); break; default: reader.skipField(); @@ -58140,9 +59871,9 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryRes * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.prototype.serializeBinary = function() { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); - proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.serializeBinaryToWriter(this, writer); + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.serializeBinaryToWriter(this, writer); return writer.getResultBuffer(); }; @@ -58150,86 +59881,94 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryRes /** * Serializes the given message to binary data (in protobuf wire * format), writing to the given BinaryWriter. - * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} message + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History} message * @param {!jspb.BinaryWriter} writer * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.serializeBinaryToWriter = function(message, writer) { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.serializeBinaryToWriter = function(message, writer) { var f = undefined; - f = message.getDocumentEntriesList(); + f = message.getEntriesList(); if (f.length > 0) { writer.writeRepeatedMessage( 1, f, - proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.serializeBinaryToWriter + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.serializeBinaryToWriter + ); + } + f = message.getLifecycle(); + if (f != null) { + writer.writeMessage( + 2, + f, + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.serializeBinaryToWriter ); } }; /** - * repeated DocumentHistoryEntry document_entries = 1; - * @return {!Array} + * repeated Entry entries = 1; + * @return {!Array} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.prototype.getDocumentEntriesList = function() { - return /** @type{!Array} */ ( - jspb.Message.getRepeatedWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry, 1)); +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.prototype.getEntriesList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry, 1)); }; /** - * @param {!Array} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} returns this + * @param {!Array} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.prototype.setDocumentEntriesList = function(value) { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.prototype.setEntriesList = function(value) { return jspb.Message.setRepeatedWrapperField(this, 1, value); }; /** - * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry=} opt_value + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry=} opt_value * @param {number=} opt_index - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.prototype.addDocumentEntries = function(opt_value, opt_index) { - return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry, opt_index); +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.prototype.addEntries = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry, opt_index); }; /** * Clears the list making it empty but non-null. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} returns this + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.prototype.clearDocumentEntriesList = function() { - return this.setDocumentEntriesList([]); +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.prototype.clearEntriesList = function() { + return this.setEntriesList([]); }; /** - * optional DocumentHistory document_history = 1; - * @return {?proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} + * optional Lifecycle lifecycle = 2; + * @return {?proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.getDocumentHistory = function() { - return /** @type{?proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} */ ( - jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory, 1)); +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.prototype.getLifecycle = function() { + return /** @type{?proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle} */ ( + jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle, 2)); }; /** - * @param {?proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory|undefined} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} returns this + * @param {?proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle|undefined} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.setDocumentHistory = function(value) { - return jspb.Message.setOneofWrapperField(this, 1, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.oneofGroups_[0], value); +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.prototype.setLifecycle = function(value) { + return jspb.Message.setWrapperField(this, 2, value); }; /** * Clears the message field making it undefined. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} returns this + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.clearDocumentHistory = function() { - return this.setDocumentHistory(undefined); +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.prototype.clearLifecycle = function() { + return this.setLifecycle(undefined); }; @@ -58237,7 +59976,44 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryRes * Returns whether this field is set. * @return {boolean} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.hasDocumentHistory = function() { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.prototype.hasLifecycle = function() { + return jspb.Message.getField(this, 2) != null; +}; + + +/** + * optional History history = 1; + * @return {?proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.prototype.getHistory = function() { + return /** @type{?proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History} */ ( + jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History, 1)); +}; + + +/** + * @param {?proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History|undefined} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1} returns this +*/ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.prototype.setHistory = function(value) { + return jspb.Message.setOneofWrapperField(this, 1, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.oneofGroups_[0], value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.prototype.clearHistory = function() { + return this.setHistory(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.prototype.hasHistory = function() { return jspb.Message.getField(this, 1) != null; }; @@ -58246,7 +60022,7 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryRes * optional Proof proof = 2; * @return {?proto.org.dash.platform.dapi.v0.Proof} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.getProof = function() { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.prototype.getProof = function() { return /** @type{?proto.org.dash.platform.dapi.v0.Proof} */ ( jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.Proof, 2)); }; @@ -58254,18 +60030,18 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryRes /** * @param {?proto.org.dash.platform.dapi.v0.Proof|undefined} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} returns this + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.setProof = function(value) { - return jspb.Message.setOneofWrapperField(this, 2, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.oneofGroups_[0], value); +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.prototype.setProof = function(value) { + return jspb.Message.setOneofWrapperField(this, 2, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.oneofGroups_[0], value); }; /** * Clears the message field making it undefined. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} returns this + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.clearProof = function() { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.prototype.clearProof = function() { return this.setProof(undefined); }; @@ -58274,7 +60050,7 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryRes * Returns whether this field is set. * @return {boolean} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.hasProof = function() { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.prototype.hasProof = function() { return jspb.Message.getField(this, 2) != null; }; @@ -58283,7 +60059,7 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryRes * optional ResponseMetadata metadata = 3; * @return {?proto.org.dash.platform.dapi.v0.ResponseMetadata} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.getMetadata = function() { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.prototype.getMetadata = function() { return /** @type{?proto.org.dash.platform.dapi.v0.ResponseMetadata} */ ( jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.ResponseMetadata, 3)); }; @@ -58291,18 +60067,18 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryRes /** * @param {?proto.org.dash.platform.dapi.v0.ResponseMetadata|undefined} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} returns this + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.setMetadata = function(value) { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.prototype.setMetadata = function(value) { return jspb.Message.setWrapperField(this, 3, value); }; /** * Clears the message field making it undefined. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} returns this + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.clearMetadata = function() { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.prototype.clearMetadata = function() { return this.setMetadata(undefined); }; @@ -58311,7 +60087,7 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryRes * Returns whether this field is set. * @return {boolean} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.hasMetadata = function() { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.prototype.hasMetadata = function() { return jspb.Message.getField(this, 3) != null; }; @@ -58353,6 +60129,43 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.prototype.hasV0 = fun }; +/** + * optional GetDocumentHistoryResponseV1 v1 = 2; + * @return {?proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.prototype.getV1 = function() { + return /** @type{?proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1} */ ( + jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1, 2)); +}; + + +/** + * @param {?proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1|undefined} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse} returns this +*/ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.prototype.setV1 = function(value) { + return jspb.Message.setOneofWrapperField(this, 2, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.oneofGroups_[0], value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.prototype.clearV1 = function() { + return this.setV1(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.prototype.hasV1 = function() { + return jspb.Message.getField(this, 2) != null; +}; + + /** * Oneof group definitions for this message. Each group defines the field 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 d0dd4299e86..f081a7414f9 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 @@ -146,9 +146,15 @@ CF_EXTERN_C_BEGIN @class GetDataContractsResponse_DataContracts; @class GetDataContractsResponse_GetDataContractsResponseV0; @class GetDocumentHistoryRequest_GetDocumentHistoryRequestV0; +@class GetDocumentHistoryRequest_GetDocumentHistoryRequestV1; +@class GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_Cursor; @class GetDocumentHistoryResponse_GetDocumentHistoryResponseV0; @class GetDocumentHistoryResponse_GetDocumentHistoryResponseV0_DocumentHistory; @class GetDocumentHistoryResponse_GetDocumentHistoryResponseV0_DocumentHistoryEntry; +@class GetDocumentHistoryResponse_GetDocumentHistoryResponseV1; +@class GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Entry; +@class GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_History; +@class GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle; @class GetDocumentsRequest_DocumentFieldValue; @class GetDocumentsRequest_DocumentFieldValue_ValueList; @class GetDocumentsRequest_GetDocumentsRequestV0; @@ -756,6 +762,27 @@ GPBEnumDescriptor *GetDocumentsRequest_GetDocumentsRequestV1_SubQuery_Kind_EnumD **/ BOOL GetDocumentsRequest_GetDocumentsRequestV1_SubQuery_Kind_IsValidValue(int32_t value); +#pragma mark - Enum GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle_State + +typedef GPB_ENUM(GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle_State) { + /** + * Value used if any message's field encounters a value that is not defined + * by this enum. The message will also have C functions to get/set the rawValue + * of the field. + **/ + GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle_State_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue, + GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle_State_Active = 0, + GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle_State_Absent = 1, +}; + +GPBEnumDescriptor *GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle_State_EnumDescriptor(void); + +/** + * Checks to see if the given value is defined by the enum or was not known at + * the time this source was generated. + **/ +BOOL GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle_State_IsValidValue(int32_t value); + #pragma mark - Enum GetYesNoVotePollStateResponse_GetYesNoVotePollStateResponseV0_YesNoVotePoll_VotingPowerRounding /** How a share of the total voting power rounds to a whole voting power */ @@ -7126,11 +7153,13 @@ void GetDocumentsResponse_GetDocumentsResponseV1_CompositeDocuments_SubQueryResu typedef GPB_ENUM(GetDocumentHistoryRequest_FieldNumber) { GetDocumentHistoryRequest_FieldNumber_V0 = 1, + GetDocumentHistoryRequest_FieldNumber_V1 = 2, }; typedef GPB_ENUM(GetDocumentHistoryRequest_Version_OneOfCase) { GetDocumentHistoryRequest_Version_OneOfCase_GPBUnsetOneOfCase = 0, GetDocumentHistoryRequest_Version_OneOfCase_V0 = 1, + GetDocumentHistoryRequest_Version_OneOfCase_V1 = 2, }; GPB_FINAL @interface GetDocumentHistoryRequest : GPBMessage @@ -7139,6 +7168,8 @@ GPB_FINAL @interface GetDocumentHistoryRequest : GPBMessage @property(nonatomic, readwrite, strong, null_resettable) GetDocumentHistoryRequest_GetDocumentHistoryRequestV0 *v0; +@property(nonatomic, readwrite, strong, null_resettable) GetDocumentHistoryRequest_GetDocumentHistoryRequestV1 *v1; + @end /** @@ -7187,15 +7218,93 @@ GPB_FINAL @interface GetDocumentHistoryRequest_GetDocumentHistoryRequestV0 : GPB @end +#pragma mark - GetDocumentHistoryRequest_GetDocumentHistoryRequestV1 + +typedef GPB_ENUM(GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_FieldNumber) { + GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_FieldNumber_DataContractId = 1, + GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_FieldNumber_DocumentTypeName = 2, + GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_FieldNumber_DocumentId = 3, + GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_FieldNumber_Limit = 4, + GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_FieldNumber_Prove = 5, + GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_FieldNumber_StartAtMs = 6, + GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_FieldNumber_StartAfter = 7, + GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_FieldNumber_StartAtRevision = 8, + GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_FieldNumber_Revision = 9, +}; + +typedef GPB_ENUM(GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_Filter_OneOfCase) { + GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_Filter_OneOfCase_GPBUnsetOneOfCase = 0, + GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_Filter_OneOfCase_StartAtMs = 6, + GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_Filter_OneOfCase_StartAfter = 7, + GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_Filter_OneOfCase_StartAtRevision = 8, + GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_Filter_OneOfCase_Revision = 9, +}; + +/** + * Reads the retained revisions of a historical document (a type with + * documentsKeepHistory), selected by time, revision, or a composite cursor. + **/ +GPB_FINAL @interface GetDocumentHistoryRequest_GetDocumentHistoryRequestV1 : GPBMessage + +@property(nonatomic, readwrite, copy, null_resettable) NSData *dataContractId; + +@property(nonatomic, readwrite, copy, null_resettable) NSString *documentTypeName; + +@property(nonatomic, readwrite, copy, null_resettable) NSData *documentId; + +@property(nonatomic, readwrite, strong, null_resettable) GPBUInt32Value *limit; +/** Test to see if @c limit has been set. */ +@property(nonatomic, readwrite) BOOL hasLimit; + +@property(nonatomic, readwrite) BOOL prove; + +@property(nonatomic, readonly) GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_Filter_OneOfCase filterOneOfCase; + +@property(nonatomic, readwrite) uint64_t startAtMs; + +@property(nonatomic, readwrite, strong, null_resettable) GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_Cursor *startAfter; + +@property(nonatomic, readwrite) uint64_t startAtRevision; + +@property(nonatomic, readwrite) uint64_t revision; + +@end + +/** + * Clears whatever value was set for the oneof 'filter'. + **/ +void GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_ClearFilterOneOfCase(GetDocumentHistoryRequest_GetDocumentHistoryRequestV1 *message); + +#pragma mark - GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_Cursor + +typedef GPB_ENUM(GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_Cursor_FieldNumber) { + GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_Cursor_FieldNumber_TimeMs = 1, + GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_Cursor_FieldNumber_Revision = 2, +}; + +/** + * Exclusive cursor returned with a page. Several revisions can share a + * block time, so resuming needs the revision as well as the time. + **/ +GPB_FINAL @interface GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_Cursor : GPBMessage + +@property(nonatomic, readwrite) uint64_t timeMs; + +@property(nonatomic, readwrite) uint64_t revision; + +@end + #pragma mark - GetDocumentHistoryResponse typedef GPB_ENUM(GetDocumentHistoryResponse_FieldNumber) { GetDocumentHistoryResponse_FieldNumber_V0 = 1, + GetDocumentHistoryResponse_FieldNumber_V1 = 2, }; typedef GPB_ENUM(GetDocumentHistoryResponse_Version_OneOfCase) { GetDocumentHistoryResponse_Version_OneOfCase_GPBUnsetOneOfCase = 0, GetDocumentHistoryResponse_Version_OneOfCase_V0 = 1, + GetDocumentHistoryResponse_Version_OneOfCase_V1 = 2, }; GPB_FINAL @interface GetDocumentHistoryResponse : GPBMessage @@ -7204,6 +7313,8 @@ GPB_FINAL @interface GetDocumentHistoryResponse : GPBMessage @property(nonatomic, readwrite, strong, null_resettable) GetDocumentHistoryResponse_GetDocumentHistoryResponseV0 *v0; +@property(nonatomic, readwrite, strong, null_resettable) GetDocumentHistoryResponse_GetDocumentHistoryResponseV1 *v1; + @end /** @@ -7285,6 +7396,125 @@ GPB_FINAL @interface GetDocumentHistoryResponse_GetDocumentHistoryResponseV0_Doc @end +#pragma mark - GetDocumentHistoryResponse_GetDocumentHistoryResponseV1 + +typedef GPB_ENUM(GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_FieldNumber) { + GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_FieldNumber_History = 1, + GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_FieldNumber_Proof = 2, + GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_FieldNumber_Metadata = 3, +}; + +typedef GPB_ENUM(GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Result_OneOfCase) { + GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Result_OneOfCase_GPBUnsetOneOfCase = 0, + GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Result_OneOfCase_History = 1, + GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Result_OneOfCase_Proof = 2, +}; + +/** + * A page of a historical document's retained revisions, with the + * document's lifecycle as of the same block. Only document types with + * documentsKeepHistory retain history; every field here describes such a + * historical document. + **/ +GPB_FINAL @interface GetDocumentHistoryResponse_GetDocumentHistoryResponseV1 : GPBMessage + +@property(nonatomic, readonly) GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Result_OneOfCase resultOneOfCase; + +@property(nonatomic, readwrite, strong, null_resettable) GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_History *history; + +/** + * One GroveDB proof authenticates the offset-paginated history page, + * current pointer, lifecycle reservation, and retained revision count. + **/ +@property(nonatomic, readwrite, strong, null_resettable) Proof *proof; + +@property(nonatomic, readwrite, strong, null_resettable) ResponseMetadata *metadata; +/** Test to see if @c metadata has been set. */ +@property(nonatomic, readwrite) BOOL hasMetadata; + +@end + +/** + * Clears whatever value was set for the oneof 'result'. + **/ +void GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_ClearResultOneOfCase(GetDocumentHistoryResponse_GetDocumentHistoryResponseV1 *message); + +#pragma mark - GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Entry + +typedef GPB_ENUM(GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Entry_FieldNumber) { + GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Entry_FieldNumber_TimeMs = 1, + GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Entry_FieldNumber_Revision = 2, + GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Entry_FieldNumber_Document = 3, +}; + +/** + * One retained revision of the historical document. + **/ +GPB_FINAL @interface GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Entry : GPBMessage + +@property(nonatomic, readwrite) uint64_t timeMs; + +@property(nonatomic, readwrite) uint64_t revision; + +@property(nonatomic, readwrite, copy, null_resettable) NSData *document; + +@end + +#pragma mark - GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle + +typedef GPB_ENUM(GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle_FieldNumber) { + GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle_FieldNumber_State = 1, + GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle_FieldNumber_RemainingRevisions = 2, +}; + +/** + * Where the historical document stands: still current, or gone with + * nothing retained. Later protocol versions add the states between. + **/ +GPB_FINAL @interface GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle : GPBMessage + +@property(nonatomic, readwrite) GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle_State state; + +/** Revisions the history still retains for the document. */ +@property(nonatomic, readwrite) uint64_t remainingRevisions; + +@end + +/** + * Fetches the raw value of a @c GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle's @c state property, even + * if the value was not defined by the enum at the time the code was generated. + **/ +int32_t GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle_State_RawValue(GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle *message); +/** + * Sets the raw value of an @c GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle's @c state property, allowing + * it to be set to a value that was not defined by the enum at the time the code + * was generated. + **/ +void SetGetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle_State_RawValue(GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle *message, int32_t value); + +#pragma mark - GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_History + +typedef GPB_ENUM(GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_History_FieldNumber) { + GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_History_FieldNumber_EntriesArray = 1, + GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_History_FieldNumber_Lifecycle = 2, +}; + +/** + * A page of retained revisions and the document's lifecycle as of the + * same block. + **/ +GPB_FINAL @interface GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_History : GPBMessage + +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *entriesArray; +/** The number of items in @c entriesArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger entriesArray_Count; + +@property(nonatomic, readwrite, strong, null_resettable) GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle *lifecycle; +/** Test to see if @c lifecycle has been set. */ +@property(nonatomic, readwrite) BOOL hasLifecycle; + +@end + #pragma mark - GetIdentityByPublicKeyHashRequest typedef GPB_ENUM(GetIdentityByPublicKeyHashRequest_FieldNumber) { 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 4d6f7cac71a..da10d54ee72 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 @@ -196,10 +196,16 @@ GPBObjCClassDeclaration(GetDataContractsResponse_GetDataContractsResponseV0); GPBObjCClassDeclaration(GetDocumentHistoryRequest); GPBObjCClassDeclaration(GetDocumentHistoryRequest_GetDocumentHistoryRequestV0); +GPBObjCClassDeclaration(GetDocumentHistoryRequest_GetDocumentHistoryRequestV1); +GPBObjCClassDeclaration(GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_Cursor); GPBObjCClassDeclaration(GetDocumentHistoryResponse); GPBObjCClassDeclaration(GetDocumentHistoryResponse_GetDocumentHistoryResponseV0); GPBObjCClassDeclaration(GetDocumentHistoryResponse_GetDocumentHistoryResponseV0_DocumentHistory); GPBObjCClassDeclaration(GetDocumentHistoryResponse_GetDocumentHistoryResponseV0_DocumentHistoryEntry); +GPBObjCClassDeclaration(GetDocumentHistoryResponse_GetDocumentHistoryResponseV1); +GPBObjCClassDeclaration(GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Entry); +GPBObjCClassDeclaration(GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_History); +GPBObjCClassDeclaration(GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle); GPBObjCClassDeclaration(GetDocumentsRequest); GPBObjCClassDeclaration(GetDocumentsRequest_DocumentFieldValue); GPBObjCClassDeclaration(GetDocumentsRequest_DocumentFieldValue_ValueList); @@ -14237,10 +14243,12 @@ @implementation GetDocumentHistoryRequest @dynamic versionOneOfCase; @dynamic v0; +@dynamic v1; typedef struct GetDocumentHistoryRequest__storage_ { uint32_t _has_storage_[2]; GetDocumentHistoryRequest_GetDocumentHistoryRequestV0 *v0; + GetDocumentHistoryRequest_GetDocumentHistoryRequestV1 *v1; } GetDocumentHistoryRequest__storage_; // This method is threadsafe because it is initially called @@ -14258,6 +14266,15 @@ + (GPBDescriptor *)descriptor { .flags = GPBFieldOptional, .dataType = GPBDataTypeMessage, }, + { + .name = "v1", + .dataTypeSpecific.clazz = GPBObjCClass(GetDocumentHistoryRequest_GetDocumentHistoryRequestV1), + .number = GetDocumentHistoryRequest_FieldNumber_V1, + .hasIndex = -1, + .offset = (uint32_t)offsetof(GetDocumentHistoryRequest__storage_, v1), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, }; GPBDescriptor *localDescriptor = [GPBDescriptor allocDescriptorForClass:[GetDocumentHistoryRequest class] @@ -14399,16 +14416,220 @@ + (GPBDescriptor *)descriptor { @end +#pragma mark - GetDocumentHistoryRequest_GetDocumentHistoryRequestV1 + +@implementation GetDocumentHistoryRequest_GetDocumentHistoryRequestV1 + +@dynamic filterOneOfCase; +@dynamic dataContractId; +@dynamic documentTypeName; +@dynamic documentId; +@dynamic hasLimit, limit; +@dynamic prove; +@dynamic startAtMs; +@dynamic startAfter; +@dynamic startAtRevision; +@dynamic revision; + +typedef struct GetDocumentHistoryRequest_GetDocumentHistoryRequestV1__storage_ { + uint32_t _has_storage_[2]; + NSData *dataContractId; + NSString *documentTypeName; + NSData *documentId; + GPBUInt32Value *limit; + GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_Cursor *startAfter; + uint64_t startAtMs; + uint64_t startAtRevision; + uint64_t revision; +} GetDocumentHistoryRequest_GetDocumentHistoryRequestV1__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "dataContractId", + .dataTypeSpecific.clazz = Nil, + .number = GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_FieldNumber_DataContractId, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GetDocumentHistoryRequest_GetDocumentHistoryRequestV1__storage_, dataContractId), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeBytes, + }, + { + .name = "documentTypeName", + .dataTypeSpecific.clazz = Nil, + .number = GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_FieldNumber_DocumentTypeName, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GetDocumentHistoryRequest_GetDocumentHistoryRequestV1__storage_, documentTypeName), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeString, + }, + { + .name = "documentId", + .dataTypeSpecific.clazz = Nil, + .number = GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_FieldNumber_DocumentId, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GetDocumentHistoryRequest_GetDocumentHistoryRequestV1__storage_, documentId), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeBytes, + }, + { + .name = "limit", + .dataTypeSpecific.clazz = GPBObjCClass(GPBUInt32Value), + .number = GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_FieldNumber_Limit, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GetDocumentHistoryRequest_GetDocumentHistoryRequestV1__storage_, limit), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "prove", + .dataTypeSpecific.clazz = Nil, + .number = GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_FieldNumber_Prove, + .hasIndex = 4, + .offset = 5, // Stored in _has_storage_ to save space. + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeBool, + }, + { + .name = "startAtMs", + .dataTypeSpecific.clazz = Nil, + .number = GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_FieldNumber_StartAtMs, + .hasIndex = -1, + .offset = (uint32_t)offsetof(GetDocumentHistoryRequest_GetDocumentHistoryRequestV1__storage_, startAtMs), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeUInt64, + }, + { + .name = "startAfter", + .dataTypeSpecific.clazz = GPBObjCClass(GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_Cursor), + .number = GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_FieldNumber_StartAfter, + .hasIndex = -1, + .offset = (uint32_t)offsetof(GetDocumentHistoryRequest_GetDocumentHistoryRequestV1__storage_, startAfter), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "startAtRevision", + .dataTypeSpecific.clazz = Nil, + .number = GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_FieldNumber_StartAtRevision, + .hasIndex = -1, + .offset = (uint32_t)offsetof(GetDocumentHistoryRequest_GetDocumentHistoryRequestV1__storage_, startAtRevision), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeUInt64, + }, + { + .name = "revision", + .dataTypeSpecific.clazz = Nil, + .number = GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_FieldNumber_Revision, + .hasIndex = -1, + .offset = (uint32_t)offsetof(GetDocumentHistoryRequest_GetDocumentHistoryRequestV1__storage_, revision), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeUInt64, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GetDocumentHistoryRequest_GetDocumentHistoryRequestV1 class] + rootClass:[PlatformRoot class] + file:PlatformRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GetDocumentHistoryRequest_GetDocumentHistoryRequestV1__storage_) + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; + static const char *oneofs[] = { + "filter", + }; + [localDescriptor setupOneofs:oneofs + count:(uint32_t)(sizeof(oneofs) / sizeof(char*)) + firstHasIndex:-1]; + [localDescriptor setupContainingMessageClass:GPBObjCClass(GetDocumentHistoryRequest)]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +void GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_ClearFilterOneOfCase(GetDocumentHistoryRequest_GetDocumentHistoryRequestV1 *message) { + GPBDescriptor *descriptor = [GetDocumentHistoryRequest_GetDocumentHistoryRequestV1 descriptor]; + GPBOneofDescriptor *oneof = [descriptor.oneofs objectAtIndex:0]; + GPBClearOneof(message, oneof); +} +#pragma mark - GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_Cursor + +@implementation GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_Cursor + +@dynamic timeMs; +@dynamic revision; + +typedef struct GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_Cursor__storage_ { + uint32_t _has_storage_[1]; + uint64_t timeMs; + uint64_t revision; +} GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_Cursor__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "timeMs", + .dataTypeSpecific.clazz = Nil, + .number = GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_Cursor_FieldNumber_TimeMs, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_Cursor__storage_, timeMs), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeUInt64, + }, + { + .name = "revision", + .dataTypeSpecific.clazz = Nil, + .number = GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_Cursor_FieldNumber_Revision, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_Cursor__storage_, revision), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeUInt64, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_Cursor class] + rootClass:[PlatformRoot class] + file:PlatformRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GetDocumentHistoryRequest_GetDocumentHistoryRequestV1_Cursor__storage_) + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; + [localDescriptor setupContainingMessageClass:GPBObjCClass(GetDocumentHistoryRequest_GetDocumentHistoryRequestV1)]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + #pragma mark - GetDocumentHistoryResponse @implementation GetDocumentHistoryResponse @dynamic versionOneOfCase; @dynamic v0; +@dynamic v1; typedef struct GetDocumentHistoryResponse__storage_ { uint32_t _has_storage_[2]; GetDocumentHistoryResponse_GetDocumentHistoryResponseV0 *v0; + GetDocumentHistoryResponse_GetDocumentHistoryResponseV1 *v1; } GetDocumentHistoryResponse__storage_; // This method is threadsafe because it is initially called @@ -14426,6 +14647,15 @@ + (GPBDescriptor *)descriptor { .flags = GPBFieldOptional, .dataType = GPBDataTypeMessage, }, + { + .name = "v1", + .dataTypeSpecific.clazz = GPBObjCClass(GetDocumentHistoryResponse_GetDocumentHistoryResponseV1), + .number = GetDocumentHistoryResponse_FieldNumber_V1, + .hasIndex = -1, + .offset = (uint32_t)offsetof(GetDocumentHistoryResponse__storage_, v1), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, }; GPBDescriptor *localDescriptor = [GPBDescriptor allocDescriptorForClass:[GetDocumentHistoryResponse class] @@ -14639,6 +14869,315 @@ + (GPBDescriptor *)descriptor { @end +#pragma mark - GetDocumentHistoryResponse_GetDocumentHistoryResponseV1 + +@implementation GetDocumentHistoryResponse_GetDocumentHistoryResponseV1 + +@dynamic resultOneOfCase; +@dynamic history; +@dynamic proof; +@dynamic hasMetadata, metadata; + +typedef struct GetDocumentHistoryResponse_GetDocumentHistoryResponseV1__storage_ { + uint32_t _has_storage_[2]; + GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_History *history; + Proof *proof; + ResponseMetadata *metadata; +} GetDocumentHistoryResponse_GetDocumentHistoryResponseV1__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "history", + .dataTypeSpecific.clazz = GPBObjCClass(GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_History), + .number = GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_FieldNumber_History, + .hasIndex = -1, + .offset = (uint32_t)offsetof(GetDocumentHistoryResponse_GetDocumentHistoryResponseV1__storage_, history), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "proof", + .dataTypeSpecific.clazz = GPBObjCClass(Proof), + .number = GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_FieldNumber_Proof, + .hasIndex = -1, + .offset = (uint32_t)offsetof(GetDocumentHistoryResponse_GetDocumentHistoryResponseV1__storage_, proof), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + { + .name = "metadata", + .dataTypeSpecific.clazz = GPBObjCClass(ResponseMetadata), + .number = GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_FieldNumber_Metadata, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GetDocumentHistoryResponse_GetDocumentHistoryResponseV1__storage_, metadata), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GetDocumentHistoryResponse_GetDocumentHistoryResponseV1 class] + rootClass:[PlatformRoot class] + file:PlatformRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GetDocumentHistoryResponse_GetDocumentHistoryResponseV1__storage_) + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; + static const char *oneofs[] = { + "result", + }; + [localDescriptor setupOneofs:oneofs + count:(uint32_t)(sizeof(oneofs) / sizeof(char*)) + firstHasIndex:-1]; + [localDescriptor setupContainingMessageClass:GPBObjCClass(GetDocumentHistoryResponse)]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +void GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_ClearResultOneOfCase(GetDocumentHistoryResponse_GetDocumentHistoryResponseV1 *message) { + GPBDescriptor *descriptor = [GetDocumentHistoryResponse_GetDocumentHistoryResponseV1 descriptor]; + GPBOneofDescriptor *oneof = [descriptor.oneofs objectAtIndex:0]; + GPBClearOneof(message, oneof); +} +#pragma mark - GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Entry + +@implementation GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Entry + +@dynamic timeMs; +@dynamic revision; +@dynamic document; + +typedef struct GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Entry__storage_ { + uint32_t _has_storage_[1]; + NSData *document; + uint64_t timeMs; + uint64_t revision; +} GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Entry__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "timeMs", + .dataTypeSpecific.clazz = Nil, + .number = GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Entry_FieldNumber_TimeMs, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Entry__storage_, timeMs), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeUInt64, + }, + { + .name = "revision", + .dataTypeSpecific.clazz = Nil, + .number = GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Entry_FieldNumber_Revision, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Entry__storage_, revision), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeUInt64, + }, + { + .name = "document", + .dataTypeSpecific.clazz = Nil, + .number = GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Entry_FieldNumber_Document, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Entry__storage_, document), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeBytes, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Entry class] + rootClass:[PlatformRoot class] + file:PlatformRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Entry__storage_) + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; + [localDescriptor setupContainingMessageClass:GPBObjCClass(GetDocumentHistoryResponse_GetDocumentHistoryResponseV1)]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle + +@implementation GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle + +@dynamic state; +@dynamic remainingRevisions; + +typedef struct GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle__storage_ { + uint32_t _has_storage_[1]; + GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle_State state; + uint64_t remainingRevisions; +} GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "state", + .dataTypeSpecific.enumDescFunc = GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle_State_EnumDescriptor, + .number = GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle_FieldNumber_State, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle__storage_, state), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeEnum, + }, + { + .name = "remainingRevisions", + .dataTypeSpecific.clazz = Nil, + .number = GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle_FieldNumber_RemainingRevisions, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle__storage_, remainingRevisions), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeUInt64, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle class] + rootClass:[PlatformRoot class] + file:PlatformRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle__storage_) + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; + [localDescriptor setupContainingMessageClass:GPBObjCClass(GetDocumentHistoryResponse_GetDocumentHistoryResponseV1)]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +int32_t GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle_State_RawValue(GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle *message) { + GPBDescriptor *descriptor = [GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle_FieldNumber_State]; + return GPBGetMessageRawEnumField(message, field); +} + +void SetGetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle_State_RawValue(GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle *message, int32_t value) { + GPBDescriptor *descriptor = [GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle_FieldNumber_State]; + GPBSetMessageRawEnumField(message, field, value); +} + +#pragma mark - Enum GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle_State + +GPBEnumDescriptor *GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle_State_EnumDescriptor(void) { + static _Atomic(GPBEnumDescriptor*) descriptor = nil; + if (!descriptor) { + static const char *valueNames = + "Active\000Absent\000"; + static const int32_t values[] = { + GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle_State_Active, + GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle_State_Absent, + }; + GPBEnumDescriptor *worker = + [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle_State) + valueNames:valueNames + values:values + count:(uint32_t)(sizeof(values) / sizeof(int32_t)) + enumVerifier:GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle_State_IsValidValue]; + GPBEnumDescriptor *expected = nil; + if (!atomic_compare_exchange_strong(&descriptor, &expected, worker)) { + [worker release]; + } + } + return descriptor; +} + +BOOL GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle_State_IsValidValue(int32_t value__) { + switch (value__) { + case GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle_State_Active: + case GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle_State_Absent: + return YES; + default: + return NO; + } +} + +#pragma mark - GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_History + +@implementation GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_History + +@dynamic entriesArray, entriesArray_Count; +@dynamic hasLifecycle, lifecycle; + +typedef struct GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_History__storage_ { + uint32_t _has_storage_[1]; + NSMutableArray *entriesArray; + GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle *lifecycle; +} GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_History__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "entriesArray", + .dataTypeSpecific.clazz = GPBObjCClass(GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Entry), + .number = GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_History_FieldNumber_EntriesArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_History__storage_, entriesArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "lifecycle", + .dataTypeSpecific.clazz = GPBObjCClass(GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_Lifecycle), + .number = GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_History_FieldNumber_Lifecycle, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_History__storage_, lifecycle), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_History class] + rootClass:[PlatformRoot class] + file:PlatformRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GetDocumentHistoryResponse_GetDocumentHistoryResponseV1_History__storage_) + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; + [localDescriptor setupContainingMessageClass:GPBObjCClass(GetDocumentHistoryResponse_GetDocumentHistoryResponseV1)]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + #pragma mark - GetIdentityByPublicKeyHashRequest @implementation GetIdentityByPublicKeyHashRequest 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 870fa53fff3..7f51606d010 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\"\x8e\x02\n&GetIdentityKeysRemainingBudgetsRequest\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetIdentityKeysRemainingBudgetsRequest.GetIdentityKeysRemainingBudgetsRequestV0H\x00\x1a_\n(GetIdentityKeysRemainingBudgetsRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x0f\n\x07key_ids\x18\x02 \x03(\r\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\x96\x06\n\'GetIdentityKeysRemainingBudgetsResponse\x12z\n\x02v0\x18\x01 \x01(\x0b\x32l.org.dash.platform.dapi.v0.GetIdentityKeysRemainingBudgetsResponse.GetIdentityKeysRemainingBudgetsResponseV0H\x00\x1a\xe3\x04\n)GetIdentityKeysRemainingBudgetsResponseV0\x12\xa4\x01\n\x16keys_remaining_budgets\x18\x01 \x01(\x0b\x32\x81\x01.org.dash.platform.dapi.v0.GetIdentityKeysRemainingBudgetsResponse.GetIdentityKeysRemainingBudgetsResponseV0.KeysRemainingBudgetsH\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\x61\n\x17KeyRemainingBudgetEntry\x12\x0e\n\x06key_id\x18\x01 \x01(\r\x12!\n\x10remaining_budget\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x88\x01\x01\x42\x13\n\x11_remaining_budget\x1a\xaf\x01\n\x14KeysRemainingBudgets\x12\x96\x01\n\x07\x65ntries\x18\x01 \x03(\x0b\x32\x84\x01.org.dash.platform.dapi.v0.GetIdentityKeysRemainingBudgetsResponse.GetIdentityKeysRemainingBudgetsResponseV0.KeyRemainingBudgetEntryB\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\"\x8c\x02\n%GetDataContractsLatestVersionsRequest\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetDataContractsLatestVersionsRequest.GetDataContractsLatestVersionsRequestV0H\x00\x1a`\n\'GetDataContractsLatestVersionsRequestV0\x12\x0b\n\x03ids\x18\x01 \x03(\x0c\x12\x19\n\x11include_contracts\x18\x02 \x01(\x08\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xfa\x05\n&GetDataContractsLatestVersionsResponse\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetDataContractsLatestVersionsResponse.GetDataContractsLatestVersionsResponseV0H\x00\x1a\x84\x01\n\x1e\x44\x61taContractLatestVersionEntry\x12\x12\n\nidentifier\x18\x01 \x01(\x0c\x12\x14\n\x07version\x18\x02 \x01(\rH\x00\x88\x01\x01\x12\x1a\n\rdata_contract\x18\x03 \x01(\x0cH\x01\x88\x01\x01\x42\n\n\x08_versionB\x10\n\x0e_data_contract\x1a\x90\x01\n\x1b\x44\x61taContractsLatestVersions\x12q\n\x07\x65ntries\x18\x01 \x03(\x0b\x32`.org.dash.platform.dapi.v0.GetDataContractsLatestVersionsResponse.DataContractLatestVersionEntry\x1a\xb0\x02\n(GetDataContractsLatestVersionsResponseV0\x12\x87\x01\n\x1e\x64\x61ta_contracts_latest_versions\x18\x01 \x01(\x0b\x32].org.dash.platform.dapi.v0.GetDataContractsLatestVersionsResponse.DataContractsLatestVersionsH\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\"R\n\x1f\x43ontractGroupDocumentTypeMember\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\"G\n\x18\x43ontractGroupTokenMember\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x16\n\x0etoken_position\x18\x02 \x01(\r\"\xd7\x01\n\x1bGetContractGroupInfoRequest\x12\x62\n\x02v0\x18\x01 \x01(\x0b\x32T.org.dash.platform.dapi.v0.GetContractGroupInfoRequest.GetContractGroupInfoRequestV0H\x00\x1aI\n\x1dGetContractGroupInfoRequestV0\x12\x19\n\x11\x63ontract_group_id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x98\x04\n\x1cGetContractGroupInfoResponse\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetContractGroupInfoResponse.GetContractGroupInfoResponseV0H\x00\x1a~\n\x11\x43ontractGroupInfo\x12\x10\n\x08owner_id\x18\x01 \x01(\x0c\x12\x11\n\tadmin_ids\x18\x02 \x03(\x0c\x12\x11\n\x04name\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x18\n\x0b\x64\x65scription\x18\x04 \x01(\tH\x01\x88\x01\x01\x42\x07\n\x05_nameB\x0e\n\x0c_description\x1a\x86\x02\n\x1eGetContractGroupInfoResponseV0\x12h\n\x13\x63ontract_group_info\x18\x01 \x01(\x0b\x32I.org.dash.platform.dapi.v0.GetContractGroupInfoResponse.ContractGroupInfoH\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\"\xf8\x06\n\x1eGetContractGroupMembersRequest\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetContractGroupMembersRequest.GetContractGroupMembersRequestV0H\x00\x1a@\n\x14\x43ontractMembersQuery\x12\x18\n\x0bstart_after\x18\x01 \x01(\x0cH\x00\x88\x01\x01\x42\x0e\n\x0c_start_after\x1a\x80\x01\n\x18\x44ocumentTypeMembersQuery\x12T\n\x0bstart_after\x18\x01 \x01(\x0b\x32:.org.dash.platform.dapi.v0.ContractGroupDocumentTypeMemberH\x00\x88\x01\x01\x42\x0e\n\x0c_start_after\x1ar\n\x11TokenMembersQuery\x12M\n\x0bstart_after\x18\x01 \x01(\x0b\x32\x33.org.dash.platform.dapi.v0.ContractGroupTokenMemberH\x00\x88\x01\x01\x42\x0e\n\x0c_start_after\x1a\xa7\x03\n GetContractGroupMembersRequestV0\x12\x19\n\x11\x63ontract_group_id\x18\x01 \x01(\x0c\x12\x63\n\tcontracts\x18\x02 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetContractGroupMembersRequest.ContractMembersQueryH\x00\x12l\n\x0e\x64ocument_types\x18\x03 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetContractGroupMembersRequest.DocumentTypeMembersQueryH\x00\x12]\n\x06tokens\x18\x04 \x01(\x0b\x32K.org.dash.platform.dapi.v0.GetContractGroupMembersRequest.TokenMembersQueryH\x00\x12\x12\n\x05limit\x18\x05 \x01(\rH\x01\x88\x01\x01\x12\r\n\x05prove\x18\x06 \x01(\x08\x42\t\n\x07membersB\x08\n\x06_limitB\t\n\x07version\"\xc9\x06\n\x1fGetContractGroupMembersResponse\x12j\n\x02v0\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetContractGroupMembersResponse.GetContractGroupMembersResponseV0H\x00\x1a\'\n\x0f\x43ontractMembers\x12\x14\n\x0c\x63ontract_ids\x18\x01 \x03(\x0c\x1ai\n\x13\x44ocumentTypeMembers\x12R\n\x0e\x64ocument_types\x18\x01 \x03(\x0b\x32:.org.dash.platform.dapi.v0.ContractGroupDocumentTypeMember\x1aS\n\x0cTokenMembers\x12\x43\n\x06tokens\x18\x01 \x03(\x0b\x32\x33.org.dash.platform.dapi.v0.ContractGroupTokenMember\x1a\xc5\x03\n!GetContractGroupMembersResponseV0\x12_\n\tcontracts\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetContractGroupMembersResponse.ContractMembersH\x00\x12h\n\x0e\x64ocument_types\x18\x02 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetContractGroupMembersResponse.DocumentTypeMembersH\x00\x12Y\n\x06tokens\x18\x03 \x01(\x0b\x32G.org.dash.platform.dapi.v0.GetContractGroupMembersResponse.TokenMembersH\x00\x12\x31\n\x05proof\x18\x04 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x05 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"M\n\x1a\x43ontractModerationDocument\x12\x1a\n\x12\x64ocument_type_name\x18\x01 \x01(\t\x12\x13\n\x0b\x64ocument_id\x18\x02 \x01(\x0c\"\xc6\x01\n\x18\x43ontractModerationReason\x12\x11\n\x04\x63ode\x18\x01 \x01(\rH\x00\x88\x01\x01\x12\x0c\n\x04text\x18\x02 \x01(\t\x12H\n\tdocuments\x18\x03 \x03(\x0b\x32\x35.org.dash.platform.dapi.v0.ContractModerationDocument\x12\x1f\n\x12reason_document_id\x18\x04 \x01(\x0cH\x01\x88\x01\x01\x42\x07\n\x05_codeB\x15\n\x13_reason_document_id\"i\n\x0f\x43ontractWarning\x12\x11\n\twarned_at\x18\x01 \x01(\x04\x12\x43\n\x06reason\x18\x02 \x01(\x0b\x32\x33.org.dash.platform.dapi.v0.ContractModerationReason\"\xc5\x02\n\"GetContractModerationStatusRequest\x12p\n\x02v0\x18\x01 \x01(\x0b\x32\x62.org.dash.platform.dapi.v0.GetContractModerationStatusRequest.GetContractModerationStatusRequestV0H\x00\x1a\xa1\x01\n$GetContractModerationStatusRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x13\n\x0bidentity_id\x18\x02 \x01(\x0c\x12@\n\x05lists\x18\x03 \x03(\x0e\x32\x31.org.dash.platform.dapi.v0.ContractModerationList\x12\r\n\x05prove\x18\x04 \x01(\x08\x42\t\n\x07version\"\xec\x06\n#GetContractModerationStatusResponse\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetContractModerationStatusResponse.GetContractModerationStatusResponseV0H\x00\x1a\xb4\x03\n\x18\x43ontractModerationStatus\x12\x13\n\x06\x62\x61nned\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x1c\n\x0fsuspended_until\x18\x02 \x01(\x04H\x01\x88\x01\x01\x12@\n\x05lists\x18\x03 \x03(\x0e\x32\x31.org.dash.platform.dapi.v0.ContractModerationList\x12L\n\nban_reason\x18\x04 \x01(\x0b\x32\x33.org.dash.platform.dapi.v0.ContractModerationReasonH\x02\x88\x01\x01\x12S\n\x11suspension_reason\x18\x05 \x01(\x0b\x32\x33.org.dash.platform.dapi.v0.ContractModerationReasonH\x03\x88\x01\x01\x12<\n\x08warnings\x18\x06 \x03(\x0b\x32*.org.dash.platform.dapi.v0.ContractWarningB\t\n\x07_bannedB\x12\n\x10_suspended_untilB\r\n\x0b_ban_reasonB\x14\n\x12_suspension_reason\x1a\x8e\x02\n%GetContractModerationStatusResponseV0\x12i\n\x06status\x18\x01 \x01(\x0b\x32W.org.dash.platform.dapi.v0.GetContractModerationStatusResponse.ContractModerationStatusH\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\"\xfb\x02\n#GetContractModerationEntriesRequest\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetContractModerationEntriesRequest.GetContractModerationEntriesRequestV0H\x00\x1a\xd4\x01\n%GetContractModerationEntriesRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12?\n\x04list\x18\x02 \x01(\x0e\x32\x31.org.dash.platform.dapi.v0.ContractModerationList\x12\x18\n\x0bstart_after\x18\x03 \x01(\x0cH\x00\x88\x01\x01\x12\x12\n\x05limit\x18\x04 \x01(\rH\x01\x88\x01\x01\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\x0e\n\x0c_start_afterB\x08\n\x06_limitB\t\n\x07version\"\x96\x06\n$GetContractModerationEntriesResponse\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetContractModerationEntriesResponse.GetContractModerationEntriesResponseV0H\x00\x1a\xcf\x01\n\x17\x43ontractModerationEntry\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x12\n\x05until\x18\x02 \x01(\x04H\x00\x88\x01\x01\x12\x43\n\x06reason\x18\x03 \x01(\x0b\x32\x33.org.dash.platform.dapi.v0.ContractModerationReason\x12<\n\x08warnings\x18\x04 \x03(\x0b\x32*.org.dash.platform.dapi.v0.ContractWarningB\x08\n\x06_until\x1a\x85\x01\n\x19\x43ontractModerationEntries\x12h\n\x07\x65ntries\x18\x01 \x03(\x0b\x32W.org.dash.platform.dapi.v0.GetContractModerationEntriesResponse.ContractModerationEntry\x1a\x92\x02\n&GetContractModerationEntriesResponseV0\x12l\n\x07\x65ntries\x18\x01 \x01(\x0b\x32Y.org.dash.platform.dapi.v0.GetContractModerationEntriesResponse.ContractModerationEntriesH\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\x04\n\"GetContractDocumentRemovalsRequest\x12p\n\x02v0\x18\x01 \x01(\x0b\x32\x62.org.dash.platform.dapi.v0.GetContractDocumentRemovalsRequest.GetContractDocumentRemovalsRequestV0H\x00\x1a#\n\x0b\x44ocumentIds\x12\x14\n\x0c\x64ocument_ids\x18\x01 \x03(\x0c\x1aN\n\x04Page\x12\x18\n\x0bstart_after\x18\x01 \x01(\x0cH\x00\x88\x01\x01\x12\x12\n\x05limit\x18\x02 \x01(\rH\x01\x88\x01\x01\x42\x0e\n\x0c_start_afterB\x08\n\x06_limit\x1a\xaa\x02\n$GetContractDocumentRemovalsRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\x61\n\x0c\x64ocument_ids\x18\x03 \x01(\x0b\x32I.org.dash.platform.dapi.v0.GetContractDocumentRemovalsRequest.DocumentIdsH\x00\x12R\n\x04page\x18\x04 \x01(\x0b\x32\x42.org.dash.platform.dapi.v0.GetContractDocumentRemovalsRequest.PageH\x00\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\x0b\n\tselectionB\t\n\x07version\"\xe0\x07\n#GetContractDocumentRemovalsResponse\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetContractDocumentRemovalsResponse.GetContractDocumentRemovalsResponseV0H\x00\x1aH\n\x1b\x43ontractDocumentRestoration\x12\x14\n\x0cmoderator_id\x18\x01 \x01(\x0c\x12\x13\n\x0brestored_at\x18\x02 \x01(\x04\x1a\xd5\x02\n\x17\x43ontractDocumentRemoval\x12\x13\n\x0b\x64ocument_id\x18\x01 \x01(\x0c\x12\x19\n\x11\x64ocument_owner_id\x18\x02 \x01(\x0c\x12\x14\n\x0cmoderator_id\x18\x03 \x01(\x0c\x12\x12\n\nremoved_at\x18\x04 \x01(\x04\x12\x43\n\x06reason\x18\x05 \x01(\x0b\x32\x33.org.dash.platform.dapi.v0.ContractModerationReason\x12\x15\n\rdocument_hash\x18\x06 \x01(\x0c\x12o\n\x0brestoration\x18\x07 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetContractDocumentRemovalsResponse.ContractDocumentRestoration\x12\x13\n\x0bkept_fields\x18\x08 \x01(\x0c\x1a\x84\x01\n\x18\x43ontractDocumentRemovals\x12h\n\x08removals\x18\x01 \x03(\x0b\x32V.org.dash.platform.dapi.v0.GetContractDocumentRemovalsResponse.ContractDocumentRemoval\x1a\x90\x02\n%GetContractDocumentRemovalsResponseV0\x12k\n\x08removals\x18\x01 \x01(\x0b\x32W.org.dash.platform.dapi.v0.GetContractDocumentRemovalsResponse.ContractDocumentRemovalsH\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\"\xc7\x04\n\x1dGetContractTeamActionsRequest\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetContractTeamActionsRequest.GetContractTeamActionsRequestV0H\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\xbc\x02\n\x1fGetContractTeamActionsRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12U\n\x06status\x18\x02 \x01(\x0e\x32\x45.org.dash.platform.dapi.v0.GetContractTeamActionsRequest.ActionStatus\x12i\n\x12start_at_action_id\x18\x03 \x01(\x0b\x32H.org.dash.platform.dapi.v0.GetContractTeamActionsRequest.StartAtActionIdH\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x04 \x01(\rH\x01\x88\x01\x01\x12\r\n\x05prove\x18\x05 \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\"\xe0\x07\n\x1eGetContractTeamActionsResponse\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetContractTeamActionsResponse.GetContractTeamActionsResponseV0H\x00\x1a\xe6\x01\n\x15\x44\x65leteSettledDocument\x12\x1a\n\x12\x64ocument_type_name\x18\x01 \x01(\t\x12\x13\n\x0b\x64ocument_id\x18\x02 \x01(\x0c\x12!\n\x19\x64ocument_last_modified_at\x18\x03 \x01(\x04\x12\x1e\n\x11\x64ocument_revision\x18\x04 \x01(\x04H\x00\x88\x01\x01\x12\x43\n\x06reason\x18\x05 \x01(\x0b\x32\x33.org.dash.platform.dapi.v0.ContractModerationReasonB\x14\n\x12_document_revision\x1a\xe6\x01\n\x12\x43ontractTeamAction\x12\x11\n\taction_id\x18\x01 \x01(\x0c\x12\x13\n\x0bproposer_id\x18\x02 \x01(\x0c\x12\x13\n\x0bproposed_at\x18\x03 \x01(\x04\x12r\n\x17\x64\x65lete_settled_document\x18\x04 \x01(\x0b\x32O.org.dash.platform.dapi.v0.GetContractTeamActionsResponse.DeleteSettledDocumentH\x00\x12\x16\n\x0e\x61pproval_count\x18\x05 \x01(\rB\x07\n\x05\x65vent\x1at\n\x13\x43ontractTeamActions\x12]\n\x07\x61\x63tions\x18\x01 \x03(\x0b\x32L.org.dash.platform.dapi.v0.GetContractTeamActionsResponse.ContractTeamAction\x1a\x80\x02\n GetContractTeamActionsResponseV0\x12`\n\x07\x61\x63tions\x18\x01 \x01(\x0b\x32M.org.dash.platform.dapi.v0.GetContractTeamActionsResponse.ContractTeamActionsH\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\"\x8a\x03\n#GetContractTeamActionSignersRequest\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetContractTeamActionSignersRequest.GetContractTeamActionSignersRequestV0H\x00\x1a\xbb\x01\n%GetContractTeamActionSignersRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12[\n\x06status\x18\x02 \x01(\x0e\x32K.org.dash.platform.dapi.v0.GetContractTeamActionSignersRequest.ActionStatus\x12\x11\n\taction_id\x18\x03 \x01(\x0c\x12\r\n\x05prove\x18\x04 \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\"\xed\x03\n$GetContractTeamActionSignersResponse\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetContractTeamActionSignersResponse.GetContractTeamActionSignersResponseV0H\x00\x1a/\n\x19\x43ontractTeamActionSigners\x12\x12\n\nsigner_ids\x18\x01 \x03(\x0c\x1a\x92\x02\n&GetContractTeamActionSignersResponseV0\x12l\n\x07signers\x18\x01 \x01(\x0b\x32Y.org.dash.platform.dapi.v0.GetContractTeamActionSignersResponse.ContractTeamActionSignersH\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\"\x85\x02\n(GetContractModerationActionCountsRequest\x12|\n\x02v0\x18\x01 \x01(\x0b\x32n.org.dash.platform.dapi.v0.GetContractModerationActionCountsRequest.GetContractModerationActionCountsRequestV0H\x00\x1aP\n*GetContractModerationActionCountsRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xb5\x05\n)GetContractModerationActionCountsResponse\x12~\n\x02v0\x18\x01 \x01(\x0b\x32p.org.dash.platform.dapi.v0.GetContractModerationActionCountsResponse.GetContractModerationActionCountsResponseV0H\x00\x1a\x43\n\x1d\x43ontractModerationActionCount\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\r\n\x05\x63ount\x18\x02 \x01(\r\x1a\x94\x01\n\x1e\x43ontractModerationActionCounts\x12r\n\x06\x63ounts\x18\x01 \x03(\x0b\x32\x62.org.dash.platform.dapi.v0.GetContractModerationActionCountsResponse.ContractModerationActionCount\x1a\xa0\x02\n+GetContractModerationActionCountsResponseV0\x12u\n\x06\x63ounts\x18\x01 \x01(\x0b\x32\x63.org.dash.platform.dapi.v0.GetContractModerationActionCountsResponse.ContractModerationActionCountsH\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\"\xc9\x01\n\x19GetContractFeePotsRequest\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetContractFeePotsRequest.GetContractFeePotsRequestV0H\x00\x1a\x41\n\x1bGetContractFeePotsRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x9f\x06\n\x1aGetContractFeePotsResponse\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetContractFeePotsResponse.GetContractFeePotsResponseV0H\x00\x1aR\n\x17\x43ontractFeePotLastClaim\x12\r\n\x05\x65poch\x18\x01 \x01(\r\x12\x13\n\x07time_ms\x18\x02 \x01(\x04\x42\x02\x30\x01\x12\x13\n\x0b\x63laimant_id\x18\x03 \x01(\x0c\x1a\x88\x01\n\x0e\x43ontractFeePot\x12\x13\n\x07\x63redits\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x61\n\nlast_claim\x18\x02 \x01(\x0b\x32M.org.dash.platform.dapi.v0.GetContractFeePotsResponse.ContractFeePotLastClaim\x1a\xc0\x01\n\x0f\x43ontractFeePots\x12S\n\x05owner\x18\x01 \x01(\x0b\x32\x44.org.dash.platform.dapi.v0.GetContractFeePotsResponse.ContractFeePot\x12X\n\nmoderators\x18\x02 \x01(\x0b\x32\x44.org.dash.platform.dapi.v0.GetContractFeePotsResponse.ContractFeePot\x1a\xf1\x01\n\x1cGetContractFeePotsResponseV0\x12U\n\x04pots\x18\x01 \x01(\x0b\x32\x45.org.dash.platform.dapi.v0.GetContractFeePotsResponse.ContractFeePotsH\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\"\xf1\x01\n#GetContractGroupsForContractRequest\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetContractGroupsForContractRequest.GetContractGroupsForContractRequestV0H\x00\x1aK\n%GetContractGroupsForContractRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xf5\x06\n$GetContractGroupsForContractResponse\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetContractGroupsForContractResponse.GetContractGroupsForContractResponseV0H\x00\x1aQ\n\x17\x44ocumentTypeMemberships\x12\x1a\n\x12\x64ocument_type_name\x18\x01 \x01(\t\x12\x1a\n\x12\x63ontract_group_ids\x18\x02 \x03(\x0c\x1a\x46\n\x10TokenMemberships\x12\x16\n\x0etoken_position\x18\x01 \x01(\r\x12\x1a\n\x12\x63ontract_group_ids\x18\x02 \x03(\x0c\x1a\x89\x02\n\x18\x43ontractGroupMemberships\x12\x1a\n\x12\x63ontract_group_ids\x18\x01 \x03(\x0c\x12o\n\x0e\x64ocument_types\x18\x02 \x03(\x0b\x32W.org.dash.platform.dapi.v0.GetContractGroupsForContractResponse.DocumentTypeMemberships\x12`\n\x06tokens\x18\x03 \x03(\x0b\x32P.org.dash.platform.dapi.v0.GetContractGroupsForContractResponse.TokenMemberships\x1a\xa4\x02\n&GetContractGroupsForContractResponseV0\x12~\n\x1a\x63ontract_group_memberships\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetContractGroupsForContractResponse.ContractGroupMembershipsH\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\"\xad\x02\n\x1eGetDataContractsByRangeRequest\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetDataContractsByRangeRequest.GetDataContractsByRangeRequestV0H\x00\x1a\x95\x01\n GetDataContractsByRangeRequestV0\x12\x12\n\x05limit\x18\x01 \x01(\rH\x01\x88\x01\x01\x12\x15\n\x0bstart_after\x18\x02 \x01(\x0cH\x00\x12\x12\n\x08start_at\x18\x03 \x01(\x0cH\x00\x12\x10\n\x08ids_only\x18\x04 \x01(\x08\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\x07\n\x05startB\x08\n\x06_limitB\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\"\xf8\"\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\xe2\x02\n\x12TimeRangeSelection\x12\\\n\x08selector\x18\x01 \x01(\x0e\x32J.org.dash.platform.dapi.v0.GetDocumentsRequest.TimeRangeSelection.Selector\x12\x19\n\x08start_ms\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x88\x01\x01\x12T\n\x04grid\x18\x03 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetDocumentsRequest.TimeRangeSelection.Grid\x1a>\n\x04Grid\x12\x11\n\x05range\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x10\n\x04step\x18\x02 \x01(\x04\x42\x02\x30\x01\x12\x11\n\x05phase\x18\x03 \x01(\x04\x42\x02\x30\x01\"0\n\x08Selector\x12\n\n\x06NEWEST\x10\x00\x12\n\n\x06OLDEST\x10\x01\x12\x0c\n\x08\x42Y_START\x10\x02\x42\x0b\n\t_start_ms\x1a\x82\x02\n\x15IntegerRangeSelection\x12P\n\x05start\x18\x01 \x01(\x0b\x32\x41.org.dash.platform.dapi.v0.GetDocumentsRequest.DocumentFieldValue\x12W\n\x04grid\x18\x02 \x01(\x0b\x32I.org.dash.platform.dapi.v0.GetDocumentsRequest.IntegerRangeSelection.Grid\x1a>\n\x04Grid\x12\x11\n\x05range\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x10\n\x04step\x18\x02 \x01(\x04\x42\x02\x30\x01\x12\x11\n\x05phase\x18\x03 \x01(\x04\x42\x02\x30\x01\x1a\xf2\x02\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\x12U\n\ntime_range\x18\x04 \x01(\x0b\x32\x41.org.dash.platform.dapi.v0.GetDocumentsRequest.TimeRangeSelection\x12[\n\rinteger_range\x18\x05 \x01(\x0b\x32\x44.org.dash.platform.dapi.v0.GetDocumentsRequest.IntegerRangeSelection\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\xa6\x0c\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\x12\x61\n\x07\x63hained\x18\r \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetDocumentsRequest.GetDocumentsRequestV1.ChainedJoin\x12\x62\n\x0bsub_queries\x18\x0e \x03(\x0b\x32M.org.dash.platform.dapi.v0.GetDocumentsRequest.GetDocumentsRequestV1.SubQuery\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\x1a\x41\n\x0b\x43hainedJoin\x12\x15\n\rjoin_property\x18\x01 \x01(\t\x12\x1b\n\x13outer_document_type\x18\x02 \x01(\t\x1a\xa6\x04\n\x08SubQuery\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\x00\x88\x01\x01\x12`\n\x04kind\x18\x06 \x01(\x0e\x32R.org.dash.platform.dapi.v0.GetDocumentsRequest.GetDocumentsRequestV1.SubQuery.Kind\x12\x63\n\x04\x62ind\x18\x07 \x01(\x0b\x32U.org.dash.platform.dapi.v0.GetDocumentsRequest.GetDocumentsRequestV1.SubQuery.Binding\x1a\x41\n\x07\x42inding\x12\x0e\n\x06source\x18\x01 \x01(\r\x12\x17\n\x0fsource_property\x18\x02 \x01(\t\x12\r\n\x05\x66ield\x18\x03 \x01(\t\" \n\x04Kind\x12\r\n\tDOCUMENTS\x10\x00\x12\t\n\x05\x43OUNT\x10\x01\x42\x08\n\x06_limitB\x07\n\x05startB\x08\n\x06_limitB\t\n\x07_offset\"\xb0\x02\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\n\x12\x11\n\rIN_TIME_RANGE\x10\x0b\x12\x14\n\x10IN_INTEGER_RANGE\x10\x0c\x12\x0c\n\x08\x43ONTAINS\x10\r\x12\x10\n\x0c\x43ONTAINS_ANY\x10\x0e\x42\t\n\x07version\"\xd5\x1d\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\xe7\x19\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\xf7\x05\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\x12j\n\x07\x63hained\x18\x06 \x01(\x0b\x32W.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.ChainedDocumentsH\x00\x12n\n\tcomposite\x18\x07 \x01(\x0b\x32Y.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.CompositeDocumentsH\x00\x42\t\n\x07variant\x1a\xd8\x01\n\x10\x43hainedDocuments\x12\x17\n\x0finner_documents\x18\x01 \x03(\x0c\x12\x17\n\x0fouter_documents\x18\x02 \x03(\x0c\x12\x19\n\x11missing_outer_ids\x18\x03 \x03(\x0c\x12w\n\x17removed_outer_documents\x18\x04 \x03(\x0b\x32V.org.dash.platform.dapi.v0.GetContractDocumentRemovalsResponse.ContractDocumentRemoval\x1a\x94\x04\n\x12\x43ompositeDocuments\x12\x16\n\x0epage_documents\x18\x01 \x03(\x0c\x12}\n\x0bsub_results\x18\x02 \x03(\x0b\x32h.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.CompositeDocuments.SubQueryResult\x1a\xe6\x02\n\x0eSubQueryResult\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.CountEntriesH\x00\x12\x13\n\x0bmissing_ids\x18\x03 \x03(\x0c\x12g\n\x07removed\x18\x04 \x03(\x0b\x32V.org.dash.platform.dapi.v0.GetContractDocumentRemovalsResponse.ContractDocumentRemovalB\x08\n\x06resultB\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\"\xc3\x04\n*GetIdentityByNonUniquePublicKeyHashRequest\x12\x80\x01\n\x02v0\x18\x01 \x01(\x0b\x32r.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashRequest.GetIdentityByNonUniquePublicKeyHashRequestV0H\x00\x12\x80\x01\n\x02v1\x18\x02 \x01(\x0b\x32r.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashRequest.GetIdentityByNonUniquePublicKeyHashRequestV1H\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_after\x1a\x80\x01\n,GetIdentityByNonUniquePublicKeyHashRequestV1\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\"\xe4\n\n+GetIdentityByNonUniquePublicKeyHashResponse\x12\x82\x01\n\x02v0\x18\x01 \x01(\x0b\x32t.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashResponse.GetIdentityByNonUniquePublicKeyHashResponseV0H\x00\x12\x82\x01\n\x02v1\x18\x02 \x01(\x0b\x32t.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashResponse.GetIdentityByNonUniquePublicKeyHashResponseV1H\x00\x1a\x9c\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\x06resultJ\x04\x08\x04\x10\x05\x1a\x80\x03\n-GetIdentityByNonUniquePublicKeyHashResponseV1\x12\x9a\x01\n\x08identity\x18\x01 \x01(\x0b\x32\x85\x01.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashResponse.GetIdentityByNonUniquePublicKeyHashResponseV1.IdentityResponseH\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\x10IdentityResponse\x12\x15\n\x08identity\x18\x01 \x01(\x0cH\x00\x88\x01\x01\x42\x0b\n\t_identityB\x08\n\x06resultB\t\n\x07version\"\x99\x02\n#WaitForStateTransitionResultRequest\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.WaitForStateTransitionResultRequest.WaitForStateTransitionResultRequestV0H\x00\x1as\n%WaitForStateTransitionResultRequestV0\x12\x1d\n\x15state_transition_hash\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x12\x1c\n\x14request_user_balance\x18\x03 \x01(\x08\x42\t\n\x07version\"\xce\x04\n$WaitForStateTransitionResultResponse\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.WaitForStateTransitionResultResponse.WaitForStateTransitionResultResponseV0H\x00\x1a\x34\n\x17SuccessWithOwnerBalance\x12\x19\n\rowner_balance\x18\x01 \x01(\x04\x42\x02\x30\x01\x1a\xee\x02\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\x1asuccess_with_owner_balance\x18\x04 \x01(\x0b\x32W.org.dash.platform.dapi.v0.WaitForStateTransitionResultResponse.SuccessWithOwnerBalanceH\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\"\xd6\x01\n\x1cGetYesNoVotePollStateRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetYesNoVotePollStateRequest.GetYesNoVotePollStateRequestV0H\x00\x1a\x45\n\x1eGetYesNoVotePollStateRequestV0\x12\x14\n\x0cvote_poll_id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xa8\x11\n\x1dGetYesNoVotePollStateResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetYesNoVotePollStateResponse.GetYesNoVotePollStateResponseV0H\x00\x1a\x93\x10\n\x1fGetYesNoVotePollStateResponseV0\x12|\n\x05state\x18\x01 \x01(\x0b\x32k.org.dash.platform.dapi.v0.GetYesNoVotePollStateResponse.GetYesNoVotePollStateResponseV0.YesNoVotePollStateH\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\x61\n\x12YesNoVotePollBlock\x12\x12\n\x06height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x13\n\x0b\x63ore_height\x18\x02 \x01(\r\x12\x13\n\x07time_ms\x18\x03 \x01(\x04\x42\x02\x30\x01\x12\r\n\x05\x65poch\x18\x04 \x01(\r\x1a\xa4\x03\n\x15\x46inishedYesNoVotePoll\x12\x0e\n\x06passed\x18\x01 \x01(\x08\x12\x18\n\x10yes_voting_power\x18\x02 \x01(\r\x12\x17\n\x0fno_voting_power\x18\x03 \x01(\r\x12\x1c\n\x14\x61\x62stain_voting_power\x18\x04 \x01(\r\x12\x1d\n\x15required_voting_power\x18\x05 \x01(\r\x12\x80\x01\n\x0bstart_block\x18\x06 \x01(\x0b\x32k.org.dash.platform.dapi.v0.GetYesNoVotePollStateResponse.GetYesNoVotePollStateResponseV0.YesNoVotePollBlock\x12\x87\x01\n\x12\x66inalization_block\x18\x07 \x01(\x0b\x32k.org.dash.platform.dapi.v0.GetYesNoVotePollStateResponse.GetYesNoVotePollStateResponseV0.YesNoVotePollBlock\x1a\xf9\x05\n\rYesNoVotePoll\x12\x94\x01\n\x11\x64\x65\x63ision_proposal\x18\x01 \x01(\x0b\x32w.org.dash.platform.dapi.v0.GetYesNoVotePollStateResponse.GetYesNoVotePollStateResponseV0.YesNoVotePoll.DecisionProposalH\x00\x12\x1f\n\x17supermajority_numerator\x18\x02 \x01(\r\x12!\n\x19supermajority_denominator\x18\x03 \x01(\r\x12\x12\n\x08\x61\x62solute\x18\x04 \x01(\rH\x01\x12\x93\x01\n\x11\x66raction_of_total\x18\x05 \x01(\x0b\x32v.org.dash.platform.dapi.v0.GetYesNoVotePollStateResponse.GetYesNoVotePollStateResponseV0.YesNoVotePoll.FractionOfTotalH\x01\x1a\'\n\x10\x44\x65\x63isionProposal\x12\x13\n\x0b\x64ocument_id\x18\x01 \x01(\x0c\x1a\xc8\x01\n\x0f\x46ractionOfTotal\x12\x11\n\tnumerator\x18\x01 \x01(\r\x12\x13\n\x0b\x64\x65nominator\x18\x02 \x01(\r\x12\x8c\x01\n\x08rounding\x18\x03 \x01(\x0e\x32z.org.dash.platform.dapi.v0.GetYesNoVotePollStateResponse.GetYesNoVotePollStateResponseV0.YesNoVotePoll.VotingPowerRounding\"L\n\x13VotingPowerRounding\x12\x08\n\x04\x44OWN\x10\x00\x12\x06\n\x02UP\x10\x01\x12\x11\n\rDOWN_PLUS_ONE\x10\x02\x12\x10\n\x0cUP_MINUS_ONE\x10\x03\x42\t\n\x07purposeB\x16\n\x14minimum_voting_power\x1a\xef\x03\n\x12YesNoVotePollState\x12~\n\x07started\x18\x01 \x01(\x0b\x32k.org.dash.platform.dapi.v0.GetYesNoVotePollStateResponse.GetYesNoVotePollStateResponseV0.YesNoVotePollBlockH\x00\x12\x82\x01\n\x08\x66inished\x18\x02 \x01(\x0b\x32n.org.dash.platform.dapi.v0.GetYesNoVotePollStateResponse.GetYesNoVotePollStateResponseV0.FinishedYesNoVotePollH\x00\x12\x18\n\x10yes_voting_power\x18\x03 \x01(\r\x12\x17\n\x0fno_voting_power\x18\x04 \x01(\r\x12\x1c\n\x14\x61\x62stain_voting_power\x18\x05 \x01(\r\x12y\n\tvote_poll\x18\x06 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetYesNoVotePollStateResponse.GetYesNoVotePollStateResponseV0.YesNoVotePollB\x08\n\x06statusB\x08\n\x06resultB\t\n\x07version\"\xef\x01\n\x1dGetMasternodeYesNoVoteRequest\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetMasternodeYesNoVoteRequest.GetMasternodeYesNoVoteRequestV0H\x00\x1a[\n\x1fGetMasternodeYesNoVoteRequestV0\x12\x13\n\x0bpro_tx_hash\x18\x01 \x01(\x0c\x12\x14\n\x0cvote_poll_id\x18\x02 \x01(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xb5\x06\n\x1eGetMasternodeYesNoVoteResponse\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetMasternodeYesNoVoteResponse.GetMasternodeYesNoVoteResponseV0H\x00\x1a\x9d\x05\n GetMasternodeYesNoVoteResponseV0\x12\x84\x01\n\x05\x65ntry\x18\x01 \x01(\x0b\x32s.org.dash.platform.dapi.v0.GetMasternodeYesNoVoteResponse.GetMasternodeYesNoVoteResponseV0.MasternodeYesNoVoteEntryH\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\x01\n\x13MasternodeYesNoVote\x12\x85\x01\n\x06\x63hoice\x18\x01 \x01(\x0e\x32u.org.dash.platform.dapi.v0.GetMasternodeYesNoVoteResponse.GetMasternodeYesNoVoteResponseV0.MasternodeYesNoVote.Choice\x12\x13\n\x0btimes_voted\x18\x02 \x01(\r\"&\n\x06\x43hoice\x12\x07\n\x03YES\x10\x00\x12\x06\n\x02NO\x10\x01\x12\x0b\n\x07\x41\x42STAIN\x10\x02\x1a\x98\x01\n\x18MasternodeYesNoVoteEntry\x12|\n\x04vote\x18\x01 \x01(\x0b\x32n.org.dash.platform.dapi.v0.GetMasternodeYesNoVoteResponse.GetMasternodeYesNoVoteResponseV0.MasternodeYesNoVoteB\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\"\x92\"\n\x17GetGroupActionsResponse\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0H\x00\x1a\x8f!\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\x63\n\x0fMintToPoolEvent\x12\x0e\n\x06\x61mount\x18\x01 \x01(\x04\x12\x16\n\x0e\x61\x63tions_digest\x18\x02 \x01(\x0c\x12\x18\n\x0bpublic_note\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_public_note\x1a\x65\n\x11\x42urnFromPoolEvent\x12\x0e\n\x06\x61mount\x18\x01 \x01(\x04\x12\x16\n\x0e\x61\x63tions_digest\x18\x02 \x01(\x0c\x12\x18\n\x0bpublic_note\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\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\xc1\t\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\x12t\n\x0cmint_to_pool\x18\t \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.MintToPoolEventH\x00\x12x\n\x0e\x62urn_from_pool\x18\n \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.BurnFromPoolEventH\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\"\x98\x02\n GetShieldedEncryptedNotesRequest\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetShieldedEncryptedNotesRequest.GetShieldedEncryptedNotesRequestV0H\x00\x1a{\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\x12\x15\n\x08token_id\x18\x04 \x01(\x0cH\x00\x88\x01\x01\x42\x0b\n\t_token_idB\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\"\xd8\x01\n\x19GetShieldedAnchorsRequest\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetShieldedAnchorsRequest.GetShieldedAnchorsRequestV0H\x00\x1aP\n\x1bGetShieldedAnchorsRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x12\x15\n\x08token_id\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x42\x0b\n\t_token_idB\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\"\xfc\x01\n\"GetMostRecentShieldedAnchorRequest\x12p\n\x02v0\x18\x01 \x01(\x0b\x32\x62.org.dash.platform.dapi.v0.GetMostRecentShieldedAnchorRequest.GetMostRecentShieldedAnchorRequestV0H\x00\x1aY\n$GetMostRecentShieldedAnchorRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x12\x15\n\x08token_id\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x42\x0b\n\t_token_idB\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\"\xe0\x01\n\x1bGetShieldedPoolStateRequest\x12\x62\n\x02v0\x18\x01 \x01(\x0b\x32T.org.dash.platform.dapi.v0.GetShieldedPoolStateRequest.GetShieldedPoolStateRequestV0H\x00\x1aR\n\x1dGetShieldedPoolStateRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x12\x15\n\x08token_id\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x42\x0b\n\t_token_idB\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\"\xe4\x01\n\x1cGetShieldedNotesCountRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetShieldedNotesCountRequest.GetShieldedNotesCountRequestV0H\x00\x1aS\n\x1eGetShieldedNotesCountRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x12\x15\n\x08token_id\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x42\x0b\n\t_token_idB\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\"\xf8\x01\n\x1cGetShieldedNullifiersRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetShieldedNullifiersRequest.GetShieldedNullifiersRequestV0H\x00\x1ag\n\x1eGetShieldedNullifiersRequestV0\x12\x12\n\nnullifiers\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x12\x15\n\x08token_id\x18\x03 \x01(\x0cH\x00\x88\x01\x01\x42\x0b\n\t_token_idB\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\"\xb0\x02\n GetPrivateDocumentEntriesRequest\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetPrivateDocumentEntriesRequest.GetPrivateDocumentEntriesRequestV0H\x00\x1a\x92\x01\n\"GetPrivateDocumentEntriesRequestV0\x12\x18\n\x10\x64\x61ta_contract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\x1a\n\x0estart_position\x18\x03 \x01(\x04\x42\x02\x30\x01\x12\r\n\x05prove\x18\x05 \x01(\x08J\x04\x08\x04\x10\x05R\x05\x63ountB\t\n\x07version\"\xfd\x05\n!GetPrivateDocumentEntriesResponse\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetPrivateDocumentEntriesResponse.GetPrivateDocumentEntriesResponseV0H\x00\x1a\xdc\x04\n#GetPrivateDocumentEntriesResponseV0\x12\x8a\x01\n\x07\x65ntries\x18\x01 \x01(\x0b\x32w.org.dash.platform.dapi.v0.GetPrivateDocumentEntriesResponse.GetPrivateDocumentEntriesResponseV0.PrivateDocumentEntriesH\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\x1ao\n\x14PrivateDocumentEntry\x12\x14\n\x08position\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x18\n\x0c\x62lock_height\x18\x02 \x01(\x04\x42\x02\x30\x01\x12\x19\n\rblock_time_ms\x18\x03 \x01(\x04\x42\x02\x30\x01\x12\x0c\n\x04\x64\x61ta\x18\x04 \x01(\x0c\x1a\xba\x01\n\x16PrivateDocumentEntries\x12\x86\x01\n\x07\x65ntries\x18\x01 \x03(\x0b\x32u.org.dash.platform.dapi.v0.GetPrivateDocumentEntriesResponse.GetPrivateDocumentEntriesResponseV0.PrivateDocumentEntry\x12\x17\n\x0btotal_count\x18\x02 \x01(\x04\x42\x02\x30\x01\x42\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*\xb9\x01\n\x16\x43ontractModerationList\x12(\n$CONTRACT_MODERATION_LIST_UNSPECIFIED\x10\x00\x12$\n CONTRACT_MODERATION_LIST_BANLIST\x10\x01\x12(\n$CONTRACT_MODERATION_LIST_SUSPENSIONS\x10\x02\x12%\n!CONTRACT_MODERATION_LIST_WARNINGS\x10\x03\x32\xe9W\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\xa8\x01\n\x1fgetIdentityKeysRemainingBudgets\x12\x41.org.dash.platform.dapi.v0.GetIdentityKeysRemainingBudgetsRequest\x1a\x42.org.dash.platform.dapi.v0.GetIdentityKeysRemainingBudgetsResponse\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\xa5\x01\n\x1egetDataContractsLatestVersions\x12@.org.dash.platform.dapi.v0.GetDataContractsLatestVersionsRequest\x1a\x41.org.dash.platform.dapi.v0.GetDataContractsLatestVersionsResponse\x12{\n\x10getDataContracts\x12\x32.org.dash.platform.dapi.v0.GetDataContractsRequest\x1a\x33.org.dash.platform.dapi.v0.GetDataContractsResponse\x12\x89\x01\n\x17getDataContractsByRange\x12\x39.org.dash.platform.dapi.v0.GetDataContractsByRangeRequest\x1a\x33.org.dash.platform.dapi.v0.GetDataContractsResponse\x12\x87\x01\n\x14getContractGroupInfo\x12\x36.org.dash.platform.dapi.v0.GetContractGroupInfoRequest\x1a\x37.org.dash.platform.dapi.v0.GetContractGroupInfoResponse\x12\x90\x01\n\x17getContractGroupMembers\x12\x39.org.dash.platform.dapi.v0.GetContractGroupMembersRequest\x1a:.org.dash.platform.dapi.v0.GetContractGroupMembersResponse\x12\x9f\x01\n\x1cgetContractGroupsForContract\x12>.org.dash.platform.dapi.v0.GetContractGroupsForContractRequest\x1a?.org.dash.platform.dapi.v0.GetContractGroupsForContractResponse\x12\x9c\x01\n\x1bgetContractModerationStatus\x12=.org.dash.platform.dapi.v0.GetContractModerationStatusRequest\x1a>.org.dash.platform.dapi.v0.GetContractModerationStatusResponse\x12\x9f\x01\n\x1cgetContractModerationEntries\x12>.org.dash.platform.dapi.v0.GetContractModerationEntriesRequest\x1a?.org.dash.platform.dapi.v0.GetContractModerationEntriesResponse\x12\x9c\x01\n\x1bgetContractDocumentRemovals\x12=.org.dash.platform.dapi.v0.GetContractDocumentRemovalsRequest\x1a>.org.dash.platform.dapi.v0.GetContractDocumentRemovalsResponse\x12\x8d\x01\n\x16getContractTeamActions\x12\x38.org.dash.platform.dapi.v0.GetContractTeamActionsRequest\x1a\x39.org.dash.platform.dapi.v0.GetContractTeamActionsResponse\x12\x9f\x01\n\x1cgetContractTeamActionSigners\x12>.org.dash.platform.dapi.v0.GetContractTeamActionSignersRequest\x1a?.org.dash.platform.dapi.v0.GetContractTeamActionSignersResponse\x12\xae\x01\n!getContractModerationActionCounts\x12\x43.org.dash.platform.dapi.v0.GetContractModerationActionCountsRequest\x1a\x44.org.dash.platform.dapi.v0.GetContractModerationActionCountsResponse\x12\x81\x01\n\x12getContractFeePots\x12\x34.org.dash.platform.dapi.v0.GetContractFeePotsRequest\x1a\x35.org.dash.platform.dapi.v0.GetContractFeePotsResponse\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\x8a\x01\n\x15getYesNoVotePollState\x12\x37.org.dash.platform.dapi.v0.GetYesNoVotePollStateRequest\x1a\x38.org.dash.platform.dapi.v0.GetYesNoVotePollStateResponse\x12\x8d\x01\n\x16getMasternodeYesNoVote\x12\x38.org.dash.platform.dapi.v0.GetMasternodeYesNoVoteRequest\x1a\x39.org.dash.platform.dapi.v0.GetMasternodeYesNoVoteResponse\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.GetShieldedNullifiersResponse\x12\x96\x01\n\x19getPrivateDocumentEntries\x12;.org.dash.platform.dapi.v0.GetPrivateDocumentEntriesRequest\x1a<.org.dash.platform.dapi.v0.GetPrivateDocumentEntriesResponseb\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\"\x8e\x02\n&GetIdentityKeysRemainingBudgetsRequest\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetIdentityKeysRemainingBudgetsRequest.GetIdentityKeysRemainingBudgetsRequestV0H\x00\x1a_\n(GetIdentityKeysRemainingBudgetsRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x0f\n\x07key_ids\x18\x02 \x03(\r\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\x96\x06\n\'GetIdentityKeysRemainingBudgetsResponse\x12z\n\x02v0\x18\x01 \x01(\x0b\x32l.org.dash.platform.dapi.v0.GetIdentityKeysRemainingBudgetsResponse.GetIdentityKeysRemainingBudgetsResponseV0H\x00\x1a\xe3\x04\n)GetIdentityKeysRemainingBudgetsResponseV0\x12\xa4\x01\n\x16keys_remaining_budgets\x18\x01 \x01(\x0b\x32\x81\x01.org.dash.platform.dapi.v0.GetIdentityKeysRemainingBudgetsResponse.GetIdentityKeysRemainingBudgetsResponseV0.KeysRemainingBudgetsH\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\x61\n\x17KeyRemainingBudgetEntry\x12\x0e\n\x06key_id\x18\x01 \x01(\r\x12!\n\x10remaining_budget\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x88\x01\x01\x42\x13\n\x11_remaining_budget\x1a\xaf\x01\n\x14KeysRemainingBudgets\x12\x96\x01\n\x07\x65ntries\x18\x01 \x03(\x0b\x32\x84\x01.org.dash.platform.dapi.v0.GetIdentityKeysRemainingBudgetsResponse.GetIdentityKeysRemainingBudgetsResponseV0.KeyRemainingBudgetEntryB\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\"\x8c\x02\n%GetDataContractsLatestVersionsRequest\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetDataContractsLatestVersionsRequest.GetDataContractsLatestVersionsRequestV0H\x00\x1a`\n\'GetDataContractsLatestVersionsRequestV0\x12\x0b\n\x03ids\x18\x01 \x03(\x0c\x12\x19\n\x11include_contracts\x18\x02 \x01(\x08\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xfa\x05\n&GetDataContractsLatestVersionsResponse\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetDataContractsLatestVersionsResponse.GetDataContractsLatestVersionsResponseV0H\x00\x1a\x84\x01\n\x1e\x44\x61taContractLatestVersionEntry\x12\x12\n\nidentifier\x18\x01 \x01(\x0c\x12\x14\n\x07version\x18\x02 \x01(\rH\x00\x88\x01\x01\x12\x1a\n\rdata_contract\x18\x03 \x01(\x0cH\x01\x88\x01\x01\x42\n\n\x08_versionB\x10\n\x0e_data_contract\x1a\x90\x01\n\x1b\x44\x61taContractsLatestVersions\x12q\n\x07\x65ntries\x18\x01 \x03(\x0b\x32`.org.dash.platform.dapi.v0.GetDataContractsLatestVersionsResponse.DataContractLatestVersionEntry\x1a\xb0\x02\n(GetDataContractsLatestVersionsResponseV0\x12\x87\x01\n\x1e\x64\x61ta_contracts_latest_versions\x18\x01 \x01(\x0b\x32].org.dash.platform.dapi.v0.GetDataContractsLatestVersionsResponse.DataContractsLatestVersionsH\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\"R\n\x1f\x43ontractGroupDocumentTypeMember\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\"G\n\x18\x43ontractGroupTokenMember\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x16\n\x0etoken_position\x18\x02 \x01(\r\"\xd7\x01\n\x1bGetContractGroupInfoRequest\x12\x62\n\x02v0\x18\x01 \x01(\x0b\x32T.org.dash.platform.dapi.v0.GetContractGroupInfoRequest.GetContractGroupInfoRequestV0H\x00\x1aI\n\x1dGetContractGroupInfoRequestV0\x12\x19\n\x11\x63ontract_group_id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x98\x04\n\x1cGetContractGroupInfoResponse\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetContractGroupInfoResponse.GetContractGroupInfoResponseV0H\x00\x1a~\n\x11\x43ontractGroupInfo\x12\x10\n\x08owner_id\x18\x01 \x01(\x0c\x12\x11\n\tadmin_ids\x18\x02 \x03(\x0c\x12\x11\n\x04name\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x18\n\x0b\x64\x65scription\x18\x04 \x01(\tH\x01\x88\x01\x01\x42\x07\n\x05_nameB\x0e\n\x0c_description\x1a\x86\x02\n\x1eGetContractGroupInfoResponseV0\x12h\n\x13\x63ontract_group_info\x18\x01 \x01(\x0b\x32I.org.dash.platform.dapi.v0.GetContractGroupInfoResponse.ContractGroupInfoH\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\"\xf8\x06\n\x1eGetContractGroupMembersRequest\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetContractGroupMembersRequest.GetContractGroupMembersRequestV0H\x00\x1a@\n\x14\x43ontractMembersQuery\x12\x18\n\x0bstart_after\x18\x01 \x01(\x0cH\x00\x88\x01\x01\x42\x0e\n\x0c_start_after\x1a\x80\x01\n\x18\x44ocumentTypeMembersQuery\x12T\n\x0bstart_after\x18\x01 \x01(\x0b\x32:.org.dash.platform.dapi.v0.ContractGroupDocumentTypeMemberH\x00\x88\x01\x01\x42\x0e\n\x0c_start_after\x1ar\n\x11TokenMembersQuery\x12M\n\x0bstart_after\x18\x01 \x01(\x0b\x32\x33.org.dash.platform.dapi.v0.ContractGroupTokenMemberH\x00\x88\x01\x01\x42\x0e\n\x0c_start_after\x1a\xa7\x03\n GetContractGroupMembersRequestV0\x12\x19\n\x11\x63ontract_group_id\x18\x01 \x01(\x0c\x12\x63\n\tcontracts\x18\x02 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetContractGroupMembersRequest.ContractMembersQueryH\x00\x12l\n\x0e\x64ocument_types\x18\x03 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetContractGroupMembersRequest.DocumentTypeMembersQueryH\x00\x12]\n\x06tokens\x18\x04 \x01(\x0b\x32K.org.dash.platform.dapi.v0.GetContractGroupMembersRequest.TokenMembersQueryH\x00\x12\x12\n\x05limit\x18\x05 \x01(\rH\x01\x88\x01\x01\x12\r\n\x05prove\x18\x06 \x01(\x08\x42\t\n\x07membersB\x08\n\x06_limitB\t\n\x07version\"\xc9\x06\n\x1fGetContractGroupMembersResponse\x12j\n\x02v0\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetContractGroupMembersResponse.GetContractGroupMembersResponseV0H\x00\x1a\'\n\x0f\x43ontractMembers\x12\x14\n\x0c\x63ontract_ids\x18\x01 \x03(\x0c\x1ai\n\x13\x44ocumentTypeMembers\x12R\n\x0e\x64ocument_types\x18\x01 \x03(\x0b\x32:.org.dash.platform.dapi.v0.ContractGroupDocumentTypeMember\x1aS\n\x0cTokenMembers\x12\x43\n\x06tokens\x18\x01 \x03(\x0b\x32\x33.org.dash.platform.dapi.v0.ContractGroupTokenMember\x1a\xc5\x03\n!GetContractGroupMembersResponseV0\x12_\n\tcontracts\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetContractGroupMembersResponse.ContractMembersH\x00\x12h\n\x0e\x64ocument_types\x18\x02 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetContractGroupMembersResponse.DocumentTypeMembersH\x00\x12Y\n\x06tokens\x18\x03 \x01(\x0b\x32G.org.dash.platform.dapi.v0.GetContractGroupMembersResponse.TokenMembersH\x00\x12\x31\n\x05proof\x18\x04 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x05 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"M\n\x1a\x43ontractModerationDocument\x12\x1a\n\x12\x64ocument_type_name\x18\x01 \x01(\t\x12\x13\n\x0b\x64ocument_id\x18\x02 \x01(\x0c\"\xc6\x01\n\x18\x43ontractModerationReason\x12\x11\n\x04\x63ode\x18\x01 \x01(\rH\x00\x88\x01\x01\x12\x0c\n\x04text\x18\x02 \x01(\t\x12H\n\tdocuments\x18\x03 \x03(\x0b\x32\x35.org.dash.platform.dapi.v0.ContractModerationDocument\x12\x1f\n\x12reason_document_id\x18\x04 \x01(\x0cH\x01\x88\x01\x01\x42\x07\n\x05_codeB\x15\n\x13_reason_document_id\"i\n\x0f\x43ontractWarning\x12\x11\n\twarned_at\x18\x01 \x01(\x04\x12\x43\n\x06reason\x18\x02 \x01(\x0b\x32\x33.org.dash.platform.dapi.v0.ContractModerationReason\"\xc5\x02\n\"GetContractModerationStatusRequest\x12p\n\x02v0\x18\x01 \x01(\x0b\x32\x62.org.dash.platform.dapi.v0.GetContractModerationStatusRequest.GetContractModerationStatusRequestV0H\x00\x1a\xa1\x01\n$GetContractModerationStatusRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x13\n\x0bidentity_id\x18\x02 \x01(\x0c\x12@\n\x05lists\x18\x03 \x03(\x0e\x32\x31.org.dash.platform.dapi.v0.ContractModerationList\x12\r\n\x05prove\x18\x04 \x01(\x08\x42\t\n\x07version\"\xec\x06\n#GetContractModerationStatusResponse\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetContractModerationStatusResponse.GetContractModerationStatusResponseV0H\x00\x1a\xb4\x03\n\x18\x43ontractModerationStatus\x12\x13\n\x06\x62\x61nned\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x1c\n\x0fsuspended_until\x18\x02 \x01(\x04H\x01\x88\x01\x01\x12@\n\x05lists\x18\x03 \x03(\x0e\x32\x31.org.dash.platform.dapi.v0.ContractModerationList\x12L\n\nban_reason\x18\x04 \x01(\x0b\x32\x33.org.dash.platform.dapi.v0.ContractModerationReasonH\x02\x88\x01\x01\x12S\n\x11suspension_reason\x18\x05 \x01(\x0b\x32\x33.org.dash.platform.dapi.v0.ContractModerationReasonH\x03\x88\x01\x01\x12<\n\x08warnings\x18\x06 \x03(\x0b\x32*.org.dash.platform.dapi.v0.ContractWarningB\t\n\x07_bannedB\x12\n\x10_suspended_untilB\r\n\x0b_ban_reasonB\x14\n\x12_suspension_reason\x1a\x8e\x02\n%GetContractModerationStatusResponseV0\x12i\n\x06status\x18\x01 \x01(\x0b\x32W.org.dash.platform.dapi.v0.GetContractModerationStatusResponse.ContractModerationStatusH\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\"\xfb\x02\n#GetContractModerationEntriesRequest\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetContractModerationEntriesRequest.GetContractModerationEntriesRequestV0H\x00\x1a\xd4\x01\n%GetContractModerationEntriesRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12?\n\x04list\x18\x02 \x01(\x0e\x32\x31.org.dash.platform.dapi.v0.ContractModerationList\x12\x18\n\x0bstart_after\x18\x03 \x01(\x0cH\x00\x88\x01\x01\x12\x12\n\x05limit\x18\x04 \x01(\rH\x01\x88\x01\x01\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\x0e\n\x0c_start_afterB\x08\n\x06_limitB\t\n\x07version\"\x96\x06\n$GetContractModerationEntriesResponse\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetContractModerationEntriesResponse.GetContractModerationEntriesResponseV0H\x00\x1a\xcf\x01\n\x17\x43ontractModerationEntry\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x12\n\x05until\x18\x02 \x01(\x04H\x00\x88\x01\x01\x12\x43\n\x06reason\x18\x03 \x01(\x0b\x32\x33.org.dash.platform.dapi.v0.ContractModerationReason\x12<\n\x08warnings\x18\x04 \x03(\x0b\x32*.org.dash.platform.dapi.v0.ContractWarningB\x08\n\x06_until\x1a\x85\x01\n\x19\x43ontractModerationEntries\x12h\n\x07\x65ntries\x18\x01 \x03(\x0b\x32W.org.dash.platform.dapi.v0.GetContractModerationEntriesResponse.ContractModerationEntry\x1a\x92\x02\n&GetContractModerationEntriesResponseV0\x12l\n\x07\x65ntries\x18\x01 \x01(\x0b\x32Y.org.dash.platform.dapi.v0.GetContractModerationEntriesResponse.ContractModerationEntriesH\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\x04\n\"GetContractDocumentRemovalsRequest\x12p\n\x02v0\x18\x01 \x01(\x0b\x32\x62.org.dash.platform.dapi.v0.GetContractDocumentRemovalsRequest.GetContractDocumentRemovalsRequestV0H\x00\x1a#\n\x0b\x44ocumentIds\x12\x14\n\x0c\x64ocument_ids\x18\x01 \x03(\x0c\x1aN\n\x04Page\x12\x18\n\x0bstart_after\x18\x01 \x01(\x0cH\x00\x88\x01\x01\x12\x12\n\x05limit\x18\x02 \x01(\rH\x01\x88\x01\x01\x42\x0e\n\x0c_start_afterB\x08\n\x06_limit\x1a\xaa\x02\n$GetContractDocumentRemovalsRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\x61\n\x0c\x64ocument_ids\x18\x03 \x01(\x0b\x32I.org.dash.platform.dapi.v0.GetContractDocumentRemovalsRequest.DocumentIdsH\x00\x12R\n\x04page\x18\x04 \x01(\x0b\x32\x42.org.dash.platform.dapi.v0.GetContractDocumentRemovalsRequest.PageH\x00\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\x0b\n\tselectionB\t\n\x07version\"\xe0\x07\n#GetContractDocumentRemovalsResponse\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetContractDocumentRemovalsResponse.GetContractDocumentRemovalsResponseV0H\x00\x1aH\n\x1b\x43ontractDocumentRestoration\x12\x14\n\x0cmoderator_id\x18\x01 \x01(\x0c\x12\x13\n\x0brestored_at\x18\x02 \x01(\x04\x1a\xd5\x02\n\x17\x43ontractDocumentRemoval\x12\x13\n\x0b\x64ocument_id\x18\x01 \x01(\x0c\x12\x19\n\x11\x64ocument_owner_id\x18\x02 \x01(\x0c\x12\x14\n\x0cmoderator_id\x18\x03 \x01(\x0c\x12\x12\n\nremoved_at\x18\x04 \x01(\x04\x12\x43\n\x06reason\x18\x05 \x01(\x0b\x32\x33.org.dash.platform.dapi.v0.ContractModerationReason\x12\x15\n\rdocument_hash\x18\x06 \x01(\x0c\x12o\n\x0brestoration\x18\x07 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetContractDocumentRemovalsResponse.ContractDocumentRestoration\x12\x13\n\x0bkept_fields\x18\x08 \x01(\x0c\x1a\x84\x01\n\x18\x43ontractDocumentRemovals\x12h\n\x08removals\x18\x01 \x03(\x0b\x32V.org.dash.platform.dapi.v0.GetContractDocumentRemovalsResponse.ContractDocumentRemoval\x1a\x90\x02\n%GetContractDocumentRemovalsResponseV0\x12k\n\x08removals\x18\x01 \x01(\x0b\x32W.org.dash.platform.dapi.v0.GetContractDocumentRemovalsResponse.ContractDocumentRemovalsH\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\"\xc7\x04\n\x1dGetContractTeamActionsRequest\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetContractTeamActionsRequest.GetContractTeamActionsRequestV0H\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\xbc\x02\n\x1fGetContractTeamActionsRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12U\n\x06status\x18\x02 \x01(\x0e\x32\x45.org.dash.platform.dapi.v0.GetContractTeamActionsRequest.ActionStatus\x12i\n\x12start_at_action_id\x18\x03 \x01(\x0b\x32H.org.dash.platform.dapi.v0.GetContractTeamActionsRequest.StartAtActionIdH\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x04 \x01(\rH\x01\x88\x01\x01\x12\r\n\x05prove\x18\x05 \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\"\xe0\x07\n\x1eGetContractTeamActionsResponse\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetContractTeamActionsResponse.GetContractTeamActionsResponseV0H\x00\x1a\xe6\x01\n\x15\x44\x65leteSettledDocument\x12\x1a\n\x12\x64ocument_type_name\x18\x01 \x01(\t\x12\x13\n\x0b\x64ocument_id\x18\x02 \x01(\x0c\x12!\n\x19\x64ocument_last_modified_at\x18\x03 \x01(\x04\x12\x1e\n\x11\x64ocument_revision\x18\x04 \x01(\x04H\x00\x88\x01\x01\x12\x43\n\x06reason\x18\x05 \x01(\x0b\x32\x33.org.dash.platform.dapi.v0.ContractModerationReasonB\x14\n\x12_document_revision\x1a\xe6\x01\n\x12\x43ontractTeamAction\x12\x11\n\taction_id\x18\x01 \x01(\x0c\x12\x13\n\x0bproposer_id\x18\x02 \x01(\x0c\x12\x13\n\x0bproposed_at\x18\x03 \x01(\x04\x12r\n\x17\x64\x65lete_settled_document\x18\x04 \x01(\x0b\x32O.org.dash.platform.dapi.v0.GetContractTeamActionsResponse.DeleteSettledDocumentH\x00\x12\x16\n\x0e\x61pproval_count\x18\x05 \x01(\rB\x07\n\x05\x65vent\x1at\n\x13\x43ontractTeamActions\x12]\n\x07\x61\x63tions\x18\x01 \x03(\x0b\x32L.org.dash.platform.dapi.v0.GetContractTeamActionsResponse.ContractTeamAction\x1a\x80\x02\n GetContractTeamActionsResponseV0\x12`\n\x07\x61\x63tions\x18\x01 \x01(\x0b\x32M.org.dash.platform.dapi.v0.GetContractTeamActionsResponse.ContractTeamActionsH\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\"\x8a\x03\n#GetContractTeamActionSignersRequest\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetContractTeamActionSignersRequest.GetContractTeamActionSignersRequestV0H\x00\x1a\xbb\x01\n%GetContractTeamActionSignersRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12[\n\x06status\x18\x02 \x01(\x0e\x32K.org.dash.platform.dapi.v0.GetContractTeamActionSignersRequest.ActionStatus\x12\x11\n\taction_id\x18\x03 \x01(\x0c\x12\r\n\x05prove\x18\x04 \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\"\xed\x03\n$GetContractTeamActionSignersResponse\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetContractTeamActionSignersResponse.GetContractTeamActionSignersResponseV0H\x00\x1a/\n\x19\x43ontractTeamActionSigners\x12\x12\n\nsigner_ids\x18\x01 \x03(\x0c\x1a\x92\x02\n&GetContractTeamActionSignersResponseV0\x12l\n\x07signers\x18\x01 \x01(\x0b\x32Y.org.dash.platform.dapi.v0.GetContractTeamActionSignersResponse.ContractTeamActionSignersH\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\"\x85\x02\n(GetContractModerationActionCountsRequest\x12|\n\x02v0\x18\x01 \x01(\x0b\x32n.org.dash.platform.dapi.v0.GetContractModerationActionCountsRequest.GetContractModerationActionCountsRequestV0H\x00\x1aP\n*GetContractModerationActionCountsRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xb5\x05\n)GetContractModerationActionCountsResponse\x12~\n\x02v0\x18\x01 \x01(\x0b\x32p.org.dash.platform.dapi.v0.GetContractModerationActionCountsResponse.GetContractModerationActionCountsResponseV0H\x00\x1a\x43\n\x1d\x43ontractModerationActionCount\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\r\n\x05\x63ount\x18\x02 \x01(\r\x1a\x94\x01\n\x1e\x43ontractModerationActionCounts\x12r\n\x06\x63ounts\x18\x01 \x03(\x0b\x32\x62.org.dash.platform.dapi.v0.GetContractModerationActionCountsResponse.ContractModerationActionCount\x1a\xa0\x02\n+GetContractModerationActionCountsResponseV0\x12u\n\x06\x63ounts\x18\x01 \x01(\x0b\x32\x63.org.dash.platform.dapi.v0.GetContractModerationActionCountsResponse.ContractModerationActionCountsH\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\"\xc9\x01\n\x19GetContractFeePotsRequest\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetContractFeePotsRequest.GetContractFeePotsRequestV0H\x00\x1a\x41\n\x1bGetContractFeePotsRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x9f\x06\n\x1aGetContractFeePotsResponse\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetContractFeePotsResponse.GetContractFeePotsResponseV0H\x00\x1aR\n\x17\x43ontractFeePotLastClaim\x12\r\n\x05\x65poch\x18\x01 \x01(\r\x12\x13\n\x07time_ms\x18\x02 \x01(\x04\x42\x02\x30\x01\x12\x13\n\x0b\x63laimant_id\x18\x03 \x01(\x0c\x1a\x88\x01\n\x0e\x43ontractFeePot\x12\x13\n\x07\x63redits\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x61\n\nlast_claim\x18\x02 \x01(\x0b\x32M.org.dash.platform.dapi.v0.GetContractFeePotsResponse.ContractFeePotLastClaim\x1a\xc0\x01\n\x0f\x43ontractFeePots\x12S\n\x05owner\x18\x01 \x01(\x0b\x32\x44.org.dash.platform.dapi.v0.GetContractFeePotsResponse.ContractFeePot\x12X\n\nmoderators\x18\x02 \x01(\x0b\x32\x44.org.dash.platform.dapi.v0.GetContractFeePotsResponse.ContractFeePot\x1a\xf1\x01\n\x1cGetContractFeePotsResponseV0\x12U\n\x04pots\x18\x01 \x01(\x0b\x32\x45.org.dash.platform.dapi.v0.GetContractFeePotsResponse.ContractFeePotsH\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\"\xf1\x01\n#GetContractGroupsForContractRequest\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetContractGroupsForContractRequest.GetContractGroupsForContractRequestV0H\x00\x1aK\n%GetContractGroupsForContractRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xf5\x06\n$GetContractGroupsForContractResponse\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetContractGroupsForContractResponse.GetContractGroupsForContractResponseV0H\x00\x1aQ\n\x17\x44ocumentTypeMemberships\x12\x1a\n\x12\x64ocument_type_name\x18\x01 \x01(\t\x12\x1a\n\x12\x63ontract_group_ids\x18\x02 \x03(\x0c\x1a\x46\n\x10TokenMemberships\x12\x16\n\x0etoken_position\x18\x01 \x01(\r\x12\x1a\n\x12\x63ontract_group_ids\x18\x02 \x03(\x0c\x1a\x89\x02\n\x18\x43ontractGroupMemberships\x12\x1a\n\x12\x63ontract_group_ids\x18\x01 \x03(\x0c\x12o\n\x0e\x64ocument_types\x18\x02 \x03(\x0b\x32W.org.dash.platform.dapi.v0.GetContractGroupsForContractResponse.DocumentTypeMemberships\x12`\n\x06tokens\x18\x03 \x03(\x0b\x32P.org.dash.platform.dapi.v0.GetContractGroupsForContractResponse.TokenMemberships\x1a\xa4\x02\n&GetContractGroupsForContractResponseV0\x12~\n\x1a\x63ontract_group_memberships\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetContractGroupsForContractResponse.ContractGroupMembershipsH\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\"\xad\x02\n\x1eGetDataContractsByRangeRequest\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetDataContractsByRangeRequest.GetDataContractsByRangeRequestV0H\x00\x1a\x95\x01\n GetDataContractsByRangeRequestV0\x12\x12\n\x05limit\x18\x01 \x01(\rH\x01\x88\x01\x01\x12\x15\n\x0bstart_after\x18\x02 \x01(\x0cH\x00\x12\x12\n\x08start_at\x18\x03 \x01(\x0cH\x00\x12\x10\n\x08ids_only\x18\x04 \x01(\x08\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\x07\n\x05startB\x08\n\x06_limitB\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\"\xf8\"\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\xe2\x02\n\x12TimeRangeSelection\x12\\\n\x08selector\x18\x01 \x01(\x0e\x32J.org.dash.platform.dapi.v0.GetDocumentsRequest.TimeRangeSelection.Selector\x12\x19\n\x08start_ms\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x88\x01\x01\x12T\n\x04grid\x18\x03 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetDocumentsRequest.TimeRangeSelection.Grid\x1a>\n\x04Grid\x12\x11\n\x05range\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x10\n\x04step\x18\x02 \x01(\x04\x42\x02\x30\x01\x12\x11\n\x05phase\x18\x03 \x01(\x04\x42\x02\x30\x01\"0\n\x08Selector\x12\n\n\x06NEWEST\x10\x00\x12\n\n\x06OLDEST\x10\x01\x12\x0c\n\x08\x42Y_START\x10\x02\x42\x0b\n\t_start_ms\x1a\x82\x02\n\x15IntegerRangeSelection\x12P\n\x05start\x18\x01 \x01(\x0b\x32\x41.org.dash.platform.dapi.v0.GetDocumentsRequest.DocumentFieldValue\x12W\n\x04grid\x18\x02 \x01(\x0b\x32I.org.dash.platform.dapi.v0.GetDocumentsRequest.IntegerRangeSelection.Grid\x1a>\n\x04Grid\x12\x11\n\x05range\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x10\n\x04step\x18\x02 \x01(\x04\x42\x02\x30\x01\x12\x11\n\x05phase\x18\x03 \x01(\x04\x42\x02\x30\x01\x1a\xf2\x02\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\x12U\n\ntime_range\x18\x04 \x01(\x0b\x32\x41.org.dash.platform.dapi.v0.GetDocumentsRequest.TimeRangeSelection\x12[\n\rinteger_range\x18\x05 \x01(\x0b\x32\x44.org.dash.platform.dapi.v0.GetDocumentsRequest.IntegerRangeSelection\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\xa6\x0c\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\x12\x61\n\x07\x63hained\x18\r \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetDocumentsRequest.GetDocumentsRequestV1.ChainedJoin\x12\x62\n\x0bsub_queries\x18\x0e \x03(\x0b\x32M.org.dash.platform.dapi.v0.GetDocumentsRequest.GetDocumentsRequestV1.SubQuery\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\x1a\x41\n\x0b\x43hainedJoin\x12\x15\n\rjoin_property\x18\x01 \x01(\t\x12\x1b\n\x13outer_document_type\x18\x02 \x01(\t\x1a\xa6\x04\n\x08SubQuery\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\x00\x88\x01\x01\x12`\n\x04kind\x18\x06 \x01(\x0e\x32R.org.dash.platform.dapi.v0.GetDocumentsRequest.GetDocumentsRequestV1.SubQuery.Kind\x12\x63\n\x04\x62ind\x18\x07 \x01(\x0b\x32U.org.dash.platform.dapi.v0.GetDocumentsRequest.GetDocumentsRequestV1.SubQuery.Binding\x1a\x41\n\x07\x42inding\x12\x0e\n\x06source\x18\x01 \x01(\r\x12\x17\n\x0fsource_property\x18\x02 \x01(\t\x12\r\n\x05\x66ield\x18\x03 \x01(\t\" \n\x04Kind\x12\r\n\tDOCUMENTS\x10\x00\x12\t\n\x05\x43OUNT\x10\x01\x42\x08\n\x06_limitB\x07\n\x05startB\x08\n\x06_limitB\t\n\x07_offset\"\xb0\x02\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\n\x12\x11\n\rIN_TIME_RANGE\x10\x0b\x12\x14\n\x10IN_INTEGER_RANGE\x10\x0c\x12\x0c\n\x08\x43ONTAINS\x10\r\x12\x10\n\x0c\x43ONTAINS_ANY\x10\x0e\x42\t\n\x07version\"\xd5\x1d\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\xe7\x19\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\xf7\x05\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\x12j\n\x07\x63hained\x18\x06 \x01(\x0b\x32W.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.ChainedDocumentsH\x00\x12n\n\tcomposite\x18\x07 \x01(\x0b\x32Y.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.CompositeDocumentsH\x00\x42\t\n\x07variant\x1a\xd8\x01\n\x10\x43hainedDocuments\x12\x17\n\x0finner_documents\x18\x01 \x03(\x0c\x12\x17\n\x0fouter_documents\x18\x02 \x03(\x0c\x12\x19\n\x11missing_outer_ids\x18\x03 \x03(\x0c\x12w\n\x17removed_outer_documents\x18\x04 \x03(\x0b\x32V.org.dash.platform.dapi.v0.GetContractDocumentRemovalsResponse.ContractDocumentRemoval\x1a\x94\x04\n\x12\x43ompositeDocuments\x12\x16\n\x0epage_documents\x18\x01 \x03(\x0c\x12}\n\x0bsub_results\x18\x02 \x03(\x0b\x32h.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.CompositeDocuments.SubQueryResult\x1a\xe6\x02\n\x0eSubQueryResult\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.CountEntriesH\x00\x12\x13\n\x0bmissing_ids\x18\x03 \x03(\x0c\x12g\n\x07removed\x18\x04 \x03(\x0b\x32V.org.dash.platform.dapi.v0.GetContractDocumentRemovalsResponse.ContractDocumentRemovalB\x08\n\x06resultB\x08\n\x06resultB\t\n\x07version\"\xfe\x06\n\x19GetDocumentHistoryRequest\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0H\x00\x12^\n\x02v1\x18\x02 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1H\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\x1a\xa7\x03\n\x1bGetDocumentHistoryRequestV1\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\r\n\x05prove\x18\x05 \x01(\x08\x12\x19\n\x0bstart_at_ms\x18\x06 \x01(\x04\x42\x02\x30\x01H\x00\x12n\n\x0bstart_after\x18\x07 \x01(\x0b\x32W.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.CursorH\x00\x12\x1f\n\x11start_at_revision\x18\x08 \x01(\x04\x42\x02\x30\x01H\x00\x12\x16\n\x08revision\x18\t \x01(\x04\x42\x02\x30\x01H\x00\x1a\x33\n\x06\x43ursor\x12\x13\n\x07time_ms\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x14\n\x08revision\x18\x02 \x01(\x04\x42\x02\x30\x01\x42\x08\n\x06\x66ilterB\t\n\x07version\"\xd6\x0b\n\x1aGetDocumentHistoryResponse\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0H\x00\x12`\n\x02v1\x18\x02 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1H\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\x06result\x1a\xfa\x05\n\x1cGetDocumentHistoryResponseV1\x12m\n\x07history\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.HistoryH\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\x05\x45ntry\x12\x13\n\x07time_ms\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x14\n\x08revision\x18\x02 \x01(\x04\x42\x02\x30\x01\x12\x10\n\x08\x64ocument\x18\x03 \x01(\x0c\x1a\xc0\x01\n\tLifecycle\x12q\n\x05state\x18\x01 \x01(\x0e\x32\x62.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.State\x12\x1f\n\x13remaining_revisions\x18\x02 \x01(\x04\x42\x02\x30\x01\"\x1f\n\x05State\x12\n\n\x06\x41\x43TIVE\x10\x00\x12\n\n\x06\x41\x42SENT\x10\x01\x1a\xe5\x01\n\x07History\x12i\n\x07\x65ntries\x18\x01 \x03(\x0b\x32X.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry\x12o\n\tlifecycle\x18\x02 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.LifecycleB\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\"\xc3\x04\n*GetIdentityByNonUniquePublicKeyHashRequest\x12\x80\x01\n\x02v0\x18\x01 \x01(\x0b\x32r.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashRequest.GetIdentityByNonUniquePublicKeyHashRequestV0H\x00\x12\x80\x01\n\x02v1\x18\x02 \x01(\x0b\x32r.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashRequest.GetIdentityByNonUniquePublicKeyHashRequestV1H\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_after\x1a\x80\x01\n,GetIdentityByNonUniquePublicKeyHashRequestV1\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\"\xe4\n\n+GetIdentityByNonUniquePublicKeyHashResponse\x12\x82\x01\n\x02v0\x18\x01 \x01(\x0b\x32t.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashResponse.GetIdentityByNonUniquePublicKeyHashResponseV0H\x00\x12\x82\x01\n\x02v1\x18\x02 \x01(\x0b\x32t.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashResponse.GetIdentityByNonUniquePublicKeyHashResponseV1H\x00\x1a\x9c\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\x06resultJ\x04\x08\x04\x10\x05\x1a\x80\x03\n-GetIdentityByNonUniquePublicKeyHashResponseV1\x12\x9a\x01\n\x08identity\x18\x01 \x01(\x0b\x32\x85\x01.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashResponse.GetIdentityByNonUniquePublicKeyHashResponseV1.IdentityResponseH\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\x10IdentityResponse\x12\x15\n\x08identity\x18\x01 \x01(\x0cH\x00\x88\x01\x01\x42\x0b\n\t_identityB\x08\n\x06resultB\t\n\x07version\"\x99\x02\n#WaitForStateTransitionResultRequest\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.WaitForStateTransitionResultRequest.WaitForStateTransitionResultRequestV0H\x00\x1as\n%WaitForStateTransitionResultRequestV0\x12\x1d\n\x15state_transition_hash\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x12\x1c\n\x14request_user_balance\x18\x03 \x01(\x08\x42\t\n\x07version\"\xce\x04\n$WaitForStateTransitionResultResponse\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.WaitForStateTransitionResultResponse.WaitForStateTransitionResultResponseV0H\x00\x1a\x34\n\x17SuccessWithOwnerBalance\x12\x19\n\rowner_balance\x18\x01 \x01(\x04\x42\x02\x30\x01\x1a\xee\x02\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\x1asuccess_with_owner_balance\x18\x04 \x01(\x0b\x32W.org.dash.platform.dapi.v0.WaitForStateTransitionResultResponse.SuccessWithOwnerBalanceH\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\"\xd6\x01\n\x1cGetYesNoVotePollStateRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetYesNoVotePollStateRequest.GetYesNoVotePollStateRequestV0H\x00\x1a\x45\n\x1eGetYesNoVotePollStateRequestV0\x12\x14\n\x0cvote_poll_id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xa8\x11\n\x1dGetYesNoVotePollStateResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetYesNoVotePollStateResponse.GetYesNoVotePollStateResponseV0H\x00\x1a\x93\x10\n\x1fGetYesNoVotePollStateResponseV0\x12|\n\x05state\x18\x01 \x01(\x0b\x32k.org.dash.platform.dapi.v0.GetYesNoVotePollStateResponse.GetYesNoVotePollStateResponseV0.YesNoVotePollStateH\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\x61\n\x12YesNoVotePollBlock\x12\x12\n\x06height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x13\n\x0b\x63ore_height\x18\x02 \x01(\r\x12\x13\n\x07time_ms\x18\x03 \x01(\x04\x42\x02\x30\x01\x12\r\n\x05\x65poch\x18\x04 \x01(\r\x1a\xa4\x03\n\x15\x46inishedYesNoVotePoll\x12\x0e\n\x06passed\x18\x01 \x01(\x08\x12\x18\n\x10yes_voting_power\x18\x02 \x01(\r\x12\x17\n\x0fno_voting_power\x18\x03 \x01(\r\x12\x1c\n\x14\x61\x62stain_voting_power\x18\x04 \x01(\r\x12\x1d\n\x15required_voting_power\x18\x05 \x01(\r\x12\x80\x01\n\x0bstart_block\x18\x06 \x01(\x0b\x32k.org.dash.platform.dapi.v0.GetYesNoVotePollStateResponse.GetYesNoVotePollStateResponseV0.YesNoVotePollBlock\x12\x87\x01\n\x12\x66inalization_block\x18\x07 \x01(\x0b\x32k.org.dash.platform.dapi.v0.GetYesNoVotePollStateResponse.GetYesNoVotePollStateResponseV0.YesNoVotePollBlock\x1a\xf9\x05\n\rYesNoVotePoll\x12\x94\x01\n\x11\x64\x65\x63ision_proposal\x18\x01 \x01(\x0b\x32w.org.dash.platform.dapi.v0.GetYesNoVotePollStateResponse.GetYesNoVotePollStateResponseV0.YesNoVotePoll.DecisionProposalH\x00\x12\x1f\n\x17supermajority_numerator\x18\x02 \x01(\r\x12!\n\x19supermajority_denominator\x18\x03 \x01(\r\x12\x12\n\x08\x61\x62solute\x18\x04 \x01(\rH\x01\x12\x93\x01\n\x11\x66raction_of_total\x18\x05 \x01(\x0b\x32v.org.dash.platform.dapi.v0.GetYesNoVotePollStateResponse.GetYesNoVotePollStateResponseV0.YesNoVotePoll.FractionOfTotalH\x01\x1a\'\n\x10\x44\x65\x63isionProposal\x12\x13\n\x0b\x64ocument_id\x18\x01 \x01(\x0c\x1a\xc8\x01\n\x0f\x46ractionOfTotal\x12\x11\n\tnumerator\x18\x01 \x01(\r\x12\x13\n\x0b\x64\x65nominator\x18\x02 \x01(\r\x12\x8c\x01\n\x08rounding\x18\x03 \x01(\x0e\x32z.org.dash.platform.dapi.v0.GetYesNoVotePollStateResponse.GetYesNoVotePollStateResponseV0.YesNoVotePoll.VotingPowerRounding\"L\n\x13VotingPowerRounding\x12\x08\n\x04\x44OWN\x10\x00\x12\x06\n\x02UP\x10\x01\x12\x11\n\rDOWN_PLUS_ONE\x10\x02\x12\x10\n\x0cUP_MINUS_ONE\x10\x03\x42\t\n\x07purposeB\x16\n\x14minimum_voting_power\x1a\xef\x03\n\x12YesNoVotePollState\x12~\n\x07started\x18\x01 \x01(\x0b\x32k.org.dash.platform.dapi.v0.GetYesNoVotePollStateResponse.GetYesNoVotePollStateResponseV0.YesNoVotePollBlockH\x00\x12\x82\x01\n\x08\x66inished\x18\x02 \x01(\x0b\x32n.org.dash.platform.dapi.v0.GetYesNoVotePollStateResponse.GetYesNoVotePollStateResponseV0.FinishedYesNoVotePollH\x00\x12\x18\n\x10yes_voting_power\x18\x03 \x01(\r\x12\x17\n\x0fno_voting_power\x18\x04 \x01(\r\x12\x1c\n\x14\x61\x62stain_voting_power\x18\x05 \x01(\r\x12y\n\tvote_poll\x18\x06 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetYesNoVotePollStateResponse.GetYesNoVotePollStateResponseV0.YesNoVotePollB\x08\n\x06statusB\x08\n\x06resultB\t\n\x07version\"\xef\x01\n\x1dGetMasternodeYesNoVoteRequest\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetMasternodeYesNoVoteRequest.GetMasternodeYesNoVoteRequestV0H\x00\x1a[\n\x1fGetMasternodeYesNoVoteRequestV0\x12\x13\n\x0bpro_tx_hash\x18\x01 \x01(\x0c\x12\x14\n\x0cvote_poll_id\x18\x02 \x01(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xb5\x06\n\x1eGetMasternodeYesNoVoteResponse\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetMasternodeYesNoVoteResponse.GetMasternodeYesNoVoteResponseV0H\x00\x1a\x9d\x05\n GetMasternodeYesNoVoteResponseV0\x12\x84\x01\n\x05\x65ntry\x18\x01 \x01(\x0b\x32s.org.dash.platform.dapi.v0.GetMasternodeYesNoVoteResponse.GetMasternodeYesNoVoteResponseV0.MasternodeYesNoVoteEntryH\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\x01\n\x13MasternodeYesNoVote\x12\x85\x01\n\x06\x63hoice\x18\x01 \x01(\x0e\x32u.org.dash.platform.dapi.v0.GetMasternodeYesNoVoteResponse.GetMasternodeYesNoVoteResponseV0.MasternodeYesNoVote.Choice\x12\x13\n\x0btimes_voted\x18\x02 \x01(\r\"&\n\x06\x43hoice\x12\x07\n\x03YES\x10\x00\x12\x06\n\x02NO\x10\x01\x12\x0b\n\x07\x41\x42STAIN\x10\x02\x1a\x98\x01\n\x18MasternodeYesNoVoteEntry\x12|\n\x04vote\x18\x01 \x01(\x0b\x32n.org.dash.platform.dapi.v0.GetMasternodeYesNoVoteResponse.GetMasternodeYesNoVoteResponseV0.MasternodeYesNoVoteB\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\"\x92\"\n\x17GetGroupActionsResponse\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0H\x00\x1a\x8f!\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\x63\n\x0fMintToPoolEvent\x12\x0e\n\x06\x61mount\x18\x01 \x01(\x04\x12\x16\n\x0e\x61\x63tions_digest\x18\x02 \x01(\x0c\x12\x18\n\x0bpublic_note\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_public_note\x1a\x65\n\x11\x42urnFromPoolEvent\x12\x0e\n\x06\x61mount\x18\x01 \x01(\x04\x12\x16\n\x0e\x61\x63tions_digest\x18\x02 \x01(\x0c\x12\x18\n\x0bpublic_note\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\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\xc1\t\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\x12t\n\x0cmint_to_pool\x18\t \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.MintToPoolEventH\x00\x12x\n\x0e\x62urn_from_pool\x18\n \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.BurnFromPoolEventH\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\"\x98\x02\n GetShieldedEncryptedNotesRequest\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetShieldedEncryptedNotesRequest.GetShieldedEncryptedNotesRequestV0H\x00\x1a{\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\x12\x15\n\x08token_id\x18\x04 \x01(\x0cH\x00\x88\x01\x01\x42\x0b\n\t_token_idB\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\"\xd8\x01\n\x19GetShieldedAnchorsRequest\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetShieldedAnchorsRequest.GetShieldedAnchorsRequestV0H\x00\x1aP\n\x1bGetShieldedAnchorsRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x12\x15\n\x08token_id\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x42\x0b\n\t_token_idB\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\"\xfc\x01\n\"GetMostRecentShieldedAnchorRequest\x12p\n\x02v0\x18\x01 \x01(\x0b\x32\x62.org.dash.platform.dapi.v0.GetMostRecentShieldedAnchorRequest.GetMostRecentShieldedAnchorRequestV0H\x00\x1aY\n$GetMostRecentShieldedAnchorRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x12\x15\n\x08token_id\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x42\x0b\n\t_token_idB\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\"\xe0\x01\n\x1bGetShieldedPoolStateRequest\x12\x62\n\x02v0\x18\x01 \x01(\x0b\x32T.org.dash.platform.dapi.v0.GetShieldedPoolStateRequest.GetShieldedPoolStateRequestV0H\x00\x1aR\n\x1dGetShieldedPoolStateRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x12\x15\n\x08token_id\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x42\x0b\n\t_token_idB\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\"\xe4\x01\n\x1cGetShieldedNotesCountRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetShieldedNotesCountRequest.GetShieldedNotesCountRequestV0H\x00\x1aS\n\x1eGetShieldedNotesCountRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x12\x15\n\x08token_id\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x42\x0b\n\t_token_idB\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\"\xf8\x01\n\x1cGetShieldedNullifiersRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetShieldedNullifiersRequest.GetShieldedNullifiersRequestV0H\x00\x1ag\n\x1eGetShieldedNullifiersRequestV0\x12\x12\n\nnullifiers\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x12\x15\n\x08token_id\x18\x03 \x01(\x0cH\x00\x88\x01\x01\x42\x0b\n\t_token_idB\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\"\xb0\x02\n GetPrivateDocumentEntriesRequest\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetPrivateDocumentEntriesRequest.GetPrivateDocumentEntriesRequestV0H\x00\x1a\x92\x01\n\"GetPrivateDocumentEntriesRequestV0\x12\x18\n\x10\x64\x61ta_contract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\x1a\n\x0estart_position\x18\x03 \x01(\x04\x42\x02\x30\x01\x12\r\n\x05prove\x18\x05 \x01(\x08J\x04\x08\x04\x10\x05R\x05\x63ountB\t\n\x07version\"\xfd\x05\n!GetPrivateDocumentEntriesResponse\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetPrivateDocumentEntriesResponse.GetPrivateDocumentEntriesResponseV0H\x00\x1a\xdc\x04\n#GetPrivateDocumentEntriesResponseV0\x12\x8a\x01\n\x07\x65ntries\x18\x01 \x01(\x0b\x32w.org.dash.platform.dapi.v0.GetPrivateDocumentEntriesResponse.GetPrivateDocumentEntriesResponseV0.PrivateDocumentEntriesH\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\x1ao\n\x14PrivateDocumentEntry\x12\x14\n\x08position\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x18\n\x0c\x62lock_height\x18\x02 \x01(\x04\x42\x02\x30\x01\x12\x19\n\rblock_time_ms\x18\x03 \x01(\x04\x42\x02\x30\x01\x12\x0c\n\x04\x64\x61ta\x18\x04 \x01(\x0c\x1a\xba\x01\n\x16PrivateDocumentEntries\x12\x86\x01\n\x07\x65ntries\x18\x01 \x03(\x0b\x32u.org.dash.platform.dapi.v0.GetPrivateDocumentEntriesResponse.GetPrivateDocumentEntriesResponseV0.PrivateDocumentEntry\x12\x17\n\x0btotal_count\x18\x02 \x01(\x04\x42\x02\x30\x01\x42\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*\xb9\x01\n\x16\x43ontractModerationList\x12(\n$CONTRACT_MODERATION_LIST_UNSPECIFIED\x10\x00\x12$\n CONTRACT_MODERATION_LIST_BANLIST\x10\x01\x12(\n$CONTRACT_MODERATION_LIST_SUSPENSIONS\x10\x02\x12%\n!CONTRACT_MODERATION_LIST_WARNINGS\x10\x03\x32\xe9W\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\xa8\x01\n\x1fgetIdentityKeysRemainingBudgets\x12\x41.org.dash.platform.dapi.v0.GetIdentityKeysRemainingBudgetsRequest\x1a\x42.org.dash.platform.dapi.v0.GetIdentityKeysRemainingBudgetsResponse\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\xa5\x01\n\x1egetDataContractsLatestVersions\x12@.org.dash.platform.dapi.v0.GetDataContractsLatestVersionsRequest\x1a\x41.org.dash.platform.dapi.v0.GetDataContractsLatestVersionsResponse\x12{\n\x10getDataContracts\x12\x32.org.dash.platform.dapi.v0.GetDataContractsRequest\x1a\x33.org.dash.platform.dapi.v0.GetDataContractsResponse\x12\x89\x01\n\x17getDataContractsByRange\x12\x39.org.dash.platform.dapi.v0.GetDataContractsByRangeRequest\x1a\x33.org.dash.platform.dapi.v0.GetDataContractsResponse\x12\x87\x01\n\x14getContractGroupInfo\x12\x36.org.dash.platform.dapi.v0.GetContractGroupInfoRequest\x1a\x37.org.dash.platform.dapi.v0.GetContractGroupInfoResponse\x12\x90\x01\n\x17getContractGroupMembers\x12\x39.org.dash.platform.dapi.v0.GetContractGroupMembersRequest\x1a:.org.dash.platform.dapi.v0.GetContractGroupMembersResponse\x12\x9f\x01\n\x1cgetContractGroupsForContract\x12>.org.dash.platform.dapi.v0.GetContractGroupsForContractRequest\x1a?.org.dash.platform.dapi.v0.GetContractGroupsForContractResponse\x12\x9c\x01\n\x1bgetContractModerationStatus\x12=.org.dash.platform.dapi.v0.GetContractModerationStatusRequest\x1a>.org.dash.platform.dapi.v0.GetContractModerationStatusResponse\x12\x9f\x01\n\x1cgetContractModerationEntries\x12>.org.dash.platform.dapi.v0.GetContractModerationEntriesRequest\x1a?.org.dash.platform.dapi.v0.GetContractModerationEntriesResponse\x12\x9c\x01\n\x1bgetContractDocumentRemovals\x12=.org.dash.platform.dapi.v0.GetContractDocumentRemovalsRequest\x1a>.org.dash.platform.dapi.v0.GetContractDocumentRemovalsResponse\x12\x8d\x01\n\x16getContractTeamActions\x12\x38.org.dash.platform.dapi.v0.GetContractTeamActionsRequest\x1a\x39.org.dash.platform.dapi.v0.GetContractTeamActionsResponse\x12\x9f\x01\n\x1cgetContractTeamActionSigners\x12>.org.dash.platform.dapi.v0.GetContractTeamActionSignersRequest\x1a?.org.dash.platform.dapi.v0.GetContractTeamActionSignersResponse\x12\xae\x01\n!getContractModerationActionCounts\x12\x43.org.dash.platform.dapi.v0.GetContractModerationActionCountsRequest\x1a\x44.org.dash.platform.dapi.v0.GetContractModerationActionCountsResponse\x12\x81\x01\n\x12getContractFeePots\x12\x34.org.dash.platform.dapi.v0.GetContractFeePotsRequest\x1a\x35.org.dash.platform.dapi.v0.GetContractFeePotsResponse\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\x8a\x01\n\x15getYesNoVotePollState\x12\x37.org.dash.platform.dapi.v0.GetYesNoVotePollStateRequest\x1a\x38.org.dash.platform.dapi.v0.GetYesNoVotePollStateResponse\x12\x8d\x01\n\x16getMasternodeYesNoVote\x12\x38.org.dash.platform.dapi.v0.GetMasternodeYesNoVoteRequest\x1a\x39.org.dash.platform.dapi.v0.GetMasternodeYesNoVoteResponse\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.GetShieldedNullifiersResponse\x12\x96\x01\n\x19getPrivateDocumentEntries\x12;.org.dash.platform.dapi.v0.GetPrivateDocumentEntriesRequest\x1a<.org.dash.platform.dapi.v0.GetPrivateDocumentEntriesResponseb\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=89685, - serialized_end=89775, + serialized_start=91070, + serialized_end=91160, ) _sym_db.RegisterEnumDescriptor(_KEYPURPOSE) @@ -98,8 +98,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=89778, - serialized_end=89963, + serialized_start=91163, + serialized_end=91348, ) _sym_db.RegisterEnumDescriptor(_CONTRACTMODERATIONLIST) @@ -480,6 +480,31 @@ ) _sym_db.RegisterEnumDescriptor(_GETDOCUMENTSREQUEST_WHEREOPERATOR) +_GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1_LIFECYCLE_STATE = _descriptor.EnumDescriptor( + name='State', + full_name='org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.State', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='ACTIVE', index=0, number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='ABSENT', index=1, number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=36251, + serialized_end=36282, +) +_sym_db.RegisterEnumDescriptor(_GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1_LIFECYCLE_STATE) + _GETYESNOVOTEPOLLSTATERESPONSE_GETYESNOVOTEPOLLSTATERESPONSEV0_YESNOVOTEPOLL_VOTINGPOWERROUNDING = _descriptor.EnumDescriptor( name='VotingPowerRounding', full_name='org.dash.platform.dapi.v0.GetYesNoVotePollStateResponse.GetYesNoVotePollStateResponseV0.YesNoVotePoll.VotingPowerRounding', @@ -510,8 +535,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=48189, - serialized_end=48265, + serialized_start=49574, + serialized_end=49650, ) _sym_db.RegisterEnumDescriptor(_GETYESNOVOTEPOLLSTATERESPONSE_GETYESNOVOTEPOLLSTATERESPONSEV0_YESNOVOTEPOLL_VOTINGPOWERROUNDING) @@ -540,8 +565,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=49671, - serialized_end=49709, + serialized_start=51056, + serialized_end=51094, ) _sym_db.RegisterEnumDescriptor(_GETMASTERNODEYESNOVOTERESPONSE_GETMASTERNODEYESNOVOTERESPONSEV0_MASTERNODEYESNOVOTE_CHOICE) @@ -570,8 +595,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=50660, - serialized_end=50733, + serialized_start=52045, + serialized_end=52118, ) _sym_db.RegisterEnumDescriptor(_GETCONTESTEDRESOURCEVOTESTATEREQUEST_GETCONTESTEDRESOURCEVOTESTATEREQUESTV0_RESULTTYPE) @@ -600,8 +625,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=51655, - serialized_end=51734, + serialized_start=53040, + serialized_end=53119, ) _sym_db.RegisterEnumDescriptor(_GETCONTESTEDRESOURCEVOTESTATERESPONSE_GETCONTESTEDRESOURCEVOTESTATERESPONSEV0_FINISHEDVOTEINFO_FINISHEDVOTEOUTCOME) @@ -630,8 +655,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=55363, - serialized_end=55424, + serialized_start=56748, + serialized_end=56809, ) _sym_db.RegisterEnumDescriptor(_GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSE_GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSEV0_RESOURCEVOTECHOICE_VOTECHOICETYPE) @@ -680,8 +705,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=75273, - serialized_end=75308, + serialized_start=76658, + serialized_end=76693, ) _sym_db.RegisterEnumDescriptor(_GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_EMERGENCYACTIONEVENT_ACTIONTYPE) @@ -9604,8 +9629,138 @@ extension_ranges=[], oneofs=[ ], - serialized_start=34270, - serialized_end=34505, + serialized_start=34366, + serialized_end=34601, +) + +_GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV1_CURSOR = _descriptor.Descriptor( + name='Cursor', + full_name='org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='time_ms', full_name='org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.time_ms', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=b'0\001', file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='revision', full_name='org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.revision', index=1, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=b'0\001', file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=34966, + serialized_end=35017, +) + +_GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV1 = _descriptor.Descriptor( + name='GetDocumentHistoryRequestV1', + full_name='org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='data_contract_id', full_name='org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.data_contract_id', index=0, + number=1, 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), + _descriptor.FieldDescriptor( + name='document_type_name', full_name='org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.document_type_name', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + 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='document_id', full_name='org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.document_id', index=2, + number=3, 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), + _descriptor.FieldDescriptor( + name='limit', full_name='org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.limit', index=3, + number=4, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + 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='prove', full_name='org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prove', index=4, + number=5, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + 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='start_at_ms', full_name='org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.start_at_ms', index=5, + number=6, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=b'0\001', file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='start_after', full_name='org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.start_after', index=6, + number=7, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + 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='start_at_revision', full_name='org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.start_at_revision', index=7, + number=8, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=b'0\001', file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='revision', full_name='org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.revision', index=8, + number=9, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=b'0\001', file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[_GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV1_CURSOR, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='filter', full_name='org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.filter', + index=0, containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[]), + ], + serialized_start=34604, + serialized_end=35027, ) _GETDOCUMENTHISTORYREQUEST = _descriptor.Descriptor( @@ -9623,10 +9778,17 @@ 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='v1', full_name='org.dash.platform.dapi.v0.GetDocumentHistoryRequest.v1', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + 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=[ ], - nested_types=[_GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV0, ], + nested_types=[_GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV0, _GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV1, ], enum_types=[ ], serialized_options=None, @@ -9641,7 +9803,7 @@ fields=[]), ], serialized_start=34144, - serialized_end=34516, + serialized_end=35038, ) @@ -9679,8 +9841,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=34922, - serialized_end=34977, + serialized_start=35542, + serialized_end=35597, ) _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV0_DOCUMENTHISTORY = _descriptor.Descriptor( @@ -9710,8 +9872,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=34980, - serialized_end=35129, + serialized_start=35600, + serialized_end=35749, ) _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV0 = _descriptor.Descriptor( @@ -9760,8 +9922,180 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=34648, - serialized_end=35139, + serialized_start=35268, + serialized_end=35759, +) + +_GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1_ENTRY = _descriptor.Descriptor( + name='Entry', + full_name='org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='time_ms', full_name='org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.time_ms', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=b'0\001', file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='revision', full_name='org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.revision', index=1, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=b'0\001', file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='document', full_name='org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.document', index=2, + number=3, 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=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=36019, + serialized_end=36087, +) + +_GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1_LIFECYCLE = _descriptor.Descriptor( + name='Lifecycle', + full_name='org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='state', full_name='org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.state', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + 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='remaining_revisions', full_name='org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.remaining_revisions', index=1, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=b'0\001', file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1_LIFECYCLE_STATE, + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=36090, + serialized_end=36282, +) + +_GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1_HISTORY = _descriptor.Descriptor( + name='History', + full_name='org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='entries', full_name='org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.entries', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + 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='lifecycle', full_name='org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.lifecycle', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + 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=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=36285, + serialized_end=36514, +) + +_GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1 = _descriptor.Descriptor( + name='GetDocumentHistoryResponseV1', + full_name='org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='history', full_name='org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.history', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + 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='proof', full_name='org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.proof', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + 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='metadata', full_name='org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.metadata', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + 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=[ + ], + nested_types=[_GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1_ENTRY, _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1_LIFECYCLE, _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1_HISTORY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='result', full_name='org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.result', + index=0, containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[]), + ], + serialized_start=35762, + serialized_end=36524, ) _GETDOCUMENTHISTORYRESPONSE = _descriptor.Descriptor( @@ -9779,10 +10113,17 @@ 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='v1', full_name='org.dash.platform.dapi.v0.GetDocumentHistoryResponse.v1', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + 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=[ ], - nested_types=[_GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV0, ], + nested_types=[_GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV0, _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1, ], enum_types=[ ], serialized_options=None, @@ -9796,8 +10137,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=34519, - serialized_end=35150, + serialized_start=35041, + serialized_end=36535, ) @@ -9835,8 +10176,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=35302, - serialized_end=35379, + serialized_start=36687, + serialized_end=36764, ) _GETIDENTITYBYPUBLICKEYHASHREQUEST = _descriptor.Descriptor( @@ -9871,8 +10212,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=35153, - serialized_end=35390, + serialized_start=36538, + serialized_end=36775, ) @@ -9922,8 +10263,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=35546, - serialized_end=35728, + serialized_start=36931, + serialized_end=37113, ) _GETIDENTITYBYPUBLICKEYHASHRESPONSE = _descriptor.Descriptor( @@ -9958,8 +10299,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=35393, - serialized_end=35739, + serialized_start=36778, + serialized_end=37124, ) @@ -10009,8 +10350,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=36051, - serialized_end=36179, + serialized_start=37436, + serialized_end=37564, ) _GETIDENTITYBYNONUNIQUEPUBLICKEYHASHREQUEST_GETIDENTITYBYNONUNIQUEPUBLICKEYHASHREQUESTV1 = _descriptor.Descriptor( @@ -10059,8 +10400,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=36182, - serialized_end=36310, + serialized_start=37567, + serialized_end=37695, ) _GETIDENTITYBYNONUNIQUEPUBLICKEYHASHREQUEST = _descriptor.Descriptor( @@ -10102,8 +10443,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=35742, - serialized_end=36321, + serialized_start=37127, + serialized_end=37706, ) @@ -10139,8 +10480,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=37067, - serialized_end=37121, + serialized_start=38452, + serialized_end=38506, ) _GETIDENTITYBYNONUNIQUEPUBLICKEYHASHRESPONSE_GETIDENTITYBYNONUNIQUEPUBLICKEYHASHRESPONSEV0_IDENTITYPROVEDRESPONSE = _descriptor.Descriptor( @@ -10182,8 +10523,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=37124, - serialized_end=37290, + serialized_start=38509, + serialized_end=38675, ) _GETIDENTITYBYNONUNIQUEPUBLICKEYHASHRESPONSE_GETIDENTITYBYNONUNIQUEPUBLICKEYHASHRESPONSEV0 = _descriptor.Descriptor( @@ -10232,8 +10573,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=36638, - serialized_end=37306, + serialized_start=38023, + serialized_end=38691, ) _GETIDENTITYBYNONUNIQUEPUBLICKEYHASHRESPONSE_GETIDENTITYBYNONUNIQUEPUBLICKEYHASHRESPONSEV1_IDENTITYRESPONSE = _descriptor.Descriptor( @@ -10268,8 +10609,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=37067, - serialized_end=37121, + serialized_start=38452, + serialized_end=38506, ) _GETIDENTITYBYNONUNIQUEPUBLICKEYHASHRESPONSE_GETIDENTITYBYNONUNIQUEPUBLICKEYHASHRESPONSEV1 = _descriptor.Descriptor( @@ -10318,8 +10659,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=37309, - serialized_end=37693, + serialized_start=38694, + serialized_end=39078, ) _GETIDENTITYBYNONUNIQUEPUBLICKEYHASHRESPONSE = _descriptor.Descriptor( @@ -10361,8 +10702,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=36324, - serialized_end=37704, + serialized_start=37709, + serialized_end=39089, ) @@ -10407,8 +10748,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=37862, - serialized_end=37977, + serialized_start=39247, + serialized_end=39362, ) _WAITFORSTATETRANSITIONRESULTREQUEST = _descriptor.Descriptor( @@ -10443,8 +10784,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=37707, - serialized_end=37988, + serialized_start=39092, + serialized_end=39373, ) @@ -10475,8 +10816,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=38149, - serialized_end=38201, + serialized_start=39534, + serialized_end=39586, ) _WAITFORSTATETRANSITIONRESULTRESPONSE_WAITFORSTATETRANSITIONRESULTRESPONSEV0 = _descriptor.Descriptor( @@ -10532,8 +10873,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=38204, - serialized_end=38570, + serialized_start=39589, + serialized_end=39955, ) _WAITFORSTATETRANSITIONRESULTRESPONSE = _descriptor.Descriptor( @@ -10568,8 +10909,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=37991, - serialized_end=38581, + serialized_start=39376, + serialized_end=39966, ) @@ -10607,8 +10948,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=38709, - serialized_end=38769, + serialized_start=40094, + serialized_end=40154, ) _GETCONSENSUSPARAMSREQUEST = _descriptor.Descriptor( @@ -10643,8 +10984,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=38584, - serialized_end=38780, + serialized_start=39969, + serialized_end=40165, ) @@ -10689,8 +11030,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=38911, - serialized_end=38991, + serialized_start=40296, + serialized_end=40376, ) _GETCONSENSUSPARAMSRESPONSE_CONSENSUSPARAMSEVIDENCE = _descriptor.Descriptor( @@ -10734,8 +11075,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=38993, - serialized_end=39091, + serialized_start=40378, + serialized_end=40476, ) _GETCONSENSUSPARAMSRESPONSE_GETCONSENSUSPARAMSRESPONSEV0 = _descriptor.Descriptor( @@ -10772,8 +11113,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=39094, - serialized_end=39312, + serialized_start=40479, + serialized_end=40697, ) _GETCONSENSUSPARAMSRESPONSE = _descriptor.Descriptor( @@ -10808,8 +11149,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=38783, - serialized_end=39323, + serialized_start=40168, + serialized_end=40708, ) @@ -10840,8 +11181,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=39487, - serialized_end=39543, + serialized_start=40872, + serialized_end=40928, ) _GETPROTOCOLVERSIONUPGRADESTATEREQUEST = _descriptor.Descriptor( @@ -10876,8 +11217,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=39326, - serialized_end=39554, + serialized_start=40711, + serialized_end=40939, ) @@ -10908,8 +11249,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=40019, - serialized_end=40169, + serialized_start=41404, + serialized_end=41554, ) _GETPROTOCOLVERSIONUPGRADESTATERESPONSE_GETPROTOCOLVERSIONUPGRADESTATERESPONSEV0_VERSIONENTRY = _descriptor.Descriptor( @@ -10946,8 +11287,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=40171, - serialized_end=40229, + serialized_start=41556, + serialized_end=41614, ) _GETPROTOCOLVERSIONUPGRADESTATERESPONSE_GETPROTOCOLVERSIONUPGRADESTATERESPONSEV0 = _descriptor.Descriptor( @@ -10996,8 +11337,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=39722, - serialized_end=40239, + serialized_start=41107, + serialized_end=41624, ) _GETPROTOCOLVERSIONUPGRADESTATERESPONSE = _descriptor.Descriptor( @@ -11032,8 +11373,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=39557, - serialized_end=40250, + serialized_start=40942, + serialized_end=41635, ) @@ -11078,8 +11419,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=40430, - serialized_end=40533, + serialized_start=41815, + serialized_end=41918, ) _GETPROTOCOLVERSIONUPGRADEVOTESTATUSREQUEST = _descriptor.Descriptor( @@ -11114,8 +11455,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=40253, - serialized_end=40544, + serialized_start=41638, + serialized_end=41929, ) @@ -11146,8 +11487,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=41047, - serialized_end=41222, + serialized_start=42432, + serialized_end=42607, ) _GETPROTOCOLVERSIONUPGRADEVOTESTATUSRESPONSE_GETPROTOCOLVERSIONUPGRADEVOTESTATUSRESPONSEV0_VERSIONSIGNAL = _descriptor.Descriptor( @@ -11184,8 +11525,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=41224, - serialized_end=41277, + serialized_start=42609, + serialized_end=42662, ) _GETPROTOCOLVERSIONUPGRADEVOTESTATUSRESPONSE_GETPROTOCOLVERSIONUPGRADEVOTESTATUSRESPONSEV0 = _descriptor.Descriptor( @@ -11234,8 +11575,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=40728, - serialized_end=41287, + serialized_start=42113, + serialized_end=42672, ) _GETPROTOCOLVERSIONUPGRADEVOTESTATUSRESPONSE = _descriptor.Descriptor( @@ -11270,8 +11611,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=40547, - serialized_end=41298, + serialized_start=41932, + serialized_end=42683, ) @@ -11323,8 +11664,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=41411, - serialized_end=41535, + serialized_start=42796, + serialized_end=42920, ) _GETEPOCHSINFOREQUEST = _descriptor.Descriptor( @@ -11359,8 +11700,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=41301, - serialized_end=41546, + serialized_start=42686, + serialized_end=42931, ) @@ -11391,8 +11732,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=41907, - serialized_end=42024, + serialized_start=43292, + serialized_end=43409, ) _GETEPOCHSINFORESPONSE_GETEPOCHSINFORESPONSEV0_EPOCHINFO = _descriptor.Descriptor( @@ -11457,8 +11798,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=42027, - serialized_end=42193, + serialized_start=43412, + serialized_end=43578, ) _GETEPOCHSINFORESPONSE_GETEPOCHSINFORESPONSEV0 = _descriptor.Descriptor( @@ -11507,8 +11848,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=41663, - serialized_end=42203, + serialized_start=43048, + serialized_end=43588, ) _GETEPOCHSINFORESPONSE = _descriptor.Descriptor( @@ -11543,8 +11884,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=41549, - serialized_end=42214, + serialized_start=42934, + serialized_end=43599, ) @@ -11603,8 +11944,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=42355, - serialized_end=42525, + serialized_start=43740, + serialized_end=43910, ) _GETFINALIZEDEPOCHINFOSREQUEST = _descriptor.Descriptor( @@ -11639,8 +11980,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=42217, - serialized_end=42536, + serialized_start=43602, + serialized_end=43921, ) @@ -11671,8 +12012,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=42962, - serialized_end=43126, + serialized_start=44347, + serialized_end=44511, ) _GETFINALIZEDEPOCHINFOSRESPONSE_GETFINALIZEDEPOCHINFOSRESPONSEV0_FINALIZEDEPOCHINFO = _descriptor.Descriptor( @@ -11786,8 +12127,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=43129, - serialized_end=43672, + serialized_start=44514, + serialized_end=45057, ) _GETFINALIZEDEPOCHINFOSRESPONSE_GETFINALIZEDEPOCHINFOSRESPONSEV0_BLOCKPROPOSER = _descriptor.Descriptor( @@ -11824,8 +12165,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=43674, - serialized_end=43731, + serialized_start=45059, + serialized_end=45116, ) _GETFINALIZEDEPOCHINFOSRESPONSE_GETFINALIZEDEPOCHINFOSRESPONSEV0 = _descriptor.Descriptor( @@ -11874,8 +12215,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=42680, - serialized_end=43741, + serialized_start=44065, + serialized_end=45126, ) _GETFINALIZEDEPOCHINFOSRESPONSE = _descriptor.Descriptor( @@ -11910,8 +12251,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=42539, - serialized_end=43752, + serialized_start=43924, + serialized_end=45137, ) @@ -11949,8 +12290,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=44247, - serialized_end=44316, + serialized_start=45632, + serialized_end=45701, ) _GETCONTESTEDRESOURCESREQUEST_GETCONTESTEDRESOURCESREQUESTV0 = _descriptor.Descriptor( @@ -12046,8 +12387,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=43890, - serialized_end=44350, + serialized_start=45275, + serialized_end=45735, ) _GETCONTESTEDRESOURCESREQUEST = _descriptor.Descriptor( @@ -12082,8 +12423,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=43755, - serialized_end=44361, + serialized_start=45140, + serialized_end=45746, ) @@ -12114,8 +12455,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=44803, - serialized_end=44863, + serialized_start=46188, + serialized_end=46248, ) _GETCONTESTEDRESOURCESRESPONSE_GETCONTESTEDRESOURCESRESPONSEV0 = _descriptor.Descriptor( @@ -12164,8 +12505,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=44502, - serialized_end=44873, + serialized_start=45887, + serialized_end=46258, ) _GETCONTESTEDRESOURCESRESPONSE = _descriptor.Descriptor( @@ -12200,8 +12541,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=44364, - serialized_end=44884, + serialized_start=45749, + serialized_end=46269, ) @@ -12239,8 +12580,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=45397, - serialized_end=45470, + serialized_start=46782, + serialized_end=46855, ) _GETVOTEPOLLSBYENDDATEREQUEST_GETVOTEPOLLSBYENDDATEREQUESTV0_ENDATTIMEINFO = _descriptor.Descriptor( @@ -12277,8 +12618,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=45472, - serialized_end=45539, + serialized_start=46857, + serialized_end=46924, ) _GETVOTEPOLLSBYENDDATEREQUEST_GETVOTEPOLLSBYENDDATEREQUESTV0 = _descriptor.Descriptor( @@ -12363,8 +12704,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=45022, - serialized_end=45598, + serialized_start=46407, + serialized_end=46983, ) _GETVOTEPOLLSBYENDDATEREQUEST = _descriptor.Descriptor( @@ -12399,8 +12740,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=44887, - serialized_end=45609, + serialized_start=46272, + serialized_end=46994, ) @@ -12438,8 +12779,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=46058, - serialized_end=46144, + serialized_start=47443, + serialized_end=47529, ) _GETVOTEPOLLSBYENDDATERESPONSE_GETVOTEPOLLSBYENDDATERESPONSEV0_SERIALIZEDVOTEPOLLSBYTIMESTAMPS = _descriptor.Descriptor( @@ -12476,8 +12817,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=46147, - serialized_end=46362, + serialized_start=47532, + serialized_end=47747, ) _GETVOTEPOLLSBYENDDATERESPONSE_GETVOTEPOLLSBYENDDATERESPONSEV0 = _descriptor.Descriptor( @@ -12526,8 +12867,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=45750, - serialized_end=46372, + serialized_start=47135, + serialized_end=47757, ) _GETVOTEPOLLSBYENDDATERESPONSE = _descriptor.Descriptor( @@ -12562,8 +12903,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=45612, - serialized_end=46383, + serialized_start=46997, + serialized_end=47768, ) @@ -12601,8 +12942,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=46520, - serialized_end=46589, + serialized_start=47905, + serialized_end=47974, ) _GETYESNOVOTEPOLLSTATEREQUEST = _descriptor.Descriptor( @@ -12637,8 +12978,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=46386, - serialized_end=46600, + serialized_start=47771, + serialized_end=47985, ) @@ -12690,8 +13031,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=47016, - serialized_end=47113, + serialized_start=48401, + serialized_end=48498, ) _GETYESNOVOTEPOLLSTATERESPONSE_GETYESNOVOTEPOLLSTATERESPONSEV0_FINISHEDYESNOVOTEPOLL = _descriptor.Descriptor( @@ -12763,8 +13104,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=47116, - serialized_end=47536, + serialized_start=48501, + serialized_end=48921, ) _GETYESNOVOTEPOLLSTATERESPONSE_GETYESNOVOTEPOLLSTATERESPONSEV0_YESNOVOTEPOLL_DECISIONPROPOSAL = _descriptor.Descriptor( @@ -12794,8 +13135,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=47945, - serialized_end=47984, + serialized_start=49330, + serialized_end=49369, ) _GETYESNOVOTEPOLLSTATERESPONSE_GETYESNOVOTEPOLLSTATERESPONSEV0_YESNOVOTEPOLL_FRACTIONOFTOTAL = _descriptor.Descriptor( @@ -12839,8 +13180,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=47987, - serialized_end=48187, + serialized_start=49372, + serialized_end=49572, ) _GETYESNOVOTEPOLLSTATERESPONSE_GETYESNOVOTEPOLLSTATERESPONSEV0_YESNOVOTEPOLL = _descriptor.Descriptor( @@ -12909,8 +13250,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=47539, - serialized_end=48300, + serialized_start=48924, + serialized_end=49685, ) _GETYESNOVOTEPOLLSTATERESPONSE_GETYESNOVOTEPOLLSTATERESPONSEV0_YESNOVOTEPOLLSTATE = _descriptor.Descriptor( @@ -12980,8 +13321,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=48303, - serialized_end=48798, + serialized_start=49688, + serialized_end=50183, ) _GETYESNOVOTEPOLLSTATERESPONSE_GETYESNOVOTEPOLLSTATERESPONSEV0 = _descriptor.Descriptor( @@ -13030,8 +13371,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=46741, - serialized_end=48808, + serialized_start=48126, + serialized_end=50193, ) _GETYESNOVOTEPOLLSTATERESPONSE = _descriptor.Descriptor( @@ -13066,8 +13407,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=46603, - serialized_end=48819, + serialized_start=47988, + serialized_end=50204, ) @@ -13112,8 +13453,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=48959, - serialized_end=49050, + serialized_start=50344, + serialized_end=50435, ) _GETMASTERNODEYESNOVOTEREQUEST = _descriptor.Descriptor( @@ -13148,8 +13489,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=48822, - serialized_end=49061, + serialized_start=50207, + serialized_end=50446, ) @@ -13188,8 +13529,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=49491, - serialized_end=49709, + serialized_start=50876, + serialized_end=51094, ) _GETMASTERNODEYESNOVOTERESPONSE_GETMASTERNODEYESNOVOTERESPONSEV0_MASTERNODEYESNOVOTEENTRY = _descriptor.Descriptor( @@ -13219,8 +13560,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=49712, - serialized_end=49864, + serialized_start=51097, + serialized_end=51249, ) _GETMASTERNODEYESNOVOTERESPONSE_GETMASTERNODEYESNOVOTERESPONSEV0 = _descriptor.Descriptor( @@ -13269,8 +13610,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=49205, - serialized_end=49874, + serialized_start=50590, + serialized_end=51259, ) _GETMASTERNODEYESNOVOTERESPONSE = _descriptor.Descriptor( @@ -13305,8 +13646,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=49064, - serialized_end=49885, + serialized_start=50449, + serialized_end=51270, ) @@ -13344,8 +13685,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=50574, - serialized_end=50658, + serialized_start=51959, + serialized_end=52043, ) _GETCONTESTEDRESOURCEVOTESTATEREQUEST_GETCONTESTEDRESOURCEVOTESTATEREQUESTV0 = _descriptor.Descriptor( @@ -13442,8 +13783,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=50047, - serialized_end=50772, + serialized_start=51432, + serialized_end=52157, ) _GETCONTESTEDRESOURCEVOTESTATEREQUEST = _descriptor.Descriptor( @@ -13478,8 +13819,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=49888, - serialized_end=50783, + serialized_start=51273, + serialized_end=52168, ) @@ -13551,8 +13892,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=51283, - serialized_end=51757, + serialized_start=52668, + serialized_end=53142, ) _GETCONTESTEDRESOURCEVOTESTATERESPONSE_GETCONTESTEDRESOURCEVOTESTATERESPONSEV0_CONTESTEDRESOURCECONTENDERS = _descriptor.Descriptor( @@ -13618,8 +13959,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=51760, - serialized_end=52212, + serialized_start=53145, + serialized_end=53597, ) _GETCONTESTEDRESOURCEVOTESTATERESPONSE_GETCONTESTEDRESOURCEVOTESTATERESPONSEV0_CONTENDER = _descriptor.Descriptor( @@ -13673,8 +14014,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=52214, - serialized_end=52321, + serialized_start=53599, + serialized_end=53706, ) _GETCONTESTEDRESOURCEVOTESTATERESPONSE_GETCONTESTEDRESOURCEVOTESTATERESPONSEV0 = _descriptor.Descriptor( @@ -13723,8 +14064,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=50948, - serialized_end=52331, + serialized_start=52333, + serialized_end=53716, ) _GETCONTESTEDRESOURCEVOTESTATERESPONSE = _descriptor.Descriptor( @@ -13759,8 +14100,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=50786, - serialized_end=52342, + serialized_start=52171, + serialized_end=53727, ) @@ -13798,8 +14139,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=50574, - serialized_end=50658, + serialized_start=51959, + serialized_end=52043, ) _GETCONTESTEDRESOURCEVOTERSFORIDENTITYREQUEST_GETCONTESTEDRESOURCEVOTERSFORIDENTITYREQUESTV0 = _descriptor.Descriptor( @@ -13895,8 +14236,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=52529, - serialized_end=53059, + serialized_start=53914, + serialized_end=54444, ) _GETCONTESTEDRESOURCEVOTERSFORIDENTITYREQUEST = _descriptor.Descriptor( @@ -13931,8 +14272,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=52345, - serialized_end=53070, + serialized_start=53730, + serialized_end=54455, ) @@ -13970,8 +14311,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=53610, - serialized_end=53677, + serialized_start=54995, + serialized_end=55062, ) _GETCONTESTEDRESOURCEVOTERSFORIDENTITYRESPONSE_GETCONTESTEDRESOURCEVOTERSFORIDENTITYRESPONSEV0 = _descriptor.Descriptor( @@ -14020,8 +14361,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=53260, - serialized_end=53687, + serialized_start=54645, + serialized_end=55072, ) _GETCONTESTEDRESOURCEVOTERSFORIDENTITYRESPONSE = _descriptor.Descriptor( @@ -14056,8 +14397,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=53073, - serialized_end=53698, + serialized_start=54458, + serialized_end=55083, ) @@ -14095,8 +14436,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=54247, - serialized_end=54344, + serialized_start=55632, + serialized_end=55729, ) _GETCONTESTEDRESOURCEIDENTITYVOTESREQUEST_GETCONTESTEDRESOURCEIDENTITYVOTESREQUESTV0 = _descriptor.Descriptor( @@ -14166,8 +14507,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=53872, - serialized_end=54375, + serialized_start=55257, + serialized_end=55760, ) _GETCONTESTEDRESOURCEIDENTITYVOTESREQUEST = _descriptor.Descriptor( @@ -14202,8 +14543,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=53701, - serialized_end=54386, + serialized_start=55086, + serialized_end=55771, ) @@ -14241,8 +14582,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=54889, - serialized_end=55136, + serialized_start=56274, + serialized_end=56521, ) _GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSE_GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSEV0_RESOURCEVOTECHOICE = _descriptor.Descriptor( @@ -14285,8 +14626,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=55139, - serialized_end=55440, + serialized_start=56524, + serialized_end=56825, ) _GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSE_GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSEV0_CONTESTEDRESOURCEIDENTITYVOTE = _descriptor.Descriptor( @@ -14337,8 +14678,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=55443, - serialized_end=55720, + serialized_start=56828, + serialized_end=57105, ) _GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSE_GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSEV0 = _descriptor.Descriptor( @@ -14387,8 +14728,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=54563, - serialized_end=55730, + serialized_start=55948, + serialized_end=57115, ) _GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSE = _descriptor.Descriptor( @@ -14423,8 +14764,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=54389, - serialized_end=55741, + serialized_start=55774, + serialized_end=57126, ) @@ -14462,8 +14803,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=55905, - serialized_end=55973, + serialized_start=57290, + serialized_end=57358, ) _GETPREFUNDEDSPECIALIZEDBALANCEREQUEST = _descriptor.Descriptor( @@ -14498,8 +14839,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=55744, - serialized_end=55984, + serialized_start=57129, + serialized_end=57369, ) @@ -14549,8 +14890,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=56152, - serialized_end=56341, + serialized_start=57537, + serialized_end=57726, ) _GETPREFUNDEDSPECIALIZEDBALANCERESPONSE = _descriptor.Descriptor( @@ -14585,8 +14926,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=55987, - serialized_end=56352, + serialized_start=57372, + serialized_end=57737, ) @@ -14617,8 +14958,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=56501, - serialized_end=56552, + serialized_start=57886, + serialized_end=57937, ) _GETTOTALCREDITSINPLATFORMREQUEST = _descriptor.Descriptor( @@ -14653,8 +14994,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=56355, - serialized_end=56563, + serialized_start=57740, + serialized_end=57948, ) @@ -14704,8 +15045,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=56716, - serialized_end=56900, + serialized_start=58101, + serialized_end=58285, ) _GETTOTALCREDITSINPLATFORMRESPONSE = _descriptor.Descriptor( @@ -14740,8 +15081,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=56566, - serialized_end=56911, + serialized_start=57951, + serialized_end=58296, ) @@ -14786,8 +15127,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=57030, - serialized_end=57099, + serialized_start=58415, + serialized_end=58484, ) _GETPATHELEMENTSREQUEST = _descriptor.Descriptor( @@ -14822,8 +15163,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=56914, - serialized_end=57110, + serialized_start=58299, + serialized_end=58495, ) @@ -14854,8 +15195,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=57483, - serialized_end=57511, + serialized_start=58868, + serialized_end=58896, ) _GETPATHELEMENTSRESPONSE_GETPATHELEMENTSRESPONSEV0 = _descriptor.Descriptor( @@ -14904,8 +15245,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=57233, - serialized_end=57521, + serialized_start=58618, + serialized_end=58906, ) _GETPATHELEMENTSRESPONSE = _descriptor.Descriptor( @@ -14940,8 +15281,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=57113, - serialized_end=57532, + serialized_start=58498, + serialized_end=58917, ) @@ -14965,8 +15306,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=57633, - serialized_end=57653, + serialized_start=59018, + serialized_end=59038, ) _GETSTATUSREQUEST = _descriptor.Descriptor( @@ -15001,8 +15342,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=57535, - serialized_end=57664, + serialized_start=58920, + serialized_end=59049, ) @@ -15057,8 +15398,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=58541, - serialized_end=58635, + serialized_start=59926, + serialized_end=60020, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_VERSION_PROTOCOL_TENDERDASH = _descriptor.Descriptor( @@ -15095,8 +15436,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=58868, - serialized_end=58908, + serialized_start=60253, + serialized_end=60293, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_VERSION_PROTOCOL_DRIVE = _descriptor.Descriptor( @@ -15140,8 +15481,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=58910, - serialized_end=58970, + serialized_start=60295, + serialized_end=60355, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_VERSION_PROTOCOL = _descriptor.Descriptor( @@ -15178,8 +15519,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=58638, - serialized_end=58970, + serialized_start=60023, + serialized_end=60355, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_VERSION = _descriptor.Descriptor( @@ -15216,8 +15557,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=58328, - serialized_end=58970, + serialized_start=59713, + serialized_end=60355, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_TIME = _descriptor.Descriptor( @@ -15283,8 +15624,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=58972, - serialized_end=59099, + serialized_start=60357, + serialized_end=60484, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_NODE = _descriptor.Descriptor( @@ -15326,8 +15667,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=59101, - serialized_end=59161, + serialized_start=60486, + serialized_end=60546, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_CHAIN = _descriptor.Descriptor( @@ -15418,8 +15759,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=59164, - serialized_end=59471, + serialized_start=60549, + serialized_end=60856, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_NETWORK = _descriptor.Descriptor( @@ -15463,8 +15804,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=59473, - serialized_end=59540, + serialized_start=60858, + serialized_end=60925, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_STATESYNC = _descriptor.Descriptor( @@ -15543,8 +15884,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=59543, - serialized_end=59804, + serialized_start=60928, + serialized_end=61189, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0 = _descriptor.Descriptor( @@ -15609,8 +15950,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=57769, - serialized_end=59804, + serialized_start=59154, + serialized_end=61189, ) _GETSTATUSRESPONSE = _descriptor.Descriptor( @@ -15645,8 +15986,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=57667, - serialized_end=59815, + serialized_start=59052, + serialized_end=61200, ) @@ -15670,8 +16011,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=59952, - serialized_end=59984, + serialized_start=61337, + serialized_end=61369, ) _GETCURRENTQUORUMSINFOREQUEST = _descriptor.Descriptor( @@ -15706,8 +16047,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=59818, - serialized_end=59995, + serialized_start=61203, + serialized_end=61380, ) @@ -15752,8 +16093,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=60135, - serialized_end=60205, + serialized_start=61520, + serialized_end=61590, ) _GETCURRENTQUORUMSINFORESPONSE_VALIDATORSETV0 = _descriptor.Descriptor( @@ -15804,8 +16145,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=60208, - serialized_end=60383, + serialized_start=61593, + serialized_end=61768, ) _GETCURRENTQUORUMSINFORESPONSE_GETCURRENTQUORUMSINFORESPONSEV0 = _descriptor.Descriptor( @@ -15863,8 +16204,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=60386, - serialized_end=60660, + serialized_start=61771, + serialized_end=62045, ) _GETCURRENTQUORUMSINFORESPONSE = _descriptor.Descriptor( @@ -15899,8 +16240,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=59998, - serialized_end=60671, + serialized_start=61383, + serialized_end=62056, ) @@ -15945,8 +16286,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=60817, - serialized_end=60907, + serialized_start=62202, + serialized_end=62292, ) _GETIDENTITYTOKENBALANCESREQUEST = _descriptor.Descriptor( @@ -15981,8 +16322,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=60674, - serialized_end=60918, + serialized_start=62059, + serialized_end=62303, ) @@ -16025,8 +16366,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=61357, - serialized_end=61428, + serialized_start=62742, + serialized_end=62813, ) _GETIDENTITYTOKENBALANCESRESPONSE_GETIDENTITYTOKENBALANCESRESPONSEV0_TOKENBALANCES = _descriptor.Descriptor( @@ -16056,8 +16397,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=61431, - serialized_end=61585, + serialized_start=62816, + serialized_end=62970, ) _GETIDENTITYTOKENBALANCESRESPONSE_GETIDENTITYTOKENBALANCESRESPONSEV0 = _descriptor.Descriptor( @@ -16106,8 +16447,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=61068, - serialized_end=61595, + serialized_start=62453, + serialized_end=62980, ) _GETIDENTITYTOKENBALANCESRESPONSE = _descriptor.Descriptor( @@ -16142,8 +16483,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=60921, - serialized_end=61606, + serialized_start=62306, + serialized_end=62991, ) @@ -16188,8 +16529,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=61758, - serialized_end=61850, + serialized_start=63143, + serialized_end=63235, ) _GETIDENTITIESTOKENBALANCESREQUEST = _descriptor.Descriptor( @@ -16224,8 +16565,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=61609, - serialized_end=61861, + serialized_start=62994, + serialized_end=63246, ) @@ -16268,8 +16609,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=62329, - serialized_end=62411, + serialized_start=63714, + serialized_end=63796, ) _GETIDENTITIESTOKENBALANCESRESPONSE_GETIDENTITIESTOKENBALANCESRESPONSEV0_IDENTITYTOKENBALANCES = _descriptor.Descriptor( @@ -16299,8 +16640,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=62414, - serialized_end=62597, + serialized_start=63799, + serialized_end=63982, ) _GETIDENTITIESTOKENBALANCESRESPONSE_GETIDENTITIESTOKENBALANCESRESPONSEV0 = _descriptor.Descriptor( @@ -16349,8 +16690,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=62017, - serialized_end=62607, + serialized_start=63402, + serialized_end=63992, ) _GETIDENTITIESTOKENBALANCESRESPONSE = _descriptor.Descriptor( @@ -16385,8 +16726,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=61864, - serialized_end=62618, + serialized_start=63249, + serialized_end=64003, ) @@ -16431,8 +16772,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=62755, - serialized_end=62842, + serialized_start=64140, + serialized_end=64227, ) _GETIDENTITYTOKENINFOSREQUEST = _descriptor.Descriptor( @@ -16467,8 +16808,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=62621, - serialized_end=62853, + serialized_start=64006, + serialized_end=64238, ) @@ -16499,8 +16840,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=63267, - serialized_end=63307, + serialized_start=64652, + serialized_end=64692, ) _GETIDENTITYTOKENINFOSRESPONSE_GETIDENTITYTOKENINFOSRESPONSEV0_TOKENINFOENTRY = _descriptor.Descriptor( @@ -16542,8 +16883,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=63310, - serialized_end=63486, + serialized_start=64695, + serialized_end=64871, ) _GETIDENTITYTOKENINFOSRESPONSE_GETIDENTITYTOKENINFOSRESPONSEV0_TOKENINFOS = _descriptor.Descriptor( @@ -16573,8 +16914,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=63489, - serialized_end=63627, + serialized_start=64874, + serialized_end=65012, ) _GETIDENTITYTOKENINFOSRESPONSE_GETIDENTITYTOKENINFOSRESPONSEV0 = _descriptor.Descriptor( @@ -16623,8 +16964,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=62994, - serialized_end=63637, + serialized_start=64379, + serialized_end=65022, ) _GETIDENTITYTOKENINFOSRESPONSE = _descriptor.Descriptor( @@ -16659,8 +17000,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=62856, - serialized_end=63648, + serialized_start=64241, + serialized_end=65033, ) @@ -16705,8 +17046,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=63791, - serialized_end=63880, + serialized_start=65176, + serialized_end=65265, ) _GETIDENTITIESTOKENINFOSREQUEST = _descriptor.Descriptor( @@ -16741,8 +17082,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=63651, - serialized_end=63891, + serialized_start=65036, + serialized_end=65276, ) @@ -16773,8 +17114,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=63267, - serialized_end=63307, + serialized_start=64652, + serialized_end=64692, ) _GETIDENTITIESTOKENINFOSRESPONSE_GETIDENTITIESTOKENINFOSRESPONSEV0_TOKENINFOENTRY = _descriptor.Descriptor( @@ -16816,8 +17157,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=64378, - serialized_end=64561, + serialized_start=65763, + serialized_end=65946, ) _GETIDENTITIESTOKENINFOSRESPONSE_GETIDENTITIESTOKENINFOSRESPONSEV0_IDENTITYTOKENINFOS = _descriptor.Descriptor( @@ -16847,8 +17188,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=64564, - serialized_end=64715, + serialized_start=65949, + serialized_end=66100, ) _GETIDENTITIESTOKENINFOSRESPONSE_GETIDENTITIESTOKENINFOSRESPONSEV0 = _descriptor.Descriptor( @@ -16897,8 +17238,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=64038, - serialized_end=64725, + serialized_start=65423, + serialized_end=66110, ) _GETIDENTITIESTOKENINFOSRESPONSE = _descriptor.Descriptor( @@ -16933,8 +17274,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=63894, - serialized_end=64736, + serialized_start=65279, + serialized_end=66121, ) @@ -16972,8 +17313,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=64858, - serialized_end=64919, + serialized_start=66243, + serialized_end=66304, ) _GETTOKENSTATUSESREQUEST = _descriptor.Descriptor( @@ -17008,8 +17349,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=64739, - serialized_end=64930, + serialized_start=66124, + serialized_end=66315, ) @@ -17052,8 +17393,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=65320, - serialized_end=65388, + serialized_start=66705, + serialized_end=66773, ) _GETTOKENSTATUSESRESPONSE_GETTOKENSTATUSESRESPONSEV0_TOKENSTATUSES = _descriptor.Descriptor( @@ -17083,8 +17424,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=65391, - serialized_end=65527, + serialized_start=66776, + serialized_end=66912, ) _GETTOKENSTATUSESRESPONSE_GETTOKENSTATUSESRESPONSEV0 = _descriptor.Descriptor( @@ -17133,8 +17474,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=65056, - serialized_end=65537, + serialized_start=66441, + serialized_end=66922, ) _GETTOKENSTATUSESRESPONSE = _descriptor.Descriptor( @@ -17169,8 +17510,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=64933, - serialized_end=65548, + serialized_start=66318, + serialized_end=66933, ) @@ -17208,8 +17549,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=65706, - serialized_end=65779, + serialized_start=67091, + serialized_end=67164, ) _GETTOKENDIRECTPURCHASEPRICESREQUEST = _descriptor.Descriptor( @@ -17244,8 +17585,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=65551, - serialized_end=65790, + serialized_start=66936, + serialized_end=67175, ) @@ -17283,8 +17624,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=66280, - serialized_end=66331, + serialized_start=67665, + serialized_end=67716, ) _GETTOKENDIRECTPURCHASEPRICESRESPONSE_GETTOKENDIRECTPURCHASEPRICESRESPONSEV0_PRICINGSCHEDULE = _descriptor.Descriptor( @@ -17314,8 +17655,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=66334, - serialized_end=66501, + serialized_start=67719, + serialized_end=67886, ) _GETTOKENDIRECTPURCHASEPRICESRESPONSE_GETTOKENDIRECTPURCHASEPRICESRESPONSEV0_TOKENDIRECTPURCHASEPRICEENTRY = _descriptor.Descriptor( @@ -17364,8 +17705,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=66504, - serialized_end=66732, + serialized_start=67889, + serialized_end=68117, ) _GETTOKENDIRECTPURCHASEPRICESRESPONSE_GETTOKENDIRECTPURCHASEPRICESRESPONSEV0_TOKENDIRECTPURCHASEPRICES = _descriptor.Descriptor( @@ -17395,8 +17736,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=66735, - serialized_end=66935, + serialized_start=68120, + serialized_end=68320, ) _GETTOKENDIRECTPURCHASEPRICESRESPONSE_GETTOKENDIRECTPURCHASEPRICESRESPONSEV0 = _descriptor.Descriptor( @@ -17445,8 +17786,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=65952, - serialized_end=66945, + serialized_start=67337, + serialized_end=68330, ) _GETTOKENDIRECTPURCHASEPRICESRESPONSE = _descriptor.Descriptor( @@ -17481,8 +17822,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=65793, - serialized_end=66956, + serialized_start=67178, + serialized_end=68341, ) @@ -17520,8 +17861,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=67090, - serialized_end=67154, + serialized_start=68475, + serialized_end=68539, ) _GETTOKENCONTRACTINFOREQUEST = _descriptor.Descriptor( @@ -17556,8 +17897,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=66959, - serialized_end=67165, + serialized_start=68344, + serialized_end=68550, ) @@ -17595,8 +17936,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=67577, - serialized_end=67654, + serialized_start=68962, + serialized_end=69039, ) _GETTOKENCONTRACTINFORESPONSE_GETTOKENCONTRACTINFORESPONSEV0 = _descriptor.Descriptor( @@ -17645,8 +17986,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=67303, - serialized_end=67664, + serialized_start=68688, + serialized_end=69049, ) _GETTOKENCONTRACTINFORESPONSE = _descriptor.Descriptor( @@ -17681,8 +18022,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=67168, - serialized_end=67675, + serialized_start=68553, + serialized_end=69060, ) @@ -17737,8 +18078,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=68108, - serialized_end=68262, + serialized_start=69493, + serialized_end=69647, ) _GETTOKENPREPROGRAMMEDDISTRIBUTIONSREQUEST_GETTOKENPREPROGRAMMEDDISTRIBUTIONSREQUESTV0 = _descriptor.Descriptor( @@ -17799,8 +18140,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=67852, - serialized_end=68290, + serialized_start=69237, + serialized_end=69675, ) _GETTOKENPREPROGRAMMEDDISTRIBUTIONSREQUEST = _descriptor.Descriptor( @@ -17835,8 +18176,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=67678, - serialized_end=68301, + serialized_start=69063, + serialized_end=69686, ) @@ -17874,8 +18215,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=68812, - serialized_end=68874, + serialized_start=70197, + serialized_end=70259, ) _GETTOKENPREPROGRAMMEDDISTRIBUTIONSRESPONSE_GETTOKENPREPROGRAMMEDDISTRIBUTIONSRESPONSEV0_TOKENTIMEDDISTRIBUTIONENTRY = _descriptor.Descriptor( @@ -17912,8 +18253,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=68877, - serialized_end=69089, + serialized_start=70262, + serialized_end=70474, ) _GETTOKENPREPROGRAMMEDDISTRIBUTIONSRESPONSE_GETTOKENPREPROGRAMMEDDISTRIBUTIONSRESPONSEV0_TOKENDISTRIBUTIONS = _descriptor.Descriptor( @@ -17943,8 +18284,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=69092, - serialized_end=69287, + serialized_start=70477, + serialized_end=70672, ) _GETTOKENPREPROGRAMMEDDISTRIBUTIONSRESPONSE_GETTOKENPREPROGRAMMEDDISTRIBUTIONSRESPONSEV0 = _descriptor.Descriptor( @@ -17993,8 +18334,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=68482, - serialized_end=69297, + serialized_start=69867, + serialized_end=70682, ) _GETTOKENPREPROGRAMMEDDISTRIBUTIONSRESPONSE = _descriptor.Descriptor( @@ -18029,8 +18370,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=68304, - serialized_end=69308, + serialized_start=69689, + serialized_end=70693, ) @@ -18068,8 +18409,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=69497, - serialized_end=69570, + serialized_start=70882, + serialized_end=70955, ) _GETTOKENPERPETUALDISTRIBUTIONLASTCLAIMREQUEST_GETTOKENPERPETUALDISTRIBUTIONLASTCLAIMREQUESTV0 = _descriptor.Descriptor( @@ -18125,8 +18466,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=69573, - serialized_end=69814, + serialized_start=70958, + serialized_end=71199, ) _GETTOKENPERPETUALDISTRIBUTIONLASTCLAIMREQUEST = _descriptor.Descriptor( @@ -18161,8 +18502,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=69311, - serialized_end=69825, + serialized_start=70696, + serialized_end=71210, ) @@ -18219,8 +18560,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=70346, - serialized_end=70466, + serialized_start=71731, + serialized_end=71851, ) _GETTOKENPERPETUALDISTRIBUTIONLASTCLAIMRESPONSE_GETTOKENPERPETUALDISTRIBUTIONLASTCLAIMRESPONSEV0 = _descriptor.Descriptor( @@ -18269,8 +18610,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=70018, - serialized_end=70476, + serialized_start=71403, + serialized_end=71861, ) _GETTOKENPERPETUALDISTRIBUTIONLASTCLAIMRESPONSE = _descriptor.Descriptor( @@ -18305,8 +18646,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=69828, - serialized_end=70487, + serialized_start=71213, + serialized_end=71872, ) @@ -18344,8 +18685,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=70618, - serialized_end=70681, + serialized_start=72003, + serialized_end=72066, ) _GETTOKENTOTALSUPPLYREQUEST = _descriptor.Descriptor( @@ -18380,8 +18721,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=70490, - serialized_end=70692, + serialized_start=71875, + serialized_end=72077, ) @@ -18426,8 +18767,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=71113, - serialized_end=71233, + serialized_start=72498, + serialized_end=72618, ) _GETTOKENTOTALSUPPLYRESPONSE_GETTOKENTOTALSUPPLYRESPONSEV0 = _descriptor.Descriptor( @@ -18476,8 +18817,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=70827, - serialized_end=71243, + serialized_start=72212, + serialized_end=72628, ) _GETTOKENTOTALSUPPLYRESPONSE = _descriptor.Descriptor( @@ -18512,8 +18853,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=70695, - serialized_end=71254, + serialized_start=72080, + serialized_end=72639, ) @@ -18558,8 +18899,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=71364, - serialized_end=71456, + serialized_start=72749, + serialized_end=72841, ) _GETGROUPINFOREQUEST = _descriptor.Descriptor( @@ -18594,8 +18935,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=71257, - serialized_end=71467, + serialized_start=72642, + serialized_end=72852, ) @@ -18633,8 +18974,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=71825, - serialized_end=71877, + serialized_start=73210, + serialized_end=73262, ) _GETGROUPINFORESPONSE_GETGROUPINFORESPONSEV0_GROUPINFOENTRY = _descriptor.Descriptor( @@ -18671,8 +19012,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=71880, - serialized_end=72032, + serialized_start=73265, + serialized_end=73417, ) _GETGROUPINFORESPONSE_GETGROUPINFORESPONSEV0_GROUPINFO = _descriptor.Descriptor( @@ -18707,8 +19048,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=72035, - serialized_end=72173, + serialized_start=73420, + serialized_end=73558, ) _GETGROUPINFORESPONSE_GETGROUPINFORESPONSEV0 = _descriptor.Descriptor( @@ -18757,8 +19098,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=71581, - serialized_end=72183, + serialized_start=72966, + serialized_end=73568, ) _GETGROUPINFORESPONSE = _descriptor.Descriptor( @@ -18793,8 +19134,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=71470, - serialized_end=72194, + serialized_start=72855, + serialized_end=73579, ) @@ -18832,8 +19173,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=72307, - serialized_end=72424, + serialized_start=73692, + serialized_end=73809, ) _GETGROUPINFOSREQUEST_GETGROUPINFOSREQUESTV0 = _descriptor.Descriptor( @@ -18894,8 +19235,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=72427, - serialized_end=72679, + serialized_start=73812, + serialized_end=74064, ) _GETGROUPINFOSREQUEST = _descriptor.Descriptor( @@ -18930,8 +19271,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=72197, - serialized_end=72690, + serialized_start=73582, + serialized_end=74075, ) @@ -18969,8 +19310,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=71825, - serialized_end=71877, + serialized_start=73210, + serialized_end=73262, ) _GETGROUPINFOSRESPONSE_GETGROUPINFOSRESPONSEV0_GROUPPOSITIONINFOENTRY = _descriptor.Descriptor( @@ -19014,8 +19355,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=73111, - serialized_end=73306, + serialized_start=74496, + serialized_end=74691, ) _GETGROUPINFOSRESPONSE_GETGROUPINFOSRESPONSEV0_GROUPINFOS = _descriptor.Descriptor( @@ -19045,8 +19386,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=73309, - serialized_end=73439, + serialized_start=74694, + serialized_end=74824, ) _GETGROUPINFOSRESPONSE_GETGROUPINFOSRESPONSEV0 = _descriptor.Descriptor( @@ -19095,8 +19436,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=72807, - serialized_end=73449, + serialized_start=74192, + serialized_end=74834, ) _GETGROUPINFOSRESPONSE = _descriptor.Descriptor( @@ -19131,8 +19472,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=72693, - serialized_end=73460, + serialized_start=74078, + serialized_end=74845, ) @@ -19246,8 +19587,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=73658, - serialized_end=73986, + serialized_start=75043, + serialized_end=75371, ) _GETGROUPACTIONSREQUEST = _descriptor.Descriptor( @@ -19283,8 +19624,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=73463, - serialized_end=74037, + serialized_start=74848, + serialized_end=75422, ) @@ -19334,8 +19675,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=74419, - serialized_end=74510, + serialized_start=75804, + serialized_end=75895, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_BURNEVENT = _descriptor.Descriptor( @@ -19384,8 +19725,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=74512, - serialized_end=74603, + serialized_start=75897, + serialized_end=75988, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_FREEZEEVENT = _descriptor.Descriptor( @@ -19427,8 +19768,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=74605, - serialized_end=74679, + serialized_start=75990, + serialized_end=76064, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_UNFREEZEEVENT = _descriptor.Descriptor( @@ -19470,8 +19811,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=74681, - serialized_end=74757, + serialized_start=76066, + serialized_end=76142, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_DESTROYFROZENFUNDSEVENT = _descriptor.Descriptor( @@ -19520,8 +19861,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=74759, - serialized_end=74861, + serialized_start=76144, + serialized_end=76246, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_SHAREDENCRYPTEDNOTE = _descriptor.Descriptor( @@ -19565,8 +19906,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=74863, - serialized_end=74963, + serialized_start=76248, + serialized_end=76348, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_PERSONALENCRYPTEDNOTE = _descriptor.Descriptor( @@ -19610,8 +19951,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=74965, - serialized_end=75088, + serialized_start=76350, + serialized_end=76473, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_EMERGENCYACTIONEVENT = _descriptor.Descriptor( @@ -19654,8 +19995,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=75091, - serialized_end=75324, + serialized_start=76476, + serialized_end=76709, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_TOKENCONFIGUPDATEEVENT = _descriptor.Descriptor( @@ -19697,8 +20038,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=75326, - serialized_end=75426, + serialized_start=76711, + serialized_end=76811, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_UPDATEDIRECTPURCHASEPRICEEVENT_PRICEFORQUANTITY = _descriptor.Descriptor( @@ -19735,8 +20076,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=66280, - serialized_end=66331, + serialized_start=67665, + serialized_end=67716, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_UPDATEDIRECTPURCHASEPRICEEVENT_PRICINGSCHEDULE = _descriptor.Descriptor( @@ -19766,8 +20107,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=75718, - serialized_end=75890, + serialized_start=77103, + serialized_end=77275, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_UPDATEDIRECTPURCHASEPRICEEVENT = _descriptor.Descriptor( @@ -19821,8 +20162,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=75429, - serialized_end=75915, + serialized_start=76814, + serialized_end=77300, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_MINTTOPOOLEVENT = _descriptor.Descriptor( @@ -19871,8 +20212,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=75917, - serialized_end=76016, + serialized_start=77302, + serialized_end=77401, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_BURNFROMPOOLEVENT = _descriptor.Descriptor( @@ -19921,8 +20262,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=76018, - serialized_end=76119, + serialized_start=77403, + serialized_end=77504, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_GROUPACTIONEVENT = _descriptor.Descriptor( @@ -19971,8 +20312,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=76122, - serialized_end=76502, + serialized_start=77507, + serialized_end=77887, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_DOCUMENTEVENT = _descriptor.Descriptor( @@ -20007,8 +20348,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=76505, - serialized_end=76644, + serialized_start=77890, + serialized_end=78029, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_DOCUMENTCREATEEVENT = _descriptor.Descriptor( @@ -20038,8 +20379,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=76646, - serialized_end=76693, + serialized_start=78031, + serialized_end=78078, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_CONTRACTUPDATEEVENT = _descriptor.Descriptor( @@ -20069,8 +20410,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=76695, - serialized_end=76742, + serialized_start=78080, + serialized_end=78127, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_CONTRACTEVENT = _descriptor.Descriptor( @@ -20105,8 +20446,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=76745, - serialized_end=76884, + serialized_start=78130, + serialized_end=78269, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_TOKENEVENT = _descriptor.Descriptor( @@ -20204,8 +20545,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=76887, - serialized_end=78104, + serialized_start=78272, + serialized_end=79489, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_GROUPACTIONENTRY = _descriptor.Descriptor( @@ -20242,8 +20583,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=78107, - serialized_end=78254, + serialized_start=79492, + serialized_end=79639, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_GROUPACTIONS = _descriptor.Descriptor( @@ -20273,8 +20614,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=78257, - serialized_end=78389, + serialized_start=79642, + serialized_end=79774, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0 = _descriptor.Descriptor( @@ -20323,8 +20664,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=74160, - serialized_end=78399, + serialized_start=75545, + serialized_end=79784, ) _GETGROUPACTIONSRESPONSE = _descriptor.Descriptor( @@ -20359,8 +20700,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=74040, - serialized_end=78410, + serialized_start=75425, + serialized_end=79795, ) @@ -20419,8 +20760,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=78548, - serialized_end=78754, + serialized_start=79933, + serialized_end=80139, ) _GETGROUPACTIONSIGNERSREQUEST = _descriptor.Descriptor( @@ -20456,8 +20797,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=78413, - serialized_end=78805, + serialized_start=79798, + serialized_end=80190, ) @@ -20495,8 +20836,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=79237, - serialized_end=79290, + serialized_start=80622, + serialized_end=80675, ) _GETGROUPACTIONSIGNERSRESPONSE_GETGROUPACTIONSIGNERSRESPONSEV0_GROUPACTIONSIGNERS = _descriptor.Descriptor( @@ -20526,8 +20867,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=79293, - serialized_end=79438, + serialized_start=80678, + serialized_end=80823, ) _GETGROUPACTIONSIGNERSRESPONSE_GETGROUPACTIONSIGNERSRESPONSEV0 = _descriptor.Descriptor( @@ -20576,8 +20917,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=78946, - serialized_end=79448, + serialized_start=80331, + serialized_end=80833, ) _GETGROUPACTIONSIGNERSRESPONSE = _descriptor.Descriptor( @@ -20612,8 +20953,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=78808, - serialized_end=79459, + serialized_start=80193, + serialized_end=80844, ) @@ -20651,8 +20992,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=79575, - serialized_end=79632, + serialized_start=80960, + serialized_end=81017, ) _GETADDRESSINFOREQUEST = _descriptor.Descriptor( @@ -20687,8 +21028,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=79462, - serialized_end=79643, + serialized_start=80847, + serialized_end=81028, ) @@ -20731,8 +21072,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=79646, - serialized_end=79779, + serialized_start=81031, + serialized_end=81164, ) @@ -20770,8 +21111,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=79781, - serialized_end=79830, + serialized_start=81166, + serialized_end=81215, ) @@ -20802,8 +21143,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=79832, - serialized_end=79927, + serialized_start=81217, + serialized_end=81312, ) @@ -20853,8 +21194,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=79929, - serialized_end=80038, + serialized_start=81314, + serialized_end=81423, ) @@ -20892,8 +21233,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=80040, - serialized_end=80160, + serialized_start=81425, + serialized_end=81545, ) @@ -20924,8 +21265,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=80162, - serialized_end=80269, + serialized_start=81547, + serialized_end=81654, ) @@ -20975,8 +21316,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=80389, - serialized_end=80614, + serialized_start=81774, + serialized_end=81999, ) _GETADDRESSINFORESPONSE = _descriptor.Descriptor( @@ -21011,8 +21352,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=80272, - serialized_end=80625, + serialized_start=81657, + serialized_end=82010, ) @@ -21050,8 +21391,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=80750, - serialized_end=80812, + serialized_start=82135, + serialized_end=82197, ) _GETADDRESSESINFOSREQUEST = _descriptor.Descriptor( @@ -21086,8 +21427,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=80628, - serialized_end=80823, + serialized_start=82013, + serialized_end=82208, ) @@ -21137,8 +21478,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=80952, - serialized_end=81184, + serialized_start=82337, + serialized_end=82569, ) _GETADDRESSESINFOSRESPONSE = _descriptor.Descriptor( @@ -21173,8 +21514,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=80826, - serialized_end=81195, + serialized_start=82211, + serialized_end=82580, ) @@ -21198,8 +21539,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=81335, - serialized_end=81368, + serialized_start=82720, + serialized_end=82753, ) _GETADDRESSESTRUNKSTATEREQUEST = _descriptor.Descriptor( @@ -21234,8 +21575,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=81198, - serialized_end=81379, + serialized_start=82583, + serialized_end=82764, ) @@ -21273,8 +21614,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=81523, - serialized_end=81669, + serialized_start=82908, + serialized_end=83054, ) _GETADDRESSESTRUNKSTATERESPONSE = _descriptor.Descriptor( @@ -21309,8 +21650,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=81382, - serialized_end=81680, + serialized_start=82767, + serialized_end=83065, ) @@ -21355,8 +21696,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=81823, - serialized_end=81912, + serialized_start=83208, + serialized_end=83297, ) _GETADDRESSESBRANCHSTATEREQUEST = _descriptor.Descriptor( @@ -21391,8 +21732,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=81683, - serialized_end=81923, + serialized_start=83068, + serialized_end=83308, ) @@ -21423,8 +21764,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=82069, - serialized_end=82124, + serialized_start=83454, + serialized_end=83509, ) _GETADDRESSESBRANCHSTATERESPONSE = _descriptor.Descriptor( @@ -21459,8 +21800,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=81926, - serialized_end=82135, + serialized_start=83311, + serialized_end=83520, ) @@ -21505,8 +21846,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=82299, - serialized_end=82413, + serialized_start=83684, + serialized_end=83798, ) _GETRECENTADDRESSBALANCECHANGESREQUEST = _descriptor.Descriptor( @@ -21541,8 +21882,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=82138, - serialized_end=82424, + serialized_start=83523, + serialized_end=83809, ) @@ -21592,8 +21933,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=82592, - serialized_end=82856, + serialized_start=83977, + serialized_end=84241, ) _GETRECENTADDRESSBALANCECHANGESRESPONSE = _descriptor.Descriptor( @@ -21628,8 +21969,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=82427, - serialized_end=82867, + serialized_start=83812, + serialized_end=84252, ) @@ -21667,8 +22008,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=82869, - serialized_end=82940, + serialized_start=84254, + serialized_end=84325, ) @@ -21718,8 +22059,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=82943, - serialized_end=83119, + serialized_start=84328, + serialized_end=84504, ) @@ -21750,8 +22091,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=83121, - serialized_end=83213, + serialized_start=84506, + serialized_end=84598, ) @@ -21796,8 +22137,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=83216, - serialized_end=83390, + serialized_start=84601, + serialized_end=84775, ) @@ -21828,8 +22169,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=83393, - serialized_end=83528, + serialized_start=84778, + serialized_end=84913, ) @@ -21867,8 +22208,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=83720, - serialized_end=83817, + serialized_start=85105, + serialized_end=85202, ) _GETRECENTCOMPACTEDADDRESSBALANCECHANGESREQUEST = _descriptor.Descriptor( @@ -21903,8 +22244,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=83531, - serialized_end=83828, + serialized_start=84916, + serialized_end=85213, ) @@ -21954,8 +22295,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=84024, - serialized_end=84316, + serialized_start=85409, + serialized_end=85701, ) _GETRECENTCOMPACTEDADDRESSBALANCECHANGESRESPONSE = _descriptor.Descriptor( @@ -21990,8 +22331,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=83831, - serialized_end=84327, + serialized_start=85216, + serialized_end=85712, ) @@ -22048,8 +22389,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=84476, - serialized_end=84599, + serialized_start=85861, + serialized_end=85984, ) _GETSHIELDEDENCRYPTEDNOTESREQUEST = _descriptor.Descriptor( @@ -22084,8 +22425,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=84330, - serialized_end=84610, + serialized_start=85715, + serialized_end=85995, ) @@ -22137,8 +22478,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=85057, - serialized_end=85144, + serialized_start=86442, + serialized_end=86529, ) _GETSHIELDEDENCRYPTEDNOTESRESPONSE_GETSHIELDEDENCRYPTEDNOTESRESPONSEV0_ENCRYPTEDNOTES = _descriptor.Descriptor( @@ -22168,8 +22509,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=85147, - serialized_end=85292, + serialized_start=86532, + serialized_end=86677, ) _GETSHIELDEDENCRYPTEDNOTESRESPONSE_GETSHIELDEDENCRYPTEDNOTESRESPONSEV0 = _descriptor.Descriptor( @@ -22218,8 +22559,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=84763, - serialized_end=85302, + serialized_start=86148, + serialized_end=86687, ) _GETSHIELDEDENCRYPTEDNOTESRESPONSE = _descriptor.Descriptor( @@ -22254,8 +22595,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=84613, - serialized_end=85313, + serialized_start=85998, + serialized_end=86698, ) @@ -22298,8 +22639,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=85441, - serialized_end=85521, + serialized_start=86826, + serialized_end=86906, ) _GETSHIELDEDANCHORSREQUEST = _descriptor.Descriptor( @@ -22334,8 +22675,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=85316, - serialized_end=85532, + serialized_start=86701, + serialized_end=86917, ) @@ -22366,8 +22707,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=85921, - serialized_end=85947, + serialized_start=87306, + serialized_end=87332, ) _GETSHIELDEDANCHORSRESPONSE_GETSHIELDEDANCHORSRESPONSEV0 = _descriptor.Descriptor( @@ -22416,8 +22757,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=85664, - serialized_end=85957, + serialized_start=87049, + serialized_end=87342, ) _GETSHIELDEDANCHORSRESPONSE = _descriptor.Descriptor( @@ -22452,8 +22793,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=85535, - serialized_end=85968, + serialized_start=86920, + serialized_end=87353, ) @@ -22496,8 +22837,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=86123, - serialized_end=86212, + serialized_start=87508, + serialized_end=87597, ) _GETMOSTRECENTSHIELDEDANCHORREQUEST = _descriptor.Descriptor( @@ -22532,8 +22873,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=85971, - serialized_end=86223, + serialized_start=87356, + serialized_end=87608, ) @@ -22583,8 +22924,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=86382, - serialized_end=86563, + serialized_start=87767, + serialized_end=87948, ) _GETMOSTRECENTSHIELDEDANCHORRESPONSE = _descriptor.Descriptor( @@ -22619,8 +22960,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=86226, - serialized_end=86574, + serialized_start=87611, + serialized_end=87959, ) @@ -22663,8 +23004,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=86708, - serialized_end=86790, + serialized_start=88093, + serialized_end=88175, ) _GETSHIELDEDPOOLSTATEREQUEST = _descriptor.Descriptor( @@ -22699,8 +23040,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=86577, - serialized_end=86801, + serialized_start=87962, + serialized_end=88186, ) @@ -22750,8 +23091,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=86939, - serialized_end=87124, + serialized_start=88324, + serialized_end=88509, ) _GETSHIELDEDPOOLSTATERESPONSE = _descriptor.Descriptor( @@ -22786,8 +23127,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=86804, - serialized_end=87135, + serialized_start=88189, + serialized_end=88520, ) @@ -22830,8 +23171,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=87272, - serialized_end=87355, + serialized_start=88657, + serialized_end=88740, ) _GETSHIELDEDNOTESCOUNTREQUEST = _descriptor.Descriptor( @@ -22866,8 +23207,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=87138, - serialized_end=87366, + serialized_start=88523, + serialized_end=88751, ) @@ -22917,8 +23258,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=87507, - serialized_end=87697, + serialized_start=88892, + serialized_end=89082, ) _GETSHIELDEDNOTESCOUNTRESPONSE = _descriptor.Descriptor( @@ -22953,8 +23294,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=87369, - serialized_end=87708, + serialized_start=88754, + serialized_end=89093, ) @@ -23004,8 +23345,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=87845, - serialized_end=87948, + serialized_start=89230, + serialized_end=89333, ) _GETSHIELDEDNULLIFIERSREQUEST = _descriptor.Descriptor( @@ -23040,8 +23381,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=87711, - serialized_end=87959, + serialized_start=89096, + serialized_end=89344, ) @@ -23079,8 +23420,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=88388, - serialized_end=88442, + serialized_start=89773, + serialized_end=89827, ) _GETSHIELDEDNULLIFIERSRESPONSE_GETSHIELDEDNULLIFIERSRESPONSEV0_NULLIFIERSTATUSES = _descriptor.Descriptor( @@ -23110,8 +23451,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=88445, - serialized_end=88587, + serialized_start=89830, + serialized_end=89972, ) _GETSHIELDEDNULLIFIERSRESPONSE_GETSHIELDEDNULLIFIERSRESPONSEV0 = _descriptor.Descriptor( @@ -23160,8 +23501,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=88100, - serialized_end=88597, + serialized_start=89485, + serialized_end=89982, ) _GETSHIELDEDNULLIFIERSRESPONSE = _descriptor.Descriptor( @@ -23196,8 +23537,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=87962, - serialized_end=88608, + serialized_start=89347, + serialized_end=89993, ) @@ -23249,8 +23590,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=88758, - serialized_end=88904, + serialized_start=90143, + serialized_end=90289, ) _GETPRIVATEDOCUMENTENTRIESREQUEST = _descriptor.Descriptor( @@ -23285,8 +23626,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=88611, - serialized_end=88915, + serialized_start=89996, + serialized_end=90300, ) @@ -23338,8 +23679,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=89362, - serialized_end=89473, + serialized_start=90747, + serialized_end=90858, ) _GETPRIVATEDOCUMENTENTRIESRESPONSE_GETPRIVATEDOCUMENTENTRIESRESPONSEV0_PRIVATEDOCUMENTENTRIES = _descriptor.Descriptor( @@ -23376,8 +23717,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=89476, - serialized_end=89662, + serialized_start=90861, + serialized_end=91047, ) _GETPRIVATEDOCUMENTENTRIESRESPONSE_GETPRIVATEDOCUMENTENTRIESRESPONSEV0 = _descriptor.Descriptor( @@ -23426,8 +23767,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=89068, - serialized_end=89672, + serialized_start=90453, + serialized_end=91057, ) _GETPRIVATEDOCUMENTENTRIESRESPONSE = _descriptor.Descriptor( @@ -23462,8 +23803,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=88918, - serialized_end=89683, + serialized_start=90303, + serialized_end=91068, ) _GETIDENTITYREQUEST_GETIDENTITYREQUESTV0.containing_type = _GETIDENTITYREQUEST @@ -24420,10 +24761,30 @@ _GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV0.fields_by_name['limit'].message_type = google_dot_protobuf_dot_wrappers__pb2._UINT32VALUE _GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV0.fields_by_name['offset'].message_type = google_dot_protobuf_dot_wrappers__pb2._UINT32VALUE _GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV0.containing_type = _GETDOCUMENTHISTORYREQUEST +_GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV1_CURSOR.containing_type = _GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV1 +_GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV1.fields_by_name['limit'].message_type = google_dot_protobuf_dot_wrappers__pb2._UINT32VALUE +_GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV1.fields_by_name['start_after'].message_type = _GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV1_CURSOR +_GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV1.containing_type = _GETDOCUMENTHISTORYREQUEST +_GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV1.oneofs_by_name['filter'].fields.append( + _GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV1.fields_by_name['start_at_ms']) +_GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV1.fields_by_name['start_at_ms'].containing_oneof = _GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV1.oneofs_by_name['filter'] +_GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV1.oneofs_by_name['filter'].fields.append( + _GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV1.fields_by_name['start_after']) +_GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV1.fields_by_name['start_after'].containing_oneof = _GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV1.oneofs_by_name['filter'] +_GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV1.oneofs_by_name['filter'].fields.append( + _GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV1.fields_by_name['start_at_revision']) +_GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV1.fields_by_name['start_at_revision'].containing_oneof = _GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV1.oneofs_by_name['filter'] +_GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV1.oneofs_by_name['filter'].fields.append( + _GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV1.fields_by_name['revision']) +_GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV1.fields_by_name['revision'].containing_oneof = _GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV1.oneofs_by_name['filter'] _GETDOCUMENTHISTORYREQUEST.fields_by_name['v0'].message_type = _GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV0 +_GETDOCUMENTHISTORYREQUEST.fields_by_name['v1'].message_type = _GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV1 _GETDOCUMENTHISTORYREQUEST.oneofs_by_name['version'].fields.append( _GETDOCUMENTHISTORYREQUEST.fields_by_name['v0']) _GETDOCUMENTHISTORYREQUEST.fields_by_name['v0'].containing_oneof = _GETDOCUMENTHISTORYREQUEST.oneofs_by_name['version'] +_GETDOCUMENTHISTORYREQUEST.oneofs_by_name['version'].fields.append( + _GETDOCUMENTHISTORYREQUEST.fields_by_name['v1']) +_GETDOCUMENTHISTORYREQUEST.fields_by_name['v1'].containing_oneof = _GETDOCUMENTHISTORYREQUEST.oneofs_by_name['version'] _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV0_DOCUMENTHISTORYENTRY.containing_type = _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV0 _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV0_DOCUMENTHISTORY.fields_by_name['document_entries'].message_type = _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV0_DOCUMENTHISTORYENTRY _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV0_DOCUMENTHISTORY.containing_type = _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV0 @@ -24437,10 +24798,31 @@ _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV0.oneofs_by_name['result'].fields.append( _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV0.fields_by_name['proof']) _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV0.fields_by_name['proof'].containing_oneof = _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV0.oneofs_by_name['result'] +_GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1_ENTRY.containing_type = _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1 +_GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1_LIFECYCLE.fields_by_name['state'].enum_type = _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1_LIFECYCLE_STATE +_GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1_LIFECYCLE.containing_type = _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1 +_GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1_LIFECYCLE_STATE.containing_type = _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1_LIFECYCLE +_GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1_HISTORY.fields_by_name['entries'].message_type = _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1_ENTRY +_GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1_HISTORY.fields_by_name['lifecycle'].message_type = _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1_LIFECYCLE +_GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1_HISTORY.containing_type = _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1 +_GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1.fields_by_name['history'].message_type = _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1_HISTORY +_GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1.fields_by_name['proof'].message_type = _PROOF +_GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1.fields_by_name['metadata'].message_type = _RESPONSEMETADATA +_GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1.containing_type = _GETDOCUMENTHISTORYRESPONSE +_GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1.oneofs_by_name['result'].fields.append( + _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1.fields_by_name['history']) +_GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1.fields_by_name['history'].containing_oneof = _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1.oneofs_by_name['result'] +_GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1.oneofs_by_name['result'].fields.append( + _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1.fields_by_name['proof']) +_GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1.fields_by_name['proof'].containing_oneof = _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1.oneofs_by_name['result'] _GETDOCUMENTHISTORYRESPONSE.fields_by_name['v0'].message_type = _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV0 +_GETDOCUMENTHISTORYRESPONSE.fields_by_name['v1'].message_type = _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1 _GETDOCUMENTHISTORYRESPONSE.oneofs_by_name['version'].fields.append( _GETDOCUMENTHISTORYRESPONSE.fields_by_name['v0']) _GETDOCUMENTHISTORYRESPONSE.fields_by_name['v0'].containing_oneof = _GETDOCUMENTHISTORYRESPONSE.oneofs_by_name['version'] +_GETDOCUMENTHISTORYRESPONSE.oneofs_by_name['version'].fields.append( + _GETDOCUMENTHISTORYRESPONSE.fields_by_name['v1']) +_GETDOCUMENTHISTORYRESPONSE.fields_by_name['v1'].containing_oneof = _GETDOCUMENTHISTORYRESPONSE.oneofs_by_name['version'] _GETIDENTITYBYPUBLICKEYHASHREQUEST_GETIDENTITYBYPUBLICKEYHASHREQUESTV0.containing_type = _GETIDENTITYBYPUBLICKEYHASHREQUEST _GETIDENTITYBYPUBLICKEYHASHREQUEST.fields_by_name['v0'].message_type = _GETIDENTITYBYPUBLICKEYHASHREQUEST_GETIDENTITYBYPUBLICKEYHASHREQUESTV0 _GETIDENTITYBYPUBLICKEYHASHREQUEST.oneofs_by_name['version'].fields.append( @@ -27534,12 +27916,28 @@ # @@protoc_insertion_point(class_scope:org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0) }) , + + 'GetDocumentHistoryRequestV1' : _reflection.GeneratedProtocolMessageType('GetDocumentHistoryRequestV1', (_message.Message,), { + + 'Cursor' : _reflection.GeneratedProtocolMessageType('Cursor', (_message.Message,), { + 'DESCRIPTOR' : _GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV1_CURSOR, + '__module__' : 'platform_pb2' + # @@protoc_insertion_point(class_scope:org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor) + }) + , + 'DESCRIPTOR' : _GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV1, + '__module__' : 'platform_pb2' + # @@protoc_insertion_point(class_scope:org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1) + }) + , 'DESCRIPTOR' : _GETDOCUMENTHISTORYREQUEST, '__module__' : 'platform_pb2' # @@protoc_insertion_point(class_scope:org.dash.platform.dapi.v0.GetDocumentHistoryRequest) }) _sym_db.RegisterMessage(GetDocumentHistoryRequest) _sym_db.RegisterMessage(GetDocumentHistoryRequest.GetDocumentHistoryRequestV0) +_sym_db.RegisterMessage(GetDocumentHistoryRequest.GetDocumentHistoryRequestV1) +_sym_db.RegisterMessage(GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor) GetDocumentHistoryResponse = _reflection.GeneratedProtocolMessageType('GetDocumentHistoryResponse', (_message.Message,), { @@ -27563,6 +27961,34 @@ # @@protoc_insertion_point(class_scope:org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0) }) , + + 'GetDocumentHistoryResponseV1' : _reflection.GeneratedProtocolMessageType('GetDocumentHistoryResponseV1', (_message.Message,), { + + 'Entry' : _reflection.GeneratedProtocolMessageType('Entry', (_message.Message,), { + 'DESCRIPTOR' : _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1_ENTRY, + '__module__' : 'platform_pb2' + # @@protoc_insertion_point(class_scope:org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry) + }) + , + + 'Lifecycle' : _reflection.GeneratedProtocolMessageType('Lifecycle', (_message.Message,), { + 'DESCRIPTOR' : _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1_LIFECYCLE, + '__module__' : 'platform_pb2' + # @@protoc_insertion_point(class_scope:org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle) + }) + , + + 'History' : _reflection.GeneratedProtocolMessageType('History', (_message.Message,), { + 'DESCRIPTOR' : _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1_HISTORY, + '__module__' : 'platform_pb2' + # @@protoc_insertion_point(class_scope:org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History) + }) + , + 'DESCRIPTOR' : _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1, + '__module__' : 'platform_pb2' + # @@protoc_insertion_point(class_scope:org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1) + }) + , 'DESCRIPTOR' : _GETDOCUMENTHISTORYRESPONSE, '__module__' : 'platform_pb2' # @@protoc_insertion_point(class_scope:org.dash.platform.dapi.v0.GetDocumentHistoryResponse) @@ -27571,6 +27997,10 @@ _sym_db.RegisterMessage(GetDocumentHistoryResponse.GetDocumentHistoryResponseV0) _sym_db.RegisterMessage(GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry) _sym_db.RegisterMessage(GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory) +_sym_db.RegisterMessage(GetDocumentHistoryResponse.GetDocumentHistoryResponseV1) +_sym_db.RegisterMessage(GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry) +_sym_db.RegisterMessage(GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle) +_sym_db.RegisterMessage(GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History) GetIdentityByPublicKeyHashRequest = _reflection.GeneratedProtocolMessageType('GetIdentityByPublicKeyHashRequest', (_message.Message,), { @@ -30033,7 +30463,15 @@ _GETDOCUMENTSRESPONSE_GETDOCUMENTSRESPONSEV1_RANKEDENTRY.fields_by_name['sum']._options = None _GETDOCUMENTSRESPONSE_GETDOCUMENTSRESPONSEV1_RANKEDENTRIES.fields_by_name['skipped']._options = None _GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV0.fields_by_name['start_at_ms']._options = None +_GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV1_CURSOR.fields_by_name['time_ms']._options = None +_GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV1_CURSOR.fields_by_name['revision']._options = None +_GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV1.fields_by_name['start_at_ms']._options = None +_GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV1.fields_by_name['start_at_revision']._options = None +_GETDOCUMENTHISTORYREQUEST_GETDOCUMENTHISTORYREQUESTV1.fields_by_name['revision']._options = None _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV0_DOCUMENTHISTORYENTRY.fields_by_name['date']._options = None +_GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1_ENTRY.fields_by_name['time_ms']._options = None +_GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1_ENTRY.fields_by_name['revision']._options = None +_GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV1_LIFECYCLE.fields_by_name['remaining_revisions']._options = None _WAITFORSTATETRANSITIONRESULTRESPONSE_SUCCESSWITHOWNERBALANCE.fields_by_name['owner_balance']._options = None _GETEPOCHSINFORESPONSE_GETEPOCHSINFORESPONSEV0_EPOCHINFO.fields_by_name['first_block_height']._options = None _GETEPOCHSINFORESPONSE_GETEPOCHSINFORESPONSEV0_EPOCHINFO.fields_by_name['start_time']._options = None @@ -30093,8 +30531,8 @@ index=0, serialized_options=None, create_key=_descriptor._internal_create_key, - serialized_start=89966, - serialized_end=101207, + serialized_start=91351, + serialized_end=102592, 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 320c763d0f7..3668b9b312b 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 @@ -6566,6 +6566,11 @@ export class GetDocumentHistoryRequest extends jspb.Message { getV0(): GetDocumentHistoryRequest.GetDocumentHistoryRequestV0 | undefined; setV0(value?: GetDocumentHistoryRequest.GetDocumentHistoryRequestV0): void; + hasV1(): boolean; + clearV1(): void; + getV1(): GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 | undefined; + setV1(value?: GetDocumentHistoryRequest.GetDocumentHistoryRequestV1): void; + getVersionCase(): GetDocumentHistoryRequest.VersionCase; serializeBinary(): Uint8Array; toObject(includeInstance?: boolean): GetDocumentHistoryRequest.AsObject; @@ -6580,6 +6585,7 @@ export class GetDocumentHistoryRequest extends jspb.Message { export namespace GetDocumentHistoryRequest { export type AsObject = { v0?: GetDocumentHistoryRequest.GetDocumentHistoryRequestV0.AsObject, + v1?: GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.AsObject, } export class GetDocumentHistoryRequestV0 extends jspb.Message { @@ -6634,9 +6640,109 @@ export namespace GetDocumentHistoryRequest { } } + export class GetDocumentHistoryRequestV1 extends jspb.Message { + getDataContractId(): Uint8Array | string; + getDataContractId_asU8(): Uint8Array; + getDataContractId_asB64(): string; + setDataContractId(value: Uint8Array | string): void; + + getDocumentTypeName(): string; + setDocumentTypeName(value: string): void; + + getDocumentId(): Uint8Array | string; + getDocumentId_asU8(): Uint8Array; + getDocumentId_asB64(): string; + setDocumentId(value: Uint8Array | string): void; + + hasLimit(): boolean; + clearLimit(): void; + getLimit(): google_protobuf_wrappers_pb.UInt32Value | undefined; + setLimit(value?: google_protobuf_wrappers_pb.UInt32Value): void; + + getProve(): boolean; + setProve(value: boolean): void; + + hasStartAtMs(): boolean; + clearStartAtMs(): void; + getStartAtMs(): string; + setStartAtMs(value: string): void; + + hasStartAfter(): boolean; + clearStartAfter(): void; + getStartAfter(): GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor | undefined; + setStartAfter(value?: GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor): void; + + hasStartAtRevision(): boolean; + clearStartAtRevision(): void; + getStartAtRevision(): string; + setStartAtRevision(value: string): void; + + hasRevision(): boolean; + clearRevision(): void; + getRevision(): string; + setRevision(value: string): void; + + getFilterCase(): GetDocumentHistoryRequestV1.FilterCase; + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): GetDocumentHistoryRequestV1.AsObject; + static toObject(includeInstance: boolean, msg: GetDocumentHistoryRequestV1): GetDocumentHistoryRequestV1.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: GetDocumentHistoryRequestV1, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): GetDocumentHistoryRequestV1; + static deserializeBinaryFromReader(message: GetDocumentHistoryRequestV1, reader: jspb.BinaryReader): GetDocumentHistoryRequestV1; + } + + export namespace GetDocumentHistoryRequestV1 { + export type AsObject = { + dataContractId: Uint8Array | string, + documentTypeName: string, + documentId: Uint8Array | string, + limit?: google_protobuf_wrappers_pb.UInt32Value.AsObject, + prove: boolean, + startAtMs: string, + startAfter?: GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.AsObject, + startAtRevision: string, + revision: string, + } + + export class Cursor extends jspb.Message { + getTimeMs(): string; + setTimeMs(value: string): void; + + getRevision(): string; + setRevision(value: string): void; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): Cursor.AsObject; + static toObject(includeInstance: boolean, msg: Cursor): Cursor.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: Cursor, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): Cursor; + static deserializeBinaryFromReader(message: Cursor, reader: jspb.BinaryReader): Cursor; + } + + export namespace Cursor { + export type AsObject = { + timeMs: string, + revision: string, + } + } + + export enum FilterCase { + FILTER_NOT_SET = 0, + START_AT_MS = 6, + START_AFTER = 7, + START_AT_REVISION = 8, + REVISION = 9, + } + } + export enum VersionCase { VERSION_NOT_SET = 0, V0 = 1, + V1 = 2, } } @@ -6646,6 +6752,11 @@ export class GetDocumentHistoryResponse extends jspb.Message { getV0(): GetDocumentHistoryResponse.GetDocumentHistoryResponseV0 | undefined; setV0(value?: GetDocumentHistoryResponse.GetDocumentHistoryResponseV0): void; + hasV1(): boolean; + clearV1(): void; + getV1(): GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 | undefined; + setV1(value?: GetDocumentHistoryResponse.GetDocumentHistoryResponseV1): void; + getVersionCase(): GetDocumentHistoryResponse.VersionCase; serializeBinary(): Uint8Array; toObject(includeInstance?: boolean): GetDocumentHistoryResponse.AsObject; @@ -6660,6 +6771,7 @@ export class GetDocumentHistoryResponse extends jspb.Message { export namespace GetDocumentHistoryResponse { export type AsObject = { v0?: GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.AsObject, + v1?: GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.AsObject, } export class GetDocumentHistoryResponseV0 extends jspb.Message { @@ -6751,9 +6863,140 @@ export namespace GetDocumentHistoryResponse { } } + export class GetDocumentHistoryResponseV1 extends jspb.Message { + hasHistory(): boolean; + clearHistory(): void; + getHistory(): GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History | undefined; + setHistory(value?: GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History): void; + + hasProof(): boolean; + clearProof(): void; + getProof(): Proof | undefined; + setProof(value?: Proof): void; + + hasMetadata(): boolean; + clearMetadata(): void; + getMetadata(): ResponseMetadata | undefined; + setMetadata(value?: ResponseMetadata): void; + + getResultCase(): GetDocumentHistoryResponseV1.ResultCase; + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): GetDocumentHistoryResponseV1.AsObject; + static toObject(includeInstance: boolean, msg: GetDocumentHistoryResponseV1): GetDocumentHistoryResponseV1.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: GetDocumentHistoryResponseV1, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): GetDocumentHistoryResponseV1; + static deserializeBinaryFromReader(message: GetDocumentHistoryResponseV1, reader: jspb.BinaryReader): GetDocumentHistoryResponseV1; + } + + export namespace GetDocumentHistoryResponseV1 { + export type AsObject = { + history?: GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.AsObject, + proof?: Proof.AsObject, + metadata?: ResponseMetadata.AsObject, + } + + export class Entry extends jspb.Message { + getTimeMs(): string; + setTimeMs(value: string): void; + + getRevision(): string; + setRevision(value: string): void; + + getDocument(): Uint8Array | string; + getDocument_asU8(): Uint8Array; + getDocument_asB64(): string; + setDocument(value: Uint8Array | string): void; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): Entry.AsObject; + static toObject(includeInstance: boolean, msg: Entry): Entry.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: Entry, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): Entry; + static deserializeBinaryFromReader(message: Entry, reader: jspb.BinaryReader): Entry; + } + + export namespace Entry { + export type AsObject = { + timeMs: string, + revision: string, + document: Uint8Array | string, + } + } + + export class Lifecycle extends jspb.Message { + getState(): GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.StateMap[keyof GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.StateMap]; + setState(value: GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.StateMap[keyof GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.StateMap]): void; + + getRemainingRevisions(): string; + setRemainingRevisions(value: string): void; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): Lifecycle.AsObject; + static toObject(includeInstance: boolean, msg: Lifecycle): Lifecycle.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: Lifecycle, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): Lifecycle; + static deserializeBinaryFromReader(message: Lifecycle, reader: jspb.BinaryReader): Lifecycle; + } + + export namespace Lifecycle { + export type AsObject = { + state: GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.StateMap[keyof GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.StateMap], + remainingRevisions: string, + } + + export interface StateMap { + ACTIVE: 0; + ABSENT: 1; + } + + export const State: StateMap; + } + + export class History extends jspb.Message { + clearEntriesList(): void; + getEntriesList(): Array; + setEntriesList(value: Array): void; + addEntries(value?: GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry, index?: number): GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry; + + hasLifecycle(): boolean; + clearLifecycle(): void; + getLifecycle(): GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle | undefined; + setLifecycle(value?: GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle): void; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): History.AsObject; + static toObject(includeInstance: boolean, msg: History): History.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: History, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): History; + static deserializeBinaryFromReader(message: History, reader: jspb.BinaryReader): History; + } + + export namespace History { + export type AsObject = { + entriesList: Array, + lifecycle?: GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.AsObject, + } + } + + export enum ResultCase { + RESULT_NOT_SET = 0, + HISTORY = 1, + PROOF = 2, + } + } + export enum VersionCase { VERSION_NOT_SET = 0, V0 = 1, + V1 = 2, } } 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 9ffea0ab9a9..dc7db229162 100644 --- a/packages/dapi-grpc/clients/platform/v0/web/platform_pb.js +++ b/packages/dapi-grpc/clients/platform/v0/web/platform_pb.js @@ -271,12 +271,21 @@ goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDataContractsResponse.GetD goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDataContractsResponse.VersionCase', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.FilterCase', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.VersionCase', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.ResultCase', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.State', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.ResultCase', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.VersionCase', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsRequest', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsRequest.DocumentFieldValue', null, { proto }); @@ -5007,6 +5016,48 @@ if (goog.DEBUG && !COMPILED) { */ proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0.displayName = 'proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0'; } +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1 = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.oneofGroups_); +}; +goog.inherits(proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.displayName = 'proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.displayName = 'proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor'; +} /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a @@ -5091,6 +5142,90 @@ if (goog.DEBUG && !COMPILED) { */ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.displayName = 'proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory'; } +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1 = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.oneofGroups_); +}; +goog.inherits(proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.displayName = 'proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.displayName = 'proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.displayName = 'proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.repeatedFields_, null); +}; +goog.inherits(proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.displayName = 'proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History'; +} /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a @@ -56987,14 +57122,15 @@ proto.org.dash.platform.dapi.v0.GetDocumentsResponse.prototype.hasV1 = function( * @private {!Array>} * @const */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.oneofGroups_ = [[1]]; +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.oneofGroups_ = [[1,2]]; /** * @enum {number} */ proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.VersionCase = { VERSION_NOT_SET: 0, - V0: 1 + V0: 1, + V1: 2 }; /** @@ -57035,7 +57171,8 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.prototype.toObject = f */ proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.toObject = function(includeInstance, msg) { var f, obj = { - v0: (f = msg.getV0()) && proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0.toObject(includeInstance, f) + v0: (f = msg.getV0()) && proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0.toObject(includeInstance, f), + v1: (f = msg.getV1()) && proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.toObject(includeInstance, f) }; if (includeInstance) { @@ -57077,6 +57214,11 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.deserializeBinaryFromR reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0.deserializeBinaryFromReader); msg.setV0(value); break; + case 2: + var value = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.deserializeBinaryFromReader); + msg.setV1(value); + break; default: reader.skipField(); break; @@ -57114,6 +57256,14 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.serializeBinaryToWrite proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0.serializeBinaryToWriter ); } + f = message.getV1(); + if (f != null) { + writer.writeMessage( + 2, + f, + proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.serializeBinaryToWriter + ); + } }; @@ -57517,43 +57667,6 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequ }; -/** - * optional GetDocumentHistoryRequestV0 v0 = 1; - * @return {?proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0} - */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.prototype.getV0 = function() { - return /** @type{?proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0} */ ( - jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0, 1)); -}; - - -/** - * @param {?proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0|undefined} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest} returns this -*/ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.prototype.setV0 = function(value) { - return jspb.Message.setOneofWrapperField(this, 1, proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.oneofGroups_[0], value); -}; - - -/** - * Clears the message field making it undefined. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest} returns this - */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.prototype.clearV0 = function() { - return this.setV0(undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.prototype.hasV0 = function() { - return jspb.Message.getField(this, 1) != null; -}; - - /** * Oneof group definitions for this message. Each group defines the field @@ -57563,21 +57676,24 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.prototype.hasV0 = func * @private {!Array>} * @const */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.oneofGroups_ = [[1]]; +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.oneofGroups_ = [[6,7,8,9]]; /** * @enum {number} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.VersionCase = { - VERSION_NOT_SET: 0, - V0: 1 +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.FilterCase = { + FILTER_NOT_SET: 0, + START_AT_MS: 6, + START_AFTER: 7, + START_AT_REVISION: 8, + REVISION: 9 }; /** - * @return {proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.VersionCase} + * @return {proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.FilterCase} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.prototype.getVersionCase = function() { - return /** @type {proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.VersionCase} */(jspb.Message.computeOneofCase(this, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.oneofGroups_[0])); +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.getFilterCase = function() { + return /** @type {proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.FilterCase} */(jspb.Message.computeOneofCase(this, proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.oneofGroups_[0])); }; @@ -57595,8 +57711,8 @@ if (jspb.Message.GENERATE_TO_OBJECT) { * http://goto/soy-param-migration * @return {!Object} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.prototype.toObject = function(opt_includeInstance) { - return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.toObject(opt_includeInstance, this); +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.toObject = function(opt_includeInstance) { + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.toObject(opt_includeInstance, this); }; @@ -57605,13 +57721,21 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.prototype.toObject = * @param {boolean|undefined} includeInstance Deprecated. Whether to include * the JSPB instance for transitional soy proto support: * http://goto/soy-param-migration - * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse} msg The msg instance to transform. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} msg The msg instance to transform. * @return {!Object} * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.toObject = function(includeInstance, msg) { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.toObject = function(includeInstance, msg) { var f, obj = { - v0: (f = msg.getV0()) && proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.toObject(includeInstance, f) + dataContractId: msg.getDataContractId_asB64(), + documentTypeName: jspb.Message.getFieldWithDefault(msg, 2, ""), + documentId: msg.getDocumentId_asB64(), + limit: (f = msg.getLimit()) && google_protobuf_wrappers_pb.UInt32Value.toObject(includeInstance, f), + prove: jspb.Message.getBooleanFieldWithDefault(msg, 5, false), + startAtMs: jspb.Message.getFieldWithDefault(msg, 6, "0"), + startAfter: (f = msg.getStartAfter()) && proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.toObject(includeInstance, f), + startAtRevision: jspb.Message.getFieldWithDefault(msg, 8, "0"), + revision: jspb.Message.getFieldWithDefault(msg, 9, "0") }; if (includeInstance) { @@ -57625,23 +57749,23 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.toObject = function(i /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse} + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.deserializeBinary = function(bytes) { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); - var msg = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse; - return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.deserializeBinaryFromReader(msg, reader); + var msg = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1; + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. - * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse} msg The message object to deserialize into. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse} + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.deserializeBinaryFromReader = function(msg, reader) { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; @@ -57649,9 +57773,42 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.deserializeBinaryFrom var field = reader.getFieldNumber(); switch (field) { case 1: - var value = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0; - reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.deserializeBinaryFromReader); - msg.setV0(value); + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setDataContractId(value); + break; + case 2: + var value = /** @type {string} */ (reader.readString()); + msg.setDocumentTypeName(value); + break; + case 3: + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setDocumentId(value); + break; + case 4: + var value = new google_protobuf_wrappers_pb.UInt32Value; + reader.readMessage(value,google_protobuf_wrappers_pb.UInt32Value.deserializeBinaryFromReader); + msg.setLimit(value); + break; + case 5: + var value = /** @type {boolean} */ (reader.readBool()); + msg.setProve(value); + break; + case 6: + var value = /** @type {string} */ (reader.readUint64String()); + msg.setStartAtMs(value); + break; + case 7: + var value = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.deserializeBinaryFromReader); + msg.setStartAfter(value); + break; + case 8: + var value = /** @type {string} */ (reader.readUint64String()); + msg.setStartAtRevision(value); + break; + case 9: + var value = /** @type {string} */ (reader.readUint64String()); + msg.setRevision(value); break; default: reader.skipField(); @@ -57666,9 +57823,9 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.deserializeBinaryFrom * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.prototype.serializeBinary = function() { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); - proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.serializeBinaryToWriter(this, writer); + proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.serializeBinaryToWriter(this, writer); return writer.getResultBuffer(); }; @@ -57676,50 +57833,81 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.prototype.serializeBi /** * Serializes the given message to binary data (in protobuf wire * format), writing to the given BinaryWriter. - * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse} message + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} message * @param {!jspb.BinaryWriter} writer * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.serializeBinaryToWriter = function(message, writer) { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.serializeBinaryToWriter = function(message, writer) { var f = undefined; - f = message.getV0(); + f = message.getDataContractId_asU8(); + if (f.length > 0) { + writer.writeBytes( + 1, + f + ); + } + f = message.getDocumentTypeName(); + if (f.length > 0) { + writer.writeString( + 2, + f + ); + } + f = message.getDocumentId_asU8(); + if (f.length > 0) { + writer.writeBytes( + 3, + f + ); + } + f = message.getLimit(); if (f != null) { writer.writeMessage( - 1, + 4, f, - proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.serializeBinaryToWriter + google_protobuf_wrappers_pb.UInt32Value.serializeBinaryToWriter + ); + } + f = message.getProve(); + if (f) { + writer.writeBool( + 5, + f + ); + } + f = /** @type {string} */ (jspb.Message.getField(message, 6)); + if (f != null) { + writer.writeUint64String( + 6, + f + ); + } + f = message.getStartAfter(); + if (f != null) { + writer.writeMessage( + 7, + f, + proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.serializeBinaryToWriter + ); + } + f = /** @type {string} */ (jspb.Message.getField(message, 8)); + if (f != null) { + writer.writeUint64String( + 8, + f + ); + } + f = /** @type {string} */ (jspb.Message.getField(message, 9)); + if (f != null) { + writer.writeUint64String( + 9, + f ); } }; -/** - * Oneof group definitions for this message. Each group defines the field - * numbers belonging to that group. When of these fields' value is set, all - * other fields in the group are cleared. During deserialization, if multiple - * fields are encountered for a group, only the last value seen will be kept. - * @private {!Array>} - * @const - */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.oneofGroups_ = [[1,2]]; - -/** - * @enum {number} - */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.ResultCase = { - RESULT_NOT_SET: 0, - DOCUMENT_HISTORY: 1, - PROOF: 2 -}; - -/** - * @return {proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.ResultCase} - */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.getResultCase = function() { - return /** @type {proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.ResultCase} */(jspb.Message.computeOneofCase(this, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.oneofGroups_[0])); -}; - if (jspb.Message.GENERATE_TO_OBJECT) { @@ -57735,8 +57923,8 @@ if (jspb.Message.GENERATE_TO_OBJECT) { * http://goto/soy-param-migration * @return {!Object} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.toObject = function(opt_includeInstance) { - return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.toObject(opt_includeInstance, this); +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.prototype.toObject = function(opt_includeInstance) { + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.toObject(opt_includeInstance, this); }; @@ -57745,15 +57933,14 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryRes * @param {boolean|undefined} includeInstance Deprecated. Whether to include * the JSPB instance for transitional soy proto support: * http://goto/soy-param-migration - * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} msg The msg instance to transform. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor} msg The msg instance to transform. * @return {!Object} * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.toObject = function(includeInstance, msg) { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.toObject = function(includeInstance, msg) { var f, obj = { - documentHistory: (f = msg.getDocumentHistory()) && proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.toObject(includeInstance, f), - proof: (f = msg.getProof()) && proto.org.dash.platform.dapi.v0.Proof.toObject(includeInstance, f), - metadata: (f = msg.getMetadata()) && proto.org.dash.platform.dapi.v0.ResponseMetadata.toObject(includeInstance, f) + timeMs: jspb.Message.getFieldWithDefault(msg, 1, "0"), + revision: jspb.Message.getFieldWithDefault(msg, 2, "0") }; if (includeInstance) { @@ -57767,23 +57954,23 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryRes /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.deserializeBinary = function(bytes) { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); - var msg = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0; - return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.deserializeBinaryFromReader(msg, reader); + var msg = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor; + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. - * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} msg The message object to deserialize into. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.deserializeBinaryFromReader = function(msg, reader) { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; @@ -57791,19 +57978,12 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryRes var field = reader.getFieldNumber(); switch (field) { case 1: - var value = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory; - reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.deserializeBinaryFromReader); - msg.setDocumentHistory(value); + var value = /** @type {string} */ (reader.readUint64String()); + msg.setTimeMs(value); break; case 2: - var value = new proto.org.dash.platform.dapi.v0.Proof; - reader.readMessage(value,proto.org.dash.platform.dapi.v0.Proof.deserializeBinaryFromReader); - msg.setProof(value); - break; - case 3: - var value = new proto.org.dash.platform.dapi.v0.ResponseMetadata; - reader.readMessage(value,proto.org.dash.platform.dapi.v0.ResponseMetadata.deserializeBinaryFromReader); - msg.setMetadata(value); + var value = /** @type {string} */ (reader.readUint64String()); + msg.setRevision(value); break; default: reader.skipField(); @@ -57818,9 +57998,9 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryRes * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.serializeBinary = function() { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); - proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.serializeBinaryToWriter(this, writer); + proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.serializeBinaryToWriter(this, writer); return writer.getResultBuffer(); }; @@ -57828,211 +58008,935 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryRes /** * Serializes the given message to binary data (in protobuf wire * format), writing to the given BinaryWriter. - * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} message + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor} message * @param {!jspb.BinaryWriter} writer * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.serializeBinaryToWriter = function(message, writer) { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.serializeBinaryToWriter = function(message, writer) { var f = undefined; - f = message.getDocumentHistory(); - if (f != null) { - writer.writeMessage( + f = message.getTimeMs(); + if (parseInt(f, 10) !== 0) { + writer.writeUint64String( 1, - f, - proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.serializeBinaryToWriter + f ); } - f = message.getProof(); - if (f != null) { - writer.writeMessage( + f = message.getRevision(); + if (parseInt(f, 10) !== 0) { + writer.writeUint64String( 2, - f, - proto.org.dash.platform.dapi.v0.Proof.serializeBinaryToWriter - ); - } - f = message.getMetadata(); - if (f != null) { - writer.writeMessage( - 3, - f, - proto.org.dash.platform.dapi.v0.ResponseMetadata.serializeBinaryToWriter + f ); } }; +/** + * optional uint64 time_ms = 1; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.prototype.getTimeMs = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "0")); +}; - -if (jspb.Message.GENERATE_TO_OBJECT) { /** - * Creates an object representation of this proto. - * Field names that are reserved in JavaScript and will be renamed to pb_name. - * Optional fields that are not set will be set to undefined. - * To access a reserved field use, foo.pb_, eg, foo.pb_default. - * For the list of reserved names please see: - * net/proto2/compiler/js/internal/generator.cc#kKeyword. - * @param {boolean=} opt_includeInstance Deprecated. whether to include the - * JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @return {!Object} + * @param {string} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.prototype.toObject = function(opt_includeInstance) { - return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.toObject(opt_includeInstance, this); +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.prototype.setTimeMs = function(value) { + return jspb.Message.setProto3StringIntField(this, 1, value); }; /** - * Static version of the {@see toObject} method. - * @param {boolean|undefined} includeInstance Deprecated. Whether to include - * the JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages + * optional uint64 revision = 2; + * @return {string} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.toObject = function(includeInstance, msg) { - var f, obj = { - date: jspb.Message.getFieldWithDefault(msg, 1, "0"), - value: msg.getValue_asB64() - }; +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.prototype.getRevision = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "0")); +}; - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; + +/** + * @param {string} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor.prototype.setRevision = function(value) { + return jspb.Message.setProto3StringIntField(this, 2, value); }; -} /** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} + * optional bytes data_contract_id = 1; + * @return {string} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry; - return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.deserializeBinaryFromReader(msg, reader); +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.getDataContractId = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); }; /** - * Deserializes binary data (in protobuf wire format) from the - * given reader into the given message object. - * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} + * optional bytes data_contract_id = 1; + * This is a type-conversion wrapper around `getDataContractId()` + * @return {string} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.deserializeBinaryFromReader = function(msg, reader) { - while (reader.nextField()) { - if (reader.isEndGroup()) { - break; - } - var field = reader.getFieldNumber(); - switch (field) { - case 1: - var value = /** @type {string} */ (reader.readUint64String()); - msg.setDate(value); - break; - case 2: - var value = /** @type {!Uint8Array} */ (reader.readBytes()); - msg.setValue(value); - break; - default: - reader.skipField(); - break; - } - } - return msg; +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.getDataContractId_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getDataContractId())); }; /** - * Serializes the message to binary data (in protobuf wire format). + * optional bytes data_contract_id = 1; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getDataContractId()` * @return {!Uint8Array} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.serializeBinaryToWriter(this, writer); - return writer.getResultBuffer(); +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.getDataContractId_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getDataContractId())); }; /** - * Serializes the given message to binary data (in protobuf wire - * format), writing to the given BinaryWriter. - * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages + * @param {!(string|Uint8Array)} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getDate(); - if (parseInt(f, 10) !== 0) { - writer.writeUint64String( - 1, - f - ); - } - f = message.getValue_asU8(); - if (f.length > 0) { - writer.writeBytes( - 2, - f - ); - } +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.setDataContractId = function(value) { + return jspb.Message.setProto3BytesField(this, 1, value); }; /** - * optional uint64 date = 1; + * optional string document_type_name = 2; * @return {string} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.prototype.getDate = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "0")); +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.getDocumentTypeName = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); }; /** * @param {string} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} returns this + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.prototype.setDate = function(value) { - return jspb.Message.setProto3StringIntField(this, 1, value); +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.setDocumentTypeName = function(value) { + return jspb.Message.setProto3StringField(this, 2, value); }; /** - * optional bytes value = 2; + * optional bytes document_id = 3; * @return {string} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.prototype.getValue = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.getDocumentId = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); }; /** - * optional bytes value = 2; - * This is a type-conversion wrapper around `getValue()` + * optional bytes document_id = 3; + * This is a type-conversion wrapper around `getDocumentId()` * @return {string} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.prototype.getValue_asB64 = function() { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.getDocumentId_asB64 = function() { return /** @type {string} */ (jspb.Message.bytesAsB64( - this.getValue())); + this.getDocumentId())); }; /** - * optional bytes value = 2; + * optional bytes document_id = 3; * Note that Uint8Array is not supported on all browsers. * @see http://caniuse.com/Uint8Array - * This is a type-conversion wrapper around `getValue()` + * This is a type-conversion wrapper around `getDocumentId()` * @return {!Uint8Array} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.prototype.getValue_asU8 = function() { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.getDocumentId_asU8 = function() { return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( - this.getValue())); + this.getDocumentId())); +}; + + +/** + * @param {!(string|Uint8Array)} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.setDocumentId = function(value) { + return jspb.Message.setProto3BytesField(this, 3, value); +}; + + +/** + * optional google.protobuf.UInt32Value limit = 4; + * @return {?proto.google.protobuf.UInt32Value} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.getLimit = function() { + return /** @type{?proto.google.protobuf.UInt32Value} */ ( + jspb.Message.getWrapperField(this, google_protobuf_wrappers_pb.UInt32Value, 4)); +}; + + +/** + * @param {?proto.google.protobuf.UInt32Value|undefined} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} returns this +*/ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.setLimit = function(value) { + return jspb.Message.setWrapperField(this, 4, value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.clearLimit = function() { + return this.setLimit(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.hasLimit = function() { + return jspb.Message.getField(this, 4) != null; +}; + + +/** + * optional bool prove = 5; + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.getProve = function() { + return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 5, false)); +}; + + +/** + * @param {boolean} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.setProve = function(value) { + return jspb.Message.setProto3BooleanField(this, 5, value); +}; + + +/** + * optional uint64 start_at_ms = 6; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.getStartAtMs = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 6, "0")); +}; + + +/** + * @param {string} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.setStartAtMs = function(value) { + return jspb.Message.setOneofField(this, 6, proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.oneofGroups_[0], value); +}; + + +/** + * Clears the field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.clearStartAtMs = function() { + return jspb.Message.setOneofField(this, 6, proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.oneofGroups_[0], undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.hasStartAtMs = function() { + return jspb.Message.getField(this, 6) != null; +}; + + +/** + * optional Cursor start_after = 7; + * @return {?proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.getStartAfter = function() { + return /** @type{?proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor} */ ( + jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor, 7)); +}; + + +/** + * @param {?proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.Cursor|undefined} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} returns this +*/ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.setStartAfter = function(value) { + return jspb.Message.setOneofWrapperField(this, 7, proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.oneofGroups_[0], value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.clearStartAfter = function() { + return this.setStartAfter(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.hasStartAfter = function() { + return jspb.Message.getField(this, 7) != null; +}; + + +/** + * optional uint64 start_at_revision = 8; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.getStartAtRevision = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 8, "0")); +}; + + +/** + * @param {string} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.setStartAtRevision = function(value) { + return jspb.Message.setOneofField(this, 8, proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.oneofGroups_[0], value); +}; + + +/** + * Clears the field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.clearStartAtRevision = function() { + return jspb.Message.setOneofField(this, 8, proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.oneofGroups_[0], undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.hasStartAtRevision = function() { + return jspb.Message.getField(this, 8) != null; +}; + + +/** + * optional uint64 revision = 9; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.getRevision = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 9, "0")); +}; + + +/** + * @param {string} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.setRevision = function(value) { + return jspb.Message.setOneofField(this, 9, proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.oneofGroups_[0], value); +}; + + +/** + * Clears the field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.clearRevision = function() { + return jspb.Message.setOneofField(this, 9, proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.oneofGroups_[0], undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1.prototype.hasRevision = function() { + return jspb.Message.getField(this, 9) != null; +}; + + +/** + * optional GetDocumentHistoryRequestV0 v0 = 1; + * @return {?proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.prototype.getV0 = function() { + return /** @type{?proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0} */ ( + jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0, 1)); +}; + + +/** + * @param {?proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0|undefined} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest} returns this +*/ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.prototype.setV0 = function(value) { + return jspb.Message.setOneofWrapperField(this, 1, proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.oneofGroups_[0], value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.prototype.clearV0 = function() { + return this.setV0(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.prototype.hasV0 = function() { + return jspb.Message.getField(this, 1) != null; +}; + + +/** + * optional GetDocumentHistoryRequestV1 v1 = 2; + * @return {?proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.prototype.getV1 = function() { + return /** @type{?proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1} */ ( + jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1, 2)); +}; + + +/** + * @param {?proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV1|undefined} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest} returns this +*/ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.prototype.setV1 = function(value) { + return jspb.Message.setOneofWrapperField(this, 2, proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.oneofGroups_[0], value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.prototype.clearV1 = function() { + return this.setV1(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.prototype.hasV1 = function() { + return jspb.Message.getField(this, 2) != null; +}; + + + +/** + * Oneof group definitions for this message. Each group defines the field + * numbers belonging to that group. When of these fields' value is set, all + * other fields in the group are cleared. During deserialization, if multiple + * fields are encountered for a group, only the last value seen will be kept. + * @private {!Array>} + * @const + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.oneofGroups_ = [[1,2]]; + +/** + * @enum {number} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.VersionCase = { + VERSION_NOT_SET: 0, + V0: 1, + V1: 2 +}; + +/** + * @return {proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.VersionCase} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.prototype.getVersionCase = function() { + return /** @type {proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.VersionCase} */(jspb.Message.computeOneofCase(this, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.oneofGroups_[0])); +}; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.prototype.toObject = function(opt_includeInstance) { + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.toObject = function(includeInstance, msg) { + var f, obj = { + v0: (f = msg.getV0()) && proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.toObject(includeInstance, f), + v1: (f = msg.getV1()) && proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.toObject(includeInstance, f) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse; + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.deserializeBinaryFromReader); + msg.setV0(value); + break; + case 2: + var value = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.deserializeBinaryFromReader); + msg.setV1(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getV0(); + if (f != null) { + writer.writeMessage( + 1, + f, + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.serializeBinaryToWriter + ); + } + f = message.getV1(); + if (f != null) { + writer.writeMessage( + 2, + f, + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.serializeBinaryToWriter + ); + } +}; + + + +/** + * Oneof group definitions for this message. Each group defines the field + * numbers belonging to that group. When of these fields' value is set, all + * other fields in the group are cleared. During deserialization, if multiple + * fields are encountered for a group, only the last value seen will be kept. + * @private {!Array>} + * @const + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.oneofGroups_ = [[1,2]]; + +/** + * @enum {number} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.ResultCase = { + RESULT_NOT_SET: 0, + DOCUMENT_HISTORY: 1, + PROOF: 2 +}; + +/** + * @return {proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.ResultCase} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.getResultCase = function() { + return /** @type {proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.ResultCase} */(jspb.Message.computeOneofCase(this, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.oneofGroups_[0])); +}; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.toObject = function(opt_includeInstance) { + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.toObject = function(includeInstance, msg) { + var f, obj = { + documentHistory: (f = msg.getDocumentHistory()) && proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.toObject(includeInstance, f), + proof: (f = msg.getProof()) && proto.org.dash.platform.dapi.v0.Proof.toObject(includeInstance, f), + metadata: (f = msg.getMetadata()) && proto.org.dash.platform.dapi.v0.ResponseMetadata.toObject(includeInstance, f) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0; + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.deserializeBinaryFromReader); + msg.setDocumentHistory(value); + break; + case 2: + var value = new proto.org.dash.platform.dapi.v0.Proof; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.Proof.deserializeBinaryFromReader); + msg.setProof(value); + break; + case 3: + var value = new proto.org.dash.platform.dapi.v0.ResponseMetadata; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.ResponseMetadata.deserializeBinaryFromReader); + msg.setMetadata(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getDocumentHistory(); + if (f != null) { + writer.writeMessage( + 1, + f, + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.serializeBinaryToWriter + ); + } + f = message.getProof(); + if (f != null) { + writer.writeMessage( + 2, + f, + proto.org.dash.platform.dapi.v0.Proof.serializeBinaryToWriter + ); + } + f = message.getMetadata(); + if (f != null) { + writer.writeMessage( + 3, + f, + proto.org.dash.platform.dapi.v0.ResponseMetadata.serializeBinaryToWriter + ); + } +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.prototype.toObject = function(opt_includeInstance) { + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.toObject = function(includeInstance, msg) { + var f, obj = { + date: jspb.Message.getFieldWithDefault(msg, 1, "0"), + value: msg.getValue_asB64() + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry; + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readUint64String()); + msg.setDate(value); + break; + case 2: + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setValue(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getDate(); + if (parseInt(f, 10) !== 0) { + writer.writeUint64String( + 1, + f + ); + } + f = message.getValue_asU8(); + if (f.length > 0) { + writer.writeBytes( + 2, + f + ); + } +}; + + +/** + * optional uint64 date = 1; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.prototype.getDate = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "0")); +}; + + +/** + * @param {string} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.prototype.setDate = function(value) { + return jspb.Message.setProto3StringIntField(this, 1, value); +}; + + +/** + * optional bytes value = 2; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.prototype.getValue = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * optional bytes value = 2; + * This is a type-conversion wrapper around `getValue()` + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.prototype.getValue_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getValue())); +}; + + +/** + * optional bytes value = 2; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getValue()` + * @return {!Uint8Array} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.prototype.getValue_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getValue())); }; @@ -58040,8 +58944,829 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryRes * @param {!(string|Uint8Array)} value * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.prototype.setValue = function(value) { - return jspb.Message.setProto3BytesField(this, 2, value); +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.prototype.setValue = function(value) { + return jspb.Message.setProto3BytesField(this, 2, value); +}; + + + +/** + * List of repeated fields within this message type. + * @private {!Array} + * @const + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.repeatedFields_ = [1]; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.prototype.toObject = function(opt_includeInstance) { + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.toObject = function(includeInstance, msg) { + var f, obj = { + documentEntriesList: jspb.Message.toObjectList(msg.getDocumentEntriesList(), + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.toObject, includeInstance) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory; + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.deserializeBinaryFromReader); + msg.addDocumentEntries(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getDocumentEntriesList(); + if (f.length > 0) { + writer.writeRepeatedMessage( + 1, + f, + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.serializeBinaryToWriter + ); + } +}; + + +/** + * repeated DocumentHistoryEntry document_entries = 1; + * @return {!Array} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.prototype.getDocumentEntriesList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry, 1)); +}; + + +/** + * @param {!Array} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} returns this +*/ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.prototype.setDocumentEntriesList = function(value) { + return jspb.Message.setRepeatedWrapperField(this, 1, value); +}; + + +/** + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry=} opt_value + * @param {number=} opt_index + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.prototype.addDocumentEntries = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry, opt_index); +}; + + +/** + * Clears the list making it empty but non-null. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.prototype.clearDocumentEntriesList = function() { + return this.setDocumentEntriesList([]); +}; + + +/** + * optional DocumentHistory document_history = 1; + * @return {?proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.getDocumentHistory = function() { + return /** @type{?proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} */ ( + jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory, 1)); +}; + + +/** + * @param {?proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory|undefined} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} returns this +*/ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.setDocumentHistory = function(value) { + return jspb.Message.setOneofWrapperField(this, 1, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.oneofGroups_[0], value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.clearDocumentHistory = function() { + return this.setDocumentHistory(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.hasDocumentHistory = function() { + return jspb.Message.getField(this, 1) != null; +}; + + +/** + * optional Proof proof = 2; + * @return {?proto.org.dash.platform.dapi.v0.Proof} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.getProof = function() { + return /** @type{?proto.org.dash.platform.dapi.v0.Proof} */ ( + jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.Proof, 2)); +}; + + +/** + * @param {?proto.org.dash.platform.dapi.v0.Proof|undefined} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} returns this +*/ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.setProof = function(value) { + return jspb.Message.setOneofWrapperField(this, 2, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.oneofGroups_[0], value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.clearProof = function() { + return this.setProof(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.hasProof = function() { + return jspb.Message.getField(this, 2) != null; +}; + + +/** + * optional ResponseMetadata metadata = 3; + * @return {?proto.org.dash.platform.dapi.v0.ResponseMetadata} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.getMetadata = function() { + return /** @type{?proto.org.dash.platform.dapi.v0.ResponseMetadata} */ ( + jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.ResponseMetadata, 3)); +}; + + +/** + * @param {?proto.org.dash.platform.dapi.v0.ResponseMetadata|undefined} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} returns this +*/ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.setMetadata = function(value) { + return jspb.Message.setWrapperField(this, 3, value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.clearMetadata = function() { + return this.setMetadata(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.hasMetadata = function() { + return jspb.Message.getField(this, 3) != null; +}; + + + +/** + * Oneof group definitions for this message. Each group defines the field + * numbers belonging to that group. When of these fields' value is set, all + * other fields in the group are cleared. During deserialization, if multiple + * fields are encountered for a group, only the last value seen will be kept. + * @private {!Array>} + * @const + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.oneofGroups_ = [[1,2]]; + +/** + * @enum {number} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.ResultCase = { + RESULT_NOT_SET: 0, + HISTORY: 1, + PROOF: 2 +}; + +/** + * @return {proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.ResultCase} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.prototype.getResultCase = function() { + return /** @type {proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.ResultCase} */(jspb.Message.computeOneofCase(this, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.oneofGroups_[0])); +}; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.prototype.toObject = function(opt_includeInstance) { + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.toObject = function(includeInstance, msg) { + var f, obj = { + history: (f = msg.getHistory()) && proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.toObject(includeInstance, f), + proof: (f = msg.getProof()) && proto.org.dash.platform.dapi.v0.Proof.toObject(includeInstance, f), + metadata: (f = msg.getMetadata()) && proto.org.dash.platform.dapi.v0.ResponseMetadata.toObject(includeInstance, f) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1; + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.deserializeBinaryFromReader); + msg.setHistory(value); + break; + case 2: + var value = new proto.org.dash.platform.dapi.v0.Proof; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.Proof.deserializeBinaryFromReader); + msg.setProof(value); + break; + case 3: + var value = new proto.org.dash.platform.dapi.v0.ResponseMetadata; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.ResponseMetadata.deserializeBinaryFromReader); + msg.setMetadata(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getHistory(); + if (f != null) { + writer.writeMessage( + 1, + f, + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.serializeBinaryToWriter + ); + } + f = message.getProof(); + if (f != null) { + writer.writeMessage( + 2, + f, + proto.org.dash.platform.dapi.v0.Proof.serializeBinaryToWriter + ); + } + f = message.getMetadata(); + if (f != null) { + writer.writeMessage( + 3, + f, + proto.org.dash.platform.dapi.v0.ResponseMetadata.serializeBinaryToWriter + ); + } +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.prototype.toObject = function(opt_includeInstance) { + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.toObject = function(includeInstance, msg) { + var f, obj = { + timeMs: jspb.Message.getFieldWithDefault(msg, 1, "0"), + revision: jspb.Message.getFieldWithDefault(msg, 2, "0"), + document: msg.getDocument_asB64() + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry; + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readUint64String()); + msg.setTimeMs(value); + break; + case 2: + var value = /** @type {string} */ (reader.readUint64String()); + msg.setRevision(value); + break; + case 3: + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setDocument(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getTimeMs(); + if (parseInt(f, 10) !== 0) { + writer.writeUint64String( + 1, + f + ); + } + f = message.getRevision(); + if (parseInt(f, 10) !== 0) { + writer.writeUint64String( + 2, + f + ); + } + f = message.getDocument_asU8(); + if (f.length > 0) { + writer.writeBytes( + 3, + f + ); + } +}; + + +/** + * optional uint64 time_ms = 1; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.prototype.getTimeMs = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "0")); +}; + + +/** + * @param {string} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.prototype.setTimeMs = function(value) { + return jspb.Message.setProto3StringIntField(this, 1, value); +}; + + +/** + * optional uint64 revision = 2; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.prototype.getRevision = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "0")); +}; + + +/** + * @param {string} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.prototype.setRevision = function(value) { + return jspb.Message.setProto3StringIntField(this, 2, value); +}; + + +/** + * optional bytes document = 3; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.prototype.getDocument = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); +}; + + +/** + * optional bytes document = 3; + * This is a type-conversion wrapper around `getDocument()` + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.prototype.getDocument_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getDocument())); +}; + + +/** + * optional bytes document = 3; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getDocument()` + * @return {!Uint8Array} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.prototype.getDocument_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getDocument())); +}; + + +/** + * @param {!(string|Uint8Array)} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.prototype.setDocument = function(value) { + return jspb.Message.setProto3BytesField(this, 3, value); +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.prototype.toObject = function(opt_includeInstance) { + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.toObject = function(includeInstance, msg) { + var f, obj = { + state: jspb.Message.getFieldWithDefault(msg, 1, 0), + remainingRevisions: jspb.Message.getFieldWithDefault(msg, 2, "0") + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle; + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.State} */ (reader.readEnum()); + msg.setState(value); + break; + case 2: + var value = /** @type {string} */ (reader.readUint64String()); + msg.setRemainingRevisions(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getState(); + if (f !== 0.0) { + writer.writeEnum( + 1, + f + ); + } + f = message.getRemainingRevisions(); + if (parseInt(f, 10) !== 0) { + writer.writeUint64String( + 2, + f + ); + } +}; + + +/** + * @enum {number} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.State = { + ACTIVE: 0, + ABSENT: 1 +}; + +/** + * optional State state = 1; + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.State} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.prototype.getState = function() { + return /** @type {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.State} */ (jspb.Message.getFieldWithDefault(this, 1, 0)); +}; + + +/** + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.State} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.prototype.setState = function(value) { + return jspb.Message.setProto3EnumField(this, 1, value); +}; + + +/** + * optional uint64 remaining_revisions = 2; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.prototype.getRemainingRevisions = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "0")); +}; + + +/** + * @param {string} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.prototype.setRemainingRevisions = function(value) { + return jspb.Message.setProto3StringIntField(this, 2, value); }; @@ -58051,7 +59776,7 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryRes * @private {!Array} * @const */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.repeatedFields_ = [1]; +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.repeatedFields_ = [1]; @@ -58068,8 +59793,8 @@ if (jspb.Message.GENERATE_TO_OBJECT) { * http://goto/soy-param-migration * @return {!Object} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.prototype.toObject = function(opt_includeInstance) { - return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.toObject(opt_includeInstance, this); +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.prototype.toObject = function(opt_includeInstance) { + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.toObject(opt_includeInstance, this); }; @@ -58078,14 +59803,15 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryRes * @param {boolean|undefined} includeInstance Deprecated. Whether to include * the JSPB instance for transitional soy proto support: * http://goto/soy-param-migration - * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} msg The msg instance to transform. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History} msg The msg instance to transform. * @return {!Object} * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.toObject = function(includeInstance, msg) { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.toObject = function(includeInstance, msg) { var f, obj = { - documentEntriesList: jspb.Message.toObjectList(msg.getDocumentEntriesList(), - proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.toObject, includeInstance) + entriesList: jspb.Message.toObjectList(msg.getEntriesList(), + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.toObject, includeInstance), + lifecycle: (f = msg.getLifecycle()) && proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.toObject(includeInstance, f) }; if (includeInstance) { @@ -58099,23 +59825,23 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryRes /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.deserializeBinary = function(bytes) { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); - var msg = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory; - return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.deserializeBinaryFromReader(msg, reader); + var msg = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History; + return proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. - * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} msg The message object to deserialize into. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.deserializeBinaryFromReader = function(msg, reader) { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; @@ -58123,9 +59849,14 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryRes var field = reader.getFieldNumber(); switch (field) { case 1: - var value = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry; - reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.deserializeBinaryFromReader); - msg.addDocumentEntries(value); + var value = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.deserializeBinaryFromReader); + msg.addEntries(value); + break; + case 2: + var value = new proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.deserializeBinaryFromReader); + msg.setLifecycle(value); break; default: reader.skipField(); @@ -58140,9 +59871,9 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryRes * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.prototype.serializeBinary = function() { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); - proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.serializeBinaryToWriter(this, writer); + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.serializeBinaryToWriter(this, writer); return writer.getResultBuffer(); }; @@ -58150,86 +59881,94 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryRes /** * Serializes the given message to binary data (in protobuf wire * format), writing to the given BinaryWriter. - * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} message + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History} message * @param {!jspb.BinaryWriter} writer * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.serializeBinaryToWriter = function(message, writer) { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.serializeBinaryToWriter = function(message, writer) { var f = undefined; - f = message.getDocumentEntriesList(); + f = message.getEntriesList(); if (f.length > 0) { writer.writeRepeatedMessage( 1, f, - proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry.serializeBinaryToWriter + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry.serializeBinaryToWriter + ); + } + f = message.getLifecycle(); + if (f != null) { + writer.writeMessage( + 2, + f, + proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle.serializeBinaryToWriter ); } }; /** - * repeated DocumentHistoryEntry document_entries = 1; - * @return {!Array} + * repeated Entry entries = 1; + * @return {!Array} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.prototype.getDocumentEntriesList = function() { - return /** @type{!Array} */ ( - jspb.Message.getRepeatedWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry, 1)); +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.prototype.getEntriesList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry, 1)); }; /** - * @param {!Array} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} returns this + * @param {!Array} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.prototype.setDocumentEntriesList = function(value) { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.prototype.setEntriesList = function(value) { return jspb.Message.setRepeatedWrapperField(this, 1, value); }; /** - * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry=} opt_value + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry=} opt_value * @param {number=} opt_index - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry} + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.prototype.addDocumentEntries = function(opt_value, opt_index) { - return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntry, opt_index); +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.prototype.addEntries = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Entry, opt_index); }; /** * Clears the list making it empty but non-null. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} returns this + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory.prototype.clearDocumentEntriesList = function() { - return this.setDocumentEntriesList([]); +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.prototype.clearEntriesList = function() { + return this.setEntriesList([]); }; /** - * optional DocumentHistory document_history = 1; - * @return {?proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} + * optional Lifecycle lifecycle = 2; + * @return {?proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.getDocumentHistory = function() { - return /** @type{?proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory} */ ( - jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory, 1)); +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.prototype.getLifecycle = function() { + return /** @type{?proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle} */ ( + jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle, 2)); }; /** - * @param {?proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistory|undefined} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} returns this + * @param {?proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.Lifecycle|undefined} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.setDocumentHistory = function(value) { - return jspb.Message.setOneofWrapperField(this, 1, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.oneofGroups_[0], value); +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.prototype.setLifecycle = function(value) { + return jspb.Message.setWrapperField(this, 2, value); }; /** * Clears the message field making it undefined. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} returns this + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.clearDocumentHistory = function() { - return this.setDocumentHistory(undefined); +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.prototype.clearLifecycle = function() { + return this.setLifecycle(undefined); }; @@ -58237,7 +59976,44 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryRes * Returns whether this field is set. * @return {boolean} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.hasDocumentHistory = function() { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History.prototype.hasLifecycle = function() { + return jspb.Message.getField(this, 2) != null; +}; + + +/** + * optional History history = 1; + * @return {?proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.prototype.getHistory = function() { + return /** @type{?proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History} */ ( + jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History, 1)); +}; + + +/** + * @param {?proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.History|undefined} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1} returns this +*/ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.prototype.setHistory = function(value) { + return jspb.Message.setOneofWrapperField(this, 1, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.oneofGroups_[0], value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.prototype.clearHistory = function() { + return this.setHistory(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.prototype.hasHistory = function() { return jspb.Message.getField(this, 1) != null; }; @@ -58246,7 +60022,7 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryRes * optional Proof proof = 2; * @return {?proto.org.dash.platform.dapi.v0.Proof} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.getProof = function() { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.prototype.getProof = function() { return /** @type{?proto.org.dash.platform.dapi.v0.Proof} */ ( jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.Proof, 2)); }; @@ -58254,18 +60030,18 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryRes /** * @param {?proto.org.dash.platform.dapi.v0.Proof|undefined} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} returns this + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.setProof = function(value) { - return jspb.Message.setOneofWrapperField(this, 2, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.oneofGroups_[0], value); +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.prototype.setProof = function(value) { + return jspb.Message.setOneofWrapperField(this, 2, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.oneofGroups_[0], value); }; /** * Clears the message field making it undefined. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} returns this + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.clearProof = function() { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.prototype.clearProof = function() { return this.setProof(undefined); }; @@ -58274,7 +60050,7 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryRes * Returns whether this field is set. * @return {boolean} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.hasProof = function() { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.prototype.hasProof = function() { return jspb.Message.getField(this, 2) != null; }; @@ -58283,7 +60059,7 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryRes * optional ResponseMetadata metadata = 3; * @return {?proto.org.dash.platform.dapi.v0.ResponseMetadata} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.getMetadata = function() { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.prototype.getMetadata = function() { return /** @type{?proto.org.dash.platform.dapi.v0.ResponseMetadata} */ ( jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.ResponseMetadata, 3)); }; @@ -58291,18 +60067,18 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryRes /** * @param {?proto.org.dash.platform.dapi.v0.ResponseMetadata|undefined} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} returns this + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.setMetadata = function(value) { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.prototype.setMetadata = function(value) { return jspb.Message.setWrapperField(this, 3, value); }; /** * Clears the message field making it undefined. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0} returns this + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.clearMetadata = function() { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.prototype.clearMetadata = function() { return this.setMetadata(undefined); }; @@ -58311,7 +60087,7 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryRes * Returns whether this field is set. * @return {boolean} */ -proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.prototype.hasMetadata = function() { +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1.prototype.hasMetadata = function() { return jspb.Message.getField(this, 3) != null; }; @@ -58353,6 +60129,43 @@ proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.prototype.hasV0 = fun }; +/** + * optional GetDocumentHistoryResponseV1 v1 = 2; + * @return {?proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.prototype.getV1 = function() { + return /** @type{?proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1} */ ( + jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1, 2)); +}; + + +/** + * @param {?proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV1|undefined} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse} returns this +*/ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.prototype.setV1 = function(value) { + return jspb.Message.setOneofWrapperField(this, 2, proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.oneofGroups_[0], value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.prototype.clearV1 = function() { + return this.setV1(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.prototype.hasV1 = function() { + return jspb.Message.getField(this, 2) != null; +}; + + /** * Oneof group definitions for this message. Each group defines the field diff --git a/packages/dapi-grpc/protos/platform/v0/platform.proto b/packages/dapi-grpc/protos/platform/v0/platform.proto index 029185b3c4a..3e7b10ea011 100644 --- a/packages/dapi-grpc/protos/platform/v0/platform.proto +++ b/packages/dapi-grpc/protos/platform/v0/platform.proto @@ -2496,7 +2496,31 @@ message GetDocumentHistoryRequest { ]; // Only return results after this time in milliseconds bool prove = 7; // Flag to request a proof as the response } - oneof version { GetDocumentHistoryRequestV0 v0 = 1; } + // Reads the retained revisions of a historical document (a type with + // documentsKeepHistory), selected by time, revision, or a composite cursor. + message GetDocumentHistoryRequestV1 { + // Exclusive cursor returned with a page. Several revisions can share a + // block time, so resuming needs the revision as well as the time. + message Cursor { + uint64 time_ms = 1 [ jstype = JS_STRING ]; + uint64 revision = 2 [ jstype = JS_STRING ]; + } + bytes data_contract_id = 1; + string document_type_name = 2; + bytes document_id = 3; + google.protobuf.UInt32Value limit = 4; + bool prove = 5; + oneof filter { + uint64 start_at_ms = 6 [ jstype = JS_STRING ]; + Cursor start_after = 7; + uint64 start_at_revision = 8 [ jstype = JS_STRING ]; + uint64 revision = 9 [ jstype = JS_STRING ]; + } + } + oneof version { + GetDocumentHistoryRequestV0 v0 = 1; + GetDocumentHistoryRequestV1 v1 = 2; + } } message GetDocumentHistoryResponse { @@ -2522,7 +2546,46 @@ message GetDocumentHistoryResponse { ResponseMetadata metadata = 3; // Metadata about the blockchain state } - oneof version { GetDocumentHistoryResponseV0 v0 = 1; } + // A page of a historical document's retained revisions, with the + // document's lifecycle as of the same block. Only document types with + // documentsKeepHistory retain history; every field here describes such a + // historical document. + message GetDocumentHistoryResponseV1 { + // One retained revision of the historical document. + message Entry { + uint64 time_ms = 1 [ jstype = JS_STRING ]; + uint64 revision = 2 [ jstype = JS_STRING ]; + bytes document = 3; + } + // Where the historical document stands: still current, or gone with + // nothing retained. Later protocol versions add the states between. + message Lifecycle { + enum State { + ACTIVE = 0; + ABSENT = 1; + } + State state = 1; + // Revisions the history still retains for the document. + uint64 remaining_revisions = 2 [ jstype = JS_STRING ]; + } + // A page of retained revisions and the document's lifecycle as of the + // same block. + message History { + repeated Entry entries = 1; + Lifecycle lifecycle = 2; + } + oneof result { + History history = 1; + // One GroveDB proof authenticates the offset-paginated history page, + // current pointer, lifecycle reservation, and retained revision count. + Proof proof = 2; + } + ResponseMetadata metadata = 3; + } + oneof version { + GetDocumentHistoryResponseV0 v0 = 1; + GetDocumentHistoryResponseV1 v1 = 2; + } } message GetIdentityByPublicKeyHashRequest { diff --git a/packages/dapi-grpc/test/unit/documentHistoryWire.spec.js b/packages/dapi-grpc/test/unit/documentHistoryWire.spec.js new file mode 100644 index 00000000000..d25cee4c14d --- /dev/null +++ b/packages/dapi-grpc/test/unit/documentHistoryWire.spec.js @@ -0,0 +1,62 @@ +const assert = require('node:assert/strict'); +const nodeMessages = require('../../clients/platform/v0/nodejs/platform_protoc'); +const webMessages = require('../../clients/platform/v0/web/platform_pb'); +const protobufMessages = require('../../clients/platform/v0/nodejs/platform_pbjs'); +const driveMessages = require('../../clients/drive/v0/nodejs/drive_pbjs'); + +describe('document history versioned wire format', () => { + const requestWire = Buffer.from([0x0a, 6, 0x2a, 2, 8, 1, 0x38, 1]); + const responseWire = Buffer.from([0x0a, 10, 0x0a, 8, 0x0a, 6, 8, 1, 0x12, 2, 255, 255]); + + it('should preserve the offset wrapper and proof flag of a version 0 request', () => { + [nodeMessages, webMessages].forEach((messages) => { + const request = messages.GetDocumentHistoryRequest.deserializeBinary(requestWire); + assert.equal(request.getV0().getOffset().getValue(), 1); + assert.equal(request.getV0().getProve(), true); + assert.deepEqual(Buffer.from(request.serializeBinary()), requestWire); + }); + [protobufMessages, driveMessages].forEach((messages) => { + const Request = messages.org.dash.platform.dapi.v0.GetDocumentHistoryRequest; + const request = Request.decode(requestWire); + assert.equal(request.v0.offset.value, 1); + assert.equal(request.v0.prove, true); + assert.deepEqual(Buffer.from(Request.encode(request).finish()), requestWire); + }); + }); + + it('should preserve document bytes at field 2 of a version 0 history entry', () => { + [nodeMessages, webMessages].forEach((messages) => { + const response = messages.GetDocumentHistoryResponse.deserializeBinary(responseWire); + const entry = response.getV0().getDocumentHistory().getDocumentEntriesList()[0]; + assert.equal(entry.getDate(), '1'); + assert.deepEqual(Buffer.from(entry.getValue_asU8()), Buffer.from([255, 255])); + assert.deepEqual(Buffer.from(response.serializeBinary()), responseWire); + }); + [protobufMessages, driveMessages].forEach((messages) => { + const Response = messages.org.dash.platform.dapi.v0.GetDocumentHistoryResponse; + const response = Response.decode(responseWire); + const entry = response.v0.documentHistory.documentEntries[0]; + assert.equal(entry.date.toString(), '1'); + assert.deepEqual(Buffer.from(entry.value), Buffer.from([255, 255])); + assert.deepEqual(Buffer.from(Response.encode(response).finish()), responseWire); + }); + }); + it('should carry composite selectors in version 1 at outer field 2', () => { + const bytes = Buffer.from([0x12, 4, 0x28, 1, 0x40, 2]); + [nodeMessages, webMessages].forEach((messages) => { + const request = messages.GetDocumentHistoryRequest.deserializeBinary(bytes); + assert.equal(request.getV1().getProve(), true); + assert.equal(request.getV1().getStartAtRevision(), '2'); + assert.equal(request.hasV0(), false); + assert.deepEqual(Buffer.from(request.serializeBinary()), bytes); + }); + [protobufMessages, driveMessages].forEach((messages) => { + const Request = messages.org.dash.platform.dapi.v0.GetDocumentHistoryRequest; + const request = Request.decode(bytes); + assert.equal(request.v1.prove, true); + assert.equal(request.v1.startAtRevision.toString(), '2'); + assert.equal(request.v0, null); + assert.deepEqual(Buffer.from(Request.encode(request).finish()), bytes); + }); + }); +}); diff --git a/packages/dapi-grpc/tests/document_history_wire.rs b/packages/dapi-grpc/tests/document_history_wire.rs new file mode 100644 index 00000000000..a0dbf38c76f --- /dev/null +++ b/packages/dapi-grpc/tests/document_history_wire.rs @@ -0,0 +1,30 @@ +use dapi_grpc::platform::v0::{GetDocumentHistoryRequest, GetDocumentHistoryResponse}; +use dapi_grpc::Message; + +#[test] +fn should_decode_released_document_history_offset_and_prove_fields() { + // The offset wrapper occupies field 5; the proof flag occupies field 7. + let bytes = [0x0a, 6, 0x2a, 2, 8, 1, 0x38, 1]; + let request = GetDocumentHistoryRequest::decode(bytes.as_slice()) + .expect("a document history request with an offset must remain decodable"); + assert_eq!(request.encode_to_vec(), bytes); +} + +#[test] +fn should_decode_released_document_history_document_bytes() { + // Entry field 2 contains document bytes, including arbitrary non-varints. + let bytes = [0x0a, 10, 0x0a, 8, 0x0a, 6, 8, 1, 0x12, 2, 0xff, 0xff]; + let response = GetDocumentHistoryResponse::decode(bytes.as_slice()) + .expect("document history entries must preserve their document bytes"); + assert_eq!(response.encode_to_vec(), bytes); +} + +#[test] +fn should_keep_composite_document_history_on_its_own_version_tag() { + let bytes = [0x12, 4, 0x28, 1, 0x40, 2]; + let request = GetDocumentHistoryRequest::decode(bytes.as_slice()).unwrap(); + assert!( + matches!(&request.version, Some(dapi_grpc::platform::v0::get_document_history_request::Version::V1(v1)) if v1.prove) + ); + assert_eq!(request.encode_to_vec(), bytes); +} diff --git a/packages/dash-platform-queries/src/documents/document_history_query.rs b/packages/dash-platform-queries/src/documents/document_history_query.rs index 1e5fa27dc70..b1d032b47a3 100644 --- a/packages/dash-platform-queries/src/documents/document_history_query.rs +++ b/packages/dash-platform-queries/src/documents/document_history_query.rs @@ -1,6 +1,7 @@ //! Query type for retrieving document history. use dpp::prelude::Identifier; +pub use drive::query::document_history_drive_query::DocumentHistoryFilter; /// Query parameters for a document's historical revisions. #[derive(Debug, Clone, PartialEq, Eq, dash_platform_macros::Mockable)] @@ -12,10 +13,8 @@ pub struct DocumentHistoryQuery { pub document_type_name: String, /// Document ID. pub document_id: Identifier, - /// Exclusive lower-bound timestamp in milliseconds. - pub start_at_ms: u64, + /// Exactly one time cursor or revision filter. + pub filter: DocumentHistoryFilter, /// Maximum number of history entries to return. pub limit: Option, - /// Offset within the history query result. - pub offset: Option, } diff --git a/packages/js-evo-sdk/src/documents/facade.ts b/packages/js-evo-sdk/src/documents/facade.ts index 2a34c3afa37..5869c959085 100644 --- a/packages/js-evo-sdk/src/documents/facade.ts +++ b/packages/js-evo-sdk/src/documents/facade.ts @@ -73,14 +73,14 @@ export class DocumentsFacade { return w.getCompositeDocumentsWithProofInfo(query); } - async history(query: wasm.DocumentHistoryQuery): Promise> { + async history(query: wasm.DocumentHistoryQuery): Promise { const w = await this.sdk.getWasmSdkConnected(); return w.getDocumentHistory(query); } async historyWithProof( query: wasm.DocumentHistoryQuery, - ): Promise>> { + ): Promise> { const w = await this.sdk.getWasmSdkConnected(); return w.getDocumentHistoryWithProofInfo(query); } diff --git a/packages/js-evo-sdk/tests/unit/facades/documents.spec.ts b/packages/js-evo-sdk/tests/unit/facades/documents.spec.ts index ad75898807a..284dbcc8f47 100644 --- a/packages/js-evo-sdk/tests/unit/facades/documents.spec.ts +++ b/packages/js-evo-sdk/tests/unit/facades/documents.spec.ts @@ -73,7 +73,10 @@ describe('DocumentsFacade', () => { proof: {}, metadata: {}, }); - getDocumentHistoryStub = this.sinon.stub(wasmSdk, 'getDocumentHistory').resolves(new Map()); + getDocumentHistoryStub = this.sinon.stub(wasmSdk, 'getDocumentHistory').resolves({ + entries: [], + lifecycle: { state: 'ABSENT', remainingRevisions: BigInt(0) }, + }); getDocumentHistoryWithProofInfoStub = this.sinon.stub( wasmSdk, 'getDocumentHistoryWithProofInfo', @@ -168,12 +171,19 @@ describe('DocumentsFacade', () => { dataContractId: 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', documentTypeName: 'note', documentId: '4mZmxva49PBb7BE7srw9o3gixvDfj1dAx1K6z4A7P9Ah', - startAtMs: 1000, + startAfter: { timeMs: BigInt(1000), revision: BigInt(1) }, limit: 10, - offset: 1, }; - await client.documents.history(query); + const result = { + entries: [ + { timeMs: BigInt(1000), revision: BigInt(2), document }, + { timeMs: BigInt(1000), revision: BigInt(3), document }, + ], + lifecycle: { state: 'ACTIVE', remainingRevisions: BigInt(3) }, + }; + getDocumentHistoryStub.resolves(result); + expect(await client.documents.history(query)).to.equal(result); expect(getDocumentHistoryStub).to.be.calledOnceWithExactly(query); }); @@ -185,14 +195,49 @@ describe('DocumentsFacade', () => { dataContractId: 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', documentTypeName: 'note', documentId: '4mZmxva49PBb7BE7srw9o3gixvDfj1dAx1K6z4A7P9Ah', + revision: BigInt(2), }; - await client.documents.historyWithProof(query); + const result = { + data: { entries: [], lifecycle: { state: 'ABSENT', remainingRevisions: BigInt(0) } }, + proof: { grovedbProof: new Uint8Array([2]) }, + metadata: {}, + }; + getDocumentHistoryWithProofInfoStub.resolves(result); + expect(await client.documents.historyWithProof(query)).to.equal(result); expect(getDocumentHistoryWithProofInfoStub).to.be.calledOnceWithExactly(query); }); }); + (['history', 'historyWithProof'] as const).forEach((method) => { + it(`should forward a returned history entry unchanged as the ${method} cursor`, async () => { + const entry = { timeMs: BigInt(1000), revision: BigInt(2), document }; + const data = { entries: [entry], lifecycle: undefined }; + const stub = method === 'history' + ? getDocumentHistoryStub : getDocumentHistoryWithProofInfoStub; + stub.resolves(method === 'history' ? data : { data, proof: {}, metadata: {} }); + const query: wasmSDKPackage.DocumentHistoryQuery = { + dataContractId: 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec', + documentTypeName: 'note', + documentId: '4mZmxva49PBb7BE7srw9o3gixvDfj1dAx1K6z4A7P9Ah', + startAtMs: BigInt(0), + }; + const response = await client.documents[method](query); + const page = 'data' in response ? response.data : response; + const nextQuery: wasmSDKPackage.DocumentHistoryQuery = { + ...query, + startAtMs: undefined, + startAfter: page.entries[0], + }; + + await client.documents[method](nextQuery); + + expect(stub.secondCall).to.have.been.calledWithExactly(nextQuery); + expect(stub.secondCall.args[0].startAfter).to.equal(entry); + }); + }); + describe('get()', () => { it('should fetch a single document by ID', async () => { const contractId = 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec'; diff --git a/packages/rs-dapi-client/src/transport/grpc.rs b/packages/rs-dapi-client/src/transport/grpc.rs index c3fe14ffb6e..04b818836a0 100644 --- a/packages/rs-dapi-client/src/transport/grpc.rs +++ b/packages/rs-dapi-client/src/transport/grpc.rs @@ -519,6 +519,11 @@ impl_transport_request_grpc!( ); impl_transport_request_grpc!( + needs_protocol_version: |request| match &request.version { + // A 5.0 node does not know V1, and every node before protocol 15 refuses it. + Some(platform_proto::get_document_history_request::Version::V1(_)) => Some(PROTOCOL_VERSION_OF_5_1), + Some(platform_proto::get_document_history_request::Version::V0(_)) | None => None, + }; platform_proto::GetDocumentHistoryRequest, platform_proto::GetDocumentHistoryResponse, PlatformGrpcClient, diff --git a/packages/rs-dapi-client/tests/request_inventory.rs b/packages/rs-dapi-client/tests/request_inventory.rs index ae4f0ec9fa3..692136dbd7c 100644 --- a/packages/rs-dapi-client/tests/request_inventory.rs +++ b/packages/rs-dapi-client/tests/request_inventory.rs @@ -100,6 +100,12 @@ const ADDITIONS: &[(&str, Verdict)] = &[ "field GetIdentityByNonUniquePublicKeyHashRequest.v1 = 2 GetIdentityByNonUniquePublicKeyHashRequest.GetIdentityByNonUniquePublicKeyHashRequestV1", Verdict::Gate(14), ), + // A 5.0 node does not know V1, and every node before protocol 15 refuses it: the history + // layout it reads exists only from protocol 15. + ( + "field GetDocumentHistoryRequest.v1 = 2 GetDocumentHistoryRequest.GetDocumentHistoryRequestV1", + Verdict::Gate(15), + ), ( "field WaitForStateTransitionResultRequest.WaitForStateTransitionResultRequestV0.request_user_balance = 3 bool", Verdict::NoGate("a node that drops it answers without the balance, which the result allows"), diff --git a/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/perform_events_on_first_block_of_protocol_change/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/perform_events_on_first_block_of_protocol_change/mod.rs index fb8bc3b0e3d..7975c0d8d5b 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/perform_events_on_first_block_of_protocol_change/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/perform_events_on_first_block_of_protocol_change/mod.rs @@ -1,6 +1,7 @@ mod v0; mod v1; mod v2; +mod v3; #[cfg(test)] mod credit_pool_backfill_tests; @@ -49,6 +50,7 @@ impl Platform { /// - If the version is `2`, it calls `perform_events_on_first_block_of_protocol_change_v2`, which /// empties the contract cache, so no read is billed at a fee cached under the old fee /// schedule, and then runs v1. + /// - If the version is `3`, it runs version `2` and migrates retained histories when crossing into protocol 15. /// - If no version is specified (`None`), the function does nothing and returns `Ok(())`. /// - If a different version is specified, it returns an error indicating an unknown version mismatch. /// @@ -87,10 +89,17 @@ impl Platform { previous_protocol_version, platform_version, ), + Some(3) => self.perform_events_on_first_block_of_protocol_change_v3( + platform_state, + block_info, + transaction, + previous_protocol_version, + platform_version, + ), None => Ok(()), Some(version) => Err(Error::Execution(ExecutionError::UnknownVersionMismatch { method: "perform_events_on_first_block_of_protocol_change".to_string(), - known_versions: vec![0, 1, 2], + known_versions: vec![0, 1, 2, 3], received: version, })), } @@ -184,7 +193,7 @@ mod tests { received, })) => { assert_eq!(method, "perform_events_on_first_block_of_protocol_change"); - assert_eq!(known_versions, vec![0, 1, 2]); + assert_eq!(known_versions, vec![0, 1, 2, 3]); assert_eq!(received, 255); } _ => panic!("expected UnknownVersionMismatch error"), diff --git a/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/perform_events_on_first_block_of_protocol_change/v3/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/perform_events_on_first_block_of_protocol_change/v3/mod.rs new file mode 100644 index 00000000000..a19c956c275 --- /dev/null +++ b/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/perform_events_on_first_block_of_protocol_change/v3/mod.rs @@ -0,0 +1,341 @@ +use crate::error::Error; +use crate::platform_types::platform::Platform; +use crate::platform_types::platform_state::PlatformState; +use dpp::block::block_info::BlockInfo; +use dpp::version::{PlatformVersion, ProtocolVersion}; +use drive::grovedb::Transaction; + +impl Platform { + /// Clears stale contract fees and runs protocol activation events before migrating history. + pub(super) fn perform_events_on_first_block_of_protocol_change_v3( + &self, + platform_state: &PlatformState, + block_info: &BlockInfo, + transaction: &Transaction, + previous_protocol_version: ProtocolVersion, + platform_version: &PlatformVersion, + ) -> Result<(), Error> { + self.perform_events_on_first_block_of_protocol_change_v2( + platform_state, + block_info, + transaction, + previous_protocol_version, + platform_version, + )?; + // Any migration error deliberately halts this activation block for every + // validator; the shared transaction prevents a partial migration from + // committing. Its corruption checks are unreachable for valid pre-15 + // state and must never be downgraded to best-effort recovery. + if previous_protocol_version < 15 && platform_version.protocol_version >= 15 { + let stats = self + .drive + .migrate_document_history_storage(transaction, platform_version)?; + tracing::info!(?stats, "Migrated document history storage"); + } + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::test::helpers::setup::TestPlatformBuilder; + + use dpp::data_contract::accessors::v0::DataContractV0Getters; + use dpp::data_contract::document_type::accessors::{ + DocumentTypeV0Getters, DocumentTypeV2Getters, + }; + use dpp::data_contract::document_type::random_document::CreateRandomDocument; + use dpp::document::{DocumentV0Getters, DocumentV0Setters}; + use dpp::system_data_contracts::{load_system_data_contract, SystemDataContract}; + use dpp::tests::json_document::json_document_to_contract; + use drive::drive::{Drive, RootTree}; + use drive::grovedb::query_result_type::{PathKeyElementTrio, QueryResultType}; + use drive::grovedb::{PathQuery, Query, TransactionArg}; + use drive::query::document_history_drive_query::{ + DocumentHistoryDriveQuery, DocumentHistoryFilter, + }; + use drive::util::object_size_info::{DocumentAndContractInfo, DocumentInfo, OwnedDocumentInfo}; + + fn document_type_path(contract_id: &[u8], name: &str) -> Vec> { + vec![ + vec![RootTree::DataContractDocuments as u8], + contract_id.to_vec(), + vec![1], + name.as_bytes().to_vec(), + ] + } + + fn subtree_rows( + drive: &Drive, + path: Vec>, + transaction: TransactionArg, + version: &PlatformVersion, + ) -> Vec { + let query = PathQuery::new_unsized(path, Query::new_range_full()); + let (rows, _) = drive + .grove_get_raw_path_query( + &query, + transaction, + QueryResultType::QueryPathKeyElementTrioResultType, + &mut vec![], + &version.drive, + ) + .unwrap(); + let mut snapshot = vec![]; + for (path, key, element) in rows.to_path_key_elements() { + if element.is_any_tree() { + let mut child = path.clone(); + child.push(key.clone()); + snapshot.extend(subtree_rows(drive, child, transaction, version)); + } + snapshot.push((path, key, element)); + } + snapshot + } + + #[test] + fn should_preserve_activation_state_across_grove_versions() { + let old = PlatformVersion::get(14).unwrap(); + let latest = PlatformVersion::get(15).unwrap(); + let platform = TestPlatformBuilder::new() + .with_initial_protocol_version(14) + .build_with_mock_rpc() + .set_genesis_state(); + let state = platform.state.load(); + let dpns = load_system_data_contract(SystemDataContract::DPNS, old).unwrap(); + let history = json_document_to_contract(concat!(env!("CARGO_MANIFEST_DIR"), "/../rs-drive/tests/supporting_files/contract/dashpay/dashpay-contract-with-profile-history.json"), false, old).unwrap(); + platform + .drive + .apply_contract(&history, BlockInfo::default(), true, None, None, old) + .unwrap(); + let mut history_id = [0; 32]; + for (contract, name, revisions) in [ + (&dpns, "preorder", 1), + (&dpns, "domain", 1), + (&history, "contactInfo", 1), + (&history, "profile", 2), + ] { + let document_type = contract.document_type_for_name(name).unwrap(); + let mut document = document_type.random_document(Some(99), old).unwrap(); + document.set_created_at(document.created_at().map(|_| 2000)); + document.set_updated_at(document.updated_at().map(|_| 2000)); + document.set_transferred_at(document.transferred_at().map(|_| 2000)); + for revision in 1..=revisions { + document.set_revision(Some(revision)); + platform + .drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentInfo::DocumentRefInfo((&document, None)), + owner_id: None, + }, + contract, + document_type, + }, + true, + BlockInfo::default_with_time(2000 + revision), + true, + None, + old, + ) + .unwrap(); + } + if name == "profile" { + history_id = document.id().to_buffer(); + } + } + let domain_path = document_type_path(dpns.id().as_bytes(), "domain"); + let ordinary_path = document_type_path(history.id().as_bytes(), "contactInfo"); + let domain_before = subtree_rows(&platform.drive, domain_path.clone(), None, old); + let ordinary_before = subtree_rows(&platform.drive, ordinary_path.clone(), None, old); + let fresh = TestPlatformBuilder::new() + .with_initial_protocol_version(15) + .build_with_mock_rpc() + .set_genesis_state(); + let preorder_path = document_type_path(dpns.id().as_bytes(), "preorder"); + let registered = subtree_rows(&fresh.drive, preorder_path.clone(), None, latest); + let mut v4 = latest.clone(); + v4.drive.grove_version = old.drive.grove_version.clone(); + let mut roots = vec![]; + for (version, commit) in [(&v4, false), (latest, true)] { + platform.drive.cache.data_contracts.clear_block_cache(); + let transaction = platform.drive.grove.start_transaction(); + platform + .perform_events_on_first_block_of_protocol_change( + &state, + &BlockInfo::default_with_time(3000), + &transaction, + 14, + version, + ) + .unwrap(); + assert_eq!( + subtree_rows( + &platform.drive, + preorder_path.clone(), + Some(&transaction), + version + ), + registered, + "rebuilt type has registration layout" + ); + assert_eq!( + subtree_rows( + &platform.drive, + domain_path.clone(), + Some(&transaction), + version + ), + domain_before + ); + assert_eq!( + subtree_rows( + &platform.drive, + ordinary_path.clone(), + Some(&transaction), + version + ), + ordinary_before + ); + let contract = platform + .drive + .get_contract_with_fetch_info( + dpns.id().to_buffer(), + false, + Some(&transaction), + version, + ) + .unwrap() + .unwrap(); + let preorder = contract + .contract + .document_type_for_name("preorder") + .unwrap(); + assert!(preorder.indexes().contains_key("ownerAndNameHash")); + assert_eq!(preorder.documents_ttl_seconds(), Some(3600)); + let query = DocumentHistoryDriveQuery { + contract_id: history.id().to_buffer(), + document_type_name: "profile".into(), + document_id: history_id, + filter: DocumentHistoryFilter::StartAtTime(0), + limit: None, + }; + // V4 cannot serve the new page query; state migration itself must + // still produce exactly the same bytes as the selected engine. + let page = query + .execute_no_proof( + &platform.drive, + history.document_type_for_name("profile").unwrap(), + Some(&transaction), + latest, + ) + .unwrap(); + assert_eq!( + page.entries + .iter() + .map(|entry| entry.revision) + .collect::>(), + vec![1, 2] + ); + let root = platform + .drive + .grove + .root_hash(Some(&transaction), &version.drive.grove_version) + .unwrap() + .unwrap(); + assert_eq!( + hex::encode(root), + "6322587059f91602b9f4d32542cc9787a266ed8b83a25bd3ce8f17e000222f7d", + "activation includes the current system contracts and retained-history migration", + ); + roots.push(root); + if commit { + platform + .drive + .grove + .commit_transaction(transaction) + .unwrap() + .unwrap(); + } + } + assert_eq!(roots[0], roots[1]); + assert_eq!( + platform + .drive + .grove + .root_hash(None, &latest.drive.grove_version) + .unwrap() + .unwrap(), + roots[1] + ); + } + + #[test] + fn should_not_migrate_history_before_protocol_15() { + let platform_version = PlatformVersion::get(14).expect("protocol version 14 should exist"); + let platform = TestPlatformBuilder::new() + .with_initial_protocol_version(14) + .build_with_mock_rpc() + .set_genesis_state(); + let transaction = platform.drive.grove.start_transaction(); + let platform_state = platform.state.load(); + + platform + .perform_events_on_first_block_of_protocol_change_v3( + &platform_state, + &BlockInfo::default(), + &transaction, + 14, + platform_version, + ) + .expect("a protocol 14 transition must not run the protocol 15 migration"); + } + #[test] + fn should_leave_the_proposal_history_layout_created_before_migration_unchanged() { + let version = PlatformVersion::latest(); + let platform = TestPlatformBuilder::new() + .with_initial_protocol_version(14) + .build_with_mock_rpc() + .set_genesis_state(); + let fresh = TestPlatformBuilder::new() + .with_initial_protocol_version(15) + .build_with_mock_rpc() + .set_genesis_state(); + let contract = + load_system_data_contract(SystemDataContract::DecisionProposals, version).unwrap(); + let path = document_type_path(contract.id().as_bytes(), "proposal"); + let expected = subtree_rows(&fresh.drive, path.clone(), None, version); + let transaction = platform.drive.grove.start_transaction(); + platform + .perform_events_on_first_block_of_protocol_change( + &platform.state.load(), + &BlockInfo::default_with_time(3000), + &transaction, + 14, + version, + ) + .unwrap(); + assert_eq!( + subtree_rows(&platform.drive, path.clone(), Some(&transaction), version), + expected + ); + platform + .drive + .migrate_document_history_storage(&transaction, version) + .unwrap(); + assert_eq!( + subtree_rows(&platform.drive, path.clone(), Some(&transaction), version), + expected, + "the activation-created proposal already has the retained-history layout" + ); + platform + .drive + .grove + .commit_transaction(transaction) + .unwrap() + .unwrap(); + assert_eq!(subtree_rows(&platform.drive, path, None, version), expected); + } +} diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/keep_history.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/keep_history.rs index 1156f7cf83a..0e20011ba8e 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/keep_history.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/keep_history.rs @@ -13,6 +13,7 @@ use drive::util::storage_flags::StorageFlags; fn process_and_commit( platform: &mut TempPlatform, serialized: Vec, + block_info: BlockInfo, ) -> StateTransitionExecutionResult { let state = platform.state.load(); let version = state.current_platform_version().unwrap(); @@ -22,7 +23,7 @@ fn process_and_commit( .process_raw_state_transitions( &[serialized], &state, - &BlockInfo::default(), + &block_info, &transaction, version, false, @@ -39,26 +40,29 @@ fn process_and_commit( result.into_execution_results().remove(0) } -/// A persisted v13 contract and document survive the v14 boundary, a repair, -/// and a subsequent ordinary contract update. Both writes use signed raw -/// transitions so parser validation, config compatibility and Drive all run. +/// A contract registered while protocol 13 still accepted keep-history +/// types that can be deleted, and a document written under v14, survive the +/// v15 boundary, a repair, and a subsequent ordinary contract update. Both +/// writes use signed raw transitions so parser validation, config +/// compatibility and Drive all run. #[tokio::test] async fn should_repair_legacy_keep_history_contract_after_upgrade() { - let old_version = PlatformVersion::get(13).unwrap(); - let new_version = PlatformVersion::get(14).unwrap(); + let registered_version = PlatformVersion::get(13).unwrap(); + let old_version = PlatformVersion::get(14).unwrap(); + let new_version = PlatformVersion::get(15).unwrap(); let mut platform = TestPlatformBuilder::new() - .with_initial_protocol_version(13) + .with_initial_protocol_version(14) .build_with_mock_rpc() - .set_initial_state_structure(); + .set_genesis_state(); let (identity, signer, key) = setup_identity(&mut platform, 958, dash_to_credits!(0.5)); let mut contract = json_document_to_contract( "tests/supporting_files/contract/note/note-contract-keep-history-and-can-be-deleted.json", true, - old_version, + registered_version, ) .expect("released protocol 13 accepts the legacy schema with full validation"); contract.set_owner_id(identity.id()); - contract.set_config(DataContractConfig::default_for_version(old_version).unwrap()); + contract.set_config(DataContractConfig::default_for_version(registered_version).unwrap()); platform .drive .apply_contract( @@ -102,7 +106,11 @@ async fn should_repair_legacy_keep_history_contract_after_upgrade() { .await .unwrap(); assert_matches!( - process_and_commit(&mut platform, create.serialize_to_bytes().unwrap()), + process_and_commit( + &mut platform, + create.serialize_to_bytes().unwrap(), + BlockInfo::default(), + ), StateTransitionExecutionResult::SuccessfulExecution { .. } ); let query = DriveDocumentQuery::from_sql_expr( @@ -114,18 +122,34 @@ async fn should_repair_legacy_keep_history_contract_after_upgrade() { .unwrap(); let documents_before = platform .drive - .query_documents(query, None, false, None, None) + .query_documents(query, None, false, None, Some(14)) .unwrap() .documents() .to_vec(); assert_eq!(documents_before.len(), 1); let mut upgraded_state = platform.state.load().as_ref().clone(); - upgraded_state.set_current_protocol_version_in_consensus(14); - upgraded_state.set_next_epoch_protocol_version(14); + upgraded_state.set_current_protocol_version_in_consensus(15); + upgraded_state.set_next_epoch_protocol_version(15); + let migration = platform.drive.grove.start_transaction(); + platform + .perform_events_on_first_block_of_protocol_change( + &upgraded_state, + &BlockInfo::default(), + &migration, + 14, + new_version, + ) + .unwrap(); + platform + .drive + .grove + .commit_transaction(migration) + .value + .unwrap(); platform.state.store(std::sync::Arc::new(upgraded_state)); - // Re-reading the actual stored contract at v14 must bypass the parser's + // Re-reading the actual stored contract at v15 must bypass the parser's // creation-time rule; do not rely only on the pre-upgrade cached object. let fetched = platform .drive @@ -167,7 +191,11 @@ async fn should_repair_legacy_keep_history_contract_after_upgrade() { .await .unwrap(); assert_matches!( - process_and_commit(&mut platform, update.serialize_to_bytes().unwrap()), + process_and_commit( + &mut platform, + update.serialize_to_bytes().unwrap(), + BlockInfo::default(), + ), StateTransitionExecutionResult::SuccessfulExecution { .. }, "the repair must pass full validation and persist" ); @@ -200,7 +228,11 @@ async fn should_repair_legacy_keep_history_contract_after_upgrade() { .await .unwrap(); assert_matches!( - process_and_commit(&mut platform, update.serialize_to_bytes().unwrap()), + process_and_commit( + &mut platform, + update.serialize_to_bytes().unwrap(), + BlockInfo::default(), + ), StateTransitionExecutionResult::SuccessfulExecution { .. } ); @@ -226,7 +258,7 @@ async fn should_repair_legacy_keep_history_contract_after_upgrade() { .unwrap(); let documents_after = platform .drive - .query_documents(query, None, false, None, None) + .query_documents(query, None, false, None, Some(15)) .unwrap() .documents() .to_vec(); @@ -235,3 +267,667 @@ async fn should_repair_legacy_keep_history_contract_after_upgrade() { "repair must preserve existing documents" ); } + +/// A validator that skips protocol 14 crosses both rungs in one block: +/// the v14 transition (contract version items) and the v15 history +/// migration, dispatched through the public hook. +#[test] +fn should_migrate_history_when_skipping_from_protocol_13_to_15() { + use dpp::data_contract::DataContractFactory; + use dpp::system_data_contracts::SystemDataContract; + use drive::drive::document::paths::document_history_path; + use drive::query::document_history_drive_query::{ + DocumentHistoryDriveQuery, DocumentHistoryFilter, DocumentHistoryState, + }; + use drive::util::object_size_info::{DocumentAndContractInfo, DocumentInfo, OwnedDocumentInfo}; + + let registered_version = PlatformVersion::get(13).unwrap(); + let new_version = PlatformVersion::get(15).unwrap(); + let platform = TestPlatformBuilder::new() + .with_initial_protocol_version(13) + .build_with_mock_rpc() + .set_genesis_state(); + let contract = DataContractFactory::new(registered_version.protocol_version) + .unwrap() + .create_with_value_config( + [7; 32].into(), + 0, + platform_value!({ + "note": { + "type": "object", "documentsKeepHistory": true, "documentsMutable": true, + "canBeDeleted": false, + "properties": { "message": { "type": "string", "maxLength": 256, "position": 0 } }, + "required": ["message"], "additionalProperties": false, + "indices": [{"name": "owner", "properties": [{"$ownerId": "asc"}]}] + } + }), + None, + None, + ) + .unwrap() + .data_contract_owned(); + platform + .drive + .apply_contract( + &contract, + BlockInfo::default(), + true, + None, + None, + registered_version, + ) + .unwrap(); + let document_type = contract.document_type_for_name("note").unwrap(); + let mut document = document_type + .random_document_with_identifier_and_entropy( + &mut StdRng::seed_from_u64(61), + [9; 32].into(), + Bytes32([3; 32]), + DocumentFieldFillType::FillIfNotRequired, + DocumentFieldFillSize::AnyDocumentFillSize, + registered_version, + ) + .unwrap(); + document.set_revision(Some(1)); + platform + .drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentInfo::DocumentRefInfo((&document, None)), + owner_id: None, + }, + contract: &contract, + document_type, + }, + false, + BlockInfo::default_with_time(1000), + true, + None, + registered_version, + ) + .unwrap(); + document.set_revision(Some(2)); + document.set("message", "edited".into()); + platform + .drive + .update_document_for_contract( + &document, + &contract, + document_type, + None, + BlockInfo::default_with_time(2000), + true, + None, + None, + registered_version, + ) + .unwrap(); + let dpns_id = SystemDataContract::DPNS.id().to_buffer(); + assert_eq!( + platform + .drive + .fetch_contract_version(dpns_id, None, new_version) + .unwrap(), + None, + "a protocol 13 state has no contract version items" + ); + + let mut upgraded_state = platform.state.load().as_ref().clone(); + upgraded_state.set_current_protocol_version_in_consensus(15); + upgraded_state.set_next_epoch_protocol_version(15); + let transaction = platform.drive.grove.start_transaction(); + platform + .perform_events_on_first_block_of_protocol_change( + &upgraded_state, + &BlockInfo::default_with_time(3000), + &transaction, + 13, + new_version, + ) + .expect("a 13 to 15 crossing runs the 14 rung and the 15 migration"); + platform + .drive + .grove + .commit_transaction(transaction) + .value + .unwrap(); + + // The 14 rung ran: every registered system contract carries its version item. + assert!(platform + .drive + .fetch_contract_version(dpns_id, None, new_version) + .unwrap() + .is_some()); + // The 15 rung ran: both retained revisions moved to the history tree and + // the primary-key entry now points at the current document. + let history_path = + document_history_path(contract.id().as_slice(), "note", document.id().as_slice()); + let mut query = drive::grovedb::Query::new(); + query.insert_all(); + let entries = platform + .drive + .grove + .query_raw( + &drive::grovedb::PathQuery::new( + history_path, + drive::grovedb::SizedQuery::new(query, None, None), + ), + false, + true, + true, + drive::query::QueryResultType::QueryKeyElementPairResultType, + None, + &new_version.drive.grove_version, + ) + .value + .unwrap() + .0 + .to_key_elements(); + assert_eq!(entries.len(), 2); + assert!(entries.iter().all(|(key, _)| key.len() == 16)); + let primary_path = vec![ + vec![drive::drive::RootTree::DataContractDocuments as u8], + contract.id().to_vec(), + vec![1], + b"note".to_vec(), + vec![0], + ]; + let primary_entry = platform + .drive + .grove + .get_raw( + primary_path.as_slice().into(), + document.id().as_slice(), + None, + &new_version.drive.grove_version, + ) + .value + .unwrap(); + assert!( + matches!(primary_entry, drive::grovedb::Element::Reference(..)), + "{primary_entry:?}" + ); + let history = platform + .drive + .fetch_document_history( + &DocumentHistoryDriveQuery { + contract_id: contract.id().to_buffer(), + document_type_name: "note".into(), + document_id: document.id().to_buffer(), + filter: DocumentHistoryFilter::StartAtTime(0), + limit: None, + }, + document_type, + None, + new_version, + ) + .unwrap(); + assert_eq!( + history + .entries + .iter() + .map(|entry| (entry.time_ms, entry.revision)) + .collect::>(), + [(1000, 1), (2000, 2)] + ); + let lifecycle = history + .lifecycle + .expect("the history tree carries a lifecycle"); + assert_eq!(lifecycle.state, DocumentHistoryState::Active); + assert_eq!(lifecycle.remaining_revisions, 2); +} + +#[tokio::test] +async fn should_retain_replacements_transfers_prices_and_purchases_at_one_timestamp() { + for countable in [false, true] { + run_history_write_sequence(false, countable).await; + } +} + +#[tokio::test] +async fn should_keep_migrated_and_new_history_writable_through_signed_transitions() { + for countable in [false, true] { + run_history_write_sequence(true, countable).await; + } +} + +async fn run_history_write_sequence(migrated: bool, countable: bool) { + use dpp::data_contract::DataContractFactory; + use drive::query::document_history_drive_query::{ + DocumentHistoryDriveQuery, DocumentHistoryFilter, + }; + let version = PlatformVersion::get(15).unwrap(); + let initial_version = PlatformVersion::get(if migrated { 14 } else { 15 }).unwrap(); + let mut platform = TestPlatformBuilder::new() + .with_initial_protocol_version(initial_version.protocol_version) + .build_with_mock_rpc() + .set_genesis_state(); + let (owner, owner_signer, owner_key) = setup_identity(&mut platform, 958, dash_to_credits!(1)); + let (buyer, buyer_signer, buyer_key) = setup_identity(&mut platform, 450, dash_to_credits!(1)); + let contract = DataContractFactory::new(initial_version.protocol_version).unwrap().create_with_value_config(owner.id(), 0, platform_value!({ + "note": { + "type": "object", "documentsKeepHistory": true, "documentsMutable": true, + "canBeDeleted": false, "transferable": 1, "tradeMode": 1, "documentsCountable": countable, "documentsSummable": "amount", + "properties": { "message": { "type": "string", "maxLength": 256, "position": 0 }, "amount": {"type": "integer", "minimum": 0, "maximum": 4294967295i64, "position": 1} }, + "required": ["message", "amount"], "additionalProperties": false, + "indices": [{"name": "owner", "properties": [{"$ownerId": "asc"}]}] + } + }), None, None).unwrap().data_contract_owned(); + platform + .drive + .apply_contract( + &contract, + BlockInfo::default(), + true, + None, + None, + initial_version, + ) + .unwrap(); + let document_type = contract.document_type_for_name("note").unwrap(); + let mut rng = StdRng::seed_from_u64(937); + let entropy = Bytes32::random_with_rng(&mut rng); + let mut document = document_type + .random_document_with_identifier_and_entropy( + &mut rng, + owner.id(), + entropy, + DocumentFieldFillType::DoNotFillIfNotRequired, + DocumentFieldFillSize::AnyDocumentFillSize, + initial_version, + ) + .unwrap(); + document + .set_id_for_creation(document_type, &entropy.0, 1, initial_version) + .unwrap(); + document.set("amount", 100u64.into()); + let query = DocumentHistoryDriveQuery { + contract_id: contract.id().to_buffer(), + document_type_name: "note".into(), + document_id: document.id().to_buffer(), + filter: DocumentHistoryFilter::StartAtTime(0), + limit: None, + }; + for revision in 1..=5 { + let write_version = if migrated && revision <= 2 { + initial_version + } else { + version + }; + document.set_revision(Some(revision)); + let transition = match revision { + 1 => { + BatchTransition::new_document_creation_transition_from_document( + document.clone(), + document_type, + entropy.0, + &owner_key, + 1, + 0, + None, + &owner_signer, + write_version, + None, + ) + .await + } + 2 => { + document.set("message", "replaced".into()); + document.set("amount", 250u64.into()); + BatchTransition::new_document_replacement_transition_from_document( + document.clone(), + document_type, + &owner_key, + 2, + 0, + None, + &owner_signer, + write_version, + None, + ) + .await + } + 3 => { + BatchTransition::new_document_transfer_transition_from_document( + document.clone(), + document_type, + buyer.id(), + &owner_key, + 3, + 0, + None, + &owner_signer, + write_version, + None, + ) + .await + } + 4 => { + BatchTransition::new_document_update_price_transition_from_document( + document.clone(), + document_type, + 100, + &buyer_key, + 1, + 0, + None, + &buyer_signer, + write_version, + None, + ) + .await + } + 5 => { + BatchTransition::new_document_purchase_transition_from_document( + document.clone(), + document_type, + owner.id(), + 100, + &owner_key, + 4, + 0, + None, + &owner_signer, + write_version, + None, + ) + .await + } + _ => unreachable!(), + } + .unwrap(); + let mut block_info = BlockInfo::default(); + if migrated { + block_info.time_ms = if revision == 1 { 1 } else { 2 }; + } + assert_matches!( + process_and_commit( + &mut platform, + transition.serialize_to_bytes().unwrap(), + block_info, + ), + StateTransitionExecutionResult::SuccessfulExecution { .. } + ); + if migrated && revision == 2 { + let legacy_history = platform + .drive + .fetch_document_history_after_time( + query.contract_id, + document_type, + query.document_id, + None, + 0, + query.limit, + None, + initial_version, + ) + .unwrap(); + let legacy_proof = platform + .drive + .prove_document_history_after_time( + query.contract_id, + document_type, + query.document_id, + None, + 0, + query.limit, + None, + initial_version, + ) + .unwrap(); + assert_eq!( + legacy_history + .values() + .map(|document| document.revision().unwrap()) + .collect::>(), + vec![1, 2] + ); + let (_, verified_legacy) = drive::drive::Drive::verify_document_history_after_time( + &legacy_proof, + query.contract_id, + &query.document_type_name, + document_type, + query.document_id, + 0, + query.limit, + None, + initial_version, + ) + .unwrap(); + assert_eq!(verified_legacy, Some(legacy_history)); + + let mut upgraded = platform.state.load().as_ref().clone(); + upgraded.set_current_protocol_version_in_consensus(15); + upgraded.set_next_epoch_protocol_version(15); + let transaction = platform.drive.grove.start_transaction(); + platform + .perform_events_on_first_block_of_protocol_change( + &upgraded, + &BlockInfo::default(), + &transaction, + 14, + version, + ) + .unwrap(); + platform + .drive + .grove + .commit_transaction(transaction) + .value + .unwrap(); + platform.state.store(std::sync::Arc::new(upgraded)); + } + let primary_read_version = if migrated && revision == 1 { + initial_version + } else { + version + }; + let type_path = vec![ + vec![drive::drive::RootTree::DataContractDocuments as u8], + contract.id().to_vec(), + vec![1], + b"note".to_vec(), + ]; + let primary = platform + .drive + .grove + .get_raw( + type_path.as_slice().into(), + &[0], + None, + &primary_read_version.drive.grove_version, + ) + .value + .unwrap(); + let expected_sum = if revision == 1 { 100 } else { 250 }; + if countable { + assert!(matches!(primary, drive::grovedb::Element::CountSumTree(_, 1, sum, _) if sum == expected_sum), "one live document contributes its current amount after each signed action: {primary:?}"); + } else { + assert!( + matches!(primary, drive::grovedb::Element::SumTree(_, sum, _) if sum == expected_sum), + "only the current revision contributes to the primary sum: {primary:?}" + ); + } + if migrated && revision == 1 { + continue; + } + let history = platform + .drive + .fetch_document_history(&query, document_type, None, version) + .unwrap(); + let proof = platform + .drive + .prove_document_history(&query, document_type, None, version) + .unwrap(); + assert_eq!( + history.lifecycle.as_ref().unwrap().remaining_revisions, + revision + ); + assert_eq!( + history + .entries + .iter() + .map(|entry| entry.revision) + .collect::>(), + (1..=revision).collect::>() + ); + if migrated { + assert_eq!( + history + .entries + .iter() + .map(|entry| entry.time_ms) + .collect::>(), + (1..=revision) + .map(|entry_revision| if entry_revision == 1 { 1 } else { 2 }) + .collect::>() + ); + } else { + assert!(history.entries.iter().all(|entry| entry.time_ms == 0)); + } + let (_, verified) = + drive::drive::Drive::verify_document_history(&query, &proof, document_type, version) + .unwrap(); + assert_eq!(verified, history); + document = history.entries.last().unwrap().document.clone(); + assert_eq!( + document.owner_id(), + if [3, 4].contains(&revision) { + buyer.id() + } else { + owner.id() + } + ); + } + + if migrated { + let fresh_entropy = Bytes32::random_with_rng(&mut rng); + let mut fresh_document = document_type + .random_document_with_identifier_and_entropy( + &mut rng, + owner.id(), + fresh_entropy, + DocumentFieldFillType::DoNotFillIfNotRequired, + DocumentFieldFillSize::AnyDocumentFillSize, + version, + ) + .unwrap(); + fresh_document + .set_id_for_creation(document_type, &fresh_entropy.0, 5, version) + .unwrap(); + fresh_document.set("amount", 30u64.into()); + let fresh_query = DocumentHistoryDriveQuery { + contract_id: contract.id().to_buffer(), + document_type_name: "note".into(), + document_id: fresh_document.id().to_buffer(), + filter: DocumentHistoryFilter::StartAtTime(0), + limit: None, + }; + + for revision in 1..=2 { + fresh_document.set_revision(Some(revision)); + let transition = if revision == 1 { + BatchTransition::new_document_creation_transition_from_document( + fresh_document.clone(), + document_type, + fresh_entropy.0, + &owner_key, + 5, + 0, + None, + &owner_signer, + version, + None, + ) + .await + } else { + fresh_document.set("message", "fresh replacement".into()); + fresh_document.set("amount", 50u64.into()); + BatchTransition::new_document_replacement_transition_from_document( + fresh_document.clone(), + document_type, + &owner_key, + 6, + 0, + None, + &owner_signer, + version, + None, + ) + .await + } + .unwrap(); + assert_matches!( + process_and_commit( + &mut platform, + transition.serialize_to_bytes().unwrap(), + BlockInfo::default(), + ), + StateTransitionExecutionResult::SuccessfulExecution { .. } + ); + + let type_path = vec![ + vec![drive::drive::RootTree::DataContractDocuments as u8], + contract.id().to_vec(), + vec![1], + b"note".to_vec(), + ]; + let primary = platform + .drive + .grove + .get_raw( + type_path.as_slice().into(), + &[0], + None, + &version.drive.grove_version, + ) + .value + .unwrap(); + let expected_sum = if revision == 1 { 280 } else { 300 }; + if countable { + assert!( + matches!(primary, drive::grovedb::Element::CountSumTree(_, 2, sum, _) if sum == expected_sum), + "both migrated and new live documents contribute to count and sum: {primary:?}" + ); + } else { + assert!( + matches!(primary, drive::grovedb::Element::SumTree(_, sum, _) if sum == expected_sum), + "both migrated and new current revisions contribute to the primary sum: {primary:?}" + ); + } + + let history = platform + .drive + .fetch_document_history(&fresh_query, document_type, None, version) + .unwrap(); + let proof = platform + .drive + .prove_document_history(&fresh_query, document_type, None, version) + .unwrap(); + assert_eq!( + history.lifecycle.as_ref().unwrap().remaining_revisions, + revision + ); + assert_eq!( + history + .entries + .iter() + .map(|entry| entry.revision) + .collect::>(), + (1..=revision).collect::>() + ); + assert!(history.entries.iter().all(|entry| entry.time_ms == 0)); + let (_, verified) = drive::drive::Drive::verify_document_history( + &fresh_query, + &proof, + document_type, + version, + ) + .unwrap(); + assert_eq!(verified, history); + fresh_document = history.entries.last().unwrap().document.clone(); + assert_eq!(fresh_document.owner_id(), owner.id()); + } + } +} diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/shielded/nullifier_batch_guard.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/shielded/nullifier_batch_guard.rs index f1692876015..38309a0ddc3 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/shielded/nullifier_batch_guard.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/shielded/nullifier_batch_guard.rs @@ -731,7 +731,7 @@ async fn should_preserve_single_entry_full_processor_fees_and_result() { .value .unwrap() ), - "b9f5883991476eb6e01109ff5bf1057eab24b756170397d4d850e3e6e2c09a5b" + "a78e27312332ff597d9bf527c061cf59e69a6b51563e0343400bfbef6e596c03" ); assert_eq!( pool.platform @@ -2182,39 +2182,39 @@ async fn should_preserve_single_entry_actions_errors_operations_and_settled_stat let (expected_validation, expected_settled) = match case { "shield" => ( "6a823c2db94612652926e6b9c1ae7feec9c2547dfd4cfc4e474318da1c16d59c", - "7eea5d32409d3df173a4ec4f5e9b56d40d2cacfcea8cac49d05e170976a893df", + "26456b2f2674b799c518535bc540b10958ced63cf02ca24ffe3575d5069cbfee", ), "valid-payment" => ( "9388d5cf63c4a571b9fb009679e2e34d0b681acc88f0f5195e7287c7efbd92f7", - "2a7e8a57360fad775ab0411ed5f4e31db9bd3ac5948e3a33a21f11ee5fa2d93c", + "75eee0fb5505f957be07f65fd78158e36c451e10303c6b25a8d37ce799cebe81", ), "failed-payment" => ( "d9b5fe191841bea952494f2a45e3833f925f4d367a1937b2ef1235a1aa01f51e", - "00315213aa7c931f2304191465a0319c9dbcc280269216e63a3e0e60ca16b178", + "5ebbe8df6322d78e259cfbac017308edec9f0faac1c6ba137135474d0ff0c1ef", ), "within-bundle-repeat" => ( "8023e03a697a20f6a78396a05503a4bc583ca8f69e19bd7ee07a6ae0ce7be478", - "9402a3dfd81a098f9575011fc0f6e5cd2415f0527ea9c4f45a04daaae2ab6ce9", + "ffabe9541bddcbcfa55e223f2611e7aa4691d9bc43772c6b17e0305ed7d97121", ), "stored-repeat" => ( "05652ac85c972902e8c09d20a7d8586e17e9434a478b335da136ad85f73def01", - "68ecfa75165f58edcf7262697fddad9378492e71eb1b340c9683b6a08131bfb6", + "5205a8992fd53d30138484eb9f04e011a3b4c2f7a9fc464a04d6f1ce5ef34a63", ), "open-mint-group" => ( "5c68381297c9bf68c5e85ebe6bb9e0f1289e2c07718eecfb5e6773d6009455bb", - "5c5eb01b9f9fa0ceaa458746fdbb705e0a4aa573c8efeb0bc9f2f4d7c499e95f", + "b316371c068be93be5a58fce59c175ef7c6c32028103b4b031d4fe45a373ac16", ), "closing-mint-group" => ( "2cedc16732c76e0605b5f46085db3d69c12936a5af55a2a82f52ec9e9ca67e38", - "a09c353badac216e6897ae44bfa6d20038ba2b9ac8b607dcfb5824da4e9e1a3d", + "1e6d20b67fcefef863533d5d3d1b708c2b3a2044c5397c4e0a9efbb01722cac7", ), "open-burn-group" => ( "e664a045f020ff84de1ca98f364fbabccfc141ad46aa82c79491a340bb0db5f8", - "de8b6eab60c7a94da3470facf22c1225e09e58f3779f0982a87a36b6dffec48c", + "04722561bf7430db3765880d08ea128b11b249e39c1ed607c4013e0f3ff17e34", ), "closing-burn-group" => ( "93e1732286f168c4a91d2765931e181c5721bfca1bfd5f93b8baacca03e00b2b", - "bcd073ee886c1e0f07f316680756ee07ffd2961a0960090f685f25a8278c65ef", + "898114233f06416d17727a955501c2ba7154236af14b3e1671500759d4861336", ), _ => unreachable!("enumerated characterization case"), }; diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/yes_no_tests/decision_proposal_tests.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/yes_no_tests/decision_proposal_tests.rs index a438f3c7337..311c6e00904 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/yes_no_tests/decision_proposal_tests.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/yes_no_tests/decision_proposal_tests.rs @@ -4,6 +4,10 @@ //! result is recorded when it closes; nothing acts on it. use super::*; +use drive::query::document_history_drive_query::{ + DocumentHistoryDriveQuery, DocumentHistoryFilter, +}; + use crate::execution::validation::state_transition::state_transitions::tests::setup_identity; use dpp::data_contract::accessors::v0::DataContractV0Getters; use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters; @@ -773,19 +777,22 @@ async fn should_let_the_proposer_edit_its_text_for_a_day_and_keep_every_version( let history = platform .drive .fetch_document_history( - contract.id().to_buffer(), + &DocumentHistoryDriveQuery { + contract_id: contract.id().to_buffer(), + document_type_name: PROPOSAL_DOCUMENT_TYPE_NAME.to_string(), + document_id: document_id.to_buffer(), + filter: DocumentHistoryFilter::StartAtTime(0), + limit: None, + }, document_type, - document_id.to_buffer(), - None, - 0, - None, None, platform_version, ) .expect("expected the history"); let titles: Vec<&Value> = history - .values() - .filter_map(|version| version.get("title")) + .entries + .iter() + .filter_map(|version| version.document.get("title")) .collect(); assert_eq!( titles, diff --git a/packages/rs-drive-abci/src/query/document_history/fixtures/wire-v0-offset.bin b/packages/rs-drive-abci/src/query/document_history/fixtures/wire-v0-offset.bin new file mode 100644 index 00000000000..55f2e8dbef7 Binary files /dev/null and b/packages/rs-drive-abci/src/query/document_history/fixtures/wire-v0-offset.bin differ diff --git a/packages/rs-drive-abci/src/query/document_history/fixtures/wire-v0-proof.bin b/packages/rs-drive-abci/src/query/document_history/fixtures/wire-v0-proof.bin new file mode 100644 index 00000000000..87b63d0cd0b Binary files /dev/null and b/packages/rs-drive-abci/src/query/document_history/fixtures/wire-v0-proof.bin differ diff --git a/packages/rs-drive-abci/src/query/document_history/fixtures/wire-v0-unproved.bin b/packages/rs-drive-abci/src/query/document_history/fixtures/wire-v0-unproved.bin new file mode 100644 index 00000000000..cc7eee0af9b Binary files /dev/null and b/packages/rs-drive-abci/src/query/document_history/fixtures/wire-v0-unproved.bin differ diff --git a/packages/rs-drive-abci/src/query/document_history/mod.rs b/packages/rs-drive-abci/src/query/document_history/mod.rs index bccdcfa9fae..65662696fb6 100644 --- a/packages/rs-drive-abci/src/query/document_history/mod.rs +++ b/packages/rs-drive-abci/src/query/document_history/mod.rs @@ -9,6 +9,10 @@ use dapi_grpc::platform::v0::{GetDocumentHistoryRequest, GetDocumentHistoryRespo use dpp::version::PlatformVersion; mod v0; +mod v1; + +#[cfg(test)] +mod wire_tests; impl Platform { /// Querying of a document history. @@ -28,6 +32,7 @@ impl Platform { let feature_version = match &version { RequestVersion::V0(_) => 0, + RequestVersion::V1(_) => 1, }; if !feature_version_bounds.check_version(feature_version) { return Ok(QueryValidationResult::new_with_error( @@ -42,12 +47,18 @@ impl Platform { } match version { + RequestVersion::V1(request_v1) => { + let result = + self.query_document_history_v1(request_v1, platform_state, platform_version)?; + Ok(result.map(|response| GetDocumentHistoryResponse { + version: Some(ResponseVersion::V1(response)), + })) + } RequestVersion::V0(request_v0) => { let result = self.query_document_history_v0(request_v0, platform_state, platform_version)?; - - Ok(result.map(|response_v0| GetDocumentHistoryResponse { - version: Some(ResponseVersion::V0(response_v0)), + Ok(result.map(|response| GetDocumentHistoryResponse { + version: Some(ResponseVersion::V0(response)), })) } } diff --git a/packages/rs-drive-abci/src/query/document_history/v0/mod.rs b/packages/rs-drive-abci/src/query/document_history/v0/mod.rs index 683f3ed69fb..afaee71c255 100644 --- a/packages/rs-drive-abci/src/query/document_history/v0/mod.rs +++ b/packages/rs-drive-abci/src/query/document_history/v0/mod.rs @@ -29,7 +29,7 @@ impl Platform { document_id, limit, offset, - start_at_ms, + start_at_ms: start_after_ms, prove, }: GetDocumentHistoryRequestV0, platform_state: &PlatformState, @@ -104,12 +104,12 @@ impl Platform { } let response = if prove { - let proof = self.drive.prove_document_history( + let proof = self.drive.prove_document_history_after_time( contract_id.to_buffer(), document_type, document_id.to_buffer(), None, - start_at_ms, + start_after_ms, limit, offset, platform_version, @@ -123,12 +123,12 @@ impl Platform { metadata: Some(self.response_metadata_v0(platform_state, CheckpointUsed::Current)), } } else { - let documents = self.drive.fetch_document_history( + let documents = self.drive.fetch_document_history_after_time( contract_id.to_buffer(), document_type, document_id.to_buffer(), None, - start_at_ms, + start_after_ms, limit, offset, platform_version, @@ -231,7 +231,7 @@ mod tests { #[test] fn should_return_empty_document_history_page_without_error() { - let (platform, state, version) = setup_platform(None, Network::Testnet, None); + let (platform, state, version) = setup_platform(None, Network::Testnet, Some(14)); let contract = json_document_to_contract( concat!( env!("CARGO_MANIFEST_DIR"), diff --git a/packages/rs-drive-abci/src/query/document_history/v1/mod.rs b/packages/rs-drive-abci/src/query/document_history/v1/mod.rs new file mode 100644 index 00000000000..a6511221ea0 --- /dev/null +++ b/packages/rs-drive-abci/src/query/document_history/v1/mod.rs @@ -0,0 +1,161 @@ +use crate::error::{query::QueryError, Error}; +use crate::platform_types::{platform::Platform, platform_state::PlatformState}; +use crate::query::{response_metadata::CheckpointUsed, QueryValidationResult}; +use dapi_grpc::platform::v0::get_document_history_request::{ + get_document_history_request_v1::Filter, GetDocumentHistoryRequestV1, +}; +use dapi_grpc::platform::v0::get_document_history_response::{ + get_document_history_response_v1::{ + lifecycle::State, Entry, History, Lifecycle, Result as ResponseResult, + }, + GetDocumentHistoryResponseV1, +}; +use dpp::check_validation_result_with_data; +use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters; +use dpp::document::serialization_traits::DocumentPlatformConversionMethodsV0; +use dpp::validation::ValidationResult; +use dpp::version::PlatformVersion; +use drive::query::document_history_drive_query::{ + DocumentHistoryDriveQuery, DocumentHistoryFilter, DocumentHistoryState, +}; +use drive::query::refuse_a_private_document_type; +use drive::util::grove_operations::GroveDBToUse; + +impl Platform { + pub(super) fn query_document_history_v1( + &self, + request: GetDocumentHistoryRequestV1, + platform_state: &PlatformState, + platform_version: &PlatformVersion, + ) -> Result, Error> { + let contract_id = + check_validation_result_with_data!(request.data_contract_id.try_into().map_err(|_| { + QueryError::InvalidArgument("data_contract_id must be 32 bytes".to_owned()) + })); + let document_id = check_validation_result_with_data!(request + .document_id + .try_into() + .map_err(|_| QueryError::InvalidArgument("document_id must be 32 bytes".to_owned()))); + let filter = check_validation_result_with_data!(request.filter.ok_or_else(|| { + QueryError::InvalidArgument("exactly one history filter is required".to_owned()) + })); + let filter = match filter { + Filter::StartAtMs(time) => DocumentHistoryFilter::StartAtTime(time), + Filter::StartAfter(cursor) => DocumentHistoryFilter::StartAfter { + time_ms: cursor.time_ms, + revision: cursor.revision, + }, + Filter::StartAtRevision(revision) => DocumentHistoryFilter::StartAtRevision(revision), + Filter::Revision(revision) => DocumentHistoryFilter::Revision(revision), + }; + let limit = check_validation_result_with_data!(request + .limit + .map(u16::try_from) + .transpose() + .map_err(|_| QueryError::InvalidArgument("history limit out of bounds".to_owned()))); + let query = DocumentHistoryDriveQuery { + contract_id, + document_type_name: request.document_type_name, + document_id, + filter, + limit, + }; + check_validation_result_with_data!(query + .validate() + .map_err(|error| QueryError::InvalidArgument(error.to_string()))); + let fetched = self + .drive + .fetch_contract(contract_id, None, None, None, platform_version) + .value?; + let fetched = check_validation_result_with_data!( + fetched.ok_or_else(|| QueryError::NotFound("data contract not found".to_owned())) + ); + let contract = &fetched.contract; + let document_type = check_validation_result_with_data!(contract + .document_type_for_name(&query.document_type_name) + .map_err(|_| QueryError::NotFound("document type not found".to_owned()))); + if let Err(refusal) = refuse_a_private_document_type(document_type) { + return Ok(QueryValidationResult::new_with_error( + QueryError::InvalidArgument(refusal.to_string()), + )); + } + if !document_type.documents_keep_history() { + return Ok(QueryValidationResult::new_with_error( + QueryError::InvalidArgument("document type does not keep history".to_owned()), + )); + } + // A query Drive refuses (a revision filter over a gapped history, for + // one) is the caller's mistake and answers as an invalid argument; + // storage and corruption errors still propagate. + let result = if request.prove { + let proof = match self.drive.prove_document_history( + &query, + document_type, + None, + platform_version, + ) { + Ok(proved) => proved, + Err(drive::error::Error::Query(query_error)) => { + return Ok(QueryValidationResult::new_with_error(QueryError::Query( + query_error, + ))); + } + Err(error) => return Err(error.into()), + }; + // The signature authenticates the history proof root. + let proof = self + .response_proof_v0(platform_state, proof, GroveDBToUse::Current)? + .1; + ResponseResult::Proof(proof) + } else { + let history = match self.drive.fetch_document_history( + &query, + document_type, + None, + platform_version, + ) { + Ok(history) => history, + Err(drive::error::Error::Query(query_error)) => { + return Ok(QueryValidationResult::new_with_error(QueryError::Query( + query_error, + ))); + } + Err(error) => return Err(error.into()), + }; + let entries = history + .entries + .into_iter() + .map(|entry| { + Ok(Entry { + time_ms: entry.time_ms, + revision: entry.revision, + document: entry + .document + .serialize(document_type, contract, platform_version) + .map_err(Error::Protocol)?, + }) + }) + .collect::, Error>>()?; + ResponseResult::History(History { + entries, + lifecycle: history.lifecycle.map(|lifecycle| Lifecycle { + state: match lifecycle.state { + DocumentHistoryState::Active => State::Active, + DocumentHistoryState::Absent => State::Absent, + } as i32, + remaining_revisions: lifecycle.remaining_revisions, + }), + }) + }; + Ok(QueryValidationResult::new_with_data( + GetDocumentHistoryResponseV1 { + result: Some(result), + metadata: Some(self.response_metadata_v0(platform_state, CheckpointUsed::Current)), + }, + )) + } +} + +#[cfg(test)] +mod tests; diff --git a/packages/rs-drive-abci/src/query/document_history/v1/tests.rs b/packages/rs-drive-abci/src/query/document_history/v1/tests.rs new file mode 100644 index 00000000000..f5bf584c998 --- /dev/null +++ b/packages/rs-drive-abci/src/query/document_history/v1/tests.rs @@ -0,0 +1,632 @@ +use super::*; +use crate::query::tests::setup_platform; +use dapi_grpc::platform::v0::get_document_history_request::get_document_history_request_v1::Cursor; +use dapi_grpc::platform::v0::get_document_history_request::GetDocumentHistoryRequestV0; +use dapi_grpc::platform::v0::get_document_history_response::Version as ResponseVersion; +use dapi_grpc::platform::v0::{ + GetDocumentHistoryRequest, GetDocumentHistoryResponse, Proof, ResponseMetadata, +}; +use dpp::block::block_info::BlockInfo; +use dpp::block::extended_block_info::v0::{ExtendedBlockInfoV0, ExtendedBlockInfoV0Setters}; +use dpp::bls::SecretKey; +use dpp::dashcore::Network; +use dpp::data_contract::TokenConfiguration; +use dpp::document::{DocumentV0Getters, DocumentV0Setters}; +use dpp::prelude::{CoreBlockHeight, DataContract, Identifier}; +use dpp::serialization::PlatformSerializableWithPlatformVersion; +use dpp::tests::json_document::{json_document_to_contract, json_document_to_document}; +use drive::util::object_size_info::{DocumentAndContractInfo, DocumentInfo, OwnedDocumentInfo}; +use drive_proof_verifier::types::DocumentHistory; +use drive_proof_verifier::{ContextProvider, ContextProviderError, FromProof}; +use std::sync::Arc; +use tenderdash_abci::{ + proto::types::{CanonicalVote, SignedMsgType, StateId}, + signatures::{Hashable, Signable}, +}; + +struct Provider { + contract: Arc, + key: [u8; 48], +} +impl ContextProvider for Provider { + fn get_data_contract( + &self, + id: &Identifier, + _: &PlatformVersion, + ) -> Result>, ContextProviderError> { + Ok((id == &self.contract.id()).then(|| self.contract.clone())) + } + fn get_token_configuration( + &self, + _: &Identifier, + ) -> Result, ContextProviderError> { + Ok(None) + } + fn get_quorum_public_key( + &self, + _: u32, + _: [u8; 32], + _: u32, + ) -> Result<[u8; 48], ContextProviderError> { + Ok(self.key) + } + fn get_platform_activation_height(&self) -> Result { + Ok(1) + } +} + +fn signed_proof( + bytes: Vec, + root: [u8; 32], + metadata: &ResponseMetadata, + key: &SecretKey, + quorum_type: u32, +) -> Proof { + let state = StateId { + app_version: metadata.protocol_version as u64, + core_chain_locked_height: metadata.core_chain_locked_height, + time: metadata.time_ms, + app_hash: root.to_vec(), + height: metadata.height, + }; + let commit = CanonicalVote { + r#type: SignedMsgType::Precommit.into(), + block_id: vec![7; 32], + chain_id: metadata.chain_id.clone(), + height: metadata.height as i64, + round: 0, + state_id: state + .calculate_msg_hash(&metadata.chain_id, metadata.height as i64, 0) + .unwrap(), + }; + let digest = commit + .calculate_sign_hash( + &metadata.chain_id, + quorum_type.try_into().unwrap(), + &[9; 32], + metadata.height as i64, + 0, + ) + .unwrap(); + Proof { + grovedb_proof: bytes, + quorum_hash: vec![9; 32], + signature: key.sign(&digest).unwrap().to_bytes().to_vec(), + round: 0, + block_id_hash: vec![7; 32], + quorum_type, + } +} + +/// The proof a proved history response answers with; a proved response never +/// carries the history itself. +fn proof_mut(response: &mut GetDocumentHistoryResponseV1) -> &mut Proof { + match response.result.as_mut() { + Some(ResponseResult::Proof(proof)) => proof, + _ => panic!("a proved history query answers with a proof"), + } +} + +#[test] +fn should_round_trip_history_api_through_quorum_and_grove_proof_verification() { + history_api_proof_round_trip(false); +} + +#[test] +fn should_reject_legacy_proof_envelopes_in_history_v1_through_sdk() { + history_api_proof_round_trip(true); +} + +#[test] +fn should_verify_signed_legacy_history_from_protocol_14_with_protocol_15_client() { + let (platform, state, version) = setup_platform(None, Network::Testnet, Some(14)); + let mut state = state.as_ref().clone(); + let contract = json_document_to_contract( + concat!( + env!("CARGO_MANIFEST_DIR"), + "/../rs-drive/tests/supporting_files/contract/dashpay/dashpay-contract-with-profile-history.json" + ), + false, + version, + ) + .unwrap(); + platform + .drive + .apply_contract(&contract, BlockInfo::default(), true, None, None, version) + .unwrap(); + let document_type = contract.document_type_for_name("profile").unwrap(); + let mut document = json_document_to_document( + concat!( + env!("CARGO_MANIFEST_DIR"), + "/../rs-drive/tests/supporting_files/contract/dashpay/profile0.json" + ), + Some([8; 32].into()), + document_type, + version, + ) + .unwrap(); + for revision in 1..=3 { + document.set_revision(Some(revision)); + platform + .drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentInfo::DocumentRefInfo((&document, None)), + owner_id: None, + }, + contract: &contract, + document_type, + }, + true, + BlockInfo::default_with_time(revision * 1000), + true, + None, + version, + ) + .unwrap(); + } + let key = SecretKey::from_be_bytes(&[1; 32]).unwrap(); + let provider = Provider { + contract: Arc::new(contract.clone()), + key: key.public_key().to_bytes(), + }; + state.last_committed_block_info = Some( + ExtendedBlockInfoV0 { + basic_info: BlockInfo { + height: 42, + core_height: 12, + time_ms: 4000, + epoch: Default::default(), + }, + app_hash: [0; 32], + quorum_hash: [9; 32], + block_id_hash: [7; 32], + proposer_pro_tx_hash: [0; 32], + signature: [0; 96], + round: 0, + } + .into(), + ); + let metadata = platform.response_metadata_v0(&state, CheckpointUsed::Current); + assert_eq!(metadata.protocol_version, 14); + let root = platform + .drive + .grove + .root_hash(None, &version.drive.grove_version) + .value + .unwrap(); + let signed = signed_proof( + vec![], + root, + &metadata, + &key, + platform.config.validator_set.quorum_type as u32, + ); + let committed = state.last_committed_block_info.as_mut().unwrap(); + committed.set_app_hash(root); + committed.set_signature(signed.signature.try_into().unwrap()); + let request: GetDocumentHistoryRequest = GetDocumentHistoryRequestV0 { + data_contract_id: contract.id().to_vec(), + document_type_name: "profile".into(), + document_id: document.id().to_vec(), + limit: Some(2), + offset: None, + start_at_ms: 1000, + prove: true, + } + .into(); + let response = platform + .query_document_history(request.clone(), &state, version) + .unwrap() + .into_data() + .unwrap(); + assert!(matches!( + response.version.as_ref(), + Some(ResponseVersion::V0(_)) + )); + for client_version in [version, PlatformVersion::latest()] { + let history = DocumentHistory::maybe_from_proof( + request.clone(), + response.clone(), + Network::Testnet, + client_version, + &provider, + ) + .unwrap() + .unwrap(); + assert_eq!( + history + .entries + .iter() + .map(|entry| (entry.time_ms, entry.revision)) + .collect::>(), + vec![(2000, 2), (3000, 3)], + ); + assert_eq!(history.lifecycle, None); + } + if std::env::var_os("UPDATE_DOCUMENT_HISTORY_VECTORS").is_some() { + let vector = serde_json::json!({ + "contract": hex::encode(contract.serialize_to_bytes_with_platform_version(version).unwrap()), + "quorum_public_key": hex::encode(provider.key), + "request": request, + "response": response, + }); + let path = std::path::Path::new(env!("CARGO_MANIFEST_DIR")) + .join("../rs-sdk/tests/vectors/document_history/pv14_time.json"); + std::fs::write( + path, + format!("{}\n", serde_json::to_string(&vector).unwrap()), + ) + .unwrap(); + } +} + +fn history_api_proof_round_trip(gapped: bool) { + let (platform, state, version) = setup_platform(None, Network::Testnet, None); + let mut state = state.as_ref().clone(); + let contract = json_document_to_contract(concat!(env!("CARGO_MANIFEST_DIR"), "/../rs-drive/tests/supporting_files/contract/dashpay/dashpay-contract-with-profile-history.json"), false, version).unwrap(); + platform + .drive + .apply_contract(&contract, BlockInfo::default(), true, None, None, version) + .unwrap(); + let document_type = contract.document_type_for_name("profile").unwrap(); + let mut document = json_document_to_document( + concat!( + env!("CARGO_MANIFEST_DIR"), + "/../rs-drive/tests/supporting_files/contract/dashpay/profile0.json" + ), + Some([8; 32].into()), + document_type, + version, + ) + .unwrap(); + for revision in 1..=3 { + if gapped && revision == 2 { + continue; + } + document.set_revision(Some(revision)); + platform + .drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentInfo::DocumentRefInfo((&document, None)), + owner_id: None, + }, + contract: &contract, + document_type, + }, + true, + BlockInfo::default_with_time(2000), + true, + None, + version, + ) + .unwrap(); + } + let key = SecretKey::from_be_bytes(&[1; 32]).unwrap(); + let provider = Provider { + contract: Arc::new(contract.clone()), + key: key.public_key().to_bytes(), + }; + state.last_committed_block_info = Some( + dpp::block::extended_block_info::v0::ExtendedBlockInfoV0 { + basic_info: BlockInfo { + height: 42, + core_height: 12, + time_ms: 3000, + epoch: Default::default(), + }, + app_hash: [0; 32], + quorum_hash: [9; 32], + block_id_hash: [7; 32], + proposer_pro_tx_hash: [0; 32], + signature: [0; 96], + round: 0, + } + .into(), + ); + let metadata = platform.response_metadata_v0(&state, CheckpointUsed::Current); + let root = platform + .drive + .grove + .root_hash(None, &version.drive.grove_version) + .value + .unwrap(); + let signed = signed_proof( + vec![], + root, + &metadata, + &key, + platform.config.validator_set.quorum_type as u32, + ); + let committed = state.last_committed_block_info.as_mut().unwrap(); + committed.set_app_hash(root); + committed.set_signature(signed.signature.try_into().unwrap()); + if gapped { + for (wire_selector, filter) in [ + (Filter::Revision(3), DocumentHistoryFilter::Revision(3)), + ( + Filter::StartAtRevision(3), + DocumentHistoryFilter::StartAtRevision(3), + ), + ] { + let request = GetDocumentHistoryRequestV1 { + data_contract_id: contract.id().to_vec(), + document_type_name: "profile".into(), + document_id: document.id().to_vec(), + limit: None, + prove: true, + filter: Some(wire_selector), + }; + // Drive refuses revision reads over a gapped history; the handler + // must answer that as an invalid argument, not as a node error + // the client would retry. + for prove in [true, false] { + let mut refused = request.clone(); + refused.prove = prove; + let result = platform + .query_document_history_v1(refused, &state, version) + .expect("a refused revision read is a query error, not a node error"); + assert!(!result.is_valid()); + assert!( + matches!(result.errors.first(), Some(QueryError::Query(_))), + "prove={prove}: {:?}", + result.errors + ); + } + let mut time_request = request.clone(); + time_request.filter = Some(Filter::StartAtMs(0)); + let mut response = platform + .query_document_history_v1(time_request, &state, version) + .unwrap() + .into_data() + .unwrap(); + let query = DocumentHistoryDriveQuery { + contract_id: contract.id().to_buffer(), + document_type_name: "profile".into(), + document_id: document.id().to_buffer(), + filter, + limit: None, + }; + let proof = proof_mut(&mut response); + let bytes = platform + .drive + .grove_get_proved_path_query( + &query.construct_path_query(version).unwrap(), + None, + &mut vec![], + &version.drive, + ) + .unwrap(); + proof.grovedb_proof = drive::util::test_helpers::history_proof::downgrade_history_count( + &bytes, + Some(3), + version, + ); + let error = DocumentHistory::maybe_from_proof( + request.clone(), + response.clone(), + Network::Testnet, + version, + &provider, + ) + .expect_err("document history requires GroveDB v1 even with a valid quorum signature"); + assert!(matches!( + error, + drive_proof_verifier::Error::UnsupportedGroveDBProofVersion { .. } + )); + assert!(drive_proof_verifier::types::DocumentHistoryProofInfo::maybe_from_proof_with_metadata( + request, response, Network::Testnet, version, &provider, + ).is_err()); + } + return; + } + let selections = [ + ( + document.id().to_buffer(), + Filter::StartAtMs(2000), + DocumentHistoryFilter::StartAtTime(2000), + ), + ( + document.id().to_buffer(), + Filter::StartAfter(Cursor { + time_ms: 2000, + revision: 1, + }), + DocumentHistoryFilter::StartAfter { + time_ms: 2000, + revision: 1, + }, + ), + ( + document.id().to_buffer(), + Filter::Revision(2), + DocumentHistoryFilter::Revision(2), + ), + ( + document.id().to_buffer(), + Filter::StartAtRevision(65535), + DocumentHistoryFilter::StartAtRevision(65535), + ), + ( + document.id().to_buffer(), + Filter::StartAtRevision(65536), + DocumentHistoryFilter::StartAtRevision(65536), + ), + ( + [255; 32], + Filter::Revision(2), + DocumentHistoryFilter::Revision(2), + ), + ]; + for (id, wire_selector, filter) in selections { + let request = GetDocumentHistoryRequestV1 { + data_contract_id: contract.id().to_vec(), + document_type_name: "profile".into(), + document_id: id.to_vec(), + limit: None, + prove: true, + filter: Some(wire_selector), + }; + let request_v0 = request.clone(); + let response = platform + .query_document_history_v1(request.clone(), &state, version) + .unwrap() + .into_data() + .unwrap(); + let query = DocumentHistoryDriveQuery { + contract_id: contract.id().to_buffer(), + document_type_name: "profile".into(), + document_id: id, + limit: None, + filter, + }; + let expected = platform + .drive + .fetch_document_history(&query, document_type, None, version) + .unwrap(); + let request: GetDocumentHistoryRequest = request.into(); + let verify = |response: GetDocumentHistoryResponseV1| { + DocumentHistory::maybe_from_proof( + request.clone(), + GetDocumentHistoryResponse::from(response), + Network::Testnet, + version, + &provider, + ) + }; + let (exported, _, _) = + drive_proof_verifier::types::DocumentHistoryProofInfo::maybe_from_proof_with_metadata( + request.clone(), + GetDocumentHistoryResponse::from(response.clone()), + Network::Testnet, + version, + &provider, + ) + .unwrap(); + let exported = exported.unwrap(); + assert_eq!(exported.response, response); + assert_eq!( + exported + .verify(request.clone(), Network::Testnet, version, &provider) + .unwrap(), + Some(exported.history) + ); + if std::env::var_os("UPDATE_DOCUMENT_HISTORY_VECTORS").is_some() { + let name = match query.filter { + DocumentHistoryFilter::Revision(2) if id == document.id().to_buffer() => { + Some("pv15_revision.json") + } + DocumentHistoryFilter::StartAfter { + time_ms: 2000, + revision: 1, + } => Some("pv15_cursor.json"), + _ => None, + }; + if let Some(name) = name { + let vector = serde_json::json!({ + "contract": hex::encode(contract.serialize_to_bytes_with_platform_version(version).unwrap()), + "quorum_public_key": hex::encode(provider.key), + "request": request, + "response": GetDocumentHistoryResponse::from(response.clone()), + }); + let path = std::path::Path::new(env!("CARGO_MANIFEST_DIR")) + .join("../rs-sdk/tests/vectors/document_history") + .join(name); + std::fs::write( + path, + format!("{}\n", serde_json::to_string(&vector).unwrap()), + ) + .unwrap(); + } + } + let result = verify(response.clone()).unwrap().unwrap(); + assert_eq!(result.entries, expected.entries); + assert_eq!(result.lifecycle, expected.lifecycle.clone()); + // Without a proof the same query answers with the history itself. + let mut plain_request = request_v0.clone(); + plain_request.prove = false; + let plain = platform + .query_document_history_v1(plain_request, &state, version) + .unwrap() + .into_data() + .unwrap(); + let Some(ResponseResult::History(history)) = plain.result else { + panic!("an unproved history query answers with the history"); + }; + assert_eq!( + history + .entries + .iter() + .map(|entry| (entry.time_ms, entry.revision)) + .collect::>(), + expected + .entries + .iter() + .map(|entry| (entry.time_ms, entry.revision)) + .collect::>() + ); + let lifecycle = history + .lifecycle + .expect("the history carries its lifecycle"); + let expected_lifecycle = expected + .lifecycle + .as_ref() + .expect("pages of the history tree carry a lifecycle"); + assert_eq!( + lifecycle.remaining_revisions, + expected_lifecycle.remaining_revisions + ); + assert_eq!( + lifecycle.state, + match expected_lifecycle.state { + DocumentHistoryState::Active => State::Active, + DocumentHistoryState::Absent => State::Absent, + } as i32 + ); + let mut legacy = response.clone(); + let proof = proof_mut(&mut legacy); + proof.grovedb_proof = drive::util::test_helpers::history_proof::downgrade_history_count( + &proof.grovedb_proof, + None, + version, + ); + let error = verify(legacy) + .expect_err("count-offset history pages require a GroveDB v1 proof envelope"); + assert!(matches!( + error, + drive_proof_verifier::Error::UnsupportedGroveDBProofVersion { .. } + )); + let mut torn = response.clone(); + proof_mut(&mut torn).grovedb_proof.push(0); + assert!( + verify(torn).is_err(), + "a proof envelope with trailing bytes is not the proof the node produced" + ); + let mut bad_signature = response.clone(); + proof_mut(&mut bad_signature).signature[0] ^= 1; + assert!(verify(bad_signature).is_err()); + let mut missing = response.clone(); + proof_mut(&mut missing).grovedb_proof.clear(); + assert!(verify(missing).is_err()); + } +} + +#[test] +fn should_reject_missing_selectors_before_reading_state() { + let (platform, state, version) = setup_platform(None, Network::Testnet, None); + let request = GetDocumentHistoryRequestV1 { + data_contract_id: vec![1; 32], + document_type_name: "note".into(), + document_id: vec![2; 32], + filter: None, + limit: None, + prove: false, + }; + assert!(!platform + .query_document_history_v1(request, &state, version) + .unwrap() + .is_valid()); +} diff --git a/packages/rs-drive-abci/src/query/document_history/wire_tests.rs b/packages/rs-drive-abci/src/query/document_history/wire_tests.rs new file mode 100644 index 00000000000..e937546a4a6 --- /dev/null +++ b/packages/rs-drive-abci/src/query/document_history/wire_tests.rs @@ -0,0 +1,251 @@ +use super::*; +use crate::query::tests::setup_platform; +use dapi_grpc::platform::v0::Proof; +use dapi_grpc::Message; +use dpp::block::block_info::BlockInfo; +use dpp::dashcore::Network; +use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::document::serialization_traits::DocumentPlatformConversionMethodsV0; +use dpp::document::{DocumentV0Getters, DocumentV0Setters}; +use dpp::tests::json_document::{json_document_to_contract, json_document_to_document}; +use drive::drive::Drive; +use drive::util::object_size_info::{DocumentAndContractInfo, DocumentInfo, OwnedDocumentInfo}; + +// These independent transport types pin the timestamp/offset format. They do +// not depend on the generated definitions used by the server under test. +#[derive(Clone, PartialEq, prost::Message)] +struct ReleasedRequest { + #[prost(message, optional, tag = "1")] + v0: Option, +} + +#[derive(Clone, PartialEq, prost::Message)] +struct ReleasedRequestV0 { + #[prost(bytes = "vec", tag = "1")] + data_contract_id: Vec, + #[prost(string, tag = "2")] + document_type_name: String, + #[prost(bytes = "vec", tag = "3")] + document_id: Vec, + #[prost(message, optional, tag = "4")] + limit: Option, + #[prost(message, optional, tag = "5")] + offset: Option, + #[prost(uint64, tag = "6")] + start_at_ms: u64, + #[prost(bool, tag = "7")] + prove: bool, +} + +#[derive(Clone, PartialEq, prost::Message)] +struct ReleasedResponse { + #[prost(message, optional, tag = "1")] + v0: Option, +} + +#[derive(Clone, PartialEq, prost::Message)] +struct ReleasedResponseV0 { + #[prost(message, optional, tag = "1")] + document_history: Option, + #[prost(message, optional, tag = "2")] + proof: Option, +} + +#[derive(Clone, PartialEq, prost::Message)] +struct ReleasedHistory { + #[prost(message, repeated, tag = "1")] + document_entries: Vec, +} + +#[derive(Clone, PartialEq, prost::Message)] +struct ReleasedEntry { + #[prost(uint64, tag = "1")] + date: u64, + #[prost(bytes = "vec", tag = "2")] + value: Vec, +} + +#[test] +fn should_refuse_document_history_v0_after_activation_before_reading_state() { + let (platform, state, version) = setup_platform(None, Network::Testnet, None); + let result = platform + .query_document_history( + GetDocumentHistoryRequest { + version: Some(RequestVersion::V0(Default::default())), + }, + &state, + version, + ) + .unwrap(); + assert!( + matches!(&result.errors[0], QueryError::UnsupportedQueryVersion(name, 1, 1, protocol, 0) + if name == "document_history" && *protocol == version.protocol_version) + ); +} + +#[test] +fn should_refuse_document_history_v1_before_activation_before_reading_state() { + let (platform, state, version) = setup_platform(None, Network::Testnet, Some(14)); + let result = platform + .query_document_history( + GetDocumentHistoryRequest { + version: Some(RequestVersion::V1(Default::default())), + }, + &state, + version, + ) + .unwrap(); + assert!( + matches!(&result.errors[0], QueryError::UnsupportedQueryVersion(name, 0, 0, 14, 1) + if name == "document_history") + ); +} + +#[test] +fn should_serve_released_document_history_wire_requests_before_activation() { + let (platform, state, version) = setup_platform(None, Network::Testnet, Some(14)); + let contract = json_document_to_contract( + concat!(env!("CARGO_MANIFEST_DIR"), "/../rs-drive/tests/supporting_files/contract/dashpay/dashpay-contract-with-profile-history.json"), + false, + version, + ).unwrap(); + platform + .drive + .apply_contract(&contract, BlockInfo::default(), true, None, None, version) + .unwrap(); + let document_type = contract.document_type_for_name("profile").unwrap(); + let mut document = json_document_to_document( + concat!( + env!("CARGO_MANIFEST_DIR"), + "/../rs-drive/tests/supporting_files/contract/dashpay/profile0.json" + ), + Some([8; 32].into()), + document_type, + version, + ) + .unwrap(); + let mut expected = Vec::new(); + for (revision, time) in [(1, 1000), (2, 2000), (3, 3000)] { + document.set_revision(Some(revision)); + platform + .drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentInfo::DocumentRefInfo((&document, None)), + owner_id: None, + }, + contract: &contract, + document_type, + }, + true, + BlockInfo::default_with_time(time), + true, + None, + version, + ) + .unwrap(); + expected.push(( + time, + document + .serialize(document_type, &contract, version) + .unwrap(), + )); + } + for (prove, offset) in [ + (false, None), + (false, Some(0)), + (false, Some(1)), + (true, Some(0)), + ] { + let wire = ReleasedRequest { + v0: Some(ReleasedRequestV0 { + data_contract_id: contract.id().to_vec(), + document_type_name: "profile".to_owned(), + document_id: document.id().to_vec(), + limit: Some(2), + offset, + start_at_ms: 1000, + prove, + }), + } + .encode_to_vec(); + let request = GetDocumentHistoryRequest::decode(wire.as_slice()) + .expect("a timestamp/offset history client must remain wire compatible"); + let result = platform + .query_document_history(request, &state, version) + .unwrap(); + assert!(result.errors.is_empty(), "{:?}", result.errors); + let response = result.data.unwrap(); + let expected_wire: &[u8] = match (prove, offset.unwrap_or(0)) { + (true, _) => include_bytes!("fixtures/wire-v0-proof.bin"), + (false, 0) => include_bytes!("fixtures/wire-v0-unproved.bin"), + (false, _) => include_bytes!("fixtures/wire-v0-offset.bin"), + }; + assert_eq!(response.encode_to_vec(), expected_wire); + let released = ReleasedResponse::decode(response.encode_to_vec().as_slice()) + .unwrap() + .v0 + .unwrap(); + let expected = expected + .iter() + .skip(1 + offset.unwrap_or(0) as usize) + .take(2) + .cloned() + .collect::>(); + if prove { + let proof = released.proof.expect("a version 0 proof response"); + let (_, verified) = Drive::verify_document_history_after_time( + &proof.grovedb_proof, + contract.id().to_buffer(), + "profile", + document_type, + document.id().to_buffer(), + 1000, + Some(2), + Some(0), + version, + ) + .unwrap(); + assert_eq!( + verified + .unwrap() + .into_iter() + .map(|(time, document)| ( + time, + document + .serialize(document_type, &contract, version) + .unwrap() + )) + .collect::>(), + expected + ); + let path_query = Drive::fetch_document_history_query( + contract.id().to_buffer(), + document_type, + document.id().to_buffer(), + 1000, + Some(2), + Some(0), + version, + ) + .unwrap(); + let original_proof = platform + .drive + .grove_get_proved_path_query(&path_query, None, &mut Vec::new(), &version.drive) + .unwrap(); + assert_eq!(proof.grovedb_proof, original_proof); + } else { + assert_eq!( + released + .document_history + .unwrap() + .document_entries + .into_iter() + .map(|entry| (entry.date, entry.value)) + .collect::>(), + expected + ); + } + } +} diff --git a/packages/rs-drive-abci/src/query/shielded/encrypted_notes/v0/mod.rs b/packages/rs-drive-abci/src/query/shielded/encrypted_notes/v0/mod.rs index 31485ba8348..627d7c8d784 100644 --- a/packages/rs-drive-abci/src/query/shielded/encrypted_notes/v0/mod.rs +++ b/packages/rs-drive-abci/src/query/shielded/encrypted_notes/v0/mod.rs @@ -90,6 +90,7 @@ impl Platform { path: pool.pool_path_vec(), query: SizedQuery { query: Query { + offset: None, read_mode: None, limit: None, items: vec![QueryItem::Key(vec![SHIELDED_NOTES_KEY])], diff --git a/packages/rs-drive-abci/tests/document_outcome.rs b/packages/rs-drive-abci/tests/document_outcome.rs index c5f944de4b6..05ea5b674db 100644 --- a/packages/rs-drive-abci/tests/document_outcome.rs +++ b/packages/rs-drive-abci/tests/document_outcome.rs @@ -14,11 +14,17 @@ use dapi_grpc::platform::v0::{ use dapi_grpc::Message; use dpp::block::block_info::BlockInfo; use dpp::dashcore::Network; -use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::data_contract::accessors::v0::{DataContractV0Getters, DataContractV0Setters}; +use dpp::data_contract::config::moderation::{ + ContractModerationConfig, ContractModerationReason, ContractModerators, +}; +use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters; use dpp::data_contract::document_type::random_document::CreateRandomDocument; +use dpp::data_contract::schema::DataContractSchemaMethodsV0; use dpp::data_contract::TokenConfiguration; use dpp::document::{DocumentV0Getters, DocumentV0Setters}; use dpp::identity::accessors::IdentityGettersV0; +use dpp::platform_value::platform_value; use dpp::prelude::{CoreBlockHeight, DataContract, Identifier, Identity}; use dpp::serialization::{PlatformSerializable, PlatformSerializableWithPlatformVersion}; use dpp::state_transition::batch_transition::batched_transition::document_transition::DocumentTransition; @@ -28,9 +34,12 @@ use dpp::state_transition::batch_transition::document_create_transition::{ DocumentCreateTransition, DocumentCreateTransitionV0, }; use dpp::state_transition::batch_transition::{BatchTransition, BatchTransitionV0}; +use dpp::state_transition::contract_user_moderation_transition::v0::ContractUserModerationTransitionV0; +use dpp::state_transition::contract_user_moderation_transition::ContractUserModerationAction; use dpp::state_transition::proof_result::StateTransitionProofOutcome; use dpp::state_transition::StateTransition; use dpp::tests::fixtures::get_dpns_data_contract_fixture; +use dpp::tests::json_document::json_document_to_contract; use dpp::version::PlatformVersion; use drive::util::object_size_info::DocumentInfo::DocumentRefInfo; use drive::util::object_size_info::{DocumentAndContractInfo, OwnedDocumentInfo}; @@ -38,6 +47,7 @@ use drive::util::test_helpers::setup::setup_drive_with_initial_state_structure; use drive_proof_verifier::{ContextProvider, ContextProviderError, FromProof}; use platform_version::version::mocks::v2_test::TEST_PROTOCOL_VERSION_2; use signed_response::{signed, Provider, NEWER_PROTOCOL_VERSION}; +use std::collections::BTreeMap; use std::sync::Arc; /// The first protocol whose document proofs carry the owner balance. Proofs made with @@ -91,19 +101,88 @@ fn fixture_signed_as( BroadcastStateTransitionRequest, WaitForStateTransitionResultResponse, ContractProvider, +) { + fixture_signed_as_for_document(producer, proof_version, signed_version, false, false) +} + +fn fixture_signed_as_for_document( + producer: u32, + proof_version: u32, + signed_version: u32, + keeps_history: bool, + moderated: bool, +) -> ( + BroadcastStateTransitionRequest, + WaitForStateTransitionResultResponse, + ContractProvider, ) { let producer = PlatformVersion::get(producer).unwrap(); let drive = setup_drive_with_initial_state_structure(Some(producer)); - let contract = get_dpns_data_contract_fixture( - Some(Identifier::new([4; 32])), - 0, - producer.protocol_version, - ) - .data_contract_owned(); + let (mut contract, document_type_name) = if keeps_history { + ( + json_document_to_contract( + concat!( + env!("CARGO_MANIFEST_DIR"), + "/../rs-drive/tests/supporting_files/contract/dashpay/dashpay-contract-with-profile-history.json" + ), + false, + producer, + ) + .unwrap(), + "profile", + ) + } else { + ( + get_dpns_data_contract_fixture( + Some(Identifier::new([4; 32])), + 0, + producer.protocol_version, + ) + .data_contract_owned(), + "preorder", + ) + }; + let owner = Identity::random_identity(2, Some(17), producer).unwrap(); + if moderated { + contract.set_owner_id(owner.id()); + contract.set_config(contract.config().clone().with_moderation(Some( + ContractModerationConfig { + banlist: false, + suspensions: false, + warnings: false, + moderators: ContractModerators::ContractOwner, + }, + ))); + let mut schema = contract + .document_type_for_name(document_type_name) + .unwrap() + .schema() + .clone(); + schema + .insert("canBeDeleted".to_string(), false.into()) + .unwrap(); + schema + .insert( + "indices".to_string(), + platform_value!([ + {"name": "ownerId", "properties": [{"$ownerId": "asc"}], "unique": true}, + {"name": "ownerIdUpdatedAt", "properties": [{"$ownerId": "asc"}, {"$updatedAt": "asc"}]} + ]), + ) + .unwrap(); + schema + .insert( + "moderatorAbilities".to_string(), + platform_value!({"changeFields": ["publicMessage"]}), + ) + .unwrap(); + contract + .set_document_schema(document_type_name, schema, true, &mut vec![], producer) + .unwrap(); + } drive .insert_contract(&contract, BlockInfo::default(), true, None, producer) .unwrap(); - let owner = Identity::random_identity(2, Some(17), producer).unwrap(); drive .add_new_identity( owner.clone(), @@ -114,9 +193,13 @@ fn fixture_signed_as( producer, ) .unwrap(); - let document_type = contract.document_type_for_name("preorder").unwrap(); + let document_type = contract.document_type_for_name(document_type_name).unwrap(); + assert_eq!(document_type.documents_keep_history(), keeps_history); let mut document = document_type.random_document(Some(99), producer).unwrap(); document.set_owner_id(owner.id()); + if moderated { + document.properties_mut().remove("publicMessage"); + } drive .add_document_for_contract( DocumentAndContractInfo { @@ -134,23 +217,59 @@ fn fixture_signed_as( producer, ) .unwrap(); - let transition = StateTransition::Batch(BatchTransition::V0(BatchTransitionV0 { - owner_id: owner.id(), - transitions: vec![DocumentTransition::Create(DocumentCreateTransition::V0( - DocumentCreateTransitionV0 { - base: DocumentBaseTransition::V0(DocumentBaseTransitionV0 { - id: document.id(), - identity_contract_nonce: 1, - document_type_name: "preorder".into(), - data_contract_id: contract.id(), - }), - entropy: [100; 32], - data: document.properties().clone(), - prefunded_voting_balance: None, + let transition = if moderated { + document.set_revision(Some(2)); + document.set("publicMessage", "changed by a moderator".into()); + document.set_moderated_at(Some(2000)); + document.set_moderated_by(Some(owner.id())); + drive + .update_document_for_contract( + &document, + &contract, + document_type, + Some(owner.id().to_buffer()), + BlockInfo::default_with_time(2000), + true, + None, + None, + producer, + ) + .unwrap(); + ContractUserModerationTransitionV0 { + owner_id: owner.id(), + data_contract_id: contract.id(), + identity_contract_nonce: 2, + action: ContractUserModerationAction::ChangeDocumentFields { + document_type_name: document_type_name.into(), + document_id: document.id(), + fields: BTreeMap::from([( + "publicMessage".to_string(), + "changed by a moderator".into(), + )]), + reason: ContractModerationReason::from_text("updated message"), }, - ))], - ..Default::default() - })); + ..Default::default() + } + .into() + } else { + StateTransition::Batch(BatchTransition::V0(BatchTransitionV0 { + owner_id: owner.id(), + transitions: vec![DocumentTransition::Create(DocumentCreateTransition::V0( + DocumentCreateTransitionV0 { + base: DocumentBaseTransition::V0(DocumentBaseTransitionV0 { + id: document.id(), + identity_contract_nonce: 1, + document_type_name: document_type_name.into(), + data_contract_id: contract.id(), + }), + entropy: [100; 32], + data: document.properties().clone(), + prefunded_voting_balance: None, + }, + ))], + ..Default::default() + })) + }; let bytes = drive .prove_state_transition( &transition, @@ -221,6 +340,101 @@ fn should_verify_signed_older_document_outcome_with_current_verifier_security() ); } } + +#[test] +fn should_verify_history_document_outcomes_using_the_signed_producers_layout() { + let latest = PlatformVersion::latest().protocol_version; + let mut failures = Vec::new(); + for (producer, verifier) in [(13, latest), (14, latest), (latest, 14)] { + let (request, response, provider) = + fixture_signed_as_for_document(producer, producer, producer, true, false); + let same_version = StateTransitionProofOutcome::maybe_from_proof( + request.clone(), + response.clone(), + Network::Testnet, + PlatformVersion::get(producer).unwrap(), + &provider, + ) + .expect("the history proof verifies with its producer's layout") + .expect("the signed response carries an outcome"); + assert!(same_version.is_execution_proved()); + assert_eq!(same_version.owner_balance().is_some(), producer >= 14); + + match StateTransitionProofOutcome::maybe_from_proof( + request, + response, + Network::Testnet, + PlatformVersion::get(verifier).unwrap(), + &provider, + ) { + Ok(Some(outcome)) => { + assert!(outcome.is_execution_proved()); + assert_eq!(outcome.owner_balance(), same_version.owner_balance()); + assert_eq!(outcome.into_result(), same_version.into_result()); + } + other => failures.push(format!( + "producer PV{producer}, verifier PV{verifier}: {other:?}" + )), + } + } + assert!(failures.is_empty(), "{}", failures.join("\n")); +} + +#[test] +fn should_verify_history_moderation_outcomes_using_the_signed_producers_layout() { + let latest = PlatformVersion::latest().protocol_version; + let mut failures = Vec::new(); + for (producer, verifier) in [(14, latest), (latest, 14)] { + let (request, response, provider) = + fixture_signed_as_for_document(producer, producer, producer, true, true); + let same_version = StateTransitionProofOutcome::maybe_from_proof( + request.clone(), + response.clone(), + Network::Testnet, + PlatformVersion::get(producer).unwrap(), + &provider, + ) + .expect("the changed history document verifies with its producer's layout") + .expect("the signed moderation response carries an outcome"); + assert!(!same_version.is_execution_proved()); + assert!(same_version.owner_balance().is_some()); + + match StateTransitionProofOutcome::maybe_from_proof( + request.clone(), + response.clone(), + Network::Testnet, + PlatformVersion::get(verifier).unwrap(), + &provider, + ) { + Ok(Some(outcome)) => assert_eq!(outcome, same_version), + other => failures.push(format!( + "moderation producer PV{producer}, verifier PV{verifier}: {other:?}" + )), + } + + let mut verifier = PlatformVersion::get(verifier).unwrap().clone(); + verifier.drive.methods.verify.single_document.verify_proof = 255; + let error = StateTransitionProofOutcome::maybe_from_proof( + request, + response, + Network::Testnet, + &verifier, + &provider, + ) + .expect_err("moderation verification must retain the caller's verifier tables"); + assert!( + matches!( + &error, + drive_proof_verifier::Error::DriveError { error } + if error.contains("SingleDocumentDriveQuery::verify_proof") + && error.contains("received: 255") + ), + "{error}" + ); + } + assert!(failures.is_empty(), "{}", failures.join("\n")); +} + /// Once a newer protocol activates, clients built before it keep verifying outcomes with /// the newest rules they know instead of refusing every result until they upgrade. #[test] diff --git a/packages/rs-drive-abci/tests/query_request_errors/offset_controls.rs b/packages/rs-drive-abci/tests/query_request_errors/offset_controls.rs index f98252d9abb..915d207fdd0 100644 --- a/packages/rs-drive-abci/tests/query_request_errors/offset_controls.rs +++ b/packages/rs-drive-abci/tests/query_request_errors/offset_controls.rs @@ -1,7 +1,7 @@ -use dapi_grpc::platform::v0::get_document_history_response::get_document_history_response_v0::Result as DocumentHistoryResult; use dapi_grpc::platform::v0::get_contested_resource_identity_votes_response::get_contested_resource_identity_votes_response_v0::Result as IdentityVotesResult; use super::offsets::{history_contract, search_kind}; use super::*; +use dapi_grpc::platform::v0::get_document_history_request::get_document_history_request_v1::Filter as DocumentHistoryRequestFilter; use dpp::data_contract::accessors::v0::DataContractV0Setters; use dpp::data_contract::document_type::random_document::CreateRandomDocument; use dpp::document::serialization_traits::DocumentPlatformConversionMethodsV0; @@ -20,6 +20,7 @@ use drive::drive::votes::resolved::vote_polls::contested_document_resource_vote_ use drive::drive::votes::storage_form::contested_document_resource_storage_form::ContestedDocumentResourceVoteStorageForm; use drive::query::contested_resource_votes_given_by_identity_query::ContestedResourceVotesGivenByIdentityQuery; use drive::query::contract_lookup_fn_for_contract; +use drive::query::document_history_drive_query::{DocumentHistoryDriveQuery, DocumentHistoryFilter}; use drive::util::object_size_info::DataContractOwnedResolvedInfo; use drive::util::object_size_info::DocumentInfo::DocumentRefInfo; use drive::util::object_size_info::{DocumentAndContractInfo, OwnedDocumentInfo}; @@ -106,11 +107,15 @@ async fn should_preserve_supported_offset_pages_and_original_proof_roots() { history_document.set_revision(Some(1)); let document_id = history_document.id().to_buffer(); let mut expected_documents = BTreeMap::new(); - for (time, display_name) in [ + for (index, (time, display_name)) in [ (1000, "Offset one"), (2000, "Offset two"), (3000, "Offset three"), - ] { + ] + .into_iter() + .enumerate() + { + history_document.set_revision(Some(index as u64 + 1)); history_document.set("displayName", display_name.into()); expected_documents.insert(time, history_document.clone()); fixture @@ -383,48 +388,80 @@ async fn should_preserve_supported_offset_pages_and_original_proof_roots() { .take(2) .map(|(time, document)| (*time, document.clone())) .collect::>(); + let start_at_ms = expected_page.keys().next().copied().unwrap_or(0); + let history_query = DocumentHistoryDriveQuery { + contract_id: history_contract.id().to_buffer(), + document_type_name: "profile".to_owned(), + document_id, + filter: DocumentHistoryFilter::StartAtTime(start_at_ms), + limit: Some(2), + }; + let legacy = version + .drive_abci + .query + .document_history + .default_current_version + == 0; + let request: wire::GetDocumentHistoryRequest = if legacy { + wire::get_document_history_request::GetDocumentHistoryRequestV0 { + data_contract_id: history_contract.id().to_vec(), + document_type_name: "profile".to_owned(), + document_id: document_id.to_vec(), + limit: Some(2), + offset, + start_at_ms: 0, + prove, + } + .into() + } else { + wire::get_document_history_request::GetDocumentHistoryRequestV1 { + data_contract_id: history_contract.id().to_vec(), + document_type_name: "profile".to_owned(), + document_id: document_id.to_vec(), + limit: Some(2), + filter: Some(DocumentHistoryRequestFilter::StartAtMs(start_at_ms)), + prove, + } + .into() + }; let response = client - .get_document_history(wire::GetDocumentHistoryRequest::from( - wire::get_document_history_request::GetDocumentHistoryRequestV0 { - data_contract_id: history_contract.id().to_vec(), - document_type_name: "profile".to_owned(), - document_id: document_id.to_vec(), - limit: Some(2), - offset, - start_at_ms: 0, - prove, - }, - )) + .get_document_history(request) .await .expect("supported document history") .into_inner(); - let Some(wire::get_document_history_response::Version::V0(v0)) = response.version - else { - panic!("document history V0") + let (plain, proof) = match response.version.expect("versioned history") { + wire::get_document_history_response::Version::V0(v0) => match v0.result.expect("document result") { + wire::get_document_history_response::get_document_history_response_v0::Result::DocumentHistory(history) => ( + Some(history.document_entries.into_iter().map(|entry| (entry.date, entry.value)).collect::>()), None, + ), + wire::get_document_history_response::get_document_history_response_v0::Result::Proof(proof) => (None, Some(proof)), + }, + wire::get_document_history_response::Version::V1(v1) => match v1.result.expect("document result") { + wire::get_document_history_response::get_document_history_response_v1::Result::History(history) => ( + Some(history.entries.into_iter().map(|entry| (entry.time_ms, entry.document)).collect::>()), None, + ), + wire::get_document_history_response::get_document_history_response_v1::Result::Proof(proof) => (None, Some(proof)), + }, }; - match v0.result.expect("document result") { - DocumentHistoryResult::DocumentHistory(history) => { - assert!(!prove); - assert_eq!( - history - .document_entries - .into_iter() - .map(|e| (e.date, e.value)) - .collect::>(), - expected_page - .iter() - .map(|(time, document)| ( - *time, - document - .serialize(document_type, &history_contract, version) - .expect("original document bytes") - )) - .collect::>() - ); - } - DocumentHistoryResult::Proof(proof) => { - assert!(prove); - let (root, documents) = Drive::verify_document_history( + if let Some(entries) = plain { + assert!(!prove); + assert_eq!( + entries, + expected_page + .iter() + .map(|(time, document)| ( + *time, + document + .serialize(document_type, &history_contract, version) + .expect("original document bytes"), + )) + .collect::>() + ); + } else { + assert!(prove); + let proof = proof.expect("proved history"); + let (root, documents) = if legacy { + let (root, documents) = Drive::verify_document_history_after_time( &proof.grovedb_proof, history_contract.id().to_buffer(), "profile", @@ -432,13 +469,30 @@ async fn should_preserve_supported_offset_pages_and_original_proof_roots() { document_id, 0, Some(2), - offset.map(|o| o as u16), + offset.map(|offset| offset as u16), version, ) .expect("original document history proof"); - assert_eq!(root, stored_root); - assert_eq!(documents.expect("history"), expected_page); - } + (root, documents.expect("verified history")) + } else { + let (root, history) = Drive::verify_document_history( + &history_query, + &proof.grovedb_proof, + document_type, + version, + ) + .expect("history page and lifecycle proof"); + ( + root, + history + .entries + .into_iter() + .map(|entry| (entry.time_ms, entry.document)) + .collect::>(), + ) + }; + assert_eq!(root, stored_root); + assert_eq!(documents, expected_page); } let expected_vote_page = expected_votes .iter() diff --git a/packages/rs-drive-abci/tests/query_request_errors/offsets.rs b/packages/rs-drive-abci/tests/query_request_errors/offsets.rs index 61bb0fa5402..8274297a2d2 100644 --- a/packages/rs-drive-abci/tests/query_request_errors/offsets.rs +++ b/packages/rs-drive-abci/tests/query_request_errors/offsets.rs @@ -1,4 +1,5 @@ use super::*; +use dapi_grpc::platform::v0::get_document_history_request::get_document_history_request_v1::Filter as DocumentHistoryFilter; use dpp::data_contract::conversion::json::DataContractJsonConversionMethodsV0; use dpp::identity::accessors::IdentityGettersV0; use dpp::identity::Identity; @@ -81,6 +82,46 @@ async fn should_refuse_unsupported_positive_offsets_over_tonic() { let (contract_id, _) = fixture.store_contract(); let profile = history_contract(&fixture); let (mut client, server) = fixture.client(); + let request: wire::GetDocumentHistoryRequest = if version + .drive_abci + .query + .document_history + .default_current_version + == 0 + { + wire::get_document_history_request::GetDocumentHistoryRequestV0 { + data_contract_id: profile.id().to_vec(), + document_type_name: "profile".to_owned(), + document_id: vec![9; 32], + limit: Some(u32::MAX), + offset: None, + start_at_ms: 0, + prove: true, + } + .into() + } else { + wire::get_document_history_request::GetDocumentHistoryRequestV1 { + data_contract_id: profile.id().to_vec(), + document_type_name: "profile".to_owned(), + document_id: vec![9; 32], + limit: Some(u32::MAX), + filter: Some(DocumentHistoryFilter::StartAtMs(0)), + prove: true, + } + .into() + }; + let status = client + .get_document_history(request) + .await + .expect_err("document-history limit must fit the query range"); + if status.code() != Code::InvalidArgument + || !status.message().contains("limit out of bounds") + { + failures.push(format!( + "PV{} document history limit: {status}", + version.protocol_version + )); + } for offset in [1, u16::MAX as u32] { for (name, kind, prove) in [ ( @@ -130,30 +171,6 @@ async fn should_refuse_unsupported_positive_offsets_over_tonic() { version.protocol_version )); } - let status = client - .get_document_history(wire::GetDocumentHistoryRequest::from( - wire::get_document_history_request::GetDocumentHistoryRequestV0 { - data_contract_id: profile.id().to_vec(), - document_type_name: "profile".to_owned(), - document_id: vec![9; 32], - limit: Some(2), - offset: Some(offset), - start_at_ms: 0, - prove: true, - }, - )) - .await - .expect_err("document-history proof cannot page by offset"); - if status.code() != Code::InvalidArgument - || !status.message().contains( - "requesting proof with offset error: proof requests do not support offsets", - ) - { - failures.push(format!( - "PV{} document history offset={offset}: {status}", - version.protocol_version - )); - } let status = client .get_contested_resource_identity_votes( wire::GetContestedResourceIdentityVotesRequest::from( @@ -404,13 +421,12 @@ async fn should_keep_all_thirteen_nodes_available_after_three_bad_offset_request assert_no_node_bans( DocumentHistoryQuery { fixture: Arc::clone(&fixture), - request: wire::get_document_history_request::GetDocumentHistoryRequestV0 { + request: wire::get_document_history_request::GetDocumentHistoryRequestV1 { data_contract_id: profile.id().to_vec(), document_type_name: "profile".to_owned(), document_id: vec![9; 32], limit: Some(2), - offset: Some(1), - start_at_ms: 0, + filter: None, prove: true, } .into(), @@ -440,7 +456,7 @@ async fn should_keep_all_thirteen_nodes_available_after_three_bad_offset_request } #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn should_validate_proof_offsets_before_missing_history_lookups() { +async fn should_validate_query_shapes_before_missing_history_lookups() { for version in [ PlatformVersion::get(12).unwrap(), PlatformVersion::get(13).unwrap(), @@ -454,29 +470,58 @@ async fn should_validate_proof_offsets_before_missing_history_lookups() { (profile.id().to_vec(), "absentType"), ] { for prove in [false, true] { - let request = wire::get_document_history_request::GetDocumentHistoryRequestV0 { - data_contract_id: id.clone(), - document_type_name: name.to_owned(), - document_id: vec![9; 32], - limit: Some(2), - offset: Some(1), - start_at_ms: 0, - prove, - }; - let status = client - .get_document_history(wire::GetDocumentHistoryRequest::from(request)) - .await - .expect_err("missing history or unsupported proof offset"); - assert_eq!( - status.code(), - if prove { - Code::InvalidArgument + for filter in [None, Some(DocumentHistoryFilter::StartAtMs(0))] { + let malformed = filter.is_none(); + let legacy = version + .drive_abci + .query + .document_history + .default_current_version + == 0; + let request: wire::GetDocumentHistoryRequest = if legacy { + wire::get_document_history_request::GetDocumentHistoryRequestV0 { + data_contract_id: id.clone(), + document_type_name: name.to_owned(), + document_id: vec![9; 32], + limit: Some(if malformed { 0 } else { 2 }), + offset: None, + start_at_ms: 0, + prove, + } + .into() } else { - Code::NotFound + wire::get_document_history_request::GetDocumentHistoryRequestV1 { + data_contract_id: id.clone(), + document_type_name: name.to_owned(), + document_id: vec![9; 32], + limit: Some(2), + filter, + prove, + } + .into() + }; + let status = client + .get_document_history(request) + .await + .expect_err("missing history or malformed filter"); + assert_eq!( + status.code(), + if malformed { + Code::InvalidArgument + } else { + Code::NotFound + } + ); + if malformed { + assert!( + status.message().contains(if legacy { + "limit 0 out of bounds" + } else { + "exactly one history filter is required" + }), + "{status}" + ); } - ); - if prove { - assert!(status.message().contains("requesting proof with offset error: proof requests do not support offsets"),"{status}"); } } } diff --git a/packages/rs-drive-abci/tests/strategy_tests/test_cases/upgrade_fork_tests.rs b/packages/rs-drive-abci/tests/strategy_tests/test_cases/upgrade_fork_tests.rs index b9c9a2afbec..a92cec2e3fc 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/test_cases/upgrade_fork_tests.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/test_cases/upgrade_fork_tests.rs @@ -3,8 +3,8 @@ mod tests { use crate::addresses_with_balance::AddressesWithBalance; use crate::execution::{continue_chain_for_strategy, run_chain_for_strategy, GENESIS_TIME_MS}; use crate::strategy::{ - ChainExecutionOutcome, ChainExecutionParameters, CoreHeightIncrease, NetworkStrategy, - StrategyRandomness, UpgradingInfo, + ChainExecutionOutcome, ChainExecutionParameters, CoreHeightIncrease, FailureStrategy, + NetworkStrategy, StrategyRandomness, UpgradingInfo, }; use dash_platform_macros::stack_size; use dpp::block::epoch::Epoch; @@ -564,6 +564,791 @@ mod tests { } } + #[stack_size(4 * 1024 * 1024)] + #[test] + async fn run_chain_v14_to_v15_migrates_document_history_and_survives_restart() { + use dpp::data_contract::document_type::random_document::{ + DocumentFieldFillSize, DocumentFieldFillType, + }; + use dpp::tests::json_document::json_document_to_created_contract; + use strategy_tests::frequency::Frequency; + use strategy_tests::operations::{DocumentAction, DocumentOp, Operation, OperationType}; + let old_version = PlatformVersion::get(14).unwrap(); + let created_contract = json_document_to_created_contract( + "tests/supporting_files/contract/note/note-contract-keep-history.json", + 1, + false, + old_version, + ) + .unwrap(); + let make_operation = |action| Operation { + op_type: OperationType::Document(DocumentOp { + contract: created_contract.data_contract().clone(), + document_type: created_contract + .data_contract() + .document_type_for_name("note") + .unwrap() + .to_owned_document_type(), + action, + }), + frequency: Frequency { + times_per_block_range: 1..2, + chance_per_block: None, + }, + }; + let operations = vec![ + make_operation(DocumentAction::DocumentActionInsertRandom( + DocumentFieldFillType::FillIfNotRequired, + DocumentFieldFillSize::AnyDocumentFillSize, + )), + make_operation(DocumentAction::DocumentActionReplaceRandom), + ]; + let strategy = NetworkStrategy { + strategy: Strategy { + start_contracts: vec![(created_contract, None)], + operations, + start_identities: StartIdentities::default(), + start_addresses: StartAddresses::default(), + identity_inserts: IdentityInsertInfo { + frequency: Frequency { + times_per_block_range: 1..2, + chance_per_block: None, + }, + ..Default::default() + }, + identity_contract_nonce_gaps: None, + signer: None, + }, + total_hpmns: 50, + extra_normal_mns: 0, + validator_quorum_count: 24, + chain_lock_quorum_count: 24, + upgrading_info: Some(UpgradingInfo { + current_protocol_version: 14, + proposed_protocol_versions_with_weight: vec![(15, 1)], + upgrade_three_quarters_life: 0.0, + }), + proposer_strategy: Default::default(), + rotate_quorums: false, + failure_testing: None, + query_testing: None, + verify_state_transition_results: false, + ..Default::default() + }; + let config = PlatformConfig { + validator_set: ValidatorSetConfig { + quorum_size: 30, + ..Default::default() + }, + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), + execution: ExecutionConfig { + verify_sum_trees: true, + epoch_time_length_s: 60, + ..Default::default() + }, + block_spacing_ms: 1_000, + testing_configs: PlatformTestConfig { + store_platform_state: true, + ..PlatformTestConfig::default_minimal_verifications() + }, + ..Default::default() + }; + let mut platform = TestPlatformBuilder::new() + .with_config(config.clone()) + .with_initial_protocol_version(14) + .build_with_mock_rpc(); + + let ChainExecutionOutcome { + abci_app, + proposers, + validator_quorums, + current_validator_quorum_hash, + current_proposer_versions, + end_time_ms, + identity_nonce_counter, + identity_contract_nonce_counter, + instant_lock_quorums, + mut strategy, + signer, + state_transition_results_per_block, + .. + } = run_chain_for_strategy( + &mut platform, + 60, + strategy.clone(), + config.clone(), + 14, + &mut None, + &mut None, + ) + .await; + + for results in state_transition_results_per_block.values() { + for (_, result) in results { + assert_eq!(result.code, 0); + } + } + let contract = strategy.strategy.start_contracts[0] + .0 + .data_contract() + .clone(); + strategy.strategy.operations.retain(|operation| { + matches!( + operation.op_type, + OperationType::Document(DocumentOp { + action: DocumentAction::DocumentActionReplaceRandom, + .. + }) + ) + }); + strategy.strategy.identity_inserts = IdentityInsertInfo::default(); + strategy.strategy.signer = Some(signer); + let primary_path = vec![ + vec![drive::drive::RootTree::DataContractDocuments as u8], + contract.id().to_vec(), + vec![1], + b"note".to_vec(), + vec![0], + ]; + let read_entries = |path: Vec>| { + let mut query = drive::grovedb::Query::new(); + query.insert_all(); + abci_app + .platform + .drive + .grove + .query_raw( + &drive::grovedb::PathQuery::new( + path, + drive::grovedb::SizedQuery::new(query, None, None), + ), + false, + true, + true, + drive::query::QueryResultType::QueryKeyElementPairResultType, + None, + &old_version.drive.grove_version, + ) + .value + .unwrap() + .0 + .to_key_elements() + }; + let (document_id, expected_revisions) = read_entries(primary_path.clone()) + .into_iter() + .map(|(id, _)| { + let mut path = primary_path.clone(); + path.push(id.clone()); + let count = read_entries(path).len() - 1; + (id, count) + }) + .max_by_key(|(_, count)| *count) + .expect("strategy must create historical documents"); + assert!( + expected_revisions > 1, + "strategy must replace existing documents" + ); + + let state = abci_app.platform.state.load(); + assert_eq!(state.last_committed_block_epoch().index, 0); + assert_eq!(state.current_protocol_version_in_consensus(), 14); + assert_eq!(state.next_epoch_protocol_version(), 14); + let block_start = state + .last_committed_block_info() + .as_ref() + .expect("expected committed block info") + .basic_info() + .height + + 1; + drop(state); + + let ChainExecutionOutcome { + abci_app, + proposers, + validator_quorums, + current_validator_quorum_hash, + end_time_ms, + identity_nonce_counter, + identity_contract_nonce_counter, + instant_lock_quorums, + state_transition_results_per_block, + .. + } = continue_chain_for_strategy( + abci_app, + ChainExecutionParameters { + block_start, + core_height_start: 1, + block_count: 1, + proposers, + validator_quorums, + current_validator_quorum_hash, + current_proposer_versions: Some(current_proposer_versions.clone()), + current_identity_nonce_counter: identity_nonce_counter, + current_identity_contract_nonce_counter: identity_contract_nonce_counter, + current_votes: BTreeMap::default(), + start_time_ms: 1681094380000, + current_time_ms: end_time_ms, + instant_lock_quorums, + current_identities: Vec::new(), + current_addresses_with_balance: AddressesWithBalance::default(), + }, + strategy.clone(), + config.clone(), + StrategyRandomness::SeedEntropy(7), + ) + .await; + + let lock_in_results = state_transition_results_per_block + .values() + .next() + .expect("the lock-in block must execute its replacement"); + assert_eq!(lock_in_results.len(), 1); + assert_eq!(lock_in_results[0].1.code, 0); + + let read_entries = |path: Vec>| { + let mut query = drive::grovedb::Query::new(); + query.insert_all(); + abci_app + .platform + .drive + .grove + .query_raw( + &drive::grovedb::PathQuery::new( + path, + drive::grovedb::SizedQuery::new(query, None, None), + ), + false, + true, + true, + drive::query::QueryResultType::QueryKeyElementPairResultType, + None, + &old_version.drive.grove_version, + ) + .value + .unwrap() + .0 + .to_key_elements() + }; + let legacy_revisions_before_activation = read_entries(primary_path.clone()) + .into_iter() + .map(|(id, _)| { + let mut path = primary_path.clone(); + path.push(id); + read_entries(path).len() - 1 + }) + .sum::(); + + let type_path = primary_path[..primary_path.len() - 1].to_vec(); + let history_tree_key = vec![drive::drive::document::paths::DOCUMENT_HISTORY_TREE_KEY]; + let has_history_tree = |drive: &drive::drive::Drive| { + let type_path: Vec<&[u8]> = type_path.iter().map(Vec::as_slice).collect(); + drive + .grove + .has_raw( + type_path.as_slice(), + &history_tree_key, + None, + &old_version.drive.grove_version, + ) + .value + .unwrap() + }; + assert!( + !has_history_tree(&abci_app.platform.drive), + "lock-in writes must stay in the per-document subtree layout" + ); + + let state = abci_app.platform.state.load(); + assert_eq!(state.last_committed_block_epoch().index, 1); + assert_eq!(state.current_protocol_version_in_consensus(), 14); + assert_eq!(state.next_epoch_protocol_version(), 15); + let block_start = state + .last_committed_block_info() + .as_ref() + .expect("expected committed block info") + .basic_info() + .height + + 1; + drop(state); + + drop(abci_app); + let TempPlatform { + platform: mut platform_before_activation_restart, + tempdir, + } = platform; + let core_rpc = std::mem::take(&mut platform_before_activation_restart.core_rpc); + drop(platform_before_activation_restart); + platform = TempPlatform::open_with_tempdir(tempdir, config.clone()); + platform.platform.core_rpc = core_rpc; + let state = platform.state.load(); + assert_eq!(state.last_committed_block_epoch().index, 1); + assert_eq!(state.current_protocol_version_in_consensus(), 14); + assert_eq!(state.next_epoch_protocol_version(), 15); + drop(state); + let abci_app = FullAbciApplication::new(&platform.platform); + + let (abci_app, state_transition_results_per_block, successful_pre_activation_replacements) = { + let before_activation = continue_chain_for_strategy( + abci_app, + ChainExecutionParameters { + block_start, + core_height_start: 1, + block_count: 59, + proposers, + validator_quorums, + current_validator_quorum_hash, + current_proposer_versions: Some(current_proposer_versions), + current_identity_nonce_counter: identity_nonce_counter, + current_identity_contract_nonce_counter: identity_contract_nonce_counter, + current_votes: BTreeMap::default(), + start_time_ms: 1681094380000, + current_time_ms: end_time_ms, + instant_lock_quorums, + current_identities: Vec::new(), + current_addresses_with_balance: AddressesWithBalance::default(), + }, + strategy.clone(), + config.clone(), + StrategyRandomness::SeedEntropy(18), + ) + .await; + + let successful_pre_activation_replacements = before_activation + .state_transition_results_per_block + .values() + .flat_map(|results| results.iter()) + .inspect(|(_, result)| assert_eq!(result.code, 0)) + .count(); + assert_eq!(successful_pre_activation_replacements, 59); + assert_eq!( + before_activation + .abci_app + .platform + .state + .load() + .current_protocol_version_in_consensus(), + 14 + ); + assert!( + !has_history_tree(&before_activation.abci_app.platform.drive), + "protocol 14 blocks must not create the history tree" + ); + + let activation_parameters = continuation_parameters(&before_activation, 1); + let ChainExecutionOutcome { abci_app, .. } = before_activation; + let mut activation_strategy = strategy; + activation_strategy.failure_testing = Some(FailureStrategy { + rounds_before_successful_block: Some(1), + ..Default::default() + }); + let ChainExecutionOutcome { + abci_app, + state_transition_results_per_block, + .. + } = continue_chain_for_strategy( + abci_app, + activation_parameters, + activation_strategy, + config.clone(), + StrategyRandomness::SeedEntropy(19), + ) + .await; + ( + abci_app, + state_transition_results_per_block, + successful_pre_activation_replacements, + ) + }; + + let activation_results = state_transition_results_per_block + .iter() + .max_by_key(|(height, _)| *height) + .map(|(_, results)| results) + .expect("the activation run must execute replacements"); + assert_eq!(activation_results.len(), 1); + assert_eq!(activation_results[0].1.code, 0); + let successful_activation_replacements = state_transition_results_per_block + .values() + .flat_map(|results| results.iter()) + .inspect(|(_, result)| assert_eq!(result.code, 0)) + .count(); + assert_eq!(successful_activation_replacements, 1); + let successful_activation_run_replacements = + successful_pre_activation_replacements + successful_activation_replacements; + + let state = abci_app.platform.state.load(); + assert_eq!(state.last_committed_block_epoch().index, 2); + assert_eq!(state.current_protocol_version_in_consensus(), 15); + assert_eq!(state.next_epoch_protocol_version(), 15); + drop(state); + assert!( + has_history_tree(&abci_app.platform.drive), + "the activation block must create the per-type history tree" + ); + let new_version = PlatformVersion::get(15).unwrap(); + let path = drive::drive::document::paths::document_history_path( + contract.id().as_slice(), + "note", + document_id.as_slice(), + ); + let mut query = drive::grovedb::Query::new(); + query.insert_all(); + let query = drive::grovedb::PathQuery::new( + path, + drive::grovedb::SizedQuery::new(query, None, None), + ); + let (entries, _) = abci_app + .platform + .drive + .grove + .query_raw( + &query, + false, + true, + true, + drive::query::QueryResultType::QueryKeyElementPairResultType, + None, + &new_version.drive.grove_version, + ) + .value + .unwrap(); + let migrated_revisions = entries.elements.len(); + assert!(migrated_revisions >= expected_revisions); + assert!(entries + .to_key_elements() + .iter() + .all(|(key, _)| key.len() == 16)); + + let read_entries = |path: Vec>| { + let mut query = drive::grovedb::Query::new(); + query.insert_all(); + abci_app + .platform + .drive + .grove + .query_raw( + &drive::grovedb::PathQuery::new( + path, + drive::grovedb::SizedQuery::new(query, None, None), + ), + false, + true, + true, + drive::query::QueryResultType::QueryKeyElementPairResultType, + None, + &new_version.drive.grove_version, + ) + .value + .unwrap() + .0 + .to_key_elements() + }; + let total_migrated_revisions = read_entries(primary_path.clone()) + .into_iter() + .map(|(id, _)| { + read_entries(drive::drive::document::paths::document_history_path( + contract.id().as_slice(), + "note", + id.as_slice(), + )) + .len() + }) + .sum::(); + assert_eq!( + total_migrated_revisions, + legacy_revisions_before_activation + successful_activation_run_replacements, + "v14 replacements must migrate before the first v15 replacement is written" + ); + + use dpp::block::block_info::BlockInfo; + use dpp::document::{DocumentV0Getters, DocumentV0Setters}; + use drive::query::document_history_drive_query::{ + DocumentHistoryDriveQuery, DocumentHistoryFilter, + }; + use drive::util::object_size_info::{ + DocumentAndContractInfo, DocumentInfo, OwnedDocumentInfo, + }; + + let document_type = contract.document_type_for_name("note").unwrap(); + let query = |id, filter, limit| DocumentHistoryDriveQuery { + contract_id: contract.id().to_buffer(), + document_type_name: "note".into(), + document_id: id, + filter, + limit, + }; + let verify = |query: &DocumentHistoryDriveQuery| { + let page = abci_app + .platform + .drive + .fetch_document_history(query, document_type, None, new_version) + .unwrap(); + let proof = abci_app + .platform + .drive + .prove_document_history(query, document_type, None, new_version) + .unwrap(); + let (proved_root, verified) = drive::drive::Drive::verify_document_history( + query, + &proof, + document_type, + new_version, + ) + .unwrap(); + assert_eq!( + proved_root, + abci_app + .platform + .drive + .grove + .root_hash(None, &new_version.drive.grove_version) + .value + .unwrap() + ); + assert_eq!(verified, page); + page + }; + + let current_query = query( + document_id.clone().try_into().unwrap(), + DocumentHistoryFilter::Revision(migrated_revisions as u64), + Some(1), + ); + let migrated_document = verify(¤t_query) + .entries + .into_iter() + .next() + .expect("the migrated document's current revision must be queryable") + .document; + let migrated_revision = migrated_document.revision().unwrap(); + assert_eq!(migrated_revision, migrated_revisions as u64); + let migrated_page = verify(&query( + document_id.clone().try_into().unwrap(), + DocumentHistoryFilter::StartAtRevision(migrated_revision), + Some(1), + )); + assert_eq!( + migrated_page + .entries + .iter() + .map(|entry| entry.revision) + .collect::>(), + [migrated_revision] + ); + + let post_activation_time = GENESIS_TIME_MS + 1_000_000; + // The migrated document keeps accepting updates under the v15 layout, + // written with the storage flags its signed transitions gave it. + let pointer_flags = abci_app + .platform + .drive + .grove + .get_raw( + primary_path + .iter() + .map(Vec::as_slice) + .collect::>() + .as_slice() + .into(), + document_id.as_slice(), + None, + &new_version.drive.grove_version, + ) + .value + .unwrap() + .get_flags() + .clone(); + let storage_flags = + drive::util::storage_flags::StorageFlags::map_some_element_flags_ref(&pointer_flags) + .unwrap() + .map(std::borrow::Cow::Owned); + let mut updated_document = migrated_document.clone(); + updated_document.set_revision(Some(migrated_revision + 1)); + updated_document.set("message", "updated after activation".into()); + abci_app + .platform + .drive + .update_document_for_contract( + &updated_document, + &contract, + document_type, + None, + BlockInfo::default_with_time(post_activation_time), + true, + storage_flags, + None, + new_version, + ) + .expect("a migrated document must remain updatable"); + let updated_page = verify(&query( + document_id.clone().try_into().unwrap(), + DocumentHistoryFilter::Revision(migrated_revision + 1), + Some(1), + )); + assert_eq!(updated_page.entries.len(), 1); + assert_eq!(updated_page.entries[0].time_ms, post_activation_time); + assert_eq!(updated_page.entries[0].document, updated_document); + assert_eq!( + updated_page + .lifecycle + .as_ref() + .map(|l| l.remaining_revisions), + Some(migrated_revision + 1) + ); + + // Every index reference rewritten by the migration resolves: a proved + // query through the index returns every current document. + let indexed_query = drive::query::DriveDocumentQuery::from_sql_expr( + "select * from note order by tag asc", + &contract, + None, + new_version, + ) + .unwrap(); + let current_documents = read_entries(primary_path.clone()).len(); + let (index_proof, _) = indexed_query + .clone() + .execute_with_proof(&abci_app.platform.drive, None, None, new_version) + .unwrap(); + let (_, index_verified) = indexed_query + .verify_proof(&index_proof, new_version) + .unwrap(); + assert_eq!(index_verified.len(), current_documents); + assert!(index_verified + .iter() + .any(|document| document.id() == updated_document.id() + && document.revision() == Some(migrated_revision + 1))); + + let fresh_id = (0..=u8::MAX) + .map(|seed| [seed; 32]) + .find(|candidate| { + !abci_app + .platform + .drive + .grove + .has_raw( + primary_path.as_slice(), + candidate, + None, + &new_version.drive.grove_version, + ) + .unwrap() + .unwrap() + }) + .expect("a deterministic unused document id must exist"); + let mut fresh_document = migrated_document.clone(); + fresh_document.set_id(fresh_id.into()); + fresh_document.set_revision(Some(1)); + abci_app + .platform + .drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentInfo::DocumentRefInfo((&fresh_document, None)), + owner_id: None, + }, + contract: &contract, + document_type, + }, + false, + BlockInfo::default_with_time(post_activation_time), + true, + None, + new_version, + ) + .expect("an existing v14 contract must accept a new v15 document"); + fresh_document.set_revision(Some(2)); + abci_app + .platform + .drive + .update_document_for_contract( + &fresh_document, + &contract, + document_type, + None, + BlockInfo::default_with_time(post_activation_time), + true, + None, + None, + new_version, + ) + .expect("a document inserted after activation must remain updatable"); + let fresh_query = query( + fresh_id, + DocumentHistoryFilter::StartAtTime(post_activation_time), + None, + ); + let fresh_page = verify(&fresh_query); + assert_eq!( + fresh_page + .entries + .iter() + .map(|entry| (entry.time_ms, entry.revision)) + .collect::>(), + [(post_activation_time, 1), (post_activation_time, 2)] + ); + let cursor_page = verify(&query( + fresh_id, + DocumentHistoryFilter::StartAfter { + time_ms: post_activation_time, + revision: 1, + }, + Some(1), + )); + assert_eq!(cursor_page.entries[0].revision, 2); + + let root = abci_app + .platform + .drive + .grove + .root_hash(None, &new_version.drive.grove_version) + .value + .unwrap(); + drop(abci_app); + let TempPlatform { + platform: old_platform, + tempdir, + } = platform; + drop(old_platform); + let restarted = TempPlatform::open_with_tempdir(tempdir, config); + assert_eq!( + restarted + .state + .load() + .current_protocol_version_in_consensus(), + 15 + ); + assert_eq!(restarted.state.load().next_epoch_protocol_version(), 15); + let restarted_page = restarted + .drive + .fetch_document_history(&fresh_query, document_type, None, new_version) + .unwrap(); + let restarted_proof = restarted + .drive + .prove_document_history(&fresh_query, document_type, None, new_version) + .unwrap(); + let (_, restarted_verified) = drive::drive::Drive::verify_document_history( + &fresh_query, + &restarted_proof, + document_type, + new_version, + ) + .unwrap(); + assert_eq!(restarted_verified, restarted_page); + assert_eq!(restarted_page.entries.len(), 2); + assert_eq!( + restarted + .drive + .grove + .root_hash(None, &new_version.drive.grove_version) + .value + .unwrap(), + root + ); + } + #[stack_size(4 * 1024 * 1024)] #[test] async fn run_chain_v12_to_v13_locks_in_before_activation() { diff --git a/packages/rs-drive-abci/tests/supporting_files/contract/note/note-contract-keep-history.json b/packages/rs-drive-abci/tests/supporting_files/contract/note/note-contract-keep-history.json new file mode 100644 index 00000000000..233fddd3977 --- /dev/null +++ b/packages/rs-drive-abci/tests/supporting_files/contract/note/note-contract-keep-history.json @@ -0,0 +1,44 @@ +{ + "$formatVersion": "1", + "id": "4Bqs6itzfoDXzmgQibYZQABbqYsXmawVf7SKe3mKDQVe", + "ownerId": "2b994p95akyNFKtkDnDvBRUotDbkH54MHwGbhQLr5gcU", + "version": 1, + "keywords": [], + "documentSchemas": { + "note": { + "type": "object", + "documentsKeepHistory": true, + "documentsMutable": true, + "canBeDeleted": false, + "properties": { + "message": { + "type": "string", + "maxLength": 256, + "position": 0 + }, + "tag": { + "type": "string", + "maxLength": 32, + "position": 1 + } + }, + "required": [ + "message", + "tag" + ], + "additionalProperties": false, + "indices": [ + { + "name": "tag", + "properties": [ + { + "tag": "asc" + } + ] + } + ] + } + }, + "groups": {}, + "tokens": {} +} diff --git a/packages/rs-drive-proof-verifier/src/proof.rs b/packages/rs-drive-proof-verifier/src/proof.rs index 761bba2b96e..1ffe2ff6767 100644 --- a/packages/rs-drive-proof-verifier/src/proof.rs +++ b/packages/rs-drive-proof-verifier/src/proof.rs @@ -1524,86 +1524,235 @@ impl FromProof for DataContractHistory } } -impl FromProof for DocumentHistory { +fn verify_document_history_response_v0( + request: platform::get_document_history_request::GetDocumentHistoryRequestV0, + response: &platform::GetDocumentHistoryResponse, + platform_version: &PlatformVersion, + provider: &dyn ContextProvider, +) -> Result<(Option, ResponseMetadata, Proof), Error> { + let proof = response.proof().or(Err(Error::NoProofInResult))?; + let metadata = response.metadata().or(Err(Error::EmptyResponseMetadata))?; + let contract_id = Identifier::from_bytes(&request.data_contract_id).map_err(|error| { + Error::ProtocolError { + error: error.to_string(), + } + })?; + let document_id = + Identifier::from_bytes(&request.document_id).map_err(|error| Error::ProtocolError { + error: error.to_string(), + })?; + let limit = u32_to_u16_opt(request.limit.unwrap_or_default())?; + let offset = u32_to_u16_opt(request.offset.unwrap_or_default())?; + let contract = provider + .get_data_contract(&contract_id, platform_version)? + .ok_or(Error::NotFound)?; + let document_type = contract + .document_type_for_name(&request.document_type_name) + .map_err(|error| Error::ProtocolError { + error: error.to_string(), + })?; + let query_version = proof_query_platform_version(metadata)?; + let (root, history) = Drive::verify_document_history_after_time( + supported_grovedb_proof_bytes(proof)?, + contract_id.to_buffer(), + &request.document_type_name, + document_type, + document_id.to_buffer(), + request.start_at_ms, + limit, + offset, + query_version, + ) + .map_drive_error(proof, metadata)?; + verify_tenderdash_proof(proof, metadata, &root, provider)?; + Ok(( + history.map(|history| DocumentHistory { + entries: history + .into_iter() + .map(|(time_ms, document)| DocumentHistoryEntry { + time_ms, + revision: document.revision().unwrap_or(1), + document, + }) + .collect(), + lifecycle: None, + }), + metadata.clone(), + proof.clone(), + )) +} + +fn verify_document_history_response_v1( + request: platform::get_document_history_request::GetDocumentHistoryRequestV1, + response: &platform::GetDocumentHistoryResponse, + platform_version: &PlatformVersion, + provider: &dyn ContextProvider, +) -> Result<(Option, ResponseMetadata, Proof), Error> { + use drive::query::document_history_drive_query::{ + DocumentHistoryDriveQuery, DocumentHistoryFilter, + }; + use platform::get_document_history_request::get_document_history_request_v1::Filter; + let proof = response.proof().or(Err(Error::NoProofInResult))?; + let metadata = response.metadata().or(Err(Error::EmptyResponseMetadata))?; + let contract_id = Identifier::from_bytes(&request.data_contract_id).map_err(|error| { + Error::ProtocolError { + error: error.to_string(), + } + })?; + let document_id = + Identifier::from_bytes(&request.document_id).map_err(|error| Error::ProtocolError { + error: error.to_string(), + })?; + let filter = match request.filter.ok_or_else(|| Error::RequestError { + error: "history filter is required".to_owned(), + })? { + Filter::StartAtMs(time) => DocumentHistoryFilter::StartAtTime(time), + Filter::StartAfter(cursor) => DocumentHistoryFilter::StartAfter { + time_ms: cursor.time_ms, + revision: cursor.revision, + }, + Filter::StartAtRevision(revision) => DocumentHistoryFilter::StartAtRevision(revision), + Filter::Revision(revision) => DocumentHistoryFilter::Revision(revision), + }; + let query = + DocumentHistoryDriveQuery { + contract_id: contract_id.to_buffer(), + document_type_name: request.document_type_name, + document_id: document_id.to_buffer(), + filter, + limit: request.limit.map(u16::try_from).transpose().map_err(|_| { + Error::RequestError { + error: "history limit out of bounds".to_owned(), + } + })?, + }; + query.validate()?; + let contract = provider + .get_data_contract(&contract_id, platform_version)? + .ok_or(Error::NotFound)?; + let document_type = contract + .document_type_for_name(&query.document_type_name) + .map_err(|error| Error::ProtocolError { + error: error.to_string(), + })?; + let query_version = proof_query_platform_version(metadata)?; + let (root, history) = Drive::verify_document_history( + &query, + supported_grovedb_proof_bytes(proof)?, + document_type, + query_version, + ) + .map_drive_error(proof, metadata)?; + verify_tenderdash_proof(proof, metadata, &root, provider)?; + Ok(( + Some(DocumentHistory { + entries: history.entries, + lifecycle: history.lifecycle, + }), + metadata.clone(), + proof.clone(), + )) +} + +impl FromProof for DocumentHistoryProofInfo { type Request = platform::GetDocumentHistoryRequest; type Response = platform::GetDocumentHistoryResponse; fn maybe_from_proof_with_metadata<'a, I: Into, O: Into>( request: I, response: O, - _network: Network, + network: Network, platform_version: &PlatformVersion, provider: &'a dyn ContextProvider, ) -> Result<(Option, ResponseMetadata, Proof), Error> where Self: Sized + 'a, { - let request: Self::Request = request.into(); - let response: Self::Response = response.into(); - - let proof = response.proof().or(Err(Error::NoProofInResult))?; - let mtd = response.metadata().or(Err(Error::EmptyResponseMetadata))?; - - let (contract_id, document_type_name, document_id, limit, offset, start_at_ms) = - match request.version.ok_or(Error::EmptyVersion)? { - get_document_history_request::Version::V0(v0) => { - let contract_id = - Identifier::from_bytes(&v0.data_contract_id).map_err(|e| { - Error::ProtocolError { - error: e.to_string(), - } - })?; - let document_id = Identifier::from_bytes(&v0.document_id).map_err(|e| { - Error::ProtocolError { - error: e.to_string(), - } - })?; - let limit = u32_to_u16_opt(v0.limit.unwrap_or_default())?; - let offset = u32_to_u16_opt(v0.offset.unwrap_or_default())?; - ( - contract_id, - v0.document_type_name, - document_id, - limit, - offset, - v0.start_at_ms, - ) - } - }; - - let data_contract = provider - .get_data_contract(&contract_id, platform_version)? - .ok_or(Error::NotFound)?; - let document_type = data_contract - .document_type_for_name(&document_type_name) - .map_err(|e| Error::ProtocolError { - error: e.to_string(), - })?; + let response = response.into(); + let Some(platform::get_document_history_response::Version::V1(wire)) = &response.version + else { + return Err(Error::ResponseDecodeError { + error: "history proof info requires a version 1 response".to_owned(), + }); + }; + let wire = wire.clone(); + let (history, metadata, proof) = DocumentHistory::maybe_from_proof_with_metadata( + request, + response, + network, + platform_version, + provider, + )?; + Ok(( + history.map(|history| Self { + history, + response: wire, + }), + metadata, + proof, + )) + } +} - let (root_hash, maybe_history) = Drive::verify_document_history( - supported_grovedb_proof_bytes(proof)?, - contract_id.into_buffer(), - &document_type_name, - document_type, - document_id.into_buffer(), - start_at_ms, - limit, - offset, +impl DocumentHistoryProofInfo { + /// Independently authenticate the retained response against its original request. + pub fn verify( + &self, + request: platform::GetDocumentHistoryRequest, + network: Network, + platform_version: &PlatformVersion, + provider: &dyn ContextProvider, + ) -> Result, Error> { + DocumentHistory::maybe_from_proof( + request, + platform::GetDocumentHistoryResponse::from(self.response.clone()), + network, platform_version, + provider, ) - .map_drive_error(proof, mtd)?; + } +} - verify_tenderdash_proof(proof, mtd, &root_hash, provider)?; +impl FromProof for DocumentHistory { + type Request = platform::GetDocumentHistoryRequest; + type Response = platform::GetDocumentHistoryResponse; - // Preserve the distinction between a verified-but-empty history page - // (e.g. an offset/start_at_ms past the last revision) and an absent - // result: DocumentHistory carries retrieved values, not proof-of-absence, - // so a proven empty page is a legitimate `Some(empty)` rather than `None`. - Ok(( - maybe_history.map(IndexMap::from_iter), - mtd.clone(), - proof.clone(), - )) + fn maybe_from_proof_with_metadata<'a, I: Into, O: Into>( + request: I, + response: O, + _network: Network, + platform_version: &PlatformVersion, + provider: &'a dyn ContextProvider, + ) -> Result<(Option, ResponseMetadata, Proof), Error> + where + Self: Sized + 'a, + { + let request: Self::Request = request.into(); + let response: Self::Response = response.into(); + // A response without a proof or metadata is refused before the request + // is even looked at, as for every other proved query. + response.proof().or(Err(Error::NoProofInResult))?; + response.metadata().or(Err(Error::EmptyResponseMetadata))?; + match ( + request.version.ok_or(Error::EmptyVersion)?, + &response.version, + ) { + ( + get_document_history_request::Version::V0(request), + Some(platform::get_document_history_response::Version::V0(_)), + ) => { + verify_document_history_response_v0(request, &response, platform_version, provider) + } + ( + get_document_history_request::Version::V1(request), + Some(platform::get_document_history_response::Version::V1(_)), + ) => { + verify_document_history_response_v1(request, &response, platform_version, provider) + } + _ => Err(Error::ResponseDecodeError { + error: "document history response version must match its request".to_owned(), + }), + } } } @@ -3150,7 +3299,11 @@ macro_rules! define_length { define_length!(DataContract); define_length!(DataContractHistory, |d: &DataContractHistory| d.len()); -define_length!(DocumentHistory, |d: &DocumentHistory| d.len()); +define_length!(DocumentHistoryProofInfo, |d: &DocumentHistoryProofInfo| d + .history + .entries + .len()); +define_length!(DocumentHistory, |d: &DocumentHistory| d.entries.len()); define_length!(Document); define_length!(Identity); define_length!(IdentityBalance); @@ -3713,12 +3866,13 @@ mod tests { fn document_history_response_with_proof_and_metadata() -> platform::GetDocumentHistoryResponse { use platform::get_document_history_response::{ - get_document_history_response_v0::Result as V0Result, GetDocumentHistoryResponseV0, - Version, + get_document_history_response_v1, GetDocumentHistoryResponseV1, Version, }; platform::GetDocumentHistoryResponse { - version: Some(Version::V0(GetDocumentHistoryResponseV0 { - result: Some(V0Result::Proof(Proof::default())), + version: Some(Version::V1(GetDocumentHistoryResponseV1 { + result: Some(get_document_history_response_v1::Result::Proof( + Proof::default(), + )), metadata: Some(ResponseMetadata::default()), })), } @@ -3729,17 +3883,17 @@ mod tests { document_type_name: &str, document_id: Vec, limit: Option, - offset: Option, ) -> platform::GetDocumentHistoryRequest { - use dapi_grpc::platform::v0::get_document_history_request::GetDocumentHistoryRequestV0; - GetDocumentHistoryRequestV0 { + use dapi_grpc::platform::v0::get_document_history_request::{ + get_document_history_request_v1::Filter, GetDocumentHistoryRequestV1, + }; + GetDocumentHistoryRequestV1 { data_contract_id, document_type_name: document_type_name.to_string(), document_id, limit, - offset, - start_at_ms: 0, prove: true, + filter: Some(Filter::StartAtMs(0)), } .into() } @@ -5319,13 +5473,14 @@ mod tests { #[test] fn document_history_empty_response_metadata() { use platform::get_document_history_response::{ - get_document_history_response_v0::Result as V0Result, GetDocumentHistoryResponseV0, - Version, + get_document_history_response_v1, GetDocumentHistoryResponseV1, Version, }; let request = platform::GetDocumentHistoryRequest::default(); let response = platform::GetDocumentHistoryResponse { - version: Some(Version::V0(GetDocumentHistoryResponseV0 { - result: Some(V0Result::Proof(Proof::default())), + version: Some(Version::V1(GetDocumentHistoryResponseV1 { + result: Some(get_document_history_response_v1::Result::Proof( + Proof::default(), + )), metadata: None, })), }; @@ -5347,10 +5502,34 @@ mod tests { assert!(matches!(err, Error::EmptyVersion), "got: {err:?}"); } + #[test] + fn should_refuse_document_history_response_version_mismatches() { + use platform::get_document_history_request::GetDocumentHistoryRequestV0; + use platform::get_document_history_response::{ + get_document_history_response_v0, GetDocumentHistoryResponseV0, + }; + let provider = unreachable_provider(); + let v0_request: platform::GetDocumentHistoryRequest = + GetDocumentHistoryRequestV0::default().into(); + let v1_request = document_history_request(vec![0; 32], "note", vec![1; 32], None); + let v0_response: platform::GetDocumentHistoryResponse = GetDocumentHistoryResponseV0 { + result: Some(get_document_history_response_v0::Result::Proof( + Proof::default(), + )), + metadata: Some(ResponseMetadata::default()), + } + .into(); + let v1_response = document_history_response_with_proof_and_metadata(); + for (request, response) in [(v0_request, v1_response), (v1_request, v0_response)] { + let error = document_history_error(request, response, &provider); + assert!(matches!(error, Error::ResponseDecodeError { error } + if error == "document history response version must match its request")); + } + } + #[test] fn document_history_rejects_bad_contract_id_length() { - let request = - document_history_request(vec![0u8; 5], "niceDocument", vec![1u8; 32], None, None); + let request = document_history_request(vec![0u8; 5], "niceDocument", vec![1u8; 32], None); let response = document_history_response_with_proof_and_metadata(); let provider = unreachable_provider(); @@ -5361,8 +5540,7 @@ mod tests { #[test] fn document_history_rejects_bad_document_id_length() { - let request = - document_history_request(vec![0u8; 32], "niceDocument", vec![1u8; 5], None, None); + let request = document_history_request(vec![0u8; 32], "niceDocument", vec![1u8; 5], None); let response = document_history_response_with_proof_and_metadata(); let provider = unreachable_provider(); @@ -5373,13 +5551,8 @@ mod tests { #[test] fn document_history_rejects_overflowing_limit() { - let request = document_history_request( - vec![0u8; 32], - "niceDocument", - vec![1u8; 32], - Some(100_000), - None, - ); + let request = + document_history_request(vec![0u8; 32], "niceDocument", vec![1u8; 32], Some(100_000)); let response = document_history_response_with_proof_and_metadata(); let provider = unreachable_provider(); @@ -5390,8 +5563,7 @@ mod tests { #[test] fn document_history_returns_not_found_when_contract_provider_misses() { - let request = - document_history_request(vec![0u8; 32], "niceDocument", vec![1u8; 32], None, None); + let request = document_history_request(vec![0u8; 32], "niceDocument", vec![1u8; 32], None); let response = document_history_response_with_proof_and_metadata(); let provider = NoDataContractProvider; @@ -5412,8 +5584,7 @@ mod tests { let provider = StaticDataContractProvider { data_contract: std::sync::Arc::new(data_contract), }; - let request = - document_history_request(contract_id, "missingDocument", vec![1u8; 32], None, None); + let request = document_history_request(contract_id, "missingDocument", vec![1u8; 32], None); let response = document_history_response_with_proof_and_metadata(); let err = document_history_error(request, response, &provider); diff --git a/packages/rs-drive-proof-verifier/src/types.rs b/packages/rs-drive-proof-verifier/src/types.rs index 7593f209222..9ff7a96734e 100644 --- a/packages/rs-drive-proof-verifier/src/types.rs +++ b/packages/rs-drive-proof-verifier/src/types.rs @@ -123,10 +123,29 @@ pub type RetrievedValues = IndexMap; /// /// Contains a map of data contract revisions to data contracts. pub type DataContractHistory = RetrievedValues; -/// History of a document. -/// -/// Contains a map of revision timestamps to documents. -pub type DocumentHistory = RetrievedValues; +pub use drive::query::document_history_drive_query::{ + DocumentHistoryEntry, DocumentHistoryLifecycle, DocumentHistoryState, +}; + +/// Ordered document revisions with lifecycle metadata when the storage layout supports it. +#[derive(Debug, Clone, PartialEq)] +pub struct DocumentHistory { + /// Entries retain their complete cursor, including edits sharing a timestamp. + pub entries: Vec, + /// Absent for the legacy layout through protocol 14 and authenticated by protocol-15 proofs. + pub lifecycle: Option, +} +/// Verified history with the complete wire response needed for independent verification. +#[derive(Debug, Clone, PartialEq)] +pub struct DocumentHistoryProofInfo { + /// Decoded and verified history page. + pub history: DocumentHistory, + /// Original metadata and the quorum-signed proof whose GroveDB payload + /// carries one GroveDB proof of the page and lifecycle. + pub response: + dapi_grpc::platform::v0::get_document_history_response::GetDocumentHistoryResponseV1, +} + /// Multiple data contracts. /// /// Mapping between data contract IDs and data contracts. diff --git a/packages/rs-drive/grovedb-structure.json b/packages/rs-drive/grovedb-structure.json index e2ecc5d7bf8..cdc8991afa6 100644 --- a/packages/rs-drive/grovedb-structure.json +++ b/packages/rs-drive/grovedb-structure.json @@ -3045,15 +3045,18 @@ "Item", "ItemWithSumItem", "Tree", - "SumTree" + "SumTree", + "Reference", + "ReferenceWithSumItem" ], - "kinds_note": "An item; with a sum when the document type is summable; a tree of revisions when it keeps history.", + "kinds_note": "An item; with a sum when the document type is summable; a tree of revisions when it keeps history before protocol version 15, and a reference to its retained current revision from version 15.", "flags": [ "EpochOwned", "None" ], "flags_note": "The owner is the owner of the document, who is refunded when it is deleted. Documents the system writes, and documents of a type declaring a `ttl`, carry no flags.", "value": "serialized document", + "reference": "contracts.contract.documents.document_type.history.document.revision", "since": 1, "presence": "always", "source": "packages/rs-drive/src/drive/document/primary_key_tree_type.rs", @@ -3072,8 +3075,14 @@ "ReferenceWithSumItem" ], "kinds_note": "With a sum when the document type is summable.", + "flags": [ + "EpochOwned", + "None" + ], + "flags_note": "The document owner when the contract can be deleted; otherwise no flags.", "reference": "contracts.contract.documents.document_type.primary_key.document.revision", "since": 1, + "until": 14, "presence": "always", "source": "packages/rs-drive/src/drive/document/primary_key_tree_type.rs", "description": "A sibling reference to the newest revision.", @@ -3101,6 +3110,7 @@ "flags_note": "The owner is the owner of the document, who is refunded when it is deleted. Documents the system writes, and documents of a type declaring a `ttl`, carry no flags.", "value": "serialized document", "since": 1, + "until": 14, "presence": "always", "source": "packages/rs-drive/src/drive/document/primary_key_tree_type.rs", "description": "The document as it was at that time.", @@ -3110,6 +3120,83 @@ } ] }, + { + "id": "contracts.contract.documents.document_type.history", + "key": { + "type": "fixed", + "hex": "02", + "label": "History", + "constant": "DOCUMENT_HISTORY_TREE_KEY" + }, + "kinds": [ + "Tree" + ], + "flags": [ + "EpochOwned", + "None" + ], + "flags_note": "The contract's flags. Only the system contracts the upgrades to protocol versions 6, 9 and 13 registered carry them (wallet utils, token history, keyword search and document history), owned by the all-zero system owner in the epoch of the upgrade. Genesis, state transitions and later upgrades write none.", + "since": 15, + "presence": "lazy", + "source": "packages/rs-drive/src/drive/document/paths.rs", + "description": "Retained revisions of a type that keeps history, separate from its current primary entries.", + "children": [ + { + "id": "contracts.contract.documents.document_type.history.document", + "key": { + "type": "dynamic", + "name": "document_id", + "matcher": { + "type": "len", + "len": 32 + }, + "encoding": "identifier32", + "description": "The document id" + }, + "kinds": [ + "ProvableCountTree" + ], + "flags": [ + "EpochOwned", + "None" + ], + "flags_note": "The owner is the owner of the document, who is refunded when it is deleted. Documents the system writes, and documents of a type declaring a `ttl`, carry no flags.", + "since": 15, + "presence": "always", + "source": "packages/rs-drive/src/drive/document/paths.rs", + "description": "One document's retained history, with an authenticated revision count.", + "children": [ + { + "id": "contracts.contract.documents.document_type.history.document.revision", + "key": { + "type": "dynamic", + "name": "block_time_and_revision", + "matcher": { + "type": "len", + "len": 16 + }, + "encoding": "composite", + "description": "The block time followed by the revision, both unsigned u64 big endian" + }, + "kinds": [ + "Item" + ], + "flags": [ + "EpochOwned", + "None" + ], + "flags_note": "The owner is the owner of the document, who is refunded when it is deleted. Documents the system writes, and documents of a type declaring a `ttl`, carry no flags.", + "value": "serialized document", + "since": 15, + "presence": "always", + "source": "packages/rs-drive/src/drive/document/paths.rs", + "description": "An immutable retained revision.", + "children": [] + } + ] + } + ] + }, { "id": "contracts.contract.documents.document_type.index_property", "key": { diff --git a/packages/rs-drive/src/cache/system_contracts.rs b/packages/rs-drive/src/cache/system_contracts.rs index 9ec224f4184..71d368d7711 100644 --- a/packages/rs-drive/src/cache/system_contracts.rs +++ b/packages/rs-drive/src/cache/system_contracts.rs @@ -567,7 +567,7 @@ mod tests { fn committing_a_block_releases_the_outgoing_protocol_version() { let contracts = SystemDataContracts::new(); - for committed_protocol_version in 9..=14 { + for committed_protocol_version in 9..=15 { // The block that switches protocol version executes at the candidate while // `check_tx` still validates against the committed one, so both are live at once. contracts @@ -592,7 +592,7 @@ mod tests { fn memoization_is_bounded_to_the_live_protocol_versions() { let contracts = SystemDataContracts::new(); - for protocol_version in [9, 10, 11, 12, 13, 14] { + for protocol_version in [9, 10, 11, 12, 13, 14, 15] { contracts .load_dpns(platform_version(protocol_version)) .expect("materialize DPNS"); @@ -600,7 +600,7 @@ mod tests { assert_eq!( memoized_protocol_versions(&contracts), - vec![13, 14], + vec![14, 15], "only the most recent protocol versions stay memoized" ); diff --git a/packages/rs-drive/src/drive/constants.rs b/packages/rs-drive/src/drive/constants.rs index 6eeffe10fb0..6b3e6cb61b3 100644 --- a/packages/rs-drive/src/drive/constants.rs +++ b/packages/rs-drive/src/drive/constants.rs @@ -13,6 +13,9 @@ pub const BASE_CONTRACT_KEEPING_HISTORY_STORAGE_PATH_SIZE: u32 = 34; // 1 + 32 + pub const BASE_CONTRACT_DOCUMENTS_KEEPING_HISTORY_STORAGE_TIME_REFERENCE_PATH: u32 = 75; /// Base contract documents_keeping_history_primary_key path for document ID size pub const BASE_CONTRACT_DOCUMENTS_KEEPING_HISTORY_PRIMARY_KEY_PATH_FOR_DOCUMENT_ID_SIZE: u32 = 67; // 1 + 32 + 1 + 1 + 32, then we need to add document_type_name.len() +/// Reference payload and hop option, with two bytes for the estimator's flags-length +/// varint allowance to bound bincode's longer length encoding at its thresholds. +pub const DOCUMENT_HISTORY_CURRENT_REFERENCE_PATH_SIZE: u32 = 59; /// BaseDataContract Documents path size pub const BASE_CONTRACT_DOCUMENTS_PATH: u32 = 34; /// BaseDataContract Documents primary key path diff --git a/packages/rs-drive/src/drive/contract/insert/insert_contract/mod.rs b/packages/rs-drive/src/drive/contract/insert/insert_contract/mod.rs index 9f5ad8fa9b3..8ef9351b9d1 100644 --- a/packages/rs-drive/src/drive/contract/insert/insert_contract/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/insert_contract/mod.rs @@ -1,6 +1,7 @@ mod v0; mod v1; mod v2; +mod v3; use crate::drive::Drive; use crate::error::drive::DriveError; @@ -58,9 +59,12 @@ impl Drive { 2 => { self.insert_contract_v2(contract, block_info, apply, transaction, platform_version) } + 3 => { + self.insert_contract_v3(contract, block_info, apply, transaction, platform_version) + } version => Err(Error::Drive(DriveError::UnknownVersionMismatch { method: "insert_contract".to_string(), - known_versions: vec![0, 1, 2], + known_versions: vec![0, 1, 2, 3], received: version, })), } @@ -128,9 +132,18 @@ impl Drive { transaction, platform_version, ), + 3 => self.insert_contract_add_operations_v3( + contract_element, + contract, + block_info, + estimated_costs_only_with_layer_info, + drive_operations, + transaction, + platform_version, + ), version => Err(Error::Drive(DriveError::UnknownVersionMismatch { method: "insert_contract_add_operations".to_string(), - known_versions: vec![0, 1, 2], + known_versions: vec![0, 1, 2, 3], received: version, })), } diff --git a/packages/rs-drive/src/drive/contract/insert/insert_contract/v0/tests/chained_query_e2e_tests.rs b/packages/rs-drive/src/drive/contract/insert/insert_contract/v0/tests/chained_query_e2e_tests.rs index c1c4247894b..0719228afd1 100644 --- a/packages/rs-drive/src/drive/contract/insert/insert_contract/v0/tests/chained_query_e2e_tests.rs +++ b/packages/rs-drive/src/drive/contract/insert/insert_contract/v0/tests/chained_query_e2e_tests.rs @@ -40,6 +40,7 @@ use dpp::platform_value::{Identifier, Value}; use dpp::prelude::DataContract; use dpp::tests::json_document::json_document_to_contract; use grovedb::{GroveDb, PathQuery}; +use grovedb_version::version::v4::GROVE_V4; use std::collections::BTreeMap; const POST_A: [u8; 32] = [0xA1; 32]; @@ -1321,10 +1322,8 @@ fn chained_posts_tipped_by<'a>( ) } -/// For a page with rows, the merged query the proof covers is the one the -/// merge built when the inner half still carried its limit as a global -/// one: grovedb's merge lifts a global limit into the same per-instance -/// cap, so such a page proves to the same bytes as before. +/// Production components preserve the merged query bytes of the earlier global +/// limit lift. The current merge refuses that descending global-limit input. fn assert_merged_query_matches_the_lifted_global_limit( chained: &DriveDocumentQuery, join_values: &[Identifier], @@ -1341,11 +1340,21 @@ fn assert_merged_query_matches_the_lifted_global_limit( lifted[0].query.limit.is_some(), "the plain lowering carries the limit as a global one" ); - let merge = |path_queries: &[PathQuery]| { - PathQuery::merge(path_queries.iter().collect(), &pv.drive.grove_version) - .expect("the components merge") - }; - assert_eq!(merge(&components), merge(&lifted)); + let merged = PathQuery::merge(components.iter().collect(), &pv.drive.grove_version) + .expect("the production components merge"); + let previous = PathQuery::merge(lifted.iter().collect(), &GROVE_V4) + .expect("the previous merge lifts the global limit"); + assert_eq!(merged, previous); + let config = bincode::config::standard().with_big_endian(); + assert_eq!( + bincode::encode_to_vec(&merged, config).expect("current query bytes"), + bincode::encode_to_vec(&previous, config).expect("previous query bytes"), + ); + assert!(matches!( + PathQuery::merge(lifted.iter().collect(), &pv.drive.grove_version), + Err(grovedb::Error::NotSupported(message)) + if message == "can not merge a path query with a global limit whose body has subqueries: a branch cap would not charge its empty subtrees; set Query::limit on the query instead" + )); } /// Reads `chained` without and with a proof, verifies the proof, checks diff --git a/packages/rs-drive/src/drive/contract/insert/insert_contract/v1/mod.rs b/packages/rs-drive/src/drive/contract/insert/insert_contract/v1/mod.rs index 1090dd3f3ee..6ece22174d6 100644 --- a/packages/rs-drive/src/drive/contract/insert/insert_contract/v1/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/insert_contract/v1/mod.rs @@ -401,38 +401,42 @@ mod tests { /// drives the `i64::MAX` guard. #[test] fn test_insert_contract_with_token_base_supply_overflow_fails() { - let drive = setup_drive_with_initial_state_structure(None); - let platform_version = PlatformVersion::latest(); - - let mut contract = get_dashpay_contract_fixture(None, 0, platform_version.protocol_version) - .data_contract_owned(); - - // Set base_supply to u64::MAX, which is > i64::MAX. - let token_config = TokenConfiguration::V0( - TokenConfigurationV0::default_most_restrictive().with_base_supply(u64::MAX), - ); - contract.set_tokens(BTreeMap::from([(0, token_config)])); - - let result = drive.insert_contract( - &contract, - BlockInfo::default(), - true, - None, - platform_version, - ); - - assert!( - matches!( - &result, - Err(crate::error::Error::Protocol(boxed)) - if matches!( - boxed.as_ref(), - dpp::ProtocolError::CriticalCorruptedCreditsCodeExecution(_) - ) - ), - "Expected CriticalCorruptedCreditsCodeExecution, got: {:?}", - result - ); + for protocol_version in [14, 15] { + let platform_version = + PlatformVersion::get(protocol_version).expect("supported protocol"); + let drive = setup_drive_with_initial_state_structure(Some(platform_version)); + + let mut contract = + get_dashpay_contract_fixture(None, 0, platform_version.protocol_version) + .data_contract_owned(); + + // Set base_supply to u64::MAX, which is > i64::MAX. + let token_config = TokenConfiguration::V0( + TokenConfigurationV0::default_most_restrictive().with_base_supply(u64::MAX), + ); + contract.set_tokens(BTreeMap::from([(0, token_config)])); + + let result = drive.insert_contract( + &contract, + BlockInfo::default(), + true, + None, + platform_version, + ); + + assert!( + matches!( + &result, + Err(crate::error::Error::Protocol(boxed)) + if matches!( + boxed.as_ref(), + dpp::ProtocolError::CriticalCorruptedCreditsCodeExecution(_) + ) + ), + "Expected CriticalCorruptedCreditsCodeExecution, got: {:?}", + result + ); + } } /// Exercises the estimated-costs branches in `insert_contract_operations_v1` @@ -444,37 +448,41 @@ mod tests { /// apply=true path PR #3516 covered. #[test] fn test_insert_contract_v1_token_estimated_costs_branches() { - let drive = setup_drive_with_initial_state_structure(None); - let platform_version = PlatformVersion::latest(); - - let mut contract = get_dashpay_contract_fixture(None, 0, platform_version.protocol_version) - .data_contract_owned(); - - // Add two tokens so the loop in insert_contract_operations_v1 iterates more - // than once; this helps exercise estimation-cost paths per token. - let mut paused_config = - TokenConfiguration::V0(TokenConfigurationV0::default_most_restrictive()); - paused_config.set_start_as_paused(true); - let normal_config = TokenConfiguration::V0( - TokenConfigurationV0::default_most_restrictive().with_base_supply(500), - ); - contract.set_tokens(BTreeMap::from([(0, paused_config), (1, normal_config)])); - - // apply=false forces the estimation branches. - let fee = drive - .insert_contract( - &contract, - BlockInfo::default(), - false, - None, - platform_version, - ) - .expect("estimation insert should succeed with tokens"); + for protocol_version in [14, 15] { + let platform_version = + PlatformVersion::get(protocol_version).expect("supported protocol"); + let drive = setup_drive_with_initial_state_structure(Some(platform_version)); + + let mut contract = + get_dashpay_contract_fixture(None, 0, platform_version.protocol_version) + .data_contract_owned(); + + // Add two tokens so the loop in insert_contract_operations_v1 iterates more + // than once; this helps exercise estimation-cost paths per token. + let mut paused_config = + TokenConfiguration::V0(TokenConfigurationV0::default_most_restrictive()); + paused_config.set_start_as_paused(true); + let normal_config = TokenConfiguration::V0( + TokenConfigurationV0::default_most_restrictive().with_base_supply(500), + ); + contract.set_tokens(BTreeMap::from([(0, paused_config), (1, normal_config)])); + + // apply=false forces the estimation branches. + let fee = drive + .insert_contract( + &contract, + BlockInfo::default(), + false, + None, + platform_version, + ) + .expect("estimation insert should succeed with tokens"); - assert!( - fee.processing_fee > 0 || fee.storage_fee > 0, - "estimation should produce non-zero fees" - ); + assert!( + fee.processing_fee > 0 || fee.storage_fee > 0, + "estimation should produce non-zero fees" + ); + } } /// Exercises the `insert_contract_v1` early-exit for `contract.groups().is_empty()`: @@ -483,32 +491,36 @@ mod tests { /// also asserting token+keyword insertion still works on a separate contract id. #[test] fn test_insert_contract_v1_empty_groups_with_tokens_and_keywords() { - let drive = setup_drive_with_initial_state_structure(None); - let platform_version = PlatformVersion::latest(); - - let mut contract = get_dashpay_contract_fixture(None, 0, platform_version.protocol_version) - .data_contract_owned(); - - // Tokens yes, groups intentionally empty. - let token_config = TokenConfiguration::V0( - TokenConfigurationV0::default_most_restrictive().with_base_supply(42), - ); - contract.set_tokens(BTreeMap::from([(0, token_config)])); - assert!(contract.groups().is_empty()); - - // Use apply=false so we don't need keyword_search contract in grove yet. - // This covers the empty-groups-AND-empty-keywords-AND-no-description branches - // while still exercising the token loop. - let fee = drive - .insert_contract( - &contract, - BlockInfo::default(), - false, - None, - platform_version, - ) - .expect("should succeed with tokens only"); - assert!(fee.processing_fee > 0 || fee.storage_fee > 0); + for protocol_version in [14, 15] { + let platform_version = + PlatformVersion::get(protocol_version).expect("supported protocol"); + let drive = setup_drive_with_initial_state_structure(Some(platform_version)); + + let mut contract = + get_dashpay_contract_fixture(None, 0, platform_version.protocol_version) + .data_contract_owned(); + + // Tokens yes, groups intentionally empty. + let token_config = TokenConfiguration::V0( + TokenConfigurationV0::default_most_restrictive().with_base_supply(42), + ); + contract.set_tokens(BTreeMap::from([(0, token_config)])); + assert!(contract.groups().is_empty()); + + // Use apply=false so we don't need keyword_search contract in grove yet. + // This covers the empty-groups-AND-empty-keywords-AND-no-description branches + // while still exercising the token loop. + let fee = drive + .insert_contract( + &contract, + BlockInfo::default(), + false, + None, + platform_version, + ) + .expect("should succeed with tokens only"); + assert!(fee.processing_fee > 0 || fee.storage_fee > 0); + } } /// Exercises `insert_contract_v1` with a token whose position doesn't round-trip @@ -519,37 +531,41 @@ mod tests { /// identity_infos trees. #[test] fn test_insert_contract_v1_two_tokens_distinct_ids_all_trees_created() { - let drive = setup_drive_with_initial_state_structure(None); - let platform_version = PlatformVersion::latest(); - - let mut contract = get_dashpay_contract_fixture(None, 0, platform_version.protocol_version) - .data_contract_owned(); - - let c1 = TokenConfiguration::V0( - TokenConfigurationV0::default_most_restrictive().with_base_supply(10), - ); - let c2 = TokenConfiguration::V0( - TokenConfigurationV0::default_most_restrictive().with_base_supply(0), - ); - contract.set_tokens(BTreeMap::from([(0, c1), (1, c2)])); - - drive - .apply_contract( - &contract, - BlockInfo::default(), - true, - StorageFlags::optional_default_as_cow(), - None, - platform_version, - ) - .expect("apply with two tokens should succeed"); - - // Token positions 0 and 1 must yield different ids. - let id0 = contract.token_id(0).expect("token 0 id"); - let id1 = contract.token_id(1).expect("token 1 id"); - assert_ne!( - id0, id1, - "tokens at different positions must have distinct ids" - ); + for protocol_version in [14, 15] { + let platform_version = + PlatformVersion::get(protocol_version).expect("supported protocol"); + let drive = setup_drive_with_initial_state_structure(Some(platform_version)); + + let mut contract = + get_dashpay_contract_fixture(None, 0, platform_version.protocol_version) + .data_contract_owned(); + + let c1 = TokenConfiguration::V0( + TokenConfigurationV0::default_most_restrictive().with_base_supply(10), + ); + let c2 = TokenConfiguration::V0( + TokenConfigurationV0::default_most_restrictive().with_base_supply(0), + ); + contract.set_tokens(BTreeMap::from([(0, c1), (1, c2)])); + + drive + .apply_contract( + &contract, + BlockInfo::default(), + true, + StorageFlags::optional_default_as_cow(), + None, + platform_version, + ) + .expect("apply with two tokens should succeed"); + + // Token positions 0 and 1 must yield different ids. + let id0 = contract.token_id(0).expect("token 0 id"); + let id1 = contract.token_id(1).expect("token 1 id"); + assert_ne!( + id0, id1, + "tokens at different positions must have distinct ids" + ); + } } } diff --git a/packages/rs-drive/src/drive/contract/insert/insert_contract/v3/mod.rs b/packages/rs-drive/src/drive/contract/insert/insert_contract/v3/mod.rs new file mode 100644 index 00000000000..5f8f2fafa28 --- /dev/null +++ b/packages/rs-drive/src/drive/contract/insert/insert_contract/v3/mod.rs @@ -0,0 +1,164 @@ +use crate::drive::document::paths::{contract_document_type_path, DOCUMENT_HISTORY_TREE_KEY}; +use crate::drive::Drive; +use crate::error::Error; +use crate::fees::op::LowLevelDriveOperation; +use crate::util::estimated_layers::EstimatedLayers; +use crate::util::object_size_info::DriveKeyInfo::KeyRef; +use crate::util::storage_flags::StorageFlags; +use dpp::block::block_info::BlockInfo; +use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters; +use dpp::data_contract::DataContract; +use dpp::fee::fee_result::FeeResult; +use dpp::version::PlatformVersion; +use grovedb::{Element, TransactionArg}; + +impl Drive { + /// Inserts the contract with all generation 2 trees and each retained type's history tree. + #[inline(always)] + pub(super) fn insert_contract_v3( + &self, + contract: &DataContract, + block_info: BlockInfo, + apply: bool, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result { + let mut drive_operations: Vec = vec![]; + + let contract_element = + Self::contract_element_for_insert_v1(contract, &block_info, platform_version)?; + + let mut estimated_costs_only_with_layer_info = if apply { + None:: + } else { + Some(EstimatedLayers::new()) + }; + let batch_operations = self.insert_contract_operations_v3( + contract_element, + contract, + &block_info, + &mut estimated_costs_only_with_layer_info, + transaction, + platform_version, + )?; + self.apply_batch_low_level_drive_operations( + estimated_costs_only_with_layer_info, + transaction, + batch_operations, + &mut drive_operations, + &platform_version.drive, + )?; + + self.calculate_fee( + None, + Some(drive_operations), + &block_info.epoch, + platform_version, + ) + } + + /// The operations for adding a contract, appended to `drive_operations`. + #[inline(always)] + #[allow(clippy::too_many_arguments)] + pub(super) fn insert_contract_add_operations_v3( + &self, + contract_element: Element, + contract: &DataContract, + block_info: &BlockInfo, + estimated_costs_only_with_layer_info: &mut Option, + drive_operations: &mut Vec, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result<(), Error> { + let batch_operations = self.insert_contract_operations_v3( + contract_element, + contract, + block_info, + estimated_costs_only_with_layer_info, + transaction, + platform_version, + )?; + drive_operations.extend(batch_operations); + Ok(()) + } + + /// Collects generation 2 writes and the per-type history trees in the same batch. + fn insert_contract_operations_v3( + &self, + contract_element: Element, + contract: &DataContract, + block_info: &BlockInfo, + estimated_costs_only_with_layer_info: &mut Option, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result, Error> { + let flags = contract_element.get_flags().clone(); + let storage_flags = StorageFlags::map_some_element_flags_ref(&flags)?; + let mut operations = vec![]; + self.insert_contract_add_operations_v2( + contract_element, + contract, + block_info, + estimated_costs_only_with_layer_info, + &mut operations, + transaction, + platform_version, + )?; + for (name, document_type) in contract.document_types() { + if document_type.documents_keep_history() { + self.batch_insert_empty_tree( + contract_document_type_path(contract.id_ref().as_bytes(), name), + KeyRef(&[DOCUMENT_HISTORY_TREE_KEY]), + storage_flags.as_ref(), + &mut operations, + &platform_version.drive, + )?; + } + } + Ok(operations) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::util::test_helpers::setup::setup_drive_with_initial_state_structure; + #[test] + fn should_create_the_history_tree_only_from_protocol_15() { + use crate::drive::document::paths::{ + contract_document_type_path_vec, DOCUMENT_HISTORY_TREE_KEY, + }; + use dpp::data_contract::accessors::v0::DataContractV0Getters; + use dpp::tests::json_document::json_document_to_contract; + + for (protocol, expected) in [(14, false), (15, true)] { + let version = PlatformVersion::get(protocol).expect("protocol version"); + let drive = setup_drive_with_initial_state_structure(Some(version)); + let contract = json_document_to_contract( + "tests/supporting_files/contract/dashpay/dashpay-contract-with-profile-history.json", + false, + version, + ) + .expect("keep-history contract fixture"); + drive + .insert_contract(&contract, BlockInfo::default(), true, None, version) + .expect("insert contract"); + let type_path = contract_document_type_path_vec(contract.id().as_slice(), "profile"); + let history_tree = drive + .grove + .get_raw( + type_path.as_slice().into(), + &[DOCUMENT_HISTORY_TREE_KEY], + None, + &version.drive.grove_version, + ) + .value; + assert_eq!( + history_tree.is_ok(), + expected, + "protocol {protocol}: {history_tree:?}" + ); + } + } +} diff --git a/packages/rs-drive/src/drive/contract/mod.rs b/packages/rs-drive/src/drive/contract/mod.rs index 2af7a2f7526..66130f9df66 100644 --- a/packages/rs-drive/src/drive/contract/mod.rs +++ b/packages/rs-drive/src/drive/contract/mod.rs @@ -2394,10 +2394,15 @@ mod tests { /// that have descriptions or keywords, because `insert_contract_v1` creates /// documents in the keyword_search contract. fn setup_drive_with_keyword_search_contract() -> Drive { + setup_drive_with_keyword_search_contract_at_version(PlatformVersion::latest()) + } + + fn setup_drive_with_keyword_search_contract_at_version( + platform_version: &PlatformVersion, + ) -> Drive { use dpp::system_data_contracts::{load_system_data_contract, SystemDataContract}; - let drive = setup_drive_with_initial_state_structure(None); - let platform_version = PlatformVersion::latest(); + let drive = setup_drive_with_initial_state_structure(Some(platform_version)); let keyword_search_contract = load_system_data_contract(SystemDataContract::KeywordSearch, platform_version) @@ -2514,50 +2519,59 @@ mod tests { #[test] fn test_insert_contract_with_keywords() { - use dpp::data_contract::accessors::v1::{DataContractV1Getters, DataContractV1Setters}; - use dpp::tests::fixtures::get_data_contract_fixture; - - let drive = setup_drive_with_keyword_search_contract(); - let platform_version = PlatformVersion::latest(); - - let mut contract = get_data_contract_fixture(None, 0, platform_version.protocol_version) - .data_contract_owned(); - - contract.set_keywords(vec![ - "alpha".to_string(), - "beta".to_string(), - "gamma".to_string(), - ]); - - // insert_contract_v1 should create keyword documents in the - // keyword_search contract without error. - let fee = drive - .apply_contract( - &contract, - BlockInfo::default(), - true, - StorageFlags::optional_default_as_cow(), - None, - platform_version, - ) - .expect("should insert contract with keywords successfully"); + for protocol_version in [14, 15] { + let platform_version = + PlatformVersion::get(protocol_version).expect("supported protocol"); + use dpp::data_contract::accessors::v1::{DataContractV1Getters, DataContractV1Setters}; + use dpp::tests::fixtures::get_data_contract_fixture; + + let drive = setup_drive_with_keyword_search_contract_at_version(platform_version); + + let mut contract = + get_data_contract_fixture(None, 0, platform_version.protocol_version) + .data_contract_owned(); + + contract.set_keywords(vec![ + "alpha".to_string(), + "beta".to_string(), + "gamma".to_string(), + ]); + + // insert_contract_v1 should create keyword documents in the + // keyword_search contract without error. + let fee = drive + .apply_contract( + &contract, + BlockInfo::default(), + true, + StorageFlags::optional_default_as_cow(), + None, + platform_version, + ) + .expect("should insert contract with keywords successfully"); - assert!( - fee.processing_fee > 0, - "inserting a contract with keywords should produce a non-zero processing fee" - ); + assert!( + fee.processing_fee > 0, + "inserting a contract with keywords should produce a non-zero processing fee" + ); - // Verify the contract can still be fetched back - let fetched = drive - .get_contract_with_fetch_info(contract.id().to_buffer(), true, None, platform_version) - .expect("should fetch contract") - .expect("contract should exist"); + // Verify the contract can still be fetched back + let fetched = drive + .get_contract_with_fetch_info( + contract.id().to_buffer(), + true, + None, + platform_version, + ) + .expect("should fetch contract") + .expect("contract should exist"); - assert_eq!(fetched.contract.id(), contract.id()); - assert_eq!( - fetched.contract.keywords(), - &vec!["alpha".to_string(), "beta".to_string(), "gamma".to_string()], - ); + assert_eq!(fetched.contract.id(), contract.id()); + assert_eq!( + fetched.contract.keywords(), + &vec!["alpha".to_string(), "beta".to_string(), "gamma".to_string()], + ); + } } #[test] @@ -2731,44 +2745,53 @@ mod tests { #[test] fn test_insert_contract_with_groups() { - use dpp::data_contract::accessors::v1::DataContractV1Setters; - use dpp::data_contract::group::v0::GroupV0; - use dpp::data_contract::group::Group; - use dpp::prelude::Identifier; - use std::collections::BTreeMap; - - let drive = setup_drive_with_initial_state_structure(None); - let platform_version = PlatformVersion::latest(); + for protocol_version in [14, 15] { + let platform_version = + PlatformVersion::get(protocol_version).expect("supported protocol"); + use dpp::data_contract::accessors::v1::DataContractV1Setters; + use dpp::data_contract::group::v0::GroupV0; + use dpp::data_contract::group::Group; + use dpp::prelude::Identifier; + use std::collections::BTreeMap; + + let drive = setup_drive_with_initial_state_structure(Some(platform_version)); + + let mut contract = + get_dashpay_contract_fixture(None, 0, platform_version.protocol_version) + .data_contract_owned(); + + // Add a group with a single member to exercise the groups branch + let member_id = Identifier::random(); + let group = Group::V0(GroupV0 { + members: BTreeMap::from([(member_id, 1)]), + required_power: 1, + }); + contract.set_groups(BTreeMap::from([(0, group)])); - let mut contract = get_dashpay_contract_fixture(None, 0, platform_version.protocol_version) - .data_contract_owned(); - - // Add a group with a single member to exercise the groups branch - let member_id = Identifier::random(); - let group = Group::V0(GroupV0 { - members: BTreeMap::from([(member_id, 1)]), - required_power: 1, - }); - contract.set_groups(BTreeMap::from([(0, group)])); - - drive - .apply_contract( - &contract, - BlockInfo::default(), - true, - StorageFlags::optional_default_as_cow(), - None, - platform_version, - ) - .expect("expected to apply contract with groups successfully"); + drive + .apply_contract( + &contract, + BlockInfo::default(), + true, + StorageFlags::optional_default_as_cow(), + None, + platform_version, + ) + .expect("expected to apply contract with groups successfully"); - // Verify the contract can be fetched back - let fetched = drive - .get_contract_with_fetch_info(contract.id().to_buffer(), true, None, platform_version) - .expect("should fetch contract") - .expect("contract should exist"); + // Verify the contract can be fetched back + let fetched = drive + .get_contract_with_fetch_info( + contract.id().to_buffer(), + true, + None, + platform_version, + ) + .expect("should fetch contract") + .expect("contract should exist"); - assert_eq!(fetched.contract.id(), contract.id()); + assert_eq!(fetched.contract.id(), contract.id()); + } } /// Exercises the `ok_or(CorruptedCodeExecution("contract should exist"))` diff --git a/packages/rs-drive/src/drive/contract/update/update_contract/mod.rs b/packages/rs-drive/src/drive/contract/update/update_contract/mod.rs index d0d94faa77b..a9dd15901f8 100644 --- a/packages/rs-drive/src/drive/contract/update/update_contract/mod.rs +++ b/packages/rs-drive/src/drive/contract/update/update_contract/mod.rs @@ -1,6 +1,7 @@ mod v0; mod v1; mod v2; +mod v3; use crate::drive::Drive; use crate::error::drive::DriveError; @@ -64,9 +65,12 @@ impl Drive { 2 => { self.update_contract_v2(contract, block_info, apply, transaction, platform_version) } + 3 => { + self.update_contract_v3(contract, block_info, apply, transaction, platform_version) + } version => Err(Error::Drive(DriveError::UnknownVersionMismatch { method: "update_contract".to_string(), - known_versions: vec![0, 1, 2], + known_versions: vec![0, 1, 2, 3], received: version, })), } @@ -144,9 +148,18 @@ impl Drive { drive_operations, platform_version, ), + 3 => self.update_contract_element_v3( + contract_element, + contract, + original_contract, + block_info, + transaction, + drive_operations, + platform_version, + ), version => Err(Error::Drive(DriveError::UnknownVersionMismatch { method: "update_contract_element".to_string(), - known_versions: vec![0, 1, 2], + known_versions: vec![0, 1, 2, 3], received: version, })), } @@ -230,9 +243,19 @@ impl Drive { drive_operations, platform_version, ), + 3 => self.update_contract_add_operations_v3( + contract_element, + contract, + original_contract, + block_info, + estimated_costs_only_with_layer_info, + transaction, + drive_operations, + platform_version, + ), version => Err(Error::Drive(DriveError::UnknownVersionMismatch { method: "update_contract_add_operations".to_string(), - known_versions: vec![0, 1, 2], + known_versions: vec![0, 1, 2, 3], received: version, })), } diff --git a/packages/rs-drive/src/drive/contract/update/update_contract/v1/mod.rs b/packages/rs-drive/src/drive/contract/update/update_contract/v1/mod.rs index 5125771d769..2f5dd7b489b 100644 --- a/packages/rs-drive/src/drive/contract/update/update_contract/v1/mod.rs +++ b/packages/rs-drive/src/drive/contract/update/update_contract/v1/mod.rs @@ -315,42 +315,46 @@ mod tests { /// UPDATE that adds tokens. #[test] fn test_update_contract_v1_adds_tokens_creates_token_trees() { - let drive = setup_drive_with_initial_state_structure(None); - let platform_version = PlatformVersion::latest(); - - // Original: no tokens. - let mut contract = get_dashpay_contract_fixture(None, 0, platform_version.protocol_version) - .data_contract_owned(); - contract.config_mut().set_readonly(false); - - drive - .apply_contract( - &contract, - BlockInfo::default(), - true, - StorageFlags::optional_default_as_cow(), - None, - platform_version, - ) - .expect("insert initial contract without tokens"); - - // Updated: add a token configuration. The update path exercises the - // `create_token_trees_operations` call in update_contract_operations_v1. - let token_config = TokenConfiguration::V0( - TokenConfigurationV0::default_most_restrictive().with_base_supply(0), - ); - contract.set_tokens(BTreeMap::from([(0, token_config)])); - contract.increment_version(); - - drive - .update_contract( - &contract, - BlockInfo::default(), - true, - None, - platform_version, - ) - .expect("update adding tokens should succeed"); + for protocol_version in [14, 15] { + let platform_version = + PlatformVersion::get(protocol_version).expect("supported protocol"); + let drive = setup_drive_with_initial_state_structure(Some(platform_version)); + + // Original: no tokens. + let mut contract = + get_dashpay_contract_fixture(None, 0, platform_version.protocol_version) + .data_contract_owned(); + contract.config_mut().set_readonly(false); + + drive + .apply_contract( + &contract, + BlockInfo::default(), + true, + StorageFlags::optional_default_as_cow(), + None, + platform_version, + ) + .expect("insert initial contract without tokens"); + + // Updated: add a token configuration. The update path exercises the + // `create_token_trees_operations` call in update_contract_operations_v1. + let token_config = TokenConfiguration::V0( + TokenConfigurationV0::default_most_restrictive().with_base_supply(0), + ); + contract.set_tokens(BTreeMap::from([(0, token_config)])); + contract.increment_version(); + + drive + .update_contract( + &contract, + BlockInfo::default(), + true, + None, + platform_version, + ) + .expect("update adding tokens should succeed"); + } } /// Exercises `update_contract_operations_v1` where the updated contract @@ -359,41 +363,45 @@ mod tests { /// `update_contract_operations_v1`, invoking `add_new_groups_operations`. #[test] fn test_update_contract_v1_adds_groups() { - let drive = setup_drive_with_initial_state_structure(None); - let platform_version = PlatformVersion::latest(); - - let mut contract = get_dashpay_contract_fixture(None, 0, platform_version.protocol_version) - .data_contract_owned(); - - drive - .apply_contract( - &contract, - BlockInfo::default(), - true, - StorageFlags::optional_default_as_cow(), - None, - platform_version, - ) - .expect("insert"); - - // Add a group. - let member = Identifier::random(); - let group = Group::V0(GroupV0 { - members: BTreeMap::from([(member, 1)]), - required_power: 1, - }); - contract.set_groups(BTreeMap::from([(0, group)])); - contract.increment_version(); - - drive - .update_contract( - &contract, - BlockInfo::default(), - true, - None, - platform_version, - ) - .expect("update adding groups should succeed"); + for protocol_version in [14, 15] { + let platform_version = + PlatformVersion::get(protocol_version).expect("supported protocol"); + let drive = setup_drive_with_initial_state_structure(Some(platform_version)); + + let mut contract = + get_dashpay_contract_fixture(None, 0, platform_version.protocol_version) + .data_contract_owned(); + + drive + .apply_contract( + &contract, + BlockInfo::default(), + true, + StorageFlags::optional_default_as_cow(), + None, + platform_version, + ) + .expect("insert"); + + // Add a group. + let member = Identifier::random(); + let group = Group::V0(GroupV0 { + members: BTreeMap::from([(member, 1)]), + required_power: 1, + }); + contract.set_groups(BTreeMap::from([(0, group)])); + contract.increment_version(); + + drive + .update_contract( + &contract, + BlockInfo::default(), + true, + None, + platform_version, + ) + .expect("update adding groups should succeed"); + } } /// Exercises `update_contract_operations_v1`'s keyword-update branch: @@ -404,58 +412,62 @@ mod tests { /// via `update_contract`. #[test] fn test_update_contract_v1_keyword_delta_via_update_contract() { - let drive = setup_drive_with_initial_state_structure(None); - let platform_version = PlatformVersion::latest(); - - // Insert the keyword_search system contract first (required because - // update_contract_v1 calls update_contract_keywords_operations). - let keyword_search = - load_system_data_contract(SystemDataContract::KeywordSearch, platform_version) - .expect("load keyword_search"); - drive - .apply_contract( - &keyword_search, - BlockInfo::default(), - true, - None, - None, - platform_version, - ) - .expect("apply keyword_search"); - - let mut contract = get_dashpay_contract_fixture(None, 0, platform_version.protocol_version) - .data_contract_owned(); - contract.set_keywords(vec!["initial_a".to_string(), "initial_b".to_string()]); - - drive - .apply_contract( - &contract, - BlockInfo::default(), - true, - StorageFlags::optional_default_as_cow(), - None, - platform_version, - ) - .expect("initial insert with keywords"); - - // Now change keywords entirely. - contract.set_keywords(vec!["new_x".to_string(), "new_y".to_string()]); - contract.increment_version(); - - drive - .update_contract( - &contract, - BlockInfo { - time_ms: 2000, - height: 10, - core_height: 5, - epoch: Default::default(), - }, - true, - None, - platform_version, - ) - .expect("update keyword delta via update_contract should succeed"); + for protocol_version in [14, 15] { + let platform_version = + PlatformVersion::get(protocol_version).expect("supported protocol"); + let drive = setup_drive_with_initial_state_structure(Some(platform_version)); + + // Insert the keyword_search system contract first (required because + // update_contract_v1 calls update_contract_keywords_operations). + let keyword_search = + load_system_data_contract(SystemDataContract::KeywordSearch, platform_version) + .expect("load keyword_search"); + drive + .apply_contract( + &keyword_search, + BlockInfo::default(), + true, + None, + None, + platform_version, + ) + .expect("apply keyword_search"); + + let mut contract = + get_dashpay_contract_fixture(None, 0, platform_version.protocol_version) + .data_contract_owned(); + contract.set_keywords(vec!["initial_a".to_string(), "initial_b".to_string()]); + + drive + .apply_contract( + &contract, + BlockInfo::default(), + true, + StorageFlags::optional_default_as_cow(), + None, + platform_version, + ) + .expect("initial insert with keywords"); + + // Now change keywords entirely. + contract.set_keywords(vec!["new_x".to_string(), "new_y".to_string()]); + contract.increment_version(); + + drive + .update_contract( + &contract, + BlockInfo { + time_ms: 2000, + height: 10, + core_height: 5, + epoch: Default::default(), + }, + true, + None, + platform_version, + ) + .expect("update keyword delta via update_contract should succeed"); + } } /// The keywords the keyword search index currently returns for `contract_id`. @@ -520,61 +532,65 @@ mod tests { /// empty group tree. Making the deletes sibling-aware has to come first. #[test] fn clearing_a_contracts_keywords_leaves_the_old_ones_indexed() { - let drive = setup_drive_with_initial_state_structure(None); - let platform_version = PlatformVersion::latest(); - - let keyword_search = - load_system_data_contract(SystemDataContract::KeywordSearch, platform_version) - .expect("load keyword_search"); - drive - .apply_contract( - &keyword_search, - BlockInfo::default(), - true, - None, - None, - platform_version, - ) - .expect("apply keyword_search"); - - let mut contract = get_dashpay_contract_fixture(None, 0, platform_version.protocol_version) - .data_contract_owned(); - contract.set_keywords(vec!["alpha".to_string(), "bravo".to_string()]); - drive - .apply_contract( - &contract, - BlockInfo::default(), - true, - StorageFlags::optional_default_as_cow(), - None, - platform_version, - ) - .expect("initial insert with keywords"); - - assert_eq!( - indexed_keywords(&drive, &keyword_search, contract.id(), platform_version), - vec!["alpha".to_string(), "bravo".to_string()], - "baseline: both keywords are indexed" - ); - - contract.set_keywords(vec![]); - contract.increment_version(); - drive - .update_contract( - &contract, - BlockInfo::default(), - true, - None, - platform_version, - ) - .expect("clearing keywords via update_contract should succeed"); + for protocol_version in [14, 15] { + let platform_version = + PlatformVersion::get(protocol_version).expect("supported protocol"); + let drive = setup_drive_with_initial_state_structure(Some(platform_version)); + + let keyword_search = + load_system_data_contract(SystemDataContract::KeywordSearch, platform_version) + .expect("load keyword_search"); + drive + .apply_contract( + &keyword_search, + BlockInfo::default(), + true, + None, + None, + platform_version, + ) + .expect("apply keyword_search"); + + let mut contract = + get_dashpay_contract_fixture(None, 0, platform_version.protocol_version) + .data_contract_owned(); + contract.set_keywords(vec!["alpha".to_string(), "bravo".to_string()]); + drive + .apply_contract( + &contract, + BlockInfo::default(), + true, + StorageFlags::optional_default_as_cow(), + None, + platform_version, + ) + .expect("initial insert with keywords"); + + assert_eq!( + indexed_keywords(&drive, &keyword_search, contract.id(), platform_version), + vec!["alpha".to_string(), "bravo".to_string()], + "baseline: both keywords are indexed" + ); - assert_eq!( - indexed_keywords(&drive, &keyword_search, contract.id(), platform_version), - vec!["alpha".to_string(), "bravo".to_string()], - "the old keyword documents are expected to survive: an empty keyword set skips \ - the keyword update rather than performing it" - ); + contract.set_keywords(vec![]); + contract.increment_version(); + drive + .update_contract( + &contract, + BlockInfo::default(), + true, + None, + platform_version, + ) + .expect("clearing keywords via update_contract should succeed"); + + assert_eq!( + indexed_keywords(&drive, &keyword_search, contract.id(), platform_version), + vec!["alpha".to_string(), "bravo".to_string()], + "the old keyword documents are expected to survive: an empty keyword set skips \ + the keyword update rather than performing it" + ); + } } /// Exercises `update_contract_operations_v1`'s description-update branch: @@ -584,54 +600,58 @@ mod tests { /// description API). #[test] fn test_update_contract_v1_description_via_update_contract() { - let drive = setup_drive_with_initial_state_structure(None); - let platform_version = PlatformVersion::latest(); - - let keyword_search = - load_system_data_contract(SystemDataContract::KeywordSearch, platform_version) - .expect("load keyword_search"); - drive - .apply_contract( - &keyword_search, - BlockInfo::default(), - true, - None, - None, - platform_version, - ) - .expect("apply keyword_search"); - - let mut contract = get_dashpay_contract_fixture(None, 0, platform_version.protocol_version) - .data_contract_owned(); - contract.set_description(Some("initial description".to_string())); - - drive - .apply_contract( - &contract, - BlockInfo::default(), - true, - StorageFlags::optional_default_as_cow(), - None, - platform_version, - ) - .expect("initial insert with description"); - - contract.set_description(Some("updated description text".to_string())); - contract.increment_version(); - - drive - .update_contract( - &contract, - BlockInfo { - time_ms: 3000, - height: 20, - core_height: 7, - epoch: Default::default(), - }, - true, - None, - platform_version, - ) - .expect("update description via update_contract should succeed"); + for protocol_version in [14, 15] { + let platform_version = + PlatformVersion::get(protocol_version).expect("supported protocol"); + let drive = setup_drive_with_initial_state_structure(Some(platform_version)); + + let keyword_search = + load_system_data_contract(SystemDataContract::KeywordSearch, platform_version) + .expect("load keyword_search"); + drive + .apply_contract( + &keyword_search, + BlockInfo::default(), + true, + None, + None, + platform_version, + ) + .expect("apply keyword_search"); + + let mut contract = + get_dashpay_contract_fixture(None, 0, platform_version.protocol_version) + .data_contract_owned(); + contract.set_description(Some("initial description".to_string())); + + drive + .apply_contract( + &contract, + BlockInfo::default(), + true, + StorageFlags::optional_default_as_cow(), + None, + platform_version, + ) + .expect("initial insert with description"); + + contract.set_description(Some("updated description text".to_string())); + contract.increment_version(); + + drive + .update_contract( + &contract, + BlockInfo { + time_ms: 3000, + height: 20, + core_height: 7, + epoch: Default::default(), + }, + true, + None, + platform_version, + ) + .expect("update description via update_contract should succeed"); + } } } diff --git a/packages/rs-drive/src/drive/contract/update/update_contract/v3/mod.rs b/packages/rs-drive/src/drive/contract/update/update_contract/v3/mod.rs new file mode 100644 index 00000000000..0cc84ed7daf --- /dev/null +++ b/packages/rs-drive/src/drive/contract/update/update_contract/v3/mod.rs @@ -0,0 +1,411 @@ +use crate::drive::document::paths::{contract_document_type_path, DOCUMENT_HISTORY_TREE_KEY}; +use crate::drive::Drive; +use crate::error::drive::DriveError; +use crate::error::Error; +use crate::fees::op::LowLevelDriveOperation; +use crate::util::estimated_layers::EstimatedLayers; +use crate::util::object_size_info::DriveKeyInfo::KeyRef; +use crate::util::storage_flags::StorageFlags; +use dpp::block::block_info::BlockInfo; +use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::data_contract::config::v0::DataContractConfigGettersV0; +use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters; +use dpp::data_contract::DataContract; +use dpp::fee::fee_result::FeeResult; + +use crate::drive::contract::serialize_contract_for_storage; + +use dpp::version::PlatformVersion; +use grovedb::{Element, TransactionArg}; + +impl Drive { + /// Updates a data contract. + /// + /// This function updates a given data contract in the storage. The fee for updating + /// the contract is also calculated and returned. + /// + /// # Arguments + /// + /// * `contract` - A reference to the `DataContract` to be updated. + /// * `block_info` - A `BlockInfo` object containing information about the block where + /// the contract is being updated. + /// * `apply` - A boolean indicating whether the contract update should be applied (`true`) or not (`false`). Passing `false` would only tell the fees but won't interact with the state. + /// * `transaction` - A `TransactionArg` object representing the transaction to be used + /// for updating the contract. + /// + /// # Returns + /// + /// * `Result` - If successful, returns a `FeeResult` representing the fee + /// for updating the contract. If an error occurs during the contract update or fee calculation, + /// returns an `Error`. + /// + /// # Errors + /// + /// This function returns an error if the contract update or fee calculation fails. + #[inline(always)] + pub(super) fn update_contract_v3( + &self, + contract: &DataContract, + block_info: BlockInfo, + apply: bool, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result { + if !apply { + return self.insert_contract( + contract, + block_info, + false, + transaction, + platform_version, + ); + } + + let mut drive_operations: Vec = vec![]; + + let contract_bytes = serialize_contract_for_storage(contract, platform_version)?; + + // Since we can update the contract by definition it already has storage flags + let storage_flags = Some(StorageFlags::new_single_epoch( + block_info.epoch.index, + Some(contract.owner_id().to_buffer()), + )); + + let contract_element = Element::Item( + contract_bytes, + StorageFlags::map_to_some_element_flags(storage_flags.as_ref()), + ); + + let original_contract_fetch_info = self + .get_contract_with_fetch_info_and_add_to_operations( + contract.id().to_buffer(), + Some(&block_info.epoch), + true, + transaction, + &mut drive_operations, + platform_version, + )? + .ok_or(Error::Drive(DriveError::CorruptedCodeExecution( + "contract should exist", + )))?; + + if original_contract_fetch_info.contract.config().readonly() { + return Err(Error::Drive(DriveError::UpdatingReadOnlyImmutableContract( + "original contract is readonly", + ))); + } + + self.update_contract_element_v3( + contract_element, + contract, + &original_contract_fetch_info.contract, + &block_info, + transaction, + &mut drive_operations, + platform_version, + )?; + + // Update DataContracts cache with the new contract + let updated_contract_fetch_info = self + .fetch_contract_and_add_operations( + contract.id().to_buffer(), + Some(&block_info.epoch), + transaction, + &mut drive_operations, + platform_version, + )? + .ok_or(Error::Drive(DriveError::CorruptedCodeExecution( + "contract should exist", + )))?; + + self.cache + .data_contracts + .insert_rewritten(updated_contract_fetch_info, transaction.is_some()); + + self.calculate_fee( + None, + Some(drive_operations), + &block_info.epoch, + platform_version, + ) + } + + /// Updates a contract. + #[inline(always)] + #[allow(clippy::too_many_arguments)] + pub(super) fn update_contract_element_v3( + &self, + contract_element: Element, + contract: &DataContract, + original_contract: &DataContract, + block_info: &BlockInfo, + transaction: TransactionArg, + drive_operations: &mut Vec, + platform_version: &PlatformVersion, + ) -> Result<(), Error> { + let mut estimated_costs_only_with_layer_info = None::; + let batch_operations = self.update_contract_operations_v3( + contract_element, + contract, + original_contract, + block_info, + &mut estimated_costs_only_with_layer_info, + transaction, + platform_version, + )?; + self.apply_batch_low_level_drive_operations( + estimated_costs_only_with_layer_info, + transaction, + batch_operations, + drive_operations, + &platform_version.drive, + ) + } + + /// Updates a contract. + #[allow(clippy::too_many_arguments)] + #[inline(always)] + pub(super) fn update_contract_add_operations_v3( + &self, + contract_element: Element, + contract: &DataContract, + original_contract: &DataContract, + block_info: &BlockInfo, + estimated_costs_only_with_layer_info: &mut Option, + transaction: TransactionArg, + drive_operations: &mut Vec, + platform_version: &PlatformVersion, + ) -> Result<(), Error> { + let batch_operations = self.update_contract_operations_v3( + contract_element, + contract, + original_contract, + block_info, + estimated_costs_only_with_layer_info, + transaction, + platform_version, + )?; + drive_operations.extend(batch_operations); + Ok(()) + } + + /// Collects generation 2 writes and the history trees of newly added document types. + #[allow(clippy::too_many_arguments)] + fn update_contract_operations_v3( + &self, + contract_element: Element, + contract: &DataContract, + original_contract: &DataContract, + block_info: &BlockInfo, + estimated_costs_only_with_layer_info: &mut Option, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result, Error> { + let flags = contract_element.get_flags().clone(); + let storage_flags = StorageFlags::map_some_element_flags_ref(&flags)?; + let mut operations = vec![]; + self.update_contract_add_operations_v2( + contract_element, + contract, + original_contract, + block_info, + estimated_costs_only_with_layer_info, + transaction, + &mut operations, + platform_version, + )?; + for (name, document_type) in contract.document_types() { + if !original_contract.document_types().contains_key(name) + && document_type.documents_keep_history() + { + self.batch_insert_empty_tree( + contract_document_type_path(contract.id_ref().as_bytes(), name), + KeyRef(&[DOCUMENT_HISTORY_TREE_KEY]), + storage_flags.as_ref(), + &mut operations, + &platform_version.drive, + )?; + } + } + Ok(operations) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::drive::contract::paths::DataContractPaths; + use crate::util::test_helpers::setup::setup_drive_with_initial_state_structure; + use dpp::data_contract::accessors::v0::DataContractV0Setters; + use dpp::data_contract::schema::DataContractSchemaMethodsV0; + use dpp::platform_value::platform_value; + use dpp::tests::fixtures::get_dashpay_contract_fixture; + + #[test] + fn should_cover_applied_keep_history_contract_updates_with_the_fee_estimate() { + let version = PlatformVersion::latest(); + for add_type in [false, true] { + for via_apply_contract in [false, true] { + let drive = setup_drive_with_initial_state_structure(Some(version)); + let mut contract = get_dashpay_contract_fixture(None, 0, version.protocol_version) + .data_contract_owned(); + let schema = |max_length: u64| { + platform_value!({ + "type": "object", + "documentsKeepHistory": true, + "documentsMutable": true, + "canBeDeleted": false, + "properties": { + "message": { "type": "string", "position": 0, "maxLength": max_length } + }, + "additionalProperties": false, + }) + }; + contract + .set_document_schema("historyNote", schema(100), true, &mut vec![], version) + .expect("add existing retained type"); + drive + .apply_contract(&contract, BlockInfo::default(), true, None, None, version) + .expect("insert original"); + let original_bytes = serialize_contract_for_storage(&contract, version).unwrap(); + contract + .set_document_schema("historyNote", schema(101), true, &mut vec![], version) + .expect("extend existing retained type"); + if add_type { + contract + .set_document_schema( + "otherHistoryNote", + schema(100), + true, + &mut vec![], + version, + ) + .expect("add another retained type"); + } + contract.increment_version(); + + let fee_for = |apply, selected_version: &PlatformVersion| { + if via_apply_contract { + drive.apply_contract( + &contract, + BlockInfo::default(), + apply, + None, + None, + selected_version, + ) + } else { + drive.update_contract( + &contract, + BlockInfo::default(), + apply, + None, + selected_version, + ) + } + .expect("calculate update fee") + }; + let estimate = fee_for(false, version); + let stored_bytes = || { + drive + .grove + .get_raw( + (&contract.root_path()).into(), + &[0], + None, + &version.drive.grove_version, + ) + .value + .unwrap() + .into_item_bytes() + .unwrap() + }; + assert_eq!( + stored_bytes(), + original_bytes, + "estimating must leave the original stored" + ); + let applied = fee_for(true, version); + assert!(estimate.total_base_fee() >= applied.total_base_fee(), + "add_type={add_type}, via_apply_contract={via_apply_contract}: estimate {estimate:?}, applied {applied:?}"); + assert!(estimate.storage_fee >= applied.storage_fee, + "add_type={add_type}, via_apply_contract={via_apply_contract}: storage estimate {}, applied {}", estimate.storage_fee, applied.storage_fee); + assert!(estimate.processing_fee >= applied.processing_fee, + "add_type={add_type}, via_apply_contract={via_apply_contract}: processing estimate {}, applied {}", estimate.processing_fee, applied.processing_fee); + assert_eq!( + stored_bytes(), + serialize_contract_for_storage(&contract, version).unwrap(), + "the applied update must be persisted" + ); + } + } + } + + #[test] + fn should_create_history_tree_for_a_new_type_only_from_protocol_15() { + use crate::drive::document::paths::{ + contract_document_type_path_vec, DOCUMENT_HISTORY_TREE_KEY, + }; + + for (protocol, expected) in [(14, false), (15, true)] { + let version = PlatformVersion::get(protocol).expect("protocol version"); + let drive = setup_drive_with_initial_state_structure(Some(version)); + let mut contract = get_dashpay_contract_fixture(None, 0, version.protocol_version) + .data_contract_owned(); + drive + .apply_contract( + &contract, + BlockInfo::default(), + true, + StorageFlags::optional_default_as_cow(), + None, + version, + ) + .expect("insert original contract"); + + contract + .set_document_schema( + "historyNote", + platform_value!({ + "type": "object", + "documentsKeepHistory": true, + "documentsMutable": true, + "canBeDeleted": false, + "properties": { + "message": { + "type": "string", + "position": 0, + "maxLength": 100, + } + }, + "additionalProperties": false, + }), + true, + &mut vec![], + version, + ) + .expect("add keep-history document type"); + contract.increment_version(); + drive + .update_contract(&contract, BlockInfo::default(), true, None, version) + .expect("update contract with keep-history document type"); + + let type_path = + contract_document_type_path_vec(contract.id().as_slice(), "historyNote"); + let history_tree = drive + .grove + .get_raw( + type_path.as_slice().into(), + &[DOCUMENT_HISTORY_TREE_KEY], + None, + &version.drive.grove_version, + ) + .value; + assert_eq!( + history_tree.is_ok(), + expected, + "protocol {protocol}: {history_tree:?}" + ); + } + } +} diff --git a/packages/rs-drive/src/drive/document/cost/mod.rs b/packages/rs-drive/src/drive/document/cost/mod.rs index ef01fcda46a..6c109cf6f9d 100644 --- a/packages/rs-drive/src/drive/document/cost/mod.rs +++ b/packages/rs-drive/src/drive/document/cost/mod.rs @@ -28,6 +28,7 @@ use crate::drive::document::expiration::pricing::{ }; use crate::drive::document::layout::LayoutRole; use crate::drive::document::sdk_value::{map, number, text, texts}; +use crate::drive::document::uses_current_document_history_layout; use crate::error::drive::DriveError; use crate::error::Error; use dpp::data_contract::accessors::v0::DataContractV0Getters; @@ -393,52 +394,51 @@ pub fn document_create_cost( } /// Refuses a platform version whose insert methods are not the ones the -/// estimate mirrors (those of protocol version 14): another version of any -/// of them may write other elements. +/// estimate mirrors: another version of any of them may write other elements. fn check_mirrored_method_versions(platform_version: &PlatformVersion) -> Result<(), Error> { let document = &platform_version.drive.methods.document; for (method, known, received) in [ ( "add_document_for_contract_operations", - 1, + &[1][..], document.insert.add_document_for_contract_operations, ), ( "add_document_to_primary_storage", - 0, + &[0, 1][..], document.insert.add_document_to_primary_storage, ), ( "add_indices_for_top_index_level_for_contract_operations", - 2, + &[2][..], document .insert .add_indices_for_top_index_level_for_contract_operations, ), ( "add_indices_for_index_level_for_contract_operations", - 2, + &[2][..], document .insert .add_indices_for_index_level_for_contract_operations, ), ( "add_reference_for_index_level_for_contract_operations", - 0, + &[0, 1][..], document .insert .add_reference_for_index_level_for_contract_operations, ), ( "add_document_expiration_operations", - 0, + &[0][..], document.expiration.add_document_expiration_operations, ), ] { - if received != known { + if !known.contains(&received) { return Err(Error::Drive(DriveError::UnknownVersionMismatch { method: format!("document_create_cost ({method})"), - known_versions: vec![known], + known_versions: known.to_vec(), received, })); } @@ -680,8 +680,12 @@ fn processing_costs( platform_version: &PlatformVersion, ) -> Result, Error> { let fee_version = &platform_version.fee_version; - // The primary key tree and one tree per first index level. + // The primary key tree, retained-history tree and first index levels. let type_entries = u64::from(!document_type.index_only()) + + u64::from( + document_type.documents_keep_history() + && uses_current_document_history_layout(platform_version)?, + ) + document_type.index_structure().sub_levels().len() as u64; let exact = |credits: Credits| Scenarios { new_values: credits, diff --git a/packages/rs-drive/src/drive/document/cost/tests.rs b/packages/rs-drive/src/drive/document/cost/tests.rs index 057712b413f..39b660990a6 100644 --- a/packages/rs-drive/src/drive/document/cost/tests.rs +++ b/packages/rs-drive/src/drive/document/cost/tests.rs @@ -5,7 +5,7 @@ use crate::drive::document::fixture_contracts::{ leave_out_optional_indexed_values, leave_out_optional_unique_values, leave_out_skip_properties, small_sums, CONTRACTS, }; -use crate::drive::document::make_document_reference; +use crate::drive::document::{make_document_reference, uses_current_document_history_layout}; use crate::drive::{Drive, RootTree}; use crate::util::grove_operations::DirectQueryType; use crate::util::object_size_info::DocumentInfo::DocumentRefInfo; @@ -310,6 +310,46 @@ fn should_price_what_drive_charges() { ); } +#[test] +fn should_include_the_retained_history_root_when_estimating_processing_paths() { + let version = PlatformVersion::latest(); + let contract = contract_with(platform_value!({ "note": { + "type": "object", "documentsKeepHistory": true, "canBeDeleted": false, + "properties": { + "tag": { "type": "string", "maxLength": 20, "position": 0 }, + "code": { "type": "string", "maxLength": 20, "position": 1 }, + "text": { "type": "string", "maxLength": 60, "position": 2 } + }, + "indices": [ + { "name": "byTag", "properties": [{ "tag": "asc" }] }, + { "name": "byCode", "properties": [{ "code": "asc" }] } + ], + "required": ["tag", "code", "text"], "additionalProperties": false + }})); + let note = contract.document_type_for_name("note").unwrap(); + let document = note_document(&contract); + let writes = writes_of(&contract, note, &document); + let assumptions = CostAssumptions::new(version); + let parts = processing_costs( + &contract, + note, + &writes, + &vec![false; writes.len()], + Scenarios::default(), + 0, + &assumptions, + version, + ) + .unwrap(); + let processing = parts.iter().find(|part| part.code == "writes").unwrap(); + // Primary storage, retained history and the two index roots make four + // entries: the additional root crosses a balanced-tree height boundary. + assert_eq!( + processing.credits.new_values, + write_processing(&writes, &[], 4, &assumptions, version) + ); +} + #[test] fn should_estimate_the_processing_of_the_writes_within_a_factor_of_two() { let platform_version = PlatformVersion::latest(); @@ -320,6 +360,11 @@ fn should_estimate_the_processing_of_the_writes_within_a_factor_of_two() { for (name, document_type) in contract.document_types() { let document_type = document_type.as_ref(); let type_entries = u64::from(!document_type.index_only()) + + u64::from( + document_type.documents_keep_history() + && uses_current_document_history_layout(platform_version) + .expect("supported history layout"), + ) + document_type.index_structure().sub_levels().len() as u64; for seed in 0..=100u64 { let mut document = document_type diff --git a/packages/rs-drive/src/drive/document/cost/writes.rs b/packages/rs-drive/src/drive/document/cost/writes.rs index fe28dd66a52..837ee20ef2d 100644 --- a/packages/rs-drive/src/drive/document/cost/writes.rs +++ b/packages/rs-drive/src/drive/document/cost/writes.rs @@ -16,15 +16,19 @@ use crate::drive::document::index_level_tree_types::{ zero_contribution_wrapper, }; use crate::drive::document::layout::{index_ending_at, index_paths, indexes_through, LayoutRole}; +use crate::drive::document::paths::DOCUMENT_HISTORY_TREE_KEY; use crate::drive::document::primary_key_tree_type::DocumentTypePrimaryKeyTreeType; +use crate::drive::document::uses_current_document_history_layout; use crate::drive::document::{ bound_value_fits_referring_property, encode_index_only_entry_payload, index_only_member_key, - index_only_row_commitment, make_document_reference, make_document_reference_with_sum_item, + index_only_row_commitment, make_document_reference, make_document_reference_v1, + make_document_reference_with_sum_item, make_document_reference_with_sum_item_v1, preallocation_bindings_targeting, read_document_sum_contribution, referenced_list_tree_keys_for_referring_property, referenced_tree_key_for_referring_property, }; use crate::error::drive::DriveError; use crate::error::Error; +use crate::util::common::encode::encode_u64; use crate::util::storage_flags::StorageFlags; use crate::util::type_constants::DEFAULT_HASH_SIZE_U16; use dpp::data_contract::accessors::v0::DataContractV0Getters; @@ -39,7 +43,9 @@ use dpp::data_contract::DataContract; use dpp::document::document_methods::DocumentMethodsV0; use dpp::document::{Document, DocumentV0Getters}; use dpp::version::PlatformVersion; -use grovedb::element::reference_path::ReferencePathType::SiblingReference; +use grovedb::element::reference_path::ReferencePathType::{ + SiblingReference, UpstreamRootHeightReference, +}; use grovedb::element::IndexAxis; use grovedb::Element; use grovedb_merk::tree_type::TreeType; @@ -461,6 +467,78 @@ impl Context<'_> { return Ok(()); } + if uses_current_document_history_layout(self.platform_version)? { + self.push(Write { + path: vec![vec![DOCUMENT_HISTORY_TREE_KEY]], + key: id.clone(), + element: empty_tree(TreeType::ProvableCountTree, false, document_flags.as_ref()), + parent: TreeType::NormalTree, + role: LayoutRole::DocumentHistory, + indexes: vec![], + if_absent: true, + ephemeral: false, + ranking: None, + referring_type: None, + expiration: false, + flagged: document_flags.is_some(), + }); + let mut revision_key = encode_u64(0); + revision_key.extend(encode_u64(self.document.revision().unwrap_or(1))); + self.push(Write { + path: vec![vec![DOCUMENT_HISTORY_TREE_KEY], id.clone()], + key: revision_key.clone(), + element: PricedElement::Serialized { + serialized_len: serialized_len( + &Element::Item( + serialized, + StorageFlags::map_to_some_element_flags(document_flags.as_ref()), + ), + self.platform_version, + )?, + }, + parent: TreeType::ProvableCountTree, + role: LayoutRole::RetainedRevision, + indexes: vec![], + if_absent: false, + ephemeral: false, + ranking: None, + referring_type: None, + expiration: false, + flagged: document_flags.is_some(), + }); + let reference = UpstreamRootHeightReference( + 4, + vec![vec![DOCUMENT_HISTORY_TREE_KEY], id.clone(), revision_key], + ); + let flags = StorageFlags::map_to_some_element_flags(document_flags.as_ref()); + let pointer = match sum_property { + Some(property) => Element::new_reference_with_sum_item_with_max_hops_and_flags( + reference, + Some(1), + read_document_sum_contribution(self.document, property)?, + flags, + ), + None => Element::Reference(reference, Some(1), flags), + }; + self.push(Write { + path: vec![vec![0]], + key: id, + element: PricedElement::Serialized { + serialized_len: serialized_len(&pointer, self.platform_version)?, + }, + parent: primary_key_tree_type, + role: LayoutRole::Document, + indexes: vec![], + if_absent: false, + ephemeral: false, + ranking: None, + referring_type: None, + expiration: false, + flagged: document_flags.is_some(), + }); + return Ok(()); + } + // With history: a tree per document holding each revision by time // and a pointer to the newest. The tree and the pointer carry flags // only when the contract can be deleted. @@ -1193,15 +1271,41 @@ impl Context<'_> { } else { self.document_flags.clone() }; - let reference = match info.summable.as_deref() { - Some(property) => make_document_reference_with_sum_item( - self.document, - self.document_type, - read_document_sum_contribution(self.document, property)?, - reference_flags.as_ref(), - ), - None => { - make_document_reference(self.document, self.document_type, reference_flags.as_ref()) + let reference = if self + .platform_version + .drive + .methods + .document + .insert + .add_reference_for_index_level_for_contract_operations + == 1 + { + match info.summable.as_deref() { + Some(property) => make_document_reference_with_sum_item_v1( + self.document, + self.document_type, + read_document_sum_contribution(self.document, property)?, + reference_flags.as_ref(), + ), + None => make_document_reference_v1( + self.document, + self.document_type, + reference_flags.as_ref(), + ), + } + } else { + match info.summable.as_deref() { + Some(property) => make_document_reference_with_sum_item( + self.document, + self.document_type, + read_document_sum_contribution(self.document, property)?, + reference_flags.as_ref(), + ), + None => make_document_reference( + self.document, + self.document_type, + reference_flags.as_ref(), + ), } }; let reference = PricedElement::Serialized { diff --git a/packages/rs-drive/src/drive/document/delete/remove_reference_for_index_level_for_contract_operations/mod.rs b/packages/rs-drive/src/drive/document/delete/remove_reference_for_index_level_for_contract_operations/mod.rs index 58eeba9bda5..98d60a30fe2 100644 --- a/packages/rs-drive/src/drive/document/delete/remove_reference_for_index_level_for_contract_operations/mod.rs +++ b/packages/rs-drive/src/drive/document/delete/remove_reference_for_index_level_for_contract_operations/mod.rs @@ -93,7 +93,7 @@ impl Drive { platform_version, ), // v2 (protocol version 15): an estimate describes the index's entries for a value - // as the references they are. + // as the references they are, including primary-pointer and summable shapes. 2 => self.remove_reference_for_index_level_for_contract_operations_v2( document_and_contract_info, index_path_info, @@ -120,6 +120,7 @@ impl Drive { #[cfg(test)] mod tests { + use crate::drive::document::document_reference_size; use crate::drive::document::paths::contract_document_type_path_vec; use crate::util::estimated_layers::EstimatedLayers; use crate::util::object_size_info::DocumentInfo::DocumentRefInfo; @@ -246,6 +247,13 @@ mod tests { .get(&KeyInfoPath::from_known_owned_path(path)) .copied() .expect("expected the entries layer to be described"); + if as_references { + assert_eq!( + entries.estimated_layer_sizes, + AllReference(32, document_reference_size(document_type), None), + "non-history PV15 describes entries as 42-byte document references" + ); + } assert_eq!( matches!(entries.estimated_layer_sizes, AllReference(..)), as_references, @@ -254,4 +262,168 @@ mod tests { ); } } + #[test] + fn should_cover_history_index_updates_with_consistent_reference_estimates() { + use crate::drive::document::document_reference_estimated_layer_sizes_v1; + use dpp::block::block_info::BlockInfo; + use dpp::data_contract::DataContractFactory; + use dpp::document::document_factory::DocumentFactory; + use dpp::document::DocumentV0Setters; + use dpp::platform_value::{platform_value, Value}; + let version = PlatformVersion::latest(); + for unique in [false, true] { + for null in [false, true] { + for summable in [false, true] { + let drive = setup_drive_with_initial_state_structure(Some(version)); + let mut index = platform_value!({"name": "byTag", "properties": [{"tag": "asc"}], "unique": unique}); + if summable { + index.insert("summable".into(), "amount".into()).unwrap(); + } + let schema = platform_value!({ + "type": "object", "documentsKeepHistory": true, "documentsMutable": true, "canBeDeleted": false, + "indices": [index], + "properties": { + "tag": {"type": "string", "maxLength": 20, "position": 0}, + "amount": {"type": "integer", "minimum": 0, "maximum": 4294967295i64, "position": 1} + }, + "required": ["amount"], "additionalProperties": false + }); + let contract = DataContractFactory::new(15) + .unwrap() + .create_with_value_config( + [7; 32].into(), + 0, + platform_value!({"note": schema}), + None, + None, + ) + .unwrap() + .data_contract_owned(); + drive + .apply_contract(&contract, BlockInfo::default(), true, None, None, version) + .unwrap(); + let document_type = contract.document_type_for_name("note").unwrap(); + let mut properties = platform_value!({"amount": 5}); + if !null { + properties.insert("tag".into(), "a".into()).unwrap(); + } + let mut document = DocumentFactory::new(15) + .unwrap() + .create_document(&contract, [7; 32].into(), "note".into(), properties) + .unwrap(); + let info = DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentRefInfo((&document, None)), + owner_id: None, + }, + contract: &contract, + document_type, + }; + let mut layers = Some(EstimatedLayers::new()); + drive + .add_document_for_contract_operations( + info.clone(), + false, + &BlockInfo::default_with_time(2000), + &mut None, + &mut layers, + None, + version, + ) + .unwrap(); + let level = document_type + .index_structure() + .sub_levels() + .get("tag") + .unwrap(); + let index_type = level.has_index_with_type().unwrap(); + let mut path = + contract_document_type_path_vec(contract.id_ref().as_bytes(), "note"); + path.push(b"tag".to_vec()); + path.push( + document + .get_raw_for_document_type("tag", document_type, None, version) + .unwrap() + .unwrap_or_default(), + ); + drive + .remove_reference_for_index_level_for_contract_operations( + &info, + PathInfo::PathAsVec(path.clone()), + index_type, + null, + null, + &None, + &None, + &mut layers, + false, + [0; 32], + None, + &mut vec![], + version, + ) + .unwrap(); + let resolved = layers.unwrap().resolve(version).unwrap(); + if !unique || null { + path.push(vec![0]); + assert_eq!( + resolved + .get(&KeyInfoPath::from_known_owned_path(path)) + .unwrap() + .estimated_layer_sizes, + document_reference_estimated_layer_sizes_v1(32, None, summable), + "unique={unique}, null={null}, summable={summable}" + ); + } + drive + .add_document_for_contract( + info, + false, + BlockInfo::default_with_time(2000), + true, + None, + version, + ) + .unwrap(); + document.set_revision(Some(2)); + document.set("tag", Value::Text("b".into())); + let block = BlockInfo::default_with_time(3000); + let estimate = drive + .update_document_for_contract( + &document, + &contract, + document_type, + None, + block, + false, + None, + None, + version, + ) + .unwrap(); + let applied = drive + .update_document_for_contract( + &document, + &contract, + document_type, + None, + block, + true, + None, + None, + version, + ) + .unwrap(); + assert!( + estimate.storage_fee >= applied.storage_fee, + "{estimate:?} < {applied:?}" + ); + assert!( + estimate.processing_fee >= applied.processing_fee, + "{estimate:?} < {applied:?}" + ); + } + } + } + } } diff --git a/packages/rs-drive/src/drive/document/delete/remove_reference_for_index_level_for_contract_operations/v2/mod.rs b/packages/rs-drive/src/drive/document/delete/remove_reference_for_index_level_for_contract_operations/v2/mod.rs index 2034c09f184..4d1da3105c0 100644 --- a/packages/rs-drive/src/drive/document/delete/remove_reference_for_index_level_for_contract_operations/v2/mod.rs +++ b/packages/rs-drive/src/drive/document/delete/remove_reference_for_index_level_for_contract_operations/v2/mod.rs @@ -1,26 +1,34 @@ -use crate::drive::document::document_reference_size; +use crate::util::estimated_layers::EstimatedLayers; +use grovedb::batch::key_info::KeyInfo::KnownKey; + +use grovedb::EstimatedLayerCount::PotentiallyAtMaxElements; +use grovedb::EstimatedLayerSizes::AllItems; +use grovedb::{EstimatedLayerInformation, MaybeTree, TransactionArg}; + +use dpp::data_contract::document_type::IndexLevelTypeInfo; +use dpp::data_contract::document_type::IndexType::{ContestedResourceIndex, NonUniqueIndex}; + +use crate::drive::constants::CONTRACT_DOCUMENTS_PATH_HEIGHT; +use crate::drive::document::document_reference_estimated_layer_sizes_v1; +use crate::drive::document::index_level_tree_types::terminal_member_tree_type; +use crate::drive::document::index_only::{index_only_member_key, index_only_terminal_max_key_size}; +use crate::drive::document::{index_only_entry_payload_max_size, INDEX_ONLY_ROW_COMMITMENT_SIZE}; +use crate::error::drive::DriveError; +use crate::util::storage_flags::StorageFlags; + use crate::drive::Drive; +use crate::util::object_size_info::{DocumentAndContractInfo, DocumentInfoV0Methods, PathInfo}; + use crate::error::Error; use crate::fees::op::LowLevelDriveOperation; -use crate::util::estimated_layers::EstimatedLayers; -use crate::util::object_size_info::{DocumentAndContractInfo, PathInfo}; -use crate::util::storage_flags::StorageFlags; -use crate::util::type_constants::DEFAULT_HASH_SIZE_U8; -use dpp::data_contract::document_type::IndexLevelTypeInfo; +use crate::util::type_constants::DEFAULT_HASH_SIZE_U8; use dpp::version::PlatformVersion; -use grovedb::EstimatedLayerSizes::AllReference; -use grovedb::TransactionArg; impl Drive { - /// Removes the terminal reference. - /// - /// v2 (protocol version 15) is v1, describing the `[0]` layer of a non-unique, contested or - /// null-field index for an estimate as the references it holds, keyed by document id, as the - /// insert walker does (`add_reference_for_index_level_for_contract_operations`). v1 describes - /// it as subtrees, so a batch that inserts a document under an index value and deletes - /// another under the same one (a create consuming a document of its own type) described - /// the layer two ways, and its estimate kept the cheaper subtree description. + /// Removes an index reference with the same pruning as v1. Estimates describe the + /// entries layer and each deleted reference as the insert walker writes them, + /// including primary-pointer and summable reference shapes. #[inline(always)] #[allow(clippy::too_many_arguments)] pub(super) fn remove_reference_for_index_level_for_contract_operations_v2( @@ -39,27 +47,276 @@ impl Drive { batch_operations: &mut Vec, platform_version: &PlatformVersion, ) -> Result<(), Error> { - self.remove_reference_for_index_level_describing_entries_as( - document_and_contract_info, - index_path_info, - index_type, - any_fields_null, - all_fields_null, - storage_flags, - previous_batch_operations, - estimated_costs_only_with_layer_info, - skip_missing_expired_entry, - event_id, - transaction, - batch_operations, - |document_type, flags_size| { - AllReference( + if all_fields_null && !index_type.should_insert_with_all_null { + return Ok(()); + } + let mut key_info_path = index_path_info.convert_to_key_info_path(); + + // TTL: for an entry in an expired-but-standing bucket, drainage may + // already have removed the deeper trees (the group's `[0]` and value + // tree go before the bucket does). The entry path is checked at + // full granularity and the whole reference removal skipped when it + // is gone — the drain took it, and there is nothing left to + // remove. Only set on the stateful path, so every KeyInfo below is + // a KnownKey. + if skip_missing_expired_entry { + let mut path_segments: Vec> = key_info_path + .0 + .iter() + .map(|key_info| match key_info { + KnownKey(key) => Ok(key.clone()), + _ => Err(Error::Drive(DriveError::CorruptedCodeExecution( + "expired-entry skip is stateful-only; its path must be known", + ))), + }) + .collect::>()?; + // The layouts that store the reference inside a `[0]` subtree + // must include that segment in the walk: the drain drops the + // flat `[0]` tree BEFORE its value tree, and a budget boundary + // between the two leaves the value tree standing with the + // `[0]` gone — every shallower segment then exists while the + // delete below would target the missing subtree. Mirrors the + // layout dispatch used for the actual delete: the indexOnly + // terminal and the non-unique / contested / null layouts use + // `[0]` trees; the unique layout stores the reference AT key + // `[0]` as a bare element of the value tree. + let uses_zero_subtree = index_type.terminal.is_some() + || index_type.index_type == NonUniqueIndex + || index_type.index_type == ContestedResourceIndex + || any_fields_null; + if uses_zero_subtree { + path_segments.push(vec![0]); + } + // The document-type path plus the (grid-qualified) index level + // key exist for every registered contract: the flag is only + // ever set for a bucketed index, whose level tree is created at + // contract registration — so the walk starts below them. + if !self.expired_entry_path_exists( + &path_segments, + usize::from(CONTRACT_DOCUMENTS_PATH_HEIGHT) + 1, + transaction, + platform_version, + )? { + return Ok(()); + } + } + + let document_type = document_and_contract_info.document_type; + + // indexOnly terminal: the member key is the terminal property's + // value and the stored element is a commitment `Item` (an + // `ItemWithSumItem` under a summable index) — mirror of the + // insert-side branch in + // `add_reference_for_index_level_for_contract_operations_v0`. + // `terminal` can only be `Some` on a PV14+ indexOnly contract, so + // this branch is unreachable for every historical document. + if let Some(terminal) = index_type.terminal.as_deref() { + key_info_path.push(KnownKey(vec![0])); + + let member_tree_type = terminal_member_tree_type(index_type); + // The member key's estimated width follows the terminal property, + // mirroring the insert side. + let member_key_max_size = + index_only_terminal_max_key_size(document_type, terminal, platform_version)?; + // The stored item: the commitment plus the type's entry payload. + let entry_value_size = INDEX_ONLY_ROW_COMMITMENT_SIZE + + index_only_entry_payload_max_size(document_type, platform_version)?; + + // Sum-bearing entries (`ItemWithSumItem`) carry the i64 sum + // item alongside the commitment payload; mirror the insert + // side's 10-byte worst case. Delete-side sum-decrement is + // implicit: grovedb reads the amount off the stored element + // and propagates the subtraction — same as stored-type + // `ReferenceWithSumItem` entries below. + let estimated_value_size = if index_type.summable.is_some() { + entry_value_size + 10 + } else { + entry_value_size + }; + + if let Some(estimated_costs_only_with_layer_info) = estimated_costs_only_with_layer_info + { + estimated_costs_only_with_layer_info.insert( + key_info_path.clone(), + EstimatedLayerInformation { + tree_type: member_tree_type, + estimated_layer_count: PotentiallyAtMaxElements, + estimated_layer_sizes: AllItems( + member_key_max_size, + estimated_value_size, + storage_flags.map(|s| s.serialized_size()), + ), + }, + ); + } + + // The member key: the terminal property's value off the + // (synthesized) document; estimation-only calls fall back to + // the event id, same as the docId fallback below. + let member_key: Vec = match document_and_contract_info + .owned_document_info + .document_info + .get_borrowed_document_and_storage_flags() + { + Some((document, _)) => index_only_member_key( + document, + document_type, + terminal, + document_and_contract_info.owned_document_info.owner_id, + platform_version, + )?, + None => event_id.to_vec(), + }; + + let delete_apply_type = Self::stateless_delete_of_non_tree_for_costs( + AllItems( + member_key_max_size, + estimated_value_size, + storage_flags.map(|s| s.serialized_size()), + ), + &key_info_path, + // we know we are not deleting a tree + Some(MaybeTree::NotTree), + estimated_costs_only_with_layer_info, + platform_version, + )?; + + // Drained groups prune upward exactly as with references, so + // ranked secondaries drop the group when its last member goes — + // EXCEPT on a preallocated index, whose trees are permanent + // structure the referenced document's creator paid for at its + // insert (see `add_preallocated_index_tree_operations`): there + // the member entry is the whole delete, and stopping the climb + // one level above it (at the emptied `0` bucket's own path) + // keeps every tree, so a later entry costs the same as this one + // did. Trees a pre-flag fallback created are kept the same way + // — if-not-exists inserts make the two histories converge. + // A FLAT index's entries sit at `[…doctype, , 0]`: + // the flat level tree is registration-time structure (like a + // property-name tree), so the climb stops at its `0` bucket + // exactly as it does on a preallocated index. The level info + // carries the flag from the index that terminates there. + let stop_path_height = if index_type.preallocated || index_type.flat { + u16::try_from(key_info_path.len() - 1).map_err(|_| { + Error::Drive(DriveError::CorruptedCodeExecution( + "index path height must fit in u16", + )) + })? + } else { + CONTRACT_DOCUMENTS_PATH_HEIGHT + }; + self.batch_delete_up_tree_while_empty( + key_info_path, + member_key.as_slice(), + Some(stop_path_height), + delete_apply_type, + transaction, + previous_batch_operations, + batch_operations, + &platform_version.drive, + )?; + + return Ok(()); + } + + // unique indexes will be stored under key "0" + // non unique indices should have a tree at key "0" that has all elements based off of primary key + if index_type.index_type == NonUniqueIndex + || index_type.index_type == ContestedResourceIndex + || any_fields_null + { + key_info_path.push(KnownKey(vec![0])); + + // Mirror the insert path: tree variant is driven by the + // composition of the index's countability AND summability — + // `terminal_member_tree_type` is the shared dispatch (eight + // cases over the v3 sum-tree-expanded TreeType set), used + // by both sides so the delete's estimation layers cannot + // drift from the trees the insert actually created. + let reference_tree_type = terminal_member_tree_type(index_type); + + // Delete-side sum-decrement is implicit: under a summable + // index, the existing reference at `[..., 0, doc_id]` is an + // `Element::ItemWithSumItem(doc_id, amount_i64, flags)` + // (written by the insert path). The contribution is + // recovered from the reference element itself — Drive + // never re-reads the source document at delete time + // (the field's value may have drifted or the document + // may not be deserializable anymore). grovedb's normal + // delete propagation subtracts that `i64` from every + // ancestor sum tree, so no sum-specific delete logic is + // needed here. + + if let Some(estimated_costs_only_with_layer_info) = estimated_costs_only_with_layer_info + { + // The `[0]` layer: the index's entries for this value + estimated_costs_only_with_layer_info.insert( + key_info_path.clone(), + EstimatedLayerInformation { + tree_type: reference_tree_type, + estimated_layer_count: PotentiallyAtMaxElements, + estimated_layer_sizes: document_reference_estimated_layer_sizes_v1( + DEFAULT_HASH_SIZE_U8, + storage_flags.map(|s| s.serialized_size()), + index_type.summable.is_some(), + ), + }, + ); + } + + let delete_apply_type = Self::stateless_delete_of_non_tree_for_costs( + document_reference_estimated_layer_sizes_v1( DEFAULT_HASH_SIZE_U8, - document_reference_size(document_type), - flags_size, - ) - }, - platform_version, - ) + storage_flags.map(|s| s.serialized_size()), + index_type.summable.is_some(), + ), + &key_info_path, + // we know we are not deleting a tree + Some(MaybeTree::NotTree), + estimated_costs_only_with_layer_info, + platform_version, + )?; + + // here we should return an error if the element already exists + self.batch_delete_up_tree_while_empty( + key_info_path, + document_and_contract_info + .owned_document_info + .document_info + .get_document_id_as_slice() + .unwrap_or(event_id.as_slice()), + Some(CONTRACT_DOCUMENTS_PATH_HEIGHT), + delete_apply_type, + transaction, + previous_batch_operations, + batch_operations, + &platform_version.drive, + )?; + } else { + let delete_apply_type = Self::stateless_delete_of_non_tree_for_costs( + document_reference_estimated_layer_sizes_v1( + 1, + storage_flags.map(|s| s.serialized_size()), + index_type.summable.is_some(), + ), + &key_info_path, + // we know we are not deleting a tree + Some(MaybeTree::NotTree), + estimated_costs_only_with_layer_info, + platform_version, + )?; + // here we should return an error if the element already exists + self.batch_delete_up_tree_while_empty( + key_info_path, + &[0], + Some(CONTRACT_DOCUMENTS_PATH_HEIGHT), + delete_apply_type, + transaction, + previous_batch_operations, + batch_operations, + &platform_version.drive, + )?; + } + Ok(()) } } diff --git a/packages/rs-drive/src/drive/document/derived_index_values.rs b/packages/rs-drive/src/drive/document/derived_index_values.rs index 591ff50e5df..c9a823228ff 100644 --- a/packages/rs-drive/src/drive/document/derived_index_values.rs +++ b/packages/rs-drive/src/drive/document/derived_index_values.rs @@ -16,6 +16,7 @@ //! type lists under `moderatorAbilities.deleteKeepsFields` (`moderatedDocument`, `$ownerId` or //! a kept field only). So a later read finds the value the entry was written under. +use crate::drive::constants::DOCUMENT_HISTORY_CURRENT_REFERENCE_PATH_SIZE; use crate::drive::contract::moderation::types::{ estimated_document_removal_kept_fields_size, estimated_document_removal_value_size, }; @@ -26,6 +27,7 @@ use crate::drive::document::paths::{ contract_documents_primary_key_path, }; use crate::drive::document::primary_key_tree_type::DocumentTypePrimaryKeyTreeType; +use crate::drive::document::uses_current_document_history_layout; use crate::drive::Drive; use crate::error::drive::DriveError; use crate::error::Error; @@ -307,7 +309,8 @@ impl Drive { )?; return Ok(ReferencedValues::Estimate); } - let element = if referenced_type.documents_keep_history() { + let current_history_layout = uses_current_document_history_layout(platform_version)?; + let element = if referenced_type.documents_keep_history() && !current_history_layout { // The `0` of a document keeping history is a reference to its current version let path = contract_documents_keeping_history_primary_key_path_for_document_id( contract.id_ref().as_bytes(), @@ -327,14 +330,25 @@ impl Drive { contract.id_ref().as_bytes(), referenced_type_name, ); - self.grove_get_raw_optional( - (&path).into(), - referenced_id.as_slice(), - DirectQueryType::StatefulDirectQuery, - transaction, - drive_operations, - &platform_version.drive, - )? + if referenced_type.documents_keep_history() { + self.grove_get( + (&path).into(), + referenced_id.as_slice(), + QueryType::StatefulQuery, + transaction, + drive_operations, + &platform_version.drive, + )? + } else { + self.grove_get_raw_optional( + (&path).into(), + referenced_id.as_slice(), + DirectQueryType::StatefulDirectQuery, + transaction, + drive_operations, + &platform_version.drive, + )? + } }; match element { Some(Element::Item(bytes, _)) | Some(Element::ItemWithSumItem(bytes, _, _)) => { @@ -413,7 +427,8 @@ impl Drive { platform_version: &PlatformVersion, ) -> Result<(), Error> { let document_size = referenced_type.estimated_size(platform_version)? as u32; - if referenced_type.documents_keep_history() { + let current_history_layout = uses_current_document_history_layout(platform_version)?; + if referenced_type.documents_keep_history() && !current_history_layout { let path = contract_documents_keeping_history_primary_key_path_for_document_id( contract.id_ref().as_bytes(), referenced_type.name(), @@ -442,17 +457,45 @@ impl Drive { contract.id_ref().as_bytes(), referenced_type.name(), ); - self.grove_get_raw_optional( - (&path).into(), - &[0; 32], - DirectQueryType::StatelessDirectQuery { - in_tree_type: referenced_type.primary_key_tree_type(platform_version)?, - query_target: QueryTargetValue(document_size), - }, - None, - drive_operations, - &platform_version.drive, - )?; + if referenced_type.documents_keep_history() { + let pointer_size = if referenced_type.documents_summable().is_some() { + Element::required_reference_with_sum_item_space( + DOCUMENT_HISTORY_CURRENT_REFERENCE_PATH_SIZE, + 0, + &platform_version.drive.grove_version, + )? + } else { + Element::required_item_space( + DOCUMENT_HISTORY_CURRENT_REFERENCE_PATH_SIZE, + 0, + &platform_version.drive.grove_version, + )? + }; + self.grove_get( + (&path).into(), + &[0; 32], + QueryType::StatelessQuery { + in_tree_type: referenced_type.primary_key_tree_type(platform_version)?, + query_target: QueryTargetValue(pointer_size), + estimated_reference_sizes: vec![document_size], + }, + None, + drive_operations, + &platform_version.drive, + )?; + } else { + self.grove_get_raw_optional( + (&path).into(), + &[0; 32], + DirectQueryType::StatelessDirectQuery { + in_tree_type: referenced_type.primary_key_tree_type(platform_version)?, + query_target: QueryTargetValue(document_size), + }, + None, + drive_operations, + &platform_version.drive, + )?; + } } if kind == DocumentReferenceKind::Moderated { let path = contract_document_type_removals_path( @@ -562,6 +605,7 @@ pub(crate) fn set_derived_index_values(document: &mut Document, values: BTreeMap #[cfg(test)] mod tests { + use super::*; use crate::config::DriveConfig; use crate::drive::document::query::QueryDocumentsOutcomeV0Methods; use crate::drive::Drive; @@ -579,6 +623,76 @@ mod tests { use dpp::version::PlatformVersion; use std::collections::BTreeMap; + #[test] + fn should_price_current_history_pointer_reads_with_the_writers_element_size() { + use grovedb::batch::key_info::KeyInfo; + use grovedb::batch::KeyInfoPath; + use grovedb::GroveDb; + + let version = PlatformVersion::latest(); + for summable in [true, false] { + let mut extra = platform_value!({ + "documentsKeepHistory":true, + "documentsSummable":"amount", + "properties":{ + "topic":{"type":"string", "maxLength":20, "position":0}, + "amount":{"type":"integer", "minimum":0, "maximum":100, "position":1} + }, + "required":["topic","amount"] + }); + if !summable { + extra.remove("documentsSummable").unwrap(); + } + let contract = contract_with( + extra, + platform_value!([{ "postId.topic": "asc" }]), + Value::Null, + ); + let drive = setup(&contract); + let post = contract.document_type_for_name("post").unwrap(); + let mut operations = vec![]; + drive + .add_referenced_document_read_estimation( + &contract, + post, + DocumentReferenceKind::Permanent, + &mut operations, + version, + ) + .unwrap(); + let pointer_size = if summable { + Element::required_reference_with_sum_item_space( + DOCUMENT_HISTORY_CURRENT_REFERENCE_PATH_SIZE, + 0, + &version.drive.grove_version, + ) + .unwrap() + } else { + Element::required_item_space( + DOCUMENT_HISTORY_CURRENT_REFERENCE_PATH_SIZE, + 0, + &version.drive.grove_version, + ) + .unwrap() + }; + let path = contract_documents_primary_key_path(contract.id_ref().as_bytes(), "post"); + let expected = GroveDb::average_case_for_get( + &KeyInfoPath::from_known_owned_path(path.map(|part| part.to_vec()).to_vec()), + &KeyInfo::KnownKey(vec![0; 32]), + post.primary_key_tree_type(version).unwrap(), + pointer_size, + vec![post.estimated_size(version).unwrap() as u32], + &version.drive.grove_version, + ) + .unwrap(); + let [LowLevelDriveOperation::CalculatedCostOperation(actual)] = operations.as_slice() + else { + panic!("one current-pointer read is priced"); + }; + assert_eq!(actual, &expected, "summable={summable}"); + } + } + const OWNER: [u8; 32] = [7; 32]; const CREATOR: [u8; 32] = [8; 32]; const POST: [u8; 32] = [1; 32]; diff --git a/packages/rs-drive/src/drive/document/estimation_costs/add_estimation_costs_for_add_document_to_primary_storage/mod.rs b/packages/rs-drive/src/drive/document/estimation_costs/add_estimation_costs_for_add_document_to_primary_storage/mod.rs index db7b5969e92..677895dbb18 100644 --- a/packages/rs-drive/src/drive/document/estimation_costs/add_estimation_costs_for_add_document_to_primary_storage/mod.rs +++ b/packages/rs-drive/src/drive/document/estimation_costs/add_estimation_costs_for_add_document_to_primary_storage/mod.rs @@ -6,6 +6,7 @@ use crate::util::object_size_info::DocumentAndContractInfo; use dpp::version::PlatformVersion; mod v0; +mod v1; impl Drive { /// Adds estimated storage costs for adding a document to primary storage based on platform version. @@ -52,10 +53,16 @@ impl Drive { estimated_costs_only_with_layer_info, platform_version, ), + 1 => Self::add_estimation_costs_for_add_document_to_primary_storage_v1( + document_and_contract_info, + primary_key_path, + estimated_costs_only_with_layer_info, + platform_version, + ), version => Err(Error::Drive(DriveError::UnknownVersionMismatch { method: "Drive::add_estimation_costs_for_add_document_to_primary_storage" .to_string(), - known_versions: vec![0], + known_versions: vec![0, 1], received: version, })), } diff --git a/packages/rs-drive/src/drive/document/estimation_costs/add_estimation_costs_for_add_document_to_primary_storage/v1/mod.rs b/packages/rs-drive/src/drive/document/estimation_costs/add_estimation_costs_for_add_document_to_primary_storage/v1/mod.rs new file mode 100644 index 00000000000..43caa8cb4d2 --- /dev/null +++ b/packages/rs-drive/src/drive/document/estimation_costs/add_estimation_costs_for_add_document_to_primary_storage/v1/mod.rs @@ -0,0 +1,110 @@ +//! Cost estimation for the protocol 15 keep-history layout. +//! +//! What changed from v0: a keep-history document no longer occupies a subtree +//! of the primary key tree with one item per revision. The primary key tree +//! holds a fixed-size reference to the current revision, and the revisions +//! live under the document type's history tree, one provable count tree per +//! document keyed by block time and revision. The estimate therefore charges +//! the primary key tree as references (or references with a sum item for a +//! summable type) instead of subtrees, and adds the history tree, its +//! provable count trees and the revision item to the layers. Types that do +//! not keep history are estimated exactly as in v0. + +use crate::drive::constants::DOCUMENT_HISTORY_CURRENT_REFERENCE_PATH_SIZE; +use crate::drive::document::paths::DOCUMENT_HISTORY_TREE_KEY; +use crate::drive::document::primary_key_tree_type::DocumentTypePrimaryKeyTreeType; +use crate::drive::Drive; +use crate::error::Error; +use crate::util::estimated_layers::EstimatedLayers; +use crate::util::object_size_info::{DocumentAndContractInfo, DocumentInfoV0Methods}; +use crate::util::storage_flags::StorageFlags; +use dpp::data_contract::document_type::accessors::{DocumentTypeV0Getters, DocumentTypeV2Getters}; +use dpp::data_contract::document_type::methods::{DocumentTypeBasicMethods, DocumentTypeV0Methods}; +use dpp::document::DocumentV0Getters; +use dpp::version::PlatformVersion; +use grovedb::batch::{key_info::KeyInfo, KeyInfoPath}; +use grovedb::EstimatedLayerCount::{ApproximateElements, PotentiallyAtMaxElements}; +use grovedb::EstimatedLayerSizes::{AllItems, AllReference, AllSubtrees, Mix}; +use grovedb::EstimatedSumTrees::AllProvableCountTrees; +use grovedb::{EstimatedLayerInformation, TreeType}; + +impl Drive { + pub(super) fn add_estimation_costs_for_add_document_to_primary_storage_v1( + info: &DocumentAndContractInfo, + primary_path: [&[u8]; 5], + layers: &mut EstimatedLayers, + platform_version: &PlatformVersion, + ) -> Result<(), Error> { + if !info.document_type.documents_keep_history() { + return Self::add_estimation_costs_for_add_document_to_primary_storage_v0( + info, + primary_path, + layers, + platform_version, + ); + } + let flags_size = Some(StorageFlags::approximate_size(true, None)); + let references = if info.document_type.documents_summable().is_some() { + Mix { + subtrees_size: None, + items_size: None, + references_size: None, + items_with_sum_item_size: None, + references_with_sum_item_size: Some(( + 32, + DOCUMENT_HISTORY_CURRENT_REFERENCE_PATH_SIZE, + flags_size, + 1, + )), + } + } else { + AllReference(32, DOCUMENT_HISTORY_CURRENT_REFERENCE_PATH_SIZE, flags_size) + }; + layers.insert( + KeyInfoPath::from_known_path(primary_path), + EstimatedLayerInformation { + tree_type: info.document_type.primary_key_tree_type(platform_version)?, + estimated_layer_count: PotentiallyAtMaxElements, + estimated_layer_sizes: references, + }, + ); + let mut root = primary_path.map(|part| part.to_vec()).to_vec(); + root[4] = vec![DOCUMENT_HISTORY_TREE_KEY]; + layers.insert( + KeyInfoPath::from_known_path(root.iter().map(Vec::as_slice)), + EstimatedLayerInformation { + tree_type: TreeType::NormalTree, + estimated_layer_count: PotentiallyAtMaxElements, + estimated_layer_sizes: AllSubtrees(32, AllProvableCountTrees, flags_size), + }, + ); + let mut path = KeyInfoPath::from_known_path(root.iter().map(Vec::as_slice)); + path.push( + info.owned_document_info + .document_info + .get_borrowed_document() + .map_or_else( + || KeyInfo::MaxKeySize { + unique_id: info.document_type.unique_id_for_storage().to_vec(), + max_size: 32, + }, + |document| KeyInfo::KnownKey(document.id().to_vec()), + ), + ); + layers.insert( + path, + EstimatedLayerInformation { + tree_type: TreeType::ProvableCountTree, + estimated_layer_count: ApproximateElements( + crate::drive::constants::AVERAGE_NUMBER_OF_UPDATES as u32, + ), + estimated_layer_sizes: AllItems( + 16, + info.document_type.estimated_size(platform_version)? as u32, + flags_size, + ), + }, + ); + Ok(()) + } +} diff --git a/packages/rs-drive/src/drive/document/get_fetch/fetch_document_history/mod.rs b/packages/rs-drive/src/drive/document/get_fetch/fetch_document_history/mod.rs index e9601dfbdfa..2a4ad97a515 100644 --- a/packages/rs-drive/src/drive/document/get_fetch/fetch_document_history/mod.rs +++ b/packages/rs-drive/src/drive/document/get_fetch/fetch_document_history/mod.rs @@ -1,24 +1,36 @@ mod v0; +mod v1; use crate::drive::Drive; +use dpp::document::Document; +use std::collections::BTreeMap; + use crate::error::drive::DriveError; use crate::error::Error; +use crate::query::document_history_drive_query::{ + DocumentHistoryDriveQuery, DocumentHistoryDriveQueryExecutionResult, +}; use dpp::data_contract::document_type::DocumentTypeRef; -use dpp::document::Document; use dpp::version::PlatformVersion; use grovedb::TransactionArg; -use std::collections::BTreeMap; impl Drive { - /// Fetches the historical revisions of a document that keeps history. + /// Reads the per-document timestamp-keyed history used through protocol version 14. + /// + /// # Parameters + /// `start_after_ms` excludes matching timestamps; `offset` optionally skips entries after + /// that bound for unproved queries. The platform version must select the timestamp-keyed reader. + /// + /// # Returns + /// The history result, or an error for an unsupported reader generation. #[allow(clippy::too_many_arguments)] - pub fn fetch_document_history( + pub fn fetch_document_history_after_time( &self, contract_id: [u8; 32], document_type: DocumentTypeRef, document_id: [u8; 32], transaction: TransactionArg, - start_at_ms: u64, + start_after_ms: u64, limit: Option, offset: Option, platform_version: &PlatformVersion, @@ -35,23 +47,50 @@ impl Drive { document_type, document_id, transaction, - start_at_ms, + start_after_ms, limit, offset, platform_version, ), version => Err(Error::Drive(DriveError::UnknownVersionMismatch { - method: "fetch_document_history".to_string(), + method: "fetch_document_history_after_time".to_owned(), known_versions: vec![0], received: version, })), } } + + /// Fetches a page and lifecycle from the per-type composite-keyed history tree. + pub fn fetch_document_history( + &self, + query: &DocumentHistoryDriveQuery, + document_type: DocumentTypeRef, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result { + match platform_version + .drive + .methods + .document + .query + .fetch_document_history + { + 1 => { + self.fetch_document_history_v1(query, document_type, transaction, platform_version) + } + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "fetch_document_history".to_string(), + known_versions: vec![1], + received: version, + })), + } + } } #[cfg(test)] -mod tests { +mod after_time_tests { use super::*; + use crate::query::document_history_drive_query::DocumentHistoryFilter; use crate::util::object_size_info::DocumentInfo::DocumentRefInfo; use crate::util::object_size_info::{DocumentAndContractInfo, OwnedDocumentInfo}; use crate::util::storage_flags::StorageFlags; @@ -61,12 +100,13 @@ mod tests { use dpp::document::{DocumentV0Getters, DocumentV0Setters}; use dpp::tests::json_document::{json_document_to_contract, json_document_to_document}; use dpp::tests::utils::generate_random_identifier_struct; + use dpp::version::FeatureVersion; const DOCUMENT_TYPE_NAME: &str = "profile"; fn setup_history_document() -> (Drive, dpp::prelude::DataContract, dpp::document::Document) { let drive = setup_drive_with_initial_state_structure(None); - let platform_version = PlatformVersion::latest(); + let platform_version = PlatformVersion::get(14).expect("protocol 14"); let contract = json_document_to_contract( "tests/supporting_files/contract/dashpay/dashpay-contract-with-profile-history.json", false, @@ -104,7 +144,7 @@ mod tests { document: &dpp::document::Document, time_ms: u64, ) { - let platform_version = PlatformVersion::latest(); + let platform_version = PlatformVersion::get(14).expect("protocol 14"); let document_type = contract .document_type_for_name(DOCUMENT_TYPE_NAME) .expect("profile document type"); @@ -131,137 +171,341 @@ mod tests { } #[test] - fn should_fetch_document_history_in_time_order_with_pagination() { + fn should_fetch_document_history_after_an_exclusive_time_with_pagination() { let (drive, contract, mut document) = setup_history_document(); - let platform_version = PlatformVersion::latest(); - let contract_id = contract.id().to_buffer(); - let document_id = document.id().to_buffer(); - let document_type = contract - .document_type_for_name(DOCUMENT_TYPE_NAME) - .expect("profile document type"); + let version = PlatformVersion::get(14).expect("protocol 14"); + let document_type = contract.document_type_for_name(DOCUMENT_TYPE_NAME).unwrap(); + for time in [1000, 2000, 3000] { + document.set("displayName", format!("Alice {time}").into()); + put_document(&drive, &contract, &document, time); + } + for (start_after_ms, limit, offset, expected) in [ + (0, None, None, vec![1000, 2000, 3000]), + (1000, Some(1), None, vec![2000]), + (2000, Some(10), None, vec![3000]), + (3000, Some(10), None, vec![]), + (1000, Some(10), Some(1), vec![3000]), + ] { + let history = drive + .fetch_document_history_after_time( + contract.id().to_buffer(), + document_type, + document.id().to_buffer(), + None, + start_after_ms, + limit, + offset, + version, + ) + .expect("fetch timestamp-keyed history"); + assert_eq!(history.keys().copied().collect::>(), expected); + } + } + #[test] + fn should_prove_and_verify_document_history_after_an_exclusive_time() { + let (drive, contract, mut document) = setup_history_document(); + let version = PlatformVersion::get(14).expect("protocol 14"); + let document_type = contract.document_type_for_name(DOCUMENT_TYPE_NAME).unwrap(); put_document(&drive, &contract, &document, 1000); document.set("displayName", "Alice 2".into()); put_document(&drive, &contract, &document, 2000); - document.set("displayName", "Alice 3".into()); - put_document(&drive, &contract, &document, 3000); - - let history = drive - .fetch_document_history( - contract_id, + for (start_after_ms, expected) in + [(0, vec![1000, 2000]), (1000, vec![2000]), (2000, vec![])] + { + let proof = drive + .prove_document_history_after_time( + contract.id().to_buffer(), + document_type, + document.id().to_buffer(), + None, + start_after_ms, + Some(10), + None, + version, + ) + .expect("prove timestamp-keyed history"); + let (_, history) = Drive::verify_document_history_after_time( + &proof, + contract.id().to_buffer(), + DOCUMENT_TYPE_NAME, document_type, - document_id, + document.id().to_buffer(), + start_after_ms, + Some(10), None, + version, + ) + .expect("verify timestamp-keyed history"); + assert_eq!( + history.unwrap().keys().copied().collect::>(), + expected + ); + } + } + + fn assert_version_mismatch( + error: Error, + expected_method: &str, + expected_version: FeatureVersion, + received_version: FeatureVersion, + ) { + assert!( + matches!(error, Error::Drive(DriveError::UnknownVersionMismatch { + method, known_versions, received, + }) if method == expected_method && known_versions == vec![expected_version] && received == received_version) + ); + } + + #[test] + fn should_refuse_composite_history_queries_with_timestamp_method_versions() { + let (drive, contract, document) = setup_history_document(); + let version = PlatformVersion::get(14).expect("protocol 14"); + let document_type = contract.document_type_for_name(DOCUMENT_TYPE_NAME).unwrap(); + for filter in [ + DocumentHistoryFilter::StartAtTime(0), + DocumentHistoryFilter::StartAtRevision(1), + ] { + let query = DocumentHistoryDriveQuery { + contract_id: contract.id().to_buffer(), + document_type_name: DOCUMENT_TYPE_NAME.into(), + document_id: document.id().to_buffer(), + filter, + limit: None, + }; + assert_version_mismatch( + drive + .fetch_document_history(&query, document_type, None, version) + .unwrap_err(), + "fetch_document_history", + 1, + 0, + ); + assert_version_mismatch( + drive + .prove_document_history(&query, document_type, None, version) + .unwrap_err(), + "prove_document_history", + 1, + 0, + ); + assert_version_mismatch( + Drive::verify_document_history(&query, &[], document_type, version).unwrap_err(), + "verify_document_history", + 1, + 0, + ); + } + } + + #[test] + fn should_refuse_timestamp_history_reads_with_composite_method_versions() { + let (drive, contract, document) = setup_history_document(); + let version = PlatformVersion::latest(); + let document_type = contract.document_type_for_name(DOCUMENT_TYPE_NAME).unwrap(); + assert_version_mismatch( + drive + .fetch_document_history_after_time( + contract.id().to_buffer(), + document_type, + document.id().to_buffer(), + None, + 0, + None, + None, + version, + ) + .unwrap_err(), + "fetch_document_history_after_time", + 0, + 1, + ); + assert_version_mismatch( + drive + .prove_document_history_after_time( + contract.id().to_buffer(), + document_type, + document.id().to_buffer(), + None, + 0, + None, + None, + version, + ) + .unwrap_err(), + "prove_document_history_after_time", + 0, + 1, + ); + assert_version_mismatch( + Drive::verify_document_history_after_time( + &[1], + contract.id().to_buffer(), + DOCUMENT_TYPE_NAME, + document_type, + document.id().to_buffer(), 0, None, None, - platform_version, + version, ) - .expect("fetch history"); - assert_eq!( - history.keys().copied().collect::>(), - vec![1000, 2000, 3000] + .unwrap_err(), + "verify_document_history_after_time", + 0, + 1, ); + } +} - let page = drive - .fetch_document_history( - contract_id, - document_type, - document_id, - None, - 1000, - Some(1), +#[cfg(test)] +mod tests { + use super::*; + use crate::drive::document::paths::DOCUMENT_HISTORY_TREE_KEY; + use crate::util::object_size_info::DocumentInfo::DocumentRefInfo; + use crate::util::object_size_info::{DocumentAndContractInfo, OwnedDocumentInfo}; + use crate::util::storage_flags::StorageFlags; + use crate::util::test_helpers::setup::setup_drive_with_initial_state_structure; + use dpp::block::block_info::BlockInfo; + use dpp::data_contract::accessors::v0::DataContractV0Getters; + use dpp::document::Document; + use dpp::document::{DocumentV0Getters, DocumentV0Setters}; + use dpp::tests::json_document::{json_document_to_contract, json_document_to_document}; + use dpp::tests::utils::generate_random_identifier_struct; + + const DOCUMENT_TYPE_NAME: &str = "profile"; + + fn setup_history_document( + platform_version: &PlatformVersion, + ) -> (Drive, dpp::prelude::DataContract, dpp::document::Document) { + let drive = setup_drive_with_initial_state_structure(None); + let contract = json_document_to_contract( + "tests/supporting_files/contract/dashpay/dashpay-contract-with-profile-history.json", + false, + platform_version, + ) + .expect("expected contract"); + drive + .apply_contract( + &contract, + BlockInfo::default(), + true, + StorageFlags::optional_default_as_cow(), None, platform_version, ) - .expect("fetch page"); - assert_eq!(page.keys().copied().collect::>(), vec![2000]); + .expect("apply contract"); - let empty_page = drive - .fetch_document_history( - contract_id, - document_type, - document_id, - None, - 3000, - Some(10), + let document_type = contract + .document_type_for_name(DOCUMENT_TYPE_NAME) + .expect("profile document type"); + let document = json_document_to_document( + "tests/supporting_files/contract/dashpay/profile0.json", + Some(generate_random_identifier_struct()), + document_type, + platform_version, + ) + .expect("expected document"); + + (drive, contract, document) + } + + fn put_document( + drive: &Drive, + contract: &dpp::prelude::DataContract, + document: &dpp::document::Document, + time_ms: u64, + platform_version: &PlatformVersion, + ) { + let document_type = contract + .document_type_for_name(DOCUMENT_TYPE_NAME) + .expect("profile document type"); + drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentRefInfo(( + document, + StorageFlags::optional_default_as_cow(), + )), + owner_id: None, + }, + contract, + document_type, + }, + true, + BlockInfo::default_with_time(time_ms), + true, None, platform_version, ) - .expect("fetch empty page"); - assert!(empty_page.is_empty()); + .expect("put document"); } #[test] - fn should_prove_and_verify_document_history() { - let (drive, contract, mut document) = setup_history_document(); + fn should_retain_both_replacements_in_the_same_block() { + use crate::drive::document::paths::contract_document_type_path_vec; + use crate::util::common::encode::encode_u64; + use dpp::document::serialization_traits::DocumentPlatformConversionMethodsV0; + use grovedb::query_result_type::{QueryResultElement, QueryResultType}; + use grovedb::{Element, PathQuery, Query, SizedQuery}; + let platform_version = PlatformVersion::latest(); - let contract_id = contract.id().to_buffer(); - let document_id = document.id().to_buffer(); + let (drive, contract, mut document) = setup_history_document(platform_version); let document_type = contract .document_type_for_name(DOCUMENT_TYPE_NAME) .expect("profile document type"); + document.set_revision(Some(1)); + put_document(&drive, &contract, &document, 1000, platform_version); - put_document(&drive, &contract, &document, 1000); - document.set("displayName", "Alice 2".into()); - put_document(&drive, &contract, &document, 2000); + for revision in [2, 3] { + document.set_revision(Some(revision)); + document.set("displayName", format!("Revision {revision}").into()); + drive + .update_document_for_contract( + &document, + &contract, + document_type, + Some(document.owner_id().to_buffer()), + BlockInfo::default_with_time(2000), + true, + StorageFlags::optional_default_as_cow(), + None, + platform_version, + ) + .expect("replace document in the same block"); + } - let proof = drive - .prove_document_history( - contract_id, - document_type, - document_id, - None, - 0, - Some(10), + let mut history_path = + contract_document_type_path_vec(contract.id().as_slice(), DOCUMENT_TYPE_NAME); + history_path.extend([vec![DOCUMENT_HISTORY_TREE_KEY], document.id().to_vec()]); + let mut query = Query::new(); + query.insert_range_from(encode_u64(0)..); + let (results, _) = drive + .grove_get_path_query( + &PathQuery::new(history_path, SizedQuery::new(query, None, None)), None, - platform_version, + QueryResultType::QueryKeyElementPairResultType, + &mut Vec::new(), + &platform_version.drive, ) - .expect("prove history"); - let (_root_hash, history) = Drive::verify_document_history( - &proof, - contract_id, - DOCUMENT_TYPE_NAME, - document_type, - document_id, - 0, - Some(10), - None, - platform_version, - ) - .expect("verify history"); - - let history = history.expect("history exists"); + .expect("read retained revision bodies"); + let revisions = results + .elements + .into_iter() + .map(|entry| match entry { + QueryResultElement::KeyElementPairResultItem((_, Element::Item(bytes, _))) => { + Document::from_bytes(&bytes, document_type, platform_version) + .expect("deserialize retained revision") + .revision() + .expect("mutable document has a revision") + } + _ => panic!("history must contain document items"), + }) + .collect::>(); assert_eq!( - history.keys().copied().collect::>(), - vec![1000, 2000] + revisions, + vec![1, 2, 3], + "every accepted edit must remain readable" ); - - let empty_page_proof = drive - .prove_document_history( - contract_id, - document_type, - document_id, - None, - 2000, - Some(10), - None, - platform_version, - ) - .expect("prove empty page"); - let (_root_hash, empty_history) = Drive::verify_document_history( - &empty_page_proof, - contract_id, - DOCUMENT_TYPE_NAME, - document_type, - document_id, - 2000, - Some(10), - None, - platform_version, - ) - .expect("verify empty history page"); - - assert!(empty_history.expect("empty history page exists").is_empty()); } } diff --git a/packages/rs-drive/src/drive/document/get_fetch/fetch_document_history/v0/mod.rs b/packages/rs-drive/src/drive/document/get_fetch/fetch_document_history/v0/mod.rs index 357a64a8f06..577a9387169 100644 --- a/packages/rs-drive/src/drive/document/get_fetch/fetch_document_history/v0/mod.rs +++ b/packages/rs-drive/src/drive/document/get_fetch/fetch_document_history/v0/mod.rs @@ -18,7 +18,7 @@ impl Drive { document_type: DocumentTypeRef, document_id: [u8; 32], transaction: TransactionArg, - start_at_ms: u64, + start_after_ms: u64, limit: Option, offset: Option, platform_version: &PlatformVersion, @@ -28,7 +28,7 @@ impl Drive { contract_id, document_type, document_id, - start_at_ms, + start_after_ms, limit, offset, platform_version, diff --git a/packages/rs-drive/src/drive/document/get_fetch/fetch_document_history/v1/mod.rs b/packages/rs-drive/src/drive/document/get_fetch/fetch_document_history/v1/mod.rs new file mode 100644 index 00000000000..7edf5278d37 --- /dev/null +++ b/packages/rs-drive/src/drive/document/get_fetch/fetch_document_history/v1/mod.rs @@ -0,0 +1,65 @@ +use crate::drive::document::paths::contract_document_type_path_vec; +use crate::drive::Drive; +use crate::error::Error; +use crate::query::document_history_drive_query::{ + invalid, DocumentHistoryDriveQuery, DocumentHistoryDriveQueryExecutionResult, +}; +use crate::query::refuse_a_private_document_type; +use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters; +use dpp::data_contract::document_type::DocumentTypeRef; +use dpp::version::PlatformVersion; +use grovedb::{Element, TransactionArg}; + +impl Drive { + /// Fetches a page of the per-type history tree with the document's + /// current lifecycle metadata. + pub(super) fn fetch_document_history_v1( + &self, + query: &DocumentHistoryDriveQuery, + document_type: DocumentTypeRef, + transaction: TransactionArg, + version: &PlatformVersion, + ) -> Result { + refuse_a_private_document_type(document_type).map_err(Error::Query)?; + if !document_type.documents_keep_history() { + return Err(invalid("document type does not keep history")); + } + let path_query = query.construct_path_query(version)?; + let (rows, _) = self.grove_get_raw_path_query( + &path_query, + transaction, + grovedb::query_result_type::QueryResultType::QueryPathKeyElementTrioResultType, + &mut vec![], + &version.drive, + )?; + let mut rows = rows.to_path_key_elements(); + let mut primary = + contract_document_type_path_vec(&query.contract_id, &query.document_type_name); + primary.push(vec![0]); + for (path, key, element) in &mut rows { + if *path == primary + && matches!( + element, + Element::Reference(..) | Element::ReferenceWithSumItem(..) + ) + { + *element = self + .grove + .get::, _>( + path.as_slice(), + key, + transaction, + &version.drive.grove_version, + ) + .value?; + } + } + query.decode_result( + rows.into_iter() + .map(|(path, key, element)| (path, key, Some(element))) + .collect(), + document_type, + version, + ) + } +} diff --git a/packages/rs-drive/src/drive/document/index_level_tree_types.rs b/packages/rs-drive/src/drive/document/index_level_tree_types.rs index fa87970e36d..182d205a5ca 100644 --- a/packages/rs-drive/src/drive/document/index_level_tree_types.rs +++ b/packages/rs-drive/src/drive/document/index_level_tree_types.rs @@ -323,14 +323,24 @@ pub(crate) fn distinct_estimated_keys<'a>( /// declare changes the trees and fees of those versions; make such a change a /// new versioned method instead of editing this function. pub(crate) fn terminal_member_tree_type(index_type: &IndexLevelTypeInfo) -> TreeType { - let count_provable = matches!( + terminal_member_tree_type_for_aggregates( index_type.countable, - IndexCountability::CountableAllowingOffset - ); - let count_root_only = - matches!(index_type.countable, IndexCountability::Countable) && !count_provable; - let sum_provable = index_type.range_summable; - let sum_root_only = index_type.summable.is_some() && !sum_provable; + index_type.summable.is_some(), + index_type.range_summable, + ) +} + +/// The same derivation over an index's own aggregate flags, for callers +/// that hold the contract's `Index` rather than a resolved level. +pub(crate) fn terminal_member_tree_type_for_aggregates( + countable: IndexCountability, + summable: bool, + range_summable: bool, +) -> TreeType { + let count_provable = matches!(countable, IndexCountability::CountableAllowingOffset); + let count_root_only = matches!(countable, IndexCountability::Countable) && !count_provable; + let sum_provable = range_summable; + let sum_root_only = summable && !sum_provable; match (count_provable, count_root_only, sum_provable, sum_root_only) { (false, false, false, false) => TreeType::NormalTree, (false, true, false, false) => TreeType::CountTree, diff --git a/packages/rs-drive/src/drive/document/insert/add_document_to_primary_storage/mod.rs b/packages/rs-drive/src/drive/document/insert/add_document_to_primary_storage/mod.rs index ff5cc8b0b99..44655a2598a 100644 --- a/packages/rs-drive/src/drive/document/insert/add_document_to_primary_storage/mod.rs +++ b/packages/rs-drive/src/drive/document/insert/add_document_to_primary_storage/mod.rs @@ -1,4 +1,5 @@ mod v0; +mod v1; use crate::util::estimated_layers::EstimatedLayers; use dpp::block::block_info::BlockInfo; @@ -54,9 +55,18 @@ impl Drive { drive_operations, platform_version, ), + 1 => self.add_document_to_primary_storage_v1( + document_and_contract_info, + block_info, + insert_without_check, + estimated_costs_only_with_layer_info, + transaction, + drive_operations, + platform_version, + ), version => Err(Error::Drive(DriveError::UnknownVersionMismatch { method: "add_document_to_primary_storage".to_string(), - known_versions: vec![0], + known_versions: vec![0, 1], received: version, })), } diff --git a/packages/rs-drive/src/drive/document/insert/add_document_to_primary_storage/v0/mod.rs b/packages/rs-drive/src/drive/document/insert/add_document_to_primary_storage/v0/mod.rs index c7a6d0336fe..d272dda5cc8 100644 --- a/packages/rs-drive/src/drive/document/insert/add_document_to_primary_storage/v0/mod.rs +++ b/packages/rs-drive/src/drive/document/insert/add_document_to_primary_storage/v0/mod.rs @@ -868,7 +868,7 @@ mod keep_history_summable_e2e { true, StorageFlags::optional_default_as_cow(), None, - PlatformVersion::latest(), + PlatformVersion::get(14).expect("protocol 14"), ) .expect("apply contract"); } @@ -894,13 +894,13 @@ mod keep_history_summable_e2e { BlockInfo::default(), true, None, - PlatformVersion::latest(), + PlatformVersion::get(14).expect("protocol 14"), ) .expect("insert doc"); } fn read_element_at(drive: &Drive, path: &[Vec], key: &[u8]) -> Element { - let pv = PlatformVersion::latest(); + let pv = PlatformVersion::get(14).expect("protocol 14"); let path_refs: Vec<&[u8]> = path.iter().map(|v| v.as_slice()).collect(); drive .grove_get_raw( @@ -1056,7 +1056,7 @@ mod keep_history_summable_e2e { true, Some(Cow::Owned(StorageFlags::SingleEpoch(0))), None, - PlatformVersion::latest(), + PlatformVersion::get(14).expect("protocol 14"), ) .expect("update doc to v2"); diff --git a/packages/rs-drive/src/drive/document/insert/add_document_to_primary_storage/v1/mod.rs b/packages/rs-drive/src/drive/document/insert/add_document_to_primary_storage/v1/mod.rs new file mode 100644 index 00000000000..f743b393386 --- /dev/null +++ b/packages/rs-drive/src/drive/document/insert/add_document_to_primary_storage/v1/mod.rs @@ -0,0 +1,225 @@ +//! Primary storage writer for the protocol 15 keep-history layout. +//! +//! What changed from v0: a keep-history document's revisions are no longer +//! items in the document's own subtree of the primary key tree, keyed by +//! block time with the current revision behind a `[0]` reference. The primary +//! key tree entry is now a reference to the current revision (carrying the sum +//! contribution for a summable type), and the revision itself is written into +//! the document type's history tree, one provable count tree per document, +//! keyed by block time followed by revision so that two revisions in one block +//! stay distinct. Types that do not keep history are written exactly as in v0. + +use crate::drive::constants::DOCUMENT_HISTORY_CURRENT_REFERENCE_PATH_SIZE; +use crate::drive::document::paths::{ + contract_documents_primary_key_path, DOCUMENT_HISTORY_TREE_KEY, +}; +use crate::drive::document::primary_key_tree_type::DocumentTypePrimaryKeyTreeType; +use crate::drive::document::read_document_sum_contribution; +use crate::drive::Drive; +use crate::error::{drive::DriveError, Error}; +use crate::fees::op::LowLevelDriveOperation; +use crate::util::common::encode::encode_u64; +use crate::util::estimated_layers::EstimatedLayers; +use crate::util::grove_operations::{BatchInsertApplyType, BatchInsertTreeApplyType, QueryTarget}; +use crate::util::object_size_info::DocumentInfo; +use crate::util::object_size_info::PathKeyElementInfo::{ + PathKeyElement, PathKeyUnknownElementSize, +}; +use crate::util::object_size_info::PathKeyInfo::PathKey; +use crate::util::object_size_info::{DocumentAndContractInfo, DocumentInfoV0Methods}; +use crate::util::storage_flags::StorageFlags; +use dpp::block::block_info::BlockInfo; +use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::data_contract::document_type::accessors::{DocumentTypeV0Getters, DocumentTypeV2Getters}; +use dpp::data_contract::document_type::methods::DocumentTypeBasicMethods; +use dpp::document::serialization_traits::DocumentPlatformConversionMethodsV0; +use dpp::document::DocumentV0Getters; +use dpp::version::PlatformVersion; +use grovedb::batch::{key_info::KeyInfo, KeyInfoPath}; +use grovedb::reference_path::ReferencePathType::UpstreamRootHeightReference; +use grovedb::{Element, TransactionArg, TreeType}; + +impl Drive { + /// Stores immutable revisions separately from the current primary-key entry. + #[allow(clippy::too_many_arguments)] + pub(super) fn add_document_to_primary_storage_v1( + &self, + info: &DocumentAndContractInfo, + block_info: &BlockInfo, + insert_without_check: bool, + estimated: &mut Option, + transaction: TransactionArg, + operations: &mut Vec, + platform_version: &PlatformVersion, + ) -> Result<(), Error> { + if !info.document_type.documents_keep_history() { + return self.add_document_to_primary_storage_0( + info, + block_info, + insert_without_check, + estimated, + transaction, + operations, + platform_version, + ); + } + let version = &platform_version.drive; + let primary_path = contract_documents_primary_key_path( + info.contract.id_ref().as_bytes(), + info.document_type.name(), + ); + if let Some(layers) = estimated { + Self::add_estimation_costs_for_add_document_to_primary_storage( + info, + primary_path, + layers, + platform_version, + )?; + } + let document_info = &info.owned_document_info.document_info; + let document = document_info.get_borrowed_document(); + let document_key = document.map_or_else( + || KeyInfo::MaxKeySize { + unique_id: info.document_type.unique_id_for_storage().to_vec(), + max_size: 32, + }, + |document| KeyInfo::KnownKey(document.id().to_vec()), + ); + let mut history_root = primary_path.map(|part| part.to_vec()).to_vec(); + history_root[4] = vec![DOCUMENT_HISTORY_TREE_KEY]; + let mut history_path = KeyInfoPath::from_known_path(history_root.iter().map(Vec::as_slice)); + history_path.push(document_key.clone()); + let flags = document_info.get_storage_flags_ref(); + let tree_apply = if estimated.is_some() { + BatchInsertTreeApplyType::StatelessBatchInsertTree { + in_tree_type: TreeType::NormalTree, + tree_type: TreeType::ProvableCountTree, + flags_len: flags.map(StorageFlags::serialized_size).unwrap_or_default(), + } + } else { + BatchInsertTreeApplyType::StatefulBatchInsertTree + }; + if let Some(document) = document { + self.batch_insert_empty_tree_if_not_exists::<0>( + PathKey((history_root, document.id().to_vec())), + TreeType::ProvableCountTree, + flags, + tree_apply, + transaction, + &mut None, + operations, + version, + )?; + } else { + operations.push( + LowLevelDriveOperation::for_estimated_path_key_empty_provable_count_tree( + KeyInfoPath::from_known_owned_path(history_root), + document_key.clone(), + flags, + ), + ); + } + + let mut revision_key = encode_u64(block_info.time_ms); + revision_key.extend(encode_u64(document.and_then(|d| d.revision()).unwrap_or(1))); + let summable = info.document_type.documents_summable(); + let (revision, pointer) = if let Some(document) = document { + let bytes = match document_info { + DocumentInfo::DocumentRefAndSerialization((_, bytes, _)) => bytes.to_vec(), + DocumentInfo::DocumentAndSerialization((_, bytes, _)) => bytes.clone(), + _ => document.serialize(info.document_type, info.contract, platform_version)?, + }; + let element_flags = StorageFlags::map_to_some_element_flags(flags); + let reference = UpstreamRootHeightReference( + 4, + vec![ + vec![DOCUMENT_HISTORY_TREE_KEY], + document.id().to_vec(), + revision_key.clone(), + ], + ); + let pointer = if let Some(property) = summable { + Element::new_reference_with_sum_item_with_max_hops_and_flags( + reference, + Some(1), + read_document_sum_contribution(document, property)?, + element_flags.clone(), + ) + } else { + Element::Reference(reference, Some(1), element_flags.clone()) + }; + let mut known_history = primary_path.map(|part| part.to_vec()).to_vec(); + known_history[4] = vec![DOCUMENT_HISTORY_TREE_KEY]; + known_history.push(document.id().to_vec()); + ( + PathKeyElement(( + known_history, + revision_key, + Element::Item(bytes, element_flags), + )), + PathKeyElement(( + primary_path.map(|part| part.to_vec()).to_vec(), + document.id().to_vec(), + pointer, + )), + ) + } else { + let DocumentInfo::DocumentEstimatedAverageSize(size) = document_info else { + return Err(Error::Drive(DriveError::CorruptedCodeExecution( + "missing document size", + ))); + }; + let flags_size = flags.map(StorageFlags::serialized_size).unwrap_or_default(); + let pointer_size = if summable.is_some() { + Element::required_reference_with_sum_item_space( + DOCUMENT_HISTORY_CURRENT_REFERENCE_PATH_SIZE, + flags_size, + &version.grove_version, + )? + } else { + Element::required_item_space( + DOCUMENT_HISTORY_CURRENT_REFERENCE_PATH_SIZE, + flags_size, + &version.grove_version, + )? + }; + ( + PathKeyUnknownElementSize(( + history_path, + KeyInfo::KnownKey(revision_key), + Element::required_item_space(*size, flags_size, &version.grove_version)?, + )), + PathKeyUnknownElementSize(( + KeyInfoPath::from_known_path(primary_path), + document_key, + pointer_size, + )), + ) + }; + self.batch_insert::<0>(revision, operations, version)?; + if insert_without_check { + self.batch_insert::<0>(pointer, operations, version)?; + } else { + let apply_type = if estimated.is_some() { + BatchInsertApplyType::StatelessBatchInsert { + in_tree_type: info.document_type.primary_key_tree_type(platform_version)?, + target: QueryTarget::QueryTargetValue(64), + } + } else { + BatchInsertApplyType::StatefulBatchInsert + }; + if !self.batch_insert_if_not_exists::<0>( + pointer, + apply_type, + transaction, + operations, + version, + )? { + return Err(Error::Drive(DriveError::CorruptedDocumentAlreadyExists( + "item already exists", + ))); + } + } + Ok(()) + } +} diff --git a/packages/rs-drive/src/drive/document/insert/add_reference_for_index_level_for_contract_operations/mod.rs b/packages/rs-drive/src/drive/document/insert/add_reference_for_index_level_for_contract_operations/mod.rs index 35299a740df..cdd7ff49141 100644 --- a/packages/rs-drive/src/drive/document/insert/add_reference_for_index_level_for_contract_operations/mod.rs +++ b/packages/rs-drive/src/drive/document/insert/add_reference_for_index_level_for_contract_operations/mod.rs @@ -1,4 +1,5 @@ mod v0; +mod v1; use crate::util::estimated_layers::EstimatedLayers; use crate::util::storage_flags::StorageFlags; @@ -61,9 +62,22 @@ impl Drive { batch_operations, platform_version, ), + 1 => self.add_reference_for_index_level_for_contract_operations_v1( + document_and_contract_info, + index_path_info, + index_type, + any_fields_null, + all_fields_null, + previous_batch_operations, + storage_flags, + estimated_costs_only_with_layer_info, + transaction, + batch_operations, + platform_version, + ), version => Err(Error::Drive(DriveError::UnknownVersionMismatch { method: "add_reference_for_index_level_for_contract_operations".to_string(), - known_versions: vec![0], + known_versions: vec![0, 1], received: version, })), } diff --git a/packages/rs-drive/src/drive/document/insert/add_reference_for_index_level_for_contract_operations/v1/mod.rs b/packages/rs-drive/src/drive/document/insert/add_reference_for_index_level_for_contract_operations/v1/mod.rs new file mode 100644 index 00000000000..97820d3e017 --- /dev/null +++ b/packages/rs-drive/src/drive/document/insert/add_reference_for_index_level_for_contract_operations/v1/mod.rs @@ -0,0 +1,656 @@ +use crate::util::estimated_layers::EstimatedLayers; +// Protocol 15 generation: index references point at the primary key tree +// entry for every document type, including keep-history types whose entry +// is itself a reference into the history tree; everything else matches v0. +use crate::drive::constants::STORAGE_FLAGS_SIZE; +use crate::drive::document::index_level_tree_types::terminal_member_tree_type; +use crate::drive::document::index_only::{index_only_member_key, index_only_terminal_max_key_size}; +use crate::drive::document::{ + document_reference_estimated_layer_sizes_v1, document_reference_estimated_value_size_v1, + make_document_reference_v1, make_document_reference_with_sum_item_v1, + read_document_sum_contribution, +}; +use crate::drive::document::{ + encode_index_only_entry_payload, index_only_item_estimated_value_size, + index_only_row_commitment_max_preimage_size, index_only_row_commitment_with_preimage_size, +}; +use crate::drive::Drive; +use crate::error::drive::DriveError; +use crate::error::Error; +use crate::fees::op::LowLevelDriveOperation::FunctionOperation; +use crate::fees::op::{FunctionOp, HashFunction, LowLevelDriveOperation}; +use crate::util::grove_operations::QueryTarget::QueryTargetValue; +use crate::util::grove_operations::{BatchInsertApplyType, BatchInsertTreeApplyType}; +use crate::util::object_size_info::DocumentInfo::{ + DocumentAndSerialization, DocumentEstimatedAverageSize, DocumentOwnedInfo, + DocumentRefAndSerialization, DocumentRefInfo, +}; +use crate::util::object_size_info::DriveKeyInfo::{Key, KeyRef}; +use crate::util::object_size_info::KeyElementInfo::{KeyElement, KeyUnknownElementSize}; +use crate::util::object_size_info::{ + DocumentAndContractInfo, DocumentInfoV0Methods, PathInfo, PathKeyElementInfo, +}; +use crate::util::storage_flags::StorageFlags; +use crate::util::type_constants::DEFAULT_HASH_SIZE_U8; +use dpp::data_contract::document_type::methods::DocumentTypeBasicMethods; +use dpp::data_contract::document_type::IndexLevelTypeInfo; +use dpp::document::Document; +use dpp::document::DocumentV0Getters; +use dpp::version::PlatformVersion; +use grovedb::batch::key_info::KeyInfo; +use grovedb::EstimatedLayerCount::PotentiallyAtMaxElements; +use grovedb::EstimatedLayerSizes::AllItems; +use grovedb::{Element, EstimatedLayerInformation, TransactionArg, TreeType}; + +impl Drive { + /// Adds the terminal reference. + #[inline(always)] + #[allow(clippy::too_many_arguments)] + pub(super) fn add_reference_for_index_level_for_contract_operations_v1( + &self, + document_and_contract_info: &DocumentAndContractInfo, + mut index_path_info: PathInfo<0>, + // See the wrapper's docstring for why this is a borrow now. + index_type: &IndexLevelTypeInfo, + any_fields_null: bool, + all_fields_null: bool, + previous_batch_operations: &mut Option<&mut Vec>, + storage_flags: &Option<&StorageFlags>, + estimated_costs_only_with_layer_info: &mut Option, + transaction: TransactionArg, + batch_operations: &mut Vec, + platform_version: &PlatformVersion, + ) -> Result<(), Error> { + let drive_version = &platform_version.drive; + + if all_fields_null && !index_type.should_insert_with_all_null { + return Ok(()); + } + + // A summableOffCountIndex index has no entry to write: the walker moves its + // counter at the value position instead of descending here. Inert before protocol + // version 14: only parser generation 3 admits the keyword, and only the v2 walkers, + // which no earlier version selects, reach such an index. + if index_type.is_summable_off_count_index() { + return Err(Error::Drive(DriveError::CorruptedCodeExecution( + "a summableOffCountIndex index's counter is moved by the walker, never written as an entry", + ))); + } + + // indexOnly terminal: the member key is the terminal property's + // value and the element is an empty `Item` — there is no + // primary-storage row to reference. `terminal` can only be `Some` + // on a PV14+ indexOnly contract (the grammar rejects the keyword + // below meta-schema v3), so this branch is unreachable for every + // historical document — the same in-place gating the count and sum + // flags in this function already rely on. + if let Some(terminal) = index_type.terminal.as_deref() { + return self.add_index_only_terminal_item_operations_v1( + document_and_contract_info, + index_path_info, + index_type, + terminal, + previous_batch_operations, + storage_flags, + estimated_costs_only_with_layer_info, + transaction, + batch_operations, + platform_version, + ); + } + + // The terminal reference's tree type is driven by the + // composition of the index's countability AND summability, + // per-axis (the TreeType set distinguishes provable from root-only + // on each axis independently): + // + // - count provable + sum root → `ProvableCountSumTree` + // (existing variant: per-node count, root-only sum) + // - count root + sum provable → `ProvableCountProvableSumTree` + // (no dedicated "count-root + sum-provable" variant exists; + // upgrades count to per-node too) + // - count provable + sum provable → + // `ProvableCountProvableSumTree` (both per-node) + // + // Same dispatch shape as the primary-key tree dispatcher's v1 + // arm in `primary_key_tree_type.rs` — see + // `terminal_member_tree_type` for the full table (shared with + // the delete side and the indexOnly terminal branches). The + // `IndexLevelTypeInfo`'s `summable` carries the property name + // the reference's sum-item will contribute (read below to + // construct the `Element::ReferenceWithSumItem` that replaces a + // plain `Element::Reference` under summable indexes). + let reference_tree_type = terminal_member_tree_type(index_type); + + // Element-shape selector. Under a summable index path the + // reference element MUST be + // `Element::ReferenceWithSumItem(reference_path, amount_i64, + // flags)` rather than a plain + // `Element::Reference` — only `ReferenceWithSumItem` + // contributes a sum to the ancestor sum trees while still + // dereferencing to the document body in primary storage + // (so document iteration via index walks keeps working + // identically to the count side). Read the sum contribution + // once per insert from the document's `summable.unwrap()` + // property and freeze it into the element. On delete, grovedb + // pulls the same sum value off the stored element and + // propagates the subtraction up the merk path — no need to + // re-read the source document on the way down. + let sum_property_name: Option<&str> = index_type.summable.as_deref(); + let make_terminal_ref = + |document: &Document, storage_flags: Option<&StorageFlags>| -> Result { + match sum_property_name { + Some(prop_name) => { + // DPP validator guarantees the property is in + // `required` and is an integer type, so this + // conversion is safe — propagated as + // `CorruptedCodeExecution` if it ever fails. + let sum_value = read_document_sum_contribution(document, prop_name)?; + Ok(make_document_reference_with_sum_item_v1( + document, + document_and_contract_info.document_type, + sum_value, + storage_flags, + )) + } + None => Ok(make_document_reference_v1( + document, + document_and_contract_info.document_type, + storage_flags, + )), + } + }; + // unique indexes will be stored under key "0" + // non-unique indices should have a tree at key "0" that has all elements based off of primary key + if !index_type.index_type.is_unique() || any_fields_null { + // Tree generation, this happens for both non unique indexes, unique indexes with a null inside + // a member of the path + let key_path_info = KeyRef(&[0]); + + let path_key_info = key_path_info.add_path_info(index_path_info.clone()); + + let apply_type = if estimated_costs_only_with_layer_info.is_none() { + BatchInsertTreeApplyType::StatefulBatchInsertTree + } else { + BatchInsertTreeApplyType::StatelessBatchInsertTree { + in_tree_type: TreeType::NormalTree, + tree_type: reference_tree_type, + flags_len: storage_flags + .map(|s| s.serialized_size()) + .unwrap_or_default(), + } + }; + + // Here we are inserting an empty tree that will have a subtree of all other index properties + // It is basically the 0 + // Underneath we will have all elements if non unique index, or all identity contenders if + // a contested resource index + self.batch_insert_empty_tree_if_not_exists( + path_key_info, + reference_tree_type, + *storage_flags, + apply_type, + transaction, + previous_batch_operations, + batch_operations, + drive_version, + )?; + + index_path_info.push(Key(vec![0]))?; + // This is the simpler situation + // Under each tree we have all the references + + if let Some(estimated_costs_only_with_layer_info) = estimated_costs_only_with_layer_info + { + // On this level we will have a 0 and all the top index paths + estimated_costs_only_with_layer_info.insert( + index_path_info.clone().convert_to_key_info_path(), + EstimatedLayerInformation { + tree_type: reference_tree_type, + estimated_layer_count: PotentiallyAtMaxElements, + estimated_layer_sizes: document_reference_estimated_layer_sizes_v1( + DEFAULT_HASH_SIZE_U8, + storage_flags.map(|s| s.serialized_size()), + sum_property_name.is_some(), + ), + }, + ); + } + + let key_element_info = + match &document_and_contract_info.owned_document_info.document_info { + DocumentRefAndSerialization((document, _, storage_flags)) + | DocumentRefInfo((document, storage_flags)) => { + let document_reference = make_terminal_ref( + document, + storage_flags.as_ref().map(|flags| flags.as_ref()), + )?; + KeyElement((document.id_ref().as_slice(), document_reference)) + } + DocumentOwnedInfo((document, storage_flags)) + | DocumentAndSerialization((document, _, storage_flags)) => { + let document_reference = make_terminal_ref( + document, + storage_flags.as_ref().map(|flags| flags.as_ref()), + )?; + KeyElement((document.id_ref().as_slice(), document_reference)) + } + DocumentEstimatedAverageSize(max_size) => KeyUnknownElementSize(( + KeyInfo::MaxKeySize { + unique_id: document_and_contract_info + .document_type + .unique_id_for_storage() + .to_vec(), + max_size: DEFAULT_HASH_SIZE_U8, + }, + // Match the sum-bearing variant the live path + // would have written: `make_document_reference_with_sum_item_v1` + // emits `Element::ReferenceWithSumItem` when + // `sum_property_name.is_some()`. The sum-aware helper + // reserves 10 worst-case bytes for the i64 sum_value. + // Unconditional switch: this entire flow is v12+ + // gated (no v11 consensus baseline for sum-bearing + // index refs). + if sum_property_name.is_some() { + Element::required_reference_with_sum_item_space( + *max_size, + STORAGE_FLAGS_SIZE, + &drive_version.grove_version, + )? + } else { + Element::required_item_space( + *max_size, + STORAGE_FLAGS_SIZE, + &drive_version.grove_version, + )? + }, + )), + }; + + let path_key_element_info = PathKeyElementInfo::from_path_info_and_key_element( + index_path_info, + key_element_info, + )?; + + // here we should return an error if the element already exists + self.batch_insert(path_key_element_info, batch_operations, drive_version)?; + } else { + let key_element_info = + match &document_and_contract_info.owned_document_info.document_info { + DocumentRefAndSerialization((document, _, storage_flags)) + | DocumentRefInfo((document, storage_flags)) => { + let document_reference = make_terminal_ref( + document, + storage_flags.as_ref().map(|flags| flags.as_ref()), + )?; + KeyElement((&[0], document_reference)) + } + DocumentOwnedInfo((document, storage_flags)) + | DocumentAndSerialization((document, _, storage_flags)) => { + let document_reference = make_terminal_ref( + document, + storage_flags.as_ref().map(|flags| flags.as_ref()), + )?; + KeyElement((&[0], document_reference)) + } + DocumentEstimatedAverageSize(estimated_size) => KeyUnknownElementSize(( + KeyInfo::MaxKeySize { + unique_id: document_and_contract_info + .document_type + .unique_id_for_storage() + .to_vec(), + max_size: 1, + }, + // Parallel to the non-unique branch above: unique + // indexes with `summable: Some(_)` still write a + // `ReferenceWithSumItem` at the terminal `[0]` slot + // when there's any non-null entry (the unique-no-op + // caveat applies only to all-non-null exact matches, + // see book/document-sum-trees.md). The estimated + // worst-case treats the sum-bearing variant. + if sum_property_name.is_some() { + Element::required_reference_with_sum_item_space( + *estimated_size, + STORAGE_FLAGS_SIZE, + &drive_version.grove_version, + )? + } else { + Element::required_item_space( + *estimated_size, + STORAGE_FLAGS_SIZE, + &drive_version.grove_version, + )? + }, + )), + }; + + let path_key_element_info = PathKeyElementInfo::from_path_info_and_key_element( + index_path_info, + key_element_info, + )?; + + let apply_type = if estimated_costs_only_with_layer_info.is_none() { + BatchInsertApplyType::StatefulBatchInsert + } else { + BatchInsertApplyType::StatelessBatchInsert { + in_tree_type: reference_tree_type, + target: QueryTargetValue(document_reference_estimated_value_size_v1( + storage_flags + .map(|s| s.serialized_size()) + .unwrap_or_default(), + sum_property_name.is_some(), + )), + } + }; + + // here we should return an error if the element already exists + let inserted = self.batch_insert_if_not_exists( + path_key_element_info, + apply_type, + transaction, + batch_operations, + drive_version, + )?; + if !inserted { + return Err(Error::Drive(DriveError::CorruptedContractIndexes( + "reference already exists".to_string(), + ))); + } + } + Ok(()) + } + + /// The indexOnly terminal: writes `[…index path, 0, ] → + /// Item(commitment, flags)` — the member key is the terminal property's + /// value in its tree-key encoding (`$ownerId` or any indexable schema + /// property, sized for estimation by its declared bound) sitting exactly + /// where a normal non-unique index keys by document id, and the element + /// payload is the row commitment because the entry IS the row. Storage + /// flags ride the element flags for epoch/owner refunds, exactly as on + /// references. + /// + /// Existence check semantics: the entry is inserted with + /// `if_not_exists`, and an existing entry is an error. ABCI state + /// validation probes every index's entry before the batch applies, so + /// reaching this error at apply time means validation was bypassed — + /// the same backstop role the unique-index "reference already exists" + /// above plays. The exception is an index whose entries outlive a delete + /// (`outlivesDelete`): validation does not probe it, and an entry there + /// already, left by a deleted document with the same key, is written over. + /// + /// Under a summable index the element is + /// `ItemWithSumItem(commitment, amount, flags)` instead — the same + /// payload, plus the summed property's value read off the document, so + /// the entry contributes to the ancestor sum trees exactly as a + /// `ReferenceWithSumItem` does for stored types. On delete, grovedb + /// reads the amount off the stored element and propagates the + /// subtraction — the delete path needs no sum-specific logic. The + /// amount is one of the document's properties, so it is already covered + /// by the row commitment: a delete carrying a falsified amount fails + /// the commitment probe before anything is removed. + #[allow(clippy::too_many_arguments)] + fn add_index_only_terminal_item_operations_v1( + &self, + document_and_contract_info: &DocumentAndContractInfo, + mut index_path_info: PathInfo<0>, + index_type: &IndexLevelTypeInfo, + terminal: &[String], + previous_batch_operations: &mut Option<&mut Vec>, + storage_flags: &Option<&StorageFlags>, + estimated_costs_only_with_layer_info: &mut Option, + transaction: TransactionArg, + batch_operations: &mut Vec, + platform_version: &PlatformVersion, + ) -> Result<(), Error> { + let drive_version = &platform_version.drive; + + let member_tree_type = terminal_member_tree_type(index_type); + let sum_property_name: Option<&str> = index_type.summable.as_deref(); + // The member key's estimated width follows the terminal property: + // 32 bytes for `$ownerId`, the declared bound otherwise. + let member_key_max_size = index_only_terminal_max_key_size( + document_and_contract_info.document_type, + terminal, + platform_version, + )?; + // The item's estimated value: the padded commitment plus the type's + // entry payload bound, when it declares one. + let estimated_item_value_size = index_only_item_estimated_value_size( + document_and_contract_info.document_type, + platform_version, + )?; + + // The `0` storage-marker tree, byte-identical in position to the + // non-unique layout above. + let key_path_info = KeyRef(&[0]); + let path_key_info = key_path_info.add_path_info(index_path_info.clone()); + + let apply_type = if estimated_costs_only_with_layer_info.is_none() { + BatchInsertTreeApplyType::StatefulBatchInsertTree + } else { + BatchInsertTreeApplyType::StatelessBatchInsertTree { + // The `0` tree's parent is the index's value tree, which + // aggregates whenever the index counts or sums — claiming + // `NormalTree` here under-estimates the parent's per-child + // aggregate bytes, and a time-range index's bucket fan-out + // multiplies the gap past the item-size padding (the + // `estimated_fees_upper_bound_actual_fees` e2e tests pin + // the invariant). + in_tree_type: + crate::drive::document::index_level_tree_types::terminal_value_tree_type( + index_type, + ), + tree_type: member_tree_type, + flags_len: storage_flags + .map(|s| s.serialized_size()) + .unwrap_or_default(), + } + }; + + self.batch_insert_empty_tree_if_not_exists( + path_key_info, + member_tree_type, + *storage_flags, + apply_type, + transaction, + previous_batch_operations, + batch_operations, + drive_version, + )?; + + index_path_info.push(Key(vec![0]))?; + + // The payload is the 32-byte row commitment; the estimated per-item + // value size is padded above it because the estimation layers + // under-count each entry's chain (the serialized item envelope — + // enum tag, length prefix, flags option — plus the per-entry share + // of parent-tree aggregate bytes), and estimation must UPPER-bound + // the applied fee. The padding is per entry, so it scales with a + // time-range index's bucket fan-out (one entry chain per bucket), + // where the original 16-byte pad measurably under-ran — the + // `estimated_fees_upper_bound_actual_fees` e2e tests (like / tip / + // beat) pin the invariant across the plain, summable and bucketed + // shapes. + // Sum-bearing entries additionally carry the i64 sum item in the + // element envelope; 10 bytes is the worst case the sum-aware space + // helpers reserve. + let estimated_value_size = if sum_property_name.is_some() { + estimated_item_value_size + 10 + } else { + estimated_item_value_size + }; + + let item_space = if sum_property_name.is_some() { + Element::required_item_with_sum_item_space( + estimated_item_value_size, + STORAGE_FLAGS_SIZE, + &drive_version.grove_version, + )? + } else { + Element::required_item_space( + estimated_item_value_size, + STORAGE_FLAGS_SIZE, + &drive_version.grove_version, + )? + }; + + if let Some(estimated_costs_only_with_layer_info) = estimated_costs_only_with_layer_info { + estimated_costs_only_with_layer_info.insert( + index_path_info.clone().convert_to_key_info_path(), + EstimatedLayerInformation { + tree_type: member_tree_type, + estimated_layer_count: PotentiallyAtMaxElements, + estimated_layer_sizes: AllItems( + member_key_max_size, + estimated_value_size, + storage_flags.map(|s| s.serialized_size()), + ), + }, + ); + } + + // Member key: the terminal property's value in its tree-key + // encoding — the same bytes a prefix level would key by. + let member_key: Option> = match document_and_contract_info + .owned_document_info + .document_info + .get_borrowed_document_and_storage_flags() + { + Some((document, _)) => Some(index_only_member_key( + document, + document_and_contract_info.document_type, + terminal, + document_and_contract_info.owned_document_info.owner_id, + platform_version, + )?), + // Estimation-only document info carries no values. + None => None, + }; + + // The applied element carries the 32-byte row commitment binding + // this entry to the document's full value tuple (see + // `index_only_row_commitment`); the dry run pads to the estimated + // size, which keeps the estimate above the applied fee across the + // indexed-tree layers' documented under-count (see + // `estimated_sum_trees_for_value_tree_type`). + // + // Each entry's commitment is a double-SHA256 over the document's + // values, a typed array's whole list included (protocol version 14), + // billed here by its preimage; the dry run bills the widest preimage + // the type allows, which upper-bounds it. + let item_value = if estimated_costs_only_with_layer_info.is_some() { + batch_operations.push(FunctionOperation(FunctionOp::new_with_byte_count( + HashFunction::Sha256_2, + index_only_row_commitment_max_preimage_size( + document_and_contract_info.document_type, + platform_version, + ), + ))); + vec![0u8; estimated_item_value_size as usize] + } else { + let (document, _) = document_and_contract_info + .owned_document_info + .document_info + .get_borrowed_document_and_storage_flags() + .ok_or(Error::Drive(DriveError::CorruptedCodeExecution( + "indexOnly terminal insert needs a document outside estimation mode", + )))?; + // The commitment first, then the type's entry payload (empty + // without an `entryPayload` declaration). + let (commitment, preimage_size) = index_only_row_commitment_with_preimage_size( + document, + document_and_contract_info.document_type, + platform_version, + )?; + batch_operations.push(FunctionOperation(FunctionOp::new_with_byte_count( + HashFunction::Sha256_2, + preimage_size, + ))); + let mut item_value = commitment.to_vec(); + item_value.extend(encode_index_only_entry_payload( + document, + document_and_contract_info.document_type, + )?); + item_value + }; + + let key_element_info = match &member_key { + Some(member_key) => { + let element_flags = StorageFlags::map_to_some_element_flags(*storage_flags); + let item = match sum_property_name { + Some(prop_name) => { + let (document, _) = document_and_contract_info + .owned_document_info + .document_info + .get_borrowed_document_and_storage_flags() + .ok_or(Error::Drive(DriveError::CorruptedCodeExecution( + "indexOnly summable terminal insert needs a document to read \ + the sum contribution from", + )))?; + let sum_value = read_document_sum_contribution(document, prop_name)?; + Element::new_item_with_sum_item_with_flags( + item_value, + sum_value, + element_flags, + ) + } + None => Element::new_item_with_flags(item_value, element_flags), + }; + KeyElement((member_key.as_slice(), item)) + } + None => KeyUnknownElementSize(( + KeyInfo::MaxKeySize { + unique_id: document_and_contract_info + .document_type + .unique_id_for_storage() + .to_vec(), + max_size: member_key_max_size, + }, + item_space, + )), + }; + + let path_key_element_info = + PathKeyElementInfo::from_path_info_and_key_element(index_path_info, key_element_info)?; + + let apply_type = if estimated_costs_only_with_layer_info.is_none() { + BatchInsertApplyType::StatefulBatchInsert + } else { + BatchInsertApplyType::StatelessBatchInsert { + in_tree_type: member_tree_type, + target: QueryTargetValue( + estimated_value_size + + storage_flags + .map(|s| s.serialized_size()) + .unwrap_or_default(), + ), + } + }; + + // An index whose entries outlive a delete may hold the entry of a + // deleted document with the same key (registration makes sure no + // document in state shares it): the create writes over it, so the + // entry carries the commitment of the row writing it, and the count + // does not move. Nothing is read. + if index_type.outlives_delete { + return self.batch_insert(path_key_element_info, batch_operations, drive_version); + } + let inserted = self.batch_insert_if_not_exists( + path_key_element_info, + apply_type, + transaction, + batch_operations, + drive_version, + )?; + // Every other index's collision was refused by state validation. + if !inserted { + return Err(Error::Drive(DriveError::CorruptedContractIndexes( + "index-only entry already exists: state validation must reject a create \ + whose entries collide before it reaches storage" + .to_string(), + ))); + } + + Ok(()) + } +} diff --git a/packages/rs-drive/src/drive/document/layout.rs b/packages/rs-drive/src/drive/document/layout.rs index 8660f7d388f..11ce98456be 100644 --- a/packages/rs-drive/src/drive/document/layout.rs +++ b/packages/rs-drive/src/drive/document/layout.rs @@ -24,12 +24,14 @@ use crate::drive::document::index_level_tree_types::{ continuation_contributes_zero, index_level_tree_types_with_continuation_demotion, terminal_member_tree_type, zero_contribution_wrapper, }; +use crate::drive::document::paths::DOCUMENT_HISTORY_TREE_KEY; use crate::drive::document::primary_key_tree_type::DocumentTypePrimaryKeyTreeType; use crate::drive::document::private_document_store::{ private_document_store_chunk_power, private_document_stored_entry_size, PRIVATE_DOCUMENT_ENTRY_HEADER_SIZE, PRIVATE_DOCUMENT_STORE_KEY, }; use crate::drive::document::sdk_value::{map, number, text, texts}; +use crate::drive::document::uses_current_document_history_layout; use crate::error::drive::DriveError; use crate::error::Error; use dpp::data_contract::document_type::accessors::{DocumentTypeV0Getters, DocumentTypeV2Getters}; @@ -96,6 +98,8 @@ pub enum LayoutKey { /// One key per stored revision: the block time of the revision in /// milliseconds, a u64 big endian with the sign bit flipped. RevisionTime, + /// The unsigned block time followed by the revision, both u64 big endian. + RevisionTimeAndRevision, /// One key per distinct value of `property` among the documents, /// serialized for ordering; an absent or null value is the empty key. PropertyValue { @@ -148,6 +152,12 @@ pub enum LayoutRole { LatestRevision, /// One stored revision of a document with history. Revision, + /// All retained histories of a document type (`[2]`). + History, + /// One document's count-bound retained history. + DocumentHistory, + /// One immutable revision in a document's retained history. + RetainedRevision, /// The first property of an index, or the level of a flat indexOnly /// index. IndexProperty, @@ -177,6 +187,13 @@ impl LayoutRole { LayoutRole::Revision => { "contracts.contract.documents.document_type.primary_key.document.revision" } + LayoutRole::History => "contracts.contract.documents.document_type.history", + LayoutRole::DocumentHistory => { + "contracts.contract.documents.document_type.history.document" + } + LayoutRole::RetainedRevision => { + "contracts.contract.documents.document_type.history.document.revision" + } LayoutRole::IndexProperty => { "contracts.contract.documents.document_type.index_property" } @@ -203,6 +220,9 @@ impl LayoutRole { LayoutRole::Document => "document", LayoutRole::LatestRevision => "latestRevision", LayoutRole::Revision => "revision", + LayoutRole::History => "history", + LayoutRole::DocumentHistory => "documentHistory", + LayoutRole::RetainedRevision => "retainedRevision", LayoutRole::IndexProperty => "indexProperty", LayoutRole::IndexValue => "indexValue", LayoutRole::NextIndexProperty => "nextIndexProperty", @@ -491,6 +511,11 @@ pub fn document_type_layout( )?); } else if !document_type.index_only() { children.push(primary_key_node(document_type, platform_version)?); + if document_type.documents_keep_history() + && uses_current_document_history_layout(platform_version)? + { + children.push(history_node()); + } } for (level_key, level) in document_type.index_structure().sub_levels() { @@ -569,6 +594,30 @@ pub(crate) fn index_ending_at( .collect() } +fn history_node() -> LayoutNode { + LayoutNode { + key: fixed(vec![DOCUMENT_HISTORY_TREE_KEY], "History"), + role: LayoutRole::History, + element: tree(TreeType::NormalTree), + alternative: None, + indexes: vec![], + notes: vec![], + children: vec![LayoutNode { + key: LayoutKey::DocumentId, + role: LayoutRole::DocumentHistory, + element: tree(TreeType::ProvableCountTree), + alternative: None, + indexes: vec![], + notes: vec![], + children: vec![leaf( + LayoutKey::RevisionTimeAndRevision, + LayoutRole::RetainedRevision, + element(LayoutElementKind::Item), + )], + }], + } +} + /// A private type's store at `[0]`, in place of the primary-key tree, sized as /// the store's creation sizes it. Its entries are not keys under it, so the /// node has no children. @@ -598,7 +647,14 @@ fn primary_key_node( platform_version: &PlatformVersion, ) -> Result { let summable = document_type.documents_summable().is_some(); - let document = if document_type.documents_keep_history() { + let current_history_layout = uses_current_document_history_layout(platform_version)?; + let document = if document_type.documents_keep_history() && current_history_layout { + leaf( + LayoutKey::DocumentId, + LayoutRole::Document, + reference(summable), + ) + } else if document_type.documents_keep_history() { LayoutNode { key: LayoutKey::DocumentId, role: LayoutRole::Document, @@ -1007,6 +1063,9 @@ impl LayoutKey { ]), LayoutKey::DocumentId => map(vec![("kind", text("documentId"))]), LayoutKey::RevisionTime => map(vec![("kind", text("revisionTime"))]), + LayoutKey::RevisionTimeAndRevision => { + map(vec![("kind", text("revisionTimeAndRevision"))]) + } LayoutKey::PropertyValue { property } => map(vec![ ("kind", text("propertyValue")), ("property", text(property)), @@ -1118,10 +1177,10 @@ mod tests { }; use crate::drive::{Drive, RootTree}; use crate::structure::{drive_structure, ElementKind, StructureNode}; - use crate::util::test_helpers::setup::{ - setup_document, setup_drive_with_initial_state_structure, - }; + use crate::util::object_size_info::{DocumentAndContractInfo, DocumentInfo, OwnedDocumentInfo}; + use crate::util::test_helpers::setup::setup_drive_with_initial_state_structure; use crate::util::test_helpers::setup_contract; + use dpp::block::block_info::BlockInfo; use dpp::data_contract::accessors::v0::DataContractV0Getters; use dpp::data_contract::conversion::value::v0::DataContractValueConversionMethodsV0; use dpp::data_contract::document_type::random_document::CreateRandomDocument; @@ -1308,8 +1367,12 @@ mod tests { } } - fn apply(drive: &Drive, index: usize, path: &str) -> DataContract { - let platform_version = PlatformVersion::latest(); + fn apply( + drive: &Drive, + index: usize, + path: &str, + platform_version: &PlatformVersion, + ) -> DataContract { let contract = setup_contract( drive, path, @@ -1338,7 +1401,23 @@ mod tests { seed == 6, ); } - setup_document(drive, &document, &contract, document_type.as_ref(), None); + drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentInfo::DocumentRefInfo((&document, None)), + owner_id: None, + }, + contract: &contract, + document_type: document_type.as_ref(), + }, + false, + BlockInfo::default(), + true, + None, + platform_version, + ) + .expect("insert fixture document"); } } contract @@ -1351,7 +1430,7 @@ mod tests { let mut walk = Walk::default(); for (index, path) in CONTRACTS.into_iter().enumerate() { - let contract = apply(&drive, index, path); + let contract = apply(&drive, index, path, platform_version); let documents_path = vec![ vec![RootTree::DataContractDocuments as u8], contract.id().to_vec(), @@ -1373,8 +1452,9 @@ mod tests { for role in [ "primaryKey", "document", - "latestRevision", - "revision", + "history", + "documentHistory", + "retainedRevision", "indexProperty", "indexValue", "nextIndexProperty", @@ -1415,6 +1495,9 @@ mod tests { LayoutRole::Document, LayoutRole::LatestRevision, LayoutRole::Revision, + LayoutRole::History, + LayoutRole::DocumentHistory, + LayoutRole::RetainedRevision, LayoutRole::IndexProperty, LayoutRole::IndexValue, LayoutRole::NextIndexProperty, @@ -1433,7 +1516,7 @@ mod tests { fn should_skip_only_an_optional_property_of_an_index_only_type_when_absent() { let platform_version = PlatformVersion::latest(); let drive = setup_drive_with_initial_state_structure(Some(platform_version)); - let contract = apply(&drive, 0, CONTRACTS[9]); + let contract = apply(&drive, 0, CONTRACTS[9], platform_version); let mark = contract.document_type_for_name("mark").expect("mark"); let layout = document_type_layout(mark, platform_version).expect("layout"); let skipped = |label: &str| { @@ -1463,9 +1546,9 @@ mod tests { #[test] fn should_store_each_document_of_a_type_with_history_as_a_tree_of_revisions() { - let platform_version = PlatformVersion::latest(); + let platform_version = PlatformVersion::get(14).expect("protocol 14"); let drive = setup_drive_with_initial_state_structure(Some(platform_version)); - let contract = apply(&drive, 0, CONTRACTS[3]); + let contract = apply(&drive, 0, CONTRACTS[3], platform_version); let person = contract.document_type_for_name("person").expect("person"); let layout = document_type_layout(person, platform_version).expect("layout"); @@ -1480,6 +1563,75 @@ mod tests { document.children.iter().map(|c| c.role).collect::>(), vec![LayoutRole::LatestRevision, LayoutRole::Revision] ); + let mut walk = Walk::default(); + walk.layer( + &drive, + vec![ + vec![RootTree::DataContractDocuments as u8], + contract.id().to_vec(), + vec![1], + b"person".to_vec(), + ], + &layout.root, + ); + assert!( + walk.mismatches.is_empty(), + "legacy layout differs from stored state: {:?}", + walk.mismatches + ); + } + + #[test] + fn should_reject_an_unknown_history_layout_instead_of_describing_legacy_history() { + let platform_version = PlatformVersion::latest(); + let drive = setup_drive_with_initial_state_structure(Some(platform_version)); + let contract = apply(&drive, 0, CONTRACTS[3], platform_version); + let person = contract.document_type_for_name("person").expect("person"); + let mut unknown = platform_version.clone(); + unknown + .drive + .methods + .document + .document_history_storage_layout = 2; + assert!(matches!( + document_type_layout(person, &unknown), + Err(Error::Drive(DriveError::UnknownVersionMismatch { + received: 2, + .. + })) + )); + } + + #[test] + fn should_describe_current_history_pointers_and_separate_retained_revisions() { + let platform_version = PlatformVersion::latest(); + let drive = setup_drive_with_initial_state_structure(Some(platform_version)); + let contract = apply(&drive, 0, CONTRACTS[3], platform_version); + let person = contract.document_type_for_name("person").expect("person"); + let layout = document_type_layout(person, platform_version).expect("layout"); + let primary = &layout.root.children[0]; + assert_eq!( + primary.children[0].element.kind, + LayoutElementKind::Reference + ); + let history = layout + .root + .children + .iter() + .find(|child| matches!(&child.key, LayoutKey::Fixed { bytes, .. } if bytes == &[2])) + .expect("per-type history root"); + assert_eq!( + history.children[0].element.kind, + LayoutElementKind::Tree(TreeType::ProvableCountTree) + ); + assert_eq!( + history.children[0].children[0].element.kind, + LayoutElementKind::Item + ); + assert_eq!( + history.children[0].children[0].key, + LayoutKey::RevisionTimeAndRevision + ); } /// A private type (protocol version 15) keeps a private document store at @@ -1568,7 +1720,7 @@ mod tests { fn should_refuse_a_version_that_selects_other_index_walkers() { let platform_version = PlatformVersion::latest(); let drive = setup_drive_with_initial_state_structure(Some(platform_version)); - let contract = apply(&drive, 0, CONTRACTS[0]); + let contract = apply(&drive, 0, CONTRACTS[0], platform_version); let person = contract.document_type_for_name("person").expect("person"); let version_13 = PlatformVersion::get(13).expect("protocol version 13"); assert!(matches!( diff --git a/packages/rs-drive/src/drive/document/migration/index_tests.rs b/packages/rs-drive/src/drive/document/migration/index_tests.rs new file mode 100644 index 00000000000..ac6736cb57f --- /dev/null +++ b/packages/rs-drive/src/drive/document/migration/index_tests.rs @@ -0,0 +1,466 @@ +use super::*; +use crate::config::DriveConfig; +use crate::drive::credit_pools::epochs::operations_factory::EpochOperations; +use crate::drive::document::query::QueryDocumentsOutcomeV0Methods; +use crate::query::document_history_drive_query::{ + DocumentHistoryDriveQuery, DocumentHistoryFilter, +}; +use crate::query::{resolve_integer_range_bucket_clause, DriveDocumentQuery}; +use crate::util::batch::grovedb_op_batch::GroveDbOpBatchV0Methods; +use crate::util::batch::GroveDbOpBatch; +use crate::util::object_size_info::{DocumentAndContractInfo, DocumentInfo, OwnedDocumentInfo}; +use dpp::block::block_info::BlockInfo; +use dpp::block::epoch::Epoch; +use dpp::data_contract::DataContractFactory; +use dpp::document::document_factory::DocumentFactory; +use dpp::document::DocumentV0Setters; +use dpp::platform_value::{platform_value, Value}; +use std::borrow::Cow; + +#[test] +fn should_read_and_prove_fresh_and_migrated_history_through_every_index_kind() { + for countable in [false, true] { + read_and_prove_index_matrix(countable); + } +} + +fn read_and_prove_index_matrix(countable: bool) { + let new = PlatformVersion::get(15).unwrap(); + for migrated in [false, true] { + let old = PlatformVersion::get(if migrated { 14 } else { 15 }).unwrap(); + let directory = tempfile::TempDir::new().unwrap(); + let (drive, _) = Drive::open(directory.path(), None).unwrap(); + drive.create_initial_state_structure(None, old).unwrap(); + // Refund pricing reads the protocol versions of the epochs in the storage flags. + let mut epoch_versions = GroveDbOpBatch::new(); + for index in [2, 3] { + epoch_versions.push( + Epoch::new(index) + .unwrap() + .update_protocol_version_operation(old.protocol_version), + ); + } + drive + .grove_apply_batch(epoch_versions, false, None, &old.drive) + .unwrap(); + let schemas = platform_value!({ + "tip": { + "type":"object", "documentsKeepHistory":true, "documentsMutable":true, "canBeDeleted":false, + "documentsCountable":countable, "documentsSummable":"amount", + "immutable":["postId"], + "properties": { + "slug":{"type":"string", "maxLength":10, "position":0}, + "group":{"type":"string", "maxLength":10, "position":1}, + "recipient":{"type":"string", "maxLength":10, "position":2}, + "amount":{"type":"integer", "minimum":0, "maximum":4294967295i64, "position":3}, + "tags":{"type":"array", "maxItems":4, "items":{"type":"string", "minLength":1, "maxLength":10}, "position":4}, + "optional":{"type":"integer", "minimum":0, "maximum":9, "position":5}, + "postId":{"type":"array", "byteArray":true, "minItems":32, "maxItems":32, + "contentMediaType":"application/x.dash.dpp.identifier", + "refersTo":{"type":"permanentDocument", "documentType":"source"}, "position":6} + }, + "required":["slug","group","recipient","amount","tags","postId","$createdAt"], "additionalProperties":false, + "indices":[ + {"name":"slug","properties":[{"slug":"asc"}],"unique":true}, + {"name":"groupAggregate","properties":[{"group":"asc"}],"countable":"countable","summable":"amount"}, + {"name":"groupAmount","properties":[{"group":"asc"},{"amount":"asc"}]}, + {"name":"recipientAmount","properties":[{"recipient":"asc"},{"amount":"asc"}],"countable":"countable","rangeCountable":true,"rankedCountable":{"at":"recipient"}}, + {"name":"recipientSlugAmount","properties":[{"recipient":"asc"},{"slug":"asc"},{"amount":"asc"}]}, + {"name":"trending","properties":[{"$createdAt":"asc"},{"group":"asc"},{"slug":"asc"}],"countable":"countable","timeRange":{"on":"$createdAt","range":3600,"step":900}}, + {"name":"byTag","properties":[{"tags":"asc"}],"countable":"countable","rangeCountable":true,"rankedCountable":true}, + {"name":"byBand","properties":[{"amount":"asc"},{"slug":"asc"}],"countable":"countable","integerRange":{"on":"amount","range":30,"step":10}}, + {"name":"sparse","properties":[{"group":"asc"},{"optional":"asc"}],"skipIfAbsent":["optional"]}, + {"name":"byTopic","properties":[{"postId.topic":"asc"}]} + ] + }, + "winner": { + "type":"object", "documentsMutable":false, "canBeDeleted":false, "documentsKeepHistory":true, + "properties":{"code":{"type":"string", "maxLength":10, "position":0}}, + "required":["code"], "additionalProperties":false, + "indices":[{"name":"byCode", "properties":[{"code":"asc"}], "unique":true, "contested":{"resolution":1}}] + }, + "source": { + "type":"object", "documentsMutable":false, "canBeDeleted":false, + "properties":{"topic":{"type":"string", "maxLength":10, "position":0}}, + "required":["topic"], "additionalProperties":false + } + }); + let contract = DataContractFactory::new(old.protocol_version) + .unwrap() + .create_with_value_config([7; 32].into(), 0, schemas, None, None) + .unwrap() + .data_contract_owned(); + let contract_flags = StorageFlags::new_single_epoch(2, Some([55; 32])); + drive + .apply_contract( + &contract, + BlockInfo::default(), + true, + Some(Cow::Borrowed(&contract_flags)), + None, + old, + ) + .unwrap(); + let document_type = contract.document_type_for_name("tip").unwrap(); + let writer_flags = StorageFlags::new_single_epoch(3, Some([99; 32])); + let insert = |document: &Document, name: &str| { + drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentInfo::DocumentRefInfo(( + document, + Some(Cow::Borrowed(&writer_flags)), + )), + owner_id: None, + }, + contract: &contract, + document_type: contract.document_type_for_name(name).unwrap(), + }, + false, + BlockInfo::default_with_time(1000), + true, + None, + old, + ) + .unwrap(); + }; + let mut source = DocumentFactory::new(old.protocol_version) + .unwrap() + .create_document( + &contract, + [7; 32].into(), + "source".into(), + platform_value!({"topic":"history"}), + ) + .unwrap(); + source.set_id([4; 32].into()); + insert(&source, "source"); + let mut winner = DocumentFactory::new(old.protocol_version) + .unwrap() + .create_document( + &contract, + [7; 32].into(), + "winner".into(), + platform_value!({"code":"winner"}), + ) + .unwrap(); + winner.set_id([5; 32].into()); + insert(&winner, "winner"); + let mut documents = vec![]; + for (id, slug, amount) in [(8u8, "a", 10u32), (9, "b", 20)] { + let mut document = DocumentFactory::new(old.protocol_version) + .unwrap() + .create_document( + &contract, + [7; 32].into(), + "tip".into(), + platform_value!({"slug":slug,"group":"all","recipient":"bob","amount":amount, + "tags":["shared",slug],"postId":Value::Identifier([4;32])}), + ) + .unwrap(); + document.set_id([id; 32].into()); + document.set_revision(Some(1)); + document.set_created_at(Some(7_200_000)); + if id == 8 { + document.set("optional", 1u8.into()); + } + insert(&document, "tip"); + documents.push(document); + } + let original = documents[0].clone(); + documents[0].set_revision(Some(2)); + documents[0].set("amount", 40u32.into()); + documents[0].set("tags", platform_value!(["shared", "new"])); + drive + .update_document_for_contract( + &documents[0], + &contract, + document_type, + Some([7; 32]), + BlockInfo::default_with_time(2000), + true, + Some(Cow::Borrowed(&writer_flags)), + None, + old, + ) + .unwrap(); + let type_path = contract_document_type_path_vec(contract.id().as_slice(), "tip"); + let transaction = drive.grove.start_transaction(); + let mut stats = DocumentHistoryMigrationStats::default(); + let mut before = BTreeMap::new(); + for name in document_type.index_structure().sub_levels().keys() { + let mut path = type_path.clone(); + path.push(name.as_bytes().to_vec()); + drive + .history_migration_index_entries(path, &transaction, &mut stats, &mut before, old) + .unwrap(); + } + // Per document: five plain references, four time windows, two array + // elements, three integer buckets and one derived topic; only the + // first document contributes to the sparse optional index. + let expected_index_entries = 2 * (5 + 4 + 2 + 3 + 1) + 1; + assert_eq!( + before.values().map(Vec::len).sum::() as u64, + expected_index_entries + ); + assert_eq!(stats.index_entries, expected_index_entries); + if migrated { + let stats = drive + .migrate_document_history_storage(&transaction, new) + .unwrap(); + assert_eq!(stats.documents, 3); + assert_eq!(stats.index_entries, expected_index_entries + 1); + assert_eq!(stats.rewritten_index_entries, expected_index_entries + 1); + } + drive.grove.commit_transaction(transaction).value.unwrap(); + drop(drive); + let (drive, _) = Drive::open(directory.path(), None).unwrap(); + for (name, document) in documents + .iter() + .map(|document| ("tip", document)) + .chain(std::iter::once(("winner", &winner))) + { + let document_type = contract.document_type_for_name(name).unwrap(); + let query = DocumentHistoryDriveQuery { + contract_id: contract.id().to_buffer(), + document_type_name: name.into(), + document_id: document.id().to_buffer(), + filter: DocumentHistoryFilter::StartAtTime(0), + limit: None, + }; + let page = drive + .fetch_document_history(&query, document_type, None, new) + .unwrap(); + let expected = if document.id() == original.id() { + vec![original.clone(), document.clone()] + } else { + vec![document.clone()] + }; + assert_eq!( + page.entries + .iter() + .map(|entry| entry.document.clone()) + .collect::>(), + expected + ); + assert_eq!( + page.lifecycle.as_ref().unwrap().remaining_revisions, + expected.len() as u64 + ); + let proof = drive + .prove_document_history(&query, document_type, None, new) + .unwrap(); + assert_eq!( + Drive::verify_document_history(&query, &proof, document_type, new) + .unwrap() + .1, + page + ); + } + for (document_id, references) in &before { + for (path, key, original) in references { + let current = drive + .grove + .get_raw(path.as_slice().into(), key, None, &new.drive.grove_version) + .value + .unwrap(); + assert_eq!(current.get_flags(), original.get_flags()); + match (¤t, original) { + ( + Element::Reference(UpstreamRootHeightReference(4, target), Some(2), _), + Element::Reference(..), + ) => assert_eq!(target, &vec![vec![0], document_id.clone()]), + ( + Element::ReferenceWithSumItem( + UpstreamRootHeightReference(4, target), + Some(2), + sum, + _, + ), + Element::ReferenceWithSumItem(_, _, previous_sum, _), + ) => { + assert_eq!(target, &vec![vec![0], document_id.clone()]); + assert_eq!(sum, previous_sum); + } + _ => panic!("unexpected index reference: {current:?}"), + } + } + } + for (sql, expected) in [ + ( + "select * from tip where slug = 'a'", + vec![documents[0].clone()], + ), + ("select * from tip where group = 'all'", documents.clone()), + ( + "select * from tip where group = 'all' and amount > 30 order by amount asc", + vec![documents[0].clone()], + ), + ( + "select * from tip where recipient = 'bob'", + documents.clone(), + ), + ( + "select * from tip where recipient = 'bob' and amount < 30 order by amount asc", + vec![documents[1].clone()], + ), + ( + "select * from tip where recipient = 'bob' and slug = 'a'", + vec![documents[0].clone()], + ), + ( + "select * from tip where group = 'all' and optional = 1", + vec![documents[0].clone()], + ), + ( + "select * from tip where group = 'all' and optional = 2", + vec![], + ), + ] { + let query = DriveDocumentQuery::from_sql_expr(sql, &contract, None, new).unwrap(); + let mut fetched = drive + .query_documents(query.clone(), None, false, None, Some(15)) + .unwrap() + .documents() + .to_vec(); + let (proof, _) = query + .clone() + .execute_with_proof(&drive, None, None, new) + .unwrap(); + let (_, mut verified) = query.verify_proof(&proof, new).unwrap(); + fetched.sort_by_key(|doc| doc.id()); + verified.sort_by_key(|doc| doc.id()); + assert_eq!(fetched, expected, "{sql}, migrated={migrated}"); + assert_eq!(verified, expected, "{sql}, migrated={migrated}"); + } + let mut new_queries = vec![( + DriveDocumentQuery::from_sql_expr( + "select * from winner where code = 'winner'", + &contract, + None, + new, + ) + .unwrap(), + vec![winner.clone()], + )]; + new_queries.push(( + DriveDocumentQuery::from_value( + platform_value!({"where":[["postId.topic","==","history"]]}), + &contract, + document_type, + &DriveConfig::default(), + new, + ) + .unwrap(), + documents.clone(), + )); + for (tag, expected) in [ + ("shared", documents.clone()), + ("new", vec![documents[0].clone()]), + ("a", vec![]), + ] { + new_queries.push(( + DriveDocumentQuery::from_value( + platform_value!({"where":[["tags","contains",tag]]}), + &contract, + document_type, + &DriveConfig::default(), + new, + ) + .unwrap(), + expected, + )); + } + for (start, expected) in [ + (30u64, vec![documents[0].clone()]), + (0, vec![documents[1].clone()]), + ] { + let (clause, resolved) = resolve_integer_range_bucket_clause( + "amount", + &Value::U64(start), + None, + document_type, + ) + .unwrap(); + let mut query = DriveDocumentQuery::from_value( + Value::Map(vec![]), + &contract, + document_type, + &DriveConfig::default(), + new, + ) + .unwrap(); + query + .internal_clauses + .equal_clauses + .insert(clause.field.clone(), clause); + query.resolved_time_ranges = vec![resolved]; + new_queries.push((query, expected)); + } + for (query, expected) in new_queries { + let mut fetched = drive + .query_documents(query.clone(), None, false, None, Some(15)) + .unwrap() + .documents() + .to_vec(); + let (proof, _) = query + .clone() + .execute_with_proof(&drive, None, None, new) + .unwrap(); + let (_, mut verified) = query.verify_proof(&proof, new).unwrap(); + fetched.sort_by_key(|doc| doc.id()); + verified.sort_by_key(|doc| doc.id()); + assert_eq!(fetched, expected, "migrated={migrated}"); + assert_eq!(verified, expected, "migrated={migrated}"); + } + let primary = drive + .grove + .get_raw( + type_path.as_slice().into(), + &[0], + None, + &new.drive.grove_version, + ) + .value + .unwrap(); + if countable { + assert!( + matches!(primary, Element::CountSumTree(_, 2, 60, _)), + "{primary:?}" + ); + } else { + assert!(matches!(primary, Element::SumTree(_, 60, _)), "{primary:?}"); + } + // Aggregates survive migration: the count-sum value tree of the + // shared-prefix index keeps both documents and their amounts, and the + // count tree of the ranked index keeps its document count. + let value_tree = |index: &[u8]| { + let mut path = type_path.clone(); + path.push(index.to_vec()); + let values = drive + .history_migration_entries(&path, &drive.grove.start_transaction(), new) + .unwrap(); + assert_eq!(values.len(), 1, "{values:?}"); + values.into_iter().next().unwrap().1 + }; + let group = value_tree(b"group"); + assert!( + matches!(group, Element::CountSumTree(_, 2, 60, _)), + "{group:?}" + ); + let recipient = value_tree(b"recipient"); + assert!( + matches!(recipient, Element::CountTree(_, 2, _)), + "{recipient:?}" + ); + // The time-range index keeps its four windows, each still a tree. + let mut path = type_path.clone(); + path.push(b"$createdAt#3600#900".to_vec()); + let windows = drive + .history_migration_entries(&path, &drive.grove.start_transaction(), new) + .unwrap(); + assert_eq!(windows.len(), 4, "{windows:?}"); + assert!(windows.iter().all(|(_, element)| element.is_any_tree())); + } +} diff --git a/packages/rs-drive/src/drive/document/migration/mod.rs b/packages/rs-drive/src/drive/document/migration/mod.rs new file mode 100644 index 00000000000..2b70d443f5b --- /dev/null +++ b/packages/rs-drive/src/drive/document/migration/mod.rs @@ -0,0 +1,557 @@ +//! Activation migration of persisted document histories. +//! +//! Any error deliberately halts the activation block for every validator. All +//! batches belong to the activation transaction; no partial migration may commit. +//! Every `corrupt()` path is unreachable for valid pre-15 state: legacy writers +//! and contract-update validation preserve the storage invariants checked here. + +use crate::drive::document::paths::{contract_document_type_path_vec, DOCUMENT_HISTORY_TREE_KEY}; +use crate::drive::document::uses_current_document_history_layout; +use crate::drive::Drive; +use crate::error::{drive::DriveError, Error}; +use crate::query::QueryResultType; +use crate::util::common::encode::encode_u64; +use crate::util::storage_flags::StorageFlags; +use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters; +use dpp::data_contract::document_type::DocumentPropertyType; +use dpp::document::serialization_traits::DocumentPlatformConversionMethodsV0; +use dpp::document::{Document, DocumentV0Getters}; +use dpp::version::PlatformVersion; +use grovedb::batch::{QualifiedGroveDbOp, SubelementsDeletionBehavior}; +use grovedb::reference_path::ReferencePathType::{SiblingReference, UpstreamRootHeightReference}; +use grovedb::{Element, PathQuery, Query, SizedQuery, Transaction, TreeType}; +use std::collections::BTreeMap; + +/// Inventory and measured GroveDB work for a history-layout migration. +#[derive(Debug, Default)] +pub struct DocumentHistoryMigrationStats { + /// All contracts inspected, including contracts with no documents. + pub contracts: u64, + /// History-keeping document types, including empty types. + pub types: u64, + /// Current documents inspected. + pub documents: u64, + /// Retained revision items inspected. + pub revisions: u64, + /// Serialized revision payload bytes. + pub revision_bytes: u64, + /// Maximum retained revisions in one document. + pub maximum_document_revisions: u64, + /// Document index references inspected. + pub index_entries: u64, + /// Index references successfully rewritten. + pub rewritten_index_entries: u64, + /// Largest index-reference count retained for one document type. + pub maximum_type_index_entries: u64, + /// Conservative owned-buffer bound for one type index inventory, excluding allocator overhead. + pub maximum_type_index_buffer_bound: u64, + /// Documents changed by this invocation. + pub migrated_documents: u64, + /// Applied batches, excluding reads. + pub batches: u64, +} + +type IndexReference = (Vec>, Vec, Element); +type IndexEntries = BTreeMap, Vec>; + +#[cfg(test)] +mod index_tests; +#[cfg(test)] +mod tests; + +fn corrupt(message: impl Into) -> Error { + Error::Drive(DriveError::CorruptedDriveState(message.into())) +} + +fn index_inventory_buffer_bound(entries: &IndexEntries) -> u64 { + // A B-tree node stores at most eleven key/value pairs and twelve child edges. + // Reserving two KiB per key plus the root bounds its inline node storage. + let mut bytes = 2048 * (entries.len() as u64 + 1); + for (id, references) in entries { + bytes += id.capacity() as u64; + bytes += (references.capacity() * std::mem::size_of::<(Vec>, Vec, Element)>()) + as u64; + for (path, key, element) in references { + bytes += (path.capacity() * std::mem::size_of::>()) as u64; + bytes += path.iter().map(|part| part.capacity() as u64).sum::(); + bytes += key.capacity() as u64; + if let Element::Reference(UpstreamRootHeightReference(_, target), _, flags) + | Element::ReferenceWithSumItem( + UpstreamRootHeightReference(_, target), + _, + _, + flags, + ) = element + { + bytes += (target.capacity() * std::mem::size_of::>()) as u64; + bytes += target + .iter() + .map(|part| part.capacity() as u64) + .sum::(); + bytes += flags.as_ref().map_or(0, |flags| flags.capacity() as u64); + } + } + } + bytes +} + +impl Drive { + /// Moves timestamp-keyed document histories out of primary storage. + /// The caller owns the transaction and must roll it back on any error. + pub fn migrate_document_history_storage( + &self, + transaction: &Transaction, + platform_version: &PlatformVersion, + ) -> Result { + if !uses_current_document_history_layout(platform_version)? { + return Err(corrupt( + "document history migration requires the composite-key layout", + )); + } + let mut stats = DocumentHistoryMigrationStats::default(); + let mut cursor: Option<[u8; 32]> = None; + loop { + let ids = self.fetch_contract_ids( + cursor.map(|id| (id, false)), + u16::MAX, + Some(transaction), + platform_version, + )?; + if ids.is_empty() { + break; + } + cursor = ids.last().copied(); + for id in ids { + stats.contracts += 1; + let fetched = self + .fetch_contract(id, None, None, Some(transaction), platform_version) + .value? + .ok_or_else(|| corrupt("enumerated contract is missing"))?; + let contract_flags = + StorageFlags::map_to_some_element_flags(fetched.storage_flags.as_ref()); + for (name, document_type) in fetched.contract.document_types() { + if !document_type.as_ref().documents_keep_history() { + continue; + } + stats.types += 1; + let type_path = contract_document_type_path_vec(&id, name); + let type_entries = + self.history_migration_entries(&type_path, transaction, platform_version)?; + let mut index_entries = BTreeMap::new(); + for (key, element) in &type_entries { + match key.as_slice() { + [0] | [DOCUMENT_HISTORY_TREE_KEY] if element.is_any_tree() => {} + [0] | [1] | [DOCUMENT_HISTORY_TREE_KEY] => { + return Err(corrupt("unexpected reserved document type child")) + } + _ => { + if !element.is_any_tree() + || !document_type + .as_ref() + .index_structure() + .sub_levels() + .keys() + .any(|name| name.as_bytes() == key) + { + return Err(corrupt( + "unrecognised document type child during history inventory", + )); + } + let mut path = type_path.clone(); + path.push(key.clone()); + self.history_migration_index_entries( + path, + transaction, + &mut stats, + &mut index_entries, + platform_version, + )?; + } + } + } + stats.maximum_type_index_entries = stats.maximum_type_index_entries.max( + index_entries + .values() + .map(|entries| entries.len() as u64) + .sum(), + ); + stats.maximum_type_index_buffer_bound = stats + .maximum_type_index_buffer_bound + .max(index_inventory_buffer_bound(&index_entries)); + if !type_entries + .iter() + .any(|(key, _)| key == &[DOCUMENT_HISTORY_TREE_KEY]) + { + self.history_migration_batch( + vec![QualifiedGroveDbOp::insert_or_replace_op( + type_path.clone(), + vec![DOCUMENT_HISTORY_TREE_KEY], + Element::empty_tree_with_flags(contract_flags.clone()), + )], + transaction, + &mut stats, + platform_version, + )?; + } + let mut primary_path = type_path.clone(); + primary_path.push(vec![0]); + for (document_id, element) in self.history_migration_entries( + &primary_path, + transaction, + platform_version, + )? { + stats.documents += 1; + let mut history_path = type_path.clone(); + history_path.extend([vec![DOCUMENT_HISTORY_TREE_KEY], document_id.clone()]); + if matches!( + element, + Element::Reference(..) | Element::ReferenceWithSumItem(..) + ) { + let entries = self.history_migration_entries( + &history_path, + transaction, + platform_version, + )?; + Self::history_migration_count_revisions(&entries, &mut stats)?; + index_entries.remove(&document_id); + continue; + } + let old_tree_type = match element { + Element::Tree(..) => TreeType::NormalTree, + Element::SumTree(..) => TreeType::SumTree, + _ => { + return Err(corrupt( + "unexpected primary entry in historical document type", + )) + } + }; + let mut old_path = primary_path.clone(); + old_path.push(document_id.clone()); + let entries = self.history_migration_entries( + &old_path, + transaction, + platform_version, + )?; + let mut pointer = None; + let mut revisions = BTreeMap::new(); + let mut copies = vec![QualifiedGroveDbOp::insert_or_replace_op( + history_path[..history_path.len() - 1].to_vec(), + document_id.clone(), + Element::empty_provable_count_tree_with_flags(contract_flags.clone()), + )]; + for (key, element) in &entries { + if key == &[0] { + pointer = Some(element.clone()); + continue; + } + if key.len() != 8 { + return Err(corrupt("legacy history key must be eight bytes")); + } + let Element::Item(bytes, _) = element else { + return Err(corrupt("legacy history revision must be an item")); + }; + let document = Document::from_bytes( + bytes, + document_type.as_ref(), + platform_version, + )?; + if document.id().as_slice() != document_id { + return Err(corrupt( + "history document id does not match its primary key", + )); + } + let time = DocumentPropertyType::decode_date_timestamp(key) + .ok_or_else(|| corrupt("invalid history timestamp"))?; + let mut composite = encode_u64(time); + composite.extend(encode_u64(document.revision().unwrap_or(1))); + revisions.insert(key.clone(), composite.clone()); + copies.push(QualifiedGroveDbOp::insert_or_replace_op( + history_path.clone(), + composite, + element.clone(), + )); + } + let revision_entries = entries + .iter() + .filter(|(key, _)| key != &[0]) + .cloned() + .collect::>(); + Self::history_migration_count_revisions(&revision_entries, &mut stats)?; + let pointer = Self::history_migration_pointer( + pointer.ok_or_else(|| corrupt("history has no current pointer"))?, + &document_id, + &revisions, + )?; + self.history_migration_batch( + copies, + transaction, + &mut stats, + platform_version, + )?; + let mut deletes = entries + .into_iter() + .map(|(key, _)| QualifiedGroveDbOp::delete_op(old_path.clone(), key)) + .collect::>(); + deletes.push(QualifiedGroveDbOp::delete_tree_op( + primary_path.clone(), + document_id.clone(), + old_tree_type, + SubelementsDeletionBehavior::Error, + )); + self.history_migration_batch( + deletes, + transaction, + &mut stats, + platform_version, + )?; + self.history_migration_batch( + vec![QualifiedGroveDbOp::insert_or_replace_op( + primary_path.clone(), + document_id.clone(), + pointer, + )], + transaction, + &mut stats, + platform_version, + )?; + if let Some(references) = index_entries.remove(&document_id) { + let rewrites = references + .iter() + .cloned() + .map(|(path, key, mut element)| { + match &mut element { + Element::Reference(reference, hops, _) + | Element::ReferenceWithSumItem(reference, hops, _, _) => { + *reference = UpstreamRootHeightReference( + 4, + vec![vec![0], document_id.clone()], + ); + *hops = Some(2); + } + // The inventory only admits references; anything + // else is corrupt state, reported like the rest. + _ => { + return Err(corrupt( + "unexpected leaf in a historical document index", + )) + } + } + Ok(QualifiedGroveDbOp::insert_or_replace_op(path, key, element)) + }) + .collect::, Error>>()?; + self.history_migration_batch( + rewrites, + transaction, + &mut stats, + platform_version, + )?; + self.history_migration_check_index_rewrites( + &references, + &document_id, + transaction, + &mut stats, + platform_version, + )?; + } + stats.migrated_documents += 1; + } + if !index_entries.is_empty() { + return Err(corrupt("history index references a missing document")); + } + } + } + } + Ok(stats) + } + + fn history_migration_check_index_rewrites( + &self, + references: &[IndexReference], + document_id: &[u8], + transaction: &Transaction, + stats: &mut DocumentHistoryMigrationStats, + platform_version: &PlatformVersion, + ) -> Result<(), Error> { + let mut rewritten = 0; + for (path, key, original) in references { + let mut expected = original.clone(); + match &mut expected { + Element::Reference(reference, hops, _) + | Element::ReferenceWithSumItem(reference, hops, _, _) => { + *reference = + UpstreamRootHeightReference(4, vec![vec![0], document_id.to_vec()]); + *hops = Some(2); + } + _ => continue, + } + let stored = self + .grove + .get_raw( + path.as_slice().into(), + key, + Some(transaction), + &platform_version.drive.grove_version, + ) + .value?; + if stored == expected { + rewritten += 1; + } + } + if rewritten != references.len() { + return Err(corrupt( + "history index rewrite count differs from its inventory", + )); + } + stats.rewritten_index_entries += rewritten as u64; + Ok(()) + } + + fn history_migration_count_revisions( + entries: &[(Vec, Element)], + stats: &mut DocumentHistoryMigrationStats, + ) -> Result<(), Error> { + stats.maximum_document_revisions = + stats.maximum_document_revisions.max(entries.len() as u64); + for (_, element) in entries { + let Element::Item(bytes, _) = element else { + return Err(corrupt("history contains a non-item revision")); + }; + stats.revisions += 1; + stats.revision_bytes += bytes.len() as u64; + } + Ok(()) + } + + fn history_migration_pointer( + mut pointer: Element, + id: &[u8], + revisions: &BTreeMap, Vec>, + ) -> Result { + let (reference, hops) = match &mut pointer { + Element::Reference(reference, hops, _) + | Element::ReferenceWithSumItem(reference, hops, _, _) => (reference, hops), + _ => return Err(corrupt("current history pointer is not a reference")), + }; + let SiblingReference(time) = reference else { + return Err(corrupt( + "current history pointer is not a sibling reference", + )); + }; + let composite = revisions + .get(time) + .ok_or_else(|| corrupt("current pointer references a missing revision"))? + .clone(); + *reference = UpstreamRootHeightReference( + 4, + vec![vec![DOCUMENT_HISTORY_TREE_KEY], id.to_vec(), composite], + ); + *hops = Some(1); + Ok(pointer) + } + + fn history_migration_entries( + &self, + path: &[Vec], + transaction: &Transaction, + version: &PlatformVersion, + ) -> Result, Element)>, Error> { + let mut query = Query::new(); + query.insert_all(); + let mut operations = vec![]; + let result = self.grove_get_raw_path_query( + &PathQuery::new(path.to_vec(), SizedQuery::new(query, None, None)), + Some(transaction), + QueryResultType::QueryKeyElementPairResultType, + &mut operations, + &version.drive, + )?; + let mut entries = result.0.to_key_elements(); + // Raw range queries normalize references to absolute paths. Read the + // stored reference itself so migration preserves its flags and shape. + for (key, element) in &mut entries { + if matches!( + element, + Element::Reference(..) | Element::ReferenceWithSumItem(..) + ) { + *element = self + .grove + .get_raw( + path.iter() + .map(Vec::as_slice) + .collect::>() + .as_slice() + .into(), + key, + Some(transaction), + &version.drive.grove_version, + ) + .value?; + } + } + Ok(entries) + } + + fn history_migration_index_entries( + &self, + path: Vec>, + transaction: &Transaction, + stats: &mut DocumentHistoryMigrationStats, + references: &mut IndexEntries, + platform_version: &PlatformVersion, + ) -> Result<(), Error> { + for (key, element) in + self.history_migration_entries(&path, transaction, platform_version)? + { + if element.is_any_tree() { + let mut child = path.clone(); + child.push(key); + self.history_migration_index_entries( + child, + transaction, + stats, + references, + platform_version, + )?; + } else if let Element::Reference(UpstreamRootHeightReference(4, target), ..) + | Element::ReferenceWithSumItem( + UpstreamRootHeightReference(4, target), + .., + ) = &element + { + if target.first().map(Vec::as_slice) != Some(&[0]) + || !(target.len() == 2 || target.len() == 3 && target[2] == [0]) + { + return Err(corrupt("unexpected document index reference target")); + } + stats.index_entries += 1; + references + .entry(target[1].clone()) + .or_default() + .push((path.clone(), key, element)); + } else { + return Err(corrupt("unexpected leaf in a historical document index")); + } + } + Ok(()) + } + + fn history_migration_batch( + &self, + operations: Vec, + transaction: &Transaction, + stats: &mut DocumentHistoryMigrationStats, + platform_version: &PlatformVersion, + ) -> Result<(), Error> { + self.grove + .apply_batch( + operations, + None, + Some(transaction), + &platform_version.drive.grove_version, + ) + .value?; + stats.batches += 1; + Ok(()) + } +} diff --git a/packages/rs-drive/src/drive/document/migration/tests.rs b/packages/rs-drive/src/drive/document/migration/tests.rs new file mode 100644 index 00000000000..2deae4768a8 --- /dev/null +++ b/packages/rs-drive/src/drive/document/migration/tests.rs @@ -0,0 +1,643 @@ +use super::*; +use crate::query::{SingleDocumentDriveQuery, SingleDocumentDriveQueryContestedStatus}; +use crate::util::object_size_info::{DocumentAndContractInfo, DocumentInfo, OwnedDocumentInfo}; +use crate::util::test_helpers::setup::setup_drive_with_initial_state_structure; +use dpp::block::block_info::BlockInfo; +use dpp::document::DocumentV0Setters; +use dpp::tests::json_document::{json_document_to_contract, json_document_to_document}; + +#[test] +fn should_accept_history_migration_when_only_primary_writer_changes() { + let mut platform_version = PlatformVersion::latest().clone(); + let drive = setup_drive_with_initial_state_structure(Some(&platform_version)); + platform_version + .drive + .methods + .document + .insert + .add_document_to_primary_storage = 2; + let transaction = drive.grove.start_transaction(); + + let stats = drive + .migrate_document_history_storage(&transaction, &platform_version) + .expect("the current history layout remains supported"); + assert_eq!(stats.migrated_documents, 0); +} + +#[test] +fn should_reject_history_migration_for_legacy_layout_with_current_writer() { + let mut platform_version = PlatformVersion::latest().clone(); + let drive = setup_drive_with_initial_state_structure(Some(&platform_version)); + platform_version + .drive + .methods + .document + .document_history_storage_layout = 0; + let transaction = drive.grove.start_transaction(); + + assert!(matches!( + drive.migrate_document_history_storage(&transaction, &platform_version), + Err(Error::Drive(DriveError::CorruptedDriveState(message))) + if message == "document history migration requires the composite-key layout" + )); +} + +#[test] +fn should_reject_history_migration_for_unknown_layout() { + let mut platform_version = PlatformVersion::latest().clone(); + let drive = setup_drive_with_initial_state_structure(Some(&platform_version)); + platform_version + .drive + .methods + .document + .document_history_storage_layout = 2; + let transaction = drive.grove.start_transaction(); + + assert!(matches!( + drive.migrate_document_history_storage(&transaction, &platform_version), + Err(Error::Drive(DriveError::UnknownVersionMismatch { + method, + known_versions, + received: 2, + })) if method == "document_history_storage_layout" && known_versions == vec![0, 1] + )); +} + +fn migrate_summable_history(revision_count: u64) -> DocumentHistoryMigrationStats { + use dpp::data_contract::DataContractFactory; + use dpp::document::document_factory::DocumentFactory; + use dpp::platform_value::platform_value; + use std::borrow::Cow; + + let old = PlatformVersion::get(14).unwrap(); + let new = PlatformVersion::get(15).unwrap(); + let schema = platform_value!({ + "type": "object", "documentsKeepHistory": true, "canBeDeleted": false, + "documentsCountable": true, "documentsSummable": "amount", + "properties": {"amount": {"type": "integer", "minimum": 0, "maximum": 4294967295i64, "position": 0}}, + "required": ["amount"], "additionalProperties": false, + "indices": [{"name": "amount", "properties": [{"amount": "asc"}]}] + }); + let contract = DataContractFactory::new(14) + .unwrap() + .create_with_value_config( + [7; 32].into(), + 0, + platform_value!({"tip": schema.clone(), "empty": schema}), + None, + None, + ) + .unwrap() + .data_contract_owned(); + let contract_flags = StorageFlags::new_single_epoch(7, Some([66; 32])); + let directory = tempfile::TempDir::new().unwrap(); + let (drive, _) = Drive::open( + directory.path(), + Some(crate::config::DriveConfig { + batching_consistency_verification: true, + ..Default::default() + }), + ) + .unwrap(); + drive.create_initial_state_structure(None, old).unwrap(); + drive + .apply_contract( + &contract, + BlockInfo::default(), + true, + Some(Cow::Borrowed(&contract_flags)), + None, + old, + ) + .unwrap(); + let document_type = contract.document_type_for_name("tip").unwrap(); + let mut document = DocumentFactory::new(14) + .unwrap() + .create_document( + &contract, + [7; 32].into(), + "tip".into(), + platform_value!({"amount": 1}), + ) + .unwrap(); + document.set_id([9; 32].into()); + for revision in 1..=revision_count { + document.set_revision(Some(revision)); + document.set("amount", revision.into()); + drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentInfo::DocumentRefInfo(( + &document, + Some(Cow::Owned(StorageFlags::new_single_epoch( + (revision % 3) as u16, + Some([revision as u8; 32]), + ))), + )), + owner_id: None, + }, + contract: &contract, + document_type, + }, + true, + BlockInfo::default_with_time(revision * 1000), + true, + None, + old, + ) + .unwrap(); + } + if revision_count == 256 { + if let Some(path) = std::env::var_os("DOCUMENT_HISTORY_MIGRATION_FIXTURE") { + assert!( + !std::path::Path::new(&path).exists(), + "fixture destination must not exist" + ); + drive.grove.create_checkpoint(path).unwrap(); + } + } + let transaction = drive.grove.start_transaction(); + let type_path = contract_document_type_path_vec(contract.id().as_slice(), "tip"); + let mut old_path = type_path.clone(); + old_path.extend([vec![0], document.id().to_vec()]); + let old_entries = drive + .history_migration_entries(&old_path, &transaction, old) + .unwrap(); + let stats = drive + .migrate_document_history_storage(&transaction, new) + .unwrap(); + assert_eq!(stats.types, 2); + assert_eq!(stats.documents, 1); + assert_eq!(stats.revisions, revision_count); + let history = drive + .history_migration_entries( + &crate::drive::document::paths::document_history_path( + contract.id().as_slice(), + "tip", + document.id().as_slice(), + ), + &transaction, + new, + ) + .unwrap(); + assert_eq!( + old_entries.iter().filter(|(key, _)| key != &[0]).count(), + history.len(), + "every retained source revision must have a destination revision", + ); + for ((_, original), (_, migrated)) in old_entries + .iter() + .filter(|(key, _)| key != &[0]) + .zip(&history) + { + assert_eq!( + original, migrated, + "revision bytes and beneficiary flags must be preserved" + ); + } + let parent = drive + .grove + .get_raw( + type_path.as_slice().into(), + &[0], + Some(&transaction), + &new.drive.grove_version, + ) + .value + .unwrap(); + assert!(matches!(parent, Element::CountSumTree(_, 1, sum, _) if sum == revision_count as i64)); + let primary_path = old_path[..old_path.len() - 1].to_vec(); + let pointer = drive + .grove + .get_raw( + primary_path.as_slice().into(), + document.id().as_slice(), + Some(&transaction), + &new.drive.grove_version, + ) + .value + .unwrap(); + assert_eq!( + pointer.get_flags(), + old_entries + .iter() + .find(|(key, _)| key == &[0]) + .unwrap() + .1 + .get_flags() + ); + let history_parent = type_path + .iter() + .cloned() + .chain([vec![DOCUMENT_HISTORY_TREE_KEY]]) + .collect::>(); + let history_tree = drive + .grove + .get_raw( + history_parent.as_slice().into(), + document.id().as_slice(), + Some(&transaction), + &new.drive.grove_version, + ) + .value + .unwrap(); + assert_eq!( + history_tree.get_flags(), + &StorageFlags::map_to_some_element_flags(Some(&contract_flags)), + "new structural bytes inherit the contract's flags" + ); + let history_root = drive + .grove + .get_raw( + type_path.as_slice().into(), + &[DOCUMENT_HISTORY_TREE_KEY], + Some(&transaction), + &new.drive.grove_version, + ) + .value + .unwrap(); + assert_eq!( + history_root.get_flags(), + &StorageFlags::map_to_some_element_flags(Some(&contract_flags)) + ); + let empty_type = contract_document_type_path_vec(contract.id().as_slice(), "empty"); + let empty_history = drive + .grove + .get_raw( + empty_type.as_slice().into(), + &[DOCUMENT_HISTORY_TREE_KEY], + Some(&transaction), + &new.drive.grove_version, + ) + .value + .unwrap(); + assert_eq!( + empty_history.get_flags(), + &StorageFlags::map_to_some_element_flags(Some(&contract_flags)) + ); + assert!(matches!(empty_history, Element::Tree(..))); + println!("revisions={revision_count} {stats:#?}"); + stats +} + +#[test] +fn should_preserve_sums_counts_flags_and_empty_types_during_migration() { + migrate_summable_history(8); +} + +#[test] +fn should_measure_history_depth_instead_of_only_document_count() { + let shallow = migrate_summable_history(16); + let deep = migrate_summable_history(256); + assert_eq!(shallow.documents, deep.documents); + assert_eq!(deep.revisions, shallow.revisions * 16); +} + +#[test] +fn should_migrate_revisions_and_indexes_without_recovering_overwritten_revisions() { + let drive = setup_drive_with_initial_state_structure(None); + let old = PlatformVersion::get(14).unwrap(); + let new = PlatformVersion::get(15).unwrap(); + let contract = json_document_to_contract( + "tests/supporting_files/contract/dashpay/dashpay-contract-with-profile-history.json", + false, + old, + ) + .unwrap(); + drive + .apply_contract(&contract, BlockInfo::default(), true, None, None, old) + .unwrap(); + let document_type = contract.document_type_for_name("profile").unwrap(); + let mut document = json_document_to_document( + "tests/supporting_files/contract/dashpay/profile0.json", + Some([7; 32].into()), + document_type, + old, + ) + .unwrap(); + for (revision, time) in [(1, 1000), (2, 2000), (3, 2000)] { + document.set_revision(Some(revision)); + drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentInfo::DocumentRefInfo(( + &document, + StorageFlags::optional_default_as_cow(), + )), + owner_id: None, + }, + contract: &contract, + document_type, + }, + true, + BlockInfo::default_with_time(time), + true, + None, + old, + ) + .unwrap(); + } + let root_before = drive + .grove + .root_hash(None, &old.drive.grove_version) + .unwrap() + .unwrap(); + let transaction = drive.grove.start_transaction(); + let stats = drive + .migrate_document_history_storage(&transaction, new) + .unwrap(); + assert_eq!(stats.documents, 1); + assert_eq!(stats.revisions, 2); + assert_eq!(stats.migrated_documents, 1); + assert!(stats.index_entries > 0); + assert_eq!(stats.rewritten_index_entries, stats.index_entries); + let root_migrated = drive + .grove + .root_hash(Some(&transaction), &new.drive.grove_version) + .unwrap() + .unwrap(); + assert_ne!(root_before, root_migrated); + assert_eq!( + drive + .grove + .root_hash(None, &new.drive.grove_version) + .unwrap() + .unwrap(), + root_before + ); + + let query = SingleDocumentDriveQuery { + contract_id: contract.id().to_buffer(), + document_type_name: "profile".into(), + document_type_keeps_history: true, + document_id: document.id().to_buffer(), + block_time_ms: None, + contested_status: SingleDocumentDriveQueryContestedStatus::NotContested, + } + .construct_path_query(new) + .unwrap(); + let (current, _) = drive + .grove_get_path_query( + &query, + Some(&transaction), + QueryResultType::QueryElementResultType, + &mut vec![], + &new.drive, + ) + .unwrap(); + assert_eq!(current.elements.len(), 1); + let history = drive + .history_migration_entries( + &crate::drive::document::paths::document_history_path( + contract.id().as_slice(), + "profile", + document.id().as_slice(), + ), + &transaction, + new, + ) + .unwrap(); + assert_eq!(history.len(), 2); + assert_eq!(&history[1].0[8..], encode_u64(3)); + use crate::query::document_history_drive_query::{ + DocumentHistoryDriveQuery, DocumentHistoryFilter, + }; + let mut history_query = DocumentHistoryDriveQuery { + contract_id: contract.id().to_buffer(), + document_type_name: "profile".into(), + document_id: document.id().to_buffer(), + filter: DocumentHistoryFilter::StartAtTime(0), + limit: None, + }; + let page = drive + .fetch_document_history(&history_query, document_type, Some(&transaction), new) + .unwrap(); + assert_eq!( + page.entries + .iter() + .map(|entry| entry.revision) + .collect::>(), + vec![1, 3] + ); + assert_eq!(page.lifecycle.as_ref().unwrap().remaining_revisions, 2); + history_query.filter = DocumentHistoryFilter::Revision(2); + assert!( + drive + .fetch_document_history(&history_query, document_type, Some(&transaction), new) + .is_err(), + "an overwritten revision must not return the next retained document" + ); + let repeated = drive + .migrate_document_history_storage(&transaction, new) + .unwrap(); + assert_eq!(repeated.migrated_documents, 0); + assert_eq!(repeated.revisions, 2); + assert_eq!( + drive + .grove + .root_hash(Some(&transaction), &new.drive.grove_version) + .unwrap() + .unwrap(), + root_migrated + ); + drop(transaction); + let retry = drive.grove.start_transaction(); + drive.migrate_document_history_storage(&retry, new).unwrap(); + assert_eq!( + drive + .grove + .root_hash(Some(&retry), &new.drive.grove_version) + .unwrap() + .unwrap(), + root_migrated + ); + drive.grove.commit_transaction(retry).unwrap().unwrap(); + history_query.filter = DocumentHistoryFilter::StartAtTime(0); + let committed_page = drive + .fetch_document_history(&history_query, document_type, None, new) + .unwrap(); + let proof = drive + .prove_document_history(&history_query, document_type, None, new) + .unwrap(); + assert_eq!(committed_page, page); + assert_eq!( + Drive::verify_document_history(&history_query, &proof, document_type, new,) + .unwrap() + .1, + page + ); + let legacy_entries = + crate::util::test_helpers::history_proof::downgrade_history_count(&proof, None, new); + let error = Drive::verify_document_history(&history_query, &legacy_entries, document_type, new) + .expect_err("entries require a GroveDB v1 envelope"); + assert!(matches!( + error, + Error::Proof( + crate::error::proof::ProofError::UnsupportedGroveDBProofEnvelopeVersion { .. } + ) + )); + for filter in [ + DocumentHistoryFilter::Revision(3), + DocumentHistoryFilter::StartAtRevision(3), + ] { + history_query.filter = filter; + let fetched = drive.fetch_document_history(&history_query, document_type, None, new); + let proved = drive.prove_document_history(&history_query, document_type, None, new); + let dishonest = drive + .grove_get_proved_path_query( + &history_query.construct_path_query(new).unwrap(), + None, + &mut vec![], + &new.drive, + ) + .unwrap(); + let verified = + Drive::verify_document_history(&history_query, &dishonest, document_type, new); + let downgraded = crate::util::test_helpers::history_proof::downgrade_history_count( + &dishonest, + Some(3), + new, + ); + let error = Drive::verify_document_history(&history_query, &downgraded, document_type, new) + .expect_err("document history rejects legacy metadata envelopes"); + assert!(matches!( + error, + Error::Proof( + crate::error::proof::ProofError::UnsupportedGroveDBProofEnvelopeVersion { .. } + ) + )); + + assert!(fetched.is_err() && proved.is_err() && verified.is_err(), "revision 3 exists in retained [1,3], so an empty ordinal page must be rejected: fetch rejected={}, prove rejected={}, verify rejected={}", fetched.is_err(), proved.is_err(), verified.is_err()); + } + println!("{stats:#?}"); +} + +#[test] +fn should_reject_unrecognised_type_children_during_migration_inventory() { + let old = PlatformVersion::get(14).unwrap(); + let new = PlatformVersion::get(15).unwrap(); + for (key, element) in [ + (vec![0, 9], Element::empty_tree()), + (b"unknown".to_vec(), Element::empty_tree()), + (b"item".to_vec(), Element::new_item(vec![])), + ] { + let drive = setup_drive_with_initial_state_structure(Some(old)); + let contract = json_document_to_contract( + "tests/supporting_files/contract/dashpay/dashpay-contract-with-profile-history.json", + false, + old, + ) + .unwrap(); + drive + .apply_contract(&contract, BlockInfo::default(), true, None, None, old) + .unwrap(); + let path = contract_document_type_path_vec(contract.id().as_slice(), "profile"); + drive + .grove + .insert( + path.as_slice(), + &key, + element, + None, + None, + &old.drive.grove_version, + ) + .value + .unwrap(); + let transaction = drive.grove.start_transaction(); + assert!( + drive + .migrate_document_history_storage(&transaction, new) + .is_err(), + "unrecognised type child {key:?} cannot be silently skipped" + ); + } +} + +#[test] +fn should_halt_migration_when_an_inventoried_index_reference_was_not_rewritten() { + let old = PlatformVersion::get(14).unwrap(); + let new = PlatformVersion::get(15).unwrap(); + let drive = setup_drive_with_initial_state_structure(Some(old)); + let contract = json_document_to_contract( + "tests/supporting_files/contract/dashpay/dashpay-contract-with-profile-history.json", + false, + old, + ) + .unwrap(); + drive + .apply_contract(&contract, BlockInfo::default(), true, None, None, old) + .unwrap(); + let document_type = contract.document_type_for_name("profile").unwrap(); + let document = json_document_to_document( + "tests/supporting_files/contract/dashpay/profile0.json", + Some([7; 32].into()), + document_type, + old, + ) + .unwrap(); + drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentInfo::DocumentRefInfo((&document, None)), + owner_id: None, + }, + contract: &contract, + document_type, + }, + true, + BlockInfo::default_with_time(1000), + true, + None, + old, + ) + .unwrap(); + let transaction = drive.grove.start_transaction(); + let type_path = contract_document_type_path_vec(contract.id().as_slice(), "profile"); + let mut stats = DocumentHistoryMigrationStats::default(); + let mut inventory = IndexEntries::new(); + for (key, _) in drive + .history_migration_entries(&type_path, &transaction, old) + .unwrap() + { + if key == [0] { + continue; + } + let mut path = type_path.clone(); + path.push(key); + drive + .history_migration_index_entries(path, &transaction, &mut stats, &mut inventory, old) + .unwrap(); + } + let references = inventory.remove(document.id().as_slice()).unwrap(); + assert!(!references.is_empty()); + let error = drive + .history_migration_check_index_rewrites( + &references, + document.id().as_slice(), + &transaction, + &mut stats, + new, + ) + .expect_err("an omitted rewrite must halt instead of being counted as rewritten"); + assert!(error + .to_string() + .contains("history index rewrite count differs from its inventory")); + assert_eq!(stats.rewritten_index_entries, 0); + drive + .migrate_document_history_storage(&transaction, new) + .unwrap(); + drive + .history_migration_check_index_rewrites( + &references, + document.id().as_slice(), + &transaction, + &mut stats, + new, + ) + .unwrap(); + assert_eq!(stats.rewritten_index_entries, references.len() as u64); +} diff --git a/packages/rs-drive/src/drive/document/mod.rs b/packages/rs-drive/src/drive/document/mod.rs index e9db8f85e46..230e749fb42 100644 --- a/packages/rs-drive/src/drive/document/mod.rs +++ b/packages/rs-drive/src/drive/document/mod.rs @@ -44,9 +44,32 @@ use dpp::version::PlatformVersion; use grovedb::element::reference_path::ReferencePathType::UpstreamRootHeightReference; #[cfg(any(feature = "server", feature = "verify"))] use grovedb::Element; +#[cfg(feature = "server")] +use grovedb::EstimatedLayerSizes; #[cfg(any(feature = "server", feature = "verify"))] use std::collections::BTreeSet; +/// Whether current documents use pointers into the separate retained-history tree. +#[cfg(any(feature = "server", feature = "verify"))] +pub(crate) fn uses_current_document_history_layout( + platform_version: &PlatformVersion, +) -> Result { + match platform_version + .drive + .methods + .document + .document_history_storage_layout + { + 0 => Ok(false), + 1 => Ok(true), + received => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "document_history_storage_layout".to_string(), + known_versions: vec![0, 1], + received, + })), + } +} + #[cfg(feature = "server")] mod delete; /// The values of derived index properties, read from the documents the references point at @@ -62,12 +85,16 @@ pub mod expiration; mod fetch_property_constraint_aggregate; #[cfg(any(feature = "server", feature = "fixtures-and-mocks"))] mod get_fetch; +/// Composite-key history queries and proof results. #[cfg(feature = "server")] mod index_uniqueness; #[cfg(any(feature = "server", feature = "fixtures-and-mocks"))] mod insert; #[cfg(any(feature = "server", feature = "fixtures-and-mocks"))] mod insert_contested; +/// Activation migration and its inventory. +#[cfg(feature = "server")] +pub mod migration; #[cfg(any(feature = "server", feature = "fixtures-and-mocks"))] pub use insert_contested::ContestWindows; #[cfg(any(feature = "server", feature = "fixtures-and-mocks"))] @@ -578,6 +605,92 @@ fn document_reference_size(document_type: DocumentTypeRef) -> u32 { 6 + reference_path_size } +#[cfg(any(feature = "server", feature = "verify"))] +/// Creates a reference to a document stored with the per-type history tree by +/// primary-storage writer version 1. +/// +/// The reference always points at the primary key tree entry. For a +/// keep-history type that entry is itself a reference to the current revision +/// in the history tree, so one more hop is allowed. +fn make_document_reference_v1( + document: &Document, + document_type: DocumentTypeRef, + storage_flags: Option<&StorageFlags>, +) -> Element { + let reference_path = vec![vec![0], document.id().to_vec()]; + let max_reference_hops = if document_type.documents_keep_history() { + 2 + } else { + 1 + }; + Element::Reference( + UpstreamRootHeightReference(4, reference_path), + Some(max_reference_hops), + StorageFlags::map_to_some_element_flags(storage_flags), + ) +} + +#[cfg(any(feature = "server", feature = "verify"))] +/// [`make_document_reference_v1`] carrying the document's sum contribution for +/// a summable index. +pub(crate) fn make_document_reference_with_sum_item_v1( + document: &Document, + document_type: DocumentTypeRef, + sum_value: i64, + storage_flags: Option<&StorageFlags>, +) -> Element { + let reference_path = vec![vec![0], document.id().to_vec()]; + let max_reference_hops = if document_type.documents_keep_history() { + 2 + } else { + 1 + }; + Element::new_reference_with_sum_item_with_max_hops_and_flags( + UpstreamRootHeightReference(4, reference_path), + Some(max_reference_hops), + sum_value, + StorageFlags::map_to_some_element_flags(storage_flags), + ) +} + +#[cfg(feature = "server")] +/// Serialized size of a [`make_document_reference_v1`] reference: the path is +/// always `[0, document id]`. +fn document_reference_size_v1() -> u32 { + // 1 for type reference + // 1 for reference type + // 1 for root height offset + // 36 for the reference path (vec size, subvec size, 0, subvec size, 32-byte id) + // 1 reference_hops option + // 1 reference_hops count + // 1 element flags option + 6 + 36 +} + +#[cfg(feature = "server")] +fn document_reference_estimated_layer_sizes_v1( + key_size: u8, + flags_size: Option, + summable: bool, +) -> EstimatedLayerSizes { + if summable { + EstimatedLayerSizes::AllReferencesWithSumItem( + key_size, + document_reference_size_v1(), + flags_size, + ) + } else { + EstimatedLayerSizes::AllReference(key_size, document_reference_size_v1(), flags_size) + } +} + +#[cfg(feature = "server")] +fn document_reference_estimated_value_size_v1(flags_size: u32, summable: bool) -> u32 { + const SUM_ITEM_SIZE: u32 = 10; + + document_reference_size_v1() + flags_size + if summable { SUM_ITEM_SIZE } else { 0 } +} + #[cfg(feature = "server")] fn unique_event_id() -> [u8; 32] { rand::random::<[u8; 32]>() @@ -589,7 +702,13 @@ fn unique_event_id() -> [u8; 32] { pub(crate) mod tests { use std::option::Option::None; + use super::{ + document_reference_estimated_layer_sizes_v1, document_reference_estimated_value_size_v1, + document_reference_size_v1, uses_current_document_history_layout, + }; use crate::drive::Drive; + use crate::error::drive::DriveError; + use crate::error::Error; use crate::util::storage_flags::StorageFlags; use dpp::block::block_info::BlockInfo; use dpp::prelude::DataContract; @@ -597,6 +716,87 @@ pub(crate) mod tests { use crate::util::test_helpers::setup::setup_drive_with_initial_state_structure; use dpp::version::PlatformVersion; + use grovedb::EstimatedLayerSizes::{AllReference, AllReferencesWithSumItem}; + + #[test] + fn should_keep_legacy_history_layout_when_primary_writer_changes() { + let mut platform_version = PlatformVersion::get(14).expect("protocol 14").clone(); + platform_version + .drive + .methods + .document + .insert + .add_document_to_primary_storage = 1; + + assert!(!uses_current_document_history_layout(&platform_version) + .expect("legacy history layout remains supported")); + } + + #[test] + fn should_keep_current_history_layout_when_primary_writer_changes() { + for writer_version in [0, 2] { + let mut platform_version = PlatformVersion::get(15).expect("protocol 15").clone(); + platform_version + .drive + .methods + .document + .insert + .add_document_to_primary_storage = writer_version; + + assert!( + uses_current_document_history_layout(&platform_version) + .expect("current history layout remains supported"), + "writer version {writer_version} must not change the history layout" + ); + } + } + + #[test] + fn should_reject_unknown_document_history_storage_layout_versions() { + for received in [2, u16::MAX] { + let mut platform_version = PlatformVersion::get(15).expect("protocol 15").clone(); + platform_version + .drive + .methods + .document + .document_history_storage_layout = received; + + assert!(matches!( + uses_current_document_history_layout(&platform_version), + Err(Error::Drive(DriveError::UnknownVersionMismatch { + method, + known_versions, + received: actual, + })) if method == "document_history_storage_layout" + && known_versions == vec![0, 1] + && actual == received + )); + } + } + + #[test] + fn summable_document_reference_estimates_include_the_sum_item() { + assert_eq!( + document_reference_estimated_layer_sizes_v1(32, Some(17), true), + AllReferencesWithSumItem(32, document_reference_size_v1(), Some(17)) + ); + assert_eq!( + document_reference_estimated_value_size_v1(17, true), + document_reference_size_v1() + 17 + 10 + ); + } + + #[test] + fn plain_document_reference_estimates_remain_unchanged() { + assert_eq!( + document_reference_estimated_layer_sizes_v1(32, Some(17), false), + AllReference(32, document_reference_size_v1(), Some(17)) + ); + assert_eq!( + document_reference_estimated_value_size_v1(17, false), + document_reference_size_v1() + 17 + ); + } /// Setup Dashpay pub fn setup_dashpay(_prefix: &str, mutable_contact_requests: bool) -> (Drive, DataContract) { diff --git a/packages/rs-drive/src/drive/document/paths.rs b/packages/rs-drive/src/drive/document/paths.rs index 3cb642a19ba..893fd219d85 100644 --- a/packages/rs-drive/src/drive/document/paths.rs +++ b/packages/rs-drive/src/drive/document/paths.rs @@ -12,6 +12,20 @@ use grovedb::batch::key_info::KeyInfo; #[cfg(feature = "server")] use grovedb::batch::KeyInfoPath; +/// Reserved document-type key containing the revision trees. +pub const DOCUMENT_HISTORY_TREE_KEY: u8 = 2; + +/// Path to all retained revisions of one document. +pub fn document_history_path( + contract_id: &[u8], + document_type_name: &str, + document_id: &[u8], +) -> Vec> { + let mut path = contract_document_type_path_vec(contract_id, document_type_name); + path.extend([vec![DOCUMENT_HISTORY_TREE_KEY], document_id.to_vec()]); + path +} + #[cfg(any(feature = "server", feature = "verify"))] /// Returns the path to a contract document type. pub(crate) fn contract_document_type_path<'a>( diff --git a/packages/rs-drive/src/drive/document/private_document_store/mod.rs b/packages/rs-drive/src/drive/document/private_document_store/mod.rs index 38179be0bec..da6830a2b8c 100644 --- a/packages/rs-drive/src/drive/document/private_document_store/mod.rs +++ b/packages/rs-drive/src/drive/document/private_document_store/mod.rs @@ -375,6 +375,9 @@ mod tests { use super::*; use crate::drive::{Drive, RootTree}; use crate::error::query::QuerySyntaxError; + use crate::query::document_history_drive_query::{ + DocumentHistoryDriveQuery, DocumentHistoryFilter, + }; use crate::query::DriveDocumentQuery; use crate::util::test_helpers::setup::setup_drive_with_initial_state_structure; use dpp::block::block_info::BlockInfo; @@ -651,47 +654,25 @@ mod tests { ) }; + let query = DocumentHistoryDriveQuery { + contract_id: CONTRACT_ID, + document_type_name: "secret".to_string(), + document_id: [1; 32], + filter: DocumentHistoryFilter::StartAtTime(0), + limit: Some(10), + }; assert!(refused( drive - .fetch_document_history( - CONTRACT_ID, - secret, - [1; 32], - None, - 0, - Some(10), - None, - platform_version, - ) + .fetch_document_history(&query, secret, None, platform_version) .map(|_| ()) )); assert!(refused( drive - .prove_document_history( - CONTRACT_ID, - secret, - [1; 32], - None, - 0, - Some(10), - None, - platform_version, - ) + .prove_document_history(&query, secret, None, platform_version) .map(|_| ()) )); assert!(refused( - Drive::verify_document_history( - &[], - CONTRACT_ID, - "secret", - secret, - [1; 32], - 0, - Some(10), - None, - platform_version, - ) - .map(|_| ()) + Drive::verify_document_history(&query, &[], secret, platform_version).map(|_| ()) )); } diff --git a/packages/rs-drive/src/drive/document/prove/prove_document_history/mod.rs b/packages/rs-drive/src/drive/document/prove/prove_document_history/mod.rs index 285d7419775..d865d0ea839 100644 --- a/packages/rs-drive/src/drive/document/prove/prove_document_history/mod.rs +++ b/packages/rs-drive/src/drive/document/prove/prove_document_history/mod.rs @@ -1,23 +1,32 @@ mod v0; +mod v1; use crate::drive::Drive; + use crate::error::drive::DriveError; use crate::error::Error; +use crate::query::document_history_drive_query::DocumentHistoryDriveQuery; use dpp::data_contract::document_type::DocumentTypeRef; use dpp::version::PlatformVersion; use grovedb::TransactionArg; impl Drive { - /// Proves the existence or absence of the specified document's history. A private - /// document type keeps none: it is refused. + /// Proves the per-document timestamp-keyed history used through protocol version 14. + /// + /// # Parameters + /// `start_after_ms` excludes matching timestamps; `offset` optionally skips entries after + /// that bound for unproved queries. The platform version must select the timestamp-keyed reader. + /// + /// # Returns + /// The history result, or an error for an unsupported reader generation. #[allow(clippy::too_many_arguments)] - pub fn prove_document_history( + pub fn prove_document_history_after_time( &self, contract_id: [u8; 32], document_type: DocumentTypeRef, document_id: [u8; 32], transaction: TransactionArg, - start_at_ms: u64, + start_after_ms: u64, limit: Option, offset: Option, platform_version: &PlatformVersion, @@ -34,16 +43,42 @@ impl Drive { document_type, document_id, transaction, - start_at_ms, + start_after_ms, limit, offset, platform_version, ), version => Err(Error::Drive(DriveError::UnknownVersionMismatch { - method: "prove_document_history".to_string(), + method: "prove_document_history_after_time".to_owned(), known_versions: vec![0], received: version, })), } } + + /// Proves a page and lifecycle from the per-type composite-keyed history tree. + pub fn prove_document_history( + &self, + query: &DocumentHistoryDriveQuery, + document_type: DocumentTypeRef, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result, Error> { + match platform_version + .drive + .methods + .document + .query + .prove_document_history + { + 1 => { + self.prove_document_history_v1(query, document_type, transaction, platform_version) + } + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "prove_document_history".to_string(), + known_versions: vec![1], + received: version, + })), + } + } } diff --git a/packages/rs-drive/src/drive/document/prove/prove_document_history/v0/mod.rs b/packages/rs-drive/src/drive/document/prove/prove_document_history/v0/mod.rs index e5bd11405d4..4d93bfd8263 100644 --- a/packages/rs-drive/src/drive/document/prove/prove_document_history/v0/mod.rs +++ b/packages/rs-drive/src/drive/document/prove/prove_document_history/v0/mod.rs @@ -12,7 +12,7 @@ impl Drive { document_type: DocumentTypeRef, document_id: [u8; 32], transaction: TransactionArg, - start_at_ms: u64, + start_after_ms: u64, limit: Option, offset: Option, platform_version: &PlatformVersion, @@ -21,7 +21,7 @@ impl Drive { contract_id, document_type, document_id, - start_at_ms, + start_after_ms, limit, offset, platform_version, diff --git a/packages/rs-drive/src/drive/document/prove/prove_document_history/v1/mod.rs b/packages/rs-drive/src/drive/document/prove/prove_document_history/v1/mod.rs new file mode 100644 index 00000000000..f1583837f79 --- /dev/null +++ b/packages/rs-drive/src/drive/document/prove/prove_document_history/v1/mod.rs @@ -0,0 +1,25 @@ +use crate::drive::Drive; +use crate::error::Error; +use crate::query::document_history_drive_query::DocumentHistoryDriveQuery; +use dpp::data_contract::document_type::DocumentTypeRef; +use dpp::version::PlatformVersion; +use grovedb::TransactionArg; + +impl Drive { + /// Proves the history page and lifecycle in one GroveDB proof. + pub(super) fn prove_document_history_v1( + &self, + query: &DocumentHistoryDriveQuery, + document_type: DocumentTypeRef, + transaction: TransactionArg, + version: &PlatformVersion, + ) -> Result, Error> { + self.fetch_document_history(query, document_type, transaction, version)?; + self.grove_get_proved_path_query( + &query.construct_path_query(version)?, + transaction, + &mut vec![], + &version.drive, + ) + } +} diff --git a/packages/rs-drive/src/drive/document/query/fetch_document_history_query/mod.rs b/packages/rs-drive/src/drive/document/query/fetch_document_history_query/mod.rs index 94f25429c77..ef0069ac8b7 100644 --- a/packages/rs-drive/src/drive/document/query/fetch_document_history_query/mod.rs +++ b/packages/rs-drive/src/drive/document/query/fetch_document_history_query/mod.rs @@ -1,9 +1,12 @@ mod v0; +mod v1; use crate::drive::document::MAX_DOCUMENT_HISTORY_FETCH_LIMIT; use crate::drive::Drive; use crate::error::drive::DriveError; use crate::error::Error; +use crate::query::refuse_a_private_document_type; +use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters; use dpp::data_contract::document_type::DocumentTypeRef; use dpp::version::PlatformVersion; use grovedb::PathQuery; @@ -12,6 +15,9 @@ impl Drive { /// Creates a path query for historical entries of a specified document of /// `document_type`. A private document type keeps no documents and no history: it is /// refused (`QuerySyntaxError::Unsupported`), for a fetch, a proof and its verification. + /// + /// `start_at_ms` is exclusive for method version 0's per-document timestamp-keyed + /// history and inclusive for method version 1's per-type composite-keyed history. #[allow(clippy::too_many_arguments)] pub fn fetch_document_history_query( contract_id: [u8; 32], @@ -22,6 +28,7 @@ impl Drive { offset: Option, platform_version: &PlatformVersion, ) -> Result { + refuse_a_private_document_type(document_type).map_err(Error::Query)?; match platform_version .drive .methods @@ -37,9 +44,17 @@ impl Drive { limit, offset, ), + 1 => Self::fetch_document_history_query_v1( + contract_id, + document_type.name(), + document_id, + start_at_ms, + limit, + offset, + ), version => Err(Error::Drive(DriveError::UnknownVersionMismatch { method: "fetch_document_history_query".to_string(), - known_versions: vec![0], + known_versions: vec![0, 1], received: version, })), } @@ -56,3 +71,41 @@ impl Drive { Ok(limit) } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::drive::document::paths::document_history_path; + use dpp::data_contract::accessors::v0::DataContractV0Getters; + + #[test] + fn should_keep_legacy_query_builder_available_after_layout_change() { + let contract_id = [1; 32]; + let document_id = [2; 32]; + let contract = dpp::tests::json_document::json_document_to_contract( + "tests/supporting_files/contract/dashpay/dashpay-contract-with-profile-history.json", + false, + PlatformVersion::latest(), + ) + .unwrap(); + let document_type_name = "profile"; + let document_type = contract.document_type_for_name(document_type_name).unwrap(); + let path_query = Drive::fetch_document_history_query( + contract_id, + document_type, + document_id, + 1_000, + Some(3), + Some(2), + PlatformVersion::get(15).expect("protocol 15"), + ) + .expect("the legacy-shaped query is supported by the new layout"); + + assert_eq!( + path_query.path, + document_history_path(&contract_id, document_type_name, &document_id) + ); + assert_eq!(path_query.query.limit, Some(3)); + assert_eq!(path_query.query.offset, Some(2)); + } +} diff --git a/packages/rs-drive/src/drive/document/query/fetch_document_history_query/v0/mod.rs b/packages/rs-drive/src/drive/document/query/fetch_document_history_query/v0/mod.rs index 1485d819ef8..0d26ce55ac1 100644 --- a/packages/rs-drive/src/drive/document/query/fetch_document_history_query/v0/mod.rs +++ b/packages/rs-drive/src/drive/document/query/fetch_document_history_query/v0/mod.rs @@ -12,14 +12,14 @@ impl Drive { contract_id: [u8; 32], document_type: DocumentTypeRef, document_id: [u8; 32], - start_at_ms: u64, + start_after_ms: u64, limit: Option, offset: Option, ) -> Result { // In place, unversioned in effect: no type is private before protocol version 15 refuse_a_private_document_type(document_type).map_err(Error::Query)?; let limit = Self::validate_document_history_limit(limit)?; - let encoded_start = DocumentPropertyType::encode_date_timestamp(start_at_ms); + let encoded_start = DocumentPropertyType::encode_date_timestamp(start_after_ms); let query = Query::new_single_query_item_with_direction( QueryItem::RangeAfter(std::ops::RangeFrom { start: encoded_start, diff --git a/packages/rs-drive/src/drive/document/query/fetch_document_history_query/v1/mod.rs b/packages/rs-drive/src/drive/document/query/fetch_document_history_query/v1/mod.rs new file mode 100644 index 00000000000..25b9b2fdea4 --- /dev/null +++ b/packages/rs-drive/src/drive/document/query/fetch_document_history_query/v1/mod.rs @@ -0,0 +1,70 @@ +use crate::drive::document::paths::document_history_path; +use crate::drive::document::MAX_DOCUMENT_HISTORY_FETCH_LIMIT; +use crate::drive::Drive; +use crate::error::Error; +use crate::query::document_history_drive_query::{ + DocumentHistoryDriveQuery, DocumentHistoryFilter, +}; +use crate::util::common::encode::encode_u64; +use grovedb::{PathQuery, Query, SizedQuery}; + +impl Drive { + #[allow(clippy::too_many_arguments)] + pub(super) fn fetch_document_history_query_v1( + contract_id: [u8; 32], + document_type_name: &str, + document_id: [u8; 32], + start_at_ms: u64, + limit: Option, + offset: Option, + ) -> Result { + let query = DocumentHistoryDriveQuery { + contract_id, + document_type_name: document_type_name.to_owned(), + document_id, + filter: DocumentHistoryFilter::StartAtTime(start_at_ms), + limit, + }; + let mut path_query = Self::fetch_document_history_drive_query_v1(&query)?; + path_query.query.offset = offset; + Ok(path_query) + } + + /// The leaf-only query over the per-type history tree required for + /// authenticated count-offset pagination. + pub(crate) fn fetch_document_history_drive_query_v1( + query: &DocumentHistoryDriveQuery, + ) -> Result { + query.validate()?; + let mut grove_query = Query::new(); + let mut limit = query.limit.unwrap_or(MAX_DOCUMENT_HISTORY_FETCH_LIMIT); + let offset = match query.filter { + DocumentHistoryFilter::StartAtTime(time) => { + grove_query.insert_range_from(encode_u64(time)..); + None + } + DocumentHistoryFilter::StartAfter { time_ms, revision } => { + let mut key = encode_u64(time_ms); + key.extend(encode_u64(revision)); + grove_query.insert_range_after(key..); + None + } + DocumentHistoryFilter::StartAtRevision(revision) + | DocumentHistoryFilter::Revision(revision) => { + grove_query.insert_all(); + if matches!(query.filter, DocumentHistoryFilter::Revision(_)) { + limit = 1; + } + Some((revision - 1) as u16) + } + }; + Ok(PathQuery::new( + document_history_path( + &query.contract_id, + &query.document_type_name, + &query.document_id, + ), + SizedQuery::new(grove_query, Some(limit), offset), + )) + } +} diff --git a/packages/rs-drive/src/drive/document/structure.rs b/packages/rs-drive/src/drive/document/structure.rs index 698c328a1de..3c2cf25a0db 100644 --- a/packages/rs-drive/src/drive/document/structure.rs +++ b/packages/rs-drive/src/drive/document/structure.rs @@ -10,6 +10,8 @@ const LEVEL_FLAGS: &str = "The owner is the owner of the document that created t system data, or created by a document of a type declaring a `ttl`, carry no flags."; const DOCUMENT: &str = "contracts.contract.documents.document_type.primary_key.document"; const REVISION: &str = "contracts.contract.documents.document_type.primary_key.document.revision"; +const RETAINED_REVISION: &str = + "contracts.contract.documents.document_type.history.document.revision"; const INDEX_PROPERTY: &str = "contracts.contract.documents.document_type.index_property"; const PRIMARY_KEY_TREES: [ElementKind; 9] = [ @@ -88,13 +90,17 @@ pub(crate) fn document_type() -> StructureNode { ElementKind::ItemWithSumItem, ElementKind::Tree, ElementKind::SumTree, + ElementKind::Reference, + ElementKind::ReferenceWithSumItem, ], "An item; with a sum when the document type is \ summable; a tree of revisions when it keeps \ - history.", + history before protocol version 15, and a reference \ + to its retained current revision from version 15.", ) .flags(&[FlagsKind::EpochOwned, FlagsKind::None], DOCUMENT_FLAGS) .value("serialized document") + .reference(RETAINED_REVISION) .describe("One document.") .children(vec![ StructureNode::fixed("latest", &[0], "Latest", "") @@ -103,6 +109,11 @@ pub(crate) fn document_type() -> StructureNode { "With a sum when the document type is summable.", ) .reference(REVISION) + .flags( + &[FlagsKind::EpochOwned, FlagsKind::None], + "The document owner when the contract can be deleted; otherwise no flags.", + ) + .until(14) .describe("A sibling reference to the newest revision."), StructureNode::dynamic( "revision", @@ -115,9 +126,29 @@ pub(crate) fn document_type() -> StructureNode { .kind(ElementKind::Item) .flags(&[FlagsKind::EpochOwned, FlagsKind::None], DOCUMENT_FLAGS) .value("serialized document") + .until(14) .describe("The document as it was at that time."), ]), ), + StructureNode::fixed("history", &[2], "History", "DOCUMENT_HISTORY_TREE_KEY") + .kind(ElementKind::Tree) + .flags(&[FlagsKind::EpochOwned, FlagsKind::None], CONTRACT_FLAGS) + .since(15) + .lazy() + .describe("Retained revisions of a type that keeps history, separate from its current primary entries.") + .child( + StructureNode::identifier("document", "document_id", "The document id") + .kind(ElementKind::ProvableCountTree) + .flags(&[FlagsKind::EpochOwned, FlagsKind::None], DOCUMENT_FLAGS) + .describe("One document's retained history, with an authenticated revision count.") + .child( + StructureNode::dynamic("revision", "block_time_and_revision", KeyMatcher::Len(16), KeyEncoding::Composite, "The block time followed by the revision, both unsigned u64 big endian") + .kind(ElementKind::Item) + .flags(&[FlagsKind::EpochOwned, FlagsKind::None], DOCUMENT_FLAGS) + .value("serialized document") + .describe("An immutable retained revision."), + ), + ), StructureNode::dynamic( "index_property", "index_property_name", diff --git a/packages/rs-drive/src/drive/document/update/internal/update_document_for_contract_operations/mod.rs b/packages/rs-drive/src/drive/document/update/internal/update_document_for_contract_operations/mod.rs index 5a6d4e397cd..e0d6eea48aa 100644 --- a/packages/rs-drive/src/drive/document/update/internal/update_document_for_contract_operations/mod.rs +++ b/packages/rs-drive/src/drive/document/update/internal/update_document_for_contract_operations/mod.rs @@ -1,5 +1,6 @@ mod v0; mod v1; +mod v2; use crate::drive::Drive; use crate::util::estimated_layers::EstimatedLayers; @@ -100,9 +101,20 @@ impl Drive { transaction, platform_version, ), + // v2 (platform v15+): keeps the v1 shared-prefix index fixes + // and addresses current keep-history documents directly in the + // primary-key tree. + 2 => self.update_document_for_contract_operations_v2( + document_and_contract_info, + block_info, + previous_batch_operations, + estimated_costs_only_with_layer_info, + transaction, + platform_version, + ), version => Err(Error::Drive(DriveError::UnknownVersionMismatch { method: "update_document_for_contract_operations".to_string(), - known_versions: vec![0, 1], + known_versions: vec![0, 1, 2], received: version, })), } diff --git a/packages/rs-drive/src/drive/document/update/internal/update_document_for_contract_operations/v2/mod.rs b/packages/rs-drive/src/drive/document/update/internal/update_document_for_contract_operations/v2/mod.rs new file mode 100644 index 00000000000..cd8adae9398 --- /dev/null +++ b/packages/rs-drive/src/drive/document/update/internal/update_document_for_contract_operations/v2/mod.rs @@ -0,0 +1,1720 @@ +use crate::drive::constants::CONTRACT_DOCUMENTS_PATH_HEIGHT; +use crate::drive::document::expiration::pricing::{ + document_expiration_cleanup_fee_for_bytes, document_remaining_lifetime_ms, document_ttl_pricing, +}; +use crate::drive::document::index_level_tree_types::{ + continuation_contributes_zero, document_takes_part_in_index, + index_level_tree_types_with_continuation_demotion, terminal_member_tree_type_for_aggregates, + IndexLevelTreeTypes, +}; +use crate::drive::document::time_range_ttl::{entry_key_bucket_start, live_time_range_entry_keys}; +use crate::drive::document::{ + make_document_reference_v1, make_document_reference_with_sum_item_v1, + read_document_sum_contribution, +}; +use crate::util::estimated_layers::EstimatedLayers; + +use crate::drive::document::derived_index_values::set_derived_index_values; +use crate::drive::Drive; +use crate::error::drive::DriveError; +use crate::error::Error; +use crate::fees::op::LowLevelDriveOperation; +use crate::util::grove_operations::{ + BatchDeleteUpTreeApplyType, BatchInsertApplyType, BatchInsertTreeApplyType, DirectQueryType, + QueryType, +}; +use crate::util::object_size_info::DocumentInfo::{ + DocumentEstimatedAverageSize, DocumentOwnedInfo, +}; +use crate::util::object_size_info::DriveKeyInfo::{Key, KeyRef, KeySize}; +use crate::util::object_size_info::PathKeyElementInfo::PathKeyRefElement; +use crate::util::object_size_info::{ + DocumentAndContractInfo, DocumentInfo, DocumentInfoV0Methods, DriveKeyInfo, OwnedDocumentInfo, + PathKeyInfo, +}; +use crate::util::storage_flags::StorageFlags; +use dpp::block::block_info::BlockInfo; +use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::data_contract::document_type::accessors::{DocumentTypeV0Getters, DocumentTypeV2Getters}; + +use dpp::document::document_methods::DocumentMethodsV0; +use dpp::document::serialization_traits::DocumentPlatformConversionMethodsV0; +use dpp::document::{Document, DocumentV0Getters}; +use dpp::fee::fee_result::FeeResult; + +use crate::drive::document::paths::{ + contract_document_type_path, contract_documents_primary_key_path, +}; +use dpp::data_contract::document_type::methods::{DocumentTypeBasicMethods, DocumentTypeV0Methods}; +use dpp::data_contract::document_type::{DocumentTypeRef, Index, IndexBucketing, IndexLevel}; +use dpp::version::PlatformVersion; +use grovedb::batch::key_info::KeyInfo; +use grovedb::batch::key_info::KeyInfo::KnownKey; +use grovedb::batch::KeyInfoPath; +use grovedb::{Element, MaybeTree, TransactionArg}; +use itertools::Itertools; +use std::borrow::Cow; +use std::collections::HashSet; + +/// Whether an old-document indexed-field value read back from storage is +/// null/absent — the counterpart of `document_top_field.is_empty()` on the +/// new-document side (a null or missing indexed property reads back as an +/// empty key). `KeySize` never reaches the stateful update path (worst-case +/// cost estimation is redirected to the insert walker at the top of +/// `update_document_for_contract_operations_v2`), so it is treated as +/// non-null. +fn drive_key_info_is_empty(key_info: &DriveKeyInfo) -> bool { + match key_info { + Key(key) => key.is_empty(), + KeyRef(key_ref) => key_ref.is_empty(), + KeySize(_) => false, + } +} + +/// The keys of a stored-values index path, for a read of what is stored +/// there. `KeySize` never reaches the stateful update path (see +/// [`drive_key_info_is_empty`]). +fn known_index_path(path: &[DriveKeyInfo]) -> Result>, Error> { + path.iter() + .map(|key_info| match key_info { + Key(key) => Ok(key.clone()), + KeyRef(key_ref) => Ok(key_ref.to_vec()), + KeySize(_) => Err(Error::Drive(DriveError::CorruptedCodeExecution( + "a stateful update walks known index paths", + ))), + }) + .collect() +} + +impl Drive { + /// Gathers operations for updating a document. + /// + /// v2 (platform v15+) is v1 with the keep-history primary layout of + /// protocol 15: the old document is read from the primary-key entry + /// itself instead of the per-document history subtree, and index + /// references are built by the v1 reference builders, which point at + /// that entry. Everything below describes the v1 behaviour it keeps. + /// + /// v1 (platform v14+) applies the shared-prefix aggregate fix to the + /// branches a key-changing update materializes, keeping them + /// bit-identical to what the v2 insert walkers would have written: + /// + /// - value-tree and property-name tree types derive through the shared + /// [`index_level_tree_types_with_continuation_demotion`] helper, so + /// provable count-bearing value trees with compound continuations + /// demote to `CountSumTree` exactly as on insert; + /// - continuation property-name trees created under an aggregating + /// value tree go through + /// [`Drive::batch_insert_empty_tree_contributing_zero_to_aggregating_parent_if_not_exists`], + /// so they contribute zero to every axis the parent aggregates. v0 + /// inserted them unwrapped, which would let a continuation's own + /// aggregates leak into the per-value count/sum. + /// + /// The same helper resolves the property-name tree through + /// [`crate::drive::document::ranked_index_tree_type`], so a branch + /// materialized here for a ranked (meta schema v3) index comes back + /// as the matching *indexed* tree with its ranking axes, not as a + /// plain tree whose secondaries nothing would maintain. A + /// key-changing update can be the operation that re-materializes a + /// property-name tree an earlier delete drained away, so it has to + /// reproduce that layout exactly. `ranked_axes` is empty for every + /// pre-v14 contract. + /// + /// v1 also fixes the terminator layout dispatch to agree with the + /// insert and delete walkers on null-bearing entries. v0 + /// dispatched unique vs + /// non-unique layout on `all_fields_null` (AND across indexed + /// fields) — and its old-entry delete on `!index.unique` alone — + /// while the insert walker's + /// `add_reference_for_index_level_for_contract_operations_v0` uses + /// `!is_unique || any_fields_null` plus an all-null skip for + /// `nullSearchable: false` indexes. Under v0, updating a document + /// holding a unique index with SOME null fields moved its entry + /// into the unique layout (bare reference at key `[0]`) where no + /// query or delete would find it, and deleted the old entry with + /// the wrong key. v1 uses the insert walker's dispatch on both + /// sides, computing the old entry's layout from the old document's + /// nullness and the new entry's from the new document's. + /// + /// The `[0]` reference-bucket tree-type dispatch and everything + /// else match v0. + pub(in crate::drive::document::update) fn update_document_for_contract_operations_v2( + &self, + document_and_contract_info: DocumentAndContractInfo, + block_info: &BlockInfo, + previous_batch_operations: &mut Option<&mut Vec>, + estimated_costs_only_with_layer_info: &mut Option, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result, Error> { + let drive_version = &platform_version.drive; + let mut batch_operations: Vec = vec![]; + // A document whose type declares a `ttl` stays without storage flags when replaced, + // transferred, bought or repriced. Dropped before anything is sized, so the replaced + // elements' sizes agree with what is stored. + let document_and_contract_info = + document_and_contract_info.without_storage_flags_if_expiring(); + if !document_and_contract_info.document_type.requires_revision() + // if it requires revision then there are reasons for us to be able to update in drive + { + return Err(Error::Drive(DriveError::UpdatingReadOnlyImmutableDocument( + "this document type is not mutable", + ))); + } + + // If we are going for estimated costs do an add instead as it always worse than an update + if document_and_contract_info + .owned_document_info + .document_info + .is_document_size() + || estimated_costs_only_with_layer_info.is_some() + { + let contract = document_and_contract_info.contract; + let document_type = document_and_contract_info.document_type; + let mut operations = self.estimate_document_change_as_insert_operations_v1( + document_and_contract_info, + block_info, + previous_batch_operations, + estimated_costs_only_with_layer_info, + transaction, + platform_version, + )?; + // A change of a document whose type indexes the elements of a typed array + // (protocol version 14) can remove far more index entries than it writes: + // emptying the list, or moving the entries to a new owner, removes one per + // element in every window. The insert above prices the new version only, + // so the removal of the stored version's entries is priced too, at its + // worst case (`maxItems` estimated elements per array), as a delete prices + // it. No other type can hold a typed array index. + if estimated_costs_only_with_layer_info.is_some() + && document_type + .indexes() + .values() + .any(|index| index.indexed_array.is_some()) + { + let stored = DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentEstimatedAverageSize( + document_type.estimated_size(platform_version)? as u32, + ), + owner_id: None, + }, + contract, + document_type, + }; + self.remove_indices_for_top_index_level_for_contract_operations( + &stored, + previous_batch_operations, + estimated_costs_only_with_layer_info, + block_info.time_ms, + transaction, + &mut operations, + platform_version, + )?; + } + return Ok(operations); + } + + // A type with derived index properties (protocol version 14) keys its documents by + // values read from the documents its references point at: read here for the new + // version, and taken from it for the old one below, whose references are the same. + // Every other type passes through unchanged. + let document_and_contract_info = self.with_derived_index_values( + document_and_contract_info, + false, + transaction, + &mut batch_operations, + platform_version, + )?; + + let contract = document_and_contract_info.contract; + let document_type = document_and_contract_info.document_type; + let owner_id = document_and_contract_info.owned_document_info.owner_id; + let Some((document, storage_flags)) = document_and_contract_info + .owned_document_info + .document_info + .get_borrowed_document_and_storage_flags() + else { + return Err(Error::Drive(DriveError::CorruptedCodeExecution( + "must have document and storage flags", + ))); + }; + // we need to construct the path for documents on the contract + // the path is + // * Document andDataContract root tree + // *DataContract ID recovered from document + // * 0 to signify Documents and notDataContract + let contract_document_type_path = + contract_document_type_path(contract.id_ref().as_bytes(), document_type.name()); + + let contract_documents_primary_key_path = + contract_documents_primary_key_path(contract.id_ref().as_bytes(), document_type.name()); + + // Per-document reference is built per-index below because + // summable indexes need `Element::ReferenceWithSumItem` (sum + // contribution propagates to ancestor sum trees) while plain + // indexes use `Element::Reference`. The non-sum reference is + // computed once here for reuse on all non-summable indexes; + // summable indexes build their own variant inside the loop. + let document_reference = make_document_reference_v1( + document, + document_and_contract_info.document_type, + storage_flags, + ); + + // next we need to get the old document from storage + let old_document_element = if document_type.documents_keep_history() { + self.grove_get( + (&contract_documents_primary_key_path).into(), + document.id().as_slice(), + QueryType::StatefulQuery, + transaction, + &mut batch_operations, + drive_version, + )? + } else { + self.grove_get_raw( + (&contract_documents_primary_key_path).into(), + document.id().as_slice(), + DirectQueryType::StatefulDirectQuery, + transaction, + &mut batch_operations, + drive_version, + )? + }; + + // we need to store the document for it's primary key + // we should be overriding if the document_type does not have history enabled + self.add_document_to_primary_storage( + &document_and_contract_info, + block_info, + true, + estimated_costs_only_with_layer_info, + transaction, + &mut batch_operations, + platform_version, + )?; + + // The stored size of the document before the change, which a type with a `ttl` needs + // to prepay the deletion of the bytes the change adds. + let old_document_bytes: u64; + let old_document_info = if let Some(old_document_element) = old_document_element { + // Accept BOTH plain `Item` (non-summable doctypes) AND + // `ItemWithSumItem` (summable doctypes — primary storage on + // doctypes with `documents_summable: Some(_)` is written as + // ItemWithSumItem by `add_document_to_primary_storage`). + // The sum_value is discarded here because the reload only + // needs the document body + flags; the new write below + // re-computes the sum from the freshly-supplied document. + let (old_serialized_document, element_flags) = match old_document_element { + Element::Item(bytes, flags) => (bytes, flags), + Element::ItemWithSumItem(bytes, _sum_value, flags) => (bytes, flags), + _ => { + return Err(Error::Drive(DriveError::CorruptedDocumentNotItem( + "old document is not an item or item-with-sum-item", + ))) + } + }; + old_document_bytes = old_serialized_document.len() as u64; + let mut old_document = Document::from_bytes( + old_serialized_document.as_slice(), + document_type, + platform_version, + )?; + if !document_type.derived_index_properties().is_empty() { + let values = self.derived_index_values( + &old_document, + Some(document), + contract, + document_type, + false, + transaction, + &mut batch_operations, + platform_version, + )?; + set_derived_index_values(&mut old_document, values); + } + let storage_flags = StorageFlags::map_some_element_flags_ref(&element_flags)?; + DocumentOwnedInfo((old_document, storage_flags.map(Cow::Owned))) + } else { + return Err(Error::Drive(DriveError::UpdatingDocumentThatDoesNotExist( + "document being updated does not exist", + ))); + }; + + let mut batch_insertion_cache: HashSet>> = HashSet::new(); + // Pre-built tree of every index path in the doctype. Walking + // this in parallel with each `index.properties` chain below + // is how we pick the right aggregate `TreeType` at each + // branch we materialize on a key-changing update — matching + // exactly what the insert path's + // `add_indices_for_{top_index_,index_}level_for_contract_operations_v1` + // helpers would have chosen. Without this walk, an update + // that moves into a previously-unseen branch under an + // aggregate index would create the branch as `NormalTree` + // beneath a `ProvableCount*` / `ProvableSum*` parent — + // diverging from the insert path (consensus break). + let index_structure = document_type.index_structure(); + + // `skipIfAbsent`: the index holds an entry for a document only when + // the document carries every property of its skip set, so a replace + // that adds or drops such a property moves the document into or out + // of the index. The old entry is removed only when the old document + // took part, and the new one written (with the trees it hangs from) + // only when the new document takes part — exactly what the insert + // and delete walkers would have done. An index that skips both + // versions holds nothing of the document. Every index of a pre-v14 + // contract has an empty skip set, so both are `true` there. + // + // An index the document leaves (the old version takes part, the new + // one does not) only removes its old entry, and that entry's upward + // prune can empty a tree another index enters in this same replace. + // So the leaving indexes run last, after every other index has + // queued its writes, where their prunes see those writes and stop + // below any tree still in use. Without a skip index no index leaves, + // and the order is the index map's. + let mut participating_indexes = Vec::with_capacity(document_type.indexes().len()); + let mut leaving_indexes = Vec::new(); + for index in document_type.indexes().values() { + let new_takes_part = document_takes_part_in_index( + &index.skip_if_absent_properties, + &document_and_contract_info.owned_document_info.document_info, + document_type, + )?; + let old_takes_part = document_takes_part_in_index( + &index.skip_if_absent_properties, + &old_document_info, + document_type, + )?; + if old_takes_part && !new_takes_part { + leaving_indexes.push((index, new_takes_part, old_takes_part)); + } else if new_takes_part { + participating_indexes.push((index, new_takes_part, old_takes_part)); + } + } + participating_indexes.extend(leaving_indexes); + + // fourth we need to store a reference to the document for each index + for (index, new_takes_part, old_takes_part) in participating_indexes { + // at this point the contract path is to the contract documents + // for each index the top index component will already have been added + // when the contract itself was created + let mut index_path: Vec> = contract_document_type_path + .iter() + .map(|&x| Vec::from(x)) + .collect(); + let top_index_property = index.properties.first().ok_or(Error::Drive( + DriveError::CorruptedContractIndexes("invalid contract indices".to_string()), + ))?; + // A bucketed (time- or integer-range) index's top level is keyed + // by the property name qualified with the grid (`storage_key`), + // so different grids over one property live in sibling + // subtrees; a plain index keeps the bare name. The same key is + // both the path segment and the `IndexLevel` lookup below. + let top_level_key = index.level_key(0, &top_index_property.name); + index_path.push(Vec::from(top_level_key.as_bytes())); + + // Mirror the insert path's IndexLevel descent. We + // start at the top-level property's `IndexLevel` node — + // the same node `add_indices_for_top_index_level_..._v1` + // would feed to its `value_tree_type` dispatch — and + // descend one step per property in `index.properties` + // below, so at every branch we materialize the matching + // `IndexLevel` node is in hand. + // + // `index_structure` carries the upgrade across ALL + // indexes that share this path (a level can host both + // `byRecipient` and `byRecipientSentAt`; the aggregate + // type at depth 1 must reflect whichever terminator is + // there). Using `has_index_with_type()` on the descended + // node ensures we pick that upgrade rather than the + // currently-iterated index's own per-level flags. + let mut current_index_level = + index_structure + .sub_levels() + .get(&top_level_key) + .ok_or(Error::Drive(DriveError::CorruptedContractIndexes(format!( + "index structure missing top level '{}' for index '{}' — \ + doctype's IndexLevel tree must contain every property of every \ + registered index", + top_level_key, index.name + ))))?; + + // Per-index reference variant. Mirror of the insert path's + // dispatch in + // `add_reference_for_index_level_for_contract_operations` — + // summable indexes must emit `Element::ReferenceWithSumItem` + // so the per-document sum propagates into ancestor sum trees + // on every update. Without this branch, an update would + // overwrite an existing `ReferenceWithSumItem` with a plain + // `Reference`, silently dropping the doc's contribution + // from ancestor sum aggregates (the document body remains + // queryable but SUM/AVG proofs would exclude it — a soundness + // bug an attacker could trigger with any benign no-op update). + let index_document_reference = if let Some(sum_property_name) = &index.summable { + let sum_value = read_document_sum_contribution(document, sum_property_name)?; + make_document_reference_with_sum_item_v1( + document, + document_and_contract_info.document_type, + sum_value, + storage_flags, + ) + } else { + document_reference.clone() + }; + + let leaving = old_takes_part && !new_takes_part; + + // Bucketed (time- and integer-range) indexes store one entry per + // containing window, and an index naming an indexed typed array + // one per distinct element, so they need a set-diff update rather + // than the single old→new value transition below. + // `current_index_level` is still the top-level node and + // `index_path` is the base + // (…//) at this point. The + // transform and the element stamps are read off the `IndexLevel` + // nodes — the same source the insert and delete walkers branch on + // — so all three walkers agree even on a document type + // constructed outside full validation. (A level's key embeds its + // grid, so the node's transform is exactly the grid every index + // sharing this level declared.) + if current_index_level.bucketing().is_some() + || index_names_indexed_array(index, current_index_level) + { + // TTL'd (ephemeral) sub-levels ride their own op batch and carry + // no storage flags — same routing as the insert and delete + // walkers; see the ttl module's Billing section. Only a time + // grid can declare a ttl. + let index_is_ephemeral = current_index_level + .time_range() + .is_some_and(|transform| transform.ttl_seconds.is_some()); + let mut ephemeral_local_operations: Vec = vec![]; + // A leaving index only prunes, so its operations go straight + // into this replace's batch (retagged below): its prune has to + // see the writes every other index queued there. + let leaving_operations_start = batch_operations.len(); + let index_batch_operations: &mut Vec = + if index_is_ephemeral && !leaving { + &mut ephemeral_local_operations + } else { + &mut batch_operations + }; + let index_storage_flags = if index_is_ephemeral { + None + } else { + storage_flags + }; + self.update_fanned_out_index_for_contract_operations_v2( + index, + document, + new_takes_part, + &old_document_info, + old_takes_part, + owner_id, + document_type, + &index_path, + current_index_level, + &index_document_reference, + index_storage_flags, + &mut batch_insertion_cache, + previous_batch_operations, + index_batch_operations, + block_info.time_ms, + transaction, + platform_version, + )?; + if index_is_ephemeral { + let index_operations = if leaving { + batch_operations.drain(leaving_operations_start..).collect() + } else { + ephemeral_local_operations + }; + batch_operations.extend( + index_operations + .into_iter() + .map(LowLevelDriveOperation::retag_ephemeral), + ); + } + continue; + } + + // with the example of the dashpay contract's first index + // the index path is now something likeDataContracts/ContractID/Documents(1)/$ownerId + let document_top_field = document + .get_raw_for_document_type( + &top_index_property.name, + document_type, + owner_id, + platform_version, + )? + .unwrap_or_default(); + + let old_document_top_field = old_document_info + .get_raw_for_document_type( + &top_index_property.name, + document_type, + None, // We want to use the old owner id + None, + platform_version, + )? + .unwrap_or_default(); + + // if we are not applying that means we are trying to get worst case costs + // which would entail a change on every index + let mut change_occurred_on_index = match &old_document_top_field { + DriveKeyInfo::Key(k) => &document_top_field != k, + DriveKeyInfo::KeyRef(k) => document_top_field.as_slice() != *k, + DriveKeyInfo::KeySize(_) => { + // we should assume true in this worst case cost scenario + true + } + }; + // A document moving into or out of a skip index changes its entry + // even when the index values read back the same. + change_occurred_on_index |= new_takes_part != old_takes_part; + + // Post-demotion tree types for the top property's level — + // the exact types the v2 insert walkers would derive. The + // value-tree type is tracked as `parent_value_tree_type` + // regardless of whether this level changed: a deeper + // materialization below still needs to know what it hangs + // under. + let top_level_tree_types = + index_level_tree_types_with_continuation_demotion(current_index_level)?; + let mut parent_value_tree_type = top_level_tree_types.value_tree_type; + // A prefix-ranking chain level (`rankedCountable: { at }`) + // inverts the zero-contribution choice below: its value trees + // count exactly their single continuation, so the continuation + // is inserted unwrapped and contributes its subtree count — + // matching the v2 insert walker's dispatch. + let mut parent_counts_continuations = current_index_level.is_ranked_chain_level(); + + if change_occurred_on_index && new_takes_part { + // here we are inserting an empty tree that will have a subtree of all other index properties + let mut qualified_path = index_path.clone(); + qualified_path.push(document_top_field.clone()); + + if !batch_insertion_cache.contains(&qualified_path) { + // Top-level value tree: aggregate variant + // depending on whether any index terminates at + // the top property (e.g., a standalone + // `[recipient]` alongside `[recipient, sentAt]`) + // and what flags that terminator carries. + // Default for pure-prefix levels collapses to + // `NormalTree`, matching pre-v12 behavior. + let value_tree_type = top_level_tree_types.value_tree_type; + let inserted = self.batch_insert_empty_tree_if_not_exists( + PathKeyInfo::PathKeyRef::<0>(( + index_path.clone(), + document_top_field.as_slice(), + )), + value_tree_type, + storage_flags, + BatchInsertTreeApplyType::StatefulBatchInsertTree, + transaction, + previous_batch_operations, + &mut batch_operations, + drive_version, + )?; + if inserted { + batch_insertion_cache.insert(qualified_path); + } + } + } + + // Null accumulators for the terminator dispatch, tracked + // separately for the new and the old document: the entry + // being written lives in the layout the NEW document's + // nullness selects, while the entry being deleted lives in + // the layout the insert walker chose from the OLD + // document's nullness — and the two can differ within one + // update (e.g. a null field acquiring a value). `any` (OR) + // picks unique vs non-unique layout, `all` (AND) drives + // the `nullSearchable: false` skip; both mirror + // `add_reference_for_index_level_for_contract_operations_v0` + // exactly. v0 of this walker AND-accumulated a single + // `all_fields_null` and used it for both sides — so for a + // unique index with SOME null fields it wrote/deleted the + // unique layout while the insert walker had used the + // non-unique one, stranding the entry where no query (and + // no later delete) would look. + let old_document_top_field_is_empty = drive_key_info_is_empty(&old_document_top_field); + // An entry written before protocol version 14 can sit in another + // layout than the rule gives (see + // `drive::document::stored_index_entry`): a unique index's entry + // in the `[0]` tree although none of its own values is missing + // (an insert carried a sibling's missing value into this path), + // or as the bare reference although one is (update v0), and a + // `nullSearchable: false` entry the rule skips. Where one could + // disagree, the old entry's layout is read (unbilled). A type + // with a `ttl` exists only from version 14, so it holds none of + // these; indexOnly and contested indexes are laid out apart. + let reads_stored_entries = index.terminal.is_none() + && index.contested_index.is_none() + && document_type.documents_ttl_seconds().is_none(); + // Whether a sibling sub-level visited before this index's next + // property, on the old document's path, is missing its value: + // what the earlier walkers carried into this index. + let mut old_sibling_value_missing = false; + let mut any_fields_null = document_top_field.is_empty(); + let mut all_fields_null = document_top_field.is_empty(); + let mut old_any_fields_null = old_document_top_field_is_empty; + let mut old_all_fields_null = old_document_top_field_is_empty; + + let mut old_index_path: Vec = index_path + .iter() + .map(|path_item| DriveKeyInfo::Key(path_item.clone())) + .collect(); + // we push the actual value of the index path + index_path.push(document_top_field); + // the index path is now something likeDataContracts/ContractID/Documents(1)/$ownerId/ + + old_index_path.push(old_document_top_field); + + for i in 1..index.properties.len() { + let index_property = index.properties.get(i).ok_or(Error::Drive( + DriveError::CorruptedContractIndexes("invalid contract indices".to_string()), + ))?; + + if reads_stored_entries && index.unique && !old_sibling_value_missing { + for (sibling, sibling_level) in current_index_level + .sub_levels() + .iter() + .take_while(|(sibling, _)| sibling.as_str() < index_property.name.as_str()) + { + // The level of an indexed typed array (protocol version 14) carries + // no missing value: an element is never empty, and a document + // holding none takes no part in the indexes naming the array. Its + // value is a list, which no scalar read keys. + if sibling_level.indexes_array_elements() { + continue; + } + let old_sibling_value = old_document_info + .get_raw_for_document_type( + sibling, + document_type, + None, + None, + platform_version, + )? + .unwrap_or_default(); + if drive_key_info_is_empty(&old_sibling_value) { + old_sibling_value_missing = true; + break; + } + } + } + + // Descend one step in the doctype's `IndexLevel` + // tree, in lockstep with `index.properties`. Failure + // here means the IndexLevel tree was built from a + // different doctype than the one we're iterating — + // a corruption signal, not a user-input error. + current_index_level = current_index_level + .sub_levels() + .get(&index_property.name) + .ok_or(Error::Drive(DriveError::CorruptedContractIndexes(format!( + "index structure missing sub_level '{}' under index '{}' at depth {}", + index_property.name, index.name, i + ))))?; + + let sub_level_tree_types = + index_level_tree_types_with_continuation_demotion(current_index_level)?; + + let document_index_field = document + .get_raw_for_document_type( + &index_property.name, + document_type, + owner_id, + platform_version, + )? + .unwrap_or_default(); + + let old_document_index_field = old_document_info + .get_raw_for_document_type( + &index_property.name, + document_type, + None, // We want to use the old owner_id + None, + platform_version, + )? + .unwrap_or_default(); + + // if we are not applying that means we are trying to get worst case costs + // which would entail a change on every index + change_occurred_on_index |= match &old_document_index_field { + DriveKeyInfo::Key(k) => &document_index_field != k, + DriveKeyInfo::KeyRef(k) => document_index_field != *k, + DriveKeyInfo::KeySize(_) => { + // we should assume true in this worst case cost scenario + true + } + }; + + if change_occurred_on_index && new_takes_part { + // here we are inserting an empty tree that will have a subtree of all other index properties + + let mut qualified_path = index_path.clone(); + qualified_path.push(index_property.name.as_bytes().to_vec()); + + if !batch_insertion_cache.contains(&qualified_path) { + // Inner property-name tree at depth i+1 — a + // continuation hanging inside the previous + // level's value tree. When that parent + // aggregates (count, sum, or both) the + // continuation must contribute zero on every + // aggregated axis, exactly as on the insert + // path; v0 inserted it unwrapped, letting the + // continuation's aggregates leak into the + // per-value count/sum. A ranked level resolves + // to an indexed tree here, which the + // non-aggregating branch creates with its axes + // and the aggregating branch rejects (an + // indexed tree cannot live inside an + // aggregating value tree — see + // `INDEXED_INNER_UNWRAPPABLE` in `fees::op`). + let property_name_tree_type = sub_level_tree_types.property_name_tree_type; + let ranked_axes = sub_level_tree_types.ranked_axes.as_slice(); + // A count-exempt sibling branch (`count_exempt_branch`, + // stamped by the IndexLevel derivation) re-inverts the + // chain-level choice per child: even though the chain + // level counts its own continuation, the sibling's + // branch tree must be zero-wrapped so its entries + // never pollute the subtree totals — matching the v2 + // insert walker's dispatch. + let inserted = if !continuation_contributes_zero( + parent_value_tree_type, + parent_counts_continuations, + current_index_level, + ) { + self.batch_insert_empty_index_tree_if_not_exists( + PathKeyInfo::PathKeyRef::<0>(( + index_path.clone(), + index_property.name.as_bytes(), + )), + property_name_tree_type, + ranked_axes, + storage_flags, + BatchInsertTreeApplyType::StatefulBatchInsertTree, + transaction, + previous_batch_operations, + &mut batch_operations, + drive_version, + )? + } else { + self.batch_insert_empty_tree_contributing_zero_to_aggregating_parent_if_not_exists( + PathKeyInfo::PathKeyRef::<0>(( + index_path.clone(), + index_property.name.as_bytes(), + )), + parent_value_tree_type, + property_name_tree_type, + ranked_axes, + storage_flags, + BatchInsertTreeApplyType::StatefulBatchInsertTree, + transaction, + previous_batch_operations, + &mut batch_operations, + drive_version, + )? + }; + if inserted { + batch_insertion_cache.insert(qualified_path); + } + } + } + + index_path.push(Vec::from(index_property.name.as_bytes())); + old_index_path.push(DriveKeyInfo::Key(Vec::from(index_property.name.as_bytes()))); + + // Iteration 1. the index path is now something likeDataContracts/ContractID/Documents(1)/$ownerId//toUserId + // Iteration 2. the index path is now something likeDataContracts/ContractID/Documents(1)/$ownerId//toUserId//accountReference + + if change_occurred_on_index && new_takes_part { + // here we are inserting an empty tree that will have a subtree of all other index properties + + let mut qualified_path = index_path.clone(); + qualified_path.push(document_index_field.clone()); + + if !batch_insertion_cache.contains(&qualified_path) { + // Inner value tree at depth i+2: same + // dispatch as the top-level value tree + // above — aggregate variant when any index + // terminates at this level (this index or + // another sharing the prefix), post-demotion. + let value_tree_type = sub_level_tree_types.value_tree_type; + let inserted = self.batch_insert_empty_tree_if_not_exists( + PathKeyInfo::PathKeyRef::<0>(( + index_path.clone(), + document_index_field.as_slice(), + )), + value_tree_type, + storage_flags, + BatchInsertTreeApplyType::StatefulBatchInsertTree, + transaction, + previous_batch_operations, + &mut batch_operations, + drive_version, + )?; + if inserted { + batch_insertion_cache.insert(qualified_path); + } + } + } + + any_fields_null |= document_index_field.is_empty(); + all_fields_null &= document_index_field.is_empty(); + let old_document_index_field_is_empty = + drive_key_info_is_empty(&old_document_index_field); + old_any_fields_null |= old_document_index_field_is_empty; + old_all_fields_null &= old_document_index_field_is_empty; + + // The next-deeper continuation (if any) hangs inside + // this level's value tree. + parent_value_tree_type = sub_level_tree_types.value_tree_type; + parent_counts_continuations = current_index_level.is_ranked_chain_level(); + + // we push the actual value of the index path, both for the new and the old + index_path.push(document_index_field); + old_index_path.push(old_document_index_field); + // Iteration 1. the index path is now something likeDataContracts/ContractID/Documents(1)/$ownerId//toUserId// + // Iteration 2. the index path is now something likeDataContracts/ContractID/Documents(1)/$ownerId//toUserId//accountReference/ + } + + if change_occurred_on_index { + // we first need to delete the old values + // unique indexes will be stored under key "0" + // non unique indices should have a tree at key "0" that has all elements based off of primary key + // + // The old entry lives in the layout the insert walker + // chose from the OLD document's nullness (see the + // accumulators above): no entry at all when every + // indexed field was null on a `nullSearchable: false` + // index, the doc-id-keyed `[0]` bucket when the index + // is non-unique OR any old field was null, and the + // bare reference at key `[0]` only for a unique index + // with no old nulls. Same dispatch as + // `remove_reference_for_index_level_for_contract_operations_v0`. + // `Some(in_tree)` when the old document has an entry here: + // `in_tree` for the doc-id-keyed `[0]` tree, else the bare + // reference at key `[0]`. + let old_entry_layout = if !old_takes_part { + // the index skipped the old document — nothing to delete + None + } else if old_all_fields_null && !index.null_searchable { + // the rule gives no entry when every indexed field is + // null on a `nullSearchable: false` index; an earlier + // version may have written one, in the `[0]` tree + (reads_stored_entries + && self.index_entry_in_tree_exists( + &known_index_path(&old_index_path)?, + document.id().as_slice(), + transaction, + drive_version, + )?) + .then_some(true) + } else if reads_stored_entries + && index.unique + && (old_any_fields_null || old_sibling_value_missing) + { + Some(self.stored_index_entry_is_tree( + &known_index_path(&old_index_path)?, + old_any_fields_null, + transaction, + drive_version, + )?) + } else { + Some(!index.unique || old_any_fields_null) + }; + if let Some(old_entry_in_tree) = old_entry_layout { + let mut key_info_path = KeyInfoPath::from_vec( + old_index_path + .into_iter() + .map(|key_info| match key_info { + Key(key) => KnownKey(key), + KeyRef(key_ref) => KnownKey(key_ref.to_vec()), + KeySize(key_info) => key_info, + }) + .collect::>(), + ); + + if old_entry_in_tree { + key_info_path.push(KnownKey(vec![0])); + + // here we should return an error if the element already exists + self.batch_delete_up_tree_while_empty( + key_info_path, + document.id().as_slice(), + Some(CONTRACT_DOCUMENTS_PATH_HEIGHT), + BatchDeleteUpTreeApplyType::StatefulBatchDelete { + is_known_to_be_subtree_with_sum: Some(MaybeTree::NotTree), + }, + transaction, + previous_batch_operations, + &mut batch_operations, + drive_version, + )?; + } else { + // here we should return an error if the element already exists + self.batch_delete_up_tree_while_empty( + key_info_path, + &[0], + Some(CONTRACT_DOCUMENTS_PATH_HEIGHT), + BatchDeleteUpTreeApplyType::StatefulBatchDelete { + is_known_to_be_subtree_with_sum: Some(MaybeTree::NotTree), + }, + transaction, + previous_batch_operations, + &mut batch_operations, + drive_version, + )?; + } + } + + // unique indexes will be stored under key "0" + // non unique indices should have a tree at key "0" that has all elements based off of primary key + if !new_takes_part || (all_fields_null && !index.null_searchable) { + // The insert walker writes no entry when the index + // skips the document, or when every indexed field is + // null on a `nullSearchable: false` index — write + // nothing here either, or the update would create an + // entry that insert/delete walkers never expect to + // exist. + } else if !index.unique || any_fields_null { + // here we are inserting an empty tree that will have a subtree of all other index properties + // + // Terminator `[0]` reference bucket: same + // dispatch as + // `add_reference_for_index_level_for_contract_operations_v0` + // — this is the leaf tree the insert path + // installs under the terminator value, and it + // must carry the index's count + sum aggregates + // so per-value `count_value_or_default()` / + // `sum_value_or_default()` walks at the parent + // value tree resolve to the right totals. + // + // Unlike the value/property-name dispatches + // above, this shared dispatch distinguishes + // `Countable` (→ `CountTree`) from + // `CountableAllowingOffset` (→ `ProvableCountTree`), + // matching the insert path's terminator bucket + // exactly. + let reference_tree_type = terminal_member_tree_type_for_aggregates( + index.countable, + index.summable.is_some(), + index.range_summable, + ); + self.batch_insert_empty_tree_if_not_exists( + PathKeyInfo::PathKeyRef::<0>((index_path.clone(), &[0])), + reference_tree_type, + storage_flags, + BatchInsertTreeApplyType::StatefulBatchInsertTree, + transaction, + previous_batch_operations, + &mut batch_operations, + drive_version, + )?; + index_path.push(vec![0]); + + // here we should return an error if the element already exists + self.batch_insert( + PathKeyRefElement::<0>(( + index_path, + document.id().as_slice(), + index_document_reference.clone(), + )), + &mut batch_operations, + drive_version, + )?; + } else { + // in one update you can't insert an element twice, so need to check the cache + // here we should return an error if the element already exists + let inserted = self.batch_insert_if_not_exists( + PathKeyRefElement::<0>(( + index_path, + &[0], + index_document_reference.clone(), + )), + BatchInsertApplyType::StatefulBatchInsert, + transaction, + &mut batch_operations, + drive_version, + )?; + if !inserted { + return Err(Error::Drive(DriveError::CorruptedContractIndexes( + "index already exists".to_string(), + ))); + } + } + } else { + // no change occurred on index, we need to refresh the references + // (both versions take part: a change in participation counts + // as a change, and an index skipping both was passed by above) + + // We can only trust the reference content has not changed if there are no storage flags + let trust_refresh_reference = storage_flags.is_none(); + + // unique indexes will be stored under key "0" + // non unique indices should have a tree at key "0" that has all elements based off of primary key + // + // No change occurred on this index, so the old and new + // nullness are identical and the new-document + // accumulators describe the stored entry's layout, save + // where an earlier version may have laid it out otherwise + // (the stored layout decides, as for the old entry above). + if all_fields_null && !index.null_searchable { + // nothing is stored for this document under this + // index — nothing to refresh + } else { + let entry_in_tree = if reads_stored_entries + && index.unique + && (old_any_fields_null || old_sibling_value_missing) + { + self.stored_index_entry_is_tree( + &index_path, + any_fields_null, + transaction, + drive_version, + )? + } else { + !index.unique || any_fields_null + }; + if entry_in_tree { + index_path.push(vec![0]); + + // here we should return an error if the element already exists + self.batch_refresh_reference( + index_path, + document.id().to_vec(), + index_document_reference.clone(), + trust_refresh_reference, + &mut batch_operations, + drive_version, + )?; + } else { + self.batch_refresh_reference( + index_path, + vec![0], + index_document_reference.clone(), + trust_refresh_reference, + &mut batch_operations, + drive_version, + )?; + } + } + } + } + + // A document whose type declares a `ttl` pays for the bytes a change adds by the + // lifetime it has left; its `$createdAt`, and so its expiry and its expirations tree + // entry, never change. Its creation prepaid its deletion; a change that grows it + // prepays the deletion of the bytes it adds. + if let Some(ttl_seconds) = document_type.documents_ttl_seconds() { + let pricing = document_ttl_pricing( + document_remaining_lifetime_ms( + document.created_at(), + ttl_seconds, + block_info.time_ms, + )?, + self.config.epoch_time_length_s, + self.config.epochs_per_era, + &platform_version.fee_version, + )?; + batch_operations = batch_operations + .into_iter() + .map(|operation| operation.retag_document_ttl(pricing)) + .collect(); + let added_bytes = (document + .serialize(document_type, contract, platform_version)? + .len() as u64) + .saturating_sub(old_document_bytes); + if added_bytes > 0 { + batch_operations.push(LowLevelDriveOperation::PreCalculatedFeeResult(FeeResult { + processing_fee: document_expiration_cleanup_fee_for_bytes( + added_bytes, + &platform_version.fee_version, + )?, + ..Default::default() + })); + } + } + Ok(batch_operations) + } + + /// Updates the index entries for a single index that enters a document + /// under several entries: a **bucketed** (time- or integer-range) index, + /// whose first property puts the document in one entry per window its + /// value falls into, an index naming an **indexed typed array** (protocol + /// version 14), which puts it in one entry per distinct element, or both. + /// + /// An entry is the document's key at every position of the index, so + /// the entries are the product of the keys at each position, and an + /// update is a set diff of the old and the new entries rather than the + /// single old→new transition the normal-index path performs: + /// - entries only the old document has are removed, + /// - entries only the new document has are inserted, + /// - entries both have are refreshed in place. + /// An entry whose window or element both versions share but whose other + /// values changed is a different entry, so it is deleted under the old + /// values and inserted under the new ones. + /// + /// The window keys mirror the insert walker exactly: a decodable + /// timestamp yields one key per containing bucket (none when the + /// timestamp predates the transform's origin), a null timestamp yields the + /// single ordinary null key, and a non-null value that fails to decode + /// yields its raw key — so null→value, value→null and null→null + /// transitions maintain the same entries insert and delete would. The + /// element keys are the document's distinct elements, which a document + /// taking part in the index always has (the array is in its skip set). + /// + /// Time-range indexes are validated to be non-contested, but they may be + /// unique when the windows do not overlap (`range == step`) and the source + /// is `$createdAt`, so both terminator layouts occur here and are chosen + /// exactly as the insert and delete walkers choose them + /// (`!unique || any_fields_null`): the non-unique layout stores the + /// reference under `…//[0]/`, the unique layout stores it + /// AT `…//[0]`. The predicate is evaluated separately for the new + /// and the old document, because the layout an entry was *written* under + /// is the layout it must be *deleted* under. An index naming a typed + /// array is never unique. + /// + /// (With a `$createdAt` source and overlap factor 1 the bucket set can + /// never change on an update — the timestamp is immutable and yields + /// exactly one bucket — so on a unique time-range index only the + /// changed-values arms below are reachable; a unique integer-range index + /// moves between windows when its value does. The layout dispatch is + /// nonetheless applied to every arm rather than reasoned away per arm: + /// the arms are shared with + /// non-unique indexes, and a future relaxation of the uniqueness rules + /// must not silently resurrect the wrong layout.) + /// + /// The estimated-cost / document-size update path never reaches this + /// method — it delegates to the insert path, which has its own fan-out. + #[allow(clippy::too_many_arguments)] + fn update_fanned_out_index_for_contract_operations_v2( + &self, + index: &Index, + document: &Document, + new_takes_part: bool, + old_document_info: &DocumentInfo, + old_takes_part: bool, + owner_id: Option<[u8; 32]>, + document_type: DocumentTypeRef, + base_index_path: &[Vec], + top_index_level: &IndexLevel, + index_document_reference: &Element, + storage_flags: Option<&StorageFlags>, + batch_insertion_cache: &mut HashSet>>, + previous_batch_operations: &mut Option<&mut Vec>, + batch_operations: &mut Vec, + block_time_ms: u64, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result<(), Error> { + let drive_version = &platform_version.drive; + + // TTL drainage already ran: the caller sweeps every TTL'd level + // once (deduplicated) before the per-index loop, so the removable + // checks below see post-drain state and no direct drop can race a + // queued mutation. Do not drain here — several indexes may share + // this level. + + // Only a time grid can declare a ttl; an integer grid never expires. + let bucketing = top_index_level.bucketing(); + let ttl_transform = bucketing.and_then(IndexBucketing::time_range); + + // The document's keys at each position of the index, for the new and + // the old document, plus the IndexLevel node below the first position + // with its (pure, hoisted) tree-type derivation — the entry loops below + // run once per entry and must not re-derive per iteration. + // + // Terminator-layout inputs are tracked separately for the new and the + // old document. The insert and delete walkers demote a unique index to + // the non-unique layout as soon as ANY indexed field is null + // (`any_fields_null`, accumulated with OR down the level recursion), so + // an entry's layout is a property of the document that wrote it — the + // delete below must therefore use the OLD document's verdict, not the + // new one's. A null bucketed source yields the single empty entry key, + // which is exactly the null case here; an element is never null. + let mut levels: Vec<(&IndexLevel, IndexLevelTreeTypes)> = Vec::new(); + let mut new_key_sets: Vec>> = Vec::with_capacity(index.properties.len()); + let mut old_key_sets: Vec>> = Vec::with_capacity(index.properties.len()); + let mut new_any_fields_null = false; + let mut old_any_fields_null = false; + let mut current_level = top_index_level; + for (position, index_property) in index.properties.iter().enumerate() { + if position > 0 { + current_level = + current_level + .sub_levels() + .get(&index_property.name) + .ok_or(Error::Drive(DriveError::CorruptedContractIndexes(format!( + "index structure missing sub_level '{}' under index '{}'", + index_property.name, index.name + ))))?; + levels.push(( + current_level, + index_level_tree_types_with_continuation_demotion(current_level)?, + )); + } + + if current_level.indexes_array_elements() { + // One key per distinct element, as the insert walker writes them. + new_key_sets.push(document.get_raw_array_elements_for_document_type( + &index_property.name, + document_type, + platform_version, + )?); + old_key_sets.push(known_index_path( + &old_document_info.get_raw_array_elements_for_document_type( + &index_property.name, + document_type, + None, + platform_version, + )?, + )?); + continue; + } + + // The first property of a bucketed index is read from its source + // property: the level key is the source qualified with the grid. + let source = match bucketing { + Some(bucketing) if position == 0 => bucketing.source(), + _ => index_property.name.as_str(), + }; + let new_raw = document + .get_raw_for_document_type(source, document_type, owner_id, platform_version)? + .unwrap_or_default(); + let old_raw = match old_document_info.get_raw_for_document_type( + source, + document_type, + None, // We want to use the old owner id + None, + platform_version, + )? { + Some(Key(k)) => k, + Some(KeyRef(k)) => k.to_vec(), + _ => Vec::new(), + }; + new_any_fields_null |= new_raw.is_empty(); + old_any_fields_null |= old_raw.is_empty(); + + match bucketing { + // The entry-key rule (null → single null entry, pre-origin → + // no entries, undecodable → raw key, decodable → containing + // buckets) is shared with the insert and delete walkers via + // `IndexBucketing::entry_keys_for_raw` — one definition, so + // the three walkers can never disagree. + Some(bucketing) if position == 0 => { + new_key_sets.push(bucketing.entry_keys_for_raw(&new_raw)); + old_key_sets.push(bucketing.entry_keys_for_raw(&old_raw)); + } + _ => { + new_key_sets.push(vec![new_raw]); + old_key_sets.push(vec![old_raw]); + } + } + } + + // TTL: writes never target expired buckets — an update of a document + // whose windows have all expired leaves it with no entries under + // this index, and never resurrects a dropped bucket. The old set is + // NOT filtered: its expired keys flow to the delete loop below, + // whose per-key removable check skips exactly the buckets the lazy + // drop already took. + if let (Some(transform), Some(window_keys)) = (ttl_transform, new_key_sets.first_mut()) { + *window_keys = + live_time_range_entry_keys(transform, std::mem::take(window_keys), block_time_ms); + } + + // `skipIfAbsent`: a version of the document the index skips has no + // entries in it, so its side of the set diff is empty — a document + // moving into the index inserts every new entry, one moving out + // deletes every old one. + let new_entries = if new_takes_part { + index_entries(&new_key_sets) + } else { + Vec::new() + }; + let old_entries = if old_takes_part { + index_entries(&old_key_sets) + } else { + Vec::new() + }; + + // The two terminator layouts, mirroring + // `add_reference_for_index_level_for_contract_operations_v0`'s + // `!index_type.index_type.is_unique() || any_fields_null` dispatch. + let new_terminator_is_unique = index.unique && !new_any_fields_null; + let old_terminator_is_unique = index.unique && !old_any_fields_null; + + let reference_tree_type = terminal_member_tree_type_for_aggregates( + index.countable, + index.summable.is_some(), + index.range_summable, + ); + let top_level_tree_types = + index_level_tree_types_with_continuation_demotion(top_index_level)?; + let top_value_tree_type = top_level_tree_types.value_tree_type; + let doc_id = document.id(); + + let new_set: HashSet<&Vec<&[u8]>> = new_entries.iter().collect(); + let old_set: HashSet<&Vec<&[u8]>> = old_entries.iter().collect(); + // The trees the inserts below found already standing: entries share + // the trees above the array's level, and each is read once. The + // insertion cache keeps the trees this batch inserts; nothing below + // deletes before the inserts are done. + let mut standing_trees: HashSet>> = HashSet::new(); + + // Insert/refresh new entries FIRST (see the ordering note on the + // delete loop below): added entries are inserted; common entries are + // refreshed. + for entry in &new_entries { + let Some((&entry_key, entry_values)) = entry.split_first() else { + continue; + }; + if old_set.contains(entry) { + // Unchanged entry — refresh the stored reference in place + // (its content can still differ via storage flags). An entry + // can only be in both sets when every value's null-ness + // matched (a null raw yields the empty key, a non-null one a + // non-empty key), so the old and new layouts coincide and + // either verdict describes the entry on disk. + let mut path: Vec> = base_index_path.to_vec(); + path.push(entry_key.to_vec()); + for (index_property, value) in index.properties.iter().skip(1).zip(entry_values) { + path.push(index_property.name.as_bytes().to_vec()); + path.push(value.to_vec()); + } + let (refresh_key, refresh_path) = if new_terminator_is_unique { + // Unique layout: the reference lives AT `[0]`. + (vec![0], path) + } else { + // Non-unique layout: `[0]` is a tree of doc-id-keyed + // references. + path.push(vec![0]); + (doc_id.to_vec(), path) + }; + self.batch_refresh_reference( + refresh_path, + refresh_key, + index_document_reference.clone(), + storage_flags.is_none(), + batch_operations, + drive_version, + )?; + continue; + } + + // Materialize every tree along the entry path — the same + // post-demotion tree types and zero-contribution wrappers the + // insert walkers use — then store the reference. The insertion + // cache prevents duplicate empty-tree operations when several + // indexes produce the same qualified path. Indexes sharing a + // first property need NOT share a transform (grids fork into + // sibling subtrees via their grid-qualified level keys), which + // is exactly why the cache keys on the full qualified path + // rather than the property name. + let mut path: Vec> = base_index_path.to_vec(); + let mut qualified_path = path.clone(); + qualified_path.push(entry_key.to_vec()); + if !batch_insertion_cache.contains(&qualified_path) + && !standing_trees.contains(&qualified_path) + { + let inserted = self.batch_insert_empty_tree_if_not_exists( + PathKeyInfo::PathKeyRef::<0>((path.clone(), entry_key)), + top_value_tree_type, + storage_flags, + BatchInsertTreeApplyType::StatefulBatchInsertTree, + transaction, + previous_batch_operations, + batch_operations, + drive_version, + )?; + if inserted { + batch_insertion_cache.insert(qualified_path); + } else { + standing_trees.insert(qualified_path); + } + } + path.push(entry_key.to_vec()); + + let mut parent_value_tree_type = top_value_tree_type; + // A prefix-ranking chain level (`rankedCountable: { at }`) + // inverts the zero-contribution choice below, exactly as in the + // non-bucketed branch above and the v2 insert walker: a chain + // level's value trees count their single continuation, so the + // continuation is inserted unwrapped and contributes its + // subtree count. The bucketed level itself can never be a + // grouping level (validation rejects `at` naming the transform + // source), but the stamps are read rather than assumed so the + // three walkers share one rule. + let mut parent_counts_continuations = top_index_level.is_ranked_chain_level(); + for (((level, sub_level_tree_types), index_property), value) in levels + .iter() + .zip(index.properties.iter().skip(1)) + .zip(entry_values) + { + let property_name = &index_property.name.as_bytes().to_vec(); + + let mut qualified_path = path.clone(); + qualified_path.push(property_name.clone()); + if !batch_insertion_cache.contains(&qualified_path) + && !standing_trees.contains(&qualified_path) + { + // Continuation property-name tree: contributes zero on + // every axis its aggregating parent maintains, exactly + // as on the insert path — except inside a ranking + // chain, whose continuation stays unwrapped, unless + // this child is a count-exempt sibling branch + // (re-inversion per child; see the non-bucketed + // dispatch above). + let property_name_tree_type = sub_level_tree_types.property_name_tree_type; + let ranked_axes = sub_level_tree_types.ranked_axes.as_slice(); + let inserted = if !continuation_contributes_zero( + parent_value_tree_type, + parent_counts_continuations, + level, + ) { + self.batch_insert_empty_index_tree_if_not_exists( + PathKeyInfo::PathKeyRef::<0>((path.clone(), property_name.as_slice())), + property_name_tree_type, + ranked_axes, + storage_flags, + BatchInsertTreeApplyType::StatefulBatchInsertTree, + transaction, + previous_batch_operations, + batch_operations, + drive_version, + )? + } else { + self.batch_insert_empty_tree_contributing_zero_to_aggregating_parent_if_not_exists( + PathKeyInfo::PathKeyRef::<0>((path.clone(), property_name.as_slice())), + parent_value_tree_type, + property_name_tree_type, + ranked_axes, + storage_flags, + BatchInsertTreeApplyType::StatefulBatchInsertTree, + transaction, + previous_batch_operations, + batch_operations, + drive_version, + )? + }; + if inserted { + batch_insertion_cache.insert(qualified_path); + } else { + standing_trees.insert(qualified_path); + } + } + path.push(property_name.clone()); + + let mut qualified_path = path.clone(); + qualified_path.push(value.to_vec()); + if !batch_insertion_cache.contains(&qualified_path) + && !standing_trees.contains(&qualified_path) + { + let inserted = self.batch_insert_empty_tree_if_not_exists( + PathKeyInfo::PathKeyRef::<0>((path.clone(), *value)), + sub_level_tree_types.value_tree_type, + storage_flags, + BatchInsertTreeApplyType::StatefulBatchInsertTree, + transaction, + previous_batch_operations, + batch_operations, + drive_version, + )?; + if inserted { + batch_insertion_cache.insert(qualified_path); + } else { + standing_trees.insert(qualified_path); + } + } + path.push(value.to_vec()); + + parent_value_tree_type = sub_level_tree_types.value_tree_type; + parent_counts_continuations = level.is_ranked_chain_level(); + } + + if new_terminator_is_unique { + // Unique layout: no per-document subtree — the reference IS + // the element at `[0]`, so the slot must be free. Insertion + // failure means two documents claim the same (bucket, …) + // tuple, which the uniqueness validation should have caught + // before we got here; treat it as index corruption exactly as + // the non-time-range branch does. + let inserted = self.batch_insert_if_not_exists( + PathKeyRefElement::<0>((path, &[0], index_document_reference.clone())), + BatchInsertApplyType::StatefulBatchInsert, + transaction, + batch_operations, + drive_version, + )?; + if !inserted { + return Err(Error::Drive(DriveError::CorruptedContractIndexes( + "index already exists".to_string(), + ))); + } + } else { + // Non-unique layout: materialize the `[0]` reference bucket + // (it carries the index's count/sum aggregates) and store the + // reference under the document id. + self.batch_insert_empty_tree_if_not_exists( + PathKeyInfo::PathKeyRef::<0>((path.clone(), &[0])), + reference_tree_type, + storage_flags, + BatchInsertTreeApplyType::StatefulBatchInsertTree, + transaction, + previous_batch_operations, + batch_operations, + drive_version, + )?; + path.push(vec![0]); + + self.batch_insert( + PathKeyRefElement::<0>(( + path, + doc_id.as_slice(), + index_document_reference.clone(), + )), + batch_operations, + drive_version, + )?; + } + } + // Delete old entries LAST: every entry the new document does not + // have, including one sharing its window or element with a new entry + // whose other values changed. The + // ordering is load-bearing: `batch_delete_up_tree_while_empty` folds + // the already-accumulated batch operations into its emptiness walk, + // so with the inserts above in place it stops before deleting a + // shared ancestor tree (bucket / property-name) that this same batch + // re-populates — e.g. on a suffix change at an unchanged timestamp. + // Deletes first would emit a delete of that ancestor alongside + // inserts into it, which grovedb's batch consistency check rejects. + for entry in &old_entries { + let Some((&entry_key, entry_values)) = entry.split_first() else { + continue; + }; + if new_set.contains(entry) { + continue; // unchanged entry — already refreshed by the insert loop above + } + // TTL: an expired bucket the drain already took entirely has no + // entry left to delete; one that still stands may be PARTIALLY + // drained (whole `[0]` and group value trees go before the + // bucket), so the entry is checked at full-path granularity + // below and skipped when its deeper trees are gone. A live + // bucket behaves exactly as before. This path is stateful-only + // (estimation redirects to the insert walker at the top of the + // v1 update), so the existence reads are always legal here. + let expired_transform = ttl_transform.filter(|transform| { + entry_key_bucket_start(entry_key) + .zip(transform.expiry_horizon_ms(block_time_ms)) + .is_some_and(|(start, horizon)| start < horizon) + }); + if let Some(transform) = expired_transform { + if !self.time_range_entry_is_removable( + transform, + entry_key, + block_time_ms, + base_index_path, + transaction, + platform_version, + )? { + continue; + } + let mut entry_path_segments: Vec> = base_index_path.to_vec(); + entry_path_segments.push(entry_key.to_vec()); + for (index_property, value) in index.properties.iter().skip(1).zip(entry_values) { + entry_path_segments.push(index_property.name.as_bytes().to_vec()); + entry_path_segments.push(value.to_vec()); + } + if !old_terminator_is_unique { + entry_path_segments.push(vec![0]); + } + // `base_index_path` — the document-type path plus the + // grid-qualified level key — exists for every registered + // contract, so the walk starts below it. + if !self.expired_entry_path_exists( + &entry_path_segments, + base_index_path.len(), + transaction, + platform_version, + )? { + continue; + } + } + let mut key_info_path: Vec = base_index_path + .iter() + .map(|s| KnownKey(s.clone())) + .collect(); + key_info_path.push(KnownKey(entry_key.to_vec())); + for (index_property, value) in index.properties.iter().skip(1).zip(entry_values) { + key_info_path.push(KnownKey(index_property.name.as_bytes().to_vec())); + key_info_path.push(KnownKey(value.to_vec())); + } + // The entry is removed under the layout the OLD document wrote it + // with: under the unique layout `[0]` IS the reference and is the + // key being deleted, under the non-unique layout `[0]` is the + // enclosing tree and the document id is the key. The stop height + // is unaffected — the emptiness walk still climbs the suffix + // values, the property-name trees and the bucket, and still stops + // at the document-type level, whose per-index property-name trees + // belong to contract registration rather than to any document. + let delete_key: Vec = if old_terminator_is_unique { + vec![0] + } else { + key_info_path.push(KnownKey(vec![0])); + doc_id.to_vec() + }; + self.batch_delete_up_tree_while_empty( + KeyInfoPath::from_vec(key_info_path), + delete_key.as_slice(), + Some(CONTRACT_DOCUMENTS_PATH_HEIGHT), + BatchDeleteUpTreeApplyType::StatefulBatchDelete { + is_known_to_be_subtree_with_sum: Some(MaybeTree::NotTree), + }, + transaction, + previous_batch_operations, + batch_operations, + drive_version, + )?; + } + + Ok(()) + } +} + +/// The entries an index holds for a document whose keys at each position of +/// the index are `key_sets`, borrowed from them: every combination of one key +/// per position, in order of the first position's keys, then the next +/// position's. A position with no key (a document before the origin of a +/// window grid) leaves the document no entry. +fn index_entries(key_sets: &[Vec>]) -> Vec> { + key_sets + .iter() + .map(|keys| keys.iter().map(Vec::as_slice)) + .multi_cartesian_product() + .collect() +} + +/// Whether `index`, whose first level is `top_index_level`, names an indexed +/// typed array at any position: its entries then fan out over the array's +/// elements. A level missing from the structure is reported by the entry +/// diff that walks it. +fn index_names_indexed_array(index: &Index, top_index_level: &IndexLevel) -> bool { + let mut level = top_index_level; + if level.indexes_array_elements() { + return true; + } + for index_property in index.properties.iter().skip(1) { + let Some(sub_level) = level.sub_levels().get(&index_property.name) else { + return false; + }; + if sub_level.indexes_array_elements() { + return true; + } + level = sub_level; + } + false +} diff --git a/packages/rs-drive/src/drive/document/update/mod.rs b/packages/rs-drive/src/drive/document/update/mod.rs index 723b0af7bde..ddfbbcd2633 100644 --- a/packages/rs-drive/src/drive/document/update/mod.rs +++ b/packages/rs-drive/src/drive/document/update/mod.rs @@ -1291,6 +1291,22 @@ mod tests { } fn test_fees_for_update_document(using_history: bool, using_transaction: bool) { + test_fees_for_update_document_at_version( + using_history, + using_transaction, + if using_history { + PlatformVersion::get(14).unwrap() + } else { + PlatformVersion::latest() + }, + ) + } + + fn test_fees_for_update_document_at_version( + using_history: bool, + using_transaction: bool, + platform_version: &PlatformVersion, + ) { let config = DriveConfig { batching_consistency_verification: true, has_raw_enabled: true, @@ -1298,8 +1314,6 @@ mod tests { ..Default::default() }; - let platform_version = PlatformVersion::latest(); - let drive: Drive = setup_drive(Some(config)); let transaction = if using_transaction { @@ -1326,7 +1340,7 @@ mod tests { None, None::, transaction.as_ref(), - None, + Some(platform_version), ); let id = Identifier::from([1u8; 32]); @@ -1385,7 +1399,11 @@ mod tests { //Explanation for 1237 //todo - 1238 + if platform_version.protocol_version >= 15 { + 1457 + } else { + 1238 + } } else { //Explanation for 959 @@ -1588,11 +1606,35 @@ mod tests { .storage .storage_disk_usage_credit_per_byte; - let expected_added_bytes = if using_history { 313 } else { 1 }; + let expected_added_bytes = if using_history { + if platform_version.protocol_version >= 15 { + 345 + } else { + 313 + } + } else { + 1 + }; assert_eq!(added_bytes, expected_added_bytes); } fn test_fees_for_update_document_on_index(using_history: bool, using_transaction: bool) { + test_fees_for_update_document_on_index_at_version( + using_history, + using_transaction, + if using_history { + PlatformVersion::get(14).unwrap() + } else { + PlatformVersion::latest() + }, + ) + } + + fn test_fees_for_update_document_on_index_at_version( + using_history: bool, + using_transaction: bool, + platform_version: &PlatformVersion, + ) { let config = DriveConfig { batching_consistency_verification: true, has_raw_enabled: true, @@ -1600,8 +1642,6 @@ mod tests { ..Default::default() }; - let platform_version = PlatformVersion::latest(); - let drive: Drive = setup_drive(Some(config)); let transaction = if using_transaction { @@ -1628,7 +1668,7 @@ mod tests { None, None::, transaction.as_ref(), - None, + Some(platform_version), ); let id = Identifier::from([1u8; 32]); @@ -1666,7 +1706,15 @@ mod tests { / FeeVersion::first() .storage .storage_disk_usage_credit_per_byte; - let expected_added_bytes = if using_history { 1238 } else { 962 }; + let expected_added_bytes = if using_history { + if platform_version.protocol_version >= 15 { + 1457 + } else { + 1238 + } + } else { + 962 + }; assert_eq!(original_bytes, expected_added_bytes); if !using_history { // let's delete it, just to make sure everything is working. @@ -1739,10 +1787,18 @@ mod tests { .unwrap(); // We added one byte, and since it is an index, and keys are doubled it's 2 extra bytes - let expected_added_bytes = if using_history { 607 } else { 605 }; + let expected_added_bytes = if using_history && platform_version.protocol_version < 15 { + 607 + } else { + 605 + }; assert_eq!(added_bytes, expected_added_bytes); - let expected_removed_credits = if using_history { 16286655 } else { 16232643 }; + let expected_removed_credits = if using_history && platform_version.protocol_version < 15 { + 16286655 + } else { + 16232643 + }; assert_eq!(*removed_credits, expected_removed_credits); let refund_equivalent_bytes = removed_credits.to_unsigned() / FeeVersion::first() @@ -1750,7 +1806,11 @@ mod tests { .storage_disk_usage_credit_per_byte; assert!(expected_added_bytes > refund_equivalent_bytes); - let expected_remove_bytes = if using_history { 603 } else { 601 }; + let expected_remove_bytes = if using_history && platform_version.protocol_version < 15 { + 603 + } else { + 601 + }; assert_eq!(refund_equivalent_bytes, expected_remove_bytes); // we refunded 1011 instead of 1014 } @@ -1795,6 +1855,22 @@ mod tests { } fn test_estimated_fees_for_update_document(using_history: bool, using_transaction: bool) { + test_estimated_fees_for_update_document_at_version( + using_history, + using_transaction, + if using_history { + PlatformVersion::get(14).unwrap() + } else { + PlatformVersion::latest() + }, + ) + } + + fn test_estimated_fees_for_update_document_at_version( + using_history: bool, + using_transaction: bool, + platform_version: &PlatformVersion, + ) { let config = DriveConfig { batching_consistency_verification: true, has_raw_enabled: true, @@ -1802,8 +1878,6 @@ mod tests { ..Default::default() }; - let platform_version = PlatformVersion::latest(); - let drive: Drive = setup_drive(Some(config)); let transaction = if using_transaction { @@ -1830,7 +1904,7 @@ mod tests { None, None::, transaction.as_ref(), - None, + Some(platform_version), ); let id = Identifier::from([1u8; 32]); @@ -1872,7 +1946,11 @@ mod tests { //Explanation for 1237 //todo - 1238 + if platform_version.protocol_version >= 15 { + 1457 + } else { + 1238 + } } else { //Explanation for 959 @@ -2028,7 +2106,15 @@ mod tests { .storage .storage_disk_usage_credit_per_byte; - let expected_added_bytes = if using_history { 1239 } else { 963 }; + let expected_added_bytes = if using_history { + if platform_version.protocol_version >= 15 { + 1458 + } else { + 1239 + } + } else { + 963 + }; assert_eq!(added_bytes, expected_added_bytes); } @@ -3470,4 +3556,34 @@ mod tests { other => panic!("expected Aggregate or Entries, got {other:?}"), } } + #[test] + fn should_pin_protocol15_history_replacement_fees() { + for transaction in [false, true] { + test_fees_for_update_document_at_version( + true, + transaction, + PlatformVersion::get(15).unwrap(), + ); + } + } + #[test] + fn should_pin_protocol15_history_index_replacement_fees() { + for transaction in [false, true] { + test_fees_for_update_document_on_index_at_version( + true, + transaction, + PlatformVersion::get(15).unwrap(), + ); + } + } + #[test] + fn should_pin_protocol15_history_estimated_replacement_fees() { + for transaction in [false, true] { + test_estimated_fees_for_update_document_at_version( + true, + transaction, + PlatformVersion::get(15).unwrap(), + ); + } + } } diff --git a/packages/rs-drive/src/query/document_history_drive_query.rs b/packages/rs-drive/src/query/document_history_drive_query.rs new file mode 100644 index 00000000000..889f79c5b6f --- /dev/null +++ b/packages/rs-drive/src/query/document_history_drive_query.rs @@ -0,0 +1,402 @@ +//! A page of a document's retained revisions with its lifecycle, read from +//! the per-type composite-keyed history tree. + +use crate::drive::document::paths::{contract_document_type_path_vec, DOCUMENT_HISTORY_TREE_KEY}; +use crate::drive::document::MAX_DOCUMENT_HISTORY_FETCH_LIMIT; +use crate::drive::Drive; +use crate::error::drive::DriveError; +use crate::error::query::QuerySyntaxError; +use crate::error::Error; +use crate::verify::RootHash; +use dpp::data_contract::document_type::{DocumentPropertyType, DocumentTypeRef}; +use dpp::document::serialization_traits::DocumentPlatformConversionMethodsV0; +use dpp::document::{Document, DocumentV0Getters}; +use dpp::version::PlatformVersion; +#[cfg(feature = "server")] +use grovedb::TransactionArg; +use grovedb::{Element, PathQuery, Query, SizedQuery}; + +/// The highest revision a revision filter can address. Revision `n` is read at +/// the zero-based offset `n - 1` of the document's history tree, and GroveDB +/// offsets are `u16`. +pub const MAX_DOCUMENT_HISTORY_REVISION_FILTER: u64 = u16::MAX as u64 + 1; + +/// Exactly one lower bound or revision position for a history page. +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum DocumentHistoryFilter { + /// Inclusive time bound for the first page. + StartAtTime(u64), + /// Exclusive composite cursor for subsequent pages. + StartAfter { + /// Timestamp of the last entry received. + time_ms: u64, + /// History sequence of the last entry received. + revision: u64, + }, + /// Inclusive retained revision position. + StartAtRevision(u64), + /// One retained revision position. + Revision(u64), +} + +/// A page of one historical document's retained revisions. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct DocumentHistoryDriveQuery { + /// Contract identifier. + pub contract_id: [u8; 32], + /// Document type name. + pub document_type_name: String, + /// Document identifier. + pub document_id: [u8; 32], + /// Page filter. + pub filter: DocumentHistoryFilter, + /// Page length, at most ten. + pub limit: Option, +} + +/// Lifecycle states supported by live-pointer storage. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum DocumentHistoryState { + /// A current document is present. + Active, + /// Neither a current document nor a retained history exists. + Absent, +} + +/// Authenticated history metadata independent of the requested page. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct DocumentHistoryLifecycle { + /// Current lifecycle state. + pub state: DocumentHistoryState, + /// Count authenticated by the per-document count-tree element. + pub remaining_revisions: u64, +} + +/// One retained edit, including its complete pagination cursor. +#[derive(Debug, Clone, PartialEq)] +pub struct DocumentHistoryEntry { + /// Block timestamp in milliseconds. + pub time_ms: u64, + /// History sequence, equal to the document revision when present. + pub revision: u64, + /// Document body at this revision. + pub document: Document, +} + +/// The result of a history query: a page and the lifecycle of the whole +/// history. +#[derive(Debug, Clone, PartialEq)] +pub struct DocumentHistoryDriveQueryExecutionResult { + /// Ordered retained revisions in this page. + pub entries: Vec, + /// Metadata for the whole history. Drive always returns it, including empty pages. + pub lifecycle: Option, +} + +pub(crate) fn invalid(message: &str) -> Error { + Error::Query(QuerySyntaxError::Unsupported(message.to_owned())) +} + +pub(crate) fn corrupt(message: &'static str) -> Error { + Error::Drive(DriveError::CorruptedDocumentPath(message)) +} + +impl DocumentHistoryDriveQuery { + /// Validates the filter without accessing state. + pub fn validate(&self) -> Result<(), Error> { + if !(1..=MAX_DOCUMENT_HISTORY_FETCH_LIMIT) + .contains(&self.limit.unwrap_or(MAX_DOCUMENT_HISTORY_FETCH_LIMIT)) + { + return Err(invalid("history limit must be between one and ten")); + } + match self.filter { + DocumentHistoryFilter::StartAtTime(time) + | DocumentHistoryFilter::StartAfter { time_ms: time, .. } + if time >= (1u64 << 63) => + { + Err(invalid("history time must be below 2^63")) + } + DocumentHistoryFilter::StartAfter { revision: 0, .. } => { + Err(invalid("history cursor revision must be positive")) + } + DocumentHistoryFilter::StartAtRevision(revision) + | DocumentHistoryFilter::Revision(revision) + if !(1..=MAX_DOCUMENT_HISTORY_REVISION_FILTER).contains(&revision) => + { + Err(invalid("history revision must be between one and 65536")) + } + DocumentHistoryFilter::Revision(_) if self.limit.is_some_and(|limit| limit != 1) => { + Err(invalid("single revision queries require limit one")) + } + _ => Ok(()), + } + } + + /// The page and its lifecycle in the per-type composite-keyed history tree. + pub fn construct_path_query( + &self, + platform_version: &PlatformVersion, + ) -> Result { + match platform_version + .drive + .methods + .document + .query + .fetch_document_history_query + { + 1 => self.merged_path_query(platform_version), + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "DocumentHistoryDriveQuery::construct_path_query".to_string(), + known_versions: vec![1], + received: version, + })), + } + } + + fn merged_path_query(&self, version: &PlatformVersion) -> Result { + let page = Drive::fetch_document_history_drive_query_v1(self)?; + let mut leaf = page.query.query; + leaf.limit = page.query.limit; + leaf.offset = page.query.offset; + let mut queries = [0, 1] + .map(|branch| { + let mut path = + contract_document_type_path_vec(&self.contract_id, &self.document_type_name); + path.push(vec![branch]); + let mut query = Query::new(); + query.insert_key(self.document_id.to_vec()); + PathQuery::new(path, SizedQuery::new(query, None, None)) + }) + .to_vec(); + let mut path = contract_document_type_path_vec(&self.contract_id, &self.document_type_name); + path.push(vec![DOCUMENT_HISTORY_TREE_KEY]); + let mut history = Query::new_single_key(self.document_id.to_vec()); + history.add_parent_tree_on_subquery = true; + history.set_subquery(leaf); + queries.push(PathQuery::new_unsized(path, history)); + // Only the page leaf is limited. Exact siblings and their selecting + // ancestors must stay unlimited so omission authenticates absence. + Ok(PathQuery::merge( + queries.iter().collect(), + &version.drive.grove_version, + )?) + } + + pub(crate) fn decode_result( + &self, + rows: Vec, + document_type: DocumentTypeRef, + version: &PlatformVersion, + ) -> Result { + let mut entry_path = + contract_document_type_path_vec(&self.contract_id, &self.document_type_name); + entry_path.push(vec![DOCUMENT_HISTORY_TREE_KEY]); + entry_path.push(self.document_id.to_vec()); + let mut metadata = vec![]; + let mut entries = vec![]; + for (path, key, element) in rows { + if path == entry_path { + entries.push(( + key, + element.ok_or_else(|| corrupt("history entry contains an absent element"))?, + )); + } else { + metadata.push((path, key, element)); + } + } + let lifecycle = self.lifecycle(metadata, document_type, version)?; + let limit = if matches!(self.filter, DocumentHistoryFilter::Revision(_)) { + 1 + } else { + self.limit.unwrap_or(MAX_DOCUMENT_HISTORY_FETCH_LIMIT) + } as u64; + let maximum = lifecycle.remaining_revisions.min(limit); + if let DocumentHistoryFilter::Revision(revision) + | DocumentHistoryFilter::StartAtRevision(revision) = self.filter + { + if entries.len() as u64 + != lifecycle + .remaining_revisions + .saturating_sub(revision - 1) + .min(limit) + { + return Err(corrupt( + "history page length disagrees with its revision count", + )); + } + } else if entries.len() as u64 > maximum { + return Err(corrupt("history page exceeds its limit or revision count")); + } + let entries = self.decode_entries(entries, document_type, version)?; + Ok(DocumentHistoryDriveQueryExecutionResult { + entries, + lifecycle: Some(lifecycle), + }) + } + + pub(crate) fn lifecycle( + &self, + metadata: Vec, + document_type: DocumentTypeRef, + version: &PlatformVersion, + ) -> Result { + let mut primary = + contract_document_type_path_vec(&self.contract_id, &self.document_type_name); + primary.push(vec![0]); + let mut history = primary.clone(); + history[4] = vec![DOCUMENT_HISTORY_TREE_KEY]; + let mut active = false; + let mut latest_revision = None; + let mut count = None; + for (path, key, element) in metadata { + let element = + element.ok_or_else(|| corrupt("history metadata contains an absent element"))?; + if key != self.document_id { + return Err(corrupt("history metadata key does not match the document")); + } + if path == primary { + let bytes = match element { + Element::Item(bytes, _) | Element::ItemWithSumItem(bytes, _, _) => bytes, + _ => { + return Err(corrupt( + "history current pointer did not resolve to a document", + )) + } + }; + let document = Document::from_bytes(&bytes, document_type, version)?; + if document.id().as_slice() != self.document_id { + return Err(corrupt( + "history current document id does not match the query", + )); + } + latest_revision = Some(document.revision().unwrap_or(1)); + if active { + return Err(corrupt("duplicate history current pointer")); + } + active = true; + } else if path == history { + let Element::ProvableCountTree(_, revisions, _) = element else { + return Err(corrupt("history metadata is not a provable count tree")); + }; + if count.replace(revisions).is_some() { + return Err(corrupt("duplicate history metadata")); + } + } else { + return Err(corrupt( + "unexpected lifecycle record or history metadata path", + )); + } + } + if active && count.unwrap_or_default() == 0 || !active && count.unwrap_or_default() > 0 { + return Err(corrupt("current document and retained history disagree")); + } + if matches!( + self.filter, + DocumentHistoryFilter::Revision(_) | DocumentHistoryFilter::StartAtRevision(_) + ) && active + && latest_revision != count + { + return Err(invalid( + "retained history contains a revision gap; use time pagination", + )); + } + Ok(DocumentHistoryLifecycle { + state: if active { + DocumentHistoryState::Active + } else { + DocumentHistoryState::Absent + }, + remaining_revisions: count.unwrap_or_default(), + }) + } + + pub(crate) fn decode_entries( + &self, + entries: Vec<(Vec, Element)>, + document_type: DocumentTypeRef, + version: &PlatformVersion, + ) -> Result, Error> { + entries + .into_iter() + .enumerate() + .map(|(position, (key, element))| { + if key.len() != 16 { + return Err(corrupt( + "history revision keys must contain exactly sixteen bytes", + )); + } + let time_ms = DocumentPropertyType::decode_date_timestamp(&key[..8]) + .ok_or_else(|| corrupt("invalid history timestamp"))?; + let revision = DocumentPropertyType::decode_date_timestamp(&key[8..]) + .ok_or_else(|| corrupt("invalid history revision"))?; + if time_ms >= (1u64 << 63) || revision == 0 { + return Err(corrupt( + "history key contains an invalid timestamp or revision", + )); + } + let Element::Item(bytes, _) = element else { + return Err(corrupt("history revision is not a plain item")); + }; + let document = Document::from_bytes(&bytes, document_type, version)?; + if document.id().as_slice() != self.document_id + || document.revision().unwrap_or(1) != revision + { + return Err(corrupt("history revision does not match its key")); + } + if let DocumentHistoryFilter::StartAtRevision(requested) + | DocumentHistoryFilter::Revision(requested) = self.filter + { + if revision != requested + position as u64 { + return Err(invalid( + "retained history contains a revision gap; use time pagination", + )); + } + } + Ok(DocumentHistoryEntry { + time_ms, + revision, + document, + }) + }) + .collect() + } + + /// Fetches the page from the per-type composite-keyed history tree. + #[cfg(feature = "server")] + pub fn execute_no_proof( + &self, + drive: &Drive, + document_type: DocumentTypeRef, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result { + drive.fetch_document_history(self, document_type, transaction, platform_version) + } + + /// Proves the page from the per-type composite-keyed history tree. + #[cfg(feature = "server")] + pub fn execute_with_proof( + &self, + drive: &Drive, + document_type: DocumentTypeRef, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result, Error> { + drive.prove_document_history(self, document_type, transaction, platform_version) + } + + /// Verifies a proof produced by [`Self::execute_with_proof`]. + pub fn verify_document_history_proof( + &self, + proof: &[u8], + document_type: DocumentTypeRef, + platform_version: &PlatformVersion, + ) -> Result<(RootHash, DocumentHistoryDriveQueryExecutionResult), Error> { + Drive::verify_document_history(self, proof, document_type, platform_version) + } +} + +#[cfg(test)] +#[path = "document_history_drive_query_tests.rs"] +mod decode_tests; diff --git a/packages/rs-drive/src/query/document_history_drive_query_tests.rs b/packages/rs-drive/src/query/document_history_drive_query_tests.rs new file mode 100644 index 00000000000..e390f1f6960 --- /dev/null +++ b/packages/rs-drive/src/query/document_history_drive_query_tests.rs @@ -0,0 +1,389 @@ +use super::{ + DocumentHistoryDriveQuery, DocumentHistoryDriveQueryExecutionResult, DocumentHistoryFilter, +}; +use crate::drive::document::paths::{contract_document_type_path_vec, DOCUMENT_HISTORY_TREE_KEY}; +use crate::error::drive::DriveError; +use crate::error::Error; +use crate::util::common::encode::encode_u64; +use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::data_contract::DataContract; +use dpp::document::serialization_traits::DocumentPlatformConversionMethodsV0; +use dpp::document::{Document, DocumentV0Getters, DocumentV0Setters}; +use dpp::tests::json_document::{json_document_to_contract, json_document_to_document}; +use dpp::version::PlatformVersion; +use grovedb::query_result_type::PathKeyOptionalElementTrio; +use grovedb::Element; + +struct Fixture { + contract: DataContract, + document: Document, +} + +impl Fixture { + fn new() -> Self { + let version = PlatformVersion::latest(); + let contract = json_document_to_contract( + "tests/supporting_files/contract/dashpay/dashpay-contract-with-profile-history.json", + false, + version, + ) + .expect("history-keeping profile contract"); + let document_type = contract + .document_type_for_name("profile") + .expect("profile type"); + let mut document = json_document_to_document( + "tests/supporting_files/contract/dashpay/profile0.json", + Some([8; 32].into()), + document_type, + version, + ) + .expect("profile document"); + document.set_revision(Some(3)); + Self { contract, document } + } + + fn query( + &self, + filter: DocumentHistoryFilter, + limit: Option, + ) -> DocumentHistoryDriveQuery { + DocumentHistoryDriveQuery { + contract_id: self.contract.id().to_buffer(), + document_type_name: "profile".into(), + document_id: self.document.id().to_buffer(), + filter, + limit, + } + } + + fn document_element(&self, revision: u64) -> Element { + let mut document = self.document.clone(); + document.set_revision(Some(revision)); + Element::new_item( + document + .serialize( + self.contract + .document_type_for_name("profile") + .expect("profile type"), + &self.contract, + PlatformVersion::latest(), + ) + .expect("serialized profile revision"), + ) + } + + fn metadata_row(&self, branch: u8, element: Option) -> PathKeyOptionalElementTrio { + let mut path = contract_document_type_path_vec(self.contract.id().as_bytes(), "profile"); + path.push(vec![branch]); + (path, self.document.id().to_vec(), element) + } + + fn entry_row(&self, revision: u64) -> PathKeyOptionalElementTrio { + let mut path = contract_document_type_path_vec(self.contract.id().as_bytes(), "profile"); + path.push(vec![DOCUMENT_HISTORY_TREE_KEY]); + path.push(self.document.id().to_vec()); + let mut key = encode_u64(2000); + key.extend(encode_u64(revision)); + (path, key, Some(self.document_element(revision))) + } + + fn rows(&self, revisions: &[u64]) -> Vec { + let mut rows = vec![ + self.metadata_row(0, Some(self.document_element(3))), + self.metadata_row( + DOCUMENT_HISTORY_TREE_KEY, + Some(Element::ProvableCountTree(Some(vec![1]), 3, None)), + ), + ]; + rows.extend(revisions.iter().map(|revision| self.entry_row(*revision))); + rows + } + + fn decode( + &self, + query: &DocumentHistoryDriveQuery, + rows: Vec, + ) -> Result { + query.decode_result( + rows, + self.contract + .document_type_for_name("profile") + .expect("profile type"), + PlatformVersion::latest(), + ) + } +} + +fn assert_corrupt( + result: Result, + expected: &'static str, +) { + let error = result.expect_err("malformed history rows must be rejected"); + assert!( + matches!(error, Error::Drive(DriveError::CorruptedDocumentPath(message)) if message == expected), + "expected {expected:?}, got {error:?}", + ); +} + +#[test] +fn should_reject_ordinal_pages_that_disagree_with_the_committed_count_or_limit() { + let fixture = Fixture::new(); + for (filter, limit, complete, incomplete) in [ + ( + DocumentHistoryFilter::StartAtRevision(2), + Some(10), + vec![2, 3], + vec![2], + ), + ( + DocumentHistoryFilter::StartAtRevision(2), + Some(10), + vec![2, 3], + vec![2, 3, 4], + ), + ( + DocumentHistoryFilter::StartAtRevision(1), + Some(2), + vec![1, 2], + vec![1], + ), + ( + DocumentHistoryFilter::StartAtRevision(1), + Some(2), + vec![1, 2], + vec![1, 2, 3], + ), + (DocumentHistoryFilter::Revision(2), None, vec![2], vec![]), + ( + DocumentHistoryFilter::Revision(2), + Some(1), + vec![2], + vec![2, 3], + ), + ( + DocumentHistoryFilter::StartAtRevision(4), + Some(10), + vec![], + vec![4], + ), + ( + DocumentHistoryFilter::Revision(65536), + None, + vec![], + vec![65536], + ), + ] { + let query = fixture.query(filter, limit); + let page = fixture + .decode(&query, fixture.rows(&complete)) + .expect("the complete ordinal page is valid"); + assert_eq!(page.entries.len(), complete.len()); + assert_corrupt( + fixture.decode(&query, fixture.rows(&incomplete)), + "history page length disagrees with its revision count", + ); + } +} + +#[test] +fn should_reject_time_and_cursor_pages_exceeding_their_limit_or_count() { + let fixture = Fixture::new(); + for filter in [ + DocumentHistoryFilter::StartAtTime(0), + DocumentHistoryFilter::StartAfter { + time_ms: 0, + revision: 1, + }, + ] { + for (limit, complete, excessive) in [ + (Some(1), vec![1], vec![1, 2]), + (None, vec![1, 2, 3], vec![1, 2, 3, 4]), + ] { + let query = fixture.query(filter.clone(), limit); + fixture + .decode(&query, fixture.rows(&complete)) + .expect("a time page within both bounds is valid"); + assert_corrupt( + fixture.decode(&query, fixture.rows(&excessive)), + "history page exceeds its limit or revision count", + ); + } + } +} + +#[test] +fn should_reject_page_entries_without_a_retained_history() { + let fixture = Fixture::new(); + for filter in [ + DocumentHistoryFilter::StartAtTime(0), + DocumentHistoryFilter::StartAtRevision(1), + ] { + let query = fixture.query(filter.clone(), None); + fixture + .decode(&query, vec![]) + .expect("omitted exact metadata keys authenticate an absent history"); + let message = if matches!(filter, DocumentHistoryFilter::StartAtTime(_)) { + "history page exceeds its limit or revision count" + } else { + "history page length disagrees with its revision count" + }; + assert_corrupt(fixture.decode(&query, vec![fixture.entry_row(1)]), message); + } +} + +#[test] +fn should_reject_a_duplicate_history_tree_echo() { + let fixture = Fixture::new(); + let query = fixture.query(DocumentHistoryFilter::StartAtTime(0), None); + let mut rows = fixture.rows(&[1, 2, 3]); + rows.push(rows[1].clone()); + assert_corrupt(fixture.decode(&query, rows), "duplicate history metadata"); +} + +#[test] +fn should_reject_a_duplicate_current_pointer() { + let fixture = Fixture::new(); + let query = fixture.query(DocumentHistoryFilter::StartAtTime(0), None); + let mut rows = fixture.rows(&[1, 2, 3]); + rows.push(rows[0].clone()); + assert_corrupt( + fixture.decode(&query, rows), + "duplicate history current pointer", + ); +} + +#[test] +fn should_reject_metadata_keys_that_do_not_match_the_document() { + let fixture = Fixture::new(); + let query = fixture.query(DocumentHistoryFilter::StartAtTime(0), None); + for index in [0, 1] { + let mut rows = fixture.rows(&[1, 2, 3]); + rows[index].1[0] ^= 1; + assert_corrupt( + fixture.decode(&query, rows), + "history metadata key does not match the document", + ); + } +} + +#[test] +fn should_reject_an_active_document_with_zero_retained_revisions() { + let fixture = Fixture::new(); + let query = fixture.query(DocumentHistoryFilter::StartAtTime(0), None); + let mut rows = fixture.rows(&[]); + rows[1].2 = Some(Element::ProvableCountTree(None, 0, None)); + assert_corrupt( + fixture.decode(&query, rows), + "current document and retained history disagree", + ); +} + +#[test] +fn should_reject_a_current_pointer_to_another_document() { + let mut fixture = Fixture::new(); + let query = fixture.query(DocumentHistoryFilter::StartAtTime(0), None); + let mut rows = fixture.rows(&[1, 2, 3]); + let mut other_id = query.document_id; + other_id[0] ^= 1; + fixture.document.set_id(other_id.into()); + rows[0].2 = Some(fixture.document_element(3)); + assert_corrupt( + fixture.decode(&query, rows), + "history current document id does not match the query", + ); +} + +#[test] +fn should_reject_a_current_pointer_that_is_not_an_item() { + let fixture = Fixture::new(); + let query = fixture.query(DocumentHistoryFilter::StartAtTime(0), None); + let mut rows = fixture.rows(&[1, 2, 3]); + rows[0].2 = Some(Element::empty_tree()); + assert_corrupt( + fixture.decode(&query, rows), + "history current pointer did not resolve to a document", + ); +} + +#[test] +fn should_reject_a_present_reserved_lifecycle_record() { + let fixture = Fixture::new(); + let query = fixture.query(DocumentHistoryFilter::StartAtTime(0), None); + let mut rows = fixture.rows(&[1, 2, 3]); + rows.push(fixture.metadata_row(1, Some(Element::new_item(vec![1])))); + assert_corrupt( + fixture.decode(&query, rows), + "unexpected lifecycle record or history metadata path", + ); +} + +#[test] +fn should_reject_a_history_echo_without_an_authenticated_count() { + let fixture = Fixture::new(); + let query = fixture.query(DocumentHistoryFilter::StartAtTime(0), None); + for element in [ + Element::empty_tree(), + Element::new_item(vec![1]), + Element::CountTree(Some(vec![1]), 3, None), + Element::ProvableCountSumTree(Some(vec![1]), 3, 0, None), + ] { + let mut rows = fixture.rows(&[1, 2, 3]); + rows[1] = fixture.metadata_row(DOCUMENT_HISTORY_TREE_KEY, Some(element)); + assert_corrupt( + fixture.decode(&query, rows), + "history metadata is not a provable count tree", + ); + } +} + +#[test] +fn should_reject_an_absent_page_entry_element() { + let fixture = Fixture::new(); + let query = fixture.query(DocumentHistoryFilter::StartAtRevision(2), Some(10)); + let mut rows = fixture.rows(&[2, 3]); + rows[2].2 = None; + assert_corrupt( + fixture.decode(&query, rows), + "history entry contains an absent element", + ); +} + +fn assert_rejects_absent_metadata(branch: u8) { + let fixture = Fixture::new(); + let query = fixture.query(DocumentHistoryFilter::StartAtTime(0), None); + let mut rows = fixture.rows(&[1, 2, 3]); + rows.push(fixture.metadata_row(branch, None)); + assert_corrupt( + fixture.decode(&query, rows), + "history metadata contains an absent element", + ); +} + +#[test] +fn should_reject_an_absent_current_pointer_metadata_element() { + assert_rejects_absent_metadata(0); +} + +#[test] +fn should_reject_an_absent_reserved_metadata_element() { + assert_rejects_absent_metadata(1); +} + +#[test] +fn should_reject_an_absent_history_metadata_element() { + assert_rejects_absent_metadata(DOCUMENT_HISTORY_TREE_KEY); +} + +#[test] +fn should_reject_a_v1_history_query_before_the_history_tree_is_active() { + let fixture = Fixture::new(); + let query = fixture.query(DocumentHistoryFilter::StartAtTime(0), Some(1)); + let error = query + .construct_path_query(PlatformVersion::get(14).unwrap()) + .expect_err("query version 1 must not be lowered into method version 0"); + assert!( + matches!(error, Error::Drive(DriveError::UnknownVersionMismatch { + method, known_versions, received: 0, + }) if method == "DocumentHistoryDriveQuery::construct_path_query" && known_versions == vec![1]) + ); +} diff --git a/packages/rs-drive/src/query/grove_version_compatibility_tests.rs b/packages/rs-drive/src/query/grove_version_compatibility_tests.rs new file mode 100644 index 00000000000..5264961cc2d --- /dev/null +++ b/packages/rs-drive/src/query/grove_version_compatibility_tests.rs @@ -0,0 +1,407 @@ +#![cfg(feature = "full")] + +use crate::config::DriveConfig; +use crate::drive::shielded::paths::shielded_credit_pool_nullifiers_path_vec; +use crate::drive::{Drive, RootTree}; +use crate::query::{ + DriveDocumentQuery, SingleDocumentDriveQuery, SingleDocumentDriveQueryContestedStatus, +}; +use crate::util::object_size_info::{DocumentAndContractInfo, DocumentInfo, OwnedDocumentInfo}; +use crate::util::test_helpers::setup::{setup_drive, setup_drive_with_initial_state_structure}; +use dpp::address_funds::PlatformAddress; +use dpp::block::block_info::BlockInfo; +use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::data_contract::config::moderation::ContractModerationList; +use dpp::data_contract::document_type::action_fees::ContractFeePot; +use dpp::document::DocumentV0Setters; +use dpp::platform_value::Value; +use dpp::tests::json_document::{json_document_to_contract, json_document_to_document}; +use dpp::version::PlatformVersion; +use grovedb::query_result_type::QueryResultType::QueryPathKeyElementTrioResultType; +use grovedb::{PathQuery, Query}; +use grovedb_version::version::{v4::GROVE_V4, v5::GROVE_V5}; +use std::collections::BTreeMap; + +fn merged_public_queries( + drive: &Drive, + platform_version: &PlatformVersion, +) -> Vec<(&'static str, PathQuery)> { + let grove_version = &platform_version.drive.grove_version; + let identity_id = [1; 32]; + let identity_ids = [identity_id, [2; 32]]; + let key_hash = [3; 20]; + let contract_id = [4; 32]; + let single_document_query = SingleDocumentDriveQuery { + contract_id, + document_type_name: "note".to_string(), + document_type_keeps_history: false, + document_id: [5; 32], + block_time_ms: None, + contested_status: SingleDocumentDriveQueryContestedStatus::MaybeContested, + }; + + let mut queries = vec![ + ( + "identity revision and balance", + Drive::revision_and_balance_path_query(identity_id, grove_version) + .expect("revision and balance query"), + ), + ( + "full identity", + Drive::full_identity_query(&identity_id, grove_version).expect("full identity query"), + ), + ( + "identity keys and revision", + Drive::identity_all_keys_query(&identity_id, grove_version) + .expect("identity keys and revision query"), + ), + ( + "full identities", + Drive::full_identities_query(&identity_ids, grove_version) + .expect("full identities query"), + ), + ( + "full identity and unique hash", + Drive::full_identity_with_public_key_hash_query(key_hash, identity_id, grove_version) + .expect("full identity and unique hash query"), + ), + ( + "full identity and nonunique hash", + Drive::full_identity_with_non_unique_public_key_hash_query( + key_hash, + identity_id, + None, + grove_version, + ) + .expect("full identity and nonunique hash query"), + ), + ( + "full identities and unique hashes", + Drive::full_identities_with_keys_hashes_query( + &identity_ids, + &[key_hash, [6; 20]], + grove_version, + ) + .expect("full identities and unique hashes query"), + ), + ( + "identity balance and revision", + Drive::balance_and_revision_for_identity_id_query(identity_id, grove_version), + ), + ( + "all identities keys without a limit", + drive + .fetch_identities_all_keys_query(&identity_ids, None, grove_version) + .expect("all identities keys query"), + ), + ( + "current and historical contracts", + Drive::fetch_contracts_query(&[contract_id], &[[7; 32]], platform_version) + .expect("current and historical contracts query"), + ), + ( + "contract fee pots and claims", + Drive::contract_fee_pots_query( + contract_id, + &[ContractFeePot::Owner, ContractFeePot::Moderators], + grove_version, + ) + .expect("contract fee pots query"), + ), + ( + "contract moderation lists", + Drive::contract_moderation_status_query( + contract_id, + identity_id, + &[ + ContractModerationList::Banlist, + ContractModerationList::Suspensions, + ContractModerationList::Warnings, + ], + grove_version, + ) + .expect("contract moderation status query"), + ), + ( + "token supply and aggregate balances", + Drive::token_total_supply_and_aggregated_identity_balances_query( + [8; 32], + platform_version, + ) + .expect("token supply and aggregate balances query"), + ), + ( + "contested and uncontested document", + single_document_query + .construct_path_query(platform_version) + .expect("contested and uncontested document query"), + ), + ]; + + queries.push(( + "full identity and nonunique hash after a cursor", + Drive::full_identity_with_non_unique_public_key_hash_query( + key_hash, + identity_id, + Some([0; 32]), + grove_version, + ) + .expect("full identity and nonunique hash query after a cursor"), + )); + queries.push(( + "all identities keys with branch limits", + drive + .fetch_identities_all_keys_query(&identity_ids, Some(2), grove_version) + .expect("limited all identities keys query"), + )); + queries.push(( + "contested and uncontested history-keeping document", + SingleDocumentDriveQuery { + document_type_keeps_history: true, + ..single_document_query + } + .construct_path_query(platform_version) + .expect("history-keeping document query"), + )); + queries +} + +#[test] +fn should_preserve_public_merged_queries_and_their_bytes_across_grove_versions() { + let drive = setup_drive(None); + for selected in [ + PlatformVersion::get(14).unwrap(), + PlatformVersion::get(15).unwrap(), + ] { + let mut previous = selected.clone(); + previous.drive.grove_version = GROVE_V4; + let mut current = selected.clone(); + current.drive.grove_version = GROVE_V5; + let previous_queries = merged_public_queries(&drive, &previous); + let current_queries = merged_public_queries(&drive, ¤t); + assert_eq!(previous_queries.len(), current_queries.len()); + + for ((name, previous_query), (current_name, current_query)) in + previous_queries.into_iter().zip(current_queries) + { + assert_eq!(name, current_name); + assert_eq!( + previous_query, current_query, + "protocol {}: {name}", + selected.protocol_version, + ); + let config = bincode::config::standard().with_big_endian(); + assert_eq!( + bincode::encode_to_vec(&previous_query, config).expect("previous query bytes"), + bincode::encode_to_vec(¤t_query, config).expect("current query bytes"), + "protocol {} query bytes: {name}", + selected.protocol_version, + ); + } + } +} + +#[test] +fn should_accept_explicit_zero_cursor_offsets_only_after_the_grove_upgrade() { + for version in [ + PlatformVersion::get(14).unwrap(), + PlatformVersion::get(15).unwrap(), + ] { + let drive = setup_drive_with_initial_state_structure(Some(version)); + let contract = json_document_to_contract( + "tests/supporting_files/contract/dashpay/dashpay-contract.json", + false, + version, + ) + .expect("profile contract"); + drive + .apply_contract(&contract, BlockInfo::default(), true, None, None, version) + .expect("registered profile contract"); + let document_type = contract + .document_type_for_name("profile") + .expect("profile type"); + for id in [1u8, 2] { + let mut document = json_document_to_document( + "tests/supporting_files/contract/dashpay/profile0.json", + Some([id; 32].into()), + document_type, + version, + ) + .expect("profile document"); + document.set_id([id; 32].into()); + drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentInfo::DocumentRefInfo((&document, None)), + owner_id: None, + }, + contract: &contract, + document_type, + }, + true, + BlockInfo::default(), + true, + None, + version, + ) + .expect("stored profile document"); + } + + for cursor in ["startAt", "startAfter"] { + let mut input = BTreeMap::from([ + (cursor.to_string(), Value::Identifier([1; 32])), + ("limit".to_string(), Value::U16(2)), + ]); + let without_offset = DriveDocumentQuery::from_btree_map_value( + input.clone(), + &contract, + document_type, + &DriveConfig::default(), + version, + ) + .expect("cursor query without an offset"); + input.insert("offset".to_string(), Value::U16(0)); + let with_zero_offset = DriveDocumentQuery::from_btree_map_value( + input, + &contract, + document_type, + &DriveConfig::default(), + version, + ) + .expect("cursor query with an explicit zero offset"); + assert_eq!(with_zero_offset.offset, Some(0)); + + let without_offset = without_offset + .construct_path_query_operations(&drive, true, None, &mut vec![], version) + .expect("merged cursor query without an offset"); + let with_zero_offset = with_zero_offset.construct_path_query_operations( + &drive, + true, + None, + &mut vec![], + version, + ); + if version.protocol_version == 14 { + assert!( + with_zero_offset + .expect_err("released GroveDB refuses explicit cursor offsets") + .to_string() + .contains("can not merge pathqueries with offsets"), + "{cursor} preserves the released offset refusal", + ); + continue; + } + + let with_zero_offset = with_zero_offset.expect("zero offset is a no-op after upgrade"); + assert_eq!(with_zero_offset, without_offset, "{cursor} merged query"); + let read = |query: &PathQuery| { + let (rows, skipped) = drive + .grove + .query_raw( + query, + false, + true, + true, + QueryPathKeyElementTrioResultType, + None, + &version.drive.grove_version, + ) + .unwrap() + .expect("merged cursor query results"); + (rows.to_path_key_elements(), skipped) + }; + let expected = read(&without_offset); + assert!(!expected.0.is_empty(), "{cursor} reads the stored profiles"); + assert_eq!(read(&with_zero_offset), expected, "{cursor} results"); + } + } +} + +#[test] +fn should_preserve_execution_proof_component_merges_and_their_bytes() { + let version = PlatformVersion::latest(); + let owner = [1; 32]; + let recipient = [2; 32]; + let addresses = [ + PlatformAddress::P2pkh([3; 20]), + PlatformAddress::P2sh([4; 20]), + ]; + let mut address_query = Drive::balances_for_clear_addresses_query(&addresses); + address_query.query.limit = None; + let balance = Drive::identity_balance_query(&owner); + let recipient_balance = Drive::identity_balance_query(&recipient); + let recipients = Drive::balances_for_identity_ids_query(&[owner, recipient]); + let revision = Drive::revision_and_balance_path_query(owner, &GROVE_V4).unwrap(); + let mut identity = Drive::full_identity_query(&owner, &GROVE_V4).unwrap(); + identity.query.limit = None; + let pots = Drive::contract_fee_pots_query(owner, &[ContractFeePot::Owner], &GROVE_V4).unwrap(); + let nullifiers = PathQuery::new_unsized( + shielded_credit_pool_nullifiers_path_vec(), + Query::new_single_key(vec![5; 32]), + ); + let outpoint = PathQuery::new_unsized( + vec![vec![RootTree::SpentAssetLockTransactions as u8]], + Query::new_single_key(vec![6; 36]), + ); + let mut document = SingleDocumentDriveQuery::latest_not_contested( + owner, + "withdrawal".to_string(), + false, + recipient, + ) + .construct_path_query(version) + .unwrap(); + document.query.limit = None; + // These are the component combinations used by execution proof producers; + // each clears its outer budget before merging a second result selection. + let combinations = [ + ("contract fee claim", vec![&pots, &recipients]), + ( + "identity credit transfer", + vec![&balance, &recipient_balance], + ), + ( + "identity transfer to addresses", + vec![&revision, &address_query], + ), + ( + "identity create from addresses", + vec![&identity, &address_query], + ), + ( + "identity top up from addresses", + vec![&revision, &address_query], + ), + ("unshield", vec![&nullifiers, &address_query]), + ("shielded withdrawal", vec![&nullifiers, &document]), + ( + "shield from asset lock surplus", + vec![&outpoint, &address_query], + ), + ( + "identity create from shielded pool", + vec![&identity, &nullifiers], + ), + ( + "identity top up from shielded pool", + vec![&nullifiers, &identity], + ), + ("owned document execution", vec![&document, &balance]), + ( + "multiple execution results", + vec![&identity, &document, &address_query, &pots], + ), + ]; + for (name, components) in combinations { + let previous = PathQuery::merge(components.clone(), &GROVE_V4).unwrap(); + let current = PathQuery::merge(components, &GROVE_V5).unwrap(); + assert_eq!(current, previous, "{name}"); + let config = bincode::config::standard().with_big_endian(); + assert_eq!( + bincode::encode_to_vec(¤t, config).unwrap(), + bincode::encode_to_vec(&previous, config).unwrap(), + "{name} query bytes", + ); + } +} diff --git a/packages/rs-drive/src/query/mod.rs b/packages/rs-drive/src/query/mod.rs index 81586ca16be..aaf18208f4f 100644 --- a/packages/rs-drive/src/query/mod.rs +++ b/packages/rs-drive/src/query/mod.rs @@ -175,8 +175,12 @@ use dpp::version::FeatureVersion; #[cfg(any(feature = "server", feature = "verify"))] pub mod canonicalize; #[cfg(any(feature = "server", feature = "verify"))] +mod primary_key_path_query; +#[cfg(any(feature = "server", feature = "verify"))] pub use canonicalize::{key_array_element_clauses, validate_and_canonicalize_where_clauses}; #[cfg(any(feature = "server", feature = "verify"))] +use primary_key_path_query::{primary_key_path_query_target, PrimaryKeyPathQueryTarget}; +#[cfg(any(feature = "server", feature = "verify"))] pub mod conditions; #[cfg(any(feature = "server", feature = "verify"))] mod defaults; @@ -211,6 +215,15 @@ pub mod vote_poll_contestant_votes_query; /// Vote polls by end date query pub mod vote_polls_by_end_date_query; +/// A page of a historical document's retained revisions +#[cfg(any(feature = "server", feature = "verify"))] +pub mod document_history_drive_query; +#[cfg(any(feature = "server", feature = "verify"))] +pub use document_history_drive_query::{ + DocumentHistoryDriveQuery, DocumentHistoryDriveQueryExecutionResult, DocumentHistoryEntry, + DocumentHistoryFilter, DocumentHistoryLifecycle, DocumentHistoryState, +}; + #[cfg(any(feature = "server", feature = "verify"))] /// Vote polls by document type query pub mod vote_polls_by_document_type_query; @@ -2547,6 +2560,26 @@ impl<'a> DriveDocumentQuery<'a> { } } + #[cfg(any(feature = "server", feature = "verify"))] + /// The cursor lookup for the protocol 15 layout, where a keep-history + /// document's primary key tree entry points at its current revision: the + /// cursor is always the document id in the primary key tree. + pub fn start_at_document_path_and_key_v1( + &self, + starts_at: &[u8; 32], + ) -> (Vec>, Vec) { + let document_holding_path = self + .contract + .documents_primary_key_path(self.document_type.name().as_str()); + ( + document_holding_path + .into_iter() + .map(|key| key.to_vec()) + .collect::>(), + starts_at.to_vec(), + ) + } + #[cfg(any(feature = "server", feature = "verify"))] /// Versioned preflight over the shape of the query's where clauses, run /// by the server and the verifier alike before any lowering. @@ -2727,6 +2760,16 @@ impl<'a> DriveDocumentQuery<'a> { drive_operations: &mut Vec, platform_version: &PlatformVersion, ) -> Result { + if self.document_type.documents_keep_history() + && self.block_time_ms.is_some() + && primary_key_path_query_target(platform_version)? + == PrimaryKeyPathQueryTarget::CurrentDocument + { + return Err(Error::Query(QuerySyntaxError::Unsupported( + "point-in-time reads are unavailable for history-keeping document types" + .to_string(), + ))); + } self.validate_where_clause_shape(platform_version)?; self.refuse_a_private_document_type()?; // indexOnly documents have no primary-key tree: nothing is ever @@ -2786,7 +2829,13 @@ impl<'a> DriveDocumentQuery<'a> { // from the backing store let (start_at_document_path, start_at_document_key) = - self.start_at_document_path_and_key(starts_at); + if primary_key_path_query_target(platform_version)? + == PrimaryKeyPathQueryTarget::CurrentDocument + { + self.start_at_document_path_and_key_v1(starts_at) + } else { + self.start_at_document_path_and_key(starts_at) + }; let start_at_document = drive .grove_get( start_at_document_path.as_slice().into(), @@ -2968,6 +3017,16 @@ impl<'a> DriveDocumentQuery<'a> { starts_at_document: Option, platform_version: &PlatformVersion, ) -> Result { + if self.document_type.documents_keep_history() + && self.block_time_ms.is_some() + && primary_key_path_query_target(platform_version)? + == PrimaryKeyPathQueryTarget::CurrentDocument + { + return Err(Error::Query(QuerySyntaxError::Unsupported( + "point-in-time reads are unavailable for history-keeping document types" + .to_string(), + ))); + } self.validate_where_clause_shape(platform_version)?; self.refuse_a_private_document_type()?; // indexOnly documents have no primary-key tree: nothing is ever @@ -3216,6 +3275,8 @@ impl<'a> DriveDocumentQuery<'a> { starts_at_document: Option<(Document, bool)>, platform_version: &PlatformVersion, ) -> Result { + let uses_current_document = primary_key_path_query_target(platform_version)? + == PrimaryKeyPathQueryTarget::CurrentDocument; let mut path = document_type_path; // Add primary key ($id) subtree @@ -3230,7 +3291,7 @@ impl<'a> DriveDocumentQuery<'a> { )?; query.insert_key(key); - if self.document_type.documents_keep_history() { + if self.document_type.documents_keep_history() && !uses_current_document { // if the documents keep history then we should insert a subquery if let Some(block_time) = self.block_time_ms { let encoded_block_time = encode_u64(block_time); @@ -3309,7 +3370,7 @@ impl<'a> DriveDocumentQuery<'a> { } } - if self.document_type.documents_keep_history() { + if self.document_type.documents_keep_history() && !uses_current_document { // if the documents keep history then we should insert a subquery if let Some(_block_time) = self.block_time_ms { //todo @@ -3350,7 +3411,7 @@ impl<'a> DriveDocumentQuery<'a> { }, } - if self.document_type.documents_keep_history() { + if self.document_type.documents_keep_history() && !uses_current_document { // if the documents keep history then we should insert a subquery if let Some(_block_time) = self.block_time_ms { return Err(Error::Query(QuerySyntaxError::Unsupported( @@ -4158,6 +4219,8 @@ mod tests { use std::option::Option::None; use crate::drive::Drive; + use crate::error::{drive::DriveError, Error}; + use crate::fees::op::LowLevelDriveOperation; use crate::query::{ DriveDocumentQuery, InternalClauses, OrderClause, WhereClause, WhereOperator, }; @@ -4211,6 +4274,116 @@ mod tests { (drive, contract) } + fn keep_history_contract() -> DataContract { + json_document_to_contract( + "tests/supporting_files/contract/family/family-contract-with-history.json", + false, + PlatformVersion::latest(), + ) + .expect("expected history contract") + } + + fn keep_history_primary_query(contract: &DataContract) -> DriveDocumentQuery<'_> { + DriveDocumentQuery { + contract, + document_type: contract + .document_type_for_name("person") + .expect("person document type"), + internal_clauses: InternalClauses::default(), + offset: None, + limit: Some(10), + order_by: IndexMap::default(), + start_at: None, + start_at_included: false, + block_time_ms: None, + resolved_time_ranges: vec![], + sub_queries: vec![], + } + } + + #[test] + fn should_select_keep_history_primary_path_by_query_version() { + let contract = keep_history_contract(); + let query = keep_history_primary_query(&contract); + let legacy = query + .construct_path_query(None, PlatformVersion::get(14).expect("protocol 14")) + .expect("legacy query"); + assert_eq!( + legacy.query.query.default_subquery_branch.subquery_path, + Some(vec![vec![0]]) + ); + + let current = query + .construct_path_query(None, PlatformVersion::get(15).expect("protocol 15")) + .expect("protocol 15 query"); + assert_eq!( + current.query.query.default_subquery_branch.subquery_path, + None + ); + } + + #[test] + fn should_reject_unknown_primary_key_path_query_version_in_pure_query() { + let contract = json_document_to_contract( + "tests/supporting_files/contract/family/family-contract.json", + false, + PlatformVersion::latest(), + ) + .expect("expected non-history contract"); + let query = keep_history_primary_query(&contract); + let mut platform_version = PlatformVersion::latest().clone(); + platform_version + .drive + .methods + .document + .document_history_storage_layout = 2; + + let error = query + .construct_path_query(None, &platform_version) + .expect_err("unknown path-query versions must fail closed"); + assert!(matches!( + error, + Error::Drive(DriveError::UnknownVersionMismatch { + method, + known_versions, + received: 2, + }) if method == "document_history_storage_layout" && known_versions == vec![0, 1] + )); + } + + #[test] + fn should_reject_unknown_primary_key_path_query_version_in_stateful_cursor_lookup() { + let drive = setup_drive_with_initial_state_structure(None); + let contract = keep_history_contract(); + let mut query = keep_history_primary_query(&contract); + query.start_at = Some([3; 32]); + let mut platform_version = PlatformVersion::latest().clone(); + platform_version + .drive + .methods + .document + .document_history_storage_layout = 2; + let mut operations: Vec = vec![]; + + let error = query + .construct_path_query_operations( + &drive, + false, + None, + &mut operations, + &platform_version, + ) + .expect_err("unknown path-query versions must fail closed"); + assert!(matches!( + error, + Error::Drive(DriveError::UnknownVersionMismatch { + method, + known_versions, + received: 2, + }) if method == "document_history_storage_layout" && known_versions == vec![0, 1] + )); + } + fn setup_withdrawal_contract() -> (Drive, DataContract) { let platform_version = PlatformVersion::latest(); @@ -5843,3 +6016,6 @@ mod tests { } } } + +#[cfg(test)] +mod grove_version_compatibility_tests; diff --git a/packages/rs-drive/src/query/primary_key_path_query/mod.rs b/packages/rs-drive/src/query/primary_key_path_query/mod.rs new file mode 100644 index 00000000000..c31809e252c --- /dev/null +++ b/packages/rs-drive/src/query/primary_key_path_query/mod.rs @@ -0,0 +1,28 @@ +//! Versioned primary-key layout selection for document queries. + +mod v0; +mod v1; + +use crate::drive::document::uses_current_document_history_layout; +use crate::error::Error; +use dpp::version::PlatformVersion; + +/// The value stored below a keep-history document's primary key. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub(in crate::query) enum PrimaryKeyPathQueryTarget { + /// The primary key contains a subtree of timestamp-keyed revisions. + LegacyHistoryTree, + /// The primary key contains the current document, directly in the ordinary + /// layout or through a reference to the current retained revision at PV15. + CurrentDocument, +} + +pub(in crate::query) fn primary_key_path_query_target( + platform_version: &PlatformVersion, +) -> Result { + if uses_current_document_history_layout(platform_version)? { + Ok(v1::primary_key_path_query_target_v1()) + } else { + Ok(v0::primary_key_path_query_target_v0()) + } +} diff --git a/packages/rs-drive/src/query/primary_key_path_query/v0/mod.rs b/packages/rs-drive/src/query/primary_key_path_query/v0/mod.rs new file mode 100644 index 00000000000..ca0bf5b00a7 --- /dev/null +++ b/packages/rs-drive/src/query/primary_key_path_query/v0/mod.rs @@ -0,0 +1,6 @@ +use super::PrimaryKeyPathQueryTarget; + +/// Primary-key layout used through protocol version 14. +pub(super) const fn primary_key_path_query_target_v0() -> PrimaryKeyPathQueryTarget { + PrimaryKeyPathQueryTarget::LegacyHistoryTree +} diff --git a/packages/rs-drive/src/query/primary_key_path_query/v1/mod.rs b/packages/rs-drive/src/query/primary_key_path_query/v1/mod.rs new file mode 100644 index 00000000000..97d17257332 --- /dev/null +++ b/packages/rs-drive/src/query/primary_key_path_query/v1/mod.rs @@ -0,0 +1,6 @@ +use super::PrimaryKeyPathQueryTarget; + +/// Primary-key layout introduced in protocol version 15. +pub(super) const fn primary_key_path_query_target_v1() -> PrimaryKeyPathQueryTarget { + PrimaryKeyPathQueryTarget::CurrentDocument +} diff --git a/packages/rs-drive/src/query/single_document_drive_query.rs b/packages/rs-drive/src/query/single_document_drive_query.rs index 1bee60799c3..d648d1c2689 100644 --- a/packages/rs-drive/src/query/single_document_drive_query.rs +++ b/packages/rs-drive/src/query/single_document_drive_query.rs @@ -1,4 +1,7 @@ use crate::drive::document::paths::contract_document_type_path_vec; +use crate::query::primary_key_path_query::{ + primary_key_path_query_target, PrimaryKeyPathQueryTarget, +}; use crate::util::common::encode::encode_u64; use crate::drive::votes; @@ -110,13 +113,46 @@ impl SingleDocumentDriveQuery { &self, platform_version: &PlatformVersion, ) -> Result { + if self.document_type_keeps_history + && self.block_time_ms.is_some() + && primary_key_path_query_target(platform_version)? + == PrimaryKeyPathQueryTarget::CurrentDocument + { + return Err(Error::Query(QuerySyntaxError::Unsupported( + "point-in-time reads are unavailable for history-keeping document types" + .to_string(), + ))); + } match self.contested_status { SingleDocumentDriveQueryContestedStatus::NotContested => { - Ok(self.construct_non_contested_path_query(true)) + self.construct_non_contested_path_query(true, platform_version) } SingleDocumentDriveQueryContestedStatus::MaybeContested => { - let non_contested = self.construct_non_contested_path_query(true); - let contested = self.construct_contested_path_query(true); + let mut non_contested = + self.construct_non_contested_path_query(true, platform_version)?; + let mut contested = self.construct_contested_path_query(true); + if platform_version + .drive + .grove_version + .grovedb_versions + .path_query_methods + .merge + == 2 + { + // Each branch selects one document, so turning its global limit into an + // instance cap produces the same merged bytes as the earlier limit lift. + for selection in [&mut non_contested, &mut contested] { + if let Some(global_limit) = selection.query.limit.take() { + selection.query.query.limit = Some( + selection + .query + .query + .limit + .map_or(global_limit, |limit| limit.min(global_limit)), + ); + } + } + } PathQuery::merge( vec![&non_contested, &contested], &platform_version.drive.grove_version, @@ -130,7 +166,13 @@ impl SingleDocumentDriveQuery { } /// Operations to construct the normal path query. - fn construct_non_contested_path_query(&self, with_limit_1: bool) -> PathQuery { + fn construct_non_contested_path_query( + &self, + with_limit_1: bool, + platform_version: &PlatformVersion, + ) -> Result { + let uses_current_document = primary_key_path_query_target(platform_version)? + == PrimaryKeyPathQueryTarget::CurrentDocument; // First we should get the overall document_type_path let mut path = contract_document_type_path_vec(&self.contract_id, self.document_type_name.as_str()); @@ -140,7 +182,7 @@ impl SingleDocumentDriveQuery { let mut query = Query::new(); query.insert_key(self.document_id.to_vec()); - if self.document_type_keeps_history { + if self.document_type_keeps_history && !uses_current_document { // if the documents keep history then we should insert a subquery if let Some(block_time) = self.block_time_ms { let encoded_block_time = encode_u64(block_time); @@ -154,7 +196,7 @@ impl SingleDocumentDriveQuery { let limit = if with_limit_1 { Some(1) } else { None }; - PathQuery::new(path, SizedQuery::new(query, limit, None)) + Ok(PathQuery::new(path, SizedQuery::new(query, limit, None))) } /// Operations to construct the contested path query. @@ -187,6 +229,273 @@ impl TryFromPlatformVersioned for PathQuery { #[cfg(test)] mod tests { use super::*; + use crate::error::drive::DriveError; + #[cfg(feature = "full")] + use crate::util::test_helpers::setup::setup_drive; + #[cfg(feature = "full")] + use grovedb::query_result_type::QueryResultType::QueryPathKeyElementTrioResultType; + #[cfg(feature = "full")] + use grovedb::{Element, GroveDb}; + #[cfg(feature = "full")] + use grovedb_version::version::{v4::GROVE_V4, v5::GROVE_V5}; + #[cfg(feature = "full")] + use std::collections::BTreeSet; + + fn keep_history_query(block_time_ms: Option) -> SingleDocumentDriveQuery { + SingleDocumentDriveQuery { + contract_id: [1; 32], + document_type_name: "note".to_string(), + document_type_keeps_history: true, + document_id: [2; 32], + block_time_ms, + contested_status: SingleDocumentDriveQueryContestedStatus::NotContested, + } + } + + #[test] + fn should_select_keep_history_primary_path_by_query_version() { + let query = keep_history_query(None); + let legacy = query + .construct_path_query(PlatformVersion::get(14).expect("protocol 14")) + .expect("legacy query"); + assert_eq!( + legacy.query.query.default_subquery_branch.subquery_path, + Some(vec![vec![0]]) + ); + + let current = query + .construct_path_query(PlatformVersion::get(15).expect("protocol 15")) + .expect("protocol 15 query"); + assert_eq!( + current.query.query.default_subquery_branch.subquery_path, + None + ); + + let legacy_point_in_time = keep_history_query(Some(1000)) + .construct_path_query(PlatformVersion::get(14).expect("protocol 14")) + .expect("legacy point-in-time query"); + assert!(legacy_point_in_time + .query + .query + .default_subquery_branch + .subquery + .is_some()); + assert!(matches!( + keep_history_query(Some(1000)) + .construct_path_query(PlatformVersion::get(15).expect("protocol 15")), + Err(Error::Query(QuerySyntaxError::Unsupported(message))) + if message == "point-in-time reads are unavailable for history-keeping document types" + )); + } + + #[test] + fn should_merge_maybe_contested_legacy_history_for_a_protocol_15_caller() { + let mut caller = PlatformVersion::get(15).expect("protocol 15").clone(); + caller + .drive + .methods + .document + .document_history_storage_layout = 0; + let mut query = keep_history_query(None); + query.contested_status = SingleDocumentDriveQueryContestedStatus::MaybeContested; + let actual = query + .construct_path_query(&caller) + .expect("legacy history query merges"); + let expected = query + .construct_path_query(PlatformVersion::get(14).expect("protocol 14")) + .expect("released query merges"); + assert_eq!(actual, expected); + } + + #[cfg(feature = "full")] + #[test] + fn should_preserve_single_document_merge_bytes_and_results_across_layouts() { + for layout in [0, 1] { + for keeps_history in [false, true] { + for present in [false, true] { + let mut caller = PlatformVersion::latest().clone(); + caller + .drive + .methods + .document + .document_history_storage_layout = layout; + let mut previous = caller.clone(); + previous.drive.grove_version = GROVE_V4; + let drive = setup_drive(None); + let mut query = keep_history_query(None); + query.document_type_keeps_history = keeps_history; + let ordinary = query + .construct_non_contested_path_query(true, &caller) + .unwrap(); + let contested = query.construct_contested_path_query(true); + let mut created = BTreeSet::new(); + for path in [&ordinary.path, &contested.path] { + for depth in 0..path.len() { + if created.insert(path[..=depth].to_vec()) { + drive + .grove + .insert( + &path[..depth], + &path[depth], + Element::empty_tree(), + None, + None, + &GROVE_V5, + ) + .unwrap() + .expect("selection subtree"); + } + } + } + if present { + let mut document_path = ordinary.path.clone(); + let key = if keeps_history && layout == 0 { + drive + .grove + .insert( + document_path.as_slice(), + &query.document_id, + Element::empty_tree(), + None, + None, + &GROVE_V5, + ) + .unwrap() + .expect("legacy document subtree"); + document_path.push(query.document_id.to_vec()); + vec![0] + } else { + query.document_id.to_vec() + }; + drive + .grove + .insert( + document_path.as_slice(), + &key, + Element::new_item(vec![7]), + None, + None, + &GROVE_V5, + ) + .unwrap() + .expect("ordinary document"); + drive + .grove + .insert( + contested.path.as_slice(), + &query.document_id, + Element::new_item(vec![8]), + None, + None, + &GROVE_V5, + ) + .unwrap() + .expect("contested document"); + } + for status in [ + SingleDocumentDriveQueryContestedStatus::NotContested, + SingleDocumentDriveQueryContestedStatus::Contested, + SingleDocumentDriveQueryContestedStatus::MaybeContested, + ] { + query.contested_status = status; + let old = query.construct_path_query(&previous).expect("V4 query"); + let new = query.construct_path_query(&caller).expect("V5 query"); + assert_eq!( + old, new, + "layout {layout}, history {keeps_history}, present {present}" + ); + let config = bincode::config::standard().with_big_endian(); + assert_eq!( + bincode::encode_to_vec(&old, config).unwrap(), + bincode::encode_to_vec(&new, config).unwrap() + ); + let read = |selection: &PathQuery, grove_version| { + drive + .grove + .query_raw( + selection, + false, + true, + true, + QueryPathKeyElementTrioResultType, + None, + grove_version, + ) + .unwrap() + .expect("document selection") + .0 + .to_path_key_elements() + }; + let expected = read(&old, &GROVE_V4); + assert_eq!(read(&new, &GROVE_V5), expected); + assert_eq!( + expected.len(), + if present { + if query.contested_status + == SingleDocumentDriveQueryContestedStatus::MaybeContested + { + 2 + } else { + 1 + } + } else { + 0 + } + ); + for (selection, grove_version) in [(&old, &GROVE_V4), (&new, &GROVE_V5)] { + let proof = drive + .grove + .prove_query(selection, None, grove_version) + .unwrap() + .expect("document proof"); + let (root, rows) = + GroveDb::verify_query(&proof, selection, grove_version) + .expect("verified document proof"); + assert_eq!( + root, + drive.grove.root_hash(None, grove_version).unwrap().unwrap() + ); + let (current_root, current_rows) = + GroveDb::verify_query(&proof, &new, &GROVE_V5) + .expect("current verifier accepts the producer's proof"); + assert_eq!((current_root, ¤t_rows), (root, &rows)); + assert_eq!( + rows.into_iter() + .filter(|(_, _, element)| element.is_some()) + .count(), + expected.len() + ); + } + } + } + } + } + } + + #[test] + fn should_reject_unknown_primary_key_path_query_version() { + let mut platform_version = PlatformVersion::latest().clone(); + platform_version + .drive + .methods + .document + .document_history_storage_layout = 2; + + let mut query = keep_history_query(None); + query.document_type_keeps_history = false; + let error = query + .construct_path_query(&platform_version) + .expect_err("unknown path-query versions must fail closed"); + assert!(matches!( + error, + Error::Drive(DriveError::UnknownVersionMismatch { + method, + known_versions, + received: 2, + }) if method == "document_history_storage_layout" && known_versions == vec![0, 1] + )); + } + use dpp::decision_proposal::{ DECISION_PROPOSALS_CONTRACT_ID, DECISION_PROPOSAL_FUND_NAME, PROPOSAL_DOCUMENT_TYPE_NAME, }; diff --git a/packages/rs-drive/src/structure/tests.rs b/packages/rs-drive/src/structure/tests.rs index bf51fd0e283..b8635dbfbc5 100644 --- a/packages/rs-drive/src/structure/tests.rs +++ b/packages/rs-drive/src/structure/tests.rs @@ -532,7 +532,15 @@ mod fixtures { /// Checks the state against the description, and records the shape of /// every layer below a template that is fuller here than seen so far fn conformance_of(drive: &Drive, fixture: &str, run: &mut FixtureRun) { - let platform_version = PlatformVersion::latest(); + conformance_of_at_version(drive, fixture, run, PlatformVersion::latest()); + } + + fn conformance_of_at_version( + drive: &Drive, + fixture: &str, + run: &mut FixtureRun, + platform_version: &PlatformVersion, + ) { let structure = drive_structure(); let report = check_conformance(drive, &structure, None, platform_version) .expect("expected to walk the state"); @@ -676,6 +684,52 @@ mod fixtures { conformance_of(&drive, "contracts_with_documents", run); } + fn legacy_document_histories(run: &mut FixtureRun) { + let version = PlatformVersion::get(14).expect("protocol 14"); + let drive = setup_drive_with_initial_state_structure(Some(version)); + let contract = setup_contract( + &drive, + "tests/supporting_files/contract/family/family-contract-with-history.json", + Some([77; 32]), + None, + Some(|contract: &mut DataContract| { + contract.config_mut().set_can_be_deleted(true); + }), + None, + Some(version), + ); + let person = contract.document_type_for_name("person").expect("person"); + for seed in 1..4 { + let document = person + .random_document(Some(seed), version) + .expect("fixture document"); + let flags = (seed == 2).then(|| { + Cow::Owned(StorageFlags::new_single_epoch( + 0, + Some(document.owner_id().to_buffer()), + )) + }); + drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentRefInfo((&document, flags)), + owner_id: None, + }, + contract: &contract, + document_type: person, + }, + false, + BlockInfo::default(), + true, + None, + version, + ) + .expect("insert legacy document"); + } + conformance_of_at_version(&drive, "legacy_document_histories", run, version); + } + /// A contract whose moderators only delete documents: no list, one document type they can /// delete from, one removal record. Kept apart from the contract with both lists, whose /// other tree is the fullest one and the one whose shape is recorded. @@ -1909,6 +1963,7 @@ mod fixtures { let mut run = FixtureRun::default(); identities(&mut run); contracts_with_documents(&mut run); + legacy_document_histories(&mut run); expiring_documents(&mut run); moderated_contract(&mut run); warned_contract(&mut run); diff --git a/packages/rs-drive/src/util/test_helpers/history_proof.rs b/packages/rs-drive/src/util/test_helpers/history_proof.rs new file mode 100644 index 00000000000..246905e80ba --- /dev/null +++ b/packages/rs-drive/src/util/test_helpers/history_proof.rs @@ -0,0 +1,110 @@ +//! Legacy GroveDB proof fixtures for document-history format validation. +use dpp::version::PlatformVersion; +use grovedb::operations::proof::{ + GroveDBProof, GroveDBProofV0, LayerProof, MerkOnlyLayerProof, ProofBytes, ProveOptions, +}; +use grovedb::Element; +use grovedb_query::proofs::{encode_into, Decoder, Node, Op}; + +/// Converts a proof to the legacy envelope with an optional terminal count override. +/// The legacy node retains the committed value hash independently of its bytes. +pub fn downgrade_history_count( + proof: &[u8], + count: Option, + version: &PlatformVersion, +) -> Vec { + fn downgrade( + layer: LayerProof, + count: Option, + version: &PlatformVersion, + changed: &mut usize, + ) -> MerkOnlyLayerProof { + let ProofBytes::Merk(bytes) = layer.merk_proof else { + panic!("expected Merk layer") + }; + let ops: Vec<_> = Decoder::new(&bytes) + .map(|op| { + let op = op.unwrap(); + let (node, inverted) = match op { + Op::Push(node) => (node, false), + Op::PushInverted(node) => (node, true), + other => return other, + }; + let node = match node { + Node::KVValueHash(key, value, hash) => { + let mut element = + Element::deserialize(&value, &version.drive.grove_version).unwrap(); + if let ( + Some(count), + Element::ProvableCountTree(_, ref mut stored_count, _), + ) = (count, &mut element) + { + *stored_count = count; + *changed += 1; + } + Node::KVValueHash( + key, + element.serialize(&version.drive.grove_version).unwrap(), + hash, + ) + } + Node::KVValueHashFeatureTypeWithChildHash(key, value, hash, feature, _) + | Node::KVValueHashFeatureType(key, value, hash, feature) => { + let mut element = + Element::deserialize(&value, &version.drive.grove_version).unwrap(); + if let ( + Some(count), + Element::ProvableCountTree(_, ref mut stored_count, _), + ) = (count, &mut element) + { + *stored_count = count; + *changed += 1; + } + Node::KVValueHashFeatureType( + key, + element.serialize(&version.drive.grove_version).unwrap(), + hash, + feature, + ) + } + other => other, + }; + if inverted { + Op::PushInverted(node) + } else { + Op::Push(node) + } + }) + .collect(); + let mut bytes = vec![]; + encode_into(ops.iter(), &mut bytes); + MerkOnlyLayerProof { + merk_proof: bytes, + lower_layers: layer + .lower_layers + .into_iter() + .map(|(key, layer)| (key, downgrade(layer, count, version, changed))) + .collect(), + } + } + let config = bincode::config::standard().with_big_endian(); + let (proof, _): (GroveDBProof, _) = bincode::decode_from_slice(proof, config).unwrap(); + let GroveDBProof::V1(proof) = proof else { + panic!("expected V1 proof") + }; + let mut changed = 0; + let root_layer = downgrade(proof.root_layer, count, version, &mut changed); + assert_eq!( + changed, + usize::from(count.is_some()), + "must override exactly the history tree count" + ); + bincode::encode_to_vec( + GroveDBProof::V0(GroveDBProofV0 { + root_layer, + prove_options: ProveOptions::default(), + }), + config, + ) + .unwrap() +} diff --git a/packages/rs-drive/src/util/test_helpers/mod.rs b/packages/rs-drive/src/util/test_helpers/mod.rs index 80f379bef5c..a045d433d77 100644 --- a/packages/rs-drive/src/util/test_helpers/mod.rs +++ b/packages/rs-drive/src/util/test_helpers/mod.rs @@ -355,6 +355,9 @@ pub fn cbor_inner_map_value<'a>( None } +#[cfg(any(test, feature = "fixtures-and-mocks"))] +/// History proof envelope fixtures. +pub mod history_proof; #[cfg(feature = "fixtures-and-mocks")] /// The yappr-likes `contract` with its `like` type read whole through /// `byLiker`: without a proof, a chained read is refused when its inner index diff --git a/packages/rs-drive/src/verify/document/verify_document_history/mod.rs b/packages/rs-drive/src/verify/document/verify_document_history/mod.rs index fb625cfa545..9dcad7b849a 100644 --- a/packages/rs-drive/src/verify/document/verify_document_history/mod.rs +++ b/packages/rs-drive/src/verify/document/verify_document_history/mod.rs @@ -1,28 +1,45 @@ mod v0; +mod v1; + +#[cfg(all(test, feature = "server", feature = "verify"))] +mod tests; use crate::drive::Drive; +use dpp::document::Document; +use std::collections::BTreeMap; + use crate::error::drive::DriveError; use crate::error::Error; +use crate::query::document_history_drive_query::{ + DocumentHistoryDriveQuery, DocumentHistoryDriveQueryExecutionResult, +}; +use crate::verify::grovedb_proof_envelope::require_supported_grovedb_proof_envelope; use crate::verify::RootHash; use dpp::data_contract::document_type::DocumentTypeRef; -use dpp::document::Document; use dpp::version::PlatformVersion; -use std::collections::BTreeMap; impl Drive { - /// Verifies that the document's history is included in the proof. + /// Verifies the per-document timestamp-keyed history used through protocol version 14. + /// + /// # Parameters + /// `start_after_ms` excludes matching timestamps; `offset` optionally skips entries after + /// that bound for unproved queries. The platform version must select the timestamp-keyed reader. + /// + /// # Returns + /// The history result, or an error for an unsupported reader generation. #[allow(clippy::too_many_arguments)] - pub fn verify_document_history( + pub fn verify_document_history_after_time( proof: &[u8], contract_id: [u8; 32], document_type_name: &str, document_type: DocumentTypeRef, document_id: [u8; 32], - start_at_ms: u64, + start_after_ms: u64, limit: Option, offset: Option, platform_version: &PlatformVersion, ) -> Result<(RootHash, Option>), Error> { + require_supported_grovedb_proof_envelope(proof, "document history proof")?; match platform_version .drive .methods @@ -30,22 +47,45 @@ impl Drive { .document .verify_document_history { - 0 => Drive::verify_document_history_v0( + 0 => Self::verify_document_history_v0( proof, contract_id, document_type_name, document_type, document_id, - start_at_ms, + start_after_ms, limit, offset, platform_version, ), version => Err(Error::Drive(DriveError::UnknownVersionMismatch { - method: "verify_document_history".to_string(), + method: "verify_document_history_after_time".to_owned(), known_versions: vec![0], received: version, })), } } + + /// Verifies a proved page and lifecycle from the per-type composite-keyed history tree. + pub fn verify_document_history( + query: &DocumentHistoryDriveQuery, + proof: &[u8], + document_type: DocumentTypeRef, + platform_version: &PlatformVersion, + ) -> Result<(RootHash, DocumentHistoryDriveQueryExecutionResult), Error> { + match platform_version + .drive + .methods + .verify + .document + .verify_document_history + { + 1 => Drive::verify_document_history_v1(query, proof, document_type, platform_version), + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "verify_document_history".to_string(), + known_versions: vec![1], + received: version, + })), + } + } } diff --git a/packages/rs-drive/src/verify/document/verify_document_history/tests.rs b/packages/rs-drive/src/verify/document/verify_document_history/tests.rs new file mode 100644 index 00000000000..94ebb620268 --- /dev/null +++ b/packages/rs-drive/src/verify/document/verify_document_history/tests.rs @@ -0,0 +1,1401 @@ +use crate::drive::document::paths::{ + contract_document_type_path_vec, document_history_path, DOCUMENT_HISTORY_TREE_KEY, +}; +use crate::drive::Drive; +use crate::error::Error; +use crate::query::document_history_drive_query::{ + DocumentHistoryDriveQuery, DocumentHistoryDriveQueryExecutionResult, DocumentHistoryFilter, + DocumentHistoryLifecycle, DocumentHistoryState, +}; +use crate::query::{SingleDocumentDriveQuery, SingleDocumentDriveQueryContestedStatus}; +use crate::util::common::encode::encode_u64; +use crate::util::object_size_info::{DocumentAndContractInfo, DocumentInfo, OwnedDocumentInfo}; +use crate::util::test_helpers::setup::setup_drive_with_initial_state_structure; +use crate::verify::RootHash; +use dpp::block::block_info::BlockInfo; +use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::data_contract::document_type::DocumentTypeRef; +use dpp::document::serialization_traits::DocumentPlatformConversionMethodsV0; +use dpp::document::DocumentV0Getters; +use dpp::document::DocumentV0Setters; +use dpp::tests::json_document::{json_document_to_contract, json_document_to_document}; +use dpp::version::PlatformVersion; +use grovedb::{Element, PathQuery, Query, SizedQuery}; + +/// Fetches and proves a page at a protocol version that stores the history +/// tree, returning the ordinary GroveDB proof for tampering. +fn prove( + drive: &Drive, + query: &DocumentHistoryDriveQuery, + document_type: DocumentTypeRef, + version: &PlatformVersion, +) -> (DocumentHistoryDriveQueryExecutionResult, Vec) { + let page = drive + .fetch_document_history(query, document_type, None, version) + .unwrap(); + let proof = drive + .prove_document_history(query, document_type, None, version) + .unwrap(); + (page, proof) +} + +fn verify( + query: &DocumentHistoryDriveQuery, + proof: &[u8], + document_type: DocumentTypeRef, + version: &PlatformVersion, +) -> Result<(RootHash, DocumentHistoryDriveQueryExecutionResult), Error> { + Drive::verify_document_history(query, proof, document_type, version) +} + +fn lifecycle(page: &DocumentHistoryDriveQueryExecutionResult) -> &DocumentHistoryLifecycle { + page.lifecycle + .as_ref() + .expect("pages of the history tree carry a lifecycle") +} + +#[test] +fn should_serve_history_as_one_grovedb_proof_with_trusted_read_parity() { + let version = PlatformVersion::latest(); + let drive = setup_drive_with_initial_state_structure(None); + let contract = json_document_to_contract( + "tests/supporting_files/contract/dashpay/dashpay-contract-with-profile-history.json", + false, + version, + ) + .unwrap(); + drive + .apply_contract(&contract, BlockInfo::default(), true, None, None, version) + .unwrap(); + let document_type = contract.document_type_for_name("profile").unwrap(); + let mut document = json_document_to_document( + "tests/supporting_files/contract/dashpay/profile0.json", + Some([8; 32].into()), + document_type, + version, + ) + .unwrap(); + for revision in 1..=3 { + document.set_revision(Some(revision)); + drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentInfo::DocumentRefInfo((&document, None)), + owner_id: None, + }, + contract: &contract, + document_type, + }, + true, + BlockInfo::default_with_time(2000), + true, + None, + version, + ) + .unwrap(); + } + let root = drive + .grove + .root_hash(None, &version.drive.grove_version) + .unwrap() + .unwrap(); + let mut failures = vec![]; + for document_id in [document.id().to_buffer(), [255; 32]] { + for filter in [ + DocumentHistoryFilter::StartAtTime(2000), + DocumentHistoryFilter::StartAfter { + time_ms: 2000, + revision: 1, + }, + DocumentHistoryFilter::StartAtRevision(2), + DocumentHistoryFilter::Revision(2), + DocumentHistoryFilter::Revision(4), + DocumentHistoryFilter::Revision(65536), + ] { + let query = DocumentHistoryDriveQuery { + contract_id: contract.id().to_buffer(), + document_type_name: "profile".into(), + document_id, + filter, + limit: None, + }; + let fetched = query + .execute_no_proof(&drive, document_type, None, version) + .unwrap(); + let proof = query + .execute_with_proof(&drive, document_type, None, version) + .unwrap(); + println!( + "single proof sample {:?}, absent={}: {} bytes", + query.filter, + document_id == [255; 32], + proof.len() + ); + match grovedb::GroveDb::verify_query_raw( + &proof, + &query.construct_path_query(version).unwrap(), + &version.drive.grove_version, + ) { + Ok((proved_root, rows)) => { + assert_eq!(proved_root, root); + assert_eq!( + rows.len(), + fetched.entries.len() + usize::from(document_id != [255; 32]) * 2 + ); + assert_eq!( + query + .verify_document_history_proof(&proof, document_type, version) + .unwrap(), + (root, fetched) + ); + } + Err(error) => failures.push(format!( + "{:?}, absent={}: {error}", + query.filter, + document_id == [255; 32] + )), + } + } + } + assert!( + failures.is_empty(), + "history must be one ordinary GroveDB proof: {failures:#?}" + ); +} + +#[test] +fn should_leave_exact_history_reads_unlimited_in_the_merged_query() { + fn check(query: &Query, page_limits: &mut usize) { + let children: Vec<_> = query + .default_subquery_branch + .subquery + .iter() + .chain( + query + .conditional_subquery_branches + .iter() + .flat_map(|branches| branches.values()) + .filter_map(|branch| branch.subquery.as_ref()), + ) + .collect(); + assert!(query.left_to_right); + if children.is_empty() + && query + .items + .iter() + .any(|item| !matches!(item, grovedb::QueryItem::Key(_))) + { + assert!(query.limit.is_some(), "only the history page is limited"); + *page_limits += 1; + } else { + assert_eq!(query.offset, None, "only the page may skip results"); + assert_eq!( + query.limit, None, + "exact selections and enclosing nodes must prove absence without truncation" + ); + } + for child in children { + check(child, page_limits); + } + } + let query = DocumentHistoryDriveQuery { + contract_id: [1; 32], + document_type_name: "profile".into(), + document_id: [2; 32], + filter: DocumentHistoryFilter::StartAtRevision(7), + limit: Some(2), + }; + let merged = query + .construct_path_query(PlatformVersion::latest()) + .unwrap(); + assert_eq!( + merged.path, + contract_document_type_path_vec(&query.contract_id, &query.document_type_name) + ); + assert_eq!( + merged.query.limit, None, + "a global limit could omit an exact sibling" + ); + assert_eq!(merged.query.offset, None); + let history = merged + .query + .query + .conditional_subquery_branches + .as_ref() + .unwrap() + .get(&grovedb::QueryItem::Key(vec![DOCUMENT_HISTORY_TREE_KEY])) + .unwrap() + .subquery + .as_ref() + .unwrap(); + assert!(history.add_parent_tree_on_subquery); + let mut page_limits = 0; + check(&merged.query.query, &mut page_limits); + assert_eq!(page_limits, 1); +} + +#[test] +fn should_serve_both_history_pointer_types_as_one_grovedb_proof() { + use dpp::data_contract::DataContractFactory; + use dpp::document::document_factory::DocumentFactory; + use dpp::platform_value::platform_value; + + let version = PlatformVersion::latest(); + for summable in [true, false] { + let drive = setup_drive_with_initial_state_structure(Some(version)); + let mut schema = platform_value!({ + "type": "object", "documentsKeepHistory": true, "canBeDeleted": false, + "properties": {"amount": {"type": "integer", "minimum": 0, "maximum": 100, "position": 0}}, + "required": ["amount"], "additionalProperties": false + }); + if summable { + schema + .insert("documentsSummable".into(), "amount".into()) + .unwrap(); + } + let contract = DataContractFactory::new(version.protocol_version) + .unwrap() + .create_with_value_config( + [7; 32].into(), + 0, + platform_value!({"note": schema}), + None, + None, + ) + .unwrap() + .data_contract_owned(); + drive + .apply_contract(&contract, BlockInfo::default(), true, None, None, version) + .unwrap(); + let document_type = contract.document_type_for_name("note").unwrap(); + let mut document = DocumentFactory::new(version.protocol_version) + .unwrap() + .create_document( + &contract, + [7; 32].into(), + "note".into(), + platform_value!({"amount": 5}), + ) + .unwrap(); + for revision in 1..=3 { + document.set_revision(Some(revision)); + drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentInfo::DocumentRefInfo((&document, None)), + owner_id: None, + }, + contract: &contract, + document_type, + }, + true, + BlockInfo::default_with_time(2000), + true, + None, + version, + ) + .unwrap(); + } + let mut primary = contract_document_type_path_vec(contract.id().as_bytes(), "note"); + primary.push(vec![0]); + let pointer = drive + .grove + .get_raw( + primary.as_slice().into(), + document.id().as_bytes(), + None, + &version.drive.grove_version, + ) + .unwrap() + .unwrap(); + assert!(matches!( + (summable, pointer), + (false, Element::Reference(..)) | (true, Element::ReferenceWithSumItem(..)) + )); + let current_bytes = document + .serialize(document_type, &contract, version) + .unwrap(); + let root = drive + .grove + .root_hash(None, &version.drive.grove_version) + .unwrap() + .unwrap(); + for filter in [ + DocumentHistoryFilter::StartAtTime(0), + DocumentHistoryFilter::StartAfter { + time_ms: 2000, + revision: 1, + }, + DocumentHistoryFilter::StartAtRevision(2), + DocumentHistoryFilter::Revision(2), + ] { + let query = DocumentHistoryDriveQuery { + contract_id: contract.id().to_buffer(), + document_type_name: "note".into(), + document_id: document.id().to_buffer(), + filter, + limit: Some(1), + }; + let page = query + .execute_no_proof(&drive, document_type, None, version) + .unwrap(); + let proof = query + .execute_with_proof(&drive, document_type, None, version) + .unwrap(); + let (proved_root, _) = grovedb::GroveDb::verify_query_raw( + &proof, + &query.construct_path_query(version).unwrap(), + &version.drive.grove_version, + ) + .expect("history uses one ordinary GroveDB proof"); + assert_eq!(proved_root, root); + assert_eq!( + query + .verify_document_history_proof(&proof, document_type, version) + .unwrap(), + (root, page) + ); + // These pages exclude the current revision, so these bytes belong + // only to the resolved primary reference in the proof. + let matches: Vec<_> = proof + .windows(current_bytes.len()) + .enumerate() + .filter_map(|(position, bytes)| (bytes == current_bytes).then_some(position)) + .collect(); + assert_eq!(matches.len(), 1); + let mut changed = proof.clone(); + changed[matches[0] + current_bytes.len() - 1] ^= 1; + let result = query.verify_document_history_proof(&changed, document_type, version); + assert!( + result.is_err() || result.unwrap().0 != root, + "changed reference target bytes must never authenticate under the trusted root" + ); + } + } +} + +#[test] +fn should_preserve_non_history_roots_fees_and_proofs_after_grove_upgrade() { + use dpp::dashcore::hashes::sha256; + use grovedb_version::version::v4::GROVE_V4; + + for selected in [ + PlatformVersion::get(14).unwrap(), + PlatformVersion::get(15).unwrap(), + ] { + // Current upstream commitments pin replay compatibility independently of agreement + // between GroveDB engines. Protocol 15 stores contracts compiled. + let (expected_root, expected_proof) = if selected.protocol_version == 14 { + ( + "7dbeb13c417200f86e7f29d5f0967d62c222ae6f4abaf6d83a79adfc6ec732c1", + "b5b70531d251fcc2dfb134f35dd34ad7599e8fcbb22aed4ea9e3e7e9f73e6cae", + ) + } else { + ( + "651594de7d2cae89a6730ecdd0332a8b9702ca4ae0774765ffe4c5a8df75b7dc", + "19f71d377e3e4378cc613495e47b6854f41d1a626b37c6a35c8ea5f8e8a19126", + ) + }; + let mut reference = selected.clone(); + reference.drive.grove_version = GROVE_V4; + let mut observations = vec![]; + for version in [&reference, selected] { + let drive = setup_drive_with_initial_state_structure(Some(version)); + let contract = json_document_to_contract( + "tests/supporting_files/contract/dashpay/dashpay-contract.json", + false, + version, + ) + .unwrap(); + let contract_fee = drive + .apply_contract(&contract, BlockInfo::default(), true, None, None, version) + .unwrap(); + let document_type = contract.document_type_for_name("profile").unwrap(); + let document = json_document_to_document( + "tests/supporting_files/contract/dashpay/profile0.json", + Some([8; 32].into()), + document_type, + version, + ) + .unwrap(); + let document_fee = drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentInfo::DocumentRefInfo((&document, None)), + owner_id: None, + }, + contract: &contract, + document_type, + }, + true, + BlockInfo::default_with_time(2000), + true, + None, + version, + ) + .unwrap(); + let mut primary = contract_document_type_path_vec(contract.id().as_bytes(), "profile"); + primary.push(vec![0]); + let document_query = PathQuery::new_single_key(primary.clone(), document.id().to_vec()); + let absent_query = PathQuery::new_single_key(primary, vec![255; 32]); + let query = PathQuery::merge( + vec![&document_query, &absent_query], + &version.drive.grove_version, + ) + .unwrap(); + let reference_query = + PathQuery::merge(vec![&document_query, &absent_query], &GROVE_V4).unwrap(); + assert_eq!(query, reference_query); + let encode = |query: &PathQuery| { + bincode::encode_to_vec(query, bincode::config::standard().with_big_endian()) + .unwrap() + }; + assert_eq!(encode(&query), encode(&reference_query)); + let (rows, skipped) = drive + .grove_get_raw_path_query( + &query, + None, + grovedb::query_result_type::QueryResultType::QueryPathKeyElementTrioResultType, + &mut vec![], + &version.drive, + ) + .unwrap(); + assert_eq!(skipped, 0); + assert_eq!(rows.len(), 1); + let proof = drive + .grove_get_proved_path_query(&query, None, &mut vec![], &version.drive) + .unwrap(); + let (root, _) = + grovedb::GroveDb::verify_query_raw(&proof, &query, &version.drive.grove_version) + .unwrap(); + assert_eq!( + grovedb::GroveDb::verify_query_raw(&proof, &reference_query, &GROVE_V4) + .unwrap() + .0, + root, + "released Grove V4 verifier must accept offset-free V5 proofs" + ); + assert_eq!( + root, + drive + .grove + .root_hash(None, &version.drive.grove_version) + .unwrap() + .unwrap() + ); + assert_eq!(hex::encode(root), expected_root); + assert_eq!(sha256::Hash::hash(&proof).to_string(), expected_proof); + assert_eq!( + (contract_fee.storage_fee, contract_fee.processing_fee), + if selected.protocol_version == 14 { + (110_781_000, 1_773_200) + } else { + (178_335_000, 2_789_600) + } + ); + assert_eq!( + (document_fee.storage_fee, document_fee.processing_fee), + (35_235_000, 901_140) + ); + let mut second_document = document.clone(); + second_document.set_id([9; 32].into()); + second_document.set_owner_id([9; 32].into()); + drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentInfo::DocumentRefInfo((&second_document, None)), + owner_id: None, + }, + contract: &contract, + document_type, + }, + true, + BlockInfo::default_with_time(2000), + true, + None, + version, + ) + .unwrap(); + let request_type = contract.document_type_for_name("contactRequest").unwrap(); + let request_document = json_document_to_document( + "tests/supporting_files/contract/dashpay/contact-request0.json", + Some([10; 32].into()), + request_type, + version, + ) + .unwrap(); + drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentInfo::DocumentRefInfo((&request_document, None)), + owner_id: None, + }, + contract: &contract, + document_type: request_type, + }, + true, + BlockInfo::default_with_time(2000), + true, + None, + version, + ) + .unwrap(); + let mut reads = vec![]; + for grove_version in [&GROVE_V4, &version.drive.grove_version] { + // A range of document types descends into each primary tree. + // Branch-local limits already used by ordinary queries must + // keep both read results and metered work across the upgrade. + let mut types = Query::new_range_full(); + let mut primary = Query::new_single_key(vec![0]); + let mut page = Query::new_range_full(); + page.limit = Some(1); + primary.set_subquery(page); + types.set_subquery(primary); + let mut path = contract_document_type_path_vec(contract.id().as_bytes(), "profile"); + path.pop(); + let nested = PathQuery::new_unsized(path, types); + let read = drive.grove.query_raw( + &nested, + false, + true, + true, + grovedb::query_result_type::QueryResultType::QueryPathKeyElementTrioResultType, + None, + grove_version, + ); + let rows = read.value.unwrap(); + let row_bytes = bincode::encode_to_vec( + rows.0.clone().to_path_key_elements(), + bincode::config::standard().with_big_endian(), + ) + .unwrap(); + let nested_proof = drive + .grove + .prove_query(&nested, None, grove_version) + .value + .unwrap(); + let (_, proved_rows) = + grovedb::GroveDb::verify_query_raw(&nested_proof, &nested, grove_version) + .unwrap(); + assert_eq!(proved_rows.len(), 2); + let mut returned_types: Vec<_> = rows + .0 + .clone() + .to_path_key_elements() + .into_iter() + .map(|(path, _, _)| path[path.len() - 2].clone()) + .collect(); + returned_types.sort(); + assert_eq!( + returned_types, + [b"contactRequest".to_vec(), b"profile".to_vec()] + ); + assert_eq!( + sha256::Hash::hash(&row_bytes).to_string(), + "c487a48e31a5b99d8149824d99b061b7e6be3fb841a9e07dcf1856855fcab322", + "limited nested rows must retain their historical bytes", + ); + assert_eq!( + read.cost, + grovedb_costs::OperationCost { + seek_count: 23, + storage_loaded_bytes: 3408, + hash_node_calls: 10, + ..Default::default() + } + ); + let expected_nested_proof = if selected.protocol_version == 14 { + "9a1b6f2933735c9a54d7eadac8872d08ce5936e4bc798aa6d00abebd73248578" + } else { + "3c84d97bc0393698e5e2a33cd55e52c4e2f526dd4e13c96065578d25af797846" + }; + assert_eq!( + sha256::Hash::hash(&nested_proof).to_string(), + expected_nested_proof + ); + reads.push((rows, read.cost)); + } + assert_eq!( + reads[0], reads[1], + "nested local-limit reads must preserve metered work" + ); + observations.push((root, proof, contract_fee, document_fee)); + } + assert_eq!( + observations[0], observations[1], + "protocol {} roots, proofs and fees must stay equal to Grove V4", + selected.protocol_version + ); + } +} + +#[test] +fn should_authenticate_history_pages_metadata_and_absence() { + let version = PlatformVersion::latest(); + let drive = setup_drive_with_initial_state_structure(None); + let contract = json_document_to_contract( + "tests/supporting_files/contract/dashpay/dashpay-contract-with-profile-history.json", + false, + version, + ) + .unwrap(); + drive + .apply_contract(&contract, BlockInfo::default(), true, None, None, version) + .unwrap(); + let document_type = contract.document_type_for_name("profile").unwrap(); + let mut document = json_document_to_document( + "tests/supporting_files/contract/dashpay/profile0.json", + Some([8; 32].into()), + document_type, + version, + ) + .unwrap(); + for revision in 1..=22 { + document.set_revision(Some(revision)); + drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentInfo::DocumentRefInfo((&document, None)), + owner_id: None, + }, + contract: &contract, + document_type, + }, + true, + BlockInfo::default_with_time(2000), + true, + None, + version, + ) + .unwrap(); + } + let mut query = DocumentHistoryDriveQuery { + contract_id: contract.id().to_buffer(), + document_type_name: "profile".into(), + document_id: document.id().to_buffer(), + filter: DocumentHistoryFilter::StartAtTime(2000), + limit: Some(10), + }; + let mut seen = vec![]; + loop { + let (page, proof) = prove(&drive, &query, document_type, version); + let (_, verified) = verify(&query, &proof, document_type, version).unwrap(); + assert_eq!(verified, page); + assert_eq!(lifecycle(&verified).remaining_revisions, 22); + assert_eq!(lifecycle(&verified).state, DocumentHistoryState::Active); + seen.extend(page.entries.iter().map(|entry| entry.revision)); + let mut missing_proof = proof.clone(); + missing_proof.truncate(proof.len() / 2); + assert!(verify(&query, &missing_proof, document_type, version).is_err()); + let Some(last) = page.entries.last() else { + break; + }; + query.filter = DocumentHistoryFilter::StartAfter { + time_ms: last.time_ms, + revision: last.revision, + }; + } + assert_eq!(seen, (1..=22).collect::>()); + for filter in [ + DocumentHistoryFilter::Revision(1), + DocumentHistoryFilter::Revision(2), + DocumentHistoryFilter::Revision(22), + DocumentHistoryFilter::Revision(23), + DocumentHistoryFilter::StartAtRevision(7), + DocumentHistoryFilter::StartAtRevision(20), + ] { + let expected = match filter { + DocumentHistoryFilter::Revision(revision) => { + if revision <= 22 { + vec![revision] + } else { + vec![] + } + } + DocumentHistoryFilter::StartAtRevision(revision) => { + (revision..=(revision + 9).min(22)).collect() + } + _ => unreachable!(), + }; + query.filter = filter; + query.limit = None; + let (page, proof) = prove(&drive, &query, document_type, version); + let (_, verified) = verify(&query, &proof, document_type, version).unwrap(); + assert_eq!(verified, page); + assert_eq!( + page.entries + .iter() + .map(|entry| entry.revision) + .collect::>(), + expected + ); + assert_eq!(lifecycle(&page).remaining_revisions, 22); + } + query.filter = DocumentHistoryFilter::StartAtTime(0); + let (_, old_proof) = prove(&drive, &query, document_type, version); + document.set_revision(Some(23)); + drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentInfo::DocumentRefInfo((&document, None)), + owner_id: None, + }, + contract: &contract, + document_type, + }, + true, + BlockInfo::default_with_time(3000), + true, + None, + version, + ) + .unwrap(); + let (_, new_proof) = prove(&drive, &query, document_type, version); + assert_ne!( + verify(&query, &old_proof, document_type, version) + .unwrap() + .0, + verify(&query, &new_proof, document_type, version) + .unwrap() + .0, + "proofs authenticate their own state root" + ); + let bytes = document + .serialize(document_type, &contract, version) + .unwrap(); + for key in [vec![0; 8], vec![0; 15], vec![0; 17]] { + assert!(query + .decode_entries( + vec![(key, Element::new_item(bytes.clone()))], + document_type, + version + ) + .is_err()); + } + query.document_id = [255; 32]; + query.filter = DocumentHistoryFilter::Revision(2); + let (page, proof) = prove(&drive, &query, document_type, version); + let (_, verified) = verify(&query, &proof, document_type, version).unwrap(); + assert_eq!(page, verified); + assert_eq!(lifecycle(&verified).state, DocumentHistoryState::Absent); + assert_eq!(lifecycle(&verified).remaining_revisions, 0); + assert!(verified.entries.is_empty()); + + let history_path = document_history_path( + &query.contract_id, + &query.document_type_name, + &query.document_id, + ); + drive + .grove + .insert( + history_path[..5].to_vec().as_slice(), + &query.document_id, + Element::empty_provable_count_tree(), + None, + None, + &version.drive.grove_version, + ) + .value + .unwrap(); + query.filter = DocumentHistoryFilter::StartAtTime(0); + let (page, proof) = prove(&drive, &query, document_type, version); + let (_, verified) = verify(&query, &proof, document_type, version).unwrap(); + assert_eq!(page, verified); + assert_eq!(lifecycle(&verified).state, DocumentHistoryState::Absent); + assert_eq!(lifecycle(&verified).remaining_revisions, 0); +} + +#[test] +fn should_reject_point_in_time_history_reads_only_after_activation() { + let query = SingleDocumentDriveQuery { + contract_id: [1; 32], + document_type_name: "note".into(), + document_type_keeps_history: true, + document_id: [2; 32], + block_time_ms: Some(1000), + contested_status: SingleDocumentDriveQueryContestedStatus::NotContested, + }; + for protocol in [12, 13, 14] { + assert!(query + .construct_path_query(PlatformVersion::get(protocol).unwrap()) + .is_ok()); + } + assert!(query + .construct_path_query(PlatformVersion::get(15).unwrap()) + .is_err()); +} + +#[test] +fn should_reject_invalid_selectors_and_unsupported_protocols() { + let mut query = DocumentHistoryDriveQuery { + contract_id: [1; 32], + document_type_name: "note".into(), + document_id: [2; 32], + filter: DocumentHistoryFilter::StartAtTime(0), + limit: None, + }; + for filter in [ + DocumentHistoryFilter::Revision(0), + DocumentHistoryFilter::StartAtRevision(65537), + DocumentHistoryFilter::StartAtTime(1 << 63), + DocumentHistoryFilter::StartAfter { + time_ms: 0, + revision: 0, + }, + ] { + query.filter = filter; + assert!(query.validate().is_err()); + } + query.filter = DocumentHistoryFilter::Revision(65535); + assert!(query.validate().is_ok()); + query.limit = Some(2); + assert!(query.validate().is_err()); + query.limit = Some(1); + for protocol in [12, 13, 14] { + assert!(query + .construct_path_query(PlatformVersion::get(protocol).unwrap()) + .is_err()); + } + assert!(query + .construct_path_query(PlatformVersion::get(15).unwrap()) + .is_ok()); +} + +#[test] +fn should_address_every_revision_whose_offset_fits_the_grovedb_offset() { + let mut query = DocumentHistoryDriveQuery { + contract_id: [1; 32], + document_type_name: "note".into(), + document_id: [2; 32], + filter: DocumentHistoryFilter::StartAtTime(0), + limit: Some(1), + }; + for (revision, offset) in [(65535, 65534), (65536, u16::MAX)] { + for filter in [ + DocumentHistoryFilter::Revision(revision), + DocumentHistoryFilter::StartAtRevision(revision), + ] { + query.filter = filter; + let path_query = query + .construct_path_query(PlatformVersion::get(15).unwrap()) + .expect("revision addressable through a u16 offset"); + fn leaf_offset(query: &Query) -> Option { + query + .offset + .or_else(|| { + query + .default_subquery_branch + .subquery + .as_ref() + .and_then(|q| leaf_offset(q)) + }) + .or_else(|| { + query + .conditional_subquery_branches + .as_ref() + .and_then(|branches| { + branches.values().find_map(|branch| { + branch.subquery.as_ref().and_then(|q| leaf_offset(q)) + }) + }) + }) + } + assert_eq!(path_query.query.offset, None); + assert_eq!(leaf_offset(&path_query.query.query), Some(offset)); + } + } + for filter in [ + DocumentHistoryFilter::Revision(65537), + DocumentHistoryFilter::StartAtRevision(65537), + ] { + query.filter = filter; + assert!(query.validate().is_err()); + } +} + +#[test] +fn should_use_sequence_one_for_an_immutable_document_without_a_revision() { + use dpp::data_contract::DataContractFactory; + use dpp::document::document_factory::DocumentFactory; + use dpp::platform_value::platform_value; + let version = PlatformVersion::get(15).unwrap(); + let drive = setup_drive_with_initial_state_structure(Some(version)); + let contract = DataContractFactory::new(15).unwrap().create_with_value_config([7; 32].into(), 0, platform_value!({ + "note": {"type": "object", "documentsMutable": false, "documentsKeepHistory": true, "canBeDeleted": false, + "properties": {"message": {"type": "string", "maxLength": 256, "position": 0}}, "required": ["message"], "additionalProperties": false} + }), None, None).unwrap().data_contract_owned(); + drive + .apply_contract(&contract, BlockInfo::default(), true, None, None, version) + .unwrap(); + let document_type = contract.document_type_for_name("note").unwrap(); + let document = DocumentFactory::new(15) + .unwrap() + .create_document( + &contract, + [7; 32].into(), + "note".into(), + platform_value!({"message": "immutable"}), + ) + .unwrap(); + assert_eq!(document.revision(), None); + drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentInfo::DocumentRefInfo((&document, None)), + owner_id: None, + }, + contract: &contract, + document_type, + }, + false, + BlockInfo::default_with_time(2000), + true, + None, + version, + ) + .unwrap(); + let query = DocumentHistoryDriveQuery { + contract_id: contract.id().to_buffer(), + document_type_name: "note".into(), + document_id: document.id().to_buffer(), + filter: DocumentHistoryFilter::Revision(1), + limit: None, + }; + let (history, proof) = prove(&drive, &query, document_type, version); + assert_eq!(history.entries[0].revision, 1); + assert_eq!(history.entries[0].document.revision(), None); + assert_eq!(lifecycle(&history).remaining_revisions, 1); + let (_, verified) = verify(&query, &proof, document_type, version).unwrap(); + assert_eq!(verified, history); +} + +#[test] +fn should_bound_estimates_for_deep_plain_and_summable_histories() { + use crate::util::storage_flags::StorageFlags; + use dpp::data_contract::DataContractFactory; + use dpp::document::document_factory::DocumentFactory; + use dpp::platform_value::platform_value; + use std::borrow::Cow; + let version = PlatformVersion::get(15).unwrap(); + for summable in [false, true] { + let drive = setup_drive_with_initial_state_structure(Some(version)); + let mut schema = platform_value!({ + "type": "object", "documentsKeepHistory": true, "canBeDeleted": false, + "documentsCountable": true, + "properties": {"amount": {"type": "integer", "minimum": 0, "maximum": 4294967295i64, "position": 0}, "message": {"type": "string", "maxLength": 1024, "position": 1}}, + "required": ["amount", "message"], "additionalProperties": false + }); + if summable { + schema + .insert("documentsSummable".into(), "amount".into()) + .unwrap(); + } + let contract = DataContractFactory::new(15) + .unwrap() + .create_with_value_config( + [7; 32].into(), + 0, + platform_value!({"note": schema}), + None, + None, + ) + .unwrap() + .data_contract_owned(); + drive + .apply_contract(&contract, BlockInfo::default(), true, None, None, version) + .unwrap(); + let document_type = contract.document_type_for_name("note").unwrap(); + let mut document = DocumentFactory::new(15) + .unwrap() + .create_document( + &contract, + [7; 32].into(), + "note".into(), + platform_value!({"amount": 1, "message": "a".repeat(1024)}), + ) + .unwrap(); + for revision in 1..=257 { + document.set_revision(Some(revision)); + let info = DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentInfo::DocumentRefInfo(( + &document, + Some(Cow::Owned(StorageFlags::new_single_epoch( + (revision % 3) as u16, + Some([revision as u8; 32]), + ))), + )), + owner_id: None, + }, + contract: &contract, + document_type, + }; + let block = BlockInfo::default_with_time(revision * 1000); + let estimated = (revision == 257).then(|| { + drive + .add_document_for_contract(info.clone(), true, block, false, None, version) + .unwrap() + }); + let actual = drive + .add_document_for_contract(info, true, block, true, None, version) + .unwrap(); + if let Some(estimated) = estimated { + assert!( + estimated.storage_fee >= actual.storage_fee, + "storage estimate {estimated:?}, actual {actual:?}" + ); + assert!( + estimated.processing_fee >= actual.processing_fee, + "processing estimate {estimated:?}, actual {actual:?}" + ); + } + } + } +} + +#[test] +fn should_include_reference_hops_in_history_pointer_size_estimates() { + use crate::drive::constants::DOCUMENT_HISTORY_CURRENT_REFERENCE_PATH_SIZE; + use grovedb::reference_path::ReferencePathType::UpstreamRootHeightReference; + let version = PlatformVersion::get(15).unwrap(); + for flags in [ + None, + Some(vec![1; 35]), + Some(vec![1; 255]), + Some(vec![1; 65536]), + ] { + let reference = UpstreamRootHeightReference( + 4, + vec![vec![DOCUMENT_HISTORY_TREE_KEY], vec![1; 32], vec![1; 16]], + ); + let flags_len = flags.as_ref().map_or(0, |flags| flags.len() as u32); + for sum in [None, Some(0), Some(i64::MAX), Some(i64::MIN)] { + let (element, estimate) = if let Some(sum) = sum { + ( + Element::ReferenceWithSumItem(reference.clone(), Some(1), sum, flags.clone()), + Element::required_reference_with_sum_item_space( + DOCUMENT_HISTORY_CURRENT_REFERENCE_PATH_SIZE, + flags_len, + &version.drive.grove_version, + ) + .unwrap(), + ) + } else { + ( + Element::Reference(reference.clone(), Some(1), flags.clone()), + Element::required_item_space( + DOCUMENT_HISTORY_CURRENT_REFERENCE_PATH_SIZE, + flags_len, + &version.drive.grove_version, + ) + .unwrap(), + ) + }; + let serialized_size = element + .serialized_size(&version.drive.grove_version) + .unwrap(); + assert!( + estimate as usize >= serialized_size, + "pointer estimate {estimate} is smaller than its serialized size {serialized_size}" + ); + } + } +} + +#[test] +fn should_charge_count_tree_overhead_when_propagating_history_roots() { + use crate::drive::document::paths::contract_documents_primary_key_path; + use crate::util::estimated_layers::EstimatedLayers; + use crate::util::storage_flags::StorageFlags; + use grovedb::batch::KeyInfoPath; + use grovedb::{EstimatedLayerCount, EstimatedLayerSizes, EstimatedSumTrees}; + let version = PlatformVersion::get(15).unwrap(); + let contract = json_document_to_contract( + "tests/supporting_files/contract/dashpay/dashpay-contract-with-profile-history.json", + false, + version, + ) + .unwrap(); + let document_type = contract.document_type_for_name("profile").unwrap(); + let document = json_document_to_document( + "tests/supporting_files/contract/dashpay/profile0.json", + Some([8; 32].into()), + document_type, + version, + ) + .unwrap(); + let info = DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentInfo::DocumentRefInfo((&document, None)), + owner_id: None, + }, + contract: &contract, + document_type, + }; + let mut layers = EstimatedLayers::new(); + Drive::add_estimation_costs_for_add_document_to_primary_storage( + &info, + contract_documents_primary_key_path(contract.id().as_slice(), "profile"), + &mut layers, + version, + ) + .unwrap(); + let mut root = contract_document_type_path_vec(contract.id().as_slice(), "profile"); + root.push(vec![DOCUMENT_HISTORY_TREE_KEY]); + let mut layer = layers + .into_layers() + .remove(&KeyInfoPath::from_known_path( + root.iter().map(Vec::as_slice), + )) + .unwrap(); + layer.estimated_layer_count = EstimatedLayerCount::ApproximateElements(7); + let propagate = |layer: &grovedb::EstimatedLayerInformation| { + grovedb::GroveDb::average_case_merk_insert_tree( + &grovedb::batch::key_info::KeyInfo::KnownKey(vec![9; 32]), + &None, + grovedb::TreeType::ProvableCountTree, + grovedb::TreeType::NormalTree, + 0, + Some(layer), + &version.drive.grove_version, + ) + }; + let actual = propagate(&layer); + actual.value.unwrap(); + layer.estimated_layer_sizes = EstimatedLayerSizes::AllSubtrees( + 32, + EstimatedSumTrees::NoSumTrees, + Some(StorageFlags::approximate_size(true, None)), + ); + let plain = propagate(&layer); + plain.value.unwrap(); + assert_eq!(actual.cost.seek_count, plain.cost.seek_count); + assert_eq!( + actual.cost.storage_cost.replaced_bytes, + plain.cost.storage_cost.replaced_bytes + 4 * 8, + "each rewritten ancestor carries its child's authenticated count" + ); +} + +#[test] +fn should_reject_history_keys_that_are_not_sixteen_bytes() { + let version = PlatformVersion::get(15).unwrap(); + let contract = json_document_to_contract( + "tests/supporting_files/contract/dashpay/dashpay-contract-with-profile-history.json", + false, + version, + ) + .unwrap(); + let document_type = contract.document_type_for_name("profile").unwrap(); + let mut document = json_document_to_document( + "tests/supporting_files/contract/dashpay/profile0.json", + Some([8; 32].into()), + document_type, + version, + ) + .unwrap(); + document.set_revision(Some(1)); + let query = DocumentHistoryDriveQuery { + contract_id: contract.id().to_buffer(), + document_type_name: "profile".into(), + document_id: document.id().to_buffer(), + filter: DocumentHistoryFilter::StartAtTime(0), + limit: None, + }; + let bytes = document + .serialize(document_type, &contract, version) + .unwrap(); + let mut key = encode_u64(1000); + key.extend(encode_u64(1)); + assert_eq!( + query + .decode_entries( + vec![(key.clone(), Element::new_item(bytes.clone()))], + document_type, + version + ) + .unwrap()[0] + .revision, + 1 + ); + let mut overlong = key.clone(); + overlong.push(0); + for invalid in [key[..8].to_vec(), key[..15].to_vec(), overlong] { + let error = query + .decode_entries( + vec![(invalid, Element::new_item(bytes.clone()))], + document_type, + version, + ) + .unwrap_err(); + assert!( + error.to_string().contains("exactly sixteen bytes"), + "{error}" + ); + } +} + +#[test] +fn should_reject_history_proofs_that_omit_a_queried_branch() { + let version = PlatformVersion::latest(); + let drive = setup_drive_with_initial_state_structure(None); + let contract = json_document_to_contract( + "tests/supporting_files/contract/dashpay/dashpay-contract-with-profile-history.json", + false, + version, + ) + .unwrap(); + drive + .apply_contract(&contract, BlockInfo::default(), true, None, None, version) + .unwrap(); + let document_type = contract.document_type_for_name("profile").unwrap(); + let mut document = json_document_to_document( + "tests/supporting_files/contract/dashpay/profile0.json", + Some([8; 32].into()), + document_type, + version, + ) + .unwrap(); + document.set_revision(Some(1)); + drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentInfo::DocumentRefInfo((&document, None)), + owner_id: None, + }, + contract: &contract, + document_type, + }, + true, + BlockInfo::default_with_time(2000), + true, + None, + version, + ) + .unwrap(); + let query = DocumentHistoryDriveQuery { + contract_id: contract.id().to_buffer(), + document_type_name: "profile".into(), + document_id: document.id().to_buffer(), + filter: DocumentHistoryFilter::StartAtTime(0), + limit: Some(10), + }; + let (page, honest) = prove(&drive, &query, document_type, version); + assert_eq!(lifecycle(&page).state, DocumentHistoryState::Active); + let (_, verified) = verify(&query, &honest, document_type, version).unwrap(); + assert_eq!(verified, page); + + // A node that answers only for the lifecycle record and the history tree, + // leaving the current pointer out of the proof entirely, must not be able + // to pass the document off as absent with an empty page. + for omitted in [0u8, DOCUMENT_HISTORY_TREE_KEY] { + let branches = [0u8, 1, DOCUMENT_HISTORY_TREE_KEY] + .into_iter() + .filter(|branch| *branch != omitted) + .map(|branch| { + let mut path = + contract_document_type_path_vec(&query.contract_id, &query.document_type_name); + path.push(vec![branch]); + let mut key_query = Query::new(); + key_query.insert_key(query.document_id.to_vec()); + PathQuery::new(path, SizedQuery::new(key_query, None, None)) + }) + .collect::>(); + let mut narrowed = + PathQuery::merge(branches.iter().collect(), &version.drive.grove_version).unwrap(); + narrowed.query.limit = Some(2); + let forged = drive + .grove_get_proved_path_query(&narrowed, None, &mut vec![], &version.drive) + .unwrap(); + assert!( + verify(&query, &forged, document_type, version).is_err(), + "a metadata proof that omits branch {omitted} verified as an authenticated absence" + ); + } +} + +#[test] +fn should_keep_the_exact_history_query_and_its_parent_echo_at_the_history_host() { + use grovedb::QueryItem; + let contract_id = [1; 32]; + let document_id = [2; 32]; + let time = vec![128, 0, 0, 0, 0, 0, 7, 208]; + let cursor = vec![128, 0, 0, 0, 0, 0, 7, 208, 128, 0, 0, 0, 0, 0, 0, 1]; + for (filter, item, offset) in [ + ( + DocumentHistoryFilter::StartAtTime(2000), + QueryItem::RangeFrom(time..), + None, + ), + ( + DocumentHistoryFilter::StartAfter { + time_ms: 2000, + revision: 1, + }, + QueryItem::RangeAfter(cursor..), + None, + ), + ( + DocumentHistoryFilter::StartAtRevision(2), + QueryItem::RangeFull(std::ops::RangeFull), + Some(1), + ), + ( + DocumentHistoryFilter::Revision(1), + QueryItem::RangeFull(std::ops::RangeFull), + Some(0), + ), + ( + DocumentHistoryFilter::Revision(65536), + QueryItem::RangeFull(std::ops::RangeFull), + Some(65535), + ), + ] { + let query = DocumentHistoryDriveQuery { + contract_id, + document_type_name: "note".into(), + document_id, + filter, + limit: Some(1), + }; + let mut expected = Query::new(); + for branch in [0, 1] { + expected.insert_key(vec![branch]); + expected.add_conditional_subquery( + QueryItem::Key(vec![branch]), + None, + Some(Query::new_single_key(document_id.to_vec())), + ); + } + let mut page = Query::new_single_query_item(item); + page.limit = Some(1); + page.offset = offset; + let mut history = Query::new_single_key(document_id.to_vec()); + history.add_parent_tree_on_subquery = true; + history.set_subquery(page); + expected.insert_key(vec![2]); + expected.add_conditional_subquery(QueryItem::Key(vec![2]), None, Some(history)); + let expected = PathQuery::new_unsized( + vec![vec![64], contract_id.to_vec(), vec![1], b"note".to_vec()], + expected, + ); + assert_eq!( + query + .construct_path_query(PlatformVersion::latest()) + .unwrap(), + expected, + "{:?}", + query.filter + ); + } +} diff --git a/packages/rs-drive/src/verify/document/verify_document_history/v0/mod.rs b/packages/rs-drive/src/verify/document/verify_document_history/v0/mod.rs index c63f37ba2b2..378992c68be 100644 --- a/packages/rs-drive/src/verify/document/verify_document_history/v0/mod.rs +++ b/packages/rs-drive/src/verify/document/verify_document_history/v0/mod.rs @@ -20,7 +20,7 @@ impl Drive { document_type_name: &str, document_type: DocumentTypeRef, document_id: [u8; 32], - start_at_ms: u64, + start_after_ms: u64, limit: Option, offset: Option, platform_version: &PlatformVersion, @@ -29,7 +29,7 @@ impl Drive { contract_id, document_type, document_id, - start_at_ms, + start_after_ms, limit, offset, platform_version, diff --git a/packages/rs-drive/src/verify/document/verify_document_history/v1/mod.rs b/packages/rs-drive/src/verify/document/verify_document_history/v1/mod.rs new file mode 100644 index 00000000000..d0c88d586ab --- /dev/null +++ b/packages/rs-drive/src/verify/document/verify_document_history/v1/mod.rs @@ -0,0 +1,45 @@ +use crate::drive::Drive; +use crate::error::Error; +use crate::query::document_history_drive_query::{ + invalid, DocumentHistoryDriveQuery, DocumentHistoryDriveQueryExecutionResult, +}; +use crate::query::refuse_a_private_document_type; +use crate::verify::grovedb_proof_envelope::{ + require_supported_grovedb_proof_envelope, MINIMUM_GROVEDB_PROOF_ENVELOPE_VERSION, +}; +use crate::verify::RootHash; +use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters; +use dpp::data_contract::document_type::DocumentTypeRef; +use dpp::version::PlatformVersion; + +// Count-tree offset pagination requires GroveDB proof envelopes from version 1. +const _: () = assert!(MINIMUM_GROVEDB_PROOF_ENVELOPE_VERSION >= 1); + +impl Drive { + /// Verifies the history page, lifecycle, and revision positions. + pub(super) fn verify_document_history_v1( + query: &DocumentHistoryDriveQuery, + proof: &[u8], + document_type: DocumentTypeRef, + version: &PlatformVersion, + ) -> Result<(RootHash, DocumentHistoryDriveQueryExecutionResult), Error> { + refuse_a_private_document_type(document_type).map_err(Error::Query)?; + require_supported_grovedb_proof_envelope(proof, "document history proof")?; + if !document_type.documents_keep_history() { + return Err(invalid("document type does not keep history")); + } + let (root, rows) = grovedb::GroveDb::verify_query_with_options( + proof, + &query.construct_path_query(version)?, + grovedb::VerifyOptions { + // All exact selections and their ancestors are unlimited, so + // omitted siblings prove absence without explicit absence rows. + absence_proofs_for_non_existing_searched_keys: false, + verify_proof_succinctness: true, + include_empty_trees_in_result: true, + }, + &version.drive.grove_version, + )?; + Ok((root, query.decode_result(rows, document_type, version)?)) + } +} diff --git a/packages/rs-drive/src/verify/document/verify_start_at_document_in_proof/mod.rs b/packages/rs-drive/src/verify/document/verify_start_at_document_in_proof/mod.rs index 840e804ec04..42fbea4e7d9 100644 --- a/packages/rs-drive/src/verify/document/verify_start_at_document_in_proof/mod.rs +++ b/packages/rs-drive/src/verify/document/verify_start_at_document_in_proof/mod.rs @@ -1,4 +1,5 @@ mod v0; +mod v1; use crate::error::drive::DriveError; use crate::verify::RootHash; @@ -51,9 +52,15 @@ impl DriveDocumentQuery<'_> { document_id, platform_version, ), + 1 => self.verify_start_at_document_in_proof_v1( + proof, + is_proof_subset, + document_id, + platform_version, + ), version => Err(Error::Drive(DriveError::UnknownVersionMismatch { method: "verify_start_at_document_in_proof".to_string(), - known_versions: vec![0], + known_versions: vec![0, 1], received: version, })), } @@ -104,7 +111,7 @@ mod tests { assert!( matches!(result, Err(Error::Drive(DriveError::UnknownVersionMismatch { method, known_versions, received })) - if method == "verify_start_at_document_in_proof" && known_versions == vec![0] && received == 255 + if method == "verify_start_at_document_in_proof" && known_versions == vec![0, 1] && received == 255 ) ); } diff --git a/packages/rs-drive/src/verify/document/verify_start_at_document_in_proof/v0/mod.rs b/packages/rs-drive/src/verify/document/verify_start_at_document_in_proof/v0/mod.rs index 149483b5cad..bf7a829700b 100644 --- a/packages/rs-drive/src/verify/document/verify_start_at_document_in_proof/v0/mod.rs +++ b/packages/rs-drive/src/verify/document/verify_start_at_document_in_proof/v0/mod.rs @@ -121,7 +121,8 @@ mod tests { #[test] fn should_prove_and_verify_start_at_document_in_proof() { let drive = setup_drive_with_initial_state_structure(None); - let platform_version = PlatformVersion::latest(); + // Protocol 14 is the last version whose verify table selects v0. + let platform_version = PlatformVersion::get(14).expect("protocol 14"); let contract = load_system_data_contract(SystemDataContract::DPNS, platform_version) .expect("expected to load DPNS contract"); diff --git a/packages/rs-drive/src/verify/document/verify_start_at_document_in_proof/v1/mod.rs b/packages/rs-drive/src/verify/document/verify_start_at_document_in_proof/v1/mod.rs new file mode 100644 index 00000000000..bd3c6d95755 --- /dev/null +++ b/packages/rs-drive/src/verify/document/verify_start_at_document_in_proof/v1/mod.rs @@ -0,0 +1,199 @@ +// Protocol 15 generation: the cursor document is looked up in the primary +// key tree, where a keep-history document's entry points at its current +// revision; everything else matches v0. +use crate::verify::RootHash; + +use crate::error::proof::ProofError; +use crate::error::Error; +use crate::query::DriveDocumentQuery; +use dpp::document::serialization_traits::DocumentPlatformConversionMethodsV0; +use dpp::document::Document; +use dpp::version::PlatformVersion; +use grovedb::{GroveDb, PathQuery}; + +impl DriveDocumentQuery<'_> { + /// Verifies if a document exists at the beginning of a proof, + /// and returns the root hash and the optionally found document. + /// + /// # Arguments + /// + /// * `proof` - A byte slice containing the proof data. + /// * `is_proof_subset` - A boolean indicating whether the proof is a subset query or not. + /// * `document_id` - A byte_32 array, representing the ID of the document to start at. + /// + /// # Returns + /// + /// A `Result` with a tuple containing: + /// * The root hash of the verified proof. + /// * An `Option` containing the found document if available. + /// + /// # Errors + /// + /// This function returns an Error in the following cases: + /// * If the proof is corrupted (wrong path, wrong key, etc.). + /// * If the provided proof has an incorrect number of elements. + #[inline(always)] + pub(super) fn verify_start_at_document_in_proof_v1( + &self, + proof: &[u8], + is_proof_subset: bool, + document_id: [u8; 32], + platform_version: &PlatformVersion, + ) -> Result<(RootHash, Option), Error> { + // Reject unsupported where-clause shapes before doing any proof work, + // mirroring the server-side preflight that runs before the cursor + // document is fetched. + self.validate_where_clause_shape(platform_version)?; + let (start_at_document_path, start_at_document_key) = + self.start_at_document_path_and_key_v1(&document_id); + let mut path_query = PathQuery::new_single_key( + start_at_document_path.clone(), + start_at_document_key.clone(), + ); + if is_proof_subset { + // Inside a page proof this one-key lookup is merged with the main + // query, and grovedb's merge needs every input to walk the same + // way, so the prover emits the cursor layer in the page's + // `orderBy` direction (see `construct_path_query_operations`). + // A V1 layer proof only verifies in the op family of the + // direction it is read in, so read it the same way here. A single + // key decodes identically either way; this only selects the op + // family, and the direction never depends on the cursor document. + path_query.query.query.left_to_right = self + .construct_path_query(None, platform_version)? + .query + .query + .left_to_right; + } + let (root_hash, mut proved_key_values) = if is_proof_subset { + GroveDb::verify_subset_query(proof, &path_query, &platform_version.drive.grove_version)? + } else { + GroveDb::verify_query(proof, &path_query, &platform_version.drive.grove_version)? + }; + match proved_key_values.len() { + 1 => { + let (path, key, maybe_element) = proved_key_values.remove(0); + if path != start_at_document_path { + return Err(Error::Proof(ProofError::CorruptedProof( + "we did not get back a document for the correct path".to_string(), + ))); + } + if key != start_at_document_key { + return Err(Error::Proof(ProofError::CorruptedProof( + "we did not get back a document for the correct key".to_string(), + ))); + } + let document = maybe_element + .map(|element| { + let document_bytes = element.into_item_bytes().map_err(Error::from)?; + Document::from_bytes( + document_bytes.as_slice(), + self.document_type, + platform_version, + ) + .map_err(Error::from) + }) + .transpose()?; + Ok((root_hash, document)) + } + 0 => Err(Error::Proof(ProofError::WrongElementCount { + expected: 1, + got: 0, + })), + _ => Err(Error::Proof(ProofError::TooManyElements( + "expected one document for start at", + ))), + } + } +} + +#[cfg(test)] +mod tests { + use crate::query::DriveDocumentQuery; + use crate::util::object_size_info::DocumentInfo::DocumentRefInfo; + use crate::util::object_size_info::{DocumentAndContractInfo, OwnedDocumentInfo}; + use crate::util::test_helpers::setup::setup_drive_with_initial_state_structure; + use dpp::block::block_info::BlockInfo; + use dpp::data_contract::accessors::v0::DataContractV0Getters; + use dpp::data_contract::document_type::random_document::CreateRandomDocument; + use dpp::data_contracts::SystemDataContract; + use dpp::document::DocumentV0Getters; + use dpp::system_data_contracts::load_system_data_contract; + use dpp::version::PlatformVersion; + + #[test] + fn should_prove_and_verify_start_at_document_in_proof() { + let drive = setup_drive_with_initial_state_structure(None); + let platform_version = PlatformVersion::latest(); + + let contract = load_system_data_contract(SystemDataContract::DPNS, platform_version) + .expect("expected to load DPNS contract"); + + drive + .apply_contract( + &contract, + BlockInfo::default(), + true, + None, + None, + platform_version, + ) + .expect("expected to apply contract"); + + let document_type = contract + .document_type_for_name("preorder") + .expect("expected preorder document type"); + + // Insert a document + let document = document_type + .random_document(Some(42), platform_version) + .expect("expected a random document"); + + let doc_id = document.id(); + + drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentRefInfo((&document, None)), + owner_id: None, + }, + contract: &contract, + document_type, + }, + false, + BlockInfo::default(), + true, + None, + platform_version, + ) + .expect("expected to insert document"); + + // Build a query - we use any_item_query to get all, then use the proof + // to verify a specific document via verify_start_at_document_in_proof + let query = DriveDocumentQuery::any_item_query(&contract, document_type); + + // Get proof that covers all documents + let (proof, _cost) = query + .clone() + .execute_with_proof(&drive, None, None, platform_version) + .expect("expected to execute query with proof"); + + // Verify that the specific document is found in the proof + let (_root_hash, found_document) = query + .verify_start_at_document_in_proof( + proof.as_slice(), + true, // is_proof_subset = true because the proof covers all documents + doc_id.to_buffer(), + platform_version, + ) + .expect("expected proof verification to succeed"); + + assert!( + found_document.is_some(), + "expected document to be found in proof" + ); + let found_doc = found_document.unwrap(); + assert_eq!(found_doc.id(), doc_id); + } +} diff --git a/packages/rs-drive/src/verify/shielded/verify_shielded_encrypted_notes/v0/mod.rs b/packages/rs-drive/src/verify/shielded/verify_shielded_encrypted_notes/v0/mod.rs index 033dcb99047..50f8700af68 100644 --- a/packages/rs-drive/src/verify/shielded/verify_shielded_encrypted_notes/v0/mod.rs +++ b/packages/rs-drive/src/verify/shielded/verify_shielded_encrypted_notes/v0/mod.rs @@ -109,6 +109,7 @@ impl Drive { path: pool_path.clone(), query: SizedQuery { query: Query { + offset: None, read_mode: None, limit: None, items: vec![QueryItem::Key(vec![SHIELDED_NOTES_KEY])], @@ -298,6 +299,7 @@ mod tests { path: shielded_credit_pool_path_vec(), query: SizedQuery { query: Query { + offset: None, read_mode: None, limit: None, items: vec![QueryItem::Key(vec![SHIELDED_NOTES_KEY])], diff --git a/packages/rs-drive/src/verify/state_transition/verify_state_transition_was_executed_with_proof/mod.rs b/packages/rs-drive/src/verify/state_transition/verify_state_transition_was_executed_with_proof/mod.rs index c0101d72c3a..4bd0f6a5d5d 100644 --- a/packages/rs-drive/src/verify/state_transition/verify_state_transition_was_executed_with_proof/mod.rs +++ b/packages/rs-drive/src/verify/state_transition/verify_state_transition_was_executed_with_proof/mod.rs @@ -79,10 +79,10 @@ impl Drive { /// /// The caller's `platform_version` selects the generation of this method and every /// rule inside it, so a producer's version cannot lower them. `query_platform_version` - /// selects only the layout the producer proved: whether the proof of an owned, - /// fee-paying transition carries the owner's credit balance, which the producer's - /// `prove_state_transition` generation decides. The caller must authenticate the - /// producer version together with the resulting root. + /// selects only the layout the producer proved. Its `prove_state_transition` generation + /// decides whether an owned, fee-paying transition carries the owner's credit balance; + /// `document_history_storage_layout` selects the document history layout. The caller + /// must authenticate the producer version together with the resulting root. /// /// # Parameters /// @@ -97,8 +97,8 @@ impl Drive { /// The root hash of the proof and the verified outcome, as for /// [`Self::verify_state_transition_was_executed_with_proof`]. A generation this build /// does not know, of this method in the caller's version or of - /// `prove_state_transition` in the producer's, is reported as - /// [`DriveError::UnknownVersionMismatch`] naming that method. + /// `prove_state_transition` or `document_history_storage_layout` in the producer's, + /// is reported as [`DriveError::UnknownVersionMismatch`] naming that method. pub fn verify_state_transition_was_executed_with_proof_for_query_version( state_transition: &StateTransition, block_info: &BlockInfo, @@ -114,8 +114,8 @@ impl Drive { .state_transition .verify_state_transition_was_executed_with_proof { - // Generations 0 and 1 run the same checks. The layout comes from the - // producer's `prove_state_transition` generation, so either one verifies a + // Generations 0 and 1 run the same checks. The owner-balance layout comes from + // the producer's `prove_state_transition` generation, so either one verifies a // proof from any producer whose prover generation this build knows; an // unknown prover generation is refused. Protocol versions 1 to 13 select // verifier and prover generation 0, and protocol versions from 14 select 1 @@ -127,6 +127,7 @@ impl Drive { proof, known_contracts_provider_fn, Self::proof_carries_owner_balance(query_platform_version)?, + Self::proof_document_history_layout(query_platform_version)?, platform_version, ), version => Err(Error::Drive(DriveError::UnknownVersionMismatch { @@ -137,6 +138,25 @@ impl Drive { } } + /// The producer's document history storage layout, restricted to supported layouts. + fn proof_document_history_layout( + query_platform_version: &PlatformVersion, + ) -> Result { + match query_platform_version + .drive + .methods + .document + .document_history_storage_layout + { + layout @ (0 | 1) => Ok(layout), + received => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "document_history_storage_layout".to_string(), + known_versions: vec![0, 1], + received, + })), + } + } + /// Whether a producer at `query_platform_version` proves an owned, fee-paying /// transition together with its owner's credit balance: generation 1 of /// `prove_state_transition` does, generation 0 does not. @@ -163,9 +183,84 @@ impl Drive { #[cfg(test)] mod tests { use super::*; + use crate::query::{SingleDocumentDriveQuery, SingleDocumentDriveQueryContestedStatus}; use dpp::state_transition::state_transitions::identity::identity_credit_transfer_transition::IdentityCreditTransferTransition; use dpp::state_transition::state_transitions::identity::identity_credit_transfer_transition::v0::IdentityCreditTransferTransitionV0; use dpp::version::PlatformVersion; + use grovedb::PathQuery; + + #[test] + fn should_reject_an_unknown_authenticated_document_history_layout() { + let mut producer = PlatformVersion::latest().clone(); + producer + .drive + .methods + .document + .document_history_storage_layout = 2; + assert!(matches!(Drive::proof_document_history_layout(&producer), + Err(Error::Drive(DriveError::UnknownVersionMismatch { method, received: 2, .. })) + if method == "document_history_storage_layout")); + } + + #[test] + fn should_preserve_execution_queries_for_every_released_caller_and_producer() { + for caller in 1..=15 { + let caller_version = PlatformVersion::get(caller).expect("released caller"); + for producer in 1..=15 { + let producer_version = PlatformVersion::get(producer).expect("released producer"); + for keeps_history in [false, true] { + for contested_status in [ + SingleDocumentDriveQueryContestedStatus::NotContested, + SingleDocumentDriveQueryContestedStatus::Contested, + ] { + let query = SingleDocumentDriveQuery { + contract_id: [1; 32], + document_type_name: "note".to_string(), + document_type_keeps_history: keeps_history, + document_id: [2; 32], + block_time_ms: None, + contested_status, + }; + let mut query_version = caller_version.clone(); + query_version + .drive + .methods + .document + .document_history_storage_layout = + Drive::proof_document_history_layout(producer_version).unwrap(); + let mut old_query = query.construct_path_query(&query_version).unwrap(); + let mut producer_query = + query.construct_path_query(producer_version).unwrap(); + assert_eq!( + old_query, producer_query, + "caller {caller}, producer {producer}" + ); + + if producer_version.drive.methods.prove.prove_state_transition == 1 { + old_query.query.limit = None; + producer_query.query.limit = None; + let balance_query = Drive::identity_balance_query(&[3; 32]); + let old_merged = PathQuery::merge( + vec![&old_query, &balance_query], + &caller_version.drive.grove_version, + ) + .unwrap(); + let producer_merged = PathQuery::merge( + vec![&producer_query, &balance_query], + &producer_version.drive.grove_version, + ) + .unwrap(); + assert_eq!( + old_merged, producer_merged, + "caller {caller}, producer {producer}" + ); + } + } + } + } + } + } + #[test] fn test_verify_state_transition_was_executed_with_proof_unknown_version_mismatch() { let mut platform_version = PlatformVersion::latest().clone(); diff --git a/packages/rs-drive/src/verify/state_transition/verify_state_transition_was_executed_with_proof/v0/mod.rs b/packages/rs-drive/src/verify/state_transition/verify_state_transition_was_executed_with_proof/v0/mod.rs index 779af2b8713..90e383617f5 100644 --- a/packages/rs-drive/src/verify/state_transition/verify_state_transition_was_executed_with_proof/v0/mod.rs +++ b/packages/rs-drive/src/verify/state_transition/verify_state_transition_was_executed_with_proof/v0/mod.rs @@ -102,6 +102,7 @@ impl Drive { proof: &[u8], known_contracts_provider_fn: &ContractLookupFn, carries_owner_balance: bool, + proof_document_history_layout: u16, platform_version: &PlatformVersion, ) -> Result<(RootHash, StateTransitionProofOutcome), Error> { // The balance a document batch's proof carried, set by its arm. @@ -424,12 +425,18 @@ impl Drive { block_time_ms: None, //None because we want latest contested_status, }; + let mut verification_version = platform_version.clone(); + verification_version + .drive + .methods + .document + .document_history_storage_layout = proof_document_history_layout; let (root_hash, document, owner_balance) = if carries_owner_balance { // One strict verification of the prover's merged query: // the document (present or proven absent) and the // owner's balance, and nothing else. let mut document_path_query = - query.construct_path_query(platform_version)?; + query.construct_path_query(&verification_version)?; document_path_query.query.limit = None; let owner_balance_query = Drive::identity_balance_query(&owner_id.to_buffer()); @@ -471,11 +478,13 @@ impl Drive { .transpose()?; (root_hash, document, Some(owner_balance)) } else { + // Only the stored path follows the signed producer version. + // Verification dispatch and decoding keep the caller's tables. let (root_hash, document) = query.verify_proof( false, proof, document_type, - platform_version, + &verification_version, )?; (root_hash, document, None) }; @@ -1466,6 +1475,7 @@ impl Drive { transition, known_contracts_provider_fn, carries_owner_balance, + proof_document_history_layout, platform_version, ) } @@ -1500,6 +1510,7 @@ impl Drive { transition, known_contracts_provider_fn, carries_owner_balance, + proof_document_history_layout, platform_version, ) } @@ -3352,6 +3363,7 @@ fn verify_contract_document_deletion_execution( transition: &ContractUserModerationTransition, known_contracts_provider_fn: &ContractLookupFn, verify_subset_of_proof: bool, + proof_document_history_layout: u16, platform_version: &PlatformVersion, ) -> Result<(RootHash, StateTransitionProofResult), Error> { let contract_id = transition.data_contract_id(); @@ -3381,11 +3393,19 @@ fn verify_contract_document_deletion_execution( document_type.documents_keep_history(), document_id.into_buffer(), ); + // Only the stored path follows the signed producer version. + // Verification dispatch and decoding keep the caller's tables. + let mut verification_version = platform_version.clone(); + verification_version + .drive + .methods + .document + .document_history_storage_layout = proof_document_history_layout; let (root_hash, document) = query.verify_proof( verify_subset_of_proof, proof, document_type, - platform_version, + &verification_version, )?; if document.is_some() { return Err(Error::Proof(ProofError::IncorrectProof(format!( @@ -3599,6 +3619,7 @@ fn verify_contract_document_change_execution( transition: &ContractUserModerationTransition, known_contracts_provider_fn: &ContractLookupFn, verify_subset_of_proof: bool, + proof_document_history_layout: u16, platform_version: &PlatformVersion, ) -> Result<(RootHash, StateTransitionProofResult), Error> { let contract_id = transition.data_contract_id(); @@ -3621,11 +3642,19 @@ fn verify_contract_document_change_execution( document_type.documents_keep_history(), document_id.into_buffer(), ); + // Only the stored path follows the signed producer version. + // Verification dispatch and decoding keep the caller's tables. + let mut verification_version = platform_version.clone(); + verification_version + .drive + .methods + .document + .document_history_storage_layout = proof_document_history_layout; let (root_hash, document) = query.verify_proof( verify_subset_of_proof, proof, document_type, - platform_version, + &verification_version, )?; // The document as changed holds every value set and none removed. Its moderation stamp is // not compared: a later moderator's write to another field of the document moves it, diff --git a/packages/rs-drive/tests/query_tests_history.rs b/packages/rs-drive/tests/query_tests_history.rs index 2e89d4eded5..93a000ae927 100644 --- a/packages/rs-drive/tests/query_tests_history.rs +++ b/packages/rs-drive/tests/query_tests_history.rs @@ -253,91 +253,92 @@ fn test_setup() { #[test] fn test_proved_primary_key_cursor_pages_over_history_in_both_directions() { // The history-keeping twin of the primary-key cursor test in - // query_tests.rs. Here the cursor lookup lands one level below the page - // query (`.../0/` with key `[0]`), so the merge point is the page - // query's own root layer: the document-id layer must keep the requested - // direction in the proof and the cursor must not claim a second slot. + // query_tests.rs. The cursor lookup follows the selected primary-key path + // generation, and in both layouts the proof must preserve page direction + // without letting the cursor claim a second result slot. use dpp::document::DocumentV0Getters; use dpp::platform_value::string_encoding::Encoding; use dpp::prelude::Identifier; use drive::query::DriveDocumentQuery; - let platform_version = PlatformVersion::latest(); - let (drive, contract) = setup(10, None, 73509, platform_version); - let person_document_type = contract - .document_type_for_name("person") - .expect("contract should have a person document type"); - let root_hash = drive - .grove - .root_hash(None, &platform_version.drive.grove_version) - .unwrap() - .expect("there is always a root hash"); - - let ids_of = |results: &[Vec]| -> Vec { - results - .iter() - .map(|bytes| { - Document::from_bytes(bytes, person_document_type, platform_version) - .expect("we should be able to deserialize the document") - .id() - }) - .collect() - }; - let build = |query_value: serde_json::Value| { - let cbor = cbor_serializer::serializable_value_to_cbor(&query_value, None) - .expect("expected to serialize to cbor"); - DriveDocumentQuery::from_cbor( - cbor.as_slice(), - &contract, - person_document_type, - &drive.config, - platform_version, - ) - .expect("query should be built") - }; - - let (all_results, _, _) = build(json!({ - "limit": 100, - "orderBy": [["$id", "asc"]], - })) - .execute_raw_results_no_proof(&drive, None, None, platform_version) - .expect("query should be executed"); - let ascending_ids = ids_of(&all_results); - assert_eq!(ascending_ids.len(), 10); - - for (ascending, included) in [(true, true), (true, false), (false, true), (false, false)] { - let ordered: Vec = if ascending { - ascending_ids.clone() - } else { - ascending_ids.iter().rev().cloned().collect() + for protocol in [14, 15] { + let platform_version = PlatformVersion::get(protocol).expect("known protocol version"); + let (drive, contract) = setup(10, None, 73509, platform_version); + let person_document_type = contract + .document_type_for_name("person") + .expect("contract should have a person document type"); + let root_hash = drive + .grove + .root_hash(None, &platform_version.drive.grove_version) + .unwrap() + .expect("there is always a root hash"); + + let ids_of = |results: &[Vec]| -> Vec { + results + .iter() + .map(|bytes| { + Document::from_bytes(bytes, person_document_type, platform_version) + .expect("we should be able to deserialize the document") + .id() + }) + .collect() }; - let cursor = ordered[3]; - let expected: Vec = if included { - ordered[3..6].to_vec() - } else { - ordered[4..7].to_vec() + let build = |query_value: serde_json::Value| { + let cbor = cbor_serializer::serializable_value_to_cbor(&query_value, None) + .expect("expected to serialize to cbor"); + DriveDocumentQuery::from_cbor( + cbor.as_slice(), + &contract, + person_document_type, + &drive.config, + platform_version, + ) + .expect("query should be built") }; - let cursor_key = if included { "startAt" } else { "startAfter" }; - let case = format!( - "history orderBy $id {} with {cursor_key}", - if ascending { "asc" } else { "desc" } - ); - let query = build(json!({ - cursor_key: cursor.to_string(Encoding::Base58), - "limit": 3, - "orderBy": [["$id", if ascending { "asc" } else { "desc" }]], - })); - let (results, _, _) = query - .execute_raw_results_no_proof(&drive, None, None, platform_version) - .expect("query should be executed"); - assert_eq!(ids_of(&results), expected, "{case}: unproved page"); - - let (proof_root_hash, proof_results, _) = query - .execute_with_proof_only_get_elements(&drive, None, None, platform_version) - .unwrap_or_else(|e| panic!("{case}: proved page should verify: {e}")); - assert_eq!(root_hash, proof_root_hash, "{case}: proof root hash"); - assert_eq!(results, proof_results, "{case}: proved page"); + let (all_results, _, _) = build(json!({ + "limit": 100, + "orderBy": [["$id", "asc"]], + })) + .execute_raw_results_no_proof(&drive, None, None, platform_version) + .expect("query should be executed"); + let ascending_ids = ids_of(&all_results); + assert_eq!(ascending_ids.len(), 10); + + for (ascending, included) in [(true, true), (true, false), (false, true), (false, false)] { + let ordered: Vec = if ascending { + ascending_ids.clone() + } else { + ascending_ids.iter().rev().cloned().collect() + }; + let cursor = ordered[3]; + let expected: Vec = if included { + ordered[3..6].to_vec() + } else { + ordered[4..7].to_vec() + }; + let cursor_key = if included { "startAt" } else { "startAfter" }; + let case = format!( + "protocol {protocol} history orderBy $id {} with {cursor_key}", + if ascending { "asc" } else { "desc" } + ); + + let query = build(json!({ + cursor_key: cursor.to_string(Encoding::Base58), + "limit": 3, + "orderBy": [["$id", if ascending { "asc" } else { "desc" }]], + })); + let (results, _, _) = query + .execute_raw_results_no_proof(&drive, None, None, platform_version) + .expect("query should be executed"); + assert_eq!(ids_of(&results), expected, "{case}: unproved page"); + + let (proof_root_hash, proof_results, _) = query + .execute_with_proof_only_get_elements(&drive, None, None, platform_version) + .unwrap_or_else(|e| panic!("{case}: proved page should verify: {e}")); + assert_eq!(root_hash, proof_root_hash, "{case}: proof root hash"); + assert_eq!(results, proof_results, "{case}: proved page"); + } } } @@ -1739,8 +1740,8 @@ fn test_query_historical_first_platform_version() { #[cfg(feature = "server")] #[test] -fn test_query_historical_latest_platform_version() { - let platform_version = PlatformVersion::latest(); +fn test_query_historical_protocol_14() { + let platform_version = PlatformVersion::get(14).unwrap(); let (drive, contract) = setup(10, None, 73509, platform_version); let db_transaction = drive.grove.start_transaction(); @@ -1751,13 +1752,12 @@ fn test_query_historical_latest_platform_version() { .unwrap() .expect("there is always a root hash"); // protocol version 14 stores the contract's version item beside the contract, one more - // element under the contract's root subtree in the app hash; from protocol version 15 - // the contract is stored compiled (format version 2) + // element under the contract's root subtree in the app hash assert_eq!( root_hash.as_slice(), vec![ - 164, 19, 82, 38, 204, 246, 241, 238, 130, 180, 160, 236, 73, 210, 55, 148, 3, 7, 136, - 162, 235, 69, 187, 186, 111, 173, 44, 45, 105, 42, 120, 31 + 154, 194, 44, 125, 179, 94, 9, 234, 111, 237, 91, 245, 165, 141, 253, 76, 143, 141, + 245, 7, 243, 30, 75, 19, 125, 230, 89, 223, 137, 197, 4, 7 ] ); @@ -3128,13 +3128,152 @@ fn test_query_historical_latest_platform_version() { .unwrap() .expect("there is always a root hash"); // protocol version 14 stores the contract's version item beside the contract, one more - // element under the contract's root subtree in the app hash; from protocol version 15 - // the contract is stored compiled (format version 2) + // element under the contract's root subtree in the app hash assert_eq!( root_hash.as_slice(), vec![ - 100, 160, 69, 189, 204, 135, 147, 36, 228, 242, 49, 99, 116, 167, 17, 44, 71, 49, 67, - 240, 202, 157, 241, 94, 39, 6, 81, 105, 213, 170, 107, 164 + 144, 239, 7, 209, 248, 216, 179, 175, 158, 85, 227, 204, 70, 8, 219, 70, 175, 116, 83, + 174, 23, 60, 153, 207, 128, 99, 192, 173, 93, 231, 31, 147 ] ); } + +#[cfg(feature = "server")] +#[test] +fn test_query_historical_protocol_15_uses_composite_history() { + use drive::drive::RootTree; + use drive::grovedb::Element; + use drive::query::document_history_drive_query::{ + DocumentHistoryDriveQuery, DocumentHistoryFilter, + }; + + let version = PlatformVersion::get(15).unwrap(); + // Compiled contract storage changes the fixture root independently of the history layout. + let mut carried_storage_version = version.clone(); + carried_storage_version + .dpp + .contract_versions + .contract_storage_serialization_version = 1; + let (carried_drive, _) = setup(10, None, 73509, &carried_storage_version); + assert_eq!( + carried_drive + .grove + .root_hash(None, &version.drive.grove_version) + .unwrap() + .unwrap(), + [ + 79, 26, 80, 105, 213, 254, 12, 9, 90, 129, 14, 60, 16, 58, 213, 28, 46, 162, 207, 99, + 226, 207, 30, 164, 65, 222, 123, 33, 180, 85, 47, 229, + ] + ); + let (drive, contract) = setup(10, None, 73509, version); + let document_type = contract.document_type_for_name("person").unwrap(); + let root = drive + .grove + .root_hash(None, &version.drive.grove_version) + .value + .unwrap(); + assert_eq!( + root, + [ + 66, 6, 172, 169, 64, 192, 127, 120, 130, 36, 173, 212, 240, 10, 216, 245, 150, 168, + 189, 249, 167, 237, 65, 203, 155, 74, 134, 83, 84, 43, 231, 80, + ] + ); + let current_query = json!({"orderBy": [["firstName", "asc"]], "limit": 100}); + let query_cbor = cbor_serializer::serializable_value_to_cbor(¤t_query, None).unwrap(); + let (documents, _, _) = drive + .query_documents_cbor_from_contract( + &contract, + document_type, + &query_cbor, + None, + None, + Some(15), + ) + .unwrap(); + assert_eq!(documents.len(), 10); + let names: Vec<_> = documents + .iter() + .map(|bytes| { + let document = Document::from_bytes(bytes, document_type, version).unwrap(); + document + .get("firstName") + .unwrap() + .as_text() + .unwrap() + .to_owned() + }) + .collect(); + assert_eq!( + names, + [ + "Adey", "Briney", "Cammi", "Celinda", "Dalia", "Gilligan", "Kevina", "Meta", "Noellyn", + "Prissie" + ] + ); + let primary_path = vec![ + vec![RootTree::DataContractDocuments as u8], + contract.id().to_vec(), + vec![1], + b"person".to_vec(), + vec![0], + ]; + for bytes in documents { + let current = Document::from_bytes(&bytes, document_type, version).unwrap(); + let pointer = drive + .grove + .get_raw( + primary_path.as_slice().into(), + current.id().as_slice(), + None, + &version.drive.grove_version, + ) + .value + .unwrap(); + assert!(matches!(pointer, Element::Reference(..))); + let query = DocumentHistoryDriveQuery { + contract_id: contract.id().to_buffer(), + document_type_name: "person".into(), + document_id: current.id().to_buffer(), + filter: DocumentHistoryFilter::StartAtTime(0), + limit: None, + }; + let page = drive + .fetch_document_history(&query, document_type, None, version) + .unwrap(); + let proof = drive + .prove_document_history(&query, document_type, None, version) + .unwrap(); + assert_eq!(page.lifecycle.as_ref().unwrap().remaining_revisions, 4); + assert_eq!( + page.entries + .iter() + .map(|entry| entry.time_ms) + .collect::>(), + [0, 15, 100, 1000] + ); + assert_eq!(page.entries.last().unwrap().document, current); + let (proved_root, verified) = + Drive::verify_document_history(&query, &proof, document_type, version).unwrap(); + assert_eq!(proved_root, root); + assert_eq!(verified, page); + } + let point_in_time = json!({ + "where": [["$id", "==", "6A8SGgdmj2NtWCYoYDPDpbsYkq2MCbgi6Lx4ALLfF179"]], + "blockTime": 300, + }); + let query_cbor = cbor_serializer::serializable_value_to_cbor(&point_in_time, None).unwrap(); + let result = drive.query_documents_cbor_from_contract( + &contract, + document_type, + &query_cbor, + None, + None, + Some(15), + ); + assert!( + matches!(result, Err(Error::Query(QuerySyntaxError::Unsupported(message))) + if message == "point-in-time reads are unavailable for history-keeping document types") + ); +} diff --git a/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_method_versions/v11.rs b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_method_versions/v11.rs index ffa5923ec3e..a032fdb42fd 100644 --- a/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_method_versions/v11.rs +++ b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_method_versions/v11.rs @@ -4,7 +4,7 @@ use super::{ DriveAbciCoreChainLockMethodVersionsAndConstants, DriveAbciEngineMethodVersions, DriveAbciIdentityCreditWithdrawalMethodVersions, DriveAbciMasternodeIdentitiesUpdatesMethodVersions, DriveAbciMethodVersions, - DriveAbciVotingMethodVersions, + DriveAbciProtocolUpgradeMethodVersions, DriveAbciVotingMethodVersions, }; /// Dash Core's DKG schedule (`llmq/params.h`) of the non-rotating quorum types, the ones chain @@ -112,6 +112,9 @@ const DKG_MINING_SCHEDULES_V1: &[DkgMiningSchedule] = &[ /// above. `verify_chain_lock_locally` 1 leaves to Core chain locks that 0 rejected, so it is /// only safe together with this check. /// - `engine.consensus_params_update` 2 installs the full evidence policy when it changes. +/// - `protocol_upgrade.perform_events_on_first_block_of_protocol_change` is `Some(3)`: +/// the first block crossing into protocol v15 migrates retained history after the other +/// activation work, in the same transaction. /// /// The asset unlocks: `withdrawals.build_untied_withdrawal_transactions_from_documents` is 1 /// rather than 0: a withdrawal pooled once `update_core_info` 1 has recorded Dash Core's V24 as @@ -122,6 +125,10 @@ const DKG_MINING_SCHEDULES_V1: &[DkgMiningSchedule] = &[ /// masternode that returns to a voting address it used before has the key of that address's /// voter identity re-enabled, where 0 re-enabled the key of the voter identity it was leaving. pub const DRIVE_ABCI_METHOD_VERSIONS_V11: DriveAbciMethodVersions = DriveAbciMethodVersions { + protocol_upgrade: DriveAbciProtocolUpgradeMethodVersions { + perform_events_on_first_block_of_protocol_change: Some(3), + ..DRIVE_ABCI_METHOD_VERSIONS_V10.protocol_upgrade + }, engine: DriveAbciEngineMethodVersions { consensus_params_update: 2, ..DRIVE_ABCI_METHOD_VERSIONS_V10.engine diff --git a/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_query_versions/mod.rs b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_query_versions/mod.rs index ab0f493c2a0..3f7fa86bbfe 100644 --- a/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_query_versions/mod.rs +++ b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_query_versions/mod.rs @@ -1,6 +1,7 @@ pub mod v0; pub mod v1; pub mod v2; +pub mod v3; use versioned_feature_core::{FeatureVersion, FeatureVersionBounds, OptionalFeatureVersion}; diff --git a/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_query_versions/v3.rs b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_query_versions/v3.rs new file mode 100644 index 00000000000..913db57bf61 --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_query_versions/v3.rs @@ -0,0 +1,13 @@ +use crate::version::drive_abci_versions::drive_abci_query_versions::v2::DRIVE_ABCI_QUERY_VERSIONS_V2; +use crate::version::drive_abci_versions::drive_abci_query_versions::DriveAbciQueryVersions; +use versioned_feature_core::FeatureVersionBounds; + +/// Composite history queries for the per-type retained history layout. +pub const DRIVE_ABCI_QUERY_VERSIONS_V3: DriveAbciQueryVersions = DriveAbciQueryVersions { + document_history: FeatureVersionBounds { + min_version: 1, + max_version: 1, + default_current_version: 1, + }, + ..DRIVE_ABCI_QUERY_VERSIONS_V2 +}; diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/v5.rs b/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/v5.rs index 957649fd9fe..5dd06fab673 100644 --- a/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/v5.rs +++ b/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/v5.rs @@ -1,6 +1,7 @@ use crate::version::drive_versions::drive_contract_method_versions::v4::DRIVE_CONTRACT_METHOD_VERSIONS_V4; use crate::version::drive_versions::drive_contract_method_versions::{ - DriveContractApplyMethodVersions, DriveContractMethodVersions, + DriveContractApplyMethodVersions, DriveContractInsertMethodVersions, + DriveContractMethodVersions, DriveContractUpdateMethodVersions, }; /// Drive contract methods for protocol v15+. @@ -12,8 +13,17 @@ use crate::version::drive_versions::drive_contract_method_versions::{ /// differ from the ones it was stored with in format version 1. v1 writes nothing when the /// two contracts' format version 1 bytes match, where v0 compared the stored bytes alone and /// would have rewritten an unchanged contract as an update. +/// * Inserts and updates create the per-type retained-history tree. pub const DRIVE_CONTRACT_METHOD_VERSIONS_V5: DriveContractMethodVersions = DriveContractMethodVersions { + insert: DriveContractInsertMethodVersions { + insert_contract: 3, + ..DRIVE_CONTRACT_METHOD_VERSIONS_V4.insert + }, + update: DriveContractUpdateMethodVersions { + update_contract: 3, + ..DRIVE_CONTRACT_METHOD_VERSIONS_V4.update + }, apply: DriveContractApplyMethodVersions { apply_contract_with_serialization: 1, ..DRIVE_CONTRACT_METHOD_VERSIONS_V4.apply diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_document_method_versions/mod.rs b/packages/rs-platform-version/src/version/drive_versions/drive_document_method_versions/mod.rs index cbd815cb9ef..55956779d6b 100644 --- a/packages/rs-platform-version/src/version/drive_versions/drive_document_method_versions/mod.rs +++ b/packages/rs-platform-version/src/version/drive_versions/drive_document_method_versions/mod.rs @@ -16,6 +16,10 @@ pub struct DriveDocumentMethodVersions { pub estimation_costs: DriveDocumentEstimationCostsMethodVersions, pub index_uniqueness: DriveDocumentIndexUniquenessMethodVersions, pub primary_key_tree_type: FeatureVersion, + /// `uses_current_document_history_layout`: selects legacy revision subtrees (0) + /// or current-document pointers into retained history (1) for derived reads, + /// cost estimation, layout descriptions and primary-key query lowering. + pub document_history_storage_layout: FeatureVersion, pub expiration: DriveDocumentExpirationMethodVersions, /// `Drive::fetch_property_constraint_aggregate`: a `countOf` or `sumOf` total a /// `propertyConstraints` rule reads, from the count or sum tree keeping it. Reachable diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_document_method_versions/v1.rs b/packages/rs-platform-version/src/version/drive_versions/drive_document_method_versions/v1.rs index f75c5277222..0eae7708634 100644 --- a/packages/rs-platform-version/src/version/drive_versions/drive_document_method_versions/v1.rs +++ b/packages/rs-platform-version/src/version/drive_versions/drive_document_method_versions/v1.rs @@ -89,6 +89,7 @@ pub const DRIVE_DOCUMENT_METHOD_VERSIONS_V1: DriveDocumentMethodVersions = validate_uniqueness_of_data: 0, }, primary_key_tree_type: 0, + document_history_storage_layout: 0, fetch_property_constraint_aggregate: 0, insert_empty_private_document_store_operation: None, // no private document type before protocol version 15 fetch_private_document_entries: None, // no private document type before protocol version 15 diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_document_method_versions/v2.rs b/packages/rs-platform-version/src/version/drive_versions/drive_document_method_versions/v2.rs index 6d7a5711d5c..fd16aecb084 100644 --- a/packages/rs-platform-version/src/version/drive_versions/drive_document_method_versions/v2.rs +++ b/packages/rs-platform-version/src/version/drive_versions/drive_document_method_versions/v2.rs @@ -123,6 +123,7 @@ pub const DRIVE_DOCUMENT_METHOD_VERSIONS_V2: DriveDocumentMethodVersions = // stop, so a future change to the v1 arm doesn't need to // re-prove v0 ≡ v1 for every pre-v12 corner case. primary_key_tree_type: 0, + document_history_storage_layout: 0, fetch_property_constraint_aggregate: 0, insert_empty_private_document_store_operation: None, // no private document type before protocol version 15 fetch_private_document_entries: None, // no private document type before protocol version 15 diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_document_method_versions/v3.rs b/packages/rs-platform-version/src/version/drive_versions/drive_document_method_versions/v3.rs index 6e66106a5ff..bba4cd57942 100644 --- a/packages/rs-platform-version/src/version/drive_versions/drive_document_method_versions/v3.rs +++ b/packages/rs-platform-version/src/version/drive_versions/drive_document_method_versions/v3.rs @@ -120,6 +120,7 @@ pub const DRIVE_DOCUMENT_METHOD_VERSIONS_V3: DriveDocumentMethodVersions = // versions stay on V2's v0 dispatch via their own method // tables (see V2's comment for the freeze rationale). primary_key_tree_type: 1, + document_history_storage_layout: 0, fetch_property_constraint_aggregate: 0, insert_empty_private_document_store_operation: None, // no private document type before protocol version 15 fetch_private_document_entries: None, // no private document type before protocol version 15 diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_document_method_versions/v4.rs b/packages/rs-platform-version/src/version/drive_versions/drive_document_method_versions/v4.rs index 7a98b33664c..1d936ee6899 100644 --- a/packages/rs-platform-version/src/version/drive_versions/drive_document_method_versions/v4.rs +++ b/packages/rs-platform-version/src/version/drive_versions/drive_document_method_versions/v4.rs @@ -190,6 +190,7 @@ pub const DRIVE_DOCUMENT_METHOD_VERSIONS_V4: DriveDocumentMethodVersions = // Unchanged from V3 — see V3's comment for the v12-gated // count/sum composition rationale. primary_key_tree_type: 1, + document_history_storage_layout: 0, fetch_property_constraint_aggregate: 0, insert_empty_private_document_store_operation: None, // no private document type before protocol version 15 fetch_private_document_entries: None, // no private document type before protocol version 15 diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_document_method_versions/v5.rs b/packages/rs-platform-version/src/version/drive_versions/drive_document_method_versions/v5.rs index a5f32ea84d2..0bfc920c38b 100644 --- a/packages/rs-platform-version/src/version/drive_versions/drive_document_method_versions/v5.rs +++ b/packages/rs-platform-version/src/version/drive_versions/drive_document_method_versions/v5.rs @@ -1,7 +1,8 @@ use crate::version::drive_versions::drive_document_method_versions::v4::DRIVE_DOCUMENT_METHOD_VERSIONS_V4; use crate::version::drive_versions::drive_document_method_versions::{ DriveDocumentDeleteMethodVersions, DriveDocumentEstimationCostsMethodVersions, - DriveDocumentMethodVersions, + DriveDocumentInsertMethodVersions, DriveDocumentMethodVersions, + DriveDocumentQueryMethodVersions, DriveDocumentUpdateMethodVersions, }; /// V5 is protocol version 15's document-method table. Relative to V4: @@ -13,13 +14,33 @@ use crate::version::drive_versions::drive_document_method_versions::{ /// `prove_private_document_entries` are `Some(0)` too (`None` before): a page of a store's /// entries can be read and proved, and `append_private_document_entries_operations` is /// `Some(0)` (`None` before): a `PrivateDocumentCreateFromShieldedPool` appends entries to one. +/// * `insert.add_reference_for_index_level_for_contract_operations` is 1: summable index +/// entries use `AllReferencesWithSumItem` for every type, as delete v2 does, so estimates +/// also change for summable types without history. /// * `delete.remove_reference_for_index_level_for_contract_operations` is 2: a delete's estimate /// describes an index's entries for a value (its `[0]` layer) as the references they are, as -/// the insert's does, not as subtrees. +/// the insert's does, including the primary-pointer and summable reference shapes. /// * `estimation_costs.stateless_delete_of_non_tree_for_costs` is 1: a delete's estimate prices /// each height of the climb with the layer GroveDB deletes in there, not the one above it. +/// * Retained-history writers, readers and estimators use the per-type revision layout. pub const DRIVE_DOCUMENT_METHOD_VERSIONS_V5: DriveDocumentMethodVersions = DriveDocumentMethodVersions { + document_history_storage_layout: 1, + query: DriveDocumentQueryMethodVersions { + fetch_document_history_query: 1, + fetch_document_history: 1, + prove_document_history: 1, + ..DRIVE_DOCUMENT_METHOD_VERSIONS_V4.query + }, + insert: DriveDocumentInsertMethodVersions { + add_document_to_primary_storage: 1, + add_reference_for_index_level_for_contract_operations: 1, + ..DRIVE_DOCUMENT_METHOD_VERSIONS_V4.insert + }, + update: DriveDocumentUpdateMethodVersions { + update_document_for_contract_operations: 2, + ..DRIVE_DOCUMENT_METHOD_VERSIONS_V4.update + }, insert_empty_private_document_store_operation: Some(0), // changed: a private document type's store is created with it fetch_private_document_entries: Some(0), // changed: a page of a store's entries can be read prove_private_document_entries: Some(0), // changed: and proved @@ -29,6 +50,7 @@ pub const DRIVE_DOCUMENT_METHOD_VERSIONS_V5: DriveDocumentMethodVersions = ..DRIVE_DOCUMENT_METHOD_VERSIONS_V4.delete }, estimation_costs: DriveDocumentEstimationCostsMethodVersions { + add_estimation_costs_for_add_document_to_primary_storage: 1, stateless_delete_of_non_tree_for_costs: 1, // changed: each height gets the layer priced there ..DRIVE_DOCUMENT_METHOD_VERSIONS_V4.estimation_costs }, diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_verify_method_versions/v4.rs b/packages/rs-platform-version/src/version/drive_versions/drive_verify_method_versions/v4.rs index 14a415f5f97..352417aa3bd 100644 --- a/packages/rs-platform-version/src/version/drive_versions/drive_verify_method_versions/v4.rs +++ b/packages/rs-platform-version/src/version/drive_versions/drive_verify_method_versions/v4.rs @@ -8,7 +8,8 @@ use crate::version::drive_versions::drive_verify_method_versions::{ /// `voting.verify_masternode_yes_no_vote` and `voting.verify_identity_yes_no_vote` are `Some(0)` /// (`None`, not active, in every earlier table), and so is /// `document.verify_private_document_entries`, with private document types. Everything else -/// matches `DRIVE_VERIFY_METHOD_VERSIONS_V3`. +/// matches `DRIVE_VERIFY_METHOD_VERSIONS_V3`, except the retained-history and cursor verifiers +/// selecting generation 1 for the per-type revision layout. pub const DRIVE_VERIFY_METHOD_VERSIONS_V4: DriveVerifyMethodVersions = DriveVerifyMethodVersions { voting: DriveVerifyVoteMethodVersions { verify_yes_no_vote_poll_state_proof: Some(0), @@ -17,6 +18,8 @@ pub const DRIVE_VERIFY_METHOD_VERSIONS_V4: DriveVerifyMethodVersions = DriveVeri ..DRIVE_VERIFY_METHOD_VERSIONS_V3.voting }, document: DriveVerifyDocumentMethodVersions { + verify_document_history: 1, + verify_start_at_document_in_proof: 1, verify_private_document_entries: Some(0), // changed: a proved page of a private type's store ..DRIVE_VERIFY_METHOD_VERSIONS_V3.document }, diff --git a/packages/rs-platform-version/src/version/drive_versions/v10.rs b/packages/rs-platform-version/src/version/drive_versions/v10.rs index 19cf3009495..bb997782435 100644 --- a/packages/rs-platform-version/src/version/drive_versions/v10.rs +++ b/packages/rs-platform-version/src/version/drive_versions/v10.rs @@ -22,6 +22,8 @@ use grovedb_version::version::v5::GROVE_V5; /// Drive version 10, introduced in protocol v15: /// +/// * **Retained history**: per-type revision trees and one proof authenticate its page, +/// count and lifecycle. /// * **Compiled contracts**: with `DRIVE_CONTRACT_METHOD_VERSIONS_V5`, applying a contract writes /// nothing when its format version 1 bytes match the stored contract's, whatever format the /// stored one is in, as contracts are stored compiled from this version @@ -138,7 +140,7 @@ pub const DRIVE_VERSION_V10: DriveVersion = DriveVersion { // changed in v10: GROVE_V5 (protocol v15 note 26), whose gates protocol v15 needs: a private // document store's entries are read and proved by position range, a store's creation is // estimated as it is applied, and a batch may repeat a keyless append. GROVE_V4, which v9 - // keeps, refuses all three. + // keeps, refuses all three. History also uses branch-local pagination and parent echoes. grove_version: GROVE_V5, ..DRIVE_VERSION_V9 }; diff --git a/packages/rs-platform-version/src/version/v15.rs b/packages/rs-platform-version/src/version/v15.rs index aa794085509..f6360e9d6fb 100644 --- a/packages/rs-platform-version/src/version/v15.rs +++ b/packages/rs-platform-version/src/version/v15.rs @@ -16,7 +16,7 @@ use crate::version::dpp_versions::dpp_voting_versions::v3::VOTING_VERSION_V3; use crate::version::dpp_versions::DPPVersion; use crate::version::drive_abci_versions::drive_abci_checkpoint_parameters::v1::DRIVE_ABCI_CHECKPOINT_PARAMETERS_V1; use crate::version::drive_abci_versions::drive_abci_method_versions::v11::DRIVE_ABCI_METHOD_VERSIONS_V11; -use crate::version::drive_abci_versions::drive_abci_query_versions::v2::DRIVE_ABCI_QUERY_VERSIONS_V2; +use crate::version::drive_abci_versions::drive_abci_query_versions::v3::DRIVE_ABCI_QUERY_VERSIONS_V3; use crate::version::drive_abci_versions::drive_abci_structure_versions::v2::DRIVE_ABCI_STRUCTURE_VERSIONS_V2; use crate::version::drive_abci_versions::drive_abci_validation_versions::v11::DRIVE_ABCI_VALIDATION_VERSIONS_V11; use crate::version::drive_abci_versions::drive_abci_withdrawal_constants::v3::DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V3; @@ -546,7 +546,7 @@ pub const PROTOCOL_VERSION_15: ProtocolVersion = 15; /// that is unreachable there. /// /// 26. **GroveDB V5**: `DRIVE_VERSION_V10` selects `GROVE_V5` (protocol v14 keeps `GROVE_V4`, -/// which GroveDB 6.1.1 shipped). Three of its gates differ from V4, and protocol v15 needs +/// which GroveDB 6.1.1 shipped). Its private-document gates differ from V4, and protocol v15 needs /// each: a private document store's entries are read and proved by position range, which /// `getPrivateDocumentEntries` (note 13) is built on (`private_document_store.get_range` /// and `range_proof` 1); creating a store is estimated as it is applied, its existence check @@ -554,8 +554,11 @@ pub const PROTOCOL_VERSION_15: ProtocolVersion = 15; /// and worst case estimators), so a contract create or update adding a private type is /// estimated no lower than it costs; and a batch may carry the same keyless append more /// than once (`apply_batch.keyless_append_repeats` 1), which the batch consistency check -/// Drive runs for estimates and partial batches used to refuse. No other GroveDB behaviour -/// changes. Private document types and their store exist only from this version, so the +/// Drive runs for estimates and partial batches used to refuse. Retained history selects `merge` 2, +/// `per_instance_query_offsets` 1, `element.path_query_push` 2, and +/// `proof.count_offset_reference_empty_tree_rows` 1: branch-local count pages, raw +/// parent-tree echoes and faithful merged queries share one ordinary proof. +/// Private document types and their store exist only from this version, so the /// first two reach no earlier state; a batch repeating a keyless append arises nowhere in /// Platform (notes are unique, and note 25 refuses identical entries). /// @@ -567,15 +570,22 @@ pub const PROTOCOL_VERSION_15: ProtocolVersion = 15; /// block's rate. Every schedule so far has the same storage rate, so no refund changes. A /// removal from an earlier epoch pays once per such epoch for reading its record, the only /// fee this changes; generation 0 reads nothing. +/// +/// 28. **Composite document history**: retained revisions move to per-type history trees, +/// primary entries reference the current revision, and matching queries and verifiers +/// authenticate history pages. The first block crossing into v15 migrates existing +/// history after all other activation events in the same transaction. +/// Insert v1 and delete v2 describe summable index entries as `AllReferencesWithSumItem` +/// for every type, so estimates also change for summable types without history. pub const PLATFORM_V15: PlatformVersion = PlatformVersion { protocol_version: PROTOCOL_VERSION_15, - drive: DRIVE_VERSION_V10, // changed: calculate_fee 1 prices a refund at the storing epoch's rate (note 27); apply_contract_with_serialization 1 writes nothing for a contract whose format version 1 bytes match the stored one's (note 8); vote method versions v4: register_identity_vote 1 registers a yes/no vote, remove_all_votes_given_by_identities 1 also removes the yes/no votes of a masternode that left the list, every yes_no method and remove_vote_poll_end_date_query_operations Some(0) make yes/no polls active, add_vote_poll_end_date_query_operations 1 adds only the entry when the batch already queues the end date's tree with other storage flags, and verify methods v4 make the yes/no proof verifiers active (note 10) and verify_private_document_entries Some(0) a page of a private type's store (note 13); state transition method versions v5: document_create_transition 1 deletes a consumed document from what its lookup read (note 11); document method versions v5: insert_empty_private_document_store_operation Some(0) creates a private document type's store, and fetch_private_document_entries and prove_private_document_entries Some(0) read and prove a page of it (note 13); apply_drive_operations 2 resolves a batch's estimate, remove_reference_for_index_level_for_contract_operations 2, stateless_delete_of_non_tree_for_costs 1 and for_total_system_credits_update 1 describe their layers as they are (note 14); create_initial_state_structure 5 adds the token marketplace escrow trees; calculate_total_tokens_balance 2 counts escrowed tokens; the escrow primitives; the identity balance, token balance, prefunded specialized balance and contract fee pot estimations (for_balances 1, for_token_balances 1, estimated_cost_for_prefunded_specialized_balance_update 2, add_estimation_costs_for_contract_fee_pot_update 1) keep a deeper layer description (note 17); fetch_core_fork_activation_height and store_core_fork_activation_height Some(0) keep the Core fork activations (note 18); document method versions v5: append_private_document_entries_operations Some(0) appends a private document create's entries (note 25); grove_version GROVE_V5 (note 26) + drive: DRIVE_VERSION_V10, // changed: calculate_fee 1 prices a refund at the storing epoch's rate (note 27); apply_contract_with_serialization 1 writes nothing for a contract whose format version 1 bytes match the stored one's (note 8); vote method versions v4: register_identity_vote 1 registers a yes/no vote, remove_all_votes_given_by_identities 1 also removes the yes/no votes of a masternode that left the list, every yes_no method and remove_vote_poll_end_date_query_operations Some(0) make yes/no polls active, add_vote_poll_end_date_query_operations 1 adds only the entry when the batch already queues the end date's tree with other storage flags, and verify methods v4 make the yes/no proof verifiers active (note 10) and verify_private_document_entries Some(0) a page of a private type's store (note 13); state transition method versions v5: document_create_transition 1 deletes a consumed document from what its lookup read (note 11); document method versions v5: insert_empty_private_document_store_operation Some(0) creates a private document type's store, and fetch_private_document_entries and prove_private_document_entries Some(0) read and prove a page of it (note 13); apply_drive_operations 2 resolves a batch's estimate, remove_reference_for_index_level_for_contract_operations 2, stateless_delete_of_non_tree_for_costs 1 and for_total_system_credits_update 1 describe their layers as they are (note 14); create_initial_state_structure 5 adds the token marketplace escrow trees; calculate_total_tokens_balance 2 counts escrowed tokens; the escrow primitives; the identity balance, token balance, prefunded specialized balance and contract fee pot estimations (for_balances 1, for_token_balances 1, estimated_cost_for_prefunded_specialized_balance_update 2, add_estimation_costs_for_contract_fee_pot_update 1) keep a deeper layer description (note 17); fetch_core_fork_activation_height and store_core_fork_activation_height Some(0) keep the Core fork activations (note 18); document method versions v5: append_private_document_entries_operations Some(0) appends a private document create's entries (note 25); grove_version GROVE_V5 (note 26); retained-history writers, readers, estimates and verifiers select the per-type revision layout (note 28) drive_abci: DriveAbciVersion { structs: DRIVE_ABCI_STRUCTURE_VERSIONS_V2, - methods: DRIVE_ABCI_METHOD_VERSIONS_V11, // changed: the yes/no poll's tally, record, clean-up and finish hook are Some(0) (note 10); verify_chain_lock_locally 1 rejects a chain lock locally only when Platform holds the quorums active at its signing height, and verify_chain_lock_through_core 1 has Core's verifychainlock check the others before submitchainlock; consensus_params_update 2 installs the full evidence policy (note 16); update_core_info 1 records the chain locked height at which Core's V24 is first seen active (note 18); build_untied_withdrawal_transactions_from_documents 1 emits asset unlock payload version 2 once V24 is recorded as active (note 20); update_voter_identity 1 re-enables the voter key of the address a masternode returns to (note 22) + methods: DRIVE_ABCI_METHOD_VERSIONS_V11, // changed: perform_events_on_first_block_of_protocol_change 3 migrates retained history after the other activation work (note 28); the yes/no poll's tally, record, clean-up and finish hook are Some(0) (note 10); verify_chain_lock_locally 1 rejects a chain lock locally only when Platform holds the quorums active at its signing height, and verify_chain_lock_through_core 1 has Core's verifychainlock check the others before submitchainlock; consensus_params_update 2 installs the full evidence policy (note 16); update_core_info 1 records the chain locked height at which Core's V24 is first seen active (note 18); build_untied_withdrawal_transactions_from_documents 1 emits asset unlock payload version 2 once V24 is recorded as active (note 20); update_voter_identity 1 re-enables the voter key of the address a masternode returns to (note 22) validation_and_processing: DRIVE_ABCI_VALIDATION_VERSIONS_V11, // changed: identity update advanced_structure 1 refuses unpaid an identity update whose added key's proof of possession does not verify (note 2); create_domain_data_trigger 2 (note 3); contract update transform_into_action 1 holds an update to the compiled size cap in check_tx (note 8); batch advanced_structure 2 refuses a token config update on a read-only contract (note 9); masternode vote transform_into_action 1 looks up a masternode's previous answer on a yes/no poll (note 10); document_reference_validation 1 keeps what a consumed commitment's lookup read (note 11); document create structure_validation 2 holds a decision proposal to its fund, rule and end date (note 12); data trigger bindings 3 refuse a replace or a delete of a token market order (note 17) and drop the DashPay bindings (note 24); document create state_validation 3 keeps a create outside a contest off the values of a live one its index values do not decide (note 19); identity create basic_structure 1 checks the identity id before the asset lock proof and advanced_structure 2 no longer does (note 23) withdrawal_constants: DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V3, - query: DRIVE_ABCI_QUERY_VERSIONS_V2, + query: DRIVE_ABCI_QUERY_VERSIONS_V3, checkpoints: DRIVE_ABCI_CHECKPOINT_PARAMETERS_V1, }, dpp: DPPVersion { diff --git a/packages/rs-platform-version/tests/document_history_storage_versions.rs b/packages/rs-platform-version/tests/document_history_storage_versions.rs new file mode 100644 index 00000000000..912841b1076 --- /dev/null +++ b/packages/rs-platform-version/tests/document_history_storage_versions.rs @@ -0,0 +1,198 @@ +#[cfg(feature = "mock-versions")] +use platform_version::version::mocks::{v2_test::TEST_PLATFORM_V2, v3_test::TEST_PLATFORM_V3}; +use platform_version::version::{PlatformVersion, ALL_VERSIONS}; + +#[test] +fn should_keep_writer_and_history_layout_versions_consistent_for_replay() { + for protocol in ALL_VERSIONS { + let version = PlatformVersion::get(protocol).expect("supported protocol version"); + let document = &version.drive.methods.document; + let expected = u16::from(protocol >= 15); + + assert_eq!( + ( + document.insert.add_document_to_primary_storage, + document.document_history_storage_layout, + ), + (expected, expected), + "protocol {protocol} must select matching writer and history layout generations" + ); + } +} + +#[cfg(feature = "mock-versions")] +#[test] +fn should_keep_mock_writer_and_history_layout_on_legacy_storage() { + for version in [TEST_PLATFORM_V2, TEST_PLATFORM_V3] { + let document = &version.drive.methods.document; + assert_eq!( + ( + document.insert.add_document_to_primary_storage, + document.document_history_storage_layout, + ), + (0, 0), + "mock protocol {} must retain legacy storage", + version.protocol_version + ); + } +} + +#[test] +fn should_keep_released_document_history_storage_and_proofs_unchanged() { + for protocol in [12, 13, 14] { + let version = PlatformVersion::get(protocol).unwrap(); + let document = &version.drive.methods.document; + assert_eq!(document.insert.add_document_to_primary_storage, 0); + assert_eq!( + document + .insert + .add_reference_for_index_level_for_contract_operations, + 0 + ); + let existing_index_walker_version = if protocol == 14 { 1 } else { 0 }; + assert_eq!( + document.update.update_document_for_contract_operations, + existing_index_walker_version + ); + assert_eq!( + document + .delete + .remove_reference_for_index_level_for_contract_operations, + existing_index_walker_version + ); + assert_eq!( + document + .estimation_costs + .add_estimation_costs_for_add_document_to_primary_storage, + 0 + ); + assert_eq!(document.query.fetch_document_history_query, 0); + assert_eq!(document.query.fetch_document_history, 0); + assert_eq!(document.query.prove_document_history, 0); + let contract = &version.drive.methods.contract; + assert_eq!( + contract.insert.insert_contract, + if protocol == 14 { 2 } else { 1 } + ); + assert_eq!( + contract.update.update_contract, + if protocol == 14 { 2 } else { 1 } + ); + assert_eq!( + version + .drive + .methods + .verify + .document + .verify_document_history, + 0 + ); + assert_eq!( + version + .drive + .methods + .verify + .document + .verify_start_at_document_in_proof, + 0 + ); + let bounds = &version.drive_abci.query.document_history; + assert_eq!( + ( + bounds.min_version, + bounds.max_version, + bounds.default_current_version + ), + (0, 0, 0) + ); + assert_ne!( + version + .drive_abci + .methods + .protocol_upgrade + .perform_events_on_first_block_of_protocol_change, + Some(3) + ); + } +} + +#[test] +fn should_activate_storage_migration_and_history_proofs_together() { + let version = PlatformVersion::get(15).unwrap(); + let document = &version.drive.methods.document; + // The layout-dependent methods change together. + assert_eq!(document.insert.add_document_to_primary_storage, 1); + assert_eq!( + document + .insert + .add_reference_for_index_level_for_contract_operations, + 1 + ); + assert_eq!(document.update.update_document_for_contract_operations, 2); + assert_eq!( + document + .delete + .remove_reference_for_index_level_for_contract_operations, + 2 + ); + assert_eq!( + document + .estimation_costs + .add_estimation_costs_for_add_document_to_primary_storage, + 1 + ); + assert_eq!(document.query.fetch_document_history_query, 1); + assert_eq!(document.query.fetch_document_history, 1); + assert_eq!(document.query.prove_document_history, 1); + let grove = &version.drive.grove_version.grovedb_versions; + assert_eq!(grove.path_query_methods.merge, 2); + assert_eq!(grove.path_query_methods.per_instance_query_offsets, 1); + assert_eq!(grove.element.path_query_push, 2); + assert_eq!( + grove + .operations + .proof + .count_offset_reference_empty_tree_rows, + 1 + ); + // Contract writers create the per-type history tree. + let contract = &version.drive.methods.contract; + assert_eq!(contract.insert.insert_contract, 3); + assert_eq!(contract.update.update_contract, 3); + assert_eq!( + version + .drive + .methods + .verify + .document + .verify_document_history, + 1 + ); + assert_eq!( + version + .drive + .methods + .verify + .document + .verify_start_at_document_in_proof, + 1 + ); + // The composite wire shape activates with its storage and proof layout. + let bounds = &version.drive_abci.query.document_history; + assert_eq!( + ( + bounds.min_version, + bounds.max_version, + bounds.default_current_version + ), + (1, 1, 1) + ); + assert_eq!( + version + .drive_abci + .methods + .protocol_upgrade + .perform_events_on_first_block_of_protocol_change, + Some(3) + ); +} diff --git a/packages/rs-sdk/src/mock/requests.rs b/packages/rs-sdk/src/mock/requests.rs index eab6ef5268f..85593c78cd0 100644 --- a/packages/rs-sdk/src/mock/requests.rs +++ b/packages/rs-sdk/src/mock/requests.rs @@ -252,6 +252,85 @@ impl MockResponse for Document { } } +type MockDocumentHistory = (Vec<(u64, u64, Vec)>, Option<(bool, u64)>); + +impl MockResponse for drive_proof_verifier::types::DocumentHistoryProofInfo { + fn mock_serialize(&self, sdk: &MockDashPlatformSdk) -> Vec { + use dapi_grpc::Message; + bincode::encode_to_vec( + ( + self.history.mock_serialize(sdk), + self.response.encode_to_vec(), + ), + BINCODE_CONFIG, + ) + .expect("encode document history proof info") + } + + fn mock_deserialize(sdk: &MockDashPlatformSdk, buf: &[u8]) -> Self { + use dapi_grpc::Message; + let ((history, response), _): ((Vec, Vec), _) = + bincode::decode_from_slice(buf, BINCODE_CONFIG) + .expect("decode document history proof info"); + Self { + history: drive_proof_verifier::types::DocumentHistory::mock_deserialize(sdk, &history), + response: dapi_grpc::platform::v0::get_document_history_response::GetDocumentHistoryResponseV1::decode(response.as_slice()) + .expect("decode document history response"), + } + } +} + +impl MockResponse for drive_proof_verifier::types::DocumentHistory { + fn mock_serialize(&self, sdk: &MockDashPlatformSdk) -> Vec { + use drive_proof_verifier::types::DocumentHistoryState; + let entries = self + .entries + .iter() + .map(|entry| { + ( + entry.time_ms, + entry.revision, + entry.document.mock_serialize(sdk), + ) + }) + .collect::>(); + let lifecycle = self.lifecycle.as_ref().map(|lifecycle| { + ( + lifecycle.state == DocumentHistoryState::Active, + lifecycle.remaining_revisions, + ) + }); + bincode::encode_to_vec((entries, lifecycle), BINCODE_CONFIG) + .expect("encode document history") + } + + fn mock_deserialize(sdk: &MockDashPlatformSdk, buf: &[u8]) -> Self { + use drive_proof_verifier::types::{ + DocumentHistoryEntry, DocumentHistoryLifecycle, DocumentHistoryState, + }; + let ((entries, lifecycle), _): (MockDocumentHistory, _) = + bincode::decode_from_slice(buf, BINCODE_CONFIG).expect("decode document history"); + Self { + entries: entries + .into_iter() + .map(|(time_ms, revision, bytes)| DocumentHistoryEntry { + time_ms, + revision, + document: Document::mock_deserialize(sdk, &bytes), + }) + .collect(), + lifecycle: lifecycle.map(|(active, remaining_revisions)| DocumentHistoryLifecycle { + state: if active { + DocumentHistoryState::Active + } else { + DocumentHistoryState::Absent + }, + remaining_revisions, + }), + } + } +} + impl MockResponse for Element { fn mock_serialize(&self, _sdk: &MockDashPlatformSdk) -> Vec { // Create a bincode configuration diff --git a/packages/rs-sdk/src/platform/fetch.rs b/packages/rs-sdk/src/platform/fetch.rs index 03455d612c7..8fcbdd58a37 100644 --- a/packages/rs-sdk/src/platform/fetch.rs +++ b/packages/rs-sdk/src/platform/fetch.rs @@ -376,6 +376,11 @@ impl Fetch for drive_proof_verifier::types::DataContractHistory { type Request = platform_proto::GetDataContractHistoryRequest; } +impl Fetch for drive_proof_verifier::types::DocumentHistoryProofInfo { + type Query = platform_proto::GetDocumentHistoryRequest; + type Request = platform_proto::GetDocumentHistoryRequest; +} + impl Fetch for drive_proof_verifier::types::DocumentHistory { type Query = platform_proto::GetDocumentHistoryRequest; type Request = platform_proto::GetDocumentHistoryRequest; diff --git a/packages/rs-sdk/src/platform/query.rs b/packages/rs-sdk/src/platform/query.rs index 3434ec94a3b..828ce8674d8 100644 --- a/packages/rs-sdk/src/platform/query.rs +++ b/packages/rs-sdk/src/platform/query.rs @@ -389,26 +389,51 @@ impl Query for DocumentHistoryQuery { &self, settings: &crate::platform::QuerySettings<'_>, ) -> Result { - let prove = settings.prove; - if !prove { + use drive::query::document_history_drive_query::{ + DocumentHistoryDriveQuery, DocumentHistoryFilter, + }; + use proto::get_document_history_request::{ + get_document_history_request_v1::{Cursor, Filter}, + GetDocumentHistoryRequestV1, + }; + // Every history fetch verifies its GroveDB proof; there is no + // unproved decoding path, so a proof-disabled request would only fail + // after the round trip. + if !settings.prove { return Err(Error::Config( - "unproved queries are not supported for this query; enable proofs".to_string(), + "unproved queries are not supported for this query; enable proofs".to_owned(), )); } - - Ok(proto::GetDocumentHistoryRequest { - version: Some(proto::get_document_history_request::Version::V0( - proto::get_document_history_request::GetDocumentHistoryRequestV0 { - data_contract_id: self.data_contract_id.to_vec(), - document_type_name: self.document_type_name.clone(), - document_id: self.document_id.to_vec(), - limit: self.limit, - offset: self.offset, - start_at_ms: self.start_at_ms, - prove, - }, - )), - }) + let limit = self + .limit + .map(u16::try_from) + .transpose() + .map_err(|_| Error::Generic("history limit out of bounds".to_owned()))?; + DocumentHistoryDriveQuery { + contract_id: self.data_contract_id.to_buffer(), + document_type_name: self.document_type_name.clone(), + document_id: self.document_id.to_buffer(), + filter: self.filter.clone(), + limit, + } + .validate()?; + let filter = match self.filter { + DocumentHistoryFilter::StartAtTime(time) => Filter::StartAtMs(time), + DocumentHistoryFilter::StartAfter { time_ms, revision } => { + Filter::StartAfter(Cursor { time_ms, revision }) + } + DocumentHistoryFilter::StartAtRevision(revision) => Filter::StartAtRevision(revision), + DocumentHistoryFilter::Revision(revision) => Filter::Revision(revision), + }; + Ok(GetDocumentHistoryRequestV1 { + data_contract_id: self.data_contract_id.to_vec(), + document_type_name: self.document_type_name.clone(), + document_id: self.document_id.to_vec(), + limit: self.limit, + filter: Some(filter), + prove: settings.prove, + } + .into()) } } @@ -1745,3 +1770,208 @@ impl Query for TokenShieldedNullifiersQuery { }) } } + +#[cfg(test)] +mod history_query_tests { + use super::*; + use crate::platform::QuerySettings; + use dapi_grpc::platform::v0::get_document_history_request::get_document_history_request_v1::Filter; + use dpp::dashcore::Network; + use dpp::version::PlatformVersion; + use drive::query::document_history_drive_query::DocumentHistoryFilter; + + #[cfg(feature = "mocks")] + #[tokio::test] + async fn should_fetch_history_with_lifecycle_and_same_time_revisions() { + use crate::platform::Fetch; + use drive_proof_verifier::types::{ + DocumentHistory, DocumentHistoryEntry, DocumentHistoryLifecycle, DocumentHistoryState, + }; + let mut sdk = crate::SdkBuilder::default() + .with_network(Network::Devnet) + .with_initial_version(PlatformVersion::get(15).unwrap()) + .build() + .unwrap(); + let query = DocumentHistoryQuery { + data_contract_id: [1; 32].into(), + document_type_name: "note".into(), + document_id: [2; 32].into(), + filter: DocumentHistoryFilter::StartAtTime(0), + limit: None, + }; + let expected = DocumentHistory { + entries: [1, 2] + .into_iter() + .map(|revision| DocumentHistoryEntry { + time_ms: 2000, + revision, + document: dpp::document::Document::V0(dpp::document::DocumentV0 { + revision: Some(revision), + ..Default::default() + }), + }) + .collect(), + lifecycle: Some(DocumentHistoryLifecycle { + state: DocumentHistoryState::Active, + remaining_revisions: 2, + }), + }; + sdk.mock() + .expect_fetch(query.clone(), Some(expected.clone())) + .await + .unwrap(); + let result = DocumentHistory::fetch(&sdk, query).await.unwrap().unwrap(); + assert_eq!(result, expected); + } + + #[test] + fn should_report_oversized_history_limits_as_request_errors() { + let request_settings = Default::default(); + let settings = QuerySettings { + request_settings: &request_settings, + protocol_version: PlatformVersion::get(15).unwrap(), + verified_protocol_version: 0, + prove: true, + }; + for limit in [u16::MAX as u32 + 1, u32::MAX] { + let query = DocumentHistoryQuery { + data_contract_id: [1; 32].into(), + document_type_name: "note".into(), + document_id: [2; 32].into(), + filter: DocumentHistoryFilter::StartAtTime(0), + limit: Some(limit), + }; + assert!( + matches!(query.query(&settings), Err(Error::Generic(message)) + if message == "history limit out of bounds") + ); + } + } + + #[test] + fn should_reject_proof_disabled_history_queries_before_sending() { + let request_settings = Default::default(); + let settings = QuerySettings { + request_settings: &request_settings, + protocol_version: PlatformVersion::get(15).unwrap(), + verified_protocol_version: 0, + prove: false, + }; + let query = DocumentHistoryQuery { + data_contract_id: [1; 32].into(), + document_type_name: "note".into(), + document_id: [2; 32].into(), + filter: DocumentHistoryFilter::StartAtTime(0), + limit: Some(1), + }; + assert!(matches!(query.query(&settings), Err(Error::Config(message)) + if message == "unproved queries are not supported for this query; enable proofs")); + } + + #[test] + fn should_encode_complete_history_selectors_before_protocol_discovery() { + let request_settings = Default::default(); + let settings = QuerySettings { + request_settings: &request_settings, + protocol_version: PlatformVersion::get(15).unwrap(), + verified_protocol_version: 0, + prove: true, + }; + let mut query = DocumentHistoryQuery { + data_contract_id: [1; 32].into(), + document_type_name: "note".into(), + document_id: [2; 32].into(), + filter: DocumentHistoryFilter::StartAfter { + time_ms: 1000, + revision: 22, + }, + limit: Some(10), + }; + let request = query.query(&settings).unwrap(); + let Some(proto::get_document_history_request::Version::V1(request)) = request.version + else { + panic!("expected history version one"); + }; + let Some(Filter::StartAfter(cursor)) = request.filter else { + panic!("expected composite cursor"); + }; + assert_eq!((cursor.time_ms, cursor.revision), (1000, 22)); + for protocol in [12, 13, 14] { + let settings = QuerySettings { + protocol_version: PlatformVersion::get(protocol).unwrap(), + ..settings + }; + for filter in [ + DocumentHistoryFilter::StartAfter { + time_ms: 1000, + revision: 22, + }, + DocumentHistoryFilter::StartAtRevision(2), + DocumentHistoryFilter::Revision(2), + ] { + query.filter = filter; + query.limit = Some(1); + assert!(query.query(&settings).is_ok()); + } + } + query.filter = DocumentHistoryFilter::Revision(2); + query.limit = Some(10); + assert!(query.query(&settings).is_err()); + query.limit = Some(1); + assert!(query.query(&settings).is_ok()); + query.filter = DocumentHistoryFilter::StartAtRevision(65536); + assert!(query.query(&settings).is_ok()); + query.filter = DocumentHistoryFilter::StartAtRevision(65537); + assert!(query.query(&settings).is_err()); + } + + #[test] + fn should_reject_malformed_history_filters_before_protocol_discovery() { + let request_settings = Default::default(); + for version in [ + PlatformVersion::get(13).unwrap(), + PlatformVersion::get(14).unwrap(), + PlatformVersion::latest(), + ] { + let settings = QuerySettings { + request_settings: &request_settings, + protocol_version: version, + verified_protocol_version: 0, + prove: true, + }; + for (filter, limit) in [ + (DocumentHistoryFilter::StartAtTime(0), Some(0)), + (DocumentHistoryFilter::StartAtTime(0), Some(11)), + (DocumentHistoryFilter::StartAtTime(1 << 63), None), + ( + DocumentHistoryFilter::StartAfter { + time_ms: 1 << 63, + revision: 1, + }, + None, + ), + ( + DocumentHistoryFilter::StartAfter { + time_ms: 0, + revision: 0, + }, + None, + ), + (DocumentHistoryFilter::Revision(0), None), + (DocumentHistoryFilter::Revision(65537), None), + (DocumentHistoryFilter::StartAtRevision(0), None), + (DocumentHistoryFilter::StartAtRevision(65537), None), + (DocumentHistoryFilter::Revision(1), Some(2)), + ] { + let query = DocumentHistoryQuery { + data_contract_id: [1; 32].into(), + document_type_name: "note".into(), + document_id: [2; 32].into(), + filter, + limit, + }; + assert!(query.query(&settings).is_err()); + } + } + } +} diff --git a/packages/rs-sdk/src/sdk.rs b/packages/rs-sdk/src/sdk.rs index c379f226b0e..ed0f50614e6 100644 --- a/packages/rs-sdk/src/sdk.rs +++ b/packages/rs-sdk/src/sdk.rs @@ -135,8 +135,8 @@ pub const DEFAULT_QUORUM_PUBLIC_KEYS_CACHE_SIZE: usize = 100; /// initial version. /// /// Mainnet, testnet and regtest seed at protocol version 13, the lowest version -/// any of those networks still runs. Devnets seed at 14: they are cut from the -/// current development line. Proved reads can use a newer version named in +/// any of those networks still runs. Devnets seed at 14, the lowest version +/// a development network may still run. Proved reads can use a newer version named in /// their signed response metadata even when the SDK starts with a lower seed; /// the stored version ratchets only after proof and signature verification. /// @@ -3004,15 +3004,13 @@ pub(crate) mod test { assert!(!sdk.version_pinned); } - /// Devnets are cut from the current development line and their contracts use - /// index grammar older versions cannot deserialize, so the devnet floor is the - /// current version while the public networks keep the lowest version they run. + /// Each network seeds at the lowest protocol version it may still run. #[test] fn test_per_network_floors() { assert_eq!( min_protocol_version(Network::Devnet), dpp::version::v14::PROTOCOL_VERSION_14, - "devnet floor must be the current development version" + "devnet floor must support networks still running protocol 14" ); for network in [Network::Mainnet, Network::Testnet, Network::Regtest] { assert_eq!( diff --git a/packages/rs-sdk/src/sdk/signed_version_tests.rs b/packages/rs-sdk/src/sdk/signed_version_tests.rs index 9e6ea785892..fd3650e508f 100644 --- a/packages/rs-sdk/src/sdk/signed_version_tests.rs +++ b/packages/rs-sdk/src/sdk/signed_version_tests.rs @@ -42,6 +42,8 @@ use std::path::PathBuf; use std::sync::atomic::{AtomicBool, AtomicU32, Ordering}; use std::sync::{Arc, Mutex, OnceLock}; +mod document_history; + /// A verifier double that exposes the table supplied by the SDK without /// interpreting proof bytes. Signature acceptance is tested separately using /// recorded, signed responses. @@ -168,6 +170,33 @@ async fn observed_table( struct NoKeys; +#[tokio::test] +async fn should_start_an_unpinned_devnet_at_14_and_learn_15_from_a_response() { + let sdk = SdkBuilder::new_mock() + .with_network(Network::Devnet) + .with_context_provider(NoKeys) + .with_time_tolerance(None) + .with_height_tolerance(Some(1)) + .with_trusted_initial_height(2) + .build() + .expect("devnet SDK"); + assert_eq!(sdk.protocol_version_number(), 14); + assert!(!sdk.version_pinned); + for (signed, expected) in [(14, 14), (15, 15), (14, 15)] { + let (request, response) = recorded_response(signed); + let (observed, _, _) = sdk + .parse_proof_with_metadata_and_proof::( + request, + response, + "get_epochs_info", + ) + .await + .expect("verifier double"); + assert_eq!(observed.expect("observed table").0, expected); + assert_eq!(sdk.protocol_version_number(), expected); + } +} + impl ContextProvider for NoKeys { fn get_data_contract( &self, diff --git a/packages/rs-sdk/src/sdk/signed_version_tests/document_history.rs b/packages/rs-sdk/src/sdk/signed_version_tests/document_history.rs new file mode 100644 index 00000000000..5885edeec98 --- /dev/null +++ b/packages/rs-sdk/src/sdk/signed_version_tests/document_history.rs @@ -0,0 +1,464 @@ +use super::super::{Sdk, SdkBuilder, SdkInstance}; +use crate::platform::{DocumentHistoryQuery, Fetch}; +use dapi_grpc::platform::v0::get_document_history_request::get_document_history_request_v1::Filter; +use dapi_grpc::platform::v0::get_document_history_request::Version as RequestVersion; +use dapi_grpc::platform::v0::get_document_history_response::Version as ResponseVersion; +use dapi_grpc::platform::v0::{GetDocumentHistoryRequest, GetDocumentHistoryResponse}; +use dapi_grpc::platform::VersionedGrpcResponse; +use dapi_grpc::tonic::{Code, Status}; +use dash_context_provider::{ContextProvider, ContextProviderError}; +use dpp::dashcore::Network; +use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::data_contract::TokenConfiguration; +use dpp::document::DocumentV0Getters; +use dpp::prelude::{CoreBlockHeight, DataContract, Identifier}; +use dpp::serialization::PlatformDeserializableWithPotentialValidationFromVersionedStructureTrusted; +use dpp::version::PlatformVersion; +use drive::query::document_history_drive_query::DocumentHistoryFilter; +use drive_proof_verifier::types::{ + DocumentHistory, DocumentHistoryProofInfo, DocumentHistoryState, +}; +use drive_proof_verifier::FromProof; +use rs_dapi_client::transport::TransportError; +use rs_dapi_client::{AddressList, DapiClientError, ExecutionError, ExecutionResponse}; +use serde::Deserialize; +use std::sync::Arc; +use test_case::test_case; + +#[derive(Deserialize)] +struct Fixture { + contract: String, + quorum_public_key: String, + request: GetDocumentHistoryRequest, + response: GetDocumentHistoryResponse, +} + +impl Fixture { + fn load(cursor: bool) -> Self { + let bytes = if cursor { + include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/tests/vectors/document_history/pv15_cursor.json" + )) + } else { + include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/tests/vectors/document_history/pv15_revision.json" + )) + }; + serde_json::from_str(bytes).expect("signed history fixture") + } + + fn provider(&self) -> Provider { + Provider { + contract: Arc::new( + DataContract::versioned_deserialize_trusted( + &hex::decode(&self.contract).expect("contract hex"), + false, + PlatformVersion::latest(), + ) + .expect("fixture contract"), + ), + key: hex::decode(&self.quorum_public_key) + .expect("quorum key hex") + .try_into() + .expect("48-byte key"), + } + } + + fn query(&self) -> DocumentHistoryQuery { + let Some(RequestVersion::V1(request)) = &self.request.version else { + panic!("versioned history request"); + }; + DocumentHistoryQuery { + data_contract_id: Identifier::from_bytes(&request.data_contract_id).unwrap(), + document_type_name: request.document_type_name.clone(), + document_id: Identifier::from_bytes(&request.document_id).unwrap(), + filter: match request.filter.as_ref().unwrap() { + Filter::Revision(revision) => DocumentHistoryFilter::Revision(*revision), + Filter::StartAfter(cursor) => DocumentHistoryFilter::StartAfter { + time_ms: cursor.time_ms, + revision: cursor.revision, + }, + _ => panic!("revision or cursor fixture"), + }, + limit: request.limit, + } + } + + fn sdk(&self, network: Network, mock: bool) -> Sdk { + let builder = if mock { + SdkBuilder::new_mock() + } else { + SdkBuilder::new(AddressList::new()) + }; + let sdk = builder + .with_network(network) + .with_context_provider(self.provider()) + .with_time_tolerance(None) + .with_height_tolerance(Some(1)) + .with_trusted_initial_height(self.response.metadata().unwrap().height) + .build() + .expect("fresh unpinned SDK"); + assert!(!sdk.version_pinned); + assert_eq!( + sdk.protocol_version_number(), + if network == Network::Devnet { 14 } else { 13 } + ); + sdk + } + + async fn mock_sdk(&self, network: Network) -> Sdk { + let sdk = self.sdk(network, true); + let SdkInstance::Mock { dapi, .. } = &sdk.inner else { + panic!("mock transport"); + }; + dapi.lock() + .await + .expect( + &self.request, + &Ok(ExecutionResponse { + inner: self.response.clone(), + ..Default::default() + }), + ) + .expect("transport response only"); + sdk + } + + fn assert_history(&self, history: &DocumentHistory) { + let expected = if matches!(self.query().filter, DocumentHistoryFilter::Revision(_)) { + vec![2] + } else { + vec![2, 3] + }; + assert_eq!( + history + .entries + .iter() + .map(|entry| entry.revision) + .collect::>(), + expected + ); + for entry in &history.entries { + assert_eq!(entry.time_ms, 2000); + assert_eq!(entry.document.revision(), Some(entry.revision)); + assert_eq!(entry.document.id(), self.query().document_id); + } + let lifecycle = history.lifecycle.as_ref().expect("PV15 lifecycle proof"); + assert_eq!(lifecycle.state, DocumentHistoryState::Active); + assert_eq!(lifecycle.remaining_revisions, 3); + } +} + +#[tokio::test] +async fn should_surface_history_version_status_without_response_decoding_or_fallback() { + for message in [ + "unsupported version for query: document_history, currently supporting versions 0 to 0 on platform protocol 14, given 1", + "decoding error: could not decode document history query", + ] { + let fixture = Fixture::load(false); + let sdk = fixture.sdk(Network::Devnet, true); + let SdkInstance::Mock { dapi, .. } = &sdk.inner else { panic!("mock transport") }; + dapi.lock().await.expect(&fixture.request, &Err(ExecutionError { + inner: DapiClientError::Transport(TransportError::Grpc(Status::invalid_argument(message))), + address: None, retries: 0, + })).unwrap(); + let error = DocumentHistory::fetch(&sdk, fixture.query()).await.unwrap_err(); + assert!(matches!(error, crate::Error::DapiClientError(DapiClientError::Transport(TransportError::Grpc(status))) + if status.code() == Code::InvalidArgument && status.message() == message)); + assert_eq!(dapi.lock().await.request_count(&fixture.request), 1); + assert_eq!(sdk.protocol_version_number(), 14); + } +} + +struct Provider { + contract: Arc, + key: [u8; 48], +} + +impl ContextProvider for Provider { + fn get_data_contract( + &self, + id: &Identifier, + _: &PlatformVersion, + ) -> Result>, ContextProviderError> { + Ok((id == &self.contract.id()).then(|| self.contract.clone())) + } + fn get_token_configuration( + &self, + _: &Identifier, + ) -> Result, ContextProviderError> { + Ok(None) + } + fn get_quorum_public_key( + &self, + _: u32, + _: [u8; 32], + _: u32, + ) -> Result<[u8; 48], ContextProviderError> { + Ok(self.key) + } + fn get_platform_activation_height(&self) -> Result { + Ok(1) + } +} + +#[test_case(Network::Mainnet, false; "mainnet revision")] +#[test_case(Network::Mainnet, true; "mainnet cursor")] +#[test_case(Network::Testnet, false; "testnet revision")] +#[test_case(Network::Testnet, true; "testnet cursor")] +#[test_case(Network::Regtest, false; "regtest revision")] +#[test_case(Network::Regtest, true; "regtest cursor")] +#[test_case(Network::Devnet, false; "devnet revision")] +#[test_case(Network::Devnet, true; "devnet cursor")] +#[tokio::test] +async fn should_fetch_history_as_the_first_proved_read_from_an_unpinned_seed( + network: Network, + cursor: bool, +) { + let fixture = Fixture::load(cursor); + let sdk = fixture.mock_sdk(network).await; + let (history, metadata, _) = + DocumentHistory::fetch_with_metadata_and_proof(&sdk, fixture.query(), None) + .await + .expect("first history read must reach and verify PV15"); + fixture.assert_history(&history.unwrap()); + assert_eq!(metadata.protocol_version, 15); + assert_eq!(sdk.protocol_version_number(), 15); +} + +#[test_case(Network::Mainnet, false; "mainnet revision")] +#[test_case(Network::Mainnet, true; "mainnet cursor")] +#[test_case(Network::Testnet, false; "testnet revision")] +#[test_case(Network::Testnet, true; "testnet cursor")] +#[test_case(Network::Regtest, false; "regtest revision")] +#[test_case(Network::Regtest, true; "regtest cursor")] +#[test_case(Network::Devnet, false; "devnet revision")] +#[test_case(Network::Devnet, true; "devnet cursor")] +#[tokio::test] +async fn should_fetch_history_proof_info_as_the_first_proved_read_from_an_unpinned_seed( + network: Network, + cursor: bool, +) { + let fixture = Fixture::load(cursor); + let sdk = fixture.mock_sdk(network).await; + let info = DocumentHistoryProofInfo::fetch(&sdk, fixture.query()) + .await + .expect("first proof-info read must reach and verify PV15") + .unwrap(); + fixture.assert_history(&info.history); + assert_eq!( + GetDocumentHistoryResponse::from(info.response.clone()), + fixture.response + ); + assert_eq!(sdk.protocol_version_number(), 15); + assert_eq!( + info.verify( + fixture.request.clone(), + network, + sdk.version(), + &fixture.provider() + ) + .unwrap(), + Some(info.history) + ); +} + +#[test] +fn should_verify_signed_history_directly_from_older_client_versions() { + for cursor in [false, true] { + let fixture = Fixture::load(cursor); + for client in [1, 14] { + let version = PlatformVersion::get(client).unwrap(); + let history = DocumentHistory::maybe_from_proof( + fixture.request.clone(), + fixture.response.clone(), + Network::Testnet, + version, + &fixture.provider(), + ) + .expect("signed producer layout must verify for an older client") + .unwrap(); + fixture.assert_history(&history); + let info = DocumentHistoryProofInfo::maybe_from_proof( + fixture.request.clone(), + fixture.response.clone(), + Network::Testnet, + version, + &fixture.provider(), + ) + .expect("proof information must use the signed producer layout") + .unwrap(); + fixture.assert_history(&info.history); + } + } +} + +#[test] +fn should_verify_signed_v0_history_from_an_older_producer() { + let fixture: Fixture = serde_json::from_str(include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/tests/vectors/document_history/pv14_time.json" + ))) + .expect("signed timestamp-keyed history fixture"); + assert!(matches!( + fixture.request.version, + Some(RequestVersion::V0(_)) + )); + assert!(matches!( + fixture.response.version, + Some(ResponseVersion::V0(_)) + )); + assert_eq!(fixture.response.metadata().unwrap().protocol_version, 14); + let provider = fixture.provider(); + let history = DocumentHistory::maybe_from_proof( + fixture.request.clone(), + fixture.response.clone(), + Network::Testnet, + PlatformVersion::get(14).unwrap(), + &provider, + ) + .expect("the producer's own timestamp-keyed history rules verify") + .unwrap(); + assert_eq!(history.lifecycle, None); + assert_eq!( + history + .entries + .iter() + .map(|entry| (entry.time_ms, entry.revision)) + .collect::>(), + vec![(2000, 2), (3000, 3)] + ); + let verified = DocumentHistory::maybe_from_proof( + fixture.request, + fixture.response, + Network::Testnet, + PlatformVersion::latest(), + &provider, + ) + .expect("a newer client selects the signed producer's v0 history rules") + .unwrap(); + assert_eq!(verified, history); +} + +#[test_case(false; "revision page")] +#[test_case(true; "cursor page")] +fn should_reject_history_protocol_version_tampering(cursor: bool) { + let fixture = Fixture::load(cursor); + let provider = fixture.provider(); + let version = PlatformVersion::latest(); + let history = DocumentHistory::maybe_from_proof( + fixture.request.clone(), + fixture.response.clone(), + Network::Testnet, + version, + &provider, + ) + .expect("the original signed history response verifies") + .unwrap(); + fixture.assert_history(&history); + + for claimed in [version.protocol_version + 1, 14, 0] { + let mut forged = fixture.response.clone(); + let Some(ResponseVersion::V1(response)) = &mut forged.version else { + panic!("versioned history response"); + }; + response.metadata.as_mut().unwrap().protocol_version = claimed; + for (kind, result) in [ + ( + "history", + DocumentHistory::maybe_from_proof( + fixture.request.clone(), + forged.clone(), + Network::Testnet, + version, + &provider, + ) + .map(|_| ()), + ), + ( + "proof information", + DocumentHistoryProofInfo::maybe_from_proof( + fixture.request.clone(), + forged.clone(), + Network::Testnet, + version, + &provider, + ) + .map(|_| ()), + ), + ] { + let error = result.expect_err(&format!( + "{kind} must reject a history response relabeled as protocol {claimed}" + )); + if claimed == 0 { + assert!( + matches!( + &error, + drive_proof_verifier::Error::ResponseDecodeError { error } + if error.contains("unsupported proof query protocol version 0") + ), + "{kind}: {error}" + ); + } else if claimed == 14 { + assert!( + matches!( + &error, + drive_proof_verifier::Error::DriveError { error } + if error == "drive: drive unknown version on verify_document_history, received: 0" + ), + "{kind}: {error}" + ); + } else if claimed == version.protocol_version + 1 { + assert!( + matches!(error, drive_proof_verifier::Error::InvalidSignature { .. }), + "{kind}: {error}" + ); + } + } + } +} + +#[test_case(false; "network parser")] +#[test_case(true; "mock parser")] +#[tokio::test] +async fn should_select_signed_history_rules_before_ratchet_and_reject_forged_metadata(mock: bool) { + let fixture = Fixture::load(true); + let sdk = fixture.sdk(Network::Devnet, mock); + let direct = DocumentHistory::maybe_from_proof( + fixture.request.clone(), + fixture.response.clone(), + Network::Devnet, + sdk.version(), + &fixture.provider(), + ) + .expect("direct verification selects the signed history layout") + .unwrap(); + fixture.assert_history(&direct); + let mut forged = fixture.response.clone(); + let Some(ResponseVersion::V1(response)) = &mut forged.version else { + panic!("versioned response"); + }; + response.metadata.as_mut().unwrap().time_ms += 1; + assert!(sdk + .parse_proof_with_metadata_and_proof::( + fixture.request.clone(), + forged, + "get_document_history" + ) + .await + .is_err()); + assert_eq!(sdk.protocol_version_number(), 14); + let (history, metadata, _) = sdk + .parse_proof_with_metadata_and_proof::( + fixture.request.clone(), + fixture.response.clone(), + "get_document_history", + ) + .await + .expect("signed history selects PV15 before the ratchet"); + fixture.assert_history(&history.unwrap().history); + assert_eq!(metadata.protocol_version, 15); + assert_eq!(sdk.protocol_version_number(), 15); +} diff --git a/packages/rs-sdk/tests/proof_options.rs b/packages/rs-sdk/tests/proof_options.rs index 1c26470d769..6cefe4cc973 100644 --- a/packages/rs-sdk/tests/proof_options.rs +++ b/packages/rs-sdk/tests/proof_options.rs @@ -21,6 +21,7 @@ use dpp::data_contract::DataContractFactory; use dpp::platform_value::platform_value; use dpp::version::PlatformVersion; use dpp::voting::vote_polls::contested_document_resource_vote_poll::ContestedDocumentResourceVotePoll; +use drive::query::document_history_drive_query::DocumentHistoryFilter; use drive::query::{ contested_resource_votes_given_by_identity_query::ContestedResourceVotesGivenByIdentityQuery, vote_poll_contestant_votes_query::ContestedDocumentVotePollVotesDriveQuery, @@ -170,17 +171,16 @@ proof_only!( data_contract_id: id(), document_type_name: "domain".into(), document_id: other_id(), - start_at_ms: 123, - limit: Some(2), - offset: None + filter: DocumentHistoryFilter::StartAtTime(123), + limit: Some(2) }, proto::GetDocumentHistoryRequest, |request: proto::GetDocumentHistoryRequest| { - let Some(proto::get_document_history_request::Version::V0(v0)) = request.version else { - panic!("expected V0 request") + let Some(proto::get_document_history_request::Version::V1(v1)) = request.version else { + panic!("expected V1 request") }; - assert!(v0.prove); - assert_eq!(v0.document_id, other_id().to_vec()); + assert!(v1.prove); + assert_eq!(v1.document_id, other_id().to_vec()); } ); diff --git a/packages/rs-sdk/tests/vectors/document_history/README.md b/packages/rs-sdk/tests/vectors/document_history/README.md new file mode 100644 index 00000000000..60f94a7b3c7 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/document_history/README.md @@ -0,0 +1,23 @@ +# Signed document-history responses + +These synthetic PV15 fixtures come from the ABCI test +`query::document_history::v1::tests::should_round_trip_history_api_through_quorum_and_grove_proof_verification`. +They contain one GroveDB proof of history and lifecycle per response, and +Tenderdash signatures, +using that harness's public test key (`SecretKey::from_be_bytes(&[1; 32])`). They +are offline test data, not responses recorded from a live network. + +The harness writes three profile revisions at time 2000. The revision fixture +selects revision 2; the cursor fixture selects revisions 2 and 3 after `(2000, 1)`. +Both include the serialized contract and quorum public key so SDK tests need no +prior contract fetch or protocol-version refresh. Requests and responses use the +generated gRPC version 1 serde representation. The SDK mocks only the transport; +the GroveDB proof and quorum signature are verified normally. Regenerate with the +ABCI test and `UPDATE_DOCUMENT_HISTORY_VECTORS=1`. + +The PV14 `pv14_time.json` fixture comes from +`query::document_history::v1::tests::should_verify_signed_legacy_history_from_protocol_14_with_protocol_15_client`. +It stores revisions at times 1000, 2000 and 3000, then selects the latter two +through the released V0 wire request. Its signed producer version selects the +legacy timestamp history layout even when a PV15 client verifies it. Regenerate +it with that ABCI test and `UPDATE_DOCUMENT_HISTORY_VECTORS=1`. diff --git a/packages/rs-sdk/tests/vectors/document_history/pv14_time.json b/packages/rs-sdk/tests/vectors/document_history/pv14_time.json new file mode 100644 index 00000000000..4cfd1d3504f --- /dev/null +++ b/packages/rs-sdk/tests/vectors/document_history/pv14_time.json @@ -0,0 +1 @@ +{"contract":"018ed417b99e5ec5c4d6ce738972e0d95f1bdf21aa10caae9bf7ed2def4011589f000000000001010000018ed417b99e5ec5c4d6ce738972e0d95f1bdf21aa10caae9bf7ed2def4011589f00030b636f6e74616374496e666f16041207696e646963657315021602120a70726f70657274696573150316011208246f776e65724964120361736316011216726f6f74456e6372797074696f6e4b6579496e64657812036173631601121c64657269766174696f6e456e6372797074696f6e4b6579496e64657812036173631206756e6971756513011601120a70726f70657274696573150216011208246f776e6572496412036173631601120a247570646174656441741203617363120a70726f706572746965731604120b656e63546f5573657249641605120474797065120561727261791209627974654172726179130112086d696e4974656d73022012086d61784974656d7302201208706f736974696f6e02001216726f6f74456e6372797074696f6e4b6579496e64657816021204747970651207696e74656765721208706f736974696f6e0201121c64657269766174696f6e456e6372797074696f6e4b6579496e64657816021204747970651207696e74656765721208706f736974696f6e0202120b70726976617465446174611606120474797065120561727261791209627974654172726179130112086d696e4974656d73023012086d61784974656d7302fb08001208706f736974696f6e0203120b6465736372697074696f6e125c546869732069732074686520656e637279707465642076616c756573206f6620616c6961734e616d65202b206e6f7465202b20646973706c617948696464656e20656e636f64656420617320616e20617272617920696e2063626f72120872657175697265641506120a24637265617465644174120a24757064617465644174120b656e63546f557365724964120b70726976617465446174611216726f6f74456e6372797074696f6e4b6579496e646578121c64657269766174696f6e456e6372797074696f6e4b6579496e64657812146164646974696f6e616c50726f7065727469657313000e636f6e746163745265717565737416051210646f63756d656e74734d757461626c6513001207696e646963657315041602120a70726f70657274696573150316011208246f776e65724964120361736316011208746f5573657249641203617363160112106163636f756e745265666572656e636512036173631206756e6971756513011601120a70726f70657274696573150216011208246f776e65724964120361736316011208746f55736572496412036173631601120a70726f70657274696573150216011208746f55736572496412036173631601120a2463726561746564417412036173631601120a70726f70657274696573150216011208246f776e6572496412036173631601120a246372656174656441741203617363120a70726f7065727469657316061208746f5573657249641605120474797065120561727261791209627974654172726179130112086d696e4974656d73022012086d61784974656d7302201208706f736974696f6e02001212656e637279707465645075626c69634b65791605120474797065120561727261791209627974654172726179130112086d696e4974656d73026012086d61784974656d7302601208706f736974696f6e0201120e73656e6465724b6579496e64657816021204747970651207696e74656765721208706f736974696f6e02021211726563697069656e744b6579496e64657816021204747970651207696e74656765721208706f736974696f6e020312106163636f756e745265666572656e636516021204747970651207696e74656765721208706f736974696f6e02041215656e637279707465644163636f756e744c6162656c1605120474797065120561727261791209627974654172726179130112086d696e4974656d73023012086d61784974656d7302501208706f736974696f6e0205120872657175697265641506120a246372656174656441741208746f5573657249641212656e637279707465645075626c69634b6579120e73656e6465724b6579496e6465781211726563697069656e744b6579496e64657812106163636f756e745265666572656e636512146164646974696f6e616c50726f7065727469657313000770726f66696c65160612047479706512066f626a6563741214646f63756d656e74734b656570486973746f727913011207696e646963657315021602120a70726f70657274696573150116011208246f776e6572496412036173631206756e6971756513011601120a70726f70657274696573150216011208246f776e6572496412036173631601120a247570646174656441741203617363120a70726f706572746965731603120961766174617255726c16041204747970651206737472696e671206666f726d6174120375726912096d61784c656e67746802fb08001208706f736974696f6e0200120d7075626c69634d65737361676516031204747970651206737472696e6712096d61784c656e677468028c1208706f736974696f6e0201120b646973706c61794e616d6516031204747970651206737472696e6712096d61784c656e67746802191208706f736974696f6e0202120872657175697265641502120a24637265617465644174120a2475706461746564417412146164646974696f6e616c50726f70657274696573130000000000000000000000","quorum_public_key":"aa1a1c26055a329817a5759d877a2795f9499b97d6056edde0eea39512f24e8bc874b4471f0501127abb1ea0d9f68ac1","request":{"version":{"v0":{"data_contract_id":[142,212,23,185,158,94,197,196,214,206,115,137,114,224,217,95,27,223,33,170,16,202,174,155,247,237,45,239,64,17,88,159],"document_type_name":"profile","document_id":[138,220,83,139,202,31,216,109,249,241,253,21,57,139,254,249,56,114,184,161,107,65,92,73,87,219,251,179,142,249,191,163],"limit":2,"offset":null,"start_at_ms":"1000","prove":true}}},"response":{"version":{"v0":{"metadata":{"height":"42","core_chain_locked_height":12,"epoch":0,"time_ms":"4000","protocol_version":14,"chain_id":"chain_id"},"result":{"proof":{"grovedb_proof":[1,0,141,1,49,146,97,127,238,234,107,217,241,108,8,228,177,228,92,41,96,160,149,95,28,102,38,49,103,58,25,32,46,143,43,167,4,1,64,0,36,2,1,32,142,212,23,185,158,94,197,196,214,206,115,137,114,224,217,95,27,223,33,170,16,202,174,155,247,237,45,239,64,17,88,159,0,89,207,56,77,165,29,141,18,63,99,107,162,228,64,179,191,188,214,206,38,189,126,110,0,145,209,75,221,252,146,114,189,16,1,65,11,54,28,170,140,106,5,196,210,156,48,221,67,168,130,27,15,40,97,25,18,23,142,101,69,114,13,248,252,246,198,17,1,1,64,0,73,4,32,142,212,23,185,158,94,197,196,214,206,115,137,114,224,217,95,27,223,33,170,16,202,174,155,247,237,45,239,64,17,88,159,0,5,2,1,1,1,0,126,177,25,230,75,99,154,6,175,250,140,17,160,30,191,192,106,227,121,3,180,23,6,201,80,1,246,192,13,86,147,11,1,32,142,212,23,185,158,94,197,196,214,206,115,137,114,224,217,95,27,223,33,170,16,202,174,155,247,237,45,239,64,17,88,159,0,123,1,9,104,234,61,57,231,48,137,38,196,46,86,154,31,114,249,39,38,153,228,67,25,168,241,110,92,3,5,89,196,152,41,4,1,1,0,18,2,1,14,99,111,110,116,97,99,116,82,101,113,117,101,115,116,0,46,198,108,152,156,150,143,75,122,58,45,39,214,45,237,232,91,156,64,240,196,121,202,141,120,127,36,202,81,28,3,216,16,1,18,15,217,179,148,167,159,175,170,235,240,180,37,144,135,96,249,154,115,198,172,249,183,215,181,194,159,229,217,91,154,35,17,1,1,1,0,123,1,236,153,75,254,53,124,209,144,57,74,187,230,144,45,193,224,47,6,239,95,24,218,35,211,15,153,133,132,168,202,47,129,2,75,109,191,116,194,156,206,220,32,149,149,230,69,25,217,62,255,222,37,141,217,143,251,117,242,78,34,16,98,224,207,15,16,4,7,112,114,111,102,105,108,101,0,12,2,1,8,36,111,119,110,101,114,73,100,0,100,129,175,241,78,254,57,178,175,163,21,124,238,70,48,191,38,19,50,174,87,2,222,53,28,245,60,183,82,70,166,87,17,1,7,112,114,111,102,105,108,101,0,107,4,1,0,0,36,2,1,32,138,220,83,139,202,31,216,109,249,241,253,21,57,139,254,249,56,114,184,161,107,65,92,73,87,219,251,179,142,249,191,163,0,229,40,203,189,239,99,39,75,240,131,98,42,172,250,187,202,255,109,221,239,153,5,75,179,161,37,252,155,8,169,230,139,2,133,215,207,116,156,131,79,215,48,79,228,158,227,104,51,224,4,39,244,91,223,169,120,131,60,70,211,117,79,118,144,154,16,1,1,0,0,80,4,32,138,220,83,139,202,31,216,109,249,241,253,21,57,139,254,249,56,114,184,161,107,65,92,73,87,219,251,179,142,249,191,163,0,12,2,1,8,128,0,0,0,0,0,3,232,0,21,131,2,151,201,88,150,91,84,201,249,161,93,47,87,120,196,243,112,1,135,112,45,95,85,202,61,172,128,188,183,241,1,32,138,220,83,139,202,31,216,109,249,241,253,21,57,139,254,249,56,114,184,161,107,65,92,73,87,219,251,179,142,249,191,163,0,251,1,156,1,141,130,175,170,96,240,199,161,73,95,243,224,161,2,183,110,236,205,206,71,162,44,96,148,163,205,116,76,119,145,64,152,5,8,128,0,0,0,0,0,3,232,118,127,29,72,38,24,172,23,107,80,189,156,37,24,165,126,247,235,251,139,152,100,184,194,253,142,79,130,218,118,0,72,16,3,8,128,0,0,0,0,0,7,208,0,155,0,152,0,138,220,83,139,202,31,216,109,249,241,253,21,57,139,254,249,56,114,184,161,107,65,92,73,87,219,251,179,142,249,191,163,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,2,0,3,0,0,1,115,164,225,142,56,0,0,1,115,164,225,142,56,1,23,112,108,97,99,101,107,105,116,116,101,110,46,99,111,109,47,50,48,48,47,51,48,48,1,36,116,111,100,97,121,32,105,115,32,97,32,103,111,111,100,32,100,97,121,32,116,111,32,103,111,32,116,111,32,116,104,101,32,122,111,111,1,3,115,97,109,0,3,8,128,0,0,0,0,0,11,184,0,155,0,152,0,138,220,83,139,202,31,216,109,249,241,253,21,57,139,254,249,56,114,184,161,107,65,92,73,87,219,251,179,142,249,191,163,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,3,0,3,0,0,1,115,164,225,142,56,0,0,1,115,164,225,142,56,1,23,112,108,97,99,101,107,105,116,116,101,110,46,99,111,109,47,50,48,48,47,51,48,48,1,36,116,111,100,97,121,32,105,115,32,97,32,103,111,111,100,32,100,97,121,32,116,111,32,103,111,32,116,111,32,116,104,101,32,122,111,111,1,3,115,97,109,0,17,17,0],"quorum_hash":[9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9],"signature":[134,12,10,235,113,63,124,57,119,179,222,25,232,252,50,86,4,130,56,169,130,181,230,43,189,82,185,184,227,76,39,100,163,59,150,125,18,165,166,254,237,51,37,33,3,7,108,134,1,92,133,216,242,150,92,34,46,214,180,185,116,11,60,22,59,249,98,173,3,67,137,37,226,183,203,207,153,222,60,125,172,247,118,81,143,187,150,213,184,17,21,210,54,137,152,58],"round":0,"block_id_hash":[7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7],"quorum_type":6}}}}}} diff --git a/packages/rs-sdk/tests/vectors/document_history/pv15_cursor.json b/packages/rs-sdk/tests/vectors/document_history/pv15_cursor.json new file mode 100644 index 00000000000..7ba7d359e6b --- /dev/null +++ b/packages/rs-sdk/tests/vectors/document_history/pv15_cursor.json @@ -0,0 +1 @@ +{"contract":"018ed417b99e5ec5c4d6ce738972e0d95f1bdf21aa10caae9bf7ed2def4011589f000000000001010000018ed417b99e5ec5c4d6ce738972e0d95f1bdf21aa10caae9bf7ed2def4011589f00030b636f6e74616374496e666f16041207696e646963657315021602120a70726f70657274696573150316011208246f776e65724964120361736316011216726f6f74456e6372797074696f6e4b6579496e64657812036173631601121c64657269766174696f6e456e6372797074696f6e4b6579496e64657812036173631206756e6971756513011601120a70726f70657274696573150216011208246f776e6572496412036173631601120a247570646174656441741203617363120a70726f706572746965731604120b656e63546f5573657249641605120474797065120561727261791209627974654172726179130112086d696e4974656d73022012086d61784974656d7302201208706f736974696f6e02001216726f6f74456e6372797074696f6e4b6579496e64657816021204747970651207696e74656765721208706f736974696f6e0201121c64657269766174696f6e456e6372797074696f6e4b6579496e64657816021204747970651207696e74656765721208706f736974696f6e0202120b70726976617465446174611606120474797065120561727261791209627974654172726179130112086d696e4974656d73023012086d61784974656d7302fb08001208706f736974696f6e0203120b6465736372697074696f6e125c546869732069732074686520656e637279707465642076616c756573206f6620616c6961734e616d65202b206e6f7465202b20646973706c617948696464656e20656e636f64656420617320616e20617272617920696e2063626f72120872657175697265641506120a24637265617465644174120a24757064617465644174120b656e63546f557365724964120b70726976617465446174611216726f6f74456e6372797074696f6e4b6579496e646578121c64657269766174696f6e456e6372797074696f6e4b6579496e64657812146164646974696f6e616c50726f7065727469657313000e636f6e746163745265717565737416051210646f63756d656e74734d757461626c6513001207696e646963657315041602120a70726f70657274696573150316011208246f776e65724964120361736316011208746f5573657249641203617363160112106163636f756e745265666572656e636512036173631206756e6971756513011601120a70726f70657274696573150216011208246f776e65724964120361736316011208746f55736572496412036173631601120a70726f70657274696573150216011208746f55736572496412036173631601120a2463726561746564417412036173631601120a70726f70657274696573150216011208246f776e6572496412036173631601120a246372656174656441741203617363120a70726f7065727469657316061208746f5573657249641605120474797065120561727261791209627974654172726179130112086d696e4974656d73022012086d61784974656d7302201208706f736974696f6e02001212656e637279707465645075626c69634b65791605120474797065120561727261791209627974654172726179130112086d696e4974656d73026012086d61784974656d7302601208706f736974696f6e0201120e73656e6465724b6579496e64657816021204747970651207696e74656765721208706f736974696f6e02021211726563697069656e744b6579496e64657816021204747970651207696e74656765721208706f736974696f6e020312106163636f756e745265666572656e636516021204747970651207696e74656765721208706f736974696f6e02041215656e637279707465644163636f756e744c6162656c1605120474797065120561727261791209627974654172726179130112086d696e4974656d73023012086d61784974656d7302501208706f736974696f6e0205120872657175697265641506120a246372656174656441741208746f5573657249641212656e637279707465645075626c69634b6579120e73656e6465724b6579496e6465781211726563697069656e744b6579496e64657812106163636f756e745265666572656e636512146164646974696f6e616c50726f7065727469657313000770726f66696c65160612047479706512066f626a6563741214646f63756d656e74734b656570486973746f727913011207696e646963657315021602120a70726f70657274696573150116011208246f776e6572496412036173631206756e6971756513011601120a70726f70657274696573150216011208246f776e6572496412036173631601120a247570646174656441741203617363120a70726f706572746965731603120961766174617255726c16041204747970651206737472696e671206666f726d6174120375726912096d61784c656e67746802fb08001208706f736974696f6e0200120d7075626c69634d65737361676516031204747970651206737472696e6712096d61784c656e677468028c1208706f736974696f6e0201120b646973706c61794e616d6516031204747970651206737472696e6712096d61784c656e67746802191208706f736974696f6e0202120872657175697265641502120a24637265617465644174120a2475706461746564417412146164646974696f6e616c50726f70657274696573130000000000000000000000","quorum_public_key":"aa1a1c26055a329817a5759d877a2795f9499b97d6056edde0eea39512f24e8bc874b4471f0501127abb1ea0d9f68ac1","request":{"version":{"v1":{"data_contract_id":[142,212,23,185,158,94,197,196,214,206,115,137,114,224,217,95,27,223,33,170,16,202,174,155,247,237,45,239,64,17,88,159],"document_type_name":"profile","document_id":[138,220,83,139,202,31,216,109,249,241,253,21,57,139,254,249,56,114,184,161,107,65,92,73,87,219,251,179,142,249,191,163],"limit":null,"prove":true,"filter":{"start_after":{"time_ms":2000,"revision":1}}}}},"response":{"version":{"v1":{"metadata":{"height":"42","core_chain_locked_height":12,"epoch":0,"time_ms":"3000","protocol_version":15,"chain_id":"chain_id"},"result":{"proof":{"grovedb_proof":[1,0,141,1,5,16,166,18,93,200,219,234,59,238,198,117,163,183,32,198,136,128,143,47,58,152,178,240,28,137,12,1,72,91,88,182,4,1,64,0,36,2,1,32,142,212,23,185,158,94,197,196,214,206,115,137,114,224,217,95,27,223,33,170,16,202,174,155,247,237,45,239,64,17,88,159,0,117,232,142,52,4,144,51,26,164,32,44,97,48,161,65,86,101,141,96,111,168,62,60,21,155,207,35,53,72,203,58,111,16,1,65,11,54,28,170,140,106,5,196,210,156,48,221,67,168,130,27,15,40,97,25,18,23,142,101,69,114,13,248,252,246,198,17,1,1,64,0,73,4,32,142,212,23,185,158,94,197,196,214,206,115,137,114,224,217,95,27,223,33,170,16,202,174,155,247,237,45,239,64,17,88,159,0,5,2,1,1,1,0,156,208,192,34,194,43,243,44,187,113,218,68,243,219,0,43,9,211,67,172,9,61,243,91,124,32,125,67,179,154,185,177,1,32,142,212,23,185,158,94,197,196,214,206,115,137,114,224,217,95,27,223,33,170,16,202,174,155,247,237,45,239,64,17,88,159,0,123,1,9,104,234,61,57,231,48,137,38,196,46,86,154,31,114,249,39,38,153,228,67,25,168,241,110,92,3,5,89,196,152,41,4,1,1,0,18,2,1,14,99,111,110,116,97,99,116,82,101,113,117,101,115,116,0,220,34,166,200,18,32,129,208,251,78,10,130,43,80,143,187,70,51,80,203,233,88,239,0,188,163,87,1,254,100,90,20,16,1,18,15,217,179,148,167,159,175,170,235,240,180,37,144,135,96,249,154,115,198,172,249,183,215,181,194,159,229,217,91,154,35,17,1,1,1,0,116,1,236,153,75,254,53,124,209,144,57,74,187,230,144,45,193,224,47,6,239,95,24,218,35,211,15,153,133,132,168,202,47,129,2,75,109,191,116,194,156,206,220,32,149,149,230,69,25,217,62,255,222,37,141,217,143,251,117,242,78,34,16,98,224,207,15,16,4,7,112,114,111,102,105,108,101,0,5,2,1,1,2,0,5,205,195,135,151,178,8,119,211,117,230,18,83,50,89,19,183,127,57,203,228,164,230,92,122,59,197,253,145,155,235,135,17,1,7,112,114,111,102,105,108,101,0,181,4,1,0,0,36,2,1,32,138,220,83,139,202,31,216,109,249,241,253,21,57,139,254,249,56,114,184,161,107,65,92,73,87,219,251,179,142,249,191,163,0,179,129,41,192,46,100,108,87,4,146,18,160,142,213,140,123,193,64,147,245,231,97,152,170,175,221,177,65,70,57,128,37,4,1,2,0,36,2,1,32,138,220,83,139,202,31,216,109,249,241,253,21,57,139,254,249,56,114,184,161,107,65,92,73,87,219,251,179,142,249,191,163,0,190,169,14,99,77,52,152,248,143,51,91,34,250,76,163,150,118,226,63,152,50,209,134,11,76,236,235,251,211,31,226,250,16,1,42,38,5,120,239,0,1,185,15,15,59,125,160,203,184,123,37,48,249,1,233,129,255,131,58,233,101,69,162,201,84,58,17,2,1,0,0,223,6,32,138,220,83,139,202,31,216,109,249,241,253,21,57,139,254,249,56,114,184,161,107,65,92,73,87,219,251,179,142,249,191,163,0,155,0,152,0,138,220,83,139,202,31,216,109,249,241,253,21,57,139,254,249,56,114,184,161,107,65,92,73,87,219,251,179,142,249,191,163,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,3,0,3,0,0,1,115,164,225,142,56,0,0,1,115,164,225,142,56,1,23,112,108,97,99,101,107,105,116,116,101,110,46,99,111,109,47,50,48,48,47,51,48,48,1,36,116,111,100,97,121,32,105,115,32,97,32,103,111,111,100,32,100,97,121,32,116,111,32,103,111,32,116,111,32,116,104,101,32,122,111,111,1,3,115,97,109,0,174,50,197,64,108,157,99,117,18,220,157,141,238,114,224,173,173,206,49,36,100,77,80,246,150,59,8,94,156,206,29,158,0,1,2,0,89,4,32,138,220,83,139,202,31,216,109,249,241,253,21,57,139,254,249,56,114,184,161,107,65,92,73,87,219,251,179,142,249,191,163,0,21,8,1,16,128,0,0,0,0,0,7,208,128,0,0,0,0,0,0,2,3,0,57,238,163,93,59,60,129,200,104,210,142,152,142,247,67,138,252,158,60,215,28,252,182,50,207,201,65,224,131,93,110,42,1,32,138,220,83,139,202,31,216,109,249,241,253,21,57,139,254,249,56,114,184,161,107,65,92,73,87,219,251,179,142,249,191,163,0,251,1,170,26,16,128,0,0,0,0,0,7,208,128,0,0,0,0,0,0,1,118,127,29,72,38,24,172,23,107,80,189,156,37,24,165,126,247,235,251,139,152,100,184,194,253,142,79,130,218,118,0,72,0,0,0,0,0,0,0,1,20,16,128,0,0,0,0,0,7,208,128,0,0,0,0,0,0,2,0,155,0,152,0,138,220,83,139,202,31,216,109,249,241,253,21,57,139,254,249,56,114,184,161,107,65,92,73,87,219,251,179,142,249,191,163,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,2,0,3,0,0,1,115,164,225,142,56,0,0,1,115,164,225,142,56,1,23,112,108,97,99,101,107,105,116,116,101,110,46,99,111,109,47,50,48,48,47,51,48,48,1,36,116,111,100,97,121,32,105,115,32,97,32,103,111,111,100,32,100,97,121,32,116,111,32,103,111,32,116,111,32,116,104,101,32,122,111,111,1,3,115,97,109,0,0,0,0,0,0,0,0,3,16,20,16,128,0,0,0,0,0,7,208,128,0,0,0,0,0,0,3,0,155,0,152,0,138,220,83,139,202,31,216,109,249,241,253,21,57,139,254,249,56,114,184,161,107,65,92,73,87,219,251,179,142,249,191,163,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,3,0,3,0,0,1,115,164,225,142,56,0,0,1,115,164,225,142,56,1,23,112,108,97,99,101,107,105,116,116,101,110,46,99,111,109,47,50,48,48,47,51,48,48,1,36,116,111,100,97,121,32,105,115,32,97,32,103,111,111,100,32,100,97,121,32,116,111,32,103,111,32,116,111,32,116,104,101,32,122,111,111,1,3,115,97,109,0,0,0,0,0,0,0,0,1,17,0],"quorum_hash":[9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9],"signature":[143,157,107,184,224,215,225,0,188,239,58,11,108,159,166,116,33,194,212,190,247,249,46,13,142,33,145,226,112,215,55,66,190,23,146,119,217,106,206,110,185,98,92,52,177,188,174,102,18,205,78,42,80,163,40,60,228,56,236,143,88,4,65,82,205,45,174,252,184,55,63,147,107,136,77,40,112,155,104,36,213,55,194,178,106,1,3,58,172,55,226,132,68,254,39,70],"round":0,"block_id_hash":[7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7],"quorum_type":6}}}}}} diff --git a/packages/rs-sdk/tests/vectors/document_history/pv15_revision.json b/packages/rs-sdk/tests/vectors/document_history/pv15_revision.json new file mode 100644 index 00000000000..d1cc51cb6f3 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/document_history/pv15_revision.json @@ -0,0 +1 @@ +{"contract":"018ed417b99e5ec5c4d6ce738972e0d95f1bdf21aa10caae9bf7ed2def4011589f000000000001010000018ed417b99e5ec5c4d6ce738972e0d95f1bdf21aa10caae9bf7ed2def4011589f00030b636f6e74616374496e666f16041207696e646963657315021602120a70726f70657274696573150316011208246f776e65724964120361736316011216726f6f74456e6372797074696f6e4b6579496e64657812036173631601121c64657269766174696f6e456e6372797074696f6e4b6579496e64657812036173631206756e6971756513011601120a70726f70657274696573150216011208246f776e6572496412036173631601120a247570646174656441741203617363120a70726f706572746965731604120b656e63546f5573657249641605120474797065120561727261791209627974654172726179130112086d696e4974656d73022012086d61784974656d7302201208706f736974696f6e02001216726f6f74456e6372797074696f6e4b6579496e64657816021204747970651207696e74656765721208706f736974696f6e0201121c64657269766174696f6e456e6372797074696f6e4b6579496e64657816021204747970651207696e74656765721208706f736974696f6e0202120b70726976617465446174611606120474797065120561727261791209627974654172726179130112086d696e4974656d73023012086d61784974656d7302fb08001208706f736974696f6e0203120b6465736372697074696f6e125c546869732069732074686520656e637279707465642076616c756573206f6620616c6961734e616d65202b206e6f7465202b20646973706c617948696464656e20656e636f64656420617320616e20617272617920696e2063626f72120872657175697265641506120a24637265617465644174120a24757064617465644174120b656e63546f557365724964120b70726976617465446174611216726f6f74456e6372797074696f6e4b6579496e646578121c64657269766174696f6e456e6372797074696f6e4b6579496e64657812146164646974696f6e616c50726f7065727469657313000e636f6e746163745265717565737416051210646f63756d656e74734d757461626c6513001207696e646963657315041602120a70726f70657274696573150316011208246f776e65724964120361736316011208746f5573657249641203617363160112106163636f756e745265666572656e636512036173631206756e6971756513011601120a70726f70657274696573150216011208246f776e65724964120361736316011208746f55736572496412036173631601120a70726f70657274696573150216011208746f55736572496412036173631601120a2463726561746564417412036173631601120a70726f70657274696573150216011208246f776e6572496412036173631601120a246372656174656441741203617363120a70726f7065727469657316061208746f5573657249641605120474797065120561727261791209627974654172726179130112086d696e4974656d73022012086d61784974656d7302201208706f736974696f6e02001212656e637279707465645075626c69634b65791605120474797065120561727261791209627974654172726179130112086d696e4974656d73026012086d61784974656d7302601208706f736974696f6e0201120e73656e6465724b6579496e64657816021204747970651207696e74656765721208706f736974696f6e02021211726563697069656e744b6579496e64657816021204747970651207696e74656765721208706f736974696f6e020312106163636f756e745265666572656e636516021204747970651207696e74656765721208706f736974696f6e02041215656e637279707465644163636f756e744c6162656c1605120474797065120561727261791209627974654172726179130112086d696e4974656d73023012086d61784974656d7302501208706f736974696f6e0205120872657175697265641506120a246372656174656441741208746f5573657249641212656e637279707465645075626c69634b6579120e73656e6465724b6579496e6465781211726563697069656e744b6579496e64657812106163636f756e745265666572656e636512146164646974696f6e616c50726f7065727469657313000770726f66696c65160612047479706512066f626a6563741214646f63756d656e74734b656570486973746f727913011207696e646963657315021602120a70726f70657274696573150116011208246f776e6572496412036173631206756e6971756513011601120a70726f70657274696573150216011208246f776e6572496412036173631601120a247570646174656441741203617363120a70726f706572746965731603120961766174617255726c16041204747970651206737472696e671206666f726d6174120375726912096d61784c656e67746802fb08001208706f736974696f6e0200120d7075626c69634d65737361676516031204747970651206737472696e6712096d61784c656e677468028c1208706f736974696f6e0201120b646973706c61794e616d6516031204747970651206737472696e6712096d61784c656e67746802191208706f736974696f6e0202120872657175697265641502120a24637265617465644174120a2475706461746564417412146164646974696f6e616c50726f70657274696573130000000000000000000000","quorum_public_key":"aa1a1c26055a329817a5759d877a2795f9499b97d6056edde0eea39512f24e8bc874b4471f0501127abb1ea0d9f68ac1","request":{"version":{"v1":{"data_contract_id":[142,212,23,185,158,94,197,196,214,206,115,137,114,224,217,95,27,223,33,170,16,202,174,155,247,237,45,239,64,17,88,159],"document_type_name":"profile","document_id":[138,220,83,139,202,31,216,109,249,241,253,21,57,139,254,249,56,114,184,161,107,65,92,73,87,219,251,179,142,249,191,163],"limit":null,"prove":true,"filter":{"revision":2}}}},"response":{"version":{"v1":{"metadata":{"height":"42","core_chain_locked_height":12,"epoch":0,"time_ms":"3000","protocol_version":15,"chain_id":"chain_id"},"result":{"proof":{"grovedb_proof":[1,0,141,1,5,16,166,18,93,200,219,234,59,238,198,117,163,183,32,198,136,128,143,47,58,152,178,240,28,137,12,1,72,91,88,182,4,1,64,0,36,2,1,32,142,212,23,185,158,94,197,196,214,206,115,137,114,224,217,95,27,223,33,170,16,202,174,155,247,237,45,239,64,17,88,159,0,117,232,142,52,4,144,51,26,164,32,44,97,48,161,65,86,101,141,96,111,168,62,60,21,155,207,35,53,72,203,58,111,16,1,65,11,54,28,170,140,106,5,196,210,156,48,221,67,168,130,27,15,40,97,25,18,23,142,101,69,114,13,248,252,246,198,17,1,1,64,0,73,4,32,142,212,23,185,158,94,197,196,214,206,115,137,114,224,217,95,27,223,33,170,16,202,174,155,247,237,45,239,64,17,88,159,0,5,2,1,1,1,0,156,208,192,34,194,43,243,44,187,113,218,68,243,219,0,43,9,211,67,172,9,61,243,91,124,32,125,67,179,154,185,177,1,32,142,212,23,185,158,94,197,196,214,206,115,137,114,224,217,95,27,223,33,170,16,202,174,155,247,237,45,239,64,17,88,159,0,123,1,9,104,234,61,57,231,48,137,38,196,46,86,154,31,114,249,39,38,153,228,67,25,168,241,110,92,3,5,89,196,152,41,4,1,1,0,18,2,1,14,99,111,110,116,97,99,116,82,101,113,117,101,115,116,0,220,34,166,200,18,32,129,208,251,78,10,130,43,80,143,187,70,51,80,203,233,88,239,0,188,163,87,1,254,100,90,20,16,1,18,15,217,179,148,167,159,175,170,235,240,180,37,144,135,96,249,154,115,198,172,249,183,215,181,194,159,229,217,91,154,35,17,1,1,1,0,116,1,236,153,75,254,53,124,209,144,57,74,187,230,144,45,193,224,47,6,239,95,24,218,35,211,15,153,133,132,168,202,47,129,2,75,109,191,116,194,156,206,220,32,149,149,230,69,25,217,62,255,222,37,141,217,143,251,117,242,78,34,16,98,224,207,15,16,4,7,112,114,111,102,105,108,101,0,5,2,1,1,2,0,5,205,195,135,151,178,8,119,211,117,230,18,83,50,89,19,183,127,57,203,228,164,230,92,122,59,197,253,145,155,235,135,17,1,7,112,114,111,102,105,108,101,0,181,4,1,0,0,36,2,1,32,138,220,83,139,202,31,216,109,249,241,253,21,57,139,254,249,56,114,184,161,107,65,92,73,87,219,251,179,142,249,191,163,0,179,129,41,192,46,100,108,87,4,146,18,160,142,213,140,123,193,64,147,245,231,97,152,170,175,221,177,65,70,57,128,37,4,1,2,0,36,2,1,32,138,220,83,139,202,31,216,109,249,241,253,21,57,139,254,249,56,114,184,161,107,65,92,73,87,219,251,179,142,249,191,163,0,190,169,14,99,77,52,152,248,143,51,91,34,250,76,163,150,118,226,63,152,50,209,134,11,76,236,235,251,211,31,226,250,16,1,42,38,5,120,239,0,1,185,15,15,59,125,160,203,184,123,37,48,249,1,233,129,255,131,58,233,101,69,162,201,84,58,17,2,1,0,0,223,6,32,138,220,83,139,202,31,216,109,249,241,253,21,57,139,254,249,56,114,184,161,107,65,92,73,87,219,251,179,142,249,191,163,0,155,0,152,0,138,220,83,139,202,31,216,109,249,241,253,21,57,139,254,249,56,114,184,161,107,65,92,73,87,219,251,179,142,249,191,163,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,3,0,3,0,0,1,115,164,225,142,56,0,0,1,115,164,225,142,56,1,23,112,108,97,99,101,107,105,116,116,101,110,46,99,111,109,47,50,48,48,47,51,48,48,1,36,116,111,100,97,121,32,105,115,32,97,32,103,111,111,100,32,100,97,121,32,116,111,32,103,111,32,116,111,32,116,104,101,32,122,111,111,1,3,115,97,109,0,174,50,197,64,108,157,99,117,18,220,157,141,238,114,224,173,173,206,49,36,100,77,80,246,150,59,8,94,156,206,29,158,0,1,2,0,89,4,32,138,220,83,139,202,31,216,109,249,241,253,21,57,139,254,249,56,114,184,161,107,65,92,73,87,219,251,179,142,249,191,163,0,21,8,1,16,128,0,0,0,0,0,7,208,128,0,0,0,0,0,0,2,3,0,57,238,163,93,59,60,129,200,104,210,142,152,142,247,67,138,252,158,60,215,28,252,182,50,207,201,65,224,131,93,110,42,1,32,138,220,83,139,202,31,216,109,249,241,253,21,57,139,254,249,56,114,184,161,107,65,92,73,87,219,251,179,142,249,191,163,0,251,1,139,30,228,51,63,101,139,131,31,185,128,136,121,42,19,104,188,96,245,155,5,105,220,248,164,202,70,194,144,216,42,194,98,24,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,20,16,128,0,0,0,0,0,7,208,128,0,0,0,0,0,0,2,0,155,0,152,0,138,220,83,139,202,31,216,109,249,241,253,21,57,139,254,249,56,114,184,161,107,65,92,73,87,219,251,179,142,249,191,163,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,2,0,3,0,0,1,115,164,225,142,56,0,0,1,115,164,225,142,56,1,23,112,108,97,99,101,107,105,116,116,101,110,46,99,111,109,47,50,48,48,47,51,48,48,1,36,116,111,100,97,121,32,105,115,32,97,32,103,111,111,100,32,100,97,121,32,116,111,32,103,111,32,116,111,32,116,104,101,32,122,111,111,1,3,115,97,109,0,0,0,0,0,0,0,0,3,16,30,15,230,213,100,93,81,164,17,140,128,156,213,44,206,186,24,20,43,247,20,166,253,135,47,30,154,232,6,175,119,24,174,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,17,0],"quorum_hash":[9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9],"signature":[143,157,107,184,224,215,225,0,188,239,58,11,108,159,166,116,33,194,212,190,247,249,46,13,142,33,145,226,112,215,55,66,190,23,146,119,217,106,206,110,185,98,92,52,177,188,174,102,18,205,78,42,80,163,40,60,228,56,236,143,88,4,65,82,205,45,174,252,184,55,63,147,107,136,77,40,112,155,104,36,213,55,194,178,106,1,3,58,172,55,226,132,68,254,39,70],"round":0,"block_id_hash":[7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7],"quorum_type":6}}}}}} diff --git a/packages/wasm-sdk/src/document_type_layout.rs b/packages/wasm-sdk/src/document_type_layout.rs index 87f0aa5e160..b23b1d3f450 100644 --- a/packages/wasm-sdk/src/document_type_layout.rs +++ b/packages/wasm-sdk/src/document_type_layout.rs @@ -28,12 +28,14 @@ export interface DocumentTypeLayoutNode { | { kind: 'fixed'; hex: string; label: string } | { kind: 'documentId' } | { kind: 'revisionTime' } + | { kind: 'revisionTimeAndRevision' } | { kind: 'propertyValue'; property: string } | { kind: 'timeRangeBucket'; property: string; rangeSeconds: number; stepSeconds: number; phaseSeconds: number } | { kind: 'integerRangeBucket'; property: string; range: number; step: number; phase: number } | { kind: 'memberKey'; components: string[] }; role: | 'documentType' | 'primaryKey' | 'document' | 'latestRevision' | 'revision' + | 'history' | 'documentHistory' | 'retainedRevision' | 'indexProperty' | 'indexValue' | 'nextIndexProperty' | 'terminal' | 'member'; /** The id of the node of Drive's structure description (grovedb-structure.json) this layer is an instance of. */ structureNode: string; diff --git a/packages/wasm-sdk/src/queries/document.rs b/packages/wasm-sdk/src/queries/document.rs index 6b540d4bbd9..48d7bccbcb8 100644 --- a/packages/wasm-sdk/src/queries/document.rs +++ b/packages/wasm-sdk/src/queries/document.rs @@ -2,12 +2,15 @@ use crate::queries::utils::deserialize_required_query; use crate::queries::ProofMetadataResponseWasm; use crate::sdk::WasmSdk; use crate::WasmSdkError; +use dapi_grpc::platform::v0::get_document_history_response::get_document_history_response_v1::Result as HistoryResponseResult; use dash_sdk::dpp::data_contract::accessors::v0::DataContractV0Getters; use dash_sdk::dpp::document::Document; use dash_sdk::dpp::platform_value::Value; use dash_sdk::dpp::prelude::Identifier; use dash_sdk::drive::query::SelectProjection; -use dash_sdk::platform::documents::document_history_query::DocumentHistoryQuery; +use dash_sdk::platform::documents::document_history_query::{ + DocumentHistoryFilter, DocumentHistoryQuery, +}; use dash_sdk::platform::documents::document_query::DocumentQuery; use dash_sdk::platform::Fetch; use dash_sdk::platform::FetchMany; @@ -15,15 +18,17 @@ use drive::query::{ IntegerRangeGridSpec, OrderClause, TimeRangeGridSpec, TimeRangeSelector, WhereClause, WhereOperator, }; -use drive_proof_verifier::types::DocumentHistory; +use drive_proof_verifier::types::{DocumentHistory, DocumentHistoryProofInfo}; use drive_proof_verifier::{DocumentSplitAverages, DocumentSplitCounts, DocumentSplitSums}; use js_sys::{BigInt, Map}; -use serde::Deserialize; +use serde::{Deserialize, Serialize}; use serde_json::Value as JsonValue; use wasm_bindgen::prelude::wasm_bindgen; use wasm_bindgen::JsValue; use wasm_dpp2::data_contract::document::DocumentWasm; use wasm_dpp2::identifier::{IdentifierLikeJs, IdentifierWasm}; +use wasm_dpp2::serialization; +use wasm_dpp2::utils::IntoWasm; #[wasm_bindgen(typescript_custom_section)] const DOCUMENTS_QUERY_TS: &'static str = r#" @@ -208,23 +213,14 @@ export interface DocumentHistoryQuery { */ documentId: IdentifierLike - /** - * Millisecond timestamp (exclusive) to start after. - * @default 0 - */ - startAtMs?: number; - - /** - * Maximum number of entries to return. - * @default undefined - */ + /** Inclusive lower time bound. Supply exactly one selector. */ + startAtMs?: bigint | number; + /** Complete exclusive cursor returned by a previous page. */ + startAfter?: { timeMs: bigint | number; revision: bigint | number } | DocumentHistoryEntry; + startAtRevision?: bigint | number; + revision?: bigint | number; + /** Maximum ten entries. A single revision requires limit one. */ limit?: number; - - /** - * Offset for pagination through the document history. - * @default undefined - */ - offset?: number; } "#; @@ -235,6 +231,9 @@ extern "C" { #[wasm_bindgen(typescript_type = "DocumentHistoryQuery")] pub type DocumentHistoryQueryJs; + + #[wasm_bindgen(method, getter = startAfter)] + fn start_after(this: &DocumentHistoryQueryJs) -> JsValue; } #[derive(Deserialize)] @@ -274,35 +273,260 @@ pub(super) struct DocumentsQueryInput { } #[derive(Deserialize)] -#[serde(rename_all = "camelCase")] +#[serde(rename_all = "camelCase", deny_unknown_fields)] struct DocumentHistoryQueryInput { data_contract_id: IdentifierWasm, document_type_name: String, document_id: IdentifierWasm, - #[serde(default)] start_at_ms: Option, - #[serde(default)] + start_after: Option, + start_at_revision: Option, + revision: Option, limit: Option, - #[serde(default)] - offset: Option, +} + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +struct DocumentHistoryCursorInput { + time_ms: u64, + revision: u64, } fn parse_document_history_query( query: DocumentHistoryQueryJs, ) -> Result { - let input: DocumentHistoryQueryInput = - deserialize_required_query(query, "Query object is required", "document history query")?; - + let input: DocumentHistoryQueryInput = deserialize_required_query( + query.clone(), + "Query object is required", + "document history query", + )?; + let start_after = input + .start_after + .map(|_| parse_document_history_cursor(query.start_after())) + .transpose()?; + let filters = [ + input.start_at_ms.is_some(), + start_after.is_some(), + input.start_at_revision.is_some(), + input.revision.is_some(), + ]; + if filters.into_iter().filter(|present| *present).count() != 1 { + return Err(WasmSdkError::invalid_argument( + "exactly one history filter is required", + )); + } + let filter = if let Some(time) = input.start_at_ms { + DocumentHistoryFilter::StartAtTime(time) + } else if let Some(cursor) = start_after { + DocumentHistoryFilter::StartAfter { + time_ms: cursor.time_ms, + revision: cursor.revision, + } + } else if let Some(revision) = input.start_at_revision { + DocumentHistoryFilter::StartAtRevision(revision) + } else { + DocumentHistoryFilter::Revision(input.revision.expect("one filter was checked")) + }; Ok(DocumentHistoryQuery { data_contract_id: input.data_contract_id.into(), document_type_name: input.document_type_name, document_id: input.document_id.into(), - start_at_ms: input.start_at_ms.unwrap_or(0), + filter, limit: input.limit, - offset: input.offset, }) } +fn parse_document_history_cursor( + value: JsValue, +) -> Result { + if let Ok(entry) = value.to_wasm::("DocumentHistoryEntry") { + return Ok(DocumentHistoryCursorInput { + time_ms: entry.time_ms, + revision: entry.revision, + }); + } + serialization::from_object(value) + .map_err(|error| WasmSdkError::invalid_argument(format!("Invalid history cursor: {error}"))) +} + +#[wasm_bindgen(js_name = "DocumentHistoryEntry")] +#[derive(Clone)] +pub struct DocumentHistoryEntryWasm { + time_ms: u64, + revision: u64, + document: DocumentWasm, +} + +wasm_dpp2::impl_wasm_type_info!(DocumentHistoryEntryWasm, DocumentHistoryEntry); + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +struct DocumentHistoryEntrySerde { + time_ms: String, + revision: String, + document: JsonValue, +} + +#[wasm_bindgen(js_class = DocumentHistoryEntry)] +impl DocumentHistoryEntryWasm { + #[wasm_bindgen(getter = "timeMs")] + pub fn time_ms(&self) -> BigInt { + BigInt::from(self.time_ms) + } + + #[wasm_bindgen(getter)] + pub fn revision(&self) -> BigInt { + BigInt::from(self.revision) + } + + #[wasm_bindgen(getter)] + pub fn document(&self) -> DocumentWasm { + self.document.clone() + } + + #[wasm_bindgen(js_name = toJSON)] + pub fn to_json(&self) -> Result { + serialization::to_json(&self.to_serde()?).map_err(WasmSdkError::from) + } +} + +impl DocumentHistoryEntryWasm { + fn to_serde(&self) -> Result { + Ok(DocumentHistoryEntrySerde { + time_ms: self.time_ms.to_string(), + revision: self.revision.to_string(), + document: serialization::js_value_to_json(&JsValue::from(self.document.clone())) + .map_err(WasmSdkError::from)?, + }) + } +} + +#[wasm_bindgen(js_name = "DocumentHistoryLifecycle")] +#[derive(Clone)] +pub struct DocumentHistoryLifecycleWasm { + state: String, + remaining_revisions: u64, +} + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +struct DocumentHistoryLifecycleSerde { + state: String, + remaining_revisions: String, +} + +#[wasm_bindgen(js_class = DocumentHistoryLifecycle)] +impl DocumentHistoryLifecycleWasm { + #[wasm_bindgen(getter)] + pub fn state(&self) -> String { + self.state.clone() + } + + #[wasm_bindgen(getter = "remainingRevisions")] + pub fn remaining_revisions(&self) -> BigInt { + BigInt::from(self.remaining_revisions) + } + + #[wasm_bindgen(js_name = toJSON)] + pub fn to_json(&self) -> Result { + serialization::to_json(&self.to_serde()).map_err(WasmSdkError::from) + } +} + +impl DocumentHistoryLifecycleWasm { + fn to_serde(&self) -> DocumentHistoryLifecycleSerde { + DocumentHistoryLifecycleSerde { + state: self.state.clone(), + remaining_revisions: self.remaining_revisions.to_string(), + } + } +} + +#[wasm_bindgen(js_name = "DocumentHistoryResult")] +#[derive(Clone)] +pub struct DocumentHistoryResultWasm { + entries: Vec, + lifecycle: Option, +} + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +struct DocumentHistoryResultSerde { + entries: Vec, + #[serde(skip_serializing_if = "Option::is_none")] + lifecycle: Option, +} + +#[wasm_bindgen(js_class = DocumentHistoryResult)] +impl DocumentHistoryResultWasm { + #[wasm_bindgen(getter)] + pub fn entries(&self) -> Vec { + self.entries.clone() + } + + #[wasm_bindgen(getter)] + pub fn lifecycle(&self) -> Option { + self.lifecycle.clone() + } + + #[wasm_bindgen(js_name = toJSON)] + pub fn to_json(&self) -> Result { + serialization::to_json(&self.to_serde()?).map_err(WasmSdkError::from) + } +} + +impl DocumentHistoryResultWasm { + fn to_serde(&self) -> Result { + Ok(DocumentHistoryResultSerde { + entries: self + .entries + .iter() + .map(DocumentHistoryEntryWasm::to_serde) + .collect::, _>>()?, + lifecycle: self + .lifecycle + .as_ref() + .map(DocumentHistoryLifecycleWasm::to_serde), + }) + } + + fn from_history( + history: DocumentHistory, + contract_id: Identifier, + document_type_name: &str, + ) -> Result { + use drive_proof_verifier::types::DocumentHistoryState; + + let entries = history + .entries + .into_iter() + .map(|entry| DocumentHistoryEntryWasm { + time_ms: entry.time_ms, + revision: entry.revision, + document: DocumentWasm::new( + entry.document, + contract_id, + document_type_name.to_owned(), + None, + ), + }) + .collect(); + Ok(Self { + entries, + lifecycle: history + .lifecycle + .map(|lifecycle| DocumentHistoryLifecycleWasm { + state: match lifecycle.state { + DocumentHistoryState::Active => "ACTIVE", + DocumentHistoryState::Absent => "ABSENT", + } + .to_owned(), + remaining_revisions: lifecycle.remaining_revisions, + }), + }) + } +} + pub(super) async fn build_documents_query( sdk: &WasmSdk, input: DocumentsQueryInput, @@ -821,48 +1045,50 @@ pub(super) fn json_to_platform_value(json_val: &JsonValue) -> Result Result { + let Some(HistoryResponseResult::Proof(proof)) = result.response.result else { + return Err(WasmSdkError::generic( + "verified document history response carries no proof", + )); + }; + Ok(ProofMetadataResponseWasm::from_sdk_parts( + DocumentHistoryResultWasm::from_history(result.history, contract_id, document_type_name)?, + result.response.metadata.ok_or_else(|| { + WasmSdkError::generic("verified document history response carries no metadata") + })?, + proof, + )) +} + #[wasm_bindgen] impl WasmSdk { - #[wasm_bindgen( - js_name = "getDocumentHistory", - unchecked_return_type = "Map" - )] + #[wasm_bindgen(js_name = "getDocumentHistory")] pub async fn get_document_history( &self, query: DocumentHistoryQueryJs, - ) -> Result { + ) -> Result { let query = parse_document_history_query(query)?; let contract_id = query.data_contract_id; let document_type_name = query.document_type_name.clone(); - - let data_contract = self.get_or_fetch_contract(contract_id).await?; - data_contract + let contract = self.get_or_fetch_contract(contract_id).await?; + contract .document_type_for_name(&document_type_name) - .map_err(|e| WasmSdkError::not_found(format!("Document type not found: {}", e)))?; - - let history_result = DocumentHistory::fetch(self.as_ref(), query).await?; - let history_map = Map::new(); - - if let Some(history) = history_result { - for (block_time_ms, document) in history { - let document_js = JsValue::from(DocumentWasm::new( - document, - contract_id, - document_type_name.clone(), - None, - )); - let key = JsValue::from(BigInt::from(block_time_ms)); - - history_map.set(&key, &document_js); - } - } - - Ok(history_map) + .map_err(|error| { + WasmSdkError::not_found(format!("Document type not found: {error}")) + })?; + let history = DocumentHistory::fetch(self.as_ref(), query) + .await? + .ok_or_else(|| WasmSdkError::not_found("document history response is missing"))?; + DocumentHistoryResultWasm::from_history(history, contract_id, &document_type_name) } #[wasm_bindgen( js_name = "getDocumentHistoryWithProofInfo", - unchecked_return_type = "ProofMetadataResponseTyped>" + unchecked_return_type = "ProofMetadataResponseTyped" )] pub async fn get_document_history_with_proof_info( &self, @@ -871,35 +1097,16 @@ impl WasmSdk { let query = parse_document_history_query(query)?; let contract_id = query.data_contract_id; let document_type_name = query.document_type_name.clone(); - - let data_contract = self.get_or_fetch_contract(contract_id).await?; - data_contract + let contract = self.get_or_fetch_contract(contract_id).await?; + contract .document_type_for_name(&document_type_name) - .map_err(|e| WasmSdkError::not_found(format!("Document type not found: {}", e)))?; - - let (history_result, metadata, proof) = - DocumentHistory::fetch_with_metadata_and_proof(self.as_ref(), query, None).await?; - let history_map = Map::new(); - - if let Some(history) = history_result { - for (block_time_ms, document) in history { - let document_js = JsValue::from(DocumentWasm::new( - document, - contract_id, - document_type_name.clone(), - None, - )); - let key = JsValue::from(BigInt::from(block_time_ms)); - - history_map.set(&key, &document_js); - } - } - - Ok(ProofMetadataResponseWasm::from_sdk_parts( - history_map, - metadata, - proof, - )) + .map_err(|error| { + WasmSdkError::not_found(format!("Document type not found: {error}")) + })?; + let result = DocumentHistoryProofInfo::fetch(self.as_ref(), query) + .await? + .ok_or_else(|| WasmSdkError::not_found("document history response is missing"))?; + document_history_proof_response(result, contract_id, &document_type_name) } #[wasm_bindgen( @@ -1355,6 +1562,19 @@ mod tests { use super::*; use serde_json::json; + #[test] + fn accepts_legacy_history_without_lifecycle_metadata() { + let history = DocumentHistory { + entries: vec![], + lifecycle: None, + }; + + let result = DocumentHistoryResultWasm::from_history(history, [1; 32].into(), "note") + .expect("the legacy history layout has no lifecycle metadata"); + + assert!(result.lifecycle.is_none()); + } + /// This parser is the only boundary turning the public JavaScript /// `{ field, selector, startMs?, grid? }` shape into a typed time-range /// clause — native and protobuf tests construct their queries after it, @@ -1551,3 +1771,309 @@ mod tests { } } } + +#[cfg(all(test, target_arch = "wasm32"))] +mod history_wasm_tests { + use super::*; + use crate::error::WasmSdkErrorKind; + use dash_sdk::platform::proto::get_document_history_response::GetDocumentHistoryResponseV1; + use drive_proof_verifier::types::{ + DocumentHistoryEntry, DocumentHistoryLifecycle, DocumentHistoryState, + }; + use js_sys::{Array, Reflect}; + use wasm_bindgen::JsCast; + use wasm_bindgen_test::wasm_bindgen_test; + + #[wasm_bindgen_test] + fn should_return_an_error_when_history_proof_metadata_is_missing() { + let result = DocumentHistoryProofInfo { + history: DocumentHistory { + entries: vec![], + lifecycle: None, + }, + response: GetDocumentHistoryResponseV1 { + metadata: None, + result: Some(HistoryResponseResult::Proof(Default::default())), + }, + }; + let error = document_history_proof_response(result, [1; 32].into(), "note") + .expect_err("missing metadata must return an error"); + assert_eq!(error.kind(), WasmSdkErrorKind::Generic); + assert_eq!( + error.to_string(), + "verified document history response carries no metadata" + ); + } + + #[wasm_bindgen_test] + fn should_return_an_error_when_history_response_has_no_proof() { + let result = DocumentHistoryProofInfo { + history: DocumentHistory { + entries: vec![], + lifecycle: None, + }, + response: Default::default(), + }; + let error = document_history_proof_response(result, [1; 32].into(), "note") + .expect_err("missing proof must return an error"); + assert_eq!(error.kind(), WasmSdkErrorKind::Generic); + assert_eq!( + error.to_string(), + "verified document history response carries no proof" + ); + } + + fn returned_history_entry(time_ms: u64, revision: u64) -> JsValue { + let history = DocumentHistory { + entries: vec![DocumentHistoryEntry { + time_ms, + revision, + document: Document::V0(Default::default()), + }], + lifecycle: None, + }; + let result = JsValue::from( + DocumentHistoryResultWasm::from_history(history, [1; 32].into(), "note").unwrap(), + ); + Array::from(&Reflect::get(&result, &"entries".into()).unwrap()).get(0) + } + + fn history_query_with_cursor(cursor: &JsValue) -> DocumentHistoryQueryJs { + let query = js_sys::JSON::parse( + r#"{"dataContractId":"GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec","documentTypeName":"note","documentId":"4mZmxva49PBb7BE7srw9o3gixvDfj1dAx1K6z4A7P9Ah"}"#, + ) + .unwrap(); + Reflect::set(&query, &"startAfter".into(), cursor).unwrap(); + query.unchecked_into() + } + + #[wasm_bindgen_test] + fn should_accept_a_returned_history_entry_as_the_next_page_cursor() { + let time_ms = (1u64 << 53) + 1; + let revision = 22; + let entry = returned_history_entry(time_ms, revision); + for _ in 0..2 { + let query = parse_document_history_query(history_query_with_cursor(&entry)) + .expect("the last returned entry is a valid cursor for the next page"); + assert_eq!( + query.filter, + DocumentHistoryFilter::StartAfter { time_ms, revision } + ); + } + } + + #[wasm_bindgen_test] + fn should_accept_plain_history_cursors_with_numbers_and_exact_bigints() { + for (cursor, time_ms) in [ + ( + js_sys::JSON::parse(r#"{"timeMs":2000,"revision":22}"#).unwrap(), + 2000, + ), + ( + serialization::to_object(&DocumentHistoryCursorInputForTest { + time_ms: (1u64 << 53) + 1, + revision: 22, + }) + .unwrap(), + (1u64 << 53) + 1, + ), + ] { + let query = parse_document_history_query(history_query_with_cursor(&cursor)).unwrap(); + assert_eq!( + query.filter, + DocumentHistoryFilter::StartAfter { + time_ms, + revision: 22 + } + ); + } + } + + #[derive(Serialize)] + #[serde(rename_all = "camelCase")] + struct DocumentHistoryCursorInputForTest { + time_ms: u64, + revision: u64, + } + + #[wasm_bindgen_test] + fn should_reject_history_cursor_pointer_and_constructor_impostors() { + let entry = returned_history_entry(2000, 22); + let pointer = Reflect::get(&entry, &"__wbg_ptr".into()).unwrap(); + let constructor = Reflect::get(&entry, &"constructor".into()).unwrap(); + for copy_constructor in [false, true] { + let impostor = js_sys::Object::new(); + Reflect::set(&impostor, &"__wbg_ptr".into(), &pointer).unwrap(); + if copy_constructor { + Reflect::set(&impostor, &"constructor".into(), &constructor).unwrap(); + } + assert!(parse_document_history_query(history_query_with_cursor(&impostor)).is_err()); + } + } + + #[wasm_bindgen_test] + fn should_reject_a_freed_history_cursor_and_accept_a_later_live_entry() { + let entry = returned_history_entry(2000, 22); + let free = Reflect::get(&entry, &"free".into()) + .unwrap() + .dyn_into::() + .unwrap(); + free.call0(&entry).unwrap(); + assert!(parse_document_history_query(history_query_with_cursor(&entry)).is_err()); + + let live_entry = returned_history_entry(2000, 23); + let query = parse_document_history_query(history_query_with_cursor(&live_entry)).unwrap(); + assert_eq!( + query.filter, + DocumentHistoryFilter::StartAfter { + time_ms: 2000, + revision: 23 + } + ); + } + + #[wasm_bindgen_test] + fn should_export_the_history_proof_as_one_proof_object() { + let result = ProofMetadataResponseWasm::from_sdk_parts( + JsValue::NULL, + dash_sdk::platform::proto::ResponseMetadata::default(), + dash_sdk::platform::proto::Proof { + grovedb_proof: vec![1, 2, 3], + ..Default::default() + }, + ); + let result = JsValue::from(result); + let proof = Reflect::get(&result, &"proof".into()).unwrap(); + assert_eq!( + js_sys::Uint8Array::new(&Reflect::get(&proof, &"grovedbProof".into()).unwrap()) + .to_vec(), + vec![1, 2, 3] + ); + } + + #[wasm_bindgen_test] + fn should_preserve_same_time_revisions_and_exact_lifecycle_counts_in_javascript() { + let count = (1u64 << 53) + 1; + let history = DocumentHistory { + entries: [1, 2] + .into_iter() + .map(|revision| DocumentHistoryEntry { + time_ms: 2000, + revision, + document: Document::V0(Default::default()), + }) + .collect(), + lifecycle: Some(DocumentHistoryLifecycle { + state: DocumentHistoryState::Active, + remaining_revisions: count, + }), + }; + let result = JsValue::from( + DocumentHistoryResultWasm::from_history(history, [1; 32].into(), "note").unwrap(), + ); + let entries = Array::from(&Reflect::get(&result, &"entries".into()).unwrap()); + assert_eq!(entries.length(), 2); + for (index, revision) in [1u64, 2].into_iter().enumerate() { + assert_eq!( + Reflect::get(&entries.get(index as u32), &"revision".into()).unwrap(), + JsValue::from(revision) + ); + } + let lifecycle = Reflect::get(&result, &"lifecycle".into()).unwrap(); + assert_eq!( + Reflect::get(&lifecycle, &"remainingRevisions".into()).unwrap(), + JsValue::from(count) + ); + assert_eq!( + Reflect::get(&lifecycle, &"state".into()).unwrap(), + JsValue::from_str("ACTIVE") + ); + } + + #[wasm_bindgen_test] + fn should_serialize_history_data_in_a_proof_metadata_response() { + let history = DocumentHistory { + entries: vec![DocumentHistoryEntry { + time_ms: 2000, + revision: 1, + document: Document::V0(Default::default()), + }], + lifecycle: Some(DocumentHistoryLifecycle { + state: DocumentHistoryState::Active, + remaining_revisions: (1u64 << 53) + 1, + }), + }; + let response = document_history_proof_response( + DocumentHistoryProofInfo { + history, + response: GetDocumentHistoryResponseV1 { + metadata: Some(Default::default()), + result: Some(HistoryResponseResult::Proof(Default::default())), + }, + }, + [1; 32].into(), + "note", + ) + .unwrap(); + + let json = response.to_json().unwrap(); + let data = Reflect::get(&json, &"data".into()).unwrap(); + let entries = Array::from(&Reflect::get(&data, &"entries".into()).unwrap()); + assert_eq!(entries.length(), 1); + assert_eq!( + Reflect::get(&entries.get(0), &"timeMs".into()).unwrap(), + JsValue::from_str("2000") + ); + assert_eq!( + Reflect::get(&entries.get(0), &"revision".into()).unwrap(), + JsValue::from_str("1") + ); + let document = Reflect::get(&entries.get(0), &"document".into()).unwrap(); + assert!(Reflect::has(&document, &"$dataContractId".into()).unwrap()); + let lifecycle = Reflect::get(&data, &"lifecycle".into()).unwrap(); + assert_eq!( + Reflect::get(&lifecycle, &"remainingRevisions".into()).unwrap(), + JsValue::from_str("9007199254740993") + ); + } + + #[wasm_bindgen_test] + fn should_expose_legacy_history_without_lifecycle_metadata() { + let history = DocumentHistory { + entries: vec![], + lifecycle: None, + }; + let result = JsValue::from( + DocumentHistoryResultWasm::from_history(history, [1; 32].into(), "note").unwrap(), + ); + + assert!(Reflect::get(&result, &"lifecycle".into()) + .unwrap() + .is_undefined()); + } + + #[wasm_bindgen_test] + fn should_reject_conflicting_selectors_and_public_offsets() { + let base = r#"{"dataContractId":"GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec","documentTypeName":"note","documentId":"4mZmxva49PBb7BE7srw9o3gixvDfj1dAx1K6z4A7P9Ah""#; + for fields in [ + "", + ",\"startAtMs\":0,\"revision\":1", + ",\"startAtMs\":0,\"offset\":1", + ] { + let input = js_sys::JSON::parse(&format!("{base}{fields}}}")).unwrap(); + assert!(parse_document_history_query(input.unchecked_into()).is_err()); + } + let input = js_sys::JSON::parse(&format!( + "{base},\"startAfter\":{{\"timeMs\":2000,\"revision\":22}}}}" + )) + .unwrap(); + let query = parse_document_history_query(input.unchecked_into()).unwrap(); + assert_eq!( + query.filter, + DocumentHistoryFilter::StartAfter { + time_ms: 2000, + revision: 22 + } + ); + } +} diff --git a/packages/wasm-sdk/tests/unit/document-type-layout.spec.ts b/packages/wasm-sdk/tests/unit/document-type-layout.spec.ts index c94b3fda963..2172618a0c0 100644 --- a/packages/wasm-sdk/tests/unit/document-type-layout.spec.ts +++ b/packages/wasm-sdk/tests/unit/document-type-layout.spec.ts @@ -6,6 +6,7 @@ */ import { expect } from './helpers/chai.ts'; import init, * as sdk from '../../dist/sdk.compressed.js'; +import type { DocumentTypeLayoutNode } from '../../dist/sdk.js'; const ownerId = '11111111111111111111111111111111'; @@ -23,6 +24,14 @@ type LayoutNode = { }; const schemas = { + note: { + type: 'object', + documentsKeepHistory: true, + canBeDeleted: false, + properties: { text: { type: 'string', maxLength: 40, position: 0 } }, + required: ['text'], + additionalProperties: false, + }, /** Plain, countable, unique, compound and ranked indexes over one type. */ review: { type: 'object', @@ -85,13 +94,25 @@ describe('documentTypeLayout()', () => { }); }); - function layout(name: string) { - return sdk.documentTypeLayout(contract, name, new sdk.PlatformVersion(14)) as unknown as { + function layout(name: string, version = 14) { + return sdk.documentTypeLayout(contract, name, new sdk.PlatformVersion(version)) as unknown as { documentType: string; root: LayoutNode; }; } + it('should describe current pointers and retained composite revisions at protocol 15', () => { + const roles: Array = ['history', 'documentHistory', 'retainedRevision']; + const revisionKey: DocumentTypeLayoutNode['key'] = { kind: 'revisionTimeAndRevision' }; + const { root } = layout('note', 15); + expect(child(root, 'PrimaryKey').children[0]).to.include({ role: 'document', element: 'Reference' }); + const history = child(root, 'History'); + expect(history.role).to.equal(roles[0]); + expect(history.children[0]).to.include({ role: roles[1], element: 'ProvableCountTree' }); + expect(history.children[0].children[0]).to.include({ role: roles[2], element: 'Item' }); + expect(history.children[0].children[0].key).to.deep.equal(revisionKey); + }); + it('should describe the document type tree, the documents and one tree per first index property', () => { const { documentType, root } = layout('review');