diff --git a/Cargo.lock b/Cargo.lock index d16a76044ac..99f1797af05 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -151,9 +151,9 @@ dependencies = [ [[package]] name = "arc-swap" -version = "1.9.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a07d1f37ff60921c83bdfc7407723bdefe89b44b98a9b772f225c8f9d67141a6" +checksum = "6a3a1fd6f75306b68087b831f025c712524bcb19aad54e557b1129cfa0a2b207" dependencies = [ "rustversion", ] @@ -247,9 +247,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "aws-lc-rs" -version = "1.16.2" +version = "1.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a054912289d18629dc78375ba2c3726a3afe3ff71b4edba9dedfca0e3446d1fc" +checksum = "0ec6fb3fe69024a75fa7e1bfb48aa6cf59706a101658ea01bfd33b2b248a038f" dependencies = [ "aws-lc-sys", "zeroize", @@ -257,9 +257,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.39.1" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a25cf98105baa966497416dbd42565ce3a8cf8dbfd59803ec9ad46f3126399" +checksum = "f50037ee5e1e41e7b8f9d161680a725bd1626cb6f8c7e901f91f942850852fe7" dependencies = [ "cc", "cmake", @@ -296,9 +296,9 @@ dependencies = [ [[package]] name = "axum" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b52af3cb4058c895d37317bb27508dccc8e5f2d39454016b297bf4a400597b8" +checksum = "31b698c5f9a010f6573133b09e0de5408834d0c82f8d7475a89fc1867a71cd90" dependencies = [ "axum-core 0.5.6", "axum-macros", @@ -369,9 +369,9 @@ dependencies = [ [[package]] name = "axum-macros" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "604fde5e028fea851ce1d8570bbdc034bec850d157f7569d10f347d06808c05c" +checksum = "7aa268c23bfbbd2c4363b9cd302a4f504fb2a9dfe7e3451d66f35dd392e20aca" dependencies = [ "proc-macro2", "quote", @@ -510,10 +510,10 @@ version = "0.72.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "cexpr", "clang-sys", - "itertools 0.10.5", + "itertools 0.13.0", "proc-macro2", "quote", "regex", @@ -539,7 +539,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90dbd31c98227229239363921e60fcf5e558e43ec69094d46fc4996f08d1d5bc" dependencies = [ "bitcoin_hashes", - "rand 0.8.5", + "rand 0.8.6", "rand_core 0.6.4", "serde", "unicode-normalization", @@ -591,9 +591,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.11.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" [[package]] name = "bitvec" @@ -620,9 +620,9 @@ dependencies = [ [[package]] name = "blake3" -version = "1.8.4" +version = "1.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d2d5991425dfd0785aed03aedcf0b321d61975c9b5b3689c774a2610ae0b51e" +checksum = "0aa83c34e62843d924f905e0f5c866eb1dd6545fc4d719e803d9ba6030371fce" dependencies = [ "arrayref", "arrayvec", @@ -667,7 +667,7 @@ source = "git+https://github.com/dashpay/bls-signatures?rev=0842b17583888e8f46c2 dependencies = [ "bls-dash-sys", "hex", - "rand 0.8.5", + "rand 0.8.6", "serde", ] @@ -693,7 +693,7 @@ dependencies = [ "hkdf", "merlin", "pairing", - "rand 0.8.5", + "rand 0.8.6", "rand_chacha 0.3.1", "rand_core 0.6.4", "serde", @@ -875,7 +875,7 @@ checksum = "3fce8dd7fcfcbf3a0a87d8f515194b49d6135acab73e18bd380d1d93bb1a15eb" dependencies = [ "clap", "heck 0.4.1", - "indexmap 2.13.1", + "indexmap 2.14.0", "log", "proc-macro2", "quote", @@ -894,7 +894,7 @@ checksum = "befbfd072a8e81c02f8c507aefce431fe5e7d051f83d48a23ffc9b9fe5a11799" dependencies = [ "clap", "heck 0.5.0", - "indexmap 2.13.1", + "indexmap 2.14.0", "log", "proc-macro2", "quote", @@ -907,9 +907,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.59" +version = "1.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7a4d3ec6524d28a329fc53654bbadc9bdd7b0431f5d65f1a56ffb28a1ee5283" +checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98" dependencies = [ "find-msvc-tools", "jobserver", @@ -917,12 +917,6 @@ dependencies = [ "shlex", ] -[[package]] -name = "cesu8" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" - [[package]] name = "cexpr" version = "0.6.0" @@ -963,7 +957,7 @@ checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" dependencies = [ "cfg-if", "cpufeatures 0.3.0", - "rand_core 0.10.0", + "rand_core 0.10.1", ] [[package]] @@ -1073,9 +1067,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.6.0" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" dependencies = [ "clap_builder", "clap_derive", @@ -1095,9 +1089,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.6.0" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a" +checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -1262,15 +1256,6 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" -[[package]] -name = "core2" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" -dependencies = [ - "memchr", -] - [[package]] name = "corez" version = "0.1.1" @@ -1306,9 +1291,9 @@ dependencies = [ [[package]] name = "crc-catalog" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" +checksum = "217698eaf96b4a3f0bc4f3662aaa55bdf913cd54d7204591faa790070c6d0853" [[package]] name = "crc32fast" @@ -1467,7 +1452,7 @@ dependencies = [ "serde_bytes", "serde_json", "tenderdash-proto", - "tonic 0.14.5", + "tonic 0.14.6", "tonic-prost", "tonic-prost-build", ] @@ -1665,7 +1650,7 @@ dependencies = [ "hex", "key-wallet", "key-wallet-manager", - "rand 0.8.5", + "rand 0.8.6", "rayon", "serde", "serde_json", @@ -1796,9 +1781,9 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea" +checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" [[package]] name = "delegate" @@ -1961,7 +1946,7 @@ dependencies = [ "getrandom 0.2.17", "grovedb-commitment-tree", "hex", - "indexmap 2.13.1", + "indexmap 2.14.0", "integer-encoding", "itertools 0.13.0", "json-schema-compatibility-validator", @@ -1979,7 +1964,7 @@ dependencies = [ "platform-version", "platform-versioning", "pretty_assertions", - "rand 0.8.5", + "rand 0.8.6", "regex", "rust_decimal", "rust_decimal_macros", @@ -2025,7 +2010,7 @@ dependencies = [ "grovedb-storage", "grovedb-version", "hex", - "indexmap 2.13.1", + "indexmap 2.14.0", "integer-encoding", "intmap", "itertools 0.13.0", @@ -2034,7 +2019,7 @@ dependencies = [ "once_cell", "parking_lot", "platform-version", - "rand 0.8.5", + "rand 0.8.6", "serde", "serde_json", "sqlparser", @@ -2069,7 +2054,7 @@ dependencies = [ "file-rotate", "grovedb-commitment-tree", "hex", - "indexmap 2.13.1", + "indexmap 2.14.0", "integer-encoding", "itertools 0.13.0", "lazy_static", @@ -2080,7 +2065,7 @@ dependencies = [ "nonempty", "platform-version", "prost 0.14.3", - "rand 0.8.5", + "rand 0.8.6", "regex", "reopen", "rocksdb", @@ -2112,7 +2097,7 @@ dependencies = [ "dpp", "drive", "hex", - "indexmap 2.13.1", + "indexmap 2.14.0", "platform-serialization", "platform-serialization-derive", "serde", @@ -2343,9 +2328,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.3.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" [[package]] name = "fdeflate" @@ -2464,9 +2449,9 @@ dependencies = [ [[package]] name = "fraction" -version = "0.15.3" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f158e3ff0a1b334408dc9fb811cd99b446986f4d8b741bb08f9df1604085ae7" +checksum = "e076045bb43dac435333ed5f04caf35c7463631d0dae2deb2638d94dd0a5b872" dependencies = [ "lazy_static", "num", @@ -2594,9 +2579,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "1.3.5" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaf57c49a95fd1fe24b90b3033bee6dc7e8f1288d51494cb44e627c295e38542" +checksum = "dab9e9188e97a93276e1fe7b56401b851e2b45a46d045ca658100c1303ada649" dependencies = [ "rustversion", "serde_core", @@ -2639,7 +2624,7 @@ dependencies = [ "cfg-if", "libc", "r-efi 6.0.0", - "rand_core 0.10.0", + "rand_core 0.10.1", "wasip2", "wasip3", ] @@ -2705,7 +2690,7 @@ checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ "ff", "memuse", - "rand 0.8.5", + "rand 0.8.6", "rand_core 0.6.4", "rand_xorshift", "subtle", @@ -2714,9 +2699,9 @@ dependencies = [ [[package]] name = "grovedb" version = "4.0.0" -source = "git+https://github.com/dashpay/grovedb?rev=dbd83dce59fbcf2866e9dd06be4ce6c320e37908#dbd83dce59fbcf2866e9dd06be4ce6c320e37908" +source = "git+https://github.com/dashpay/grovedb?rev=a917d92d2477672eed73c4c08e53e93449a6a094#a917d92d2477672eed73c4c08e53e93449a6a094" dependencies = [ - "axum 0.8.8", + "axum 0.8.9", "bincode", "bincode_derive", "blake3", @@ -2735,11 +2720,11 @@ dependencies = [ "grovedbg-types", "hex", "hex-literal", - "indexmap 2.13.1", + "indexmap 2.14.0", "integer-encoding", "intmap", "itertools 0.14.0", - "reqwest 0.13.2", + "reqwest 0.13.3", "sha2", "tempfile", "thiserror 2.0.18", @@ -2752,7 +2737,7 @@ dependencies = [ [[package]] name = "grovedb-bulk-append-tree" version = "4.0.0" -source = "git+https://github.com/dashpay/grovedb?rev=dbd83dce59fbcf2866e9dd06be4ce6c320e37908#dbd83dce59fbcf2866e9dd06be4ce6c320e37908" +source = "git+https://github.com/dashpay/grovedb?rev=a917d92d2477672eed73c4c08e53e93449a6a094#a917d92d2477672eed73c4c08e53e93449a6a094" dependencies = [ "bincode", "blake3", @@ -2768,7 +2753,7 @@ dependencies = [ [[package]] name = "grovedb-commitment-tree" version = "4.0.0" -source = "git+https://github.com/dashpay/grovedb?rev=dbd83dce59fbcf2866e9dd06be4ce6c320e37908#dbd83dce59fbcf2866e9dd06be4ce6c320e37908" +source = "git+https://github.com/dashpay/grovedb?rev=a917d92d2477672eed73c4c08e53e93449a6a094#a917d92d2477672eed73c4c08e53e93449a6a094" dependencies = [ "blake3", "grovedb-bulk-append-tree", @@ -2784,7 +2769,7 @@ dependencies = [ [[package]] name = "grovedb-costs" version = "4.0.0" -source = "git+https://github.com/dashpay/grovedb?rev=dbd83dce59fbcf2866e9dd06be4ce6c320e37908#dbd83dce59fbcf2866e9dd06be4ce6c320e37908" +source = "git+https://github.com/dashpay/grovedb?rev=a917d92d2477672eed73c4c08e53e93449a6a094#a917d92d2477672eed73c4c08e53e93449a6a094" dependencies = [ "integer-encoding", "intmap", @@ -2794,7 +2779,7 @@ dependencies = [ [[package]] name = "grovedb-dense-fixed-sized-merkle-tree" version = "4.0.0" -source = "git+https://github.com/dashpay/grovedb?rev=dbd83dce59fbcf2866e9dd06be4ce6c320e37908#dbd83dce59fbcf2866e9dd06be4ce6c320e37908" +source = "git+https://github.com/dashpay/grovedb?rev=a917d92d2477672eed73c4c08e53e93449a6a094#a917d92d2477672eed73c4c08e53e93449a6a094" dependencies = [ "bincode", "blake3", @@ -2807,7 +2792,7 @@ dependencies = [ [[package]] name = "grovedb-element" version = "4.0.0" -source = "git+https://github.com/dashpay/grovedb?rev=dbd83dce59fbcf2866e9dd06be4ce6c320e37908#dbd83dce59fbcf2866e9dd06be4ce6c320e37908" +source = "git+https://github.com/dashpay/grovedb?rev=a917d92d2477672eed73c4c08e53e93449a6a094#a917d92d2477672eed73c4c08e53e93449a6a094" dependencies = [ "bincode", "bincode_derive", @@ -2822,7 +2807,7 @@ dependencies = [ [[package]] name = "grovedb-epoch-based-storage-flags" version = "4.0.0" -source = "git+https://github.com/dashpay/grovedb?rev=dbd83dce59fbcf2866e9dd06be4ce6c320e37908#dbd83dce59fbcf2866e9dd06be4ce6c320e37908" +source = "git+https://github.com/dashpay/grovedb?rev=a917d92d2477672eed73c4c08e53e93449a6a094#a917d92d2477672eed73c4c08e53e93449a6a094" dependencies = [ "grovedb-costs", "hex", @@ -2834,7 +2819,7 @@ dependencies = [ [[package]] name = "grovedb-merk" version = "4.0.0" -source = "git+https://github.com/dashpay/grovedb?rev=dbd83dce59fbcf2866e9dd06be4ce6c320e37908#dbd83dce59fbcf2866e9dd06be4ce6c320e37908" +source = "git+https://github.com/dashpay/grovedb?rev=a917d92d2477672eed73c4c08e53e93449a6a094#a917d92d2477672eed73c4c08e53e93449a6a094" dependencies = [ "bincode", "bincode_derive", @@ -2850,17 +2835,17 @@ dependencies = [ "grovedb-version", "grovedb-visualize", "hex", - "indexmap 2.13.1", + "indexmap 2.14.0", "integer-encoding", "num_cpus", - "rand 0.10.0", + "rand 0.10.1", "thiserror 2.0.18", ] [[package]] name = "grovedb-merkle-mountain-range" version = "4.0.0" -source = "git+https://github.com/dashpay/grovedb?rev=dbd83dce59fbcf2866e9dd06be4ce6c320e37908#dbd83dce59fbcf2866e9dd06be4ce6c320e37908" +source = "git+https://github.com/dashpay/grovedb?rev=a917d92d2477672eed73c4c08e53e93449a6a094#a917d92d2477672eed73c4c08e53e93449a6a094" dependencies = [ "bincode", "blake3", @@ -2871,7 +2856,7 @@ dependencies = [ [[package]] name = "grovedb-path" version = "4.0.0" -source = "git+https://github.com/dashpay/grovedb?rev=dbd83dce59fbcf2866e9dd06be4ce6c320e37908#dbd83dce59fbcf2866e9dd06be4ce6c320e37908" +source = "git+https://github.com/dashpay/grovedb?rev=a917d92d2477672eed73c4c08e53e93449a6a094#a917d92d2477672eed73c4c08e53e93449a6a094" dependencies = [ "hex", ] @@ -2879,7 +2864,7 @@ dependencies = [ [[package]] name = "grovedb-query" version = "4.0.0" -source = "git+https://github.com/dashpay/grovedb?rev=dbd83dce59fbcf2866e9dd06be4ce6c320e37908#dbd83dce59fbcf2866e9dd06be4ce6c320e37908" +source = "git+https://github.com/dashpay/grovedb?rev=a917d92d2477672eed73c4c08e53e93449a6a094#a917d92d2477672eed73c4c08e53e93449a6a094" dependencies = [ "bincode", "byteorder", @@ -2887,7 +2872,7 @@ dependencies = [ "grovedb-costs", "grovedb-storage", "hex", - "indexmap 2.13.1", + "indexmap 2.14.0", "integer-encoding", "thiserror 2.0.18", ] @@ -2895,7 +2880,7 @@ dependencies = [ [[package]] name = "grovedb-storage" version = "4.0.0" -source = "git+https://github.com/dashpay/grovedb?rev=dbd83dce59fbcf2866e9dd06be4ce6c320e37908#dbd83dce59fbcf2866e9dd06be4ce6c320e37908" +source = "git+https://github.com/dashpay/grovedb?rev=a917d92d2477672eed73c4c08e53e93449a6a094#a917d92d2477672eed73c4c08e53e93449a6a094" dependencies = [ "blake3", "grovedb-costs", @@ -2914,7 +2899,7 @@ dependencies = [ [[package]] name = "grovedb-version" version = "4.0.0" -source = "git+https://github.com/dashpay/grovedb?rev=dbd83dce59fbcf2866e9dd06be4ce6c320e37908#dbd83dce59fbcf2866e9dd06be4ce6c320e37908" +source = "git+https://github.com/dashpay/grovedb?rev=a917d92d2477672eed73c4c08e53e93449a6a094#a917d92d2477672eed73c4c08e53e93449a6a094" dependencies = [ "thiserror 2.0.18", "versioned-feature-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2923,7 +2908,7 @@ dependencies = [ [[package]] name = "grovedb-visualize" version = "4.0.0" -source = "git+https://github.com/dashpay/grovedb?rev=dbd83dce59fbcf2866e9dd06be4ce6c320e37908#dbd83dce59fbcf2866e9dd06be4ce6c320e37908" +source = "git+https://github.com/dashpay/grovedb?rev=a917d92d2477672eed73c4c08e53e93449a6a094#a917d92d2477672eed73c4c08e53e93449a6a094" dependencies = [ "hex", "itertools 0.14.0", @@ -2932,17 +2917,17 @@ dependencies = [ [[package]] name = "grovedbg-types" version = "4.0.0" -source = "git+https://github.com/dashpay/grovedb?rev=dbd83dce59fbcf2866e9dd06be4ce6c320e37908#dbd83dce59fbcf2866e9dd06be4ce6c320e37908" +source = "git+https://github.com/dashpay/grovedb?rev=a917d92d2477672eed73c4c08e53e93449a6a094#a917d92d2477672eed73c4c08e53e93449a6a094" dependencies = [ "serde", - "serde_with 3.18.0", + "serde_with 3.20.0", ] [[package]] name = "h2" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" +checksum = "171fefbc92fe4a4de27e0698d6a5b392d6a0e333506bc49133760b3bcf948733" dependencies = [ "atomic-waker", "bytes", @@ -2950,7 +2935,7 @@ dependencies = [ "futures-core", "futures-sink", "http", - "indexmap 2.13.1", + "indexmap 2.14.0", "slab", "tokio", "tokio-util", @@ -2982,7 +2967,7 @@ dependencies = [ "halo2_proofs", "lazy_static", "pasta_curves", - "rand 0.8.5", + "rand 0.8.6", "sinsemilla", "subtle", "uint", @@ -3061,6 +3046,12 @@ dependencies = [ "foldhash 0.2.0", ] +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + [[package]] name = "hashlink" version = "0.11.0" @@ -3259,16 +3250,15 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.7" +version = "0.27.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" dependencies = [ "http", "hyper", "hyper-util", "rustls", "rustls-native-certs", - "rustls-pki-types", "tokio", "tokio-rustls", "tower-service", @@ -3460,9 +3450,9 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" dependencies = [ "icu_normalizer", "icu_properties", @@ -3523,12 +3513,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.13.1" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.16.1", + "hashbrown 0.17.1", "serde", "serde_core", ] @@ -3564,16 +3554,6 @@ version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" -[[package]] -name = "iri-string" -version = "0.7.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25e659a4bb38e810ebc252e53b5814ff908a8c58c2a9ce2fae1bbec24cbf4e20" -dependencies = [ - "memchr", - "serde", -] - [[package]] name = "is-terminal" version = "0.4.17" @@ -3635,9 +3615,9 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jiff" -version = "0.2.23" +version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a3546dc96b6d42c5f24902af9e2538e82e39ad350b0c766eb3fbf2d8f3d8359" +checksum = "f00b5dbd620d61dfdcb6007c9c1f6054ebd75319f163d886a9055cec1155073d" dependencies = [ "jiff-static", "log", @@ -3648,9 +3628,9 @@ dependencies = [ [[package]] name = "jiff-static" -version = "0.2.23" +version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a8c8b344124222efd714b73bb41f8b5120b27a7cc1c75593a6ff768d9d05aa4" +checksum = "e000de030ff8022ea1da3f466fbb0f3a809f5e51ed31f6dd931c35181ad8e6d7" dependencies = [ "proc-macro2", "quote", @@ -3659,27 +3639,32 @@ dependencies = [ [[package]] name = "jni" -version = "0.21.1" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" dependencies = [ - "cesu8", "cfg-if", "combine", - "jni-sys 0.3.1", + "jni-macros", + "jni-sys", "log", - "thiserror 1.0.69", + "simd_cesu8", + "thiserror 2.0.18", "walkdir", - "windows-sys 0.45.0", + "windows-link", ] [[package]] -name = "jni-sys" -version = "0.3.1" +name = "jni-macros" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" dependencies = [ - "jni-sys 0.4.1", + "proc-macro2", + "quote", + "rustc_version", + "simd_cesu8", + "syn 2.0.117", ] [[package]] @@ -3816,14 +3801,14 @@ dependencies = [ "bincode", "bincode_derive", "bip39", - "bitflags 2.11.0", + "bitflags 2.11.1", "bs58", "dashcore", "dashcore-private", "dashcore_hashes", "getrandom 0.2.17", "hex", - "rand 0.8.5", + "rand 0.8.6", "scrypt", "secp256k1", "serde", @@ -3904,9 +3889,9 @@ checksum = "744a4c881f502e98c2241d2e5f50040ac73b30194d64452bb6260393b53f0dc9" [[package]] name = "libc" -version = "0.2.184" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libloading" @@ -3951,9 +3936,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.25" +version = "1.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52f4c29e2a68ac30c9087e1b772dc9f44a2b66ed44edf2266cf2be9b03dafc1" +checksum = "fc3a226e576f50782b3305c5ccf458698f92798987f551c6a02efe8276721e22" dependencies = [ "cc", "pkg-config", @@ -3995,9 +3980,9 @@ checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "lru" -version = "0.16.3" +version = "0.16.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1dc47f592c06f33f8e3aea9591776ec7c9f9e4124778ff8a3c3b87159f7e593" +checksum = "7f66e8d5d03f609abc3a39e6f08e4164ebf1447a732906d39eb9b99b7919ef39" dependencies = [ "hashbrown 0.16.1", ] @@ -4095,12 +4080,12 @@ dependencies = [ [[package]] name = "metrics" -version = "0.24.3" +version = "0.24.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d5312e9ba3771cfa961b585728215e3d972c950a3eed9252aa093d6301277e8" +checksum = "ff56c2e7dce6bd462e3b8919986a617027481b1dcc703175b58cf9dd98a2f071" dependencies = [ - "ahash 0.8.12", "portable-atomic", + "rapidhash", ] [[package]] @@ -4113,7 +4098,7 @@ dependencies = [ "http-body-util", "hyper", "hyper-util", - "indexmap 2.13.1", + "indexmap 2.14.0", "ipnet", "metrics", "metrics-util", @@ -4134,7 +4119,7 @@ dependencies = [ "hashbrown 0.15.5", "metrics", "quanta", - "rand 0.9.2", + "rand 0.9.4", "rand_xoshiro", "sketches-ddsketch", ] @@ -4353,7 +4338,7 @@ checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "num-integer", "num-traits", - "rand 0.8.5", + "rand 0.8.6", "serde", ] @@ -4370,7 +4355,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ "num-traits", - "rand 0.8.5", + "rand 0.8.6", "serde", ] @@ -4512,15 +4497,14 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" -version = "0.10.76" +version = "0.10.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "951c002c75e16ea2c65b8c7e4d3d51d5530d8dfa7d060b4776828c88cfb18ecf" +checksum = "bf0b434746ee2832f4f0baf10137e1cabb18cbe6912c69e2e33263c45250f542" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "cfg-if", "foreign-types", "libc", - "once_cell", "openssl-macros", "openssl-sys", ] @@ -4544,9 +4528,9 @@ checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "openssl-sys" -version = "0.9.112" +version = "0.9.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d55af3b3e226502be1526dfdba67ab0e9c96fc293004e79576b2b9edb0dbdb" +checksum = "158fe5b292746440aa6e7a7e690e55aeb72d41505e2804c23c6973ad0e9c9781" dependencies = [ "cc", "libc", @@ -4576,7 +4560,7 @@ dependencies = [ "memuse", "nonempty", "pasta_curves", - "rand 0.8.5", + "rand 0.8.6", "rand_core 0.6.4", "reddsa", "serde", @@ -4646,16 +4630,16 @@ dependencies = [ "ff", "group", "lazy_static", - "rand 0.8.5", + "rand 0.8.6", "static_assertions", "subtle", ] [[package]] name = "pastey" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b867cad97c0791bbd3aaa6472142568c6c9e8f71937e98379f584cfb0cf35bec" +checksum = "c5a797f0e07bdf071d15742978fc3128ec6c22891c31a3a931513263904c982a" [[package]] name = "pbkdf2" @@ -4687,7 +4671,7 @@ checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" dependencies = [ "fixedbitset", "hashbrown 0.15.5", - "indexmap 2.13.1", + "indexmap 2.14.0", ] [[package]] @@ -4716,7 +4700,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ "phf_shared", - "rand 0.8.5", + "rand 0.8.6", ] [[package]] @@ -4730,18 +4714,18 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.11" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517" +checksum = "cbf0d9e68100b3a7989b4901972f265cd542e560a3a8a724e1e20322f4d06ce9" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.11" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" +checksum = "a990e22f43e84855daf260dded30524ef4a9021cc7541c26540500a50b624389" dependencies = [ "proc-macro2", "quote", @@ -4766,9 +4750,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" [[package]] name = "platform-encryption" @@ -4808,10 +4792,10 @@ dependencies = [ "bs58", "ciborium", "hex", - "indexmap 2.13.1", + "indexmap 2.14.0", "platform-serialization", "platform-version", - "rand 0.8.5", + "rand 0.8.6", "serde", "serde_json", "thiserror 2.0.18", @@ -4863,7 +4847,7 @@ dependencies = [ "key-wallet", "key-wallet-manager", "platform-encryption", - "rand 0.8.5", + "rand 0.8.6", "serde_json", "sha2", "static_assertions", @@ -4936,7 +4920,7 @@ version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "crc32fast", "fdeflate", "flate2", @@ -4962,9 +4946,9 @@ checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" [[package]] name = "portable-atomic-util" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "091397be61a01d4be58e7841595bd4bfedb15f1cd54977d79b8271e94ed799a3" +checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618" dependencies = [ "portable-atomic", ] @@ -5055,7 +5039,7 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "toml_edit 0.25.10+spec-1.1.0", + "toml_edit 0.25.11+spec-1.1.0", ] [[package]] @@ -5131,7 +5115,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "343d3bd7056eda839b03204e68deff7d1b13aba7af2b2fd16890697274262ee7" dependencies = [ "heck 0.4.1", - "itertools 0.10.5", + "itertools 0.13.0", "log", "multimap", "petgraph", @@ -5152,7 +5136,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" dependencies = [ "anyhow", - "itertools 0.10.5", + "itertools 0.13.0", "proc-macro2", "quote", "syn 2.0.117", @@ -5165,7 +5149,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b" dependencies = [ "anyhow", - "itertools 0.10.5", + "itertools 0.13.0", "proc-macro2", "quote", "syn 2.0.117", @@ -5235,7 +5219,7 @@ version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c3a14896dfa883796f1cb410461aef38810ea05f2b2c33c5aded3649095fdad" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "memchr", "unicase", ] @@ -5251,9 +5235,9 @@ dependencies = [ [[package]] name = "pxfm" -version = "0.1.28" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5a041e753da8b807c9255f28de81879c78c876392ff2469cde94799b2896b9d" +checksum = "e0c5ccf5294c6ccd63a74f1565028353830a9c2f5eb0c682c355c471726a6e3f" [[package]] name = "quanta" @@ -5312,7 +5296,7 @@ dependencies = [ "bytes", "getrandom 0.3.4", "lru-slab", - "rand 0.9.2", + "rand 0.9.4", "ring", "rustc-hash 2.1.2", "rustls", @@ -5367,9 +5351,9 @@ checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" [[package]] name = "rand" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" dependencies = [ "libc", "rand_chacha 0.3.1", @@ -5378,9 +5362,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.5", @@ -5388,13 +5372,13 @@ dependencies = [ [[package]] name = "rand" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8" +checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" dependencies = [ "chacha20 0.10.0", "getrandom 0.4.2", - "rand_core 0.10.0", + "rand_core 0.10.1", ] [[package]] @@ -5437,9 +5421,9 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" [[package]] name = "rand_xorshift" @@ -5459,20 +5443,29 @@ dependencies = [ "rand_core 0.9.5", ] +[[package]] +name = "rapidhash" +version = "4.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e48930979c155e2f33aa36ab3119b5ee81332beb6482199a8ecd6029b80b59" +dependencies = [ + "rustversion", +] + [[package]] name = "raw-cpuid" version = "11.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", ] [[package]] name = "rayon" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" dependencies = [ "either", "rayon-core", @@ -5512,7 +5505,7 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", ] [[package]] @@ -5629,9 +5622,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.13.2" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3f43e3283ab1488b624b44b0e988d0acea0b3214e694730a055cb6b2efa801" +checksum = "62e0021ea2c22aed41653bc7e1419abb2c97e038ff2c33d0e1309e49a97deec0" dependencies = [ "base64 0.22.1", "bytes", @@ -5771,13 +5764,13 @@ dependencies = [ [[package]] name = "rpassword" -version = "7.4.0" +version = "7.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66d4c8b64f049c6721ec8ccec37ddfc3d641c4a7fca57e8f2a89de509c73df39" +checksum = "5ac5b223d9738ef56e0b98305410be40fa0941bf6036c56f1506751e43552d64" dependencies = [ "libc", "rtoolbox", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -5785,7 +5778,7 @@ name = "rs-dapi" version = "3.1.0-dev.1" dependencies = [ "async-trait", - "axum 0.8.8", + "axum 0.8.9", "base64 0.22.1", "chrono", "ciborium", @@ -5818,7 +5811,7 @@ dependencies = [ "tokio-stream", "tokio-tungstenite", "tokio-util", - "tonic 0.14.5", + "tonic 0.14.6", "tower 0.5.3", "tower-http", "tracing", @@ -5843,7 +5836,7 @@ dependencies = [ "http", "http-serde", "lru", - "rand 0.8.5", + "rand 0.8.6", "serde", "serde_json", "sha2", @@ -5878,7 +5871,7 @@ dependencies = [ "serde", "serde_json", "tokio", - "tonic 0.14.5", + "tonic 0.14.6", "ureq", ] @@ -5968,12 +5961,12 @@ dependencies = [ [[package]] name = "rtoolbox" -version = "0.0.3" +version = "0.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7cc970b249fbe527d6e02e0a227762c9108b2f49d81094fe357ffc6d14d7f6f" +checksum = "50a0e551c1e27e1731aba276dbeaeac73f53c7cd34d1bda485d02bd1e0f36844" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -5982,7 +5975,7 @@ version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1c93dd1c9683b438c392c492109cb702b8090b2bfc8fed6f6e4eb4523f17af3" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "fallible-iterator", "fallible-streaming-iterator", "hashlink", @@ -5993,15 +5986,15 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.41.0" +version = "1.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ce901f9a19d251159075a4c37af514c3b8ef99c22e02dd8c19161cf397ee94a" +checksum = "0c5108e3d4d903e21aac27f12ba5377b6b34f9f44b325e4894c7924169d06995" dependencies = [ "arrayvec", "borsh", "bytes", "num-traits", - "rand 0.8.5", + "rand 0.8.6", "rkyv", "serde", "serde_json", @@ -6045,7 +6038,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "errno", "libc", "linux-raw-sys 0.4.15", @@ -6058,7 +6051,7 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "errno", "libc", "linux-raw-sys 0.12.1", @@ -6067,9 +6060,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.37" +version = "0.23.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4" +checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b" dependencies = [ "aws-lc-rs", "log", @@ -6095,9 +6088,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.14.0" +version = "1.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" +checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" dependencies = [ "web-time", "zeroize", @@ -6105,9 +6098,9 @@ dependencies = [ [[package]] name = "rustls-platform-verifier" -version = "0.6.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784" +checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0" dependencies = [ "core-foundation 0.10.1", "core-foundation-sys", @@ -6132,9 +6125,9 @@ checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" [[package]] name = "rustls-webpki" -version = "0.103.10" +version = "0.103.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df33b2b81ac578cabaf06b89b0631153a3f416b0a886e8a7a1707fb51abbd1ef" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" dependencies = [ "aws-lc-rs", "ring", @@ -6273,7 +6266,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b50c5943d326858130af85e049f2661ba3c78b26589b8ab98e65e80ae44a1252" dependencies = [ "bitcoin_hashes", - "rand 0.8.5", + "rand 0.8.6", "secp256k1-sys", "serde", ] @@ -6293,7 +6286,7 @@ version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "core-foundation 0.10.1", "core-foundation-sys", "libc", @@ -6312,9 +6305,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] name = "serde" @@ -6402,7 +6395,7 @@ version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ - "indexmap 2.13.1", + "indexmap 2.14.0", "itoa", "memchr", "serde", @@ -6480,20 +6473,21 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.18.0" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd5414fad8e6907dbdd5bc441a50ae8d6e26151a03b1de04d89a5576de61d01f" +checksum = "e72c1c2cb7b223fafb600a619537a871c2818583d619401b785e7c0b746ccde2" dependencies = [ "base64 0.22.1", + "bs58", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.13.1", + "indexmap 2.14.0", "schemars 0.9.0", "schemars 1.2.1", "serde_core", "serde_json", - "serde_with_macros 3.18.0", + "serde_with_macros 3.20.0", "time", ] @@ -6511,9 +6505,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.18.0" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3db8978e608f1fe7357e211969fd9abdcae80bac1ba7a3369bb7eb6b404eb65" +checksum = "b90c488738ecb4fb0262f41f43bc40efc5868d9fb744319ddf5f5317f417bfac" dependencies = [ "darling 0.23.0", "proc-macro2", @@ -6581,9 +6575,9 @@ dependencies = [ [[package]] name = "sha3" -version = "0.10.8" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +checksum = "77fd7028345d415a4034cf8777cd4f8ab1851274233b45f84e3d955502d93874" dependencies = [ "digest", "keccak", @@ -6604,7 +6598,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "359e552886ae54d1642091645980d83f7db465fd9b5b0248e3680713c1773388" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "either", "incrementalmerkletree", "tracing", @@ -6641,6 +6635,16 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" +[[package]] +name = "simd_cesu8" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" +dependencies = [ + "rustc_version", + "simdutf8", +] + [[package]] name = "simdutf8" version = "0.1.5" @@ -6672,9 +6676,9 @@ dependencies = [ [[package]] name = "siphasher" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" +checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" [[package]] name = "sketches-ddsketch" @@ -6738,9 +6742,9 @@ dependencies = [ [[package]] name = "sqlite-wasm-rs" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f4206ed3a67690b9c29b77d728f6acc3ce78f16bf846d83c94f76400320181b" +checksum = "1b2c760607300407ddeaee518acf28c795661b7108c75421303dbefb237d3a36" dependencies = [ "cc", "js-sys", @@ -6789,7 +6793,7 @@ dependencies = [ "drive", "hex", "platform-version", - "rand 0.8.5", + "rand 0.8.6", "simple-signer", "tokio", "tracing", @@ -6859,6 +6863,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "symlink" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7973cce6668464ea31f176d85b13c7ab3bba2cb3b77a2ed26abd7801688010a" + [[package]] name = "syn" version = "1.0.109" @@ -6907,7 +6917,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "core-foundation 0.9.4", "system-configuration-sys", ] @@ -6984,7 +6994,7 @@ dependencies = [ "tenderdash-proto-compiler", "thiserror 2.0.18", "time", - "tonic 0.14.5", + "tonic 0.14.6", "tonic-prost", ] @@ -7000,7 +7010,7 @@ dependencies = [ "tonic-prost-build", "ureq", "walkdir", - "zip 8.5.1", + "zip 8.6.0", ] [[package]] @@ -7178,9 +7188,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.51.0" +version = "1.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bd1c4c0fc4a7ab90fc15ef6daaa3ec3b893f004f915f2392557ed23237820cd" +checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" dependencies = [ "bytes", "libc", @@ -7294,7 +7304,7 @@ version = "0.9.12+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" dependencies = [ - "indexmap 2.13.1", + "indexmap 2.14.0", "serde_core", "serde_spanned 1.1.1", "toml_datetime 0.7.5+spec-1.1.0", @@ -7336,7 +7346,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.13.1", + "indexmap 2.14.0", "toml_datetime 0.6.11", "winnow 0.5.40", ] @@ -7347,7 +7357,7 @@ version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.13.1", + "indexmap 2.14.0", "serde", "serde_spanned 0.6.9", "toml_datetime 0.6.11", @@ -7357,14 +7367,14 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.25.10+spec-1.1.0" +version = "0.25.11+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82418ca169e235e6c399a84e395ab6debeb3bc90edc959bf0f48647c6a32d1b" +checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b" dependencies = [ - "indexmap 2.13.1", + "indexmap 2.14.0", "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", - "winnow 1.0.1", + "winnow 1.0.2", ] [[package]] @@ -7373,7 +7383,7 @@ version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ - "winnow 1.0.1", + "winnow 1.0.2", ] [[package]] @@ -7420,12 +7430,12 @@ dependencies = [ [[package]] name = "tonic" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fec7c61a0695dc1887c1b53952990f3ad2e3a31453e1f49f10e75424943a93ec" +checksum = "ac2a5518c70fa84342385732db33fb3f44bc4cc748936eb5833d2df34d6445ef" dependencies = [ "async-trait", - "axum 0.8.8", + "axum 0.8.9", "base64 0.22.1", "bytes", "h2", @@ -7452,9 +7462,9 @@ dependencies = [ [[package]] name = "tonic-build" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1882ac3bf5ef12877d7ed57aad87e75154c11931c2ba7e6cde5e22d63522c734" +checksum = "c68f61875ac5293cf72e6c8cf0158086428c82c37229e98c840878f1706b0322" dependencies = [ "prettyplease", "proc-macro2", @@ -7464,20 +7474,20 @@ dependencies = [ [[package]] name = "tonic-prost" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a55376a0bbaa4975a3f10d009ad763d8f4108f067c7c2e74f3001fb49778d309" +checksum = "50849f68853be452acf590cde0b146665b8d507b3b8af17261df47e02c209ea0" dependencies = [ "bytes", "prost 0.14.3", - "tonic 0.14.5", + "tonic 0.14.6", ] [[package]] name = "tonic-prost-build" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3144df636917574672e93d0f56d7edec49f90305749c668df5101751bb8f95a" +checksum = "654e5643eff75d7f8c99197ce1440ed19a3474eada74c12bbac488b2cafdae27" dependencies = [ "prettyplease", "proc-macro2", @@ -7506,7 +7516,7 @@ dependencies = [ "js-sys", "pin-project", "thiserror 2.0.18", - "tonic 0.14.5", + "tonic 0.14.6", "tower-service", "wasm-bindgen", "wasm-bindgen-futures", @@ -7525,7 +7535,7 @@ dependencies = [ "indexmap 1.9.3", "pin-project", "pin-project-lite", - "rand 0.8.5", + "rand 0.8.6", "slab", "tokio", "tokio-util", @@ -7542,7 +7552,7 @@ checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" dependencies = [ "futures-core", "futures-util", - "indexmap 2.13.1", + "indexmap 2.14.0", "pin-project-lite", "slab", "sync_wrapper", @@ -7555,11 +7565,11 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.6.8" +version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" +checksum = "68d6fdd9f81c2819c9a8b0e0cd91660e7746a8e6ea2ba7c6b2b057985f6bcb51" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "bytes", "futures-core", "futures-util", @@ -7568,7 +7578,6 @@ dependencies = [ "http-body-util", "http-range-header", "httpdate", - "iri-string", "mime", "mime_guess", "percent-encoding", @@ -7579,6 +7588,7 @@ dependencies = [ "tower-layer", "tower-service", "tracing", + "url", ] [[package]] @@ -7607,11 +7617,12 @@ dependencies = [ [[package]] name = "tracing-appender" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "786d480bce6247ab75f005b14ae1624ad978d3029d9113f0a22fa1ac773faeaf" +checksum = "050686193eb999b4bb3bc2acfa891a13da00f79734704c4b8b4ef1a10b368a3c" dependencies = [ "crossbeam-channel", + "symlink", "thiserror 2.0.18", "time", "tracing-subscriber", @@ -7716,7 +7727,7 @@ dependencies = [ "httparse", "log", "native-tls", - "rand 0.8.5", + "rand 0.8.6", "sha1", "thiserror 1.0.69", "url", @@ -7731,9 +7742,9 @@ checksum = "8e28f89b80c87b8fb0cf04ab448d5dd0dd0ade2f8891bae878de66a75a28600e" [[package]] name = "typenum" -version = "1.19.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" +checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" [[package]] name = "uint" @@ -7749,12 +7760,9 @@ dependencies = [ [[package]] name = "uint-zigzag" -version = "0.2.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abbf77aed65cb885a8ba07138c365879be3d9a93dce82bf6cc50feca9138ec15" -dependencies = [ - "core2", -] +checksum = "61faa33dc26b2851a37da5390a1a4cac015887b1e97ecd77ce7b4f987431de9f" [[package]] name = "unicase" @@ -7878,13 +7886,13 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.23.0" +version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ac8b6f42ead25368cf5b098aeb3dc8a1a2c05a3eee8a9a1a68c640edbfc79d9" +checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" dependencies = [ "getrandom 0.4.2", "js-sys", - "rand 0.10.0", + "rand 0.10.1", "wasm-bindgen", ] @@ -7948,7 +7956,7 @@ dependencies = [ "crypto-bigint", "elliptic-curve", "elliptic-curve-tools", - "generic-array 1.3.5", + "generic-array 1.4.1", "hex", "num", "rand_core 0.6.4", @@ -7995,11 +8003,11 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasip2" -version = "1.0.2+wasi-0.2.9" +version = "1.0.3+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" dependencies = [ - "wit-bindgen", + "wit-bindgen 0.57.1", ] [[package]] @@ -8008,7 +8016,7 @@ version = "0.4.0+wasi-0.3.0-rc-2026-01-06" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" dependencies = [ - "wit-bindgen", + "wit-bindgen 0.51.0", ] [[package]] @@ -8166,7 +8174,7 @@ dependencies = [ "dpp", "drive", "hex", - "indexmap 2.13.1", + "indexmap 2.14.0", "js-sys", "serde", "serde-wasm-bindgen 0.6.5", @@ -8204,7 +8212,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" dependencies = [ "anyhow", - "indexmap 2.13.1", + "indexmap 2.14.0", "wasm-encoder", "wasmparser", ] @@ -8227,7 +8235,7 @@ dependencies = [ "js-sys", "once_cell", "platform-value", - "rand 0.8.5", + "rand 0.8.6", "rs-dapi-client", "rs-sdk-trusted-context-provider", "serde", @@ -8264,9 +8272,9 @@ version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "hashbrown 0.15.5", - "indexmap 2.13.1", + "indexmap 2.14.0", "semver", ] @@ -8292,18 +8300,18 @@ dependencies = [ [[package]] name = "webpki-root-certs" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "804f18a4ac2676ffb4e8b5b5fa9ae38af06df08162314f96a68d2a363e21a8ca" +checksum = "f31141ce3fc3e300ae89b78c0dd67f9708061d1d2eda54b8209346fd6be9a92c" dependencies = [ "rustls-pki-types", ] [[package]] name = "webpki-roots" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cfaf3c063993ff62e73cb4311efde4db1efb31ab78a3e5c457939ad5cc0bed" +checksum = "52f5ee44c96cf55f1b349600768e3ece3a8f26010c05265ab73f945bb1a2eb9d" dependencies = [ "rustls-pki-types", ] @@ -8427,22 +8435,13 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -8451,7 +8450,7 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -8463,67 +8462,34 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - [[package]] name = "windows-targets" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -8536,48 +8502,24 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -8604,9 +8546,9 @@ dependencies = [ [[package]] name = "winnow" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5" +checksum = "2ee1708bef14716a11bae175f579062d4554d95be2c6829f518df847b7b3fdd0" dependencies = [ "memchr", ] @@ -8620,6 +8562,12 @@ dependencies = [ "wit-bindgen-rust-macro", ] +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + [[package]] name = "wit-bindgen-core" version = "0.51.0" @@ -8639,7 +8587,7 @@ checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" dependencies = [ "anyhow", "heck 0.5.0", - "indexmap 2.13.1", + "indexmap 2.14.0", "prettyplease", "syn 2.0.117", "wasm-metadata", @@ -8669,8 +8617,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" dependencies = [ "anyhow", - "bitflags 2.11.0", - "indexmap 2.13.1", + "bitflags 2.11.1", + "indexmap 2.14.0", "log", "serde", "serde_derive", @@ -8689,7 +8637,7 @@ checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" dependencies = [ "anyhow", "id-arena", - "indexmap 2.13.1", + "indexmap 2.14.0", "log", "semver", "serde", @@ -8859,7 +8807,7 @@ dependencies = [ "num-traits", "once_cell", "parking_lot", - "rand 0.8.5", + "rand 0.8.6", "regex", "scc", "thiserror 1.0.69", @@ -8914,7 +8862,7 @@ dependencies = [ "flate2", "getrandom 0.3.4", "hmac", - "indexmap 2.13.1", + "indexmap 2.14.0", "lzma-rust2", "memchr", "pbkdf2", @@ -8925,13 +8873,13 @@ dependencies = [ [[package]] name = "zip" -version = "8.5.1" +version = "8.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcab981e19633ebcf0b001ddd37dd802996098bc1864f90b7c5d970ce76c1d59" +checksum = "2d04a6b5381502aa6087c94c669499eb1602eb9c5e8198e534de571f7154809b" dependencies = [ "crc32fast", "flate2", - "indexmap 2.13.1", + "indexmap 2.14.0", "memchr", "typed-path", "zopfli", diff --git a/book/book.toml b/book/book.toml index fc755288f6b..95257761104 100644 --- a/book/book.toml +++ b/book/book.toml @@ -14,3 +14,8 @@ preferred-dark-theme = "navy" git-repository-url = "https://github.com/dashpay/platform" additional-js = ["mermaid.min.js", "mermaid-init.js"] +[preprocessor] + +[preprocessor.mermaid] +command = "mdbook-mermaid" + diff --git a/book/mermaid-init.js b/book/mermaid-init.js index 4f67ecc9cab..0469ff1675e 100644 --- a/book/mermaid-init.js +++ b/book/mermaid-init.js @@ -1,5 +1,7 @@ -// Mermaid initialization for mdBook (without preprocessor) -// Converts ```mermaid code blocks into rendered diagrams. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + (() => { const darkThemes = ['ayu', 'navy', 'coal']; const lightThemes = ['light', 'rust']; @@ -15,29 +17,23 @@ } const theme = lastThemeWasLight ? 'default' : 'dark'; - - // Convert code blocks with language-mermaid into mermaid divs - document.querySelectorAll('pre code.language-mermaid').forEach((codeBlock) => { - const pre = codeBlock.parentElement; - const div = document.createElement('div'); - div.className = 'mermaid'; - div.textContent = codeBlock.textContent; - pre.parentElement.replaceChild(div, pre); - }); - mermaid.initialize({ startOnLoad: true, theme }); - // Re-render on theme switch + // Simplest way to make mermaid re-render the diagrams in the new theme is via refreshing the page + for (const darkTheme of darkThemes) { - const el = document.getElementById(darkTheme); - if (el) el.addEventListener('click', () => { - if (lastThemeWasLight) window.location.reload(); + document.getElementById(darkTheme).addEventListener('click', () => { + if (lastThemeWasLight) { + window.location.reload(); + } }); } + for (const lightTheme of lightThemes) { - const el = document.getElementById(lightTheme); - if (el) el.addEventListener('click', () => { - if (!lastThemeWasLight) window.location.reload(); + document.getElementById(lightTheme).addEventListener('click', () => { + if (!lastThemeWasLight) { + window.location.reload(); + } }); } })(); diff --git a/book/src/drive/document-count-trees.md b/book/src/drive/document-count-trees.md index 7efaac29eb9..e858971ef4d 100644 --- a/book/src/drive/document-count-trees.md +++ b/book/src/drive/document-count-trees.md @@ -55,8 +55,8 @@ In a `CountTree`, the only count-bearing node is the root. To compute "how many A document type opts in via two schema flags: -- `documentsCountable: true` → primary-key tree is a `CountTree`. Enables O(1) total-count for the document type; sufficient for `GetDocumentsCount`. -- `rangeCountable: true` → primary-key tree is a `ProvableCountTree`. Implies `documentsCountable`. Required for `GetDocumentsSplitCount` to be answerable without enumerating documents (the sub-counts at the split-property level are read from internal nodes). +- `documentsCountable: true` → primary-key tree is a `CountTree`. Enables O(1) total-count for the document type; sufficient for `GetDocumentsCount` with no `where` filter. +- `rangeCountable: true` → primary-key tree is a `ProvableCountTree`. Implies `documentsCountable`. The same flag is also accepted *per-index*, where it controls range-count storage layout (see below) and is required for any `GetDocumentsCount` request that carries a range where-clause. ## How a Document Type Picks Its Tree Variant @@ -118,62 +118,121 @@ Tests pinning these guards live in `packages/rs-dpp/src/data_contract/document_t ## Counting Documents at Query Time -Two gRPC endpoints expose the feature: +A single unified gRPC endpoint exposes the feature: `GetDocumentsCount`. The response shape varies by request mode (total / per-`In`-value / per-distinct-value-in-range / total-over-range), see [Range Modes](#range-modes) below. The wire-level shape makes that split explicit: on the no-proof path the response's `CountResults` carries an inner `oneof variant { uint64 aggregate_count; CountEntries entries; }` — total-count and range-without-distinct modes return `aggregate_count` (a single `u64`), per-`In`-value and per-distinct-value-in-range modes return `entries` (a list of `CountEntry { optional bytes in_key; bytes key; uint64 count }` where `in_key` is the prefix value for compound `In + range` shapes and absent for flat queries). The endpoint has two underlying paths (prove vs. no-prove); every mode — including `return_distinct_counts_in_range = true` — is valid on both paths. The prove path uses two different proof shapes depending on whether you want a single aggregate or per-distinct-value entries (see [Prove (Client-Side Verify-Then-Aggregate or Aggregate-Count Proof)](#prove-client-side-verify-then-aggregate-or-aggregate-count-proof) below). -- `GetDocumentsCount` — total count of documents matching a query, optionally with proof. -- `GetDocumentsSplitCount` — counts split by an index property, again optionally with proof. +### No-Prove (Server-Side O(1) or O(log n)) -Both endpoints have two underlying paths: +When `prove=false`, drive-abci calls into `DriveDocumentCountQuery` (in [`packages/rs-drive/src/query/drive_document_count_query/mod.rs`](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-drive/src/query/drive_document_count_query/mod.rs)). The handler picks a path based on the where clauses: -### No-Prove (Server-Side O(1)) +**Unfiltered total (no where clauses) on a `documentsCountable: true` document type** ([`Drive::read_primary_key_count_tree`](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-drive/src/query/drive_document_count_query/drive_dispatcher.rs)): -When `prove=false`, drive-abci calls into `DriveDocumentCountQuery` (in [`packages/rs-drive/src/query/drive_document_count_query.rs`](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-drive/src/query/drive_document_count_query.rs)). For total counts the path is roughly: +The doctype's primary-key tree at `[contract_doc, contract_id, 1, doctype, 0]` is itself a `CountTree`. One grovedb read gives `count_value` — the total document count. O(1). -1. Pick a `CountTree`-typed primary-key index whose properties cover all `Equal` / `In` `WhereClause` predicates (a covering index — see the supported-operators note below). -2. Walk the tree from the root down to the deepest covered level, pushing `prop_name` and `serialize_value_for_key(prop_name, value)` at each step. `Equal` extends one path; `In` clones the current path once per value in its array (a cartesian fork) and the per-branch counts are summed. -3. If every index property was covered: read the `CountTree` element at the resulting path and return its built-in `u64` count. O(1) per branch. -4. If only a prefix was covered: sum the counts of all `CountTree` children at the deepest covered level. +**Equal/In only** ([`execute_no_proof`](https://docs.rs/drive/latest/drive/query/struct.DriveDocumentCountQuery.html#method.execute_no_proof)): -For split counts the path is similar, but stops at the level *before* the split property, then for each value subtree under the split-property level reads its sub-count and emits a `(key_bytes, count)` entry. The result is wire-formatted as `repeated SplitCountEntry { bytes key; uint64 count }`. +1. Pick a `countable: true` index whose properties **exactly match** the Equal/In where-clause fields — every index property has a matching clause, no orphan clauses, no uncovered properties. If no such index exists the request rejects with `WhereClauseOnNonIndexedProperty` (the strict-coverage contract; see "Index design" below). +2. Walk the tree from the root down to the terminal level, pushing `prop_name` and `serialize_value_for_key(prop_name, value)` at each step. `Equal` extends one path; `In` clones the current path once per value in its array (a cartesian fork) and the per-branch counts are summed. +3. Read the `CountTree` element at the resulting path and return its `count_value`. O(1) per branch. -### Prove (Client-Side Verify-Then-Aggregate) +If the request carries an `In` clause, the response is the `entries` variant — one `CountEntry` per `In` value (the per-value split mode). Otherwise the response is the `aggregate_count` variant — a single `u64`. -When `prove=true`, drive-abci returns a standard `DriveDocumentQuery` proof of the matching documents themselves — there is no signed-count primitive on the wire today. The client then verifies the proof, deserializes the documents, and aggregates locally: +**Index design contract**: a `countable: true` index counts exactly its declared properties. Want `count(*) WHERE color = X`? Define a `[color]` countable index. Want `count(*) WHERE color = X AND shape = Y`? Define a `[color, shape]` countable index. Want both? Define both. Partial coverage (e.g. `color = X` against a `[color, shape]` index) is rejected — define a more specific countable index, or set `documentsCountable: true` on the document type for unfiltered total counts. The prove path enforces the same contract, so `prove=true` and `prove=false` reject in the same situations with the same error. -- For total counts the aggregation is `documents.len() as u64` ([`packages/rs-drive-proof-verifier/src/proof/document_count.rs`](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-drive-proof-verifier/src/proof/document_count.rs)). -- For split counts the aggregation walks each verified document, reads `properties.get(split_property)`, encodes the value via `document_type.serialize_value_for_key(split_property, value, platform_version)` so the byte keys line up with what the no-prove path produces, and increments the per-key counter ([`packages/rs-drive-proof-verifier/src/proof/document_split_count.rs`](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-drive-proof-verifier/src/proof/document_split_count.rs)). +**Range** ([`execute_range_count_no_proof`](https://docs.rs/drive/latest/drive/query/struct.DriveDocumentCountQuery.html#method.execute_range_count_no_proof)): -Because the prove path materializes documents, drive-abci caps it at `u16::MAX` matching documents per request as a defensive bound on response size; result sets larger than that need a covering countable index and `prove=false`. The SDK side (`DocumentCountQuery`/`DocumentSplitCountQuery` → `DriveDocumentQuery`) explicitly clears the underlying `DocumentQuery.limit` so the verifier counts every document in the proof rather than truncating at the caller's pagination limit. +1. Pick a `range_countable: true` index where the Equal/In clauses cover the prefix and the range operator hits the index's last property. +2. Build the path `[contract_doc, doctype, prefix..., range_prop_name]` — pointing at the property-name `ProvableCountTree`. +3. Issue a grovedb path query with the converted range `QueryItem` (`>`, `>=`, `<`, `<=`, `Range`, `RangeInclusive`, `RangeAfter`, `RangeAfterTo`, `RangeAfterToInclusive`) and walk the children whose keys lie inside the range. +4. Each child's `count_value_or_default()` is the doc count at that property value. Either sum all per-value counts and return as the `aggregate_count` variant (summed mode), or emit them as per-value `CountEntry`s under the `entries` variant (distinct mode), then apply order / cursor / limit. -Aggregation needs the split-property name, but `DriveDocumentQuery` does not carry it. The proof verifier exposes a dedicated entry point that takes it explicitly: +### Prove (Client-Side Verify-Then-Aggregate or Aggregate-Count Proof) -```rust -DocumentSplitCounts::maybe_from_proof_with_split_property( - drive_query, - split_property, - response, - network, - platform_version, - provider, -) -``` +When `prove=true`, the proof shape depends on whether the query carries a range clause. + +**With a range clause**: the handler picks one of two prove sub-paths based on `return_distinct_counts_in_range`: + +- **Aggregate (`return_distinct_counts_in_range = false`, default)**: drive-abci builds a grovedb [`AggregateCountOnRange`](https://docs.rs/grovedb/latest/grovedb/struct.GroveDb.html#method.verify_aggregate_count_query) path query against the property-name `ProvableCountTree`, and `get_proved_path_query` produces an aggregate-count proof. The client verifies via `GroveDb::verify_aggregate_count_query` and recovers `(root_hash, count)` directly — proof size is O(log n) regardless of how many keys match. No documents are ever materialized. + +- **Distinct (`return_distinct_counts_in_range = true`)**: drive-abci builds a *regular* range path query (no `AggregateCountOnRange` wrapper) against the same `ProvableCountTree`. Because the leaf is a `ProvableCountTree`, merk emits one `Node::KVCount(key, value, count)` op per matched in-range key, with each `count` cryptographically committed to the merk root via `node_hash_with_count(kv_hash, l_hash, r_hash, count)` — same forge-resistance as the aggregate path's `HashWithCount` collapse. The SDK's [`drive_proof_verifier::verify_distinct_count_proof`](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-drive-proof-verifier/src/proof/document_count.rs) runs the standard hash-chain check, then walks the proof's op stream to extract the counts as a `BTreeMap, u64>`. Trade-off vs. the aggregate path: proof size is O(distinct values matched) rather than O(log n), because each distinct in-range key emits its own `KVCount` op instead of being collapsed into a boundary subtree. Acceptable for typical histograms (a few dozen distinct values in range); for "give me a single count" use the aggregate path instead. + +**Without a range clause** (point-lookup with prove): two sub-paths based on the request shape. + +- **Unfiltered total + `documentsCountable: true`**: drive-abci proves the doctype's primary-key `CountTree` element at `[contract_doc, contract_id, 1, doctype, 0]`. One merk path proof; the SDK's [`drive_proof_verifier::verify_primary_key_count_tree_proof`](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-drive-proof-verifier/src/proof/document_count.rs) reads `count_value` off the verified element. O(log n) bytes. + +- **Equal/In against a fully-covering `countable: true` index**: drive-abci proves one `Element::CountTree` per covered branch. Two sub-shapes: + - **Equal-only fully-covered** → one element at `[..., last_field, last_value, 0]`. + - **`In` at any index position (with any number of trailing Equals)** → one element per In value, fetched via outer Query + a subquery whose `set_subquery_path` carries the post-In Equal segments (zero of them when In is on the last property; one or more when In sits earlier in the index). The subquery's `Key([0])` picks off the CountTree at `[..., in_field, in_value, , 0]` for each matched In branch. + + The In position rule for count queries is **more permissive than the regular document query path's `Index::matches`** rule (which restricts In to last-or-before-last because of a positional path-construction assumption — see `DriveDocumentQuery::get_non_primary_key_path_query` for the layout that forces it). The count path doesn't have that constraint: there's no document-key terminator descent, no `order_by` interpretation, and no `limit/offset` semantics — it's a pure CountTree-element lookup, so `set_subquery_path` with an arbitrary trailing tail works. Both no-proof and prove count executors route through a single `point_lookup_count_path_query` builder (no-proof runs the path query via `grove.query` and sums the emitted `CountTree` elements' counts; prove signs the same path query via `get_proved_path_query`), so they accept the same query shapes by construction. The SDK's [`drive_proof_verifier::verify_point_lookup_count_proof`](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-drive-proof-verifier/src/proof/document_count.rs) verifies and extracts `count_value_or_default()` from each verified element. + +Both sub-paths share the proof shape: each CountTree element's `count_value` is cryptographically bound to the merk root via `node_hash_with_count(kv_hash, l_hash, r_hash, count)`, same forge-resistance guarantee the range-distinct path relies on. Neither materializes documents or runs per-key bookkeeping client-side. -The generic `FromProof` impl on `DocumentSplitCounts` is intentionally *not* the way to reach split counts under proof — calling it returns an explicit error. This is a load-bearing design choice: an earlier version of this code silently returned `Some(BTreeMap::new())` from the generic path, so any caller using `prove=true` got a valid-looking but empty result. Erroring loudly forces every caller to thread the split property through. +Proof size: **O(k × log n)** where k is the number of covered branches (1 for the documents_countable fast path and Equal-only fully-covered case; ≤ |In values| for Equal-prefix + In-on-last). + +**Symmetric rejection contract**: prove count requires a `countable: true` index whose properties exactly match the where clauses — same requirement as the no-proof `Total` / `PerInValue` modes. Partial coverage (where the where clauses are a strict prefix of the index, or the index has uncovered properties) rejects with a `WhereClauseOnNonIndexedProperty`-class error pointing the caller at the index-design fix. The `documents_countable: true` fast path handles unfiltered total counts in O(log n) proof bytes when set on the document type. No silent fallback to materializing matching documents — that path doesn't exist anymore. + +Implementation reference: +- Path query: [`DriveDocumentCountQuery::point_lookup_count_path_query`](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-drive/src/query/drive_document_count_query/path_query.rs) — shared by prover and verifier. +- Server executor: [`DriveDocumentCountQuery::execute_point_lookup_count_with_proof`](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-drive/src/query/drive_document_count_query/execute_point_lookup.rs). +- Verifier: [`DriveDocumentCountQuery::verify_point_lookup_count_proof`](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-drive/src/verify/document_count/verify_point_lookup_count_proof/mod.rs); SDK wrapper [`drive_proof_verifier::verify_point_lookup_count_proof`](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-drive-proof-verifier/src/proof/document_count.rs) composes tenderdash signature verification on top. ### Supported Where Operators -The no-prove fast path covers two operator shapes today: +The no-prove fast path covers three operator shapes: + +- **`Equal` (`==`)** — single point lookup against the count tree at a fully-resolved index path. Picked by [`find_countable_index_for_where_clauses`](https://docs.rs/drive/latest/drive/query/struct.DriveDocumentCountQuery.html#method.find_countable_index_for_where_clauses). +- **`In` (`in`)** — cartesian fork. Each value in the `In` array becomes its own index path; their counts are summed (or, for split counts, merged by split key). An `In` clause with `k` values costs `k` point lookups, not a tree walk. The `In` clause also doubles as the per-value split signal in the unified `GetDocumentsCount` endpoint — at most one `In` per request. +- **Range** (`>`, `>=`, `<`, `<=`, `between*`, `startsWith`) — walks the property-name `ProvableCountTree`'s children whose keys lie inside the range, reading each child `CountTree`'s count value. Picked by [`find_range_countable_index_for_where_clauses`](https://docs.rs/drive/latest/drive/query/struct.DriveDocumentCountQuery.html#method.find_range_countable_index_for_where_clauses); requires the index to have `range_countable: true` AND the range property to be the index's last property (the IndexLevel terminator). `startsWith "p"` becomes the half-open range `[serialize("p"), serialize("p") with last byte +1)` — the same byte-incremented encoding the normal docs path uses (see `conditions.rs`'s `StartsWith` arm), valid for UTF-8 string keys since UTF-8 never contains `0xFF`. + +Through the unified `GetDocumentsCount` request handler, range queries take a single range terminator clause plus a prefix of `Equal` clauses and/or one `In` clause. `In` on a prefix property exercises grovedb's native subquery primitive — each emitted entry then carries both the `in_key` (the In value for that fork) and the `key` (the terminator value within the range). Per-fork counts are NOT merged server-side — see [No-Merge Compound Semantics](#no-merge-compound-semantics) below for rationale. + +#### Range Modes + +A range query in the unified endpoint produces one of two response shapes, controlled by `return_distinct_counts_in_range`: + +- **`return_distinct_counts_in_range = false`** (default) — `CountResults.aggregate_count` carrying the sum of the per-value `CountTree` counts within the range. Use for "how many widgets have color in `[red, tomato]`?". +- **`return_distinct_counts_in_range = true`** — `CountResults.entries` with one `CountEntry` per distinct property value within the range (`key` = serialized terminator value, `count` = `CountTree` count for that value, `in_key` = the In-fork value for compound queries or absent for flat queries). Use for "show me a histogram of widgets by color in `[red, tomato]`". + +#### No-Merge Compound Semantics + +For compound queries (`In` on a prefix property + range on the terminator), the entries are returned **unmerged** — one `CountEntry` per emitted `(in_key, key)` pair. The server does NOT collapse them down to a flat histogram keyed only by `key`. This is a load-bearing design choice: + +1. **Correctness under `limit`.** Pushing a `limit` into grovedb's path query truncates the emitted elements before any merge could run. With cross-fork merging this can undercount the merged sums (e.g. `brand IN (acme, contoso)` + `color > x` + `limit=1` could return `acme/red, count=2` and silently drop `contoso/red, count=3` so the merged `red` count comes out as `2` instead of `5`). Without merge, `limit` and the user's "number of entries returned" mean the same thing. +2. **Proof verification stays straightforward.** A malicious server omitting one `In` branch shows up as missing entries with that `in_key` rather than as a silent undercount in a merged total. The caller can detect "I asked for 3 In values but only got entries for 2" directly from the response shape. +3. **No information loss.** A caller who wanted the merged histogram can compute `result.fold(by=key, sum=count)` client-side trivially. A caller who wanted per-`(in_key, key)` counts can't reverse a merged histogram. + +The rs-sdk surfaces this via `DocumentSplitCounts.0: Vec`. Callers wanting the historical flat-map shape can call `DocumentSplitCounts::into_flat_map()` which sums across `in_key` forks. -- **`Equal` (`==`)** — single point lookup against the count tree at a fully-resolved index path. -- **`In` (`in`)** — cartesian fork. Each value in the `In` array becomes its own index path; their counts are summed (or, for split counts, merged by split key). An `In` clause with `k` values costs `k` point lookups, not a tree walk. +Flat queries (no `In` on prefix) have `in_key = None` on every entry; for those callers the API behaves identically to the pre-no-merge shape. -Both `find_countable_index_for_where_clauses` (total count) and `find_countable_index_for_split` (split count) accept either operator on any prefix property of a countable index, mixed freely with `Equal` clauses on other prefix properties. +#### Pagination -Range operators (`>`, `<`, `>=`, `<=`, `between*`, `startsWith`) require a boundary walk that the current count `PathQuery` model cannot express. The handlers detect those upfront and return a clear `InvalidArgument` error rather than silently returning a wrong count. Callers that need counts under range predicates should use `prove=true` and aggregate client-side, or pre-aggregate via a separate countable index whose leading columns are the equality / `In` fields. +Distinct mode accepts pagination knobs: + +| Field | Effect | +|---|---| +| `order_by` | CBOR-encoded list of `[field, "asc"\|"desc"]` clauses, same shape as `GetDocumentsRequestV0.order_by`. First clause's direction controls split-mode entry ordering; ascending (default) walks the range in BTreeMap natural order, descending reverses. Only meaningful in split modes (per-`In`-value, per-distinct-value-in-range, prove-distinct); total-count and aggregate-prove responses are scalar and have no entry ordering. | +| `limit` | Truncate after `min(requested, max_query_limit)` entries; applied last (after order). **Unset (`None`) is normalized to `default_query_limit` before the cap is applied** — the server never walks an unbounded distinct-mode result set, even if the client omits the field. Clients that want a tight working-set should still set this explicitly. | + +For pagination, clients narrow the underlying range itself rather than passing a cursor — page 2 is just `color > ` with the same `limit`. There's no cursor field on the request because a single-`bytes` cursor would be ambiguous for compound (`In + range + distinct`) queries whose natural sort is `(in_key, key)`, and range narrowing has the same expressivity for the simple cases. + +These knobs are ignored on summed mode (they have no defined meaning for a single aggregate). + +#### Range Queries on the Prove Path + +When `prove = true` and the query carries a range clause, the handler picks one of two prove sub-paths based on `return_distinct_counts_in_range`. The aggregate sub-path (default) builds a grovedb [`AggregateCountOnRange`](https://docs.rs/grovedb/latest/grovedb/struct.GroveDb.html#method.verify_aggregate_count_query) proof — verified via `GroveDb::verify_aggregate_count_query`, recovering `(root_hash, count)` *without materializing any matching documents*. Proof size is O(log n) regardless of how many documents match. The distinct sub-path (`return_distinct_counts_in_range = true`) builds a regular range proof against the property-name `ProvableCountTree` — the leaf merk emits per-`(in_key, key)` `KVCount` ops, each bound to the merk root via `node_hash_with_count`, and the SDK extracts them as a `Vec` (preserving the unmerged compound shape per [No-Merge Compound Semantics](#no-merge-compound-semantics)). Distinct proof size is O(distinct `(in_key, key)` pairs matched) instead of the aggregate's O(log n) — pick the aggregate path when you want one number, the distinct path when you want a histogram. + +`In` on a prefix property is supported on the distinct sub-path: grovedb's outer Query enumerates `Key(in_value)` entries at the In-bearing prop's property-name subtree, `set_subquery_path` carries any post-In Equal pairs + terminator name, and `set_subquery` is the range item. The aggregate sub-path still rejects `In` on prefix because `AggregateCountOnRange` is a single-range merk primitive that can't fork at the merk layer — for compound aggregates, callers use `return_distinct_counts_in_range = true` and reduce client-side via `DocumentSplitCounts::into_flat_map`. + +A `"desc"` direction in the first `order_by` clause is supported on the distinct sub-path. The derived direction flows into grovedb's `Query.left_to_right` on both the outer In-keys Query and the inner range subquery, so descending iteration walks `(in_key_desc, key_desc)` tuples. The prover and verifier MUST agree on this direction — the path query bytes include it, and disagreement breaks merk-root recomputation. The SDK derives `left_to_right` from the first `request.document_query.order_by_clauses` direction, matching the server's derivation in `drive_dispatcher`, so the two stay in lockstep by construction. Combined with `limit`, descending order returns the LAST `limit` matched entries (the largest keys) rather than the first `limit` reversed — exactly what callers paginating from the end expect. + +For point-lookup count proofs (no range clause), drive emits a CountTree element proof against the covering countable index — proof size is O(k × log n) where k is the number of covered branches, with no cap on the underlying document count. See [the Prove path section above](#prove-client-side-verify-then-aggregate-or-aggregate-count-proof) for the symmetric-rejection contract. ## Range Queries and ProvableCountTree -> Provable count trees will later be able to answer offset-style queries (e.g. "the next 50 items starting after item 7") in O(log n). That capability isn't released yet — if you want offsets in the future, pick a `ProvableCountTree` (`rangeCountable: true`) for that document type now. +Range count queries (`>`, `<`, `between*`) over an index with `range_countable: true` are answered in O(log n) by walking the property-name `ProvableCountTree`'s boundary nodes. The proof path uses grovedb's `AggregateCountOnRange`, which lets clients verify a range count without ever materializing the underlying documents. + +> Offset-style queries ("the next 50 items starting after item 7") are a separate primitive that will likely build on the same `ProvableCountTree` shape. They are not exposed via `GetDocumentsCount` today — pagination of distinct-mode entries is done by narrowing the range itself (e.g. `color > `), not by offsetting into the underlying documents. ### Why Internal-Node Counts Make Range Counts O(log n) @@ -257,7 +316,7 @@ Set at the same level as `type` / `properties` / `indices` on a document type: That contract gets a `CountTree` for the `widget` primary-key tree. `GetDocumentsCount` for `widget` with no `where` filter is now an O(1) lookup of the tree element's count value. -To opt into a `ProvableCountTree` instead — required if you want today's `GetDocumentsSplitCount` over an index property, and what you'd pick today if you want offset-style range queries to work later — set `rangeCountable: true`. It implies `documentsCountable`, so you don't need both: +To opt into a `ProvableCountTree` for the *primary-key* tree instead — useful if you want range queries on the primary key in the future, or if you intend to use this document type behind range proof primitives — set `rangeCountable: true` at the document-type level. It implies `documentsCountable`, so you don't need both: ```json { @@ -300,7 +359,7 @@ Set on a single entry in the document type's `indices` array: } ``` -With `byColor.countable: true` the `byColor` index's tree carries counts, so `GetDocumentsCount` with `where: [["color", "==", "red"]]` reaches the count via that index in O(1) instead of falling back to a scan. Without the flag, `find_countable_index_for_where_clauses` will skip this index and the count won't take the fast path. +With `byColor.countable: true` the `byColor` index's tree carries counts, so `GetDocumentsCount` with `where: [["color", "==", "red"]]` reaches the count via that index in O(1). Without the flag, `find_countable_index_for_where_clauses` skips the index and the query rejects with `WhereClauseOnNonIndexedProperty` — there's no slow fallback, only fast counts on properly-indexed properties. The `countable` field accepts three forms: @@ -315,7 +374,7 @@ The boolean `true` / `false` form is kept for back-compat with contracts written A few notes about the index-level flag: - Setting any countable variant increases storage cost — every insert and delete updates the index tree's count alongside the document. `"countableAllowingOffset"` costs more than plain `"countable"` (every internal node carries count metadata, not just the root). Don't sprinkle it on every index; opt in for the ones you'll actually count by, and use the cheaper variant unless you specifically need the offset capability. -- The flag is on the *whole* index, not per-property. The index handles `count(*)` queries whose equality `where` clauses cover the index's properties **exactly**, in order. A `["color", "size"]` countable index gives you O(1) counts for `WHERE color = X AND size = Y` — but for `WHERE color = X` alone (only the leading prefix matched) the count is computed by walking every distinct-`size` bucket under `color = X` and summing their counts. That works and avoids document enumeration, but it scales with the cardinality of `size`, not constant time. If single-column `WHERE color = X` counts are a hot path, add a separate `["color"]` countable index. +- The flag is on the *whole* index, not per-property. The index handles `count(*)` queries whose equality `where` clauses cover the index's properties **exactly** — every index property has a matching `==` (or `in`) clause, and every clause's field appears in the index. A `["color", "size"]` countable index gives you O(1) counts for `WHERE color = X AND size = Y` — but `WHERE color = X` alone is rejected with `WhereClauseOnNonIndexedProperty` because that index doesn't claim to count by color alone. If you want both single-column-by-color counts AND compound color+size counts, define both `["color"]` and `["color", "size"]` countable indexes (or just `["color"]` if size-filtered counts aren't a hot path). The picker is strict by design: each countable index represents a deliberate decision about which count queries the contract supports. - Index-level countable is independent of the primary-key flags. You can have `documentsCountable: true` on the document type AND `countable: true` on a specific index — the first gives you fast totals, the second gives you fast filtered counts that match that index. - **`countable` on a `unique` index is mostly a no-op, but not always.** A unique index stores its terminal as a bare reference at key `[0]` rather than wrapping it in a count tree, so for documents whose indexed fields are *all* non-null the flag has no storage effect — insertion bypasses the count-tree code entirely. It does still do meaningful work for **null-bearing** entries: when a document has any null value among the indexed properties, insertion takes the same count-tree branch a non-unique index uses (because uniqueness can't be enforced on null), and the count tree at that path aggregates them. So `countable` on a unique index is worth setting when at least one of the indexed properties is optional in the schema and you expect null values; otherwise it's an inert flag. Counts on all-non-null exact matches still return correctly (1 if present, 0 if not) because the on-disk reference reads as count 1 via grovedb's default-aggregate semantics. @@ -324,25 +383,29 @@ A few notes about the index-level flag: | You want | Set | |---|---| | Fast `count(*)` for the whole document type | `documentsCountable: true` on the document type | -| O(1) filtered count: `count(*) WHERE col = X` | `documentsCountable: true` (or `rangeCountable: true`) at the type level **plus** `countable: true` on an index whose properties are exactly `["col"]`. A composite index whose leading column is `col` (e.g. `["col", "other"]`) still answers the query, but as O(distinct values of `other`) instead of O(1). | -| Per-distinct-value sub-counts via `GetDocumentsSplitCount` | `rangeCountable: true` on the document type **plus** an index whose leading columns cover any equality `where` predicates and whose next column is the split property | +| O(1) filtered count: `count(*) WHERE col = X` | `countable: true` on an index whose properties are exactly `["col"]`. A composite index whose leading column is `col` (e.g. `["col", "other"]`) does NOT answer this query — partial coverage rejects with `WhereClauseOnNonIndexedProperty`. Define a separate `["col"]` countable index if you want this count. | +| Per-`In`-value sub-counts: one `CountEntry` per value in an `In` clause | `countable: true` on an index whose properties exactly match the query's `==` clauses plus the `In` field. **The `In` field may sit at any position in the index** — both the no-proof and prove count paths use `set_subquery_path` to descend through any trailing Equals after the In, which is strictly more permissive than the regular document query path's last-or-before-last rule. E.g. `WHERE color IN [...]` needs `["color"]`; `WHERE brand = X AND color IN [...]` needs `["brand", "color"]`; `WHERE brand IN [...] AND model = X AND year = 2024` needs `["brand", "model", "year"]` with In on `brand` (position 0 of 3). | +| O(log n) range count: `count(*) WHERE col BETWEEN A AND B` | `rangeCountable: true` on an index whose last property is `col` and whose other properties cover any equality predicates as a prefix. Implies `countable: true`. | +| Per-distinct-value range histogram: one `CountEntry` per distinct value in a range | Same `rangeCountable: true` index as above, plus `return_distinct_counts_in_range = true` on the request. Available on both prove and no-prove paths; the prove path returns a regular range proof against the property-name `ProvableCountTree` and the SDK extracts per-key counts from the proof's `KVCount` ops via [`drive_proof_verifier::verify_distinct_count_proof`](https://github.com/dashpay/platform/blob/v3.1-dev/packages/rs-drive-proof-verifier/src/proof/document_count.rs). | +| Range count proof (`prove = true` + range clause) | Same `rangeCountable: true` index. The handler uses grovedb's `AggregateCountOnRange` proof primitive — proof is O(log n), no cap on matched docs. | | Future offset-style range queries (not yet released — see above) | `rangeCountable: true` on the document type | | Nothing count-aware (default) | Don't set any of these flags. Primary-key tree stays a `NormalTree`. | -A migration check from `dapi-grpc` server logic: if you ask for `GetDocumentsCount` with a `where` clause, the no-prove path needs a covering countable index. If no such index exists for that document type, the call falls back to `prove=true` semantics or returns an error depending on the path you took. Pick your indexes deliberately; a `countable: true` flag is cheap to add at contract creation time and impossible to add later. +A migration check from `dapi-grpc` server logic: every count query requires either `documentsCountable: true` (for unfiltered totals) or a `countable: true` / `rangeCountable: true` index whose properties **exactly match** the query's where-clause fields. No covering index → the call returns a clear `InvalidArgument` describing what the picker was looking for ("requires a `range_countable: true` index whose last property matches the range field" for range queries, "requires a countable index whose properties exactly match the where clause fields" for Equal/In queries). Pick your indexes deliberately at contract creation time — per-index `countable: true` / `rangeCountable: true` flags can't be added later (contract indexes are immutable post-creation). ## SDK Access at Three Layers ### `rs-sdk` (native Rust) -Both endpoints land on the standard `Fetch` trait: +Both shapes land on the standard `Fetch` trait against a single `DocumentCountQuery`: ```rust use dash_sdk::platform::documents::document_count_query::DocumentCountQuery; -use dash_sdk::platform::documents::document_split_count_query::DocumentSplitCountQuery; use dash_sdk::platform::Fetch; +use drive::query::{WhereClause, WhereOperator}; use drive_proof_verifier::{DocumentCount, DocumentSplitCounts}; +// Total count: no In clause. let DocumentCount(count) = DocumentCount::fetch( &sdk, DocumentCountQuery::new(contract.clone(), "widget")?, @@ -350,46 +413,61 @@ let DocumentCount(count) = DocumentCount::fetch( .await? .expect("DocumentCount::fetch always returns a value on success"); -let DocumentSplitCounts(splits) = DocumentSplitCounts::fetch( - &sdk, - DocumentSplitCountQuery::new(contract, "widget", "color")?, -) -.await? -.expect("DocumentSplitCounts::fetch always returns a value on success"); +// Split count: signal split by including an `In` clause whose field +// is the split property. The In's values enumerate the keys to count. +let split_query = DocumentCountQuery::new(contract, "widget")? + .with_where(WhereClause { + field: "color".to_string(), + operator: WhereOperator::In, + value: platform_value::Value::Array(vec![ + "red".into(), + "blue".into(), + "green".into(), + ]), + }); +let splits = DocumentSplitCounts::fetch(&sdk, split_query) + .await? + .expect("DocumentSplitCounts::fetch always returns a value on success"); +// `splits` is `DocumentSplitCounts(Vec)` — for the +// flat-histogram view, collapse via `splits.into_flat_map()`. ``` -`DocumentCountQuery` and `DocumentSplitCountQuery` wrap an internal `DocumentQuery` (so they reuse where-clause / order-by / contract-id machinery) and expose a `with_where(WhereClause)` builder for filters. Their `TransportRequest` impls target `GetDocumentsCountRequest` / `GetDocumentsSplitCountRequest`; their `FromProof` impls go through the dedicated proof-verifier entry points described above. +`DocumentCountQuery` wraps an internal `DocumentQuery` (so it reuses where-clause / order-by / contract-id machinery) and exposes `with_where(WhereClause)` + `with_order_by(OrderClause)` builders. The SDK picks the request mode (total / per-`In`-value / total-range / per-distinct-range) from query *shape* — Equal/`In`/range operators in the where clauses — *plus* explicit request flags. `return_distinct_counts_in_range = true` (set via `.with_distinct_counts_in_range(true)`) selects per-distinct-range over the default total-range when a range clause is present; without it a range query returns a single sum. ### `wasm-sdk` (browser) -Four methods on the `WasmSdk` JS class: +Two methods on the `WasmSdk` JS class — one entry per `[plain | withProofInfo]` variant covers every count mode, because the underlying `DocumentSplitCounts::fetch` dispatches on the query shape: ```typescript -sdk.getDocumentsCount(query: DocumentsQuery): Promise; -sdk.getDocumentsCountWithProofInfo( - query: DocumentsQuery, -): Promise>; - -sdk.getDocumentsSplitCount( +sdk.getDocumentsCount( query: DocumentsQuery, - splitProperty: string, ): Promise>; -sdk.getDocumentsSplitCountWithProofInfo( + +sdk.getDocumentsCountWithProofInfo( query: DocumentsQuery, - splitProperty: string, ): Promise>>; ``` -The split-count map's keys are *hex-encoded bytes*. They correspond to the canonical `serialize_value_for_key` encoding of each property value, so callers that need a typed key (`"red"`, `42`, etc.) need to hex-decode and interpret per the contract's index-property type. This shape matches the no-prove server response too, so a caller that wants to merge or compare count maps from both paths doesn't need a transformation step. +Result shapes: + +- **No `where`, or Equal-only `where`** — single map entry with the empty-string key carrying the total count. +- **`where` includes an `In` clause** — one entry per (deduped) In value, keyed by the hex-encoded canonical bytes of that value. +- **`where` includes a range clause + `returnDistinctCountsInRange: true`** — one entry per distinct property value in the range. For compound `In + range + distinct` queries, entries are summed by terminator `key` into a flat map (callers needing the unmerged per-(in_key, key) view should use a richer binding). + +Map keys are always *hex-encoded bytes* matching the canonical `serialize_value_for_key` encoding of each property value, so callers that need a typed key (`"red"`, `42`, etc.) need to hex-decode and interpret per the contract's index-property type. The hex-encoded shape matches the no-prove server response, so merging or comparing count maps from prove and no-prove paths needs no transformation. ### `rs-sdk-ffi` (iOS / native bindings) ```rust -dash_sdk_document_count(sdk, data_contract, document_type, where_json) - -> JSON {"count": } - -dash_sdk_document_split_count(sdk, data_contract, document_type, split_property, where_json) - -> JSON {"counts": {"": , ...}} +dash_sdk_document_count( + sdk, + data_contract, + document_type, + where_json, // null or JSON [{field, operator, value}] + order_by_json, // null or JSON [{field, direction}] + return_distinct_counts_in_range, // bool + limit, // i64; -1 = server default, >= 0 = explicit cap +) -> JSON {"counts": {"": , ...}} ``` -`where_json` is the same JSON shape `dash_sdk_document_search` already accepts (`[{field, operator, value}]`), so iOS callers can reuse their where-clause encoding. Both endpoints return their results as a JSON-encoded C string allocated on the heap — caller frees it via the standard SDK string-free routine. +Single FFI entry covers every count mode — the result is always `{"counts": {...}}` with hex-encoded keys. For total counts (no `where`/`In`, distinct flag off), the map carries a single entry with the empty-string key. `where_json` is the same JSON shape `dash_sdk_document_search` already accepts (`[{field, operator, value}]`), so iOS callers can reuse their where-clause encoding. `order_by_json` is optional and controls split-mode entry ordering only (per-`In`-value and per-distinct-value-in-range results); pass `null` for total counts and aggregate range counts where ordering has no defined meaning. The endpoint returns its result as a JSON-encoded C string allocated on the heap — caller frees it via the standard SDK string-free routine. diff --git a/book/src/drive/indexes.md b/book/src/drive/indexes.md index d0372b4ab47..dbcbc750026 100644 --- a/book/src/drive/indexes.md +++ b/book/src/drive/indexes.md @@ -402,9 +402,17 @@ With the layout above, a query like `WHERE color BETWEEN 'red' AND 'tomato'` res No leaf-level enumeration of distinct color values, no enumeration of individual documents — the count is computed entirely from the tree's pre-aggregated structure. -#### Compound indexes (open question) +#### Compound indexes -What `range_countable` means on a compound index — e.g., `byColorShape = [color, shape]` with `range_countable: true` — is left for later design. The natural reading is "the parent of the *terminating* level of this index", i.e., the `'shape'` tree under each color value, which would itself become a `ProvableCountTree` (and `'circle'` / `'square'` would become `CountTree`s). When that compound's leading prefix is itself another index (`byColor`), the layering of `NonCounted` and counted variants needs to be worked out so neither index's counts pollute the other. We'll cross that bridge when we actually need range queries on a compound index. +`range_countable: true` on a compound index applies at the index's *terminating* level (its last property). For `byColorShape = [color, shape]` with `range_countable: true`: + +- `'shape'` (the property-name tree under each color value) becomes a `ProvableCountTree`. +- Each `'circle'` / `'square'` value tree becomes a `CountTree`. +- Documents are referenced as `Element::Reference` leaves under those `CountTree`s, contributing 1 each to the count aggregate. + +When the compound's leading prefix is also indexed by another `range_countable` index (e.g. `byColor` is also `range_countable`), sibling continuations under each color `CountTree` are wrapped with `Element::NonCounted` so a doc routed via `byColorShape` doesn't double-count under `byColor`'s color aggregate. The walker (`add_indices_for_index_level_for_contract_operations`) threads a `parent_value_tree_is_range_countable` flag down the recursion to decide when to wrap, regardless of whether the inner tree is itself a `ProvableCountTree`, `CountTree`, or plain `NormalTree`. + +End-to-end coverage in `range_countable_index_e2e_tests` (in `packages/rs-drive/src/drive/contract/insert/insert_contract/v0/mod.rs`) pins the storage layout against a real grovedb — including the `count_tree_value_count_excludes_compound_continuation_via_non_counted` test that proves NonCounted-wrapping is load-bearing for compound-index correctness. ## Tree Type at the Terminal Level @@ -518,7 +526,7 @@ Quick checklist for contract authors: - **Don't index what you won't query.** Each index costs storage on every insert/delete and counts against the per-document-type index limit (10 indexes per type currently). - **Order index properties from most-selective to least-selective.** A `[country, city]` index is more useful than `[city, country]` for queries like `where country = "FR"`. - **`unique: true`** when the platform should reject duplicates at the consensus layer. This is the right place for "this should be unique" invariants — don't enforce them application-side. -- **`countable: "countable"`** when you'll regularly call `GetDocumentsCount` filtered by this index's leading columns. Adds a constant-factor overhead on insert/delete; reads become O(1). +- **`countable: "countable"`** when you'll regularly call `GetDocumentsCount` with `==` (or `in`) clauses on **exactly** this index's properties. Adds a constant-factor overhead on insert/delete; reads become O(1). A `countable: true` index counts only queries whose where clauses match its properties exactly — partial-prefix queries are rejected with `WhereClauseOnNonIndexedProperty`, not falling through to a slow scan. Define a separate index per distinct count-query shape you want to support, or set `documentsCountable: true` on the document type for unfiltered totals. - **`countable: "countableAllowingOffset"`** when you'll *also* want offset / range queries on this index in a future release. Strictly more expensive than plain `"countable"`; only worth it if you need the capability. - **`null_searchable: true`** (the default) is right for almost all cases. Set to `false` only when documents with all-null indexed values shouldn't be findable through this index — typically a niche optimization to avoid a hot all-null prefix. diff --git a/packages/dapi-grpc/build.rs b/packages/dapi-grpc/build.rs index 4f2f728b091..8d6988113bb 100644 --- a/packages/dapi-grpc/build.rs +++ b/packages/dapi-grpc/build.rs @@ -84,13 +84,12 @@ fn configure_platform(mut platform: MappingConfig) -> MappingConfig { // Derive features for versioned messages // // "GetConsensusParamsRequest" is excluded as this message does not support proofs - const VERSIONED_REQUESTS: [&str; 58] = [ + const VERSIONED_REQUESTS: [&str; 57] = [ "GetDataContractHistoryRequest", "GetDataContractRequest", "GetDataContractsRequest", "GetDocumentsRequest", "GetDocumentsCountRequest", - "GetDocumentsSplitCountRequest", "GetIdentitiesByPublicKeyHashesRequest", "GetIdentitiesRequest", "GetIdentitiesBalancesRequest", @@ -163,13 +162,12 @@ fn configure_platform(mut platform: MappingConfig) -> MappingConfig { // - "GetIdentityByNonUniquePublicKeyHashResponse" // // "GetEvonodesProposedEpochBlocksResponse" is used for 2 Requests - const VERSIONED_RESPONSES: [&str; 56] = [ + const VERSIONED_RESPONSES: [&str; 55] = [ "GetDataContractHistoryResponse", "GetDataContractResponse", "GetDataContractsResponse", "GetDocumentsResponse", "GetDocumentsCountResponse", - "GetDocumentsSplitCountResponse", "GetIdentitiesByPublicKeyHashesResponse", "GetIdentitiesResponse", "GetIdentitiesBalancesResponse", 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 cf3978e3d7d..a17520e22d7 100644 --- a/packages/dapi-grpc/clients/drive/v0/nodejs/drive_pbjs.js +++ b/packages/dapi-grpc/clients/drive/v0/nodejs/drive_pbjs.js @@ -1122,39 +1122,6 @@ $root.org = (function() { * @variation 2 */ - /** - * Callback as used by {@link org.dash.platform.dapi.v0.Platform#getDocumentsSplitCount}. - * @memberof org.dash.platform.dapi.v0.Platform - * @typedef getDocumentsSplitCountCallback - * @type {function} - * @param {Error|null} error Error, if any - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse} [response] GetDocumentsSplitCountResponse - */ - - /** - * Calls getDocumentsSplitCount. - * @function getDocumentsSplitCount - * @memberof org.dash.platform.dapi.v0.Platform - * @instance - * @param {org.dash.platform.dapi.v0.IGetDocumentsSplitCountRequest} request GetDocumentsSplitCountRequest message or plain object - * @param {org.dash.platform.dapi.v0.Platform.getDocumentsSplitCountCallback} callback Node-style callback called with the error, if any, and GetDocumentsSplitCountResponse - * @returns {undefined} - * @variation 1 - */ - Object.defineProperty(Platform.prototype.getDocumentsSplitCount = function getDocumentsSplitCount(request, callback) { - return this.rpcCall(getDocumentsSplitCount, $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest, $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse, request, callback); - }, "name", { value: "getDocumentsSplitCount" }); - - /** - * Calls getDocumentsSplitCount. - * @function getDocumentsSplitCount - * @memberof org.dash.platform.dapi.v0.Platform - * @instance - * @param {org.dash.platform.dapi.v0.IGetDocumentsSplitCountRequest} request GetDocumentsSplitCountRequest message or plain object - * @returns {Promise} Promise - * @variation 2 - */ - /** * Callback as used by {@link org.dash.platform.dapi.v0.Platform#getIdentityByPublicKeyHash}. * @memberof org.dash.platform.dapi.v0.Platform @@ -21432,6 +21399,9 @@ $root.org = (function() { * @property {Uint8Array|null} [dataContractId] GetDocumentsCountRequestV0 dataContractId * @property {string|null} [documentType] GetDocumentsCountRequestV0 documentType * @property {Uint8Array|null} [where] GetDocumentsCountRequestV0 where + * @property {boolean|null} [returnDistinctCountsInRange] GetDocumentsCountRequestV0 returnDistinctCountsInRange + * @property {Uint8Array|null} [orderBy] GetDocumentsCountRequestV0 orderBy + * @property {number|null} [limit] GetDocumentsCountRequestV0 limit * @property {boolean|null} [prove] GetDocumentsCountRequestV0 prove */ @@ -21474,6 +21444,30 @@ $root.org = (function() { */ GetDocumentsCountRequestV0.prototype.where = $util.newBuffer([]); + /** + * GetDocumentsCountRequestV0 returnDistinctCountsInRange. + * @member {boolean} returnDistinctCountsInRange + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0 + * @instance + */ + GetDocumentsCountRequestV0.prototype.returnDistinctCountsInRange = false; + + /** + * GetDocumentsCountRequestV0 orderBy. + * @member {Uint8Array} orderBy + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0 + * @instance + */ + GetDocumentsCountRequestV0.prototype.orderBy = $util.newBuffer([]); + + /** + * GetDocumentsCountRequestV0 limit. + * @member {number} limit + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0 + * @instance + */ + GetDocumentsCountRequestV0.prototype.limit = 0; + /** * GetDocumentsCountRequestV0 prove. * @member {boolean} prove @@ -21512,8 +21506,14 @@ $root.org = (function() { writer.uint32(/* id 2, wireType 2 =*/18).string(message.documentType); if (message.where != null && Object.hasOwnProperty.call(message, "where")) writer.uint32(/* id 3, wireType 2 =*/26).bytes(message.where); + if (message.returnDistinctCountsInRange != null && Object.hasOwnProperty.call(message, "returnDistinctCountsInRange")) + writer.uint32(/* id 4, wireType 0 =*/32).bool(message.returnDistinctCountsInRange); + if (message.orderBy != null && Object.hasOwnProperty.call(message, "orderBy")) + writer.uint32(/* id 5, wireType 2 =*/42).bytes(message.orderBy); + if (message.limit != null && Object.hasOwnProperty.call(message, "limit")) + writer.uint32(/* id 6, wireType 0 =*/48).uint32(message.limit); if (message.prove != null && Object.hasOwnProperty.call(message, "prove")) - writer.uint32(/* id 4, wireType 0 =*/32).bool(message.prove); + writer.uint32(/* id 7, wireType 0 =*/56).bool(message.prove); return writer; }; @@ -21558,6 +21558,15 @@ $root.org = (function() { message.where = reader.bytes(); break; case 4: + message.returnDistinctCountsInRange = reader.bool(); + break; + case 5: + message.orderBy = reader.bytes(); + break; + case 6: + message.limit = reader.uint32(); + break; + case 7: message.prove = reader.bool(); break; default: @@ -21604,6 +21613,15 @@ $root.org = (function() { if (message.where != null && message.hasOwnProperty("where")) if (!(message.where && typeof message.where.length === "number" || $util.isString(message.where))) return "where: buffer expected"; + if (message.returnDistinctCountsInRange != null && message.hasOwnProperty("returnDistinctCountsInRange")) + if (typeof message.returnDistinctCountsInRange !== "boolean") + return "returnDistinctCountsInRange: boolean expected"; + if (message.orderBy != null && message.hasOwnProperty("orderBy")) + if (!(message.orderBy && typeof message.orderBy.length === "number" || $util.isString(message.orderBy))) + return "orderBy: buffer expected"; + if (message.limit != null && message.hasOwnProperty("limit")) + if (!$util.isInteger(message.limit)) + return "limit: integer expected"; if (message.prove != null && message.hasOwnProperty("prove")) if (typeof message.prove !== "boolean") return "prove: boolean expected"; @@ -21634,6 +21652,15 @@ $root.org = (function() { $util.base64.decode(object.where, message.where = $util.newBuffer($util.base64.length(object.where)), 0); else if (object.where.length >= 0) message.where = object.where; + if (object.returnDistinctCountsInRange != null) + message.returnDistinctCountsInRange = Boolean(object.returnDistinctCountsInRange); + if (object.orderBy != null) + if (typeof object.orderBy === "string") + $util.base64.decode(object.orderBy, message.orderBy = $util.newBuffer($util.base64.length(object.orderBy)), 0); + else if (object.orderBy.length >= 0) + message.orderBy = object.orderBy; + if (object.limit != null) + message.limit = object.limit >>> 0; if (object.prove != null) message.prove = Boolean(object.prove); return message; @@ -21668,6 +21695,15 @@ $root.org = (function() { if (options.bytes !== Array) object.where = $util.newBuffer(object.where); } + object.returnDistinctCountsInRange = false; + if (options.bytes === String) + object.orderBy = ""; + else { + object.orderBy = []; + if (options.bytes !== Array) + object.orderBy = $util.newBuffer(object.orderBy); + } + object.limit = 0; object.prove = false; } if (message.dataContractId != null && message.hasOwnProperty("dataContractId")) @@ -21676,6 +21712,12 @@ $root.org = (function() { object.documentType = message.documentType; if (message.where != null && message.hasOwnProperty("where")) object.where = options.bytes === String ? $util.base64.encode(message.where, 0, message.where.length) : options.bytes === Array ? Array.prototype.slice.call(message.where) : message.where; + if (message.returnDistinctCountsInRange != null && message.hasOwnProperty("returnDistinctCountsInRange")) + object.returnDistinctCountsInRange = message.returnDistinctCountsInRange; + if (message.orderBy != null && message.hasOwnProperty("orderBy")) + object.orderBy = options.bytes === String ? $util.base64.encode(message.orderBy, 0, message.orderBy.length) : options.bytes === Array ? Array.prototype.slice.call(message.orderBy) : message.orderBy; + if (message.limit != null && message.hasOwnProperty("limit")) + object.limit = message.limit; if (message.prove != null && message.hasOwnProperty("prove")) object.prove = message.prove; return object; @@ -21912,7 +21954,7 @@ $root.org = (function() { * Properties of a GetDocumentsCountResponseV0. * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse * @interface IGetDocumentsCountResponseV0 - * @property {number|Long|null} [count] GetDocumentsCountResponseV0 count + * @property {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.ICountResults|null} [counts] GetDocumentsCountResponseV0 counts * @property {org.dash.platform.dapi.v0.IProof|null} [proof] GetDocumentsCountResponseV0 proof * @property {org.dash.platform.dapi.v0.IResponseMetadata|null} [metadata] GetDocumentsCountResponseV0 metadata */ @@ -21933,12 +21975,12 @@ $root.org = (function() { } /** - * GetDocumentsCountResponseV0 count. - * @member {number|Long} count + * GetDocumentsCountResponseV0 counts. + * @member {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.ICountResults|null|undefined} counts * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0 * @instance */ - GetDocumentsCountResponseV0.prototype.count = $util.Long ? $util.Long.fromBits(0,0,true) : 0; + GetDocumentsCountResponseV0.prototype.counts = null; /** * GetDocumentsCountResponseV0 proof. @@ -21961,12 +22003,12 @@ $root.org = (function() { /** * GetDocumentsCountResponseV0 result. - * @member {"count"|"proof"|undefined} result + * @member {"counts"|"proof"|undefined} result * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0 * @instance */ Object.defineProperty(GetDocumentsCountResponseV0.prototype, "result", { - get: $util.oneOfGetter($oneOfFields = ["count", "proof"]), + get: $util.oneOfGetter($oneOfFields = ["counts", "proof"]), set: $util.oneOfSetter($oneOfFields) }); @@ -21994,8 +22036,8 @@ $root.org = (function() { GetDocumentsCountResponseV0.encode = function encode(message, writer) { if (!writer) writer = $Writer.create(); - if (message.count != null && Object.hasOwnProperty.call(message, "count")) - writer.uint32(/* id 1, wireType 0 =*/8).uint64(message.count); + if (message.counts != null && Object.hasOwnProperty.call(message, "counts")) + $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.encode(message.counts, 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")) @@ -22035,7 +22077,7 @@ $root.org = (function() { var tag = reader.uint32(); switch (tag >>> 3) { case 1: - message.count = reader.uint64(); + message.counts = $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.decode(reader, reader.uint32()); break; case 2: message.proof = $root.org.dash.platform.dapi.v0.Proof.decode(reader, reader.uint32()); @@ -22079,10 +22121,13 @@ $root.org = (function() { if (typeof message !== "object" || message === null) return "object expected"; var properties = {}; - if (message.count != null && message.hasOwnProperty("count")) { + if (message.counts != null && message.hasOwnProperty("counts")) { properties.result = 1; - if (!$util.isInteger(message.count) && !(message.count && $util.isInteger(message.count.low) && $util.isInteger(message.count.high))) - return "count: integer|Long expected"; + { + var error = $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.verify(message.counts); + if (error) + return "counts." + error; + } } if (message.proof != null && message.hasOwnProperty("proof")) { if (properties.result === 1) @@ -22114,15 +22159,11 @@ $root.org = (function() { if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0) return object; var message = new $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0(); - if (object.count != null) - if ($util.Long) - (message.count = $util.Long.fromValue(object.count)).unsigned = true; - else if (typeof object.count === "string") - message.count = parseInt(object.count, 10); - else if (typeof object.count === "number") - message.count = object.count; - else if (typeof object.count === "object") - message.count = new $util.LongBits(object.count.low >>> 0, object.count.high >>> 0).toNumber(true); + if (object.counts != null) { + if (typeof object.counts !== "object") + throw TypeError(".org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.counts: object expected"); + message.counts = $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.fromObject(object.counts); + } if (object.proof != null) { if (typeof object.proof !== "object") throw TypeError(".org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.proof: object expected"); @@ -22151,13 +22192,10 @@ $root.org = (function() { var object = {}; if (options.defaults) object.metadata = null; - if (message.count != null && message.hasOwnProperty("count")) { - if (typeof message.count === "number") - object.count = options.longs === String ? String(message.count) : message.count; - else - object.count = options.longs === String ? $util.Long.prototype.toString.call(message.count) : options.longs === Number ? new $util.LongBits(message.count.low >>> 0, message.count.high >>> 0).toNumber(true) : message.count; + if (message.counts != null && message.hasOwnProperty("counts")) { + object.counts = $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.toObject(message.counts, options); if (options.oneofs) - object.result = "count"; + object.result = "counts"; } if (message.proof != null && message.hasOwnProperty("proof")) { object.proof = $root.org.dash.platform.dapi.v0.Proof.toObject(message.proof, options); @@ -22180,1014 +22218,289 @@ $root.org = (function() { return this.constructor.toObject(this, $protobuf.util.toJSONOptions); }; - return GetDocumentsCountResponseV0; - })(); + GetDocumentsCountResponseV0.CountEntry = (function() { - return GetDocumentsCountResponse; - })(); + /** + * Properties of a CountEntry. + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0 + * @interface ICountEntry + * @property {Uint8Array|null} [inKey] CountEntry inKey + * @property {Uint8Array|null} [key] CountEntry key + * @property {number|Long|null} [count] CountEntry count + */ - v0.GetDocumentsSplitCountRequest = (function() { + /** + * Constructs a new CountEntry. + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0 + * @classdesc Represents a CountEntry. + * @implements ICountEntry + * @constructor + * @param {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.ICountEntry=} [properties] Properties to set + */ + function CountEntry(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]]; + } - /** - * Properties of a GetDocumentsSplitCountRequest. - * @memberof org.dash.platform.dapi.v0 - * @interface IGetDocumentsSplitCountRequest - * @property {org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.IGetDocumentsSplitCountRequestV0|null} [v0] GetDocumentsSplitCountRequest v0 - */ + /** + * CountEntry inKey. + * @member {Uint8Array} inKey + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry + * @instance + */ + CountEntry.prototype.inKey = $util.newBuffer([]); - /** - * Constructs a new GetDocumentsSplitCountRequest. - * @memberof org.dash.platform.dapi.v0 - * @classdesc Represents a GetDocumentsSplitCountRequest. - * @implements IGetDocumentsSplitCountRequest - * @constructor - * @param {org.dash.platform.dapi.v0.IGetDocumentsSplitCountRequest=} [properties] Properties to set - */ - function GetDocumentsSplitCountRequest(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]]; - } + /** + * CountEntry key. + * @member {Uint8Array} key + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry + * @instance + */ + CountEntry.prototype.key = $util.newBuffer([]); - /** - * GetDocumentsSplitCountRequest v0. - * @member {org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.IGetDocumentsSplitCountRequestV0|null|undefined} v0 - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest - * @instance - */ - GetDocumentsSplitCountRequest.prototype.v0 = null; + /** + * CountEntry count. + * @member {number|Long} count + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry + * @instance + */ + CountEntry.prototype.count = $util.Long ? $util.Long.fromBits(0,0,true) : 0; - // OneOf field names bound to virtual getters and setters - var $oneOfFields; + /** + * Creates a new CountEntry instance using the specified properties. + * @function create + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.ICountEntry=} [properties] Properties to set + * @returns {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry} CountEntry instance + */ + CountEntry.create = function create(properties) { + return new CountEntry(properties); + }; - /** - * GetDocumentsSplitCountRequest version. - * @member {"v0"|undefined} version - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest - * @instance - */ - Object.defineProperty(GetDocumentsSplitCountRequest.prototype, "version", { - get: $util.oneOfGetter($oneOfFields = ["v0"]), - set: $util.oneOfSetter($oneOfFields) - }); + /** + * Encodes the specified CountEntry message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.verify|verify} messages. + * @function encode + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.ICountEntry} message CountEntry message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + CountEntry.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.inKey != null && Object.hasOwnProperty.call(message, "inKey")) + writer.uint32(/* id 1, wireType 2 =*/10).bytes(message.inKey); + if (message.key != null && Object.hasOwnProperty.call(message, "key")) + writer.uint32(/* id 2, wireType 2 =*/18).bytes(message.key); + if (message.count != null && Object.hasOwnProperty.call(message, "count")) + writer.uint32(/* id 3, wireType 0 =*/24).uint64(message.count); + return writer; + }; - /** - * Creates a new GetDocumentsSplitCountRequest instance using the specified properties. - * @function create - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest - * @static - * @param {org.dash.platform.dapi.v0.IGetDocumentsSplitCountRequest=} [properties] Properties to set - * @returns {org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest} GetDocumentsSplitCountRequest instance - */ - GetDocumentsSplitCountRequest.create = function create(properties) { - return new GetDocumentsSplitCountRequest(properties); - }; + /** + * Encodes the specified CountEntry message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.verify|verify} messages. + * @function encodeDelimited + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.ICountEntry} message CountEntry message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + CountEntry.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; - /** - * Encodes the specified GetDocumentsSplitCountRequest message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.verify|verify} messages. - * @function encode - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest - * @static - * @param {org.dash.platform.dapi.v0.IGetDocumentsSplitCountRequest} message GetDocumentsSplitCountRequest message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - GetDocumentsSplitCountRequest.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.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.encode(message.v0, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); - return writer; - }; + /** + * Decodes a CountEntry message from the specified reader or buffer. + * @function decode + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry + * @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.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry} CountEntry + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + CountEntry.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.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.inKey = reader.bytes(); + break; + case 2: + message.key = reader.bytes(); + break; + case 3: + message.count = reader.uint64(); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; - /** - * Encodes the specified GetDocumentsSplitCountRequest message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.verify|verify} messages. - * @function encodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest - * @static - * @param {org.dash.platform.dapi.v0.IGetDocumentsSplitCountRequest} message GetDocumentsSplitCountRequest message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - GetDocumentsSplitCountRequest.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; + /** + * Decodes a CountEntry message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry} CountEntry + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + CountEntry.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; - /** - * Decodes a GetDocumentsSplitCountRequest message from the specified reader or buffer. - * @function decode - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest - * @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.GetDocumentsSplitCountRequest} GetDocumentsSplitCountRequest - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - GetDocumentsSplitCountRequest.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.GetDocumentsSplitCountRequest(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.v0 = $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.decode(reader, reader.uint32()); - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; + /** + * Verifies a CountEntry message. + * @function verify + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + CountEntry.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.inKey != null && message.hasOwnProperty("inKey")) + if (!(message.inKey && typeof message.inKey.length === "number" || $util.isString(message.inKey))) + return "inKey: buffer expected"; + if (message.key != null && message.hasOwnProperty("key")) + if (!(message.key && typeof message.key.length === "number" || $util.isString(message.key))) + return "key: buffer expected"; + if (message.count != null && message.hasOwnProperty("count")) + if (!$util.isInteger(message.count) && !(message.count && $util.isInteger(message.count.low) && $util.isInteger(message.count.high))) + return "count: integer|Long expected"; + return null; + }; - /** - * Decodes a GetDocumentsSplitCountRequest message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest} GetDocumentsSplitCountRequest - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - GetDocumentsSplitCountRequest.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a GetDocumentsSplitCountRequest message. - * @function verify - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - GetDocumentsSplitCountRequest.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.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.verify(message.v0); - if (error) - return "v0." + error; - } - } - return null; - }; - - /** - * Creates a GetDocumentsSplitCountRequest message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest - * @static - * @param {Object.} object Plain object - * @returns {org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest} GetDocumentsSplitCountRequest - */ - GetDocumentsSplitCountRequest.fromObject = function fromObject(object) { - if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest) - return object; - var message = new $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest(); - if (object.v0 != null) { - if (typeof object.v0 !== "object") - throw TypeError(".org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.v0: object expected"); - message.v0 = $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.fromObject(object.v0); - } - return message; - }; - - /** - * Creates a plain object from a GetDocumentsSplitCountRequest message. Also converts values to other types if specified. - * @function toObject - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest - * @static - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest} message GetDocumentsSplitCountRequest - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - GetDocumentsSplitCountRequest.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.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.toObject(message.v0, options); - if (options.oneofs) - object.version = "v0"; - } - return object; - }; - - /** - * Converts this GetDocumentsSplitCountRequest to JSON. - * @function toJSON - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest - * @instance - * @returns {Object.} JSON object - */ - GetDocumentsSplitCountRequest.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0 = (function() { - - /** - * Properties of a GetDocumentsSplitCountRequestV0. - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest - * @interface IGetDocumentsSplitCountRequestV0 - * @property {Uint8Array|null} [dataContractId] GetDocumentsSplitCountRequestV0 dataContractId - * @property {string|null} [documentType] GetDocumentsSplitCountRequestV0 documentType - * @property {Uint8Array|null} [where] GetDocumentsSplitCountRequestV0 where - * @property {string|null} [splitCountByIndexProperty] GetDocumentsSplitCountRequestV0 splitCountByIndexProperty - * @property {boolean|null} [prove] GetDocumentsSplitCountRequestV0 prove - */ - - /** - * Constructs a new GetDocumentsSplitCountRequestV0. - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest - * @classdesc Represents a GetDocumentsSplitCountRequestV0. - * @implements IGetDocumentsSplitCountRequestV0 - * @constructor - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.IGetDocumentsSplitCountRequestV0=} [properties] Properties to set - */ - function GetDocumentsSplitCountRequestV0(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]]; - } - - /** - * GetDocumentsSplitCountRequestV0 dataContractId. - * @member {Uint8Array} dataContractId - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0 - * @instance - */ - GetDocumentsSplitCountRequestV0.prototype.dataContractId = $util.newBuffer([]); - - /** - * GetDocumentsSplitCountRequestV0 documentType. - * @member {string} documentType - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0 - * @instance - */ - GetDocumentsSplitCountRequestV0.prototype.documentType = ""; - - /** - * GetDocumentsSplitCountRequestV0 where. - * @member {Uint8Array} where - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0 - * @instance - */ - GetDocumentsSplitCountRequestV0.prototype.where = $util.newBuffer([]); - - /** - * GetDocumentsSplitCountRequestV0 splitCountByIndexProperty. - * @member {string} splitCountByIndexProperty - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0 - * @instance - */ - GetDocumentsSplitCountRequestV0.prototype.splitCountByIndexProperty = ""; - - /** - * GetDocumentsSplitCountRequestV0 prove. - * @member {boolean} prove - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0 - * @instance - */ - GetDocumentsSplitCountRequestV0.prototype.prove = false; - - /** - * Creates a new GetDocumentsSplitCountRequestV0 instance using the specified properties. - * @function create - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0 - * @static - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.IGetDocumentsSplitCountRequestV0=} [properties] Properties to set - * @returns {org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0} GetDocumentsSplitCountRequestV0 instance - */ - GetDocumentsSplitCountRequestV0.create = function create(properties) { - return new GetDocumentsSplitCountRequestV0(properties); - }; - - /** - * Encodes the specified GetDocumentsSplitCountRequestV0 message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.verify|verify} messages. - * @function encode - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0 - * @static - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.IGetDocumentsSplitCountRequestV0} message GetDocumentsSplitCountRequestV0 message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - GetDocumentsSplitCountRequestV0.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.documentType != null && Object.hasOwnProperty.call(message, "documentType")) - writer.uint32(/* id 2, wireType 2 =*/18).string(message.documentType); - if (message.where != null && Object.hasOwnProperty.call(message, "where")) - writer.uint32(/* id 3, wireType 2 =*/26).bytes(message.where); - if (message.splitCountByIndexProperty != null && Object.hasOwnProperty.call(message, "splitCountByIndexProperty")) - writer.uint32(/* id 4, wireType 2 =*/34).string(message.splitCountByIndexProperty); - if (message.prove != null && Object.hasOwnProperty.call(message, "prove")) - writer.uint32(/* id 5, wireType 0 =*/40).bool(message.prove); - return writer; - }; - - /** - * Encodes the specified GetDocumentsSplitCountRequestV0 message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.verify|verify} messages. - * @function encodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0 - * @static - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.IGetDocumentsSplitCountRequestV0} message GetDocumentsSplitCountRequestV0 message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - GetDocumentsSplitCountRequestV0.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a GetDocumentsSplitCountRequestV0 message from the specified reader or buffer. - * @function decode - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0 - * @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.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0} GetDocumentsSplitCountRequestV0 - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - GetDocumentsSplitCountRequestV0.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.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.dataContractId = reader.bytes(); - break; - case 2: - message.documentType = reader.string(); - break; - case 3: - message.where = reader.bytes(); - break; - case 4: - message.splitCountByIndexProperty = reader.string(); - break; - case 5: - message.prove = reader.bool(); - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a GetDocumentsSplitCountRequestV0 message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0 - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0} GetDocumentsSplitCountRequestV0 - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - GetDocumentsSplitCountRequestV0.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a GetDocumentsSplitCountRequestV0 message. - * @function verify - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0 - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - GetDocumentsSplitCountRequestV0.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - 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.documentType != null && message.hasOwnProperty("documentType")) - if (!$util.isString(message.documentType)) - return "documentType: string expected"; - if (message.where != null && message.hasOwnProperty("where")) - if (!(message.where && typeof message.where.length === "number" || $util.isString(message.where))) - return "where: buffer expected"; - if (message.splitCountByIndexProperty != null && message.hasOwnProperty("splitCountByIndexProperty")) - if (!$util.isString(message.splitCountByIndexProperty)) - return "splitCountByIndexProperty: string expected"; - if (message.prove != null && message.hasOwnProperty("prove")) - if (typeof message.prove !== "boolean") - return "prove: boolean expected"; - return null; - }; - - /** - * Creates a GetDocumentsSplitCountRequestV0 message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0 - * @static - * @param {Object.} object Plain object - * @returns {org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0} GetDocumentsSplitCountRequestV0 - */ - GetDocumentsSplitCountRequestV0.fromObject = function fromObject(object) { - if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0) - return object; - var message = new $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0(); - 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.documentType != null) - message.documentType = String(object.documentType); - if (object.where != null) - if (typeof object.where === "string") - $util.base64.decode(object.where, message.where = $util.newBuffer($util.base64.length(object.where)), 0); - else if (object.where.length >= 0) - message.where = object.where; - if (object.splitCountByIndexProperty != null) - message.splitCountByIndexProperty = String(object.splitCountByIndexProperty); - if (object.prove != null) - message.prove = Boolean(object.prove); - return message; - }; - - /** - * Creates a plain object from a GetDocumentsSplitCountRequestV0 message. Also converts values to other types if specified. - * @function toObject - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0 - * @static - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0} message GetDocumentsSplitCountRequestV0 - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - GetDocumentsSplitCountRequestV0.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.documentType = ""; - if (options.bytes === String) - object.where = ""; - else { - object.where = []; - if (options.bytes !== Array) - object.where = $util.newBuffer(object.where); - } - object.splitCountByIndexProperty = ""; - 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.documentType != null && message.hasOwnProperty("documentType")) - object.documentType = message.documentType; - if (message.where != null && message.hasOwnProperty("where")) - object.where = options.bytes === String ? $util.base64.encode(message.where, 0, message.where.length) : options.bytes === Array ? Array.prototype.slice.call(message.where) : message.where; - if (message.splitCountByIndexProperty != null && message.hasOwnProperty("splitCountByIndexProperty")) - object.splitCountByIndexProperty = message.splitCountByIndexProperty; - if (message.prove != null && message.hasOwnProperty("prove")) - object.prove = message.prove; - return object; - }; - - /** - * Converts this GetDocumentsSplitCountRequestV0 to JSON. - * @function toJSON - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0 - * @instance - * @returns {Object.} JSON object - */ - GetDocumentsSplitCountRequestV0.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - return GetDocumentsSplitCountRequestV0; - })(); - - return GetDocumentsSplitCountRequest; - })(); - - v0.GetDocumentsSplitCountResponse = (function() { - - /** - * Properties of a GetDocumentsSplitCountResponse. - * @memberof org.dash.platform.dapi.v0 - * @interface IGetDocumentsSplitCountResponse - * @property {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.IGetDocumentsSplitCountResponseV0|null} [v0] GetDocumentsSplitCountResponse v0 - */ - - /** - * Constructs a new GetDocumentsSplitCountResponse. - * @memberof org.dash.platform.dapi.v0 - * @classdesc Represents a GetDocumentsSplitCountResponse. - * @implements IGetDocumentsSplitCountResponse - * @constructor - * @param {org.dash.platform.dapi.v0.IGetDocumentsSplitCountResponse=} [properties] Properties to set - */ - function GetDocumentsSplitCountResponse(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]]; - } - - /** - * GetDocumentsSplitCountResponse v0. - * @member {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.IGetDocumentsSplitCountResponseV0|null|undefined} v0 - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse - * @instance - */ - GetDocumentsSplitCountResponse.prototype.v0 = null; - - // OneOf field names bound to virtual getters and setters - var $oneOfFields; - - /** - * GetDocumentsSplitCountResponse version. - * @member {"v0"|undefined} version - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse - * @instance - */ - Object.defineProperty(GetDocumentsSplitCountResponse.prototype, "version", { - get: $util.oneOfGetter($oneOfFields = ["v0"]), - set: $util.oneOfSetter($oneOfFields) - }); - - /** - * Creates a new GetDocumentsSplitCountResponse instance using the specified properties. - * @function create - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse - * @static - * @param {org.dash.platform.dapi.v0.IGetDocumentsSplitCountResponse=} [properties] Properties to set - * @returns {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse} GetDocumentsSplitCountResponse instance - */ - GetDocumentsSplitCountResponse.create = function create(properties) { - return new GetDocumentsSplitCountResponse(properties); - }; - - /** - * Encodes the specified GetDocumentsSplitCountResponse message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.verify|verify} messages. - * @function encode - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse - * @static - * @param {org.dash.platform.dapi.v0.IGetDocumentsSplitCountResponse} message GetDocumentsSplitCountResponse message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - GetDocumentsSplitCountResponse.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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.encode(message.v0, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified GetDocumentsSplitCountResponse message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.verify|verify} messages. - * @function encodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse - * @static - * @param {org.dash.platform.dapi.v0.IGetDocumentsSplitCountResponse} message GetDocumentsSplitCountResponse message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - GetDocumentsSplitCountResponse.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a GetDocumentsSplitCountResponse message from the specified reader or buffer. - * @function decode - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse - * @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.GetDocumentsSplitCountResponse} GetDocumentsSplitCountResponse - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - GetDocumentsSplitCountResponse.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.GetDocumentsSplitCountResponse(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.v0 = $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.decode(reader, reader.uint32()); - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a GetDocumentsSplitCountResponse message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse} GetDocumentsSplitCountResponse - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - GetDocumentsSplitCountResponse.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a GetDocumentsSplitCountResponse message. - * @function verify - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - GetDocumentsSplitCountResponse.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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.verify(message.v0); - if (error) - return "v0." + error; - } - } - return null; - }; - - /** - * Creates a GetDocumentsSplitCountResponse message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse - * @static - * @param {Object.} object Plain object - * @returns {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse} GetDocumentsSplitCountResponse - */ - GetDocumentsSplitCountResponse.fromObject = function fromObject(object) { - if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse) - return object; - var message = new $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse(); - if (object.v0 != null) { - if (typeof object.v0 !== "object") - throw TypeError(".org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.v0: object expected"); - message.v0 = $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.fromObject(object.v0); - } - return message; - }; - - /** - * Creates a plain object from a GetDocumentsSplitCountResponse message. Also converts values to other types if specified. - * @function toObject - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse - * @static - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse} message GetDocumentsSplitCountResponse - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - GetDocumentsSplitCountResponse.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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.toObject(message.v0, options); - if (options.oneofs) - object.version = "v0"; - } - return object; - }; - - /** - * Converts this GetDocumentsSplitCountResponse to JSON. - * @function toJSON - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse - * @instance - * @returns {Object.} JSON object - */ - GetDocumentsSplitCountResponse.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 = (function() { - - /** - * Properties of a GetDocumentsSplitCountResponseV0. - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse - * @interface IGetDocumentsSplitCountResponseV0 - * @property {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.ISplitCounts|null} [splitCounts] GetDocumentsSplitCountResponseV0 splitCounts - * @property {org.dash.platform.dapi.v0.IProof|null} [proof] GetDocumentsSplitCountResponseV0 proof - * @property {org.dash.platform.dapi.v0.IResponseMetadata|null} [metadata] GetDocumentsSplitCountResponseV0 metadata - */ - - /** - * Constructs a new GetDocumentsSplitCountResponseV0. - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse - * @classdesc Represents a GetDocumentsSplitCountResponseV0. - * @implements IGetDocumentsSplitCountResponseV0 - * @constructor - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.IGetDocumentsSplitCountResponseV0=} [properties] Properties to set - */ - function GetDocumentsSplitCountResponseV0(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]]; - } - - /** - * GetDocumentsSplitCountResponseV0 splitCounts. - * @member {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.ISplitCounts|null|undefined} splitCounts - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 - * @instance - */ - GetDocumentsSplitCountResponseV0.prototype.splitCounts = null; - - /** - * GetDocumentsSplitCountResponseV0 proof. - * @member {org.dash.platform.dapi.v0.IProof|null|undefined} proof - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 - * @instance - */ - GetDocumentsSplitCountResponseV0.prototype.proof = null; - - /** - * GetDocumentsSplitCountResponseV0 metadata. - * @member {org.dash.platform.dapi.v0.IResponseMetadata|null|undefined} metadata - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 - * @instance - */ - GetDocumentsSplitCountResponseV0.prototype.metadata = null; - - // OneOf field names bound to virtual getters and setters - var $oneOfFields; - - /** - * GetDocumentsSplitCountResponseV0 result. - * @member {"splitCounts"|"proof"|undefined} result - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 - * @instance - */ - Object.defineProperty(GetDocumentsSplitCountResponseV0.prototype, "result", { - get: $util.oneOfGetter($oneOfFields = ["splitCounts", "proof"]), - set: $util.oneOfSetter($oneOfFields) - }); - - /** - * Creates a new GetDocumentsSplitCountResponseV0 instance using the specified properties. - * @function create - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 - * @static - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.IGetDocumentsSplitCountResponseV0=} [properties] Properties to set - * @returns {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0} GetDocumentsSplitCountResponseV0 instance - */ - GetDocumentsSplitCountResponseV0.create = function create(properties) { - return new GetDocumentsSplitCountResponseV0(properties); - }; - - /** - * Encodes the specified GetDocumentsSplitCountResponseV0 message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.verify|verify} messages. - * @function encode - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 - * @static - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.IGetDocumentsSplitCountResponseV0} message GetDocumentsSplitCountResponseV0 message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - GetDocumentsSplitCountResponseV0.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.splitCounts != null && Object.hasOwnProperty.call(message, "splitCounts")) - $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.encode(message.splitCounts, 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 GetDocumentsSplitCountResponseV0 message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.verify|verify} messages. - * @function encodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 - * @static - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.IGetDocumentsSplitCountResponseV0} message GetDocumentsSplitCountResponseV0 message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - GetDocumentsSplitCountResponseV0.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a GetDocumentsSplitCountResponseV0 message from the specified reader or buffer. - * @function decode - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 - * @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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0} GetDocumentsSplitCountResponseV0 - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - GetDocumentsSplitCountResponseV0.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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.splitCounts = $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.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 GetDocumentsSplitCountResponseV0 message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0} GetDocumentsSplitCountResponseV0 - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - GetDocumentsSplitCountResponseV0.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; + /** + * Creates a CountEntry message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry + * @static + * @param {Object.} object Plain object + * @returns {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry} CountEntry + */ + CountEntry.fromObject = function fromObject(object) { + if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry) + return object; + var message = new $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry(); + if (object.inKey != null) + if (typeof object.inKey === "string") + $util.base64.decode(object.inKey, message.inKey = $util.newBuffer($util.base64.length(object.inKey)), 0); + else if (object.inKey.length >= 0) + message.inKey = object.inKey; + if (object.key != null) + if (typeof object.key === "string") + $util.base64.decode(object.key, message.key = $util.newBuffer($util.base64.length(object.key)), 0); + else if (object.key.length >= 0) + message.key = object.key; + if (object.count != null) + if ($util.Long) + (message.count = $util.Long.fromValue(object.count)).unsigned = true; + else if (typeof object.count === "string") + message.count = parseInt(object.count, 10); + else if (typeof object.count === "number") + message.count = object.count; + else if (typeof object.count === "object") + message.count = new $util.LongBits(object.count.low >>> 0, object.count.high >>> 0).toNumber(true); + return message; + }; - /** - * Verifies a GetDocumentsSplitCountResponseV0 message. - * @function verify - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - GetDocumentsSplitCountResponseV0.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - var properties = {}; - if (message.splitCounts != null && message.hasOwnProperty("splitCounts")) { - properties.result = 1; - { - var error = $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.verify(message.splitCounts); - if (error) - return "splitCounts." + 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; + /** + * Creates a plain object from a CountEntry message. Also converts values to other types if specified. + * @function toObject + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry} message CountEntry + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + CountEntry.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.defaults) { + if (options.bytes === String) + object.inKey = ""; + else { + object.inKey = []; + if (options.bytes !== Array) + object.inKey = $util.newBuffer(object.inKey); + } + if (options.bytes === String) + object.key = ""; + else { + object.key = []; + if (options.bytes !== Array) + object.key = $util.newBuffer(object.key); + } + if ($util.Long) { + var long = new $util.Long(0, 0, true); + object.count = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else + object.count = options.longs === String ? "0" : 0; } - } - 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 GetDocumentsSplitCountResponseV0 message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 - * @static - * @param {Object.} object Plain object - * @returns {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0} GetDocumentsSplitCountResponseV0 - */ - GetDocumentsSplitCountResponseV0.fromObject = function fromObject(object) { - if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0) + if (message.inKey != null && message.hasOwnProperty("inKey")) + object.inKey = options.bytes === String ? $util.base64.encode(message.inKey, 0, message.inKey.length) : options.bytes === Array ? Array.prototype.slice.call(message.inKey) : message.inKey; + if (message.key != null && message.hasOwnProperty("key")) + object.key = options.bytes === String ? $util.base64.encode(message.key, 0, message.key.length) : options.bytes === Array ? Array.prototype.slice.call(message.key) : message.key; + if (message.count != null && message.hasOwnProperty("count")) + if (typeof message.count === "number") + object.count = options.longs === String ? String(message.count) : message.count; + else + object.count = options.longs === String ? $util.Long.prototype.toString.call(message.count) : options.longs === Number ? new $util.LongBits(message.count.low >>> 0, message.count.high >>> 0).toNumber(true) : message.count; return object; - var message = new $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0(); - if (object.splitCounts != null) { - if (typeof object.splitCounts !== "object") - throw TypeError(".org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.splitCounts: object expected"); - message.splitCounts = $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.fromObject(object.splitCounts); - } - if (object.proof != null) { - if (typeof object.proof !== "object") - throw TypeError(".org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.metadata: object expected"); - message.metadata = $root.org.dash.platform.dapi.v0.ResponseMetadata.fromObject(object.metadata); - } - return message; - }; + }; - /** - * Creates a plain object from a GetDocumentsSplitCountResponseV0 message. Also converts values to other types if specified. - * @function toObject - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 - * @static - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0} message GetDocumentsSplitCountResponseV0 - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - GetDocumentsSplitCountResponseV0.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) - object.metadata = null; - if (message.splitCounts != null && message.hasOwnProperty("splitCounts")) { - object.splitCounts = $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.toObject(message.splitCounts, options); - if (options.oneofs) - object.result = "splitCounts"; - } - 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 CountEntry to JSON. + * @function toJSON + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry + * @instance + * @returns {Object.} JSON object + */ + CountEntry.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; - /** - * Converts this GetDocumentsSplitCountResponseV0 to JSON. - * @function toJSON - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 - * @instance - * @returns {Object.} JSON object - */ - GetDocumentsSplitCountResponseV0.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; + return CountEntry; + })(); - GetDocumentsSplitCountResponseV0.SplitCountEntry = (function() { + GetDocumentsCountResponseV0.CountEntries = (function() { /** - * Properties of a SplitCountEntry. - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 - * @interface ISplitCountEntry - * @property {Uint8Array|null} [key] SplitCountEntry key - * @property {number|Long|null} [count] SplitCountEntry count + * Properties of a CountEntries. + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0 + * @interface ICountEntries + * @property {Array.|null} [entries] CountEntries entries */ /** - * Constructs a new SplitCountEntry. - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 - * @classdesc Represents a SplitCountEntry. - * @implements ISplitCountEntry + * Constructs a new CountEntries. + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0 + * @classdesc Represents a CountEntries. + * @implements ICountEntries * @constructor - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.ISplitCountEntry=} [properties] Properties to set + * @param {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.ICountEntries=} [properties] Properties to set */ - function SplitCountEntry(properties) { + function CountEntries(properties) { + this.entries = []; if (properties) for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) if (properties[keys[i]] != null) @@ -23195,88 +22508,78 @@ $root.org = (function() { } /** - * SplitCountEntry key. - * @member {Uint8Array} key - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry - * @instance - */ - SplitCountEntry.prototype.key = $util.newBuffer([]); - - /** - * SplitCountEntry count. - * @member {number|Long} count - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry + * CountEntries entries. + * @member {Array.} entries + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries * @instance */ - SplitCountEntry.prototype.count = $util.Long ? $util.Long.fromBits(0,0,true) : 0; + CountEntries.prototype.entries = $util.emptyArray; /** - * Creates a new SplitCountEntry instance using the specified properties. + * Creates a new CountEntries instance using the specified properties. * @function create - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries * @static - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.ISplitCountEntry=} [properties] Properties to set - * @returns {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry} SplitCountEntry instance + * @param {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.ICountEntries=} [properties] Properties to set + * @returns {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries} CountEntries instance */ - SplitCountEntry.create = function create(properties) { - return new SplitCountEntry(properties); + CountEntries.create = function create(properties) { + return new CountEntries(properties); }; /** - * Encodes the specified SplitCountEntry message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.verify|verify} messages. + * Encodes the specified CountEntries message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.verify|verify} messages. * @function encode - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries * @static - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.ISplitCountEntry} message SplitCountEntry message or plain object to encode + * @param {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.ICountEntries} message CountEntries message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - SplitCountEntry.encode = function encode(message, writer) { + CountEntries.encode = function encode(message, writer) { if (!writer) writer = $Writer.create(); - if (message.key != null && Object.hasOwnProperty.call(message, "key")) - writer.uint32(/* id 1, wireType 2 =*/10).bytes(message.key); - if (message.count != null && Object.hasOwnProperty.call(message, "count")) - writer.uint32(/* id 2, wireType 0 =*/16).uint64(message.count); + if (message.entries != null && message.entries.length) + for (var i = 0; i < message.entries.length; ++i) + $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.encode(message.entries[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); return writer; }; /** - * Encodes the specified SplitCountEntry message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.verify|verify} messages. + * Encodes the specified CountEntries message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.verify|verify} messages. * @function encodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries * @static - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.ISplitCountEntry} message SplitCountEntry message or plain object to encode + * @param {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.ICountEntries} message CountEntries message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - SplitCountEntry.encodeDelimited = function encodeDelimited(message, writer) { + CountEntries.encodeDelimited = function encodeDelimited(message, writer) { return this.encode(message, writer).ldelim(); }; /** - * Decodes a SplitCountEntry message from the specified reader or buffer. + * Decodes a CountEntries message from the specified reader or buffer. * @function decode - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries * @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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry} SplitCountEntry + * @returns {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries} CountEntries * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - SplitCountEntry.decode = function decode(reader, length) { + CountEntries.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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry(); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries(); while (reader.pos < end) { var tag = reader.uint32(); switch (tag >>> 3) { case 1: - message.key = reader.bytes(); - break; - case 2: - message.count = reader.uint64(); + if (!(message.entries && message.entries.length)) + message.entries = []; + message.entries.push($root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.decode(reader, reader.uint32())); break; default: reader.skipType(tag & 7); @@ -23287,140 +22590,125 @@ $root.org = (function() { }; /** - * Decodes a SplitCountEntry message from the specified reader or buffer, length delimited. + * Decodes a CountEntries message from the specified reader or buffer, length delimited. * @function decodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries * @static * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry} SplitCountEntry + * @returns {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries} CountEntries * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - SplitCountEntry.decodeDelimited = function decodeDelimited(reader) { + CountEntries.decodeDelimited = function decodeDelimited(reader) { if (!(reader instanceof $Reader)) reader = new $Reader(reader); return this.decode(reader, reader.uint32()); }; /** - * Verifies a SplitCountEntry message. + * Verifies a CountEntries message. * @function verify - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries * @static * @param {Object.} message Plain object to verify * @returns {string|null} `null` if valid, otherwise the reason why it is not */ - SplitCountEntry.verify = function verify(message) { + CountEntries.verify = function verify(message) { if (typeof message !== "object" || message === null) return "object expected"; - if (message.key != null && message.hasOwnProperty("key")) - if (!(message.key && typeof message.key.length === "number" || $util.isString(message.key))) - return "key: buffer expected"; - if (message.count != null && message.hasOwnProperty("count")) - if (!$util.isInteger(message.count) && !(message.count && $util.isInteger(message.count.low) && $util.isInteger(message.count.high))) - return "count: integer|Long expected"; + 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.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.verify(message.entries[i]); + if (error) + return "entries." + error; + } + } return null; }; /** - * Creates a SplitCountEntry message from a plain object. Also converts values to their respective internal types. + * Creates a CountEntries message from a plain object. Also converts values to their respective internal types. * @function fromObject - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries * @static * @param {Object.} object Plain object - * @returns {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry} SplitCountEntry + * @returns {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries} CountEntries */ - SplitCountEntry.fromObject = function fromObject(object) { - if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry) + CountEntries.fromObject = function fromObject(object) { + if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries) return object; - var message = new $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry(); - if (object.key != null) - if (typeof object.key === "string") - $util.base64.decode(object.key, message.key = $util.newBuffer($util.base64.length(object.key)), 0); - else if (object.key.length >= 0) - message.key = object.key; - if (object.count != null) - if ($util.Long) - (message.count = $util.Long.fromValue(object.count)).unsigned = true; - else if (typeof object.count === "string") - message.count = parseInt(object.count, 10); - else if (typeof object.count === "number") - message.count = object.count; - else if (typeof object.count === "object") - message.count = new $util.LongBits(object.count.low >>> 0, object.count.high >>> 0).toNumber(true); + var message = new $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries(); + if (object.entries) { + if (!Array.isArray(object.entries)) + throw TypeError(".org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.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.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.entries: object expected"); + message.entries[i] = $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.fromObject(object.entries[i]); + } + } return message; }; /** - * Creates a plain object from a SplitCountEntry message. Also converts values to other types if specified. + * Creates a plain object from a CountEntries message. Also converts values to other types if specified. * @function toObject - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries * @static - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry} message SplitCountEntry + * @param {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries} message CountEntries * @param {$protobuf.IConversionOptions} [options] Conversion options * @returns {Object.} Plain object */ - SplitCountEntry.toObject = function toObject(message, options) { + CountEntries.toObject = function toObject(message, options) { if (!options) options = {}; var object = {}; - if (options.defaults) { - if (options.bytes === String) - object.key = ""; - else { - object.key = []; - if (options.bytes !== Array) - object.key = $util.newBuffer(object.key); - } - if ($util.Long) { - var long = new $util.Long(0, 0, true); - object.count = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; - } else - object.count = options.longs === String ? "0" : 0; + if (options.arrays || options.defaults) + object.entries = []; + 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.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.toObject(message.entries[j], options); } - if (message.key != null && message.hasOwnProperty("key")) - object.key = options.bytes === String ? $util.base64.encode(message.key, 0, message.key.length) : options.bytes === Array ? Array.prototype.slice.call(message.key) : message.key; - if (message.count != null && message.hasOwnProperty("count")) - if (typeof message.count === "number") - object.count = options.longs === String ? String(message.count) : message.count; - else - object.count = options.longs === String ? $util.Long.prototype.toString.call(message.count) : options.longs === Number ? new $util.LongBits(message.count.low >>> 0, message.count.high >>> 0).toNumber(true) : message.count; return object; }; /** - * Converts this SplitCountEntry to JSON. + * Converts this CountEntries to JSON. * @function toJSON - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries * @instance * @returns {Object.} JSON object */ - SplitCountEntry.prototype.toJSON = function toJSON() { + CountEntries.prototype.toJSON = function toJSON() { return this.constructor.toObject(this, $protobuf.util.toJSONOptions); }; - return SplitCountEntry; + return CountEntries; })(); - GetDocumentsSplitCountResponseV0.SplitCounts = (function() { + GetDocumentsCountResponseV0.CountResults = (function() { /** - * Properties of a SplitCounts. - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 - * @interface ISplitCounts - * @property {Array.|null} [entries] SplitCounts entries + * Properties of a CountResults. + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0 + * @interface ICountResults + * @property {number|Long|null} [aggregateCount] CountResults aggregateCount + * @property {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.ICountEntries|null} [entries] CountResults entries */ /** - * Constructs a new SplitCounts. - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 - * @classdesc Represents a SplitCounts. - * @implements ISplitCounts + * Constructs a new CountResults. + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0 + * @classdesc Represents a CountResults. + * @implements ICountResults * @constructor - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.ISplitCounts=} [properties] Properties to set + * @param {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.ICountResults=} [properties] Properties to set */ - function SplitCounts(properties) { - this.entries = []; + function CountResults(properties) { if (properties) for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) if (properties[keys[i]] != null) @@ -23428,78 +22716,102 @@ $root.org = (function() { } /** - * SplitCounts entries. - * @member {Array.} entries - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts + * CountResults aggregateCount. + * @member {number|Long} aggregateCount + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults + * @instance + */ + CountResults.prototype.aggregateCount = $util.Long ? $util.Long.fromBits(0,0,true) : 0; + + /** + * CountResults entries. + * @member {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.ICountEntries|null|undefined} entries + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults * @instance */ - SplitCounts.prototype.entries = $util.emptyArray; + CountResults.prototype.entries = null; + + // OneOf field names bound to virtual getters and setters + var $oneOfFields; + + /** + * CountResults variant. + * @member {"aggregateCount"|"entries"|undefined} variant + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults + * @instance + */ + Object.defineProperty(CountResults.prototype, "variant", { + get: $util.oneOfGetter($oneOfFields = ["aggregateCount", "entries"]), + set: $util.oneOfSetter($oneOfFields) + }); /** - * Creates a new SplitCounts instance using the specified properties. + * Creates a new CountResults instance using the specified properties. * @function create - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults * @static - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.ISplitCounts=} [properties] Properties to set - * @returns {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts} SplitCounts instance + * @param {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.ICountResults=} [properties] Properties to set + * @returns {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults} CountResults instance */ - SplitCounts.create = function create(properties) { - return new SplitCounts(properties); + CountResults.create = function create(properties) { + return new CountResults(properties); }; /** - * Encodes the specified SplitCounts message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.verify|verify} messages. + * Encodes the specified CountResults message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.verify|verify} messages. * @function encode - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults * @static - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.ISplitCounts} message SplitCounts message or plain object to encode + * @param {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.ICountResults} message CountResults message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - SplitCounts.encode = function encode(message, writer) { + CountResults.encode = function encode(message, writer) { if (!writer) writer = $Writer.create(); - if (message.entries != null && message.entries.length) - for (var i = 0; i < message.entries.length; ++i) - $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.encode(message.entries[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); + if (message.aggregateCount != null && Object.hasOwnProperty.call(message, "aggregateCount")) + writer.uint32(/* id 1, wireType 0 =*/8).uint64(message.aggregateCount); + if (message.entries != null && Object.hasOwnProperty.call(message, "entries")) + $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.encode(message.entries, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); return writer; }; /** - * Encodes the specified SplitCounts message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.verify|verify} messages. + * Encodes the specified CountResults message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.verify|verify} messages. * @function encodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults * @static - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.ISplitCounts} message SplitCounts message or plain object to encode + * @param {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.ICountResults} message CountResults message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - SplitCounts.encodeDelimited = function encodeDelimited(message, writer) { + CountResults.encodeDelimited = function encodeDelimited(message, writer) { return this.encode(message, writer).ldelim(); }; /** - * Decodes a SplitCounts message from the specified reader or buffer. + * Decodes a CountResults message from the specified reader or buffer. * @function decode - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults * @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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts} SplitCounts + * @returns {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults} CountResults * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - SplitCounts.decode = function decode(reader, length) { + CountResults.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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts(); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults(); while (reader.pos < end) { var tag = reader.uint32(); switch (tag >>> 3) { case 1: - if (!(message.entries && message.entries.length)) - message.entries = []; - message.entries.push($root.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.decode(reader, reader.uint32())); + message.aggregateCount = reader.uint64(); + break; + case 2: + message.entries = $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.decode(reader, reader.uint32()); break; default: reader.skipType(tag & 7); @@ -23510,37 +22822,44 @@ $root.org = (function() { }; /** - * Decodes a SplitCounts message from the specified reader or buffer, length delimited. + * Decodes a CountResults message from the specified reader or buffer, length delimited. * @function decodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults * @static * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts} SplitCounts + * @returns {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults} CountResults * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - SplitCounts.decodeDelimited = function decodeDelimited(reader) { + CountResults.decodeDelimited = function decodeDelimited(reader) { if (!(reader instanceof $Reader)) reader = new $Reader(reader); return this.decode(reader, reader.uint32()); }; /** - * Verifies a SplitCounts message. + * Verifies a CountResults message. * @function verify - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults * @static * @param {Object.} message Plain object to verify * @returns {string|null} `null` if valid, otherwise the reason why it is not */ - SplitCounts.verify = function verify(message) { + CountResults.verify = function verify(message) { if (typeof message !== "object" || message === null) return "object expected"; + var properties = {}; + if (message.aggregateCount != null && message.hasOwnProperty("aggregateCount")) { + properties.variant = 1; + if (!$util.isInteger(message.aggregateCount) && !(message.aggregateCount && $util.isInteger(message.aggregateCount.low) && $util.isInteger(message.aggregateCount.high))) + return "aggregateCount: integer|Long expected"; + } 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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.verify(message.entries[i]); + if (properties.variant === 1) + return "variant: multiple values"; + properties.variant = 1; + { + var error = $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.verify(message.entries); if (error) return "entries." + error; } @@ -23549,71 +22868,81 @@ $root.org = (function() { }; /** - * Creates a SplitCounts message from a plain object. Also converts values to their respective internal types. + * Creates a CountResults message from a plain object. Also converts values to their respective internal types. * @function fromObject - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults * @static * @param {Object.} object Plain object - * @returns {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts} SplitCounts + * @returns {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults} CountResults */ - SplitCounts.fromObject = function fromObject(object) { - if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts) + CountResults.fromObject = function fromObject(object) { + if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults) return object; - var message = new $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts(); - if (object.entries) { - if (!Array.isArray(object.entries)) - throw TypeError(".org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.entries: object expected"); - message.entries[i] = $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.fromObject(object.entries[i]); - } + var message = new $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults(); + if (object.aggregateCount != null) + if ($util.Long) + (message.aggregateCount = $util.Long.fromValue(object.aggregateCount)).unsigned = true; + else if (typeof object.aggregateCount === "string") + message.aggregateCount = parseInt(object.aggregateCount, 10); + else if (typeof object.aggregateCount === "number") + message.aggregateCount = object.aggregateCount; + else if (typeof object.aggregateCount === "object") + message.aggregateCount = new $util.LongBits(object.aggregateCount.low >>> 0, object.aggregateCount.high >>> 0).toNumber(true); + if (object.entries != null) { + if (typeof object.entries !== "object") + throw TypeError(".org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.entries: object expected"); + message.entries = $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.fromObject(object.entries); } return message; }; /** - * Creates a plain object from a SplitCounts message. Also converts values to other types if specified. + * Creates a plain object from a CountResults message. Also converts values to other types if specified. * @function toObject - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults * @static - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts} message SplitCounts + * @param {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults} message CountResults * @param {$protobuf.IConversionOptions} [options] Conversion options * @returns {Object.} Plain object */ - SplitCounts.toObject = function toObject(message, options) { + CountResults.toObject = function toObject(message, options) { if (!options) options = {}; var object = {}; - if (options.arrays || options.defaults) - object.entries = []; - 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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.toObject(message.entries[j], options); + if (message.aggregateCount != null && message.hasOwnProperty("aggregateCount")) { + if (typeof message.aggregateCount === "number") + object.aggregateCount = options.longs === String ? String(message.aggregateCount) : message.aggregateCount; + else + object.aggregateCount = options.longs === String ? $util.Long.prototype.toString.call(message.aggregateCount) : options.longs === Number ? new $util.LongBits(message.aggregateCount.low >>> 0, message.aggregateCount.high >>> 0).toNumber(true) : message.aggregateCount; + if (options.oneofs) + object.variant = "aggregateCount"; + } + if (message.entries != null && message.hasOwnProperty("entries")) { + object.entries = $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.toObject(message.entries, options); + if (options.oneofs) + object.variant = "entries"; } return object; }; /** - * Converts this SplitCounts to JSON. + * Converts this CountResults to JSON. * @function toJSON - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults * @instance * @returns {Object.} JSON object */ - SplitCounts.prototype.toJSON = function toJSON() { + CountResults.prototype.toJSON = function toJSON() { return this.constructor.toObject(this, $protobuf.util.toJSONOptions); }; - return SplitCounts; + return CountResults; })(); - return GetDocumentsSplitCountResponseV0; + return GetDocumentsCountResponseV0; })(); - return GetDocumentsSplitCountResponse; + return GetDocumentsCountResponse; })(); v0.GetIdentityByPublicKeyHashRequest = (function() { diff --git a/packages/dapi-grpc/clients/platform/v0/java/org/dash/platform/dapi/v0/PlatformGrpc.java b/packages/dapi-grpc/clients/platform/v0/java/org/dash/platform/dapi/v0/PlatformGrpc.java index e35b3783ab0..e17802268c1 100644 --- a/packages/dapi-grpc/clients/platform/v0/java/org/dash/platform/dapi/v0/PlatformGrpc.java +++ b/packages/dapi-grpc/clients/platform/v0/java/org/dash/platform/dapi/v0/PlatformGrpc.java @@ -511,37 +511,6 @@ org.dash.platform.dapi.v0.PlatformOuterClass.GetDocumentsCountResponse> getGetDo return getGetDocumentsCountMethod; } - private static volatile io.grpc.MethodDescriptor getGetDocumentsSplitCountMethod; - - @io.grpc.stub.annotations.RpcMethod( - fullMethodName = SERVICE_NAME + '/' + "getDocumentsSplitCount", - requestType = org.dash.platform.dapi.v0.PlatformOuterClass.GetDocumentsSplitCountRequest.class, - responseType = org.dash.platform.dapi.v0.PlatformOuterClass.GetDocumentsSplitCountResponse.class, - methodType = io.grpc.MethodDescriptor.MethodType.UNARY) - public static io.grpc.MethodDescriptor getGetDocumentsSplitCountMethod() { - io.grpc.MethodDescriptor getGetDocumentsSplitCountMethod; - if ((getGetDocumentsSplitCountMethod = PlatformGrpc.getGetDocumentsSplitCountMethod) == null) { - synchronized (PlatformGrpc.class) { - if ((getGetDocumentsSplitCountMethod = PlatformGrpc.getGetDocumentsSplitCountMethod) == null) { - PlatformGrpc.getGetDocumentsSplitCountMethod = getGetDocumentsSplitCountMethod = - io.grpc.MethodDescriptor.newBuilder() - .setType(io.grpc.MethodDescriptor.MethodType.UNARY) - .setFullMethodName(generateFullMethodName(SERVICE_NAME, "getDocumentsSplitCount")) - .setSampledToLocalTracing(true) - .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - org.dash.platform.dapi.v0.PlatformOuterClass.GetDocumentsSplitCountRequest.getDefaultInstance())) - .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( - org.dash.platform.dapi.v0.PlatformOuterClass.GetDocumentsSplitCountResponse.getDefaultInstance())) - .setSchemaDescriptor(new PlatformMethodDescriptorSupplier("getDocumentsSplitCount")) - .build(); - } - } - } - return getGetDocumentsSplitCountMethod; - } - private static volatile io.grpc.MethodDescriptor getGetIdentityByPublicKeyHashMethod; @@ -2162,13 +2131,6 @@ public void getDocumentsCount(org.dash.platform.dapi.v0.PlatformOuterClass.GetDo io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getGetDocumentsCountMethod(), responseObserver); } - /** - */ - public void getDocumentsSplitCount(org.dash.platform.dapi.v0.PlatformOuterClass.GetDocumentsSplitCountRequest request, - io.grpc.stub.StreamObserver responseObserver) { - io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getGetDocumentsSplitCountMethod(), responseObserver); - } - /** */ public void getIdentityByPublicKeyHash(org.dash.platform.dapi.v0.PlatformOuterClass.GetIdentityByPublicKeyHashRequest request, @@ -2630,13 +2592,6 @@ public void getRecentCompactedNullifierChanges(org.dash.platform.dapi.v0.Platfor org.dash.platform.dapi.v0.PlatformOuterClass.GetDocumentsCountRequest, org.dash.platform.dapi.v0.PlatformOuterClass.GetDocumentsCountResponse>( this, METHODID_GET_DOCUMENTS_COUNT))) - .addMethod( - getGetDocumentsSplitCountMethod(), - io.grpc.stub.ServerCalls.asyncUnaryCall( - new MethodHandlers< - org.dash.platform.dapi.v0.PlatformOuterClass.GetDocumentsSplitCountRequest, - org.dash.platform.dapi.v0.PlatformOuterClass.GetDocumentsSplitCountResponse>( - this, METHODID_GET_DOCUMENTS_SPLIT_COUNT))) .addMethod( getGetIdentityByPublicKeyHashMethod(), io.grpc.stub.ServerCalls.asyncUnaryCall( @@ -3115,14 +3070,6 @@ public void getDocumentsCount(org.dash.platform.dapi.v0.PlatformOuterClass.GetDo getChannel().newCall(getGetDocumentsCountMethod(), getCallOptions()), request, responseObserver); } - /** - */ - public void getDocumentsSplitCount(org.dash.platform.dapi.v0.PlatformOuterClass.GetDocumentsSplitCountRequest request, - io.grpc.stub.StreamObserver responseObserver) { - io.grpc.stub.ClientCalls.asyncUnaryCall( - getChannel().newCall(getGetDocumentsSplitCountMethod(), getCallOptions()), request, responseObserver); - } - /** */ public void getIdentityByPublicKeyHash(org.dash.platform.dapi.v0.PlatformOuterClass.GetIdentityByPublicKeyHashRequest request, @@ -3647,13 +3594,6 @@ public org.dash.platform.dapi.v0.PlatformOuterClass.GetDocumentsCountResponse ge getChannel(), getGetDocumentsCountMethod(), getCallOptions(), request); } - /** - */ - public org.dash.platform.dapi.v0.PlatformOuterClass.GetDocumentsSplitCountResponse getDocumentsSplitCount(org.dash.platform.dapi.v0.PlatformOuterClass.GetDocumentsSplitCountRequest request) { - return io.grpc.stub.ClientCalls.blockingUnaryCall( - getChannel(), getGetDocumentsSplitCountMethod(), getCallOptions(), request); - } - /** */ public org.dash.platform.dapi.v0.PlatformOuterClass.GetIdentityByPublicKeyHashResponse getIdentityByPublicKeyHash(org.dash.platform.dapi.v0.PlatformOuterClass.GetIdentityByPublicKeyHashRequest request) { @@ -4147,14 +4087,6 @@ public com.google.common.util.concurrent.ListenableFuture getDocumentsSplitCount( - org.dash.platform.dapi.v0.PlatformOuterClass.GetDocumentsSplitCountRequest request) { - return io.grpc.stub.ClientCalls.futureUnaryCall( - getChannel().newCall(getGetDocumentsSplitCountMethod(), getCallOptions()), request); - } - /** */ public com.google.common.util.concurrent.ListenableFuture getIdentityByPublicKeyHash( @@ -4566,54 +4498,53 @@ public com.google.common.util.concurrent.ListenableFuture implements io.grpc.stub.ServerCalls.UnaryMethod, @@ -4696,10 +4627,6 @@ public void invoke(Req request, io.grpc.stub.StreamObserver responseObserv serviceImpl.getDocumentsCount((org.dash.platform.dapi.v0.PlatformOuterClass.GetDocumentsCountRequest) request, (io.grpc.stub.StreamObserver) responseObserver); break; - case METHODID_GET_DOCUMENTS_SPLIT_COUNT: - serviceImpl.getDocumentsSplitCount((org.dash.platform.dapi.v0.PlatformOuterClass.GetDocumentsSplitCountRequest) request, - (io.grpc.stub.StreamObserver) responseObserver); - break; case METHODID_GET_IDENTITY_BY_PUBLIC_KEY_HASH: serviceImpl.getIdentityByPublicKeyHash((org.dash.platform.dapi.v0.PlatformOuterClass.GetIdentityByPublicKeyHashRequest) request, (io.grpc.stub.StreamObserver) responseObserver); @@ -4965,7 +4892,6 @@ public static io.grpc.ServiceDescriptor getServiceDescriptor() { .addMethod(getGetDataContractsMethod()) .addMethod(getGetDocumentsMethod()) .addMethod(getGetDocumentsCountMethod()) - .addMethod(getGetDocumentsSplitCountMethod()) .addMethod(getGetIdentityByPublicKeyHashMethod()) .addMethod(getGetIdentityByNonUniquePublicKeyHashMethod()) .addMethod(getWaitForStateTransitionResultMethod()) 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 98ff6239af1..f4ef49f1d2b 100644 --- a/packages/dapi-grpc/clients/platform/v0/nodejs/platform_pbjs.js +++ b/packages/dapi-grpc/clients/platform/v0/nodejs/platform_pbjs.js @@ -614,39 +614,6 @@ $root.org = (function() { * @variation 2 */ - /** - * Callback as used by {@link org.dash.platform.dapi.v0.Platform#getDocumentsSplitCount}. - * @memberof org.dash.platform.dapi.v0.Platform - * @typedef getDocumentsSplitCountCallback - * @type {function} - * @param {Error|null} error Error, if any - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse} [response] GetDocumentsSplitCountResponse - */ - - /** - * Calls getDocumentsSplitCount. - * @function getDocumentsSplitCount - * @memberof org.dash.platform.dapi.v0.Platform - * @instance - * @param {org.dash.platform.dapi.v0.IGetDocumentsSplitCountRequest} request GetDocumentsSplitCountRequest message or plain object - * @param {org.dash.platform.dapi.v0.Platform.getDocumentsSplitCountCallback} callback Node-style callback called with the error, if any, and GetDocumentsSplitCountResponse - * @returns {undefined} - * @variation 1 - */ - Object.defineProperty(Platform.prototype.getDocumentsSplitCount = function getDocumentsSplitCount(request, callback) { - return this.rpcCall(getDocumentsSplitCount, $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest, $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse, request, callback); - }, "name", { value: "getDocumentsSplitCount" }); - - /** - * Calls getDocumentsSplitCount. - * @function getDocumentsSplitCount - * @memberof org.dash.platform.dapi.v0.Platform - * @instance - * @param {org.dash.platform.dapi.v0.IGetDocumentsSplitCountRequest} request GetDocumentsSplitCountRequest message or plain object - * @returns {Promise} Promise - * @variation 2 - */ - /** * Callback as used by {@link org.dash.platform.dapi.v0.Platform#getIdentityByPublicKeyHash}. * @memberof org.dash.platform.dapi.v0.Platform @@ -20924,6 +20891,9 @@ $root.org = (function() { * @property {Uint8Array|null} [dataContractId] GetDocumentsCountRequestV0 dataContractId * @property {string|null} [documentType] GetDocumentsCountRequestV0 documentType * @property {Uint8Array|null} [where] GetDocumentsCountRequestV0 where + * @property {boolean|null} [returnDistinctCountsInRange] GetDocumentsCountRequestV0 returnDistinctCountsInRange + * @property {Uint8Array|null} [orderBy] GetDocumentsCountRequestV0 orderBy + * @property {number|null} [limit] GetDocumentsCountRequestV0 limit * @property {boolean|null} [prove] GetDocumentsCountRequestV0 prove */ @@ -20966,6 +20936,30 @@ $root.org = (function() { */ GetDocumentsCountRequestV0.prototype.where = $util.newBuffer([]); + /** + * GetDocumentsCountRequestV0 returnDistinctCountsInRange. + * @member {boolean} returnDistinctCountsInRange + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0 + * @instance + */ + GetDocumentsCountRequestV0.prototype.returnDistinctCountsInRange = false; + + /** + * GetDocumentsCountRequestV0 orderBy. + * @member {Uint8Array} orderBy + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0 + * @instance + */ + GetDocumentsCountRequestV0.prototype.orderBy = $util.newBuffer([]); + + /** + * GetDocumentsCountRequestV0 limit. + * @member {number} limit + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0 + * @instance + */ + GetDocumentsCountRequestV0.prototype.limit = 0; + /** * GetDocumentsCountRequestV0 prove. * @member {boolean} prove @@ -21004,8 +20998,14 @@ $root.org = (function() { writer.uint32(/* id 2, wireType 2 =*/18).string(message.documentType); if (message.where != null && Object.hasOwnProperty.call(message, "where")) writer.uint32(/* id 3, wireType 2 =*/26).bytes(message.where); + if (message.returnDistinctCountsInRange != null && Object.hasOwnProperty.call(message, "returnDistinctCountsInRange")) + writer.uint32(/* id 4, wireType 0 =*/32).bool(message.returnDistinctCountsInRange); + if (message.orderBy != null && Object.hasOwnProperty.call(message, "orderBy")) + writer.uint32(/* id 5, wireType 2 =*/42).bytes(message.orderBy); + if (message.limit != null && Object.hasOwnProperty.call(message, "limit")) + writer.uint32(/* id 6, wireType 0 =*/48).uint32(message.limit); if (message.prove != null && Object.hasOwnProperty.call(message, "prove")) - writer.uint32(/* id 4, wireType 0 =*/32).bool(message.prove); + writer.uint32(/* id 7, wireType 0 =*/56).bool(message.prove); return writer; }; @@ -21050,6 +21050,15 @@ $root.org = (function() { message.where = reader.bytes(); break; case 4: + message.returnDistinctCountsInRange = reader.bool(); + break; + case 5: + message.orderBy = reader.bytes(); + break; + case 6: + message.limit = reader.uint32(); + break; + case 7: message.prove = reader.bool(); break; default: @@ -21096,6 +21105,15 @@ $root.org = (function() { if (message.where != null && message.hasOwnProperty("where")) if (!(message.where && typeof message.where.length === "number" || $util.isString(message.where))) return "where: buffer expected"; + if (message.returnDistinctCountsInRange != null && message.hasOwnProperty("returnDistinctCountsInRange")) + if (typeof message.returnDistinctCountsInRange !== "boolean") + return "returnDistinctCountsInRange: boolean expected"; + if (message.orderBy != null && message.hasOwnProperty("orderBy")) + if (!(message.orderBy && typeof message.orderBy.length === "number" || $util.isString(message.orderBy))) + return "orderBy: buffer expected"; + if (message.limit != null && message.hasOwnProperty("limit")) + if (!$util.isInteger(message.limit)) + return "limit: integer expected"; if (message.prove != null && message.hasOwnProperty("prove")) if (typeof message.prove !== "boolean") return "prove: boolean expected"; @@ -21126,6 +21144,15 @@ $root.org = (function() { $util.base64.decode(object.where, message.where = $util.newBuffer($util.base64.length(object.where)), 0); else if (object.where.length >= 0) message.where = object.where; + if (object.returnDistinctCountsInRange != null) + message.returnDistinctCountsInRange = Boolean(object.returnDistinctCountsInRange); + if (object.orderBy != null) + if (typeof object.orderBy === "string") + $util.base64.decode(object.orderBy, message.orderBy = $util.newBuffer($util.base64.length(object.orderBy)), 0); + else if (object.orderBy.length >= 0) + message.orderBy = object.orderBy; + if (object.limit != null) + message.limit = object.limit >>> 0; if (object.prove != null) message.prove = Boolean(object.prove); return message; @@ -21160,6 +21187,15 @@ $root.org = (function() { if (options.bytes !== Array) object.where = $util.newBuffer(object.where); } + object.returnDistinctCountsInRange = false; + if (options.bytes === String) + object.orderBy = ""; + else { + object.orderBy = []; + if (options.bytes !== Array) + object.orderBy = $util.newBuffer(object.orderBy); + } + object.limit = 0; object.prove = false; } if (message.dataContractId != null && message.hasOwnProperty("dataContractId")) @@ -21168,6 +21204,12 @@ $root.org = (function() { object.documentType = message.documentType; if (message.where != null && message.hasOwnProperty("where")) object.where = options.bytes === String ? $util.base64.encode(message.where, 0, message.where.length) : options.bytes === Array ? Array.prototype.slice.call(message.where) : message.where; + if (message.returnDistinctCountsInRange != null && message.hasOwnProperty("returnDistinctCountsInRange")) + object.returnDistinctCountsInRange = message.returnDistinctCountsInRange; + if (message.orderBy != null && message.hasOwnProperty("orderBy")) + object.orderBy = options.bytes === String ? $util.base64.encode(message.orderBy, 0, message.orderBy.length) : options.bytes === Array ? Array.prototype.slice.call(message.orderBy) : message.orderBy; + if (message.limit != null && message.hasOwnProperty("limit")) + object.limit = message.limit; if (message.prove != null && message.hasOwnProperty("prove")) object.prove = message.prove; return object; @@ -21404,7 +21446,7 @@ $root.org = (function() { * Properties of a GetDocumentsCountResponseV0. * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse * @interface IGetDocumentsCountResponseV0 - * @property {number|Long|null} [count] GetDocumentsCountResponseV0 count + * @property {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.ICountResults|null} [counts] GetDocumentsCountResponseV0 counts * @property {org.dash.platform.dapi.v0.IProof|null} [proof] GetDocumentsCountResponseV0 proof * @property {org.dash.platform.dapi.v0.IResponseMetadata|null} [metadata] GetDocumentsCountResponseV0 metadata */ @@ -21425,12 +21467,12 @@ $root.org = (function() { } /** - * GetDocumentsCountResponseV0 count. - * @member {number|Long} count + * GetDocumentsCountResponseV0 counts. + * @member {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.ICountResults|null|undefined} counts * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0 * @instance */ - GetDocumentsCountResponseV0.prototype.count = $util.Long ? $util.Long.fromBits(0,0,true) : 0; + GetDocumentsCountResponseV0.prototype.counts = null; /** * GetDocumentsCountResponseV0 proof. @@ -21453,12 +21495,12 @@ $root.org = (function() { /** * GetDocumentsCountResponseV0 result. - * @member {"count"|"proof"|undefined} result + * @member {"counts"|"proof"|undefined} result * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0 * @instance */ Object.defineProperty(GetDocumentsCountResponseV0.prototype, "result", { - get: $util.oneOfGetter($oneOfFields = ["count", "proof"]), + get: $util.oneOfGetter($oneOfFields = ["counts", "proof"]), set: $util.oneOfSetter($oneOfFields) }); @@ -21486,8 +21528,8 @@ $root.org = (function() { GetDocumentsCountResponseV0.encode = function encode(message, writer) { if (!writer) writer = $Writer.create(); - if (message.count != null && Object.hasOwnProperty.call(message, "count")) - writer.uint32(/* id 1, wireType 0 =*/8).uint64(message.count); + if (message.counts != null && Object.hasOwnProperty.call(message, "counts")) + $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.encode(message.counts, 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")) @@ -21527,7 +21569,7 @@ $root.org = (function() { var tag = reader.uint32(); switch (tag >>> 3) { case 1: - message.count = reader.uint64(); + message.counts = $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.decode(reader, reader.uint32()); break; case 2: message.proof = $root.org.dash.platform.dapi.v0.Proof.decode(reader, reader.uint32()); @@ -21571,10 +21613,13 @@ $root.org = (function() { if (typeof message !== "object" || message === null) return "object expected"; var properties = {}; - if (message.count != null && message.hasOwnProperty("count")) { + if (message.counts != null && message.hasOwnProperty("counts")) { properties.result = 1; - if (!$util.isInteger(message.count) && !(message.count && $util.isInteger(message.count.low) && $util.isInteger(message.count.high))) - return "count: integer|Long expected"; + { + var error = $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.verify(message.counts); + if (error) + return "counts." + error; + } } if (message.proof != null && message.hasOwnProperty("proof")) { if (properties.result === 1) @@ -21606,15 +21651,11 @@ $root.org = (function() { if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0) return object; var message = new $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0(); - if (object.count != null) - if ($util.Long) - (message.count = $util.Long.fromValue(object.count)).unsigned = true; - else if (typeof object.count === "string") - message.count = parseInt(object.count, 10); - else if (typeof object.count === "number") - message.count = object.count; - else if (typeof object.count === "object") - message.count = new $util.LongBits(object.count.low >>> 0, object.count.high >>> 0).toNumber(true); + if (object.counts != null) { + if (typeof object.counts !== "object") + throw TypeError(".org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.counts: object expected"); + message.counts = $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.fromObject(object.counts); + } if (object.proof != null) { if (typeof object.proof !== "object") throw TypeError(".org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.proof: object expected"); @@ -21643,13 +21684,10 @@ $root.org = (function() { var object = {}; if (options.defaults) object.metadata = null; - if (message.count != null && message.hasOwnProperty("count")) { - if (typeof message.count === "number") - object.count = options.longs === String ? String(message.count) : message.count; - else - object.count = options.longs === String ? $util.Long.prototype.toString.call(message.count) : options.longs === Number ? new $util.LongBits(message.count.low >>> 0, message.count.high >>> 0).toNumber(true) : message.count; + if (message.counts != null && message.hasOwnProperty("counts")) { + object.counts = $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.toObject(message.counts, options); if (options.oneofs) - object.result = "count"; + object.result = "counts"; } if (message.proof != null && message.hasOwnProperty("proof")) { object.proof = $root.org.dash.platform.dapi.v0.Proof.toObject(message.proof, options); @@ -21672,1014 +21710,289 @@ $root.org = (function() { return this.constructor.toObject(this, $protobuf.util.toJSONOptions); }; - return GetDocumentsCountResponseV0; - })(); + GetDocumentsCountResponseV0.CountEntry = (function() { - return GetDocumentsCountResponse; - })(); + /** + * Properties of a CountEntry. + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0 + * @interface ICountEntry + * @property {Uint8Array|null} [inKey] CountEntry inKey + * @property {Uint8Array|null} [key] CountEntry key + * @property {number|Long|null} [count] CountEntry count + */ - v0.GetDocumentsSplitCountRequest = (function() { + /** + * Constructs a new CountEntry. + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0 + * @classdesc Represents a CountEntry. + * @implements ICountEntry + * @constructor + * @param {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.ICountEntry=} [properties] Properties to set + */ + function CountEntry(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]]; + } - /** - * Properties of a GetDocumentsSplitCountRequest. - * @memberof org.dash.platform.dapi.v0 - * @interface IGetDocumentsSplitCountRequest - * @property {org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.IGetDocumentsSplitCountRequestV0|null} [v0] GetDocumentsSplitCountRequest v0 - */ + /** + * CountEntry inKey. + * @member {Uint8Array} inKey + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry + * @instance + */ + CountEntry.prototype.inKey = $util.newBuffer([]); - /** - * Constructs a new GetDocumentsSplitCountRequest. - * @memberof org.dash.platform.dapi.v0 - * @classdesc Represents a GetDocumentsSplitCountRequest. - * @implements IGetDocumentsSplitCountRequest - * @constructor - * @param {org.dash.platform.dapi.v0.IGetDocumentsSplitCountRequest=} [properties] Properties to set - */ - function GetDocumentsSplitCountRequest(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]]; - } + /** + * CountEntry key. + * @member {Uint8Array} key + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry + * @instance + */ + CountEntry.prototype.key = $util.newBuffer([]); - /** - * GetDocumentsSplitCountRequest v0. - * @member {org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.IGetDocumentsSplitCountRequestV0|null|undefined} v0 - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest - * @instance - */ - GetDocumentsSplitCountRequest.prototype.v0 = null; + /** + * CountEntry count. + * @member {number|Long} count + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry + * @instance + */ + CountEntry.prototype.count = $util.Long ? $util.Long.fromBits(0,0,true) : 0; - // OneOf field names bound to virtual getters and setters - var $oneOfFields; + /** + * Creates a new CountEntry instance using the specified properties. + * @function create + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.ICountEntry=} [properties] Properties to set + * @returns {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry} CountEntry instance + */ + CountEntry.create = function create(properties) { + return new CountEntry(properties); + }; - /** - * GetDocumentsSplitCountRequest version. - * @member {"v0"|undefined} version - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest - * @instance - */ - Object.defineProperty(GetDocumentsSplitCountRequest.prototype, "version", { - get: $util.oneOfGetter($oneOfFields = ["v0"]), - set: $util.oneOfSetter($oneOfFields) - }); + /** + * Encodes the specified CountEntry message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.verify|verify} messages. + * @function encode + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.ICountEntry} message CountEntry message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + CountEntry.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.inKey != null && Object.hasOwnProperty.call(message, "inKey")) + writer.uint32(/* id 1, wireType 2 =*/10).bytes(message.inKey); + if (message.key != null && Object.hasOwnProperty.call(message, "key")) + writer.uint32(/* id 2, wireType 2 =*/18).bytes(message.key); + if (message.count != null && Object.hasOwnProperty.call(message, "count")) + writer.uint32(/* id 3, wireType 0 =*/24).uint64(message.count); + return writer; + }; - /** - * Creates a new GetDocumentsSplitCountRequest instance using the specified properties. - * @function create - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest - * @static - * @param {org.dash.platform.dapi.v0.IGetDocumentsSplitCountRequest=} [properties] Properties to set - * @returns {org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest} GetDocumentsSplitCountRequest instance - */ - GetDocumentsSplitCountRequest.create = function create(properties) { - return new GetDocumentsSplitCountRequest(properties); - }; + /** + * Encodes the specified CountEntry message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.verify|verify} messages. + * @function encodeDelimited + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.ICountEntry} message CountEntry message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + CountEntry.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; - /** - * Encodes the specified GetDocumentsSplitCountRequest message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.verify|verify} messages. - * @function encode - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest - * @static - * @param {org.dash.platform.dapi.v0.IGetDocumentsSplitCountRequest} message GetDocumentsSplitCountRequest message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - GetDocumentsSplitCountRequest.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.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.encode(message.v0, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); - return writer; - }; + /** + * Decodes a CountEntry message from the specified reader or buffer. + * @function decode + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry + * @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.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry} CountEntry + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + CountEntry.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.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.inKey = reader.bytes(); + break; + case 2: + message.key = reader.bytes(); + break; + case 3: + message.count = reader.uint64(); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; - /** - * Encodes the specified GetDocumentsSplitCountRequest message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.verify|verify} messages. - * @function encodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest - * @static - * @param {org.dash.platform.dapi.v0.IGetDocumentsSplitCountRequest} message GetDocumentsSplitCountRequest message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - GetDocumentsSplitCountRequest.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; + /** + * Decodes a CountEntry message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry} CountEntry + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + CountEntry.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; - /** - * Decodes a GetDocumentsSplitCountRequest message from the specified reader or buffer. - * @function decode - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest - * @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.GetDocumentsSplitCountRequest} GetDocumentsSplitCountRequest - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - GetDocumentsSplitCountRequest.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.GetDocumentsSplitCountRequest(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.v0 = $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.decode(reader, reader.uint32()); - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; + /** + * Verifies a CountEntry message. + * @function verify + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + CountEntry.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.inKey != null && message.hasOwnProperty("inKey")) + if (!(message.inKey && typeof message.inKey.length === "number" || $util.isString(message.inKey))) + return "inKey: buffer expected"; + if (message.key != null && message.hasOwnProperty("key")) + if (!(message.key && typeof message.key.length === "number" || $util.isString(message.key))) + return "key: buffer expected"; + if (message.count != null && message.hasOwnProperty("count")) + if (!$util.isInteger(message.count) && !(message.count && $util.isInteger(message.count.low) && $util.isInteger(message.count.high))) + return "count: integer|Long expected"; + return null; + }; - /** - * Decodes a GetDocumentsSplitCountRequest message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest} GetDocumentsSplitCountRequest - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - GetDocumentsSplitCountRequest.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a GetDocumentsSplitCountRequest message. - * @function verify - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - GetDocumentsSplitCountRequest.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.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.verify(message.v0); - if (error) - return "v0." + error; - } - } - return null; - }; - - /** - * Creates a GetDocumentsSplitCountRequest message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest - * @static - * @param {Object.} object Plain object - * @returns {org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest} GetDocumentsSplitCountRequest - */ - GetDocumentsSplitCountRequest.fromObject = function fromObject(object) { - if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest) - return object; - var message = new $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest(); - if (object.v0 != null) { - if (typeof object.v0 !== "object") - throw TypeError(".org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.v0: object expected"); - message.v0 = $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.fromObject(object.v0); - } - return message; - }; - - /** - * Creates a plain object from a GetDocumentsSplitCountRequest message. Also converts values to other types if specified. - * @function toObject - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest - * @static - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest} message GetDocumentsSplitCountRequest - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - GetDocumentsSplitCountRequest.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.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.toObject(message.v0, options); - if (options.oneofs) - object.version = "v0"; - } - return object; - }; - - /** - * Converts this GetDocumentsSplitCountRequest to JSON. - * @function toJSON - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest - * @instance - * @returns {Object.} JSON object - */ - GetDocumentsSplitCountRequest.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0 = (function() { - - /** - * Properties of a GetDocumentsSplitCountRequestV0. - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest - * @interface IGetDocumentsSplitCountRequestV0 - * @property {Uint8Array|null} [dataContractId] GetDocumentsSplitCountRequestV0 dataContractId - * @property {string|null} [documentType] GetDocumentsSplitCountRequestV0 documentType - * @property {Uint8Array|null} [where] GetDocumentsSplitCountRequestV0 where - * @property {string|null} [splitCountByIndexProperty] GetDocumentsSplitCountRequestV0 splitCountByIndexProperty - * @property {boolean|null} [prove] GetDocumentsSplitCountRequestV0 prove - */ - - /** - * Constructs a new GetDocumentsSplitCountRequestV0. - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest - * @classdesc Represents a GetDocumentsSplitCountRequestV0. - * @implements IGetDocumentsSplitCountRequestV0 - * @constructor - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.IGetDocumentsSplitCountRequestV0=} [properties] Properties to set - */ - function GetDocumentsSplitCountRequestV0(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]]; - } - - /** - * GetDocumentsSplitCountRequestV0 dataContractId. - * @member {Uint8Array} dataContractId - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0 - * @instance - */ - GetDocumentsSplitCountRequestV0.prototype.dataContractId = $util.newBuffer([]); - - /** - * GetDocumentsSplitCountRequestV0 documentType. - * @member {string} documentType - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0 - * @instance - */ - GetDocumentsSplitCountRequestV0.prototype.documentType = ""; - - /** - * GetDocumentsSplitCountRequestV0 where. - * @member {Uint8Array} where - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0 - * @instance - */ - GetDocumentsSplitCountRequestV0.prototype.where = $util.newBuffer([]); - - /** - * GetDocumentsSplitCountRequestV0 splitCountByIndexProperty. - * @member {string} splitCountByIndexProperty - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0 - * @instance - */ - GetDocumentsSplitCountRequestV0.prototype.splitCountByIndexProperty = ""; - - /** - * GetDocumentsSplitCountRequestV0 prove. - * @member {boolean} prove - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0 - * @instance - */ - GetDocumentsSplitCountRequestV0.prototype.prove = false; - - /** - * Creates a new GetDocumentsSplitCountRequestV0 instance using the specified properties. - * @function create - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0 - * @static - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.IGetDocumentsSplitCountRequestV0=} [properties] Properties to set - * @returns {org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0} GetDocumentsSplitCountRequestV0 instance - */ - GetDocumentsSplitCountRequestV0.create = function create(properties) { - return new GetDocumentsSplitCountRequestV0(properties); - }; - - /** - * Encodes the specified GetDocumentsSplitCountRequestV0 message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.verify|verify} messages. - * @function encode - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0 - * @static - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.IGetDocumentsSplitCountRequestV0} message GetDocumentsSplitCountRequestV0 message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - GetDocumentsSplitCountRequestV0.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.documentType != null && Object.hasOwnProperty.call(message, "documentType")) - writer.uint32(/* id 2, wireType 2 =*/18).string(message.documentType); - if (message.where != null && Object.hasOwnProperty.call(message, "where")) - writer.uint32(/* id 3, wireType 2 =*/26).bytes(message.where); - if (message.splitCountByIndexProperty != null && Object.hasOwnProperty.call(message, "splitCountByIndexProperty")) - writer.uint32(/* id 4, wireType 2 =*/34).string(message.splitCountByIndexProperty); - if (message.prove != null && Object.hasOwnProperty.call(message, "prove")) - writer.uint32(/* id 5, wireType 0 =*/40).bool(message.prove); - return writer; - }; - - /** - * Encodes the specified GetDocumentsSplitCountRequestV0 message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.verify|verify} messages. - * @function encodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0 - * @static - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.IGetDocumentsSplitCountRequestV0} message GetDocumentsSplitCountRequestV0 message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - GetDocumentsSplitCountRequestV0.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a GetDocumentsSplitCountRequestV0 message from the specified reader or buffer. - * @function decode - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0 - * @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.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0} GetDocumentsSplitCountRequestV0 - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - GetDocumentsSplitCountRequestV0.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.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.dataContractId = reader.bytes(); - break; - case 2: - message.documentType = reader.string(); - break; - case 3: - message.where = reader.bytes(); - break; - case 4: - message.splitCountByIndexProperty = reader.string(); - break; - case 5: - message.prove = reader.bool(); - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a GetDocumentsSplitCountRequestV0 message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0 - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0} GetDocumentsSplitCountRequestV0 - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - GetDocumentsSplitCountRequestV0.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a GetDocumentsSplitCountRequestV0 message. - * @function verify - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0 - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - GetDocumentsSplitCountRequestV0.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - 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.documentType != null && message.hasOwnProperty("documentType")) - if (!$util.isString(message.documentType)) - return "documentType: string expected"; - if (message.where != null && message.hasOwnProperty("where")) - if (!(message.where && typeof message.where.length === "number" || $util.isString(message.where))) - return "where: buffer expected"; - if (message.splitCountByIndexProperty != null && message.hasOwnProperty("splitCountByIndexProperty")) - if (!$util.isString(message.splitCountByIndexProperty)) - return "splitCountByIndexProperty: string expected"; - if (message.prove != null && message.hasOwnProperty("prove")) - if (typeof message.prove !== "boolean") - return "prove: boolean expected"; - return null; - }; - - /** - * Creates a GetDocumentsSplitCountRequestV0 message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0 - * @static - * @param {Object.} object Plain object - * @returns {org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0} GetDocumentsSplitCountRequestV0 - */ - GetDocumentsSplitCountRequestV0.fromObject = function fromObject(object) { - if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0) - return object; - var message = new $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0(); - 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.documentType != null) - message.documentType = String(object.documentType); - if (object.where != null) - if (typeof object.where === "string") - $util.base64.decode(object.where, message.where = $util.newBuffer($util.base64.length(object.where)), 0); - else if (object.where.length >= 0) - message.where = object.where; - if (object.splitCountByIndexProperty != null) - message.splitCountByIndexProperty = String(object.splitCountByIndexProperty); - if (object.prove != null) - message.prove = Boolean(object.prove); - return message; - }; - - /** - * Creates a plain object from a GetDocumentsSplitCountRequestV0 message. Also converts values to other types if specified. - * @function toObject - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0 - * @static - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0} message GetDocumentsSplitCountRequestV0 - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - GetDocumentsSplitCountRequestV0.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.documentType = ""; - if (options.bytes === String) - object.where = ""; - else { - object.where = []; - if (options.bytes !== Array) - object.where = $util.newBuffer(object.where); - } - object.splitCountByIndexProperty = ""; - 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.documentType != null && message.hasOwnProperty("documentType")) - object.documentType = message.documentType; - if (message.where != null && message.hasOwnProperty("where")) - object.where = options.bytes === String ? $util.base64.encode(message.where, 0, message.where.length) : options.bytes === Array ? Array.prototype.slice.call(message.where) : message.where; - if (message.splitCountByIndexProperty != null && message.hasOwnProperty("splitCountByIndexProperty")) - object.splitCountByIndexProperty = message.splitCountByIndexProperty; - if (message.prove != null && message.hasOwnProperty("prove")) - object.prove = message.prove; - return object; - }; - - /** - * Converts this GetDocumentsSplitCountRequestV0 to JSON. - * @function toJSON - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0 - * @instance - * @returns {Object.} JSON object - */ - GetDocumentsSplitCountRequestV0.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - return GetDocumentsSplitCountRequestV0; - })(); - - return GetDocumentsSplitCountRequest; - })(); - - v0.GetDocumentsSplitCountResponse = (function() { - - /** - * Properties of a GetDocumentsSplitCountResponse. - * @memberof org.dash.platform.dapi.v0 - * @interface IGetDocumentsSplitCountResponse - * @property {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.IGetDocumentsSplitCountResponseV0|null} [v0] GetDocumentsSplitCountResponse v0 - */ - - /** - * Constructs a new GetDocumentsSplitCountResponse. - * @memberof org.dash.platform.dapi.v0 - * @classdesc Represents a GetDocumentsSplitCountResponse. - * @implements IGetDocumentsSplitCountResponse - * @constructor - * @param {org.dash.platform.dapi.v0.IGetDocumentsSplitCountResponse=} [properties] Properties to set - */ - function GetDocumentsSplitCountResponse(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]]; - } - - /** - * GetDocumentsSplitCountResponse v0. - * @member {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.IGetDocumentsSplitCountResponseV0|null|undefined} v0 - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse - * @instance - */ - GetDocumentsSplitCountResponse.prototype.v0 = null; - - // OneOf field names bound to virtual getters and setters - var $oneOfFields; - - /** - * GetDocumentsSplitCountResponse version. - * @member {"v0"|undefined} version - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse - * @instance - */ - Object.defineProperty(GetDocumentsSplitCountResponse.prototype, "version", { - get: $util.oneOfGetter($oneOfFields = ["v0"]), - set: $util.oneOfSetter($oneOfFields) - }); - - /** - * Creates a new GetDocumentsSplitCountResponse instance using the specified properties. - * @function create - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse - * @static - * @param {org.dash.platform.dapi.v0.IGetDocumentsSplitCountResponse=} [properties] Properties to set - * @returns {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse} GetDocumentsSplitCountResponse instance - */ - GetDocumentsSplitCountResponse.create = function create(properties) { - return new GetDocumentsSplitCountResponse(properties); - }; - - /** - * Encodes the specified GetDocumentsSplitCountResponse message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.verify|verify} messages. - * @function encode - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse - * @static - * @param {org.dash.platform.dapi.v0.IGetDocumentsSplitCountResponse} message GetDocumentsSplitCountResponse message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - GetDocumentsSplitCountResponse.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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.encode(message.v0, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); - return writer; - }; - - /** - * Encodes the specified GetDocumentsSplitCountResponse message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.verify|verify} messages. - * @function encodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse - * @static - * @param {org.dash.platform.dapi.v0.IGetDocumentsSplitCountResponse} message GetDocumentsSplitCountResponse message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - GetDocumentsSplitCountResponse.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a GetDocumentsSplitCountResponse message from the specified reader or buffer. - * @function decode - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse - * @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.GetDocumentsSplitCountResponse} GetDocumentsSplitCountResponse - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - GetDocumentsSplitCountResponse.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.GetDocumentsSplitCountResponse(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.v0 = $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.decode(reader, reader.uint32()); - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a GetDocumentsSplitCountResponse message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse} GetDocumentsSplitCountResponse - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - GetDocumentsSplitCountResponse.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a GetDocumentsSplitCountResponse message. - * @function verify - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - GetDocumentsSplitCountResponse.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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.verify(message.v0); - if (error) - return "v0." + error; - } - } - return null; - }; - - /** - * Creates a GetDocumentsSplitCountResponse message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse - * @static - * @param {Object.} object Plain object - * @returns {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse} GetDocumentsSplitCountResponse - */ - GetDocumentsSplitCountResponse.fromObject = function fromObject(object) { - if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse) - return object; - var message = new $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse(); - if (object.v0 != null) { - if (typeof object.v0 !== "object") - throw TypeError(".org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.v0: object expected"); - message.v0 = $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.fromObject(object.v0); - } - return message; - }; - - /** - * Creates a plain object from a GetDocumentsSplitCountResponse message. Also converts values to other types if specified. - * @function toObject - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse - * @static - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse} message GetDocumentsSplitCountResponse - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - GetDocumentsSplitCountResponse.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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.toObject(message.v0, options); - if (options.oneofs) - object.version = "v0"; - } - return object; - }; - - /** - * Converts this GetDocumentsSplitCountResponse to JSON. - * @function toJSON - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse - * @instance - * @returns {Object.} JSON object - */ - GetDocumentsSplitCountResponse.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 = (function() { - - /** - * Properties of a GetDocumentsSplitCountResponseV0. - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse - * @interface IGetDocumentsSplitCountResponseV0 - * @property {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.ISplitCounts|null} [splitCounts] GetDocumentsSplitCountResponseV0 splitCounts - * @property {org.dash.platform.dapi.v0.IProof|null} [proof] GetDocumentsSplitCountResponseV0 proof - * @property {org.dash.platform.dapi.v0.IResponseMetadata|null} [metadata] GetDocumentsSplitCountResponseV0 metadata - */ - - /** - * Constructs a new GetDocumentsSplitCountResponseV0. - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse - * @classdesc Represents a GetDocumentsSplitCountResponseV0. - * @implements IGetDocumentsSplitCountResponseV0 - * @constructor - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.IGetDocumentsSplitCountResponseV0=} [properties] Properties to set - */ - function GetDocumentsSplitCountResponseV0(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]]; - } - - /** - * GetDocumentsSplitCountResponseV0 splitCounts. - * @member {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.ISplitCounts|null|undefined} splitCounts - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 - * @instance - */ - GetDocumentsSplitCountResponseV0.prototype.splitCounts = null; - - /** - * GetDocumentsSplitCountResponseV0 proof. - * @member {org.dash.platform.dapi.v0.IProof|null|undefined} proof - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 - * @instance - */ - GetDocumentsSplitCountResponseV0.prototype.proof = null; - - /** - * GetDocumentsSplitCountResponseV0 metadata. - * @member {org.dash.platform.dapi.v0.IResponseMetadata|null|undefined} metadata - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 - * @instance - */ - GetDocumentsSplitCountResponseV0.prototype.metadata = null; - - // OneOf field names bound to virtual getters and setters - var $oneOfFields; - - /** - * GetDocumentsSplitCountResponseV0 result. - * @member {"splitCounts"|"proof"|undefined} result - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 - * @instance - */ - Object.defineProperty(GetDocumentsSplitCountResponseV0.prototype, "result", { - get: $util.oneOfGetter($oneOfFields = ["splitCounts", "proof"]), - set: $util.oneOfSetter($oneOfFields) - }); - - /** - * Creates a new GetDocumentsSplitCountResponseV0 instance using the specified properties. - * @function create - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 - * @static - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.IGetDocumentsSplitCountResponseV0=} [properties] Properties to set - * @returns {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0} GetDocumentsSplitCountResponseV0 instance - */ - GetDocumentsSplitCountResponseV0.create = function create(properties) { - return new GetDocumentsSplitCountResponseV0(properties); - }; - - /** - * Encodes the specified GetDocumentsSplitCountResponseV0 message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.verify|verify} messages. - * @function encode - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 - * @static - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.IGetDocumentsSplitCountResponseV0} message GetDocumentsSplitCountResponseV0 message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - GetDocumentsSplitCountResponseV0.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.splitCounts != null && Object.hasOwnProperty.call(message, "splitCounts")) - $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.encode(message.splitCounts, 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 GetDocumentsSplitCountResponseV0 message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.verify|verify} messages. - * @function encodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 - * @static - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.IGetDocumentsSplitCountResponseV0} message GetDocumentsSplitCountResponseV0 message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - GetDocumentsSplitCountResponseV0.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a GetDocumentsSplitCountResponseV0 message from the specified reader or buffer. - * @function decode - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 - * @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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0} GetDocumentsSplitCountResponseV0 - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - GetDocumentsSplitCountResponseV0.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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.splitCounts = $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.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 GetDocumentsSplitCountResponseV0 message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0} GetDocumentsSplitCountResponseV0 - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - GetDocumentsSplitCountResponseV0.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; + /** + * Creates a CountEntry message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry + * @static + * @param {Object.} object Plain object + * @returns {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry} CountEntry + */ + CountEntry.fromObject = function fromObject(object) { + if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry) + return object; + var message = new $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry(); + if (object.inKey != null) + if (typeof object.inKey === "string") + $util.base64.decode(object.inKey, message.inKey = $util.newBuffer($util.base64.length(object.inKey)), 0); + else if (object.inKey.length >= 0) + message.inKey = object.inKey; + if (object.key != null) + if (typeof object.key === "string") + $util.base64.decode(object.key, message.key = $util.newBuffer($util.base64.length(object.key)), 0); + else if (object.key.length >= 0) + message.key = object.key; + if (object.count != null) + if ($util.Long) + (message.count = $util.Long.fromValue(object.count)).unsigned = true; + else if (typeof object.count === "string") + message.count = parseInt(object.count, 10); + else if (typeof object.count === "number") + message.count = object.count; + else if (typeof object.count === "object") + message.count = new $util.LongBits(object.count.low >>> 0, object.count.high >>> 0).toNumber(true); + return message; + }; - /** - * Verifies a GetDocumentsSplitCountResponseV0 message. - * @function verify - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - GetDocumentsSplitCountResponseV0.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - var properties = {}; - if (message.splitCounts != null && message.hasOwnProperty("splitCounts")) { - properties.result = 1; - { - var error = $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.verify(message.splitCounts); - if (error) - return "splitCounts." + 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; + /** + * Creates a plain object from a CountEntry message. Also converts values to other types if specified. + * @function toObject + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry + * @static + * @param {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry} message CountEntry + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + CountEntry.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.defaults) { + if (options.bytes === String) + object.inKey = ""; + else { + object.inKey = []; + if (options.bytes !== Array) + object.inKey = $util.newBuffer(object.inKey); + } + if (options.bytes === String) + object.key = ""; + else { + object.key = []; + if (options.bytes !== Array) + object.key = $util.newBuffer(object.key); + } + if ($util.Long) { + var long = new $util.Long(0, 0, true); + object.count = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + } else + object.count = options.longs === String ? "0" : 0; } - } - 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 GetDocumentsSplitCountResponseV0 message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 - * @static - * @param {Object.} object Plain object - * @returns {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0} GetDocumentsSplitCountResponseV0 - */ - GetDocumentsSplitCountResponseV0.fromObject = function fromObject(object) { - if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0) + if (message.inKey != null && message.hasOwnProperty("inKey")) + object.inKey = options.bytes === String ? $util.base64.encode(message.inKey, 0, message.inKey.length) : options.bytes === Array ? Array.prototype.slice.call(message.inKey) : message.inKey; + if (message.key != null && message.hasOwnProperty("key")) + object.key = options.bytes === String ? $util.base64.encode(message.key, 0, message.key.length) : options.bytes === Array ? Array.prototype.slice.call(message.key) : message.key; + if (message.count != null && message.hasOwnProperty("count")) + if (typeof message.count === "number") + object.count = options.longs === String ? String(message.count) : message.count; + else + object.count = options.longs === String ? $util.Long.prototype.toString.call(message.count) : options.longs === Number ? new $util.LongBits(message.count.low >>> 0, message.count.high >>> 0).toNumber(true) : message.count; return object; - var message = new $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0(); - if (object.splitCounts != null) { - if (typeof object.splitCounts !== "object") - throw TypeError(".org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.splitCounts: object expected"); - message.splitCounts = $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.fromObject(object.splitCounts); - } - if (object.proof != null) { - if (typeof object.proof !== "object") - throw TypeError(".org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.metadata: object expected"); - message.metadata = $root.org.dash.platform.dapi.v0.ResponseMetadata.fromObject(object.metadata); - } - return message; - }; + }; - /** - * Creates a plain object from a GetDocumentsSplitCountResponseV0 message. Also converts values to other types if specified. - * @function toObject - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 - * @static - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0} message GetDocumentsSplitCountResponseV0 - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - GetDocumentsSplitCountResponseV0.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) - object.metadata = null; - if (message.splitCounts != null && message.hasOwnProperty("splitCounts")) { - object.splitCounts = $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.toObject(message.splitCounts, options); - if (options.oneofs) - object.result = "splitCounts"; - } - 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 CountEntry to JSON. + * @function toJSON + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry + * @instance + * @returns {Object.} JSON object + */ + CountEntry.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; - /** - * Converts this GetDocumentsSplitCountResponseV0 to JSON. - * @function toJSON - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 - * @instance - * @returns {Object.} JSON object - */ - GetDocumentsSplitCountResponseV0.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; + return CountEntry; + })(); - GetDocumentsSplitCountResponseV0.SplitCountEntry = (function() { + GetDocumentsCountResponseV0.CountEntries = (function() { /** - * Properties of a SplitCountEntry. - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 - * @interface ISplitCountEntry - * @property {Uint8Array|null} [key] SplitCountEntry key - * @property {number|Long|null} [count] SplitCountEntry count + * Properties of a CountEntries. + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0 + * @interface ICountEntries + * @property {Array.|null} [entries] CountEntries entries */ /** - * Constructs a new SplitCountEntry. - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 - * @classdesc Represents a SplitCountEntry. - * @implements ISplitCountEntry + * Constructs a new CountEntries. + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0 + * @classdesc Represents a CountEntries. + * @implements ICountEntries * @constructor - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.ISplitCountEntry=} [properties] Properties to set + * @param {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.ICountEntries=} [properties] Properties to set */ - function SplitCountEntry(properties) { + function CountEntries(properties) { + this.entries = []; if (properties) for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) if (properties[keys[i]] != null) @@ -22687,88 +22000,78 @@ $root.org = (function() { } /** - * SplitCountEntry key. - * @member {Uint8Array} key - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry - * @instance - */ - SplitCountEntry.prototype.key = $util.newBuffer([]); - - /** - * SplitCountEntry count. - * @member {number|Long} count - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry + * CountEntries entries. + * @member {Array.} entries + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries * @instance */ - SplitCountEntry.prototype.count = $util.Long ? $util.Long.fromBits(0,0,true) : 0; + CountEntries.prototype.entries = $util.emptyArray; /** - * Creates a new SplitCountEntry instance using the specified properties. + * Creates a new CountEntries instance using the specified properties. * @function create - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries * @static - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.ISplitCountEntry=} [properties] Properties to set - * @returns {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry} SplitCountEntry instance + * @param {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.ICountEntries=} [properties] Properties to set + * @returns {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries} CountEntries instance */ - SplitCountEntry.create = function create(properties) { - return new SplitCountEntry(properties); + CountEntries.create = function create(properties) { + return new CountEntries(properties); }; /** - * Encodes the specified SplitCountEntry message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.verify|verify} messages. + * Encodes the specified CountEntries message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.verify|verify} messages. * @function encode - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries * @static - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.ISplitCountEntry} message SplitCountEntry message or plain object to encode + * @param {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.ICountEntries} message CountEntries message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - SplitCountEntry.encode = function encode(message, writer) { + CountEntries.encode = function encode(message, writer) { if (!writer) writer = $Writer.create(); - if (message.key != null && Object.hasOwnProperty.call(message, "key")) - writer.uint32(/* id 1, wireType 2 =*/10).bytes(message.key); - if (message.count != null && Object.hasOwnProperty.call(message, "count")) - writer.uint32(/* id 2, wireType 0 =*/16).uint64(message.count); + if (message.entries != null && message.entries.length) + for (var i = 0; i < message.entries.length; ++i) + $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.encode(message.entries[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); return writer; }; /** - * Encodes the specified SplitCountEntry message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.verify|verify} messages. + * Encodes the specified CountEntries message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.verify|verify} messages. * @function encodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries * @static - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.ISplitCountEntry} message SplitCountEntry message or plain object to encode + * @param {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.ICountEntries} message CountEntries message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - SplitCountEntry.encodeDelimited = function encodeDelimited(message, writer) { + CountEntries.encodeDelimited = function encodeDelimited(message, writer) { return this.encode(message, writer).ldelim(); }; /** - * Decodes a SplitCountEntry message from the specified reader or buffer. + * Decodes a CountEntries message from the specified reader or buffer. * @function decode - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries * @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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry} SplitCountEntry + * @returns {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries} CountEntries * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - SplitCountEntry.decode = function decode(reader, length) { + CountEntries.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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry(); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries(); while (reader.pos < end) { var tag = reader.uint32(); switch (tag >>> 3) { case 1: - message.key = reader.bytes(); - break; - case 2: - message.count = reader.uint64(); + if (!(message.entries && message.entries.length)) + message.entries = []; + message.entries.push($root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.decode(reader, reader.uint32())); break; default: reader.skipType(tag & 7); @@ -22779,140 +22082,125 @@ $root.org = (function() { }; /** - * Decodes a SplitCountEntry message from the specified reader or buffer, length delimited. + * Decodes a CountEntries message from the specified reader or buffer, length delimited. * @function decodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries * @static * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry} SplitCountEntry + * @returns {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries} CountEntries * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - SplitCountEntry.decodeDelimited = function decodeDelimited(reader) { + CountEntries.decodeDelimited = function decodeDelimited(reader) { if (!(reader instanceof $Reader)) reader = new $Reader(reader); return this.decode(reader, reader.uint32()); }; /** - * Verifies a SplitCountEntry message. + * Verifies a CountEntries message. * @function verify - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries * @static * @param {Object.} message Plain object to verify * @returns {string|null} `null` if valid, otherwise the reason why it is not */ - SplitCountEntry.verify = function verify(message) { + CountEntries.verify = function verify(message) { if (typeof message !== "object" || message === null) return "object expected"; - if (message.key != null && message.hasOwnProperty("key")) - if (!(message.key && typeof message.key.length === "number" || $util.isString(message.key))) - return "key: buffer expected"; - if (message.count != null && message.hasOwnProperty("count")) - if (!$util.isInteger(message.count) && !(message.count && $util.isInteger(message.count.low) && $util.isInteger(message.count.high))) - return "count: integer|Long expected"; + 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.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.verify(message.entries[i]); + if (error) + return "entries." + error; + } + } return null; }; /** - * Creates a SplitCountEntry message from a plain object. Also converts values to their respective internal types. + * Creates a CountEntries message from a plain object. Also converts values to their respective internal types. * @function fromObject - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries * @static * @param {Object.} object Plain object - * @returns {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry} SplitCountEntry + * @returns {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries} CountEntries */ - SplitCountEntry.fromObject = function fromObject(object) { - if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry) + CountEntries.fromObject = function fromObject(object) { + if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries) return object; - var message = new $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry(); - if (object.key != null) - if (typeof object.key === "string") - $util.base64.decode(object.key, message.key = $util.newBuffer($util.base64.length(object.key)), 0); - else if (object.key.length >= 0) - message.key = object.key; - if (object.count != null) - if ($util.Long) - (message.count = $util.Long.fromValue(object.count)).unsigned = true; - else if (typeof object.count === "string") - message.count = parseInt(object.count, 10); - else if (typeof object.count === "number") - message.count = object.count; - else if (typeof object.count === "object") - message.count = new $util.LongBits(object.count.low >>> 0, object.count.high >>> 0).toNumber(true); + var message = new $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries(); + if (object.entries) { + if (!Array.isArray(object.entries)) + throw TypeError(".org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.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.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.entries: object expected"); + message.entries[i] = $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.fromObject(object.entries[i]); + } + } return message; }; /** - * Creates a plain object from a SplitCountEntry message. Also converts values to other types if specified. + * Creates a plain object from a CountEntries message. Also converts values to other types if specified. * @function toObject - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries * @static - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry} message SplitCountEntry + * @param {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries} message CountEntries * @param {$protobuf.IConversionOptions} [options] Conversion options * @returns {Object.} Plain object */ - SplitCountEntry.toObject = function toObject(message, options) { + CountEntries.toObject = function toObject(message, options) { if (!options) options = {}; var object = {}; - if (options.defaults) { - if (options.bytes === String) - object.key = ""; - else { - object.key = []; - if (options.bytes !== Array) - object.key = $util.newBuffer(object.key); - } - if ($util.Long) { - var long = new $util.Long(0, 0, true); - object.count = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; - } else - object.count = options.longs === String ? "0" : 0; + if (options.arrays || options.defaults) + object.entries = []; + 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.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.toObject(message.entries[j], options); } - if (message.key != null && message.hasOwnProperty("key")) - object.key = options.bytes === String ? $util.base64.encode(message.key, 0, message.key.length) : options.bytes === Array ? Array.prototype.slice.call(message.key) : message.key; - if (message.count != null && message.hasOwnProperty("count")) - if (typeof message.count === "number") - object.count = options.longs === String ? String(message.count) : message.count; - else - object.count = options.longs === String ? $util.Long.prototype.toString.call(message.count) : options.longs === Number ? new $util.LongBits(message.count.low >>> 0, message.count.high >>> 0).toNumber(true) : message.count; return object; }; /** - * Converts this SplitCountEntry to JSON. + * Converts this CountEntries to JSON. * @function toJSON - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries * @instance * @returns {Object.} JSON object */ - SplitCountEntry.prototype.toJSON = function toJSON() { + CountEntries.prototype.toJSON = function toJSON() { return this.constructor.toObject(this, $protobuf.util.toJSONOptions); }; - return SplitCountEntry; + return CountEntries; })(); - GetDocumentsSplitCountResponseV0.SplitCounts = (function() { + GetDocumentsCountResponseV0.CountResults = (function() { /** - * Properties of a SplitCounts. - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 - * @interface ISplitCounts - * @property {Array.|null} [entries] SplitCounts entries + * Properties of a CountResults. + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0 + * @interface ICountResults + * @property {number|Long|null} [aggregateCount] CountResults aggregateCount + * @property {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.ICountEntries|null} [entries] CountResults entries */ /** - * Constructs a new SplitCounts. - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 - * @classdesc Represents a SplitCounts. - * @implements ISplitCounts + * Constructs a new CountResults. + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0 + * @classdesc Represents a CountResults. + * @implements ICountResults * @constructor - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.ISplitCounts=} [properties] Properties to set + * @param {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.ICountResults=} [properties] Properties to set */ - function SplitCounts(properties) { - this.entries = []; + function CountResults(properties) { if (properties) for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) if (properties[keys[i]] != null) @@ -22920,78 +22208,102 @@ $root.org = (function() { } /** - * SplitCounts entries. - * @member {Array.} entries - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts + * CountResults aggregateCount. + * @member {number|Long} aggregateCount + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults + * @instance + */ + CountResults.prototype.aggregateCount = $util.Long ? $util.Long.fromBits(0,0,true) : 0; + + /** + * CountResults entries. + * @member {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.ICountEntries|null|undefined} entries + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults * @instance */ - SplitCounts.prototype.entries = $util.emptyArray; + CountResults.prototype.entries = null; + + // OneOf field names bound to virtual getters and setters + var $oneOfFields; + + /** + * CountResults variant. + * @member {"aggregateCount"|"entries"|undefined} variant + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults + * @instance + */ + Object.defineProperty(CountResults.prototype, "variant", { + get: $util.oneOfGetter($oneOfFields = ["aggregateCount", "entries"]), + set: $util.oneOfSetter($oneOfFields) + }); /** - * Creates a new SplitCounts instance using the specified properties. + * Creates a new CountResults instance using the specified properties. * @function create - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults * @static - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.ISplitCounts=} [properties] Properties to set - * @returns {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts} SplitCounts instance + * @param {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.ICountResults=} [properties] Properties to set + * @returns {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults} CountResults instance */ - SplitCounts.create = function create(properties) { - return new SplitCounts(properties); + CountResults.create = function create(properties) { + return new CountResults(properties); }; /** - * Encodes the specified SplitCounts message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.verify|verify} messages. + * Encodes the specified CountResults message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.verify|verify} messages. * @function encode - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults * @static - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.ISplitCounts} message SplitCounts message or plain object to encode + * @param {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.ICountResults} message CountResults message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - SplitCounts.encode = function encode(message, writer) { + CountResults.encode = function encode(message, writer) { if (!writer) writer = $Writer.create(); - if (message.entries != null && message.entries.length) - for (var i = 0; i < message.entries.length; ++i) - $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.encode(message.entries[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); + if (message.aggregateCount != null && Object.hasOwnProperty.call(message, "aggregateCount")) + writer.uint32(/* id 1, wireType 0 =*/8).uint64(message.aggregateCount); + if (message.entries != null && Object.hasOwnProperty.call(message, "entries")) + $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.encode(message.entries, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); return writer; }; /** - * Encodes the specified SplitCounts message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.verify|verify} messages. + * Encodes the specified CountResults message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.verify|verify} messages. * @function encodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults * @static - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.ISplitCounts} message SplitCounts message or plain object to encode + * @param {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.ICountResults} message CountResults message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - SplitCounts.encodeDelimited = function encodeDelimited(message, writer) { + CountResults.encodeDelimited = function encodeDelimited(message, writer) { return this.encode(message, writer).ldelim(); }; /** - * Decodes a SplitCounts message from the specified reader or buffer. + * Decodes a CountResults message from the specified reader or buffer. * @function decode - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults * @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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts} SplitCounts + * @returns {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults} CountResults * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - SplitCounts.decode = function decode(reader, length) { + CountResults.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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts(); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults(); while (reader.pos < end) { var tag = reader.uint32(); switch (tag >>> 3) { case 1: - if (!(message.entries && message.entries.length)) - message.entries = []; - message.entries.push($root.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.decode(reader, reader.uint32())); + message.aggregateCount = reader.uint64(); + break; + case 2: + message.entries = $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.decode(reader, reader.uint32()); break; default: reader.skipType(tag & 7); @@ -23002,37 +22314,44 @@ $root.org = (function() { }; /** - * Decodes a SplitCounts message from the specified reader or buffer, length delimited. + * Decodes a CountResults message from the specified reader or buffer, length delimited. * @function decodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults * @static * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts} SplitCounts + * @returns {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults} CountResults * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - SplitCounts.decodeDelimited = function decodeDelimited(reader) { + CountResults.decodeDelimited = function decodeDelimited(reader) { if (!(reader instanceof $Reader)) reader = new $Reader(reader); return this.decode(reader, reader.uint32()); }; /** - * Verifies a SplitCounts message. + * Verifies a CountResults message. * @function verify - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults * @static * @param {Object.} message Plain object to verify * @returns {string|null} `null` if valid, otherwise the reason why it is not */ - SplitCounts.verify = function verify(message) { + CountResults.verify = function verify(message) { if (typeof message !== "object" || message === null) return "object expected"; + var properties = {}; + if (message.aggregateCount != null && message.hasOwnProperty("aggregateCount")) { + properties.variant = 1; + if (!$util.isInteger(message.aggregateCount) && !(message.aggregateCount && $util.isInteger(message.aggregateCount.low) && $util.isInteger(message.aggregateCount.high))) + return "aggregateCount: integer|Long expected"; + } 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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.verify(message.entries[i]); + if (properties.variant === 1) + return "variant: multiple values"; + properties.variant = 1; + { + var error = $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.verify(message.entries); if (error) return "entries." + error; } @@ -23041,71 +22360,81 @@ $root.org = (function() { }; /** - * Creates a SplitCounts message from a plain object. Also converts values to their respective internal types. + * Creates a CountResults message from a plain object. Also converts values to their respective internal types. * @function fromObject - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults * @static * @param {Object.} object Plain object - * @returns {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts} SplitCounts + * @returns {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults} CountResults */ - SplitCounts.fromObject = function fromObject(object) { - if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts) + CountResults.fromObject = function fromObject(object) { + if (object instanceof $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults) return object; - var message = new $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts(); - if (object.entries) { - if (!Array.isArray(object.entries)) - throw TypeError(".org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.entries: object expected"); - message.entries[i] = $root.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.fromObject(object.entries[i]); - } + var message = new $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults(); + if (object.aggregateCount != null) + if ($util.Long) + (message.aggregateCount = $util.Long.fromValue(object.aggregateCount)).unsigned = true; + else if (typeof object.aggregateCount === "string") + message.aggregateCount = parseInt(object.aggregateCount, 10); + else if (typeof object.aggregateCount === "number") + message.aggregateCount = object.aggregateCount; + else if (typeof object.aggregateCount === "object") + message.aggregateCount = new $util.LongBits(object.aggregateCount.low >>> 0, object.aggregateCount.high >>> 0).toNumber(true); + if (object.entries != null) { + if (typeof object.entries !== "object") + throw TypeError(".org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.entries: object expected"); + message.entries = $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.fromObject(object.entries); } return message; }; /** - * Creates a plain object from a SplitCounts message. Also converts values to other types if specified. + * Creates a plain object from a CountResults message. Also converts values to other types if specified. * @function toObject - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults * @static - * @param {org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts} message SplitCounts + * @param {org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults} message CountResults * @param {$protobuf.IConversionOptions} [options] Conversion options * @returns {Object.} Plain object */ - SplitCounts.toObject = function toObject(message, options) { + CountResults.toObject = function toObject(message, options) { if (!options) options = {}; var object = {}; - if (options.arrays || options.defaults) - object.entries = []; - 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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.toObject(message.entries[j], options); + if (message.aggregateCount != null && message.hasOwnProperty("aggregateCount")) { + if (typeof message.aggregateCount === "number") + object.aggregateCount = options.longs === String ? String(message.aggregateCount) : message.aggregateCount; + else + object.aggregateCount = options.longs === String ? $util.Long.prototype.toString.call(message.aggregateCount) : options.longs === Number ? new $util.LongBits(message.aggregateCount.low >>> 0, message.aggregateCount.high >>> 0).toNumber(true) : message.aggregateCount; + if (options.oneofs) + object.variant = "aggregateCount"; + } + if (message.entries != null && message.hasOwnProperty("entries")) { + object.entries = $root.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.toObject(message.entries, options); + if (options.oneofs) + object.variant = "entries"; } return object; }; /** - * Converts this SplitCounts to JSON. + * Converts this CountResults to JSON. * @function toJSON - * @memberof org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts + * @memberof org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults * @instance * @returns {Object.} JSON object */ - SplitCounts.prototype.toJSON = function toJSON() { + CountResults.prototype.toJSON = function toJSON() { return this.constructor.toObject(this, $protobuf.util.toJSONOptions); }; - return SplitCounts; + return CountResults; })(); - return GetDocumentsSplitCountResponseV0; + return GetDocumentsCountResponseV0; })(); - return GetDocumentsSplitCountResponse; + return GetDocumentsCountResponse; })(); v0.GetIdentityByPublicKeyHashRequest = (function() { 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 b670f84bcc7..d70c2e95669 100644 --- a/packages/dapi-grpc/clients/platform/v0/nodejs/platform_protoc.js +++ b/packages/dapi-grpc/clients/platform/v0/nodejs/platform_protoc.js @@ -155,6 +155,10 @@ goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetD goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.VersionCase', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.VariantCase', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.ResultCase', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.VersionCase', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsRequest', null, { proto }); @@ -166,15 +170,6 @@ goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocum goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV0.Documents', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV0.ResultCase', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsResponse.VersionCase', null, { proto }); -goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest', null, { proto }); -goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0', null, { proto }); -goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.VersionCase', null, { proto }); -goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse', null, { proto }); -goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0', null, { proto }); -goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.ResultCase', null, { proto }); -goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry', null, { proto }); -goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts', null, { proto }); -goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.VersionCase', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetEpochsInfoRequest', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetEpochsInfoRequest.GetEpochsInfoRequestV0', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetEpochsInfoRequest.VersionCase', null, { proto }); @@ -2345,79 +2340,16 @@ if (goog.DEBUG && !COMPILED) { * @extends {jspb.Message} * @constructor */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, null, proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.oneofGroups_); -}; -goog.inherits(proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.displayName = 'proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest'; -} -/** - * 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.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0 = function(opt_data) { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry = function(opt_data) { jspb.Message.initialize(this, opt_data, 0, -1, null, null); }; -goog.inherits(proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.displayName = 'proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0'; -} -/** - * 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.GetDocumentsSplitCountResponse = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, null, proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.oneofGroups_); -}; -goog.inherits(proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.displayName = 'proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse'; -} -/** - * 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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, null, proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.oneofGroups_); -}; -goog.inherits(proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0, jspb.Message); +goog.inherits(proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry, jspb.Message); if (goog.DEBUG && !COMPILED) { /** * @public * @override */ - proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.displayName = 'proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0'; + proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.displayName = 'proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry'; } /** * Generated by JsPbCodeGenerator. @@ -2429,16 +2361,16 @@ if (goog.DEBUG && !COMPILED) { * @extends {jspb.Message} * @constructor */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, null, null); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.repeatedFields_, null); }; -goog.inherits(proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry, jspb.Message); +goog.inherits(proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries, jspb.Message); if (goog.DEBUG && !COMPILED) { /** * @public * @override */ - proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.displayName = 'proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry'; + proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.displayName = 'proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries'; } /** * Generated by JsPbCodeGenerator. @@ -2450,16 +2382,16 @@ if (goog.DEBUG && !COMPILED) { * @extends {jspb.Message} * @constructor */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.repeatedFields_, null); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.oneofGroups_); }; -goog.inherits(proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts, jspb.Message); +goog.inherits(proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults, jspb.Message); if (goog.DEBUG && !COMPILED) { /** * @public * @override */ - proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.displayName = 'proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts'; + proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.displayName = 'proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults'; } /** * Generated by JsPbCodeGenerator. @@ -25658,7 +25590,10 @@ proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountReques dataContractId: msg.getDataContractId_asB64(), documentType: jspb.Message.getFieldWithDefault(msg, 2, ""), where: msg.getWhere_asB64(), - prove: jspb.Message.getBooleanFieldWithDefault(msg, 4, false) + returnDistinctCountsInRange: jspb.Message.getBooleanFieldWithDefault(msg, 4, false), + orderBy: msg.getOrderBy_asB64(), + limit: jspb.Message.getFieldWithDefault(msg, 6, 0), + prove: jspb.Message.getBooleanFieldWithDefault(msg, 7, false) }; if (includeInstance) { @@ -25708,6 +25643,18 @@ proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountReques msg.setWhere(value); break; case 4: + var value = /** @type {boolean} */ (reader.readBool()); + msg.setReturnDistinctCountsInRange(value); + break; + case 5: + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setOrderBy(value); + break; + case 6: + var value = /** @type {number} */ (reader.readUint32()); + msg.setLimit(value); + break; + case 7: var value = /** @type {boolean} */ (reader.readBool()); msg.setProve(value); break; @@ -25761,13 +25708,34 @@ proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountReques f ); } - f = message.getProve(); + f = message.getReturnDistinctCountsInRange(); if (f) { writer.writeBool( 4, f ); } + f = message.getOrderBy_asU8(); + if (f.length > 0) { + writer.writeBytes( + 5, + f + ); + } + f = /** @type {number} */ (jspb.Message.getField(message, 6)); + if (f != null) { + writer.writeUint32( + 6, + f + ); + } + f = message.getProve(); + if (f) { + writer.writeBool( + 7, + f + ); + } }; @@ -25874,10 +25842,10 @@ proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountReques /** - * optional bool prove = 4; + * optional bool return_distinct_counts_in_range = 4; * @return {boolean} */ -proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0.prototype.getProve = function() { +proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0.prototype.getReturnDistinctCountsInRange = function() { return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 4, false)); }; @@ -25886,11 +25854,107 @@ proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountReques * @param {boolean} value * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0.prototype.setProve = function(value) { +proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0.prototype.setReturnDistinctCountsInRange = function(value) { return jspb.Message.setProto3BooleanField(this, 4, value); }; +/** + * optional bytes order_by = 5; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0.prototype.getOrderBy = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 5, "")); +}; + + +/** + * optional bytes order_by = 5; + * This is a type-conversion wrapper around `getOrderBy()` + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0.prototype.getOrderBy_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getOrderBy())); +}; + + +/** + * optional bytes order_by = 5; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getOrderBy()` + * @return {!Uint8Array} + */ +proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0.prototype.getOrderBy_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getOrderBy())); +}; + + +/** + * @param {!(string|Uint8Array)} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0.prototype.setOrderBy = function(value) { + return jspb.Message.setProto3BytesField(this, 5, value); +}; + + +/** + * optional uint32 limit = 6; + * @return {number} + */ +proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0.prototype.getLimit = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 6, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0.prototype.setLimit = function(value) { + return jspb.Message.setField(this, 6, value); +}; + + +/** + * Clears the field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0.prototype.clearLimit = function() { + return jspb.Message.setField(this, 6, undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0.prototype.hasLimit = function() { + return jspb.Message.getField(this, 6) != null; +}; + + +/** + * optional bool prove = 7; + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0.prototype.getProve = function() { + return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 7, false)); +}; + + +/** + * @param {boolean} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0.prototype.setProve = function(value) { + return jspb.Message.setProto3BooleanField(this, 7, value); +}; + + /** * optional GetDocumentsCountRequestV0 v0 = 1; * @return {?proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0} @@ -26083,7 +26147,7 @@ proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountRespo */ proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.ResultCase = { RESULT_NOT_SET: 0, - COUNT: 1, + COUNTS: 1, PROOF: 2 }; @@ -26125,7 +26189,7 @@ proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountRespo */ proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.toObject = function(includeInstance, msg) { var f, obj = { - count: jspb.Message.getFieldWithDefault(msg, 1, 0), + counts: (f = msg.getCounts()) && proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.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) }; @@ -26165,8 +26229,9 @@ proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountRespo var field = reader.getFieldNumber(); switch (field) { case 1: - var value = /** @type {number} */ (reader.readUint64()); - msg.setCount(value); + var value = new proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.deserializeBinaryFromReader); + msg.setCounts(value); break; case 2: var value = new proto.org.dash.platform.dapi.v0.Proof; @@ -26207,11 +26272,12 @@ proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountRespo */ proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.serializeBinaryToWriter = function(message, writer) { var f = undefined; - f = /** @type {number} */ (jspb.Message.getField(message, 1)); + f = message.getCounts(); if (f != null) { - writer.writeUint64( + writer.writeMessage( 1, - f + f, + proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.serializeBinaryToWriter ); } f = message.getProof(); @@ -26233,935 +26299,270 @@ proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountRespo }; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { /** - * optional uint64 count = 1; - * @return {number} + * 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.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.getCount = function() { - return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0)); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.prototype.toObject = function(opt_includeInstance) { + return proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.toObject(opt_includeInstance, this); }; /** - * @param {number} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0} returns 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.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.setCount = function(value) { - return jspb.Message.setOneofField(this, 1, proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.oneofGroups_[0], value); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.toObject = function(includeInstance, msg) { + var f, obj = { + inKey: msg.getInKey_asB64(), + key: msg.getKey_asB64(), + count: jspb.Message.getFieldWithDefault(msg, 3, "0") + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; }; +} /** - * Clears the field making it undefined. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0} returns this + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry} */ -proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.clearCount = function() { - return jspb.Message.setOneofField(this, 1, proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.oneofGroups_[0], undefined); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry; + return proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.deserializeBinaryFromReader(msg, reader); }; /** - * Returns whether this field is set. - * @return {boolean} + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry} */ -proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.hasCount = function() { - return jspb.Message.getField(this, 1) != null; +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setInKey(value); + break; + case 2: + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setKey(value); + break; + case 3: + var value = /** @type {string} */ (reader.readUint64String()); + msg.setCount(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; }; /** - * optional Proof proof = 2; - * @return {?proto.org.dash.platform.dapi.v0.Proof} + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} */ -proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.getProof = function() { - return /** @type{?proto.org.dash.platform.dapi.v0.Proof} */ ( - jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.Proof, 2)); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); }; /** - * @param {?proto.org.dash.platform.dapi.v0.Proof|undefined} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0} returns this -*/ -proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.setProof = function(value) { - return jspb.Message.setOneofWrapperField(this, 2, proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.oneofGroups_[0], value); -}; - - -/** - * Clears the message field making it undefined. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0} returns this - */ -proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.clearProof = function() { - return this.setProof(undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.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.GetDocumentsCountResponse.GetDocumentsCountResponseV0.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.GetDocumentsCountResponse.GetDocumentsCountResponseV0} returns this -*/ -proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.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.GetDocumentsCountResponse.GetDocumentsCountResponseV0} returns this - */ -proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.clearMetadata = function() { - return this.setMetadata(undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.hasMetadata = function() { - return jspb.Message.getField(this, 3) != null; -}; - - -/** - * optional GetDocumentsCountResponseV0 v0 = 1; - * @return {?proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.prototype.getV0 = function() { - return /** @type{?proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0} */ ( - jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0, 1)); -}; - - -/** - * @param {?proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0|undefined} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse} returns this -*/ -proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.prototype.setV0 = function(value) { - return jspb.Message.setOneofWrapperField(this, 1, proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.oneofGroups_[0], value); -}; - - -/** - * Clears the message field making it undefined. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse} returns this - */ -proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.prototype.clearV0 = function() { - return this.setV0(undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.prototype.hasV0 = function() { - return jspb.Message.getField(this, 1) != 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.GetDocumentsSplitCountRequest.oneofGroups_ = [[1]]; - -/** - * @enum {number} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.VersionCase = { - VERSION_NOT_SET: 0, - V0: 1 -}; - -/** - * @return {proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.VersionCase} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.prototype.getVersionCase = function() { - return /** @type {proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.VersionCase} */(jspb.Message.computeOneofCase(this, proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.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.GetDocumentsSplitCountRequest.prototype.toObject = function(opt_includeInstance) { - return proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.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.GetDocumentsSplitCountRequest} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.toObject = function(includeInstance, msg) { - var f, obj = { - v0: (f = msg.getV0()) && proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.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.GetDocumentsSplitCountRequest} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest; - return proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.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.GetDocumentsSplitCountRequest} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.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.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0; - reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.deserializeBinaryFromReader); - msg.setV0(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.GetDocumentsSplitCountRequest.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.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.GetDocumentsSplitCountRequest} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getV0(); - if (f != null) { - writer.writeMessage( - 1, - f, - proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.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.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.prototype.toObject = function(opt_includeInstance) { - return proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.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.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.toObject = function(includeInstance, msg) { - var f, obj = { - dataContractId: msg.getDataContractId_asB64(), - documentType: jspb.Message.getFieldWithDefault(msg, 2, ""), - where: msg.getWhere_asB64(), - splitCountByIndexProperty: jspb.Message.getFieldWithDefault(msg, 4, ""), - prove: jspb.Message.getBooleanFieldWithDefault(msg, 5, false) - }; - - 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.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0; - return proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.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.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.deserializeBinaryFromReader = function(msg, reader) { - while (reader.nextField()) { - if (reader.isEndGroup()) { - break; - } - var field = reader.getFieldNumber(); - switch (field) { - case 1: - var value = /** @type {!Uint8Array} */ (reader.readBytes()); - msg.setDataContractId(value); - break; - case 2: - var value = /** @type {string} */ (reader.readString()); - msg.setDocumentType(value); - break; - case 3: - var value = /** @type {!Uint8Array} */ (reader.readBytes()); - msg.setWhere(value); - break; - case 4: - var value = /** @type {string} */ (reader.readString()); - msg.setSplitCountByIndexProperty(value); - break; - case 5: - var value = /** @type {boolean} */ (reader.readBool()); - msg.setProve(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.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.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.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getDataContractId_asU8(); - if (f.length > 0) { - writer.writeBytes( - 1, - f - ); - } - f = message.getDocumentType(); - if (f.length > 0) { - writer.writeString( - 2, - f - ); - } - f = message.getWhere_asU8(); - if (f.length > 0) { - writer.writeBytes( - 3, - f - ); - } - f = message.getSplitCountByIndexProperty(); - if (f.length > 0) { - writer.writeString( - 4, - f - ); - } - f = message.getProve(); - if (f) { - writer.writeBool( - 5, - f - ); - } -}; - - -/** - * optional bytes data_contract_id = 1; - * @return {string} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.prototype.getDataContractId = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); -}; - - -/** - * optional bytes data_contract_id = 1; - * This is a type-conversion wrapper around `getDataContractId()` - * @return {string} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.prototype.getDataContractId_asB64 = function() { - return /** @type {string} */ (jspb.Message.bytesAsB64( - this.getDataContractId())); -}; - - -/** - * 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.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.prototype.getDataContractId_asU8 = function() { - return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( - this.getDataContractId())); -}; - - -/** - * @param {!(string|Uint8Array)} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0} returns this - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.prototype.setDataContractId = function(value) { - return jspb.Message.setProto3BytesField(this, 1, value); -}; - - -/** - * optional string document_type = 2; - * @return {string} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.prototype.getDocumentType = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); -}; - - -/** - * @param {string} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0} returns this + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.prototype.setDocumentType = function(value) { - return jspb.Message.setProto3StringField(this, 2, value); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = /** @type {!(string|Uint8Array)} */ (jspb.Message.getField(message, 1)); + if (f != null) { + writer.writeBytes( + 1, + f + ); + } + f = message.getKey_asU8(); + if (f.length > 0) { + writer.writeBytes( + 2, + f + ); + } + f = message.getCount(); + if (parseInt(f, 10) !== 0) { + writer.writeUint64String( + 3, + f + ); + } }; /** - * optional bytes where = 3; + * optional bytes in_key = 1; * @return {string} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.prototype.getWhere = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.prototype.getInKey = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); }; /** - * optional bytes where = 3; - * This is a type-conversion wrapper around `getWhere()` + * optional bytes in_key = 1; + * This is a type-conversion wrapper around `getInKey()` * @return {string} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.prototype.getWhere_asB64 = function() { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.prototype.getInKey_asB64 = function() { return /** @type {string} */ (jspb.Message.bytesAsB64( - this.getWhere())); + this.getInKey())); }; /** - * optional bytes where = 3; + * optional bytes in_key = 1; * Note that Uint8Array is not supported on all browsers. * @see http://caniuse.com/Uint8Array - * This is a type-conversion wrapper around `getWhere()` + * This is a type-conversion wrapper around `getInKey()` * @return {!Uint8Array} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.prototype.getWhere_asU8 = function() { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.prototype.getInKey_asU8 = function() { return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( - this.getWhere())); + this.getInKey())); }; /** * @param {!(string|Uint8Array)} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0} returns this - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.prototype.setWhere = function(value) { - return jspb.Message.setProto3BytesField(this, 3, value); -}; - - -/** - * optional string split_count_by_index_property = 4; - * @return {string} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.prototype.getSplitCountByIndexProperty = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 4, "")); -}; - - -/** - * @param {string} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0} returns this - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.prototype.setSplitCountByIndexProperty = function(value) { - return jspb.Message.setProto3StringField(this, 4, value); -}; - - -/** - * optional bool prove = 5; - * @return {boolean} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.prototype.getProve = function() { - return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 5, false)); -}; - - -/** - * @param {boolean} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0} returns this - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.prototype.setProve = function(value) { - return jspb.Message.setProto3BooleanField(this, 5, value); -}; - - -/** - * optional GetDocumentsSplitCountRequestV0 v0 = 1; - * @return {?proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.prototype.getV0 = function() { - return /** @type{?proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0} */ ( - jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0, 1)); -}; - - -/** - * @param {?proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0|undefined} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest} returns this -*/ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.prototype.setV0 = function(value) { - return jspb.Message.setOneofWrapperField(this, 1, proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.oneofGroups_[0], value); -}; - - -/** - * Clears the message field making it undefined. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest} returns this - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.prototype.clearV0 = function() { - return this.setV0(undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.prototype.hasV0 = function() { - return jspb.Message.getField(this, 1) != 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.GetDocumentsSplitCountResponse.oneofGroups_ = [[1]]; - -/** - * @enum {number} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.VersionCase = { - VERSION_NOT_SET: 0, - V0: 1 -}; - -/** - * @return {proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.VersionCase} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.prototype.getVersionCase = function() { - return /** @type {proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.VersionCase} */(jspb.Message.computeOneofCase(this, proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.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.GetDocumentsSplitCountResponse.prototype.toObject = function(opt_includeInstance) { - return proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.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.GetDocumentsSplitCountResponse} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.toObject = function(includeInstance, msg) { - var f, obj = { - v0: (f = msg.getV0()) && proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.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.GetDocumentsSplitCountResponse} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse; - return proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.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.GetDocumentsSplitCountResponse} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0; - reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.deserializeBinaryFromReader); - msg.setV0(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.GetDocumentsSplitCountResponse.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.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.GetDocumentsSplitCountResponse} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getV0(); - if (f != null) { - writer.writeMessage( - 1, - f, - proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.serializeBinaryToWriter - ); - } +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.prototype.setInKey = function(value) { + return jspb.Message.setField(this, 1, value); }; - -/** - * 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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.oneofGroups_ = [[1,2]]; - -/** - * @enum {number} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.ResultCase = { - RESULT_NOT_SET: 0, - SPLIT_COUNTS: 1, - PROOF: 2 -}; - /** - * @return {proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.ResultCase} + * Clears the field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.prototype.getResultCase = function() { - return /** @type {proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.ResultCase} */(jspb.Message.computeOneofCase(this, proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.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.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.prototype.clearInKey = function() { + return jspb.Message.setField(this, 1, undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.prototype.toObject = function(opt_includeInstance) { - return proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.toObject(opt_includeInstance, this); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.prototype.hasInKey = function() { + return jspb.Message.getField(this, 1) != null; }; /** - * 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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages + * optional bytes key = 2; + * @return {string} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.toObject = function(includeInstance, msg) { - var f, obj = { - splitCounts: (f = msg.getSplitCounts()) && proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.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) - }; +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.prototype.getKey = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; + +/** + * optional bytes key = 2; + * This is a type-conversion wrapper around `getKey()` + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.prototype.getKey_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getKey())); }; -} /** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0} + * optional bytes key = 2; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getKey()` + * @return {!Uint8Array} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0; - return proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.deserializeBinaryFromReader(msg, reader); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.prototype.getKey_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getKey())); }; /** - * Deserializes binary data (in protobuf wire format) from the - * given reader into the given message object. - * @param {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0} + * @param {!(string|Uint8Array)} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts; - reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.deserializeBinaryFromReader); - msg.setSplitCounts(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; +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.prototype.setKey = function(value) { + return jspb.Message.setProto3BytesField(this, 2, value); }; /** - * Serializes the message to binary data (in protobuf wire format). - * @return {!Uint8Array} + * optional uint64 count = 3; + * @return {string} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.serializeBinaryToWriter(this, writer); - return writer.getResultBuffer(); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.prototype.getCount = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "0")); }; /** - * Serializes the given message to binary data (in protobuf wire - * format), writing to the given BinaryWriter. - * @param {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages + * @param {string} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getSplitCounts(); - if (f != null) { - writer.writeMessage( - 1, - f, - proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.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 - ); - } +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.prototype.setCount = function(value) { + return jspb.Message.setProto3StringIntField(this, 3, value); }; +/** + * List of repeated fields within this message type. + * @private {!Array} + * @const + */ +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.repeatedFields_ = [1]; + if (jspb.Message.GENERATE_TO_OBJECT) { @@ -27177,8 +26578,8 @@ if (jspb.Message.GENERATE_TO_OBJECT) { * http://goto/soy-param-migration * @return {!Object} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.prototype.toObject = function(opt_includeInstance) { - return proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.toObject(opt_includeInstance, this); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.prototype.toObject = function(opt_includeInstance) { + return proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.toObject(opt_includeInstance, this); }; @@ -27187,14 +26588,14 @@ proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplit * @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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry} msg The msg instance to transform. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries} msg The msg instance to transform. * @return {!Object} * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.toObject = function(includeInstance, msg) { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.toObject = function(includeInstance, msg) { var f, obj = { - key: msg.getKey_asB64(), - count: jspb.Message.getFieldWithDefault(msg, 2, 0) + entriesList: jspb.Message.toObjectList(msg.getEntriesList(), + proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.toObject, includeInstance) }; if (includeInstance) { @@ -27208,23 +26609,23 @@ proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplit /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry} + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.deserializeBinary = function(bytes) { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); - var msg = new proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry; - return proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.deserializeBinaryFromReader(msg, reader); + var msg = new proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries; + return proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry} msg The message object to deserialize into. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry} + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.deserializeBinaryFromReader = function(msg, reader) { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; @@ -27232,12 +26633,9 @@ proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplit var field = reader.getFieldNumber(); switch (field) { case 1: - var value = /** @type {!Uint8Array} */ (reader.readBytes()); - msg.setKey(value); - break; - case 2: - var value = /** @type {number} */ (reader.readUint64()); - msg.setCount(value); + var value = new proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.deserializeBinaryFromReader); + msg.addEntries(value); break; default: reader.skipField(); @@ -27252,9 +26650,9 @@ proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplit * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.prototype.serializeBinary = function() { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); - proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.serializeBinaryToWriter(this, writer); + proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.serializeBinaryToWriter(this, writer); return writer.getResultBuffer(); }; @@ -27262,96 +26660,87 @@ proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplit /** * Serializes the given message to binary data (in protobuf wire * format), writing to the given BinaryWriter. - * @param {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry} message + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries} message * @param {!jspb.BinaryWriter} writer * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.serializeBinaryToWriter = function(message, writer) { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.serializeBinaryToWriter = function(message, writer) { var f = undefined; - f = message.getKey_asU8(); + f = message.getEntriesList(); if (f.length > 0) { - writer.writeBytes( + writer.writeRepeatedMessage( 1, - f - ); - } - f = message.getCount(); - if (f !== 0) { - writer.writeUint64( - 2, - f + f, + proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.serializeBinaryToWriter ); } }; /** - * optional bytes key = 1; - * @return {string} + * repeated CountEntry entries = 1; + * @return {!Array} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.prototype.getKey = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.prototype.getEntriesList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry, 1)); }; /** - * optional bytes key = 1; - * This is a type-conversion wrapper around `getKey()` - * @return {string} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.prototype.getKey_asB64 = function() { - return /** @type {string} */ (jspb.Message.bytesAsB64( - this.getKey())); + * @param {!Array} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries} returns this +*/ +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.prototype.setEntriesList = function(value) { + return jspb.Message.setRepeatedWrapperField(this, 1, value); }; /** - * optional bytes key = 1; - * Note that Uint8Array is not supported on all browsers. - * @see http://caniuse.com/Uint8Array - * This is a type-conversion wrapper around `getKey()` - * @return {!Uint8Array} + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry=} opt_value + * @param {number=} opt_index + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.prototype.getKey_asU8 = function() { - return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( - this.getKey())); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.prototype.addEntries = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry, opt_index); }; /** - * @param {!(string|Uint8Array)} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry} returns this + * Clears the list making it empty but non-null. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.prototype.setKey = function(value) { - return jspb.Message.setProto3BytesField(this, 1, value); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.prototype.clearEntriesList = function() { + return this.setEntriesList([]); }; + /** - * optional uint64 count = 2; - * @return {number} + * 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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.prototype.getCount = function() { - return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0)); -}; - +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.oneofGroups_ = [[1,2]]; /** - * @param {number} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry} returns this + * @enum {number} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.prototype.setCount = function(value) { - return jspb.Message.setProto3IntField(this, 2, value); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.VariantCase = { + VARIANT_NOT_SET: 0, + AGGREGATE_COUNT: 1, + ENTRIES: 2 }; - - /** - * List of repeated fields within this message type. - * @private {!Array} - * @const + * @return {proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.VariantCase} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.repeatedFields_ = [1]; +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.prototype.getVariantCase = function() { + return /** @type {proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.VariantCase} */(jspb.Message.computeOneofCase(this, proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.oneofGroups_[0])); +}; @@ -27368,8 +26757,8 @@ if (jspb.Message.GENERATE_TO_OBJECT) { * http://goto/soy-param-migration * @return {!Object} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.prototype.toObject = function(opt_includeInstance) { - return proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.toObject(opt_includeInstance, this); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.prototype.toObject = function(opt_includeInstance) { + return proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.toObject(opt_includeInstance, this); }; @@ -27378,14 +26767,14 @@ proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplit * @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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts} msg The msg instance to transform. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults} msg The msg instance to transform. * @return {!Object} * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.toObject = function(includeInstance, msg) { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.toObject = function(includeInstance, msg) { var f, obj = { - entriesList: jspb.Message.toObjectList(msg.getEntriesList(), - proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.toObject, includeInstance) + aggregateCount: jspb.Message.getFieldWithDefault(msg, 1, "0"), + entries: (f = msg.getEntries()) && proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.toObject(includeInstance, f) }; if (includeInstance) { @@ -27399,23 +26788,23 @@ proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplit /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts} + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.deserializeBinary = function(bytes) { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); - var msg = new proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts; - return proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.deserializeBinaryFromReader(msg, reader); + var msg = new proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults; + return proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts} msg The message object to deserialize into. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts} + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.deserializeBinaryFromReader = function(msg, reader) { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; @@ -27423,9 +26812,13 @@ proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplit var field = reader.getFieldNumber(); switch (field) { case 1: - var value = new proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry; - reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.deserializeBinaryFromReader); - msg.addEntries(value); + var value = /** @type {string} */ (reader.readUint64String()); + msg.setAggregateCount(value); + break; + case 2: + var value = new proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.deserializeBinaryFromReader); + msg.setEntries(value); break; default: reader.skipField(); @@ -27440,9 +26833,9 @@ proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplit * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.prototype.serializeBinary = function() { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); - proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.serializeBinaryToWriter(this, writer); + proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.serializeBinaryToWriter(this, writer); return writer.getResultBuffer(); }; @@ -27450,86 +26843,128 @@ proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplit /** * Serializes the given message to binary data (in protobuf wire * format), writing to the given BinaryWriter. - * @param {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts} message + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults} message * @param {!jspb.BinaryWriter} writer * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.serializeBinaryToWriter = function(message, writer) { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.serializeBinaryToWriter = function(message, writer) { var f = undefined; - f = message.getEntriesList(); - if (f.length > 0) { - writer.writeRepeatedMessage( + f = /** @type {string} */ (jspb.Message.getField(message, 1)); + if (f != null) { + writer.writeUint64String( 1, + f + ); + } + f = message.getEntries(); + if (f != null) { + writer.writeMessage( + 2, f, - proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.serializeBinaryToWriter + proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.serializeBinaryToWriter ); } }; /** - * repeated SplitCountEntry entries = 1; - * @return {!Array} + * optional uint64 aggregate_count = 1; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.prototype.getAggregateCount = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "0")); +}; + + +/** + * @param {string} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.prototype.setAggregateCount = function(value) { + return jspb.Message.setOneofField(this, 1, proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.oneofGroups_[0], value); +}; + + +/** + * Clears the field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.prototype.clearAggregateCount = function() { + return jspb.Message.setOneofField(this, 1, proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.oneofGroups_[0], undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.prototype.hasAggregateCount = function() { + return jspb.Message.getField(this, 1) != null; +}; + + +/** + * optional CountEntries entries = 2; + * @return {?proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.prototype.getEntriesList = function() { - return /** @type{!Array} */ ( - jspb.Message.getRepeatedWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry, 1)); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.prototype.getEntries = function() { + return /** @type{?proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries} */ ( + jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries, 2)); }; /** - * @param {!Array} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts} returns this + * @param {?proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries|undefined} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.prototype.setEntriesList = function(value) { - return jspb.Message.setRepeatedWrapperField(this, 1, value); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.prototype.setEntries = function(value) { + return jspb.Message.setOneofWrapperField(this, 2, proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.oneofGroups_[0], value); }; /** - * @param {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry=} opt_value - * @param {number=} opt_index - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry} + * Clears the message field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.prototype.addEntries = function(opt_value, opt_index) { - return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry, opt_index); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.prototype.clearEntries = function() { + return this.setEntries(undefined); }; /** - * Clears the list making it empty but non-null. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts} returns this + * Returns whether this field is set. + * @return {boolean} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.prototype.clearEntriesList = function() { - return this.setEntriesList([]); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.prototype.hasEntries = function() { + return jspb.Message.getField(this, 2) != null; }; /** - * optional SplitCounts split_counts = 1; - * @return {?proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts} + * optional CountResults counts = 1; + * @return {?proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.prototype.getSplitCounts = function() { - return /** @type{?proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts} */ ( - jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts, 1)); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.getCounts = function() { + return /** @type{?proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults} */ ( + jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults, 1)); }; /** - * @param {?proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts|undefined} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0} returns this + * @param {?proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults|undefined} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.prototype.setSplitCounts = function(value) { - return jspb.Message.setOneofWrapperField(this, 1, proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.oneofGroups_[0], value); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.setCounts = function(value) { + return jspb.Message.setOneofWrapperField(this, 1, proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.oneofGroups_[0], value); }; /** * Clears the message field making it undefined. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0} returns this + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.prototype.clearSplitCounts = function() { - return this.setSplitCounts(undefined); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.clearCounts = function() { + return this.setCounts(undefined); }; @@ -27537,7 +26972,7 @@ proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplit * Returns whether this field is set. * @return {boolean} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.prototype.hasSplitCounts = function() { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.hasCounts = function() { return jspb.Message.getField(this, 1) != null; }; @@ -27546,7 +26981,7 @@ proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplit * optional Proof proof = 2; * @return {?proto.org.dash.platform.dapi.v0.Proof} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.prototype.getProof = function() { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.getProof = function() { return /** @type{?proto.org.dash.platform.dapi.v0.Proof} */ ( jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.Proof, 2)); }; @@ -27554,18 +26989,18 @@ proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplit /** * @param {?proto.org.dash.platform.dapi.v0.Proof|undefined} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0} returns this + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.prototype.setProof = function(value) { - return jspb.Message.setOneofWrapperField(this, 2, proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.oneofGroups_[0], value); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.setProof = function(value) { + return jspb.Message.setOneofWrapperField(this, 2, proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.oneofGroups_[0], value); }; /** * Clears the message field making it undefined. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0} returns this + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.prototype.clearProof = function() { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.clearProof = function() { return this.setProof(undefined); }; @@ -27574,7 +27009,7 @@ proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplit * Returns whether this field is set. * @return {boolean} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.prototype.hasProof = function() { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.hasProof = function() { return jspb.Message.getField(this, 2) != null; }; @@ -27583,7 +27018,7 @@ proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplit * optional ResponseMetadata metadata = 3; * @return {?proto.org.dash.platform.dapi.v0.ResponseMetadata} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.prototype.getMetadata = function() { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.getMetadata = function() { return /** @type{?proto.org.dash.platform.dapi.v0.ResponseMetadata} */ ( jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.ResponseMetadata, 3)); }; @@ -27591,18 +27026,18 @@ proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplit /** * @param {?proto.org.dash.platform.dapi.v0.ResponseMetadata|undefined} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0} returns this + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.prototype.setMetadata = function(value) { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0} returns this + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.prototype.clearMetadata = function() { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.clearMetadata = function() { return this.setMetadata(undefined); }; @@ -27611,35 +27046,35 @@ proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplit * Returns whether this field is set. * @return {boolean} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.prototype.hasMetadata = function() { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.hasMetadata = function() { return jspb.Message.getField(this, 3) != null; }; /** - * optional GetDocumentsSplitCountResponseV0 v0 = 1; - * @return {?proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0} + * optional GetDocumentsCountResponseV0 v0 = 1; + * @return {?proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.prototype.getV0 = function() { - return /** @type{?proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0} */ ( - jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0, 1)); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.prototype.getV0 = function() { + return /** @type{?proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0} */ ( + jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0, 1)); }; /** - * @param {?proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0|undefined} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse} returns this + * @param {?proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0|undefined} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.prototype.setV0 = function(value) { - return jspb.Message.setOneofWrapperField(this, 1, proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.oneofGroups_[0], value); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.prototype.setV0 = function(value) { + return jspb.Message.setOneofWrapperField(this, 1, proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.oneofGroups_[0], value); }; /** * Clears the message field making it undefined. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse} returns this + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.prototype.clearV0 = function() { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.prototype.clearV0 = function() { return this.setV0(undefined); }; @@ -27648,7 +27083,7 @@ proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.prototype.clearV0 * Returns whether this field is set. * @return {boolean} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.prototype.hasV0 = function() { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.prototype.hasV0 = function() { return jspb.Message.getField(this, 1) != null; }; 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 69ec8ea3eb3..15fccb22398 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 @@ -92,13 +92,12 @@ CF_EXTERN_C_BEGIN @class GetDataContractsResponse_GetDataContractsResponseV0; @class GetDocumentsCountRequest_GetDocumentsCountRequestV0; @class GetDocumentsCountResponse_GetDocumentsCountResponseV0; +@class GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountEntries; +@class GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountEntry; +@class GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountResults; @class GetDocumentsRequest_GetDocumentsRequestV0; @class GetDocumentsResponse_GetDocumentsResponseV0; @class GetDocumentsResponse_GetDocumentsResponseV0_Documents; -@class GetDocumentsSplitCountRequest_GetDocumentsSplitCountRequestV0; -@class GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0; -@class GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_SplitCountEntry; -@class GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_SplitCounts; @class GetEpochsInfoRequest_GetEpochsInfoRequestV0; @class GetEpochsInfoResponse_GetEpochsInfoResponseV0; @class GetEpochsInfoResponse_GetEpochsInfoResponseV0_EpochInfo; @@ -2422,6 +2421,40 @@ typedef GPB_ENUM(GetDocumentsCountRequest_Version_OneOfCase) { GetDocumentsCountRequest_Version_OneOfCase_V0 = 1, }; +/** + * Unified count query. + * + * Mode is determined by the where clauses encoded in `where` plus + * the explicit `return_distinct_counts_in_range` flag. The wire + * shape of the no-proof response makes the mode explicit via + * `CountResults.variant`: + * * No `In` clause and `return_distinct_counts_in_range` = false: + * total count → `CountResults.aggregate_count` (single u64). + * * Exactly one `In` clause (no range): per-`In`-value counts → + * `CountResults.entries`, one `CountEntry` for each value in + * the `In` array constrained by the other `==` clauses. At + * most one `In` per request; multiple `In` clauses are an + * InvalidArgument error. + * * A range clause (`>`, `<`, `between*`, `startsWith`) and + * `return_distinct_counts_in_range` = true: per-distinct-value + * range histogram → `CountResults.entries`, one `CountEntry` + * per distinct value within the range. Requires + * `range_countable: true` on the index (see Indexes book + * chapter). Also supports an `In` clause on a prefix property + * of the index — in that case each entry carries BOTH the In + * value (`CountEntry.in_key`) and the terminator value + * (`CountEntry.key`). Cross-fork sums are NOT computed + * server-side; callers reduce client-side if they want a flat + * histogram (see book chapter "Range Modes"). + * * A range clause with `return_distinct_counts_in_range` = false: + * total over range → `CountResults.aggregate_count`. Also + * requires `range_countable: true`. + * + * When `prove = true`, the response is a grovedb proof instead of + * a `CountResults` value; the client verifies and recovers the + * same per-mode shape (single u64 for aggregate, per-key map for + * distinct). + **/ GPB_FINAL @interface GetDocumentsCountRequest : GPBMessage @property(nonatomic, readonly) GetDocumentsCountRequest_Version_OneOfCase versionOneOfCase; @@ -2441,21 +2474,47 @@ typedef GPB_ENUM(GetDocumentsCountRequest_GetDocumentsCountRequestV0_FieldNumber GetDocumentsCountRequest_GetDocumentsCountRequestV0_FieldNumber_DataContractId = 1, GetDocumentsCountRequest_GetDocumentsCountRequestV0_FieldNumber_DocumentType = 2, GetDocumentsCountRequest_GetDocumentsCountRequestV0_FieldNumber_Where = 3, - GetDocumentsCountRequest_GetDocumentsCountRequestV0_FieldNumber_Prove = 4, + GetDocumentsCountRequest_GetDocumentsCountRequestV0_FieldNumber_ReturnDistinctCountsInRange = 4, + GetDocumentsCountRequest_GetDocumentsCountRequestV0_FieldNumber_OrderBy = 5, + GetDocumentsCountRequest_GetDocumentsCountRequestV0_FieldNumber_Limit = 6, + GetDocumentsCountRequest_GetDocumentsCountRequestV0_FieldNumber_Prove = 7, }; GPB_FINAL @interface GetDocumentsCountRequest_GetDocumentsCountRequestV0 : GPBMessage -/** The ID of the data contract containing the documents */ @property(nonatomic, readwrite, copy, null_resettable) NSData *dataContractId; -/** The type of document being requested */ @property(nonatomic, readwrite, copy, null_resettable) NSString *documentType; -/** CBOR-encoded where clauses for filtering */ +/** CBOR-encoded where clauses */ @property(nonatomic, readwrite, copy, null_resettable) NSData *where; -/** Flag to request a proof as the response */ +/** + * Default false (single sum). When true and a range clause is + * present, return per-distinct-value entries within the range. + **/ +@property(nonatomic, readwrite) BOOL returnDistinctCountsInRange; + +/** + * CBOR-encoded order_by clauses. Same encoding as + * `GetDocumentsRequestV0.order_by`. Required when `where` carries + * an `In` or range operator on the prove path: the materialize- + * and-count walker needs a deterministic walk order so the SDK + * can reconstruct the same path query and verify the proof. The + * first orderBy clause's direction also controls entry ordering + * in split-mode responses (per-`In`-value or per-range-distinct- + * value); ignored for total-count responses. + **/ +@property(nonatomic, readwrite, copy, null_resettable) NSData *orderBy; + +/** + * Maximum number of entries to return on the no-prove path. + * Server clamps to its `max_query_limit` config. Unset → + * server default. Has no effect on total-count responses. + **/ +@property(nonatomic, readwrite) uint32_t limit; + +@property(nonatomic, readwrite) BOOL hasLimit; @property(nonatomic, readwrite) BOOL prove; @end @@ -2487,14 +2546,14 @@ void GetDocumentsCountResponse_ClearVersionOneOfCase(GetDocumentsCountResponse * #pragma mark - GetDocumentsCountResponse_GetDocumentsCountResponseV0 typedef GPB_ENUM(GetDocumentsCountResponse_GetDocumentsCountResponseV0_FieldNumber) { - GetDocumentsCountResponse_GetDocumentsCountResponseV0_FieldNumber_Count = 1, + GetDocumentsCountResponse_GetDocumentsCountResponseV0_FieldNumber_Counts = 1, GetDocumentsCountResponse_GetDocumentsCountResponseV0_FieldNumber_Proof = 2, GetDocumentsCountResponse_GetDocumentsCountResponseV0_FieldNumber_Metadata = 3, }; typedef GPB_ENUM(GetDocumentsCountResponse_GetDocumentsCountResponseV0_Result_OneOfCase) { GetDocumentsCountResponse_GetDocumentsCountResponseV0_Result_OneOfCase_GPBUnsetOneOfCase = 0, - GetDocumentsCountResponse_GetDocumentsCountResponseV0_Result_OneOfCase_Count = 1, + GetDocumentsCountResponse_GetDocumentsCountResponseV0_Result_OneOfCase_Counts = 1, GetDocumentsCountResponse_GetDocumentsCountResponseV0_Result_OneOfCase_Proof = 2, }; @@ -2502,13 +2561,10 @@ GPB_FINAL @interface GetDocumentsCountResponse_GetDocumentsCountResponseV0 : GPB @property(nonatomic, readonly) GetDocumentsCountResponse_GetDocumentsCountResponseV0_Result_OneOfCase resultOneOfCase; -/** Total document count matching the query */ -@property(nonatomic, readwrite) uint64_t count; +@property(nonatomic, readwrite, strong, null_resettable) GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountResults *counts; -/** Cryptographic proof, if requested */ @property(nonatomic, readwrite, strong, null_resettable) Proof *proof; -/** Metadata about the blockchain state */ @property(nonatomic, readwrite, strong, null_resettable) ResponseMetadata *metadata; /** Test to see if @c metadata has been set. */ @property(nonatomic, readwrite) BOOL hasMetadata; @@ -2520,152 +2576,113 @@ GPB_FINAL @interface GetDocumentsCountResponse_GetDocumentsCountResponseV0 : GPB **/ void GetDocumentsCountResponse_GetDocumentsCountResponseV0_ClearResultOneOfCase(GetDocumentsCountResponse_GetDocumentsCountResponseV0 *message); -#pragma mark - GetDocumentsSplitCountRequest - -typedef GPB_ENUM(GetDocumentsSplitCountRequest_FieldNumber) { - GetDocumentsSplitCountRequest_FieldNumber_V0 = 1, -}; +#pragma mark - GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountEntry -typedef GPB_ENUM(GetDocumentsSplitCountRequest_Version_OneOfCase) { - GetDocumentsSplitCountRequest_Version_OneOfCase_GPBUnsetOneOfCase = 0, - GetDocumentsSplitCountRequest_Version_OneOfCase_V0 = 1, +typedef GPB_ENUM(GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountEntry_FieldNumber) { + GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountEntry_FieldNumber_InKey = 1, + GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountEntry_FieldNumber_Key = 2, + GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountEntry_FieldNumber_Count = 3, }; -GPB_FINAL @interface GetDocumentsSplitCountRequest : GPBMessage - -@property(nonatomic, readonly) GetDocumentsSplitCountRequest_Version_OneOfCase versionOneOfCase; - -@property(nonatomic, readwrite, strong, null_resettable) GetDocumentsSplitCountRequest_GetDocumentsSplitCountRequestV0 *v0; - -@end - /** - * Clears whatever value was set for the oneof 'version'. + * A single per-key entry: the splitting key value and how many + * documents match. Used by the `entries` variant of + * `CountResults` for per-`In`-value and per-distinct-value-in- + * range modes. + * + * For compound queries (an `In` clause on a prefix property of a + * `range_countable` index plus a range clause on the terminator), + * each entry carries BOTH the In-fork's prefix value + * (`in_key`) and the terminator value (`key`). Cross-fork + * aggregation is intentionally NOT done server-side — callers + * get the unmerged per-(in_key, key) view and can sum + * client-side if they want a flat histogram. See the book + * chapter ("Range Modes") for rationale. **/ -void GetDocumentsSplitCountRequest_ClearVersionOneOfCase(GetDocumentsSplitCountRequest *message); - -#pragma mark - GetDocumentsSplitCountRequest_GetDocumentsSplitCountRequestV0 - -typedef GPB_ENUM(GetDocumentsSplitCountRequest_GetDocumentsSplitCountRequestV0_FieldNumber) { - GetDocumentsSplitCountRequest_GetDocumentsSplitCountRequestV0_FieldNumber_DataContractId = 1, - GetDocumentsSplitCountRequest_GetDocumentsSplitCountRequestV0_FieldNumber_DocumentType = 2, - GetDocumentsSplitCountRequest_GetDocumentsSplitCountRequestV0_FieldNumber_Where = 3, - GetDocumentsSplitCountRequest_GetDocumentsSplitCountRequestV0_FieldNumber_SplitCountByIndexProperty = 4, - GetDocumentsSplitCountRequest_GetDocumentsSplitCountRequestV0_FieldNumber_Prove = 5, -}; +GPB_FINAL @interface GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountEntry : GPBMessage -GPB_FINAL @interface GetDocumentsSplitCountRequest_GetDocumentsSplitCountRequestV0 : GPBMessage - -/** The ID of the data contract containing the documents */ -@property(nonatomic, readwrite, copy, null_resettable) NSData *dataContractId; - -/** The type of document being requested */ -@property(nonatomic, readwrite, copy, null_resettable) NSString *documentType; - -/** CBOR-encoded where clauses for filtering */ -@property(nonatomic, readwrite, copy, null_resettable) NSData *where; +/** + * Serialized prefix key for compound queries — the In's value + * for this fork. Absent for flat queries with no `In` on + * prefix (in which case entries are keyed purely by `key`). + **/ +@property(nonatomic, readwrite, copy, null_resettable) NSData *inKey; +/** Test to see if @c inKey has been set. */ +@property(nonatomic, readwrite) BOOL hasInKey; -/** The index property to split counts by */ -@property(nonatomic, readwrite, copy, null_resettable) NSString *splitCountByIndexProperty; +/** + * Serialized terminator key (the range-property value for + * distinct-range modes, or the `In` value for per-In-value + * mode without a range clause). + **/ +@property(nonatomic, readwrite, copy, null_resettable) NSData *key; -/** Flag to request a proof as the response */ -@property(nonatomic, readwrite) BOOL prove; +/** + * `jstype = JS_STRING` so JS/Web clients receive a string and don't + * round counts > 2^53-1 to the nearest representable Number. Matches + * the convention used elsewhere in this proto for `uint64` fields + * that can exceed Number.MAX_SAFE_INTEGER. + **/ +@property(nonatomic, readwrite) uint64_t count; @end -#pragma mark - GetDocumentsSplitCountResponse - -typedef GPB_ENUM(GetDocumentsSplitCountResponse_FieldNumber) { - GetDocumentsSplitCountResponse_FieldNumber_V0 = 1, -}; +#pragma mark - GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountEntries -typedef GPB_ENUM(GetDocumentsSplitCountResponse_Version_OneOfCase) { - GetDocumentsSplitCountResponse_Version_OneOfCase_GPBUnsetOneOfCase = 0, - GetDocumentsSplitCountResponse_Version_OneOfCase_V0 = 1, +typedef GPB_ENUM(GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountEntries_FieldNumber) { + GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountEntries_FieldNumber_EntriesArray = 1, }; -GPB_FINAL @interface GetDocumentsSplitCountResponse : GPBMessage +GPB_FINAL @interface GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountEntries : GPBMessage -@property(nonatomic, readonly) GetDocumentsSplitCountResponse_Version_OneOfCase versionOneOfCase; - -@property(nonatomic, readwrite, strong, null_resettable) GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0 *v0; +@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; @end -/** - * Clears whatever value was set for the oneof 'version'. - **/ -void GetDocumentsSplitCountResponse_ClearVersionOneOfCase(GetDocumentsSplitCountResponse *message); - -#pragma mark - GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0 +#pragma mark - GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountResults -typedef GPB_ENUM(GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_FieldNumber) { - GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_FieldNumber_SplitCounts = 1, - GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_FieldNumber_Proof = 2, - GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_FieldNumber_Metadata = 3, +typedef GPB_ENUM(GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountResults_FieldNumber) { + GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountResults_FieldNumber_AggregateCount = 1, + GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountResults_FieldNumber_Entries = 2, }; -typedef GPB_ENUM(GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_Result_OneOfCase) { - GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_Result_OneOfCase_GPBUnsetOneOfCase = 0, - GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_Result_OneOfCase_SplitCounts = 1, - GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_Result_OneOfCase_Proof = 2, +typedef GPB_ENUM(GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountResults_Variant_OneOfCase) { + GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountResults_Variant_OneOfCase_GPBUnsetOneOfCase = 0, + GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountResults_Variant_OneOfCase_AggregateCount = 1, + GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountResults_Variant_OneOfCase_Entries = 2, }; -GPB_FINAL @interface GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0 : GPBMessage - -@property(nonatomic, readonly) GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_Result_OneOfCase resultOneOfCase; - -/** Per-key counts */ -@property(nonatomic, readwrite, strong, null_resettable) GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_SplitCounts *splitCounts; - -/** Cryptographic proof, if requested */ -@property(nonatomic, readwrite, strong, null_resettable) Proof *proof; - -/** Metadata about the blockchain state */ -@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'. + * Non-proof count result. Shape is mode-dependent and made + * explicit on the wire via the inner `variant` oneof: + * * `aggregate_count`: total-count and range-without-distinct + * modes — a single u64 with no per-key breakdown. Callers + * read the total directly without scanning an entries list. + * * `entries`: per-`In`-value and per-distinct-value-in-range + * modes — one CountEntry per distinct value, in serialized- + * key order subject to the first `order_by` clause's + * direction and `limit`. **/ -void GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_ClearResultOneOfCase(GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0 *message); - -#pragma mark - GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_SplitCountEntry +GPB_FINAL @interface GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountResults : GPBMessage -typedef GPB_ENUM(GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_SplitCountEntry_FieldNumber) { - GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_SplitCountEntry_FieldNumber_Key = 1, - GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_SplitCountEntry_FieldNumber_Count = 2, -}; +@property(nonatomic, readonly) GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountResults_Variant_OneOfCase variantOneOfCase; /** - * A single entry: the key value and how many documents match + * `jstype = JS_STRING` for the same reason as + * `CountEntry.count` — JS Number rounds at 2^53−1. **/ -GPB_FINAL @interface GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_SplitCountEntry : GPBMessage - -/** The index property value */ -@property(nonatomic, readwrite, copy, null_resettable) NSData *key; +@property(nonatomic, readwrite) uint64_t aggregateCount; -/** Number of documents with this key value */ -@property(nonatomic, readwrite) uint64_t count; +@property(nonatomic, readwrite, strong, null_resettable) GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountEntries *entries; @end -#pragma mark - GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_SplitCounts - -typedef GPB_ENUM(GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_SplitCounts_FieldNumber) { - GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_SplitCounts_FieldNumber_EntriesArray = 1, -}; - -GPB_FINAL @interface GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_SplitCounts : 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; - -@end +/** + * Clears whatever value was set for the oneof 'variant'. + **/ +void GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountResults_ClearVariantOneOfCase(GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountResults *message); #pragma mark - GetIdentityByPublicKeyHashRequest 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 dc79f030c9d..c4e72e7c9ef 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 @@ -120,17 +120,14 @@ GPBObjCClassDeclaration(GetDocumentsCountRequest_GetDocumentsCountRequestV0); GPBObjCClassDeclaration(GetDocumentsCountResponse); GPBObjCClassDeclaration(GetDocumentsCountResponse_GetDocumentsCountResponseV0); +GPBObjCClassDeclaration(GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountEntries); +GPBObjCClassDeclaration(GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountEntry); +GPBObjCClassDeclaration(GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountResults); GPBObjCClassDeclaration(GetDocumentsRequest); GPBObjCClassDeclaration(GetDocumentsRequest_GetDocumentsRequestV0); GPBObjCClassDeclaration(GetDocumentsResponse); GPBObjCClassDeclaration(GetDocumentsResponse_GetDocumentsResponseV0); GPBObjCClassDeclaration(GetDocumentsResponse_GetDocumentsResponseV0_Documents); -GPBObjCClassDeclaration(GetDocumentsSplitCountRequest); -GPBObjCClassDeclaration(GetDocumentsSplitCountRequest_GetDocumentsSplitCountRequestV0); -GPBObjCClassDeclaration(GetDocumentsSplitCountResponse); -GPBObjCClassDeclaration(GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0); -GPBObjCClassDeclaration(GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_SplitCountEntry); -GPBObjCClassDeclaration(GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_SplitCounts); GPBObjCClassDeclaration(GetEpochsInfoRequest); GPBObjCClassDeclaration(GetEpochsInfoRequest_GetEpochsInfoRequestV0); GPBObjCClassDeclaration(GetEpochsInfoResponse); @@ -5513,13 +5510,18 @@ @implementation GetDocumentsCountRequest_GetDocumentsCountRequestV0 @dynamic dataContractId; @dynamic documentType; @dynamic where; +@dynamic returnDistinctCountsInRange; +@dynamic orderBy; +@dynamic hasLimit, limit; @dynamic prove; typedef struct GetDocumentsCountRequest_GetDocumentsCountRequestV0__storage_ { uint32_t _has_storage_[1]; + uint32_t limit; NSData *dataContractId; NSString *documentType; NSData *where; + NSData *orderBy; } GetDocumentsCountRequest_GetDocumentsCountRequestV0__storage_; // This method is threadsafe because it is initially called @@ -5556,14 +5558,41 @@ + (GPBDescriptor *)descriptor { .dataType = GPBDataTypeBytes, }, { - .name = "prove", + .name = "returnDistinctCountsInRange", .dataTypeSpecific.clazz = Nil, - .number = GetDocumentsCountRequest_GetDocumentsCountRequestV0_FieldNumber_Prove, + .number = GetDocumentsCountRequest_GetDocumentsCountRequestV0_FieldNumber_ReturnDistinctCountsInRange, .hasIndex = 3, .offset = 4, // Stored in _has_storage_ to save space. .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeBool, }, + { + .name = "orderBy", + .dataTypeSpecific.clazz = Nil, + .number = GetDocumentsCountRequest_GetDocumentsCountRequestV0_FieldNumber_OrderBy, + .hasIndex = 5, + .offset = (uint32_t)offsetof(GetDocumentsCountRequest_GetDocumentsCountRequestV0__storage_, orderBy), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeBytes, + }, + { + .name = "limit", + .dataTypeSpecific.clazz = Nil, + .number = GetDocumentsCountRequest_GetDocumentsCountRequestV0_FieldNumber_Limit, + .hasIndex = 6, + .offset = (uint32_t)offsetof(GetDocumentsCountRequest_GetDocumentsCountRequestV0__storage_, limit), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeUInt32, + }, + { + .name = "prove", + .dataTypeSpecific.clazz = Nil, + .number = GetDocumentsCountRequest_GetDocumentsCountRequestV0_FieldNumber_Prove, + .hasIndex = 7, + .offset = 8, // Stored in _has_storage_ to save space. + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeBool, + }, }; GPBDescriptor *localDescriptor = [GPBDescriptor allocDescriptorForClass:[GetDocumentsCountRequest_GetDocumentsCountRequestV0 class] @@ -5646,15 +5675,15 @@ void GetDocumentsCountResponse_ClearVersionOneOfCase(GetDocumentsCountResponse * @implementation GetDocumentsCountResponse_GetDocumentsCountResponseV0 @dynamic resultOneOfCase; -@dynamic count; +@dynamic counts; @dynamic proof; @dynamic hasMetadata, metadata; typedef struct GetDocumentsCountResponse_GetDocumentsCountResponseV0__storage_ { uint32_t _has_storage_[2]; + GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountResults *counts; Proof *proof; ResponseMetadata *metadata; - uint64_t count; } GetDocumentsCountResponse_GetDocumentsCountResponseV0__storage_; // This method is threadsafe because it is initially called @@ -5664,13 +5693,13 @@ + (GPBDescriptor *)descriptor { if (!descriptor) { static GPBMessageFieldDescription fields[] = { { - .name = "count", - .dataTypeSpecific.clazz = Nil, - .number = GetDocumentsCountResponse_GetDocumentsCountResponseV0_FieldNumber_Count, + .name = "counts", + .dataTypeSpecific.clazz = GPBObjCClass(GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountResults), + .number = GetDocumentsCountResponse_GetDocumentsCountResponseV0_FieldNumber_Counts, .hasIndex = -1, - .offset = (uint32_t)offsetof(GetDocumentsCountResponse_GetDocumentsCountResponseV0__storage_, count), + .offset = (uint32_t)offsetof(GetDocumentsCountResponse_GetDocumentsCountResponseV0__storage_, counts), .flags = GPBFieldOptional, - .dataType = GPBDataTypeUInt64, + .dataType = GPBDataTypeMessage, }, { .name = "proof", @@ -5721,80 +5750,20 @@ void GetDocumentsCountResponse_GetDocumentsCountResponseV0_ClearResultOneOfCase( GPBOneofDescriptor *oneof = [descriptor.oneofs objectAtIndex:0]; GPBClearOneof(message, oneof); } -#pragma mark - GetDocumentsSplitCountRequest - -@implementation GetDocumentsSplitCountRequest +#pragma mark - GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountEntry -@dynamic versionOneOfCase; -@dynamic v0; +@implementation GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountEntry -typedef struct GetDocumentsSplitCountRequest__storage_ { - uint32_t _has_storage_[2]; - GetDocumentsSplitCountRequest_GetDocumentsSplitCountRequestV0 *v0; -} GetDocumentsSplitCountRequest__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 = "v0", - .dataTypeSpecific.clazz = GPBObjCClass(GetDocumentsSplitCountRequest_GetDocumentsSplitCountRequestV0), - .number = GetDocumentsSplitCountRequest_FieldNumber_V0, - .hasIndex = -1, - .offset = (uint32_t)offsetof(GetDocumentsSplitCountRequest__storage_, v0), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeMessage, - }, - }; - GPBDescriptor *localDescriptor = - [GPBDescriptor allocDescriptorForClass:[GetDocumentsSplitCountRequest class] - rootClass:[PlatformRoot class] - file:PlatformRoot_FileDescriptor() - fields:fields - fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) - storageSize:sizeof(GetDocumentsSplitCountRequest__storage_) - flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; - static const char *oneofs[] = { - "version", - }; - [localDescriptor setupOneofs:oneofs - count:(uint32_t)(sizeof(oneofs) / sizeof(char*)) - firstHasIndex:-1]; - #if defined(DEBUG) && DEBUG - NSAssert(descriptor == nil, @"Startup recursed!"); - #endif // DEBUG - descriptor = localDescriptor; - } - return descriptor; -} - -@end - -void GetDocumentsSplitCountRequest_ClearVersionOneOfCase(GetDocumentsSplitCountRequest *message) { - GPBDescriptor *descriptor = [GetDocumentsSplitCountRequest descriptor]; - GPBOneofDescriptor *oneof = [descriptor.oneofs objectAtIndex:0]; - GPBClearOneof(message, oneof); -} -#pragma mark - GetDocumentsSplitCountRequest_GetDocumentsSplitCountRequestV0 - -@implementation GetDocumentsSplitCountRequest_GetDocumentsSplitCountRequestV0 - -@dynamic dataContractId; -@dynamic documentType; -@dynamic where; -@dynamic splitCountByIndexProperty; -@dynamic prove; +@dynamic hasInKey, inKey; +@dynamic key; +@dynamic count; -typedef struct GetDocumentsSplitCountRequest_GetDocumentsSplitCountRequestV0__storage_ { +typedef struct GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountEntry__storage_ { uint32_t _has_storage_[1]; - NSData *dataContractId; - NSString *documentType; - NSData *where; - NSString *splitCountByIndexProperty; -} GetDocumentsSplitCountRequest_GetDocumentsSplitCountRequestV0__storage_; + NSData *inKey; + NSData *key; + uint64_t count; +} GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountEntry__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. @@ -5803,60 +5772,42 @@ + (GPBDescriptor *)descriptor { if (!descriptor) { static GPBMessageFieldDescription fields[] = { { - .name = "dataContractId", + .name = "inKey", .dataTypeSpecific.clazz = Nil, - .number = GetDocumentsSplitCountRequest_GetDocumentsSplitCountRequestV0_FieldNumber_DataContractId, + .number = GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountEntry_FieldNumber_InKey, .hasIndex = 0, - .offset = (uint32_t)offsetof(GetDocumentsSplitCountRequest_GetDocumentsSplitCountRequestV0__storage_, dataContractId), - .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .offset = (uint32_t)offsetof(GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountEntry__storage_, inKey), + .flags = GPBFieldOptional, .dataType = GPBDataTypeBytes, }, { - .name = "documentType", + .name = "key", .dataTypeSpecific.clazz = Nil, - .number = GetDocumentsSplitCountRequest_GetDocumentsSplitCountRequestV0_FieldNumber_DocumentType, + .number = GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountEntry_FieldNumber_Key, .hasIndex = 1, - .offset = (uint32_t)offsetof(GetDocumentsSplitCountRequest_GetDocumentsSplitCountRequestV0__storage_, documentType), - .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), - .dataType = GPBDataTypeString, - }, - { - .name = "where", - .dataTypeSpecific.clazz = Nil, - .number = GetDocumentsSplitCountRequest_GetDocumentsSplitCountRequestV0_FieldNumber_Where, - .hasIndex = 2, - .offset = (uint32_t)offsetof(GetDocumentsSplitCountRequest_GetDocumentsSplitCountRequestV0__storage_, where), + .offset = (uint32_t)offsetof(GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountEntry__storage_, key), .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeBytes, }, { - .name = "splitCountByIndexProperty", - .dataTypeSpecific.clazz = Nil, - .number = GetDocumentsSplitCountRequest_GetDocumentsSplitCountRequestV0_FieldNumber_SplitCountByIndexProperty, - .hasIndex = 3, - .offset = (uint32_t)offsetof(GetDocumentsSplitCountRequest_GetDocumentsSplitCountRequestV0__storage_, splitCountByIndexProperty), - .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), - .dataType = GPBDataTypeString, - }, - { - .name = "prove", + .name = "count", .dataTypeSpecific.clazz = Nil, - .number = GetDocumentsSplitCountRequest_GetDocumentsSplitCountRequestV0_FieldNumber_Prove, - .hasIndex = 4, - .offset = 5, // Stored in _has_storage_ to save space. + .number = GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountEntry_FieldNumber_Count, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountEntry__storage_, count), .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), - .dataType = GPBDataTypeBool, + .dataType = GPBDataTypeUInt64, }, }; GPBDescriptor *localDescriptor = - [GPBDescriptor allocDescriptorForClass:[GetDocumentsSplitCountRequest_GetDocumentsSplitCountRequestV0 class] + [GPBDescriptor allocDescriptorForClass:[GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountEntry class] rootClass:[PlatformRoot class] file:PlatformRoot_FileDescriptor() fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) - storageSize:sizeof(GetDocumentsSplitCountRequest_GetDocumentsSplitCountRequestV0__storage_) + storageSize:sizeof(GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountEntry__storage_) flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; - [localDescriptor setupContainingMessageClass:GPBObjCClass(GetDocumentsSplitCountRequest)]; + [localDescriptor setupContainingMessageClass:GPBObjCClass(GetDocumentsCountResponse_GetDocumentsCountResponseV0)]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG @@ -5867,17 +5818,16 @@ + (GPBDescriptor *)descriptor { @end -#pragma mark - GetDocumentsSplitCountResponse +#pragma mark - GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountEntries -@implementation GetDocumentsSplitCountResponse +@implementation GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountEntries -@dynamic versionOneOfCase; -@dynamic v0; +@dynamic entriesArray, entriesArray_Count; -typedef struct GetDocumentsSplitCountResponse__storage_ { - uint32_t _has_storage_[2]; - GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0 *v0; -} GetDocumentsSplitCountResponse__storage_; +typedef struct GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountEntries__storage_ { + uint32_t _has_storage_[1]; + NSMutableArray *entriesArray; +} GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountEntries__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. @@ -5886,29 +5836,24 @@ + (GPBDescriptor *)descriptor { if (!descriptor) { static GPBMessageFieldDescription fields[] = { { - .name = "v0", - .dataTypeSpecific.clazz = GPBObjCClass(GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0), - .number = GetDocumentsSplitCountResponse_FieldNumber_V0, - .hasIndex = -1, - .offset = (uint32_t)offsetof(GetDocumentsSplitCountResponse__storage_, v0), - .flags = GPBFieldOptional, + .name = "entriesArray", + .dataTypeSpecific.clazz = GPBObjCClass(GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountEntry), + .number = GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountEntries_FieldNumber_EntriesArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountEntries__storage_, entriesArray), + .flags = GPBFieldRepeated, .dataType = GPBDataTypeMessage, }, }; GPBDescriptor *localDescriptor = - [GPBDescriptor allocDescriptorForClass:[GetDocumentsSplitCountResponse class] + [GPBDescriptor allocDescriptorForClass:[GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountEntries class] rootClass:[PlatformRoot class] file:PlatformRoot_FileDescriptor() fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) - storageSize:sizeof(GetDocumentsSplitCountResponse__storage_) + storageSize:sizeof(GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountEntries__storage_) flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; - static const char *oneofs[] = { - "version", - }; - [localDescriptor setupOneofs:oneofs - count:(uint32_t)(sizeof(oneofs) / sizeof(char*)) - firstHasIndex:-1]; + [localDescriptor setupContainingMessageClass:GPBObjCClass(GetDocumentsCountResponse_GetDocumentsCountResponseV0)]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG @@ -5919,26 +5864,19 @@ + (GPBDescriptor *)descriptor { @end -void GetDocumentsSplitCountResponse_ClearVersionOneOfCase(GetDocumentsSplitCountResponse *message) { - GPBDescriptor *descriptor = [GetDocumentsSplitCountResponse descriptor]; - GPBOneofDescriptor *oneof = [descriptor.oneofs objectAtIndex:0]; - GPBClearOneof(message, oneof); -} -#pragma mark - GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0 +#pragma mark - GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountResults -@implementation GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0 +@implementation GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountResults -@dynamic resultOneOfCase; -@dynamic splitCounts; -@dynamic proof; -@dynamic hasMetadata, metadata; +@dynamic variantOneOfCase; +@dynamic aggregateCount; +@dynamic entries; -typedef struct GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0__storage_ { +typedef struct GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountResults__storage_ { uint32_t _has_storage_[2]; - GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_SplitCounts *splitCounts; - Proof *proof; - ResponseMetadata *metadata; -} GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0__storage_; + GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountEntries *entries; + uint64_t aggregateCount; +} GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountResults__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. @@ -5947,48 +5885,39 @@ + (GPBDescriptor *)descriptor { if (!descriptor) { static GPBMessageFieldDescription fields[] = { { - .name = "splitCounts", - .dataTypeSpecific.clazz = GPBObjCClass(GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_SplitCounts), - .number = GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_FieldNumber_SplitCounts, + .name = "aggregateCount", + .dataTypeSpecific.clazz = Nil, + .number = GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountResults_FieldNumber_AggregateCount, .hasIndex = -1, - .offset = (uint32_t)offsetof(GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0__storage_, splitCounts), + .offset = (uint32_t)offsetof(GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountResults__storage_, aggregateCount), .flags = GPBFieldOptional, - .dataType = GPBDataTypeMessage, + .dataType = GPBDataTypeUInt64, }, { - .name = "proof", - .dataTypeSpecific.clazz = GPBObjCClass(Proof), - .number = GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_FieldNumber_Proof, + .name = "entries", + .dataTypeSpecific.clazz = GPBObjCClass(GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountEntries), + .number = GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountResults_FieldNumber_Entries, .hasIndex = -1, - .offset = (uint32_t)offsetof(GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0__storage_, proof), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeMessage, - }, - { - .name = "metadata", - .dataTypeSpecific.clazz = GPBObjCClass(ResponseMetadata), - .number = GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_FieldNumber_Metadata, - .hasIndex = 0, - .offset = (uint32_t)offsetof(GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0__storage_, metadata), + .offset = (uint32_t)offsetof(GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountResults__storage_, entries), .flags = GPBFieldOptional, .dataType = GPBDataTypeMessage, }, }; GPBDescriptor *localDescriptor = - [GPBDescriptor allocDescriptorForClass:[GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0 class] + [GPBDescriptor allocDescriptorForClass:[GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountResults class] rootClass:[PlatformRoot class] file:PlatformRoot_FileDescriptor() fields:fields fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) - storageSize:sizeof(GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0__storage_) + storageSize:sizeof(GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountResults__storage_) flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; static const char *oneofs[] = { - "result", + "variant", }; [localDescriptor setupOneofs:oneofs count:(uint32_t)(sizeof(oneofs) / sizeof(char*)) firstHasIndex:-1]; - [localDescriptor setupContainingMessageClass:GPBObjCClass(GetDocumentsSplitCountResponse)]; + [localDescriptor setupContainingMessageClass:GPBObjCClass(GetDocumentsCountResponse_GetDocumentsCountResponseV0)]; #if defined(DEBUG) && DEBUG NSAssert(descriptor == nil, @"Startup recursed!"); #endif // DEBUG @@ -5999,114 +5928,11 @@ + (GPBDescriptor *)descriptor { @end -void GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_ClearResultOneOfCase(GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0 *message) { - GPBDescriptor *descriptor = [GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0 descriptor]; +void GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountResults_ClearVariantOneOfCase(GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountResults *message) { + GPBDescriptor *descriptor = [GetDocumentsCountResponse_GetDocumentsCountResponseV0_CountResults descriptor]; GPBOneofDescriptor *oneof = [descriptor.oneofs objectAtIndex:0]; GPBClearOneof(message, oneof); } -#pragma mark - GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_SplitCountEntry - -@implementation GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_SplitCountEntry - -@dynamic key; -@dynamic count; - -typedef struct GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_SplitCountEntry__storage_ { - uint32_t _has_storage_[1]; - NSData *key; - uint64_t count; -} GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_SplitCountEntry__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 = "key", - .dataTypeSpecific.clazz = Nil, - .number = GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_SplitCountEntry_FieldNumber_Key, - .hasIndex = 0, - .offset = (uint32_t)offsetof(GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_SplitCountEntry__storage_, key), - .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), - .dataType = GPBDataTypeBytes, - }, - { - .name = "count", - .dataTypeSpecific.clazz = Nil, - .number = GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_SplitCountEntry_FieldNumber_Count, - .hasIndex = 1, - .offset = (uint32_t)offsetof(GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_SplitCountEntry__storage_, count), - .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), - .dataType = GPBDataTypeUInt64, - }, - }; - GPBDescriptor *localDescriptor = - [GPBDescriptor allocDescriptorForClass:[GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_SplitCountEntry class] - rootClass:[PlatformRoot class] - file:PlatformRoot_FileDescriptor() - fields:fields - fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) - storageSize:sizeof(GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_SplitCountEntry__storage_) - flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; - [localDescriptor setupContainingMessageClass:GPBObjCClass(GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0)]; - #if defined(DEBUG) && DEBUG - NSAssert(descriptor == nil, @"Startup recursed!"); - #endif // DEBUG - descriptor = localDescriptor; - } - return descriptor; -} - -@end - -#pragma mark - GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_SplitCounts - -@implementation GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_SplitCounts - -@dynamic entriesArray, entriesArray_Count; - -typedef struct GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_SplitCounts__storage_ { - uint32_t _has_storage_[1]; - NSMutableArray *entriesArray; -} GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_SplitCounts__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(GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_SplitCountEntry), - .number = GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_SplitCounts_FieldNumber_EntriesArray, - .hasIndex = GPBNoHasBit, - .offset = (uint32_t)offsetof(GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_SplitCounts__storage_, entriesArray), - .flags = GPBFieldRepeated, - .dataType = GPBDataTypeMessage, - }, - }; - GPBDescriptor *localDescriptor = - [GPBDescriptor allocDescriptorForClass:[GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_SplitCounts class] - rootClass:[PlatformRoot class] - file:PlatformRoot_FileDescriptor() - fields:fields - fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) - storageSize:sizeof(GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0_SplitCounts__storage_) - flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; - [localDescriptor setupContainingMessageClass:GPBObjCClass(GetDocumentsSplitCountResponse_GetDocumentsSplitCountResponseV0)]; - #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/objective-c/Platform.pbrpc.h b/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbrpc.h index f0b6902be5c..614772fb595 100644 --- a/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbrpc.h +++ b/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbrpc.h @@ -46,8 +46,6 @@ @class GetDocumentsCountResponse; @class GetDocumentsRequest; @class GetDocumentsResponse; -@class GetDocumentsSplitCountRequest; -@class GetDocumentsSplitCountResponse; @class GetEpochsInfoRequest; @class GetEpochsInfoResponse; @class GetEvonodesProposedEpochBlocksByIdsRequest; @@ -238,10 +236,6 @@ NS_ASSUME_NONNULL_BEGIN - (GRPCUnaryProtoCall *)getDocumentsCountWithMessage:(GetDocumentsCountRequest *)message responseHandler:(id)handler callOptions:(GRPCCallOptions *_Nullable)callOptions; -#pragma mark getDocumentsSplitCount(GetDocumentsSplitCountRequest) returns (GetDocumentsSplitCountResponse) - -- (GRPCUnaryProtoCall *)getDocumentsSplitCountWithMessage:(GetDocumentsSplitCountRequest *)message responseHandler:(id)handler callOptions:(GRPCCallOptions *_Nullable)callOptions; - #pragma mark getIdentityByPublicKeyHash(GetIdentityByPublicKeyHashRequest) returns (GetIdentityByPublicKeyHashResponse) - (GRPCUnaryProtoCall *)getIdentityByPublicKeyHashWithMessage:(GetIdentityByPublicKeyHashRequest *)message responseHandler:(id)handler callOptions:(GRPCCallOptions *_Nullable)callOptions; @@ -578,13 +572,6 @@ NS_ASSUME_NONNULL_BEGIN - (GRPCProtoCall *)RPCTogetDocumentsCountWithRequest:(GetDocumentsCountRequest *)request handler:(void(^)(GetDocumentsCountResponse *_Nullable response, NSError *_Nullable error))handler; -#pragma mark getDocumentsSplitCount(GetDocumentsSplitCountRequest) returns (GetDocumentsSplitCountResponse) - -- (void)getDocumentsSplitCountWithRequest:(GetDocumentsSplitCountRequest *)request handler:(void(^)(GetDocumentsSplitCountResponse *_Nullable response, NSError *_Nullable error))handler; - -- (GRPCProtoCall *)RPCTogetDocumentsSplitCountWithRequest:(GetDocumentsSplitCountRequest *)request handler:(void(^)(GetDocumentsSplitCountResponse *_Nullable response, NSError *_Nullable error))handler; - - #pragma mark getIdentityByPublicKeyHash(GetIdentityByPublicKeyHashRequest) returns (GetIdentityByPublicKeyHashResponse) - (void)getIdentityByPublicKeyHashWithRequest:(GetIdentityByPublicKeyHashRequest *)request handler:(void(^)(GetIdentityByPublicKeyHashResponse *_Nullable response, NSError *_Nullable error))handler; diff --git a/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbrpc.m b/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbrpc.m index 4a440188fd1..95bfaa8245a 100644 --- a/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbrpc.m +++ b/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbrpc.m @@ -403,26 +403,6 @@ - (GRPCUnaryProtoCall *)getDocumentsCountWithMessage:(GetDocumentsCountRequest * responseClass:[GetDocumentsCountResponse class]]; } -#pragma mark getDocumentsSplitCount(GetDocumentsSplitCountRequest) returns (GetDocumentsSplitCountResponse) - -- (void)getDocumentsSplitCountWithRequest:(GetDocumentsSplitCountRequest *)request handler:(void(^)(GetDocumentsSplitCountResponse *_Nullable response, NSError *_Nullable error))handler{ - [[self RPCTogetDocumentsSplitCountWithRequest:request handler:handler] start]; -} -// Returns a not-yet-started RPC object. -- (GRPCProtoCall *)RPCTogetDocumentsSplitCountWithRequest:(GetDocumentsSplitCountRequest *)request handler:(void(^)(GetDocumentsSplitCountResponse *_Nullable response, NSError *_Nullable error))handler{ - return [self RPCToMethod:@"getDocumentsSplitCount" - requestsWriter:[GRXWriter writerWithValue:request] - responseClass:[GetDocumentsSplitCountResponse class] - responsesWriteable:[GRXWriteable writeableWithSingleHandler:handler]]; -} -- (GRPCUnaryProtoCall *)getDocumentsSplitCountWithMessage:(GetDocumentsSplitCountRequest *)message responseHandler:(id)handler callOptions:(GRPCCallOptions *_Nullable)callOptions { - return [self RPCToMethod:@"getDocumentsSplitCount" - message:message - responseHandler:handler - callOptions:callOptions - responseClass:[GetDocumentsSplitCountResponse class]]; -} - #pragma mark getIdentityByPublicKeyHash(GetIdentityByPublicKeyHashRequest) returns (GetIdentityByPublicKeyHashResponse) - (void)getIdentityByPublicKeyHashWithRequest:(GetIdentityByPublicKeyHashRequest *)request handler:(void(^)(GetIdentityByPublicKeyHashResponse *_Nullable response, NSError *_Nullable error))handler{ 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 fad9590a2c3..cc449f137d3 100644 --- a/packages/dapi-grpc/clients/platform/v0/python/platform_pb2.py +++ b/packages/dapi-grpc/clients/platform/v0/python/platform_pb2.py @@ -23,7 +23,7 @@ syntax='proto3', serialized_options=None, create_key=_descriptor._internal_create_key, - serialized_pb=b'\n\x0eplatform.proto\x12\x19org.dash.platform.dapi.v0\x1a\x1egoogle/protobuf/wrappers.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\x81\x01\n\x05Proof\x12\x15\n\rgrovedb_proof\x18\x01 \x01(\x0c\x12\x13\n\x0bquorum_hash\x18\x02 \x01(\x0c\x12\x11\n\tsignature\x18\x03 \x01(\x0c\x12\r\n\x05round\x18\x04 \x01(\r\x12\x15\n\rblock_id_hash\x18\x05 \x01(\x0c\x12\x13\n\x0bquorum_type\x18\x06 \x01(\r\"\x98\x01\n\x10ResponseMetadata\x12\x12\n\x06height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12 \n\x18\x63ore_chain_locked_height\x18\x02 \x01(\r\x12\r\n\x05\x65poch\x18\x03 \x01(\r\x12\x13\n\x07time_ms\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\x18\n\x10protocol_version\x18\x05 \x01(\r\x12\x10\n\x08\x63hain_id\x18\x06 \x01(\t\"L\n\x1dStateTransitionBroadcastError\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x03 \x01(\x0c\";\n\x1f\x42roadcastStateTransitionRequest\x12\x18\n\x10state_transition\x18\x01 \x01(\x0c\"\"\n BroadcastStateTransitionResponse\"\xa4\x01\n\x12GetIdentityRequest\x12P\n\x02v0\x18\x01 \x01(\x0b\x32\x42.org.dash.platform.dapi.v0.GetIdentityRequest.GetIdentityRequestV0H\x00\x1a\x31\n\x14GetIdentityRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xc1\x01\n\x17GetIdentityNonceRequest\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetIdentityNonceRequest.GetIdentityNonceRequestV0H\x00\x1a?\n\x19GetIdentityNonceRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xf6\x01\n\x1fGetIdentityContractNonceRequest\x12j\n\x02v0\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetIdentityContractNonceRequest.GetIdentityContractNonceRequestV0H\x00\x1a\\\n!GetIdentityContractNonceRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x13\n\x0b\x63ontract_id\x18\x02 \x01(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xc0\x01\n\x19GetIdentityBalanceRequest\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetIdentityBalanceRequest.GetIdentityBalanceRequestV0H\x00\x1a\x38\n\x1bGetIdentityBalanceRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xec\x01\n$GetIdentityBalanceAndRevisionRequest\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionRequest.GetIdentityBalanceAndRevisionRequestV0H\x00\x1a\x43\n&GetIdentityBalanceAndRevisionRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x9e\x02\n\x13GetIdentityResponse\x12R\n\x02v0\x18\x01 \x01(\x0b\x32\x44.org.dash.platform.dapi.v0.GetIdentityResponse.GetIdentityResponseV0H\x00\x1a\xa7\x01\n\x15GetIdentityResponseV0\x12\x12\n\x08identity\x18\x01 \x01(\x0cH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xbc\x02\n\x18GetIdentityNonceResponse\x12\\\n\x02v0\x18\x01 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetIdentityNonceResponse.GetIdentityNonceResponseV0H\x00\x1a\xb6\x01\n\x1aGetIdentityNonceResponseV0\x12\x1c\n\x0eidentity_nonce\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xe5\x02\n GetIdentityContractNonceResponse\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetIdentityContractNonceResponse.GetIdentityContractNonceResponseV0H\x00\x1a\xc7\x01\n\"GetIdentityContractNonceResponseV0\x12%\n\x17identity_contract_nonce\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xbd\x02\n\x1aGetIdentityBalanceResponse\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetIdentityBalanceResponse.GetIdentityBalanceResponseV0H\x00\x1a\xb1\x01\n\x1cGetIdentityBalanceResponseV0\x12\x15\n\x07\x62\x61lance\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xb1\x04\n%GetIdentityBalanceAndRevisionResponse\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionResponse.GetIdentityBalanceAndRevisionResponseV0H\x00\x1a\x84\x03\n\'GetIdentityBalanceAndRevisionResponseV0\x12\x9b\x01\n\x14\x62\x61lance_and_revision\x18\x01 \x01(\x0b\x32{.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionResponse.GetIdentityBalanceAndRevisionResponseV0.BalanceAndRevisionH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a?\n\x12\x42\x61lanceAndRevision\x12\x13\n\x07\x62\x61lance\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x14\n\x08revision\x18\x02 \x01(\x04\x42\x02\x30\x01\x42\x08\n\x06resultB\t\n\x07version\"\xd1\x01\n\x0eKeyRequestType\x12\x36\n\x08\x61ll_keys\x18\x01 \x01(\x0b\x32\".org.dash.platform.dapi.v0.AllKeysH\x00\x12@\n\rspecific_keys\x18\x02 \x01(\x0b\x32\'.org.dash.platform.dapi.v0.SpecificKeysH\x00\x12:\n\nsearch_key\x18\x03 \x01(\x0b\x32$.org.dash.platform.dapi.v0.SearchKeyH\x00\x42\t\n\x07request\"\t\n\x07\x41llKeys\"\x1f\n\x0cSpecificKeys\x12\x0f\n\x07key_ids\x18\x01 \x03(\r\"\xb6\x01\n\tSearchKey\x12I\n\x0bpurpose_map\x18\x01 \x03(\x0b\x32\x34.org.dash.platform.dapi.v0.SearchKey.PurposeMapEntry\x1a^\n\x0fPurposeMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12:\n\x05value\x18\x02 \x01(\x0b\x32+.org.dash.platform.dapi.v0.SecurityLevelMap:\x02\x38\x01\"\xbf\x02\n\x10SecurityLevelMap\x12]\n\x12security_level_map\x18\x01 \x03(\x0b\x32\x41.org.dash.platform.dapi.v0.SecurityLevelMap.SecurityLevelMapEntry\x1aw\n\x15SecurityLevelMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12M\n\x05value\x18\x02 \x01(\x0e\x32>.org.dash.platform.dapi.v0.SecurityLevelMap.KeyKindRequestType:\x02\x38\x01\"S\n\x12KeyKindRequestType\x12\x1f\n\x1b\x43URRENT_KEY_OF_KIND_REQUEST\x10\x00\x12\x1c\n\x18\x41LL_KEYS_OF_KIND_REQUEST\x10\x01\"\xda\x02\n\x16GetIdentityKeysRequest\x12X\n\x02v0\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetIdentityKeysRequest.GetIdentityKeysRequestV0H\x00\x1a\xda\x01\n\x18GetIdentityKeysRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12?\n\x0crequest_type\x18\x02 \x01(\x0b\x32).org.dash.platform.dapi.v0.KeyRequestType\x12+\n\x05limit\x18\x03 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12,\n\x06offset\x18\x04 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\t\n\x07version\"\x99\x03\n\x17GetIdentityKeysResponse\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetIdentityKeysResponse.GetIdentityKeysResponseV0H\x00\x1a\x96\x02\n\x19GetIdentityKeysResponseV0\x12\x61\n\x04keys\x18\x01 \x01(\x0b\x32Q.org.dash.platform.dapi.v0.GetIdentityKeysResponse.GetIdentityKeysResponseV0.KeysH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1a\n\x04Keys\x12\x12\n\nkeys_bytes\x18\x01 \x03(\x0c\x42\x08\n\x06resultB\t\n\x07version\"\xef\x02\n GetIdentitiesContractKeysRequest\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetIdentitiesContractKeysRequest.GetIdentitiesContractKeysRequestV0H\x00\x1a\xd1\x01\n\"GetIdentitiesContractKeysRequestV0\x12\x16\n\x0eidentities_ids\x18\x01 \x03(\x0c\x12\x13\n\x0b\x63ontract_id\x18\x02 \x01(\x0c\x12\x1f\n\x12\x64ocument_type_name\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x37\n\x08purposes\x18\x04 \x03(\x0e\x32%.org.dash.platform.dapi.v0.KeyPurpose\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\x15\n\x13_document_type_nameB\t\n\x07version\"\xdf\x06\n!GetIdentitiesContractKeysResponse\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse.GetIdentitiesContractKeysResponseV0H\x00\x1a\xbe\x05\n#GetIdentitiesContractKeysResponseV0\x12\x8a\x01\n\x0fidentities_keys\x18\x01 \x01(\x0b\x32o.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse.GetIdentitiesContractKeysResponseV0.IdentitiesKeysH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aY\n\x0bPurposeKeys\x12\x36\n\x07purpose\x18\x01 \x01(\x0e\x32%.org.dash.platform.dapi.v0.KeyPurpose\x12\x12\n\nkeys_bytes\x18\x02 \x03(\x0c\x1a\x9f\x01\n\x0cIdentityKeys\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12z\n\x04keys\x18\x02 \x03(\x0b\x32l.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse.GetIdentitiesContractKeysResponseV0.PurposeKeys\x1a\x90\x01\n\x0eIdentitiesKeys\x12~\n\x07\x65ntries\x18\x01 \x03(\x0b\x32m.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse.GetIdentitiesContractKeysResponseV0.IdentityKeysB\x08\n\x06resultB\t\n\x07version\"\xa4\x02\n*GetEvonodesProposedEpochBlocksByIdsRequest\x12\x80\x01\n\x02v0\x18\x01 \x01(\x0b\x32r.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByIdsRequest.GetEvonodesProposedEpochBlocksByIdsRequestV0H\x00\x1ah\n,GetEvonodesProposedEpochBlocksByIdsRequestV0\x12\x12\n\x05\x65poch\x18\x01 \x01(\rH\x00\x88\x01\x01\x12\x0b\n\x03ids\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\x08\n\x06_epochB\t\n\x07version\"\x92\x06\n&GetEvonodesProposedEpochBlocksResponse\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksResponse.GetEvonodesProposedEpochBlocksResponseV0H\x00\x1a\xe2\x04\n(GetEvonodesProposedEpochBlocksResponseV0\x12\xb1\x01\n#evonodes_proposed_block_counts_info\x18\x01 \x01(\x0b\x32\x81\x01.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksResponse.GetEvonodesProposedEpochBlocksResponseV0.EvonodesProposedBlocksH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a?\n\x15\x45vonodeProposedBlocks\x12\x13\n\x0bpro_tx_hash\x18\x01 \x01(\x0c\x12\x11\n\x05\x63ount\x18\x02 \x01(\x04\x42\x02\x30\x01\x1a\xc4\x01\n\x16\x45vonodesProposedBlocks\x12\xa9\x01\n\x1e\x65vonodes_proposed_block_counts\x18\x01 \x03(\x0b\x32\x80\x01.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksResponse.GetEvonodesProposedEpochBlocksResponseV0.EvonodeProposedBlocksB\x08\n\x06resultB\t\n\x07version\"\xf2\x02\n,GetEvonodesProposedEpochBlocksByRangeRequest\x12\x84\x01\n\x02v0\x18\x01 \x01(\x0b\x32v.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByRangeRequest.GetEvonodesProposedEpochBlocksByRangeRequestV0H\x00\x1a\xaf\x01\n.GetEvonodesProposedEpochBlocksByRangeRequestV0\x12\x12\n\x05\x65poch\x18\x01 \x01(\rH\x01\x88\x01\x01\x12\x12\n\x05limit\x18\x02 \x01(\rH\x02\x88\x01\x01\x12\x15\n\x0bstart_after\x18\x03 \x01(\x0cH\x00\x12\x12\n\x08start_at\x18\x04 \x01(\x0cH\x00\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\x07\n\x05startB\x08\n\x06_epochB\x08\n\x06_limitB\t\n\x07version\"\xcd\x01\n\x1cGetIdentitiesBalancesRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0H\x00\x1a<\n\x1eGetIdentitiesBalancesRequestV0\x12\x0b\n\x03ids\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x9f\x05\n\x1dGetIdentitiesBalancesResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetIdentitiesBalancesResponse.GetIdentitiesBalancesResponseV0H\x00\x1a\x8a\x04\n\x1fGetIdentitiesBalancesResponseV0\x12\x8a\x01\n\x13identities_balances\x18\x01 \x01(\x0b\x32k.org.dash.platform.dapi.v0.GetIdentitiesBalancesResponse.GetIdentitiesBalancesResponseV0.IdentitiesBalancesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aL\n\x0fIdentityBalance\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x18\n\x07\x62\x61lance\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x88\x01\x01\x42\n\n\x08_balance\x1a\x8f\x01\n\x12IdentitiesBalances\x12y\n\x07\x65ntries\x18\x01 \x03(\x0b\x32h.org.dash.platform.dapi.v0.GetIdentitiesBalancesResponse.GetIdentitiesBalancesResponseV0.IdentityBalanceB\x08\n\x06resultB\t\n\x07version\"\xb4\x01\n\x16GetDataContractRequest\x12X\n\x02v0\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetDataContractRequest.GetDataContractRequestV0H\x00\x1a\x35\n\x18GetDataContractRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xb3\x02\n\x17GetDataContractResponse\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetDataContractResponse.GetDataContractResponseV0H\x00\x1a\xb0\x01\n\x19GetDataContractResponseV0\x12\x17\n\rdata_contract\x18\x01 \x01(\x0cH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xb9\x01\n\x17GetDataContractsRequest\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetDataContractsRequest.GetDataContractsRequestV0H\x00\x1a\x37\n\x19GetDataContractsRequestV0\x12\x0b\n\x03ids\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xcf\x04\n\x18GetDataContractsResponse\x12\\\n\x02v0\x18\x01 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetDataContractsResponse.GetDataContractsResponseV0H\x00\x1a[\n\x11\x44\x61taContractEntry\x12\x12\n\nidentifier\x18\x01 \x01(\x0c\x12\x32\n\rdata_contract\x18\x02 \x01(\x0b\x32\x1b.google.protobuf.BytesValue\x1au\n\rDataContracts\x12\x64\n\x15\x64\x61ta_contract_entries\x18\x01 \x03(\x0b\x32\x45.org.dash.platform.dapi.v0.GetDataContractsResponse.DataContractEntry\x1a\xf5\x01\n\x1aGetDataContractsResponseV0\x12[\n\x0e\x64\x61ta_contracts\x18\x01 \x01(\x0b\x32\x41.org.dash.platform.dapi.v0.GetDataContractsResponse.DataContractsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xc5\x02\n\x1dGetDataContractHistoryRequest\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.GetDataContractHistoryRequestV0H\x00\x1a\xb0\x01\n\x1fGetDataContractHistoryRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12+\n\x05limit\x18\x02 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12,\n\x06offset\x18\x03 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\x17\n\x0bstart_at_ms\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\t\n\x07version\"\xb2\x05\n\x1eGetDataContractHistoryResponse\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.GetDataContractHistoryResponseV0H\x00\x1a\x9a\x04\n GetDataContractHistoryResponseV0\x12\x8f\x01\n\x15\x64\x61ta_contract_history\x18\x01 \x01(\x0b\x32n.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.GetDataContractHistoryResponseV0.DataContractHistoryH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a;\n\x18\x44\x61taContractHistoryEntry\x12\x10\n\x04\x64\x61te\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\r\n\x05value\x18\x02 \x01(\x0c\x1a\xaa\x01\n\x13\x44\x61taContractHistory\x12\x92\x01\n\x15\x64\x61ta_contract_entries\x18\x01 \x03(\x0b\x32s.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.GetDataContractHistoryResponseV0.DataContractHistoryEntryB\x08\n\x06resultB\t\n\x07version\"\xb2\x02\n\x13GetDocumentsRequest\x12R\n\x02v0\x18\x01 \x01(\x0b\x32\x44.org.dash.platform.dapi.v0.GetDocumentsRequest.GetDocumentsRequestV0H\x00\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\x05startB\t\n\x07version\"\x95\x03\n\x14GetDocumentsResponse\x12T\n\x02v0\x18\x01 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV0H\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\x06resultB\t\n\x07version\"\xf0\x01\n\x18GetDocumentsCountRequest\x12\\\n\x02v0\x18\x01 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0H\x00\x1ak\n\x1aGetDocumentsCountRequestV0\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\r\n\x05prove\x18\x04 \x01(\x08\x42\t\n\x07version\"\xb3\x02\n\x19GetDocumentsCountResponse\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0H\x00\x1a\xaa\x01\n\x1bGetDocumentsCountResponseV0\x12\x0f\n\x05\x63ount\x18\x01 \x01(\x04H\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\"\xac\x02\n\x1dGetDocumentsSplitCountRequest\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0H\x00\x1a\x97\x01\n\x1fGetDocumentsSplitCountRequestV0\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%\n\x1dsplit_count_by_index_property\x18\x04 \x01(\t\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\t\n\x07version\"\xf2\x04\n\x1eGetDocumentsSplitCountResponse\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0H\x00\x1a\xda\x03\n GetDocumentsSplitCountResponseV0\x12~\n\x0csplit_counts\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountsH\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\x0fSplitCountEntry\x12\x0b\n\x03key\x18\x01 \x01(\x0c\x12\r\n\x05\x63ount\x18\x02 \x01(\x04\x1a\x8a\x01\n\x0bSplitCounts\x12{\n\x07\x65ntries\x18\x01 \x03(\x0b\x32j.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntryB\x08\n\x06resultB\t\n\x07version\"\xed\x01\n!GetIdentityByPublicKeyHashRequest\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashRequest.GetIdentityByPublicKeyHashRequestV0H\x00\x1aM\n#GetIdentityByPublicKeyHashRequestV0\x12\x17\n\x0fpublic_key_hash\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xda\x02\n\"GetIdentityByPublicKeyHashResponse\x12p\n\x02v0\x18\x01 \x01(\x0b\x32\x62.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashResponse.GetIdentityByPublicKeyHashResponseV0H\x00\x1a\xb6\x01\n$GetIdentityByPublicKeyHashResponseV0\x12\x12\n\x08identity\x18\x01 \x01(\x0cH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xbd\x02\n*GetIdentityByNonUniquePublicKeyHashRequest\x12\x80\x01\n\x02v0\x18\x01 \x01(\x0b\x32r.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashRequest.GetIdentityByNonUniquePublicKeyHashRequestV0H\x00\x1a\x80\x01\n,GetIdentityByNonUniquePublicKeyHashRequestV0\x12\x17\n\x0fpublic_key_hash\x18\x01 \x01(\x0c\x12\x18\n\x0bstart_after\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\x0e\n\x0c_start_afterB\t\n\x07version\"\xd6\x06\n+GetIdentityByNonUniquePublicKeyHashResponse\x12\x82\x01\n\x02v0\x18\x01 \x01(\x0b\x32t.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashResponse.GetIdentityByNonUniquePublicKeyHashResponseV0H\x00\x1a\x96\x05\n-GetIdentityByNonUniquePublicKeyHashResponseV0\x12\x9a\x01\n\x08identity\x18\x01 \x01(\x0b\x32\x85\x01.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashResponse.GetIdentityByNonUniquePublicKeyHashResponseV0.IdentityResponseH\x00\x12\x9d\x01\n\x05proof\x18\x02 \x01(\x0b\x32\x8b\x01.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashResponse.GetIdentityByNonUniquePublicKeyHashResponseV0.IdentityProvedResponseH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x36\n\x10IdentityResponse\x12\x15\n\x08identity\x18\x01 \x01(\x0cH\x00\x88\x01\x01\x42\x0b\n\t_identity\x1a\xa6\x01\n\x16IdentityProvedResponse\x12P\n&grovedb_identity_public_key_hash_proof\x18\x01 \x01(\x0b\x32 .org.dash.platform.dapi.v0.Proof\x12!\n\x14identity_proof_bytes\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x42\x17\n\x15_identity_proof_bytesB\x08\n\x06resultB\t\n\x07version\"\xfb\x01\n#WaitForStateTransitionResultRequest\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.WaitForStateTransitionResultRequest.WaitForStateTransitionResultRequestV0H\x00\x1aU\n%WaitForStateTransitionResultRequestV0\x12\x1d\n\x15state_transition_hash\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x99\x03\n$WaitForStateTransitionResultResponse\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.WaitForStateTransitionResultResponse.WaitForStateTransitionResultResponseV0H\x00\x1a\xef\x01\n&WaitForStateTransitionResultResponseV0\x12I\n\x05\x65rror\x18\x01 \x01(\x0b\x32\x38.org.dash.platform.dapi.v0.StateTransitionBroadcastErrorH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xc4\x01\n\x19GetConsensusParamsRequest\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetConsensusParamsRequest.GetConsensusParamsRequestV0H\x00\x1a<\n\x1bGetConsensusParamsRequestV0\x12\x0e\n\x06height\x18\x01 \x01(\x05\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x9c\x04\n\x1aGetConsensusParamsResponse\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetConsensusParamsResponse.GetConsensusParamsResponseV0H\x00\x1aP\n\x14\x43onsensusParamsBlock\x12\x11\n\tmax_bytes\x18\x01 \x01(\t\x12\x0f\n\x07max_gas\x18\x02 \x01(\t\x12\x14\n\x0ctime_iota_ms\x18\x03 \x01(\t\x1a\x62\n\x17\x43onsensusParamsEvidence\x12\x1a\n\x12max_age_num_blocks\x18\x01 \x01(\t\x12\x18\n\x10max_age_duration\x18\x02 \x01(\t\x12\x11\n\tmax_bytes\x18\x03 \x01(\t\x1a\xda\x01\n\x1cGetConsensusParamsResponseV0\x12Y\n\x05\x62lock\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetConsensusParamsResponse.ConsensusParamsBlock\x12_\n\x08\x65vidence\x18\x02 \x01(\x0b\x32M.org.dash.platform.dapi.v0.GetConsensusParamsResponse.ConsensusParamsEvidenceB\t\n\x07version\"\xe4\x01\n%GetProtocolVersionUpgradeStateRequest\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateRequest.GetProtocolVersionUpgradeStateRequestV0H\x00\x1a\x38\n\'GetProtocolVersionUpgradeStateRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x42\t\n\x07version\"\xb5\x05\n&GetProtocolVersionUpgradeStateResponse\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateResponse.GetProtocolVersionUpgradeStateResponseV0H\x00\x1a\x85\x04\n(GetProtocolVersionUpgradeStateResponseV0\x12\x87\x01\n\x08versions\x18\x01 \x01(\x0b\x32s.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateResponse.GetProtocolVersionUpgradeStateResponseV0.VersionsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x96\x01\n\x08Versions\x12\x89\x01\n\x08versions\x18\x01 \x03(\x0b\x32w.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateResponse.GetProtocolVersionUpgradeStateResponseV0.VersionEntry\x1a:\n\x0cVersionEntry\x12\x16\n\x0eversion_number\x18\x01 \x01(\r\x12\x12\n\nvote_count\x18\x02 \x01(\rB\x08\n\x06resultB\t\n\x07version\"\xa3\x02\n*GetProtocolVersionUpgradeVoteStatusRequest\x12\x80\x01\n\x02v0\x18\x01 \x01(\x0b\x32r.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusRequest.GetProtocolVersionUpgradeVoteStatusRequestV0H\x00\x1ag\n,GetProtocolVersionUpgradeVoteStatusRequestV0\x12\x19\n\x11start_pro_tx_hash\x18\x01 \x01(\x0c\x12\r\n\x05\x63ount\x18\x02 \x01(\r\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xef\x05\n+GetProtocolVersionUpgradeVoteStatusResponse\x12\x82\x01\n\x02v0\x18\x01 \x01(\x0b\x32t.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusResponse.GetProtocolVersionUpgradeVoteStatusResponseV0H\x00\x1a\xaf\x04\n-GetProtocolVersionUpgradeVoteStatusResponseV0\x12\x98\x01\n\x08versions\x18\x01 \x01(\x0b\x32\x83\x01.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusResponse.GetProtocolVersionUpgradeVoteStatusResponseV0.VersionSignalsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\xaf\x01\n\x0eVersionSignals\x12\x9c\x01\n\x0fversion_signals\x18\x01 \x03(\x0b\x32\x82\x01.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusResponse.GetProtocolVersionUpgradeVoteStatusResponseV0.VersionSignal\x1a\x35\n\rVersionSignal\x12\x13\n\x0bpro_tx_hash\x18\x01 \x01(\x0c\x12\x0f\n\x07version\x18\x02 \x01(\rB\x08\n\x06resultB\t\n\x07version\"\xf5\x01\n\x14GetEpochsInfoRequest\x12T\n\x02v0\x18\x01 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetEpochsInfoRequest.GetEpochsInfoRequestV0H\x00\x1a|\n\x16GetEpochsInfoRequestV0\x12\x31\n\x0bstart_epoch\x18\x01 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\r\n\x05\x63ount\x18\x02 \x01(\r\x12\x11\n\tascending\x18\x03 \x01(\x08\x12\r\n\x05prove\x18\x04 \x01(\x08\x42\t\n\x07version\"\x99\x05\n\x15GetEpochsInfoResponse\x12V\n\x02v0\x18\x01 \x01(\x0b\x32H.org.dash.platform.dapi.v0.GetEpochsInfoResponse.GetEpochsInfoResponseV0H\x00\x1a\x9c\x04\n\x17GetEpochsInfoResponseV0\x12\x65\n\x06\x65pochs\x18\x01 \x01(\x0b\x32S.org.dash.platform.dapi.v0.GetEpochsInfoResponse.GetEpochsInfoResponseV0.EpochInfosH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1au\n\nEpochInfos\x12g\n\x0b\x65poch_infos\x18\x01 \x03(\x0b\x32R.org.dash.platform.dapi.v0.GetEpochsInfoResponse.GetEpochsInfoResponseV0.EpochInfo\x1a\xa6\x01\n\tEpochInfo\x12\x0e\n\x06number\x18\x01 \x01(\r\x12\x1e\n\x12\x66irst_block_height\x18\x02 \x01(\x04\x42\x02\x30\x01\x12\x1f\n\x17\x66irst_core_block_height\x18\x03 \x01(\r\x12\x16\n\nstart_time\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\x16\n\x0e\x66\x65\x65_multiplier\x18\x05 \x01(\x01\x12\x18\n\x10protocol_version\x18\x06 \x01(\rB\x08\n\x06resultB\t\n\x07version\"\xbf\x02\n\x1dGetFinalizedEpochInfosRequest\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetFinalizedEpochInfosRequest.GetFinalizedEpochInfosRequestV0H\x00\x1a\xaa\x01\n\x1fGetFinalizedEpochInfosRequestV0\x12\x19\n\x11start_epoch_index\x18\x01 \x01(\r\x12\"\n\x1astart_epoch_index_included\x18\x02 \x01(\x08\x12\x17\n\x0f\x65nd_epoch_index\x18\x03 \x01(\r\x12 \n\x18\x65nd_epoch_index_included\x18\x04 \x01(\x08\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\t\n\x07version\"\xbd\t\n\x1eGetFinalizedEpochInfosResponse\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetFinalizedEpochInfosResponse.GetFinalizedEpochInfosResponseV0H\x00\x1a\xa5\x08\n GetFinalizedEpochInfosResponseV0\x12\x80\x01\n\x06\x65pochs\x18\x01 \x01(\x0b\x32n.org.dash.platform.dapi.v0.GetFinalizedEpochInfosResponse.GetFinalizedEpochInfosResponseV0.FinalizedEpochInfosH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\xa4\x01\n\x13\x46inalizedEpochInfos\x12\x8c\x01\n\x15\x66inalized_epoch_infos\x18\x01 \x03(\x0b\x32m.org.dash.platform.dapi.v0.GetFinalizedEpochInfosResponse.GetFinalizedEpochInfosResponseV0.FinalizedEpochInfo\x1a\x9f\x04\n\x12\x46inalizedEpochInfo\x12\x0e\n\x06number\x18\x01 \x01(\r\x12\x1e\n\x12\x66irst_block_height\x18\x02 \x01(\x04\x42\x02\x30\x01\x12\x1f\n\x17\x66irst_core_block_height\x18\x03 \x01(\r\x12\x1c\n\x10\x66irst_block_time\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\x16\n\x0e\x66\x65\x65_multiplier\x18\x05 \x01(\x01\x12\x18\n\x10protocol_version\x18\x06 \x01(\r\x12!\n\x15total_blocks_in_epoch\x18\x07 \x01(\x04\x42\x02\x30\x01\x12*\n\"next_epoch_start_core_block_height\x18\x08 \x01(\r\x12!\n\x15total_processing_fees\x18\t \x01(\x04\x42\x02\x30\x01\x12*\n\x1etotal_distributed_storage_fees\x18\n \x01(\x04\x42\x02\x30\x01\x12&\n\x1atotal_created_storage_fees\x18\x0b \x01(\x04\x42\x02\x30\x01\x12\x1e\n\x12\x63ore_block_rewards\x18\x0c \x01(\x04\x42\x02\x30\x01\x12\x81\x01\n\x0f\x62lock_proposers\x18\r \x03(\x0b\x32h.org.dash.platform.dapi.v0.GetFinalizedEpochInfosResponse.GetFinalizedEpochInfosResponseV0.BlockProposer\x1a\x39\n\rBlockProposer\x12\x13\n\x0bproposer_id\x18\x01 \x01(\x0c\x12\x13\n\x0b\x62lock_count\x18\x02 \x01(\rB\x08\n\x06resultB\t\n\x07version\"\xde\x04\n\x1cGetContestedResourcesRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetContestedResourcesRequest.GetContestedResourcesRequestV0H\x00\x1a\xcc\x03\n\x1eGetContestedResourcesRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\x12\n\nindex_name\x18\x03 \x01(\t\x12\x1a\n\x12start_index_values\x18\x04 \x03(\x0c\x12\x18\n\x10\x65nd_index_values\x18\x05 \x03(\x0c\x12\x89\x01\n\x13start_at_value_info\x18\x06 \x01(\x0b\x32g.org.dash.platform.dapi.v0.GetContestedResourcesRequest.GetContestedResourcesRequestV0.StartAtValueInfoH\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x07 \x01(\rH\x01\x88\x01\x01\x12\x17\n\x0forder_ascending\x18\x08 \x01(\x08\x12\r\n\x05prove\x18\t \x01(\x08\x1a\x45\n\x10StartAtValueInfo\x12\x13\n\x0bstart_value\x18\x01 \x01(\x0c\x12\x1c\n\x14start_value_included\x18\x02 \x01(\x08\x42\x16\n\x14_start_at_value_infoB\x08\n\x06_countB\t\n\x07version\"\x88\x04\n\x1dGetContestedResourcesResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetContestedResourcesResponse.GetContestedResourcesResponseV0H\x00\x1a\xf3\x02\n\x1fGetContestedResourcesResponseV0\x12\x95\x01\n\x19\x63ontested_resource_values\x18\x01 \x01(\x0b\x32p.org.dash.platform.dapi.v0.GetContestedResourcesResponse.GetContestedResourcesResponseV0.ContestedResourceValuesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a<\n\x17\x43ontestedResourceValues\x12!\n\x19\x63ontested_resource_values\x18\x01 \x03(\x0c\x42\x08\n\x06resultB\t\n\x07version\"\xd2\x05\n\x1cGetVotePollsByEndDateRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetVotePollsByEndDateRequest.GetVotePollsByEndDateRequestV0H\x00\x1a\xc0\x04\n\x1eGetVotePollsByEndDateRequestV0\x12\x84\x01\n\x0fstart_time_info\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetVotePollsByEndDateRequest.GetVotePollsByEndDateRequestV0.StartAtTimeInfoH\x00\x88\x01\x01\x12\x80\x01\n\rend_time_info\x18\x02 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetVotePollsByEndDateRequest.GetVotePollsByEndDateRequestV0.EndAtTimeInfoH\x01\x88\x01\x01\x12\x12\n\x05limit\x18\x03 \x01(\rH\x02\x88\x01\x01\x12\x13\n\x06offset\x18\x04 \x01(\rH\x03\x88\x01\x01\x12\x11\n\tascending\x18\x05 \x01(\x08\x12\r\n\x05prove\x18\x06 \x01(\x08\x1aI\n\x0fStartAtTimeInfo\x12\x19\n\rstart_time_ms\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x1b\n\x13start_time_included\x18\x02 \x01(\x08\x1a\x43\n\rEndAtTimeInfo\x12\x17\n\x0b\x65nd_time_ms\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x19\n\x11\x65nd_time_included\x18\x02 \x01(\x08\x42\x12\n\x10_start_time_infoB\x10\n\x0e_end_time_infoB\x08\n\x06_limitB\t\n\x07_offsetB\t\n\x07version\"\x83\x06\n\x1dGetVotePollsByEndDateResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetVotePollsByEndDateResponse.GetVotePollsByEndDateResponseV0H\x00\x1a\xee\x04\n\x1fGetVotePollsByEndDateResponseV0\x12\x9c\x01\n\x18vote_polls_by_timestamps\x18\x01 \x01(\x0b\x32x.org.dash.platform.dapi.v0.GetVotePollsByEndDateResponse.GetVotePollsByEndDateResponseV0.SerializedVotePollsByTimestampsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aV\n\x1eSerializedVotePollsByTimestamp\x12\x15\n\ttimestamp\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x1d\n\x15serialized_vote_polls\x18\x02 \x03(\x0c\x1a\xd7\x01\n\x1fSerializedVotePollsByTimestamps\x12\x99\x01\n\x18vote_polls_by_timestamps\x18\x01 \x03(\x0b\x32w.org.dash.platform.dapi.v0.GetVotePollsByEndDateResponse.GetVotePollsByEndDateResponseV0.SerializedVotePollsByTimestamp\x12\x18\n\x10\x66inished_results\x18\x02 \x01(\x08\x42\x08\n\x06resultB\t\n\x07version\"\xff\x06\n$GetContestedResourceVoteStateRequest\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetContestedResourceVoteStateRequest.GetContestedResourceVoteStateRequestV0H\x00\x1a\xd5\x05\n&GetContestedResourceVoteStateRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\x12\n\nindex_name\x18\x03 \x01(\t\x12\x14\n\x0cindex_values\x18\x04 \x03(\x0c\x12\x86\x01\n\x0bresult_type\x18\x05 \x01(\x0e\x32q.org.dash.platform.dapi.v0.GetContestedResourceVoteStateRequest.GetContestedResourceVoteStateRequestV0.ResultType\x12\x36\n.allow_include_locked_and_abstaining_vote_tally\x18\x06 \x01(\x08\x12\xa3\x01\n\x18start_at_identifier_info\x18\x07 \x01(\x0b\x32|.org.dash.platform.dapi.v0.GetContestedResourceVoteStateRequest.GetContestedResourceVoteStateRequestV0.StartAtIdentifierInfoH\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x08 \x01(\rH\x01\x88\x01\x01\x12\r\n\x05prove\x18\t \x01(\x08\x1aT\n\x15StartAtIdentifierInfo\x12\x18\n\x10start_identifier\x18\x01 \x01(\x0c\x12!\n\x19start_identifier_included\x18\x02 \x01(\x08\"I\n\nResultType\x12\r\n\tDOCUMENTS\x10\x00\x12\x0e\n\nVOTE_TALLY\x10\x01\x12\x1c\n\x18\x44OCUMENTS_AND_VOTE_TALLY\x10\x02\x42\x1b\n\x19_start_at_identifier_infoB\x08\n\x06_countB\t\n\x07version\"\x94\x0c\n%GetContestedResourceVoteStateResponse\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0H\x00\x1a\xe7\n\n\'GetContestedResourceVoteStateResponseV0\x12\xae\x01\n\x1d\x63ontested_resource_contenders\x18\x01 \x01(\x0b\x32\x84\x01.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0.ContestedResourceContendersH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\xda\x03\n\x10\x46inishedVoteInfo\x12\xad\x01\n\x15\x66inished_vote_outcome\x18\x01 \x01(\x0e\x32\x8d\x01.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0.FinishedVoteInfo.FinishedVoteOutcome\x12\x1f\n\x12won_by_identity_id\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x12$\n\x18\x66inished_at_block_height\x18\x03 \x01(\x04\x42\x02\x30\x01\x12%\n\x1d\x66inished_at_core_block_height\x18\x04 \x01(\r\x12%\n\x19\x66inished_at_block_time_ms\x18\x05 \x01(\x04\x42\x02\x30\x01\x12\x19\n\x11\x66inished_at_epoch\x18\x06 \x01(\r\"O\n\x13\x46inishedVoteOutcome\x12\x14\n\x10TOWARDS_IDENTITY\x10\x00\x12\n\n\x06LOCKED\x10\x01\x12\x16\n\x12NO_PREVIOUS_WINNER\x10\x02\x42\x15\n\x13_won_by_identity_id\x1a\xc4\x03\n\x1b\x43ontestedResourceContenders\x12\x86\x01\n\ncontenders\x18\x01 \x03(\x0b\x32r.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0.Contender\x12\x1f\n\x12\x61\x62stain_vote_tally\x18\x02 \x01(\rH\x00\x88\x01\x01\x12\x1c\n\x0flock_vote_tally\x18\x03 \x01(\rH\x01\x88\x01\x01\x12\x9a\x01\n\x12\x66inished_vote_info\x18\x04 \x01(\x0b\x32y.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0.FinishedVoteInfoH\x02\x88\x01\x01\x42\x15\n\x13_abstain_vote_tallyB\x12\n\x10_lock_vote_tallyB\x15\n\x13_finished_vote_info\x1ak\n\tContender\x12\x12\n\nidentifier\x18\x01 \x01(\x0c\x12\x17\n\nvote_count\x18\x02 \x01(\rH\x00\x88\x01\x01\x12\x15\n\x08\x64ocument\x18\x03 \x01(\x0cH\x01\x88\x01\x01\x42\r\n\x0b_vote_countB\x0b\n\t_documentB\x08\n\x06resultB\t\n\x07version\"\xd5\x05\n,GetContestedResourceVotersForIdentityRequest\x12\x84\x01\n\x02v0\x18\x01 \x01(\x0b\x32v.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityRequest.GetContestedResourceVotersForIdentityRequestV0H\x00\x1a\x92\x04\n.GetContestedResourceVotersForIdentityRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\x12\n\nindex_name\x18\x03 \x01(\t\x12\x14\n\x0cindex_values\x18\x04 \x03(\x0c\x12\x15\n\rcontestant_id\x18\x05 \x01(\x0c\x12\xb4\x01\n\x18start_at_identifier_info\x18\x06 \x01(\x0b\x32\x8c\x01.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityRequest.GetContestedResourceVotersForIdentityRequestV0.StartAtIdentifierInfoH\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x07 \x01(\rH\x01\x88\x01\x01\x12\x17\n\x0forder_ascending\x18\x08 \x01(\x08\x12\r\n\x05prove\x18\t \x01(\x08\x1aT\n\x15StartAtIdentifierInfo\x12\x18\n\x10start_identifier\x18\x01 \x01(\x0c\x12!\n\x19start_identifier_included\x18\x02 \x01(\x08\x42\x1b\n\x19_start_at_identifier_infoB\x08\n\x06_countB\t\n\x07version\"\xf1\x04\n-GetContestedResourceVotersForIdentityResponse\x12\x86\x01\n\x02v0\x18\x01 \x01(\x0b\x32x.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityResponse.GetContestedResourceVotersForIdentityResponseV0H\x00\x1a\xab\x03\n/GetContestedResourceVotersForIdentityResponseV0\x12\xb6\x01\n\x19\x63ontested_resource_voters\x18\x01 \x01(\x0b\x32\x90\x01.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityResponse.GetContestedResourceVotersForIdentityResponseV0.ContestedResourceVotersH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x43\n\x17\x43ontestedResourceVoters\x12\x0e\n\x06voters\x18\x01 \x03(\x0c\x12\x18\n\x10\x66inished_results\x18\x02 \x01(\x08\x42\x08\n\x06resultB\t\n\x07version\"\xad\x05\n(GetContestedResourceIdentityVotesRequest\x12|\n\x02v0\x18\x01 \x01(\x0b\x32n.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesRequest.GetContestedResourceIdentityVotesRequestV0H\x00\x1a\xf7\x03\n*GetContestedResourceIdentityVotesRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12+\n\x05limit\x18\x02 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12,\n\x06offset\x18\x03 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\x17\n\x0forder_ascending\x18\x04 \x01(\x08\x12\xae\x01\n\x1astart_at_vote_poll_id_info\x18\x05 \x01(\x0b\x32\x84\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesRequest.GetContestedResourceIdentityVotesRequestV0.StartAtVotePollIdInfoH\x00\x88\x01\x01\x12\r\n\x05prove\x18\x06 \x01(\x08\x1a\x61\n\x15StartAtVotePollIdInfo\x12 \n\x18start_at_poll_identifier\x18\x01 \x01(\x0c\x12&\n\x1estart_poll_identifier_included\x18\x02 \x01(\x08\x42\x1d\n\x1b_start_at_vote_poll_id_infoB\t\n\x07version\"\xc8\n\n)GetContestedResourceIdentityVotesResponse\x12~\n\x02v0\x18\x01 \x01(\x0b\x32p.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0H\x00\x1a\x8f\t\n+GetContestedResourceIdentityVotesResponseV0\x12\xa1\x01\n\x05votes\x18\x01 \x01(\x0b\x32\x8f\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0.ContestedResourceIdentityVotesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\xf7\x01\n\x1e\x43ontestedResourceIdentityVotes\x12\xba\x01\n!contested_resource_identity_votes\x18\x01 \x03(\x0b\x32\x8e\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0.ContestedResourceIdentityVote\x12\x18\n\x10\x66inished_results\x18\x02 \x01(\x08\x1a\xad\x02\n\x12ResourceVoteChoice\x12\xad\x01\n\x10vote_choice_type\x18\x01 \x01(\x0e\x32\x92\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0.ResourceVoteChoice.VoteChoiceType\x12\x18\n\x0bidentity_id\x18\x02 \x01(\x0cH\x00\x88\x01\x01\"=\n\x0eVoteChoiceType\x12\x14\n\x10TOWARDS_IDENTITY\x10\x00\x12\x0b\n\x07\x41\x42STAIN\x10\x01\x12\x08\n\x04LOCK\x10\x02\x42\x0e\n\x0c_identity_id\x1a\x95\x02\n\x1d\x43ontestedResourceIdentityVote\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\'\n\x1fserialized_index_storage_values\x18\x03 \x03(\x0c\x12\x99\x01\n\x0bvote_choice\x18\x04 \x01(\x0b\x32\x83\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0.ResourceVoteChoiceB\x08\n\x06resultB\t\n\x07version\"\xf0\x01\n%GetPrefundedSpecializedBalanceRequest\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetPrefundedSpecializedBalanceRequest.GetPrefundedSpecializedBalanceRequestV0H\x00\x1a\x44\n\'GetPrefundedSpecializedBalanceRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xed\x02\n&GetPrefundedSpecializedBalanceResponse\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetPrefundedSpecializedBalanceResponse.GetPrefundedSpecializedBalanceResponseV0H\x00\x1a\xbd\x01\n(GetPrefundedSpecializedBalanceResponseV0\x12\x15\n\x07\x62\x61lance\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xd0\x01\n GetTotalCreditsInPlatformRequest\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetTotalCreditsInPlatformRequest.GetTotalCreditsInPlatformRequestV0H\x00\x1a\x33\n\"GetTotalCreditsInPlatformRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x42\t\n\x07version\"\xd9\x02\n!GetTotalCreditsInPlatformResponse\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetTotalCreditsInPlatformResponse.GetTotalCreditsInPlatformResponseV0H\x00\x1a\xb8\x01\n#GetTotalCreditsInPlatformResponseV0\x12\x15\n\x07\x63redits\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xc4\x01\n\x16GetPathElementsRequest\x12X\n\x02v0\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetPathElementsRequest.GetPathElementsRequestV0H\x00\x1a\x45\n\x18GetPathElementsRequestV0\x12\x0c\n\x04path\x18\x01 \x03(\x0c\x12\x0c\n\x04keys\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xa3\x03\n\x17GetPathElementsResponse\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetPathElementsResponse.GetPathElementsResponseV0H\x00\x1a\xa0\x02\n\x19GetPathElementsResponseV0\x12i\n\x08\x65lements\x18\x01 \x01(\x0b\x32U.org.dash.platform.dapi.v0.GetPathElementsResponse.GetPathElementsResponseV0.ElementsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1c\n\x08\x45lements\x12\x10\n\x08\x65lements\x18\x01 \x03(\x0c\x42\x08\n\x06resultB\t\n\x07version\"\x81\x01\n\x10GetStatusRequest\x12L\n\x02v0\x18\x01 \x01(\x0b\x32>.org.dash.platform.dapi.v0.GetStatusRequest.GetStatusRequestV0H\x00\x1a\x14\n\x12GetStatusRequestV0B\t\n\x07version\"\xe4\x10\n\x11GetStatusResponse\x12N\n\x02v0\x18\x01 \x01(\x0b\x32@.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0H\x00\x1a\xf3\x0f\n\x13GetStatusResponseV0\x12Y\n\x07version\x18\x01 \x01(\x0b\x32H.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Version\x12S\n\x04node\x18\x02 \x01(\x0b\x32\x45.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Node\x12U\n\x05\x63hain\x18\x03 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Chain\x12Y\n\x07network\x18\x04 \x01(\x0b\x32H.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Network\x12^\n\nstate_sync\x18\x05 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.StateSync\x12S\n\x04time\x18\x06 \x01(\x0b\x32\x45.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Time\x1a\x82\x05\n\x07Version\x12\x63\n\x08software\x18\x01 \x01(\x0b\x32Q.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Version.Software\x12\x63\n\x08protocol\x18\x02 \x01(\x0b\x32Q.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Version.Protocol\x1a^\n\x08Software\x12\x0c\n\x04\x64\x61pi\x18\x01 \x01(\t\x12\x12\n\x05\x64rive\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x17\n\ntenderdash\x18\x03 \x01(\tH\x01\x88\x01\x01\x42\x08\n\x06_driveB\r\n\x0b_tenderdash\x1a\xcc\x02\n\x08Protocol\x12p\n\ntenderdash\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Version.Protocol.Tenderdash\x12\x66\n\x05\x64rive\x18\x02 \x01(\x0b\x32W.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Version.Protocol.Drive\x1a(\n\nTenderdash\x12\x0b\n\x03p2p\x18\x01 \x01(\r\x12\r\n\x05\x62lock\x18\x02 \x01(\r\x1a<\n\x05\x44rive\x12\x0e\n\x06latest\x18\x03 \x01(\r\x12\x0f\n\x07\x63urrent\x18\x04 \x01(\r\x12\x12\n\nnext_epoch\x18\x05 \x01(\r\x1a\x7f\n\x04Time\x12\x11\n\x05local\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x16\n\x05\x62lock\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x88\x01\x01\x12\x18\n\x07genesis\x18\x03 \x01(\x04\x42\x02\x30\x01H\x01\x88\x01\x01\x12\x12\n\x05\x65poch\x18\x04 \x01(\rH\x02\x88\x01\x01\x42\x08\n\x06_blockB\n\n\x08_genesisB\x08\n\x06_epoch\x1a<\n\x04Node\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\x18\n\x0bpro_tx_hash\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x42\x0e\n\x0c_pro_tx_hash\x1a\xb3\x02\n\x05\x43hain\x12\x13\n\x0b\x63\x61tching_up\x18\x01 \x01(\x08\x12\x19\n\x11latest_block_hash\x18\x02 \x01(\x0c\x12\x17\n\x0flatest_app_hash\x18\x03 \x01(\x0c\x12\x1f\n\x13latest_block_height\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\x1b\n\x13\x65\x61rliest_block_hash\x18\x05 \x01(\x0c\x12\x19\n\x11\x65\x61rliest_app_hash\x18\x06 \x01(\x0c\x12!\n\x15\x65\x61rliest_block_height\x18\x07 \x01(\x04\x42\x02\x30\x01\x12!\n\x15max_peer_block_height\x18\t \x01(\x04\x42\x02\x30\x01\x12%\n\x18\x63ore_chain_locked_height\x18\n \x01(\rH\x00\x88\x01\x01\x42\x1b\n\x19_core_chain_locked_height\x1a\x43\n\x07Network\x12\x10\n\x08\x63hain_id\x18\x01 \x01(\t\x12\x13\n\x0bpeers_count\x18\x02 \x01(\r\x12\x11\n\tlistening\x18\x03 \x01(\x08\x1a\x85\x02\n\tStateSync\x12\x1d\n\x11total_synced_time\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x1a\n\x0eremaining_time\x18\x02 \x01(\x04\x42\x02\x30\x01\x12\x17\n\x0ftotal_snapshots\x18\x03 \x01(\r\x12\"\n\x16\x63hunk_process_avg_time\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\x1b\n\x0fsnapshot_height\x18\x05 \x01(\x04\x42\x02\x30\x01\x12!\n\x15snapshot_chunks_count\x18\x06 \x01(\x04\x42\x02\x30\x01\x12\x1d\n\x11\x62\x61\x63kfilled_blocks\x18\x07 \x01(\x04\x42\x02\x30\x01\x12!\n\x15\x62\x61\x63kfill_blocks_total\x18\x08 \x01(\x04\x42\x02\x30\x01\x42\t\n\x07version\"\xb1\x01\n\x1cGetCurrentQuorumsInfoRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0H\x00\x1a \n\x1eGetCurrentQuorumsInfoRequestV0B\t\n\x07version\"\xa1\x05\n\x1dGetCurrentQuorumsInfoResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0H\x00\x1a\x46\n\x0bValidatorV0\x12\x13\n\x0bpro_tx_hash\x18\x01 \x01(\x0c\x12\x0f\n\x07node_ip\x18\x02 \x01(\t\x12\x11\n\tis_banned\x18\x03 \x01(\x08\x1a\xaf\x01\n\x0eValidatorSetV0\x12\x13\n\x0bquorum_hash\x18\x01 \x01(\x0c\x12\x13\n\x0b\x63ore_height\x18\x02 \x01(\r\x12U\n\x07members\x18\x03 \x03(\x0b\x32\x44.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0\x12\x1c\n\x14threshold_public_key\x18\x04 \x01(\x0c\x1a\x92\x02\n\x1fGetCurrentQuorumsInfoResponseV0\x12\x15\n\rquorum_hashes\x18\x01 \x03(\x0c\x12\x1b\n\x13\x63urrent_quorum_hash\x18\x02 \x01(\x0c\x12_\n\x0evalidator_sets\x18\x03 \x03(\x0b\x32G.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0\x12\x1b\n\x13last_block_proposer\x18\x04 \x01(\x0c\x12=\n\x08metadata\x18\x05 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\t\n\x07version\"\xf4\x01\n\x1fGetIdentityTokenBalancesRequest\x12j\n\x02v0\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetIdentityTokenBalancesRequest.GetIdentityTokenBalancesRequestV0H\x00\x1aZ\n!GetIdentityTokenBalancesRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x11\n\ttoken_ids\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xad\x05\n GetIdentityTokenBalancesResponse\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetIdentityTokenBalancesResponse.GetIdentityTokenBalancesResponseV0H\x00\x1a\x8f\x04\n\"GetIdentityTokenBalancesResponseV0\x12\x86\x01\n\x0etoken_balances\x18\x01 \x01(\x0b\x32l.org.dash.platform.dapi.v0.GetIdentityTokenBalancesResponse.GetIdentityTokenBalancesResponseV0.TokenBalancesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aG\n\x11TokenBalanceEntry\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x14\n\x07\x62\x61lance\x18\x02 \x01(\x04H\x00\x88\x01\x01\x42\n\n\x08_balance\x1a\x9a\x01\n\rTokenBalances\x12\x88\x01\n\x0etoken_balances\x18\x01 \x03(\x0b\x32p.org.dash.platform.dapi.v0.GetIdentityTokenBalancesResponse.GetIdentityTokenBalancesResponseV0.TokenBalanceEntryB\x08\n\x06resultB\t\n\x07version\"\xfc\x01\n!GetIdentitiesTokenBalancesRequest\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetIdentitiesTokenBalancesRequest.GetIdentitiesTokenBalancesRequestV0H\x00\x1a\\\n#GetIdentitiesTokenBalancesRequestV0\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x14\n\x0cidentity_ids\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xf2\x05\n\"GetIdentitiesTokenBalancesResponse\x12p\n\x02v0\x18\x01 \x01(\x0b\x32\x62.org.dash.platform.dapi.v0.GetIdentitiesTokenBalancesResponse.GetIdentitiesTokenBalancesResponseV0H\x00\x1a\xce\x04\n$GetIdentitiesTokenBalancesResponseV0\x12\x9b\x01\n\x17identity_token_balances\x18\x01 \x01(\x0b\x32x.org.dash.platform.dapi.v0.GetIdentitiesTokenBalancesResponse.GetIdentitiesTokenBalancesResponseV0.IdentityTokenBalancesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aR\n\x19IdentityTokenBalanceEntry\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x14\n\x07\x62\x61lance\x18\x02 \x01(\x04H\x00\x88\x01\x01\x42\n\n\x08_balance\x1a\xb7\x01\n\x15IdentityTokenBalances\x12\x9d\x01\n\x17identity_token_balances\x18\x01 \x03(\x0b\x32|.org.dash.platform.dapi.v0.GetIdentitiesTokenBalancesResponse.GetIdentitiesTokenBalancesResponseV0.IdentityTokenBalanceEntryB\x08\n\x06resultB\t\n\x07version\"\xe8\x01\n\x1cGetIdentityTokenInfosRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetIdentityTokenInfosRequest.GetIdentityTokenInfosRequestV0H\x00\x1aW\n\x1eGetIdentityTokenInfosRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x11\n\ttoken_ids\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\x98\x06\n\x1dGetIdentityTokenInfosResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetIdentityTokenInfosResponse.GetIdentityTokenInfosResponseV0H\x00\x1a\x83\x05\n\x1fGetIdentityTokenInfosResponseV0\x12z\n\x0btoken_infos\x18\x01 \x01(\x0b\x32\x63.org.dash.platform.dapi.v0.GetIdentityTokenInfosResponse.GetIdentityTokenInfosResponseV0.TokenInfosH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a(\n\x16TokenIdentityInfoEntry\x12\x0e\n\x06\x66rozen\x18\x01 \x01(\x08\x1a\xb0\x01\n\x0eTokenInfoEntry\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x82\x01\n\x04info\x18\x02 \x01(\x0b\x32o.org.dash.platform.dapi.v0.GetIdentityTokenInfosResponse.GetIdentityTokenInfosResponseV0.TokenIdentityInfoEntryH\x00\x88\x01\x01\x42\x07\n\x05_info\x1a\x8a\x01\n\nTokenInfos\x12|\n\x0btoken_infos\x18\x01 \x03(\x0b\x32g.org.dash.platform.dapi.v0.GetIdentityTokenInfosResponse.GetIdentityTokenInfosResponseV0.TokenInfoEntryB\x08\n\x06resultB\t\n\x07version\"\xf0\x01\n\x1eGetIdentitiesTokenInfosRequest\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosRequest.GetIdentitiesTokenInfosRequestV0H\x00\x1aY\n GetIdentitiesTokenInfosRequestV0\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x14\n\x0cidentity_ids\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xca\x06\n\x1fGetIdentitiesTokenInfosResponse\x12j\n\x02v0\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosResponse.GetIdentitiesTokenInfosResponseV0H\x00\x1a\xaf\x05\n!GetIdentitiesTokenInfosResponseV0\x12\x8f\x01\n\x14identity_token_infos\x18\x01 \x01(\x0b\x32o.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosResponse.GetIdentitiesTokenInfosResponseV0.IdentityTokenInfosH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a(\n\x16TokenIdentityInfoEntry\x12\x0e\n\x06\x66rozen\x18\x01 \x01(\x08\x1a\xb7\x01\n\x0eTokenInfoEntry\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x86\x01\n\x04info\x18\x02 \x01(\x0b\x32s.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosResponse.GetIdentitiesTokenInfosResponseV0.TokenIdentityInfoEntryH\x00\x88\x01\x01\x42\x07\n\x05_info\x1a\x97\x01\n\x12IdentityTokenInfos\x12\x80\x01\n\x0btoken_infos\x18\x01 \x03(\x0b\x32k.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosResponse.GetIdentitiesTokenInfosResponseV0.TokenInfoEntryB\x08\n\x06resultB\t\n\x07version\"\xbf\x01\n\x17GetTokenStatusesRequest\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetTokenStatusesRequest.GetTokenStatusesRequestV0H\x00\x1a=\n\x19GetTokenStatusesRequestV0\x12\x11\n\ttoken_ids\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xe7\x04\n\x18GetTokenStatusesResponse\x12\\\n\x02v0\x18\x01 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetTokenStatusesResponse.GetTokenStatusesResponseV0H\x00\x1a\xe1\x03\n\x1aGetTokenStatusesResponseV0\x12v\n\x0etoken_statuses\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetTokenStatusesResponse.GetTokenStatusesResponseV0.TokenStatusesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x44\n\x10TokenStatusEntry\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x13\n\x06paused\x18\x02 \x01(\x08H\x00\x88\x01\x01\x42\t\n\x07_paused\x1a\x88\x01\n\rTokenStatuses\x12w\n\x0etoken_statuses\x18\x01 \x03(\x0b\x32_.org.dash.platform.dapi.v0.GetTokenStatusesResponse.GetTokenStatusesResponseV0.TokenStatusEntryB\x08\n\x06resultB\t\n\x07version\"\xef\x01\n#GetTokenDirectPurchasePricesRequest\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesRequest.GetTokenDirectPurchasePricesRequestV0H\x00\x1aI\n%GetTokenDirectPurchasePricesRequestV0\x12\x11\n\ttoken_ids\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x8b\t\n$GetTokenDirectPurchasePricesResponse\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesResponse.GetTokenDirectPurchasePricesResponseV0H\x00\x1a\xe1\x07\n&GetTokenDirectPurchasePricesResponseV0\x12\xa9\x01\n\x1ctoken_direct_purchase_prices\x18\x01 \x01(\x0b\x32\x80\x01.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesResponse.GetTokenDirectPurchasePricesResponseV0.TokenDirectPurchasePricesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x33\n\x10PriceForQuantity\x12\x10\n\x08quantity\x18\x01 \x01(\x04\x12\r\n\x05price\x18\x02 \x01(\x04\x1a\xa7\x01\n\x0fPricingSchedule\x12\x93\x01\n\x12price_for_quantity\x18\x01 \x03(\x0b\x32w.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesResponse.GetTokenDirectPurchasePricesResponseV0.PriceForQuantity\x1a\xe4\x01\n\x1dTokenDirectPurchasePriceEntry\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x15\n\x0b\x66ixed_price\x18\x02 \x01(\x04H\x00\x12\x90\x01\n\x0evariable_price\x18\x03 \x01(\x0b\x32v.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesResponse.GetTokenDirectPurchasePricesResponseV0.PricingScheduleH\x00\x42\x07\n\x05price\x1a\xc8\x01\n\x19TokenDirectPurchasePrices\x12\xaa\x01\n\x1btoken_direct_purchase_price\x18\x01 \x03(\x0b\x32\x84\x01.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesResponse.GetTokenDirectPurchasePricesResponseV0.TokenDirectPurchasePriceEntryB\x08\n\x06resultB\t\n\x07version\"\xce\x01\n\x1bGetTokenContractInfoRequest\x12\x62\n\x02v0\x18\x01 \x01(\x0b\x32T.org.dash.platform.dapi.v0.GetTokenContractInfoRequest.GetTokenContractInfoRequestV0H\x00\x1a@\n\x1dGetTokenContractInfoRequestV0\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xfb\x03\n\x1cGetTokenContractInfoResponse\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetTokenContractInfoResponse.GetTokenContractInfoResponseV0H\x00\x1a\xe9\x02\n\x1eGetTokenContractInfoResponseV0\x12|\n\x04\x64\x61ta\x18\x01 \x01(\x0b\x32l.org.dash.platform.dapi.v0.GetTokenContractInfoResponse.GetTokenContractInfoResponseV0.TokenContractInfoDataH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aM\n\x15TokenContractInfoData\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1f\n\x17token_contract_position\x18\x02 \x01(\rB\x08\n\x06resultB\t\n\x07version\"\xef\x04\n)GetTokenPreProgrammedDistributionsRequest\x12~\n\x02v0\x18\x01 \x01(\x0b\x32p.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsRequest.GetTokenPreProgrammedDistributionsRequestV0H\x00\x1a\xb6\x03\n+GetTokenPreProgrammedDistributionsRequestV0\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x98\x01\n\rstart_at_info\x18\x02 \x01(\x0b\x32|.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsRequest.GetTokenPreProgrammedDistributionsRequestV0.StartAtInfoH\x00\x88\x01\x01\x12\x12\n\x05limit\x18\x03 \x01(\rH\x01\x88\x01\x01\x12\r\n\x05prove\x18\x04 \x01(\x08\x1a\x9a\x01\n\x0bStartAtInfo\x12\x15\n\rstart_time_ms\x18\x01 \x01(\x04\x12\x1c\n\x0fstart_recipient\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x12%\n\x18start_recipient_included\x18\x03 \x01(\x08H\x01\x88\x01\x01\x42\x12\n\x10_start_recipientB\x1b\n\x19_start_recipient_includedB\x10\n\x0e_start_at_infoB\x08\n\x06_limitB\t\n\x07version\"\xec\x07\n*GetTokenPreProgrammedDistributionsResponse\x12\x80\x01\n\x02v0\x18\x01 \x01(\x0b\x32r.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsResponse.GetTokenPreProgrammedDistributionsResponseV0H\x00\x1a\xaf\x06\n,GetTokenPreProgrammedDistributionsResponseV0\x12\xa5\x01\n\x13token_distributions\x18\x01 \x01(\x0b\x32\x85\x01.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsResponse.GetTokenPreProgrammedDistributionsResponseV0.TokenDistributionsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a>\n\x16TokenDistributionEntry\x12\x14\n\x0crecipient_id\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\x1a\xd4\x01\n\x1bTokenTimedDistributionEntry\x12\x11\n\ttimestamp\x18\x01 \x01(\x04\x12\xa1\x01\n\rdistributions\x18\x02 \x03(\x0b\x32\x89\x01.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsResponse.GetTokenPreProgrammedDistributionsResponseV0.TokenDistributionEntry\x1a\xc3\x01\n\x12TokenDistributions\x12\xac\x01\n\x13token_distributions\x18\x01 \x03(\x0b\x32\x8e\x01.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsResponse.GetTokenPreProgrammedDistributionsResponseV0.TokenTimedDistributionEntryB\x08\n\x06resultB\t\n\x07version\"\x82\x04\n-GetTokenPerpetualDistributionLastClaimRequest\x12\x86\x01\n\x02v0\x18\x01 \x01(\x0b\x32x.org.dash.platform.dapi.v0.GetTokenPerpetualDistributionLastClaimRequest.GetTokenPerpetualDistributionLastClaimRequestV0H\x00\x1aI\n\x11\x43ontractTokenInfo\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1f\n\x17token_contract_position\x18\x02 \x01(\r\x1a\xf1\x01\n/GetTokenPerpetualDistributionLastClaimRequestV0\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12v\n\rcontract_info\x18\x02 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetTokenPerpetualDistributionLastClaimRequest.ContractTokenInfoH\x00\x88\x01\x01\x12\x13\n\x0bidentity_id\x18\x04 \x01(\x0c\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\x10\n\x0e_contract_infoB\t\n\x07version\"\x93\x05\n.GetTokenPerpetualDistributionLastClaimResponse\x12\x88\x01\n\x02v0\x18\x01 \x01(\x0b\x32z.org.dash.platform.dapi.v0.GetTokenPerpetualDistributionLastClaimResponse.GetTokenPerpetualDistributionLastClaimResponseV0H\x00\x1a\xca\x03\n0GetTokenPerpetualDistributionLastClaimResponseV0\x12\x9f\x01\n\nlast_claim\x18\x01 \x01(\x0b\x32\x88\x01.org.dash.platform.dapi.v0.GetTokenPerpetualDistributionLastClaimResponse.GetTokenPerpetualDistributionLastClaimResponseV0.LastClaimInfoH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1ax\n\rLastClaimInfo\x12\x1a\n\x0ctimestamp_ms\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x1a\n\x0c\x62lock_height\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x12\x0f\n\x05\x65poch\x18\x03 \x01(\rH\x00\x12\x13\n\traw_bytes\x18\x04 \x01(\x0cH\x00\x42\t\n\x07paid_atB\x08\n\x06resultB\t\n\x07version\"\xca\x01\n\x1aGetTokenTotalSupplyRequest\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetTokenTotalSupplyRequest.GetTokenTotalSupplyRequestV0H\x00\x1a?\n\x1cGetTokenTotalSupplyRequestV0\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xaf\x04\n\x1bGetTokenTotalSupplyResponse\x12\x62\n\x02v0\x18\x01 \x01(\x0b\x32T.org.dash.platform.dapi.v0.GetTokenTotalSupplyResponse.GetTokenTotalSupplyResponseV0H\x00\x1a\xa0\x03\n\x1dGetTokenTotalSupplyResponseV0\x12\x88\x01\n\x12token_total_supply\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetTokenTotalSupplyResponse.GetTokenTotalSupplyResponseV0.TokenTotalSupplyEntryH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1ax\n\x15TokenTotalSupplyEntry\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x30\n(total_aggregated_amount_in_user_accounts\x18\x02 \x01(\x04\x12\x1b\n\x13total_system_amount\x18\x03 \x01(\x04\x42\x08\n\x06resultB\t\n\x07version\"\xd2\x01\n\x13GetGroupInfoRequest\x12R\n\x02v0\x18\x01 \x01(\x0b\x32\x44.org.dash.platform.dapi.v0.GetGroupInfoRequest.GetGroupInfoRequestV0H\x00\x1a\\\n\x15GetGroupInfoRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1f\n\x17group_contract_position\x18\x02 \x01(\r\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xd4\x05\n\x14GetGroupInfoResponse\x12T\n\x02v0\x18\x01 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetGroupInfoResponse.GetGroupInfoResponseV0H\x00\x1a\xda\x04\n\x16GetGroupInfoResponseV0\x12\x66\n\ngroup_info\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetGroupInfoResponse.GetGroupInfoResponseV0.GroupInfoH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x04 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x34\n\x10GroupMemberEntry\x12\x11\n\tmember_id\x18\x01 \x01(\x0c\x12\r\n\x05power\x18\x02 \x01(\r\x1a\x98\x01\n\x0eGroupInfoEntry\x12h\n\x07members\x18\x01 \x03(\x0b\x32W.org.dash.platform.dapi.v0.GetGroupInfoResponse.GetGroupInfoResponseV0.GroupMemberEntry\x12\x1c\n\x14group_required_power\x18\x02 \x01(\r\x1a\x8a\x01\n\tGroupInfo\x12n\n\ngroup_info\x18\x01 \x01(\x0b\x32U.org.dash.platform.dapi.v0.GetGroupInfoResponse.GetGroupInfoResponseV0.GroupInfoEntryH\x00\x88\x01\x01\x42\r\n\x0b_group_infoB\x08\n\x06resultB\t\n\x07version\"\xed\x03\n\x14GetGroupInfosRequest\x12T\n\x02v0\x18\x01 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetGroupInfosRequest.GetGroupInfosRequestV0H\x00\x1au\n\x1cStartAtGroupContractPosition\x12%\n\x1dstart_group_contract_position\x18\x01 \x01(\r\x12.\n&start_group_contract_position_included\x18\x02 \x01(\x08\x1a\xfc\x01\n\x16GetGroupInfosRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12{\n start_at_group_contract_position\x18\x02 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetGroupInfosRequest.StartAtGroupContractPositionH\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x03 \x01(\rH\x01\x88\x01\x01\x12\r\n\x05prove\x18\x04 \x01(\x08\x42#\n!_start_at_group_contract_positionB\x08\n\x06_countB\t\n\x07version\"\xff\x05\n\x15GetGroupInfosResponse\x12V\n\x02v0\x18\x01 \x01(\x0b\x32H.org.dash.platform.dapi.v0.GetGroupInfosResponse.GetGroupInfosResponseV0H\x00\x1a\x82\x05\n\x17GetGroupInfosResponseV0\x12j\n\x0bgroup_infos\x18\x01 \x01(\x0b\x32S.org.dash.platform.dapi.v0.GetGroupInfosResponse.GetGroupInfosResponseV0.GroupInfosH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x04 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x34\n\x10GroupMemberEntry\x12\x11\n\tmember_id\x18\x01 \x01(\x0c\x12\r\n\x05power\x18\x02 \x01(\r\x1a\xc3\x01\n\x16GroupPositionInfoEntry\x12\x1f\n\x17group_contract_position\x18\x01 \x01(\r\x12j\n\x07members\x18\x02 \x03(\x0b\x32Y.org.dash.platform.dapi.v0.GetGroupInfosResponse.GetGroupInfosResponseV0.GroupMemberEntry\x12\x1c\n\x14group_required_power\x18\x03 \x01(\r\x1a\x82\x01\n\nGroupInfos\x12t\n\x0bgroup_infos\x18\x01 \x03(\x0b\x32_.org.dash.platform.dapi.v0.GetGroupInfosResponse.GetGroupInfosResponseV0.GroupPositionInfoEntryB\x08\n\x06resultB\t\n\x07version\"\xbe\x04\n\x16GetGroupActionsRequest\x12X\n\x02v0\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetGroupActionsRequest.GetGroupActionsRequestV0H\x00\x1aL\n\x0fStartAtActionId\x12\x17\n\x0fstart_action_id\x18\x01 \x01(\x0c\x12 \n\x18start_action_id_included\x18\x02 \x01(\x08\x1a\xc8\x02\n\x18GetGroupActionsRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1f\n\x17group_contract_position\x18\x02 \x01(\r\x12N\n\x06status\x18\x03 \x01(\x0e\x32>.org.dash.platform.dapi.v0.GetGroupActionsRequest.ActionStatus\x12\x62\n\x12start_at_action_id\x18\x04 \x01(\x0b\x32\x41.org.dash.platform.dapi.v0.GetGroupActionsRequest.StartAtActionIdH\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x05 \x01(\rH\x01\x88\x01\x01\x12\r\n\x05prove\x18\x06 \x01(\x08\x42\x15\n\x13_start_at_action_idB\x08\n\x06_count\"&\n\x0c\x41\x63tionStatus\x12\n\n\x06\x41\x43TIVE\x10\x00\x12\n\n\x06\x43LOSED\x10\x01\x42\t\n\x07version\"\xd6\x1e\n\x17GetGroupActionsResponse\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0H\x00\x1a\xd3\x1d\n\x19GetGroupActionsResponseV0\x12r\n\rgroup_actions\x18\x01 \x01(\x0b\x32Y.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.GroupActionsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a[\n\tMintEvent\x12\x0e\n\x06\x61mount\x18\x01 \x01(\x04\x12\x14\n\x0crecipient_id\x18\x02 \x01(\x0c\x12\x18\n\x0bpublic_note\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_public_note\x1a[\n\tBurnEvent\x12\x0e\n\x06\x61mount\x18\x01 \x01(\x04\x12\x14\n\x0c\x62urn_from_id\x18\x02 \x01(\x0c\x12\x18\n\x0bpublic_note\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_public_note\x1aJ\n\x0b\x46reezeEvent\x12\x11\n\tfrozen_id\x18\x01 \x01(\x0c\x12\x18\n\x0bpublic_note\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_public_note\x1aL\n\rUnfreezeEvent\x12\x11\n\tfrozen_id\x18\x01 \x01(\x0c\x12\x18\n\x0bpublic_note\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_public_note\x1a\x66\n\x17\x44\x65stroyFrozenFundsEvent\x12\x11\n\tfrozen_id\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\x12\x18\n\x0bpublic_note\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_public_note\x1a\x64\n\x13SharedEncryptedNote\x12\x18\n\x10sender_key_index\x18\x01 \x01(\r\x12\x1b\n\x13recipient_key_index\x18\x02 \x01(\r\x12\x16\n\x0e\x65ncrypted_data\x18\x03 \x01(\x0c\x1a{\n\x15PersonalEncryptedNote\x12!\n\x19root_encryption_key_index\x18\x01 \x01(\r\x12\'\n\x1f\x64\x65rivation_encryption_key_index\x18\x02 \x01(\r\x12\x16\n\x0e\x65ncrypted_data\x18\x03 \x01(\x0c\x1a\xe9\x01\n\x14\x45mergencyActionEvent\x12\x81\x01\n\x0b\x61\x63tion_type\x18\x01 \x01(\x0e\x32l.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.EmergencyActionEvent.ActionType\x12\x18\n\x0bpublic_note\x18\x02 \x01(\tH\x00\x88\x01\x01\"#\n\nActionType\x12\t\n\x05PAUSE\x10\x00\x12\n\n\x06RESUME\x10\x01\x42\x0e\n\x0c_public_note\x1a\x64\n\x16TokenConfigUpdateEvent\x12 \n\x18token_config_update_item\x18\x01 \x01(\x0c\x12\x18\n\x0bpublic_note\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_public_note\x1a\xe6\x03\n\x1eUpdateDirectPurchasePriceEvent\x12\x15\n\x0b\x66ixed_price\x18\x01 \x01(\x04H\x00\x12\x95\x01\n\x0evariable_price\x18\x02 \x01(\x0b\x32{.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.UpdateDirectPurchasePriceEvent.PricingScheduleH\x00\x12\x18\n\x0bpublic_note\x18\x03 \x01(\tH\x01\x88\x01\x01\x1a\x33\n\x10PriceForQuantity\x12\x10\n\x08quantity\x18\x01 \x01(\x04\x12\r\n\x05price\x18\x02 \x01(\x04\x1a\xac\x01\n\x0fPricingSchedule\x12\x98\x01\n\x12price_for_quantity\x18\x01 \x03(\x0b\x32|.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.UpdateDirectPurchasePriceEvent.PriceForQuantityB\x07\n\x05priceB\x0e\n\x0c_public_note\x1a\xfc\x02\n\x10GroupActionEvent\x12n\n\x0btoken_event\x18\x01 \x01(\x0b\x32W.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.TokenEventH\x00\x12t\n\x0e\x64ocument_event\x18\x02 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.DocumentEventH\x00\x12t\n\x0e\x63ontract_event\x18\x03 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.ContractEventH\x00\x42\x0c\n\nevent_type\x1a\x8b\x01\n\rDocumentEvent\x12r\n\x06\x63reate\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.DocumentCreateEventH\x00\x42\x06\n\x04type\x1a/\n\x13\x44ocumentCreateEvent\x12\x18\n\x10\x63reated_document\x18\x01 \x01(\x0c\x1a/\n\x13\x43ontractUpdateEvent\x12\x18\n\x10updated_contract\x18\x01 \x01(\x0c\x1a\x8b\x01\n\rContractEvent\x12r\n\x06update\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.ContractUpdateEventH\x00\x42\x06\n\x04type\x1a\xd1\x07\n\nTokenEvent\x12\x66\n\x04mint\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.MintEventH\x00\x12\x66\n\x04\x62urn\x18\x02 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.BurnEventH\x00\x12j\n\x06\x66reeze\x18\x03 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.FreezeEventH\x00\x12n\n\x08unfreeze\x18\x04 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.UnfreezeEventH\x00\x12\x84\x01\n\x14\x64\x65stroy_frozen_funds\x18\x05 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.DestroyFrozenFundsEventH\x00\x12}\n\x10\x65mergency_action\x18\x06 \x01(\x0b\x32\x61.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.EmergencyActionEventH\x00\x12\x82\x01\n\x13token_config_update\x18\x07 \x01(\x0b\x32\x63.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.TokenConfigUpdateEventH\x00\x12\x83\x01\n\x0cupdate_price\x18\x08 \x01(\x0b\x32k.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.UpdateDirectPurchasePriceEventH\x00\x42\x06\n\x04type\x1a\x93\x01\n\x10GroupActionEntry\x12\x11\n\taction_id\x18\x01 \x01(\x0c\x12l\n\x05\x65vent\x18\x02 \x01(\x0b\x32].org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.GroupActionEvent\x1a\x84\x01\n\x0cGroupActions\x12t\n\rgroup_actions\x18\x01 \x03(\x0b\x32].org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.GroupActionEntryB\x08\n\x06resultB\t\n\x07version\"\x88\x03\n\x1cGetGroupActionSignersRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetGroupActionSignersRequest.GetGroupActionSignersRequestV0H\x00\x1a\xce\x01\n\x1eGetGroupActionSignersRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1f\n\x17group_contract_position\x18\x02 \x01(\r\x12T\n\x06status\x18\x03 \x01(\x0e\x32\x44.org.dash.platform.dapi.v0.GetGroupActionSignersRequest.ActionStatus\x12\x11\n\taction_id\x18\x04 \x01(\x0c\x12\r\n\x05prove\x18\x05 \x01(\x08\"&\n\x0c\x41\x63tionStatus\x12\n\n\x06\x41\x43TIVE\x10\x00\x12\n\n\x06\x43LOSED\x10\x01\x42\t\n\x07version\"\x8b\x05\n\x1dGetGroupActionSignersResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetGroupActionSignersResponse.GetGroupActionSignersResponseV0H\x00\x1a\xf6\x03\n\x1fGetGroupActionSignersResponseV0\x12\x8b\x01\n\x14group_action_signers\x18\x01 \x01(\x0b\x32k.org.dash.platform.dapi.v0.GetGroupActionSignersResponse.GetGroupActionSignersResponseV0.GroupActionSignersH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x35\n\x11GroupActionSigner\x12\x11\n\tsigner_id\x18\x01 \x01(\x0c\x12\r\n\x05power\x18\x02 \x01(\r\x1a\x91\x01\n\x12GroupActionSigners\x12{\n\x07signers\x18\x01 \x03(\x0b\x32j.org.dash.platform.dapi.v0.GetGroupActionSignersResponse.GetGroupActionSignersResponseV0.GroupActionSignerB\x08\n\x06resultB\t\n\x07version\"\xb5\x01\n\x15GetAddressInfoRequest\x12V\n\x02v0\x18\x01 \x01(\x0b\x32H.org.dash.platform.dapi.v0.GetAddressInfoRequest.GetAddressInfoRequestV0H\x00\x1a\x39\n\x17GetAddressInfoRequestV0\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x85\x01\n\x10\x41\x64\x64ressInfoEntry\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12J\n\x11\x62\x61lance_and_nonce\x18\x02 \x01(\x0b\x32*.org.dash.platform.dapi.v0.BalanceAndNonceH\x00\x88\x01\x01\x42\x14\n\x12_balance_and_nonce\"1\n\x0f\x42\x61lanceAndNonce\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\x12\r\n\x05nonce\x18\x02 \x01(\r\"_\n\x12\x41\x64\x64ressInfoEntries\x12I\n\x14\x61\x64\x64ress_info_entries\x18\x01 \x03(\x0b\x32+.org.dash.platform.dapi.v0.AddressInfoEntry\"m\n\x14\x41\x64\x64ressBalanceChange\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x19\n\x0bset_balance\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x12\x1c\n\x0e\x61\x64\x64_to_balance\x18\x03 \x01(\x04\x42\x02\x30\x01H\x00\x42\x0b\n\toperation\"x\n\x1a\x42lockAddressBalanceChanges\x12\x18\n\x0c\x62lock_height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12@\n\x07\x63hanges\x18\x02 \x03(\x0b\x32/.org.dash.platform.dapi.v0.AddressBalanceChange\"k\n\x1b\x41\x64\x64ressBalanceUpdateEntries\x12L\n\rblock_changes\x18\x01 \x03(\x0b\x32\x35.org.dash.platform.dapi.v0.BlockAddressBalanceChanges\"\xe1\x02\n\x16GetAddressInfoResponse\x12X\n\x02v0\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetAddressInfoResponse.GetAddressInfoResponseV0H\x00\x1a\xe1\x01\n\x18GetAddressInfoResponseV0\x12I\n\x12\x61\x64\x64ress_info_entry\x18\x01 \x01(\x0b\x32+.org.dash.platform.dapi.v0.AddressInfoEntryH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xc3\x01\n\x18GetAddressesInfosRequest\x12\\\n\x02v0\x18\x01 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetAddressesInfosRequest.GetAddressesInfosRequestV0H\x00\x1a>\n\x1aGetAddressesInfosRequestV0\x12\x11\n\taddresses\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xf1\x02\n\x19GetAddressesInfosResponse\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetAddressesInfosResponse.GetAddressesInfosResponseV0H\x00\x1a\xe8\x01\n\x1bGetAddressesInfosResponseV0\x12M\n\x14\x61\x64\x64ress_info_entries\x18\x01 \x01(\x0b\x32-.org.dash.platform.dapi.v0.AddressInfoEntriesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xb5\x01\n\x1dGetAddressesTrunkStateRequest\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetAddressesTrunkStateRequest.GetAddressesTrunkStateRequestV0H\x00\x1a!\n\x1fGetAddressesTrunkStateRequestV0B\t\n\x07version\"\xaa\x02\n\x1eGetAddressesTrunkStateResponse\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetAddressesTrunkStateResponse.GetAddressesTrunkStateResponseV0H\x00\x1a\x92\x01\n GetAddressesTrunkStateResponseV0\x12/\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.Proof\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\t\n\x07version\"\xf0\x01\n\x1eGetAddressesBranchStateRequest\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetAddressesBranchStateRequest.GetAddressesBranchStateRequestV0H\x00\x1aY\n GetAddressesBranchStateRequestV0\x12\x0b\n\x03key\x18\x01 \x01(\x0c\x12\r\n\x05\x64\x65pth\x18\x02 \x01(\r\x12\x19\n\x11\x63heckpoint_height\x18\x03 \x01(\x04\x42\t\n\x07version\"\xd1\x01\n\x1fGetAddressesBranchStateResponse\x12j\n\x02v0\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetAddressesBranchStateResponse.GetAddressesBranchStateResponseV0H\x00\x1a\x37\n!GetAddressesBranchStateResponseV0\x12\x12\n\nmerk_proof\x18\x02 \x01(\x0c\x42\t\n\x07version\"\x9e\x02\n%GetRecentAddressBalanceChangesRequest\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetRecentAddressBalanceChangesRequest.GetRecentAddressBalanceChangesRequestV0H\x00\x1ar\n\'GetRecentAddressBalanceChangesRequestV0\x12\x18\n\x0cstart_height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\r\n\x05prove\x18\x02 \x01(\x08\x12\x1e\n\x16start_height_exclusive\x18\x03 \x01(\x08\x42\t\n\x07version\"\xb8\x03\n&GetRecentAddressBalanceChangesResponse\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetRecentAddressBalanceChangesResponse.GetRecentAddressBalanceChangesResponseV0H\x00\x1a\x88\x02\n(GetRecentAddressBalanceChangesResponseV0\x12`\n\x1e\x61\x64\x64ress_balance_update_entries\x18\x01 \x01(\x0b\x32\x36.org.dash.platform.dapi.v0.AddressBalanceUpdateEntriesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"G\n\x16\x42lockHeightCreditEntry\x12\x18\n\x0c\x62lock_height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x13\n\x07\x63redits\x18\x02 \x01(\x04\x42\x02\x30\x01\"\xb0\x01\n\x1d\x43ompactedAddressBalanceChange\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x19\n\x0bset_credits\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x12V\n\x19\x61\x64\x64_to_credits_operations\x18\x03 \x01(\x0b\x32\x31.org.dash.platform.dapi.v0.AddToCreditsOperationsH\x00\x42\x0b\n\toperation\"\\\n\x16\x41\x64\x64ToCreditsOperations\x12\x42\n\x07\x65ntries\x18\x01 \x03(\x0b\x32\x31.org.dash.platform.dapi.v0.BlockHeightCreditEntry\"\xae\x01\n#CompactedBlockAddressBalanceChanges\x12\x1e\n\x12start_block_height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x1c\n\x10\x65nd_block_height\x18\x02 \x01(\x04\x42\x02\x30\x01\x12I\n\x07\x63hanges\x18\x03 \x03(\x0b\x32\x38.org.dash.platform.dapi.v0.CompactedAddressBalanceChange\"\x87\x01\n$CompactedAddressBalanceUpdateEntries\x12_\n\x17\x63ompacted_block_changes\x18\x01 \x03(\x0b\x32>.org.dash.platform.dapi.v0.CompactedBlockAddressBalanceChanges\"\xa9\x02\n.GetRecentCompactedAddressBalanceChangesRequest\x12\x88\x01\n\x02v0\x18\x01 \x01(\x0b\x32z.org.dash.platform.dapi.v0.GetRecentCompactedAddressBalanceChangesRequest.GetRecentCompactedAddressBalanceChangesRequestV0H\x00\x1a\x61\n0GetRecentCompactedAddressBalanceChangesRequestV0\x12\x1e\n\x12start_block_height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xf0\x03\n/GetRecentCompactedAddressBalanceChangesResponse\x12\x8a\x01\n\x02v0\x18\x01 \x01(\x0b\x32|.org.dash.platform.dapi.v0.GetRecentCompactedAddressBalanceChangesResponse.GetRecentCompactedAddressBalanceChangesResponseV0H\x00\x1a\xa4\x02\n1GetRecentCompactedAddressBalanceChangesResponseV0\x12s\n(compacted_address_balance_update_entries\x18\x01 \x01(\x0b\x32?.org.dash.platform.dapi.v0.CompactedAddressBalanceUpdateEntriesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xf4\x01\n GetShieldedEncryptedNotesRequest\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetShieldedEncryptedNotesRequest.GetShieldedEncryptedNotesRequestV0H\x00\x1aW\n\"GetShieldedEncryptedNotesRequestV0\x12\x13\n\x0bstart_index\x18\x01 \x01(\x04\x12\r\n\x05\x63ount\x18\x02 \x01(\r\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xac\x05\n!GetShieldedEncryptedNotesResponse\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetShieldedEncryptedNotesResponse.GetShieldedEncryptedNotesResponseV0H\x00\x1a\x8b\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\x1aG\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\x1a\x91\x01\n\x0e\x45ncryptedNotes\x12\x7f\n\x07\x65ntries\x18\x01 \x03(\x0b\x32n.org.dash.platform.dapi.v0.GetShieldedEncryptedNotesResponse.GetShieldedEncryptedNotesResponseV0.EncryptedNoteB\x08\n\x06resultB\t\n\x07version\"\xb4\x01\n\x19GetShieldedAnchorsRequest\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetShieldedAnchorsRequest.GetShieldedAnchorsRequestV0H\x00\x1a,\n\x1bGetShieldedAnchorsRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x42\t\n\x07version\"\xb1\x03\n\x1aGetShieldedAnchorsResponse\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetShieldedAnchorsResponse.GetShieldedAnchorsResponseV0H\x00\x1a\xa5\x02\n\x1cGetShieldedAnchorsResponseV0\x12m\n\x07\x61nchors\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetShieldedAnchorsResponse.GetShieldedAnchorsResponseV0.AnchorsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1a\n\x07\x41nchors\x12\x0f\n\x07\x61nchors\x18\x01 \x03(\x0c\x42\x08\n\x06resultB\t\n\x07version\"\xd8\x01\n\"GetMostRecentShieldedAnchorRequest\x12p\n\x02v0\x18\x01 \x01(\x0b\x32\x62.org.dash.platform.dapi.v0.GetMostRecentShieldedAnchorRequest.GetMostRecentShieldedAnchorRequestV0H\x00\x1a\x35\n$GetMostRecentShieldedAnchorRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x42\t\n\x07version\"\xdc\x02\n#GetMostRecentShieldedAnchorResponse\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetMostRecentShieldedAnchorResponse.GetMostRecentShieldedAnchorResponseV0H\x00\x1a\xb5\x01\n%GetMostRecentShieldedAnchorResponseV0\x12\x10\n\x06\x61nchor\x18\x01 \x01(\x0cH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xbc\x01\n\x1bGetShieldedPoolStateRequest\x12\x62\n\x02v0\x18\x01 \x01(\x0b\x32T.org.dash.platform.dapi.v0.GetShieldedPoolStateRequest.GetShieldedPoolStateRequestV0H\x00\x1a.\n\x1dGetShieldedPoolStateRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x42\t\n\x07version\"\xcb\x02\n\x1cGetShieldedPoolStateResponse\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetShieldedPoolStateResponse.GetShieldedPoolStateResponseV0H\x00\x1a\xb9\x01\n\x1eGetShieldedPoolStateResponseV0\x12\x1b\n\rtotal_balance\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xd4\x01\n\x1cGetShieldedNullifiersRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetShieldedNullifiersRequest.GetShieldedNullifiersRequestV0H\x00\x1a\x43\n\x1eGetShieldedNullifiersRequestV0\x12\x12\n\nnullifiers\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x86\x05\n\x1dGetShieldedNullifiersResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetShieldedNullifiersResponse.GetShieldedNullifiersResponseV0H\x00\x1a\xf1\x03\n\x1fGetShieldedNullifiersResponseV0\x12\x88\x01\n\x12nullifier_statuses\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetShieldedNullifiersResponse.GetShieldedNullifiersResponseV0.NullifierStatusesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x36\n\x0fNullifierStatus\x12\x11\n\tnullifier\x18\x01 \x01(\x0c\x12\x10\n\x08is_spent\x18\x02 \x01(\x08\x1a\x8e\x01\n\x11NullifierStatuses\x12y\n\x07\x65ntries\x18\x01 \x03(\x0b\x32h.org.dash.platform.dapi.v0.GetShieldedNullifiersResponse.GetShieldedNullifiersResponseV0.NullifierStatusB\x08\n\x06resultB\t\n\x07version\"\xe5\x01\n\x1eGetNullifiersTrunkStateRequest\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetNullifiersTrunkStateRequest.GetNullifiersTrunkStateRequestV0H\x00\x1aN\n GetNullifiersTrunkStateRequestV0\x12\x11\n\tpool_type\x18\x01 \x01(\r\x12\x17\n\x0fpool_identifier\x18\x02 \x01(\x0c\x42\t\n\x07version\"\xae\x02\n\x1fGetNullifiersTrunkStateResponse\x12j\n\x02v0\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetNullifiersTrunkStateResponse.GetNullifiersTrunkStateResponseV0H\x00\x1a\x93\x01\n!GetNullifiersTrunkStateResponseV0\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\"\xa1\x02\n\x1fGetNullifiersBranchStateRequest\x12j\n\x02v0\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetNullifiersBranchStateRequest.GetNullifiersBranchStateRequestV0H\x00\x1a\x86\x01\n!GetNullifiersBranchStateRequestV0\x12\x11\n\tpool_type\x18\x01 \x01(\r\x12\x17\n\x0fpool_identifier\x18\x02 \x01(\x0c\x12\x0b\n\x03key\x18\x03 \x01(\x0c\x12\r\n\x05\x64\x65pth\x18\x04 \x01(\r\x12\x19\n\x11\x63heckpoint_height\x18\x05 \x01(\x04\x42\t\n\x07version\"\xd5\x01\n GetNullifiersBranchStateResponse\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetNullifiersBranchStateResponse.GetNullifiersBranchStateResponseV0H\x00\x1a\x38\n\"GetNullifiersBranchStateResponseV0\x12\x12\n\nmerk_proof\x18\x02 \x01(\x0c\x42\t\n\x07version\"E\n\x15\x42lockNullifierChanges\x12\x18\n\x0c\x62lock_height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x12\n\nnullifiers\x18\x02 \x03(\x0c\"a\n\x16NullifierUpdateEntries\x12G\n\rblock_changes\x18\x01 \x03(\x0b\x32\x30.org.dash.platform.dapi.v0.BlockNullifierChanges\"\xea\x01\n GetRecentNullifierChangesRequest\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetRecentNullifierChangesRequest.GetRecentNullifierChangesRequestV0H\x00\x1aM\n\"GetRecentNullifierChangesRequestV0\x12\x18\n\x0cstart_height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x99\x03\n!GetRecentNullifierChangesResponse\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetRecentNullifierChangesResponse.GetRecentNullifierChangesResponseV0H\x00\x1a\xf8\x01\n#GetRecentNullifierChangesResponseV0\x12U\n\x18nullifier_update_entries\x18\x01 \x01(\x0b\x32\x31.org.dash.platform.dapi.v0.NullifierUpdateEntriesH\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\x1e\x43ompactedBlockNullifierChanges\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\x12\x12\n\nnullifiers\x18\x03 \x03(\x0c\"}\n\x1f\x43ompactedNullifierUpdateEntries\x12Z\n\x17\x63ompacted_block_changes\x18\x01 \x03(\x0b\x32\x39.org.dash.platform.dapi.v0.CompactedBlockNullifierChanges\"\x94\x02\n)GetRecentCompactedNullifierChangesRequest\x12~\n\x02v0\x18\x01 \x01(\x0b\x32p.org.dash.platform.dapi.v0.GetRecentCompactedNullifierChangesRequest.GetRecentCompactedNullifierChangesRequestV0H\x00\x1a\\\n+GetRecentCompactedNullifierChangesRequestV0\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\"\xd1\x03\n*GetRecentCompactedNullifierChangesResponse\x12\x80\x01\n\x02v0\x18\x01 \x01(\x0b\x32r.org.dash.platform.dapi.v0.GetRecentCompactedNullifierChangesResponse.GetRecentCompactedNullifierChangesResponseV0H\x00\x1a\x94\x02\n,GetRecentCompactedNullifierChangesResponseV0\x12h\n\"compacted_nullifier_update_entries\x18\x01 \x01(\x0b\x32:.org.dash.platform.dapi.v0.CompactedNullifierUpdateEntriesH\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*Z\n\nKeyPurpose\x12\x12\n\x0e\x41UTHENTICATION\x10\x00\x12\x0e\n\nENCRYPTION\x10\x01\x12\x0e\n\nDECRYPTION\x10\x02\x12\x0c\n\x08TRANSFER\x10\x03\x12\n\n\x06VOTING\x10\x05\x32\xc3I\n\x08Platform\x12\x93\x01\n\x18\x62roadcastStateTransition\x12:.org.dash.platform.dapi.v0.BroadcastStateTransitionRequest\x1a;.org.dash.platform.dapi.v0.BroadcastStateTransitionResponse\x12l\n\x0bgetIdentity\x12-.org.dash.platform.dapi.v0.GetIdentityRequest\x1a..org.dash.platform.dapi.v0.GetIdentityResponse\x12x\n\x0fgetIdentityKeys\x12\x31.org.dash.platform.dapi.v0.GetIdentityKeysRequest\x1a\x32.org.dash.platform.dapi.v0.GetIdentityKeysResponse\x12\x96\x01\n\x19getIdentitiesContractKeys\x12;.org.dash.platform.dapi.v0.GetIdentitiesContractKeysRequest\x1a<.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse\x12{\n\x10getIdentityNonce\x12\x32.org.dash.platform.dapi.v0.GetIdentityNonceRequest\x1a\x33.org.dash.platform.dapi.v0.GetIdentityNonceResponse\x12\x93\x01\n\x18getIdentityContractNonce\x12:.org.dash.platform.dapi.v0.GetIdentityContractNonceRequest\x1a;.org.dash.platform.dapi.v0.GetIdentityContractNonceResponse\x12\x81\x01\n\x12getIdentityBalance\x12\x34.org.dash.platform.dapi.v0.GetIdentityBalanceRequest\x1a\x35.org.dash.platform.dapi.v0.GetIdentityBalanceResponse\x12\x8a\x01\n\x15getIdentitiesBalances\x12\x37.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest\x1a\x38.org.dash.platform.dapi.v0.GetIdentitiesBalancesResponse\x12\xa2\x01\n\x1dgetIdentityBalanceAndRevision\x12?.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionRequest\x1a@.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionResponse\x12\xaf\x01\n#getEvonodesProposedEpochBlocksByIds\x12\x45.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByIdsRequest\x1a\x41.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksResponse\x12\xb3\x01\n%getEvonodesProposedEpochBlocksByRange\x12G.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByRangeRequest\x1a\x41.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksResponse\x12x\n\x0fgetDataContract\x12\x31.org.dash.platform.dapi.v0.GetDataContractRequest\x1a\x32.org.dash.platform.dapi.v0.GetDataContractResponse\x12\x8d\x01\n\x16getDataContractHistory\x12\x38.org.dash.platform.dapi.v0.GetDataContractHistoryRequest\x1a\x39.org.dash.platform.dapi.v0.GetDataContractHistoryResponse\x12{\n\x10getDataContracts\x12\x32.org.dash.platform.dapi.v0.GetDataContractsRequest\x1a\x33.org.dash.platform.dapi.v0.GetDataContractsResponse\x12o\n\x0cgetDocuments\x12..org.dash.platform.dapi.v0.GetDocumentsRequest\x1a/.org.dash.platform.dapi.v0.GetDocumentsResponse\x12~\n\x11getDocumentsCount\x12\x33.org.dash.platform.dapi.v0.GetDocumentsCountRequest\x1a\x34.org.dash.platform.dapi.v0.GetDocumentsCountResponse\x12\x8d\x01\n\x16getDocumentsSplitCount\x12\x38.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest\x1a\x39.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse\x12\x99\x01\n\x1agetIdentityByPublicKeyHash\x12<.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashRequest\x1a=.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashResponse\x12\xb4\x01\n#getIdentityByNonUniquePublicKeyHash\x12\x45.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashRequest\x1a\x46.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashResponse\x12\x9f\x01\n\x1cwaitForStateTransitionResult\x12>.org.dash.platform.dapi.v0.WaitForStateTransitionResultRequest\x1a?.org.dash.platform.dapi.v0.WaitForStateTransitionResultResponse\x12\x81\x01\n\x12getConsensusParams\x12\x34.org.dash.platform.dapi.v0.GetConsensusParamsRequest\x1a\x35.org.dash.platform.dapi.v0.GetConsensusParamsResponse\x12\xa5\x01\n\x1egetProtocolVersionUpgradeState\x12@.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateRequest\x1a\x41.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateResponse\x12\xb4\x01\n#getProtocolVersionUpgradeVoteStatus\x12\x45.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusRequest\x1a\x46.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusResponse\x12r\n\rgetEpochsInfo\x12/.org.dash.platform.dapi.v0.GetEpochsInfoRequest\x1a\x30.org.dash.platform.dapi.v0.GetEpochsInfoResponse\x12\x8d\x01\n\x16getFinalizedEpochInfos\x12\x38.org.dash.platform.dapi.v0.GetFinalizedEpochInfosRequest\x1a\x39.org.dash.platform.dapi.v0.GetFinalizedEpochInfosResponse\x12\x8a\x01\n\x15getContestedResources\x12\x37.org.dash.platform.dapi.v0.GetContestedResourcesRequest\x1a\x38.org.dash.platform.dapi.v0.GetContestedResourcesResponse\x12\xa2\x01\n\x1dgetContestedResourceVoteState\x12?.org.dash.platform.dapi.v0.GetContestedResourceVoteStateRequest\x1a@.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse\x12\xba\x01\n%getContestedResourceVotersForIdentity\x12G.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityRequest\x1aH.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityResponse\x12\xae\x01\n!getContestedResourceIdentityVotes\x12\x43.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesRequest\x1a\x44.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse\x12\x8a\x01\n\x15getVotePollsByEndDate\x12\x37.org.dash.platform.dapi.v0.GetVotePollsByEndDateRequest\x1a\x38.org.dash.platform.dapi.v0.GetVotePollsByEndDateResponse\x12\xa5\x01\n\x1egetPrefundedSpecializedBalance\x12@.org.dash.platform.dapi.v0.GetPrefundedSpecializedBalanceRequest\x1a\x41.org.dash.platform.dapi.v0.GetPrefundedSpecializedBalanceResponse\x12\x96\x01\n\x19getTotalCreditsInPlatform\x12;.org.dash.platform.dapi.v0.GetTotalCreditsInPlatformRequest\x1a<.org.dash.platform.dapi.v0.GetTotalCreditsInPlatformResponse\x12x\n\x0fgetPathElements\x12\x31.org.dash.platform.dapi.v0.GetPathElementsRequest\x1a\x32.org.dash.platform.dapi.v0.GetPathElementsResponse\x12\x66\n\tgetStatus\x12+.org.dash.platform.dapi.v0.GetStatusRequest\x1a,.org.dash.platform.dapi.v0.GetStatusResponse\x12\x8a\x01\n\x15getCurrentQuorumsInfo\x12\x37.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest\x1a\x38.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse\x12\x93\x01\n\x18getIdentityTokenBalances\x12:.org.dash.platform.dapi.v0.GetIdentityTokenBalancesRequest\x1a;.org.dash.platform.dapi.v0.GetIdentityTokenBalancesResponse\x12\x99\x01\n\x1agetIdentitiesTokenBalances\x12<.org.dash.platform.dapi.v0.GetIdentitiesTokenBalancesRequest\x1a=.org.dash.platform.dapi.v0.GetIdentitiesTokenBalancesResponse\x12\x8a\x01\n\x15getIdentityTokenInfos\x12\x37.org.dash.platform.dapi.v0.GetIdentityTokenInfosRequest\x1a\x38.org.dash.platform.dapi.v0.GetIdentityTokenInfosResponse\x12\x90\x01\n\x17getIdentitiesTokenInfos\x12\x39.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosRequest\x1a:.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosResponse\x12{\n\x10getTokenStatuses\x12\x32.org.dash.platform.dapi.v0.GetTokenStatusesRequest\x1a\x33.org.dash.platform.dapi.v0.GetTokenStatusesResponse\x12\x9f\x01\n\x1cgetTokenDirectPurchasePrices\x12>.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesRequest\x1a?.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesResponse\x12\x87\x01\n\x14getTokenContractInfo\x12\x36.org.dash.platform.dapi.v0.GetTokenContractInfoRequest\x1a\x37.org.dash.platform.dapi.v0.GetTokenContractInfoResponse\x12\xb1\x01\n\"getTokenPreProgrammedDistributions\x12\x44.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsRequest\x1a\x45.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsResponse\x12\xbd\x01\n&getTokenPerpetualDistributionLastClaim\x12H.org.dash.platform.dapi.v0.GetTokenPerpetualDistributionLastClaimRequest\x1aI.org.dash.platform.dapi.v0.GetTokenPerpetualDistributionLastClaimResponse\x12\x84\x01\n\x13getTokenTotalSupply\x12\x35.org.dash.platform.dapi.v0.GetTokenTotalSupplyRequest\x1a\x36.org.dash.platform.dapi.v0.GetTokenTotalSupplyResponse\x12o\n\x0cgetGroupInfo\x12..org.dash.platform.dapi.v0.GetGroupInfoRequest\x1a/.org.dash.platform.dapi.v0.GetGroupInfoResponse\x12r\n\rgetGroupInfos\x12/.org.dash.platform.dapi.v0.GetGroupInfosRequest\x1a\x30.org.dash.platform.dapi.v0.GetGroupInfosResponse\x12x\n\x0fgetGroupActions\x12\x31.org.dash.platform.dapi.v0.GetGroupActionsRequest\x1a\x32.org.dash.platform.dapi.v0.GetGroupActionsResponse\x12\x8a\x01\n\x15getGroupActionSigners\x12\x37.org.dash.platform.dapi.v0.GetGroupActionSignersRequest\x1a\x38.org.dash.platform.dapi.v0.GetGroupActionSignersResponse\x12u\n\x0egetAddressInfo\x12\x30.org.dash.platform.dapi.v0.GetAddressInfoRequest\x1a\x31.org.dash.platform.dapi.v0.GetAddressInfoResponse\x12~\n\x11getAddressesInfos\x12\x33.org.dash.platform.dapi.v0.GetAddressesInfosRequest\x1a\x34.org.dash.platform.dapi.v0.GetAddressesInfosResponse\x12\x8d\x01\n\x16getAddressesTrunkState\x12\x38.org.dash.platform.dapi.v0.GetAddressesTrunkStateRequest\x1a\x39.org.dash.platform.dapi.v0.GetAddressesTrunkStateResponse\x12\x90\x01\n\x17getAddressesBranchState\x12\x39.org.dash.platform.dapi.v0.GetAddressesBranchStateRequest\x1a:.org.dash.platform.dapi.v0.GetAddressesBranchStateResponse\x12\xa5\x01\n\x1egetRecentAddressBalanceChanges\x12@.org.dash.platform.dapi.v0.GetRecentAddressBalanceChangesRequest\x1a\x41.org.dash.platform.dapi.v0.GetRecentAddressBalanceChangesResponse\x12\xc0\x01\n\'getRecentCompactedAddressBalanceChanges\x12I.org.dash.platform.dapi.v0.GetRecentCompactedAddressBalanceChangesRequest\x1aJ.org.dash.platform.dapi.v0.GetRecentCompactedAddressBalanceChangesResponse\x12\x96\x01\n\x19getShieldedEncryptedNotes\x12;.org.dash.platform.dapi.v0.GetShieldedEncryptedNotesRequest\x1a<.org.dash.platform.dapi.v0.GetShieldedEncryptedNotesResponse\x12\x81\x01\n\x12getShieldedAnchors\x12\x34.org.dash.platform.dapi.v0.GetShieldedAnchorsRequest\x1a\x35.org.dash.platform.dapi.v0.GetShieldedAnchorsResponse\x12\x9c\x01\n\x1bgetMostRecentShieldedAnchor\x12=.org.dash.platform.dapi.v0.GetMostRecentShieldedAnchorRequest\x1a>.org.dash.platform.dapi.v0.GetMostRecentShieldedAnchorResponse\x12\x87\x01\n\x14getShieldedPoolState\x12\x36.org.dash.platform.dapi.v0.GetShieldedPoolStateRequest\x1a\x37.org.dash.platform.dapi.v0.GetShieldedPoolStateResponse\x12\x8a\x01\n\x15getShieldedNullifiers\x12\x37.org.dash.platform.dapi.v0.GetShieldedNullifiersRequest\x1a\x38.org.dash.platform.dapi.v0.GetShieldedNullifiersResponse\x12\x90\x01\n\x17getNullifiersTrunkState\x12\x39.org.dash.platform.dapi.v0.GetNullifiersTrunkStateRequest\x1a:.org.dash.platform.dapi.v0.GetNullifiersTrunkStateResponse\x12\x93\x01\n\x18getNullifiersBranchState\x12:.org.dash.platform.dapi.v0.GetNullifiersBranchStateRequest\x1a;.org.dash.platform.dapi.v0.GetNullifiersBranchStateResponse\x12\x96\x01\n\x19getRecentNullifierChanges\x12;.org.dash.platform.dapi.v0.GetRecentNullifierChangesRequest\x1a<.org.dash.platform.dapi.v0.GetRecentNullifierChangesResponse\x12\xb1\x01\n\"getRecentCompactedNullifierChanges\x12\x44.org.dash.platform.dapi.v0.GetRecentCompactedNullifierChangesRequest\x1a\x45.org.dash.platform.dapi.v0.GetRecentCompactedNullifierChangesResponseb\x06proto3' + serialized_pb=b'\n\x0eplatform.proto\x12\x19org.dash.platform.dapi.v0\x1a\x1egoogle/protobuf/wrappers.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\x81\x01\n\x05Proof\x12\x15\n\rgrovedb_proof\x18\x01 \x01(\x0c\x12\x13\n\x0bquorum_hash\x18\x02 \x01(\x0c\x12\x11\n\tsignature\x18\x03 \x01(\x0c\x12\r\n\x05round\x18\x04 \x01(\r\x12\x15\n\rblock_id_hash\x18\x05 \x01(\x0c\x12\x13\n\x0bquorum_type\x18\x06 \x01(\r\"\x98\x01\n\x10ResponseMetadata\x12\x12\n\x06height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12 \n\x18\x63ore_chain_locked_height\x18\x02 \x01(\r\x12\r\n\x05\x65poch\x18\x03 \x01(\r\x12\x13\n\x07time_ms\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\x18\n\x10protocol_version\x18\x05 \x01(\r\x12\x10\n\x08\x63hain_id\x18\x06 \x01(\t\"L\n\x1dStateTransitionBroadcastError\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x03 \x01(\x0c\";\n\x1f\x42roadcastStateTransitionRequest\x12\x18\n\x10state_transition\x18\x01 \x01(\x0c\"\"\n BroadcastStateTransitionResponse\"\xa4\x01\n\x12GetIdentityRequest\x12P\n\x02v0\x18\x01 \x01(\x0b\x32\x42.org.dash.platform.dapi.v0.GetIdentityRequest.GetIdentityRequestV0H\x00\x1a\x31\n\x14GetIdentityRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xc1\x01\n\x17GetIdentityNonceRequest\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetIdentityNonceRequest.GetIdentityNonceRequestV0H\x00\x1a?\n\x19GetIdentityNonceRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xf6\x01\n\x1fGetIdentityContractNonceRequest\x12j\n\x02v0\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetIdentityContractNonceRequest.GetIdentityContractNonceRequestV0H\x00\x1a\\\n!GetIdentityContractNonceRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x13\n\x0b\x63ontract_id\x18\x02 \x01(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xc0\x01\n\x19GetIdentityBalanceRequest\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetIdentityBalanceRequest.GetIdentityBalanceRequestV0H\x00\x1a\x38\n\x1bGetIdentityBalanceRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xec\x01\n$GetIdentityBalanceAndRevisionRequest\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionRequest.GetIdentityBalanceAndRevisionRequestV0H\x00\x1a\x43\n&GetIdentityBalanceAndRevisionRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x9e\x02\n\x13GetIdentityResponse\x12R\n\x02v0\x18\x01 \x01(\x0b\x32\x44.org.dash.platform.dapi.v0.GetIdentityResponse.GetIdentityResponseV0H\x00\x1a\xa7\x01\n\x15GetIdentityResponseV0\x12\x12\n\x08identity\x18\x01 \x01(\x0cH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xbc\x02\n\x18GetIdentityNonceResponse\x12\\\n\x02v0\x18\x01 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetIdentityNonceResponse.GetIdentityNonceResponseV0H\x00\x1a\xb6\x01\n\x1aGetIdentityNonceResponseV0\x12\x1c\n\x0eidentity_nonce\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xe5\x02\n GetIdentityContractNonceResponse\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetIdentityContractNonceResponse.GetIdentityContractNonceResponseV0H\x00\x1a\xc7\x01\n\"GetIdentityContractNonceResponseV0\x12%\n\x17identity_contract_nonce\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xbd\x02\n\x1aGetIdentityBalanceResponse\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetIdentityBalanceResponse.GetIdentityBalanceResponseV0H\x00\x1a\xb1\x01\n\x1cGetIdentityBalanceResponseV0\x12\x15\n\x07\x62\x61lance\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xb1\x04\n%GetIdentityBalanceAndRevisionResponse\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionResponse.GetIdentityBalanceAndRevisionResponseV0H\x00\x1a\x84\x03\n\'GetIdentityBalanceAndRevisionResponseV0\x12\x9b\x01\n\x14\x62\x61lance_and_revision\x18\x01 \x01(\x0b\x32{.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionResponse.GetIdentityBalanceAndRevisionResponseV0.BalanceAndRevisionH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a?\n\x12\x42\x61lanceAndRevision\x12\x13\n\x07\x62\x61lance\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x14\n\x08revision\x18\x02 \x01(\x04\x42\x02\x30\x01\x42\x08\n\x06resultB\t\n\x07version\"\xd1\x01\n\x0eKeyRequestType\x12\x36\n\x08\x61ll_keys\x18\x01 \x01(\x0b\x32\".org.dash.platform.dapi.v0.AllKeysH\x00\x12@\n\rspecific_keys\x18\x02 \x01(\x0b\x32\'.org.dash.platform.dapi.v0.SpecificKeysH\x00\x12:\n\nsearch_key\x18\x03 \x01(\x0b\x32$.org.dash.platform.dapi.v0.SearchKeyH\x00\x42\t\n\x07request\"\t\n\x07\x41llKeys\"\x1f\n\x0cSpecificKeys\x12\x0f\n\x07key_ids\x18\x01 \x03(\r\"\xb6\x01\n\tSearchKey\x12I\n\x0bpurpose_map\x18\x01 \x03(\x0b\x32\x34.org.dash.platform.dapi.v0.SearchKey.PurposeMapEntry\x1a^\n\x0fPurposeMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12:\n\x05value\x18\x02 \x01(\x0b\x32+.org.dash.platform.dapi.v0.SecurityLevelMap:\x02\x38\x01\"\xbf\x02\n\x10SecurityLevelMap\x12]\n\x12security_level_map\x18\x01 \x03(\x0b\x32\x41.org.dash.platform.dapi.v0.SecurityLevelMap.SecurityLevelMapEntry\x1aw\n\x15SecurityLevelMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12M\n\x05value\x18\x02 \x01(\x0e\x32>.org.dash.platform.dapi.v0.SecurityLevelMap.KeyKindRequestType:\x02\x38\x01\"S\n\x12KeyKindRequestType\x12\x1f\n\x1b\x43URRENT_KEY_OF_KIND_REQUEST\x10\x00\x12\x1c\n\x18\x41LL_KEYS_OF_KIND_REQUEST\x10\x01\"\xda\x02\n\x16GetIdentityKeysRequest\x12X\n\x02v0\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetIdentityKeysRequest.GetIdentityKeysRequestV0H\x00\x1a\xda\x01\n\x18GetIdentityKeysRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12?\n\x0crequest_type\x18\x02 \x01(\x0b\x32).org.dash.platform.dapi.v0.KeyRequestType\x12+\n\x05limit\x18\x03 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12,\n\x06offset\x18\x04 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\t\n\x07version\"\x99\x03\n\x17GetIdentityKeysResponse\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetIdentityKeysResponse.GetIdentityKeysResponseV0H\x00\x1a\x96\x02\n\x19GetIdentityKeysResponseV0\x12\x61\n\x04keys\x18\x01 \x01(\x0b\x32Q.org.dash.platform.dapi.v0.GetIdentityKeysResponse.GetIdentityKeysResponseV0.KeysH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1a\n\x04Keys\x12\x12\n\nkeys_bytes\x18\x01 \x03(\x0c\x42\x08\n\x06resultB\t\n\x07version\"\xef\x02\n GetIdentitiesContractKeysRequest\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetIdentitiesContractKeysRequest.GetIdentitiesContractKeysRequestV0H\x00\x1a\xd1\x01\n\"GetIdentitiesContractKeysRequestV0\x12\x16\n\x0eidentities_ids\x18\x01 \x03(\x0c\x12\x13\n\x0b\x63ontract_id\x18\x02 \x01(\x0c\x12\x1f\n\x12\x64ocument_type_name\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x37\n\x08purposes\x18\x04 \x03(\x0e\x32%.org.dash.platform.dapi.v0.KeyPurpose\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\x15\n\x13_document_type_nameB\t\n\x07version\"\xdf\x06\n!GetIdentitiesContractKeysResponse\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse.GetIdentitiesContractKeysResponseV0H\x00\x1a\xbe\x05\n#GetIdentitiesContractKeysResponseV0\x12\x8a\x01\n\x0fidentities_keys\x18\x01 \x01(\x0b\x32o.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse.GetIdentitiesContractKeysResponseV0.IdentitiesKeysH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aY\n\x0bPurposeKeys\x12\x36\n\x07purpose\x18\x01 \x01(\x0e\x32%.org.dash.platform.dapi.v0.KeyPurpose\x12\x12\n\nkeys_bytes\x18\x02 \x03(\x0c\x1a\x9f\x01\n\x0cIdentityKeys\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12z\n\x04keys\x18\x02 \x03(\x0b\x32l.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse.GetIdentitiesContractKeysResponseV0.PurposeKeys\x1a\x90\x01\n\x0eIdentitiesKeys\x12~\n\x07\x65ntries\x18\x01 \x03(\x0b\x32m.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse.GetIdentitiesContractKeysResponseV0.IdentityKeysB\x08\n\x06resultB\t\n\x07version\"\xa4\x02\n*GetEvonodesProposedEpochBlocksByIdsRequest\x12\x80\x01\n\x02v0\x18\x01 \x01(\x0b\x32r.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByIdsRequest.GetEvonodesProposedEpochBlocksByIdsRequestV0H\x00\x1ah\n,GetEvonodesProposedEpochBlocksByIdsRequestV0\x12\x12\n\x05\x65poch\x18\x01 \x01(\rH\x00\x88\x01\x01\x12\x0b\n\x03ids\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\x08\n\x06_epochB\t\n\x07version\"\x92\x06\n&GetEvonodesProposedEpochBlocksResponse\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksResponse.GetEvonodesProposedEpochBlocksResponseV0H\x00\x1a\xe2\x04\n(GetEvonodesProposedEpochBlocksResponseV0\x12\xb1\x01\n#evonodes_proposed_block_counts_info\x18\x01 \x01(\x0b\x32\x81\x01.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksResponse.GetEvonodesProposedEpochBlocksResponseV0.EvonodesProposedBlocksH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a?\n\x15\x45vonodeProposedBlocks\x12\x13\n\x0bpro_tx_hash\x18\x01 \x01(\x0c\x12\x11\n\x05\x63ount\x18\x02 \x01(\x04\x42\x02\x30\x01\x1a\xc4\x01\n\x16\x45vonodesProposedBlocks\x12\xa9\x01\n\x1e\x65vonodes_proposed_block_counts\x18\x01 \x03(\x0b\x32\x80\x01.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksResponse.GetEvonodesProposedEpochBlocksResponseV0.EvonodeProposedBlocksB\x08\n\x06resultB\t\n\x07version\"\xf2\x02\n,GetEvonodesProposedEpochBlocksByRangeRequest\x12\x84\x01\n\x02v0\x18\x01 \x01(\x0b\x32v.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByRangeRequest.GetEvonodesProposedEpochBlocksByRangeRequestV0H\x00\x1a\xaf\x01\n.GetEvonodesProposedEpochBlocksByRangeRequestV0\x12\x12\n\x05\x65poch\x18\x01 \x01(\rH\x01\x88\x01\x01\x12\x12\n\x05limit\x18\x02 \x01(\rH\x02\x88\x01\x01\x12\x15\n\x0bstart_after\x18\x03 \x01(\x0cH\x00\x12\x12\n\x08start_at\x18\x04 \x01(\x0cH\x00\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\x07\n\x05startB\x08\n\x06_epochB\x08\n\x06_limitB\t\n\x07version\"\xcd\x01\n\x1cGetIdentitiesBalancesRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0H\x00\x1a<\n\x1eGetIdentitiesBalancesRequestV0\x12\x0b\n\x03ids\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x9f\x05\n\x1dGetIdentitiesBalancesResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetIdentitiesBalancesResponse.GetIdentitiesBalancesResponseV0H\x00\x1a\x8a\x04\n\x1fGetIdentitiesBalancesResponseV0\x12\x8a\x01\n\x13identities_balances\x18\x01 \x01(\x0b\x32k.org.dash.platform.dapi.v0.GetIdentitiesBalancesResponse.GetIdentitiesBalancesResponseV0.IdentitiesBalancesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aL\n\x0fIdentityBalance\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x18\n\x07\x62\x61lance\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x88\x01\x01\x42\n\n\x08_balance\x1a\x8f\x01\n\x12IdentitiesBalances\x12y\n\x07\x65ntries\x18\x01 \x03(\x0b\x32h.org.dash.platform.dapi.v0.GetIdentitiesBalancesResponse.GetIdentitiesBalancesResponseV0.IdentityBalanceB\x08\n\x06resultB\t\n\x07version\"\xb4\x01\n\x16GetDataContractRequest\x12X\n\x02v0\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetDataContractRequest.GetDataContractRequestV0H\x00\x1a\x35\n\x18GetDataContractRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xb3\x02\n\x17GetDataContractResponse\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetDataContractResponse.GetDataContractResponseV0H\x00\x1a\xb0\x01\n\x19GetDataContractResponseV0\x12\x17\n\rdata_contract\x18\x01 \x01(\x0cH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xb9\x01\n\x17GetDataContractsRequest\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetDataContractsRequest.GetDataContractsRequestV0H\x00\x1a\x37\n\x19GetDataContractsRequestV0\x12\x0b\n\x03ids\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xcf\x04\n\x18GetDataContractsResponse\x12\\\n\x02v0\x18\x01 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetDataContractsResponse.GetDataContractsResponseV0H\x00\x1a[\n\x11\x44\x61taContractEntry\x12\x12\n\nidentifier\x18\x01 \x01(\x0c\x12\x32\n\rdata_contract\x18\x02 \x01(\x0b\x32\x1b.google.protobuf.BytesValue\x1au\n\rDataContracts\x12\x64\n\x15\x64\x61ta_contract_entries\x18\x01 \x03(\x0b\x32\x45.org.dash.platform.dapi.v0.GetDataContractsResponse.DataContractEntry\x1a\xf5\x01\n\x1aGetDataContractsResponseV0\x12[\n\x0e\x64\x61ta_contracts\x18\x01 \x01(\x0b\x32\x41.org.dash.platform.dapi.v0.GetDataContractsResponse.DataContractsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xc5\x02\n\x1dGetDataContractHistoryRequest\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.GetDataContractHistoryRequestV0H\x00\x1a\xb0\x01\n\x1fGetDataContractHistoryRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12+\n\x05limit\x18\x02 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12,\n\x06offset\x18\x03 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\x17\n\x0bstart_at_ms\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\t\n\x07version\"\xb2\x05\n\x1eGetDataContractHistoryResponse\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.GetDataContractHistoryResponseV0H\x00\x1a\x9a\x04\n GetDataContractHistoryResponseV0\x12\x8f\x01\n\x15\x64\x61ta_contract_history\x18\x01 \x01(\x0b\x32n.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.GetDataContractHistoryResponseV0.DataContractHistoryH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a;\n\x18\x44\x61taContractHistoryEntry\x12\x10\n\x04\x64\x61te\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\r\n\x05value\x18\x02 \x01(\x0c\x1a\xaa\x01\n\x13\x44\x61taContractHistory\x12\x92\x01\n\x15\x64\x61ta_contract_entries\x18\x01 \x03(\x0b\x32s.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.GetDataContractHistoryResponseV0.DataContractHistoryEntryB\x08\n\x06resultB\t\n\x07version\"\xb2\x02\n\x13GetDocumentsRequest\x12R\n\x02v0\x18\x01 \x01(\x0b\x32\x44.org.dash.platform.dapi.v0.GetDocumentsRequest.GetDocumentsRequestV0H\x00\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\x05startB\t\n\x07version\"\x95\x03\n\x14GetDocumentsResponse\x12T\n\x02v0\x18\x01 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV0H\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\x06resultB\t\n\x07version\"\xca\x02\n\x18GetDocumentsCountRequest\x12\\\n\x02v0\x18\x01 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0H\x00\x1a\xc4\x01\n\x1aGetDocumentsCountRequestV0\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\'\n\x1freturn_distinct_counts_in_range\x18\x04 \x01(\x08\x12\x10\n\x08order_by\x18\x05 \x01(\x0c\x12\x12\n\x05limit\x18\x06 \x01(\rH\x00\x88\x01\x01\x12\r\n\x05prove\x18\x07 \x01(\x08\x42\x08\n\x06_limitB\t\n\x07version\"\x8c\x06\n\x19GetDocumentsCountResponse\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0H\x00\x1a\x83\x05\n\x1bGetDocumentsCountResponseV0\x12o\n\x06\x63ounts\x18\x01 \x01(\x0b\x32].org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResultsH\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\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\x1a|\n\x0c\x43ountEntries\x12l\n\x07\x65ntries\x18\x01 \x03(\x0b\x32[.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry\x1a\xaa\x01\n\x0c\x43ountResults\x12\x1d\n\x0f\x61ggregate_count\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12p\n\x07\x65ntries\x18\x02 \x01(\x0b\x32].org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntriesH\x00\x42\t\n\x07variantB\x08\n\x06resultB\t\n\x07version\"\xed\x01\n!GetIdentityByPublicKeyHashRequest\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashRequest.GetIdentityByPublicKeyHashRequestV0H\x00\x1aM\n#GetIdentityByPublicKeyHashRequestV0\x12\x17\n\x0fpublic_key_hash\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xda\x02\n\"GetIdentityByPublicKeyHashResponse\x12p\n\x02v0\x18\x01 \x01(\x0b\x32\x62.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashResponse.GetIdentityByPublicKeyHashResponseV0H\x00\x1a\xb6\x01\n$GetIdentityByPublicKeyHashResponseV0\x12\x12\n\x08identity\x18\x01 \x01(\x0cH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xbd\x02\n*GetIdentityByNonUniquePublicKeyHashRequest\x12\x80\x01\n\x02v0\x18\x01 \x01(\x0b\x32r.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashRequest.GetIdentityByNonUniquePublicKeyHashRequestV0H\x00\x1a\x80\x01\n,GetIdentityByNonUniquePublicKeyHashRequestV0\x12\x17\n\x0fpublic_key_hash\x18\x01 \x01(\x0c\x12\x18\n\x0bstart_after\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\x0e\n\x0c_start_afterB\t\n\x07version\"\xd6\x06\n+GetIdentityByNonUniquePublicKeyHashResponse\x12\x82\x01\n\x02v0\x18\x01 \x01(\x0b\x32t.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashResponse.GetIdentityByNonUniquePublicKeyHashResponseV0H\x00\x1a\x96\x05\n-GetIdentityByNonUniquePublicKeyHashResponseV0\x12\x9a\x01\n\x08identity\x18\x01 \x01(\x0b\x32\x85\x01.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashResponse.GetIdentityByNonUniquePublicKeyHashResponseV0.IdentityResponseH\x00\x12\x9d\x01\n\x05proof\x18\x02 \x01(\x0b\x32\x8b\x01.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashResponse.GetIdentityByNonUniquePublicKeyHashResponseV0.IdentityProvedResponseH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x36\n\x10IdentityResponse\x12\x15\n\x08identity\x18\x01 \x01(\x0cH\x00\x88\x01\x01\x42\x0b\n\t_identity\x1a\xa6\x01\n\x16IdentityProvedResponse\x12P\n&grovedb_identity_public_key_hash_proof\x18\x01 \x01(\x0b\x32 .org.dash.platform.dapi.v0.Proof\x12!\n\x14identity_proof_bytes\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x42\x17\n\x15_identity_proof_bytesB\x08\n\x06resultB\t\n\x07version\"\xfb\x01\n#WaitForStateTransitionResultRequest\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.WaitForStateTransitionResultRequest.WaitForStateTransitionResultRequestV0H\x00\x1aU\n%WaitForStateTransitionResultRequestV0\x12\x1d\n\x15state_transition_hash\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x99\x03\n$WaitForStateTransitionResultResponse\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.WaitForStateTransitionResultResponse.WaitForStateTransitionResultResponseV0H\x00\x1a\xef\x01\n&WaitForStateTransitionResultResponseV0\x12I\n\x05\x65rror\x18\x01 \x01(\x0b\x32\x38.org.dash.platform.dapi.v0.StateTransitionBroadcastErrorH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xc4\x01\n\x19GetConsensusParamsRequest\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetConsensusParamsRequest.GetConsensusParamsRequestV0H\x00\x1a<\n\x1bGetConsensusParamsRequestV0\x12\x0e\n\x06height\x18\x01 \x01(\x05\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x9c\x04\n\x1aGetConsensusParamsResponse\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetConsensusParamsResponse.GetConsensusParamsResponseV0H\x00\x1aP\n\x14\x43onsensusParamsBlock\x12\x11\n\tmax_bytes\x18\x01 \x01(\t\x12\x0f\n\x07max_gas\x18\x02 \x01(\t\x12\x14\n\x0ctime_iota_ms\x18\x03 \x01(\t\x1a\x62\n\x17\x43onsensusParamsEvidence\x12\x1a\n\x12max_age_num_blocks\x18\x01 \x01(\t\x12\x18\n\x10max_age_duration\x18\x02 \x01(\t\x12\x11\n\tmax_bytes\x18\x03 \x01(\t\x1a\xda\x01\n\x1cGetConsensusParamsResponseV0\x12Y\n\x05\x62lock\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetConsensusParamsResponse.ConsensusParamsBlock\x12_\n\x08\x65vidence\x18\x02 \x01(\x0b\x32M.org.dash.platform.dapi.v0.GetConsensusParamsResponse.ConsensusParamsEvidenceB\t\n\x07version\"\xe4\x01\n%GetProtocolVersionUpgradeStateRequest\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateRequest.GetProtocolVersionUpgradeStateRequestV0H\x00\x1a\x38\n\'GetProtocolVersionUpgradeStateRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x42\t\n\x07version\"\xb5\x05\n&GetProtocolVersionUpgradeStateResponse\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateResponse.GetProtocolVersionUpgradeStateResponseV0H\x00\x1a\x85\x04\n(GetProtocolVersionUpgradeStateResponseV0\x12\x87\x01\n\x08versions\x18\x01 \x01(\x0b\x32s.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateResponse.GetProtocolVersionUpgradeStateResponseV0.VersionsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x96\x01\n\x08Versions\x12\x89\x01\n\x08versions\x18\x01 \x03(\x0b\x32w.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateResponse.GetProtocolVersionUpgradeStateResponseV0.VersionEntry\x1a:\n\x0cVersionEntry\x12\x16\n\x0eversion_number\x18\x01 \x01(\r\x12\x12\n\nvote_count\x18\x02 \x01(\rB\x08\n\x06resultB\t\n\x07version\"\xa3\x02\n*GetProtocolVersionUpgradeVoteStatusRequest\x12\x80\x01\n\x02v0\x18\x01 \x01(\x0b\x32r.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusRequest.GetProtocolVersionUpgradeVoteStatusRequestV0H\x00\x1ag\n,GetProtocolVersionUpgradeVoteStatusRequestV0\x12\x19\n\x11start_pro_tx_hash\x18\x01 \x01(\x0c\x12\r\n\x05\x63ount\x18\x02 \x01(\r\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xef\x05\n+GetProtocolVersionUpgradeVoteStatusResponse\x12\x82\x01\n\x02v0\x18\x01 \x01(\x0b\x32t.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusResponse.GetProtocolVersionUpgradeVoteStatusResponseV0H\x00\x1a\xaf\x04\n-GetProtocolVersionUpgradeVoteStatusResponseV0\x12\x98\x01\n\x08versions\x18\x01 \x01(\x0b\x32\x83\x01.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusResponse.GetProtocolVersionUpgradeVoteStatusResponseV0.VersionSignalsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\xaf\x01\n\x0eVersionSignals\x12\x9c\x01\n\x0fversion_signals\x18\x01 \x03(\x0b\x32\x82\x01.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusResponse.GetProtocolVersionUpgradeVoteStatusResponseV0.VersionSignal\x1a\x35\n\rVersionSignal\x12\x13\n\x0bpro_tx_hash\x18\x01 \x01(\x0c\x12\x0f\n\x07version\x18\x02 \x01(\rB\x08\n\x06resultB\t\n\x07version\"\xf5\x01\n\x14GetEpochsInfoRequest\x12T\n\x02v0\x18\x01 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetEpochsInfoRequest.GetEpochsInfoRequestV0H\x00\x1a|\n\x16GetEpochsInfoRequestV0\x12\x31\n\x0bstart_epoch\x18\x01 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\r\n\x05\x63ount\x18\x02 \x01(\r\x12\x11\n\tascending\x18\x03 \x01(\x08\x12\r\n\x05prove\x18\x04 \x01(\x08\x42\t\n\x07version\"\x99\x05\n\x15GetEpochsInfoResponse\x12V\n\x02v0\x18\x01 \x01(\x0b\x32H.org.dash.platform.dapi.v0.GetEpochsInfoResponse.GetEpochsInfoResponseV0H\x00\x1a\x9c\x04\n\x17GetEpochsInfoResponseV0\x12\x65\n\x06\x65pochs\x18\x01 \x01(\x0b\x32S.org.dash.platform.dapi.v0.GetEpochsInfoResponse.GetEpochsInfoResponseV0.EpochInfosH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1au\n\nEpochInfos\x12g\n\x0b\x65poch_infos\x18\x01 \x03(\x0b\x32R.org.dash.platform.dapi.v0.GetEpochsInfoResponse.GetEpochsInfoResponseV0.EpochInfo\x1a\xa6\x01\n\tEpochInfo\x12\x0e\n\x06number\x18\x01 \x01(\r\x12\x1e\n\x12\x66irst_block_height\x18\x02 \x01(\x04\x42\x02\x30\x01\x12\x1f\n\x17\x66irst_core_block_height\x18\x03 \x01(\r\x12\x16\n\nstart_time\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\x16\n\x0e\x66\x65\x65_multiplier\x18\x05 \x01(\x01\x12\x18\n\x10protocol_version\x18\x06 \x01(\rB\x08\n\x06resultB\t\n\x07version\"\xbf\x02\n\x1dGetFinalizedEpochInfosRequest\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetFinalizedEpochInfosRequest.GetFinalizedEpochInfosRequestV0H\x00\x1a\xaa\x01\n\x1fGetFinalizedEpochInfosRequestV0\x12\x19\n\x11start_epoch_index\x18\x01 \x01(\r\x12\"\n\x1astart_epoch_index_included\x18\x02 \x01(\x08\x12\x17\n\x0f\x65nd_epoch_index\x18\x03 \x01(\r\x12 \n\x18\x65nd_epoch_index_included\x18\x04 \x01(\x08\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\t\n\x07version\"\xbd\t\n\x1eGetFinalizedEpochInfosResponse\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetFinalizedEpochInfosResponse.GetFinalizedEpochInfosResponseV0H\x00\x1a\xa5\x08\n GetFinalizedEpochInfosResponseV0\x12\x80\x01\n\x06\x65pochs\x18\x01 \x01(\x0b\x32n.org.dash.platform.dapi.v0.GetFinalizedEpochInfosResponse.GetFinalizedEpochInfosResponseV0.FinalizedEpochInfosH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\xa4\x01\n\x13\x46inalizedEpochInfos\x12\x8c\x01\n\x15\x66inalized_epoch_infos\x18\x01 \x03(\x0b\x32m.org.dash.platform.dapi.v0.GetFinalizedEpochInfosResponse.GetFinalizedEpochInfosResponseV0.FinalizedEpochInfo\x1a\x9f\x04\n\x12\x46inalizedEpochInfo\x12\x0e\n\x06number\x18\x01 \x01(\r\x12\x1e\n\x12\x66irst_block_height\x18\x02 \x01(\x04\x42\x02\x30\x01\x12\x1f\n\x17\x66irst_core_block_height\x18\x03 \x01(\r\x12\x1c\n\x10\x66irst_block_time\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\x16\n\x0e\x66\x65\x65_multiplier\x18\x05 \x01(\x01\x12\x18\n\x10protocol_version\x18\x06 \x01(\r\x12!\n\x15total_blocks_in_epoch\x18\x07 \x01(\x04\x42\x02\x30\x01\x12*\n\"next_epoch_start_core_block_height\x18\x08 \x01(\r\x12!\n\x15total_processing_fees\x18\t \x01(\x04\x42\x02\x30\x01\x12*\n\x1etotal_distributed_storage_fees\x18\n \x01(\x04\x42\x02\x30\x01\x12&\n\x1atotal_created_storage_fees\x18\x0b \x01(\x04\x42\x02\x30\x01\x12\x1e\n\x12\x63ore_block_rewards\x18\x0c \x01(\x04\x42\x02\x30\x01\x12\x81\x01\n\x0f\x62lock_proposers\x18\r \x03(\x0b\x32h.org.dash.platform.dapi.v0.GetFinalizedEpochInfosResponse.GetFinalizedEpochInfosResponseV0.BlockProposer\x1a\x39\n\rBlockProposer\x12\x13\n\x0bproposer_id\x18\x01 \x01(\x0c\x12\x13\n\x0b\x62lock_count\x18\x02 \x01(\rB\x08\n\x06resultB\t\n\x07version\"\xde\x04\n\x1cGetContestedResourcesRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetContestedResourcesRequest.GetContestedResourcesRequestV0H\x00\x1a\xcc\x03\n\x1eGetContestedResourcesRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\x12\n\nindex_name\x18\x03 \x01(\t\x12\x1a\n\x12start_index_values\x18\x04 \x03(\x0c\x12\x18\n\x10\x65nd_index_values\x18\x05 \x03(\x0c\x12\x89\x01\n\x13start_at_value_info\x18\x06 \x01(\x0b\x32g.org.dash.platform.dapi.v0.GetContestedResourcesRequest.GetContestedResourcesRequestV0.StartAtValueInfoH\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x07 \x01(\rH\x01\x88\x01\x01\x12\x17\n\x0forder_ascending\x18\x08 \x01(\x08\x12\r\n\x05prove\x18\t \x01(\x08\x1a\x45\n\x10StartAtValueInfo\x12\x13\n\x0bstart_value\x18\x01 \x01(\x0c\x12\x1c\n\x14start_value_included\x18\x02 \x01(\x08\x42\x16\n\x14_start_at_value_infoB\x08\n\x06_countB\t\n\x07version\"\x88\x04\n\x1dGetContestedResourcesResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetContestedResourcesResponse.GetContestedResourcesResponseV0H\x00\x1a\xf3\x02\n\x1fGetContestedResourcesResponseV0\x12\x95\x01\n\x19\x63ontested_resource_values\x18\x01 \x01(\x0b\x32p.org.dash.platform.dapi.v0.GetContestedResourcesResponse.GetContestedResourcesResponseV0.ContestedResourceValuesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a<\n\x17\x43ontestedResourceValues\x12!\n\x19\x63ontested_resource_values\x18\x01 \x03(\x0c\x42\x08\n\x06resultB\t\n\x07version\"\xd2\x05\n\x1cGetVotePollsByEndDateRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetVotePollsByEndDateRequest.GetVotePollsByEndDateRequestV0H\x00\x1a\xc0\x04\n\x1eGetVotePollsByEndDateRequestV0\x12\x84\x01\n\x0fstart_time_info\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetVotePollsByEndDateRequest.GetVotePollsByEndDateRequestV0.StartAtTimeInfoH\x00\x88\x01\x01\x12\x80\x01\n\rend_time_info\x18\x02 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetVotePollsByEndDateRequest.GetVotePollsByEndDateRequestV0.EndAtTimeInfoH\x01\x88\x01\x01\x12\x12\n\x05limit\x18\x03 \x01(\rH\x02\x88\x01\x01\x12\x13\n\x06offset\x18\x04 \x01(\rH\x03\x88\x01\x01\x12\x11\n\tascending\x18\x05 \x01(\x08\x12\r\n\x05prove\x18\x06 \x01(\x08\x1aI\n\x0fStartAtTimeInfo\x12\x19\n\rstart_time_ms\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x1b\n\x13start_time_included\x18\x02 \x01(\x08\x1a\x43\n\rEndAtTimeInfo\x12\x17\n\x0b\x65nd_time_ms\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x19\n\x11\x65nd_time_included\x18\x02 \x01(\x08\x42\x12\n\x10_start_time_infoB\x10\n\x0e_end_time_infoB\x08\n\x06_limitB\t\n\x07_offsetB\t\n\x07version\"\x83\x06\n\x1dGetVotePollsByEndDateResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetVotePollsByEndDateResponse.GetVotePollsByEndDateResponseV0H\x00\x1a\xee\x04\n\x1fGetVotePollsByEndDateResponseV0\x12\x9c\x01\n\x18vote_polls_by_timestamps\x18\x01 \x01(\x0b\x32x.org.dash.platform.dapi.v0.GetVotePollsByEndDateResponse.GetVotePollsByEndDateResponseV0.SerializedVotePollsByTimestampsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aV\n\x1eSerializedVotePollsByTimestamp\x12\x15\n\ttimestamp\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x1d\n\x15serialized_vote_polls\x18\x02 \x03(\x0c\x1a\xd7\x01\n\x1fSerializedVotePollsByTimestamps\x12\x99\x01\n\x18vote_polls_by_timestamps\x18\x01 \x03(\x0b\x32w.org.dash.platform.dapi.v0.GetVotePollsByEndDateResponse.GetVotePollsByEndDateResponseV0.SerializedVotePollsByTimestamp\x12\x18\n\x10\x66inished_results\x18\x02 \x01(\x08\x42\x08\n\x06resultB\t\n\x07version\"\xff\x06\n$GetContestedResourceVoteStateRequest\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetContestedResourceVoteStateRequest.GetContestedResourceVoteStateRequestV0H\x00\x1a\xd5\x05\n&GetContestedResourceVoteStateRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\x12\n\nindex_name\x18\x03 \x01(\t\x12\x14\n\x0cindex_values\x18\x04 \x03(\x0c\x12\x86\x01\n\x0bresult_type\x18\x05 \x01(\x0e\x32q.org.dash.platform.dapi.v0.GetContestedResourceVoteStateRequest.GetContestedResourceVoteStateRequestV0.ResultType\x12\x36\n.allow_include_locked_and_abstaining_vote_tally\x18\x06 \x01(\x08\x12\xa3\x01\n\x18start_at_identifier_info\x18\x07 \x01(\x0b\x32|.org.dash.platform.dapi.v0.GetContestedResourceVoteStateRequest.GetContestedResourceVoteStateRequestV0.StartAtIdentifierInfoH\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x08 \x01(\rH\x01\x88\x01\x01\x12\r\n\x05prove\x18\t \x01(\x08\x1aT\n\x15StartAtIdentifierInfo\x12\x18\n\x10start_identifier\x18\x01 \x01(\x0c\x12!\n\x19start_identifier_included\x18\x02 \x01(\x08\"I\n\nResultType\x12\r\n\tDOCUMENTS\x10\x00\x12\x0e\n\nVOTE_TALLY\x10\x01\x12\x1c\n\x18\x44OCUMENTS_AND_VOTE_TALLY\x10\x02\x42\x1b\n\x19_start_at_identifier_infoB\x08\n\x06_countB\t\n\x07version\"\x94\x0c\n%GetContestedResourceVoteStateResponse\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0H\x00\x1a\xe7\n\n\'GetContestedResourceVoteStateResponseV0\x12\xae\x01\n\x1d\x63ontested_resource_contenders\x18\x01 \x01(\x0b\x32\x84\x01.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0.ContestedResourceContendersH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\xda\x03\n\x10\x46inishedVoteInfo\x12\xad\x01\n\x15\x66inished_vote_outcome\x18\x01 \x01(\x0e\x32\x8d\x01.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0.FinishedVoteInfo.FinishedVoteOutcome\x12\x1f\n\x12won_by_identity_id\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x12$\n\x18\x66inished_at_block_height\x18\x03 \x01(\x04\x42\x02\x30\x01\x12%\n\x1d\x66inished_at_core_block_height\x18\x04 \x01(\r\x12%\n\x19\x66inished_at_block_time_ms\x18\x05 \x01(\x04\x42\x02\x30\x01\x12\x19\n\x11\x66inished_at_epoch\x18\x06 \x01(\r\"O\n\x13\x46inishedVoteOutcome\x12\x14\n\x10TOWARDS_IDENTITY\x10\x00\x12\n\n\x06LOCKED\x10\x01\x12\x16\n\x12NO_PREVIOUS_WINNER\x10\x02\x42\x15\n\x13_won_by_identity_id\x1a\xc4\x03\n\x1b\x43ontestedResourceContenders\x12\x86\x01\n\ncontenders\x18\x01 \x03(\x0b\x32r.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0.Contender\x12\x1f\n\x12\x61\x62stain_vote_tally\x18\x02 \x01(\rH\x00\x88\x01\x01\x12\x1c\n\x0flock_vote_tally\x18\x03 \x01(\rH\x01\x88\x01\x01\x12\x9a\x01\n\x12\x66inished_vote_info\x18\x04 \x01(\x0b\x32y.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0.FinishedVoteInfoH\x02\x88\x01\x01\x42\x15\n\x13_abstain_vote_tallyB\x12\n\x10_lock_vote_tallyB\x15\n\x13_finished_vote_info\x1ak\n\tContender\x12\x12\n\nidentifier\x18\x01 \x01(\x0c\x12\x17\n\nvote_count\x18\x02 \x01(\rH\x00\x88\x01\x01\x12\x15\n\x08\x64ocument\x18\x03 \x01(\x0cH\x01\x88\x01\x01\x42\r\n\x0b_vote_countB\x0b\n\t_documentB\x08\n\x06resultB\t\n\x07version\"\xd5\x05\n,GetContestedResourceVotersForIdentityRequest\x12\x84\x01\n\x02v0\x18\x01 \x01(\x0b\x32v.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityRequest.GetContestedResourceVotersForIdentityRequestV0H\x00\x1a\x92\x04\n.GetContestedResourceVotersForIdentityRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\x12\n\nindex_name\x18\x03 \x01(\t\x12\x14\n\x0cindex_values\x18\x04 \x03(\x0c\x12\x15\n\rcontestant_id\x18\x05 \x01(\x0c\x12\xb4\x01\n\x18start_at_identifier_info\x18\x06 \x01(\x0b\x32\x8c\x01.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityRequest.GetContestedResourceVotersForIdentityRequestV0.StartAtIdentifierInfoH\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x07 \x01(\rH\x01\x88\x01\x01\x12\x17\n\x0forder_ascending\x18\x08 \x01(\x08\x12\r\n\x05prove\x18\t \x01(\x08\x1aT\n\x15StartAtIdentifierInfo\x12\x18\n\x10start_identifier\x18\x01 \x01(\x0c\x12!\n\x19start_identifier_included\x18\x02 \x01(\x08\x42\x1b\n\x19_start_at_identifier_infoB\x08\n\x06_countB\t\n\x07version\"\xf1\x04\n-GetContestedResourceVotersForIdentityResponse\x12\x86\x01\n\x02v0\x18\x01 \x01(\x0b\x32x.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityResponse.GetContestedResourceVotersForIdentityResponseV0H\x00\x1a\xab\x03\n/GetContestedResourceVotersForIdentityResponseV0\x12\xb6\x01\n\x19\x63ontested_resource_voters\x18\x01 \x01(\x0b\x32\x90\x01.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityResponse.GetContestedResourceVotersForIdentityResponseV0.ContestedResourceVotersH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x43\n\x17\x43ontestedResourceVoters\x12\x0e\n\x06voters\x18\x01 \x03(\x0c\x12\x18\n\x10\x66inished_results\x18\x02 \x01(\x08\x42\x08\n\x06resultB\t\n\x07version\"\xad\x05\n(GetContestedResourceIdentityVotesRequest\x12|\n\x02v0\x18\x01 \x01(\x0b\x32n.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesRequest.GetContestedResourceIdentityVotesRequestV0H\x00\x1a\xf7\x03\n*GetContestedResourceIdentityVotesRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12+\n\x05limit\x18\x02 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12,\n\x06offset\x18\x03 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\x17\n\x0forder_ascending\x18\x04 \x01(\x08\x12\xae\x01\n\x1astart_at_vote_poll_id_info\x18\x05 \x01(\x0b\x32\x84\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesRequest.GetContestedResourceIdentityVotesRequestV0.StartAtVotePollIdInfoH\x00\x88\x01\x01\x12\r\n\x05prove\x18\x06 \x01(\x08\x1a\x61\n\x15StartAtVotePollIdInfo\x12 \n\x18start_at_poll_identifier\x18\x01 \x01(\x0c\x12&\n\x1estart_poll_identifier_included\x18\x02 \x01(\x08\x42\x1d\n\x1b_start_at_vote_poll_id_infoB\t\n\x07version\"\xc8\n\n)GetContestedResourceIdentityVotesResponse\x12~\n\x02v0\x18\x01 \x01(\x0b\x32p.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0H\x00\x1a\x8f\t\n+GetContestedResourceIdentityVotesResponseV0\x12\xa1\x01\n\x05votes\x18\x01 \x01(\x0b\x32\x8f\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0.ContestedResourceIdentityVotesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\xf7\x01\n\x1e\x43ontestedResourceIdentityVotes\x12\xba\x01\n!contested_resource_identity_votes\x18\x01 \x03(\x0b\x32\x8e\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0.ContestedResourceIdentityVote\x12\x18\n\x10\x66inished_results\x18\x02 \x01(\x08\x1a\xad\x02\n\x12ResourceVoteChoice\x12\xad\x01\n\x10vote_choice_type\x18\x01 \x01(\x0e\x32\x92\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0.ResourceVoteChoice.VoteChoiceType\x12\x18\n\x0bidentity_id\x18\x02 \x01(\x0cH\x00\x88\x01\x01\"=\n\x0eVoteChoiceType\x12\x14\n\x10TOWARDS_IDENTITY\x10\x00\x12\x0b\n\x07\x41\x42STAIN\x10\x01\x12\x08\n\x04LOCK\x10\x02\x42\x0e\n\x0c_identity_id\x1a\x95\x02\n\x1d\x43ontestedResourceIdentityVote\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\'\n\x1fserialized_index_storage_values\x18\x03 \x03(\x0c\x12\x99\x01\n\x0bvote_choice\x18\x04 \x01(\x0b\x32\x83\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0.ResourceVoteChoiceB\x08\n\x06resultB\t\n\x07version\"\xf0\x01\n%GetPrefundedSpecializedBalanceRequest\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetPrefundedSpecializedBalanceRequest.GetPrefundedSpecializedBalanceRequestV0H\x00\x1a\x44\n\'GetPrefundedSpecializedBalanceRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xed\x02\n&GetPrefundedSpecializedBalanceResponse\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetPrefundedSpecializedBalanceResponse.GetPrefundedSpecializedBalanceResponseV0H\x00\x1a\xbd\x01\n(GetPrefundedSpecializedBalanceResponseV0\x12\x15\n\x07\x62\x61lance\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xd0\x01\n GetTotalCreditsInPlatformRequest\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetTotalCreditsInPlatformRequest.GetTotalCreditsInPlatformRequestV0H\x00\x1a\x33\n\"GetTotalCreditsInPlatformRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x42\t\n\x07version\"\xd9\x02\n!GetTotalCreditsInPlatformResponse\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetTotalCreditsInPlatformResponse.GetTotalCreditsInPlatformResponseV0H\x00\x1a\xb8\x01\n#GetTotalCreditsInPlatformResponseV0\x12\x15\n\x07\x63redits\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xc4\x01\n\x16GetPathElementsRequest\x12X\n\x02v0\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetPathElementsRequest.GetPathElementsRequestV0H\x00\x1a\x45\n\x18GetPathElementsRequestV0\x12\x0c\n\x04path\x18\x01 \x03(\x0c\x12\x0c\n\x04keys\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xa3\x03\n\x17GetPathElementsResponse\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetPathElementsResponse.GetPathElementsResponseV0H\x00\x1a\xa0\x02\n\x19GetPathElementsResponseV0\x12i\n\x08\x65lements\x18\x01 \x01(\x0b\x32U.org.dash.platform.dapi.v0.GetPathElementsResponse.GetPathElementsResponseV0.ElementsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1c\n\x08\x45lements\x12\x10\n\x08\x65lements\x18\x01 \x03(\x0c\x42\x08\n\x06resultB\t\n\x07version\"\x81\x01\n\x10GetStatusRequest\x12L\n\x02v0\x18\x01 \x01(\x0b\x32>.org.dash.platform.dapi.v0.GetStatusRequest.GetStatusRequestV0H\x00\x1a\x14\n\x12GetStatusRequestV0B\t\n\x07version\"\xe4\x10\n\x11GetStatusResponse\x12N\n\x02v0\x18\x01 \x01(\x0b\x32@.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0H\x00\x1a\xf3\x0f\n\x13GetStatusResponseV0\x12Y\n\x07version\x18\x01 \x01(\x0b\x32H.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Version\x12S\n\x04node\x18\x02 \x01(\x0b\x32\x45.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Node\x12U\n\x05\x63hain\x18\x03 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Chain\x12Y\n\x07network\x18\x04 \x01(\x0b\x32H.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Network\x12^\n\nstate_sync\x18\x05 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.StateSync\x12S\n\x04time\x18\x06 \x01(\x0b\x32\x45.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Time\x1a\x82\x05\n\x07Version\x12\x63\n\x08software\x18\x01 \x01(\x0b\x32Q.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Version.Software\x12\x63\n\x08protocol\x18\x02 \x01(\x0b\x32Q.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Version.Protocol\x1a^\n\x08Software\x12\x0c\n\x04\x64\x61pi\x18\x01 \x01(\t\x12\x12\n\x05\x64rive\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x17\n\ntenderdash\x18\x03 \x01(\tH\x01\x88\x01\x01\x42\x08\n\x06_driveB\r\n\x0b_tenderdash\x1a\xcc\x02\n\x08Protocol\x12p\n\ntenderdash\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Version.Protocol.Tenderdash\x12\x66\n\x05\x64rive\x18\x02 \x01(\x0b\x32W.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Version.Protocol.Drive\x1a(\n\nTenderdash\x12\x0b\n\x03p2p\x18\x01 \x01(\r\x12\r\n\x05\x62lock\x18\x02 \x01(\r\x1a<\n\x05\x44rive\x12\x0e\n\x06latest\x18\x03 \x01(\r\x12\x0f\n\x07\x63urrent\x18\x04 \x01(\r\x12\x12\n\nnext_epoch\x18\x05 \x01(\r\x1a\x7f\n\x04Time\x12\x11\n\x05local\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x16\n\x05\x62lock\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x88\x01\x01\x12\x18\n\x07genesis\x18\x03 \x01(\x04\x42\x02\x30\x01H\x01\x88\x01\x01\x12\x12\n\x05\x65poch\x18\x04 \x01(\rH\x02\x88\x01\x01\x42\x08\n\x06_blockB\n\n\x08_genesisB\x08\n\x06_epoch\x1a<\n\x04Node\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\x18\n\x0bpro_tx_hash\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x42\x0e\n\x0c_pro_tx_hash\x1a\xb3\x02\n\x05\x43hain\x12\x13\n\x0b\x63\x61tching_up\x18\x01 \x01(\x08\x12\x19\n\x11latest_block_hash\x18\x02 \x01(\x0c\x12\x17\n\x0flatest_app_hash\x18\x03 \x01(\x0c\x12\x1f\n\x13latest_block_height\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\x1b\n\x13\x65\x61rliest_block_hash\x18\x05 \x01(\x0c\x12\x19\n\x11\x65\x61rliest_app_hash\x18\x06 \x01(\x0c\x12!\n\x15\x65\x61rliest_block_height\x18\x07 \x01(\x04\x42\x02\x30\x01\x12!\n\x15max_peer_block_height\x18\t \x01(\x04\x42\x02\x30\x01\x12%\n\x18\x63ore_chain_locked_height\x18\n \x01(\rH\x00\x88\x01\x01\x42\x1b\n\x19_core_chain_locked_height\x1a\x43\n\x07Network\x12\x10\n\x08\x63hain_id\x18\x01 \x01(\t\x12\x13\n\x0bpeers_count\x18\x02 \x01(\r\x12\x11\n\tlistening\x18\x03 \x01(\x08\x1a\x85\x02\n\tStateSync\x12\x1d\n\x11total_synced_time\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x1a\n\x0eremaining_time\x18\x02 \x01(\x04\x42\x02\x30\x01\x12\x17\n\x0ftotal_snapshots\x18\x03 \x01(\r\x12\"\n\x16\x63hunk_process_avg_time\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\x1b\n\x0fsnapshot_height\x18\x05 \x01(\x04\x42\x02\x30\x01\x12!\n\x15snapshot_chunks_count\x18\x06 \x01(\x04\x42\x02\x30\x01\x12\x1d\n\x11\x62\x61\x63kfilled_blocks\x18\x07 \x01(\x04\x42\x02\x30\x01\x12!\n\x15\x62\x61\x63kfill_blocks_total\x18\x08 \x01(\x04\x42\x02\x30\x01\x42\t\n\x07version\"\xb1\x01\n\x1cGetCurrentQuorumsInfoRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0H\x00\x1a \n\x1eGetCurrentQuorumsInfoRequestV0B\t\n\x07version\"\xa1\x05\n\x1dGetCurrentQuorumsInfoResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0H\x00\x1a\x46\n\x0bValidatorV0\x12\x13\n\x0bpro_tx_hash\x18\x01 \x01(\x0c\x12\x0f\n\x07node_ip\x18\x02 \x01(\t\x12\x11\n\tis_banned\x18\x03 \x01(\x08\x1a\xaf\x01\n\x0eValidatorSetV0\x12\x13\n\x0bquorum_hash\x18\x01 \x01(\x0c\x12\x13\n\x0b\x63ore_height\x18\x02 \x01(\r\x12U\n\x07members\x18\x03 \x03(\x0b\x32\x44.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0\x12\x1c\n\x14threshold_public_key\x18\x04 \x01(\x0c\x1a\x92\x02\n\x1fGetCurrentQuorumsInfoResponseV0\x12\x15\n\rquorum_hashes\x18\x01 \x03(\x0c\x12\x1b\n\x13\x63urrent_quorum_hash\x18\x02 \x01(\x0c\x12_\n\x0evalidator_sets\x18\x03 \x03(\x0b\x32G.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0\x12\x1b\n\x13last_block_proposer\x18\x04 \x01(\x0c\x12=\n\x08metadata\x18\x05 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\t\n\x07version\"\xf4\x01\n\x1fGetIdentityTokenBalancesRequest\x12j\n\x02v0\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetIdentityTokenBalancesRequest.GetIdentityTokenBalancesRequestV0H\x00\x1aZ\n!GetIdentityTokenBalancesRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x11\n\ttoken_ids\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xad\x05\n GetIdentityTokenBalancesResponse\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetIdentityTokenBalancesResponse.GetIdentityTokenBalancesResponseV0H\x00\x1a\x8f\x04\n\"GetIdentityTokenBalancesResponseV0\x12\x86\x01\n\x0etoken_balances\x18\x01 \x01(\x0b\x32l.org.dash.platform.dapi.v0.GetIdentityTokenBalancesResponse.GetIdentityTokenBalancesResponseV0.TokenBalancesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aG\n\x11TokenBalanceEntry\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x14\n\x07\x62\x61lance\x18\x02 \x01(\x04H\x00\x88\x01\x01\x42\n\n\x08_balance\x1a\x9a\x01\n\rTokenBalances\x12\x88\x01\n\x0etoken_balances\x18\x01 \x03(\x0b\x32p.org.dash.platform.dapi.v0.GetIdentityTokenBalancesResponse.GetIdentityTokenBalancesResponseV0.TokenBalanceEntryB\x08\n\x06resultB\t\n\x07version\"\xfc\x01\n!GetIdentitiesTokenBalancesRequest\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetIdentitiesTokenBalancesRequest.GetIdentitiesTokenBalancesRequestV0H\x00\x1a\\\n#GetIdentitiesTokenBalancesRequestV0\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x14\n\x0cidentity_ids\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xf2\x05\n\"GetIdentitiesTokenBalancesResponse\x12p\n\x02v0\x18\x01 \x01(\x0b\x32\x62.org.dash.platform.dapi.v0.GetIdentitiesTokenBalancesResponse.GetIdentitiesTokenBalancesResponseV0H\x00\x1a\xce\x04\n$GetIdentitiesTokenBalancesResponseV0\x12\x9b\x01\n\x17identity_token_balances\x18\x01 \x01(\x0b\x32x.org.dash.platform.dapi.v0.GetIdentitiesTokenBalancesResponse.GetIdentitiesTokenBalancesResponseV0.IdentityTokenBalancesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aR\n\x19IdentityTokenBalanceEntry\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x14\n\x07\x62\x61lance\x18\x02 \x01(\x04H\x00\x88\x01\x01\x42\n\n\x08_balance\x1a\xb7\x01\n\x15IdentityTokenBalances\x12\x9d\x01\n\x17identity_token_balances\x18\x01 \x03(\x0b\x32|.org.dash.platform.dapi.v0.GetIdentitiesTokenBalancesResponse.GetIdentitiesTokenBalancesResponseV0.IdentityTokenBalanceEntryB\x08\n\x06resultB\t\n\x07version\"\xe8\x01\n\x1cGetIdentityTokenInfosRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetIdentityTokenInfosRequest.GetIdentityTokenInfosRequestV0H\x00\x1aW\n\x1eGetIdentityTokenInfosRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x11\n\ttoken_ids\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\x98\x06\n\x1dGetIdentityTokenInfosResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetIdentityTokenInfosResponse.GetIdentityTokenInfosResponseV0H\x00\x1a\x83\x05\n\x1fGetIdentityTokenInfosResponseV0\x12z\n\x0btoken_infos\x18\x01 \x01(\x0b\x32\x63.org.dash.platform.dapi.v0.GetIdentityTokenInfosResponse.GetIdentityTokenInfosResponseV0.TokenInfosH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a(\n\x16TokenIdentityInfoEntry\x12\x0e\n\x06\x66rozen\x18\x01 \x01(\x08\x1a\xb0\x01\n\x0eTokenInfoEntry\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x82\x01\n\x04info\x18\x02 \x01(\x0b\x32o.org.dash.platform.dapi.v0.GetIdentityTokenInfosResponse.GetIdentityTokenInfosResponseV0.TokenIdentityInfoEntryH\x00\x88\x01\x01\x42\x07\n\x05_info\x1a\x8a\x01\n\nTokenInfos\x12|\n\x0btoken_infos\x18\x01 \x03(\x0b\x32g.org.dash.platform.dapi.v0.GetIdentityTokenInfosResponse.GetIdentityTokenInfosResponseV0.TokenInfoEntryB\x08\n\x06resultB\t\n\x07version\"\xf0\x01\n\x1eGetIdentitiesTokenInfosRequest\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosRequest.GetIdentitiesTokenInfosRequestV0H\x00\x1aY\n GetIdentitiesTokenInfosRequestV0\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x14\n\x0cidentity_ids\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xca\x06\n\x1fGetIdentitiesTokenInfosResponse\x12j\n\x02v0\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosResponse.GetIdentitiesTokenInfosResponseV0H\x00\x1a\xaf\x05\n!GetIdentitiesTokenInfosResponseV0\x12\x8f\x01\n\x14identity_token_infos\x18\x01 \x01(\x0b\x32o.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosResponse.GetIdentitiesTokenInfosResponseV0.IdentityTokenInfosH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a(\n\x16TokenIdentityInfoEntry\x12\x0e\n\x06\x66rozen\x18\x01 \x01(\x08\x1a\xb7\x01\n\x0eTokenInfoEntry\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x86\x01\n\x04info\x18\x02 \x01(\x0b\x32s.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosResponse.GetIdentitiesTokenInfosResponseV0.TokenIdentityInfoEntryH\x00\x88\x01\x01\x42\x07\n\x05_info\x1a\x97\x01\n\x12IdentityTokenInfos\x12\x80\x01\n\x0btoken_infos\x18\x01 \x03(\x0b\x32k.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosResponse.GetIdentitiesTokenInfosResponseV0.TokenInfoEntryB\x08\n\x06resultB\t\n\x07version\"\xbf\x01\n\x17GetTokenStatusesRequest\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetTokenStatusesRequest.GetTokenStatusesRequestV0H\x00\x1a=\n\x19GetTokenStatusesRequestV0\x12\x11\n\ttoken_ids\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xe7\x04\n\x18GetTokenStatusesResponse\x12\\\n\x02v0\x18\x01 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetTokenStatusesResponse.GetTokenStatusesResponseV0H\x00\x1a\xe1\x03\n\x1aGetTokenStatusesResponseV0\x12v\n\x0etoken_statuses\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetTokenStatusesResponse.GetTokenStatusesResponseV0.TokenStatusesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x44\n\x10TokenStatusEntry\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x13\n\x06paused\x18\x02 \x01(\x08H\x00\x88\x01\x01\x42\t\n\x07_paused\x1a\x88\x01\n\rTokenStatuses\x12w\n\x0etoken_statuses\x18\x01 \x03(\x0b\x32_.org.dash.platform.dapi.v0.GetTokenStatusesResponse.GetTokenStatusesResponseV0.TokenStatusEntryB\x08\n\x06resultB\t\n\x07version\"\xef\x01\n#GetTokenDirectPurchasePricesRequest\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesRequest.GetTokenDirectPurchasePricesRequestV0H\x00\x1aI\n%GetTokenDirectPurchasePricesRequestV0\x12\x11\n\ttoken_ids\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x8b\t\n$GetTokenDirectPurchasePricesResponse\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesResponse.GetTokenDirectPurchasePricesResponseV0H\x00\x1a\xe1\x07\n&GetTokenDirectPurchasePricesResponseV0\x12\xa9\x01\n\x1ctoken_direct_purchase_prices\x18\x01 \x01(\x0b\x32\x80\x01.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesResponse.GetTokenDirectPurchasePricesResponseV0.TokenDirectPurchasePricesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x33\n\x10PriceForQuantity\x12\x10\n\x08quantity\x18\x01 \x01(\x04\x12\r\n\x05price\x18\x02 \x01(\x04\x1a\xa7\x01\n\x0fPricingSchedule\x12\x93\x01\n\x12price_for_quantity\x18\x01 \x03(\x0b\x32w.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesResponse.GetTokenDirectPurchasePricesResponseV0.PriceForQuantity\x1a\xe4\x01\n\x1dTokenDirectPurchasePriceEntry\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x15\n\x0b\x66ixed_price\x18\x02 \x01(\x04H\x00\x12\x90\x01\n\x0evariable_price\x18\x03 \x01(\x0b\x32v.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesResponse.GetTokenDirectPurchasePricesResponseV0.PricingScheduleH\x00\x42\x07\n\x05price\x1a\xc8\x01\n\x19TokenDirectPurchasePrices\x12\xaa\x01\n\x1btoken_direct_purchase_price\x18\x01 \x03(\x0b\x32\x84\x01.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesResponse.GetTokenDirectPurchasePricesResponseV0.TokenDirectPurchasePriceEntryB\x08\n\x06resultB\t\n\x07version\"\xce\x01\n\x1bGetTokenContractInfoRequest\x12\x62\n\x02v0\x18\x01 \x01(\x0b\x32T.org.dash.platform.dapi.v0.GetTokenContractInfoRequest.GetTokenContractInfoRequestV0H\x00\x1a@\n\x1dGetTokenContractInfoRequestV0\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xfb\x03\n\x1cGetTokenContractInfoResponse\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetTokenContractInfoResponse.GetTokenContractInfoResponseV0H\x00\x1a\xe9\x02\n\x1eGetTokenContractInfoResponseV0\x12|\n\x04\x64\x61ta\x18\x01 \x01(\x0b\x32l.org.dash.platform.dapi.v0.GetTokenContractInfoResponse.GetTokenContractInfoResponseV0.TokenContractInfoDataH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aM\n\x15TokenContractInfoData\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1f\n\x17token_contract_position\x18\x02 \x01(\rB\x08\n\x06resultB\t\n\x07version\"\xef\x04\n)GetTokenPreProgrammedDistributionsRequest\x12~\n\x02v0\x18\x01 \x01(\x0b\x32p.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsRequest.GetTokenPreProgrammedDistributionsRequestV0H\x00\x1a\xb6\x03\n+GetTokenPreProgrammedDistributionsRequestV0\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x98\x01\n\rstart_at_info\x18\x02 \x01(\x0b\x32|.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsRequest.GetTokenPreProgrammedDistributionsRequestV0.StartAtInfoH\x00\x88\x01\x01\x12\x12\n\x05limit\x18\x03 \x01(\rH\x01\x88\x01\x01\x12\r\n\x05prove\x18\x04 \x01(\x08\x1a\x9a\x01\n\x0bStartAtInfo\x12\x15\n\rstart_time_ms\x18\x01 \x01(\x04\x12\x1c\n\x0fstart_recipient\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x12%\n\x18start_recipient_included\x18\x03 \x01(\x08H\x01\x88\x01\x01\x42\x12\n\x10_start_recipientB\x1b\n\x19_start_recipient_includedB\x10\n\x0e_start_at_infoB\x08\n\x06_limitB\t\n\x07version\"\xec\x07\n*GetTokenPreProgrammedDistributionsResponse\x12\x80\x01\n\x02v0\x18\x01 \x01(\x0b\x32r.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsResponse.GetTokenPreProgrammedDistributionsResponseV0H\x00\x1a\xaf\x06\n,GetTokenPreProgrammedDistributionsResponseV0\x12\xa5\x01\n\x13token_distributions\x18\x01 \x01(\x0b\x32\x85\x01.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsResponse.GetTokenPreProgrammedDistributionsResponseV0.TokenDistributionsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a>\n\x16TokenDistributionEntry\x12\x14\n\x0crecipient_id\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\x1a\xd4\x01\n\x1bTokenTimedDistributionEntry\x12\x11\n\ttimestamp\x18\x01 \x01(\x04\x12\xa1\x01\n\rdistributions\x18\x02 \x03(\x0b\x32\x89\x01.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsResponse.GetTokenPreProgrammedDistributionsResponseV0.TokenDistributionEntry\x1a\xc3\x01\n\x12TokenDistributions\x12\xac\x01\n\x13token_distributions\x18\x01 \x03(\x0b\x32\x8e\x01.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsResponse.GetTokenPreProgrammedDistributionsResponseV0.TokenTimedDistributionEntryB\x08\n\x06resultB\t\n\x07version\"\x82\x04\n-GetTokenPerpetualDistributionLastClaimRequest\x12\x86\x01\n\x02v0\x18\x01 \x01(\x0b\x32x.org.dash.platform.dapi.v0.GetTokenPerpetualDistributionLastClaimRequest.GetTokenPerpetualDistributionLastClaimRequestV0H\x00\x1aI\n\x11\x43ontractTokenInfo\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1f\n\x17token_contract_position\x18\x02 \x01(\r\x1a\xf1\x01\n/GetTokenPerpetualDistributionLastClaimRequestV0\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12v\n\rcontract_info\x18\x02 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetTokenPerpetualDistributionLastClaimRequest.ContractTokenInfoH\x00\x88\x01\x01\x12\x13\n\x0bidentity_id\x18\x04 \x01(\x0c\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\x10\n\x0e_contract_infoB\t\n\x07version\"\x93\x05\n.GetTokenPerpetualDistributionLastClaimResponse\x12\x88\x01\n\x02v0\x18\x01 \x01(\x0b\x32z.org.dash.platform.dapi.v0.GetTokenPerpetualDistributionLastClaimResponse.GetTokenPerpetualDistributionLastClaimResponseV0H\x00\x1a\xca\x03\n0GetTokenPerpetualDistributionLastClaimResponseV0\x12\x9f\x01\n\nlast_claim\x18\x01 \x01(\x0b\x32\x88\x01.org.dash.platform.dapi.v0.GetTokenPerpetualDistributionLastClaimResponse.GetTokenPerpetualDistributionLastClaimResponseV0.LastClaimInfoH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1ax\n\rLastClaimInfo\x12\x1a\n\x0ctimestamp_ms\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x1a\n\x0c\x62lock_height\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x12\x0f\n\x05\x65poch\x18\x03 \x01(\rH\x00\x12\x13\n\traw_bytes\x18\x04 \x01(\x0cH\x00\x42\t\n\x07paid_atB\x08\n\x06resultB\t\n\x07version\"\xca\x01\n\x1aGetTokenTotalSupplyRequest\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetTokenTotalSupplyRequest.GetTokenTotalSupplyRequestV0H\x00\x1a?\n\x1cGetTokenTotalSupplyRequestV0\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xaf\x04\n\x1bGetTokenTotalSupplyResponse\x12\x62\n\x02v0\x18\x01 \x01(\x0b\x32T.org.dash.platform.dapi.v0.GetTokenTotalSupplyResponse.GetTokenTotalSupplyResponseV0H\x00\x1a\xa0\x03\n\x1dGetTokenTotalSupplyResponseV0\x12\x88\x01\n\x12token_total_supply\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetTokenTotalSupplyResponse.GetTokenTotalSupplyResponseV0.TokenTotalSupplyEntryH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1ax\n\x15TokenTotalSupplyEntry\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x30\n(total_aggregated_amount_in_user_accounts\x18\x02 \x01(\x04\x12\x1b\n\x13total_system_amount\x18\x03 \x01(\x04\x42\x08\n\x06resultB\t\n\x07version\"\xd2\x01\n\x13GetGroupInfoRequest\x12R\n\x02v0\x18\x01 \x01(\x0b\x32\x44.org.dash.platform.dapi.v0.GetGroupInfoRequest.GetGroupInfoRequestV0H\x00\x1a\\\n\x15GetGroupInfoRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1f\n\x17group_contract_position\x18\x02 \x01(\r\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xd4\x05\n\x14GetGroupInfoResponse\x12T\n\x02v0\x18\x01 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetGroupInfoResponse.GetGroupInfoResponseV0H\x00\x1a\xda\x04\n\x16GetGroupInfoResponseV0\x12\x66\n\ngroup_info\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetGroupInfoResponse.GetGroupInfoResponseV0.GroupInfoH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x04 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x34\n\x10GroupMemberEntry\x12\x11\n\tmember_id\x18\x01 \x01(\x0c\x12\r\n\x05power\x18\x02 \x01(\r\x1a\x98\x01\n\x0eGroupInfoEntry\x12h\n\x07members\x18\x01 \x03(\x0b\x32W.org.dash.platform.dapi.v0.GetGroupInfoResponse.GetGroupInfoResponseV0.GroupMemberEntry\x12\x1c\n\x14group_required_power\x18\x02 \x01(\r\x1a\x8a\x01\n\tGroupInfo\x12n\n\ngroup_info\x18\x01 \x01(\x0b\x32U.org.dash.platform.dapi.v0.GetGroupInfoResponse.GetGroupInfoResponseV0.GroupInfoEntryH\x00\x88\x01\x01\x42\r\n\x0b_group_infoB\x08\n\x06resultB\t\n\x07version\"\xed\x03\n\x14GetGroupInfosRequest\x12T\n\x02v0\x18\x01 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetGroupInfosRequest.GetGroupInfosRequestV0H\x00\x1au\n\x1cStartAtGroupContractPosition\x12%\n\x1dstart_group_contract_position\x18\x01 \x01(\r\x12.\n&start_group_contract_position_included\x18\x02 \x01(\x08\x1a\xfc\x01\n\x16GetGroupInfosRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12{\n start_at_group_contract_position\x18\x02 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetGroupInfosRequest.StartAtGroupContractPositionH\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x03 \x01(\rH\x01\x88\x01\x01\x12\r\n\x05prove\x18\x04 \x01(\x08\x42#\n!_start_at_group_contract_positionB\x08\n\x06_countB\t\n\x07version\"\xff\x05\n\x15GetGroupInfosResponse\x12V\n\x02v0\x18\x01 \x01(\x0b\x32H.org.dash.platform.dapi.v0.GetGroupInfosResponse.GetGroupInfosResponseV0H\x00\x1a\x82\x05\n\x17GetGroupInfosResponseV0\x12j\n\x0bgroup_infos\x18\x01 \x01(\x0b\x32S.org.dash.platform.dapi.v0.GetGroupInfosResponse.GetGroupInfosResponseV0.GroupInfosH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x04 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x34\n\x10GroupMemberEntry\x12\x11\n\tmember_id\x18\x01 \x01(\x0c\x12\r\n\x05power\x18\x02 \x01(\r\x1a\xc3\x01\n\x16GroupPositionInfoEntry\x12\x1f\n\x17group_contract_position\x18\x01 \x01(\r\x12j\n\x07members\x18\x02 \x03(\x0b\x32Y.org.dash.platform.dapi.v0.GetGroupInfosResponse.GetGroupInfosResponseV0.GroupMemberEntry\x12\x1c\n\x14group_required_power\x18\x03 \x01(\r\x1a\x82\x01\n\nGroupInfos\x12t\n\x0bgroup_infos\x18\x01 \x03(\x0b\x32_.org.dash.platform.dapi.v0.GetGroupInfosResponse.GetGroupInfosResponseV0.GroupPositionInfoEntryB\x08\n\x06resultB\t\n\x07version\"\xbe\x04\n\x16GetGroupActionsRequest\x12X\n\x02v0\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetGroupActionsRequest.GetGroupActionsRequestV0H\x00\x1aL\n\x0fStartAtActionId\x12\x17\n\x0fstart_action_id\x18\x01 \x01(\x0c\x12 \n\x18start_action_id_included\x18\x02 \x01(\x08\x1a\xc8\x02\n\x18GetGroupActionsRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1f\n\x17group_contract_position\x18\x02 \x01(\r\x12N\n\x06status\x18\x03 \x01(\x0e\x32>.org.dash.platform.dapi.v0.GetGroupActionsRequest.ActionStatus\x12\x62\n\x12start_at_action_id\x18\x04 \x01(\x0b\x32\x41.org.dash.platform.dapi.v0.GetGroupActionsRequest.StartAtActionIdH\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x05 \x01(\rH\x01\x88\x01\x01\x12\r\n\x05prove\x18\x06 \x01(\x08\x42\x15\n\x13_start_at_action_idB\x08\n\x06_count\"&\n\x0c\x41\x63tionStatus\x12\n\n\x06\x41\x43TIVE\x10\x00\x12\n\n\x06\x43LOSED\x10\x01\x42\t\n\x07version\"\xd6\x1e\n\x17GetGroupActionsResponse\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0H\x00\x1a\xd3\x1d\n\x19GetGroupActionsResponseV0\x12r\n\rgroup_actions\x18\x01 \x01(\x0b\x32Y.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.GroupActionsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a[\n\tMintEvent\x12\x0e\n\x06\x61mount\x18\x01 \x01(\x04\x12\x14\n\x0crecipient_id\x18\x02 \x01(\x0c\x12\x18\n\x0bpublic_note\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_public_note\x1a[\n\tBurnEvent\x12\x0e\n\x06\x61mount\x18\x01 \x01(\x04\x12\x14\n\x0c\x62urn_from_id\x18\x02 \x01(\x0c\x12\x18\n\x0bpublic_note\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_public_note\x1aJ\n\x0b\x46reezeEvent\x12\x11\n\tfrozen_id\x18\x01 \x01(\x0c\x12\x18\n\x0bpublic_note\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_public_note\x1aL\n\rUnfreezeEvent\x12\x11\n\tfrozen_id\x18\x01 \x01(\x0c\x12\x18\n\x0bpublic_note\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_public_note\x1a\x66\n\x17\x44\x65stroyFrozenFundsEvent\x12\x11\n\tfrozen_id\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\x12\x18\n\x0bpublic_note\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_public_note\x1a\x64\n\x13SharedEncryptedNote\x12\x18\n\x10sender_key_index\x18\x01 \x01(\r\x12\x1b\n\x13recipient_key_index\x18\x02 \x01(\r\x12\x16\n\x0e\x65ncrypted_data\x18\x03 \x01(\x0c\x1a{\n\x15PersonalEncryptedNote\x12!\n\x19root_encryption_key_index\x18\x01 \x01(\r\x12\'\n\x1f\x64\x65rivation_encryption_key_index\x18\x02 \x01(\r\x12\x16\n\x0e\x65ncrypted_data\x18\x03 \x01(\x0c\x1a\xe9\x01\n\x14\x45mergencyActionEvent\x12\x81\x01\n\x0b\x61\x63tion_type\x18\x01 \x01(\x0e\x32l.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.EmergencyActionEvent.ActionType\x12\x18\n\x0bpublic_note\x18\x02 \x01(\tH\x00\x88\x01\x01\"#\n\nActionType\x12\t\n\x05PAUSE\x10\x00\x12\n\n\x06RESUME\x10\x01\x42\x0e\n\x0c_public_note\x1a\x64\n\x16TokenConfigUpdateEvent\x12 \n\x18token_config_update_item\x18\x01 \x01(\x0c\x12\x18\n\x0bpublic_note\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_public_note\x1a\xe6\x03\n\x1eUpdateDirectPurchasePriceEvent\x12\x15\n\x0b\x66ixed_price\x18\x01 \x01(\x04H\x00\x12\x95\x01\n\x0evariable_price\x18\x02 \x01(\x0b\x32{.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.UpdateDirectPurchasePriceEvent.PricingScheduleH\x00\x12\x18\n\x0bpublic_note\x18\x03 \x01(\tH\x01\x88\x01\x01\x1a\x33\n\x10PriceForQuantity\x12\x10\n\x08quantity\x18\x01 \x01(\x04\x12\r\n\x05price\x18\x02 \x01(\x04\x1a\xac\x01\n\x0fPricingSchedule\x12\x98\x01\n\x12price_for_quantity\x18\x01 \x03(\x0b\x32|.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.UpdateDirectPurchasePriceEvent.PriceForQuantityB\x07\n\x05priceB\x0e\n\x0c_public_note\x1a\xfc\x02\n\x10GroupActionEvent\x12n\n\x0btoken_event\x18\x01 \x01(\x0b\x32W.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.TokenEventH\x00\x12t\n\x0e\x64ocument_event\x18\x02 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.DocumentEventH\x00\x12t\n\x0e\x63ontract_event\x18\x03 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.ContractEventH\x00\x42\x0c\n\nevent_type\x1a\x8b\x01\n\rDocumentEvent\x12r\n\x06\x63reate\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.DocumentCreateEventH\x00\x42\x06\n\x04type\x1a/\n\x13\x44ocumentCreateEvent\x12\x18\n\x10\x63reated_document\x18\x01 \x01(\x0c\x1a/\n\x13\x43ontractUpdateEvent\x12\x18\n\x10updated_contract\x18\x01 \x01(\x0c\x1a\x8b\x01\n\rContractEvent\x12r\n\x06update\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.ContractUpdateEventH\x00\x42\x06\n\x04type\x1a\xd1\x07\n\nTokenEvent\x12\x66\n\x04mint\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.MintEventH\x00\x12\x66\n\x04\x62urn\x18\x02 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.BurnEventH\x00\x12j\n\x06\x66reeze\x18\x03 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.FreezeEventH\x00\x12n\n\x08unfreeze\x18\x04 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.UnfreezeEventH\x00\x12\x84\x01\n\x14\x64\x65stroy_frozen_funds\x18\x05 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.DestroyFrozenFundsEventH\x00\x12}\n\x10\x65mergency_action\x18\x06 \x01(\x0b\x32\x61.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.EmergencyActionEventH\x00\x12\x82\x01\n\x13token_config_update\x18\x07 \x01(\x0b\x32\x63.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.TokenConfigUpdateEventH\x00\x12\x83\x01\n\x0cupdate_price\x18\x08 \x01(\x0b\x32k.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.UpdateDirectPurchasePriceEventH\x00\x42\x06\n\x04type\x1a\x93\x01\n\x10GroupActionEntry\x12\x11\n\taction_id\x18\x01 \x01(\x0c\x12l\n\x05\x65vent\x18\x02 \x01(\x0b\x32].org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.GroupActionEvent\x1a\x84\x01\n\x0cGroupActions\x12t\n\rgroup_actions\x18\x01 \x03(\x0b\x32].org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.GroupActionEntryB\x08\n\x06resultB\t\n\x07version\"\x88\x03\n\x1cGetGroupActionSignersRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetGroupActionSignersRequest.GetGroupActionSignersRequestV0H\x00\x1a\xce\x01\n\x1eGetGroupActionSignersRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1f\n\x17group_contract_position\x18\x02 \x01(\r\x12T\n\x06status\x18\x03 \x01(\x0e\x32\x44.org.dash.platform.dapi.v0.GetGroupActionSignersRequest.ActionStatus\x12\x11\n\taction_id\x18\x04 \x01(\x0c\x12\r\n\x05prove\x18\x05 \x01(\x08\"&\n\x0c\x41\x63tionStatus\x12\n\n\x06\x41\x43TIVE\x10\x00\x12\n\n\x06\x43LOSED\x10\x01\x42\t\n\x07version\"\x8b\x05\n\x1dGetGroupActionSignersResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetGroupActionSignersResponse.GetGroupActionSignersResponseV0H\x00\x1a\xf6\x03\n\x1fGetGroupActionSignersResponseV0\x12\x8b\x01\n\x14group_action_signers\x18\x01 \x01(\x0b\x32k.org.dash.platform.dapi.v0.GetGroupActionSignersResponse.GetGroupActionSignersResponseV0.GroupActionSignersH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x35\n\x11GroupActionSigner\x12\x11\n\tsigner_id\x18\x01 \x01(\x0c\x12\r\n\x05power\x18\x02 \x01(\r\x1a\x91\x01\n\x12GroupActionSigners\x12{\n\x07signers\x18\x01 \x03(\x0b\x32j.org.dash.platform.dapi.v0.GetGroupActionSignersResponse.GetGroupActionSignersResponseV0.GroupActionSignerB\x08\n\x06resultB\t\n\x07version\"\xb5\x01\n\x15GetAddressInfoRequest\x12V\n\x02v0\x18\x01 \x01(\x0b\x32H.org.dash.platform.dapi.v0.GetAddressInfoRequest.GetAddressInfoRequestV0H\x00\x1a\x39\n\x17GetAddressInfoRequestV0\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x85\x01\n\x10\x41\x64\x64ressInfoEntry\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12J\n\x11\x62\x61lance_and_nonce\x18\x02 \x01(\x0b\x32*.org.dash.platform.dapi.v0.BalanceAndNonceH\x00\x88\x01\x01\x42\x14\n\x12_balance_and_nonce\"1\n\x0f\x42\x61lanceAndNonce\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\x12\r\n\x05nonce\x18\x02 \x01(\r\"_\n\x12\x41\x64\x64ressInfoEntries\x12I\n\x14\x61\x64\x64ress_info_entries\x18\x01 \x03(\x0b\x32+.org.dash.platform.dapi.v0.AddressInfoEntry\"m\n\x14\x41\x64\x64ressBalanceChange\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x19\n\x0bset_balance\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x12\x1c\n\x0e\x61\x64\x64_to_balance\x18\x03 \x01(\x04\x42\x02\x30\x01H\x00\x42\x0b\n\toperation\"x\n\x1a\x42lockAddressBalanceChanges\x12\x18\n\x0c\x62lock_height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12@\n\x07\x63hanges\x18\x02 \x03(\x0b\x32/.org.dash.platform.dapi.v0.AddressBalanceChange\"k\n\x1b\x41\x64\x64ressBalanceUpdateEntries\x12L\n\rblock_changes\x18\x01 \x03(\x0b\x32\x35.org.dash.platform.dapi.v0.BlockAddressBalanceChanges\"\xe1\x02\n\x16GetAddressInfoResponse\x12X\n\x02v0\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetAddressInfoResponse.GetAddressInfoResponseV0H\x00\x1a\xe1\x01\n\x18GetAddressInfoResponseV0\x12I\n\x12\x61\x64\x64ress_info_entry\x18\x01 \x01(\x0b\x32+.org.dash.platform.dapi.v0.AddressInfoEntryH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xc3\x01\n\x18GetAddressesInfosRequest\x12\\\n\x02v0\x18\x01 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetAddressesInfosRequest.GetAddressesInfosRequestV0H\x00\x1a>\n\x1aGetAddressesInfosRequestV0\x12\x11\n\taddresses\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xf1\x02\n\x19GetAddressesInfosResponse\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetAddressesInfosResponse.GetAddressesInfosResponseV0H\x00\x1a\xe8\x01\n\x1bGetAddressesInfosResponseV0\x12M\n\x14\x61\x64\x64ress_info_entries\x18\x01 \x01(\x0b\x32-.org.dash.platform.dapi.v0.AddressInfoEntriesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xb5\x01\n\x1dGetAddressesTrunkStateRequest\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetAddressesTrunkStateRequest.GetAddressesTrunkStateRequestV0H\x00\x1a!\n\x1fGetAddressesTrunkStateRequestV0B\t\n\x07version\"\xaa\x02\n\x1eGetAddressesTrunkStateResponse\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetAddressesTrunkStateResponse.GetAddressesTrunkStateResponseV0H\x00\x1a\x92\x01\n GetAddressesTrunkStateResponseV0\x12/\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.Proof\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\t\n\x07version\"\xf0\x01\n\x1eGetAddressesBranchStateRequest\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetAddressesBranchStateRequest.GetAddressesBranchStateRequestV0H\x00\x1aY\n GetAddressesBranchStateRequestV0\x12\x0b\n\x03key\x18\x01 \x01(\x0c\x12\r\n\x05\x64\x65pth\x18\x02 \x01(\r\x12\x19\n\x11\x63heckpoint_height\x18\x03 \x01(\x04\x42\t\n\x07version\"\xd1\x01\n\x1fGetAddressesBranchStateResponse\x12j\n\x02v0\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetAddressesBranchStateResponse.GetAddressesBranchStateResponseV0H\x00\x1a\x37\n!GetAddressesBranchStateResponseV0\x12\x12\n\nmerk_proof\x18\x02 \x01(\x0c\x42\t\n\x07version\"\x9e\x02\n%GetRecentAddressBalanceChangesRequest\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetRecentAddressBalanceChangesRequest.GetRecentAddressBalanceChangesRequestV0H\x00\x1ar\n\'GetRecentAddressBalanceChangesRequestV0\x12\x18\n\x0cstart_height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\r\n\x05prove\x18\x02 \x01(\x08\x12\x1e\n\x16start_height_exclusive\x18\x03 \x01(\x08\x42\t\n\x07version\"\xb8\x03\n&GetRecentAddressBalanceChangesResponse\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetRecentAddressBalanceChangesResponse.GetRecentAddressBalanceChangesResponseV0H\x00\x1a\x88\x02\n(GetRecentAddressBalanceChangesResponseV0\x12`\n\x1e\x61\x64\x64ress_balance_update_entries\x18\x01 \x01(\x0b\x32\x36.org.dash.platform.dapi.v0.AddressBalanceUpdateEntriesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"G\n\x16\x42lockHeightCreditEntry\x12\x18\n\x0c\x62lock_height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x13\n\x07\x63redits\x18\x02 \x01(\x04\x42\x02\x30\x01\"\xb0\x01\n\x1d\x43ompactedAddressBalanceChange\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x19\n\x0bset_credits\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x12V\n\x19\x61\x64\x64_to_credits_operations\x18\x03 \x01(\x0b\x32\x31.org.dash.platform.dapi.v0.AddToCreditsOperationsH\x00\x42\x0b\n\toperation\"\\\n\x16\x41\x64\x64ToCreditsOperations\x12\x42\n\x07\x65ntries\x18\x01 \x03(\x0b\x32\x31.org.dash.platform.dapi.v0.BlockHeightCreditEntry\"\xae\x01\n#CompactedBlockAddressBalanceChanges\x12\x1e\n\x12start_block_height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x1c\n\x10\x65nd_block_height\x18\x02 \x01(\x04\x42\x02\x30\x01\x12I\n\x07\x63hanges\x18\x03 \x03(\x0b\x32\x38.org.dash.platform.dapi.v0.CompactedAddressBalanceChange\"\x87\x01\n$CompactedAddressBalanceUpdateEntries\x12_\n\x17\x63ompacted_block_changes\x18\x01 \x03(\x0b\x32>.org.dash.platform.dapi.v0.CompactedBlockAddressBalanceChanges\"\xa9\x02\n.GetRecentCompactedAddressBalanceChangesRequest\x12\x88\x01\n\x02v0\x18\x01 \x01(\x0b\x32z.org.dash.platform.dapi.v0.GetRecentCompactedAddressBalanceChangesRequest.GetRecentCompactedAddressBalanceChangesRequestV0H\x00\x1a\x61\n0GetRecentCompactedAddressBalanceChangesRequestV0\x12\x1e\n\x12start_block_height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xf0\x03\n/GetRecentCompactedAddressBalanceChangesResponse\x12\x8a\x01\n\x02v0\x18\x01 \x01(\x0b\x32|.org.dash.platform.dapi.v0.GetRecentCompactedAddressBalanceChangesResponse.GetRecentCompactedAddressBalanceChangesResponseV0H\x00\x1a\xa4\x02\n1GetRecentCompactedAddressBalanceChangesResponseV0\x12s\n(compacted_address_balance_update_entries\x18\x01 \x01(\x0b\x32?.org.dash.platform.dapi.v0.CompactedAddressBalanceUpdateEntriesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xf4\x01\n GetShieldedEncryptedNotesRequest\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetShieldedEncryptedNotesRequest.GetShieldedEncryptedNotesRequestV0H\x00\x1aW\n\"GetShieldedEncryptedNotesRequestV0\x12\x13\n\x0bstart_index\x18\x01 \x01(\x04\x12\r\n\x05\x63ount\x18\x02 \x01(\r\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xac\x05\n!GetShieldedEncryptedNotesResponse\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetShieldedEncryptedNotesResponse.GetShieldedEncryptedNotesResponseV0H\x00\x1a\x8b\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\x1aG\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\x1a\x91\x01\n\x0e\x45ncryptedNotes\x12\x7f\n\x07\x65ntries\x18\x01 \x03(\x0b\x32n.org.dash.platform.dapi.v0.GetShieldedEncryptedNotesResponse.GetShieldedEncryptedNotesResponseV0.EncryptedNoteB\x08\n\x06resultB\t\n\x07version\"\xb4\x01\n\x19GetShieldedAnchorsRequest\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetShieldedAnchorsRequest.GetShieldedAnchorsRequestV0H\x00\x1a,\n\x1bGetShieldedAnchorsRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x42\t\n\x07version\"\xb1\x03\n\x1aGetShieldedAnchorsResponse\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetShieldedAnchorsResponse.GetShieldedAnchorsResponseV0H\x00\x1a\xa5\x02\n\x1cGetShieldedAnchorsResponseV0\x12m\n\x07\x61nchors\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetShieldedAnchorsResponse.GetShieldedAnchorsResponseV0.AnchorsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1a\n\x07\x41nchors\x12\x0f\n\x07\x61nchors\x18\x01 \x03(\x0c\x42\x08\n\x06resultB\t\n\x07version\"\xd8\x01\n\"GetMostRecentShieldedAnchorRequest\x12p\n\x02v0\x18\x01 \x01(\x0b\x32\x62.org.dash.platform.dapi.v0.GetMostRecentShieldedAnchorRequest.GetMostRecentShieldedAnchorRequestV0H\x00\x1a\x35\n$GetMostRecentShieldedAnchorRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x42\t\n\x07version\"\xdc\x02\n#GetMostRecentShieldedAnchorResponse\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetMostRecentShieldedAnchorResponse.GetMostRecentShieldedAnchorResponseV0H\x00\x1a\xb5\x01\n%GetMostRecentShieldedAnchorResponseV0\x12\x10\n\x06\x61nchor\x18\x01 \x01(\x0cH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xbc\x01\n\x1bGetShieldedPoolStateRequest\x12\x62\n\x02v0\x18\x01 \x01(\x0b\x32T.org.dash.platform.dapi.v0.GetShieldedPoolStateRequest.GetShieldedPoolStateRequestV0H\x00\x1a.\n\x1dGetShieldedPoolStateRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x42\t\n\x07version\"\xcb\x02\n\x1cGetShieldedPoolStateResponse\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetShieldedPoolStateResponse.GetShieldedPoolStateResponseV0H\x00\x1a\xb9\x01\n\x1eGetShieldedPoolStateResponseV0\x12\x1b\n\rtotal_balance\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xd4\x01\n\x1cGetShieldedNullifiersRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetShieldedNullifiersRequest.GetShieldedNullifiersRequestV0H\x00\x1a\x43\n\x1eGetShieldedNullifiersRequestV0\x12\x12\n\nnullifiers\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x86\x05\n\x1dGetShieldedNullifiersResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetShieldedNullifiersResponse.GetShieldedNullifiersResponseV0H\x00\x1a\xf1\x03\n\x1fGetShieldedNullifiersResponseV0\x12\x88\x01\n\x12nullifier_statuses\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetShieldedNullifiersResponse.GetShieldedNullifiersResponseV0.NullifierStatusesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x36\n\x0fNullifierStatus\x12\x11\n\tnullifier\x18\x01 \x01(\x0c\x12\x10\n\x08is_spent\x18\x02 \x01(\x08\x1a\x8e\x01\n\x11NullifierStatuses\x12y\n\x07\x65ntries\x18\x01 \x03(\x0b\x32h.org.dash.platform.dapi.v0.GetShieldedNullifiersResponse.GetShieldedNullifiersResponseV0.NullifierStatusB\x08\n\x06resultB\t\n\x07version\"\xe5\x01\n\x1eGetNullifiersTrunkStateRequest\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetNullifiersTrunkStateRequest.GetNullifiersTrunkStateRequestV0H\x00\x1aN\n GetNullifiersTrunkStateRequestV0\x12\x11\n\tpool_type\x18\x01 \x01(\r\x12\x17\n\x0fpool_identifier\x18\x02 \x01(\x0c\x42\t\n\x07version\"\xae\x02\n\x1fGetNullifiersTrunkStateResponse\x12j\n\x02v0\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetNullifiersTrunkStateResponse.GetNullifiersTrunkStateResponseV0H\x00\x1a\x93\x01\n!GetNullifiersTrunkStateResponseV0\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\"\xa1\x02\n\x1fGetNullifiersBranchStateRequest\x12j\n\x02v0\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetNullifiersBranchStateRequest.GetNullifiersBranchStateRequestV0H\x00\x1a\x86\x01\n!GetNullifiersBranchStateRequestV0\x12\x11\n\tpool_type\x18\x01 \x01(\r\x12\x17\n\x0fpool_identifier\x18\x02 \x01(\x0c\x12\x0b\n\x03key\x18\x03 \x01(\x0c\x12\r\n\x05\x64\x65pth\x18\x04 \x01(\r\x12\x19\n\x11\x63heckpoint_height\x18\x05 \x01(\x04\x42\t\n\x07version\"\xd5\x01\n GetNullifiersBranchStateResponse\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetNullifiersBranchStateResponse.GetNullifiersBranchStateResponseV0H\x00\x1a\x38\n\"GetNullifiersBranchStateResponseV0\x12\x12\n\nmerk_proof\x18\x02 \x01(\x0c\x42\t\n\x07version\"E\n\x15\x42lockNullifierChanges\x12\x18\n\x0c\x62lock_height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x12\n\nnullifiers\x18\x02 \x03(\x0c\"a\n\x16NullifierUpdateEntries\x12G\n\rblock_changes\x18\x01 \x03(\x0b\x32\x30.org.dash.platform.dapi.v0.BlockNullifierChanges\"\xea\x01\n GetRecentNullifierChangesRequest\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetRecentNullifierChangesRequest.GetRecentNullifierChangesRequestV0H\x00\x1aM\n\"GetRecentNullifierChangesRequestV0\x12\x18\n\x0cstart_height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x99\x03\n!GetRecentNullifierChangesResponse\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetRecentNullifierChangesResponse.GetRecentNullifierChangesResponseV0H\x00\x1a\xf8\x01\n#GetRecentNullifierChangesResponseV0\x12U\n\x18nullifier_update_entries\x18\x01 \x01(\x0b\x32\x31.org.dash.platform.dapi.v0.NullifierUpdateEntriesH\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\x1e\x43ompactedBlockNullifierChanges\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\x12\x12\n\nnullifiers\x18\x03 \x03(\x0c\"}\n\x1f\x43ompactedNullifierUpdateEntries\x12Z\n\x17\x63ompacted_block_changes\x18\x01 \x03(\x0b\x32\x39.org.dash.platform.dapi.v0.CompactedBlockNullifierChanges\"\x94\x02\n)GetRecentCompactedNullifierChangesRequest\x12~\n\x02v0\x18\x01 \x01(\x0b\x32p.org.dash.platform.dapi.v0.GetRecentCompactedNullifierChangesRequest.GetRecentCompactedNullifierChangesRequestV0H\x00\x1a\\\n+GetRecentCompactedNullifierChangesRequestV0\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\"\xd1\x03\n*GetRecentCompactedNullifierChangesResponse\x12\x80\x01\n\x02v0\x18\x01 \x01(\x0b\x32r.org.dash.platform.dapi.v0.GetRecentCompactedNullifierChangesResponse.GetRecentCompactedNullifierChangesResponseV0H\x00\x1a\x94\x02\n,GetRecentCompactedNullifierChangesResponseV0\x12h\n\"compacted_nullifier_update_entries\x18\x01 \x01(\x0b\x32:.org.dash.platform.dapi.v0.CompactedNullifierUpdateEntriesH\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*Z\n\nKeyPurpose\x12\x12\n\x0e\x41UTHENTICATION\x10\x00\x12\x0e\n\nENCRYPTION\x10\x01\x12\x0e\n\nDECRYPTION\x10\x02\x12\x0c\n\x08TRANSFER\x10\x03\x12\n\n\x06VOTING\x10\x05\x32\xb3H\n\x08Platform\x12\x93\x01\n\x18\x62roadcastStateTransition\x12:.org.dash.platform.dapi.v0.BroadcastStateTransitionRequest\x1a;.org.dash.platform.dapi.v0.BroadcastStateTransitionResponse\x12l\n\x0bgetIdentity\x12-.org.dash.platform.dapi.v0.GetIdentityRequest\x1a..org.dash.platform.dapi.v0.GetIdentityResponse\x12x\n\x0fgetIdentityKeys\x12\x31.org.dash.platform.dapi.v0.GetIdentityKeysRequest\x1a\x32.org.dash.platform.dapi.v0.GetIdentityKeysResponse\x12\x96\x01\n\x19getIdentitiesContractKeys\x12;.org.dash.platform.dapi.v0.GetIdentitiesContractKeysRequest\x1a<.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse\x12{\n\x10getIdentityNonce\x12\x32.org.dash.platform.dapi.v0.GetIdentityNonceRequest\x1a\x33.org.dash.platform.dapi.v0.GetIdentityNonceResponse\x12\x93\x01\n\x18getIdentityContractNonce\x12:.org.dash.platform.dapi.v0.GetIdentityContractNonceRequest\x1a;.org.dash.platform.dapi.v0.GetIdentityContractNonceResponse\x12\x81\x01\n\x12getIdentityBalance\x12\x34.org.dash.platform.dapi.v0.GetIdentityBalanceRequest\x1a\x35.org.dash.platform.dapi.v0.GetIdentityBalanceResponse\x12\x8a\x01\n\x15getIdentitiesBalances\x12\x37.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest\x1a\x38.org.dash.platform.dapi.v0.GetIdentitiesBalancesResponse\x12\xa2\x01\n\x1dgetIdentityBalanceAndRevision\x12?.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionRequest\x1a@.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionResponse\x12\xaf\x01\n#getEvonodesProposedEpochBlocksByIds\x12\x45.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByIdsRequest\x1a\x41.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksResponse\x12\xb3\x01\n%getEvonodesProposedEpochBlocksByRange\x12G.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByRangeRequest\x1a\x41.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksResponse\x12x\n\x0fgetDataContract\x12\x31.org.dash.platform.dapi.v0.GetDataContractRequest\x1a\x32.org.dash.platform.dapi.v0.GetDataContractResponse\x12\x8d\x01\n\x16getDataContractHistory\x12\x38.org.dash.platform.dapi.v0.GetDataContractHistoryRequest\x1a\x39.org.dash.platform.dapi.v0.GetDataContractHistoryResponse\x12{\n\x10getDataContracts\x12\x32.org.dash.platform.dapi.v0.GetDataContractsRequest\x1a\x33.org.dash.platform.dapi.v0.GetDataContractsResponse\x12o\n\x0cgetDocuments\x12..org.dash.platform.dapi.v0.GetDocumentsRequest\x1a/.org.dash.platform.dapi.v0.GetDocumentsResponse\x12~\n\x11getDocumentsCount\x12\x33.org.dash.platform.dapi.v0.GetDocumentsCountRequest\x1a\x34.org.dash.platform.dapi.v0.GetDocumentsCountResponse\x12\x99\x01\n\x1agetIdentityByPublicKeyHash\x12<.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashRequest\x1a=.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashResponse\x12\xb4\x01\n#getIdentityByNonUniquePublicKeyHash\x12\x45.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashRequest\x1a\x46.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashResponse\x12\x9f\x01\n\x1cwaitForStateTransitionResult\x12>.org.dash.platform.dapi.v0.WaitForStateTransitionResultRequest\x1a?.org.dash.platform.dapi.v0.WaitForStateTransitionResultResponse\x12\x81\x01\n\x12getConsensusParams\x12\x34.org.dash.platform.dapi.v0.GetConsensusParamsRequest\x1a\x35.org.dash.platform.dapi.v0.GetConsensusParamsResponse\x12\xa5\x01\n\x1egetProtocolVersionUpgradeState\x12@.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateRequest\x1a\x41.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateResponse\x12\xb4\x01\n#getProtocolVersionUpgradeVoteStatus\x12\x45.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusRequest\x1a\x46.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusResponse\x12r\n\rgetEpochsInfo\x12/.org.dash.platform.dapi.v0.GetEpochsInfoRequest\x1a\x30.org.dash.platform.dapi.v0.GetEpochsInfoResponse\x12\x8d\x01\n\x16getFinalizedEpochInfos\x12\x38.org.dash.platform.dapi.v0.GetFinalizedEpochInfosRequest\x1a\x39.org.dash.platform.dapi.v0.GetFinalizedEpochInfosResponse\x12\x8a\x01\n\x15getContestedResources\x12\x37.org.dash.platform.dapi.v0.GetContestedResourcesRequest\x1a\x38.org.dash.platform.dapi.v0.GetContestedResourcesResponse\x12\xa2\x01\n\x1dgetContestedResourceVoteState\x12?.org.dash.platform.dapi.v0.GetContestedResourceVoteStateRequest\x1a@.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse\x12\xba\x01\n%getContestedResourceVotersForIdentity\x12G.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityRequest\x1aH.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityResponse\x12\xae\x01\n!getContestedResourceIdentityVotes\x12\x43.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesRequest\x1a\x44.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse\x12\x8a\x01\n\x15getVotePollsByEndDate\x12\x37.org.dash.platform.dapi.v0.GetVotePollsByEndDateRequest\x1a\x38.org.dash.platform.dapi.v0.GetVotePollsByEndDateResponse\x12\xa5\x01\n\x1egetPrefundedSpecializedBalance\x12@.org.dash.platform.dapi.v0.GetPrefundedSpecializedBalanceRequest\x1a\x41.org.dash.platform.dapi.v0.GetPrefundedSpecializedBalanceResponse\x12\x96\x01\n\x19getTotalCreditsInPlatform\x12;.org.dash.platform.dapi.v0.GetTotalCreditsInPlatformRequest\x1a<.org.dash.platform.dapi.v0.GetTotalCreditsInPlatformResponse\x12x\n\x0fgetPathElements\x12\x31.org.dash.platform.dapi.v0.GetPathElementsRequest\x1a\x32.org.dash.platform.dapi.v0.GetPathElementsResponse\x12\x66\n\tgetStatus\x12+.org.dash.platform.dapi.v0.GetStatusRequest\x1a,.org.dash.platform.dapi.v0.GetStatusResponse\x12\x8a\x01\n\x15getCurrentQuorumsInfo\x12\x37.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest\x1a\x38.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse\x12\x93\x01\n\x18getIdentityTokenBalances\x12:.org.dash.platform.dapi.v0.GetIdentityTokenBalancesRequest\x1a;.org.dash.platform.dapi.v0.GetIdentityTokenBalancesResponse\x12\x99\x01\n\x1agetIdentitiesTokenBalances\x12<.org.dash.platform.dapi.v0.GetIdentitiesTokenBalancesRequest\x1a=.org.dash.platform.dapi.v0.GetIdentitiesTokenBalancesResponse\x12\x8a\x01\n\x15getIdentityTokenInfos\x12\x37.org.dash.platform.dapi.v0.GetIdentityTokenInfosRequest\x1a\x38.org.dash.platform.dapi.v0.GetIdentityTokenInfosResponse\x12\x90\x01\n\x17getIdentitiesTokenInfos\x12\x39.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosRequest\x1a:.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosResponse\x12{\n\x10getTokenStatuses\x12\x32.org.dash.platform.dapi.v0.GetTokenStatusesRequest\x1a\x33.org.dash.platform.dapi.v0.GetTokenStatusesResponse\x12\x9f\x01\n\x1cgetTokenDirectPurchasePrices\x12>.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesRequest\x1a?.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesResponse\x12\x87\x01\n\x14getTokenContractInfo\x12\x36.org.dash.platform.dapi.v0.GetTokenContractInfoRequest\x1a\x37.org.dash.platform.dapi.v0.GetTokenContractInfoResponse\x12\xb1\x01\n\"getTokenPreProgrammedDistributions\x12\x44.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsRequest\x1a\x45.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsResponse\x12\xbd\x01\n&getTokenPerpetualDistributionLastClaim\x12H.org.dash.platform.dapi.v0.GetTokenPerpetualDistributionLastClaimRequest\x1aI.org.dash.platform.dapi.v0.GetTokenPerpetualDistributionLastClaimResponse\x12\x84\x01\n\x13getTokenTotalSupply\x12\x35.org.dash.platform.dapi.v0.GetTokenTotalSupplyRequest\x1a\x36.org.dash.platform.dapi.v0.GetTokenTotalSupplyResponse\x12o\n\x0cgetGroupInfo\x12..org.dash.platform.dapi.v0.GetGroupInfoRequest\x1a/.org.dash.platform.dapi.v0.GetGroupInfoResponse\x12r\n\rgetGroupInfos\x12/.org.dash.platform.dapi.v0.GetGroupInfosRequest\x1a\x30.org.dash.platform.dapi.v0.GetGroupInfosResponse\x12x\n\x0fgetGroupActions\x12\x31.org.dash.platform.dapi.v0.GetGroupActionsRequest\x1a\x32.org.dash.platform.dapi.v0.GetGroupActionsResponse\x12\x8a\x01\n\x15getGroupActionSigners\x12\x37.org.dash.platform.dapi.v0.GetGroupActionSignersRequest\x1a\x38.org.dash.platform.dapi.v0.GetGroupActionSignersResponse\x12u\n\x0egetAddressInfo\x12\x30.org.dash.platform.dapi.v0.GetAddressInfoRequest\x1a\x31.org.dash.platform.dapi.v0.GetAddressInfoResponse\x12~\n\x11getAddressesInfos\x12\x33.org.dash.platform.dapi.v0.GetAddressesInfosRequest\x1a\x34.org.dash.platform.dapi.v0.GetAddressesInfosResponse\x12\x8d\x01\n\x16getAddressesTrunkState\x12\x38.org.dash.platform.dapi.v0.GetAddressesTrunkStateRequest\x1a\x39.org.dash.platform.dapi.v0.GetAddressesTrunkStateResponse\x12\x90\x01\n\x17getAddressesBranchState\x12\x39.org.dash.platform.dapi.v0.GetAddressesBranchStateRequest\x1a:.org.dash.platform.dapi.v0.GetAddressesBranchStateResponse\x12\xa5\x01\n\x1egetRecentAddressBalanceChanges\x12@.org.dash.platform.dapi.v0.GetRecentAddressBalanceChangesRequest\x1a\x41.org.dash.platform.dapi.v0.GetRecentAddressBalanceChangesResponse\x12\xc0\x01\n\'getRecentCompactedAddressBalanceChanges\x12I.org.dash.platform.dapi.v0.GetRecentCompactedAddressBalanceChangesRequest\x1aJ.org.dash.platform.dapi.v0.GetRecentCompactedAddressBalanceChangesResponse\x12\x96\x01\n\x19getShieldedEncryptedNotes\x12;.org.dash.platform.dapi.v0.GetShieldedEncryptedNotesRequest\x1a<.org.dash.platform.dapi.v0.GetShieldedEncryptedNotesResponse\x12\x81\x01\n\x12getShieldedAnchors\x12\x34.org.dash.platform.dapi.v0.GetShieldedAnchorsRequest\x1a\x35.org.dash.platform.dapi.v0.GetShieldedAnchorsResponse\x12\x9c\x01\n\x1bgetMostRecentShieldedAnchor\x12=.org.dash.platform.dapi.v0.GetMostRecentShieldedAnchorRequest\x1a>.org.dash.platform.dapi.v0.GetMostRecentShieldedAnchorResponse\x12\x87\x01\n\x14getShieldedPoolState\x12\x36.org.dash.platform.dapi.v0.GetShieldedPoolStateRequest\x1a\x37.org.dash.platform.dapi.v0.GetShieldedPoolStateResponse\x12\x8a\x01\n\x15getShieldedNullifiers\x12\x37.org.dash.platform.dapi.v0.GetShieldedNullifiersRequest\x1a\x38.org.dash.platform.dapi.v0.GetShieldedNullifiersResponse\x12\x90\x01\n\x17getNullifiersTrunkState\x12\x39.org.dash.platform.dapi.v0.GetNullifiersTrunkStateRequest\x1a:.org.dash.platform.dapi.v0.GetNullifiersTrunkStateResponse\x12\x93\x01\n\x18getNullifiersBranchState\x12:.org.dash.platform.dapi.v0.GetNullifiersBranchStateRequest\x1a;.org.dash.platform.dapi.v0.GetNullifiersBranchStateResponse\x12\x96\x01\n\x19getRecentNullifierChanges\x12;.org.dash.platform.dapi.v0.GetRecentNullifierChangesRequest\x1a<.org.dash.platform.dapi.v0.GetRecentNullifierChangesResponse\x12\xb1\x01\n\"getRecentCompactedNullifierChanges\x12\x44.org.dash.platform.dapi.v0.GetRecentCompactedNullifierChangesRequest\x1a\x45.org.dash.platform.dapi.v0.GetRecentCompactedNullifierChangesResponseb\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=63695, - serialized_end=63785, + serialized_start=63326, + serialized_end=63416, ) _sym_db.RegisterEnumDescriptor(_KEYPURPOSE) @@ -125,8 +125,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=24104, - serialized_end=24177, + serialized_start=23735, + serialized_end=23808, ) _sym_db.RegisterEnumDescriptor(_GETCONTESTEDRESOURCEVOTESTATEREQUEST_GETCONTESTEDRESOURCEVOTESTATEREQUESTV0_RESULTTYPE) @@ -155,8 +155,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=25099, - serialized_end=25178, + serialized_start=24730, + serialized_end=24809, ) _sym_db.RegisterEnumDescriptor(_GETCONTESTEDRESOURCEVOTESTATERESPONSE_GETCONTESTEDRESOURCEVOTESTATERESPONSEV0_FINISHEDVOTEINFO_FINISHEDVOTEOUTCOME) @@ -185,8 +185,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=28807, - serialized_end=28868, + serialized_start=28438, + serialized_end=28499, ) _sym_db.RegisterEnumDescriptor(_GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSE_GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSEV0_RESOURCEVOTECHOICE_VOTECHOICETYPE) @@ -210,8 +210,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=47432, - serialized_end=47470, + serialized_start=47063, + serialized_end=47101, ) _sym_db.RegisterEnumDescriptor(_GETGROUPACTIONSREQUEST_ACTIONSTATUS) @@ -235,8 +235,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=48717, - serialized_end=48752, + serialized_start=48348, + serialized_end=48383, ) _sym_db.RegisterEnumDescriptor(_GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_EMERGENCYACTIONEVENT_ACTIONTYPE) @@ -260,8 +260,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=47432, - serialized_end=47470, + serialized_start=47063, + serialized_end=47101, ) _sym_db.RegisterEnumDescriptor(_GETGROUPACTIONSIGNERSREQUEST_ACTIONSTATUS) @@ -3621,91 +3621,30 @@ 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.GetDocumentsCountRequest.GetDocumentsCountRequestV0.prove', index=3, + name='return_distinct_counts_in_range', full_name='org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0.return_distinct_counts_in_range', index=3, number=4, 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), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=11735, - serialized_end=11842, -) - -_GETDOCUMENTSCOUNTREQUEST = _descriptor.Descriptor( - name='GetDocumentsCountRequest', - full_name='org.dash.platform.dapi.v0.GetDocumentsCountRequest', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ _descriptor.FieldDescriptor( - name='v0', full_name='org.dash.platform.dapi.v0.GetDocumentsCountRequest.v0', index=0, - number=1, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, + name='order_by', full_name='org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0.order_by', index=4, + number=5, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=b"", message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[_GETDOCUMENTSCOUNTREQUEST_GETDOCUMENTSCOUNTREQUESTV0, ], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - _descriptor.OneofDescriptor( - name='version', full_name='org.dash.platform.dapi.v0.GetDocumentsCountRequest.version', - index=0, containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[]), - ], - serialized_start=11613, - serialized_end=11853, -) - - -_GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0 = _descriptor.Descriptor( - name='GetDocumentsCountResponseV0', - full_name='org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ _descriptor.FieldDescriptor( - name='count', full_name='org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.count', index=0, - number=1, type=4, cpp_type=4, label=1, + name='limit', full_name='org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0.limit', index=5, + number=6, type=13, cpp_type=3, 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='proof', full_name='org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.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.GetDocumentsCountResponse.GetDocumentsCountResponseV0.metadata', index=2, - number=3, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, + name='prove', full_name='org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0.prove', index=6, + number=7, 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), @@ -3721,25 +3660,25 @@ extension_ranges=[], oneofs=[ _descriptor.OneofDescriptor( - name='result', full_name='org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.result', + name='_limit', full_name='org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0._limit', index=0, containing_type=None, create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=11982, - serialized_end=12152, + serialized_start=11736, + serialized_end=11932, ) -_GETDOCUMENTSCOUNTRESPONSE = _descriptor.Descriptor( - name='GetDocumentsCountResponse', - full_name='org.dash.platform.dapi.v0.GetDocumentsCountResponse', +_GETDOCUMENTSCOUNTREQUEST = _descriptor.Descriptor( + name='GetDocumentsCountRequest', + full_name='org.dash.platform.dapi.v0.GetDocumentsCountRequest', filename=None, file=DESCRIPTOR, containing_type=None, create_key=_descriptor._internal_create_key, fields=[ _descriptor.FieldDescriptor( - name='v0', full_name='org.dash.platform.dapi.v0.GetDocumentsCountResponse.v0', index=0, + name='v0', full_name='org.dash.platform.dapi.v0.GetDocumentsCountRequest.v0', 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, @@ -3748,7 +3687,7 @@ ], extensions=[ ], - nested_types=[_GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0, ], + nested_types=[_GETDOCUMENTSCOUNTREQUEST_GETDOCUMENTSCOUNTREQUESTV0, ], enum_types=[ ], serialized_options=None, @@ -3757,59 +3696,45 @@ extension_ranges=[], oneofs=[ _descriptor.OneofDescriptor( - name='version', full_name='org.dash.platform.dapi.v0.GetDocumentsCountResponse.version', + name='version', full_name='org.dash.platform.dapi.v0.GetDocumentsCountRequest.version', index=0, containing_type=None, create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=11856, - serialized_end=12163, + serialized_start=11613, + serialized_end=11943, ) -_GETDOCUMENTSSPLITCOUNTREQUEST_GETDOCUMENTSSPLITCOUNTREQUESTV0 = _descriptor.Descriptor( - name='GetDocumentsSplitCountRequestV0', - full_name='org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0', +_GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0_COUNTENTRY = _descriptor.Descriptor( + name='CountEntry', + full_name='org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry', 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.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.data_contract_id', index=0, + name='in_key', full_name='org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.in_key', 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', full_name='org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.document_type', 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='where', full_name='org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.where', index=2, - number=3, type=12, cpp_type=9, label=1, + name='key', full_name='org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.key', index=1, + number=2, 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='split_count_by_index_property', full_name='org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.split_count_by_index_property', index=3, - number=4, 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='prove', full_name='org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.prove', index=4, - number=5, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, + name='count', full_name='org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.count', index=2, + number=3, 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=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + serialized_options=b'0\001', file=DESCRIPTOR, create_key=_descriptor._internal_create_key), ], extensions=[ ], @@ -3820,68 +3745,29 @@ is_extendable=False, syntax='proto3', extension_ranges=[], - oneofs=[ - ], - serialized_start=12304, - serialized_end=12455, -) - -_GETDOCUMENTSSPLITCOUNTREQUEST = _descriptor.Descriptor( - name='GetDocumentsSplitCountRequest', - full_name='org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='v0', full_name='org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.v0', 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), - ], - extensions=[ - ], - nested_types=[_GETDOCUMENTSSPLITCOUNTREQUEST_GETDOCUMENTSSPLITCOUNTREQUESTV0, ], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], oneofs=[ _descriptor.OneofDescriptor( - name='version', full_name='org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.version', + name='_in_key', full_name='org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry._in_key', index=0, containing_type=None, create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=12166, - serialized_end=12466, + serialized_start=12330, + serialized_end=12406, ) - -_GETDOCUMENTSSPLITCOUNTRESPONSE_GETDOCUMENTSSPLITCOUNTRESPONSEV0_SPLITCOUNTENTRY = _descriptor.Descriptor( - name='SplitCountEntry', - full_name='org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry', +_GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0_COUNTENTRIES = _descriptor.Descriptor( + name='CountEntries', + full_name='org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries', filename=None, file=DESCRIPTOR, containing_type=None, create_key=_descriptor._internal_create_key, fields=[ _descriptor.FieldDescriptor( - name='key', full_name='org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.key', 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='count', full_name='org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.count', index=1, - number=2, type=4, cpp_type=4, label=1, - has_default_value=False, default_value=0, + name='entries', full_name='org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.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), @@ -3897,22 +3783,29 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12888, - serialized_end=12933, + serialized_start=12408, + serialized_end=12532, ) -_GETDOCUMENTSSPLITCOUNTRESPONSE_GETDOCUMENTSSPLITCOUNTRESPONSEV0_SPLITCOUNTS = _descriptor.Descriptor( - name='SplitCounts', - full_name='org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts', +_GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0_COUNTRESULTS = _descriptor.Descriptor( + name='CountResults', + full_name='org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults', 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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.entries', index=0, - number=1, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], + name='aggregate_count', full_name='org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.aggregate_count', 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='entries', full_name='org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.entries', 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), @@ -3927,35 +3820,40 @@ syntax='proto3', extension_ranges=[], oneofs=[ + _descriptor.OneofDescriptor( + name='variant', full_name='org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.variant', + index=0, containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[]), ], - serialized_start=12936, - serialized_end=13074, + serialized_start=12535, + serialized_end=12705, ) -_GETDOCUMENTSSPLITCOUNTRESPONSE_GETDOCUMENTSSPLITCOUNTRESPONSEV0 = _descriptor.Descriptor( - name='GetDocumentsSplitCountResponseV0', - full_name='org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0', +_GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0 = _descriptor.Descriptor( + name='GetDocumentsCountResponseV0', + full_name='org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0', filename=None, file=DESCRIPTOR, containing_type=None, create_key=_descriptor._internal_create_key, fields=[ _descriptor.FieldDescriptor( - name='split_counts', full_name='org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.split_counts', index=0, + name='counts', full_name='org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.counts', 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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.proof', index=1, + name='proof', full_name='org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.metadata', index=2, + name='metadata', full_name='org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.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, @@ -3964,7 +3862,7 @@ ], extensions=[ ], - nested_types=[_GETDOCUMENTSSPLITCOUNTRESPONSE_GETDOCUMENTSSPLITCOUNTRESPONSEV0_SPLITCOUNTENTRY, _GETDOCUMENTSSPLITCOUNTRESPONSE_GETDOCUMENTSSPLITCOUNTRESPONSEV0_SPLITCOUNTS, ], + nested_types=[_GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0_COUNTENTRY, _GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0_COUNTENTRIES, _GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0_COUNTRESULTS, ], enum_types=[ ], serialized_options=None, @@ -3973,25 +3871,25 @@ extension_ranges=[], oneofs=[ _descriptor.OneofDescriptor( - name='result', full_name='org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.result', + name='result', full_name='org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.result', index=0, containing_type=None, create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=12610, - serialized_end=13084, + serialized_start=12072, + serialized_end=12715, ) -_GETDOCUMENTSSPLITCOUNTRESPONSE = _descriptor.Descriptor( - name='GetDocumentsSplitCountResponse', - full_name='org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse', +_GETDOCUMENTSCOUNTRESPONSE = _descriptor.Descriptor( + name='GetDocumentsCountResponse', + full_name='org.dash.platform.dapi.v0.GetDocumentsCountResponse', filename=None, file=DESCRIPTOR, containing_type=None, create_key=_descriptor._internal_create_key, fields=[ _descriptor.FieldDescriptor( - name='v0', full_name='org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.v0', index=0, + name='v0', full_name='org.dash.platform.dapi.v0.GetDocumentsCountResponse.v0', 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, @@ -4000,7 +3898,7 @@ ], extensions=[ ], - nested_types=[_GETDOCUMENTSSPLITCOUNTRESPONSE_GETDOCUMENTSSPLITCOUNTRESPONSEV0, ], + nested_types=[_GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0, ], enum_types=[ ], serialized_options=None, @@ -4009,13 +3907,13 @@ extension_ranges=[], oneofs=[ _descriptor.OneofDescriptor( - name='version', full_name='org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.version', + name='version', full_name='org.dash.platform.dapi.v0.GetDocumentsCountResponse.version', index=0, containing_type=None, create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=12469, - serialized_end=13095, + serialized_start=11946, + serialized_end=12726, ) @@ -4053,8 +3951,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13247, - serialized_end=13324, + serialized_start=12878, + serialized_end=12955, ) _GETIDENTITYBYPUBLICKEYHASHREQUEST = _descriptor.Descriptor( @@ -4089,8 +3987,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=13098, - serialized_end=13335, + serialized_start=12729, + serialized_end=12966, ) @@ -4140,8 +4038,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=13491, - serialized_end=13673, + serialized_start=13122, + serialized_end=13304, ) _GETIDENTITYBYPUBLICKEYHASHRESPONSE = _descriptor.Descriptor( @@ -4176,8 +4074,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=13338, - serialized_end=13684, + serialized_start=12969, + serialized_end=13315, ) @@ -4227,8 +4125,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=13865, - serialized_end=13993, + serialized_start=13496, + serialized_end=13624, ) _GETIDENTITYBYNONUNIQUEPUBLICKEYHASHREQUEST = _descriptor.Descriptor( @@ -4263,8 +4161,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=13687, - serialized_end=14004, + serialized_start=13318, + serialized_end=13635, ) @@ -4300,8 +4198,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=14617, - serialized_end=14671, + serialized_start=14248, + serialized_end=14302, ) _GETIDENTITYBYNONUNIQUEPUBLICKEYHASHRESPONSE_GETIDENTITYBYNONUNIQUEPUBLICKEYHASHRESPONSEV0_IDENTITYPROVEDRESPONSE = _descriptor.Descriptor( @@ -4343,8 +4241,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=14674, - serialized_end=14840, + serialized_start=14305, + serialized_end=14471, ) _GETIDENTITYBYNONUNIQUEPUBLICKEYHASHRESPONSE_GETIDENTITYBYNONUNIQUEPUBLICKEYHASHRESPONSEV0 = _descriptor.Descriptor( @@ -4393,8 +4291,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=14188, - serialized_end=14850, + serialized_start=13819, + serialized_end=14481, ) _GETIDENTITYBYNONUNIQUEPUBLICKEYHASHRESPONSE = _descriptor.Descriptor( @@ -4429,8 +4327,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=14007, - serialized_end=14861, + serialized_start=13638, + serialized_end=14492, ) @@ -4468,8 +4366,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=15019, - serialized_end=15104, + serialized_start=14650, + serialized_end=14735, ) _WAITFORSTATETRANSITIONRESULTREQUEST = _descriptor.Descriptor( @@ -4504,8 +4402,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=14864, - serialized_end=15115, + serialized_start=14495, + serialized_end=14746, ) @@ -4555,8 +4453,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=15277, - serialized_end=15516, + serialized_start=14908, + serialized_end=15147, ) _WAITFORSTATETRANSITIONRESULTRESPONSE = _descriptor.Descriptor( @@ -4591,8 +4489,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=15118, - serialized_end=15527, + serialized_start=14749, + serialized_end=15158, ) @@ -4630,8 +4528,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=15655, - serialized_end=15715, + serialized_start=15286, + serialized_end=15346, ) _GETCONSENSUSPARAMSREQUEST = _descriptor.Descriptor( @@ -4666,8 +4564,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=15530, - serialized_end=15726, + serialized_start=15161, + serialized_end=15357, ) @@ -4712,8 +4610,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=15857, - serialized_end=15937, + serialized_start=15488, + serialized_end=15568, ) _GETCONSENSUSPARAMSRESPONSE_CONSENSUSPARAMSEVIDENCE = _descriptor.Descriptor( @@ -4757,8 +4655,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=15939, - serialized_end=16037, + serialized_start=15570, + serialized_end=15668, ) _GETCONSENSUSPARAMSRESPONSE_GETCONSENSUSPARAMSRESPONSEV0 = _descriptor.Descriptor( @@ -4795,8 +4693,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=16040, - serialized_end=16258, + serialized_start=15671, + serialized_end=15889, ) _GETCONSENSUSPARAMSRESPONSE = _descriptor.Descriptor( @@ -4831,8 +4729,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=15729, - serialized_end=16269, + serialized_start=15360, + serialized_end=15900, ) @@ -4863,8 +4761,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=16433, - serialized_end=16489, + serialized_start=16064, + serialized_end=16120, ) _GETPROTOCOLVERSIONUPGRADESTATEREQUEST = _descriptor.Descriptor( @@ -4899,8 +4797,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=16272, - serialized_end=16500, + serialized_start=15903, + serialized_end=16131, ) @@ -4931,8 +4829,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=16965, - serialized_end=17115, + serialized_start=16596, + serialized_end=16746, ) _GETPROTOCOLVERSIONUPGRADESTATERESPONSE_GETPROTOCOLVERSIONUPGRADESTATERESPONSEV0_VERSIONENTRY = _descriptor.Descriptor( @@ -4969,8 +4867,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=17117, - serialized_end=17175, + serialized_start=16748, + serialized_end=16806, ) _GETPROTOCOLVERSIONUPGRADESTATERESPONSE_GETPROTOCOLVERSIONUPGRADESTATERESPONSEV0 = _descriptor.Descriptor( @@ -5019,8 +4917,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=16668, - serialized_end=17185, + serialized_start=16299, + serialized_end=16816, ) _GETPROTOCOLVERSIONUPGRADESTATERESPONSE = _descriptor.Descriptor( @@ -5055,8 +4953,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=16503, - serialized_end=17196, + serialized_start=16134, + serialized_end=16827, ) @@ -5101,8 +4999,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=17376, - serialized_end=17479, + serialized_start=17007, + serialized_end=17110, ) _GETPROTOCOLVERSIONUPGRADEVOTESTATUSREQUEST = _descriptor.Descriptor( @@ -5137,8 +5035,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=17199, - serialized_end=17490, + serialized_start=16830, + serialized_end=17121, ) @@ -5169,8 +5067,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=17993, - serialized_end=18168, + serialized_start=17624, + serialized_end=17799, ) _GETPROTOCOLVERSIONUPGRADEVOTESTATUSRESPONSE_GETPROTOCOLVERSIONUPGRADEVOTESTATUSRESPONSEV0_VERSIONSIGNAL = _descriptor.Descriptor( @@ -5207,8 +5105,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=18170, - serialized_end=18223, + serialized_start=17801, + serialized_end=17854, ) _GETPROTOCOLVERSIONUPGRADEVOTESTATUSRESPONSE_GETPROTOCOLVERSIONUPGRADEVOTESTATUSRESPONSEV0 = _descriptor.Descriptor( @@ -5257,8 +5155,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=17674, - serialized_end=18233, + serialized_start=17305, + serialized_end=17864, ) _GETPROTOCOLVERSIONUPGRADEVOTESTATUSRESPONSE = _descriptor.Descriptor( @@ -5293,8 +5191,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=17493, - serialized_end=18244, + serialized_start=17124, + serialized_end=17875, ) @@ -5346,8 +5244,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=18357, - serialized_end=18481, + serialized_start=17988, + serialized_end=18112, ) _GETEPOCHSINFOREQUEST = _descriptor.Descriptor( @@ -5382,8 +5280,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=18247, - serialized_end=18492, + serialized_start=17878, + serialized_end=18123, ) @@ -5414,8 +5312,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=18853, - serialized_end=18970, + serialized_start=18484, + serialized_end=18601, ) _GETEPOCHSINFORESPONSE_GETEPOCHSINFORESPONSEV0_EPOCHINFO = _descriptor.Descriptor( @@ -5480,8 +5378,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=18973, - serialized_end=19139, + serialized_start=18604, + serialized_end=18770, ) _GETEPOCHSINFORESPONSE_GETEPOCHSINFORESPONSEV0 = _descriptor.Descriptor( @@ -5530,8 +5428,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=18609, - serialized_end=19149, + serialized_start=18240, + serialized_end=18780, ) _GETEPOCHSINFORESPONSE = _descriptor.Descriptor( @@ -5566,8 +5464,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=18495, - serialized_end=19160, + serialized_start=18126, + serialized_end=18791, ) @@ -5626,8 +5524,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=19301, - serialized_end=19471, + serialized_start=18932, + serialized_end=19102, ) _GETFINALIZEDEPOCHINFOSREQUEST = _descriptor.Descriptor( @@ -5662,8 +5560,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=19163, - serialized_end=19482, + serialized_start=18794, + serialized_end=19113, ) @@ -5694,8 +5592,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=19908, - serialized_end=20072, + serialized_start=19539, + serialized_end=19703, ) _GETFINALIZEDEPOCHINFOSRESPONSE_GETFINALIZEDEPOCHINFOSRESPONSEV0_FINALIZEDEPOCHINFO = _descriptor.Descriptor( @@ -5809,8 +5707,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=20075, - serialized_end=20618, + serialized_start=19706, + serialized_end=20249, ) _GETFINALIZEDEPOCHINFOSRESPONSE_GETFINALIZEDEPOCHINFOSRESPONSEV0_BLOCKPROPOSER = _descriptor.Descriptor( @@ -5847,8 +5745,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=20620, - serialized_end=20677, + serialized_start=20251, + serialized_end=20308, ) _GETFINALIZEDEPOCHINFOSRESPONSE_GETFINALIZEDEPOCHINFOSRESPONSEV0 = _descriptor.Descriptor( @@ -5897,8 +5795,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=19626, - serialized_end=20687, + serialized_start=19257, + serialized_end=20318, ) _GETFINALIZEDEPOCHINFOSRESPONSE = _descriptor.Descriptor( @@ -5933,8 +5831,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=19485, - serialized_end=20698, + serialized_start=19116, + serialized_end=20329, ) @@ -5972,8 +5870,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=21193, - serialized_end=21262, + serialized_start=20824, + serialized_end=20893, ) _GETCONTESTEDRESOURCESREQUEST_GETCONTESTEDRESOURCESREQUESTV0 = _descriptor.Descriptor( @@ -6069,8 +5967,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=20836, - serialized_end=21296, + serialized_start=20467, + serialized_end=20927, ) _GETCONTESTEDRESOURCESREQUEST = _descriptor.Descriptor( @@ -6105,8 +6003,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=20701, - serialized_end=21307, + serialized_start=20332, + serialized_end=20938, ) @@ -6137,8 +6035,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=21749, - serialized_end=21809, + serialized_start=21380, + serialized_end=21440, ) _GETCONTESTEDRESOURCESRESPONSE_GETCONTESTEDRESOURCESRESPONSEV0 = _descriptor.Descriptor( @@ -6187,8 +6085,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=21448, - serialized_end=21819, + serialized_start=21079, + serialized_end=21450, ) _GETCONTESTEDRESOURCESRESPONSE = _descriptor.Descriptor( @@ -6223,8 +6121,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=21310, - serialized_end=21830, + serialized_start=20941, + serialized_end=21461, ) @@ -6262,8 +6160,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=22343, - serialized_end=22416, + serialized_start=21974, + serialized_end=22047, ) _GETVOTEPOLLSBYENDDATEREQUEST_GETVOTEPOLLSBYENDDATEREQUESTV0_ENDATTIMEINFO = _descriptor.Descriptor( @@ -6300,8 +6198,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=22418, - serialized_end=22485, + serialized_start=22049, + serialized_end=22116, ) _GETVOTEPOLLSBYENDDATEREQUEST_GETVOTEPOLLSBYENDDATEREQUESTV0 = _descriptor.Descriptor( @@ -6386,8 +6284,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=21968, - serialized_end=22544, + serialized_start=21599, + serialized_end=22175, ) _GETVOTEPOLLSBYENDDATEREQUEST = _descriptor.Descriptor( @@ -6422,8 +6320,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=21833, - serialized_end=22555, + serialized_start=21464, + serialized_end=22186, ) @@ -6461,8 +6359,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=23004, - serialized_end=23090, + serialized_start=22635, + serialized_end=22721, ) _GETVOTEPOLLSBYENDDATERESPONSE_GETVOTEPOLLSBYENDDATERESPONSEV0_SERIALIZEDVOTEPOLLSBYTIMESTAMPS = _descriptor.Descriptor( @@ -6499,8 +6397,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=23093, - serialized_end=23308, + serialized_start=22724, + serialized_end=22939, ) _GETVOTEPOLLSBYENDDATERESPONSE_GETVOTEPOLLSBYENDDATERESPONSEV0 = _descriptor.Descriptor( @@ -6549,8 +6447,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=22696, - serialized_end=23318, + serialized_start=22327, + serialized_end=22949, ) _GETVOTEPOLLSBYENDDATERESPONSE = _descriptor.Descriptor( @@ -6585,8 +6483,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=22558, - serialized_end=23329, + serialized_start=22189, + serialized_end=22960, ) @@ -6624,8 +6522,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=24018, - serialized_end=24102, + serialized_start=23649, + serialized_end=23733, ) _GETCONTESTEDRESOURCEVOTESTATEREQUEST_GETCONTESTEDRESOURCEVOTESTATEREQUESTV0 = _descriptor.Descriptor( @@ -6722,8 +6620,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=23491, - serialized_end=24216, + serialized_start=23122, + serialized_end=23847, ) _GETCONTESTEDRESOURCEVOTESTATEREQUEST = _descriptor.Descriptor( @@ -6758,8 +6656,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=23332, - serialized_end=24227, + serialized_start=22963, + serialized_end=23858, ) @@ -6831,8 +6729,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=24727, - serialized_end=25201, + serialized_start=24358, + serialized_end=24832, ) _GETCONTESTEDRESOURCEVOTESTATERESPONSE_GETCONTESTEDRESOURCEVOTESTATERESPONSEV0_CONTESTEDRESOURCECONTENDERS = _descriptor.Descriptor( @@ -6898,8 +6796,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=25204, - serialized_end=25656, + serialized_start=24835, + serialized_end=25287, ) _GETCONTESTEDRESOURCEVOTESTATERESPONSE_GETCONTESTEDRESOURCEVOTESTATERESPONSEV0_CONTENDER = _descriptor.Descriptor( @@ -6953,8 +6851,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=25658, - serialized_end=25765, + serialized_start=25289, + serialized_end=25396, ) _GETCONTESTEDRESOURCEVOTESTATERESPONSE_GETCONTESTEDRESOURCEVOTESTATERESPONSEV0 = _descriptor.Descriptor( @@ -7003,8 +6901,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=24392, - serialized_end=25775, + serialized_start=24023, + serialized_end=25406, ) _GETCONTESTEDRESOURCEVOTESTATERESPONSE = _descriptor.Descriptor( @@ -7039,8 +6937,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=24230, - serialized_end=25786, + serialized_start=23861, + serialized_end=25417, ) @@ -7078,8 +6976,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=24018, - serialized_end=24102, + serialized_start=23649, + serialized_end=23733, ) _GETCONTESTEDRESOURCEVOTERSFORIDENTITYREQUEST_GETCONTESTEDRESOURCEVOTERSFORIDENTITYREQUESTV0 = _descriptor.Descriptor( @@ -7175,8 +7073,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=25973, - serialized_end=26503, + serialized_start=25604, + serialized_end=26134, ) _GETCONTESTEDRESOURCEVOTERSFORIDENTITYREQUEST = _descriptor.Descriptor( @@ -7211,8 +7109,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=25789, - serialized_end=26514, + serialized_start=25420, + serialized_end=26145, ) @@ -7250,8 +7148,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=27054, - serialized_end=27121, + serialized_start=26685, + serialized_end=26752, ) _GETCONTESTEDRESOURCEVOTERSFORIDENTITYRESPONSE_GETCONTESTEDRESOURCEVOTERSFORIDENTITYRESPONSEV0 = _descriptor.Descriptor( @@ -7300,8 +7198,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=26704, - serialized_end=27131, + serialized_start=26335, + serialized_end=26762, ) _GETCONTESTEDRESOURCEVOTERSFORIDENTITYRESPONSE = _descriptor.Descriptor( @@ -7336,8 +7234,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=26517, - serialized_end=27142, + serialized_start=26148, + serialized_end=26773, ) @@ -7375,8 +7273,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=27691, - serialized_end=27788, + serialized_start=27322, + serialized_end=27419, ) _GETCONTESTEDRESOURCEIDENTITYVOTESREQUEST_GETCONTESTEDRESOURCEIDENTITYVOTESREQUESTV0 = _descriptor.Descriptor( @@ -7446,8 +7344,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=27316, - serialized_end=27819, + serialized_start=26947, + serialized_end=27450, ) _GETCONTESTEDRESOURCEIDENTITYVOTESREQUEST = _descriptor.Descriptor( @@ -7482,8 +7380,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=27145, - serialized_end=27830, + serialized_start=26776, + serialized_end=27461, ) @@ -7521,8 +7419,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=28333, - serialized_end=28580, + serialized_start=27964, + serialized_end=28211, ) _GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSE_GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSEV0_RESOURCEVOTECHOICE = _descriptor.Descriptor( @@ -7565,8 +7463,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=28583, - serialized_end=28884, + serialized_start=28214, + serialized_end=28515, ) _GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSE_GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSEV0_CONTESTEDRESOURCEIDENTITYVOTE = _descriptor.Descriptor( @@ -7617,8 +7515,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=28887, - serialized_end=29164, + serialized_start=28518, + serialized_end=28795, ) _GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSE_GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSEV0 = _descriptor.Descriptor( @@ -7667,8 +7565,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=28007, - serialized_end=29174, + serialized_start=27638, + serialized_end=28805, ) _GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSE = _descriptor.Descriptor( @@ -7703,8 +7601,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=27833, - serialized_end=29185, + serialized_start=27464, + serialized_end=28816, ) @@ -7742,8 +7640,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=29349, - serialized_end=29417, + serialized_start=28980, + serialized_end=29048, ) _GETPREFUNDEDSPECIALIZEDBALANCEREQUEST = _descriptor.Descriptor( @@ -7778,8 +7676,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=29188, - serialized_end=29428, + serialized_start=28819, + serialized_end=29059, ) @@ -7829,8 +7727,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=29596, - serialized_end=29785, + serialized_start=29227, + serialized_end=29416, ) _GETPREFUNDEDSPECIALIZEDBALANCERESPONSE = _descriptor.Descriptor( @@ -7865,8 +7763,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=29431, - serialized_end=29796, + serialized_start=29062, + serialized_end=29427, ) @@ -7897,8 +7795,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=29945, - serialized_end=29996, + serialized_start=29576, + serialized_end=29627, ) _GETTOTALCREDITSINPLATFORMREQUEST = _descriptor.Descriptor( @@ -7933,8 +7831,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=29799, - serialized_end=30007, + serialized_start=29430, + serialized_end=29638, ) @@ -7984,8 +7882,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=30160, - serialized_end=30344, + serialized_start=29791, + serialized_end=29975, ) _GETTOTALCREDITSINPLATFORMRESPONSE = _descriptor.Descriptor( @@ -8020,8 +7918,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=30010, - serialized_end=30355, + serialized_start=29641, + serialized_end=29986, ) @@ -8066,8 +7964,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=30474, - serialized_end=30543, + serialized_start=30105, + serialized_end=30174, ) _GETPATHELEMENTSREQUEST = _descriptor.Descriptor( @@ -8102,8 +8000,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=30358, - serialized_end=30554, + serialized_start=29989, + serialized_end=30185, ) @@ -8134,8 +8032,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=30927, - serialized_end=30955, + serialized_start=30558, + serialized_end=30586, ) _GETPATHELEMENTSRESPONSE_GETPATHELEMENTSRESPONSEV0 = _descriptor.Descriptor( @@ -8184,8 +8082,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=30677, - serialized_end=30965, + serialized_start=30308, + serialized_end=30596, ) _GETPATHELEMENTSRESPONSE = _descriptor.Descriptor( @@ -8220,8 +8118,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=30557, - serialized_end=30976, + serialized_start=30188, + serialized_end=30607, ) @@ -8245,8 +8143,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=31077, - serialized_end=31097, + serialized_start=30708, + serialized_end=30728, ) _GETSTATUSREQUEST = _descriptor.Descriptor( @@ -8281,8 +8179,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=30979, - serialized_end=31108, + serialized_start=30610, + serialized_end=30739, ) @@ -8337,8 +8235,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=31985, - serialized_end=32079, + serialized_start=31616, + serialized_end=31710, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_VERSION_PROTOCOL_TENDERDASH = _descriptor.Descriptor( @@ -8375,8 +8273,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=32312, - serialized_end=32352, + serialized_start=31943, + serialized_end=31983, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_VERSION_PROTOCOL_DRIVE = _descriptor.Descriptor( @@ -8420,8 +8318,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=32354, - serialized_end=32414, + serialized_start=31985, + serialized_end=32045, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_VERSION_PROTOCOL = _descriptor.Descriptor( @@ -8458,8 +8356,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=32082, - serialized_end=32414, + serialized_start=31713, + serialized_end=32045, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_VERSION = _descriptor.Descriptor( @@ -8496,8 +8394,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=31772, - serialized_end=32414, + serialized_start=31403, + serialized_end=32045, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_TIME = _descriptor.Descriptor( @@ -8563,8 +8461,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=32416, - serialized_end=32543, + serialized_start=32047, + serialized_end=32174, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_NODE = _descriptor.Descriptor( @@ -8606,8 +8504,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=32545, - serialized_end=32605, + serialized_start=32176, + serialized_end=32236, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_CHAIN = _descriptor.Descriptor( @@ -8698,8 +8596,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=32608, - serialized_end=32915, + serialized_start=32239, + serialized_end=32546, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_NETWORK = _descriptor.Descriptor( @@ -8743,8 +8641,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=32917, - serialized_end=32984, + serialized_start=32548, + serialized_end=32615, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_STATESYNC = _descriptor.Descriptor( @@ -8823,8 +8721,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=32987, - serialized_end=33248, + serialized_start=32618, + serialized_end=32879, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0 = _descriptor.Descriptor( @@ -8889,8 +8787,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=31213, - serialized_end=33248, + serialized_start=30844, + serialized_end=32879, ) _GETSTATUSRESPONSE = _descriptor.Descriptor( @@ -8925,8 +8823,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=31111, - serialized_end=33259, + serialized_start=30742, + serialized_end=32890, ) @@ -8950,8 +8848,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=33396, - serialized_end=33428, + serialized_start=33027, + serialized_end=33059, ) _GETCURRENTQUORUMSINFOREQUEST = _descriptor.Descriptor( @@ -8986,8 +8884,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=33262, - serialized_end=33439, + serialized_start=32893, + serialized_end=33070, ) @@ -9032,8 +8930,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=33579, - serialized_end=33649, + serialized_start=33210, + serialized_end=33280, ) _GETCURRENTQUORUMSINFORESPONSE_VALIDATORSETV0 = _descriptor.Descriptor( @@ -9084,8 +8982,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=33652, - serialized_end=33827, + serialized_start=33283, + serialized_end=33458, ) _GETCURRENTQUORUMSINFORESPONSE_GETCURRENTQUORUMSINFORESPONSEV0 = _descriptor.Descriptor( @@ -9143,8 +9041,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=33830, - serialized_end=34104, + serialized_start=33461, + serialized_end=33735, ) _GETCURRENTQUORUMSINFORESPONSE = _descriptor.Descriptor( @@ -9179,8 +9077,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=33442, - serialized_end=34115, + serialized_start=33073, + serialized_end=33746, ) @@ -9225,8 +9123,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=34261, - serialized_end=34351, + serialized_start=33892, + serialized_end=33982, ) _GETIDENTITYTOKENBALANCESREQUEST = _descriptor.Descriptor( @@ -9261,8 +9159,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=34118, - serialized_end=34362, + serialized_start=33749, + serialized_end=33993, ) @@ -9305,8 +9203,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=34801, - serialized_end=34872, + serialized_start=34432, + serialized_end=34503, ) _GETIDENTITYTOKENBALANCESRESPONSE_GETIDENTITYTOKENBALANCESRESPONSEV0_TOKENBALANCES = _descriptor.Descriptor( @@ -9336,8 +9234,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=34875, - serialized_end=35029, + serialized_start=34506, + serialized_end=34660, ) _GETIDENTITYTOKENBALANCESRESPONSE_GETIDENTITYTOKENBALANCESRESPONSEV0 = _descriptor.Descriptor( @@ -9386,8 +9284,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=34512, - serialized_end=35039, + serialized_start=34143, + serialized_end=34670, ) _GETIDENTITYTOKENBALANCESRESPONSE = _descriptor.Descriptor( @@ -9422,8 +9320,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=34365, - serialized_end=35050, + serialized_start=33996, + serialized_end=34681, ) @@ -9468,8 +9366,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=35202, - serialized_end=35294, + serialized_start=34833, + serialized_end=34925, ) _GETIDENTITIESTOKENBALANCESREQUEST = _descriptor.Descriptor( @@ -9504,8 +9402,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=35053, - serialized_end=35305, + serialized_start=34684, + serialized_end=34936, ) @@ -9548,8 +9446,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=35773, - serialized_end=35855, + serialized_start=35404, + serialized_end=35486, ) _GETIDENTITIESTOKENBALANCESRESPONSE_GETIDENTITIESTOKENBALANCESRESPONSEV0_IDENTITYTOKENBALANCES = _descriptor.Descriptor( @@ -9579,8 +9477,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=35858, - serialized_end=36041, + serialized_start=35489, + serialized_end=35672, ) _GETIDENTITIESTOKENBALANCESRESPONSE_GETIDENTITIESTOKENBALANCESRESPONSEV0 = _descriptor.Descriptor( @@ -9629,8 +9527,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=35461, - serialized_end=36051, + serialized_start=35092, + serialized_end=35682, ) _GETIDENTITIESTOKENBALANCESRESPONSE = _descriptor.Descriptor( @@ -9665,8 +9563,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=35308, - serialized_end=36062, + serialized_start=34939, + serialized_end=35693, ) @@ -9711,8 +9609,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=36199, - serialized_end=36286, + serialized_start=35830, + serialized_end=35917, ) _GETIDENTITYTOKENINFOSREQUEST = _descriptor.Descriptor( @@ -9747,8 +9645,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=36065, - serialized_end=36297, + serialized_start=35696, + serialized_end=35928, ) @@ -9779,8 +9677,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=36711, - serialized_end=36751, + serialized_start=36342, + serialized_end=36382, ) _GETIDENTITYTOKENINFOSRESPONSE_GETIDENTITYTOKENINFOSRESPONSEV0_TOKENINFOENTRY = _descriptor.Descriptor( @@ -9822,8 +9720,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=36754, - serialized_end=36930, + serialized_start=36385, + serialized_end=36561, ) _GETIDENTITYTOKENINFOSRESPONSE_GETIDENTITYTOKENINFOSRESPONSEV0_TOKENINFOS = _descriptor.Descriptor( @@ -9853,8 +9751,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=36933, - serialized_end=37071, + serialized_start=36564, + serialized_end=36702, ) _GETIDENTITYTOKENINFOSRESPONSE_GETIDENTITYTOKENINFOSRESPONSEV0 = _descriptor.Descriptor( @@ -9903,8 +9801,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=36438, - serialized_end=37081, + serialized_start=36069, + serialized_end=36712, ) _GETIDENTITYTOKENINFOSRESPONSE = _descriptor.Descriptor( @@ -9939,8 +9837,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=36300, - serialized_end=37092, + serialized_start=35931, + serialized_end=36723, ) @@ -9985,8 +9883,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=37235, - serialized_end=37324, + serialized_start=36866, + serialized_end=36955, ) _GETIDENTITIESTOKENINFOSREQUEST = _descriptor.Descriptor( @@ -10021,8 +9919,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=37095, - serialized_end=37335, + serialized_start=36726, + serialized_end=36966, ) @@ -10053,8 +9951,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=36711, - serialized_end=36751, + serialized_start=36342, + serialized_end=36382, ) _GETIDENTITIESTOKENINFOSRESPONSE_GETIDENTITIESTOKENINFOSRESPONSEV0_TOKENINFOENTRY = _descriptor.Descriptor( @@ -10096,8 +9994,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=37822, - serialized_end=38005, + serialized_start=37453, + serialized_end=37636, ) _GETIDENTITIESTOKENINFOSRESPONSE_GETIDENTITIESTOKENINFOSRESPONSEV0_IDENTITYTOKENINFOS = _descriptor.Descriptor( @@ -10127,8 +10025,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=38008, - serialized_end=38159, + serialized_start=37639, + serialized_end=37790, ) _GETIDENTITIESTOKENINFOSRESPONSE_GETIDENTITIESTOKENINFOSRESPONSEV0 = _descriptor.Descriptor( @@ -10177,8 +10075,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=37482, - serialized_end=38169, + serialized_start=37113, + serialized_end=37800, ) _GETIDENTITIESTOKENINFOSRESPONSE = _descriptor.Descriptor( @@ -10213,8 +10111,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=37338, - serialized_end=38180, + serialized_start=36969, + serialized_end=37811, ) @@ -10252,8 +10150,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=38302, - serialized_end=38363, + serialized_start=37933, + serialized_end=37994, ) _GETTOKENSTATUSESREQUEST = _descriptor.Descriptor( @@ -10288,8 +10186,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=38183, - serialized_end=38374, + serialized_start=37814, + serialized_end=38005, ) @@ -10332,8 +10230,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=38764, - serialized_end=38832, + serialized_start=38395, + serialized_end=38463, ) _GETTOKENSTATUSESRESPONSE_GETTOKENSTATUSESRESPONSEV0_TOKENSTATUSES = _descriptor.Descriptor( @@ -10363,8 +10261,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=38835, - serialized_end=38971, + serialized_start=38466, + serialized_end=38602, ) _GETTOKENSTATUSESRESPONSE_GETTOKENSTATUSESRESPONSEV0 = _descriptor.Descriptor( @@ -10413,8 +10311,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=38500, - serialized_end=38981, + serialized_start=38131, + serialized_end=38612, ) _GETTOKENSTATUSESRESPONSE = _descriptor.Descriptor( @@ -10449,8 +10347,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=38377, - serialized_end=38992, + serialized_start=38008, + serialized_end=38623, ) @@ -10488,8 +10386,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=39150, - serialized_end=39223, + serialized_start=38781, + serialized_end=38854, ) _GETTOKENDIRECTPURCHASEPRICESREQUEST = _descriptor.Descriptor( @@ -10524,8 +10422,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=38995, - serialized_end=39234, + serialized_start=38626, + serialized_end=38865, ) @@ -10563,8 +10461,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=39724, - serialized_end=39775, + serialized_start=39355, + serialized_end=39406, ) _GETTOKENDIRECTPURCHASEPRICESRESPONSE_GETTOKENDIRECTPURCHASEPRICESRESPONSEV0_PRICINGSCHEDULE = _descriptor.Descriptor( @@ -10594,8 +10492,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=39778, - serialized_end=39945, + serialized_start=39409, + serialized_end=39576, ) _GETTOKENDIRECTPURCHASEPRICESRESPONSE_GETTOKENDIRECTPURCHASEPRICESRESPONSEV0_TOKENDIRECTPURCHASEPRICEENTRY = _descriptor.Descriptor( @@ -10644,8 +10542,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=39948, - serialized_end=40176, + serialized_start=39579, + serialized_end=39807, ) _GETTOKENDIRECTPURCHASEPRICESRESPONSE_GETTOKENDIRECTPURCHASEPRICESRESPONSEV0_TOKENDIRECTPURCHASEPRICES = _descriptor.Descriptor( @@ -10675,8 +10573,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=40179, - serialized_end=40379, + serialized_start=39810, + serialized_end=40010, ) _GETTOKENDIRECTPURCHASEPRICESRESPONSE_GETTOKENDIRECTPURCHASEPRICESRESPONSEV0 = _descriptor.Descriptor( @@ -10725,8 +10623,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=39396, - serialized_end=40389, + serialized_start=39027, + serialized_end=40020, ) _GETTOKENDIRECTPURCHASEPRICESRESPONSE = _descriptor.Descriptor( @@ -10761,8 +10659,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=39237, - serialized_end=40400, + serialized_start=38868, + serialized_end=40031, ) @@ -10800,8 +10698,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=40534, - serialized_end=40598, + serialized_start=40165, + serialized_end=40229, ) _GETTOKENCONTRACTINFOREQUEST = _descriptor.Descriptor( @@ -10836,8 +10734,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=40403, - serialized_end=40609, + serialized_start=40034, + serialized_end=40240, ) @@ -10875,8 +10773,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=41021, - serialized_end=41098, + serialized_start=40652, + serialized_end=40729, ) _GETTOKENCONTRACTINFORESPONSE_GETTOKENCONTRACTINFORESPONSEV0 = _descriptor.Descriptor( @@ -10925,8 +10823,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=40747, - serialized_end=41108, + serialized_start=40378, + serialized_end=40739, ) _GETTOKENCONTRACTINFORESPONSE = _descriptor.Descriptor( @@ -10961,8 +10859,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=40612, - serialized_end=41119, + serialized_start=40243, + serialized_end=40750, ) @@ -11017,8 +10915,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=41552, - serialized_end=41706, + serialized_start=41183, + serialized_end=41337, ) _GETTOKENPREPROGRAMMEDDISTRIBUTIONSREQUEST_GETTOKENPREPROGRAMMEDDISTRIBUTIONSREQUESTV0 = _descriptor.Descriptor( @@ -11079,8 +10977,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=41296, - serialized_end=41734, + serialized_start=40927, + serialized_end=41365, ) _GETTOKENPREPROGRAMMEDDISTRIBUTIONSREQUEST = _descriptor.Descriptor( @@ -11115,8 +11013,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=41122, - serialized_end=41745, + serialized_start=40753, + serialized_end=41376, ) @@ -11154,8 +11052,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=42256, - serialized_end=42318, + serialized_start=41887, + serialized_end=41949, ) _GETTOKENPREPROGRAMMEDDISTRIBUTIONSRESPONSE_GETTOKENPREPROGRAMMEDDISTRIBUTIONSRESPONSEV0_TOKENTIMEDDISTRIBUTIONENTRY = _descriptor.Descriptor( @@ -11192,8 +11090,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=42321, - serialized_end=42533, + serialized_start=41952, + serialized_end=42164, ) _GETTOKENPREPROGRAMMEDDISTRIBUTIONSRESPONSE_GETTOKENPREPROGRAMMEDDISTRIBUTIONSRESPONSEV0_TOKENDISTRIBUTIONS = _descriptor.Descriptor( @@ -11223,8 +11121,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=42536, - serialized_end=42731, + serialized_start=42167, + serialized_end=42362, ) _GETTOKENPREPROGRAMMEDDISTRIBUTIONSRESPONSE_GETTOKENPREPROGRAMMEDDISTRIBUTIONSRESPONSEV0 = _descriptor.Descriptor( @@ -11273,8 +11171,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=41926, - serialized_end=42741, + serialized_start=41557, + serialized_end=42372, ) _GETTOKENPREPROGRAMMEDDISTRIBUTIONSRESPONSE = _descriptor.Descriptor( @@ -11309,8 +11207,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=41748, - serialized_end=42752, + serialized_start=41379, + serialized_end=42383, ) @@ -11348,8 +11246,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=42941, - serialized_end=43014, + serialized_start=42572, + serialized_end=42645, ) _GETTOKENPERPETUALDISTRIBUTIONLASTCLAIMREQUEST_GETTOKENPERPETUALDISTRIBUTIONLASTCLAIMREQUESTV0 = _descriptor.Descriptor( @@ -11405,8 +11303,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=43017, - serialized_end=43258, + serialized_start=42648, + serialized_end=42889, ) _GETTOKENPERPETUALDISTRIBUTIONLASTCLAIMREQUEST = _descriptor.Descriptor( @@ -11441,8 +11339,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=42755, - serialized_end=43269, + serialized_start=42386, + serialized_end=42900, ) @@ -11499,8 +11397,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=43790, - serialized_end=43910, + serialized_start=43421, + serialized_end=43541, ) _GETTOKENPERPETUALDISTRIBUTIONLASTCLAIMRESPONSE_GETTOKENPERPETUALDISTRIBUTIONLASTCLAIMRESPONSEV0 = _descriptor.Descriptor( @@ -11549,8 +11447,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=43462, - serialized_end=43920, + serialized_start=43093, + serialized_end=43551, ) _GETTOKENPERPETUALDISTRIBUTIONLASTCLAIMRESPONSE = _descriptor.Descriptor( @@ -11585,8 +11483,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=43272, - serialized_end=43931, + serialized_start=42903, + serialized_end=43562, ) @@ -11624,8 +11522,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=44062, - serialized_end=44125, + serialized_start=43693, + serialized_end=43756, ) _GETTOKENTOTALSUPPLYREQUEST = _descriptor.Descriptor( @@ -11660,8 +11558,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=43934, - serialized_end=44136, + serialized_start=43565, + serialized_end=43767, ) @@ -11706,8 +11604,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=44557, - serialized_end=44677, + serialized_start=44188, + serialized_end=44308, ) _GETTOKENTOTALSUPPLYRESPONSE_GETTOKENTOTALSUPPLYRESPONSEV0 = _descriptor.Descriptor( @@ -11756,8 +11654,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=44271, - serialized_end=44687, + serialized_start=43902, + serialized_end=44318, ) _GETTOKENTOTALSUPPLYRESPONSE = _descriptor.Descriptor( @@ -11792,8 +11690,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=44139, - serialized_end=44698, + serialized_start=43770, + serialized_end=44329, ) @@ -11838,8 +11736,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=44808, - serialized_end=44900, + serialized_start=44439, + serialized_end=44531, ) _GETGROUPINFOREQUEST = _descriptor.Descriptor( @@ -11874,8 +11772,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=44701, - serialized_end=44911, + serialized_start=44332, + serialized_end=44542, ) @@ -11913,8 +11811,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=45269, - serialized_end=45321, + serialized_start=44900, + serialized_end=44952, ) _GETGROUPINFORESPONSE_GETGROUPINFORESPONSEV0_GROUPINFOENTRY = _descriptor.Descriptor( @@ -11951,8 +11849,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=45324, - serialized_end=45476, + serialized_start=44955, + serialized_end=45107, ) _GETGROUPINFORESPONSE_GETGROUPINFORESPONSEV0_GROUPINFO = _descriptor.Descriptor( @@ -11987,8 +11885,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=45479, - serialized_end=45617, + serialized_start=45110, + serialized_end=45248, ) _GETGROUPINFORESPONSE_GETGROUPINFORESPONSEV0 = _descriptor.Descriptor( @@ -12037,8 +11935,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=45025, - serialized_end=45627, + serialized_start=44656, + serialized_end=45258, ) _GETGROUPINFORESPONSE = _descriptor.Descriptor( @@ -12073,8 +11971,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=44914, - serialized_end=45638, + serialized_start=44545, + serialized_end=45269, ) @@ -12112,8 +12010,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=45751, - serialized_end=45868, + serialized_start=45382, + serialized_end=45499, ) _GETGROUPINFOSREQUEST_GETGROUPINFOSREQUESTV0 = _descriptor.Descriptor( @@ -12174,8 +12072,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=45871, - serialized_end=46123, + serialized_start=45502, + serialized_end=45754, ) _GETGROUPINFOSREQUEST = _descriptor.Descriptor( @@ -12210,8 +12108,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=45641, - serialized_end=46134, + serialized_start=45272, + serialized_end=45765, ) @@ -12249,8 +12147,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=45269, - serialized_end=45321, + serialized_start=44900, + serialized_end=44952, ) _GETGROUPINFOSRESPONSE_GETGROUPINFOSRESPONSEV0_GROUPPOSITIONINFOENTRY = _descriptor.Descriptor( @@ -12294,8 +12192,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=46555, - serialized_end=46750, + serialized_start=46186, + serialized_end=46381, ) _GETGROUPINFOSRESPONSE_GETGROUPINFOSRESPONSEV0_GROUPINFOS = _descriptor.Descriptor( @@ -12325,8 +12223,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=46753, - serialized_end=46883, + serialized_start=46384, + serialized_end=46514, ) _GETGROUPINFOSRESPONSE_GETGROUPINFOSRESPONSEV0 = _descriptor.Descriptor( @@ -12375,8 +12273,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=46251, - serialized_end=46893, + serialized_start=45882, + serialized_end=46524, ) _GETGROUPINFOSRESPONSE = _descriptor.Descriptor( @@ -12411,8 +12309,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=46137, - serialized_end=46904, + serialized_start=45768, + serialized_end=46535, ) @@ -12450,8 +12348,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=47023, - serialized_end=47099, + serialized_start=46654, + serialized_end=46730, ) _GETGROUPACTIONSREQUEST_GETGROUPACTIONSREQUESTV0 = _descriptor.Descriptor( @@ -12526,8 +12424,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=47102, - serialized_end=47430, + serialized_start=46733, + serialized_end=47061, ) _GETGROUPACTIONSREQUEST = _descriptor.Descriptor( @@ -12563,8 +12461,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=46907, - serialized_end=47481, + serialized_start=46538, + serialized_end=47112, ) @@ -12614,8 +12512,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=47863, - serialized_end=47954, + serialized_start=47494, + serialized_end=47585, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_BURNEVENT = _descriptor.Descriptor( @@ -12664,8 +12562,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=47956, - serialized_end=48047, + serialized_start=47587, + serialized_end=47678, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_FREEZEEVENT = _descriptor.Descriptor( @@ -12707,8 +12605,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=48049, - serialized_end=48123, + serialized_start=47680, + serialized_end=47754, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_UNFREEZEEVENT = _descriptor.Descriptor( @@ -12750,8 +12648,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=48125, - serialized_end=48201, + serialized_start=47756, + serialized_end=47832, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_DESTROYFROZENFUNDSEVENT = _descriptor.Descriptor( @@ -12800,8 +12698,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=48203, - serialized_end=48305, + serialized_start=47834, + serialized_end=47936, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_SHAREDENCRYPTEDNOTE = _descriptor.Descriptor( @@ -12845,8 +12743,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=48307, - serialized_end=48407, + serialized_start=47938, + serialized_end=48038, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_PERSONALENCRYPTEDNOTE = _descriptor.Descriptor( @@ -12890,8 +12788,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=48409, - serialized_end=48532, + serialized_start=48040, + serialized_end=48163, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_EMERGENCYACTIONEVENT = _descriptor.Descriptor( @@ -12934,8 +12832,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=48535, - serialized_end=48768, + serialized_start=48166, + serialized_end=48399, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_TOKENCONFIGUPDATEEVENT = _descriptor.Descriptor( @@ -12977,8 +12875,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=48770, - serialized_end=48870, + serialized_start=48401, + serialized_end=48501, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_UPDATEDIRECTPURCHASEPRICEEVENT_PRICEFORQUANTITY = _descriptor.Descriptor( @@ -13015,8 +12913,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=39724, - serialized_end=39775, + serialized_start=39355, + serialized_end=39406, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_UPDATEDIRECTPURCHASEPRICEEVENT_PRICINGSCHEDULE = _descriptor.Descriptor( @@ -13046,8 +12944,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=49162, - serialized_end=49334, + serialized_start=48793, + serialized_end=48965, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_UPDATEDIRECTPURCHASEPRICEEVENT = _descriptor.Descriptor( @@ -13101,8 +12999,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=48873, - serialized_end=49359, + serialized_start=48504, + serialized_end=48990, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_GROUPACTIONEVENT = _descriptor.Descriptor( @@ -13151,8 +13049,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=49362, - serialized_end=49742, + serialized_start=48993, + serialized_end=49373, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_DOCUMENTEVENT = _descriptor.Descriptor( @@ -13187,8 +13085,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=49745, - serialized_end=49884, + serialized_start=49376, + serialized_end=49515, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_DOCUMENTCREATEEVENT = _descriptor.Descriptor( @@ -13218,8 +13116,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=49886, - serialized_end=49933, + serialized_start=49517, + serialized_end=49564, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_CONTRACTUPDATEEVENT = _descriptor.Descriptor( @@ -13249,8 +13147,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=49935, - serialized_end=49982, + serialized_start=49566, + serialized_end=49613, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_CONTRACTEVENT = _descriptor.Descriptor( @@ -13285,8 +13183,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=49985, - serialized_end=50124, + serialized_start=49616, + serialized_end=49755, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_TOKENEVENT = _descriptor.Descriptor( @@ -13370,8 +13268,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=50127, - serialized_end=51104, + serialized_start=49758, + serialized_end=50735, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_GROUPACTIONENTRY = _descriptor.Descriptor( @@ -13408,8 +13306,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=51107, - serialized_end=51254, + serialized_start=50738, + serialized_end=50885, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_GROUPACTIONS = _descriptor.Descriptor( @@ -13439,8 +13337,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=51257, - serialized_end=51389, + serialized_start=50888, + serialized_end=51020, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0 = _descriptor.Descriptor( @@ -13489,8 +13387,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=47604, - serialized_end=51399, + serialized_start=47235, + serialized_end=51030, ) _GETGROUPACTIONSRESPONSE = _descriptor.Descriptor( @@ -13525,8 +13423,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=47484, - serialized_end=51410, + serialized_start=47115, + serialized_end=51041, ) @@ -13585,8 +13483,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=51548, - serialized_end=51754, + serialized_start=51179, + serialized_end=51385, ) _GETGROUPACTIONSIGNERSREQUEST = _descriptor.Descriptor( @@ -13622,8 +13520,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=51413, - serialized_end=51805, + serialized_start=51044, + serialized_end=51436, ) @@ -13661,8 +13559,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=52237, - serialized_end=52290, + serialized_start=51868, + serialized_end=51921, ) _GETGROUPACTIONSIGNERSRESPONSE_GETGROUPACTIONSIGNERSRESPONSEV0_GROUPACTIONSIGNERS = _descriptor.Descriptor( @@ -13692,8 +13590,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=52293, - serialized_end=52438, + serialized_start=51924, + serialized_end=52069, ) _GETGROUPACTIONSIGNERSRESPONSE_GETGROUPACTIONSIGNERSRESPONSEV0 = _descriptor.Descriptor( @@ -13742,8 +13640,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=51946, - serialized_end=52448, + serialized_start=51577, + serialized_end=52079, ) _GETGROUPACTIONSIGNERSRESPONSE = _descriptor.Descriptor( @@ -13778,8 +13676,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=51808, - serialized_end=52459, + serialized_start=51439, + serialized_end=52090, ) @@ -13817,8 +13715,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=52575, - serialized_end=52632, + serialized_start=52206, + serialized_end=52263, ) _GETADDRESSINFOREQUEST = _descriptor.Descriptor( @@ -13853,8 +13751,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=52462, - serialized_end=52643, + serialized_start=52093, + serialized_end=52274, ) @@ -13897,8 +13795,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=52646, - serialized_end=52779, + serialized_start=52277, + serialized_end=52410, ) @@ -13936,8 +13834,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=52781, - serialized_end=52830, + serialized_start=52412, + serialized_end=52461, ) @@ -13968,8 +13866,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=52832, - serialized_end=52927, + serialized_start=52463, + serialized_end=52558, ) @@ -14019,8 +13917,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=52929, - serialized_end=53038, + serialized_start=52560, + serialized_end=52669, ) @@ -14058,8 +13956,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=53040, - serialized_end=53160, + serialized_start=52671, + serialized_end=52791, ) @@ -14090,8 +13988,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=53162, - serialized_end=53269, + serialized_start=52793, + serialized_end=52900, ) @@ -14141,8 +14039,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=53389, - serialized_end=53614, + serialized_start=53020, + serialized_end=53245, ) _GETADDRESSINFORESPONSE = _descriptor.Descriptor( @@ -14177,8 +14075,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=53272, - serialized_end=53625, + serialized_start=52903, + serialized_end=53256, ) @@ -14216,8 +14114,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=53750, - serialized_end=53812, + serialized_start=53381, + serialized_end=53443, ) _GETADDRESSESINFOSREQUEST = _descriptor.Descriptor( @@ -14252,8 +14150,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=53628, - serialized_end=53823, + serialized_start=53259, + serialized_end=53454, ) @@ -14303,8 +14201,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=53952, - serialized_end=54184, + serialized_start=53583, + serialized_end=53815, ) _GETADDRESSESINFOSRESPONSE = _descriptor.Descriptor( @@ -14339,8 +14237,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=53826, - serialized_end=54195, + serialized_start=53457, + serialized_end=53826, ) @@ -14364,8 +14262,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=54335, - serialized_end=54368, + serialized_start=53966, + serialized_end=53999, ) _GETADDRESSESTRUNKSTATEREQUEST = _descriptor.Descriptor( @@ -14400,8 +14298,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=54198, - serialized_end=54379, + serialized_start=53829, + serialized_end=54010, ) @@ -14439,8 +14337,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=54523, - serialized_end=54669, + serialized_start=54154, + serialized_end=54300, ) _GETADDRESSESTRUNKSTATERESPONSE = _descriptor.Descriptor( @@ -14475,8 +14373,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=54382, - serialized_end=54680, + serialized_start=54013, + serialized_end=54311, ) @@ -14521,8 +14419,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=54823, - serialized_end=54912, + serialized_start=54454, + serialized_end=54543, ) _GETADDRESSESBRANCHSTATEREQUEST = _descriptor.Descriptor( @@ -14557,8 +14455,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=54683, - serialized_end=54923, + serialized_start=54314, + serialized_end=54554, ) @@ -14589,8 +14487,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=55069, - serialized_end=55124, + serialized_start=54700, + serialized_end=54755, ) _GETADDRESSESBRANCHSTATERESPONSE = _descriptor.Descriptor( @@ -14625,8 +14523,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=54926, - serialized_end=55135, + serialized_start=54557, + serialized_end=54766, ) @@ -14671,8 +14569,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=55299, - serialized_end=55413, + serialized_start=54930, + serialized_end=55044, ) _GETRECENTADDRESSBALANCECHANGESREQUEST = _descriptor.Descriptor( @@ -14707,8 +14605,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=55138, - serialized_end=55424, + serialized_start=54769, + serialized_end=55055, ) @@ -14758,8 +14656,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=55592, - serialized_end=55856, + serialized_start=55223, + serialized_end=55487, ) _GETRECENTADDRESSBALANCECHANGESRESPONSE = _descriptor.Descriptor( @@ -14794,8 +14692,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=55427, - serialized_end=55867, + serialized_start=55058, + serialized_end=55498, ) @@ -14833,8 +14731,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=55869, - serialized_end=55940, + serialized_start=55500, + serialized_end=55571, ) @@ -14884,8 +14782,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=55943, - serialized_end=56119, + serialized_start=55574, + serialized_end=55750, ) @@ -14916,8 +14814,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=56121, - serialized_end=56213, + serialized_start=55752, + serialized_end=55844, ) @@ -14962,8 +14860,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=56216, - serialized_end=56390, + serialized_start=55847, + serialized_end=56021, ) @@ -14994,8 +14892,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=56393, - serialized_end=56528, + serialized_start=56024, + serialized_end=56159, ) @@ -15033,8 +14931,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=56720, - serialized_end=56817, + serialized_start=56351, + serialized_end=56448, ) _GETRECENTCOMPACTEDADDRESSBALANCECHANGESREQUEST = _descriptor.Descriptor( @@ -15069,8 +14967,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=56531, - serialized_end=56828, + serialized_start=56162, + serialized_end=56459, ) @@ -15120,8 +15018,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=57024, - serialized_end=57316, + serialized_start=56655, + serialized_end=56947, ) _GETRECENTCOMPACTEDADDRESSBALANCECHANGESRESPONSE = _descriptor.Descriptor( @@ -15156,8 +15054,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=56831, - serialized_end=57327, + serialized_start=56462, + serialized_end=56958, ) @@ -15202,8 +15100,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=57476, - serialized_end=57563, + serialized_start=57107, + serialized_end=57194, ) _GETSHIELDEDENCRYPTEDNOTESREQUEST = _descriptor.Descriptor( @@ -15238,8 +15136,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=57330, - serialized_end=57574, + serialized_start=56961, + serialized_end=57205, ) @@ -15284,8 +15182,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=58021, - serialized_end=58092, + serialized_start=57652, + serialized_end=57723, ) _GETSHIELDEDENCRYPTEDNOTESRESPONSE_GETSHIELDEDENCRYPTEDNOTESRESPONSEV0_ENCRYPTEDNOTES = _descriptor.Descriptor( @@ -15315,8 +15213,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=58095, - serialized_end=58240, + serialized_start=57726, + serialized_end=57871, ) _GETSHIELDEDENCRYPTEDNOTESRESPONSE_GETSHIELDEDENCRYPTEDNOTESRESPONSEV0 = _descriptor.Descriptor( @@ -15365,8 +15263,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=57727, - serialized_end=58250, + serialized_start=57358, + serialized_end=57881, ) _GETSHIELDEDENCRYPTEDNOTESRESPONSE = _descriptor.Descriptor( @@ -15401,8 +15299,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=57577, - serialized_end=58261, + serialized_start=57208, + serialized_end=57892, ) @@ -15433,8 +15331,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=58389, - serialized_end=58433, + serialized_start=58020, + serialized_end=58064, ) _GETSHIELDEDANCHORSREQUEST = _descriptor.Descriptor( @@ -15469,8 +15367,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=58264, - serialized_end=58444, + serialized_start=57895, + serialized_end=58075, ) @@ -15501,8 +15399,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=58833, - serialized_end=58859, + serialized_start=58464, + serialized_end=58490, ) _GETSHIELDEDANCHORSRESPONSE_GETSHIELDEDANCHORSRESPONSEV0 = _descriptor.Descriptor( @@ -15551,8 +15449,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=58576, - serialized_end=58869, + serialized_start=58207, + serialized_end=58500, ) _GETSHIELDEDANCHORSRESPONSE = _descriptor.Descriptor( @@ -15587,8 +15485,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=58447, - serialized_end=58880, + serialized_start=58078, + serialized_end=58511, ) @@ -15619,8 +15517,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=59035, - serialized_end=59088, + serialized_start=58666, + serialized_end=58719, ) _GETMOSTRECENTSHIELDEDANCHORREQUEST = _descriptor.Descriptor( @@ -15655,8 +15553,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=58883, - serialized_end=59099, + serialized_start=58514, + serialized_end=58730, ) @@ -15706,8 +15604,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=59258, - serialized_end=59439, + serialized_start=58889, + serialized_end=59070, ) _GETMOSTRECENTSHIELDEDANCHORRESPONSE = _descriptor.Descriptor( @@ -15742,8 +15640,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=59102, - serialized_end=59450, + serialized_start=58733, + serialized_end=59081, ) @@ -15774,8 +15672,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=59584, - serialized_end=59630, + serialized_start=59215, + serialized_end=59261, ) _GETSHIELDEDPOOLSTATEREQUEST = _descriptor.Descriptor( @@ -15810,8 +15708,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=59453, - serialized_end=59641, + serialized_start=59084, + serialized_end=59272, ) @@ -15861,8 +15759,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=59779, - serialized_end=59964, + serialized_start=59410, + serialized_end=59595, ) _GETSHIELDEDPOOLSTATERESPONSE = _descriptor.Descriptor( @@ -15897,8 +15795,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=59644, - serialized_end=59975, + serialized_start=59275, + serialized_end=59606, ) @@ -15936,8 +15834,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=60112, - serialized_end=60179, + serialized_start=59743, + serialized_end=59810, ) _GETSHIELDEDNULLIFIERSREQUEST = _descriptor.Descriptor( @@ -15972,8 +15870,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=59978, - serialized_end=60190, + serialized_start=59609, + serialized_end=59821, ) @@ -16011,8 +15909,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=60619, - serialized_end=60673, + serialized_start=60250, + serialized_end=60304, ) _GETSHIELDEDNULLIFIERSRESPONSE_GETSHIELDEDNULLIFIERSRESPONSEV0_NULLIFIERSTATUSES = _descriptor.Descriptor( @@ -16042,8 +15940,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=60676, - serialized_end=60818, + serialized_start=60307, + serialized_end=60449, ) _GETSHIELDEDNULLIFIERSRESPONSE_GETSHIELDEDNULLIFIERSRESPONSEV0 = _descriptor.Descriptor( @@ -16092,8 +15990,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=60331, - serialized_end=60828, + serialized_start=59962, + serialized_end=60459, ) _GETSHIELDEDNULLIFIERSRESPONSE = _descriptor.Descriptor( @@ -16128,8 +16026,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=60193, - serialized_end=60839, + serialized_start=59824, + serialized_end=60470, ) @@ -16167,8 +16065,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=60982, - serialized_end=61060, + serialized_start=60613, + serialized_end=60691, ) _GETNULLIFIERSTRUNKSTATEREQUEST = _descriptor.Descriptor( @@ -16203,8 +16101,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=60842, - serialized_end=61071, + serialized_start=60473, + serialized_end=60702, ) @@ -16242,8 +16140,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=61218, - serialized_end=61365, + serialized_start=60849, + serialized_end=60996, ) _GETNULLIFIERSTRUNKSTATERESPONSE = _descriptor.Descriptor( @@ -16278,8 +16176,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=61074, - serialized_end=61376, + serialized_start=60705, + serialized_end=61007, ) @@ -16338,8 +16236,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=61523, - serialized_end=61657, + serialized_start=61154, + serialized_end=61288, ) _GETNULLIFIERSBRANCHSTATEREQUEST = _descriptor.Descriptor( @@ -16374,8 +16272,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=61379, - serialized_end=61668, + serialized_start=61010, + serialized_end=61299, ) @@ -16406,8 +16304,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=61817, - serialized_end=61873, + serialized_start=61448, + serialized_end=61504, ) _GETNULLIFIERSBRANCHSTATERESPONSE = _descriptor.Descriptor( @@ -16442,8 +16340,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=61671, - serialized_end=61884, + serialized_start=61302, + serialized_end=61515, ) @@ -16481,8 +16379,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=61886, - serialized_end=61955, + serialized_start=61517, + serialized_end=61586, ) @@ -16513,8 +16411,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=61957, - serialized_end=62054, + serialized_start=61588, + serialized_end=61685, ) @@ -16552,8 +16450,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=62203, - serialized_end=62280, + serialized_start=61834, + serialized_end=61911, ) _GETRECENTNULLIFIERCHANGESREQUEST = _descriptor.Descriptor( @@ -16588,8 +16486,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=62057, - serialized_end=62291, + serialized_start=61688, + serialized_end=61922, ) @@ -16639,8 +16537,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=62444, - serialized_end=62692, + serialized_start=62075, + serialized_end=62323, ) _GETRECENTNULLIFIERCHANGESRESPONSE = _descriptor.Descriptor( @@ -16675,8 +16573,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=62294, - serialized_end=62703, + serialized_start=61925, + serialized_end=62334, ) @@ -16721,8 +16619,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=62705, - serialized_end=62819, + serialized_start=62336, + serialized_end=62450, ) @@ -16753,8 +16651,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=62821, - serialized_end=62946, + serialized_start=62452, + serialized_end=62577, ) @@ -16792,8 +16690,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=63122, - serialized_end=63214, + serialized_start=62753, + serialized_end=62845, ) _GETRECENTCOMPACTEDNULLIFIERCHANGESREQUEST = _descriptor.Descriptor( @@ -16828,8 +16726,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=62949, - serialized_end=63225, + serialized_start=62580, + serialized_end=62856, ) @@ -16879,8 +16777,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=63406, - serialized_end=63682, + serialized_start=63037, + serialized_end=63313, ) _GETRECENTCOMPACTEDNULLIFIERCHANGESRESPONSE = _descriptor.Descriptor( @@ -16915,8 +16813,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=63228, - serialized_end=63693, + serialized_start=62859, + serialized_end=63324, ) _GETIDENTITYREQUEST_GETIDENTITYREQUESTV0.containing_type = _GETIDENTITYREQUEST @@ -17241,16 +17139,34 @@ _GETDOCUMENTSRESPONSE.fields_by_name['v0']) _GETDOCUMENTSRESPONSE.fields_by_name['v0'].containing_oneof = _GETDOCUMENTSRESPONSE.oneofs_by_name['version'] _GETDOCUMENTSCOUNTREQUEST_GETDOCUMENTSCOUNTREQUESTV0.containing_type = _GETDOCUMENTSCOUNTREQUEST +_GETDOCUMENTSCOUNTREQUEST_GETDOCUMENTSCOUNTREQUESTV0.oneofs_by_name['_limit'].fields.append( + _GETDOCUMENTSCOUNTREQUEST_GETDOCUMENTSCOUNTREQUESTV0.fields_by_name['limit']) +_GETDOCUMENTSCOUNTREQUEST_GETDOCUMENTSCOUNTREQUESTV0.fields_by_name['limit'].containing_oneof = _GETDOCUMENTSCOUNTREQUEST_GETDOCUMENTSCOUNTREQUESTV0.oneofs_by_name['_limit'] _GETDOCUMENTSCOUNTREQUEST.fields_by_name['v0'].message_type = _GETDOCUMENTSCOUNTREQUEST_GETDOCUMENTSCOUNTREQUESTV0 _GETDOCUMENTSCOUNTREQUEST.oneofs_by_name['version'].fields.append( _GETDOCUMENTSCOUNTREQUEST.fields_by_name['v0']) _GETDOCUMENTSCOUNTREQUEST.fields_by_name['v0'].containing_oneof = _GETDOCUMENTSCOUNTREQUEST.oneofs_by_name['version'] +_GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0_COUNTENTRY.containing_type = _GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0 +_GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0_COUNTENTRY.oneofs_by_name['_in_key'].fields.append( + _GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0_COUNTENTRY.fields_by_name['in_key']) +_GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0_COUNTENTRY.fields_by_name['in_key'].containing_oneof = _GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0_COUNTENTRY.oneofs_by_name['_in_key'] +_GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0_COUNTENTRIES.fields_by_name['entries'].message_type = _GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0_COUNTENTRY +_GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0_COUNTENTRIES.containing_type = _GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0 +_GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0_COUNTRESULTS.fields_by_name['entries'].message_type = _GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0_COUNTENTRIES +_GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0_COUNTRESULTS.containing_type = _GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0 +_GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0_COUNTRESULTS.oneofs_by_name['variant'].fields.append( + _GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0_COUNTRESULTS.fields_by_name['aggregate_count']) +_GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0_COUNTRESULTS.fields_by_name['aggregate_count'].containing_oneof = _GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0_COUNTRESULTS.oneofs_by_name['variant'] +_GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0_COUNTRESULTS.oneofs_by_name['variant'].fields.append( + _GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0_COUNTRESULTS.fields_by_name['entries']) +_GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0_COUNTRESULTS.fields_by_name['entries'].containing_oneof = _GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0_COUNTRESULTS.oneofs_by_name['variant'] +_GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0.fields_by_name['counts'].message_type = _GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0_COUNTRESULTS _GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0.fields_by_name['proof'].message_type = _PROOF _GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0.fields_by_name['metadata'].message_type = _RESPONSEMETADATA _GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0.containing_type = _GETDOCUMENTSCOUNTRESPONSE _GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0.oneofs_by_name['result'].fields.append( - _GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0.fields_by_name['count']) -_GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0.fields_by_name['count'].containing_oneof = _GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0.oneofs_by_name['result'] + _GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0.fields_by_name['counts']) +_GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0.fields_by_name['counts'].containing_oneof = _GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0.oneofs_by_name['result'] _GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0.oneofs_by_name['result'].fields.append( _GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0.fields_by_name['proof']) _GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0.fields_by_name['proof'].containing_oneof = _GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0.oneofs_by_name['result'] @@ -17258,28 +17174,6 @@ _GETDOCUMENTSCOUNTRESPONSE.oneofs_by_name['version'].fields.append( _GETDOCUMENTSCOUNTRESPONSE.fields_by_name['v0']) _GETDOCUMENTSCOUNTRESPONSE.fields_by_name['v0'].containing_oneof = _GETDOCUMENTSCOUNTRESPONSE.oneofs_by_name['version'] -_GETDOCUMENTSSPLITCOUNTREQUEST_GETDOCUMENTSSPLITCOUNTREQUESTV0.containing_type = _GETDOCUMENTSSPLITCOUNTREQUEST -_GETDOCUMENTSSPLITCOUNTREQUEST.fields_by_name['v0'].message_type = _GETDOCUMENTSSPLITCOUNTREQUEST_GETDOCUMENTSSPLITCOUNTREQUESTV0 -_GETDOCUMENTSSPLITCOUNTREQUEST.oneofs_by_name['version'].fields.append( - _GETDOCUMENTSSPLITCOUNTREQUEST.fields_by_name['v0']) -_GETDOCUMENTSSPLITCOUNTREQUEST.fields_by_name['v0'].containing_oneof = _GETDOCUMENTSSPLITCOUNTREQUEST.oneofs_by_name['version'] -_GETDOCUMENTSSPLITCOUNTRESPONSE_GETDOCUMENTSSPLITCOUNTRESPONSEV0_SPLITCOUNTENTRY.containing_type = _GETDOCUMENTSSPLITCOUNTRESPONSE_GETDOCUMENTSSPLITCOUNTRESPONSEV0 -_GETDOCUMENTSSPLITCOUNTRESPONSE_GETDOCUMENTSSPLITCOUNTRESPONSEV0_SPLITCOUNTS.fields_by_name['entries'].message_type = _GETDOCUMENTSSPLITCOUNTRESPONSE_GETDOCUMENTSSPLITCOUNTRESPONSEV0_SPLITCOUNTENTRY -_GETDOCUMENTSSPLITCOUNTRESPONSE_GETDOCUMENTSSPLITCOUNTRESPONSEV0_SPLITCOUNTS.containing_type = _GETDOCUMENTSSPLITCOUNTRESPONSE_GETDOCUMENTSSPLITCOUNTRESPONSEV0 -_GETDOCUMENTSSPLITCOUNTRESPONSE_GETDOCUMENTSSPLITCOUNTRESPONSEV0.fields_by_name['split_counts'].message_type = _GETDOCUMENTSSPLITCOUNTRESPONSE_GETDOCUMENTSSPLITCOUNTRESPONSEV0_SPLITCOUNTS -_GETDOCUMENTSSPLITCOUNTRESPONSE_GETDOCUMENTSSPLITCOUNTRESPONSEV0.fields_by_name['proof'].message_type = _PROOF -_GETDOCUMENTSSPLITCOUNTRESPONSE_GETDOCUMENTSSPLITCOUNTRESPONSEV0.fields_by_name['metadata'].message_type = _RESPONSEMETADATA -_GETDOCUMENTSSPLITCOUNTRESPONSE_GETDOCUMENTSSPLITCOUNTRESPONSEV0.containing_type = _GETDOCUMENTSSPLITCOUNTRESPONSE -_GETDOCUMENTSSPLITCOUNTRESPONSE_GETDOCUMENTSSPLITCOUNTRESPONSEV0.oneofs_by_name['result'].fields.append( - _GETDOCUMENTSSPLITCOUNTRESPONSE_GETDOCUMENTSSPLITCOUNTRESPONSEV0.fields_by_name['split_counts']) -_GETDOCUMENTSSPLITCOUNTRESPONSE_GETDOCUMENTSSPLITCOUNTRESPONSEV0.fields_by_name['split_counts'].containing_oneof = _GETDOCUMENTSSPLITCOUNTRESPONSE_GETDOCUMENTSSPLITCOUNTRESPONSEV0.oneofs_by_name['result'] -_GETDOCUMENTSSPLITCOUNTRESPONSE_GETDOCUMENTSSPLITCOUNTRESPONSEV0.oneofs_by_name['result'].fields.append( - _GETDOCUMENTSSPLITCOUNTRESPONSE_GETDOCUMENTSSPLITCOUNTRESPONSEV0.fields_by_name['proof']) -_GETDOCUMENTSSPLITCOUNTRESPONSE_GETDOCUMENTSSPLITCOUNTRESPONSEV0.fields_by_name['proof'].containing_oneof = _GETDOCUMENTSSPLITCOUNTRESPONSE_GETDOCUMENTSSPLITCOUNTRESPONSEV0.oneofs_by_name['result'] -_GETDOCUMENTSSPLITCOUNTRESPONSE.fields_by_name['v0'].message_type = _GETDOCUMENTSSPLITCOUNTRESPONSE_GETDOCUMENTSSPLITCOUNTRESPONSEV0 -_GETDOCUMENTSSPLITCOUNTRESPONSE.oneofs_by_name['version'].fields.append( - _GETDOCUMENTSSPLITCOUNTRESPONSE.fields_by_name['v0']) -_GETDOCUMENTSSPLITCOUNTRESPONSE.fields_by_name['v0'].containing_oneof = _GETDOCUMENTSSPLITCOUNTRESPONSE.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( @@ -18577,8 +18471,6 @@ DESCRIPTOR.message_types_by_name['GetDocumentsResponse'] = _GETDOCUMENTSRESPONSE DESCRIPTOR.message_types_by_name['GetDocumentsCountRequest'] = _GETDOCUMENTSCOUNTREQUEST DESCRIPTOR.message_types_by_name['GetDocumentsCountResponse'] = _GETDOCUMENTSCOUNTRESPONSE -DESCRIPTOR.message_types_by_name['GetDocumentsSplitCountRequest'] = _GETDOCUMENTSSPLITCOUNTREQUEST -DESCRIPTOR.message_types_by_name['GetDocumentsSplitCountResponse'] = _GETDOCUMENTSSPLITCOUNTRESPONSE DESCRIPTOR.message_types_by_name['GetIdentityByPublicKeyHashRequest'] = _GETIDENTITYBYPUBLICKEYHASHREQUEST DESCRIPTOR.message_types_by_name['GetIdentityByPublicKeyHashResponse'] = _GETIDENTITYBYPUBLICKEYHASHRESPONSE DESCRIPTOR.message_types_by_name['GetIdentityByNonUniquePublicKeyHashRequest'] = _GETIDENTITYBYNONUNIQUEPUBLICKEYHASHREQUEST @@ -19312,63 +19204,41 @@ GetDocumentsCountResponse = _reflection.GeneratedProtocolMessageType('GetDocumentsCountResponse', (_message.Message,), { 'GetDocumentsCountResponseV0' : _reflection.GeneratedProtocolMessageType('GetDocumentsCountResponseV0', (_message.Message,), { - 'DESCRIPTOR' : _GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0, - '__module__' : 'platform_pb2' - # @@protoc_insertion_point(class_scope:org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0) - }) - , - 'DESCRIPTOR' : _GETDOCUMENTSCOUNTRESPONSE, - '__module__' : 'platform_pb2' - # @@protoc_insertion_point(class_scope:org.dash.platform.dapi.v0.GetDocumentsCountResponse) - }) -_sym_db.RegisterMessage(GetDocumentsCountResponse) -_sym_db.RegisterMessage(GetDocumentsCountResponse.GetDocumentsCountResponseV0) - -GetDocumentsSplitCountRequest = _reflection.GeneratedProtocolMessageType('GetDocumentsSplitCountRequest', (_message.Message,), { - - 'GetDocumentsSplitCountRequestV0' : _reflection.GeneratedProtocolMessageType('GetDocumentsSplitCountRequestV0', (_message.Message,), { - 'DESCRIPTOR' : _GETDOCUMENTSSPLITCOUNTREQUEST_GETDOCUMENTSSPLITCOUNTREQUESTV0, - '__module__' : 'platform_pb2' - # @@protoc_insertion_point(class_scope:org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0) - }) - , - 'DESCRIPTOR' : _GETDOCUMENTSSPLITCOUNTREQUEST, - '__module__' : 'platform_pb2' - # @@protoc_insertion_point(class_scope:org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest) - }) -_sym_db.RegisterMessage(GetDocumentsSplitCountRequest) -_sym_db.RegisterMessage(GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0) - -GetDocumentsSplitCountResponse = _reflection.GeneratedProtocolMessageType('GetDocumentsSplitCountResponse', (_message.Message,), { - 'GetDocumentsSplitCountResponseV0' : _reflection.GeneratedProtocolMessageType('GetDocumentsSplitCountResponseV0', (_message.Message,), { + 'CountEntry' : _reflection.GeneratedProtocolMessageType('CountEntry', (_message.Message,), { + 'DESCRIPTOR' : _GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0_COUNTENTRY, + '__module__' : 'platform_pb2' + # @@protoc_insertion_point(class_scope:org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry) + }) + , - 'SplitCountEntry' : _reflection.GeneratedProtocolMessageType('SplitCountEntry', (_message.Message,), { - 'DESCRIPTOR' : _GETDOCUMENTSSPLITCOUNTRESPONSE_GETDOCUMENTSSPLITCOUNTRESPONSEV0_SPLITCOUNTENTRY, + 'CountEntries' : _reflection.GeneratedProtocolMessageType('CountEntries', (_message.Message,), { + 'DESCRIPTOR' : _GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0_COUNTENTRIES, '__module__' : 'platform_pb2' - # @@protoc_insertion_point(class_scope:org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry) + # @@protoc_insertion_point(class_scope:org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries) }) , - 'SplitCounts' : _reflection.GeneratedProtocolMessageType('SplitCounts', (_message.Message,), { - 'DESCRIPTOR' : _GETDOCUMENTSSPLITCOUNTRESPONSE_GETDOCUMENTSSPLITCOUNTRESPONSEV0_SPLITCOUNTS, + 'CountResults' : _reflection.GeneratedProtocolMessageType('CountResults', (_message.Message,), { + 'DESCRIPTOR' : _GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0_COUNTRESULTS, '__module__' : 'platform_pb2' - # @@protoc_insertion_point(class_scope:org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts) + # @@protoc_insertion_point(class_scope:org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults) }) , - 'DESCRIPTOR' : _GETDOCUMENTSSPLITCOUNTRESPONSE_GETDOCUMENTSSPLITCOUNTRESPONSEV0, + 'DESCRIPTOR' : _GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0, '__module__' : 'platform_pb2' - # @@protoc_insertion_point(class_scope:org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0) + # @@protoc_insertion_point(class_scope:org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0) }) , - 'DESCRIPTOR' : _GETDOCUMENTSSPLITCOUNTRESPONSE, + 'DESCRIPTOR' : _GETDOCUMENTSCOUNTRESPONSE, '__module__' : 'platform_pb2' - # @@protoc_insertion_point(class_scope:org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse) + # @@protoc_insertion_point(class_scope:org.dash.platform.dapi.v0.GetDocumentsCountResponse) }) -_sym_db.RegisterMessage(GetDocumentsSplitCountResponse) -_sym_db.RegisterMessage(GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0) -_sym_db.RegisterMessage(GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry) -_sym_db.RegisterMessage(GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts) +_sym_db.RegisterMessage(GetDocumentsCountResponse) +_sym_db.RegisterMessage(GetDocumentsCountResponse.GetDocumentsCountResponseV0) +_sym_db.RegisterMessage(GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry) +_sym_db.RegisterMessage(GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries) +_sym_db.RegisterMessage(GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults) GetIdentityByPublicKeyHashRequest = _reflection.GeneratedProtocolMessageType('GetIdentityByPublicKeyHashRequest', (_message.Message,), { @@ -21707,6 +21577,8 @@ _GETIDENTITIESBALANCESRESPONSE_GETIDENTITIESBALANCESRESPONSEV0_IDENTITYBALANCE.fields_by_name['balance']._options = None _GETDATACONTRACTHISTORYREQUEST_GETDATACONTRACTHISTORYREQUESTV0.fields_by_name['start_at_ms']._options = None _GETDATACONTRACTHISTORYRESPONSE_GETDATACONTRACTHISTORYRESPONSEV0_DATACONTRACTHISTORYENTRY.fields_by_name['date']._options = None +_GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0_COUNTENTRY.fields_by_name['count']._options = None +_GETDOCUMENTSCOUNTRESPONSE_GETDOCUMENTSCOUNTRESPONSEV0_COUNTRESULTS.fields_by_name['aggregate_count']._options = None _GETEPOCHSINFORESPONSE_GETEPOCHSINFORESPONSEV0_EPOCHINFO.fields_by_name['first_block_height']._options = None _GETEPOCHSINFORESPONSE_GETEPOCHSINFORESPONSEV0_EPOCHINFO.fields_by_name['start_time']._options = None _GETFINALIZEDEPOCHINFOSRESPONSE_GETFINALIZEDEPOCHINFOSRESPONSEV0_FINALIZEDEPOCHINFO.fields_by_name['first_block_height']._options = None @@ -21762,8 +21634,8 @@ index=0, serialized_options=None, create_key=_descriptor._internal_create_key, - serialized_start=63788, - serialized_end=73199, + serialized_start=63419, + serialized_end=72686, methods=[ _descriptor.MethodDescriptor( name='broadcastStateTransition', @@ -21925,20 +21797,10 @@ serialized_options=None, create_key=_descriptor._internal_create_key, ), - _descriptor.MethodDescriptor( - name='getDocumentsSplitCount', - full_name='org.dash.platform.dapi.v0.Platform.getDocumentsSplitCount', - index=16, - containing_service=None, - input_type=_GETDOCUMENTSSPLITCOUNTREQUEST, - output_type=_GETDOCUMENTSSPLITCOUNTRESPONSE, - serialized_options=None, - create_key=_descriptor._internal_create_key, - ), _descriptor.MethodDescriptor( name='getIdentityByPublicKeyHash', full_name='org.dash.platform.dapi.v0.Platform.getIdentityByPublicKeyHash', - index=17, + index=16, containing_service=None, input_type=_GETIDENTITYBYPUBLICKEYHASHREQUEST, output_type=_GETIDENTITYBYPUBLICKEYHASHRESPONSE, @@ -21948,7 +21810,7 @@ _descriptor.MethodDescriptor( name='getIdentityByNonUniquePublicKeyHash', full_name='org.dash.platform.dapi.v0.Platform.getIdentityByNonUniquePublicKeyHash', - index=18, + index=17, containing_service=None, input_type=_GETIDENTITYBYNONUNIQUEPUBLICKEYHASHREQUEST, output_type=_GETIDENTITYBYNONUNIQUEPUBLICKEYHASHRESPONSE, @@ -21958,7 +21820,7 @@ _descriptor.MethodDescriptor( name='waitForStateTransitionResult', full_name='org.dash.platform.dapi.v0.Platform.waitForStateTransitionResult', - index=19, + index=18, containing_service=None, input_type=_WAITFORSTATETRANSITIONRESULTREQUEST, output_type=_WAITFORSTATETRANSITIONRESULTRESPONSE, @@ -21968,7 +21830,7 @@ _descriptor.MethodDescriptor( name='getConsensusParams', full_name='org.dash.platform.dapi.v0.Platform.getConsensusParams', - index=20, + index=19, containing_service=None, input_type=_GETCONSENSUSPARAMSREQUEST, output_type=_GETCONSENSUSPARAMSRESPONSE, @@ -21978,7 +21840,7 @@ _descriptor.MethodDescriptor( name='getProtocolVersionUpgradeState', full_name='org.dash.platform.dapi.v0.Platform.getProtocolVersionUpgradeState', - index=21, + index=20, containing_service=None, input_type=_GETPROTOCOLVERSIONUPGRADESTATEREQUEST, output_type=_GETPROTOCOLVERSIONUPGRADESTATERESPONSE, @@ -21988,7 +21850,7 @@ _descriptor.MethodDescriptor( name='getProtocolVersionUpgradeVoteStatus', full_name='org.dash.platform.dapi.v0.Platform.getProtocolVersionUpgradeVoteStatus', - index=22, + index=21, containing_service=None, input_type=_GETPROTOCOLVERSIONUPGRADEVOTESTATUSREQUEST, output_type=_GETPROTOCOLVERSIONUPGRADEVOTESTATUSRESPONSE, @@ -21998,7 +21860,7 @@ _descriptor.MethodDescriptor( name='getEpochsInfo', full_name='org.dash.platform.dapi.v0.Platform.getEpochsInfo', - index=23, + index=22, containing_service=None, input_type=_GETEPOCHSINFOREQUEST, output_type=_GETEPOCHSINFORESPONSE, @@ -22008,7 +21870,7 @@ _descriptor.MethodDescriptor( name='getFinalizedEpochInfos', full_name='org.dash.platform.dapi.v0.Platform.getFinalizedEpochInfos', - index=24, + index=23, containing_service=None, input_type=_GETFINALIZEDEPOCHINFOSREQUEST, output_type=_GETFINALIZEDEPOCHINFOSRESPONSE, @@ -22018,7 +21880,7 @@ _descriptor.MethodDescriptor( name='getContestedResources', full_name='org.dash.platform.dapi.v0.Platform.getContestedResources', - index=25, + index=24, containing_service=None, input_type=_GETCONTESTEDRESOURCESREQUEST, output_type=_GETCONTESTEDRESOURCESRESPONSE, @@ -22028,7 +21890,7 @@ _descriptor.MethodDescriptor( name='getContestedResourceVoteState', full_name='org.dash.platform.dapi.v0.Platform.getContestedResourceVoteState', - index=26, + index=25, containing_service=None, input_type=_GETCONTESTEDRESOURCEVOTESTATEREQUEST, output_type=_GETCONTESTEDRESOURCEVOTESTATERESPONSE, @@ -22038,7 +21900,7 @@ _descriptor.MethodDescriptor( name='getContestedResourceVotersForIdentity', full_name='org.dash.platform.dapi.v0.Platform.getContestedResourceVotersForIdentity', - index=27, + index=26, containing_service=None, input_type=_GETCONTESTEDRESOURCEVOTERSFORIDENTITYREQUEST, output_type=_GETCONTESTEDRESOURCEVOTERSFORIDENTITYRESPONSE, @@ -22048,7 +21910,7 @@ _descriptor.MethodDescriptor( name='getContestedResourceIdentityVotes', full_name='org.dash.platform.dapi.v0.Platform.getContestedResourceIdentityVotes', - index=28, + index=27, containing_service=None, input_type=_GETCONTESTEDRESOURCEIDENTITYVOTESREQUEST, output_type=_GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSE, @@ -22058,7 +21920,7 @@ _descriptor.MethodDescriptor( name='getVotePollsByEndDate', full_name='org.dash.platform.dapi.v0.Platform.getVotePollsByEndDate', - index=29, + index=28, containing_service=None, input_type=_GETVOTEPOLLSBYENDDATEREQUEST, output_type=_GETVOTEPOLLSBYENDDATERESPONSE, @@ -22068,7 +21930,7 @@ _descriptor.MethodDescriptor( name='getPrefundedSpecializedBalance', full_name='org.dash.platform.dapi.v0.Platform.getPrefundedSpecializedBalance', - index=30, + index=29, containing_service=None, input_type=_GETPREFUNDEDSPECIALIZEDBALANCEREQUEST, output_type=_GETPREFUNDEDSPECIALIZEDBALANCERESPONSE, @@ -22078,7 +21940,7 @@ _descriptor.MethodDescriptor( name='getTotalCreditsInPlatform', full_name='org.dash.platform.dapi.v0.Platform.getTotalCreditsInPlatform', - index=31, + index=30, containing_service=None, input_type=_GETTOTALCREDITSINPLATFORMREQUEST, output_type=_GETTOTALCREDITSINPLATFORMRESPONSE, @@ -22088,7 +21950,7 @@ _descriptor.MethodDescriptor( name='getPathElements', full_name='org.dash.platform.dapi.v0.Platform.getPathElements', - index=32, + index=31, containing_service=None, input_type=_GETPATHELEMENTSREQUEST, output_type=_GETPATHELEMENTSRESPONSE, @@ -22098,7 +21960,7 @@ _descriptor.MethodDescriptor( name='getStatus', full_name='org.dash.platform.dapi.v0.Platform.getStatus', - index=33, + index=32, containing_service=None, input_type=_GETSTATUSREQUEST, output_type=_GETSTATUSRESPONSE, @@ -22108,7 +21970,7 @@ _descriptor.MethodDescriptor( name='getCurrentQuorumsInfo', full_name='org.dash.platform.dapi.v0.Platform.getCurrentQuorumsInfo', - index=34, + index=33, containing_service=None, input_type=_GETCURRENTQUORUMSINFOREQUEST, output_type=_GETCURRENTQUORUMSINFORESPONSE, @@ -22118,7 +21980,7 @@ _descriptor.MethodDescriptor( name='getIdentityTokenBalances', full_name='org.dash.platform.dapi.v0.Platform.getIdentityTokenBalances', - index=35, + index=34, containing_service=None, input_type=_GETIDENTITYTOKENBALANCESREQUEST, output_type=_GETIDENTITYTOKENBALANCESRESPONSE, @@ -22128,7 +21990,7 @@ _descriptor.MethodDescriptor( name='getIdentitiesTokenBalances', full_name='org.dash.platform.dapi.v0.Platform.getIdentitiesTokenBalances', - index=36, + index=35, containing_service=None, input_type=_GETIDENTITIESTOKENBALANCESREQUEST, output_type=_GETIDENTITIESTOKENBALANCESRESPONSE, @@ -22138,7 +22000,7 @@ _descriptor.MethodDescriptor( name='getIdentityTokenInfos', full_name='org.dash.platform.dapi.v0.Platform.getIdentityTokenInfos', - index=37, + index=36, containing_service=None, input_type=_GETIDENTITYTOKENINFOSREQUEST, output_type=_GETIDENTITYTOKENINFOSRESPONSE, @@ -22148,7 +22010,7 @@ _descriptor.MethodDescriptor( name='getIdentitiesTokenInfos', full_name='org.dash.platform.dapi.v0.Platform.getIdentitiesTokenInfos', - index=38, + index=37, containing_service=None, input_type=_GETIDENTITIESTOKENINFOSREQUEST, output_type=_GETIDENTITIESTOKENINFOSRESPONSE, @@ -22158,7 +22020,7 @@ _descriptor.MethodDescriptor( name='getTokenStatuses', full_name='org.dash.platform.dapi.v0.Platform.getTokenStatuses', - index=39, + index=38, containing_service=None, input_type=_GETTOKENSTATUSESREQUEST, output_type=_GETTOKENSTATUSESRESPONSE, @@ -22168,7 +22030,7 @@ _descriptor.MethodDescriptor( name='getTokenDirectPurchasePrices', full_name='org.dash.platform.dapi.v0.Platform.getTokenDirectPurchasePrices', - index=40, + index=39, containing_service=None, input_type=_GETTOKENDIRECTPURCHASEPRICESREQUEST, output_type=_GETTOKENDIRECTPURCHASEPRICESRESPONSE, @@ -22178,7 +22040,7 @@ _descriptor.MethodDescriptor( name='getTokenContractInfo', full_name='org.dash.platform.dapi.v0.Platform.getTokenContractInfo', - index=41, + index=40, containing_service=None, input_type=_GETTOKENCONTRACTINFOREQUEST, output_type=_GETTOKENCONTRACTINFORESPONSE, @@ -22188,7 +22050,7 @@ _descriptor.MethodDescriptor( name='getTokenPreProgrammedDistributions', full_name='org.dash.platform.dapi.v0.Platform.getTokenPreProgrammedDistributions', - index=42, + index=41, containing_service=None, input_type=_GETTOKENPREPROGRAMMEDDISTRIBUTIONSREQUEST, output_type=_GETTOKENPREPROGRAMMEDDISTRIBUTIONSRESPONSE, @@ -22198,7 +22060,7 @@ _descriptor.MethodDescriptor( name='getTokenPerpetualDistributionLastClaim', full_name='org.dash.platform.dapi.v0.Platform.getTokenPerpetualDistributionLastClaim', - index=43, + index=42, containing_service=None, input_type=_GETTOKENPERPETUALDISTRIBUTIONLASTCLAIMREQUEST, output_type=_GETTOKENPERPETUALDISTRIBUTIONLASTCLAIMRESPONSE, @@ -22208,7 +22070,7 @@ _descriptor.MethodDescriptor( name='getTokenTotalSupply', full_name='org.dash.platform.dapi.v0.Platform.getTokenTotalSupply', - index=44, + index=43, containing_service=None, input_type=_GETTOKENTOTALSUPPLYREQUEST, output_type=_GETTOKENTOTALSUPPLYRESPONSE, @@ -22218,7 +22080,7 @@ _descriptor.MethodDescriptor( name='getGroupInfo', full_name='org.dash.platform.dapi.v0.Platform.getGroupInfo', - index=45, + index=44, containing_service=None, input_type=_GETGROUPINFOREQUEST, output_type=_GETGROUPINFORESPONSE, @@ -22228,7 +22090,7 @@ _descriptor.MethodDescriptor( name='getGroupInfos', full_name='org.dash.platform.dapi.v0.Platform.getGroupInfos', - index=46, + index=45, containing_service=None, input_type=_GETGROUPINFOSREQUEST, output_type=_GETGROUPINFOSRESPONSE, @@ -22238,7 +22100,7 @@ _descriptor.MethodDescriptor( name='getGroupActions', full_name='org.dash.platform.dapi.v0.Platform.getGroupActions', - index=47, + index=46, containing_service=None, input_type=_GETGROUPACTIONSREQUEST, output_type=_GETGROUPACTIONSRESPONSE, @@ -22248,7 +22110,7 @@ _descriptor.MethodDescriptor( name='getGroupActionSigners', full_name='org.dash.platform.dapi.v0.Platform.getGroupActionSigners', - index=48, + index=47, containing_service=None, input_type=_GETGROUPACTIONSIGNERSREQUEST, output_type=_GETGROUPACTIONSIGNERSRESPONSE, @@ -22258,7 +22120,7 @@ _descriptor.MethodDescriptor( name='getAddressInfo', full_name='org.dash.platform.dapi.v0.Platform.getAddressInfo', - index=49, + index=48, containing_service=None, input_type=_GETADDRESSINFOREQUEST, output_type=_GETADDRESSINFORESPONSE, @@ -22268,7 +22130,7 @@ _descriptor.MethodDescriptor( name='getAddressesInfos', full_name='org.dash.platform.dapi.v0.Platform.getAddressesInfos', - index=50, + index=49, containing_service=None, input_type=_GETADDRESSESINFOSREQUEST, output_type=_GETADDRESSESINFOSRESPONSE, @@ -22278,7 +22140,7 @@ _descriptor.MethodDescriptor( name='getAddressesTrunkState', full_name='org.dash.platform.dapi.v0.Platform.getAddressesTrunkState', - index=51, + index=50, containing_service=None, input_type=_GETADDRESSESTRUNKSTATEREQUEST, output_type=_GETADDRESSESTRUNKSTATERESPONSE, @@ -22288,7 +22150,7 @@ _descriptor.MethodDescriptor( name='getAddressesBranchState', full_name='org.dash.platform.dapi.v0.Platform.getAddressesBranchState', - index=52, + index=51, containing_service=None, input_type=_GETADDRESSESBRANCHSTATEREQUEST, output_type=_GETADDRESSESBRANCHSTATERESPONSE, @@ -22298,7 +22160,7 @@ _descriptor.MethodDescriptor( name='getRecentAddressBalanceChanges', full_name='org.dash.platform.dapi.v0.Platform.getRecentAddressBalanceChanges', - index=53, + index=52, containing_service=None, input_type=_GETRECENTADDRESSBALANCECHANGESREQUEST, output_type=_GETRECENTADDRESSBALANCECHANGESRESPONSE, @@ -22308,7 +22170,7 @@ _descriptor.MethodDescriptor( name='getRecentCompactedAddressBalanceChanges', full_name='org.dash.platform.dapi.v0.Platform.getRecentCompactedAddressBalanceChanges', - index=54, + index=53, containing_service=None, input_type=_GETRECENTCOMPACTEDADDRESSBALANCECHANGESREQUEST, output_type=_GETRECENTCOMPACTEDADDRESSBALANCECHANGESRESPONSE, @@ -22318,7 +22180,7 @@ _descriptor.MethodDescriptor( name='getShieldedEncryptedNotes', full_name='org.dash.platform.dapi.v0.Platform.getShieldedEncryptedNotes', - index=55, + index=54, containing_service=None, input_type=_GETSHIELDEDENCRYPTEDNOTESREQUEST, output_type=_GETSHIELDEDENCRYPTEDNOTESRESPONSE, @@ -22328,7 +22190,7 @@ _descriptor.MethodDescriptor( name='getShieldedAnchors', full_name='org.dash.platform.dapi.v0.Platform.getShieldedAnchors', - index=56, + index=55, containing_service=None, input_type=_GETSHIELDEDANCHORSREQUEST, output_type=_GETSHIELDEDANCHORSRESPONSE, @@ -22338,7 +22200,7 @@ _descriptor.MethodDescriptor( name='getMostRecentShieldedAnchor', full_name='org.dash.platform.dapi.v0.Platform.getMostRecentShieldedAnchor', - index=57, + index=56, containing_service=None, input_type=_GETMOSTRECENTSHIELDEDANCHORREQUEST, output_type=_GETMOSTRECENTSHIELDEDANCHORRESPONSE, @@ -22348,7 +22210,7 @@ _descriptor.MethodDescriptor( name='getShieldedPoolState', full_name='org.dash.platform.dapi.v0.Platform.getShieldedPoolState', - index=58, + index=57, containing_service=None, input_type=_GETSHIELDEDPOOLSTATEREQUEST, output_type=_GETSHIELDEDPOOLSTATERESPONSE, @@ -22358,7 +22220,7 @@ _descriptor.MethodDescriptor( name='getShieldedNullifiers', full_name='org.dash.platform.dapi.v0.Platform.getShieldedNullifiers', - index=59, + index=58, containing_service=None, input_type=_GETSHIELDEDNULLIFIERSREQUEST, output_type=_GETSHIELDEDNULLIFIERSRESPONSE, @@ -22368,7 +22230,7 @@ _descriptor.MethodDescriptor( name='getNullifiersTrunkState', full_name='org.dash.platform.dapi.v0.Platform.getNullifiersTrunkState', - index=60, + index=59, containing_service=None, input_type=_GETNULLIFIERSTRUNKSTATEREQUEST, output_type=_GETNULLIFIERSTRUNKSTATERESPONSE, @@ -22378,7 +22240,7 @@ _descriptor.MethodDescriptor( name='getNullifiersBranchState', full_name='org.dash.platform.dapi.v0.Platform.getNullifiersBranchState', - index=61, + index=60, containing_service=None, input_type=_GETNULLIFIERSBRANCHSTATEREQUEST, output_type=_GETNULLIFIERSBRANCHSTATERESPONSE, @@ -22388,7 +22250,7 @@ _descriptor.MethodDescriptor( name='getRecentNullifierChanges', full_name='org.dash.platform.dapi.v0.Platform.getRecentNullifierChanges', - index=62, + index=61, containing_service=None, input_type=_GETRECENTNULLIFIERCHANGESREQUEST, output_type=_GETRECENTNULLIFIERCHANGESRESPONSE, @@ -22398,7 +22260,7 @@ _descriptor.MethodDescriptor( name='getRecentCompactedNullifierChanges', full_name='org.dash.platform.dapi.v0.Platform.getRecentCompactedNullifierChanges', - index=63, + index=62, containing_service=None, input_type=_GETRECENTCOMPACTEDNULLIFIERCHANGESREQUEST, output_type=_GETRECENTCOMPACTEDNULLIFIERCHANGESRESPONSE, diff --git a/packages/dapi-grpc/clients/platform/v0/python/platform_pb2_grpc.py b/packages/dapi-grpc/clients/platform/v0/python/platform_pb2_grpc.py index 13785d5c8e0..281b978988d 100644 --- a/packages/dapi-grpc/clients/platform/v0/python/platform_pb2_grpc.py +++ b/packages/dapi-grpc/clients/platform/v0/python/platform_pb2_grpc.py @@ -94,11 +94,6 @@ def __init__(self, channel): request_serializer=platform__pb2.GetDocumentsCountRequest.SerializeToString, response_deserializer=platform__pb2.GetDocumentsCountResponse.FromString, ) - self.getDocumentsSplitCount = channel.unary_unary( - '/org.dash.platform.dapi.v0.Platform/getDocumentsSplitCount', - request_serializer=platform__pb2.GetDocumentsSplitCountRequest.SerializeToString, - response_deserializer=platform__pb2.GetDocumentsSplitCountResponse.FromString, - ) self.getIdentityByPublicKeyHash = channel.unary_unary( '/org.dash.platform.dapi.v0.Platform/getIdentityByPublicKeyHash', request_serializer=platform__pb2.GetIdentityByPublicKeyHashRequest.SerializeToString, @@ -436,12 +431,6 @@ def getDocumentsCount(self, request, context): context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') - def getDocumentsSplitCount(self, request, context): - """Missing associated documentation comment in .proto file.""" - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') - def getIdentityByPublicKeyHash(self, request, context): """Missing associated documentation comment in .proto file.""" context.set_code(grpc.StatusCode.UNIMPLEMENTED) @@ -813,11 +802,6 @@ def add_PlatformServicer_to_server(servicer, server): request_deserializer=platform__pb2.GetDocumentsCountRequest.FromString, response_serializer=platform__pb2.GetDocumentsCountResponse.SerializeToString, ), - 'getDocumentsSplitCount': grpc.unary_unary_rpc_method_handler( - servicer.getDocumentsSplitCount, - request_deserializer=platform__pb2.GetDocumentsSplitCountRequest.FromString, - response_serializer=platform__pb2.GetDocumentsSplitCountResponse.SerializeToString, - ), 'getIdentityByPublicKeyHash': grpc.unary_unary_rpc_method_handler( servicer.getIdentityByPublicKeyHash, request_deserializer=platform__pb2.GetIdentityByPublicKeyHashRequest.FromString, @@ -1335,23 +1319,6 @@ def getDocumentsCount(request, options, channel_credentials, insecure, call_credentials, compression, wait_for_ready, timeout, metadata) - @staticmethod - def getDocumentsSplitCount(request, - target, - options=(), - channel_credentials=None, - call_credentials=None, - insecure=False, - compression=None, - wait_for_ready=None, - timeout=None, - metadata=None): - return grpc.experimental.unary_unary(request, target, '/org.dash.platform.dapi.v0.Platform/getDocumentsSplitCount', - platform__pb2.GetDocumentsSplitCountRequest.SerializeToString, - platform__pb2.GetDocumentsSplitCountResponse.FromString, - options, channel_credentials, - insecure, call_credentials, compression, wait_for_ready, timeout, metadata) - @staticmethod def getIdentityByPublicKeyHash(request, target, 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 5b84143a33b..55dd228abc7 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 @@ -2470,6 +2470,19 @@ export namespace GetDocumentsCountRequest { getWhere_asB64(): string; setWhere(value: Uint8Array | string): void; + getReturnDistinctCountsInRange(): boolean; + setReturnDistinctCountsInRange(value: boolean): void; + + getOrderBy(): Uint8Array | string; + getOrderBy_asU8(): Uint8Array; + getOrderBy_asB64(): string; + setOrderBy(value: Uint8Array | string): void; + + hasLimit(): boolean; + clearLimit(): void; + getLimit(): number; + setLimit(value: number): void; + getProve(): boolean; setProve(value: boolean): void; @@ -2488,6 +2501,9 @@ export namespace GetDocumentsCountRequest { dataContractId: Uint8Array | string, documentType: string, where: Uint8Array | string, + returnDistinctCountsInRange: boolean, + orderBy: Uint8Array | string, + limit: number, prove: boolean, } } @@ -2521,10 +2537,10 @@ export namespace GetDocumentsCountResponse { } export class GetDocumentsCountResponseV0 extends jspb.Message { - hasCount(): boolean; - clearCount(): void; - getCount(): number; - setCount(value: number): void; + hasCounts(): boolean; + clearCounts(): void; + getCounts(): GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults | undefined; + setCounts(value?: GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults): void; hasProof(): boolean; clearProof(): void; @@ -2549,199 +2565,105 @@ export namespace GetDocumentsCountResponse { export namespace GetDocumentsCountResponseV0 { export type AsObject = { - count: number, + counts?: GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.AsObject, proof?: Proof.AsObject, metadata?: ResponseMetadata.AsObject, } - export enum ResultCase { - RESULT_NOT_SET = 0, - COUNT = 1, - PROOF = 2, - } - } - - export enum VersionCase { - VERSION_NOT_SET = 0, - V0 = 1, - } -} - -export class GetDocumentsSplitCountRequest extends jspb.Message { - hasV0(): boolean; - clearV0(): void; - getV0(): GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0 | undefined; - setV0(value?: GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0): void; - - getVersionCase(): GetDocumentsSplitCountRequest.VersionCase; - serializeBinary(): Uint8Array; - toObject(includeInstance?: boolean): GetDocumentsSplitCountRequest.AsObject; - static toObject(includeInstance: boolean, msg: GetDocumentsSplitCountRequest): GetDocumentsSplitCountRequest.AsObject; - static extensions: {[key: number]: jspb.ExtensionFieldInfo}; - static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; - static serializeBinaryToWriter(message: GetDocumentsSplitCountRequest, writer: jspb.BinaryWriter): void; - static deserializeBinary(bytes: Uint8Array): GetDocumentsSplitCountRequest; - static deserializeBinaryFromReader(message: GetDocumentsSplitCountRequest, reader: jspb.BinaryReader): GetDocumentsSplitCountRequest; -} - -export namespace GetDocumentsSplitCountRequest { - export type AsObject = { - v0?: GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.AsObject, - } - - export class GetDocumentsSplitCountRequestV0 extends jspb.Message { - getDataContractId(): Uint8Array | string; - getDataContractId_asU8(): Uint8Array; - getDataContractId_asB64(): string; - setDataContractId(value: Uint8Array | string): void; - - getDocumentType(): string; - setDocumentType(value: string): void; - - getWhere(): Uint8Array | string; - getWhere_asU8(): Uint8Array; - getWhere_asB64(): string; - setWhere(value: Uint8Array | string): void; - - getSplitCountByIndexProperty(): string; - setSplitCountByIndexProperty(value: string): void; - - getProve(): boolean; - setProve(value: boolean): void; - - serializeBinary(): Uint8Array; - toObject(includeInstance?: boolean): GetDocumentsSplitCountRequestV0.AsObject; - static toObject(includeInstance: boolean, msg: GetDocumentsSplitCountRequestV0): GetDocumentsSplitCountRequestV0.AsObject; - static extensions: {[key: number]: jspb.ExtensionFieldInfo}; - static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; - static serializeBinaryToWriter(message: GetDocumentsSplitCountRequestV0, writer: jspb.BinaryWriter): void; - static deserializeBinary(bytes: Uint8Array): GetDocumentsSplitCountRequestV0; - static deserializeBinaryFromReader(message: GetDocumentsSplitCountRequestV0, reader: jspb.BinaryReader): GetDocumentsSplitCountRequestV0; - } - - export namespace GetDocumentsSplitCountRequestV0 { - export type AsObject = { - dataContractId: Uint8Array | string, - documentType: string, - where: Uint8Array | string, - splitCountByIndexProperty: string, - prove: boolean, - } - } - - export enum VersionCase { - VERSION_NOT_SET = 0, - V0 = 1, - } -} - -export class GetDocumentsSplitCountResponse extends jspb.Message { - hasV0(): boolean; - clearV0(): void; - getV0(): GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 | undefined; - setV0(value?: GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0): void; - - getVersionCase(): GetDocumentsSplitCountResponse.VersionCase; - serializeBinary(): Uint8Array; - toObject(includeInstance?: boolean): GetDocumentsSplitCountResponse.AsObject; - static toObject(includeInstance: boolean, msg: GetDocumentsSplitCountResponse): GetDocumentsSplitCountResponse.AsObject; - static extensions: {[key: number]: jspb.ExtensionFieldInfo}; - static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; - static serializeBinaryToWriter(message: GetDocumentsSplitCountResponse, writer: jspb.BinaryWriter): void; - static deserializeBinary(bytes: Uint8Array): GetDocumentsSplitCountResponse; - static deserializeBinaryFromReader(message: GetDocumentsSplitCountResponse, reader: jspb.BinaryReader): GetDocumentsSplitCountResponse; -} - -export namespace GetDocumentsSplitCountResponse { - export type AsObject = { - v0?: GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.AsObject, - } - - export class GetDocumentsSplitCountResponseV0 extends jspb.Message { - hasSplitCounts(): boolean; - clearSplitCounts(): void; - getSplitCounts(): GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts | undefined; - setSplitCounts(value?: GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts): void; - - hasProof(): boolean; - clearProof(): void; - getProof(): Proof | undefined; - setProof(value?: Proof): void; - - hasMetadata(): boolean; - clearMetadata(): void; - getMetadata(): ResponseMetadata | undefined; - setMetadata(value?: ResponseMetadata): void; - - getResultCase(): GetDocumentsSplitCountResponseV0.ResultCase; - serializeBinary(): Uint8Array; - toObject(includeInstance?: boolean): GetDocumentsSplitCountResponseV0.AsObject; - static toObject(includeInstance: boolean, msg: GetDocumentsSplitCountResponseV0): GetDocumentsSplitCountResponseV0.AsObject; - static extensions: {[key: number]: jspb.ExtensionFieldInfo}; - static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; - static serializeBinaryToWriter(message: GetDocumentsSplitCountResponseV0, writer: jspb.BinaryWriter): void; - static deserializeBinary(bytes: Uint8Array): GetDocumentsSplitCountResponseV0; - static deserializeBinaryFromReader(message: GetDocumentsSplitCountResponseV0, reader: jspb.BinaryReader): GetDocumentsSplitCountResponseV0; - } - - export namespace GetDocumentsSplitCountResponseV0 { - export type AsObject = { - splitCounts?: GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.AsObject, - proof?: Proof.AsObject, - metadata?: ResponseMetadata.AsObject, - } + export class CountEntry extends jspb.Message { + hasInKey(): boolean; + clearInKey(): void; + getInKey(): Uint8Array | string; + getInKey_asU8(): Uint8Array; + getInKey_asB64(): string; + setInKey(value: Uint8Array | string): void; - export class SplitCountEntry extends jspb.Message { getKey(): Uint8Array | string; getKey_asU8(): Uint8Array; getKey_asB64(): string; setKey(value: Uint8Array | string): void; - getCount(): number; - setCount(value: number): void; + getCount(): string; + setCount(value: string): void; serializeBinary(): Uint8Array; - toObject(includeInstance?: boolean): SplitCountEntry.AsObject; - static toObject(includeInstance: boolean, msg: SplitCountEntry): SplitCountEntry.AsObject; + toObject(includeInstance?: boolean): CountEntry.AsObject; + static toObject(includeInstance: boolean, msg: CountEntry): CountEntry.AsObject; static extensions: {[key: number]: jspb.ExtensionFieldInfo}; static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; - static serializeBinaryToWriter(message: SplitCountEntry, writer: jspb.BinaryWriter): void; - static deserializeBinary(bytes: Uint8Array): SplitCountEntry; - static deserializeBinaryFromReader(message: SplitCountEntry, reader: jspb.BinaryReader): SplitCountEntry; + static serializeBinaryToWriter(message: CountEntry, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): CountEntry; + static deserializeBinaryFromReader(message: CountEntry, reader: jspb.BinaryReader): CountEntry; } - export namespace SplitCountEntry { + export namespace CountEntry { export type AsObject = { + inKey: Uint8Array | string, key: Uint8Array | string, - count: number, + count: string, } } - export class SplitCounts extends jspb.Message { + export class CountEntries extends jspb.Message { clearEntriesList(): void; - getEntriesList(): Array; - setEntriesList(value: Array): void; - addEntries(value?: GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry, index?: number): GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry; + getEntriesList(): Array; + setEntriesList(value: Array): void; + addEntries(value?: GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry, index?: number): GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry; serializeBinary(): Uint8Array; - toObject(includeInstance?: boolean): SplitCounts.AsObject; - static toObject(includeInstance: boolean, msg: SplitCounts): SplitCounts.AsObject; + toObject(includeInstance?: boolean): CountEntries.AsObject; + static toObject(includeInstance: boolean, msg: CountEntries): CountEntries.AsObject; static extensions: {[key: number]: jspb.ExtensionFieldInfo}; static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; - static serializeBinaryToWriter(message: SplitCounts, writer: jspb.BinaryWriter): void; - static deserializeBinary(bytes: Uint8Array): SplitCounts; - static deserializeBinaryFromReader(message: SplitCounts, reader: jspb.BinaryReader): SplitCounts; + static serializeBinaryToWriter(message: CountEntries, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): CountEntries; + static deserializeBinaryFromReader(message: CountEntries, reader: jspb.BinaryReader): CountEntries; } - export namespace SplitCounts { + export namespace CountEntries { export type AsObject = { - entriesList: Array, + entriesList: Array, + } + } + + export class CountResults extends jspb.Message { + hasAggregateCount(): boolean; + clearAggregateCount(): void; + getAggregateCount(): string; + setAggregateCount(value: string): void; + + hasEntries(): boolean; + clearEntries(): void; + getEntries(): GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries | undefined; + setEntries(value?: GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries): void; + + getVariantCase(): CountResults.VariantCase; + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): CountResults.AsObject; + static toObject(includeInstance: boolean, msg: CountResults): CountResults.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: CountResults, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): CountResults; + static deserializeBinaryFromReader(message: CountResults, reader: jspb.BinaryReader): CountResults; + } + + export namespace CountResults { + export type AsObject = { + aggregateCount: string, + entries?: GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.AsObject, + } + + export enum VariantCase { + VARIANT_NOT_SET = 0, + AGGREGATE_COUNT = 1, + ENTRIES = 2, } } export enum ResultCase { RESULT_NOT_SET = 0, - SPLIT_COUNTS = 1, + COUNTS = 1, PROOF = 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 b670f84bcc7..d70c2e95669 100644 --- a/packages/dapi-grpc/clients/platform/v0/web/platform_pb.js +++ b/packages/dapi-grpc/clients/platform/v0/web/platform_pb.js @@ -155,6 +155,10 @@ goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetD goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.VersionCase', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.VariantCase', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.ResultCase', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.VersionCase', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsRequest', null, { proto }); @@ -166,15 +170,6 @@ goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocum goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV0.Documents', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV0.ResultCase', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsResponse.VersionCase', null, { proto }); -goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest', null, { proto }); -goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0', null, { proto }); -goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.VersionCase', null, { proto }); -goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse', null, { proto }); -goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0', null, { proto }); -goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.ResultCase', null, { proto }); -goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry', null, { proto }); -goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts', null, { proto }); -goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.VersionCase', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetEpochsInfoRequest', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetEpochsInfoRequest.GetEpochsInfoRequestV0', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetEpochsInfoRequest.VersionCase', null, { proto }); @@ -2345,79 +2340,16 @@ if (goog.DEBUG && !COMPILED) { * @extends {jspb.Message} * @constructor */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, null, proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.oneofGroups_); -}; -goog.inherits(proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.displayName = 'proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest'; -} -/** - * 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.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0 = function(opt_data) { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry = function(opt_data) { jspb.Message.initialize(this, opt_data, 0, -1, null, null); }; -goog.inherits(proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.displayName = 'proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0'; -} -/** - * 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.GetDocumentsSplitCountResponse = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, null, proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.oneofGroups_); -}; -goog.inherits(proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.displayName = 'proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse'; -} -/** - * 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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0 = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, null, proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.oneofGroups_); -}; -goog.inherits(proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0, jspb.Message); +goog.inherits(proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry, jspb.Message); if (goog.DEBUG && !COMPILED) { /** * @public * @override */ - proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.displayName = 'proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0'; + proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.displayName = 'proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry'; } /** * Generated by JsPbCodeGenerator. @@ -2429,16 +2361,16 @@ if (goog.DEBUG && !COMPILED) { * @extends {jspb.Message} * @constructor */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, null, null); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.repeatedFields_, null); }; -goog.inherits(proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry, jspb.Message); +goog.inherits(proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries, jspb.Message); if (goog.DEBUG && !COMPILED) { /** * @public * @override */ - proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.displayName = 'proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry'; + proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.displayName = 'proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries'; } /** * Generated by JsPbCodeGenerator. @@ -2450,16 +2382,16 @@ if (goog.DEBUG && !COMPILED) { * @extends {jspb.Message} * @constructor */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.repeatedFields_, null); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.oneofGroups_); }; -goog.inherits(proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts, jspb.Message); +goog.inherits(proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults, jspb.Message); if (goog.DEBUG && !COMPILED) { /** * @public * @override */ - proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.displayName = 'proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts'; + proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.displayName = 'proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults'; } /** * Generated by JsPbCodeGenerator. @@ -25658,7 +25590,10 @@ proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountReques dataContractId: msg.getDataContractId_asB64(), documentType: jspb.Message.getFieldWithDefault(msg, 2, ""), where: msg.getWhere_asB64(), - prove: jspb.Message.getBooleanFieldWithDefault(msg, 4, false) + returnDistinctCountsInRange: jspb.Message.getBooleanFieldWithDefault(msg, 4, false), + orderBy: msg.getOrderBy_asB64(), + limit: jspb.Message.getFieldWithDefault(msg, 6, 0), + prove: jspb.Message.getBooleanFieldWithDefault(msg, 7, false) }; if (includeInstance) { @@ -25708,6 +25643,18 @@ proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountReques msg.setWhere(value); break; case 4: + var value = /** @type {boolean} */ (reader.readBool()); + msg.setReturnDistinctCountsInRange(value); + break; + case 5: + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setOrderBy(value); + break; + case 6: + var value = /** @type {number} */ (reader.readUint32()); + msg.setLimit(value); + break; + case 7: var value = /** @type {boolean} */ (reader.readBool()); msg.setProve(value); break; @@ -25761,13 +25708,34 @@ proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountReques f ); } - f = message.getProve(); + f = message.getReturnDistinctCountsInRange(); if (f) { writer.writeBool( 4, f ); } + f = message.getOrderBy_asU8(); + if (f.length > 0) { + writer.writeBytes( + 5, + f + ); + } + f = /** @type {number} */ (jspb.Message.getField(message, 6)); + if (f != null) { + writer.writeUint32( + 6, + f + ); + } + f = message.getProve(); + if (f) { + writer.writeBool( + 7, + f + ); + } }; @@ -25874,10 +25842,10 @@ proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountReques /** - * optional bool prove = 4; + * optional bool return_distinct_counts_in_range = 4; * @return {boolean} */ -proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0.prototype.getProve = function() { +proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0.prototype.getReturnDistinctCountsInRange = function() { return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 4, false)); }; @@ -25886,11 +25854,107 @@ proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountReques * @param {boolean} value * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0.prototype.setProve = function(value) { +proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0.prototype.setReturnDistinctCountsInRange = function(value) { return jspb.Message.setProto3BooleanField(this, 4, value); }; +/** + * optional bytes order_by = 5; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0.prototype.getOrderBy = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 5, "")); +}; + + +/** + * optional bytes order_by = 5; + * This is a type-conversion wrapper around `getOrderBy()` + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0.prototype.getOrderBy_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getOrderBy())); +}; + + +/** + * optional bytes order_by = 5; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getOrderBy()` + * @return {!Uint8Array} + */ +proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0.prototype.getOrderBy_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getOrderBy())); +}; + + +/** + * @param {!(string|Uint8Array)} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0.prototype.setOrderBy = function(value) { + return jspb.Message.setProto3BytesField(this, 5, value); +}; + + +/** + * optional uint32 limit = 6; + * @return {number} + */ +proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0.prototype.getLimit = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 6, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0.prototype.setLimit = function(value) { + return jspb.Message.setField(this, 6, value); +}; + + +/** + * Clears the field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0.prototype.clearLimit = function() { + return jspb.Message.setField(this, 6, undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0.prototype.hasLimit = function() { + return jspb.Message.getField(this, 6) != null; +}; + + +/** + * optional bool prove = 7; + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0.prototype.getProve = function() { + return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 7, false)); +}; + + +/** + * @param {boolean} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0.prototype.setProve = function(value) { + return jspb.Message.setProto3BooleanField(this, 7, value); +}; + + /** * optional GetDocumentsCountRequestV0 v0 = 1; * @return {?proto.org.dash.platform.dapi.v0.GetDocumentsCountRequest.GetDocumentsCountRequestV0} @@ -26083,7 +26147,7 @@ proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountRespo */ proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.ResultCase = { RESULT_NOT_SET: 0, - COUNT: 1, + COUNTS: 1, PROOF: 2 }; @@ -26125,7 +26189,7 @@ proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountRespo */ proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.toObject = function(includeInstance, msg) { var f, obj = { - count: jspb.Message.getFieldWithDefault(msg, 1, 0), + counts: (f = msg.getCounts()) && proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.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) }; @@ -26165,8 +26229,9 @@ proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountRespo var field = reader.getFieldNumber(); switch (field) { case 1: - var value = /** @type {number} */ (reader.readUint64()); - msg.setCount(value); + var value = new proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.deserializeBinaryFromReader); + msg.setCounts(value); break; case 2: var value = new proto.org.dash.platform.dapi.v0.Proof; @@ -26207,11 +26272,12 @@ proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountRespo */ proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.serializeBinaryToWriter = function(message, writer) { var f = undefined; - f = /** @type {number} */ (jspb.Message.getField(message, 1)); + f = message.getCounts(); if (f != null) { - writer.writeUint64( + writer.writeMessage( 1, - f + f, + proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.serializeBinaryToWriter ); } f = message.getProof(); @@ -26233,935 +26299,270 @@ proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountRespo }; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { /** - * optional uint64 count = 1; - * @return {number} + * 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.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.getCount = function() { - return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0)); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.prototype.toObject = function(opt_includeInstance) { + return proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.toObject(opt_includeInstance, this); }; /** - * @param {number} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0} returns 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.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.setCount = function(value) { - return jspb.Message.setOneofField(this, 1, proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.oneofGroups_[0], value); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.toObject = function(includeInstance, msg) { + var f, obj = { + inKey: msg.getInKey_asB64(), + key: msg.getKey_asB64(), + count: jspb.Message.getFieldWithDefault(msg, 3, "0") + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; }; +} /** - * Clears the field making it undefined. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0} returns this + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry} */ -proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.clearCount = function() { - return jspb.Message.setOneofField(this, 1, proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.oneofGroups_[0], undefined); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry; + return proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.deserializeBinaryFromReader(msg, reader); }; /** - * Returns whether this field is set. - * @return {boolean} + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry} */ -proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.hasCount = function() { - return jspb.Message.getField(this, 1) != null; +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setInKey(value); + break; + case 2: + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setKey(value); + break; + case 3: + var value = /** @type {string} */ (reader.readUint64String()); + msg.setCount(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; }; /** - * optional Proof proof = 2; - * @return {?proto.org.dash.platform.dapi.v0.Proof} + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} */ -proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.getProof = function() { - return /** @type{?proto.org.dash.platform.dapi.v0.Proof} */ ( - jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.Proof, 2)); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); }; /** - * @param {?proto.org.dash.platform.dapi.v0.Proof|undefined} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0} returns this -*/ -proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.setProof = function(value) { - return jspb.Message.setOneofWrapperField(this, 2, proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.oneofGroups_[0], value); -}; - - -/** - * Clears the message field making it undefined. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0} returns this - */ -proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.clearProof = function() { - return this.setProof(undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.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.GetDocumentsCountResponse.GetDocumentsCountResponseV0.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.GetDocumentsCountResponse.GetDocumentsCountResponseV0} returns this -*/ -proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.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.GetDocumentsCountResponse.GetDocumentsCountResponseV0} returns this - */ -proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.clearMetadata = function() { - return this.setMetadata(undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.hasMetadata = function() { - return jspb.Message.getField(this, 3) != null; -}; - - -/** - * optional GetDocumentsCountResponseV0 v0 = 1; - * @return {?proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.prototype.getV0 = function() { - return /** @type{?proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0} */ ( - jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0, 1)); -}; - - -/** - * @param {?proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0|undefined} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse} returns this -*/ -proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.prototype.setV0 = function(value) { - return jspb.Message.setOneofWrapperField(this, 1, proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.oneofGroups_[0], value); -}; - - -/** - * Clears the message field making it undefined. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse} returns this - */ -proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.prototype.clearV0 = function() { - return this.setV0(undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.prototype.hasV0 = function() { - return jspb.Message.getField(this, 1) != 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.GetDocumentsSplitCountRequest.oneofGroups_ = [[1]]; - -/** - * @enum {number} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.VersionCase = { - VERSION_NOT_SET: 0, - V0: 1 -}; - -/** - * @return {proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.VersionCase} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.prototype.getVersionCase = function() { - return /** @type {proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.VersionCase} */(jspb.Message.computeOneofCase(this, proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.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.GetDocumentsSplitCountRequest.prototype.toObject = function(opt_includeInstance) { - return proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.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.GetDocumentsSplitCountRequest} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.toObject = function(includeInstance, msg) { - var f, obj = { - v0: (f = msg.getV0()) && proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.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.GetDocumentsSplitCountRequest} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest; - return proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.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.GetDocumentsSplitCountRequest} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.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.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0; - reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.deserializeBinaryFromReader); - msg.setV0(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.GetDocumentsSplitCountRequest.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.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.GetDocumentsSplitCountRequest} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getV0(); - if (f != null) { - writer.writeMessage( - 1, - f, - proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.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.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.prototype.toObject = function(opt_includeInstance) { - return proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.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.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.toObject = function(includeInstance, msg) { - var f, obj = { - dataContractId: msg.getDataContractId_asB64(), - documentType: jspb.Message.getFieldWithDefault(msg, 2, ""), - where: msg.getWhere_asB64(), - splitCountByIndexProperty: jspb.Message.getFieldWithDefault(msg, 4, ""), - prove: jspb.Message.getBooleanFieldWithDefault(msg, 5, false) - }; - - 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.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0; - return proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.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.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.deserializeBinaryFromReader = function(msg, reader) { - while (reader.nextField()) { - if (reader.isEndGroup()) { - break; - } - var field = reader.getFieldNumber(); - switch (field) { - case 1: - var value = /** @type {!Uint8Array} */ (reader.readBytes()); - msg.setDataContractId(value); - break; - case 2: - var value = /** @type {string} */ (reader.readString()); - msg.setDocumentType(value); - break; - case 3: - var value = /** @type {!Uint8Array} */ (reader.readBytes()); - msg.setWhere(value); - break; - case 4: - var value = /** @type {string} */ (reader.readString()); - msg.setSplitCountByIndexProperty(value); - break; - case 5: - var value = /** @type {boolean} */ (reader.readBool()); - msg.setProve(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.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.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.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getDataContractId_asU8(); - if (f.length > 0) { - writer.writeBytes( - 1, - f - ); - } - f = message.getDocumentType(); - if (f.length > 0) { - writer.writeString( - 2, - f - ); - } - f = message.getWhere_asU8(); - if (f.length > 0) { - writer.writeBytes( - 3, - f - ); - } - f = message.getSplitCountByIndexProperty(); - if (f.length > 0) { - writer.writeString( - 4, - f - ); - } - f = message.getProve(); - if (f) { - writer.writeBool( - 5, - f - ); - } -}; - - -/** - * optional bytes data_contract_id = 1; - * @return {string} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.prototype.getDataContractId = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); -}; - - -/** - * optional bytes data_contract_id = 1; - * This is a type-conversion wrapper around `getDataContractId()` - * @return {string} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.prototype.getDataContractId_asB64 = function() { - return /** @type {string} */ (jspb.Message.bytesAsB64( - this.getDataContractId())); -}; - - -/** - * 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.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.prototype.getDataContractId_asU8 = function() { - return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( - this.getDataContractId())); -}; - - -/** - * @param {!(string|Uint8Array)} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0} returns this - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.prototype.setDataContractId = function(value) { - return jspb.Message.setProto3BytesField(this, 1, value); -}; - - -/** - * optional string document_type = 2; - * @return {string} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.prototype.getDocumentType = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); -}; - - -/** - * @param {string} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0} returns this + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.prototype.setDocumentType = function(value) { - return jspb.Message.setProto3StringField(this, 2, value); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = /** @type {!(string|Uint8Array)} */ (jspb.Message.getField(message, 1)); + if (f != null) { + writer.writeBytes( + 1, + f + ); + } + f = message.getKey_asU8(); + if (f.length > 0) { + writer.writeBytes( + 2, + f + ); + } + f = message.getCount(); + if (parseInt(f, 10) !== 0) { + writer.writeUint64String( + 3, + f + ); + } }; /** - * optional bytes where = 3; + * optional bytes in_key = 1; * @return {string} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.prototype.getWhere = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.prototype.getInKey = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); }; /** - * optional bytes where = 3; - * This is a type-conversion wrapper around `getWhere()` + * optional bytes in_key = 1; + * This is a type-conversion wrapper around `getInKey()` * @return {string} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.prototype.getWhere_asB64 = function() { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.prototype.getInKey_asB64 = function() { return /** @type {string} */ (jspb.Message.bytesAsB64( - this.getWhere())); + this.getInKey())); }; /** - * optional bytes where = 3; + * optional bytes in_key = 1; * Note that Uint8Array is not supported on all browsers. * @see http://caniuse.com/Uint8Array - * This is a type-conversion wrapper around `getWhere()` + * This is a type-conversion wrapper around `getInKey()` * @return {!Uint8Array} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.prototype.getWhere_asU8 = function() { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.prototype.getInKey_asU8 = function() { return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( - this.getWhere())); + this.getInKey())); }; /** * @param {!(string|Uint8Array)} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0} returns this - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.prototype.setWhere = function(value) { - return jspb.Message.setProto3BytesField(this, 3, value); -}; - - -/** - * optional string split_count_by_index_property = 4; - * @return {string} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.prototype.getSplitCountByIndexProperty = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 4, "")); -}; - - -/** - * @param {string} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0} returns this - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.prototype.setSplitCountByIndexProperty = function(value) { - return jspb.Message.setProto3StringField(this, 4, value); -}; - - -/** - * optional bool prove = 5; - * @return {boolean} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.prototype.getProve = function() { - return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 5, false)); -}; - - -/** - * @param {boolean} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0} returns this - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0.prototype.setProve = function(value) { - return jspb.Message.setProto3BooleanField(this, 5, value); -}; - - -/** - * optional GetDocumentsSplitCountRequestV0 v0 = 1; - * @return {?proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.prototype.getV0 = function() { - return /** @type{?proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0} */ ( - jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0, 1)); -}; - - -/** - * @param {?proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.GetDocumentsSplitCountRequestV0|undefined} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest} returns this -*/ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.prototype.setV0 = function(value) { - return jspb.Message.setOneofWrapperField(this, 1, proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.oneofGroups_[0], value); -}; - - -/** - * Clears the message field making it undefined. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest} returns this - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.prototype.clearV0 = function() { - return this.setV0(undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountRequest.prototype.hasV0 = function() { - return jspb.Message.getField(this, 1) != 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.GetDocumentsSplitCountResponse.oneofGroups_ = [[1]]; - -/** - * @enum {number} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.VersionCase = { - VERSION_NOT_SET: 0, - V0: 1 -}; - -/** - * @return {proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.VersionCase} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.prototype.getVersionCase = function() { - return /** @type {proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.VersionCase} */(jspb.Message.computeOneofCase(this, proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.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.GetDocumentsSplitCountResponse.prototype.toObject = function(opt_includeInstance) { - return proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.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.GetDocumentsSplitCountResponse} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.toObject = function(includeInstance, msg) { - var f, obj = { - v0: (f = msg.getV0()) && proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.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.GetDocumentsSplitCountResponse} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse; - return proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.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.GetDocumentsSplitCountResponse} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0; - reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.deserializeBinaryFromReader); - msg.setV0(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.GetDocumentsSplitCountResponse.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.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.GetDocumentsSplitCountResponse} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getV0(); - if (f != null) { - writer.writeMessage( - 1, - f, - proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.serializeBinaryToWriter - ); - } +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.prototype.setInKey = function(value) { + return jspb.Message.setField(this, 1, value); }; - -/** - * 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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.oneofGroups_ = [[1,2]]; - -/** - * @enum {number} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.ResultCase = { - RESULT_NOT_SET: 0, - SPLIT_COUNTS: 1, - PROOF: 2 -}; - /** - * @return {proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.ResultCase} + * Clears the field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.prototype.getResultCase = function() { - return /** @type {proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.ResultCase} */(jspb.Message.computeOneofCase(this, proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.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.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.prototype.clearInKey = function() { + return jspb.Message.setField(this, 1, undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.prototype.toObject = function(opt_includeInstance) { - return proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.toObject(opt_includeInstance, this); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.prototype.hasInKey = function() { + return jspb.Message.getField(this, 1) != null; }; /** - * 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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages + * optional bytes key = 2; + * @return {string} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.toObject = function(includeInstance, msg) { - var f, obj = { - splitCounts: (f = msg.getSplitCounts()) && proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.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) - }; +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.prototype.getKey = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; + +/** + * optional bytes key = 2; + * This is a type-conversion wrapper around `getKey()` + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.prototype.getKey_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getKey())); }; -} /** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0} + * optional bytes key = 2; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getKey()` + * @return {!Uint8Array} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0; - return proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.deserializeBinaryFromReader(msg, reader); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.prototype.getKey_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getKey())); }; /** - * Deserializes binary data (in protobuf wire format) from the - * given reader into the given message object. - * @param {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0} + * @param {!(string|Uint8Array)} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts; - reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.deserializeBinaryFromReader); - msg.setSplitCounts(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; +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.prototype.setKey = function(value) { + return jspb.Message.setProto3BytesField(this, 2, value); }; /** - * Serializes the message to binary data (in protobuf wire format). - * @return {!Uint8Array} + * optional uint64 count = 3; + * @return {string} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.serializeBinaryToWriter(this, writer); - return writer.getResultBuffer(); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.prototype.getCount = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "0")); }; /** - * Serializes the given message to binary data (in protobuf wire - * format), writing to the given BinaryWriter. - * @param {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages + * @param {string} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getSplitCounts(); - if (f != null) { - writer.writeMessage( - 1, - f, - proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.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 - ); - } +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.prototype.setCount = function(value) { + return jspb.Message.setProto3StringIntField(this, 3, value); }; +/** + * List of repeated fields within this message type. + * @private {!Array} + * @const + */ +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.repeatedFields_ = [1]; + if (jspb.Message.GENERATE_TO_OBJECT) { @@ -27177,8 +26578,8 @@ if (jspb.Message.GENERATE_TO_OBJECT) { * http://goto/soy-param-migration * @return {!Object} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.prototype.toObject = function(opt_includeInstance) { - return proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.toObject(opt_includeInstance, this); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.prototype.toObject = function(opt_includeInstance) { + return proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.toObject(opt_includeInstance, this); }; @@ -27187,14 +26588,14 @@ proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplit * @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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry} msg The msg instance to transform. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries} msg The msg instance to transform. * @return {!Object} * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.toObject = function(includeInstance, msg) { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.toObject = function(includeInstance, msg) { var f, obj = { - key: msg.getKey_asB64(), - count: jspb.Message.getFieldWithDefault(msg, 2, 0) + entriesList: jspb.Message.toObjectList(msg.getEntriesList(), + proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.toObject, includeInstance) }; if (includeInstance) { @@ -27208,23 +26609,23 @@ proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplit /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry} + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.deserializeBinary = function(bytes) { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); - var msg = new proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry; - return proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.deserializeBinaryFromReader(msg, reader); + var msg = new proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries; + return proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry} msg The message object to deserialize into. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry} + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.deserializeBinaryFromReader = function(msg, reader) { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; @@ -27232,12 +26633,9 @@ proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplit var field = reader.getFieldNumber(); switch (field) { case 1: - var value = /** @type {!Uint8Array} */ (reader.readBytes()); - msg.setKey(value); - break; - case 2: - var value = /** @type {number} */ (reader.readUint64()); - msg.setCount(value); + var value = new proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.deserializeBinaryFromReader); + msg.addEntries(value); break; default: reader.skipField(); @@ -27252,9 +26650,9 @@ proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplit * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.prototype.serializeBinary = function() { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); - proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.serializeBinaryToWriter(this, writer); + proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.serializeBinaryToWriter(this, writer); return writer.getResultBuffer(); }; @@ -27262,96 +26660,87 @@ proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplit /** * Serializes the given message to binary data (in protobuf wire * format), writing to the given BinaryWriter. - * @param {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry} message + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries} message * @param {!jspb.BinaryWriter} writer * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.serializeBinaryToWriter = function(message, writer) { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.serializeBinaryToWriter = function(message, writer) { var f = undefined; - f = message.getKey_asU8(); + f = message.getEntriesList(); if (f.length > 0) { - writer.writeBytes( + writer.writeRepeatedMessage( 1, - f - ); - } - f = message.getCount(); - if (f !== 0) { - writer.writeUint64( - 2, - f + f, + proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry.serializeBinaryToWriter ); } }; /** - * optional bytes key = 1; - * @return {string} + * repeated CountEntry entries = 1; + * @return {!Array} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.prototype.getKey = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.prototype.getEntriesList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry, 1)); }; /** - * optional bytes key = 1; - * This is a type-conversion wrapper around `getKey()` - * @return {string} - */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.prototype.getKey_asB64 = function() { - return /** @type {string} */ (jspb.Message.bytesAsB64( - this.getKey())); + * @param {!Array} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries} returns this +*/ +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.prototype.setEntriesList = function(value) { + return jspb.Message.setRepeatedWrapperField(this, 1, value); }; /** - * optional bytes key = 1; - * Note that Uint8Array is not supported on all browsers. - * @see http://caniuse.com/Uint8Array - * This is a type-conversion wrapper around `getKey()` - * @return {!Uint8Array} + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry=} opt_value + * @param {number=} opt_index + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.prototype.getKey_asU8 = function() { - return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( - this.getKey())); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.prototype.addEntries = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntry, opt_index); }; /** - * @param {!(string|Uint8Array)} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry} returns this + * Clears the list making it empty but non-null. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.prototype.setKey = function(value) { - return jspb.Message.setProto3BytesField(this, 1, value); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.prototype.clearEntriesList = function() { + return this.setEntriesList([]); }; + /** - * optional uint64 count = 2; - * @return {number} + * 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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.prototype.getCount = function() { - return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0)); -}; - +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.oneofGroups_ = [[1,2]]; /** - * @param {number} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry} returns this + * @enum {number} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.prototype.setCount = function(value) { - return jspb.Message.setProto3IntField(this, 2, value); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.VariantCase = { + VARIANT_NOT_SET: 0, + AGGREGATE_COUNT: 1, + ENTRIES: 2 }; - - /** - * List of repeated fields within this message type. - * @private {!Array} - * @const + * @return {proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.VariantCase} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.repeatedFields_ = [1]; +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.prototype.getVariantCase = function() { + return /** @type {proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.VariantCase} */(jspb.Message.computeOneofCase(this, proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.oneofGroups_[0])); +}; @@ -27368,8 +26757,8 @@ if (jspb.Message.GENERATE_TO_OBJECT) { * http://goto/soy-param-migration * @return {!Object} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.prototype.toObject = function(opt_includeInstance) { - return proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.toObject(opt_includeInstance, this); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.prototype.toObject = function(opt_includeInstance) { + return proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.toObject(opt_includeInstance, this); }; @@ -27378,14 +26767,14 @@ proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplit * @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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts} msg The msg instance to transform. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults} msg The msg instance to transform. * @return {!Object} * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.toObject = function(includeInstance, msg) { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.toObject = function(includeInstance, msg) { var f, obj = { - entriesList: jspb.Message.toObjectList(msg.getEntriesList(), - proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.toObject, includeInstance) + aggregateCount: jspb.Message.getFieldWithDefault(msg, 1, "0"), + entries: (f = msg.getEntries()) && proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.toObject(includeInstance, f) }; if (includeInstance) { @@ -27399,23 +26788,23 @@ proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplit /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts} + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.deserializeBinary = function(bytes) { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); - var msg = new proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts; - return proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.deserializeBinaryFromReader(msg, reader); + var msg = new proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults; + return proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts} msg The message object to deserialize into. + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts} + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.deserializeBinaryFromReader = function(msg, reader) { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; @@ -27423,9 +26812,13 @@ proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplit var field = reader.getFieldNumber(); switch (field) { case 1: - var value = new proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry; - reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.deserializeBinaryFromReader); - msg.addEntries(value); + var value = /** @type {string} */ (reader.readUint64String()); + msg.setAggregateCount(value); + break; + case 2: + var value = new proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.deserializeBinaryFromReader); + msg.setEntries(value); break; default: reader.skipField(); @@ -27440,9 +26833,9 @@ proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplit * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.prototype.serializeBinary = function() { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); - proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.serializeBinaryToWriter(this, writer); + proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.serializeBinaryToWriter(this, writer); return writer.getResultBuffer(); }; @@ -27450,86 +26843,128 @@ proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplit /** * Serializes the given message to binary data (in protobuf wire * format), writing to the given BinaryWriter. - * @param {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts} message + * @param {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults} message * @param {!jspb.BinaryWriter} writer * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.serializeBinaryToWriter = function(message, writer) { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.serializeBinaryToWriter = function(message, writer) { var f = undefined; - f = message.getEntriesList(); - if (f.length > 0) { - writer.writeRepeatedMessage( + f = /** @type {string} */ (jspb.Message.getField(message, 1)); + if (f != null) { + writer.writeUint64String( 1, + f + ); + } + f = message.getEntries(); + if (f != null) { + writer.writeMessage( + 2, f, - proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry.serializeBinaryToWriter + proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries.serializeBinaryToWriter ); } }; /** - * repeated SplitCountEntry entries = 1; - * @return {!Array} + * optional uint64 aggregate_count = 1; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.prototype.getAggregateCount = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "0")); +}; + + +/** + * @param {string} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.prototype.setAggregateCount = function(value) { + return jspb.Message.setOneofField(this, 1, proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.oneofGroups_[0], value); +}; + + +/** + * Clears the field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults} returns this + */ +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.prototype.clearAggregateCount = function() { + return jspb.Message.setOneofField(this, 1, proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.oneofGroups_[0], undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.prototype.hasAggregateCount = function() { + return jspb.Message.getField(this, 1) != null; +}; + + +/** + * optional CountEntries entries = 2; + * @return {?proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.prototype.getEntriesList = function() { - return /** @type{!Array} */ ( - jspb.Message.getRepeatedWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry, 1)); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.prototype.getEntries = function() { + return /** @type{?proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries} */ ( + jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries, 2)); }; /** - * @param {!Array} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts} returns this + * @param {?proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountEntries|undefined} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.prototype.setEntriesList = function(value) { - return jspb.Message.setRepeatedWrapperField(this, 1, value); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.prototype.setEntries = function(value) { + return jspb.Message.setOneofWrapperField(this, 2, proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.oneofGroups_[0], value); }; /** - * @param {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry=} opt_value - * @param {number=} opt_index - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry} + * Clears the message field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.prototype.addEntries = function(opt_value, opt_index) { - return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCountEntry, opt_index); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.prototype.clearEntries = function() { + return this.setEntries(undefined); }; /** - * Clears the list making it empty but non-null. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts} returns this + * Returns whether this field is set. + * @return {boolean} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts.prototype.clearEntriesList = function() { - return this.setEntriesList([]); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults.prototype.hasEntries = function() { + return jspb.Message.getField(this, 2) != null; }; /** - * optional SplitCounts split_counts = 1; - * @return {?proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts} + * optional CountResults counts = 1; + * @return {?proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.prototype.getSplitCounts = function() { - return /** @type{?proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts} */ ( - jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts, 1)); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.getCounts = function() { + return /** @type{?proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults} */ ( + jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults, 1)); }; /** - * @param {?proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.SplitCounts|undefined} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0} returns this + * @param {?proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.CountResults|undefined} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.prototype.setSplitCounts = function(value) { - return jspb.Message.setOneofWrapperField(this, 1, proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.oneofGroups_[0], value); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.setCounts = function(value) { + return jspb.Message.setOneofWrapperField(this, 1, proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.oneofGroups_[0], value); }; /** * Clears the message field making it undefined. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0} returns this + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.prototype.clearSplitCounts = function() { - return this.setSplitCounts(undefined); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.clearCounts = function() { + return this.setCounts(undefined); }; @@ -27537,7 +26972,7 @@ proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplit * Returns whether this field is set. * @return {boolean} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.prototype.hasSplitCounts = function() { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.hasCounts = function() { return jspb.Message.getField(this, 1) != null; }; @@ -27546,7 +26981,7 @@ proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplit * optional Proof proof = 2; * @return {?proto.org.dash.platform.dapi.v0.Proof} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.prototype.getProof = function() { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.getProof = function() { return /** @type{?proto.org.dash.platform.dapi.v0.Proof} */ ( jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.Proof, 2)); }; @@ -27554,18 +26989,18 @@ proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplit /** * @param {?proto.org.dash.platform.dapi.v0.Proof|undefined} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0} returns this + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.prototype.setProof = function(value) { - return jspb.Message.setOneofWrapperField(this, 2, proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.oneofGroups_[0], value); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.setProof = function(value) { + return jspb.Message.setOneofWrapperField(this, 2, proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.oneofGroups_[0], value); }; /** * Clears the message field making it undefined. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0} returns this + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.prototype.clearProof = function() { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.clearProof = function() { return this.setProof(undefined); }; @@ -27574,7 +27009,7 @@ proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplit * Returns whether this field is set. * @return {boolean} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.prototype.hasProof = function() { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.hasProof = function() { return jspb.Message.getField(this, 2) != null; }; @@ -27583,7 +27018,7 @@ proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplit * optional ResponseMetadata metadata = 3; * @return {?proto.org.dash.platform.dapi.v0.ResponseMetadata} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.prototype.getMetadata = function() { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.getMetadata = function() { return /** @type{?proto.org.dash.platform.dapi.v0.ResponseMetadata} */ ( jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.ResponseMetadata, 3)); }; @@ -27591,18 +27026,18 @@ proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplit /** * @param {?proto.org.dash.platform.dapi.v0.ResponseMetadata|undefined} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0} returns this + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.prototype.setMetadata = function(value) { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.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.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0} returns this + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.prototype.clearMetadata = function() { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.clearMetadata = function() { return this.setMetadata(undefined); }; @@ -27611,35 +27046,35 @@ proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplit * Returns whether this field is set. * @return {boolean} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0.prototype.hasMetadata = function() { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0.prototype.hasMetadata = function() { return jspb.Message.getField(this, 3) != null; }; /** - * optional GetDocumentsSplitCountResponseV0 v0 = 1; - * @return {?proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0} + * optional GetDocumentsCountResponseV0 v0 = 1; + * @return {?proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.prototype.getV0 = function() { - return /** @type{?proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0} */ ( - jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0, 1)); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.prototype.getV0 = function() { + return /** @type{?proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0} */ ( + jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0, 1)); }; /** - * @param {?proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.GetDocumentsSplitCountResponseV0|undefined} value - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse} returns this + * @param {?proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.GetDocumentsCountResponseV0|undefined} value + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.prototype.setV0 = function(value) { - return jspb.Message.setOneofWrapperField(this, 1, proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.oneofGroups_[0], value); +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.prototype.setV0 = function(value) { + return jspb.Message.setOneofWrapperField(this, 1, proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.oneofGroups_[0], value); }; /** * Clears the message field making it undefined. - * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse} returns this + * @return {!proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse} returns this */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.prototype.clearV0 = function() { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.prototype.clearV0 = function() { return this.setV0(undefined); }; @@ -27648,7 +27083,7 @@ proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.prototype.clearV0 * Returns whether this field is set. * @return {boolean} */ -proto.org.dash.platform.dapi.v0.GetDocumentsSplitCountResponse.prototype.hasV0 = function() { +proto.org.dash.platform.dapi.v0.GetDocumentsCountResponse.prototype.hasV0 = function() { return jspb.Message.getField(this, 1) != null; }; diff --git a/packages/dapi-grpc/clients/platform/v0/web/platform_pb_service.d.ts b/packages/dapi-grpc/clients/platform/v0/web/platform_pb_service.d.ts index b7062d2387d..c693f69285a 100644 --- a/packages/dapi-grpc/clients/platform/v0/web/platform_pb_service.d.ts +++ b/packages/dapi-grpc/clients/platform/v0/web/platform_pb_service.d.ts @@ -148,15 +148,6 @@ type PlatformgetDocumentsCount = { readonly responseType: typeof platform_pb.GetDocumentsCountResponse; }; -type PlatformgetDocumentsSplitCount = { - readonly methodName: string; - readonly service: typeof Platform; - readonly requestStream: false; - readonly responseStream: false; - readonly requestType: typeof platform_pb.GetDocumentsSplitCountRequest; - readonly responseType: typeof platform_pb.GetDocumentsSplitCountResponse; -}; - type PlatformgetIdentityByPublicKeyHash = { readonly methodName: string; readonly service: typeof Platform; @@ -598,7 +589,6 @@ export class Platform { static readonly getDataContracts: PlatformgetDataContracts; static readonly getDocuments: PlatformgetDocuments; static readonly getDocumentsCount: PlatformgetDocumentsCount; - static readonly getDocumentsSplitCount: PlatformgetDocumentsSplitCount; static readonly getIdentityByPublicKeyHash: PlatformgetIdentityByPublicKeyHash; static readonly getIdentityByNonUniquePublicKeyHash: PlatformgetIdentityByNonUniquePublicKeyHash; static readonly waitForStateTransitionResult: PlatformwaitForStateTransitionResult; @@ -824,15 +814,6 @@ export class PlatformClient { requestMessage: platform_pb.GetDocumentsCountRequest, callback: (error: ServiceError|null, responseMessage: platform_pb.GetDocumentsCountResponse|null) => void ): UnaryResponse; - getDocumentsSplitCount( - requestMessage: platform_pb.GetDocumentsSplitCountRequest, - metadata: grpc.Metadata, - callback: (error: ServiceError|null, responseMessage: platform_pb.GetDocumentsSplitCountResponse|null) => void - ): UnaryResponse; - getDocumentsSplitCount( - requestMessage: platform_pb.GetDocumentsSplitCountRequest, - callback: (error: ServiceError|null, responseMessage: platform_pb.GetDocumentsSplitCountResponse|null) => void - ): UnaryResponse; getIdentityByPublicKeyHash( requestMessage: platform_pb.GetIdentityByPublicKeyHashRequest, metadata: grpc.Metadata, diff --git a/packages/dapi-grpc/clients/platform/v0/web/platform_pb_service.js b/packages/dapi-grpc/clients/platform/v0/web/platform_pb_service.js index 4a2c1f4dfdf..b59c679c8df 100644 --- a/packages/dapi-grpc/clients/platform/v0/web/platform_pb_service.js +++ b/packages/dapi-grpc/clients/platform/v0/web/platform_pb_service.js @@ -154,15 +154,6 @@ Platform.getDocumentsCount = { responseType: platform_pb.GetDocumentsCountResponse }; -Platform.getDocumentsSplitCount = { - methodName: "getDocumentsSplitCount", - service: Platform, - requestStream: false, - responseStream: false, - requestType: platform_pb.GetDocumentsSplitCountRequest, - responseType: platform_pb.GetDocumentsSplitCountResponse -}; - Platform.getIdentityByPublicKeyHash = { methodName: "getIdentityByPublicKeyHash", service: Platform, @@ -1089,37 +1080,6 @@ PlatformClient.prototype.getDocumentsCount = function getDocumentsCount(requestM }; }; -PlatformClient.prototype.getDocumentsSplitCount = function getDocumentsSplitCount(requestMessage, metadata, callback) { - if (arguments.length === 2) { - callback = arguments[1]; - } - var client = grpc.unary(Platform.getDocumentsSplitCount, { - request: requestMessage, - host: this.serviceHost, - metadata: metadata, - transport: this.options.transport, - debug: this.options.debug, - onEnd: function (response) { - if (callback) { - if (response.status !== grpc.Code.OK) { - var err = new Error(response.statusMessage); - err.code = response.status; - err.metadata = response.trailers; - callback(err, null); - } else { - callback(null, response.message); - } - } - } - }); - return { - cancel: function () { - callback = null; - client.close(); - } - }; -}; - PlatformClient.prototype.getIdentityByPublicKeyHash = function getIdentityByPublicKeyHash(requestMessage, metadata, callback) { if (arguments.length === 2) { callback = arguments[1]; diff --git a/packages/dapi-grpc/protos/platform/v0/platform.proto b/packages/dapi-grpc/protos/platform/v0/platform.proto index 002eef33638..14dd5bae289 100644 --- a/packages/dapi-grpc/protos/platform/v0/platform.proto +++ b/packages/dapi-grpc/protos/platform/v0/platform.proto @@ -38,8 +38,6 @@ service Platform { rpc getDocuments(GetDocumentsRequest) returns (GetDocumentsResponse); rpc getDocumentsCount(GetDocumentsCountRequest) returns (GetDocumentsCountResponse); - rpc getDocumentsSplitCount(GetDocumentsSplitCountRequest) - returns (GetDocumentsSplitCountResponse); rpc getIdentityByPublicKeyHash(GetIdentityByPublicKeyHashRequest) returns (GetIdentityByPublicKeyHashResponse); rpc getIdentityByNonUniquePublicKeyHash( @@ -616,57 +614,136 @@ message GetDocumentsResponse { } +// Unified count query. +// +// Mode is determined by the where clauses encoded in `where` plus +// the explicit `return_distinct_counts_in_range` flag. The wire +// shape of the no-proof response makes the mode explicit via +// `CountResults.variant`: +// * No `In` clause and `return_distinct_counts_in_range` = false: +// total count → `CountResults.aggregate_count` (single u64). +// * Exactly one `In` clause (no range): per-`In`-value counts → +// `CountResults.entries`, one `CountEntry` for each value in +// the `In` array constrained by the other `==` clauses. At +// most one `In` per request; multiple `In` clauses are an +// InvalidArgument error. +// * A range clause (`>`, `<`, `between*`, `startsWith`) and +// `return_distinct_counts_in_range` = true: per-distinct-value +// range histogram → `CountResults.entries`, one `CountEntry` +// per distinct value within the range. Requires +// `range_countable: true` on the index (see Indexes book +// chapter). Also supports an `In` clause on a prefix property +// of the index — in that case each entry carries BOTH the In +// value (`CountEntry.in_key`) and the terminator value +// (`CountEntry.key`). Cross-fork sums are NOT computed +// server-side; callers reduce client-side if they want a flat +// histogram (see book chapter "Range Modes"). +// * A range clause with `return_distinct_counts_in_range` = false: +// total over range → `CountResults.aggregate_count`. Also +// requires `range_countable: true`. +// +// When `prove = true`, the response is a grovedb proof instead of +// a `CountResults` value; the client verifies and recovers the +// same per-mode shape (single u64 for aggregate, per-key map for +// distinct). message GetDocumentsCountRequest { message GetDocumentsCountRequestV0 { - bytes data_contract_id = 1; // The ID of the data contract containing the documents - string document_type = 2; // The type of document being requested - bytes where = 3; // CBOR-encoded where clauses for filtering - bool prove = 4; // Flag to request a proof as the response + bytes data_contract_id = 1; + string document_type = 2; + bytes where = 3; // CBOR-encoded where clauses + // Default false (single sum). When true and a range clause is + // present, return per-distinct-value entries within the range. + bool return_distinct_counts_in_range = 4; + // CBOR-encoded order_by clauses. Same encoding as + // `GetDocumentsRequestV0.order_by`. The first clause's direction + // controls entry ordering in split-mode responses (per-`In`-value + // or per-range-distinct-value). On the `RangeDistinctProof` prove + // path the direction is part of the proof's path query, so the + // SDK must reconstruct the same value — empty `order_by` defaults + // to ascending on both sides for determinism. Ignored for + // total-count responses and for the `PointLookupProof` path + // (which sorts In keys lex-ascending unconditionally for prove/ + // no-proof parity). + bytes order_by = 5; + // Maximum number of entries to return. + // - **No-proof paths**: server clamps to its `max_query_limit` + // config; unset → server default. + // - **Prove paths** (`RangeDistinctProof`): validate-don't-clamp. + // `limit > max_query_limit` returns `InvalidLimit` rather than + // silently clamping, because silent clamping would invisibly + // break verification (proof determinism requires the SDK to + // reconstruct the same path query). Unset falls back to + // `crate::config::DEFAULT_QUERY_LIMIT` (a compile-time constant + // the SDK also reads) — explicitly NOT the operator-tunable + // `default_query_limit`, so proof bytes are deterministic + // across operators regardless of their runtime config. + // Has no effect on total-count responses. + optional uint32 limit = 6; + bool prove = 7; } oneof version { GetDocumentsCountRequestV0 v0 = 1; } } message GetDocumentsCountResponse { message GetDocumentsCountResponseV0 { - oneof result { - uint64 count = 1; // Total document count matching the query - Proof proof = 2; // Cryptographic proof, if requested - } - ResponseMetadata metadata = 3; // Metadata about the blockchain state - } - oneof version { GetDocumentsCountResponseV0 v0 = 1; } -} - -message GetDocumentsSplitCountRequest { - message GetDocumentsSplitCountRequestV0 { - bytes data_contract_id = 1; // The ID of the data contract containing the documents - string document_type = 2; // The type of document being requested - bytes where = 3; // CBOR-encoded where clauses for filtering - string split_count_by_index_property = 4; // The index property to split counts by - bool prove = 5; // Flag to request a proof as the response - } - oneof version { GetDocumentsSplitCountRequestV0 v0 = 1; } -} - -message GetDocumentsSplitCountResponse { - message GetDocumentsSplitCountResponseV0 { - // A single entry: the key value and how many documents match - message SplitCountEntry { - bytes key = 1; // The index property value - uint64 count = 2; // Number of documents with this key value - } - - message SplitCounts { - repeated SplitCountEntry entries = 1; + // A single per-key entry: the splitting key value and how many + // documents match. Used by the `entries` variant of + // `CountResults` for per-`In`-value and per-distinct-value-in- + // range modes. + // + // For compound queries (an `In` clause on a prefix property of a + // `range_countable` index plus a range clause on the terminator), + // each entry carries BOTH the In-fork's prefix value + // (`in_key`) and the terminator value (`key`). Cross-fork + // aggregation is intentionally NOT done server-side — callers + // get the unmerged per-(in_key, key) view and can sum + // client-side if they want a flat histogram. See the book + // chapter ("Range Modes") for rationale. + message CountEntry { + // Serialized prefix key for compound queries — the In's value + // for this fork. Absent for flat queries with no `In` on + // prefix (in which case entries are keyed purely by `key`). + optional bytes in_key = 1; + // Serialized terminator key (the range-property value for + // distinct-range modes, or the `In` value for per-In-value + // mode without a range clause). + bytes key = 2; + // `jstype = JS_STRING` so JS/Web clients receive a string and don't + // round counts > 2^53-1 to the nearest representable Number. Matches + // the convention used elsewhere in this proto for `uint64` fields + // that can exceed Number.MAX_SAFE_INTEGER. + uint64 count = 3 [jstype = JS_STRING]; + } + + message CountEntries { + repeated CountEntry entries = 1; + } + + // Non-proof count result. Shape is mode-dependent and made + // explicit on the wire via the inner `variant` oneof: + // * `aggregate_count`: total-count and range-without-distinct + // modes — a single u64 with no per-key breakdown. Callers + // read the total directly without scanning an entries list. + // * `entries`: per-`In`-value and per-distinct-value-in-range + // modes — one CountEntry per distinct value, in serialized- + // key order subject to the first `order_by` clause's + // direction and `limit`. + message CountResults { + oneof variant { + // `jstype = JS_STRING` for the same reason as + // `CountEntry.count` — JS Number rounds at 2^53−1. + uint64 aggregate_count = 1 [jstype = JS_STRING]; + CountEntries entries = 2; + } } oneof result { - SplitCounts split_counts = 1; // Per-key counts - Proof proof = 2; // Cryptographic proof, if requested + CountResults counts = 1; + Proof proof = 2; } - ResponseMetadata metadata = 3; // Metadata about the blockchain state + ResponseMetadata metadata = 3; } - oneof version { GetDocumentsSplitCountResponseV0 v0 = 1; } + oneof version { GetDocumentsCountResponseV0 v0 = 1; } } message GetIdentityByPublicKeyHashRequest { diff --git a/packages/rs-dapi-client/src/transport/grpc.rs b/packages/rs-dapi-client/src/transport/grpc.rs index 2fb9e0e78a5..49c4d7147f0 100644 --- a/packages/rs-dapi-client/src/transport/grpc.rs +++ b/packages/rs-dapi-client/src/transport/grpc.rs @@ -213,14 +213,6 @@ impl_transport_request_grpc!( get_documents_count ); -impl_transport_request_grpc!( - platform_proto::GetDocumentsSplitCountRequest, - platform_proto::GetDocumentsSplitCountResponse, - PlatformGrpcClient, - RequestSettings::default(), - get_documents_split_count -); - impl_transport_request_grpc!( platform_proto::GetDataContractRequest, platform_proto::GetDataContractResponse, diff --git a/packages/rs-dapi/src/services/platform_service/mod.rs b/packages/rs-dapi/src/services/platform_service/mod.rs index 9086389e158..437a10bf13f 100644 --- a/packages/rs-dapi/src/services/platform_service/mod.rs +++ b/packages/rs-dapi/src/services/platform_service/mod.rs @@ -350,12 +350,6 @@ impl Platform for PlatformServiceImpl { dapi_grpc::platform::v0::GetDocumentsCountResponse ); - drive_method!( - get_documents_split_count, - dapi_grpc::platform::v0::GetDocumentsSplitCountRequest, - dapi_grpc::platform::v0::GetDocumentsSplitCountResponse - ); - // System methods drive_method!( get_consensus_params, diff --git a/packages/rs-dpp/Cargo.toml b/packages/rs-dpp/Cargo.toml index bebcf31989b..a9fce764e0c 100644 --- a/packages/rs-dpp/Cargo.toml +++ b/packages/rs-dpp/Cargo.toml @@ -71,7 +71,7 @@ strum = { version = "0.26", features = ["derive"] } json-schema-compatibility-validator = { path = '../rs-json-schema-compatibility-validator', optional = true } once_cell = "1.19.0" tracing = { version = "0.1.41" } -grovedb-commitment-tree = { git = "https://github.com/dashpay/grovedb", rev = "dbd83dce59fbcf2866e9dd06be4ce6c320e37908", optional = true } +grovedb-commitment-tree = { git = "https://github.com/dashpay/grovedb", rev = "a917d92d2477672eed73c4c08e53e93449a6a094", optional = true } [dev-dependencies] tokio = { version = "1.40", features = ["full"] } diff --git a/packages/rs-dpp/schema/meta_schemas/document/v1/document-meta.json b/packages/rs-dpp/schema/meta_schemas/document/v1/document-meta.json index 39836336d9b..b5a787b3d01 100644 --- a/packages/rs-dpp/schema/meta_schemas/document/v1/document-meta.json +++ b/packages/rs-dpp/schema/meta_schemas/document/v1/document-meta.json @@ -441,6 +441,10 @@ } ], "description": "Whether and how the index supports count fast paths. Adds extra storage cost for non-default values." + }, + "rangeCountable": { + "type": "boolean", + "description": "When true, the property-name level becomes a ProvableCountTree and value trees become CountTrees so range-count queries on the indexed property are O(log n). Requires `countable` to be \"countable\" or \"countableAllowingOffset\". Per-protocol-version 12+; rejected on earlier protocol versions." } }, "required": [ diff --git a/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v1/mod.rs b/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v1/mod.rs index 0e11b14f6be..61c591299f4 100644 --- a/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v1/mod.rs +++ b/packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v1/mod.rs @@ -341,9 +341,18 @@ impl DocumentTypeV1 { #[cfg(feature = "validation")] if full_validation { - // Countable indices are only supported starting from protocol version 12. - // Both `Countable` and `CountableAllowingOffset` are gated together — - // either form requires v12+ since it changes the GroveDB tree type. + // `countable` and `rangeCountable` index features + // require GroveDB tree variants and query primitives + // (CountTree / ProvableCountTree / NonCounted / + // AggregateCountOnRange) that only exist from + // protocol v12 onward. NOTE: at protocol v12+ the + // dispatch routes to `try_from_schema_v2`, but v2 + // delegates to V1's parser internally for the + // shared core — so this body IS reached at v12+ + // and the `< 12` check is load-bearing, not + // defense-in-depth. Without it, v12 contracts + // with countable / range_countable indexes would + // be rejected here. if index.countable.is_countable() && platform_version.protocol_version < 12 { @@ -355,6 +364,15 @@ impl DocumentTypeV1 { .into(), ))); } + if index.range_countable && platform_version.protocol_version < 12 { + return Err(ProtocolError::ConsensusError(Box::new( + UnsupportedFeatureError::new( + "range-countable index".to_string(), + platform_version.protocol_version, + ) + .into(), + ))); + } validation_operations.extend(std::iter::once( ProtocolValidationOperation::DocumentTypeSchemaIndexValidation( diff --git a/packages/rs-dpp/src/data_contract/document_type/index/mod.rs b/packages/rs-dpp/src/data_contract/document_type/index/mod.rs index 0f4aa0d8ae5..4d9d92cdc39 100644 --- a/packages/rs-dpp/src/data_contract/document_type/index/mod.rs +++ b/packages/rs-dpp/src/data_contract/document_type/index/mod.rs @@ -356,6 +356,23 @@ pub struct Index { /// Whether and how the index supports count fast paths. See /// [`IndexCountability`]. pub countable: IndexCountability, + /// Whether the index supports O(log n) count queries over a *range* of + /// values for the index's last property (the terminator). The flag + /// only affects the storage layout at the last property level — all + /// preceding (prefix) properties keep their default tree shape: + /// - The property-name tree at the *last* property (whose keys are + /// that property's distinct values) is stored as a + /// `ProvableCountTree`, so range queries over distinct values can + /// be answered by walking the boundary in O(log n). + /// - Each value tree under it is stored as a `CountTree`, so the + /// property-name aggregate sums per-value counts cleanly. + /// - Sibling continuations inside each value tree (compound-index + /// suffixes) are wrapped with `Element::NonCounted` so their counts + /// do not pollute the value tree's count. + /// + /// `range_countable: true` requires `countable` to be `Countable` or + /// `CountableAllowingOffset` (it's additive, not a replacement). + pub range_countable: bool, } impl Index { @@ -531,6 +548,7 @@ impl TryFrom<&[(Value, Value)]> for Index { let mut contested_index = None; let mut index_properties: Vec = Vec::new(); let mut countable = IndexCountability::NotCountable; + let mut range_countable = false; for (key_value, value_value) in index_type_value_map { let key = key_value.to_str()?; @@ -679,6 +697,14 @@ impl TryFrom<&[(Value, Value)]> for Index { } }; } + "rangeCountable" => { + range_countable = + value_value + .as_bool() + .ok_or(DataContractError::ValueWrongType( + "rangeCountable value must be a boolean".to_string(), + ))?; + } "properties" => { let properties = value_value @@ -712,6 +738,20 @@ impl TryFrom<&[(Value, Value)]> for Index { )); } + // `rangeCountable` is additive on top of `countable`: it changes how + // the index's tree is laid out (property-name → ProvableCountTree, + // value level → CountTree, sibling continuations → NonCounted) so + // that range-count queries can be answered in O(log n). It is + // meaningless without the underlying countability. + if range_countable && !countable.is_countable() { + return Err(DataContractError::InvalidContractStructure( + "rangeCountable requires countable to be \"countable\" or \ + \"countableAllowingOffset\"; range-count queries only make \ + sense on a count-bearing index" + .to_string(), + )); + } + // if the index didn't have a name let's make one let name = name.unwrap_or_else(|| Alphanumeric.sample_string(&mut rand::thread_rng(), 24)); @@ -722,6 +762,7 @@ impl TryFrom<&[(Value, Value)]> for Index { null_searchable, contested_index, countable, + range_countable, }) } } @@ -776,6 +817,7 @@ mod tests { null_searchable: true, contested_index: None, countable: IndexCountability::NotCountable, + range_countable: false, } } diff --git a/packages/rs-dpp/src/data_contract/document_type/index/random_index.rs b/packages/rs-dpp/src/data_contract/document_type/index/random_index.rs index e215b403701..23ac5946961 100644 --- a/packages/rs-dpp/src/data_contract/document_type/index/random_index.rs +++ b/packages/rs-dpp/src/data_contract/document_type/index/random_index.rs @@ -61,6 +61,7 @@ impl Index { null_searchable: true, contested_index: None, countable: IndexCountability::NotCountable, + range_countable: false, }) } } diff --git a/packages/rs-dpp/src/data_contract/document_type/index_level/mod.rs b/packages/rs-dpp/src/data_contract/document_type/index_level/mod.rs index 8c5e8a5ef12..b9fce6b208c 100644 --- a/packages/rs-dpp/src/data_contract/document_type/index_level/mod.rs +++ b/packages/rs-dpp/src/data_contract/document_type/index_level/mod.rs @@ -42,6 +42,18 @@ pub struct IndexLevelTypeInfo { /// `Countable` → `CountTree`, /// `CountableAllowingOffset` → `ProvableCountTree`. pub countable: IndexCountability, + /// Whether this index supports range-count queries. When true: + /// - The property-name level (the level *above* this terminating + /// level, whose keys are the property's distinct values) is laid out + /// as a `ProvableCountTree`. + /// - Each value tree under it is laid out as a `CountTree`. + /// - Sibling continuations inside each value tree get wrapped with + /// `Element::NonCounted` so their counts don't leak into the value + /// tree's count. + /// + /// Mutually compatible with the `countable` flag — additive, not a + /// replacement. + pub range_countable: bool, } impl IndexType { @@ -222,6 +234,7 @@ impl IndexLevel { should_insert_with_all_null: index.null_searchable, index_type, countable: index.countable, + range_countable: index.range_countable, }); } } @@ -230,23 +243,32 @@ impl IndexLevel { Ok(index_level) } - /// Recursively finds the first index path where the `countable` property differs - /// between two IndexLevel trees. Returns `None` if countable is the same everywhere. + /// Recursively finds the first index path where a count-affecting + /// property (`countable` or `range_countable`) differs between two + /// IndexLevel trees. Both flags drive GroveDB tree-variant choice + /// at contract creation (NormalTree / CountTree / ProvableCountTree + /// at the [0] terminal, and additionally NonCounted-wrapped + /// continuations + ProvableCountTree property-name level for + /// `range_countable`), so toggling either after creation would + /// require rebuilding the index tree and is rejected. + /// Returns `None` if both properties are the same everywhere. #[cfg(feature = "validation")] - fn find_first_countable_change(&self, new: &IndexLevel) -> Option { - // Compare countable at this level if both have an index termination + fn find_first_countability_change(&self, new: &IndexLevel) -> Option { if let (Some(old_info), Some(new_info)) = (&self.has_index_with_type, &new.has_index_with_type) { if old_info.countable != new_info.countable { return Some("(countable changed)".to_string()); } + if old_info.range_countable != new_info.range_countable { + return Some("(range_countable changed)".to_string()); + } } // Recurse into sub-levels that exist in both old and new for (key, old_sub) in &self.sub_index_levels { if let Some(new_sub) = new.sub_index_levels.get(key) { - if let Some(inner_path) = old_sub.find_first_countable_change(new_sub) { + if let Some(inner_path) = old_sub.find_first_countability_change(new_sub) { return Some(format!("{} -> {}", key, inner_path)); } } @@ -291,10 +313,12 @@ impl IndexLevel { ); } - // Check that the countable property has not changed on any existing index. - // Changing countable requires rebuilding the entire index tree structure - // (NormalTree vs CountTree), so it must be treated as immutable after creation. - if let Some(countable_change_path) = self.find_first_countable_change(new_indices) { + // Check that the countability properties (`countable` and + // `range_countable`) have not changed on any existing index. + // Both flags drive GroveDB tree-variant choice at contract + // creation, so changing either would require rebuilding the + // index tree structure — both are immutable after creation. + if let Some(countable_change_path) = self.find_first_countability_change(new_indices) { return SimpleConsensusValidationResult::new_with_error( DataContractInvalidIndexDefinitionUpdateError::new( document_type_name.to_string(), @@ -329,6 +353,7 @@ mod tests { null_searchable: true, contested_index: None, countable: IndexCountability::NotCountable, + range_countable: false, }]; let old_index_structure = @@ -357,6 +382,7 @@ mod tests { null_searchable: true, contested_index: None, countable: IndexCountability::NotCountable, + range_countable: false, }]; let new_indices = vec![ @@ -370,6 +396,7 @@ mod tests { null_searchable: true, contested_index: None, countable: IndexCountability::NotCountable, + range_countable: false, }, Index { name: "test2".to_string(), @@ -381,6 +408,7 @@ mod tests { null_searchable: true, contested_index: None, countable: IndexCountability::NotCountable, + range_countable: false, }, ]; @@ -418,6 +446,7 @@ mod tests { null_searchable: true, contested_index: None, countable: IndexCountability::NotCountable, + range_countable: false, }, Index { name: "test2".to_string(), @@ -429,6 +458,7 @@ mod tests { null_searchable: true, contested_index: None, countable: IndexCountability::NotCountable, + range_countable: false, }, ]; @@ -442,6 +472,7 @@ mod tests { null_searchable: true, contested_index: None, countable: IndexCountability::NotCountable, + range_countable: false, }]; let old_index_structure = @@ -477,6 +508,7 @@ mod tests { null_searchable: true, contested_index: None, countable: IndexCountability::NotCountable, + range_countable: false, }]; let new_indices = vec![Index { @@ -495,6 +527,7 @@ mod tests { null_searchable: true, contested_index: None, countable: IndexCountability::NotCountable, + range_countable: false, }]; let old_index_structure = @@ -536,6 +569,7 @@ mod tests { null_searchable: true, contested_index: None, countable: IndexCountability::NotCountable, + range_countable: false, }]; let new_indices = vec![Index { @@ -548,6 +582,7 @@ mod tests { null_searchable: true, contested_index: None, countable: IndexCountability::NotCountable, + range_countable: false, }]; let old_index_structure = @@ -583,6 +618,7 @@ mod tests { null_searchable: true, contested_index: None, countable: IndexCountability::NotCountable, + range_countable: false, }]; let new_indices = vec![Index { @@ -595,6 +631,7 @@ mod tests { null_searchable: true, contested_index: None, countable: IndexCountability::Countable, + range_countable: false, }]; let old_index_structure = @@ -630,6 +667,7 @@ mod tests { null_searchable: true, contested_index: None, countable: IndexCountability::Countable, + range_countable: false, }]; let new_indices = vec![Index { @@ -642,6 +680,7 @@ mod tests { null_searchable: true, contested_index: None, countable: IndexCountability::NotCountable, + range_countable: false, }]; let old_index_structure = @@ -677,6 +716,7 @@ mod tests { null_searchable: true, contested_index: None, countable: IndexCountability::Countable, + range_countable: false, }]; let old_index_structure = @@ -691,6 +731,171 @@ mod tests { assert!(result.is_valid()); } + /// `range_countable` is layered on top of `countable` (it changes + /// the index's tree shape: property-name → ProvableCountTree, value + /// level → CountTree, sibling continuations → NonCounted) and is + /// just as load-bearing as `countable` itself for state-sync + /// determinism. Toggling it post-creation must be rejected for the + /// same reasons. + #[test] + fn should_return_invalid_result_if_range_countable_changed_from_false_to_true() { + let platform_version = PlatformVersion::latest(); + let document_type_name = "test"; + + let old_indices = vec![Index { + name: "test".to_string(), + properties: vec![IndexProperty { + name: "test".to_string(), + ascending: false, + }], + unique: false, + null_searchable: true, + contested_index: None, + countable: IndexCountability::Countable, + range_countable: false, + }]; + + let new_indices = vec![Index { + name: "test".to_string(), + properties: vec![IndexProperty { + name: "test".to_string(), + ascending: false, + }], + unique: false, + null_searchable: true, + contested_index: None, + countable: IndexCountability::Countable, + range_countable: true, + }]; + + let old_index_structure = + IndexLevel::try_from_indices(&old_indices, document_type_name, platform_version) + .expect("failed to create old index level"); + + let new_index_structure = + IndexLevel::try_from_indices(&new_indices, document_type_name, platform_version) + .expect("failed to create new index level"); + + let result = old_index_structure.validate_update(document_type_name, &new_index_structure); + + assert_matches!( + result.errors.as_slice(), + [ConsensusError::BasicError( + BasicError::DataContractInvalidIndexDefinitionUpdateError(e) + )] if e.index_path() == "test -> (range_countable changed)" + ); + } + + #[test] + fn should_return_invalid_result_if_range_countable_changed_from_true_to_false() { + let platform_version = PlatformVersion::latest(); + let document_type_name = "test"; + + let old_indices = vec![Index { + name: "test".to_string(), + properties: vec![IndexProperty { + name: "test".to_string(), + ascending: false, + }], + unique: false, + null_searchable: true, + contested_index: None, + countable: IndexCountability::Countable, + range_countable: true, + }]; + + let new_indices = vec![Index { + name: "test".to_string(), + properties: vec![IndexProperty { + name: "test".to_string(), + ascending: false, + }], + unique: false, + null_searchable: true, + contested_index: None, + countable: IndexCountability::Countable, + range_countable: false, + }]; + + let old_index_structure = + IndexLevel::try_from_indices(&old_indices, document_type_name, platform_version) + .expect("failed to create old index level"); + + let new_index_structure = + IndexLevel::try_from_indices(&new_indices, document_type_name, platform_version) + .expect("failed to create new index level"); + + let result = old_index_structure.validate_update(document_type_name, &new_index_structure); + + assert_matches!( + result.errors.as_slice(), + [ConsensusError::BasicError( + BasicError::DataContractInvalidIndexDefinitionUpdateError(e) + )] if e.index_path() == "test -> (range_countable changed)" + ); + } + + #[test] + fn should_return_invalid_result_if_range_countable_changed_on_compound_index() { + let platform_version = PlatformVersion::latest(); + let document_type_name = "test"; + + let old_indices = vec![Index { + name: "compound".to_string(), + properties: vec![ + IndexProperty { + name: "first".to_string(), + ascending: true, + }, + IndexProperty { + name: "second".to_string(), + ascending: true, + }, + ], + unique: false, + null_searchable: true, + contested_index: None, + countable: IndexCountability::Countable, + range_countable: false, + }]; + + let new_indices = vec![Index { + name: "compound".to_string(), + properties: vec![ + IndexProperty { + name: "first".to_string(), + ascending: true, + }, + IndexProperty { + name: "second".to_string(), + ascending: true, + }, + ], + unique: false, + null_searchable: true, + contested_index: None, + countable: IndexCountability::Countable, + range_countable: true, + }]; + + let old_index_structure = + IndexLevel::try_from_indices(&old_indices, document_type_name, platform_version) + .expect("failed to create old index level"); + + let new_index_structure = + IndexLevel::try_from_indices(&new_indices, document_type_name, platform_version) + .expect("failed to create new index level"); + + let result = old_index_structure.validate_update(document_type_name, &new_index_structure); + + assert_matches!( + result.errors.as_slice(), + [ConsensusError::BasicError( + BasicError::DataContractInvalidIndexDefinitionUpdateError(e) + )] if e.index_path() == "first -> second -> (range_countable changed)" + ); + } + #[test] fn should_return_invalid_result_if_countable_changed_on_compound_index() { let platform_version = PlatformVersion::latest(); @@ -712,6 +917,7 @@ mod tests { null_searchable: true, contested_index: None, countable: IndexCountability::NotCountable, + range_countable: false, }]; let new_indices = vec![Index { @@ -730,6 +936,7 @@ mod tests { null_searchable: true, contested_index: None, countable: IndexCountability::Countable, + range_countable: false, }]; let old_index_structure = diff --git a/packages/rs-drive-abci/Cargo.toml b/packages/rs-drive-abci/Cargo.toml index afaccec27cf..423531000c0 100644 --- a/packages/rs-drive-abci/Cargo.toml +++ b/packages/rs-drive-abci/Cargo.toml @@ -82,7 +82,7 @@ derive_more = { version = "1.0", features = ["from", "deref", "deref_mut"] } async-trait = "0.1.77" console-subscriber = { version = "0.4", optional = true } bls-signatures = { git = "https://github.com/dashpay/bls-signatures", rev = "0842b17583888e8f46c252a4ee84cdfd58e0546f", optional = true } -grovedb-commitment-tree = { git = "https://github.com/dashpay/grovedb", rev = "dbd83dce59fbcf2866e9dd06be4ce6c320e37908" } +grovedb-commitment-tree = { git = "https://github.com/dashpay/grovedb", rev = "a917d92d2477672eed73c4c08e53e93449a6a094" } nonempty = "0.11" [dev-dependencies] @@ -103,7 +103,7 @@ dpp = { path = "../rs-dpp", default-features = false, features = [ drive = { path = "../rs-drive", features = ["fixtures-and-mocks"] } drive-proof-verifier = { path = "../rs-drive-proof-verifier" } strategy-tests = { path = "../strategy-tests" } -grovedb-commitment-tree = { git = "https://github.com/dashpay/grovedb", rev = "dbd83dce59fbcf2866e9dd06be4ce6c320e37908", features = ["client"] } +grovedb-commitment-tree = { git = "https://github.com/dashpay/grovedb", rev = "a917d92d2477672eed73c4c08e53e93449a6a094", features = ["client"] } assert_matches = "1.5.0" drive-abci = { path = ".", features = ["testing-config", "mocks"] } bls-signatures = { git = "https://github.com/dashpay/bls-signatures", rev = "0842b17583888e8f46c252a4ee84cdfd58e0546f" } diff --git a/packages/rs-drive-abci/src/query/document_count_query/v0/mod.rs b/packages/rs-drive-abci/src/query/document_count_query/v0/mod.rs index 5c68d6c6ba3..c97f3d971d2 100644 --- a/packages/rs-drive-abci/src/query/document_count_query/v0/mod.rs +++ b/packages/rs-drive-abci/src/query/document_count_query/v0/mod.rs @@ -10,15 +10,70 @@ use dapi_grpc::platform::v0::get_documents_count_response::{ }; use dpp::check_validation_result_with_data; use dpp::data_contract::accessors::v0::DataContractV0Getters; -use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters; use dpp::identifier::Identifier; use dpp::platform_value::Value; use dpp::validation::ValidationResult; use dpp::version::PlatformVersion; use drive::error::query::QuerySyntaxError; -use drive::query::{DriveDocumentCountQuery, DriveDocumentQuery, WhereClause}; +use drive::query::{DocumentCountRequest, DocumentCountResponse, SplitCountEntry}; use drive::util::grove_operations::GroveDBToUse; +/// Wrap a single aggregate `u64` plus current-state metadata into the +/// protobuf `GetDocumentsCountResponseV0`. Produces the `CountResults +/// .variant.AggregateCount(_)` wire shape used by total-count and +/// range-without-distinct modes — the dispatcher routes drive's +/// `DocumentCountResponse::Aggregate(_)` through here so the wire +/// answer is a single u64, not an entries map with one empty-key +/// entry. +fn count_response_aggregate( + count: u64, + platform: &Platform, + platform_state: &PlatformState, +) -> GetDocumentsCountResponseV0 { + GetDocumentsCountResponseV0 { + result: Some(get_documents_count_response_v0::Result::Counts( + get_documents_count_response_v0::CountResults { + variant: Some( + get_documents_count_response_v0::count_results::Variant::AggregateCount(count), + ), + }, + )), + metadata: Some(platform.response_metadata_v0(platform_state, CheckpointUsed::Current)), + } +} + +/// Wrap a vector of [`SplitCountEntry`]s plus current-state metadata +/// into the protobuf `GetDocumentsCountResponseV0`. Produces the +/// `CountResults.variant.Entries(_)` wire shape used by per-`In`-value +/// and per-distinct-value-in-range modes. Note that an aggregate +/// total never reaches here — see [`count_response_aggregate`]. +fn count_response_with_entries( + entries: Vec, + platform: &Platform, + platform_state: &PlatformState, +) -> GetDocumentsCountResponseV0 { + let entries: Vec = entries + .into_iter() + .map(|e| get_documents_count_response_v0::CountEntry { + in_key: e.in_key, + key: e.key, + count: e.count, + }) + .collect(); + GetDocumentsCountResponseV0 { + result: Some(get_documents_count_response_v0::Result::Counts( + get_documents_count_response_v0::CountResults { + variant: Some( + get_documents_count_response_v0::count_results::Variant::Entries( + get_documents_count_response_v0::CountEntries { entries }, + ), + ), + }, + )), + metadata: Some(platform.response_metadata_v0(platform_state, CheckpointUsed::Current)), + } +} + impl Platform { pub(super) fn query_documents_count_v0( &self, @@ -26,6 +81,9 @@ impl Platform { data_contract_id, document_type: document_type_name, r#where, + return_distinct_counts_in_range, + order_by, + limit, prove, }: GetDocumentsCountRequestV0, platform_state: &PlatformState, @@ -71,137 +129,76 @@ impl Platform { })) }; - // Parse where clauses into WhereClause structs so we can match them against - // index properties for the CountTree path. - let all_where_clauses: Vec = - check_validation_result_with_data!(match &where_clause { - Value::Null => Ok(vec![]), - Value::Array(clauses) => clauses - .iter() - .map(|wc| { - if let Value::Array(components) = wc { - WhereClause::from_components(components).map_err(|e| match e { - drive::error::Error::Query(qe) => QueryError::Query(qe), - other => QueryError::InvalidArgument(format!( - "error parsing where clauses: {}", - other - )), - }) - } else { - Err(QueryError::Query( - QuerySyntaxError::InvalidFormatWhereClause( - "where clause must be an array", - ), - )) - } - }) - .collect::, QueryError>>(), - _ => Err(QueryError::Query( - QuerySyntaxError::InvalidFormatWhereClause("where clause must be an array"), - )), - }); - - let response = if prove { - // For prove path, use the standard DriveDocumentQuery approach. - // We still need the full path query structure for proof generation. - let mut drive_query = - check_validation_result_with_data!(DriveDocumentQuery::from_decomposed_values( - where_clause, - None, - Some(self.config.drive.default_query_limit), - None, - true, - None, - contract_ref, - document_type, - &self.config.drive, - )); - - // Cap the proof at u16::MAX matching documents. The proof - // verifier returns the count by deserializing every document in - // the proof, so an unbounded query would force the server to - // materialize and the client to verify an arbitrarily large set - // of documents purely to learn their count. Until count-tree - // proofs are implemented, callers that need exact counts on - // larger result sets should use `prove=false` with a covering - // countable index. - drive_query.limit = Some(u16::MAX); - - let proof = - match drive_query.execute_with_proof(&self.drive, None, None, platform_version) { - Ok(result) => result.0, - Err(drive::error::Error::Query(query_error)) => { - return Ok(QueryValidationResult::new_with_error(QueryError::Query( - query_error, - ))); - } - Err(e) => return Err(e.into()), - }; - - let (grovedb_used, proof) = - self.response_proof_v0(platform_state, proof, GroveDBToUse::Current)?; - - GetDocumentsCountResponseV0 { - result: Some(get_documents_count_response_v0::Result::Proof(proof)), - metadata: Some(self.response_metadata_v0(platform_state, grovedb_used)), - } + // `order_by` is decoded the same way as `where`: empty bytes + // → `Value::Null` (no clauses), any other shape must be a + // CBOR-encoded outer array of `[field, direction]` inner + // arrays. Drive parses + validates per clause. Required on + // the `(In + prove)` dispatch arm for proof determinism; + // empty is fine on every other arm (drive synthesizes an + // ascending default for split-mode entry direction). + let order_by_clause = if order_by.is_empty() { + Value::Null } else { - // The count fast path supports only Equal and In where-clause - // operators. Range operators (>, <, between, startsWith) need a - // boundary walk that the current count-tree path query model - // cannot express; surface that as a clear error rather than - // letting it fall through and silently drop the predicate. - if DriveDocumentCountQuery::has_unsupported_operator(&all_where_clauses) { - return Ok(QueryValidationResult::new_with_error( - QueryError::InvalidArgument( - "count query supports only `==` and `in` where-clause operators; \ - range operators (`>`, `<`, `between`, `startsWith`) are not yet \ - supported on the no-prove path" - .to_string(), - ), - )); - } - - // For no-prove path, use CountTree-based O(1) counting when possible. - // Find a countable index that matches the where clause properties. - let countable_index = DriveDocumentCountQuery::find_countable_index_for_where_clauses( - document_type.indexes(), - &all_where_clauses, - ); + check_validation_result_with_data!(ciborium::de::from_reader(order_by.as_slice()) + .map_err(|_| { + QueryError::Query(QuerySyntaxError::DeserializationError( + "unable to decode 'order_by' query from cbor".to_string(), + )) + })) + }; - let count = if let Some(index) = countable_index { - let count_query = DriveDocumentCountQuery { - document_type, - contract_id: contract_id.to_buffer(), - document_type_name: document_type_name.clone(), - index, - where_clauses: all_where_clauses, - split_by_property: None, - }; - - let results = count_query.execute_no_proof(&self.drive, None, platform_version)?; - - // For a total count query, execute_no_proof returns a single entry - // with an empty key and the total count. - results.first().map_or(0, |entry| entry.count) - } else { - // No countable index found. Return an error telling the caller - // that count queries require a countable index. - return Ok(QueryValidationResult::new_with_error( - QueryError::InvalidArgument( - "count query requires a countable index on the document type that \ - matches the where clause properties" - .to_string(), - ), - )); + // Hand the raw decoded where + order_by `Value`s to drive — + // same pattern `query_documents_v0` uses. Drive parses + + // validates per clause and surfaces any error as + // `Error::Query(...)`, which the existing match arm below maps + // to a query-validation result. Drive also applies per-mode + // limit policy: + // - no-proof modes silently clamp to `max_query_limit` + // (proto contract — "passing a larger value just gets + // clamped, not rejected") + // - the prove-distinct mode rejects `limit > max_query_limit` + // instead of clamping, because client-side proof + // reconstruction needs the exact same limit value the + // server used; silent clamping would silently break + // verification on requests above the cap. + let request = DocumentCountRequest { + contract: contract_ref, + document_type, + raw_where_value: where_clause, + raw_order_by_value: order_by_clause, + return_distinct_counts_in_range, + limit, + prove, + drive_config: &self.config.drive, + }; + let drive_response = + match self + .drive + .execute_document_count_request(request, None, platform_version) + { + Ok(r) => r, + Err(drive::error::Error::Query(qe)) => { + return Ok(QueryValidationResult::new_with_error(QueryError::Query(qe))); + } + Err(e) => return Err(e.into()), }; - GetDocumentsCountResponseV0 { - result: Some(get_documents_count_response_v0::Result::Count(count)), - metadata: Some(self.response_metadata_v0(platform_state, CheckpointUsed::Current)), + let response = match drive_response { + DocumentCountResponse::Aggregate(count) => { + count_response_aggregate(count, self, platform_state) + } + DocumentCountResponse::Entries(entries) => { + count_response_with_entries(entries, self, platform_state) + } + DocumentCountResponse::Proof(proof_bytes) => { + let (grovedb_used, proof) = + self.response_proof_v0(platform_state, proof_bytes, GroveDBToUse::Current)?; + GetDocumentsCountResponseV0 { + result: Some(get_documents_count_response_v0::Result::Proof(proof)), + metadata: Some(self.response_metadata_v0(platform_state, grovedb_used)), + } } }; - Ok(QueryValidationResult::new_with_data(response)) } } @@ -212,41 +209,68 @@ mod tests { use crate::query::tests::{setup_platform, store_data_contract, store_document}; use dpp::dashcore::Network; use dpp::data_contract::document_type::random_document::CreateRandomDocument; + use dpp::document::DocumentV0Setters; use dpp::tests::json_document::json_document_to_contract_with_ids; use rand::rngs::StdRng; use rand::SeedableRng; + /// Builds an in-memory v12 contract with a `widget` document type + /// that has `documentsCountable: true` — the type's primary-key + /// tree becomes a CountTree, enabling the unfiltered total-count + /// fast path on both no-proof and prove paths. + fn build_documents_countable_widget_contract() -> dpp::prelude::DataContract { + use dpp::data_contract::DataContractFactory; + use dpp::platform_value::platform_value; + + const PROTOCOL_VERSION_V12: u32 = 12; + let factory = + DataContractFactory::new(PROTOCOL_VERSION_V12).expect("expected to create factory"); + let document_schema = platform_value!({ + "type": "object", + "documentsCountable": true, + "properties": { + "color": {"type": "string", "position": 0, "maxLength": 32}, + }, + "additionalProperties": false, + }); + let schemas = platform_value!({ "widget": document_schema }); + factory + .create_with_value_config( + dpp::tests::utils::generate_random_identifier_struct(), + 0, + schemas, + None, + None, + ) + .expect("create contract") + .data_contract_owned() + } + + /// Unfiltered total count via the `documentsCountable: true` fast + /// path. Asserts O(1) read of the primary-key CountTree returns + /// the correct count after a few inserts. #[test] fn test_documents_count_no_prove() { - let (platform, state, version) = setup_platform(None, Network::Testnet, None); + use dpp::data_contract::accessors::v0::DataContractV0Getters; + let (platform, state, version) = setup_platform(None, Network::Testnet, None); let platform_version = PlatformVersion::latest(); - let data_contract = json_document_to_contract_with_ids( - "tests/supporting_files/contract/family/family-contract-countable.json", - None, - None, - false, - platform_version, - ) - .expect("expected to get json based contract"); - - store_data_contract(&platform, &data_contract, version); + let contract = build_documents_countable_widget_contract(); + store_data_contract(&platform, &contract, version); - let data_contract_id = data_contract.id(); - let document_type_name = "person"; - let document_type = data_contract - .document_type_for_name(document_type_name) - .expect("expected document type"); + let document_type = contract + .document_type_for_name("widget") + .expect("widget exists"); - let mut std_rng = StdRng::seed_from_u64(500); - for _ in 0..5 { + // Insert 5 widgets. + for i in 1..=5u8 { let random_document = document_type - .random_document_with_rng(&mut std_rng, platform_version) + .random_document(Some(i as u64), platform_version) .expect("expected to get random document"); store_document( &platform, - &data_contract, + &contract, document_type, &random_document, platform_version, @@ -254,9 +278,12 @@ mod tests { } let request = GetDocumentsCountRequestV0 { - data_contract_id: data_contract_id.to_vec(), - document_type: document_type_name.to_string(), + data_contract_id: contract.id().to_vec(), + document_type: "widget".to_string(), r#where: vec![], + return_distinct_counts_in_range: false, + order_by: Vec::new(), + limit: None, prove: false, }; @@ -268,39 +295,42 @@ mod tests { match result.data { Some(GetDocumentsCountResponseV0 { - result: Some(get_documents_count_response_v0::Result::Count(count)), + result: Some(get_documents_count_response_v0::Result::Counts( + get_documents_count_response_v0::CountResults { + variant: + Some(get_documents_count_response_v0::count_results::Variant::AggregateCount( + total, + )), + }, + )), metadata: Some(_), }) => { - assert_eq!(count, 5, "expected count of 5 documents"); + assert_eq!(total, 5, "expected count of 5 documents"); } - other => panic!("expected count result, got {:?}", other), + other => panic!("expected aggregate count result, got {:?}", other), } } + /// Same fast-path query as `test_documents_count_no_prove`, but + /// against an empty contract (no documents inserted). Asserts the + /// path returns 0 cleanly rather than erroring. #[test] fn test_documents_count_empty_result() { - let (platform, state, version) = setup_platform(None, Network::Testnet, None); - - let platform_version = PlatformVersion::latest(); + use dpp::data_contract::accessors::v0::DataContractV0Getters; - let data_contract = json_document_to_contract_with_ids( - "tests/supporting_files/contract/family/family-contract-countable.json", - None, - None, - false, - platform_version, - ) - .expect("expected to get json based contract"); - - store_data_contract(&platform, &data_contract, version); + let (platform, state, version) = setup_platform(None, Network::Testnet, None); + let _platform_version = PlatformVersion::latest(); - let data_contract_id = data_contract.id(); - let document_type_name = "person"; + let contract = build_documents_countable_widget_contract(); + store_data_contract(&platform, &contract, version); let request = GetDocumentsCountRequestV0 { - data_contract_id: data_contract_id.to_vec(), - document_type: document_type_name.to_string(), + data_contract_id: contract.id().to_vec(), + document_type: "widget".to_string(), r#where: vec![], + return_distinct_counts_in_range: false, + order_by: Vec::new(), + limit: None, prove: false, }; @@ -312,12 +342,19 @@ mod tests { match result.data { Some(GetDocumentsCountResponseV0 { - result: Some(get_documents_count_response_v0::Result::Count(count)), + result: Some(get_documents_count_response_v0::Result::Counts( + get_documents_count_response_v0::CountResults { + variant: + Some(get_documents_count_response_v0::count_results::Variant::AggregateCount( + total, + )), + }, + )), metadata: Some(_), }) => { - assert_eq!(count, 0, "expected count of 0 documents"); + assert_eq!(total, 0, "expected count of 0 documents"); } - other => panic!("expected count result, got {:?}", other), + other => panic!("expected aggregate count result, got {:?}", other), } } @@ -461,6 +498,9 @@ mod tests { data_contract_id: data_contract.id().to_vec(), document_type: "person".to_string(), r#where: serialize_where_clauses_to_cbor(where_clauses), + return_distinct_counts_in_range: false, + order_by: Vec::new(), + limit: None, prove: false, }; @@ -472,17 +512,26 @@ mod tests { match result.data { Some(GetDocumentsCountResponseV0 { - result: Some(get_documents_count_response_v0::Result::Count(count)), + result: + Some(get_documents_count_response_v0::Result::Counts( + get_documents_count_response_v0::CountResults { + variant: + Some(get_documents_count_response_v0::count_results::Variant::Entries( + entries, + )), + }, + )), metadata: Some(_), }) => { - assert_eq!(count, 5, "expected count of 5 (3 age=30 + 2 age=40)"); + let total: u64 = entries.entries.iter().map(|e| e.count).sum(); + assert_eq!(total, 5, "expected count of 5 (3 age=30 + 2 age=40)"); } - other => panic!("expected count result, got {:?}", other), + other => panic!("expected per-In-value entries result, got {:?}", other), } } #[test] - fn test_documents_count_rejects_range_operator() { + fn test_documents_count_range_without_range_countable_index_returns_clear_error() { let (platform, state, version) = setup_platform(None, Network::Testnet, None); let platform_version = PlatformVersion::latest(); @@ -497,7 +546,10 @@ mod tests { store_data_contract(&platform, &data_contract, version); - // [["age", ">", 20]] — range operator, must be rejected on no-prove path. + // [["age", ">", 20]] — range operator on a contract whose `age` + // index is `countable` but NOT `range_countable`. The range + // path now accepts range operators, but the picker must report + // "no usable index" so the handler surfaces a clear error. let where_clauses = vec![Value::Array(vec![ Value::Text("age".to_string()), Value::Text(">".to_string()), @@ -508,6 +560,9 @@ mod tests { data_contract_id: data_contract.id().to_vec(), document_type: "person".to_string(), r#where: serialize_where_clauses_to_cbor(where_clauses), + return_distinct_counts_in_range: false, + order_by: Vec::new(), + limit: None, prove: false, }; @@ -515,20 +570,36 @@ mod tests { .query_documents_count_v0(request, &state, version) .expect("expected query to return validation error"); + // Step 2 of the refactor moved the no-covering-index check into + // rs-drive, where it surfaces as + // `Query(WhereClauseOnNonIndexedProperty)` rather than the + // handler-local `InvalidArgument`. Both shapes are valid + // rejections — accept either. assert!( matches!( result.errors.as_slice(), - [QueryError::InvalidArgument(msg)] if msg.contains("range operators") && msg.contains("not yet") + [QueryError::InvalidArgument(msg)] if msg.contains("range_countable") + ) || matches!( + result.errors.as_slice(), + [QueryError::Query(QuerySyntaxError::WhereClauseOnNonIndexedProperty(msg))] + if msg.contains("range_countable") ), - "expected range-operator rejection, got {:?}", + "expected range_countable-index rejection, got {:?}", result.errors ); } + /// `prove = true` + Equal-on-single-property-countable-index = + /// the fully-covered fast path that produces a real grovedb proof + /// of the CountTree element at `[..., firstName, "Alice", 0]`. + /// Asserts the response is a `Proof` variant with non-empty bytes + /// — drive emits a CountTree element proof here, not the legacy + /// materialize-and-count document proof. #[test] - fn test_documents_count_with_prove() { - let (platform, state, version) = setup_platform(None, Network::Testnet, None); + fn test_documents_count_with_prove_and_covering_equal() { + use dpp::document::DocumentV0Setters; + let (platform, state, version) = setup_platform(None, Network::Testnet, None); let platform_version = PlatformVersion::latest(); let data_contract = json_document_to_contract_with_ids( @@ -542,30 +613,197 @@ mod tests { store_data_contract(&platform, &data_contract, version); - let data_contract_id = data_contract.id(); - let document_type_name = "person"; let document_type = data_contract - .document_type_for_name(document_type_name) + .document_type_for_name("person") .expect("expected document type"); + // Insert 2 docs at firstName=Alice and 1 at firstName=Bob so + // the targeted CountTree (`byFirstName` index, value=Alice) + // has count_value > 0. let mut std_rng = StdRng::seed_from_u64(500); - for _ in 0..3 { - let random_document = document_type + for first_name in ["Alice", "Alice", "Bob"] { + let mut doc = document_type .random_document_with_rng(&mut std_rng, platform_version) .expect("expected to get random document"); + let mut props = std::collections::BTreeMap::new(); + props.insert("firstName".to_string(), Value::Text(first_name.to_string())); + props.insert("lastName".to_string(), Value::Text("Smith".to_string())); + props.insert("age".to_string(), Value::U64(30)); + doc.set_properties(props); store_document( &platform, &data_contract, document_type, - &random_document, + &doc, platform_version, ); } + let where_clauses = vec![Value::Array(vec![ + Value::Text("firstName".to_string()), + Value::Text("==".to_string()), + Value::Text("Alice".to_string()), + ])]; + let request = GetDocumentsCountRequestV0 { - data_contract_id: data_contract_id.to_vec(), - document_type: document_type_name.to_string(), + data_contract_id: data_contract.id().to_vec(), + document_type: "person".to_string(), + r#where: serialize_where_clauses_to_cbor(where_clauses), + return_distinct_counts_in_range: false, + order_by: Vec::new(), + limit: None, + prove: true, + }; + + let result = platform + .query_documents_count_v0(request, &state, version) + .expect("expected query to succeed"); + + assert!(result.errors.is_empty(), "errors: {:?}", result.errors); + + match result.data { + Some(GetDocumentsCountResponseV0 { + result: Some(get_documents_count_response_v0::Result::Proof(proof)), + metadata: Some(_), + }) => { + assert!( + !proof.grovedb_proof.is_empty(), + "expected non-empty grovedb proof bytes for covered prove count", + ); + } + other => panic!("expected Proof response, got {:?}", other), + } + } + + /// Symmetric-rejection contract: `prove = true` with no where + /// clauses (or any where shape that doesn't fully cover a + /// `countable: true` index) rejects with + /// `WhereClauseOnNonIndexedProperty`. Matches the no-proof Total + /// mode's behaviour when no covering countable index exists, and + /// makes contract authors' index-design defects visible at the + /// API boundary rather than silently materializing every doc. + #[test] + fn test_documents_count_prove_without_covering_index_returns_clear_error() { + let (platform, state, version) = setup_platform(None, Network::Testnet, None); + let platform_version = PlatformVersion::latest(); + + let data_contract = json_document_to_contract_with_ids( + "tests/supporting_files/contract/family/family-contract-countable.json", + None, + None, + false, + platform_version, + ) + .expect("expected to get json based contract"); + + store_data_contract(&platform, &data_contract, version); + + let request = GetDocumentsCountRequestV0 { + data_contract_id: data_contract.id().to_vec(), + document_type: "person".to_string(), r#where: vec![], + return_distinct_counts_in_range: false, + order_by: Vec::new(), + limit: None, + prove: true, + }; + + let result = platform + .query_documents_count_v0(request, &state, version) + .expect("expected query to surface a validation error"); + + assert!( + matches!( + result.errors.as_slice(), + [QueryError::Query( + QuerySyntaxError::WhereClauseOnNonIndexedProperty(msg), + )] if msg.contains("countable") + ), + "expected covering-index rejection, got {:?}", + result.errors, + ); + } + + /// End-to-end pin for `prove = true` + `In`. + /// + /// `detect_mode` must route `(has_range=false, has_in=true, + /// prove=true, _)` to `PointLookupProof`, which builds a + /// per-branch CountTree-element proof via the shared + /// [`DriveDocumentCountQuery::point_lookup_count_path_query`] + /// builder (no document materialization, no `u16::MAX` cap on + /// matching docs — the proof shape is O(|In values| × log n)). + /// A regression that dispatches In+prove back through + /// `PerInValue` would emit a `Counts(...)` no-proof variant + /// instead, and the SDK verifier would bail with + /// `NoProofInResult`. + /// + /// Asserts the response variant is `Proof(non-empty bytes)`. + /// `order_by` is unused on this path — the builder sorts In + /// keys lex-ascending unconditionally for prove/no-proof + /// parity (see `point_lookup_count_path_query`), so proof + /// determinism is independent of the request's order_by. + #[test] + fn test_documents_count_with_in_and_prove_returns_proof() { + let (platform, state, version) = setup_platform(None, Network::Testnet, None); + let platform_version = PlatformVersion::latest(); + + let data_contract = json_document_to_contract_with_ids( + "tests/supporting_files/contract/family/family-contract-countable.json", + None, + None, + false, + platform_version, + ) + .expect("expected to get json based contract"); + + store_data_contract(&platform, &data_contract, version); + + // Same distribution as `test_documents_count_with_in_operator`: + // 3 docs at age=30, 2 at age=40, 1 at age=50. We ask for + // `age in [30, 40]` so the proof has to cover two forks. One + // doc at age=50 is outside the In set, so the proof must NOT + // collapse to the full contents. + for (id, name, age) in [ + ([1u8; 32], "Alice", 30u64), + ([2u8; 32], "Bob", 30), + ([3u8; 32], "Carol", 30), + ([4u8; 32], "Dave", 40), + ([5u8; 32], "Eve", 40), + ([6u8; 32], "Frank", 50), + ] { + store_person_document( + &platform, + &data_contract, + id, + name, + "Smith", + age, + platform_version, + ); + } + + // [["age", "in", [30, 40]]] + let where_clauses = vec![Value::Array(vec![ + Value::Text("age".to_string()), + Value::Text("in".to_string()), + Value::Array(vec![Value::U64(30), Value::U64(40)]), + ])]; + + // [["age", "asc"]] — required for the materialize-and-count + // proof walker; bug #2 in the doc comment above turned this + // omission into a hard error. + let order_by = vec![Value::Array(vec![ + Value::Text("age".to_string()), + Value::Text("asc".to_string()), + ])]; + + let request = GetDocumentsCountRequestV0 { + data_contract_id: data_contract.id().to_vec(), + document_type: "person".to_string(), + r#where: serialize_where_clauses_to_cbor(where_clauses), + return_distinct_counts_in_range: false, + order_by: serialize_where_clauses_to_cbor(order_by), + limit: None, prove: true, }; @@ -575,12 +813,337 @@ mod tests { assert!(result.errors.is_empty(), "errors: {:?}", result.errors); - assert!(matches!( - result.data, + match result.data { Some(GetDocumentsCountResponseV0 { - result: Some(get_documents_count_response_v0::Result::Proof(_)), + result: Some(get_documents_count_response_v0::Result::Proof(proof)), metadata: Some(_), - }) - )); + }) => { + // Non-empty grovedb proof bytes pin that the + // `PointLookupProof` dispatch actually emitted a + // materialize-and-count proof rather than a + // degenerate empty envelope. End-to-end SDK-verifier + // round-trip (group verified docs by the In field's + // serialized value → per-key entries) is exercised + // by the SDK integration tests once those are + // restored post-testnet. + assert!( + !proof.grovedb_proof.is_empty(), + "expected non-empty grovedb proof bytes for In + prove count" + ); + } + other => panic!( + "expected Proof response from In + prove count, got {:?}", + other + ), + } + } + + /// End-to-end test for the range count happy path against a v12 + /// contract whose `widget` document type carries a + /// `rangeCountable: true` index over `color`. Exercises the + /// `find_range_countable_index_for_where_clauses` → + /// `execute_range_count_no_proof` route in the no-prove handler, + /// in both summed and distinct modes plus the pagination knobs. + #[test] + fn test_documents_count_range_query_no_prove() { + use dpp::data_contract::DataContractFactory; + use dpp::document::DocumentV0Setters; + use dpp::platform_value::platform_value; + + const PROTOCOL_VERSION_V12: u32 = 12; + + let (platform, state, version) = setup_platform(None, Network::Testnet, None); + let platform_version = PlatformVersion::latest(); + + // Build an in-memory v12 contract with a range_countable index. + let factory = + DataContractFactory::new(PROTOCOL_VERSION_V12).expect("expected to create factory"); + let document_schema = platform_value!({ + "type": "object", + "properties": { + "color": {"type": "string", "position": 0, "maxLength": 32}, + }, + "indices": [{ + "name": "byColor", + "properties": [{"color": "asc"}], + "countable": "countable", + "rangeCountable": true, + }], + "additionalProperties": false, + }); + let schemas = platform_value!({ "widget": document_schema }); + let contract = factory + .create_with_value_config( + dpp::tests::utils::generate_random_identifier_struct(), + 0, + schemas, + None, + None, + ) + .expect("create contract") + .data_contract_owned(); + + store_data_contract(&platform, &contract, version); + + let document_type = contract + .document_type_for_name("widget") + .expect("widget exists"); + + // 6 docs across 3 colors: red×2, blue×1, green×3. + for (i, color) in ["red", "red", "blue", "green", "green", "green"] + .iter() + .enumerate() + { + let mut doc = document_type + .random_document(Some((i + 1) as u64), platform_version) + .expect("random doc"); + let mut props = std::collections::BTreeMap::new(); + props.insert("color".to_string(), Value::Text(color.to_string())); + doc.set_properties(props); + store_document(&platform, &contract, document_type, &doc, platform_version); + } + + // Helper: issue a range count request with the given options. + // `ascending` controls the direction encoded into the + // `order_by` field as `[["color", "asc"|"desc"]]`. `None` → + // empty `order_by` bytes, which drive treats as "use ascending + // default" for split-mode entry ordering. + let make_request = |distinct: bool, limit: Option, ascending: Option| { + let where_clauses = vec![Value::Array(vec![ + Value::Text("color".to_string()), + Value::Text(">".to_string()), + Value::Text("blue".to_string()), + ])]; + let order_by_bytes = match ascending { + Some(asc) => serialize_where_clauses_to_cbor(vec![Value::Array(vec![ + Value::Text("color".to_string()), + Value::Text(if asc { "asc" } else { "desc" }.to_string()), + ])]), + None => Vec::new(), + }; + GetDocumentsCountRequestV0 { + data_contract_id: contract.id().to_vec(), + document_type: "widget".to_string(), + r#where: serialize_where_clauses_to_cbor(where_clauses), + return_distinct_counts_in_range: distinct, + order_by: order_by_bytes, + limit, + prove: false, + } + }; + + // Sum mode: green(3) + red(2) = 5. Range-without-distinct + // collapses to `AggregateCount` on the wire (no empty-key + // entry wrapping). + let result = platform + .query_documents_count_v0(make_request(false, None, None), &state, version) + .expect("query should succeed"); + assert!(result.errors.is_empty(), "errors: {:?}", result.errors); + match result.data { + Some(GetDocumentsCountResponseV0 { + result: Some(get_documents_count_response_v0::Result::Counts( + get_documents_count_response_v0::CountResults { + variant: + Some(get_documents_count_response_v0::count_results::Variant::AggregateCount( + total, + )), + }, + )), + .. + }) => { + assert_eq!(total, 5, "summed range mode → aggregate of 5"); + } + other => panic!("expected aggregate result, got {:?}", other), + } + + // Distinct mode ascending: [(green, 3), (red, 2)] in entries. + let result = platform + .query_documents_count_v0(make_request(true, None, Some(true)), &state, version) + .expect("query should succeed"); + assert!(result.errors.is_empty(), "errors: {:?}", result.errors); + match result.data { + Some(GetDocumentsCountResponseV0 { + result: + Some(get_documents_count_response_v0::Result::Counts( + get_documents_count_response_v0::CountResults { + variant: + Some(get_documents_count_response_v0::count_results::Variant::Entries( + entries, + )), + }, + )), + .. + }) => { + assert_eq!(entries.entries.len(), 2); + assert_eq!(entries.entries[0].key, b"green".to_vec()); + assert_eq!(entries.entries[0].count, 3); + assert_eq!(entries.entries[1].key, b"red".to_vec()); + assert_eq!(entries.entries[1].count, 2); + } + other => panic!("expected entries result, got {:?}", other), + } + + // Distinct mode with limit=1: only the first entry (ascending → green). + let result = platform + .query_documents_count_v0(make_request(true, Some(1), Some(true)), &state, version) + .expect("query should succeed"); + assert!(result.errors.is_empty()); + match result.data { + Some(GetDocumentsCountResponseV0 { + result: + Some(get_documents_count_response_v0::Result::Counts( + get_documents_count_response_v0::CountResults { + variant: + Some(get_documents_count_response_v0::count_results::Variant::Entries( + entries, + )), + }, + )), + .. + }) => { + assert_eq!(entries.entries.len(), 1); + assert_eq!(entries.entries[0].key, b"green".to_vec()); + } + other => panic!("expected entries result, got {:?}", other), + } + + // Distinct descending: [(red, 2), (green, 3)] in entries. + let result = platform + .query_documents_count_v0(make_request(true, None, Some(false)), &state, version) + .expect("query should succeed"); + assert!(result.errors.is_empty()); + match result.data { + Some(GetDocumentsCountResponseV0 { + result: + Some(get_documents_count_response_v0::Result::Counts( + get_documents_count_response_v0::CountResults { + variant: + Some(get_documents_count_response_v0::count_results::Variant::Entries( + entries, + )), + }, + )), + .. + }) => { + assert_eq!(entries.entries.len(), 2); + assert_eq!(entries.entries[0].key, b"red".to_vec()); + assert_eq!(entries.entries[1].key, b"green".to_vec()); + } + other => panic!("expected entries result, got {:?}", other), + } + } + + /// End-to-end pin for the `RangeDistinctProof` dispatch path — + /// `return_distinct_counts_in_range = true` + `prove = true` + + /// a range clause. Backed by a regular grovedb range proof + /// against the property-name `ProvableCountTree` whose + /// `KVValueHashFeatureType[WithChildHash]` ops carry per- + /// distinct-value counts bound to the merk root via + /// `node_hash_with_count`. Asserts the wire-shape contract: + /// a `Proof` response variant with non-empty grovedb proof + /// bytes (not the empty-envelope degenerate shape that a + /// no-match query would emit). + #[test] + fn test_documents_count_range_with_prove_and_distinct_returns_proof() { + use dpp::data_contract::DataContractFactory; + use dpp::platform_value::platform_value; + + const PROTOCOL_VERSION_V12: u32 = 12; + + let (platform, state, version) = setup_platform(None, Network::Testnet, None); + + let factory = + DataContractFactory::new(PROTOCOL_VERSION_V12).expect("expected to create factory"); + let document_schema = platform_value!({ + "type": "object", + "properties": { + "color": {"type": "string", "position": 0, "maxLength": 32}, + }, + "indices": [{ + "name": "byColor", + "properties": [{"color": "asc"}], + "countable": "countable", + "rangeCountable": true, + }], + "additionalProperties": false, + }); + let schemas = platform_value!({ "widget": document_schema }); + let contract = factory + .create_with_value_config( + dpp::tests::utils::generate_random_identifier_struct(), + 0, + schemas, + None, + None, + ) + .expect("create contract") + .data_contract_owned(); + + store_data_contract(&platform, &contract, version); + + // Insert a few widgets spread across distinct color values + // so the prove-distinct path actually carries per-key counts + // in its proof — without this the proof covers an empty + // range and the test only verifies dispatch acceptance. + // Same distribution as the no-prove test above: + // red×2, green×3, blue×1. `color > "blue"` excludes blue, + // so the proof should carry per-color entries for red(2) + // and green(3). + let document_type = contract + .document_type_for_name("widget") + .expect("widget exists"); + let platform_version = PlatformVersion::latest(); + for (i, color) in ["red", "red", "green", "green", "green", "blue"] + .iter() + .enumerate() + { + let mut doc = document_type + .random_document(Some((i + 1) as u64), platform_version) + .expect("random doc"); + let mut props = std::collections::BTreeMap::new(); + props.insert("color".to_string(), Value::Text(color.to_string())); + doc.set_properties(props); + store_document(&platform, &contract, document_type, &doc, platform_version); + } + + let where_clauses = vec![Value::Array(vec![ + Value::Text("color".to_string()), + Value::Text(">".to_string()), + Value::Text("blue".to_string()), + ])]; + let request = GetDocumentsCountRequestV0 { + data_contract_id: contract.id().to_vec(), + document_type: "widget".to_string(), + r#where: serialize_where_clauses_to_cbor(where_clauses), + return_distinct_counts_in_range: true, + order_by: Vec::new(), + limit: None, + prove: true, + }; + + let result = platform + .query_documents_count_v0(request, &state, version) + .expect("query should succeed"); + assert!( + result.errors.is_empty(), + "expected no validation errors, got {:?}", + result.errors + ); + match result.data { + Some(GetDocumentsCountResponseV0 { + result: Some(get_documents_count_response_v0::Result::Proof(proof)), + metadata: Some(_), + }) => { + // The proof should not be empty since we inserted + // matching documents — a non-trivial proof shape + // pins that the prover actually emitted per-key + // count entries, not just a degenerate envelope. + assert!( + !proof.grovedb_proof.is_empty(), + "expected non-empty grovedb proof bytes for non-empty range result" + ); + } + other => panic!("expected Proof response, got {:?}", other), + } } } diff --git a/packages/rs-drive-abci/src/query/document_split_count_query/mod.rs b/packages/rs-drive-abci/src/query/document_split_count_query/mod.rs deleted file mode 100644 index ccb7145123d..00000000000 --- a/packages/rs-drive-abci/src/query/document_split_count_query/mod.rs +++ /dev/null @@ -1,59 +0,0 @@ -use crate::error::query::QueryError; -use crate::error::Error; -use crate::platform_types::platform::Platform; -use crate::platform_types::platform_state::PlatformState; -use crate::query::QueryValidationResult; -use dapi_grpc::platform::v0::get_documents_split_count_request::Version as RequestVersion; -use dapi_grpc::platform::v0::get_documents_split_count_response::Version as ResponseVersion; -use dapi_grpc::platform::v0::{GetDocumentsSplitCountRequest, GetDocumentsSplitCountResponse}; -use dpp::version::PlatformVersion; - -mod v0; - -impl Platform { - /// Querying of document split count - pub fn query_documents_split_count( - &self, - GetDocumentsSplitCountRequest { version }: GetDocumentsSplitCountRequest, - platform_state: &PlatformState, - platform_version: &PlatformVersion, - ) -> Result, Error> { - let Some(version) = version else { - return Ok(QueryValidationResult::new_with_error( - QueryError::DecodingError( - "could not decode documents split count query".to_string(), - ), - )); - }; - - let feature_version_bounds = &platform_version.drive_abci.query.document_split_count_query; - - let feature_version = match &version { - RequestVersion::V0(_) => 0, - }; - if !feature_version_bounds.check_version(feature_version) { - return Ok(QueryValidationResult::new_with_error( - QueryError::UnsupportedQueryVersion( - "documents_split_count".to_string(), - feature_version_bounds.min_version, - feature_version_bounds.max_version, - platform_version.protocol_version, - feature_version, - ), - )); - } - match version { - RequestVersion::V0(request_v0) => { - let result = self.query_documents_split_count_v0( - request_v0, - platform_state, - platform_version, - )?; - - Ok(result.map(|response_v0| GetDocumentsSplitCountResponse { - version: Some(ResponseVersion::V0(response_v0)), - })) - } - } - } -} diff --git a/packages/rs-drive-abci/src/query/document_split_count_query/v0/mod.rs b/packages/rs-drive-abci/src/query/document_split_count_query/v0/mod.rs deleted file mode 100644 index 80d3c51b345..00000000000 --- a/packages/rs-drive-abci/src/query/document_split_count_query/v0/mod.rs +++ /dev/null @@ -1,666 +0,0 @@ -use crate::error::query::QueryError; -use crate::error::Error; -use crate::platform_types::platform::Platform; -use crate::platform_types::platform_state::PlatformState; -use crate::query::response_metadata::CheckpointUsed; -use crate::query::QueryValidationResult; -use dapi_grpc::platform::v0::get_documents_split_count_request::GetDocumentsSplitCountRequestV0; -use dapi_grpc::platform::v0::get_documents_split_count_response::{ - get_documents_split_count_response_v0, GetDocumentsSplitCountResponseV0, -}; -use dpp::check_validation_result_with_data; -use dpp::data_contract::accessors::v0::DataContractV0Getters; -use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters; -use dpp::identifier::Identifier; -use dpp::platform_value::Value; -use dpp::validation::ValidationResult; -use dpp::version::PlatformVersion; -use drive::error::query::QuerySyntaxError; -use drive::query::{DriveDocumentCountQuery, DriveDocumentQuery, WhereClause}; -use drive::util::grove_operations::GroveDBToUse; - -impl Platform { - pub(super) fn query_documents_split_count_v0( - &self, - GetDocumentsSplitCountRequestV0 { - data_contract_id, - document_type: document_type_name, - r#where, - split_count_by_index_property, - prove, - }: GetDocumentsSplitCountRequestV0, - platform_state: &PlatformState, - platform_version: &PlatformVersion, - ) -> Result, Error> { - let contract_id: Identifier = check_validation_result_with_data!(data_contract_id - .try_into() - .map_err(|_| QueryError::InvalidArgument( - "id must be a valid identifier (32 bytes long)".to_string() - ))); - - let (_, contract) = self.drive.get_contract_with_fetch_info_and_fee( - contract_id.to_buffer(), - None, - true, - None, - platform_version, - )?; - - let contract = check_validation_result_with_data!(contract.ok_or(QueryError::Query( - QuerySyntaxError::DataContractNotFound( - "contract not found when querying from value with contract info", - ) - ))); - - let contract_ref = &contract.contract; - - let document_type = check_validation_result_with_data!(contract_ref - .document_type_for_name(document_type_name.as_str()) - .map_err(|_| QueryError::InvalidArgument(format!( - "document type {} not found for contract {}", - document_type_name, contract_id - )))); - - // Validate the split property exists in the document type - if split_count_by_index_property.is_empty() { - return Ok(QueryValidationResult::new_with_error( - QueryError::InvalidArgument( - "split_count_by_index_property must not be empty".to_string(), - ), - )); - } - - // Check that the property exists in the document type schema - if document_type - .properties() - .get(split_count_by_index_property.as_str()) - .is_none() - { - return Ok(QueryValidationResult::new_with_error( - QueryError::InvalidArgument(format!( - "property {} not found in document type {}", - split_count_by_index_property, document_type_name - )), - )); - } - - let where_clause = if r#where.is_empty() { - Value::Null - } else { - check_validation_result_with_data!(ciborium::de::from_reader(r#where.as_slice()) - .map_err(|_| { - QueryError::Query(QuerySyntaxError::DeserializationError( - "unable to decode 'where' query from cbor".to_string(), - )) - })) - }; - - // Parse where clauses - let all_where_clauses: Vec = - check_validation_result_with_data!(match &where_clause { - Value::Null => Ok(vec![]), - Value::Array(clauses) => clauses - .iter() - .map(|wc| { - if let Value::Array(components) = wc { - WhereClause::from_components(components).map_err(|e| match e { - drive::error::Error::Query(qe) => QueryError::Query(qe), - other => QueryError::InvalidArgument(format!( - "error parsing where clauses: {}", - other - )), - }) - } else { - Err(QueryError::Query( - QuerySyntaxError::InvalidFormatWhereClause( - "where clause must be an array", - ), - )) - } - }) - .collect::, QueryError>>(), - _ => Err(QueryError::Query( - QuerySyntaxError::InvalidFormatWhereClause("where clause must be an array"), - )), - }); - - let response = if prove { - // For prove path, use the standard DriveDocumentQuery approach. - let mut drive_query = - check_validation_result_with_data!(DriveDocumentQuery::from_decomposed_values( - where_clause, - None, - Some(self.config.drive.default_query_limit), - None, - true, - None, - contract_ref, - document_type, - &self.config.drive, - )); - - // Same defensive cap as on the total-count handler; see the - // matching note there. - drive_query.limit = Some(u16::MAX); - - let proof = - match drive_query.execute_with_proof(&self.drive, None, None, platform_version) { - Ok(result) => result.0, - Err(drive::error::Error::Query(query_error)) => { - return Ok(QueryValidationResult::new_with_error(QueryError::Query( - query_error, - ))); - } - Err(e) => return Err(e.into()), - }; - - let (grovedb_used, proof) = - self.response_proof_v0(platform_state, proof, GroveDBToUse::Current)?; - - GetDocumentsSplitCountResponseV0 { - result: Some(get_documents_split_count_response_v0::Result::Proof(proof)), - metadata: Some(self.response_metadata_v0(platform_state, grovedb_used)), - } - } else { - // Same operator restriction as the total-count fast path. - if DriveDocumentCountQuery::has_unsupported_operator(&all_where_clauses) { - return Ok(QueryValidationResult::new_with_error( - QueryError::InvalidArgument( - "split count query supports only `==` and `in` where-clause operators; \ - range operators (`>`, `<`, `between`, `startsWith`) are not yet \ - supported on the no-prove path" - .to_string(), - ), - )); - } - - // For no-prove path, use CountTree-based approach. - // Find a countable index where the split property follows the where clause - // properties in the index. - let countable_index = DriveDocumentCountQuery::find_countable_index_for_split( - document_type.indexes(), - &all_where_clauses, - &split_count_by_index_property, - ); - - let entries = if let Some(index) = countable_index { - let count_query = DriveDocumentCountQuery { - document_type, - contract_id: contract_id.to_buffer(), - document_type_name: document_type_name.clone(), - index, - where_clauses: all_where_clauses, - split_by_property: Some(split_count_by_index_property), - }; - - let results = count_query.execute_no_proof(&self.drive, None, platform_version)?; - - results - .into_iter() - .map( - |entry| get_documents_split_count_response_v0::SplitCountEntry { - key: entry.key, - count: entry.count, - }, - ) - .collect() - } else { - return Ok(QueryValidationResult::new_with_error( - QueryError::InvalidArgument( - "split count query requires a countable index where the split property \ - follows the where clause properties in the index" - .to_string(), - ), - )); - }; - - GetDocumentsSplitCountResponseV0 { - result: Some(get_documents_split_count_response_v0::Result::SplitCounts( - get_documents_split_count_response_v0::SplitCounts { entries }, - )), - metadata: Some(self.response_metadata_v0(platform_state, CheckpointUsed::Current)), - } - }; - - Ok(QueryValidationResult::new_with_data(response)) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::query::tests::{setup_platform, store_data_contract, store_document}; - use dpp::dashcore::Network; - use dpp::data_contract::document_type::random_document::CreateRandomDocument; - use dpp::tests::json_document::json_document_to_contract_with_ids; - use rand::rngs::StdRng; - use rand::SeedableRng; - - #[test] - fn test_documents_split_count_no_prove() { - let (platform, state, version) = setup_platform(None, Network::Testnet, None); - - let platform_version = PlatformVersion::latest(); - - let data_contract = json_document_to_contract_with_ids( - "tests/supporting_files/contract/family/family-contract-countable.json", - None, - None, - false, - platform_version, - ) - .expect("expected to get json based contract"); - - store_data_contract(&platform, &data_contract, version); - - let data_contract_id = data_contract.id(); - let document_type_name = "person"; - let document_type = data_contract - .document_type_for_name(document_type_name) - .expect("expected document type"); - - let mut std_rng = StdRng::seed_from_u64(600); - for _ in 0..5 { - let random_document = document_type - .random_document_with_rng(&mut std_rng, platform_version) - .expect("expected to get random document"); - store_document( - &platform, - &data_contract, - document_type, - &random_document, - platform_version, - ); - } - - let request = GetDocumentsSplitCountRequestV0 { - data_contract_id: data_contract_id.to_vec(), - document_type: document_type_name.to_string(), - r#where: vec![], - split_count_by_index_property: "firstName".to_string(), - prove: false, - }; - - let result = platform - .query_documents_split_count_v0(request, &state, version) - .expect("expected query to succeed"); - - assert!(result.errors.is_empty(), "errors: {:?}", result.errors); - - match result.data { - Some(GetDocumentsSplitCountResponseV0 { - result: - Some(get_documents_split_count_response_v0::Result::SplitCounts(split_counts)), - metadata: Some(_), - }) => { - // The total count across all splits should equal 5 - let total: u64 = split_counts.entries.iter().map(|e| e.count).sum(); - assert_eq!(total, 5, "expected total split count of 5 documents"); - // Each entry should have a non-empty key (firstName is required) - for entry in &split_counts.entries { - assert!(!entry.key.is_empty(), "expected non-empty split key"); - assert!(entry.count > 0, "expected positive count per split"); - } - } - other => panic!("expected split counts result, got {:?}", other), - } - } - - #[test] - fn test_documents_split_count_with_prove() { - let (platform, state, version) = setup_platform(None, Network::Testnet, None); - - let platform_version = PlatformVersion::latest(); - - let data_contract = json_document_to_contract_with_ids( - "tests/supporting_files/contract/family/family-contract-countable.json", - None, - None, - false, - platform_version, - ) - .expect("expected to get json based contract"); - - store_data_contract(&platform, &data_contract, version); - - let data_contract_id = data_contract.id(); - let document_type_name = "person"; - let document_type = data_contract - .document_type_for_name(document_type_name) - .expect("expected document type"); - - let mut std_rng = StdRng::seed_from_u64(600); - for _ in 0..3 { - let random_document = document_type - .random_document_with_rng(&mut std_rng, platform_version) - .expect("expected to get random document"); - store_document( - &platform, - &data_contract, - document_type, - &random_document, - platform_version, - ); - } - - let request = GetDocumentsSplitCountRequestV0 { - data_contract_id: data_contract_id.to_vec(), - document_type: document_type_name.to_string(), - r#where: vec![], - split_count_by_index_property: "firstName".to_string(), - prove: true, - }; - - let result = platform - .query_documents_split_count_v0(request, &state, version) - .expect("expected query to succeed"); - - assert!(result.errors.is_empty(), "errors: {:?}", result.errors); - - assert!(matches!( - result.data, - Some(GetDocumentsSplitCountResponseV0 { - result: Some(get_documents_split_count_response_v0::Result::Proof(_)), - metadata: Some(_), - }) - )); - } - - #[test] - fn test_documents_split_count_empty_split_property() { - let (platform, state, version) = setup_platform(None, Network::Testnet, None); - - let platform_version = PlatformVersion::latest(); - - let data_contract = json_document_to_contract_with_ids( - "tests/supporting_files/contract/family/family-contract-countable.json", - None, - None, - false, - platform_version, - ) - .expect("expected to get json based contract"); - - store_data_contract(&platform, &data_contract, version); - - let data_contract_id = data_contract.id(); - let document_type_name = "person"; - - let request = GetDocumentsSplitCountRequestV0 { - data_contract_id: data_contract_id.to_vec(), - document_type: document_type_name.to_string(), - r#where: vec![], - split_count_by_index_property: "".to_string(), - prove: false, - }; - - let result = platform - .query_documents_split_count_v0(request, &state, version) - .expect("expected query to succeed"); - - assert!(matches!( - result.errors.as_slice(), - [QueryError::InvalidArgument(msg)] if msg == "split_count_by_index_property must not be empty" - )); - } - - fn serialize_where_clauses_to_cbor(where_clauses: Vec) -> Vec { - use ciborium::value::Value as CborValue; - let cbor: CborValue = TryInto::::try_into(Value::Array(where_clauses)) - .expect("expected to convert where clauses to cbor value"); - let mut out = Vec::new(); - ciborium::ser::into_writer(&cbor, &mut out).expect("expected to serialize where clauses"); - out - } - - fn store_person_document( - platform: &crate::test::helpers::setup::TempPlatform, - data_contract: &dpp::prelude::DataContract, - id: [u8; 32], - first_name: &str, - last_name: &str, - age: u64, - platform_version: &PlatformVersion, - ) { - use dpp::document::{Document, DocumentV0}; - use std::collections::BTreeMap; - - let document_type = data_contract - .document_type_for_name("person") - .expect("expected document type"); - - let mut properties = BTreeMap::new(); - properties.insert("firstName".to_string(), Value::Text(first_name.to_string())); - properties.insert("lastName".to_string(), Value::Text(last_name.to_string())); - properties.insert("age".to_string(), Value::U64(age)); - - let document: Document = DocumentV0 { - id: Identifier::from(id), - owner_id: Identifier::from([0u8; 32]), - properties, - revision: None, - created_at: None, - updated_at: None, - transferred_at: None, - created_at_block_height: None, - updated_at_block_height: None, - transferred_at_block_height: None, - created_at_core_block_height: None, - updated_at_core_block_height: None, - transferred_at_core_block_height: None, - creator_id: None, - } - .into(); - - store_document( - platform, - data_contract, - document_type, - &document, - platform_version, - ); - } - - #[test] - fn test_documents_split_count_with_in_prefix() { - let (platform, state, version) = setup_platform(None, Network::Testnet, None); - let platform_version = PlatformVersion::latest(); - - let data_contract = json_document_to_contract_with_ids( - "tests/supporting_files/contract/family/family-contract-countable.json", - None, - None, - false, - platform_version, - ) - .expect("expected to get json based contract"); - - store_data_contract(&platform, &data_contract, version); - - // firstName IN ["Alice", "Bob"] split by lastName. - // Smith=3 (Alice+Alice+Bob), Jones=2 (Alice+Bob); Carol/Doe excluded. - store_person_document( - &platform, - &data_contract, - [1u8; 32], - "Alice", - "Smith", - 30, - platform_version, - ); - store_person_document( - &platform, - &data_contract, - [2u8; 32], - "Alice", - "Smith", - 31, - platform_version, - ); - store_person_document( - &platform, - &data_contract, - [3u8; 32], - "Bob", - "Smith", - 32, - platform_version, - ); - store_person_document( - &platform, - &data_contract, - [4u8; 32], - "Alice", - "Jones", - 33, - platform_version, - ); - store_person_document( - &platform, - &data_contract, - [5u8; 32], - "Bob", - "Jones", - 34, - platform_version, - ); - store_person_document( - &platform, - &data_contract, - [6u8; 32], - "Carol", - "Doe", - 35, - platform_version, - ); - - let where_clauses = vec![Value::Array(vec![ - Value::Text("firstName".to_string()), - Value::Text("in".to_string()), - Value::Array(vec![ - Value::Text("Alice".to_string()), - Value::Text("Bob".to_string()), - ]), - ])]; - - let request = GetDocumentsSplitCountRequestV0 { - data_contract_id: data_contract.id().to_vec(), - document_type: "person".to_string(), - r#where: serialize_where_clauses_to_cbor(where_clauses), - split_count_by_index_property: "lastName".to_string(), - prove: false, - }; - - let result = platform - .query_documents_split_count_v0(request, &state, version) - .expect("expected query to succeed"); - - assert!(result.errors.is_empty(), "errors: {:?}", result.errors); - - match result.data { - Some(GetDocumentsSplitCountResponseV0 { - result: - Some(get_documents_split_count_response_v0::Result::SplitCounts(split_counts)), - metadata: Some(_), - }) => { - let total: u64 = split_counts.entries.iter().map(|e| e.count).sum(); - assert_eq!( - total, 5, - "expected total of 5 (3 Smith + 2 Jones, Carol/Doe excluded)" - ); - assert_eq!( - split_counts.entries.len(), - 2, - "expected 2 split entries (Smith and Jones)" - ); - for entry in &split_counts.entries { - assert!(entry.count > 0); - } - } - other => panic!("expected split counts result, got {:?}", other), - } - } - - #[test] - fn test_documents_split_count_rejects_range_operator() { - let (platform, state, version) = setup_platform(None, Network::Testnet, None); - let platform_version = PlatformVersion::latest(); - - let data_contract = json_document_to_contract_with_ids( - "tests/supporting_files/contract/family/family-contract-countable.json", - None, - None, - false, - platform_version, - ) - .expect("expected to get json based contract"); - - store_data_contract(&platform, &data_contract, version); - - // [["age", ">=", 30]] — range operator, must be rejected on no-prove path. - let where_clauses = vec![Value::Array(vec![ - Value::Text("age".to_string()), - Value::Text(">=".to_string()), - Value::U64(30), - ])]; - - let request = GetDocumentsSplitCountRequestV0 { - data_contract_id: data_contract.id().to_vec(), - document_type: "person".to_string(), - r#where: serialize_where_clauses_to_cbor(where_clauses), - split_count_by_index_property: "firstName".to_string(), - prove: false, - }; - - let result = platform - .query_documents_split_count_v0(request, &state, version) - .expect("expected query to return validation error"); - - assert!( - matches!( - result.errors.as_slice(), - [QueryError::InvalidArgument(msg)] if msg.contains("range operators") && msg.contains("not yet") - ), - "expected range-operator rejection, got {:?}", - result.errors - ); - } - - #[test] - fn test_documents_split_count_nonexistent_property() { - let (platform, state, version) = setup_platform(None, Network::Testnet, None); - - let platform_version = PlatformVersion::latest(); - - let data_contract = json_document_to_contract_with_ids( - "tests/supporting_files/contract/family/family-contract-countable.json", - None, - None, - false, - platform_version, - ) - .expect("expected to get json based contract"); - - store_data_contract(&platform, &data_contract, version); - - let data_contract_id = data_contract.id(); - let document_type_name = "person"; - - let request = GetDocumentsSplitCountRequestV0 { - data_contract_id: data_contract_id.to_vec(), - document_type: document_type_name.to_string(), - r#where: vec![], - split_count_by_index_property: "nonExistentProp".to_string(), - prove: false, - }; - - let result = platform - .query_documents_split_count_v0(request, &state, version) - .expect("expected query to succeed"); - - assert!(matches!( - result.errors.as_slice(), - [QueryError::InvalidArgument(msg)] if msg.contains("property nonExistentProp not found") - )); - } -} diff --git a/packages/rs-drive-abci/src/query/mod.rs b/packages/rs-drive-abci/src/query/mod.rs index e87aaf112a0..79ac258b28c 100644 --- a/packages/rs-drive-abci/src/query/mod.rs +++ b/packages/rs-drive-abci/src/query/mod.rs @@ -2,7 +2,6 @@ mod address_funds; mod data_contract_based_queries; mod document_count_query; mod document_query; -mod document_split_count_query; mod group_queries; mod identity_based_queries; mod prefunded_specialized_balances; diff --git a/packages/rs-drive-abci/src/query/service.rs b/packages/rs-drive-abci/src/query/service.rs index 4a5aceb2f3f..14fa7c49974 100644 --- a/packages/rs-drive-abci/src/query/service.rs +++ b/packages/rs-drive-abci/src/query/service.rs @@ -23,8 +23,7 @@ use dapi_grpc::platform::v0::{ GetCurrentQuorumsInfoResponse, GetDataContractHistoryRequest, GetDataContractHistoryResponse, GetDataContractRequest, GetDataContractResponse, GetDataContractsRequest, GetDataContractsResponse, GetDocumentsCountRequest, GetDocumentsCountResponse, - GetDocumentsRequest, GetDocumentsResponse, GetDocumentsSplitCountRequest, - GetDocumentsSplitCountResponse, GetEpochsInfoRequest, GetEpochsInfoResponse, + GetDocumentsRequest, GetDocumentsResponse, GetEpochsInfoRequest, GetEpochsInfoResponse, GetEvonodesProposedEpochBlocksByIdsRequest, GetEvonodesProposedEpochBlocksByRangeRequest, GetEvonodesProposedEpochBlocksResponse, GetFinalizedEpochInfosRequest, GetFinalizedEpochInfosResponse, GetGroupActionSignersRequest, GetGroupActionSignersResponse, @@ -419,18 +418,6 @@ impl PlatformService for QueryService { .await } - async fn get_documents_split_count( - &self, - request: Request, - ) -> Result, Status> { - self.handle_blocking_query( - request, - Platform::::query_documents_split_count, - "get_documents_split_count", - ) - .await - } - async fn get_identity_by_public_key_hash( &self, request: Request, diff --git a/packages/rs-drive-proof-verifier/src/lib.rs b/packages/rs-drive-proof-verifier/src/lib.rs index 955fa0602dd..cece98edd60 100644 --- a/packages/rs-drive-proof-verifier/src/lib.rs +++ b/packages/rs-drive-proof-verifier/src/lib.rs @@ -9,8 +9,16 @@ mod proof; pub mod types; mod verify; pub use error::Error; -pub use proof::document_count::DocumentCount; +pub use proof::document_count::{ + verify_aggregate_count_proof, verify_distinct_count_proof, verify_point_lookup_count_proof, + verify_primary_key_count_tree_proof, DocumentCount, +}; pub use proof::document_split_count::DocumentSplitCounts; +// Re-export `SplitCountEntry` from rs-drive at the proof-verifier +// crate root so SDK consumers don't have to depend on rs-drive +// directly just to name the entry type returned by +// `verify_distinct_count_proof` and `DocumentSplitCounts::from_verified`. +pub use drive::query::SplitCountEntry; pub use proof::{FromProof, Length}; // Re-export context provider types from dash-context-provider diff --git a/packages/rs-drive-proof-verifier/src/proof/document_count.rs b/packages/rs-drive-proof-verifier/src/proof/document_count.rs index 46065aeae4c..13f104f1806 100644 --- a/packages/rs-drive-proof-verifier/src/proof/document_count.rs +++ b/packages/rs-drive-proof-verifier/src/proof/document_count.rs @@ -5,7 +5,7 @@ use dapi_grpc::platform::v0::{GetDocumentsCountResponse, Proof, ResponseMetadata use dapi_grpc::platform::VersionedGrpcResponse; use dpp::dashcore::Network; use dpp::version::PlatformVersion; -use drive::query::DriveDocumentQuery; +use drive::query::{DriveDocumentCountQuery, DriveDocumentQuery, SplitCountEntry}; /// The count of documents matching a query, verified from proof. #[derive(Debug, Clone, PartialEq, Eq)] @@ -55,3 +55,288 @@ where Ok((Some(DocumentCount(count)), mtd.clone(), proof.clone())) } } + +/// Verify a grovedb `AggregateCountOnRange` proof and the surrounding +/// tenderdash commit, returning the verified document count. +/// +/// Thin tenderdash-composition wrapper over +/// [`DriveDocumentCountQuery::verify_aggregate_count_proof`] in +/// rs-drive (which does the merk-level verification). Both helpers +/// reuse the prover's `aggregate_count_path_query` internally so the +/// path query bytes match byte-for-byte and the merk root +/// recomputation succeeds; the caller passes the `query` struct +/// itself rather than a pre-built `PathQuery`, removing a step +/// where the SDK and server could drift. +/// +/// Counterpart to the materialize-and-count path in +/// [`FromProof for DocumentCount`] above: where +/// that one verifies a regular grovedb proof that yields concrete +/// documents and counts them client-side, this verifies the +/// merk-level aggregate primitive that yields a single `u64` +/// directly (capped only by the merk tree size, not `u16::MAX`). +pub fn verify_aggregate_count_proof( + query: &DriveDocumentCountQuery, + proof: &Proof, + mtd: &ResponseMetadata, + platform_version: &PlatformVersion, + provider: &dyn ContextProvider, +) -> Result { + let (root_hash, count) = query + .verify_aggregate_count_proof(&proof.grovedb_proof, platform_version) + .map_drive_error(proof, mtd)?; + + verify_tenderdash_proof(proof, mtd, &root_hash, provider)?; + + Ok(count) +} + +/// Verify a regular grovedb range proof against a `ProvableCountTree` +/// and the surrounding tenderdash commit, returning the verified +/// per-`(in_key, key)` counts the proof commits to. +/// +/// Thin tenderdash-composition wrapper over +/// [`DriveDocumentCountQuery::verify_distinct_count_proof`] in +/// rs-drive (which does the merk-level verification and the +/// in_key extraction from `(path, key, element)` triples). +/// +/// ## No cross-fork merge +/// +/// For compound queries (an `In` clause on a prefix property) each +/// returned [`SplitCountEntry`] retains its `in_key` (the In value +/// for that fork) alongside the terminator `key`. Cross-fork +/// aggregation is intentionally NOT done here — see +/// [`SplitCountEntry`]'s doc for the rationale. +/// +/// ## Trade-off vs. the aggregate path +/// +/// Proof size is O(distinct `(in_key, terminator)` pairs matched) +/// rather than O(log n), because each distinct in-range pair emits +/// its own `KVCount` op instead of being collapsed into a boundary +/// subtree. Still strictly smaller than materialize-and-count. +pub fn verify_distinct_count_proof( + query: &DriveDocumentCountQuery, + proof: &Proof, + mtd: &ResponseMetadata, + limit: u16, + left_to_right: bool, + platform_version: &PlatformVersion, + provider: &dyn ContextProvider, +) -> Result, Error> { + let (root_hash, entries) = query + .verify_distinct_count_proof(&proof.grovedb_proof, limit, left_to_right, platform_version) + .map_drive_error(proof, mtd)?; + + verify_tenderdash_proof(proof, mtd, &root_hash, provider)?; + + Ok(entries) +} + +/// Verify a grovedb point-lookup count proof against a +/// `countable: true` index and return the per-branch entries. +/// +/// Thin tenderdash-composition wrapper over +/// [`DriveDocumentCountQuery::verify_point_lookup_count_proof`] in +/// rs-drive (which does the merk-level verification and walks the +/// verified elements to extract `count_value`). +/// +/// ## Entry shape +/// +/// - **Equal-only, fully covered**: a single entry with empty `key` +/// and `count` equal to the covered branch's CountTree +/// `count_value`. +/// - **Equal prefix + `In` on last property**: one entry per In +/// value, `key = `, `count` equal to that In +/// value's CountTree `count_value`. Branches with zero documents +/// are omitted from the result (callers can detect "I asked for 3 +/// In values but got entries for 2" directly). +/// +/// ## Replaces materialize-and-count +/// +/// Before this primitive landed, prove count queries with no range +/// clause used `DriveDocumentQuery::execute_with_proof` to prove +/// every matching document and counted them client-side. That path +/// scaled with matching docs and was capped at `u16::MAX`. The +/// CountTree element proof is O(k × log n) where k is the number of +/// covered branches — bandwidth and CPU drop by orders of magnitude +/// on counted indexes and the cap disappears. +pub fn verify_point_lookup_count_proof( + query: &DriveDocumentCountQuery, + proof: &Proof, + mtd: &ResponseMetadata, + platform_version: &PlatformVersion, + provider: &dyn ContextProvider, +) -> Result, Error> { + let (root_hash, entries) = query + .verify_point_lookup_count_proof(&proof.grovedb_proof, platform_version) + .map_drive_error(proof, mtd)?; + + verify_tenderdash_proof(proof, mtd, &root_hash, provider)?; + + Ok(entries) +} + +/// Verify a grovedb proof of the document type's primary-key +/// `CountTree` element and return the unfiltered total count. +/// +/// Thin tenderdash-composition wrapper over +/// [`DriveDocumentCountQuery::verify_primary_key_count_tree_proof`]. +/// Used by the prove path's `documents_countable: true` fast path — +/// when the where clauses are empty and the document type has +/// `documents_countable: true`, the server proves the type-level +/// CountTree element directly and the SDK extracts the count from +/// the verified element. +pub fn verify_primary_key_count_tree_proof( + contract_id: [u8; 32], + document_type_name: &str, + proof: &Proof, + mtd: &ResponseMetadata, + platform_version: &PlatformVersion, + provider: &dyn ContextProvider, +) -> Result { + let (root_hash, count) = DriveDocumentCountQuery::verify_primary_key_count_tree_proof( + &proof.grovedb_proof, + contract_id, + document_type_name, + platform_version, + ) + .map_drive_error(proof, mtd)?; + + verify_tenderdash_proof(proof, mtd, &root_hash, provider)?; + + Ok(count) +} + +#[cfg(test)] +mod tests { + //! Local-only tests for parts of this module that don't need a + //! populated Drive. The full happy-path verification of + //! `verify_aggregate_count_proof` / `verify_distinct_count_proof` + //! is covered end-to-end in the drive crate's + //! `range_countable_index_e2e_tests` (where the prover and + //! verifier roundtrip on a real Drive), and in the rs-sdk + //! integration tests. Here we cover the error-mapping branch + //! for garbage proof bytes: the rs-drive verify call fails, and + //! the `MapGroveDbError` adapter must thread the grovedb error + //! into our `Error::GroveDBError` variant with the right + //! correlation fields (proof_bytes, height, time_ms). + use super::*; + use dapi_grpc::platform::v0::{Proof, ResponseMetadata}; + use dash_context_provider::ContextProviderError; + use dpp::data_contract::TokenConfiguration; + use dpp::prelude::{CoreBlockHeight, DataContract, Identifier}; + use std::sync::Arc; + + /// Provider that panics if called — the GroveDBError path + /// short-circuits before reaching tenderdash verification, so + /// the provider must never be touched by these tests. + struct UnreachableProvider; + + impl ContextProvider for UnreachableProvider { + fn get_data_contract( + &self, + _id: &Identifier, + _pv: &PlatformVersion, + ) -> Result>, ContextProviderError> { + panic!("should not be called") + } + fn get_token_configuration( + &self, + _id: &Identifier, + ) -> Result, ContextProviderError> { + panic!("should not be called") + } + fn get_quorum_public_key( + &self, + _qt: u32, + _qh: [u8; 32], + _h: u32, + ) -> Result<[u8; 48], ContextProviderError> { + panic!("should not be called") + } + fn get_platform_activation_height(&self) -> Result { + panic!("should not be called") + } + } + + fn arbitrary_metadata() -> ResponseMetadata { + ResponseMetadata { + height: 1, + time_ms: 0, + ..Default::default() + } + } + + #[test] + fn split_count_entry_struct_constructs_and_clones() { + // Pins the `SplitCountEntry` public-API shape (Clone + Eq + + // per-field accessors). The struct now lives in rs-drive and + // is re-exported from drive-proof-verifier, but SDK callers + // pattern-match on it heavily, so a stable derivation set is + // load-bearing for the API surface. + let a = SplitCountEntry { + in_key: Some(b"acme".to_vec()), + key: b"red".to_vec(), + count: 42, + }; + let b = a.clone(); + assert_eq!(a, b); + assert_eq!(a.in_key.as_deref(), Some(b"acme".as_slice())); + assert_eq!(a.key, b"red".to_vec()); + assert_eq!(a.count, 42); + + let flat = SplitCountEntry { + in_key: None, + key: b"green".to_vec(), + count: 7, + }; + assert!(flat.in_key.is_none()); + + // Inequality across each field. + let different_in_key = SplitCountEntry { + in_key: Some(b"contoso".to_vec()), + ..a.clone() + }; + assert_ne!(a, different_in_key); + let different_key = SplitCountEntry { + key: b"blue".to_vec(), + ..a.clone() + }; + assert_ne!(a, different_key); + let different_count = SplitCountEntry { count: 99, ..a }; + assert_ne!(b, different_count); + } + + /// Tests for the error-mapping path require a real + /// `DriveDocumentCountQuery` (the new API takes the query rather + /// than a pre-built path query). Constructing one needs a + /// `DocumentTypeRef` + `Index` which require dpp/fixtures-and- + /// mocks. The error-mapping is exercised end-to-end by the + /// drive crate's range_countable_index_e2e_tests instead. + /// + /// What we can pin here: the wrappers are thin enough that + /// running them isn't more interesting than running the + /// underlying rs-drive verify methods. The structural test + /// above is the load-bearing guarantee for the public API. + #[test] + fn proof_metadata_helper_round_trips() { + // Defense-in-depth: the wrappers carry `Proof` and + // `ResponseMetadata` through `MapGroveDbError`. Pin that + // the helper types are constructible with the fields we + // depend on (height, time_ms, grovedb_proof) so a future + // dapi-grpc refactor that renames any of them fails this + // test in addition to breaking the call sites in this file. + let proof = Proof { + grovedb_proof: vec![0xab, 0xcd], + ..Default::default() + }; + let mtd = arbitrary_metadata(); + assert_eq!(proof.grovedb_proof, vec![0xab, 0xcd]); + assert_eq!(mtd.height, 1); + assert_eq!(mtd.time_ms, 0); + + // Touch the provider type so unused-import linters don't + // strip it (it's not used by other assertions in this + // module). + let _provider: &dyn ContextProvider = &UnreachableProvider; + } +} diff --git a/packages/rs-drive-proof-verifier/src/proof/document_split_count.rs b/packages/rs-drive-proof-verifier/src/proof/document_split_count.rs index 7b1277e9577..ef53b2dd15f 100644 --- a/packages/rs-drive-proof-verifier/src/proof/document_split_count.rs +++ b/packages/rs-drive-proof-verifier/src/proof/document_split_count.rs @@ -1,42 +1,66 @@ -use crate::error::MapGroveDbError; -use crate::verify::verify_tenderdash_proof; use crate::{ContextProvider, Error, FromProof}; -use dapi_grpc::platform::v0::{GetDocumentsSplitCountResponse, Proof, ResponseMetadata}; -use dapi_grpc::platform::VersionedGrpcResponse; +use dapi_grpc::platform::v0::{GetDocumentsCountResponse, Proof, ResponseMetadata}; use dpp::dashcore::Network; -use dpp::data_contract::document_type::methods::DocumentTypeV0Methods; -use dpp::document::Document; -use dpp::document::DocumentV0Getters; use dpp::version::PlatformVersion; -use drive::query::DriveDocumentQuery; +use drive::query::{DriveDocumentQuery, SplitCountEntry}; use std::collections::BTreeMap; /// The split counts of documents matching a query, verified from proof. -/// Maps property value bytes to count. /// -/// The keys are the byte form of each split-property value as produced by -/// [`DocumentTypeBasicMethods::serialize_value_for_key`], so they line up -/// with the keys returned on the no-proof / CountTree path. +/// Each entry carries the serialized split-property value (`key`) as +/// produced by +/// [`DocumentTypeBasicMethods::serialize_value_for_key`], the verified +/// `count`, and an optional `in_key` carrying the In-prefix value for +/// compound range-distinct queries (see the [`SplitCountEntry`] +/// doc for rationale on why compound results stay unmerged). +/// +/// For flat queries (per-`In`-value mode without a range, or per- +/// distinct-value-in-range mode without an `In` on prefix) every +/// entry's `in_key` is `None`. Callers can recover the historical +/// `BTreeMap, u64>` shape by collecting `(key, count)` pairs +/// — see [`Self::into_flat_map`]. #[derive(Debug, Clone, PartialEq, Eq, Default)] -pub struct DocumentSplitCounts(pub BTreeMap, u64>); +pub struct DocumentSplitCounts(pub Vec); + +impl DocumentSplitCounts { + /// Collect entries into a `BTreeMap, u64>` keyed by the + /// terminator `key`, summing across `in_key` forks. Use this when + /// the caller wants the merged-histogram view of a compound + /// query (or for backwards compatibility with the pre-no-merge + /// API shape). Flat queries pass through unchanged. + pub fn into_flat_map(self) -> BTreeMap, u64> { + let mut out: BTreeMap, u64> = BTreeMap::new(); + for entry in self.0 { + *out.entry(entry.key).or_insert(0) += entry.count; + } + out + } + + /// Build a [`DocumentSplitCounts`] from a verifier-side + /// `Vec`. Identity for now; kept as a + /// constructor in case the internal shape evolves. + pub fn from_verified(entries: Vec) -> Self { + DocumentSplitCounts(entries) + } +} /// Reject the generic [`FromProof`] entry point for [`DocumentSplitCounts`]. /// -/// Splitting requires the split-property name, which isn't carried by -/// `DriveDocumentQuery`. Earlier versions of this impl silently returned an -/// empty map under proof, which made `prove=true` callers think there were -/// zero documents per group. To stop that footgun, the generic -/// [`FromProof`] now returns an explicit error; SDK-level callers must use -/// [`DocumentSplitCounts::maybe_from_proof_with_split_property`] (or, in -/// `rs-sdk`, the [`Fetch`](dash_sdk::platform::Fetch) impl on -/// `DocumentSplitCountQuery`) which threads the split property through. +/// `DocumentSplitCounts` is reached from rs-sdk via +/// `FromProof` (which routes to the count-tree +/// element proof / aggregate-count proof / distinct-count proof based +/// on the request shape — see +/// `rs-sdk/src/platform/documents/document_count_query.rs`). The +/// generic `FromProof` path doesn't carry enough information to +/// pick a proof shape, so it errors out explicitly. Calling this +/// directly is a programmer mistake. impl<'dq, Q> FromProof for DocumentSplitCounts where Q: TryInto> + Clone + 'dq, Q::Error: std::fmt::Display, { type Request = Q; - type Response = GetDocumentsSplitCountResponse; + type Response = GetDocumentsCountResponse; fn maybe_from_proof_with_metadata<'a, I: Into, O: Into>( _request: I, @@ -49,109 +73,124 @@ where Self: 'a, { Err(Error::RequestError { - error: "DocumentSplitCounts requires a split-property; call \ - DocumentSplitCounts::maybe_from_proof_with_split_property \ - (or use the rs-sdk Fetch impl on DocumentSplitCountQuery)" + error: "DocumentSplitCounts can't be verified via the generic FromProof path; \ + use the rs-sdk Fetch impl on DocumentCountQuery, which routes to the \ + correct proof shape (CountTree element / aggregate / distinct) based \ + on the request" .to_string(), }) } } -impl DocumentSplitCounts { - /// Verify a `GetDocumentsSplitCount` proof and aggregate the verified - /// documents into per-key counts using `split_property` as the grouping - /// key. - /// - /// `Q` is anything that can be turned into a [`DriveDocumentQuery`] — - /// typically a `DocumentSplitCountQuery` from `rs-sdk` or a - /// `DriveDocumentQuery` directly. - /// - /// Returns `(Some(splits), metadata, proof)` even when no documents - /// matched (in which case `splits.0` is empty). - pub fn maybe_from_proof_with_split_property<'dq, 'a, Q, I, O>( - request: I, - split_property: &str, - response: O, - _network: Network, - platform_version: &PlatformVersion, - provider: &'a dyn ContextProvider, - ) -> Result<(Option, ResponseMetadata, Proof), Error> - where - Q: TryInto> + Clone + 'dq, - Q::Error: std::fmt::Display, - I: Into, - O: Into, - Self: 'a, - { - let request: Q = request.into(); - let response: GetDocumentsSplitCountResponse = response.into(); - - let drive_query: DriveDocumentQuery<'dq> = - request - .clone() - .try_into() - .map_err(|e: Q::Error| Error::RequestError { - error: e.to_string(), - })?; - - let proof = response.proof().or(Err(Error::NoProofInResult))?; - let mtd = response.metadata().or(Err(Error::EmptyResponseMetadata))?; - - let (root_hash, documents) = drive_query - .verify_proof(&proof.grovedb_proof, platform_version) - .map_drive_error(proof, mtd)?; - - verify_tenderdash_proof(proof, mtd, &root_hash, provider)?; +#[cfg(test)] +mod tests { + //! Local-only tests for the parts of `DocumentSplitCounts` that + //! don't need a real grovedb proof or a populated Drive: + //! + //! - `into_flat_map` — pure data reduction over the new + //! `Vec` shape (covers the no-merge → + //! merged-histogram backwards-compat path). + //! - `from_verified` — identity constructor wrapping the raw + //! verified-entries vec. + //! - The generic `FromProof` impl that intentionally errors + //! to prevent the silently-empty footgun documented above. + //! + //! The actual proof verification (CountTree-element / + //! aggregate / distinct) is exercised end-to-end by drive's + //! `range_countable_index_e2e_tests` (running the prover and + //! verifier on a real Drive); exercising it here would need a + //! populated Drive + a real proof, which is outside this + //! crate's feature surface. + use super::*; + + /// Helper to make a `SplitCountEntry` with the given fields + /// without each call site needing to type the struct out. + fn entry(in_key: Option<&[u8]>, key: &[u8], count: u64) -> SplitCountEntry { + SplitCountEntry { + in_key: in_key.map(|s| s.to_vec()), + key: key.to_vec(), + count, + } + } - let aggregated = aggregate_documents_by_property( - &documents, - drive_query.document_type, - split_property, - platform_version, - )?; + #[test] + fn from_verified_round_trips_the_input_vec() { + let entries = vec![ + entry(None, b"red", 5), + entry(None, b"green", 3), + entry(None, b"blue", 8), + ]; + let counts = DocumentSplitCounts::from_verified(entries.clone()); + assert_eq!(counts.0, entries); + } - Ok(( - Some(DocumentSplitCounts(aggregated)), - mtd.clone(), - proof.clone(), - )) + #[test] + fn from_verified_empty_round_trip() { + let counts = DocumentSplitCounts::from_verified(Vec::new()); + assert!(counts.0.is_empty()); } -} -/// Group documents by the byte-encoded value of `split_property` and return -/// the per-key counts. Documents that don't carry the property are skipped -/// (mirroring the server-side CountTree path, which only counts documents -/// whose primary-key tree path includes the property). -fn aggregate_documents_by_property( - documents: &[Document], - document_type: dpp::data_contract::document_type::DocumentTypeRef<'_>, - split_property: &str, - platform_version: &PlatformVersion, -) -> Result, u64>, Error> { - let mut counts: BTreeMap, u64> = BTreeMap::new(); + #[test] + fn into_flat_map_passes_through_flat_entries() { + // No In dimension — every entry has `in_key = None`. The flat + // map should be one-to-one with the input. + let counts = DocumentSplitCounts::from_verified(vec![ + entry(None, b"red", 5), + entry(None, b"green", 3), + entry(None, b"blue", 8), + ]); + let flat = counts.into_flat_map(); + assert_eq!(flat.len(), 3); + assert_eq!(flat.get(b"red".as_slice()), Some(&5)); + assert_eq!(flat.get(b"green".as_slice()), Some(&3)); + assert_eq!(flat.get(b"blue".as_slice()), Some(&8)); + } - for document in documents { - let value = match document.properties().get(split_property) { - Some(v) => v, - None => continue, - }; + #[test] + fn into_flat_map_sums_across_in_key_forks_for_compound_entries() { + // Compound query result: `brand in [acme, contoso]` × `color in [red, green]`. + // `into_flat_map` should sum `red` across both brand forks + // (3 + 2 = 5) — that's the whole point of providing the + // historical merged-histogram view. + let counts = DocumentSplitCounts::from_verified(vec![ + entry(Some(b"acme"), b"red", 3), + entry(Some(b"acme"), b"green", 2), + entry(Some(b"contoso"), b"red", 2), + entry(Some(b"contoso"), b"green", 4), + ]); + let flat = counts.into_flat_map(); + assert_eq!(flat.len(), 2, "merges by `key` across in_key forks"); + assert_eq!(flat.get(b"red".as_slice()), Some(&5)); + assert_eq!(flat.get(b"green".as_slice()), Some(&6)); + } - let key = document_type - .serialize_value_for_key(split_property, value, platform_version) - .map_err(|e| Error::ResponseDecodeError { - error: format!( - "Failed to serialize split property `{}` for grouping: {}", - split_property, e - ), - })?; + #[test] + fn into_flat_map_handles_mixed_in_key_and_none_entries() { + // Edge case: a result set that mixes flat entries (in_key=None) + // and compound entries (in_key=Some). Both should fold into + // the same `key` buckets when sharing a terminator value. + let counts = DocumentSplitCounts::from_verified(vec![ + entry(None, b"red", 1), + entry(Some(b"acme"), b"red", 2), + entry(Some(b"contoso"), b"red", 3), + entry(Some(b"acme"), b"green", 4), + ]); + let flat = counts.into_flat_map(); + assert_eq!(flat.get(b"red".as_slice()), Some(&6)); + assert_eq!(flat.get(b"green".as_slice()), Some(&4)); + } - *counts.entry(key).or_insert(0) += 1; + #[test] + fn into_flat_map_empty_input_produces_empty_map() { + let counts = DocumentSplitCounts::from_verified(Vec::new()); + assert!(counts.into_flat_map().is_empty()); } - Ok(counts) + // The generic `FromProof` rejection (returning the explicit + // "needs a split property" error rather than silently returning + // `Some(empty)`) is covered by the SDK integration tests, which + // can construct a valid `DriveDocumentQuery` via dpp's + // `fixtures-and-mocks` feature. drive-proof-verifier itself + // doesn't depend on `dpp/fixtures-and-mocks` so we can't build + // one here. } - -// Aggregation unit tests live in higher-level crates with full test fixtures: -// - SDK: packages/rs-sdk/tests/fetch/document_split_count.rs -// - drive-abci: src/query/document_split_count_query/v0/mod.rs tests -// (drive-proof-verifier's feature surface doesn't expose dpp test helpers) diff --git a/packages/rs-drive/Cargo.toml b/packages/rs-drive/Cargo.toml index 111cd9d257b..62b6fc0c59f 100644 --- a/packages/rs-drive/Cargo.toml +++ b/packages/rs-drive/Cargo.toml @@ -52,12 +52,12 @@ enum-map = { version = "2.0.3", optional = true } intmap = { version = "3.0.1", features = ["serde"], optional = true } chrono = { version = "0.4.35", optional = true } itertools = { version = "0.13", optional = true } -grovedb = { git = "https://github.com/dashpay/grovedb", rev = "dbd83dce59fbcf2866e9dd06be4ce6c320e37908", optional = true, default-features = false } -grovedb-costs = { git = "https://github.com/dashpay/grovedb", rev = "dbd83dce59fbcf2866e9dd06be4ce6c320e37908", optional = true } -grovedb-path = { git = "https://github.com/dashpay/grovedb", rev = "dbd83dce59fbcf2866e9dd06be4ce6c320e37908" } -grovedb-storage = { git = "https://github.com/dashpay/grovedb", rev = "dbd83dce59fbcf2866e9dd06be4ce6c320e37908", optional = true } -grovedb-version = { git = "https://github.com/dashpay/grovedb", rev = "dbd83dce59fbcf2866e9dd06be4ce6c320e37908" } -grovedb-epoch-based-storage-flags = { git = "https://github.com/dashpay/grovedb", rev = "dbd83dce59fbcf2866e9dd06be4ce6c320e37908" } +grovedb = { git = "https://github.com/dashpay/grovedb", rev = "a917d92d2477672eed73c4c08e53e93449a6a094", optional = true, default-features = false } +grovedb-costs = { git = "https://github.com/dashpay/grovedb", rev = "a917d92d2477672eed73c4c08e53e93449a6a094", optional = true } +grovedb-path = { git = "https://github.com/dashpay/grovedb", rev = "a917d92d2477672eed73c4c08e53e93449a6a094" } +grovedb-storage = { git = "https://github.com/dashpay/grovedb", rev = "a917d92d2477672eed73c4c08e53e93449a6a094", optional = true } +grovedb-version = { git = "https://github.com/dashpay/grovedb", rev = "a917d92d2477672eed73c4c08e53e93449a6a094" } +grovedb-epoch-based-storage-flags = { git = "https://github.com/dashpay/grovedb", rev = "a917d92d2477672eed73c4c08e53e93449a6a094" } [dev-dependencies] criterion = "0.5" diff --git a/packages/rs-drive/src/drive/contract/estimation_costs/add_estimation_costs_for_contract_insertion/mod.rs b/packages/rs-drive/src/drive/contract/estimation_costs/add_estimation_costs_for_contract_insertion/mod.rs index db5f85f037c..4becca132d6 100644 --- a/packages/rs-drive/src/drive/contract/estimation_costs/add_estimation_costs_for_contract_insertion/mod.rs +++ b/packages/rs-drive/src/drive/contract/estimation_costs/add_estimation_costs_for_contract_insertion/mod.rs @@ -1,4 +1,5 @@ mod v0; +mod v1; use crate::drive::Drive; use crate::error::drive::DriveError; @@ -42,9 +43,17 @@ impl Drive { )?; Ok(()) } + 1 => { + Self::add_estimation_costs_for_contract_insertion_v1( + contract, + estimated_costs_only_with_layer_info, + platform_version, + )?; + Ok(()) + } version => Err(Error::Drive(DriveError::UnknownVersionMismatch { method: "add_estimation_costs_for_contract_insertion".to_string(), - known_versions: vec![0], + known_versions: vec![0, 1], received: version, })), } diff --git a/packages/rs-drive/src/drive/contract/estimation_costs/add_estimation_costs_for_contract_insertion/v1/mod.rs b/packages/rs-drive/src/drive/contract/estimation_costs/add_estimation_costs_for_contract_insertion/v1/mod.rs new file mode 100644 index 00000000000..e04275e6baf --- /dev/null +++ b/packages/rs-drive/src/drive/contract/estimation_costs/add_estimation_costs_for_contract_insertion/v1/mod.rs @@ -0,0 +1,472 @@ +use crate::drive::constants::{AVERAGE_NUMBER_OF_UPDATES, ESTIMATED_AVERAGE_INDEX_NAME_SIZE}; +use crate::drive::contract::paths::contract_keeping_history_root_path; +use crate::drive::document::paths::contract_document_type_path; +use crate::drive::document::primary_key_tree_type::DocumentTypePrimaryKeyTreeType; +use crate::drive::Drive; +use crate::util::storage_flags::StorageFlags; + +use crate::error::Error; +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::document_type::methods::DocumentTypeBasicMethods; +use dpp::data_contract::DataContract; + +use dpp::serialization::PlatformSerializableWithPlatformVersion; + +use crate::drive::votes::paths::vote_contested_resource_active_polls_contract_document_tree_path; +use crate::util::type_constants::{DEFAULT_FLOAT_SIZE, DEFAULT_FLOAT_SIZE_U8}; +use dpp::version::PlatformVersion; +use grovedb::batch::KeyInfoPath; +use grovedb::EstimatedLayerCount::{ApproximateElements, EstimatedLevel}; +use grovedb::EstimatedLayerSizes::{AllSubtrees, Mix}; +use grovedb::EstimatedSumTrees::{NoSumTrees, SomeSumTrees}; +use grovedb::{EstimatedLayerInformation, TreeType}; +use std::collections::{HashMap, HashSet}; + +impl Drive { + /// v1 of contract-insertion cost estimation. Differs from v0 by computing + /// the per-doctype `EstimatedSumTrees` mix instead of unconditionally + /// asserting `NoSumTrees`. + /// + /// The doctype-named subtree (the layer this loop estimates) is always + /// itself a `NormalTree` — `tree_type: TreeType::NormalTree` is unchanged + /// from v0. What v0 got wrong is the description of its CHILDREN: + /// + /// - The primary-key tree at `[0]` is a `CountTree` if + /// `documents_countable` is set, a `ProvableCountTree` if + /// `range_countable` is set (see + /// [`DocumentTypePrimaryKeyTreeType::primary_key_tree_type`]), or a + /// `NormalTree` otherwise. + /// - A top-level index whose terminator level has `range_countable = true` + /// is itself created as a `ProvableCountTree` (see the matching branch + /// in `insert_contract_v0`). + /// + /// Both `CountTree` and `ProvableCountTree` map to a node with a count + /// aggregate — `NodeType::CountNode` and `NodeType::ProvableCountNode` + /// both report `cost() == 8` (versus `NormalNode::cost() == 0`). So + /// counting them under grovedb's single `count_trees_weight` slot is + /// byte-accurate for the average-case fee estimate, even though + /// `EstimatedSumTrees` doesn't expose a separate `ProvableCountTrees` + /// bucket. + /// + /// For non-countable contracts (no `documentsCountable` / no + /// `rangeCountable` anywhere) all children are normal subtrees and this + /// method emits exactly the same `NoSumTrees` shape v0 emits — so for the + /// pre-v12 contract surface this is a byte-identical no-op. The fee math + /// only diverges from v0 once a doctype opts into `documentsCountable` or + /// `rangeCountable`, which is itself a v12+ feature. + #[inline(always)] + pub(super) fn add_estimation_costs_for_contract_insertion_v1( + contract: &DataContract, + estimated_costs_only_with_layer_info: &mut HashMap, + platform_version: &PlatformVersion, + ) -> Result<(), Error> { + Self::add_estimation_costs_for_levels_up_to_contract_document_type_excluded( + contract, + estimated_costs_only_with_layer_info, + &platform_version.drive, + )?; + + // we only store the owner_id storage + let storage_flags = if contract.config().can_be_deleted() || !contract.config().readonly() { + Some(StorageFlags::approximate_size(true, None)) + } else { + None + }; + + let document_types_with_contested_unique_indexes = + contract.document_types_with_contested_indexes(); + + if !document_types_with_contested_unique_indexes.is_empty() { + Self::add_estimation_costs_for_contested_document_tree_levels_up_to_contract_document_type_excluded( + contract, + estimated_costs_only_with_layer_info, + &platform_version.drive, + )?; + + for document_type_name in document_types_with_contested_unique_indexes.keys() { + estimated_costs_only_with_layer_info.insert( + KeyInfoPath::from_known_path( + vote_contested_resource_active_polls_contract_document_tree_path( + contract.id_ref().as_bytes(), + document_type_name.as_str(), + ), + ), + EstimatedLayerInformation { + tree_type: TreeType::NormalTree, + estimated_layer_count: ApproximateElements(2), + estimated_layer_sizes: AllSubtrees( + ESTIMATED_AVERAGE_INDEX_NAME_SIZE, + NoSumTrees, + None, + ), + }, + ); + } + } + + for (document_type_name, document_type) in contract.document_types() { + // Compute the (count, non-count) child mix at this doctype's + // layer. Mirror what `insert_contract_v0` actually creates: + // + // - key `[0]` (the primary-key tree) → tree type from + // `primary_key_tree_type()` (count-bearing iff + // `documents_countable` or `range_countable` is set). + // - each top-level index key → `ProvableCountTree` iff its + // terminator level reports `range_countable = true`, + // `NormalTree` otherwise. + // + // The boolean below routes both `CountTree` and + // `ProvableCountTree` into the same `count_trees_weight` slot + // (see the doc comment on this method for why that's + // byte-accurate). + let document_type_ref = document_type.as_ref(); + let pk_tree_type = document_type_ref.primary_key_tree_type(platform_version)?; + let pk_is_count_bearing = matches!( + pk_tree_type, + TreeType::CountTree | TreeType::ProvableCountTree + ); + + let mut count_children: u8 = if pk_is_count_bearing { 1 } else { 0 }; + let mut non_count_children: u8 = if pk_is_count_bearing { 0 } else { 1 }; + + let index_structure = document_type_ref.index_structure(); + let mut seen_indexes: HashSet<&[u8]> = HashSet::new(); + for index in document_type_ref.top_level_indices() { + let index_bytes = index.name.as_bytes(); + if !seen_indexes.insert(index_bytes) { + continue; + } + let property_name_is_range_countable_terminator = index_structure + .sub_levels() + .get(index.name.as_str()) + .and_then(|level| level.has_index_with_type()) + .map(|info| info.range_countable) + .unwrap_or(false); + if property_name_is_range_countable_terminator { + count_children = count_children.saturating_add(1); + } else { + non_count_children = non_count_children.saturating_add(1); + } + } + + let estimated_sum_trees = if count_children == 0 { + NoSumTrees + } else { + SomeSumTrees { + sum_trees_weight: 0, + big_sum_trees_weight: 0, + count_trees_weight: count_children, + count_sum_trees_weight: 0, + non_sum_trees_weight: non_count_children, + } + }; + + estimated_costs_only_with_layer_info.insert( + KeyInfoPath::from_known_path(contract_document_type_path( + contract.id_ref().as_bytes(), + document_type_name.as_str(), + )), + EstimatedLayerInformation { + tree_type: TreeType::NormalTree, + estimated_layer_count: EstimatedLevel(0, true), + estimated_layer_sizes: AllSubtrees( + ESTIMATED_AVERAGE_INDEX_NAME_SIZE, + estimated_sum_trees, + storage_flags, + ), + }, + ); + } + + if contract.config().keeps_history() { + // We are dealing with a sibling reference. + // The sibling reference serialized size is going to be the encoded time size + // (DEFAULT_FLOAT_SIZE) plus 1 byte for reference type and 1 byte for the space of + // the encoded time + let reference_size = DEFAULT_FLOAT_SIZE + 2; + + estimated_costs_only_with_layer_info.insert( + KeyInfoPath::from_known_path(contract_keeping_history_root_path( + contract.id_ref().as_bytes(), + )), + EstimatedLayerInformation { + tree_type: TreeType::NormalTree, + estimated_layer_count: ApproximateElements(AVERAGE_NUMBER_OF_UPDATES as u32), + estimated_layer_sizes: Mix { + subtrees_size: None, + items_size: Some(( + DEFAULT_FLOAT_SIZE_U8, + contract + .serialize_to_bytes_with_platform_version(platform_version)? + .len() as u32, //todo: fix this + storage_flags, + AVERAGE_NUMBER_OF_UPDATES, + )), + references_size: Some((1, reference_size, storage_flags, 1)), + }, + }, + ); + } + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + //! These tests pin the per-doctype `EstimatedSumTrees` shape v1 emits + //! against the actual tree types `insert_contract_v0` writes to grove + //! (see the `countable_e2e_tests` module in + //! `packages/rs-drive/src/drive/contract/insert/insert_contract/v0/mod.rs`, + //! which reads the primary-key tree back from grove and asserts the + //! concrete variant). The estimation has to mirror that shape; if these + //! tests start failing, either the on-disk creation moved or the + //! estimation did — they need to move together. + use super::*; + use crate::drive::document::paths::contract_document_type_path; + use dpp::data_contract::DataContractFactory; + use dpp::platform_value::{platform_value, Value}; + use dpp::tests::utils::generate_random_identifier_struct; + use grovedb::EstimatedLayerSizes; + + const PROTOCOL_VERSION_V12: u32 = 12; + + fn build_contract( + documents_countable: bool, + range_countable_index_on_color: bool, + ) -> DataContract { + let factory = + DataContractFactory::new(PROTOCOL_VERSION_V12).expect("expected to create factory"); + let mut document_schema = platform_value!({ + "type": "object", + "properties": { + "color": {"type": "string", "position": 0, "maxLength": 32}, + }, + "additionalProperties": false, + }); + if documents_countable { + document_schema.as_map_mut().unwrap().push(( + Value::Text("documentsCountable".to_string()), + Value::Bool(true), + )); + } + if range_countable_index_on_color { + // `rangeCountable: true` on the index puts a `ProvableCountTree` + // both at the primary-key key `[0]` AND at the `byColor` index + // name key (per `insert_contract_v0`'s + // `property_name_is_range_countable_terminator` branch). + document_schema.as_map_mut().unwrap().push(( + Value::Text("indices".to_string()), + platform_value!([{ + "name": "byColor", + "properties": [{"color": "asc"}], + "countable": "countable", + "rangeCountable": true, + }]), + )); + } + let schemas = platform_value!({ "widget": document_schema }); + factory + .create_with_value_config(generate_random_identifier_struct(), 0, schemas, None, None) + .expect("create contract") + .data_contract_owned() + } + + /// For a plain (non-countable) contract v1 must emit `NoSumTrees` — same + /// shape as v0. Otherwise v1 would change fees for pre-v12 contract + /// shapes that don't even have count-tree children. + #[test] + fn non_countable_contract_emits_no_sum_trees_same_as_v0() { + let pv = PlatformVersion::latest(); + let contract = build_contract(false, false); + let mut layer_info: HashMap = HashMap::new(); + crate::drive::Drive::add_estimation_costs_for_contract_insertion_v1( + &contract, + &mut layer_info, + pv, + ) + .expect("v1 estimation"); + let key = KeyInfoPath::from_known_path(contract_document_type_path( + contract.id_ref().as_bytes(), + "widget", + )); + let layer = layer_info.get(&key).expect("layer info for widget doctype"); + assert_eq!( + layer.tree_type, + TreeType::NormalTree, + "doctype parent layer is always NormalTree" + ); + match layer.estimated_layer_sizes { + EstimatedLayerSizes::AllSubtrees(_, NoSumTrees, _) => {} + other => panic!( + "non-countable contract expected NoSumTrees, got {:?}", + other + ), + } + } + + /// `documentsCountable: true` only — primary-key tree is `CountTree`, + /// no `rangeCountable` index, so we expect a 1:1 weight split between + /// the count-bearing primary key tree and... no other children (no + /// indexes declared). + #[test] + fn documents_countable_contract_emits_some_sum_trees_with_count_weight() { + let pv = PlatformVersion::latest(); + let contract = build_contract(true, false); + let mut layer_info: HashMap = HashMap::new(); + crate::drive::Drive::add_estimation_costs_for_contract_insertion_v1( + &contract, + &mut layer_info, + pv, + ) + .expect("v1 estimation"); + let key = KeyInfoPath::from_known_path(contract_document_type_path( + contract.id_ref().as_bytes(), + "widget", + )); + let layer = layer_info.get(&key).expect("layer info for widget doctype"); + match layer.estimated_layer_sizes { + EstimatedLayerSizes::AllSubtrees( + _, + SomeSumTrees { + count_trees_weight, + non_sum_trees_weight, + sum_trees_weight, + big_sum_trees_weight, + count_sum_trees_weight, + }, + _, + ) => { + assert_eq!( + count_trees_weight, 1, + "primary-key CountTree contributes 1 count-tree child" + ); + assert_eq!( + non_sum_trees_weight, 0, + "no indexes declared → no non-count children" + ); + assert_eq!(sum_trees_weight, 0); + assert_eq!(big_sum_trees_weight, 0); + assert_eq!(count_sum_trees_weight, 0); + } + other => panic!( + "documentsCountable contract expected SomeSumTrees, got {:?}", + other + ), + } + } + + /// `rangeCountable` on the `byColor` index → primary-key tree is + /// `ProvableCountTree` AND the `byColor` index tree is also a + /// `ProvableCountTree`, so both children should map onto + /// `count_trees_weight` (per the doc comment on the v1 method — + /// `CountNode` and `ProvableCountNode` have the same per-feature cost). + #[test] + fn range_countable_index_contract_counts_both_pk_and_index_as_count_children() { + let pv = PlatformVersion::latest(); + let contract = build_contract(true, true); + let mut layer_info: HashMap = HashMap::new(); + crate::drive::Drive::add_estimation_costs_for_contract_insertion_v1( + &contract, + &mut layer_info, + pv, + ) + .expect("v1 estimation"); + let key = KeyInfoPath::from_known_path(contract_document_type_path( + contract.id_ref().as_bytes(), + "widget", + )); + let layer = layer_info.get(&key).expect("layer info for widget doctype"); + match layer.estimated_layer_sizes { + EstimatedLayerSizes::AllSubtrees( + _, + SomeSumTrees { + count_trees_weight, + non_sum_trees_weight, + .. + }, + _, + ) => { + assert_eq!( + count_trees_weight, 2, + "primary-key ProvableCountTree + byColor ProvableCountTree → 2 count-tree \ + children" + ); + assert_eq!(non_sum_trees_weight, 0, "no non-count children"); + } + other => panic!( + "rangeCountable contract expected SomeSumTrees, got {:?}", + other + ), + } + } + + /// Diff vs v0: for the same `documentsCountable` contract, v0 emits + /// `NoSumTrees` (the bug) and v1 emits `SomeSumTrees { count_trees_weight: 1, ... }`. + /// This is the smallest-possible test that pins the behavioral divergence. + #[test] + fn v1_differs_from_v0_only_when_count_children_present() { + let pv = PlatformVersion::latest(); + + // Non-countable: v0 and v1 must agree (byte-identical NoSumTrees). + let plain = build_contract(false, false); + let mut v0_layer: HashMap = HashMap::new(); + let mut v1_layer: HashMap = HashMap::new(); + crate::drive::Drive::add_estimation_costs_for_contract_insertion_v0( + &plain, + &mut v0_layer, + pv, + ) + .expect("v0"); + crate::drive::Drive::add_estimation_costs_for_contract_insertion_v1( + &plain, + &mut v1_layer, + pv, + ) + .expect("v1"); + let key = KeyInfoPath::from_known_path(contract_document_type_path( + plain.id_ref().as_bytes(), + "widget", + )); + assert_eq!( + v0_layer.get(&key).map(|l| l.estimated_layer_sizes), + v1_layer.get(&key).map(|l| l.estimated_layer_sizes), + "v0 and v1 must produce the same shape for non-countable contracts" + ); + + // Countable: v0 still says NoSumTrees (the bug); v1 says + // SomeSumTrees. Diverging on this case is the whole point of v1. + let countable = build_contract(true, false); + let mut v0_layer: HashMap = HashMap::new(); + let mut v1_layer: HashMap = HashMap::new(); + crate::drive::Drive::add_estimation_costs_for_contract_insertion_v0( + &countable, + &mut v0_layer, + pv, + ) + .expect("v0"); + crate::drive::Drive::add_estimation_costs_for_contract_insertion_v1( + &countable, + &mut v1_layer, + pv, + ) + .expect("v1"); + let key = KeyInfoPath::from_known_path(contract_document_type_path( + countable.id_ref().as_bytes(), + "widget", + )); + let v0_sizes = v0_layer.get(&key).unwrap().estimated_layer_sizes; + let v1_sizes = v1_layer.get(&key).unwrap().estimated_layer_sizes; + assert!( + matches!(v0_sizes, EstimatedLayerSizes::AllSubtrees(_, NoSumTrees, _)), + "v0 emits NoSumTrees (under-bills count-tree children)" + ); + assert!( + !matches!(v1_sizes, EstimatedLayerSizes::AllSubtrees(_, NoSumTrees, _)), + "v1 must NOT emit NoSumTrees for countable contracts — got {:?}", + v1_sizes + ); + } +} diff --git a/packages/rs-drive/src/drive/contract/insert/insert_contract/v0/mod.rs b/packages/rs-drive/src/drive/contract/insert/insert_contract/v0/mod.rs index 05c57682037..f9ce615801d 100644 --- a/packages/rs-drive/src/drive/contract/insert/insert_contract/v0/mod.rs +++ b/packages/rs-drive/src/drive/contract/insert/insert_contract/v0/mod.rs @@ -10,6 +10,7 @@ use crate::fees::op::LowLevelDriveOperation; 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; @@ -317,18 +318,42 @@ impl Drive { } let mut index_cache: HashSet<&[u8]> = HashSet::new(); + let document_type_ref = document_type.as_ref(); + let index_structure = document_type_ref.index_structure(); // for each type we should insert the indices that are top level for index in document_type.as_ref().top_level_indices() { // toDo: change this to be a reference by index let index_bytes = index.name.as_bytes(); if !index_cache.contains(index_bytes) { - self.batch_insert_empty_tree( - type_path, - KeyRef(index_bytes), - storage_flags.as_ref(), - &mut batch_operations, - &platform_version.drive, - )?; + // If a range_countable index terminates at this top + // level (i.e. a single-property index over `index.name` + // with range_countable: true), the property-name tree + // must be a `ProvableCountTree` so range-count queries + // over the property's distinct values can use grovedb's + // `AggregateCountOnRange`. Otherwise it's a NormalTree. + let property_name_is_range_countable_terminator = index_structure + .sub_levels() + .get(index.name.as_str()) + .and_then(|level| level.has_index_with_type()) + .map(|info| info.range_countable) + .unwrap_or(false); + if property_name_is_range_countable_terminator { + self.batch_insert_empty_provable_count_tree( + type_path, + KeyRef(index_bytes), + storage_flags.as_ref(), + &mut batch_operations, + &platform_version.drive, + )?; + } else { + self.batch_insert_empty_tree( + type_path, + KeyRef(index_bytes), + storage_flags.as_ref(), + &mut batch_operations, + &platform_version.drive, + )?; + } index_cache.insert(index_bytes); } } @@ -955,3 +980,3216 @@ mod countable_e2e_tests { ); } } + +#[cfg(test)] +mod range_countable_index_e2e_tests { + //! End-to-end coverage for an *indexed* `rangeCountable` property. + //! + //! Where `countable_e2e_tests` only checks the document-type-level flag + //! (`documentsCountable` / `rangeCountable` on the document type, which + //! drives the primary-key tree variant), this module builds a contract + //! whose `indices` section contains a `rangeCountable: true` index over + //! a property and verifies the *index storage tree shape*: + //! + //! - `[contract_doc, doctype, "color"]` is a `ProvableCountTree` + //! (created at contract setup). + //! - `[..., "color", ]` is a `CountTree` (created on document + //! insert by the index walker), whose count tracks how many docs + //! have that color value. + //! - Sibling continuations under that `CountTree` (compound index + //! suffixes) are wrapped with `Element::NonCounted` so they + //! contribute 0 to the parent count. + + use crate::drive::Drive; + use crate::util::grove_operations::DirectQueryType; + 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::data_contract::document_type::accessors::DocumentTypeV0Getters; + use dpp::data_contract::document_type::random_document::CreateRandomDocument; + use dpp::data_contract::DataContractFactory; + use dpp::document::{Document, DocumentV0Getters, DocumentV0Setters}; + use dpp::platform_value::{platform_value, Value}; + use dpp::prelude::DataContract; + use dpp::tests::utils::generate_random_identifier_struct; + use dpp::version::PlatformVersion; + use grovedb::Element; + + const PROTOCOL_VERSION_V12: u32 = 12; + + /// Build a v12 contract whose `widget` document type has a + /// `rangeCountable: true` single-property index over `color`. The + /// optional `compound_index` adds a non-range-countable compound + /// `[color, size]` index so we can verify NonCounted-wrapping of the + /// sibling continuation. + fn build_widget_with_color_index(compound_index: bool) -> DataContract { + let factory = + DataContractFactory::new(PROTOCOL_VERSION_V12).expect("expected to create factory"); + + let mut indices = vec![platform_value!({ + "name": "byColor", + "properties": [{"color": "asc"}], + "countable": "countable", + "rangeCountable": true, + })]; + if compound_index { + indices.push(platform_value!({ + "name": "byColorSize", + "properties": [{"color": "asc"}, {"size": "asc"}], + })); + } + + let document_schema = platform_value!({ + "type": "object", + "properties": { + "color": { + "type": "string", + "position": 0, + "maxLength": 32, + }, + "size": { + "type": "string", + "position": 1, + "maxLength": 32, + }, + }, + "indices": Value::Array(indices), + "additionalProperties": false, + }); + + let schemas = platform_value!({ "widget": document_schema }); + let owner_id = generate_random_identifier_struct(); + + factory + .create_with_value_config(owner_id, 0, schemas, None, None) + .expect("expected to create data contract") + .data_contract_owned() + } + + fn property_name_tree_path( + contract: &DataContract, + document_type_name: &str, + property_name: &str, + ) -> Vec> { + vec![ + vec![crate::drive::RootTree::DataContractDocuments as u8], + contract.id().as_bytes().to_vec(), + vec![1], + document_type_name.as_bytes().to_vec(), + property_name.as_bytes().to_vec(), + ] + } + + fn read_grove_element(drive: &Drive, path: &[Vec], key: &[u8]) -> Option { + let pv = PlatformVersion::latest(); + let path_refs: Vec<&[u8]> = path.iter().map(|v| v.as_slice()).collect(); + drive + .grove_get_raw( + path_refs.as_slice().into(), + key, + DirectQueryType::StatefulDirectQuery, + None, + &mut vec![], + &pv.drive, + ) + .expect("grove_get_raw should succeed") + } + + fn build_widget_doc(contract: &DataContract, color: &str, size: &str, seed: u64) -> Document { + let pv = PlatformVersion::latest(); + let document_type = contract + .document_type_for_name("widget") + .expect("widget exists"); + let mut doc = document_type + .random_document(Some(seed), pv) + .expect("random document"); + let mut props = std::collections::BTreeMap::new(); + props.insert("color".to_string(), Value::Text(color.to_string())); + props.insert("size".to_string(), Value::Text(size.to_string())); + doc.set_properties(props); + doc + } + + /// The top-level property-name tree at `[contract_doc, doctype, "color"]` + /// must be a `ProvableCountTree` for a contract with a `rangeCountable` + /// single-property index over `color`. This is the layer that + /// `AggregateCountOnRange` walks for O(log n) range counts. + #[test] + fn property_name_tree_for_range_countable_index_is_provable_count_tree() { + let drive = setup_drive_with_initial_state_structure(None); + let pv = PlatformVersion::latest(); + let contract = build_widget_with_color_index(false); + + drive + .apply_contract( + &contract, + BlockInfo::default(), + true, + StorageFlags::optional_default_as_cow(), + None, + pv, + ) + .expect("expected to apply contract"); + + let path = property_name_tree_path(&contract, "widget", "color"); + let parent_path: Vec> = path[..path.len() - 1].to_vec(); + let key = path.last().unwrap().clone(); + let elem = read_grove_element(&drive, &parent_path, &key) + .expect("color property-name tree must exist"); + match elem { + Element::ProvableCountTree(_, count, _) => { + assert_eq!( + count, 0, + "freshly created property-name ProvableCountTree should have aggregate 0" + ); + } + other => panic!( + "rangeCountable index property-name tree should be ProvableCountTree, got {:?}", + other + ), + } + } + + /// Inserting a document whose indexed property has value `c1` creates + /// the value tree at `[contract_doc, doctype, "color", "c1"]`. With + /// `rangeCountable: true` the walker must lay this down as a + /// `CountTree` so the parent property-name `ProvableCountTree`'s + /// aggregate sums per-value counts cleanly. + #[test] + fn value_tree_for_range_countable_index_is_count_tree_after_insert() { + let drive = setup_drive_with_initial_state_structure(None); + let pv = PlatformVersion::latest(); + let contract = build_widget_with_color_index(false); + + drive + .apply_contract( + &contract, + BlockInfo::default(), + true, + StorageFlags::optional_default_as_cow(), + None, + pv, + ) + .expect("expected to apply contract"); + + let document_type = contract + .document_type_for_name("widget") + .expect("widget exists"); + let doc = build_widget_doc(&contract, "red", "small", 1); + + drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentRefInfo((&doc, None)), + owner_id: None, + }, + contract: &contract, + document_type, + }, + false, + BlockInfo::default(), + true, + None, + pv, + None, + ) + .expect("expected to insert document"); + + // Property-name aggregate should now reflect the inserted doc. + let property_path = property_name_tree_path(&contract, "widget", "color"); + let prop_parent: Vec> = property_path[..property_path.len() - 1].to_vec(); + let prop_key = property_path.last().unwrap().clone(); + let prop_elem = read_grove_element(&drive, &prop_parent, &prop_key) + .expect("color property-name tree must exist"); + match prop_elem { + Element::ProvableCountTree(_, count, _) => { + assert_eq!( + count, 1, + "ProvableCountTree aggregate should be 1 after inserting one doc" + ); + } + other => panic!("expected ProvableCountTree, got {:?}", other), + } + + // Value tree at should be a CountTree counting the docs with + // color="red". + let value_elem = read_grove_element(&drive, &property_path, b"red") + .expect("value tree for color=red must exist"); + match value_elem { + Element::CountTree(_, count, _) => { + assert_eq!(count, 1, "value-tree CountTree should count 1 doc"); + } + other => panic!( + "rangeCountable value tree should be a CountTree, got {:?}", + other + ), + } + } + + /// Walking the same property's IndexLevel for a *compound* sibling + /// index `[color, size]` requires the walker to insert a continuation + /// property-name tree under the `CountTree` value tree. That + /// continuation must be wrapped with `Element::NonCounted` so it + /// contributes 0 to the value tree's count — otherwise the count + /// would be `1 (reference) + 1 (continuation NormalTree) = 2` per + /// inserted doc instead of the correct `1`. + #[test] + fn count_tree_value_count_excludes_compound_continuation_via_non_counted() { + let drive = setup_drive_with_initial_state_structure(None); + let pv = PlatformVersion::latest(); + let contract = build_widget_with_color_index(true); + + drive + .apply_contract( + &contract, + BlockInfo::default(), + true, + StorageFlags::optional_default_as_cow(), + None, + pv, + ) + .expect("expected to apply contract"); + + let document_type = contract + .document_type_for_name("widget") + .expect("widget exists"); + let doc = build_widget_doc(&contract, "red", "small", 1); + + drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentRefInfo((&doc, None)), + owner_id: None, + }, + contract: &contract, + document_type, + }, + false, + BlockInfo::default(), + true, + None, + pv, + None, + ) + .expect("expected to insert document"); + + // CountTree count must be exactly 1 (the doc reference), even + // though there's a compound continuation tree inserted as a + // sibling. If NonCounted-wrapping is broken, count will be 2 (or + // more, depending on how the [0] tree contributes). + let property_path = property_name_tree_path(&contract, "widget", "color"); + let value_elem = read_grove_element(&drive, &property_path, b"red") + .expect("value tree for color=red must exist"); + match value_elem { + Element::CountTree(_, count, _) => { + assert_eq!( + count, 1, + "CountTree count should equal exactly the number of docs with color=red, \ + not including the compound-index continuation tree (NonCounted wrapping \ + check)" + ); + } + other => panic!("expected CountTree, got {:?}", other), + } + + // The compound continuation property-name tree at [..., "color", + // "red", "size"] should exist and be wrapped with NonCounted. + let mut size_path = property_path.clone(); + size_path.push(b"red".to_vec()); + let size_elem = read_grove_element(&drive, &size_path, b"size") + .expect("compound continuation tree at 'size' must exist"); + match size_elem { + Element::NonCounted(inner) => match inner.as_ref() { + Element::Tree(_, _) => {} // expected: NonCounted + other => panic!( + "expected NonCounted, got NonCounted<{:?}>", + other + ), + }, + other => panic!( + "compound continuation under a CountTree must be NonCounted-wrapped, got {:?}", + other + ), + } + } + + /// Deleting a document under a `range_countable` index must decrement + /// the value tree's `CountTree` and the parent property-name tree's + /// `ProvableCountTree` aggregate. If the delete walker doesn't see + /// the right tree variants in cost estimation, removals can leave + /// stale references or over-bill the operation; this test pins the + /// observable outcome (counts after delete). + #[test] + fn delete_decrements_count_tree_and_provable_count_aggregate() { + let drive = setup_drive_with_initial_state_structure(None); + let pv = PlatformVersion::latest(); + let contract = build_widget_with_color_index(false); + + drive + .apply_contract( + &contract, + BlockInfo::default(), + true, + StorageFlags::optional_default_as_cow(), + None, + pv, + ) + .expect("expected to apply contract"); + + let document_type = contract + .document_type_for_name("widget") + .expect("widget exists"); + + // Insert two docs at color="red" so we can delete one and watch + // the count drop from 2 → 1 (instead of 1 → 0, which is also + // correct but doesn't distinguish "decrement" from "tree + // collapsed"). + let doc1 = build_widget_doc(&contract, "red", "small", 1); + let doc2 = build_widget_doc(&contract, "red", "large", 2); + for doc in [&doc1, &doc2] { + drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentRefInfo((doc, None)), + owner_id: None, + }, + contract: &contract, + document_type, + }, + false, + BlockInfo::default(), + true, + None, + pv, + None, + ) + .expect("expected to insert document"); + } + + let property_path = property_name_tree_path(&contract, "widget", "color"); + + // Sanity: 2 docs, both red. + let value_elem = + read_grove_element(&drive, &property_path, b"red").expect("value tree exists"); + match value_elem { + Element::CountTree(_, count, _) => assert_eq!(count, 2), + other => panic!("expected CountTree, got {:?}", other), + } + + drive + .delete_document_for_contract( + doc1.id(), + &contract, + "widget", + BlockInfo::default(), + true, + None, + pv, + None, + ) + .expect("expected to delete document"); + + let prop_parent: Vec> = property_path[..property_path.len() - 1].to_vec(); + let prop_key = property_path.last().unwrap().clone(); + let prop_elem = + read_grove_element(&drive, &prop_parent, &prop_key).expect("property-name tree exists"); + match prop_elem { + Element::ProvableCountTree(_, count, _) => assert_eq!( + count, 1, + "ProvableCountTree aggregate should drop to 1 after one delete" + ), + other => panic!("expected ProvableCountTree, got {:?}", other), + } + let value_elem = + read_grove_element(&drive, &property_path, b"red").expect("value tree exists"); + match value_elem { + Element::CountTree(_, count, _) => assert_eq!( + count, 1, + "CountTree count should drop to 1 after one delete" + ), + other => panic!("expected CountTree, got {:?}", other), + } + } + + /// Inserting multiple docs at the same color value increments the + /// CountTree, and the aggregate at the property-name + /// `ProvableCountTree` reflects the total across all values. + #[test] + fn aggregate_count_grows_across_distinct_values() { + let drive = setup_drive_with_initial_state_structure(None); + let pv = PlatformVersion::latest(); + let contract = build_widget_with_color_index(false); + + drive + .apply_contract( + &contract, + BlockInfo::default(), + true, + StorageFlags::optional_default_as_cow(), + None, + pv, + ) + .expect("expected to apply contract"); + + let document_type = contract + .document_type_for_name("widget") + .expect("widget exists"); + + for (i, color) in ["red", "red", "blue", "green", "green", "green"] + .iter() + .enumerate() + { + let doc = build_widget_doc(&contract, color, "small", (i + 1) as u64); + drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentRefInfo((&doc, None)), + owner_id: None, + }, + contract: &contract, + document_type, + }, + false, + BlockInfo::default(), + true, + None, + pv, + None, + ) + .expect("expected to insert document"); + } + + let property_path = property_name_tree_path(&contract, "widget", "color"); + + // 6 inserts total → ProvableCountTree aggregate = 6 + let prop_parent: Vec> = property_path[..property_path.len() - 1].to_vec(); + let prop_key = property_path.last().unwrap().clone(); + let prop_elem = + read_grove_element(&drive, &prop_parent, &prop_key).expect("property-name tree exists"); + match prop_elem { + Element::ProvableCountTree(_, count, _) => assert_eq!(count, 6), + other => panic!("expected ProvableCountTree, got {:?}", other), + } + + // Per-value counts: red=2, blue=1, green=3 + for (color, expected) in [("red", 2u64), ("blue", 1), ("green", 3)] { + let value_elem = read_grove_element(&drive, &property_path, color.as_bytes()) + .unwrap_or_else(|| panic!("value tree for color={} must exist", color)); + match value_elem { + Element::CountTree(_, count, _) => { + assert_eq!(count, expected, "color={} CountTree count mismatch", color) + } + other => panic!("expected CountTree at color={}, got {:?}", color, other), + } + } + } + + /// End-to-end exercise of the range count executor: + /// `DriveDocumentCountQuery::execute_range_count_no_proof`. With six + /// docs at three distinct color values, a `> "blue"` range + /// should hit `green` (3 docs) and `red` (2 docs) for a total of 5, + /// and `distinct = true` returns one entry per matching value. + #[test] + fn range_count_executor_sums_and_splits_correctly() { + use crate::query::{ + DriveDocumentCountQuery, RangeCountOptions, WhereClause, WhereOperator, + }; + + let drive = setup_drive_with_initial_state_structure(None); + let pv = PlatformVersion::latest(); + let contract = build_widget_with_color_index(false); + + drive + .apply_contract( + &contract, + BlockInfo::default(), + true, + StorageFlags::optional_default_as_cow(), + None, + pv, + ) + .expect("expected to apply contract"); + + let document_type = contract + .document_type_for_name("widget") + .expect("widget exists"); + + for (i, color) in ["red", "red", "blue", "green", "green", "green"] + .iter() + .enumerate() + { + let doc = build_widget_doc(&contract, color, "small", (i + 1) as u64); + drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentRefInfo((&doc, None)), + owner_id: None, + }, + contract: &contract, + document_type, + }, + false, + BlockInfo::default(), + true, + None, + pv, + None, + ) + .expect("expected to insert document"); + } + + // Find the range_countable index via the picker so the test + // doesn't depend on any particular index name. + let where_clauses = vec![WhereClause { + field: "color".to_string(), + operator: WhereOperator::GreaterThan, + value: dpp::platform_value::Value::Text("blue".to_string()), + }]; + let index = DriveDocumentCountQuery::find_range_countable_index_for_where_clauses( + document_type.indexes(), + &where_clauses, + ) + .expect("range_countable index should be picked"); + + let query = DriveDocumentCountQuery { + document_type, + contract_id: contract.id().to_buffer(), + document_type_name: "widget".to_string(), + index, + where_clauses: where_clauses.clone(), + }; + + // distinct=false: single summed entry. green(3) + red(2) = 5. + let summed = query + .execute_range_count_no_proof( + &drive, + &RangeCountOptions { + distinct: false, + limit: None, + order_by_ascending: true, + }, + None, + pv, + ) + .expect("range count should succeed"); + assert_eq!(summed.len(), 1); + assert!(summed[0].key.is_empty(), "summed entry has empty key"); + assert_eq!( + summed[0].count, 5, + "color > 'blue' should sum to 3 (green) + 2 (red) = 5" + ); + + // distinct=true: per-value entries, ascending. Should be + // [(green, 3), (red, 2)] — `blue` is excluded by the + // exclusive lower bound. + let split = query + .execute_range_count_no_proof( + &drive, + &RangeCountOptions { + distinct: true, + limit: None, + order_by_ascending: true, + }, + None, + pv, + ) + .expect("range count should succeed"); + assert_eq!(split.len(), 2); + assert_eq!(split[0].key, b"green".to_vec()); + assert_eq!(split[0].count, 3); + assert_eq!(split[1].key, b"red".to_vec()); + assert_eq!(split[1].count, 2); + + // distinct=true with limit=1: only the first entry. + let limited = query + .execute_range_count_no_proof( + &drive, + &RangeCountOptions { + distinct: true, + limit: Some(1), + order_by_ascending: true, + }, + None, + pv, + ) + .expect("range count should succeed"); + assert_eq!(limited.len(), 1); + assert_eq!(limited[0].key, b"green".to_vec()); + + // Pagination via range adjustment: `color > "green"` (rather + // than `color > "blue"` + a cursor field) yields the same + // "everything past green" page, which here is just red. + let after_clauses = vec![WhereClause { + field: "color".to_string(), + operator: WhereOperator::GreaterThan, + value: dpp::platform_value::Value::Text("green".to_string()), + }]; + let after_index = DriveDocumentCountQuery::find_range_countable_index_for_where_clauses( + document_type.indexes(), + &after_clauses, + ) + .expect("range_countable index should be picked"); + let after_query = DriveDocumentCountQuery { + document_type, + contract_id: contract.id().to_buffer(), + document_type_name: "widget".to_string(), + index: after_index, + where_clauses: after_clauses, + }; + let after = after_query + .execute_range_count_no_proof( + &drive, + &RangeCountOptions { + distinct: true, + limit: None, + order_by_ascending: true, + }, + None, + pv, + ) + .expect("range count should succeed"); + assert_eq!(after.len(), 1); + assert_eq!(after[0].key, b"red".to_vec()); + + // distinct=true descending: [(red, 2), (green, 3)]. + let desc = query + .execute_range_count_no_proof( + &drive, + &RangeCountOptions { + distinct: true, + limit: None, + order_by_ascending: false, + }, + None, + pv, + ) + .expect("range count should succeed"); + assert_eq!(desc.len(), 2); + assert_eq!(desc[0].key, b"red".to_vec()); + assert_eq!(desc[1].key, b"green".to_vec()); + } + + /// `Between [a, b]` is inclusive on both ends — a value at + /// exactly the lower or upper bound must be counted. + #[test] + fn range_count_executor_between_is_inclusive_on_both_bounds() { + use crate::query::{ + DriveDocumentCountQuery, RangeCountOptions, WhereClause, WhereOperator, + }; + + let drive = setup_drive_with_initial_state_structure(None); + let pv = PlatformVersion::latest(); + let contract = build_widget_with_color_index(false); + + drive + .apply_contract( + &contract, + BlockInfo::default(), + true, + StorageFlags::optional_default_as_cow(), + None, + pv, + ) + .expect("expected to apply contract"); + + let document_type = contract + .document_type_for_name("widget") + .expect("widget exists"); + + for (i, color) in ["aaa", "bbb", "ccc", "ddd"].iter().enumerate() { + let doc = build_widget_doc(&contract, color, "small", (i + 1) as u64); + drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentRefInfo((&doc, None)), + owner_id: None, + }, + contract: &contract, + document_type, + }, + false, + BlockInfo::default(), + true, + None, + pv, + None, + ) + .expect("expected to insert document"); + } + + let where_clauses = vec![WhereClause { + field: "color".to_string(), + operator: WhereOperator::Between, + value: dpp::platform_value::Value::Array(vec![ + dpp::platform_value::Value::Text("bbb".to_string()), + dpp::platform_value::Value::Text("ccc".to_string()), + ]), + }]; + let index = DriveDocumentCountQuery::find_range_countable_index_for_where_clauses( + document_type.indexes(), + &where_clauses, + ) + .expect("range_countable index should be picked"); + + let query = DriveDocumentCountQuery { + document_type, + contract_id: contract.id().to_buffer(), + document_type_name: "widget".to_string(), + index, + where_clauses, + }; + + let split = query + .execute_range_count_no_proof( + &drive, + &RangeCountOptions { + distinct: true, + limit: None, + order_by_ascending: true, + }, + None, + pv, + ) + .expect("range count should succeed"); + assert_eq!(split.len(), 2); + assert_eq!(split[0].key, b"bbb".to_vec()); + assert_eq!(split[0].count, 1); + assert_eq!(split[1].key, b"ccc".to_vec()); + assert_eq!(split[1].count, 1); + } + + /// `execute_aggregate_count_with_proof` should produce a grovedb + /// `AggregateCountOnRange` proof that verifies to the same total + /// count as the no-proof range walk. This is the prove-path + /// counterpart of [`range_count_executor_sums_and_splits_correctly`]. + /// + /// The verification step uses + /// `GroveDb::verify_aggregate_count_query` directly — proves the + /// returned bytes are a real proof, not just any blob — and asserts + /// the recovered count matches the no-proof sum. + #[test] + fn aggregate_count_proof_verifies_and_returns_correct_count() { + use crate::query::{DriveDocumentCountQuery, WhereClause, WhereOperator}; + use grovedb::{GroveDb, PathQuery}; + + let drive = setup_drive_with_initial_state_structure(None); + let pv = PlatformVersion::latest(); + let contract = build_widget_with_color_index(false); + + drive + .apply_contract( + &contract, + BlockInfo::default(), + true, + StorageFlags::optional_default_as_cow(), + None, + pv, + ) + .expect("expected to apply contract"); + + let document_type = contract + .document_type_for_name("widget") + .expect("widget exists"); + + // Same six-doc fixture as the no-proof test. + for (i, color) in ["red", "red", "blue", "green", "green", "green"] + .iter() + .enumerate() + { + let doc = build_widget_doc(&contract, color, "small", (i + 1) as u64); + drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentRefInfo((&doc, None)), + owner_id: None, + }, + contract: &contract, + document_type, + }, + false, + BlockInfo::default(), + true, + None, + pv, + None, + ) + .expect("expected to insert document"); + } + + let where_clauses = vec![WhereClause { + field: "color".to_string(), + operator: WhereOperator::GreaterThan, + value: dpp::platform_value::Value::Text("blue".to_string()), + }]; + let index = DriveDocumentCountQuery::find_range_countable_index_for_where_clauses( + document_type.indexes(), + &where_clauses, + ) + .expect("range_countable index should be picked"); + + let query = DriveDocumentCountQuery { + document_type, + contract_id: contract.id().to_buffer(), + document_type_name: "widget".to_string(), + index, + where_clauses: where_clauses.clone(), + }; + + let proof_bytes = query + .execute_aggregate_count_with_proof(&drive, None, pv) + .expect("should generate aggregate count proof"); + assert!(!proof_bytes.is_empty(), "proof must not be empty"); + + // Reconstruct the same path query the prover used, verify the + // proof against it, and check the recovered count. + let path = vec![ + vec![crate::drive::RootTree::DataContractDocuments as u8], + contract.id().as_bytes().to_vec(), + vec![1u8], + b"widget".to_vec(), + b"color".to_vec(), + ]; + let query_item = grovedb::QueryItem::RangeAfter(b"blue".to_vec()..); + let path_query = PathQuery::new_aggregate_count_on_range(path, query_item); + + let (root_hash, count) = GroveDb::verify_aggregate_count_query( + &proof_bytes, + &path_query, + &pv.drive.grove_version, + ) + .expect("aggregate-count proof should verify"); + assert_ne!(root_hash, [0u8; 32], "root hash should not be zero"); + assert_eq!( + count, 5, + "verified count should match no-proof sum: 3 (green) + 2 (red) = 5" + ); + } + + /// Range count with an `In` clause on the prefix forks the walk + /// into one path per prefix value. Each emitted entry carries + /// the `in_key` (the brand) alongside `key` (the color) — the + /// server does NOT merge across forks, because limit applied + /// pre-merge could undercount cross-fork sums (the entries the + /// limit drops on one fork might be the ones whose key collides + /// with another fork's surviving entries). Callers reduce by + /// `key` client-side via `DocumentSplitCounts::into_flat_map` if + /// they want the flat histogram view. + #[test] + fn range_count_with_in_on_prefix_returns_per_brand_color_entries() { + use crate::query::{ + DriveDocumentCountQuery, RangeCountOptions, WhereClause, WhereOperator, + }; + use dpp::platform_value::Value; + + let drive = setup_drive_with_initial_state_structure(None); + let pv = PlatformVersion::latest(); + + // Build a contract with `[brand, color]` range_countable. + let factory = dpp::data_contract::DataContractFactory::new(PROTOCOL_VERSION_V12) + .expect("expected to create factory"); + let document_schema = platform_value!({ + "type": "object", + "properties": { + "brand": { "type": "string", "position": 0, "maxLength": 32 }, + "color": { "type": "string", "position": 1, "maxLength": 32 }, + }, + "indices": [{ + "name": "byBrandColor", + "properties": [{"brand": "asc"}, {"color": "asc"}], + "countable": "countable", + "rangeCountable": true, + }], + "additionalProperties": false, + }); + let schemas = platform_value!({ "widget": document_schema }); + let contract = factory + .create_with_value_config(generate_random_identifier_struct(), 0, schemas, None, None) + .expect("create contract") + .data_contract_owned(); + + drive + .apply_contract( + &contract, + BlockInfo::default(), + true, + StorageFlags::optional_default_as_cow(), + None, + pv, + ) + .expect("apply contract"); + + let document_type = contract + .document_type_for_name("widget") + .expect("widget exists"); + + // 3 acme + red, 2 acme + blue, 2 contoso + red, 1 contoso + green. + let docs: Vec<(&str, &str)> = vec![ + ("acme", "red"), + ("acme", "red"), + ("acme", "red"), + ("acme", "blue"), + ("acme", "blue"), + ("contoso", "red"), + ("contoso", "red"), + ("contoso", "green"), + ]; + for (i, (brand, color)) in docs.iter().enumerate() { + let mut doc = document_type + .random_document(Some((i + 1) as u64), pv) + .expect("random doc"); + let mut props = std::collections::BTreeMap::new(); + props.insert("brand".to_string(), Value::Text(brand.to_string())); + props.insert("color".to_string(), Value::Text(color.to_string())); + doc.set_properties(props); + drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentRefInfo((&doc, None)), + owner_id: None, + }, + contract: &contract, + document_type, + }, + false, + BlockInfo::default(), + true, + None, + pv, + None, + ) + .expect("insert"); + } + + // brand IN (acme, contoso) AND color > "blue" + // Match: acme+red(3), contoso+red(2), contoso+green(1) = 6 + // (Excluded: acme+blue, contoso+blue — but there's no + // contoso+blue, just acme+blue which doesn't match.) + let where_clauses = vec![ + WhereClause { + field: "brand".to_string(), + operator: WhereOperator::In, + value: Value::Array(vec![ + Value::Text("acme".to_string()), + Value::Text("contoso".to_string()), + ]), + }, + WhereClause { + field: "color".to_string(), + operator: WhereOperator::GreaterThan, + value: Value::Text("blue".to_string()), + }, + ]; + let index = DriveDocumentCountQuery::find_range_countable_index_for_where_clauses( + document_type.indexes(), + &where_clauses, + ) + .expect("range_countable index should be picked"); + + let query = DriveDocumentCountQuery { + document_type, + contract_id: contract.id().to_buffer(), + document_type_name: "widget".to_string(), + index, + where_clauses, + }; + + // Distinct mode: per-(brand, color) entries, unmerged. + // brand=acme + color > "blue" matches red(3). + // brand=contoso + color > "blue" matches red(2), green(1). + // Expected order: ascending (in_key, key) tuple → + // (acme, red) count=3 + // (contoso, green) count=1 + // (contoso, red) count=2 + let split = query + .execute_range_count_no_proof( + &drive, + &RangeCountOptions { + distinct: true, + limit: None, + order_by_ascending: true, + }, + None, + pv, + ) + .expect("range count should succeed"); + assert_eq!( + split.len(), + 3, + "expected unmerged per-(brand, color) entries, not a cross-fork sum" + ); + assert_eq!(split[0].in_key.as_deref(), Some(b"acme".as_slice())); + assert_eq!(split[0].key, b"red".to_vec()); + assert_eq!(split[0].count, 3); + assert_eq!(split[1].in_key.as_deref(), Some(b"contoso".as_slice())); + assert_eq!(split[1].key, b"green".to_vec()); + assert_eq!(split[1].count, 1); + assert_eq!(split[2].in_key.as_deref(), Some(b"contoso".as_slice())); + assert_eq!(split[2].key, b"red".to_vec()); + assert_eq!(split[2].count, 2); + + // Client-side merge over `key` recovers the flat histogram: + // green: 1 + // red: 3 + 2 = 5 + let merged: std::collections::BTreeMap, u64> = + split + .iter() + .fold(std::collections::BTreeMap::new(), |mut m, e| { + *m.entry(e.key.clone()).or_insert(0) += e.count; + m + }); + assert_eq!(merged.get(b"green".as_slice()), Some(&1)); + assert_eq!(merged.get(b"red".as_slice()), Some(&5)); + + // Summed mode: 6 docs total across all forks. + let summed = query + .execute_range_count_no_proof( + &drive, + &RangeCountOptions { + distinct: false, + limit: None, + order_by_ascending: true, + }, + None, + pv, + ) + .expect("range count should succeed"); + assert_eq!(summed.len(), 1); + assert!( + summed[0].in_key.is_none(), + "summed mode always emits a single in_key=None, key=empty entry" + ); + assert!(summed[0].key.is_empty()); + assert_eq!(summed[0].count, 6); + } + + /// `StartsWith "r"` is encoded as `Range(serialize("r").. + /// serialize("r") with last byte +1)` — the same half-open + /// byte-incremented encoding `conditions.rs:1129`'s `StartsWith` + /// arm uses for the normal docs path. On the count fast path this + /// becomes a `QueryItem::Range(..)` no different in structure from + /// `betweenExcludeRight`, so all four executor modes (no-proof + /// aggregate, no-proof distinct, prove aggregate, prove distinct) + /// serve it via the same code paths that already cover `>` / `<` + /// / `between*`. This test pins acceptance across all four. + #[test] + fn range_count_executor_accepts_starts_with_in_all_four_modes() { + use crate::query::{ + DriveDocumentCountQuery, RangeCountOptions, WhereClause, WhereOperator, + }; + use grovedb::GroveDb; + + let drive = setup_drive_with_initial_state_structure(None); + let pv = PlatformVersion::latest(); + let contract = build_widget_with_color_index(false); + + drive + .apply_contract( + &contract, + BlockInfo::default(), + true, + StorageFlags::optional_default_as_cow(), + None, + pv, + ) + .expect("apply contract"); + + let document_type = contract + .document_type_for_name("widget") + .expect("widget exists"); + + // Three colors share the `r` prefix (red, rose, ruby) and + // one doesn't (blue). The half-open range `[r, s)` should + // hit the three `r*` colors and miss `blue` entirely. + // red ×2, rose ×3, ruby ×1, blue ×4 → 6 in-range docs + // across 3 distinct values. + for (i, color) in [ + "red", "red", "rose", "rose", "rose", "ruby", "blue", "blue", "blue", "blue", + ] + .iter() + .enumerate() + { + let doc = build_widget_doc(&contract, color, "small", (i + 1) as u64); + drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentRefInfo((&doc, None)), + owner_id: None, + }, + contract: &contract, + document_type, + }, + false, + BlockInfo::default(), + true, + None, + pv, + None, + ) + .expect("insert document"); + } + + let where_clauses = vec![WhereClause { + field: "color".to_string(), + operator: WhereOperator::StartsWith, + value: dpp::platform_value::Value::Text("r".to_string()), + }]; + let index = DriveDocumentCountQuery::find_range_countable_index_for_where_clauses( + document_type.indexes(), + &where_clauses, + ) + .expect("picker accepts StartsWith"); + let query = DriveDocumentCountQuery { + document_type, + contract_id: contract.id().to_buffer(), + document_type_name: "widget".to_string(), + index, + where_clauses, + }; + + // Mode 1: no-proof aggregate. red(2) + rose(3) + ruby(1) = 6. + let summed = query + .execute_range_count_no_proof( + &drive, + &RangeCountOptions { + distinct: false, + limit: None, + order_by_ascending: true, + }, + None, + pv, + ) + .expect("no-proof aggregate over StartsWith"); + assert_eq!(summed.len(), 1, "summed mode → one entry"); + assert!(summed[0].key.is_empty(), "summed entry has empty key"); + assert_eq!( + summed[0].count, 6, + "color startsWith 'r' should sum to 2 (red) + 3 (rose) + 1 (ruby) = 6" + ); + + // Mode 2: no-proof distinct. Per-distinct-value entries, + // ascending. red < rose < ruby alphabetically. + let split = query + .execute_range_count_no_proof( + &drive, + &RangeCountOptions { + distinct: true, + limit: None, + order_by_ascending: true, + }, + None, + pv, + ) + .expect("no-proof distinct over StartsWith"); + assert_eq!( + split.len(), + 3, + "distinct mode → one entry per matching color" + ); + assert_eq!(split[0].key, b"red".to_vec()); + assert_eq!(split[0].count, 2); + assert_eq!(split[1].key, b"rose".to_vec()); + assert_eq!(split[1].count, 3); + assert_eq!(split[2].key, b"ruby".to_vec()); + assert_eq!(split[2].count, 1); + + // Mode 3: prove aggregate. Verifies via + // `GroveDb::verify_aggregate_count_query` against the path + // query the SDK would rebuild — same shape the existing `>` + // prove tests use, just with a half-open `[r, s)` range + // instead of `(b, ∞)`. + let proof_bytes = query + .execute_aggregate_count_with_proof(&drive, None, pv) + .expect("aggregate count proof over StartsWith"); + let path_query = query + .aggregate_count_path_query(pv) + .expect("aggregate path query builds for StartsWith"); + let (root_hash, count) = GroveDb::verify_aggregate_count_query( + &proof_bytes, + &path_query, + &pv.drive.grove_version, + ) + .expect("aggregate-count proof should verify"); + assert_ne!(root_hash, [0u8; 32], "root hash should not be zero"); + assert_eq!( + count, 6, + "verified aggregate count should match no-proof sum" + ); + + // Mode 4: prove distinct. The KVCount ops in the leaf merk + // proof carry per-key counts bound to the merk root via + // `node_hash_with_count`. Verify with standard `verify_query` + // (matching the docs handler / distinct verifier pattern). + const TEST_LIMIT: u16 = crate::config::DEFAULT_QUERY_LIMIT; + let proof_bytes = query + .execute_distinct_count_with_proof(&drive, TEST_LIMIT, true, None, pv) + .expect("distinct count proof over StartsWith"); + assert!( + !proof_bytes.is_empty(), + "distinct count proof must not be empty" + ); + let path_query = query + .distinct_count_path_query(Some(TEST_LIMIT), true, pv) + .expect("distinct path query builds for StartsWith"); + let (root_hash, _elements) = + GroveDb::verify_query(&proof_bytes, &path_query, &pv.drive.grove_version) + .expect("distinct-count proof should verify"); + assert_ne!(root_hash, [0u8; 32], "root hash should not be zero"); + } + + /// Empty `startsWith` prefix: `encode_value_for_tree_keys` maps + /// `Value::Text("")` to `[0]` (the explicit empty-string + /// sentinel — see `DocumentPropertyType::String`'s arm in + /// `packages/rs-dpp/src/data_contract/document_type/property/mod.rs`, + /// "we don't want to collide with the definition of an empty + /// string"). The half-open range becomes `[[0], [1])`, which + /// matches the empty-string sentinel value itself but nothing + /// else. Since no widget in this fixture has `color = ""` the + /// result is a successful sum of `0` — verifying the executor + /// reaches the count walk rather than panicking on the + /// `last_mut()` branch. + /// + /// The `last_mut().ok_or(InvalidStartsWithClause)` branch in + /// `range_clause_to_query_item` is unreachable in practice + /// through this entry point because the empty-string sentinel + /// produces a non-empty serialized buffer; the check is purely + /// defense-in-depth against future encoding changes. + #[test] + fn range_count_executor_accepts_empty_starts_with_prefix_via_sentinel() { + use crate::query::{ + DriveDocumentCountQuery, RangeCountOptions, WhereClause, WhereOperator, + }; + + let drive = setup_drive_with_initial_state_structure(None); + let pv = PlatformVersion::latest(); + let contract = build_widget_with_color_index(false); + + drive + .apply_contract( + &contract, + BlockInfo::default(), + true, + StorageFlags::optional_default_as_cow(), + None, + pv, + ) + .expect("apply contract"); + + let document_type = contract + .document_type_for_name("widget") + .expect("widget exists"); + let where_clauses = vec![WhereClause { + field: "color".to_string(), + operator: WhereOperator::StartsWith, + value: dpp::platform_value::Value::Text(String::new()), + }]; + let index = DriveDocumentCountQuery::find_range_countable_index_for_where_clauses( + document_type.indexes(), + &where_clauses, + ) + .expect("picker accepts StartsWith with any value"); + let query = DriveDocumentCountQuery { + document_type, + contract_id: contract.id().to_buffer(), + document_type_name: "widget".to_string(), + index, + where_clauses, + }; + + let result = query + .execute_range_count_no_proof( + &drive, + &RangeCountOptions { + distinct: false, + limit: None, + order_by_ascending: true, + }, + None, + pv, + ) + .expect("empty startsWith prefix should succeed (matches empty-string sentinel only)"); + assert_eq!(result.len(), 1, "summed mode → one entry"); + assert_eq!( + result[0].count, 0, + "no docs have color = empty-string sentinel" + ); + } + + // -------- Aggregate-count prove-path coverage helpers ---------- + // + // The existing `aggregate_count_proof_verifies_and_returns_correct_count` + // tests exactly one operator (`>` → grovedb's `RangeAfter`). The + // remaining 7 mapped operator shapes + // (`>=`/`<`/`<=`/`between`/`betweenExcludeBounds`/ + // `betweenExcludeLeft`/`betweenExcludeRight`) all generate + // structurally different `QueryItem` variants and exercise + // different `Disjoint`/`Contained`/`Boundary` classifications in + // grovedb's `prove_aggregate_count_on_range` walk. Each is its own + // potential regression site even though all share the same + // platform-side path-builder. The helpers + per-operator tests + // below close that gap. + + /// Single-byColor fixture with 5 distinct color values + /// (`a`..`e`, two docs each — 10 docs total) so range tests can + /// land Disjoint, Contained, and Boundary classifications across + /// the AVL tree without carrying contract setup duplication. + fn setup_widget_with_5_colors_2_docs_each() -> (Drive, DataContract) { + let drive = setup_drive_with_initial_state_structure(None); + let pv = PlatformVersion::latest(); + let contract = build_widget_with_color_index(false); + + drive + .apply_contract( + &contract, + BlockInfo::default(), + true, + StorageFlags::optional_default_as_cow(), + None, + pv, + ) + .expect("apply contract"); + + let document_type = contract + .document_type_for_name("widget") + .expect("widget exists"); + + let mut seed = 1u64; + for color in ["a", "b", "c", "d", "e"] { + for _ in 0..2 { + let doc = build_widget_doc(&contract, color, "small", seed); + drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentRefInfo((&doc, None)), + owner_id: None, + }, + contract: &contract, + document_type, + }, + false, + BlockInfo::default(), + true, + None, + pv, + None, + ) + .expect("expected to insert document"); + seed += 1; + } + } + + (drive, contract) + } + + /// Prove-path roundtrip helper: builds the path query via the + /// shared `aggregate_count_path_query` (the same path the prover + /// internally uses), generates the proof, verifies it via + /// grovedb's `verify_aggregate_count_query`, and asserts the + /// recovered count equals `expected_count`. Reusing the + /// path-builder rather than hand-coding the path matches the SDK's + /// runtime flow — a divergence between prover and verifier + /// path-construction would surface here as a verification failure. + fn assert_aggregate_count_proof_returns( + drive: &Drive, + contract: &DataContract, + document_type_name: &str, + where_clauses: Vec, + expected_count: u64, + ) { + use crate::query::DriveDocumentCountQuery; + use grovedb::GroveDb; + + let pv = PlatformVersion::latest(); + let document_type = contract + .document_type_for_name(document_type_name) + .expect("document type exists"); + let index = DriveDocumentCountQuery::find_range_countable_index_for_where_clauses( + document_type.indexes(), + &where_clauses, + ) + .expect("range_countable index should be picked"); + + let query = DriveDocumentCountQuery { + document_type, + contract_id: contract.id().to_buffer(), + document_type_name: document_type_name.to_string(), + index, + where_clauses, + }; + + let proof_bytes = query + .execute_aggregate_count_with_proof(drive, None, pv) + .expect("should generate aggregate count proof"); + assert!(!proof_bytes.is_empty(), "proof must not be empty"); + + let path_query = query + .aggregate_count_path_query(pv) + .expect("aggregate_count_path_query should build"); + + let (root_hash, count) = GroveDb::verify_aggregate_count_query( + &proof_bytes, + &path_query, + &pv.drive.grove_version, + ) + .expect("aggregate-count proof should verify"); + assert_ne!(root_hash, [0u8; 32], "root hash should not be zero"); + assert_eq!( + count, expected_count, + "verified count should equal expected count" + ); + } + + /// `>=` → grovedb `RangeFrom`. Lower bound inclusive, no upper + /// bound. Differs from `>` (RangeAfter) in whether the bound key + /// itself contributes — both share the same one-sided-from-below + /// AVL walk shape so this also serves as the regression for the + /// inclusivity bit. + #[test] + fn aggregate_count_proof_verifies_lower_bound_inclusive_ge() { + use crate::query::{WhereClause, WhereOperator}; + + let (drive, contract) = setup_widget_with_5_colors_2_docs_each(); + let where_clauses = vec![WhereClause { + field: "color".to_string(), + operator: WhereOperator::GreaterThanOrEquals, + value: dpp::platform_value::Value::Text("c".to_string()), + }]; + // c, d, e each have 2 docs; a, b excluded → 6. + assert_aggregate_count_proof_returns(&drive, &contract, "widget", where_clauses, 6); + } + + /// `<` → grovedb `RangeTo`. Upper bound strict, no lower bound. + /// Pins the one-sided-from-above walk shape; without this we'd + /// only ever exercise the symmetric `RangeAfter` half. + #[test] + fn aggregate_count_proof_verifies_upper_bound_strict_lt() { + use crate::query::{WhereClause, WhereOperator}; + + let (drive, contract) = setup_widget_with_5_colors_2_docs_each(); + let where_clauses = vec![WhereClause { + field: "color".to_string(), + operator: WhereOperator::LessThan, + value: dpp::platform_value::Value::Text("c".to_string()), + }]; + // a, b each have 2 docs; c, d, e excluded → 4. + assert_aggregate_count_proof_returns(&drive, &contract, "widget", where_clauses, 4); + } + + /// `<=` → grovedb `RangeToInclusive`. Pins the upper-bound + /// inclusivity bit on the from-above shape. + #[test] + fn aggregate_count_proof_verifies_upper_bound_inclusive_le() { + use crate::query::{WhereClause, WhereOperator}; + + let (drive, contract) = setup_widget_with_5_colors_2_docs_each(); + let where_clauses = vec![WhereClause { + field: "color".to_string(), + operator: WhereOperator::LessThanOrEquals, + value: dpp::platform_value::Value::Text("c".to_string()), + }]; + // a, b, c each have 2 docs; d, e excluded → 6. + assert_aggregate_count_proof_returns(&drive, &contract, "widget", where_clauses, 6); + } + + /// `between` → grovedb `RangeInclusive` (closed-closed). The most + /// common two-sided range shape; both bounds are matched. + #[test] + fn aggregate_count_proof_verifies_between_closed_closed() { + use crate::query::{WhereClause, WhereOperator}; + + let (drive, contract) = setup_widget_with_5_colors_2_docs_each(); + let where_clauses = vec![WhereClause { + field: "color".to_string(), + operator: WhereOperator::Between, + value: dpp::platform_value::Value::Array(vec![ + dpp::platform_value::Value::Text("b".to_string()), + dpp::platform_value::Value::Text("d".to_string()), + ]), + }]; + // b, c, d each have 2 docs → 6. + assert_aggregate_count_proof_returns(&drive, &contract, "widget", where_clauses, 6); + } + + /// `betweenExcludeBounds` → grovedb `RangeAfterTo` (open-open). + /// Both bounds are excluded — the only `between*` variant where + /// neither bound key contributes. + #[test] + fn aggregate_count_proof_verifies_between_open_open() { + use crate::query::{WhereClause, WhereOperator}; + + let (drive, contract) = setup_widget_with_5_colors_2_docs_each(); + let where_clauses = vec![WhereClause { + field: "color".to_string(), + operator: WhereOperator::BetweenExcludeBounds, + value: dpp::platform_value::Value::Array(vec![ + dpp::platform_value::Value::Text("a".to_string()), + dpp::platform_value::Value::Text("d".to_string()), + ]), + }]; + // b, c each have 2 docs (a excluded as lower, d excluded as + // upper) → 4. + assert_aggregate_count_proof_returns(&drive, &contract, "widget", where_clauses, 4); + } + + /// `betweenExcludeLeft` → grovedb `RangeAfterToInclusive` + /// (open-closed). Lower excluded, upper included. + #[test] + fn aggregate_count_proof_verifies_between_open_closed() { + use crate::query::{WhereClause, WhereOperator}; + + let (drive, contract) = setup_widget_with_5_colors_2_docs_each(); + let where_clauses = vec![WhereClause { + field: "color".to_string(), + operator: WhereOperator::BetweenExcludeLeft, + value: dpp::platform_value::Value::Array(vec![ + dpp::platform_value::Value::Text("a".to_string()), + dpp::platform_value::Value::Text("c".to_string()), + ]), + }]; + // b, c each have 2 docs (a excluded as lower) → 4. + assert_aggregate_count_proof_returns(&drive, &contract, "widget", where_clauses, 4); + } + + /// `betweenExcludeRight` → grovedb `Range` (closed-open). Lower + /// included, upper excluded — the conventional half-open range. + #[test] + fn aggregate_count_proof_verifies_between_closed_open() { + use crate::query::{WhereClause, WhereOperator}; + + let (drive, contract) = setup_widget_with_5_colors_2_docs_each(); + let where_clauses = vec![WhereClause { + field: "color".to_string(), + operator: WhereOperator::BetweenExcludeRight, + value: dpp::platform_value::Value::Array(vec![ + dpp::platform_value::Value::Text("b".to_string()), + dpp::platform_value::Value::Text("d".to_string()), + ]), + }]; + // b, c each have 2 docs (d excluded as upper) → 4. + assert_aggregate_count_proof_returns(&drive, &contract, "widget", where_clauses, 4); + } + + /// Empty range: zero matching keys must still produce a valid + /// proof with count = 0. This is the boundary case where every + /// subtree is `Disjoint` from the inner range — grovedb's prover + /// short-circuits at every link without descending. The verifier + /// must accept this proof shape and recover count = 0 (not error + /// "no items in range"). Without this test a regression that made + /// empty proofs fail would only surface at customer time. + #[test] + fn aggregate_count_proof_verifies_empty_range_returns_zero() { + use crate::query::{WhereClause, WhereOperator}; + + let (drive, contract) = setup_widget_with_5_colors_2_docs_each(); + let where_clauses = vec![WhereClause { + field: "color".to_string(), + operator: WhereOperator::GreaterThan, + value: dpp::platform_value::Value::Text("z".to_string()), + }]; + // No colors > "z" — count = 0. + assert_aggregate_count_proof_returns(&drive, &contract, "widget", where_clauses, 0); + } + + /// Compound `[brand, color]` range_countable index, prove path: + /// the `Equal`-on-brand prefix becomes path bytes (not a query + /// shape), and only the terminator `color > X` becomes the merk + /// `AggregateCountOnRange` walk. This exercises grovedb's multi- + /// layer aggregate-count proof envelope: the verifier walks + /// through one non-leaf layer (the `brand=acme` value tree's + /// existence proof) before reaching the leaf merk's count proof. + /// The single-property tests above all run at the top property- + /// name layer directly so they don't reach this code path. + #[test] + fn aggregate_count_proof_verifies_on_compound_index_with_equal_prefix() { + use crate::query::{DriveDocumentCountQuery, WhereClause, WhereOperator}; + use dpp::platform_value::Value; + use grovedb::GroveDb; + + let drive = setup_drive_with_initial_state_structure(None); + let pv = PlatformVersion::latest(); + + // Build a contract with `[brand, color]` range_countable. + // Same shape as `range_count_with_in_on_prefix_forks_and_merges` + // uses, but here we exercise the prove path instead of the + // no-proof executor. + let factory = dpp::data_contract::DataContractFactory::new(PROTOCOL_VERSION_V12) + .expect("expected to create factory"); + let document_schema = platform_value!({ + "type": "object", + "properties": { + "brand": { "type": "string", "position": 0, "maxLength": 32 }, + "color": { "type": "string", "position": 1, "maxLength": 32 }, + }, + "indices": [{ + "name": "byBrandColor", + "properties": [{"brand": "asc"}, {"color": "asc"}], + "countable": "countable", + "rangeCountable": true, + }], + "additionalProperties": false, + }); + let schemas = platform_value!({ "widget": document_schema }); + let contract = factory + .create_with_value_config(generate_random_identifier_struct(), 0, schemas, None, None) + .expect("create contract") + .data_contract_owned(); + + drive + .apply_contract( + &contract, + BlockInfo::default(), + true, + StorageFlags::optional_default_as_cow(), + None, + pv, + ) + .expect("apply contract"); + + let document_type = contract + .document_type_for_name("widget") + .expect("widget exists"); + + // acme: red×3, blue×2; contoso: red×2, green×1, blue×1. + // Query: brand = acme AND color > "blue" → 3 (acme reds). + let docs: &[(&str, &str)] = &[ + ("acme", "red"), + ("acme", "red"), + ("acme", "red"), + ("acme", "blue"), + ("acme", "blue"), + ("contoso", "red"), + ("contoso", "red"), + ("contoso", "green"), + ("contoso", "blue"), + ]; + for (i, (brand, color)) in docs.iter().enumerate() { + let mut doc = document_type + .random_document(Some((i + 1) as u64), pv) + .expect("random document"); + let mut props = std::collections::BTreeMap::new(); + props.insert("brand".to_string(), Value::Text(brand.to_string())); + props.insert("color".to_string(), Value::Text(color.to_string())); + doc.set_properties(props); + + drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentRefInfo((&doc, None)), + owner_id: None, + }, + contract: &contract, + document_type, + }, + false, + BlockInfo::default(), + true, + None, + pv, + None, + ) + .expect("expected to insert document"); + } + + let where_clauses = vec![ + WhereClause { + field: "brand".to_string(), + operator: WhereOperator::Equal, + value: Value::Text("acme".to_string()), + }, + WhereClause { + field: "color".to_string(), + operator: WhereOperator::GreaterThan, + value: Value::Text("blue".to_string()), + }, + ]; + let index = DriveDocumentCountQuery::find_range_countable_index_for_where_clauses( + document_type.indexes(), + &where_clauses, + ) + .expect("compound range_countable index should be picked"); + + let query = DriveDocumentCountQuery { + document_type, + contract_id: contract.id().to_buffer(), + document_type_name: "widget".to_string(), + index, + where_clauses, + }; + + let proof_bytes = query + .execute_aggregate_count_with_proof(&drive, None, pv) + .expect("should generate aggregate count proof"); + assert!(!proof_bytes.is_empty(), "proof must not be empty"); + + let path_query = query + .aggregate_count_path_query(pv) + .expect("compound aggregate_count_path_query should build"); + + let (root_hash, count) = GroveDb::verify_aggregate_count_query( + &proof_bytes, + &path_query, + &pv.drive.grove_version, + ) + .expect( + "compound aggregate-count proof should verify (multi-layer \ + envelope walk through brand=acme to color leaf merk)", + ); + assert_ne!(root_hash, [0u8; 32], "root hash should not be zero"); + assert_eq!( + count, 3, + "verified count should be 3 (acme reds; acme blues excluded by `> blue`)" + ); + } + + /// Scale test for the `AggregateCountOnRange` proof primitive at + /// non-trivial fan-out: a parking-lot contract with one document + /// per car, each tagged with its lot letter (`a`..`z`). Lot `a` + /// has 1 car, `b` has 2, ..., `z` has 26 — total `1+2+...+26 = + /// 351` cars across 26 distinct lot values. + /// + /// Question: how many cars are in parking lots > b? + /// Answer: cars in lots `c..=z` = `3+4+...+26` = 348. + /// + /// Why this test earns its keep on top of the operator-shape + /// matrix above: + /// + /// 1. **Wide range** — 24 of 26 distinct values are in-range, so + /// grovedb's prover walks the AVL tree end-to-end and + /// classifies most subtrees as `Contained` (one-level kv_hash + /// + grandchild-hash visit) rather than `Boundary` (recurse). + /// The narrow ranges in the operator-shape tests don't + /// exercise this regime. + /// 2. **Realistic per-key fan-out** — multi-doc lots (b=2, c=3, + /// …, z=26) mean each value tree is a non-trivial CountTree + /// with internal counts > 1. The aggregate count must sum + /// those internal counts correctly, not just count keys. + /// 3. **The proof stays O(log n)** even though the answer is 348 + /// — the verifier never sees the underlying 348 documents, + /// only the merk-level count proof. That's the whole reason + /// the aggregate primitive exists vs. the materialize-and- + /// count fallback. + #[test] + fn aggregate_count_proof_counts_cars_in_parking_lots_greater_than_b() { + use crate::query::{WhereClause, WhereOperator}; + use dpp::platform_value::Value; + + let drive = setup_drive_with_initial_state_structure(None); + let pv = PlatformVersion::latest(); + + // parking-lot contract: one `car` document type with a `byLot` + // range_countable index on the `lot` property. Single-property + // index keeps the path-builder at the top property-name layer + // (the leaf-merk count proof is the whole envelope here). + let factory = dpp::data_contract::DataContractFactory::new(PROTOCOL_VERSION_V12) + .expect("expected to create factory"); + let document_schema = platform_value!({ + "type": "object", + "properties": { + "lot": { "type": "string", "position": 0, "maxLength": 4 }, + }, + "indices": [{ + "name": "byLot", + "properties": [{"lot": "asc"}], + "countable": "countable", + "rangeCountable": true, + }], + "additionalProperties": false, + }); + let schemas = platform_value!({ "car": document_schema }); + let contract = factory + .create_with_value_config(generate_random_identifier_struct(), 0, schemas, None, None) + .expect("create parking-lot contract") + .data_contract_owned(); + + drive + .apply_contract( + &contract, + BlockInfo::default(), + true, + StorageFlags::optional_default_as_cow(), + None, + pv, + ) + .expect("apply parking-lot contract"); + + let document_type = contract + .document_type_for_name("car") + .expect("car document type exists"); + + // Insert N cars for each lot, where N = lot's 1-based + // position in the alphabet (a → 1, b → 2, …, z → 26). + let mut seed = 1u64; + for (idx, letter) in ('a'..='z').enumerate() { + let car_count = idx + 1; + for _ in 0..car_count { + let mut doc = document_type + .random_document(Some(seed), pv) + .expect("random document"); + let mut props = std::collections::BTreeMap::new(); + props.insert("lot".to_string(), Value::Text(letter.to_string())); + doc.set_properties(props); + + drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentRefInfo((&doc, None)), + owner_id: None, + }, + contract: &contract, + document_type, + }, + false, + BlockInfo::default(), + true, + None, + pv, + None, + ) + .expect("expected to insert car document"); + seed += 1; + } + } + + // Quick math check on the closed-form expected count so a + // future reader doesn't have to recompute the sum to follow + // the assertion. + let expected: u64 = (3..=26).sum(); + assert_eq!( + expected, 348, + "sanity check: cars in lots c..=z = 3 + 4 + … + 26 = 348" + ); + + // The actual scenario: how many cars are in parking lots > b? + let where_clauses = vec![WhereClause { + field: "lot".to_string(), + operator: WhereOperator::GreaterThan, + value: Value::Text("b".to_string()), + }]; + + use crate::query::DriveDocumentCountQuery; + use grovedb::GroveDb; + let index = DriveDocumentCountQuery::find_range_countable_index_for_where_clauses( + document_type.indexes(), + &where_clauses, + ) + .expect("byLot range_countable index should be picked"); + let query = DriveDocumentCountQuery { + document_type, + contract_id: contract.id().to_buffer(), + document_type_name: "car".to_string(), + index, + where_clauses, + }; + + let proof_bytes = query + .execute_aggregate_count_with_proof(&drive, None, pv) + .expect("should generate aggregate count proof"); + + let path_query = query + .aggregate_count_path_query(pv) + .expect("path query should build"); + + let (root_hash, count) = GroveDb::verify_aggregate_count_query( + &proof_bytes, + &path_query, + &pv.drive.grove_version, + ) + .expect("aggregate-count proof should verify"); + + // Inline-print under `cargo test -- --nocapture`. The + // envelope walk decodes the bincode-wrapped `GroveDBProof`, + // then for each layer's merk proof bytes uses + // `MerkProofDecoder` to print the per-layer Op stream. This + // is the same decoding the verifier above performed + // internally — surfacing it makes the O(log n) shape concrete + // (the leaf merk proof for `lot > "b"` is ~700 bytes + // regardless of how many of the 351 cars are in-range). + use grovedb::operations::proof::{ + GroveDBProof, GroveDBProofV0, GroveDBProofV1, LayerProof, MerkOnlyLayerProof, + ProofBytes, + }; + use grovedb::{MerkProofDecoder, MerkProofOp}; + + fn label_path_segment(key: &[u8]) -> String { + // Path keys are mostly small ascii, but the contract-id + // bytes and the `[1]` doctype-table marker aren't — + // hex-encode anything non-printable. + if key.iter().all(|b| b.is_ascii_graphic() || *b == b' ') { + format!("\"{}\"", String::from_utf8_lossy(key)) + } else { + format!("0x{}", hex::encode(key)) + } + } + + fn print_ops(label: &str, depth: usize, merk_bytes: &[u8]) { + let indent = " ".repeat(depth); + println!( + "{}{} (merk_proof = {} bytes)", + indent, + label, + merk_bytes.len() + ); + for (i, op_res) in MerkProofDecoder::new(merk_bytes).enumerate() { + match op_res { + Ok(MerkProofOp::Push(n)) => println!("{} [{:>2}] Push({})", indent, i, n), + Ok(MerkProofOp::PushInverted(n)) => { + println!("{} [{:>2}] PushInverted({})", indent, i, n) + } + Ok(MerkProofOp::Parent) => println!("{} [{:>2}] Parent", indent, i), + Ok(MerkProofOp::Child) => println!("{} [{:>2}] Child", indent, i), + Ok(MerkProofOp::ParentInverted) => { + println!("{} [{:>2}] ParentInverted", indent, i) + } + Ok(MerkProofOp::ChildInverted) => { + println!("{} [{:>2}] ChildInverted", indent, i) + } + Err(e) => println!("{} [{:>2}] ", indent, i, e), + } + } + } + + fn walk_v0(layer: &MerkOnlyLayerProof, depth: usize, label: String) { + print_ops(&label, depth, &layer.merk_proof); + for (k, lower) in &layer.lower_layers { + walk_v0( + lower, + depth + 1, + format!( + "layer @ depth {} (path key {})", + depth + 1, + label_path_segment(k) + ), + ); + } + } + + fn walk_v1(layer: &LayerProof, depth: usize, label: String) { + let bytes = match &layer.merk_proof { + ProofBytes::Merk(b) => b.as_slice(), + _ => { + println!( + "{}{}: ", + " ".repeat(depth), + label + ); + return; + } + }; + print_ops(&label, depth, bytes); + for (k, lower) in &layer.lower_layers { + walk_v1( + lower, + depth + 1, + format!( + "layer @ depth {} (path key {})", + depth + 1, + label_path_segment(k) + ), + ); + } + } + + let config = bincode::config::standard() + .with_big_endian() + .with_limit::<{ 256 * 1024 * 1024 }>(); + let (envelope, _): (GroveDBProof, _) = + bincode::decode_from_slice(&proof_bytes, config).expect("envelope decodes"); + + println!("=== parking-lot aggregate-count proof ==="); + println!("inserted docs: 351 (1 + 2 + ... + 26)"); + println!("query: lot > \"b\""); + println!("verified count: {}", count); + println!("verified root hash: {}", hex::encode(root_hash)); + println!("envelope size: {} bytes", proof_bytes.len()); + + match envelope { + GroveDBProof::V0(GroveDBProofV0 { root_layer, .. }) => { + walk_v0(&root_layer, 0, "layer @ depth 0 (root)".to_string()) + } + GroveDBProof::V1(GroveDBProofV1 { root_layer }) => { + walk_v1(&root_layer, 0, "layer @ depth 0 (root)".to_string()) + } + } + println!("=== end proof ==="); + + assert_ne!(root_hash, [0u8; 32], "root hash should not be zero"); + assert_eq!( + count, expected, + "expected {} cars in parking lots > b (sum of 3+4+...+26)", + expected + ); + } + + /// Same parking-lot fixture as the prove-path scenario, but + /// asking the no-proof distinct-mode executor for *per-lot* + /// counts in the same range. Where the aggregate-count proof + /// returns one number (348 = total cars in lots > b), distinct + /// mode walks the property-name `ProvableCountTree` and emits + /// one entry per distinct in-range value: + /// `c=3, d=4, e=5, ..., z=26`. + /// + /// No-proof companion to the aggregate-count proof path: the + /// `AggregateCountOnRange` merk primitive returns a single u64, + /// so getting per-distinct-value counts requires the executor to + /// walk the children of the property-name tree directly. That + /// walk is cheaper than the materialize-and-count fallback (no + /// documents are loaded), but isn't cryptographically committed + /// by a single proof shape on the prove + non-distinct path — + /// see `book/src/drive/document-count-trees.md` for the + /// prove-vs-no-proof matrix. + /// + /// The fixture is identical to + /// `aggregate_count_proof_counts_cars_in_parking_lots_greater_than_b` + /// — duplicating the setup keeps each test independently + /// runnable rather than introducing a fragile shared-fixture + /// helper. + #[test] + fn range_count_executor_returns_per_lot_counts_for_lots_greater_than_b() { + use crate::query::{ + DriveDocumentCountQuery, RangeCountOptions, WhereClause, WhereOperator, + }; + use dpp::platform_value::Value; + + let drive = setup_drive_with_initial_state_structure(None); + let pv = PlatformVersion::latest(); + + let factory = dpp::data_contract::DataContractFactory::new(PROTOCOL_VERSION_V12) + .expect("expected to create factory"); + let document_schema = platform_value!({ + "type": "object", + "properties": { + "lot": { "type": "string", "position": 0, "maxLength": 4 }, + }, + "indices": [{ + "name": "byLot", + "properties": [{"lot": "asc"}], + "countable": "countable", + "rangeCountable": true, + }], + "additionalProperties": false, + }); + let schemas = platform_value!({ "car": document_schema }); + let contract = factory + .create_with_value_config(generate_random_identifier_struct(), 0, schemas, None, None) + .expect("create parking-lot contract") + .data_contract_owned(); + + drive + .apply_contract( + &contract, + BlockInfo::default(), + true, + StorageFlags::optional_default_as_cow(), + None, + pv, + ) + .expect("apply parking-lot contract"); + + let document_type = contract + .document_type_for_name("car") + .expect("car document type exists"); + + let mut seed = 1u64; + for (idx, letter) in ('a'..='z').enumerate() { + let car_count = idx + 1; + for _ in 0..car_count { + let mut doc = document_type + .random_document(Some(seed), pv) + .expect("random document"); + let mut props = std::collections::BTreeMap::new(); + props.insert("lot".to_string(), Value::Text(letter.to_string())); + doc.set_properties(props); + + drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentRefInfo((&doc, None)), + owner_id: None, + }, + contract: &contract, + document_type, + }, + false, + BlockInfo::default(), + true, + None, + pv, + None, + ) + .expect("expected to insert car document"); + seed += 1; + } + } + + // Range query: `lot > "b"` (same predicate as the prove + // test). Distinct mode → one entry per distinct in-range + // value, each carrying that lot's car count. + let where_clauses = vec![WhereClause { + field: "lot".to_string(), + operator: WhereOperator::GreaterThan, + value: Value::Text("b".to_string()), + }]; + let index = DriveDocumentCountQuery::find_range_countable_index_for_where_clauses( + document_type.indexes(), + &where_clauses, + ) + .expect("byLot range_countable index should be picked"); + + let query = DriveDocumentCountQuery { + document_type, + contract_id: contract.id().to_buffer(), + document_type_name: "car".to_string(), + index, + where_clauses, + }; + + let entries = query + .execute_range_count_no_proof( + &drive, + &RangeCountOptions { + distinct: true, + limit: None, + order_by_ascending: true, + }, + None, + pv, + ) + .expect("distinct-range count should succeed"); + + // 24 distinct lots in range (c through z). + assert_eq!( + entries.len(), + 24, + "expected one entry per lot from c through z" + ); + + // Each entry: lot letter (as serialized key bytes) → its + // alphabet-position car count. Ascending serialized-key + // order matches alphabetical order for ASCII single chars. + for (i, entry) in entries.iter().enumerate() { + let expected_letter = (b'c' + i as u8) as char; + let expected_count = (i + 3) as u64; // c → 3, d → 4, …, z → 26 + assert_eq!( + entry.key, + expected_letter.to_string().as_bytes().to_vec(), + "entry {} should be lot '{}'", + i, + expected_letter + ); + assert_eq!( + entry.count, expected_count, + "lot '{}' should have {} cars", + expected_letter, expected_count + ); + } + + // Sum-check: per-lot counts must total the prove-path + // aggregate (348). Different code path, same answer — the + // distinct walk and the merk-level aggregate are obligated + // to agree. + let total: u64 = entries.iter().map(|e| e.count).sum(); + assert_eq!( + total, 348, + "sum of per-lot counts must equal the aggregate (3+4+...+26 = 348)" + ); + } + + /// The trustless companion to the no-proof distinct test above: + /// same parking-lot fixture, same `lot > "b"` predicate, asking + /// for *per-lot* counts but this time via the prove path. Returns + /// a regular grovedb range proof against the property-name + /// `ProvableCountTree` — no `AggregateCountOnRange` wrapper. + /// merk's `to_kv_count_node` emits one `Node::KVCount(key, value, + /// count)` per matched in-range key, each `count` bound to the + /// merk root via `node_hash_with_count`, and we recover the + /// per-key map by walking the proof's op stream after the + /// standard hash-chain check passes. + /// + /// Pinned guarantees: + /// 1. Per-lot counts match the no-proof distinct walk exactly + /// (cross-checked against the `range_count_executor_returns + /// _per_lot_counts_for_lots_greater_than_b` expectations). + /// 2. The recovered counts sum to 348 — same answer the + /// aggregate prove path produces, just decomposed per-key. + /// All three code paths (no-proof distinct, prove aggregate, + /// prove distinct) are obligated to agree. + /// 3. The proof never materializes the underlying 348 documents. + /// Total proof bytes scale with O(distinct lots in range) + /// rather than O(matched docs), proving the + /// "doesn't-materialize-docs" win that distinguishes this + /// from the materialize-and-count fallback. + #[test] + fn distinct_count_proof_returns_per_lot_counts_for_lots_greater_than_b() { + use crate::query::{DriveDocumentCountQuery, WhereClause, WhereOperator}; + use dpp::platform_value::Value; + use grovedb::GroveDb; + + let drive = setup_drive_with_initial_state_structure(None); + let pv = PlatformVersion::latest(); + + let factory = dpp::data_contract::DataContractFactory::new(PROTOCOL_VERSION_V12) + .expect("expected to create factory"); + let document_schema = platform_value!({ + "type": "object", + "properties": { + "lot": { "type": "string", "position": 0, "maxLength": 4 }, + }, + "indices": [{ + "name": "byLot", + "properties": [{"lot": "asc"}], + "countable": "countable", + "rangeCountable": true, + }], + "additionalProperties": false, + }); + let schemas = platform_value!({ "car": document_schema }); + let contract = factory + .create_with_value_config(generate_random_identifier_struct(), 0, schemas, None, None) + .expect("create parking-lot contract") + .data_contract_owned(); + + drive + .apply_contract( + &contract, + BlockInfo::default(), + true, + StorageFlags::optional_default_as_cow(), + None, + pv, + ) + .expect("apply parking-lot contract"); + + let document_type = contract + .document_type_for_name("car") + .expect("car document type exists"); + + let mut seed = 1u64; + for (idx, letter) in ('a'..='z').enumerate() { + let car_count = idx + 1; + for _ in 0..car_count { + let mut doc = document_type + .random_document(Some(seed), pv) + .expect("random document"); + let mut props = std::collections::BTreeMap::new(); + props.insert("lot".to_string(), Value::Text(letter.to_string())); + doc.set_properties(props); + + drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentRefInfo((&doc, None)), + owner_id: None, + }, + contract: &contract, + document_type, + }, + false, + BlockInfo::default(), + true, + None, + pv, + None, + ) + .expect("expected to insert car document"); + seed += 1; + } + } + + let where_clauses = vec![WhereClause { + field: "lot".to_string(), + operator: WhereOperator::GreaterThan, + value: Value::Text("b".to_string()), + }]; + let index = DriveDocumentCountQuery::find_range_countable_index_for_where_clauses( + document_type.indexes(), + &where_clauses, + ) + .expect("byLot range_countable index should be picked"); + + let query = DriveDocumentCountQuery { + document_type, + contract_id: contract.id().to_buffer(), + document_type_name: "car".to_string(), + index, + where_clauses, + }; + + // Prove side: no `AggregateCountOnRange` wrapper. Use the + // shared `DEFAULT_QUERY_LIMIT` so the test exercises the + // same default the dispatcher would apply when a client + // omits `limit`. 24 distinct lots fit comfortably under + // 100 so all entries land in the proof. + const TEST_LIMIT: u16 = crate::config::DEFAULT_QUERY_LIMIT; + let proof_bytes = query + .execute_distinct_count_with_proof(&drive, TEST_LIMIT, true, None, pv) + .expect("should generate distinct count proof"); + assert!(!proof_bytes.is_empty(), "proof must not be empty"); + + // Verify side: standard verify_query gives us the integrity + // check + root_hash. The per-lot counts inside the proof are + // bound to root_hash via node_hash_with_count, so once this + // returns we just read each element's count. + let path_query = query + .distinct_count_path_query(Some(TEST_LIMIT), true, pv) + .expect("path query should build"); + + // Mirror the normal docs query's verify pattern: `verify_query` + // (strict succinctness, no absence-proof requirement) — see + // `DriveDocumentQuery::verify_proof_keep_serialized_v0`. The + // `verify_query_with_options` default has + // `absence_proofs_for_non_existing_searched_keys: true` which + // can't handle unbounded ranges like `lot > "b"`; this helper + // doesn't. + let (root_hash, _elements) = + GroveDb::verify_query(&proof_bytes, &path_query, &pv.drive.grove_version) + .expect("standard verify_query must succeed for the regular range proof shape"); + assert_ne!(root_hash, [0u8; 32], "root hash should not be zero"); + + // Walk the envelope down to the leaf merk and pluck per-lot + // counts. Mirrors verify_distinct_count_proof's extraction. + // At the property-name `ProvableCountTree` layer each child's + // value is a serialized `Element::CountTree(_, lot_count, _)` + // pointing to that lot's value-CountTree; we deserialize the + // value bytes and read `count_value_or_default()` for the per- + // lot count. The AVL-aggregate count carried by the + // `ProvableCountedMerkNode(_)` feature type is the *wrong* + // number — it includes left/right AVL-subtree contributions, + // not just this lot. + use grovedb::operations::proof::{ + GroveDBProof, GroveDBProofV0, GroveDBProofV1, ProofBytes, + }; + use grovedb::{Element, MerkProofDecoder, MerkProofNode, MerkProofOp}; + use std::collections::BTreeMap; + + let config = bincode::config::standard() + .with_big_endian() + .with_limit::<{ 256 * 1024 * 1024 }>(); + let (envelope, _): (GroveDBProof, _) = + bincode::decode_from_slice(&proof_bytes, config).expect("envelope decodes"); + + let mut counts: BTreeMap, u64> = BTreeMap::new(); + let target_depth = path_query.path.len(); + + let extract_per_lot = |merk_bytes: &[u8], counts: &mut BTreeMap, u64>| { + for op in MerkProofDecoder::new(merk_bytes) { + let (key, value) = + match op { + Ok(MerkProofOp::Push(MerkProofNode::KVValueHashFeatureType( + key, + value, + _, + _, + ))) => (key, value), + Ok(MerkProofOp::Push( + MerkProofNode::KVValueHashFeatureTypeWithChildHash(key, value, _, _, _), + )) => (key, value), + Ok(MerkProofOp::Push(MerkProofNode::KVCount(key, value, _))) => { + (key, value) + } + _ => continue, + }; + let elem = Element::deserialize(&value, &pv.drive.grove_version) + .expect("element value should deserialize"); + counts.insert(key, elem.count_value_or_default()); + } + }; + + match envelope { + GroveDBProof::V0(GroveDBProofV0 { root_layer, .. }) => { + let mut layer = &root_layer; + let mut depth = 0; + while depth < target_depth { + let next_key = &path_query.path[depth]; + layer = layer + .lower_layers + .get(next_key) + .expect("lower layer must exist for each path key"); + depth += 1; + } + extract_per_lot(&layer.merk_proof, &mut counts); + } + GroveDBProof::V1(GroveDBProofV1 { root_layer }) => { + let mut layer = &root_layer; + let mut depth = 0; + while depth < target_depth { + let next_key = &path_query.path[depth]; + layer = layer + .lower_layers + .get(next_key) + .expect("lower layer must exist for each path key"); + depth += 1; + } + let merk_bytes = match &layer.merk_proof { + ProofBytes::Merk(b) => b.as_slice(), + _ => panic!("unexpected non-merk leaf bytes for distinct-count proof"), + }; + extract_per_lot(merk_bytes, &mut counts); + } + } + + // Inline-print under `cargo test -- --nocapture`. Mirrors the + // aggregate test's print-decoded-proof block but for the + // distinct shape: matched children show up as + // `KVValueHashFeatureType[WithChildHash]` ops carrying the + // encoded `Element::CountTree(_, lot_count, _)` value plus + // the AVL-aggregate `ProvableCountedMerkNode(_)` feature + // count. Side-by-side comparison with the aggregate proof + // makes the size/shape trade-off visible. + fn label_path_segment(key: &[u8]) -> String { + if key.iter().all(|b| b.is_ascii_graphic() || *b == b' ') { + format!("\"{}\"", String::from_utf8_lossy(key)) + } else { + format!("0x{}", hex::encode(key)) + } + } + fn print_ops(label: &str, depth: usize, merk_bytes: &[u8]) { + let indent = " ".repeat(depth); + println!( + "{}{} (merk_proof = {} bytes)", + indent, + label, + merk_bytes.len() + ); + for (i, op_res) in MerkProofDecoder::new(merk_bytes).enumerate() { + match op_res { + Ok(MerkProofOp::Push(n)) => println!("{} [{:>2}] Push({})", indent, i, n), + Ok(MerkProofOp::PushInverted(n)) => { + println!("{} [{:>2}] PushInverted({})", indent, i, n) + } + Ok(MerkProofOp::Parent) => println!("{} [{:>2}] Parent", indent, i), + Ok(MerkProofOp::Child) => println!("{} [{:>2}] Child", indent, i), + Ok(MerkProofOp::ParentInverted) => { + println!("{} [{:>2}] ParentInverted", indent, i) + } + Ok(MerkProofOp::ChildInverted) => { + println!("{} [{:>2}] ChildInverted", indent, i) + } + Err(e) => println!("{} [{:>2}] ", indent, i, e), + } + } + } + fn walk_v0_print( + layer: &grovedb::operations::proof::MerkOnlyLayerProof, + depth: usize, + label: String, + ) { + print_ops(&label, depth, &layer.merk_proof); + for (k, lower) in &layer.lower_layers { + walk_v0_print( + lower, + depth + 1, + format!( + "layer @ depth {} (path key {})", + depth + 1, + label_path_segment(k) + ), + ); + } + } + fn walk_v1_print( + layer: &grovedb::operations::proof::LayerProof, + depth: usize, + label: String, + ) { + let bytes = match &layer.merk_proof { + ProofBytes::Merk(b) => b.as_slice(), + _ => { + println!( + "{}{}: ", + " ".repeat(depth), + label + ); + return; + } + }; + print_ops(&label, depth, bytes); + for (k, lower) in &layer.lower_layers { + walk_v1_print( + lower, + depth + 1, + format!( + "layer @ depth {} (path key {})", + depth + 1, + label_path_segment(k) + ), + ); + } + } + let (envelope_for_print, _): (GroveDBProof, _) = + bincode::decode_from_slice(&proof_bytes, config).expect("envelope decodes"); + + println!("=== parking-lot DISTINCT-count proof ==="); + println!("inserted docs: 351 (1 + 2 + ... + 26)"); + println!("query: lot > \"b\" (return_distinct_counts_in_range = true)"); + println!("verified per-lot count entries: {}", counts.len()); + println!("verified root hash: {}", hex::encode(root_hash)); + println!("envelope size: {} bytes", proof_bytes.len()); + match envelope_for_print { + GroveDBProof::V0(GroveDBProofV0 { root_layer, .. }) => { + walk_v0_print(&root_layer, 0, "layer @ depth 0 (root)".to_string()) + } + GroveDBProof::V1(GroveDBProofV1 { root_layer }) => { + walk_v1_print(&root_layer, 0, "layer @ depth 0 (root)".to_string()) + } + } + println!("=== end distinct proof ==="); + + // 24 distinct lots (c..=z) each with their alphabet-position + // count. Same expectation as the no-proof distinct test — the + // prove path is obligated to return the same numbers, just + // with cryptographic bounding on each. + assert_eq!( + counts.len(), + 24, + "expected one entry per lot from c through z, got {}", + counts.len() + ); + for (i, letter) in ('c'..='z').enumerate() { + let key = letter.to_string().into_bytes(); + let expected_count = (i + 3) as u64; + assert_eq!( + counts.get(&key).copied(), + Some(expected_count), + "lot '{}' should have {} cars", + letter, + expected_count + ); + } + + // Cross-path agreement: per-lot sum equals the aggregate + // proof's answer (348). Three code paths (no-proof distinct, + // prove aggregate, prove distinct) all obligated to agree. + let total: u64 = counts.values().sum(); + assert_eq!( + total, 348, + "sum of per-lot counts must equal aggregate (3+4+...+26 = 348)" + ); + } + + /// `RangeDistinctProof` honors the request's `limit` field — the + /// path query carries `SizedQuery::limit = Some(N)` so the + /// prover bounds the proof at `N` matched keys. With `limit = 5` + /// over the 24-distinct-lots-in-range parking-lot fixture, the + /// verified proof should cover exactly the first 5 lots in + /// ascending order: `c, d, e, f, g`. + /// + /// Pins two things at once: (1) the limit is plumbed end-to-end + /// through `execute_document_count_range_distinct_proof` → + /// `execute_distinct_count_with_proof` → + /// `distinct_count_path_query`, and (2) the prover and verifier + /// build the *exact same* `PathQuery` with that limit so the + /// merk-root recomputation matches. + #[test] + fn distinct_count_proof_honors_request_limit() { + use crate::query::{DriveDocumentCountQuery, WhereClause, WhereOperator}; + use dpp::platform_value::Value; + use grovedb::{Element, GroveDb}; + + let drive = setup_drive_with_initial_state_structure(None); + let pv = PlatformVersion::latest(); + let factory = + dpp::data_contract::DataContractFactory::new(PROTOCOL_VERSION_V12).expect("factory"); + let document_schema = platform_value!({ + "type": "object", + "properties": { "lot": { "type": "string", "position": 0, "maxLength": 4 } }, + "indices": [{ + "name": "byLot", + "properties": [{"lot": "asc"}], + "countable": "countable", + "rangeCountable": true, + }], + "additionalProperties": false, + }); + let schemas = platform_value!({ "car": document_schema }); + let contract = factory + .create_with_value_config(generate_random_identifier_struct(), 0, schemas, None, None) + .expect("create contract") + .data_contract_owned(); + drive + .apply_contract( + &contract, + BlockInfo::default(), + true, + StorageFlags::optional_default_as_cow(), + None, + pv, + ) + .expect("apply contract"); + let document_type = contract.document_type_for_name("car").expect("car doctype"); + + // 1 car per lot a..z = 26 docs; small fixture is fine since + // we're only testing the limit, not per-lot counts. + let mut seed = 1u64; + for letter in 'a'..='z' { + let mut doc = document_type + .random_document(Some(seed), pv) + .expect("random doc"); + let mut props = std::collections::BTreeMap::new(); + props.insert("lot".to_string(), Value::Text(letter.to_string())); + doc.set_properties(props); + drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentRefInfo((&doc, None)), + owner_id: None, + }, + contract: &contract, + document_type, + }, + false, + BlockInfo::default(), + true, + None, + pv, + None, + ) + .expect("insert"); + seed += 1; + } + + let where_clauses = vec![WhereClause { + field: "lot".to_string(), + operator: WhereOperator::GreaterThan, + value: Value::Text("b".to_string()), + }]; + let index = DriveDocumentCountQuery::find_range_countable_index_for_where_clauses( + document_type.indexes(), + &where_clauses, + ) + .expect("byLot picked"); + let query = DriveDocumentCountQuery { + document_type, + contract_id: contract.id().to_buffer(), + document_type_name: "car".to_string(), + index, + where_clauses, + }; + + const LIMIT: u16 = 5; + let proof_bytes = query + .execute_distinct_count_with_proof(&drive, LIMIT, true, None, pv) + .expect("proof"); + let path_query = query + .distinct_count_path_query(Some(LIMIT), true, pv) + .expect("path query"); + + let (root_hash, elements) = + GroveDb::verify_query(&proof_bytes, &path_query, &pv.drive.grove_version) + .expect("verify"); + assert_ne!(root_hash, [0u8; 32]); + + // Proof should cover exactly LIMIT entries — the first 5 in + // ascending key order: c, d, e, f, g. + let keys: Vec> = elements + .iter() + .filter_map(|(_p, k, e)| e.as_ref().map(|_| k.clone())) + .collect(); + assert_eq!( + keys.len(), + LIMIT as usize, + "proof should cover exactly {} matched keys, got {}", + LIMIT, + keys.len() + ); + assert_eq!( + keys, + vec![ + b"c".to_vec(), + b"d".to_vec(), + b"e".to_vec(), + b"f".to_vec(), + b"g".to_vec() + ], + "first {} matched keys in ascending order", + LIMIT + ); + + // Spot-check that we can still recover the per-lot count + // (everyone is 1 in this fixture). + for (_p, _k, elem) in elements { + let elem = elem.expect("matched element"); + assert_eq!( + elem.count_value_or_default(), + 1, + "each lot has exactly 1 doc in this fixture" + ); + // Suppress unused-import if nothing else uses Element. + let _: Element = elem; + } + } + + /// `order_by_ascending = false` on the prove-distinct path + /// flips grovedb's `Query.left_to_right` to `false`, so the + /// proof covers the last `limit` matched keys in descending + /// order instead of the first `limit` in ascending order. + /// + /// Same parking-lot fixture as + /// [`distinct_count_proof_honors_request_limit`] (one car per + /// letter `a..=z`, queried with `lot > "b"` so 24 lots are + /// in-range). With `LIMIT = 5` and descending iteration the + /// proof should cover `z, y, x, w, v` — pinning that: + /// (1) `left_to_right = false` propagates end-to-end through + /// `execute_document_count_range_distinct_proof` → + /// `execute_distinct_count_with_proof` → + /// `distinct_count_path_query`; + /// (2) the prover and verifier agree on the descending path + /// query so the merk-root recomputation matches; + /// (3) descending order under `limit` is semantically + /// correct — we get the LAST `limit` keys, not the first + /// `limit` keys reversed (which would be `c, d, e, f, g` + /// reversed, i.e. `g, f, e, d, c` — wrong). + #[test] + fn distinct_count_proof_descending_returns_last_limit_keys() { + use crate::query::{DriveDocumentCountQuery, WhereClause, WhereOperator}; + use dpp::platform_value::Value; + use grovedb::{Element, GroveDb}; + + let drive = setup_drive_with_initial_state_structure(None); + let pv = PlatformVersion::latest(); + let factory = + dpp::data_contract::DataContractFactory::new(PROTOCOL_VERSION_V12).expect("factory"); + let document_schema = platform_value!({ + "type": "object", + "properties": { "lot": { "type": "string", "position": 0, "maxLength": 4 } }, + "indices": [{ + "name": "byLot", + "properties": [{"lot": "asc"}], + "countable": "countable", + "rangeCountable": true, + }], + "additionalProperties": false, + }); + let schemas = platform_value!({ "car": document_schema }); + let contract = factory + .create_with_value_config(generate_random_identifier_struct(), 0, schemas, None, None) + .expect("create contract") + .data_contract_owned(); + drive + .apply_contract( + &contract, + BlockInfo::default(), + true, + StorageFlags::optional_default_as_cow(), + None, + pv, + ) + .expect("apply parking-lot contract"); + let document_type = contract.document_type_for_name("car").expect("car"); + + // One car per letter a..=z. + let mut seed = 1u64; + for letter in 'a'..='z' { + let mut doc = document_type + .random_document(Some(seed), pv) + .expect("random doc"); + let mut props = std::collections::BTreeMap::new(); + props.insert("lot".to_string(), Value::Text(letter.to_string())); + doc.set_properties(props); + drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentRefInfo((&doc, None)), + owner_id: None, + }, + contract: &contract, + document_type, + }, + false, + BlockInfo::default(), + true, + None, + pv, + None, + ) + .expect("insert"); + seed += 1; + } + + let where_clauses = vec![WhereClause { + field: "lot".to_string(), + operator: WhereOperator::GreaterThan, + value: Value::Text("b".to_string()), + }]; + let index = DriveDocumentCountQuery::find_range_countable_index_for_where_clauses( + document_type.indexes(), + &where_clauses, + ) + .expect("byLot picked"); + let query = DriveDocumentCountQuery { + document_type, + contract_id: contract.id().to_buffer(), + document_type_name: "car".to_string(), + index, + where_clauses, + }; + + const LIMIT: u16 = 5; + // left_to_right = false → descending. Both prove and verify + // sides MUST pass the same value or the merk-root chain + // check below fails. + let proof_bytes = query + .execute_distinct_count_with_proof(&drive, LIMIT, false, None, pv) + .expect("proof"); + let path_query = query + .distinct_count_path_query(Some(LIMIT), false, pv) + .expect("path query"); + + let (root_hash, elements) = + GroveDb::verify_query(&proof_bytes, &path_query, &pv.drive.grove_version) + .expect("descending path query must verify against the prover's proof"); + assert_ne!(root_hash, [0u8; 32]); + + // Proof should cover exactly LIMIT entries — the LAST 5 in + // descending key order: z, y, x, w, v. Critically, NOT the + // first 5 ascending reversed (that would be g, f, e, d, c). + let keys: Vec> = elements + .iter() + .filter_map(|(_p, k, e)| e.as_ref().map(|_| k.clone())) + .collect(); + assert_eq!( + keys.len(), + LIMIT as usize, + "proof should cover exactly {} matched keys, got {}", + LIMIT, + keys.len() + ); + assert_eq!( + keys, + vec![ + b"z".to_vec(), + b"y".to_vec(), + b"x".to_vec(), + b"w".to_vec(), + b"v".to_vec() + ], + "last {} matched keys in descending order", + LIMIT + ); + for (_p, _k, elem) in elements { + let elem = elem.expect("matched element"); + assert_eq!(elem.count_value_or_default(), 1); + let _: Element = elem; + } + } + + /// The dispatcher rejects `RangeDistinctProof` requests where + /// the effective limit exceeds `max_query_limit` rather than + /// silently clamping. Silent clamping would invisibly break + /// client-side proof reconstruction (the SDK builds its + /// `PathQuery` from `request.limit`, not from a server-clamped + /// value the SDK never sees), so the policy is to fail loudly. + #[test] + fn distinct_count_proof_rejects_limit_above_max_query_limit() { + use crate::query::{DocumentCountRequest, DocumentCountResponse, DriveDocumentCountQuery}; + use dpp::platform_value::Value; + + let drive = setup_drive_with_initial_state_structure(None); + let pv = PlatformVersion::latest(); + let factory = + dpp::data_contract::DataContractFactory::new(PROTOCOL_VERSION_V12).expect("factory"); + let document_schema = platform_value!({ + "type": "object", + "properties": { "lot": { "type": "string", "position": 0, "maxLength": 4 } }, + "indices": [{ + "name": "byLot", + "properties": [{"lot": "asc"}], + "countable": "countable", + "rangeCountable": true, + }], + "additionalProperties": false, + }); + let schemas = platform_value!({ "car": document_schema }); + let contract = factory + .create_with_value_config(generate_random_identifier_struct(), 0, schemas, None, None) + .expect("create contract") + .data_contract_owned(); + drive + .apply_contract( + &contract, + BlockInfo::default(), + true, + StorageFlags::optional_default_as_cow(), + None, + pv, + ) + .expect("apply contract"); + let document_type = contract.document_type_for_name("car").expect("car doctype"); + + // Build a where-clause `Value::Array` of one range clause: + // [["lot", ">", "b"]]. Mirrors the wire shape the abci + // handler hands to drive after CBOR-decoding. + let where_clause_value = Value::Array(vec![Value::Array(vec![ + Value::Text("lot".to_string()), + Value::Text(">".to_string()), + Value::Text("b".to_string()), + ])]); + + let drive_config = crate::config::DriveConfig::default(); + let too_large = drive_config.max_query_limit as u32 + 1; + + let request = DocumentCountRequest { + contract: &contract, + document_type, + raw_where_value: where_clause_value, + raw_order_by_value: dpp::platform_value::Value::Null, + return_distinct_counts_in_range: true, + limit: Some(too_large), + prove: true, + drive_config: &drive_config, + }; + let result = drive.execute_document_count_request(request, None, pv); + + match &result { + Err(crate::error::Error::Query( + crate::error::query::QuerySyntaxError::InvalidLimit(msg), + )) => assert!( + msg.contains("exceeds max_query_limit"), + "expected message about exceeding max_query_limit, got: {}", + msg + ), + Ok(DocumentCountResponse::Aggregate(_)) => { + panic!("expected rejection, got Aggregate") + } + Ok(DocumentCountResponse::Entries(_)) => panic!("expected rejection, got Entries"), + Ok(DocumentCountResponse::Proof(_)) => panic!("expected rejection, got Proof"), + Err(e) => panic!("expected InvalidLimit, got different error: {:?}", e), + } + // Silence unused-import for `DriveDocumentCountQuery` — + // referenced as a type for `PhantomData` only. + let _ = std::marker::PhantomData::; + } + + /// The prove-distinct path supports `In` on prefix via grovedb's + /// native subquery primitive: outer `Query` has one `Key(...)` + /// per In value at the In-bearing prop's property-name subtree, + /// `set_subquery_path` carries any post-In Equal pairs + + /// terminator name, `set_subquery` is the range item. The + /// resulting proof emits per-(brand, color) elements which the + /// verifier reads as-is. The server intentionally does NOT merge + /// across forks here, because `limit` pushed into the prover's + /// path query is applied per-fork: merging post-limit would let + /// one fork's surviving entries collide with another fork's + /// dropped entries on the same `key` and silently undercount. + /// Callers that want the flat-histogram view reduce by `key` + /// client-side via [`DocumentSplitCounts::into_flat_map`]. + /// + /// Mirrors the no-proof + /// `range_count_with_in_on_prefix_returns_per_brand_color_entries` + /// test — same fixture (3 acme+red, 2 acme+blue, 2 contoso+red, + /// 1 contoso+green), same predicate (`brand IN (acme, contoso) + /// AND color > "blue"`), same expected per-(brand, color) + /// entries. Pins that both code paths agree on the unmerged + /// compound shape. + #[test] + fn distinct_count_proof_with_in_on_prefix_returns_per_brand_color_entries() { + use crate::query::{DriveDocumentCountQuery, WhereClause, WhereOperator}; + use dpp::platform_value::Value; + use grovedb::{Element, GroveDb}; + + let drive = setup_drive_with_initial_state_structure(None); + let pv = PlatformVersion::latest(); + + let factory = + dpp::data_contract::DataContractFactory::new(PROTOCOL_VERSION_V12).expect("factory"); + let document_schema = platform_value!({ + "type": "object", + "properties": { + "brand": { "type": "string", "position": 0, "maxLength": 32 }, + "color": { "type": "string", "position": 1, "maxLength": 32 }, + }, + "indices": [{ + "name": "byBrandColor", + "properties": [{"brand": "asc"}, {"color": "asc"}], + "countable": "countable", + "rangeCountable": true, + }], + "additionalProperties": false, + }); + let schemas = platform_value!({ "widget": document_schema }); + let contract = factory + .create_with_value_config(generate_random_identifier_struct(), 0, schemas, None, None) + .expect("create contract") + .data_contract_owned(); + drive + .apply_contract( + &contract, + BlockInfo::default(), + true, + StorageFlags::optional_default_as_cow(), + None, + pv, + ) + .expect("apply contract"); + let document_type = contract + .document_type_for_name("widget") + .expect("widget exists"); + + // Same fixture as the no-proof counterpart. + let docs: Vec<(&str, &str)> = vec![ + ("acme", "red"), + ("acme", "red"), + ("acme", "red"), + ("acme", "blue"), + ("acme", "blue"), + ("contoso", "red"), + ("contoso", "red"), + ("contoso", "green"), + ]; + for (i, (brand, color)) in docs.iter().enumerate() { + let mut doc = document_type + .random_document(Some((i + 1) as u64), pv) + .expect("random doc"); + let mut props = std::collections::BTreeMap::new(); + props.insert("brand".to_string(), Value::Text(brand.to_string())); + props.insert("color".to_string(), Value::Text(color.to_string())); + doc.set_properties(props); + drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentRefInfo((&doc, None)), + owner_id: None, + }, + contract: &contract, + document_type, + }, + false, + BlockInfo::default(), + true, + None, + pv, + None, + ) + .expect("insert"); + } + + let where_clauses = vec![ + WhereClause { + field: "brand".to_string(), + operator: WhereOperator::In, + value: Value::Array(vec![ + Value::Text("acme".to_string()), + Value::Text("contoso".to_string()), + ]), + }, + WhereClause { + field: "color".to_string(), + operator: WhereOperator::GreaterThan, + value: Value::Text("blue".to_string()), + }, + ]; + let index = DriveDocumentCountQuery::find_range_countable_index_for_where_clauses( + document_type.indexes(), + &where_clauses, + ) + .expect("byBrandColor picked"); + let query = DriveDocumentCountQuery { + document_type, + contract_id: contract.id().to_buffer(), + document_type_name: "widget".to_string(), + index, + where_clauses, + }; + + const LIMIT: u16 = 100; + let proof_bytes = query + .execute_distinct_count_with_proof(&drive, LIMIT, true, None, pv) + .expect("proof"); + assert!(!proof_bytes.is_empty(), "proof must not be empty"); + + let path_query = query + .distinct_count_path_query(Some(LIMIT), true, pv) + .expect("path query"); + + // `lot > "blue"` is one-sided — disable absence proofs + // (same reason as the other distinct-prove tests). + let verify_options = grovedb::VerifyOptions { + absence_proofs_for_non_existing_searched_keys: false, + ..grovedb::VerifyOptions::default() + }; + let (root_hash, elements) = GroveDb::verify_query_with_options( + &proof_bytes, + &path_query, + verify_options, + &pv.drive.grove_version, + ) + .expect("verify"); + assert_ne!(root_hash, [0u8; 32]); + + // Walk the verified `(path, key, element)` triples and + // collect per-(brand, color) entries — mirrors what + // `verify_distinct_count_proof` does. We do NOT sum across + // brand forks here; the unmerged shape is what the verifier + // returns. + let base_path_len = path_query.path.len(); + let mut per_pair: std::collections::BTreeMap<(Vec, Vec), u64> = + std::collections::BTreeMap::new(); + for (path, key, elem) in elements { + if let Some(e) = elem { + let _: Element = e.clone(); + let count = e.count_value_or_default(); + if count == 0 { + continue; + } + let in_key = if path.len() > base_path_len { + path[base_path_len].clone() + } else { + Vec::new() + }; + *per_pair.entry((in_key, key)).or_insert(0) += count; + } + } + + // Expected unmerged: + // (acme, red) → 3 + // (contoso, green) → 1 + // (contoso, red) → 2 + // blue excluded by `> blue`. + assert_eq!( + per_pair.len(), + 3, + "expected three (brand, color) pairs in the verified proof" + ); + assert_eq!(per_pair.get(&(b"acme".to_vec(), b"red".to_vec())), Some(&3)); + assert_eq!( + per_pair.get(&(b"contoso".to_vec(), b"green".to_vec())), + Some(&1) + ); + assert_eq!( + per_pair.get(&(b"contoso".to_vec(), b"red".to_vec())), + Some(&2) + ); + + // Cross-path agreement (client-side merge): sum across + // brand forks per color matches what callers reducing by + // `key` would see. Sum of all per-(brand, color) counts + // matches the sum-mode no-proof answer (6 docs). + let mut per_color: std::collections::BTreeMap, u64> = + std::collections::BTreeMap::new(); + for ((_, color), count) in &per_pair { + *per_color.entry(color.clone()).or_insert(0) += count; + } + assert_eq!(per_color.get(b"red".as_slice()), Some(&5)); + assert_eq!(per_color.get(b"green".as_slice()), Some(&1)); + let total: u64 = per_pair.values().sum(); + assert_eq!(total, 6); + } +} diff --git a/packages/rs-drive/src/drive/document/delete/remove_indices_for_index_level_for_contract_operations/mod.rs b/packages/rs-drive/src/drive/document/delete/remove_indices_for_index_level_for_contract_operations/mod.rs index 7ce1ad04227..cf5d4fb4ba5 100644 --- a/packages/rs-drive/src/drive/document/delete/remove_indices_for_index_level_for_contract_operations/mod.rs +++ b/packages/rs-drive/src/drive/document/delete/remove_indices_for_index_level_for_contract_operations/mod.rs @@ -41,6 +41,7 @@ impl Drive { index_level: &IndexLevel, any_fields_null: bool, all_fields_null: bool, + parent_value_tree_is_range_countable: bool, storage_flags: &Option<&StorageFlags>, previous_batch_operations: &Option<&mut Vec>, estimated_costs_only_with_layer_info: &mut Option< @@ -64,6 +65,7 @@ impl Drive { index_level, any_fields_null, all_fields_null, + parent_value_tree_is_range_countable, storage_flags, previous_batch_operations, estimated_costs_only_with_layer_info, diff --git a/packages/rs-drive/src/drive/document/delete/remove_indices_for_index_level_for_contract_operations/v0/mod.rs b/packages/rs-drive/src/drive/document/delete/remove_indices_for_index_level_for_contract_operations/v0/mod.rs index f92a34005d3..9da9dae15cf 100644 --- a/packages/rs-drive/src/drive/document/delete/remove_indices_for_index_level_for_contract_operations/v0/mod.rs +++ b/packages/rs-drive/src/drive/document/delete/remove_indices_for_index_level_for_contract_operations/v0/mod.rs @@ -26,6 +26,13 @@ use dpp::version::PlatformVersion; impl Drive { /// Removes indices for an index level and recurses. + /// + /// `parent_value_tree_is_range_countable` mirrors the insert walker — + /// it tells us whether the value tree at `index_path_info` was stored + /// as a `CountTree` (because the IndexLevel that produced it terminates + /// a `range_countable` index). Cost estimation uses this to report the + /// correct tree variant for the layer being walked, so storage-cost + /// math matches what's actually on disk. #[inline] #[allow(clippy::too_many_arguments)] pub(super) fn remove_indices_for_index_level_for_contract_operations_v0( @@ -35,6 +42,7 @@ impl Drive { index_level: &IndexLevel, mut any_fields_null: bool, mut all_fields_null: bool, + parent_value_tree_is_range_countable: bool, storage_flags: &Option<&StorageFlags>, previous_batch_operations: &Option<&mut Vec>, estimated_costs_only_with_layer_info: &mut Option< @@ -47,12 +55,18 @@ impl Drive { ) -> Result<(), Error> { let sub_level_index_count = index_level.sub_levels().len() as u32; + let current_layer_tree_type = if parent_value_tree_is_range_countable { + TreeType::CountTree + } else { + TreeType::NormalTree + }; + 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: TreeType::NormalTree, + tree_type: current_layer_tree_type, estimated_layer_count: ApproximateElements(sub_level_index_count + 1), estimated_layer_sizes: AllSubtrees( DEFAULT_HASH_SIZE_U8, @@ -84,6 +98,16 @@ impl Drive { // fourth we need to store a reference to the document for each index for (name, sub_level) in index_level.sub_levels() { + let sub_level_range_countable = sub_level + .has_index_with_type() + .map(|info| info.range_countable) + .unwrap_or(false); + let property_name_tree_type = if sub_level_range_countable { + TreeType::ProvableCountTree + } else { + TreeType::NormalTree + }; + let mut sub_level_index_path_info = index_path_info.clone(); let index_property_key = KeyRef(name.as_bytes()); @@ -117,7 +141,7 @@ impl Drive { estimated_costs_only_with_layer_info.insert( sub_level_index_path_info.clone().convert_to_key_info_path(), EstimatedLayerInformation { - tree_type: TreeType::NormalTree, + tree_type: property_name_tree_type, estimated_layer_count: PotentiallyAtMaxElements, estimated_layer_sizes: AllSubtrees( document_top_field_estimated_size as u8, @@ -144,6 +168,7 @@ impl Drive { sub_level, any_fields_null, all_fields_null, + sub_level_range_countable, storage_flags, previous_batch_operations, estimated_costs_only_with_layer_info, diff --git a/packages/rs-drive/src/drive/document/delete/remove_indices_for_top_index_level_for_contract_operations/v0/mod.rs b/packages/rs-drive/src/drive/document/delete/remove_indices_for_top_index_level_for_contract_operations/v0/mod.rs index 050982c266f..dd8ee567328 100644 --- a/packages/rs-drive/src/drive/document/delete/remove_indices_for_top_index_level_for_contract_operations/v0/mod.rs +++ b/packages/rs-drive/src/drive/document/delete/remove_indices_for_top_index_level_for_contract_operations/v0/mod.rs @@ -82,6 +82,16 @@ impl Drive { // next we need to store a reference to the document for each index for (name, sub_level) in index_level.sub_levels() { + let sub_level_range_countable = sub_level + .has_index_with_type() + .map(|info| info.range_countable) + .unwrap_or(false); + let property_name_tree_type = if sub_level_range_countable { + TreeType::ProvableCountTree + } else { + TreeType::NormalTree + }; + // 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 @@ -119,7 +129,7 @@ impl Drive { estimated_costs_only_with_layer_info.insert( KeyInfoPath::from_known_owned_path(index_path.clone()), EstimatedLayerInformation { - tree_type: TreeType::NormalTree, + tree_type: property_name_tree_type, estimated_layer_count: PotentiallyAtMaxElements, estimated_layer_sizes: AllSubtrees( document_top_field_estimated_size as u8, @@ -154,6 +164,7 @@ impl Drive { sub_level, any_fields_null, all_fields_null, + sub_level_range_countable, &storage_flags, previous_batch_operations, estimated_costs_only_with_layer_info, diff --git a/packages/rs-drive/src/drive/document/insert/add_indices_for_index_level_for_contract_operations/mod.rs b/packages/rs-drive/src/drive/document/insert/add_indices_for_index_level_for_contract_operations/mod.rs index 1de0a643320..f991021d422 100644 --- a/packages/rs-drive/src/drive/document/insert/add_indices_for_index_level_for_contract_operations/mod.rs +++ b/packages/rs-drive/src/drive/document/insert/add_indices_for_index_level_for_contract_operations/mod.rs @@ -18,6 +18,10 @@ use std::collections::HashMap; impl Drive { /// Adds indices for an index level and recurses. + /// + /// `parent_value_tree_is_range_countable` reflects whether the value + /// tree at `index_path_info` is a `CountTree`. See the v0 doc for why + /// this matters for `Element::NonCounted` wrapping. #[allow(clippy::too_many_arguments)] pub(crate) fn add_indices_for_index_level_for_contract_operations( &self, @@ -26,6 +30,7 @@ impl Drive { index_level: &IndexLevel, any_fields_null: bool, all_fields_null: bool, + parent_value_tree_is_range_countable: bool, previous_batch_operations: &mut Option<&mut Vec>, storage_flags: &Option<&StorageFlags>, estimated_costs_only_with_layer_info: &mut Option< @@ -49,6 +54,7 @@ impl Drive { index_level, any_fields_null, all_fields_null, + parent_value_tree_is_range_countable, previous_batch_operations, storage_flags, estimated_costs_only_with_layer_info, diff --git a/packages/rs-drive/src/drive/document/insert/add_indices_for_index_level_for_contract_operations/v0/mod.rs b/packages/rs-drive/src/drive/document/insert/add_indices_for_index_level_for_contract_operations/v0/mod.rs index 94662fd923a..32325bccaca 100644 --- a/packages/rs-drive/src/drive/document/insert/add_indices_for_index_level_for_contract_operations/v0/mod.rs +++ b/packages/rs-drive/src/drive/document/insert/add_indices_for_index_level_for_contract_operations/v0/mod.rs @@ -19,6 +19,17 @@ use std::collections::HashMap; impl Drive { /// Adds indices for an index level and recurses. + /// + /// `parent_value_tree_is_range_countable` reflects whether the value tree + /// at `index_path_info` is a `CountTree` (because the IndexLevel that + /// produced it is a range-countable terminator). When true, every + /// continuation property-name tree we insert here as a child of that + /// `CountTree` is wrapped with `Element::NonCounted` so its storage + /// stays addressable but it contributes 0 to the parent count's + /// aggregate. Without this, compound continuations would each add 1 (a + /// `NormalTree` child) — or worse, their own count_value (a + /// `ProvableCountTree` child in nested-range_countable layouts) — and + /// double-count documents. #[inline] #[allow(clippy::too_many_arguments)] pub(super) fn add_indices_for_index_level_for_contract_operations_v0( @@ -28,6 +39,7 @@ impl Drive { index_level: &IndexLevel, mut any_fields_null: bool, mut all_fields_null: bool, + parent_value_tree_is_range_countable: bool, previous_batch_operations: &mut Option<&mut Vec>, storage_flags: &Option<&StorageFlags>, estimated_costs_only_with_layer_info: &mut Option< @@ -58,12 +70,21 @@ impl Drive { let sub_level_index_count = index_level.sub_levels().len() as u32; + // The current level (the value tree at index_path_info) is a CountTree + // when `parent_value_tree_is_range_countable`; otherwise NormalTree. + // This shows up in the layer info for the layer we're walking through. + let current_layer_tree_type = if parent_value_tree_is_range_countable { + TreeType::CountTree + } else { + TreeType::NormalTree + }; + 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: TreeType::NormalTree, + tree_type: current_layer_tree_type, estimated_layer_count: ApproximateElements(sub_level_index_count + 1), estimated_layer_sizes: AllSubtrees( DEFAULT_HASH_SIZE_U8, @@ -74,20 +95,65 @@ impl Drive { ); } - let apply_type = if estimated_costs_only_with_layer_info.is_none() { - BatchInsertTreeApplyType::StatefulBatchInsertTree - } else { - BatchInsertTreeApplyType::StatelessBatchInsertTree { - in_tree_type: TreeType::NormalTree, - tree_type: TreeType::NormalTree, - flags_len: storage_flags - .map(|s| s.serialized_size()) - .unwrap_or_default(), - } - }; - // fourth we need to store a reference to the document for each index for (name, sub_level) in index_level.sub_levels() { + let sub_level_range_countable = sub_level + .has_index_with_type() + .map(|info| info.range_countable) + .unwrap_or(false); + + // The property-name tree below the current value tree. If the + // index sub_level is a range_countable terminator we need a + // `ProvableCountTree` so range queries over the property's + // distinct values can use grovedb's `AggregateCountOnRange`. + let property_name_tree_type = if sub_level_range_countable { + TreeType::ProvableCountTree + } else { + TreeType::NormalTree + }; + + // The value tree (one per distinct property value, hosting the + // `[0]` reference subtree + sibling continuations) becomes a + // `CountTree` when its sub_level is range_countable, so the + // parent property-name `ProvableCountTree`'s aggregate sums + // per-value counts cleanly. + let value_tree_type = if sub_level_range_countable { + TreeType::CountTree + } else { + TreeType::NormalTree + }; + + // Wrap the property-name tree with `Element::NonCounted` iff its + // immediate parent (the value tree at `index_path_info`) is a + // CountTree. NonCounted-wrapping is independent of + // `property_name_tree_type` — it only affects the *parent's* + // count aggregation, not the wrapped element's internals. + let wrap_property_name_tree_non_counted = parent_value_tree_is_range_countable; + + let property_name_apply_type = if estimated_costs_only_with_layer_info.is_none() { + BatchInsertTreeApplyType::StatefulBatchInsertTree + } else { + BatchInsertTreeApplyType::StatelessBatchInsertTree { + in_tree_type: current_layer_tree_type, + tree_type: property_name_tree_type, + flags_len: storage_flags + .map(|s| s.serialized_size()) + .unwrap_or_default(), + } + }; + + let value_apply_type = if estimated_costs_only_with_layer_info.is_none() { + BatchInsertTreeApplyType::StatefulBatchInsertTree + } else { + BatchInsertTreeApplyType::StatelessBatchInsertTree { + in_tree_type: property_name_tree_type, + tree_type: value_tree_type, + flags_len: storage_flags + .map(|s| s.serialized_size()) + .unwrap_or_default(), + } + }; + let mut sub_level_index_path_info = index_path_info.clone(); let index_property_key = KeyRef(name.as_bytes()); @@ -108,16 +174,29 @@ impl Drive { .add_path_info(sub_level_index_path_info.clone()); // here we are inserting an empty tree that will have a subtree of all other index properties - self.batch_insert_empty_tree_if_not_exists( - path_key_info.clone(), - TreeType::NormalTree, - *storage_flags, - apply_type, - transaction, - previous_batch_operations, - batch_operations, - &platform_version.drive, - )?; + if wrap_property_name_tree_non_counted { + self.batch_insert_empty_non_counted_tree_if_not_exists( + path_key_info.clone(), + property_name_tree_type, + *storage_flags, + property_name_apply_type, + transaction, + previous_batch_operations, + batch_operations, + &platform_version.drive, + )?; + } else { + self.batch_insert_empty_tree_if_not_exists( + path_key_info.clone(), + property_name_tree_type, + *storage_flags, + property_name_apply_type, + transaction, + previous_batch_operations, + batch_operations, + &platform_version.drive, + )?; + } sub_level_index_path_info.push(index_property_key)?; @@ -137,7 +216,7 @@ impl Drive { estimated_costs_only_with_layer_info.insert( sub_level_index_path_info.clone().convert_to_key_info_path(), EstimatedLayerInformation { - tree_type: TreeType::NormalTree, + tree_type: property_name_tree_type, estimated_layer_count: PotentiallyAtMaxElements, estimated_layer_sizes: AllSubtrees( document_top_field_estimated_size as u8, @@ -155,12 +234,12 @@ impl Drive { .clone() .add_path_info(sub_level_index_path_info.clone()); - // here we are inserting an empty tree that will have a subtree of all other index properties + // here we are inserting the value tree self.batch_insert_empty_tree_if_not_exists( path_key_info.clone(), - TreeType::NormalTree, + value_tree_type, *storage_flags, - apply_type, + value_apply_type, transaction, previous_batch_operations, batch_operations, @@ -180,6 +259,7 @@ impl Drive { sub_level, any_fields_null, all_fields_null, + sub_level_range_countable, previous_batch_operations, storage_flags, estimated_costs_only_with_layer_info, diff --git a/packages/rs-drive/src/drive/document/insert/add_indices_for_top_index_level_for_contract_operations/v0/mod.rs b/packages/rs-drive/src/drive/document/insert/add_indices_for_top_index_level_for_contract_operations/v0/mod.rs index e7d56f81d7e..2e03e90b3d0 100644 --- a/packages/rs-drive/src/drive/document/insert/add_indices_for_top_index_level_for_contract_operations/v0/mod.rs +++ b/packages/rs-drive/src/drive/document/insert/add_indices_for_top_index_level_for_contract_operations/v0/mod.rs @@ -81,20 +81,34 @@ impl Drive { ); } - let apply_type = if estimated_costs_only_with_layer_info.is_none() { - BatchInsertTreeApplyType::StatefulBatchInsertTree - } else { - BatchInsertTreeApplyType::StatelessBatchInsertTree { - in_tree_type: TreeType::NormalTree, - tree_type: TreeType::NormalTree, - flags_len: storage_flags - .map(|s| s.serialized_size()) - .unwrap_or_default(), - } - }; + // The per-iteration `value_apply_type` (built below) selects + // `in_tree_type` / `tree_type` based on each index sub-level's + // range_countable flag — see the block inside the loop. We don't + // share a single `apply_type` here anymore because the top-level + // property-name tree variant is data-driven. // next we need to store a reference to the document for each index for (name, sub_level) in index_level.sub_levels() { + // If `sub_level` terminates a `range_countable` index, the + // top-level property-name tree (created at contract setup) is a + // `ProvableCountTree` and each value tree under it must be a + // `CountTree` so the parent's aggregate sums per-value counts + // cleanly. Otherwise both stay `NormalTree`. + let sub_level_range_countable = sub_level + .has_index_with_type() + .map(|info| info.range_countable) + .unwrap_or(false); + let property_name_tree_type = if sub_level_range_countable { + TreeType::ProvableCountTree + } else { + TreeType::NormalTree + }; + let value_tree_type = if sub_level_range_countable { + TreeType::CountTree + } else { + TreeType::NormalTree + }; + // 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 @@ -117,12 +131,26 @@ impl Drive { // The zero will not matter here, because the PathKeyInfo is variable let path_key_info = document_top_field.clone().add_path::<0>(index_path.clone()); - // here we are inserting an empty tree that will have a subtree of all other index properties + // here we are inserting the value tree (per distinct property value) + // under the top-level property-name tree. The top-level property-name + // tree itself is created at contract setup, so the apply_type's + // `in_tree_type` reflects whichever variant the contract setup used. + let value_apply_type = if estimated_costs_only_with_layer_info.is_none() { + BatchInsertTreeApplyType::StatefulBatchInsertTree + } else { + BatchInsertTreeApplyType::StatelessBatchInsertTree { + in_tree_type: property_name_tree_type, + tree_type: value_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.clone(), - TreeType::NormalTree, + value_tree_type, storage_flags, - apply_type, + value_apply_type, transaction, previous_batch_operations, batch_operations, @@ -146,7 +174,7 @@ impl Drive { estimated_costs_only_with_layer_info.insert( KeyInfoPath::from_known_owned_path(index_path.clone()), EstimatedLayerInformation { - tree_type: TreeType::NormalTree, + tree_type: property_name_tree_type, estimated_layer_count: PotentiallyAtMaxElements, estimated_layer_sizes: AllSubtrees( document_top_field_estimated_size as u8, @@ -181,6 +209,7 @@ impl Drive { sub_level, any_fields_null, all_fields_null, + sub_level_range_countable, previous_batch_operations, &storage_flags, estimated_costs_only_with_layer_info, diff --git a/packages/rs-drive/src/fees/op.rs b/packages/rs-drive/src/fees/op.rs index ebcaf8844c9..55b46bb9684 100644 --- a/packages/rs-drive/src/fees/op.rs +++ b/packages/rs-drive/src/fees/op.rs @@ -443,6 +443,69 @@ impl LowLevelDriveOperation { LowLevelDriveOperation::insert_for_known_path_key_element(path, key, tree) } + /// Sets `GroveOperation` for inserting an empty `NormalTree` wrapped in + /// `Element::NonCounted` at the given path and key. The wrapper makes + /// the inserted subtree contribute 0 to a parent count tree's aggregate + /// (per grovedb #654). Used by the index-walker for sibling continuations + /// inside a `range_countable` value tree, so e.g. a compound `byColorShape` + /// continuation under a `byColor` value tree (which is a `CountTree`) + /// doesn't pollute the byColor count. + pub fn for_known_path_key_empty_non_counted_normal_tree( + path: Vec>, + key: Vec, + storage_flags: Option<&StorageFlags>, + ) -> Self { + Self::for_known_path_key_empty_non_counted_tree( + path, + key, + TreeType::NormalTree, + storage_flags, + ) + .expect("NormalTree NonCounted wrapping never fails") + } + + /// Sets `GroveOperation` for inserting an empty tree of the given + /// `tree_type` wrapped in `Element::NonCounted`. The wrapper makes the + /// inserted subtree contribute 0 to a parent count tree's aggregate + /// count (per grovedb #654), regardless of the inner tree variant. + /// + /// Used by the index walker for sibling continuations inside a + /// `range_countable` value tree (a `CountTree`). Most continuations are + /// plain `NormalTree`, but in nested-`range_countable` cases (e.g. an + /// index `[color]` is range-countable AND a deeper compound index + /// `[color, size]` is also range-countable), the continuation + /// property-name tree at `"size"` is itself a `ProvableCountTree` and + /// must still contribute 0 to the parent `` `CountTree`. + /// + /// Returns an error for tree variants whose `NonCounted` wrapping + /// hasn't been validated end-to-end yet (currently anything outside + /// `NormalTree` / `CountTree` / `ProvableCountTree`). + pub fn for_known_path_key_empty_non_counted_tree( + path: Vec>, + key: Vec, + tree_type: TreeType, + storage_flags: Option<&StorageFlags>, + ) -> Result { + let element_flags = storage_flags.map(|s| s.to_element_flags()); + let inner = match tree_type { + TreeType::NormalTree => Element::empty_tree_with_flags(element_flags), + TreeType::CountTree => Element::empty_count_tree_with_flags(element_flags), + TreeType::ProvableCountTree => { + Element::empty_provable_count_tree_with_flags(element_flags) + } + _ => { + return Err(Error::Drive(DriveError::NotSupported( + "NonCounted-wrapping is only supported for NormalTree, CountTree, and ProvableCountTree", + ))); + } + }; + let tree = Element::new_non_counted(inner) + .expect("new_non_counted only fails when wrapping another NonCounted"); + Ok(LowLevelDriveOperation::insert_for_known_path_key_element( + path, key, tree, + )) + } + /// Sets `GroveOperation` for inserting an empty provable count tree at the given path and key pub fn for_known_path_key_empty_provable_count_tree( path: Vec>, diff --git a/packages/rs-drive/src/query/drive_document_count_query/drive_dispatcher.rs b/packages/rs-drive/src/query/drive_document_count_query/drive_dispatcher.rs new file mode 100644 index 00000000000..a558eaa6be7 --- /dev/null +++ b/packages/rs-drive/src/query/drive_document_count_query/drive_dispatcher.rs @@ -0,0 +1,893 @@ +//! Drive-level dispatcher for the unified `GetDocumentsCount` request. +//! +//! Two layers live here: +//! +//! 1. **Per-mode `impl Drive` executors** — `execute_document_count_*` +//! methods that pick a covering index for their specific mode and +//! run the matching `DriveDocumentCountQuery::*` executor. Each +//! one collapses index-picking + executor invocation into a single +//! call so the dispatcher's match arms stay one line per mode. +//! +//! 2. **Top-level `execute_document_count_request`** that owns the +//! whole pipeline: mode detection → per-mode executor → response +//! wrapping. The drive-abci handler just builds a +//! [`DocumentCountRequest`] and calls this; everything past CBOR +//! decode + contract lookup lives in drive. +//! +//! Both `DocumentCountRequest` and `DocumentCountResponse` are the +//! abi for this dispatcher; they're public so drive-abci can name +//! the input/output types without reaching into the executor surface. +//! +//! Whole module is gated `feature = "server"` via the parent's +//! `pub mod drive_dispatcher;` declaration. + +use super::super::conditions::{WhereClause, WhereOperator}; +use super::super::ordering::OrderClause; +use super::execute_range_count::RangeCountOptions; +use super::{DocumentCountMode, DriveDocumentCountQuery, SplitCountEntry}; +use crate::drive::Drive; +use crate::error::query::QuerySyntaxError; +use crate::error::Error; +use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters; +use dpp::data_contract::document_type::DocumentTypeRef; +use dpp::version::PlatformVersion; +use grovedb::TransactionArg; + +impl Drive { + //! Per-mode count-query executors. Each method: + //! 1. Picks the right covering index for its mode (returns + //! `Error::Query(QuerySyntaxError::WhereClauseOnNonIndexedProperty)` + //! if no index covers the where clauses). + //! 2. Builds the appropriate `DriveDocumentCountQuery` / + //! `DriveDocumentQuery`. + //! 3. Runs the right executor (`execute_no_proof`, + //! `execute_range_count_no_proof`, + //! `execute_aggregate_count_with_proof`, or + //! `execute_with_proof`). + //! 4. Returns either `Vec` (no-proof modes) + //! or `Vec` proof bytes (proof modes). + //! + //! Each per-mode executor is its own narrow contract — splitting + //! along mode boundaries keeps the dispatcher arms one line each + //! and lets each executor's index-picking + clause-handling logic + //! stay close to the executor it feeds. + + /// Total count for the given where clauses against an exactly- + /// covering countable index, OR — when the where clauses are + /// empty and the document type has `documents_countable: true` — + /// the type's primary-key CountTree (O(1) read at the doctype + /// tree's root). + /// + /// Single summed entry with empty key. Used by + /// [`DocumentCountMode::Total`] dispatch. + pub fn execute_document_count_total_no_proof( + &self, + contract_id: [u8; 32], + document_type: DocumentTypeRef, + document_type_name: String, + where_clauses: Vec, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result, Error> { + use dpp::data_contract::document_type::accessors::{ + DocumentTypeV0Getters, DocumentTypeV2Getters, + }; + + // Fast path: unfiltered total count on a `documents_countable: + // true` document type reads the primary-key CountTree directly + // (O(1)). No index needed — the doctype tree itself carries + // the count. + if where_clauses.is_empty() && document_type.documents_countable() { + let count = self.read_primary_key_count_tree( + &contract_id, + &document_type_name, + transaction, + platform_version, + )?; + return Ok(vec![SplitCountEntry { + in_key: None, + key: vec![], + count, + }]); + } + + let index = DriveDocumentCountQuery::find_countable_index_for_where_clauses( + document_type.indexes(), + &where_clauses, + ) + .ok_or_else(|| { + Error::Query(QuerySyntaxError::WhereClauseOnNonIndexedProperty( + "count query requires a `countable: true` index whose properties \ + exactly match the where clause fields, or `documentsCountable: \ + true` on the document type for unfiltered total counts" + .to_string(), + )) + })?; + let count_query = DriveDocumentCountQuery { + document_type, + contract_id, + document_type_name, + index, + where_clauses, + }; + count_query.execute_no_proof(self, transaction, platform_version) + } + + /// Reads the document-type primary-key tree's `CountTree` element + /// (`[contract_doc, contract_id, [1], doctype, 0]`) and returns + /// `count_value_or_default()`. Used by the `documents_countable: + /// true` fast path on the total-count flows (both no-proof and + /// prove builder). + /// + /// Returns 0 when the element doesn't exist (e.g. fresh contract + /// with no documents inserted). Caller is responsible for ensuring + /// `documents_countable` is set on the document type before + /// calling — without it the element at `[..., doctype, 0]` is a + /// regular `NormalTree` and `count_value_or_default()` returns 0 + /// regardless of how many documents the type actually has. + fn read_primary_key_count_tree( + &self, + contract_id: &[u8; 32], + document_type_name: &str, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result { + let drive_version = &platform_version.drive; + let path = [ + &[crate::drive::RootTree::DataContractDocuments as u8] as &[u8], + contract_id, + &[1u8], + document_type_name.as_bytes(), + ]; + let mut drive_operations = vec![]; + let element = self.grove_get_raw_optional( + grovedb_path::SubtreePath::from(path.as_slice()), + &[0], + crate::util::grove_operations::DirectQueryType::StatefulDirectQuery, + transaction, + &mut drive_operations, + drive_version, + )?; + Ok(element.map_or(0, |e| e.count_value_or_default())) + } + + /// Per-`In`-value entries: cartesian-fork the single `In` clause + /// into one Equal-on-each-value sub-query, run each, emit a + /// `(serialized_value, count)` entry. Used by + /// [`DocumentCountMode::PerInValue`] dispatch. + /// + /// `options` (limit / order / distinct) applies to the returned + /// entry list — split-mode pagination per the proto contract on + /// `GetDocumentsCountRequestV0.{order_by, limit}` (the dispatcher + /// derives `RangeCountOptions.order_by_ascending` from the first + /// `order_by` clause's direction; empty `order_by` → ascending). + /// The `distinct` flag has no effect here (PerInValue is always + /// per-value); it's accepted for symmetry with the range-mode + /// executor. + /// + /// Caller has already verified via [`DriveDocumentCountQuery::detect_mode`] + /// that exactly one `In` clause is present in `where_clauses`. + #[allow(clippy::too_many_arguments)] + pub fn execute_document_count_per_in_value_no_proof( + &self, + contract_id: [u8; 32], + document_type: DocumentTypeRef, + document_type_name: String, + where_clauses: Vec, + options: RangeCountOptions, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result, Error> { + let in_clause = where_clauses + .iter() + .find(|wc| wc.operator == WhereOperator::In) + .ok_or_else(|| { + Error::Query(QuerySyntaxError::InvalidWhereClauseComponents( + "execute_document_count_per_in_value_no_proof requires exactly one `in` clause", + )) + })? + .clone(); + // `in_values()` enforces non-empty, ≤100, no-duplicates — the + // same shape validation `WhereClause::from_clause` would have + // applied on the regular query path. Without it the executor + // below performs one GroveDB walk per value with no input cap, + // which lets a single 64 MiB gRPC request schedule arbitrarily + // many backend reads (request-amplification DoS). Inheriting + // the existing 100-cap is the same defensive bound the other + // `In` consumers (mod.rs:1246, conditions.rs:852) use. + let in_values = in_clause.in_values().into_data_with_error()??; + + let other_clauses: Vec = where_clauses + .iter() + .filter(|wc| wc.operator != WhereOperator::In) + .cloned() + .collect(); + + // Aggregate first into a key-ordered map (dedupes duplicate + // `In` values via the same canonical-byte rule as the range + // walker uses; BTreeMap ordering matches `RangeCountOptions`'s + // ascending convention). Order, cursor, and limit get applied + // after. + use dpp::data_contract::document_type::methods::DocumentTypeV0Methods; + let mut merged: std::collections::BTreeMap, u64> = + std::collections::BTreeMap::new(); + for value in in_values.iter() { + let key_bytes = document_type.serialize_value_for_key( + in_clause.field.as_str(), + value, + platform_version, + )?; + if merged.contains_key(&key_bytes) { + // Duplicate `In` values resolve to the same indexed path, + // so the count is the same — no need to re-query. + continue; + } + + let mut clauses_for_value = other_clauses.clone(); + clauses_for_value.push(WhereClause { + field: in_clause.field.clone(), + operator: WhereOperator::Equal, + value: value.clone(), + }); + + let index = DriveDocumentCountQuery::find_countable_index_for_where_clauses( + document_type.indexes(), + &clauses_for_value, + ) + .ok_or_else(|| { + Error::Query(QuerySyntaxError::WhereClauseOnNonIndexedProperty( + "count query requires a countable index on the document type that \ + matches the where clause properties" + .to_string(), + )) + })?; + + let count_query = DriveDocumentCountQuery { + document_type, + contract_id, + document_type_name: document_type_name.clone(), + index, + where_clauses: clauses_for_value, + }; + let results = count_query.execute_no_proof(self, transaction, platform_version)?; + let count = results.first().map_or(0, |entry| entry.count); + merged.insert(key_bytes, count); + } + + // Apply order, then cursor, then limit — same shape as the + // range walker. BTreeMap iteration is already ascending; flip + // the vec if descending was requested. + // + // PerInValue mode splits by the `In` dimension itself, so + // the In value goes in `key` (the split-key field) and + // `in_key` is `None`. The `in_key` field is reserved for + // compound queries where the `In` is on a prefix property + // distinct from the value being counted. + let mut entries: Vec = merged + .into_iter() + .map(|(key, count)| SplitCountEntry { + in_key: None, + key, + count, + }) + .collect(); + if !options.order_by_ascending { + entries.reverse(); + } + // For pagination, callers chunk the `In` array client-side + // (the values are caller-supplied to begin with); no + // server-side cursor is needed or supported. + if let Some(limit) = options.limit { + entries.truncate(limit as usize); + } + Ok(entries) + } + + /// Range-count walk against a `range_countable` index. Returns a + /// summed entry or per-distinct-value entries depending on + /// `options.distinct`. Used by [`DocumentCountMode::RangeNoProof`] + /// dispatch. + #[allow(clippy::too_many_arguments)] + pub fn execute_document_count_range_no_proof( + &self, + contract_id: [u8; 32], + document_type: DocumentTypeRef, + document_type_name: String, + where_clauses: Vec, + options: RangeCountOptions, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result, Error> { + let index = DriveDocumentCountQuery::find_range_countable_index_for_where_clauses( + document_type.indexes(), + &where_clauses, + ) + .ok_or_else(|| { + Error::Query(QuerySyntaxError::WhereClauseOnNonIndexedProperty( + "range count requires a `range_countable: true` index whose last \ + property matches the range field, with all other clauses covering \ + its prefix as `==` matches" + .to_string(), + )) + })?; + let count_query = DriveDocumentCountQuery { + document_type, + contract_id, + document_type_name, + index, + where_clauses, + }; + count_query.execute_range_count_no_proof(self, &options, transaction, platform_version) + } + + /// Range-count proof via grovedb's `AggregateCountOnRange`. Returns + /// proof bytes that the client verifies via + /// `GroveDb::verify_aggregate_count_query`. Used by + /// [`DocumentCountMode::RangeProof`] dispatch. + pub fn execute_document_count_range_proof( + &self, + contract_id: [u8; 32], + document_type: DocumentTypeRef, + document_type_name: String, + where_clauses: Vec, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result, Error> { + let index = DriveDocumentCountQuery::find_range_countable_index_for_where_clauses( + document_type.indexes(), + &where_clauses, + ) + .ok_or_else(|| { + Error::Query(QuerySyntaxError::WhereClauseOnNonIndexedProperty( + "range count requires a `range_countable: true` index whose last \ + property matches the range field" + .to_string(), + )) + })?; + let count_query = DriveDocumentCountQuery { + document_type, + contract_id, + document_type_name, + index, + where_clauses, + }; + count_query.execute_aggregate_count_with_proof(self, transaction, platform_version) + } + + /// Distinct-counts-with-proof companion to + /// [`Self::execute_document_count_range_proof`]. Returns proof + /// bytes that the client verifies via + /// [`drive_proof_verifier::verify_distinct_count_proof`], yielding + /// a `BTreeMap, u64>` keyed by serialized property value. + /// Used by [`DocumentCountMode::RangeDistinctProof`] dispatch. + /// + /// `limit` caps the number of distinct in-range values the proof + /// covers — the dispatcher pre-validates `limit ≤ max_query_limit` + /// so client-side proof reconstruction can use the exact same + /// value without divergence. The SDK reads it back off the + /// request when building the verifier's `PathQuery`. + #[allow(clippy::too_many_arguments)] + pub fn execute_document_count_range_distinct_proof( + &self, + contract_id: [u8; 32], + document_type: DocumentTypeRef, + document_type_name: String, + where_clauses: Vec, + limit: u16, + left_to_right: bool, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result, Error> { + let index = DriveDocumentCountQuery::find_range_countable_index_for_where_clauses( + document_type.indexes(), + &where_clauses, + ) + .ok_or_else(|| { + Error::Query(QuerySyntaxError::WhereClauseOnNonIndexedProperty( + "range count requires a `range_countable: true` index whose last \ + property matches the range field" + .to_string(), + )) + })?; + let count_query = DriveDocumentCountQuery { + document_type, + contract_id, + document_type_name, + index, + where_clauses, + }; + count_query.execute_distinct_count_with_proof( + self, + limit, + left_to_right, + transaction, + platform_version, + ) + } + + /// Point-lookup count proof against a `countable: true` index for + /// `prove = true` Equal/`In` count queries, OR — when the where + /// clauses are empty and the document type has + /// `documents_countable: true` — a proof of the type's primary-key + /// CountTree (one merk path proof, O(log n) bytes). + /// + /// In both cases the SDK-side verifier extracts each verified + /// CountTree element's `count_value` directly, no document + /// materialization. + /// + /// Mirrors the no-proof `Total` / `PerInValue` modes' rejection + /// contract: if no `countable: true` index exactly covers the + /// where clauses (and the documents_countable fast path doesn't + /// apply), rejects with `WhereClauseOnNonIndexedProperty`. Same + /// contract on both prove and no-proof paths — no silent fallback. + /// + /// Used by [`DocumentCountMode::PointLookupProof`] dispatch. + pub fn execute_document_count_point_lookup_proof( + &self, + contract_id: [u8; 32], + document_type: DocumentTypeRef, + document_type_name: String, + where_clauses: Vec, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result, Error> { + use dpp::data_contract::document_type::accessors::DocumentTypeV2Getters; + + // Fast path: unfiltered prove count on a `documents_countable: + // true` document type proves the primary-key CountTree + // element directly. Same path-query shape as the index-based + // case, just rooted at `[..., doctype]` instead of inside an + // index. + if where_clauses.is_empty() && document_type.documents_countable() { + let path_query = DriveDocumentCountQuery::primary_key_count_tree_path_query( + contract_id, + &document_type_name, + ); + let proof = self + .grove + .get_proved_path_query( + &path_query, + None, + transaction, + &platform_version.drive.grove_version, + ) + .unwrap() + .map_err(|e| Error::GroveDB(Box::new(e)))?; + return Ok(proof); + } + + let index = DriveDocumentCountQuery::find_countable_index_for_where_clauses( + document_type.indexes(), + &where_clauses, + ) + .ok_or_else(|| { + Error::Query(QuerySyntaxError::WhereClauseOnNonIndexedProperty( + "prove count requires a `countable: true` index whose properties \ + exactly match the where clause fields, or `documentsCountable: \ + true` on the document type for unfiltered total counts — same \ + requirement as the no-proof path" + .to_string(), + )) + })?; + let count_query = DriveDocumentCountQuery { + document_type, + contract_id, + document_type_name, + index, + where_clauses, + }; + count_query.execute_point_lookup_count_with_proof(self, transaction, platform_version) + } +} + +/// All inputs required for the unified document-count entry point +/// [`Drive::execute_document_count_request`]. Built by the gRPC +/// handler from a `GetDocumentsCountRequestV0` after CBOR-decoding + +/// contract lookup; drive owns everything past this point including +/// mode detection, index picking, and per-mode dispatch. +/// +/// `raw_where_value` and `raw_order_by_value` arrive as CBOR-decoded +/// `Value`s and the dispatcher parses them once into structured +/// `Vec` / `Vec` for mode detection + +/// per-mode executors. None of the count executors consume the raw +/// `Value` form — the structured parse is the single source of +/// truth past the dispatcher entry point. +pub struct DocumentCountRequest<'a> { + /// Live contract (already loaded by the handler). + pub contract: &'a dpp::data_contract::DataContract, + /// Resolved document type within `contract`. + pub document_type: DocumentTypeRef<'a>, + /// Decoded `where` value as it came off the wire (after CBOR + /// decode). The dispatcher parses this into `Vec` + /// once (`where_clauses_from_value`) for every downstream + /// consumer — mode detection, index picking, and the per-mode + /// executors all operate on the structured form. + /// + /// Mirrors how the regular `query_documents_v0` handler + /// delegates where-clause decomposition to drive: the abci + /// layer just CBOR-decodes and hands the raw value down. + pub raw_where_value: dpp::platform_value::Value, + /// Decoded `order_by` value as it came off the wire. Parsed + /// once via `order_clauses_from_value` into + /// `Vec`. The first clause's direction governs + /// split-mode entry ordering (per-`In`-value / per-distinct- + /// value-in-range) and, on the `RangeDistinctProof` prove + /// path, is part of the path-query bytes the SDK reconstructs + /// to verify the proof. `PointLookupProof` and the no-proof + /// `Total` / `PerInValue` paths don't read order_by. + /// + /// `Value::Null` (empty `order_by` field on the wire) → no + /// clauses. The dispatcher synthesizes a default direction of + /// "ascending" for split-mode response ordering when no clauses + /// are present. + pub raw_order_by_value: dpp::platform_value::Value, + /// `return_distinct_counts_in_range` flag from the request. + pub return_distinct_counts_in_range: bool, + /// Limit cap from the request. Callers SHOULD pre-clamp against + /// their server-side `max_query_limit` policy, but Drive also + /// enforces a defense-in-depth clamp before forwarding to the + /// distinct-mode walk: an `Option::None` here is normalized to + /// `drive_config.default_query_limit` and any `Some(value)` is + /// reduced to `drive_config.max_query_limit` if larger. After + /// dispatch, the limit forwarded to + /// [`RangeCountOptions::limit`] is always `Some(_)` ≤ system cap. + pub limit: Option, + /// Whether to produce a proof (vs. raw counts). + pub prove: bool, + /// Drive-side query config — only consumed by the materialize-and- + /// count fallback. + pub drive_config: &'a crate::config::DriveConfig, +} + +/// Output shape of [`Drive::execute_document_count_request`]. Three +/// variants mirror the proto's `CountResults.variant` oneof (for +/// no-proof responses) plus the outer `Proof` arm: +/// +/// - `Aggregate(u64)` — total-count modes (`Total` and +/// `RangeNoProof` with `return_distinct_counts_in_range = false`). +/// The abci handler maps this to `CountResults.aggregate_count`. +/// - `Entries(Vec)` — per-key modes (`PerInValue` +/// and `RangeNoProof` with `return_distinct_counts_in_range = +/// true`). The abci handler maps this to `CountResults.entries`. +/// - `Proof(Vec)` — grovedb proof bytes the client verifies via +/// either `verify_aggregate_count_query` (for `RangeProof`), +/// `verify_distinct_count_proof` (for `RangeDistinctProof`), or +/// the `DriveDocumentQuery` proof verifier (for +/// `PointLookupProof`). +#[derive(Debug, Clone)] +pub enum DocumentCountResponse { + /// Single aggregate count — total across the matching set. + Aggregate(u64), + /// Per-key entries. + Entries(Vec), + /// Grovedb proof bytes. + Proof(Vec), +} + +/// Parse the decoded `where` value into structured [`WhereClause`]s. +/// +/// Mirrors the per-clause loop the regular `query_documents_v0` +/// handler delegates to `DriveDocumentQuery::from_decomposed_values`: +/// the abci layer just CBOR-decodes the wire bytes into a `Value` and +/// hands the raw value down. Drive owns the parsing so a future +/// per-clause validation (e.g. forbidding operators in distinct mode) +/// can live next to the executors instead of being scattered across +/// abci handlers. +/// +/// `Value::Null` (empty `where` field) → no clauses. Any other shape +/// must be an outer array of inner arrays-of-components. +/// +/// After component parsing, the resulting clause list is run through +/// [`WhereClause::group_clauses`] — the same validator the regular +/// document-query path uses — to reject malformed shapes the count +/// path otherwise silently reduces: +/// +/// - Duplicate `Equal` clauses on the same field +/// (`DuplicateNonGroupableClauseSameField`). +/// - Multiple `In` clauses (`MultipleInClauses`). +/// - Multiple non-groupable range clauses (`MultipleRangeClauses`). +/// - Equality + `In` on the same field, range + equality/In on the +/// same field (`DuplicateNonGroupableClauseSameField` / +/// `InvalidWhereClauseComponents`). +/// +/// Without this validation, downstream +/// [`DriveDocumentCountQuery::find_countable_index_for_where_clauses`] +/// collapses repeated fields into a `BTreeSet` and +/// [`DriveDocumentCountQuery::point_lookup_count_path_query`] +/// resolves each index property with a single `.find(...)` — both +/// of which silently pick the first clause on a duplicated field +/// and return a count for an arbitrarily reduced query rather than +/// rejecting the malformed request. `group_clauses` is the single +/// source of truth for what shapes the query stack as a whole +/// accepts; running it here aligns the count endpoint with the +/// regular document-query path's rejection contract. +/// +/// Only the validation side-effect is consumed — the dispatcher +/// continues to operate on the parsed `Vec` directly, +/// since the count-specific mode detection and index pickers +/// expect a flat list, not the equal-clauses/in-clause/range-clause +/// triple that `group_clauses` returns. (The regular query path's +/// `InternalClauses::extract_from_clauses` uses the triple; the +/// count path doesn't.) +fn where_clauses_from_value(value: &dpp::platform_value::Value) -> Result, Error> { + let clauses: Vec = match value { + dpp::platform_value::Value::Null => Vec::new(), + dpp::platform_value::Value::Array(clauses) => clauses + .iter() + .map(|wc| match wc { + dpp::platform_value::Value::Array(components) => { + WhereClause::from_components(components) + } + _ => Err(Error::Query(QuerySyntaxError::InvalidFormatWhereClause( + "where clause must be an array", + ))), + }) + .collect::, _>>()?, + _ => { + return Err(Error::Query(QuerySyntaxError::InvalidFormatWhereClause( + "where clause must be an array", + ))); + } + }; + + // Run the parsed clauses through the system-wide validator. + // The returned triple is discarded; we only care about the + // validation errors — see this function's docstring for the + // catalog of rejections this enables on the count endpoint. + let _ = WhereClause::group_clauses(&clauses)?; + Ok(clauses) +} + +/// Parse the decoded `order_by` value into structured [`OrderClause`]s. +/// +/// Same shape as [`where_clauses_from_value`] for `order_by`: +/// `Value::Null` (empty `order_by` field on the wire) → no clauses; +/// any other shape must be an outer array of `[field, direction]` +/// inner arrays. Direction is `"asc"` / `"desc"` per +/// `OrderClause::from_components`. +fn order_clauses_from_value(value: &dpp::platform_value::Value) -> Result, Error> { + match value { + dpp::platform_value::Value::Null => Ok(Vec::new()), + dpp::platform_value::Value::Array(clauses) => clauses + .iter() + .map(|oc| match oc { + dpp::platform_value::Value::Array(components) => { + // `OrderClause::from_components` returns + // `grovedb::Error`; wrap as drive's query-syntax + // error so the dispatcher's error contract stays + // uniform with the where-clause parser above. + OrderClause::from_components(components).map_err(|_e| { + Error::Query(QuerySyntaxError::InvalidFormatWhereClause( + "order_by clause must have [field, \"asc\"|\"desc\"] shape", + )) + }) + } + _ => Err(Error::Query(QuerySyntaxError::InvalidFormatWhereClause( + "order_by clause must be an array", + ))), + }) + .collect(), + _ => Err(Error::Query(QuerySyntaxError::InvalidFormatWhereClause( + "order_by clause must be an array", + ))), + } +} + +impl Drive { + /// Single entry point for the unified `GetDocumentsCount` request. + /// + /// Owns the whole pipeline: + /// 1. [`DriveDocumentCountQuery::detect_mode`] classifies the + /// query shape from the where clauses + flags. + /// 2. The matching `Drive::execute_document_count_*` per-mode + /// method picks an index and runs the executor. + /// 3. The result is wrapped in [`DocumentCountResponse`] — + /// `Counts(...)` for no-proof modes, `Proof(...)` for proof + /// modes. + /// + /// Errors: + /// - Mode-detection failures (multiple range clauses, range + + /// `In`, distinct on prove path, …) come back as + /// `Error::Query(QuerySyntaxError::InvalidWhereClauseComponents)`. + /// - "No covering index" failures come back as + /// `Error::Query(QuerySyntaxError::WhereClauseOnNonIndexedProperty)`. + /// - All other failures (grovedb, cost calculation, …) surface + /// as their native `Error` variants. + /// + /// The handler maps both `Error::Query(...)` cases to its own + /// `QueryError::Query(...)` variant uniformly. + pub fn execute_document_count_request( + &self, + request: DocumentCountRequest, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result { + use dpp::data_contract::accessors::v0::DataContractV0Getters; + + // Parse where clauses out of the raw decoded `Value` once, + // then thread them through the per-mode executors. Mirrors + // how the regular `query_documents_v0` handler delegates this + // to `DriveDocumentQuery::from_decomposed_values` — + // where-clause decomposition is a drive concern, not abci's. + let where_clauses = where_clauses_from_value(&request.raw_where_value)?; + let order_clauses = order_clauses_from_value(&request.raw_order_by_value)?; + + // Split-mode entry direction is whatever the first orderBy + // clause specifies. Empty orderBy → ascending default. Used + // by per-`In`-value, distinct-range no-proof, and + // distinct-range prove paths; the `PointLookupProof` and + // flat `Total` paths don't read it. + let order_by_ascending = order_clauses.first().map(|c| c.ascending).unwrap_or(true); + + let mode = DriveDocumentCountQuery::detect_mode( + &where_clauses, + request.return_distinct_counts_in_range, + request.prove, + )?; + + let contract_id = request.contract.id_ref().to_buffer(); + let document_type_name = request.document_type.name().to_string(); + + match mode { + DocumentCountMode::Total => { + // Total mode → single aggregate. The executor returns + // at most one entry (with empty key); collapse to + // `Aggregate(count)` here so the response is a u64 + // with no per-key wrapping. Empty result (indexed + // path doesn't exist yet) → `Aggregate(0)`. + let entries = self.execute_document_count_total_no_proof( + contract_id, + request.document_type, + document_type_name, + where_clauses, + transaction, + platform_version, + )?; + let total = entries.first().map(|e| e.count).unwrap_or(0); + Ok(DocumentCountResponse::Aggregate(total)) + } + DocumentCountMode::PerInValue => { + // Per-`In`-value → entries. The proto contract on + // `GetDocumentsCountRequestV0.{order_by, limit}` + // applies; clamp `limit` defensively (the abci handler + // passes raw, see `DocumentCountRequest::limit` doc). + let effective_limit = request + .limit + .unwrap_or(request.drive_config.default_query_limit as u32) + .min(request.drive_config.max_query_limit as u32); + let options = RangeCountOptions { + distinct: false, // ignored by PerInValue executor + limit: Some(effective_limit), + order_by_ascending, + }; + Ok(DocumentCountResponse::Entries( + self.execute_document_count_per_in_value_no_proof( + contract_id, + request.document_type, + document_type_name, + where_clauses, + options, + transaction, + platform_version, + )?, + )) + } + DocumentCountMode::RangeNoProof => { + // Range no-proof → either aggregate (sum) or entries + // (per-distinct-value), based on + // `return_distinct_counts_in_range`. Clamp limit + // defense-in-depth. + let effective_limit = request + .limit + .unwrap_or(request.drive_config.default_query_limit as u32) + .min(request.drive_config.max_query_limit as u32); + let options = RangeCountOptions { + distinct: request.return_distinct_counts_in_range, + limit: Some(effective_limit), + order_by_ascending, + }; + let entries = self.execute_document_count_range_no_proof( + contract_id, + request.document_type, + document_type_name, + where_clauses, + options, + transaction, + platform_version, + )?; + if request.return_distinct_counts_in_range { + Ok(DocumentCountResponse::Entries(entries)) + } else { + // !distinct: executor returns a single empty-key + // entry containing the sum (or empty vec if the + // path doesn't exist). Collapse to `Aggregate`. + let total = entries.first().map(|e| e.count).unwrap_or(0); + Ok(DocumentCountResponse::Aggregate(total)) + } + } + DocumentCountMode::RangeProof => Ok(DocumentCountResponse::Proof( + self.execute_document_count_range_proof( + contract_id, + request.document_type, + document_type_name, + where_clauses, + transaction, + platform_version, + )?, + )), + DocumentCountMode::RangeDistinctProof => { + // Validate-don't-clamp limit policy on the prove + // path: client-side proof reconstruction needs the + // exact same limit value the server applied to the + // path query (so the merk-root recomputation + // matches). Silent clamping would invisibly break + // verification on any request with `limit > + // max_query_limit`. + // + // **Limit fallback uses `crate::config::DEFAULT_QUERY_LIMIT` + // (the compile-time constant), NOT + // `drive_config.default_query_limit` (the + // operator-tunable runtime value).** The SDK verifier + // can't know an operator's tuned config, so any + // operator who tuned `default_query_limit` away from + // `DEFAULT_QUERY_LIMIT` would produce proofs whose + // `SizedQuery::limit` byte-differs from the + // verifier's reconstruction — silent verify failure + // on a consensus-adjacent path. Anchoring the + // fallback to the shared compile-time constant + // removes that operator-tunable degree of freedom + // from proof bytes entirely; the runtime + // `default_query_limit` continues to govern no-proof + // dispatch paths where there's no verifier to match. + // `max_query_limit` still gates the request as a + // DoS-protection knob (proofs never cross the + // operator-set ceiling, but the ceiling itself doesn't + // affect proof bytes — it only decides whether the + // request gets served). + let effective_limit = request + .limit + .unwrap_or(crate::config::DEFAULT_QUERY_LIMIT as u32); + if effective_limit > request.drive_config.max_query_limit as u32 { + return Err(Error::Query(QuerySyntaxError::InvalidLimit(format!( + "limit {} exceeds max_query_limit {} on the prove + \ + return_distinct_counts_in_range path; reduce the requested \ + limit or use prove = false", + effective_limit, request.drive_config.max_query_limit + )))); + } + let limit_u16 = effective_limit as u16; + // Default to ascending if the request didn't specify + // — matches the no-proof default. The verifier reads + // the same field to reconstruct the matching path + // query (see SDK's + // `FromProof` for + // `DocumentSplitCounts`); both sides MUST land on the + // same `left_to_right` value or the merk-root + // recomputation fails. + let left_to_right = order_by_ascending; + Ok(DocumentCountResponse::Proof( + self.execute_document_count_range_distinct_proof( + contract_id, + request.document_type, + document_type_name, + where_clauses, + limit_u16, + left_to_right, + transaction, + platform_version, + )?, + )) + } + DocumentCountMode::PointLookupProof => Ok(DocumentCountResponse::Proof( + self.execute_document_count_point_lookup_proof( + contract_id, + request.document_type, + document_type_name, + where_clauses, + transaction, + platform_version, + )?, + )), + } + } +} diff --git a/packages/rs-drive/src/query/drive_document_count_query/execute_point_lookup.rs b/packages/rs-drive/src/query/drive_document_count_query/execute_point_lookup.rs new file mode 100644 index 00000000000..a67a44b1b61 --- /dev/null +++ b/packages/rs-drive/src/query/drive_document_count_query/execute_point_lookup.rs @@ -0,0 +1,125 @@ +//! Equal/In point-lookup execution paths for the count query. +//! +//! No-proof and proof executors for fully-covered Equal/`In` queries +//! against a `countable: true` index. Both sides share the same +//! [`DriveDocumentCountQuery::point_lookup_count_path_query`] builder, +//! so the proof bytes the server signs and the path query the verifier +//! reconstructs (and the no-proof read this file performs) all see +//! the exact same shape — there's only one source of truth for which +//! `CountTree` elements compose the answer. +//! +//! Range-mode executors live in +//! [`super::execute_range_count`](super::execute_range_count); this +//! file is the Equal/In half of the dispatch surface. +//! +//! Whole module is gated `feature = "server"` via the parent's +//! `pub mod execute_point_lookup;` declaration. + +use super::{DriveDocumentCountQuery, SplitCountEntry}; +use crate::drive::Drive; +use crate::error::Error; +use dpp::version::PlatformVersion; +use grovedb::query_result_type::{QueryResultElement, QueryResultType}; +use grovedb::TransactionArg; + +impl DriveDocumentCountQuery<'_> { + /// Executes the count query without generating a proof. + /// + /// Returns the total count as a single `SplitCountEntry` with + /// empty `key` (the unified-count Total shape). + /// + /// Implementation goes through the same + /// [`Self::point_lookup_count_path_query`] builder the prove + /// path uses, then runs `grove.query` to fetch the matched + /// `CountTree` elements and sums their `count_value_or_default()` + /// values. The builder handles all three structural cases + /// (Equal-only fully covered, In at any index position, In with + /// trailing Equals via `set_subquery_path`) — there's no need + /// for a separate recursive walker on the no-proof side. + pub fn execute_no_proof( + &self, + drive: &Drive, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result, Error> { + let drive_version = &platform_version.drive; + let path_query = self.point_lookup_count_path_query(platform_version)?; + // `grove_get_path_query` requires a `drive_operations` sink for + // cost accounting; the no-proof executor doesn't propagate fees + // upward (callers that need cost are the per-mode dispatchers + // in `drive_dispatcher.rs`, which wrap this for fee calculation), + // so we use a local vec and discard. + let mut drive_operations = vec![]; + let (results, _) = drive.grove_get_path_query( + &path_query, + transaction, + QueryResultType::QueryElementResultType, + &mut drive_operations, + drive_version, + )?; + // Sum across emitted CountTree elements: + // - Equal-only: 0 or 1 element (0 when the branch is absent). + // - In at any position: one element per In branch that has at + // least one doc; missing branches contribute 0 by virtue of + // being absent from the result set. + // `count_value_or_default()` returns the `CountTree`'s count + // for `Element::CountTree` / `Element::SumTree` and 1 for + // `Element::Reference` (the unique-index-with-all-non-null + // case — see `Element::count_value_or_default` for the per- + // variant contract). + let count: u64 = results + .elements + .iter() + .map(|e| match e { + QueryResultElement::ElementResultItem(elem) => elem.count_value_or_default(), + // `QueryElementResultType` only emits `ElementResultItem`; + // the other variants belong to `QueryKeyElementPairResultType` + // / `QueryPathKeyElementTrioResultType` which we don't + // request. Defensive 0 keeps the executor total-correct + // even if grovedb's emission shape ever broadens. + _ => 0, + }) + .sum(); + Ok(vec![SplitCountEntry { + in_key: None, + key: vec![], + count, + }]) + } + + /// Generates a grovedb proof of the CountTree elements covering a + /// fully-covered Equal/`In` count query against a `countable: true` + /// index. Returns the raw proof bytes; the SDK-side + /// [`Self::verify_point_lookup_count_proof`] walks the proof and + /// extracts `count_value_or_default()` from each verified CountTree + /// element. + /// + /// Builds the path query via + /// [`Self::point_lookup_count_path_query`] (shared with the + /// verifier AND with [`Self::execute_no_proof`] above, so all three + /// sites see byte-identical path queries). Errors surface from the + /// builder when the query shape isn't supported — partial + /// coverage, more than one In, etc. — see that builder's docstring + /// for the exhaustive contract. + /// + /// Proof size is O(k × log n) where k is the number of covered + /// (Equal/In) branches and n is the tree depth: one merk path proof + /// per CountTree element, not per matching document. Replaces the + /// pre-this-PR materialize-and-count proof which scaled with + /// matching docs and was capped at `u16::MAX`. + pub fn execute_point_lookup_count_with_proof( + &self, + drive: &Drive, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result, Error> { + let drive_version = &platform_version.drive; + let path_query = self.point_lookup_count_path_query(platform_version)?; + let proof = drive + .grove + .get_proved_path_query(&path_query, None, transaction, &drive_version.grove_version) + .unwrap() + .map_err(|e| Error::GroveDB(Box::new(e)))?; + Ok(proof) + } +} diff --git a/packages/rs-drive/src/query/drive_document_count_query/execute_range_count.rs b/packages/rs-drive/src/query/drive_document_count_query/execute_range_count.rs new file mode 100644 index 00000000000..ad98c7216c1 --- /dev/null +++ b/packages/rs-drive/src/query/drive_document_count_query/execute_range_count.rs @@ -0,0 +1,397 @@ +//! Range execution paths for the count query. +//! +//! Three executors all keyed on a `range_countable: true` index: +//! - [`DriveDocumentCountQuery::execute_range_count_no_proof`] — Rust- +//! side walk of the property-name `ProvableCountTree`'s children, +//! returning per-(in_key, key) entries (or a single sum) without a +//! proof. +//! - [`DriveDocumentCountQuery::execute_aggregate_count_with_proof`] — +//! grovedb `AggregateCountOnRange` proof, returning a single u64. +//! - [`DriveDocumentCountQuery::execute_distinct_count_with_proof`] — +//! regular range proof against the `ProvableCountTree`, returning +//! per-key `KVCount` ops bound to the merk root. +//! +//! Point-lookup execution (Equal/In with no range) lives in +//! [`super::execute_point_lookup`](super::execute_point_lookup). +//! +//! Whole module is gated `feature = "server"` via the parent's +//! `pub mod execute_range_count;` declaration. + +use super::super::conditions::{WhereClause, WhereOperator}; +use super::{DriveDocumentCountQuery, SplitCountEntry}; +use crate::drive::Drive; +use crate::error::query::QuerySyntaxError; +use crate::error::Error; +use dpp::data_contract::document_type::methods::DocumentTypeV0Methods; +use dpp::version::PlatformVersion; +use grovedb::query_result_type::QueryResultType; +use grovedb::TransactionArg; + +/// Pagination + ordering knobs for `execute_range_count_no_proof`. +/// +/// Mirrors the protobuf request fields on +/// `GetDocumentsCountRequestV0` so the drive-abci handler can pass them +/// through unmodified. `distinct = false` collapses the range walk to a +/// single summed entry; `distinct = true` returns one entry per distinct +/// property value within the range. +#[derive(Debug, Clone, Default)] +pub struct RangeCountOptions { + /// When `true`, return one [`SplitCountEntry`] per distinct property + /// value within the range. When `false`, return a single entry + /// (empty `key`) summing all per-value counts. + pub distinct: bool, + /// Maximum number of entries to return. Only meaningful when + /// `distinct = true`. `None` means no limit. + /// + /// To paginate, callers narrow the range itself (`color > + /// `). There's no cursor field + /// because a single-`bytes` cursor would be ambiguous for + /// compound (`In + range + distinct`) queries whose natural sort + /// is `(in_key, key)`, and range narrowing has the same + /// expressivity for the simple cases. + pub limit: Option, + /// Sort order for distinct entries. `true` (default) is ascending by + /// serialized key bytes. Ignored when `distinct = false`. + pub order_by_ascending: bool, +} + +impl DriveDocumentCountQuery<'_> { + /// Executes a range-aware count query against a `range_countable` + /// index. Path layout is `[contract_doc, doctype, prefix..., + /// range_prop_name]`, whose children are the per-value + /// `CountTree` leaves keyed by the range property's serialized + /// value. + /// + /// The caller picks the index via + /// [`Self::find_range_countable_index_for_where_clauses`]; this + /// method assumes: + /// - `self.index.range_countable == true` + /// - All `Equal` / `In` where clauses cover the index prefix + /// - Exactly one range-operator where clause hits the index's last + /// property + /// + /// ## Execution strategies by mode + /// + /// - **Flat summed** (no `In`, `distinct = false`): single + /// `query_aggregate_count` call against the merk-level + /// `AggregateCountOnRange` primitive. O(log n). + /// - **Compound summed** (`In` on prefix, `distinct = false`): + /// per-In-value fan-out — one `query_aggregate_count` call per + /// matched In branch, summed in Rust. Bounded by the In + /// array's 100-element cap (enforced by + /// [`WhereClause::in_values`]) times O(log n), so worst-case + /// work is 100 × O(log n) regardless of how many documents + /// the range actually matches. Closes the request-amplification + /// surface a pre-fix walk-and-sum implementation had: that + /// path materialized every matched `(in_key, key)` element + /// even though the response was still a single aggregate + /// `u64`. + /// - **Distinct mode** (`distinct = true`, with or without + /// `In` on prefix): walks the unified + /// [`Self::distinct_count_path_query`] and emits one entry per + /// matched `(in_key, key)` pair. The path query carries + /// `options.limit` (clamped to `max_query_limit` upstream by + /// the dispatcher) and `options.order_by_ascending`, so + /// per-query work is O(limit × log n). Cross-fork aggregation + /// is intentionally NOT performed server-side; callers reduce + /// by `key` client-side if they want a flat histogram. See the + /// book chapter ("No-Merge Compound Semantics") for the rationale. + /// + /// ## Returned entry shape + /// + /// When `options.distinct = false`, returns a single entry with + /// `in_key = None`, empty `key`, and `count` equal to the sum of + /// all matched per-value counts. When `options.distinct = true`, + /// returns one entry per emitted `(in_key, key)` pair, after + /// applying `order_by_ascending` and `limit` over the + /// lexicographic `(in_key, key)` tuple. + pub fn execute_range_count_no_proof( + &self, + drive: &Drive, + options: &RangeCountOptions, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result, Error> { + let drive_version = &platform_version.drive; + let has_in_on_prefix = self + .where_clauses + .iter() + .any(|wc| wc.operator == WhereOperator::In); + + // Summed mode (both flat and compound `In + range`) goes + // through grovedb's `AggregateCountOnRange` primitive + // (`query_aggregate_count`), bounding per-query work to + // O(log n) per merk-tree fan-out. Compound mode loops over + // the In values (≤100 per the `in_values()` validator cap + // in `WhereClause::in_values()`) and issues one aggregate + // call per value, then sums the results — total bound is + // O(|In| × log n), independent of how many documents + // actually match the range. + // + // The pre-fix walk-and-sum path materialized every matched + // `(in_key, key)` element via `query_raw` to sum them in + // Rust. With one broad range × 100 In values that scans + // potentially millions of CountTree elements even though + // the response is still a single aggregate `u64` — a + // classic request-amplification surface on a public DAPI + // endpoint. The per-In fan-out closes that surface. + if !options.distinct { + if has_in_on_prefix { + let in_clause = self + .where_clauses + .iter() + .find(|wc| wc.operator == WhereOperator::In) + .ok_or_else(|| { + Error::Query(QuerySyntaxError::InvalidWhereClauseComponents( + "compound summed range count path requires an `in` clause; \ + dispatcher bug if reached without one", + )) + })?; + // `in_values()` enforces non-empty, ≤100, no-duplicates + // — same defensive cap every other In consumer in + // drive uses. Without it a single 64 MiB gRPC request + // could schedule arbitrarily many backend aggregate + // reads. + let in_values = in_clause.in_values().into_data_with_error()??; + let other_clauses: Vec = self + .where_clauses + .iter() + .filter(|wc| wc.operator != WhereOperator::In) + .cloned() + .collect(); + + let mut total: u64 = 0; + let mut seen_keys: std::collections::BTreeSet> = + std::collections::BTreeSet::new(); + for value in in_values.iter() { + // Dedupe by serialized canonical key, not by raw + // Value, so that distinct DPP values that + // collapse to the same indexed bytes don't get + // double-counted. `in_values()` already rejects + // raw-Value duplicates, but this is defense-in- + // depth against future Value variants that + // serialize identically (e.g. integer vs + // float-with-zero-fraction). + let key_bytes = self.document_type.serialize_value_for_key( + in_clause.field.as_str(), + value, + platform_version, + )?; + if !seen_keys.insert(key_bytes) { + continue; + } + + // Per-In-value query: replace the In clause with + // an Equal on the specific value. The resulting + // shape is flat (no In, Equal-prefix + range + // terminator), so `aggregate_count_path_query` + // accepts it and `query_aggregate_count` walks + // boundary nodes in O(log n). + let mut clauses_for_value = other_clauses.clone(); + clauses_for_value.push(WhereClause { + field: in_clause.field.clone(), + operator: WhereOperator::Equal, + value: value.clone(), + }); + let per_value_query = DriveDocumentCountQuery { + document_type: self.document_type, + contract_id: self.contract_id, + document_type_name: self.document_type_name.clone(), + index: self.index, + where_clauses: clauses_for_value, + }; + let path_query = + per_value_query.aggregate_count_path_query(platform_version)?; + let count = drive + .grove + .query_aggregate_count( + &path_query, + transaction, + &drive_version.grove_version, + ) + .unwrap() + .map_err(|e| Error::GroveDB(Box::new(e)))?; + total = total.saturating_add(count); + } + return Ok(vec![SplitCountEntry { + in_key: None, + key: Vec::new(), + count: total, + }]); + } + // Flat summed (no In on prefix): single aggregate read. + let path_query = self.aggregate_count_path_query(platform_version)?; + let count = drive + .grove + .query_aggregate_count(&path_query, transaction, &drive_version.grove_version) + .unwrap() + .map_err(|e| Error::GroveDB(Box::new(e)))?; + return Ok(vec![SplitCountEntry { + in_key: None, + key: Vec::new(), + count, + }]); + } + + // Distinct mode (with or without In on prefix): walk and + // emit per-`(in_key, key)` entries. Bounded by the request's + // `limit` clause — the dispatcher already clamped that to + // `max_query_limit`, so this walk is O(limit × log n) and + // can't blow past the operator's DoS budget. + // + // Builds a single path query via the unified + // `distinct_count_path_query` builder. For an Equal-only + // prefix this collapses to a flat range-only query at the + // terminator's property-name subtree; for an In-on-prefix + // it becomes a compound query with one outer `Key` per In + // value (sorted lex-ascending by the builder) plus a + // `subquery_path`/`subquery` descending to the terminator's + // range item. The builder pushes the caller's `limit` and + // `order_by_ascending` directly into grovedb so the walk + // stops at `limit` elements in the requested direction — + // no Rust-side sort/reverse/truncate needed. + let (path_query_limit, left_to_right) = + (options.limit.map(|l| l as u16), options.order_by_ascending); + let path_query = + self.distinct_count_path_query(path_query_limit, left_to_right, platform_version)?; + let base_path_len = path_query.path.len(); + + let mut drive_operations = vec![]; + let result = drive.grove_get_raw_path_query( + &path_query, + transaction, + // PathKeyElementTrio so we can recover the In value from + // the emitted element's full path (for compound queries + // the In value sits at `path[base_path_len]` — the first + // segment beyond the path query's `path`). + QueryResultType::QueryPathKeyElementTrioResultType, + &mut drive_operations, + drive_version, + ); + let elements = match result { + Ok((elements, _)) => elements, + Err(Error::GroveDB(e)) + if matches!( + e.as_ref(), + grovedb::Error::PathNotFound(_) + | grovedb::Error::PathParentLayerNotFound(_) + | grovedb::Error::PathKeyNotFound(_) + ) => + { + // No matching prefix path — distinct mode returns + // an empty entry list. (Summed modes returned earlier + // via the aggregate fast path, so the empty case is + // distinct-only here.) + return Ok(Vec::new()); + } + Err(e) => return Err(e), + }; + + // Walk emitted `(path, key, element)` triples and build the + // unmerged entry list. For compound (In-on-prefix) queries + // the In value sits at `path[base_path_len]`; for flat + // queries `path.len() == base_path_len` so `in_key` is + // `None`. We DO NOT collapse multiple emitted entries with + // the same `key` into one — that's the whole point of the + // no-merge contract. + let mut entries: Vec = Vec::new(); + for triple in elements.to_path_key_elements() { + let (path, key, element) = triple; + let count = element.count_value_or_default(); + if count == 0 { + continue; + } + let in_key = if has_in_on_prefix && path.len() > base_path_len { + Some(path[base_path_len].clone()) + } else { + None + }; + entries.push(SplitCountEntry { in_key, key, count }); + } + + // Distinct mode: grovedb already emitted entries in the + // requested direction (controlled by `left_to_right`) and + // truncated to the path-query limit, so we return the entry + // list as-is. The In keys are lex-sorted by the builder + // (see `distinct_count_path_query`), so the natural emit + // order is `(in_key_lex_asc, key_lex_asc)` for ascending + // and `(in_key_lex_desc, key_lex_desc)` for descending — + // the documented order contract holds by construction. + // + // For pagination, callers narrow the range bound itself + // (`color > ` for the next page) rather than + // passing a cursor — see `RangeCountOptions::limit` doc. + Ok(entries) + } + + /// Generates a grovedb `AggregateCountOnRange` proof for a + /// range-count query against a `range_countable` index. The returned + /// proof bytes can be verified client-side via + /// `GroveDb::verify_aggregate_count_query`, which yields + /// `(root_hash, count)` — replacing the materialize-and-count proof + /// path that capped at `u16::MAX` documents. + /// + /// Limitations vs. [`Self::execute_range_count_no_proof`]: + /// - Returns ONLY the total count (a single number, no + /// per-distinct-value entries) — `AggregateCountOnRange` is a + /// single-aggregate primitive at the merk layer. + /// - Requires the prefix to resolve to exactly one path. `In` on + /// prefix properties is not supported because grovedb's aggregate + /// primitive only lifts a single inner range. + pub fn execute_aggregate_count_with_proof( + &self, + drive: &Drive, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result, Error> { + let drive_version = &platform_version.drive; + let path_query = self.aggregate_count_path_query(platform_version)?; + let proof = drive + .grove + .get_proved_path_query(&path_query, None, transaction, &drive_version.grove_version) + .unwrap() + .map_err(|e| Error::GroveDB(Box::new(e)))?; + Ok(proof) + } + + /// Generates a regular grovedb range proof against this count + /// query's `range_countable` index — the distinct-counts-with- + /// proof companion to [`Self::execute_aggregate_count_with_proof`]. + /// + /// No new prover code: the leaf is a `ProvableCountTree` and + /// merk's existing `prove_query` already emits `KVCount(key, + /// value, count)` per matched in-range key (via + /// `to_kv_count_node`). Each `count` is hash-bound to the merk + /// root via `node_hash_with_count`, so the per-key correctness + /// guarantee comes for free with the standard hash-chain check — + /// the SDK-side + /// [`drive_proof_verifier::verify_distinct_count_proof`] just + /// pulls the counts out of the proof's op stream after the + /// integrity check passes. + /// + /// Trade-off vs. the aggregate prove path: + /// - Returns per-distinct-value counts (one `(key, count)` per + /// matched lot value), not just a single sum. + /// - Proof size is O(distinct values matched), not O(log n) — so + /// ~1 `KVCount` op per matched key instead of subtree collapse + /// via `HashWithCount`. Still strictly smaller than + /// materialize-and-count, which would emit each underlying doc. + pub fn execute_distinct_count_with_proof( + &self, + drive: &Drive, + limit: u16, + left_to_right: bool, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result, Error> { + let drive_version = &platform_version.drive; + let path_query = + self.distinct_count_path_query(Some(limit), left_to_right, platform_version)?; + let proof = drive + .grove + .get_proved_path_query(&path_query, None, transaction, &drive_version.grove_version) + .unwrap() + .map_err(|e| Error::GroveDB(Box::new(e)))?; + Ok(proof) + } +} diff --git a/packages/rs-drive/src/query/drive_document_count_query/index_picker.rs b/packages/rs-drive/src/query/drive_document_count_query/index_picker.rs new file mode 100644 index 00000000000..002f2e38587 --- /dev/null +++ b/packages/rs-drive/src/query/drive_document_count_query/index_picker.rs @@ -0,0 +1,153 @@ +//! Index pickers for the count query. +//! +//! Pure functions on the document type's index map + where clauses; +//! no Drive, no proof. Picks a covering index for a given query +//! shape, returning `None` if no index can serve the query. + +use super::super::conditions::WhereClause; +use super::DriveDocumentCountQuery; +use dpp::data_contract::document_type::Index; +use std::collections::{BTreeMap, BTreeSet}; + +impl DriveDocumentCountQuery<'_> { + /// Finds a `countable: true` index whose properties **exactly match** the + /// indexable (Equal/In) where-clause fields — every index property has a + /// corresponding clause AND every clause's field appears in the index. + /// + /// Exact coverage is the contract for both no-proof and prove count + /// paths: a countable index counts exactly what it indexes, and queries + /// against partially-covered indexes are rejected with a clear error + /// directing the caller at the index-design fix. This avoids the + /// product-of-uncovered-branching-factors walk that a prefix-match + /// approach would silently fall through to, and keeps the storage's + /// "count maintained only at the terminal level" trade-off intact (no + /// need to maintain counts at intermediate index levels just to serve + /// partial-coverage queries cheaply). + /// + /// Returns `None` if: + /// - Any where clause uses an operator other than `Equal` / `In`. + /// - The set of indexable where-clause fields doesn't exactly equal the + /// set of properties of any single `countable: true` index. + /// + /// For the `documents_countable: true` case (total count with no where + /// clauses), the dispatcher reads the document-type primary-key tree's + /// CountTree directly — that path doesn't use this picker because no + /// index is involved. + pub fn find_countable_index_for_where_clauses<'b>( + indexes: &'b BTreeMap, + where_clauses: &[WhereClause], + ) -> Option<&'b Index> { + if Self::has_unsupported_operator(where_clauses) { + return None; + } + + let indexable_fields: BTreeSet<&str> = where_clauses + .iter() + .filter(|wc| Self::is_indexable_for_count(wc.operator)) + .map(|wc| wc.field.as_str()) + .collect(); + + // Need a clause for every property of the index, so empty + // `indexable_fields` only matches an empty-properties index + // (which doesn't exist — indexes always have at least one + // property — so empty where clauses never match here). + if indexable_fields.is_empty() { + return None; + } + + for index in indexes.values() { + if !index.countable.is_countable() { + continue; + } + if index.properties.len() != indexable_fields.len() { + continue; + } + // Every index property must have a matching where-clause + // field. Because lengths match, this also implies every + // where-clause field appears in the index (no orphan + // clauses). + let all_covered = index + .properties + .iter() + .all(|prop| indexable_fields.contains(prop.name.as_str())); + if all_covered { + return Some(index); + } + } + + None + } + + /// Finds a `range_countable` index that can serve a range-count query. + /// + /// Match criteria: + /// - All `Equal`/`In` where-clause fields form a prefix of the index + /// properties. + /// - There is exactly one range-operator where-clause, on a property + /// that is the *last* property of the index (the IndexLevel + /// terminator). This is the property whose values get walked. + /// - The index has `range_countable = true` and `countable.is_countable()`. + /// + /// Returns `None` if no such index exists or if there's more than one + /// range operator in the where clauses (which would require nested range + /// walks the current model doesn't support). Pure point-lookup queries + /// (no range operator) should fall back to + /// [`Self::find_countable_index_for_where_clauses`]. + pub fn find_range_countable_index_for_where_clauses<'b>( + indexes: &'b BTreeMap, + where_clauses: &[WhereClause], + ) -> Option<&'b Index> { + let range_clauses: Vec<&WhereClause> = where_clauses + .iter() + .filter(|wc| Self::is_range_operator(wc.operator)) + .collect(); + if range_clauses.len() != 1 { + return None; + } + let range_clause = range_clauses[0]; + + // Reject any operator that's neither indexable (Equal/In) nor a + // range operator — anything else has no defined count semantics. + if where_clauses.iter().any(|wc| { + !Self::is_indexable_for_count(wc.operator) && !Self::is_range_operator(wc.operator) + }) { + return None; + } + + let prefix_fields: BTreeSet<&str> = where_clauses + .iter() + .filter(|wc| Self::is_indexable_for_count(wc.operator)) + .map(|wc| wc.field.as_str()) + .collect(); + + for index in indexes.values() { + if !index.range_countable || !index.countable.is_countable() { + continue; + } + + // Walk the index properties: prefix matches must come first, + // followed by the range property as the LAST element. + let mut prefix_len = 0usize; + for prop in &index.properties { + if prefix_fields.contains(prop.name.as_str()) { + prefix_len += 1; + } else { + break; + } + } + if prefix_len < prefix_fields.len() { + continue; + } + if prefix_len + 1 != index.properties.len() { + // Range property must be the terminator (last property). + continue; + } + let range_prop = &index.properties[prefix_len]; + if range_prop.name == range_clause.field { + return Some(index); + } + } + + None + } +} diff --git a/packages/rs-drive/src/query/drive_document_count_query/mod.rs b/packages/rs-drive/src/query/drive_document_count_query/mod.rs index e7a34ae3f5f..d7eb5e688f6 100644 --- a/packages/rs-drive/src/query/drive_document_count_query/mod.rs +++ b/packages/rs-drive/src/query/drive_document_count_query/mod.rs @@ -1,33 +1,55 @@ -use std::collections::{BTreeMap, BTreeSet}; +//! Types and module structure for the `GetDocumentsCount` query. +//! +//! The implementation is split across siblings: +//! - [`mode_detection`] — operator classification + `detect_mode`. +//! - [`index_picker`] — covering-index pickers +//! (`find_countable_index_*`, `find_range_countable_index_*`). +//! - [`path_query`] — the load-bearing prover/verifier-agreement +//! path-query builders (`aggregate_count_path_query`, +//! `distinct_count_path_query`, `range_clause_to_query_item`). +//! - [`execute_point_lookup`] — Equal/In point-lookup execution +//! (`execute_no_proof`, `execute_with_proof`). +//! - [`execute_range_count`] — range-mode execution + `RangeCountOptions`. +//! - [`drive_dispatcher`] — `impl Drive` per-mode dispatchers + +//! `DocumentCountRequest` / `DocumentCountResponse` + +//! `execute_document_count_request`. +//! - [`tests`] (cfg `server` + `test`) — integration tests. +//! +//! This file owns the three public types every other submodule +//! references and the corresponding `mod` / `pub use` plumbing. +use dpp::data_contract::document_type::{DocumentTypeRef, Index}; + +use super::conditions::WhereClause; + +// Re-exports for the submodules and the `tests` module's +// `use super::*;`. `WhereOperator` is used by every submodule that +// builds path queries or executes; `QuerySyntaxError` is the canonical +// error variant the mode detector and dispatchers surface. +#[cfg(any(feature = "server", feature = "verify"))] +pub use super::conditions::WhereOperator; +#[cfg(any(feature = "server", feature = "verify"))] +pub use crate::error::query::QuerySyntaxError; + +pub mod mode_detection; +// Index pickers + path-query builders are reachable from both the +// server prove path and the SDK proof verifier; their submodule cfgs +// match. +pub mod index_picker; +pub mod path_query; + +// Server-side execution paths. #[cfg(feature = "server")] -use crate::drive::Drive; -#[cfg(feature = "server")] -use crate::error::query::QuerySyntaxError; -#[cfg(feature = "server")] -use crate::error::Error; -#[cfg(feature = "server")] -use crate::util::grove_operations::DirectQueryType; -#[cfg(feature = "server")] -use dpp::version::drive_versions::DriveVersion; -#[cfg(feature = "server")] -use grovedb::query_result_type::QueryResultType; +pub mod drive_dispatcher; #[cfg(feature = "server")] -use grovedb::{PathQuery, Query, SizedQuery, TransactionArg}; +pub mod execute_point_lookup; #[cfg(feature = "server")] -use grovedb_path::SubtreePath; +pub mod execute_range_count; #[cfg(feature = "server")] -use crate::drive::RootTree; -#[cfg(feature = "server")] -use dpp::data_contract::document_type::methods::DocumentTypeV0Methods; +pub use drive_dispatcher::{DocumentCountRequest, DocumentCountResponse}; #[cfg(feature = "server")] -use dpp::data_contract::document_type::IndexProperty; -use dpp::data_contract::document_type::{DocumentTypeRef, Index}; -#[cfg(feature = "server")] -use dpp::version::PlatformVersion; - -use super::conditions::{WhereClause, WhereOperator}; +pub use execute_range_count::RangeCountOptions; #[cfg(feature = "server")] #[cfg(test)] @@ -36,8 +58,7 @@ mod tests; /// A query to count documents using CountTree elements in the index path. /// /// This struct encapsulates all the information needed to perform a count -/// query on a document type's countable index, including optional split-by -/// functionality for getting per-value counts. +/// query on a document type's countable index. #[derive(Debug, Clone)] pub struct DriveDocumentCountQuery<'a> { /// The document type to count @@ -50,693 +71,90 @@ pub struct DriveDocumentCountQuery<'a> { pub index: &'a Index, /// The equality where clauses that match index prefix properties pub where_clauses: Vec, - /// Optional property to split counts by. When set, returns per-value - /// counts for this property instead of a single total count. - pub split_by_property: Option, } -/// An entry in a split count result, containing the serialized key -/// and the count of documents matching that key value. -#[derive(Debug, Clone, PartialEq)] +/// An entry in a split count result, containing the serialized +/// key(s) and the count of documents matching them. +/// +/// For flat queries (per-`In`-value mode without a range, or +/// per-distinct-value-in-range mode without an `In` on prefix) only +/// `key` is meaningful and `in_key` is `None`. +/// +/// For compound range-distinct queries (an `In` clause on a prefix +/// property plus a range on the terminator) BOTH keys are carried: +/// `in_key` is the In-fork's prefix value and `key` is the +/// terminator value. Cross-fork aggregation is intentionally NOT +/// done server-side — emitting the unmerged per-(in_key, key) shape +/// lets `limit` push directly into grovedb (no pre-merge issue), +/// keeps proof verification straightforward (no absence-proof +/// gymnastics for omitted In branches), and gives callers strictly +/// more information than a flat histogram. Callers reduce +/// client-side when they want the sum. +#[derive(Debug, Clone, PartialEq, Eq)] pub struct SplitCountEntry { - /// The serialized key bytes for this value + /// The serialized prefix key for compound queries (the `In` + /// value for this fork). `None` for flat queries. + pub in_key: Option>, + /// The serialized terminator/value key for this entry. pub key: Vec, - /// The count of documents matching this key value + /// The count of documents matching this `(in_key, key)` tuple + /// (or just `key` for flat queries). pub count: u64, } -impl<'a> DriveDocumentCountQuery<'a> { - /// Returns `true` if the where-clause operator is one the count fast path - /// can serve via point-lookups in a CountTree. - /// - /// Today that's `Equal` (one path) and `In` (cartesian fork over the listed - /// values). Range operators (`>`, `<`, `Between*`, `StartsWith`) need a - /// boundary walk that the current PathQuery infrastructure cannot express; - /// callers detect those via [`Self::has_unsupported_operator`] and surface - /// an error instead of silently returning a wrong count. - fn is_indexable_for_count(op: WhereOperator) -> bool { - matches!(op, WhereOperator::Equal | WhereOperator::In) - } - - /// Returns `true` if any where clause uses an operator the count fast path - /// cannot serve. Callers should treat this as a query-rejection signal. - pub fn has_unsupported_operator(where_clauses: &[WhereClause]) -> bool { - where_clauses - .iter() - .any(|wc| !Self::is_indexable_for_count(wc.operator)) - } - - /// Finds a countable index whose properties form a prefix that matches the - /// indexable (Equal / In) where-clause fields. For a count query: - /// - All indexable where-clause fields must appear as a prefix of the index properties - /// - The index must have `countable = true` - /// - Returns `None` if any where clause uses an operator other than `Equal` / `In` - /// - Among matching indexes, we prefer the one with the most properties - /// matched by where clauses (most specific) - pub fn find_countable_index_for_where_clauses<'b>( - indexes: &'b BTreeMap, - where_clauses: &[WhereClause], - ) -> Option<&'b Index> { - if Self::has_unsupported_operator(where_clauses) { - return None; - } - - let indexable_fields: BTreeSet<&str> = where_clauses - .iter() - .filter(|wc| Self::is_indexable_for_count(wc.operator)) - .map(|wc| wc.field.as_str()) - .collect(); - - let mut best_match: Option<(&Index, usize)> = None; - - for index in indexes.values() { - if !index.countable.is_countable() { - continue; - } - - // Check that the indexable where-clause fields form a prefix of - // the index properties. - let mut prefix_len = 0; - for prop in &index.properties { - if indexable_fields.contains(prop.name.as_str()) { - prefix_len += 1; - } else { - break; - } - } - - // All indexable where-clause fields must be consumed as a prefix. - if prefix_len < indexable_fields.len() { - continue; - } - - // Prefer the index with the longest matching prefix (most specific). - match &best_match { - None => best_match = Some((index, prefix_len)), - Some((_, best_len)) if prefix_len > *best_len => { - best_match = Some((index, prefix_len)); - } - _ => {} - } - } - - best_match.map(|(index, _)| index) - } - - /// Finds a countable index where: - /// - The indexable (Equal / In) where-clause fields form a prefix of the index properties - /// - The `split_property` is the next property after the covered prefix - /// - The index has `countable = true` - /// - Returns `None` if any where clause uses an operator other than `Equal` / `In` - pub fn find_countable_index_for_split<'b>( - indexes: &'b BTreeMap, - where_clauses: &[WhereClause], - split_property: &str, - ) -> Option<&'b Index> { - if Self::has_unsupported_operator(where_clauses) { - return None; - } - - let indexable_fields: BTreeSet<&str> = where_clauses - .iter() - .filter(|wc| Self::is_indexable_for_count(wc.operator)) - .map(|wc| wc.field.as_str()) - .collect(); - - for index in indexes.values() { - if !index.countable.is_countable() { - continue; - } - - // Check that indexable where-clause fields form a prefix. - let mut prefix_len = 0; - for prop in &index.properties { - if indexable_fields.contains(prop.name.as_str()) { - prefix_len += 1; - } else { - break; - } - } - - if prefix_len < indexable_fields.len() { - continue; - } - - // The split property must be the next property after the prefix. - if let Some(next_prop) = index.properties.get(prefix_len) { - if next_prop.name == split_property { - return Some(index); - } - } - } - - None - } - - /// Executes the count query without generating a proof. - /// - /// When `split_by_property` is `None`, returns the total count as a single - /// `SplitCountEntry` with an empty key. - /// - /// When `split_by_property` is `Some`, returns per-value counts for the - /// split property. - #[cfg(feature = "server")] - pub fn execute_no_proof( - &self, - drive: &Drive, - transaction: TransactionArg, - platform_version: &PlatformVersion, - ) -> Result, Error> { - if self.split_by_property.is_some() { - self.execute_split_count(drive, transaction, platform_version) - } else { - let count = self.execute_total_count(drive, transaction, platform_version)?; - Ok(vec![SplitCountEntry { key: vec![], count }]) - } - } - - /// Executes the count query and generates a GroveDB proof. - /// - /// Returns the raw proof bytes. The caller is responsible for verifying - /// the proof and extracting the count from the verified result. - #[cfg(feature = "server")] - pub fn execute_with_proof( - &self, - drive: &Drive, - transaction: TransactionArg, - platform_version: &PlatformVersion, - ) -> Result, Error> { - let drive_version = &platform_version.drive; - - // Build the same path as execute_no_proof - let mut path = vec![ - vec![RootTree::DataContractDocuments as u8], - self.contract_id.to_vec(), - vec![1u8], - self.document_type_name.as_bytes().to_vec(), - ]; - - // Walk the index properties, pushing property keys and equality values - for prop in &self.index.properties { - let matching_clause = self - .where_clauses - .iter() - .find(|wc| wc.field == prop.name && wc.operator == WhereOperator::Equal); - - if let Some(clause) = matching_clause { - path.push(prop.name.as_bytes().to_vec()); - let serialized_value = self.document_type.serialize_value_for_key( - prop.name.as_str(), - &clause.value, - platform_version, - )?; - path.push(serialized_value); - } else { - break; - } - } - - // Build a path query that covers the count tree and its contents - let mut query = Query::new(); - query.insert_all(); - - let path_query = PathQuery::new(path, SizedQuery::new(query, None, None)); - - let proof = drive - .grove - .get_proved_path_query(&path_query, None, transaction, &drive_version.grove_version) - .unwrap() - .map_err(|e| Error::GroveDB(Box::new(e)))?; - - Ok(proof) - } - - /// Executes the total count query, returning a single u64 count. - /// - /// Walks the index level-by-level, branching on `In` clauses (each value - /// adds a path) and falling through to [`Self::count_recursive`] for any - /// trailing index properties that have no matching where clause. - #[cfg(feature = "server")] - fn execute_total_count( - &self, - drive: &Drive, - transaction: TransactionArg, - platform_version: &PlatformVersion, - ) -> Result { - // Build the base path: [DataContractDocuments, contract_id, 1, doc_type_name] - let base_path = vec![ - vec![RootTree::DataContractDocuments as u8], - self.contract_id.to_vec(), - vec![1u8], - self.document_type_name.as_bytes().to_vec(), - ]; - - self.expand_paths_and_count(drive, base_path, 0, transaction, platform_version) - } - - /// Recursive helper for [`Self::execute_total_count`]. - /// - /// Visits the index property at `prop_idx`. If a matching where clause is - /// found: - /// - `Equal` → extend the current path with `(prop_name, value)` and recurse. - /// - `In` → for each value in the clause's array, clone the path, extend - /// with that value, recurse, and sum the per-branch counts. This is the - /// cartesian fork. - /// - anything else → unreachable; the index picker rejects the query. - /// - /// If no clause matches the current property, hand off to - /// [`Self::count_recursive`] which sums all sub-counts at the remaining - /// levels. - #[cfg(feature = "server")] - fn expand_paths_and_count( - &self, - drive: &Drive, - current_path: Vec>, - prop_idx: usize, - transaction: TransactionArg, - platform_version: &PlatformVersion, - ) -> Result { - let drive_version = &platform_version.drive; - - if prop_idx == self.index.properties.len() { - // All index properties resolved to a fixed key — O(1) read. - return Self::fetch_count_at_path(drive, ¤t_path, transaction, drive_version); - } - - let prop = &self.index.properties[prop_idx]; - let matching_clause = self.where_clauses.iter().find(|wc| wc.field == prop.name); - - let Some(clause) = matching_clause else { - // No clause for this property. Walk all values at the remaining - // levels and sum. - let remaining = &self.index.properties[prop_idx..]; - return Self::count_recursive( - drive, - current_path, - remaining, - transaction, - drive_version, - ); - }; - - match clause.operator { - WhereOperator::Equal => { - let mut new_path = current_path; - new_path.push(prop.name.as_bytes().to_vec()); - new_path.push(self.document_type.serialize_value_for_key( - prop.name.as_str(), - &clause.value, - platform_version, - )?); - self.expand_paths_and_count( - drive, - new_path, - prop_idx + 1, - transaction, - platform_version, - ) - } - WhereOperator::In => { - let values = clause.value.as_array().ok_or_else(|| { - Error::Query(QuerySyntaxError::InvalidWhereClauseComponents( - "In where-clause value must be an array", - )) - })?; - - // `In` is set-membership: serialize each value to the canonical - // index key and dedupe before forking. Without this, a query - // like `age in [30, 30]` would visit and sum the same subtree - // twice (Codex review finding #3). - let mut seen_keys: BTreeSet> = BTreeSet::new(); - let mut total: u64 = 0; - for v in values { - let serialized = self.document_type.serialize_value_for_key( - prop.name.as_str(), - v, - platform_version, - )?; - if !seen_keys.insert(serialized.clone()) { - continue; - } - let mut new_path = current_path.clone(); - new_path.push(prop.name.as_bytes().to_vec()); - new_path.push(serialized); - total = total.saturating_add(self.expand_paths_and_count( - drive, - new_path, - prop_idx + 1, - transaction, - platform_version, - )?); - } - Ok(total) - } - _ => Err(Error::Query( - QuerySyntaxError::InvalidWhereClauseComponents( - "count fast path supports only Equal and In where-clause operators", - ), - )), - } - } - - /// Executes a split count query, returning per-value counts for the - /// split property. - /// - /// Walks the index prefix that precedes `split_by_property` level by - /// level, branching on `In` clauses. For each fully-resolved prefix, - /// runs the per-split-value sub-query (see [`Self::collect_split_at_prefix`]) - /// and merges the results by split key, summing counts. - #[cfg(feature = "server")] - fn execute_split_count( - &self, - drive: &Drive, - transaction: TransactionArg, - platform_version: &PlatformVersion, - ) -> Result, Error> { - let split_property = self - .split_by_property - .as_deref() - .expect("split_by_property must be Some when calling execute_split_count"); - - let split_prop_idx = self - .index - .properties - .iter() - .position(|p| p.name == split_property) - .unwrap_or(0); - - let base_path = vec![ - vec![RootTree::DataContractDocuments as u8], - self.contract_id.to_vec(), - vec![1u8], - self.document_type_name.as_bytes().to_vec(), - ]; - - let mut merged: BTreeMap, u64> = BTreeMap::new(); - self.expand_split_prefix_paths( - drive, - base_path, - 0, - split_prop_idx, - split_property, - transaction, - platform_version, - &mut merged, - )?; - - Ok(merged - .into_iter() - .filter(|(_, count)| *count > 0) - .map(|(key, count)| SplitCountEntry { key, count }) - .collect()) - } - - /// Walks the index up to `split_prop_idx`, branching on `In`. At each - /// fully-resolved prefix, calls [`Self::collect_split_at_prefix`] to - /// gather the per-split-value counts, and accumulates them into `merged`. - #[cfg(feature = "server")] - #[allow(clippy::too_many_arguments)] - fn expand_split_prefix_paths( - &self, - drive: &Drive, - current_path: Vec>, - prop_idx: usize, - split_prop_idx: usize, - split_property: &str, - transaction: TransactionArg, - platform_version: &PlatformVersion, - merged: &mut BTreeMap, u64>, - ) -> Result<(), Error> { - if prop_idx == split_prop_idx { - // Reached the split property level under this prefix. Run the - // per-split-value sub-query and merge entries by key. - return self.collect_split_at_prefix( - drive, - current_path, - split_prop_idx, - split_property, - transaction, - platform_version, - merged, - ); - } - - let prop = &self.index.properties[prop_idx]; - let clause = self - .where_clauses - .iter() - .find(|wc| wc.field == prop.name) - .ok_or_else(|| { - // The index picker guarantees every property before the split - // property has a matching clause; missing one indicates a - // mis-picked index. - Error::Query(QuerySyntaxError::InvalidWhereClauseComponents( - "split count: missing where clause for an index property preceding the split property", - )) - })?; - - match clause.operator { - WhereOperator::Equal => { - let mut new_path = current_path; - new_path.push(prop.name.as_bytes().to_vec()); - new_path.push(self.document_type.serialize_value_for_key( - prop.name.as_str(), - &clause.value, - platform_version, - )?); - self.expand_split_prefix_paths( - drive, - new_path, - prop_idx + 1, - split_prop_idx, - split_property, - transaction, - platform_version, - merged, - ) - } - WhereOperator::In => { - let values = clause.value.as_array().ok_or_else(|| { - Error::Query(QuerySyntaxError::InvalidWhereClauseComponents( - "In where-clause value must be an array", - )) - })?; - - // Same dedup as in `expand_paths_and_count`: serialize each - // value to the canonical index key and skip duplicates. - // Without this, a duplicated `In` value on the prefix would - // visit the same prefix subtree twice and double its - // contribution to the merged split counts. - let mut seen_keys: BTreeSet> = BTreeSet::new(); - for v in values { - let serialized = self.document_type.serialize_value_for_key( - prop.name.as_str(), - v, - platform_version, - )?; - if !seen_keys.insert(serialized.clone()) { - continue; - } - let mut new_path = current_path.clone(); - new_path.push(prop.name.as_bytes().to_vec()); - new_path.push(serialized); - self.expand_split_prefix_paths( - drive, - new_path, - prop_idx + 1, - split_prop_idx, - split_property, - transaction, - platform_version, - merged, - )?; - } - Ok(()) - } - _ => Err(Error::Query( - QuerySyntaxError::InvalidWhereClauseComponents( - "split count fast path supports only Equal and In where-clause operators", - ), - )), - } - } - - /// Reads all per-value sub-counts for `split_property` under - /// `prefix_path`, summing per-key counts into `merged`. Mirrors the - /// original (pre-`In`-support) loop; factored out so the prefix-walk - /// recursion can call it once per resolved prefix. - #[cfg(feature = "server")] - #[allow(clippy::too_many_arguments)] - fn collect_split_at_prefix( - &self, - drive: &Drive, - prefix_path: Vec>, - split_prop_idx: usize, - split_property: &str, - transaction: TransactionArg, - platform_version: &PlatformVersion, - merged: &mut BTreeMap, u64>, - ) -> Result<(), Error> { - let drive_version = &platform_version.drive; - - // Push the split-property key onto the prefix to address the per-value - // subtree level. - let mut path = prefix_path; - path.push(split_property.as_bytes().to_vec()); - - let mut query = Query::new(); - query.insert_all(); - let path_query = PathQuery::new(path.clone(), SizedQuery::new(query, None, None)); - - let mut drive_operations = vec![]; - let result = drive.grove_get_raw_path_query( - &path_query, - transaction, - QueryResultType::QueryKeyElementPairResultType, - &mut drive_operations, - drive_version, - ); - - let (elements, _) = match result { - Ok(result) => result, - Err(Error::GroveDB(e)) - if matches!( - e.as_ref(), - grovedb::Error::PathNotFound(_) - | grovedb::Error::PathParentLayerNotFound(_) - | grovedb::Error::PathKeyNotFound(_) - ) => - { - // No documents under this prefix; nothing to merge. - return Ok(()); - } - Err(e) => return Err(e), - }; - - let key_elements = elements.to_key_elements(); - if key_elements.is_empty() { - return Ok(()); - } - - let remaining_properties = &self.index.properties[split_prop_idx + 1..]; - - for (key, _element) in key_elements { - let mut value_path = path.clone(); - value_path.push(key.clone()); - - let count = if remaining_properties.is_empty() { - Self::fetch_count_at_path(drive, &value_path, transaction, drive_version)? - } else { - Self::count_recursive( - drive, - value_path, - remaining_properties, - transaction, - drive_version, - )? - }; - - if count == 0 { - continue; - } - *merged.entry(key).or_insert(0) += count; - } - - Ok(()) - } - - /// Fetches the CountTree element count at the given path. - /// The CountTree element is at key [0] under the path. - #[cfg(feature = "server")] - fn fetch_count_at_path( - drive: &Drive, - path: &[Vec], - transaction: TransactionArg, - drive_version: &DriveVersion, - ) -> Result { - let mut drive_operations = vec![]; - let path_refs: Vec<&[u8]> = path.iter().map(|p| p.as_slice()).collect(); - let element = drive.grove_get_raw_optional( - SubtreePath::from(path_refs.as_slice()), - &[0], - DirectQueryType::StatefulDirectQuery, - transaction, - &mut drive_operations, - drive_version, - )?; - - Ok(element.map_or(0, |e| e.count_value_or_default())) - } - - /// Recursively descends through remaining index property levels, - /// iterating over all values at each level, and sums the CountTree - /// counts at the terminal level. - #[cfg(feature = "server")] - fn count_recursive( - drive: &Drive, - current_path: Vec>, - remaining_properties: &[IndexProperty], - transaction: TransactionArg, - drive_version: &DriveVersion, - ) -> Result { - if remaining_properties.is_empty() { - return Self::fetch_count_at_path(drive, ¤t_path, transaction, drive_version); - } - - let prop = &remaining_properties[0]; - let rest = &remaining_properties[1..]; - - // Push the index property key to descend into that level - let mut property_path = current_path; - property_path.push(prop.name.as_bytes().to_vec()); - - // Query all children (value subtrees) at this property level - let mut query = Query::new(); - query.insert_all(); - - let path_query = PathQuery::new(property_path.clone(), SizedQuery::new(query, None, None)); - - let mut drive_operations = vec![]; - let result = drive.grove_get_raw_path_query( - &path_query, - transaction, - QueryResultType::QueryKeyElementPairResultType, - &mut drive_operations, - drive_version, - ); - - let (elements, _) = match result { - Ok(result) => result, - Err(Error::GroveDB(e)) - if matches!( - e.as_ref(), - grovedb::Error::PathNotFound(_) - | grovedb::Error::PathParentLayerNotFound(_) - | grovedb::Error::PathKeyNotFound(_) - ) => - { - return Ok(0); - } - Err(e) => return Err(e), - }; - - let key_elements = elements.to_key_elements(); - - if key_elements.is_empty() { - return Ok(0); - } - - let mut total_count: u64 = 0; - - for (key, _element) in key_elements { - let mut value_path = property_path.clone(); - value_path.push(key); - - let sub_count = - Self::count_recursive(drive, value_path, rest, transaction, drive_version)?; - total_count = total_count.saturating_add(sub_count); - } - - Ok(total_count) - } +/// Classification of a count query's shape, used to dispatch to the +/// right executor. Returned by +/// [`DriveDocumentCountQuery::detect_mode`]. +/// +/// The discriminator is purely a function of the where-clause operators +/// + request flags (`return_distinct_counts_in_range`, `prove`); it +/// does not depend on the contract's index set. Picking a covering +/// index for the chosen mode is a separate step that requires the +/// document type's `BTreeMap`. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum DocumentCountMode { + /// No range, no `In` — single summed entry with empty key. Reads + /// the `CountTree` count directly at the indexed path. + Total, + /// Exactly one `In` clause, no range — one entry per (deduped) + /// `In` value, each computed as the count at that single value. + /// The `In` doubles as the per-value split signal. + PerInValue, + /// Exactly one range clause, no proof — walks the property-name + /// `ProvableCountTree`'s children inside the range. Returns either + /// a single summed entry or per-distinct-value entries depending on + /// `return_distinct_counts_in_range`. + RangeNoProof, + /// Exactly one range clause + `prove = true` + + /// `return_distinct_counts_in_range = false` — produces a grovedb + /// `AggregateCountOnRange` proof that verifies to a single u64. + /// The merk-level primitive returns one aggregate; per-distinct- + /// value entries with proof go through [`Self::RangeDistinctProof`] + /// instead. + RangeProof, + /// Exactly one range clause + `prove = true` + + /// `return_distinct_counts_in_range = true` — produces a regular + /// range proof against the property-name `ProvableCountTree`. The + /// proof's `KVCount(key, value, count)` ops carry per-distinct- + /// value counts, each cryptographically committed via + /// `node_hash_with_count` to the merk root. The verifier walks the + /// proof op stream and emits a per-key count map, no opt-in + /// aggregate-collapse wrapper. Proof size is O(distinct values + /// matched) rather than the O(log n) of [`Self::RangeProof`], but + /// still much smaller than materialize-and-count. + RangeDistinctProof, + /// No range clause + `prove = true` — produces a per-branch + /// `Element::CountTree` proof. Either an unfiltered total + /// (`documents_countable: true` fast path, proving the + /// doctype's primary-key CountTree directly) or a covered + /// Equal/`In` lookup against a `countable: true` index (proving + /// one CountTree element per matched branch via + /// [`DriveDocumentCountQuery::point_lookup_count_path_query`]). + /// Proof size is O(k × log n) where k is the number of covered + /// branches (1 for the empty-where fast path and Equal-only + /// fully-covered case; ≤ |In values| for In-on-prefix). No + /// document materialization, no `u16::MAX` matching-docs cap — + /// the merk-level `count_value` IS the result, the SDK + /// extracts it via `verify_point_lookup_count_proof`. + PointLookupProof, } diff --git a/packages/rs-drive/src/query/drive_document_count_query/mode_detection.rs b/packages/rs-drive/src/query/drive_document_count_query/mode_detection.rs new file mode 100644 index 00000000000..5e864c59e73 --- /dev/null +++ b/packages/rs-drive/src/query/drive_document_count_query/mode_detection.rs @@ -0,0 +1,196 @@ +//! Mode detection + operator classification for the count query. +//! +//! Pure functions on the where-clause shape + request flags — no +//! Drive, no contract, no indexes. Used both server-side (to pick an +//! executor) and verifier-side (to validate the request before +//! attempting verification). + +use super::super::conditions::{WhereClause, WhereOperator}; +use super::{DocumentCountMode, DriveDocumentCountQuery}; +#[cfg(any(feature = "server", feature = "verify"))] +use crate::error::query::QuerySyntaxError; + +impl DriveDocumentCountQuery<'_> { + /// Returns `true` if the where-clause operator is one the count fast path + /// can serve via point-lookups in a CountTree. + /// + /// Today that's `Equal` (one path) and `In` (cartesian fork over the listed + /// values). Range operators (`>`, `<`, `Between*`, `StartsWith`) need a + /// boundary walk that the current PathQuery infrastructure cannot express; + /// callers detect those via [`Self::has_unsupported_operator`] and surface + /// an error instead of silently returning a wrong count. + /// + /// `pub(super)` so the sibling [`index_picker`](super::index_picker) module + /// can call it from `Self::is_indexable_for_count`; not part of the public + /// API. + pub(super) fn is_indexable_for_count(op: WhereOperator) -> bool { + matches!(op, WhereOperator::Equal | WhereOperator::In) + } + + /// Returns `true` if `op` is a range operator that can be served by a + /// `range_countable` index walking the property-name `ProvableCountTree`'s + /// children. The non-prefix portion of a range count query carries + /// exactly one range operator on the index's last property. + pub fn is_range_operator(op: WhereOperator) -> bool { + matches!( + op, + WhereOperator::GreaterThan + | WhereOperator::GreaterThanOrEquals + | WhereOperator::LessThan + | WhereOperator::LessThanOrEquals + | WhereOperator::Between + | WhereOperator::BetweenExcludeBounds + | WhereOperator::BetweenExcludeLeft + | WhereOperator::BetweenExcludeRight + | WhereOperator::StartsWith + ) + } + + /// Returns `true` if any where clause uses an operator the count fast path + /// cannot serve. Callers should treat this as a query-rejection signal. + pub fn has_unsupported_operator(where_clauses: &[WhereClause]) -> bool { + where_clauses + .iter() + .any(|wc| !Self::is_indexable_for_count(wc.operator)) + } + + /// Classify a count query's mode from its where clauses + request flags. + /// + /// This is the protocol-version-agnostic shape detection that decides + /// which executor (Equal/In point lookup, range walk, range proof, + /// materialize-and-count proof, etc.) the request maps to. The + /// returned [`DocumentCountMode`] discriminates among the handler's + /// dispatch arms; concrete pagination / index-picker inputs still + /// flow through the call sites separately. + /// + /// All validation that depends only on the where clauses + flags + /// (multiple range clauses, range mixed with `In`, distinct mode on + /// the prove path, distinct mode without a range clause, etc.) is + /// done here and surfaces as + /// [`QuerySyntaxError::InvalidWhereClauseComponents`]. Validation + /// that depends on the contract's index set (no covering index) + /// stays at the call site since it requires the + /// `&BTreeMap`. + #[cfg(any(feature = "server", feature = "verify"))] + pub fn detect_mode( + where_clauses: &[WhereClause], + return_distinct_counts_in_range: bool, + prove: bool, + ) -> Result { + // Reject any operator that's neither an indexable point operator + // (Equal/In) nor a range operator. Defense-in-depth: the request + // shape forbids these elsewhere, but folding the check in here + // keeps the mode-detection contract self-contained. + // + // `startsWith` IS in `is_range_operator` and routes through the + // same `Range(a..b)` path as `betweenExcludeRight` — the + // half-open upper bound is computed by byte-incrementing the + // serialized prefix's last byte (see `range_clause_to_query_item`, + // mirroring `conditions.rs:1129`'s normal-docs encoding). + for wc in where_clauses { + if !Self::is_indexable_for_count(wc.operator) && !Self::is_range_operator(wc.operator) { + return Err(QuerySyntaxError::InvalidWhereClauseComponents( + "count query supports only `==`, `in`, and range operators", + )); + } + } + + let range_count = where_clauses + .iter() + .filter(|wc| Self::is_range_operator(wc.operator)) + .count(); + let in_count = where_clauses + .iter() + .filter(|wc| wc.operator == WhereOperator::In) + .count(); + + if range_count > 1 { + return Err(QuerySyntaxError::InvalidWhereClauseComponents( + "count query supports at most one range where-clause; combine \ + two-sided ranges via `between*` instead of separate `>` / `<` clauses", + )); + } + if in_count > 1 { + return Err(QuerySyntaxError::InvalidWhereClauseComponents( + "count query supports at most one `in` where-clause; the In carries \ + the split property and only one split dimension is supported per request", + )); + } + + let has_range = range_count == 1; + let has_in = in_count == 1; + + // `range + In` is only rejected on the aggregate prove path + // (grovedb's `AggregateCountOnRange` primitive wraps a single + // inner range and can't cartesian-fork over multiple In + // values at the merk layer — see the comment on + // `aggregate_count_path_query`). For distinct modes (both + // no-proof and prove) and for total-range-no-proof, the + // `distinct_count_path_query` builder handles In on prefix + // via grovedb's native subquery primitive. + if has_range && has_in && prove && !return_distinct_counts_in_range { + return Err(QuerySyntaxError::InvalidWhereClauseComponents( + "range count queries with an `in` clause are not supported on the \ + aggregate prove path; use `return_distinct_counts_in_range = true` \ + for compound In-on-prefix prove queries, or `prove = false` for the \ + no-proof variant", + )); + } + + if return_distinct_counts_in_range && !has_range { + return Err(QuerySyntaxError::InvalidWhereClauseComponents( + "return_distinct_counts_in_range requires a range where-clause", + )); + } + + Ok( + match (has_range, has_in, prove, return_distinct_counts_in_range) { + // Range + prove + distinct (with or without In on + // prefix): per-distinct-value counts come from a + // regular range proof against the property-name + // `ProvableCountTree`. With In on prefix the path + // query uses grovedb's subquery primitive to + // cartesian-fork; the verifier walks the same + // compound shape. + (true, _, true, true) => DocumentCountMode::RangeDistinctProof, + // Range + prove + summed (no In): `AggregateCountOnRange` + // collapse — single u64 verified out. The In case is + // rejected above. + (true, false, true, false) => DocumentCountMode::RangeProof, + // Range + no-proof: the executor uses the same + // `distinct_count_path_query` builder; In on prefix + // forks via grovedb subquery at execution time. Sum + // vs. distinct comes from `RangeCountOptions.distinct` + // applied to the merged result. + (true, _, false, _) => DocumentCountMode::RangeNoProof, + (false, true, false, _) => DocumentCountMode::PerInValue, + // `In` + `prove = true` (no range): route to the + // CountTree-element proof path. The shared + // `point_lookup_count_path_query` builder emits one + // `Element::CountTree` per matched In branch (via + // outer `Key`s + `[0]` subquery); the SDK's + // `verify_point_lookup_count_proof` extracts + // `count_value_or_default()` from each verified + // element and the `FromProof` + // for `DocumentSplitCounts` returns them as + // per-In-value entries. Proof size is O(|In values| + // × log n) — no document materialization, no + // `u16::MAX` cap on matching docs. + (false, true, true, _) => DocumentCountMode::PointLookupProof, + // No range, no In, `prove = true`: same CountTree- + // element proof shape — either the documents_countable + // primary-key CountTree fast path (empty where) or + // a single per-branch CountTree element for an + // Equal-only fully-covered query. + (false, false, true, _) => DocumentCountMode::PointLookupProof, + (false, false, false, _) => DocumentCountMode::Total, + // (true, true, true, false) — range + In on the + // aggregate prove path — is rejected by the + // explicit early check above. + (true, true, true, false) => unreachable!( + "range + In + prove + !distinct is rejected before the dispatch match" + ), + }, + ) + } +} diff --git a/packages/rs-drive/src/query/drive_document_count_query/path_query.rs b/packages/rs-drive/src/query/drive_document_count_query/path_query.rs new file mode 100644 index 00000000000..37ad8ac8378 --- /dev/null +++ b/packages/rs-drive/src/query/drive_document_count_query/path_query.rs @@ -0,0 +1,754 @@ +//! Path-query builders for the count query. +//! +//! These are the **load-bearing prover/verifier-agreement boundary**: +//! the bytes these builders produce must match byte-for-byte between +//! the prover and the verifier, or the merk-root recomputation +//! fails. Touching anything here without updating both the +//! server-side prove executor AND the SDK's verifier path-query +//! reconstruction simultaneously is a bug waiting to happen. +//! +//! All three builders are gated `#[cfg(any(feature = "server", +//! feature = "verify"))]` so the verifier crate (which only enables +//! `verify`) can reach them via `DriveDocumentCountQuery::*` method +//! syntax. + +#![cfg(any(feature = "server", feature = "verify"))] + +use super::super::conditions::{WhereClause, WhereOperator}; +use super::DriveDocumentCountQuery; +use crate::drive::RootTree; +use crate::error::query::QuerySyntaxError; +use crate::error::Error; +use dpp::data_contract::document_type::methods::DocumentTypeV0Methods; +use dpp::version::PlatformVersion; +use grovedb::{PathQuery, Query, QueryItem, SizedQuery}; + +impl DriveDocumentCountQuery<'_> { + /// Convert a single range where-clause + value into the grovedb + /// `QueryItem` used to walk children of the property-name + /// `ProvableCountTree`. The clause's value is serialized via the + /// document type's `serialize_value_for_key`, which produces the + /// canonical bytes used everywhere else in the index path. + /// + /// Range mappings: + /// - `>` → `RangeAfter(value..)` (exclusive lower) + /// - `>=` → `RangeFrom(value..)` (inclusive lower) + /// - `<` → `RangeTo(..value)` (exclusive upper) + /// - `<=` → `RangeToInclusive(..=value)` (inclusive upper) + /// - `between [a, b]` → `RangeInclusive(a..=b)` (inclusive both) + /// - `between (a, b)` → `RangeAfterTo(a..b)` (exclusive both — the + /// inner range is half-open in grovedb terms; this models + /// exclude-bounds) + /// - `between (a, b]` → `RangeAfterToInclusive(a..=b)` + /// - `between [a, b)` → `Range(a..b)` + /// - `startsWith "p"` → `Range(serialize("p")..serialize("p") with + /// last byte +1)` — same byte-incremented half-open encoding the + /// normal docs path uses (see `conditions.rs:1129`'s `StartsWith` + /// arm). `value_shape_ok` constrains the prefix to `Value::Text`, + /// and valid UTF-8 never contains `0xFF`, so the `+1` doesn't + /// overflow for valid string keys; the unlikely 0xFF-tail case is + /// caught via `checked_add` and rejected with a clear error. + fn range_clause_to_query_item( + &self, + clause: &WhereClause, + platform_version: &PlatformVersion, + ) -> Result { + let serialize = |v: &dpp::platform_value::Value| -> Result, Error> { + Ok(self.document_type.serialize_value_for_key( + clause.field.as_str(), + v, + platform_version, + )?) + }; + // Shared helper for all four `between*` operators. The + // operator the caller used (`between`, `betweenExcludeBounds`, + // etc.) is not woven into error messages because + // `InvalidWhereClauseComponents` takes `&'static str` — a + // String-typed error variant would let us do that, but the + // existing static-string contract is fine to live with: the + // arm name (`WhereOperator::Between` etc.) is visible in + // backtraces if a malformed payload reaches this far, and + // mode detection has already filtered out non-range operators. + let serialize_pair = || -> Result<(Vec, Vec), Error> { + let arr = clause.value.as_array().ok_or_else(|| { + Error::Query(QuerySyntaxError::InvalidWhereClauseComponents( + "range bounds value must be a 2-element array", + )) + })?; + if arr.len() != 2 { + return Err(Error::Query( + QuerySyntaxError::InvalidWhereClauseComponents( + "range bounds value must be a 2-element array", + ), + )); + } + let a = serialize(&arr[0])?; + let b = serialize(&arr[1])?; + if a > b { + return Err(Error::Query( + QuerySyntaxError::InvalidWhereClauseComponents( + "range lower bound must be <= upper bound", + ), + )); + } + Ok((a, b)) + }; + + Ok(match clause.operator { + WhereOperator::GreaterThan => { + let v = serialize(&clause.value)?; + QueryItem::RangeAfter(v..) + } + WhereOperator::GreaterThanOrEquals => { + let v = serialize(&clause.value)?; + QueryItem::RangeFrom(v..) + } + WhereOperator::LessThan => { + let v = serialize(&clause.value)?; + QueryItem::RangeTo(..v) + } + WhereOperator::LessThanOrEquals => { + let v = serialize(&clause.value)?; + QueryItem::RangeToInclusive(..=v) + } + WhereOperator::Between => { + let (a, b) = serialize_pair()?; + QueryItem::RangeInclusive(a..=b) + } + WhereOperator::BetweenExcludeBounds => { + let (a, b) = serialize_pair()?; + QueryItem::RangeAfterTo(a..b) + } + WhereOperator::BetweenExcludeLeft => { + let (a, b) = serialize_pair()?; + QueryItem::RangeAfterToInclusive(a..=b) + } + WhereOperator::BetweenExcludeRight => { + let (a, b) = serialize_pair()?; + QueryItem::Range(a..b) + } + WhereOperator::StartsWith => { + let left_key = serialize(&clause.value)?; + let mut right_key = left_key.clone(); + // Byte-increment the last byte to form the half-open + // upper bound `[prefix, prefix+1)`. Mirrors the + // normal-docs encoding in `conditions.rs:1129`'s + // `StartsWith` arm; we use `checked_add` so the + // pathological `0xFF`-tail input fails loudly instead + // of wrapping silently (UTF-8 never contains 0xFF so + // valid string keys never hit this). + let last = right_key.last_mut().ok_or_else(|| { + Error::Query(QuerySyntaxError::InvalidStartsWithClause( + "startsWith prefix must have at least one byte", + )) + })?; + *last = last.checked_add(1).ok_or_else(|| { + Error::Query(QuerySyntaxError::InvalidStartsWithClause( + "startsWith prefix ends in 0xFF; cannot form half-open upper bound", + )) + })?; + QueryItem::Range(left_key..right_key) + } + _ => { + return Err(Error::Query( + QuerySyntaxError::InvalidWhereClauseComponents( + "range_clause_to_query_item called on a non-range operator", + ), + )); + } + }) + } + + /// Build the grovedb `PathQuery` for an `AggregateCountOnRange` + /// query against this count query's `range_countable` index. + /// + /// Shared between the server-side prove path + /// ([`Self::execute_aggregate_count_with_proof`]) and the client- + /// side verify path (the SDK's `FromProof` for + /// `DocumentCount`). Both sides must produce the *exact same* + /// `PathQuery` for verification to recompute the same merk root. + /// + /// Aggregate-count specifically restricts prefix props to `Equal`: + /// grovedb's `AggregateCountOnRange` primitive wraps a *single* + /// inner range and emits one aggregate `u64` — there's no way for + /// it to cartesian-fork over multiple In values at the merk + /// layer. For per-distinct-value counts with In on prefix, use + /// [`Self::distinct_count_path_query`] instead. + /// + /// Errors: + /// - No range where-clause / multiple range where-clauses → + /// `InvalidWhereClauseComponents` + /// - `In` on a prefix property → `InvalidWhereClauseComponents` + /// (aggregate primitive can't fork) + /// - Missing prefix clause → `InvalidWhereClauseComponents` + pub fn aggregate_count_path_query( + &self, + platform_version: &PlatformVersion, + ) -> Result { + let range_clause = self + .where_clauses + .iter() + .find(|wc| Self::is_range_operator(wc.operator)) + .ok_or(Error::Query( + QuerySyntaxError::InvalidWhereClauseComponents( + "aggregate_count_path_query requires a range where-clause", + ), + ))?; + let query_item = self.range_clause_to_query_item(range_clause, platform_version)?; + + let mut path = vec![ + vec![RootTree::DataContractDocuments as u8], + self.contract_id.to_vec(), + vec![1u8], + self.document_type_name.as_bytes().to_vec(), + ]; + let prefix_props = &self.index.properties[..self.index.properties.len() - 1]; + for prop in prefix_props { + let clause = self + .where_clauses + .iter() + .find(|wc| wc.field == prop.name) + .ok_or(Error::Query( + QuerySyntaxError::InvalidWhereClauseComponents( + "aggregate-count proof: missing where clause for an index prefix property", + ), + ))?; + if clause.operator != WhereOperator::Equal { + return Err(Error::Query( + QuerySyntaxError::InvalidWhereClauseComponents( + "aggregate-count proof: prefix properties must use `==` (no `in`); \ + use `return_distinct_counts_in_range = true` for compound In-on-prefix \ + queries", + ), + )); + } + path.push(prop.name.as_bytes().to_vec()); + path.push(self.document_type.serialize_value_for_key( + prop.name.as_str(), + &clause.value, + platform_version, + )?); + } + let range_prop_name = &self + .index + .properties + .last() + .ok_or(Error::Query( + QuerySyntaxError::InvalidWhereClauseComponents( + "range_countable index must have at least one property", + ), + ))? + .name; + path.push(range_prop_name.as_bytes().to_vec()); + + Ok(PathQuery::new_aggregate_count_on_range(path, query_item)) + } + + /// Build the grovedb `PathQuery` for a *regular* range query + /// against this count query's `range_countable` index — the + /// distinct-counts variant. Used by: + /// - the server's prove-distinct executor + /// ([`Self::execute_distinct_count_with_proof`]) + /// - the server's no-proof range executor + /// ([`Self::execute_range_count_no_proof`]) + /// - the SDK's per-key-count verifier + /// ([`drive_proof_verifier::verify_distinct_count_proof`]) + /// + /// **In-on-prefix support via grovedb subqueries.** Where + /// [`Self::aggregate_count_path_query`] rejects In on prefix + /// (the aggregate merk primitive can't cartesian-fork), this + /// builder uses grovedb's native subquery primitive: + /// + /// - **Flat shape** (no In on prefix, only Equal): path includes + /// the range terminator; outer Query has the range item. + /// - **Compound shape** (one In on prefix): path stops at the + /// In-bearing prop's property-name subtree; outer Query has + /// one `Key(value)` item per In value; `set_subquery_path` + /// carries any post-In Equal-clause `(name, value)` pairs plus + /// the terminator name; `set_subquery` is the range item. + /// + /// Both shapes return `(path, branched-or-flat Query)` and feed + /// the same `grove_get_raw_path_query` / `get_proved_path_query` + /// pipelines downstream. The compound shape replaces the + /// pre-existing cartesian-fork loop in + /// `execute_range_count_no_proof`. + /// + /// `limit` IS load-bearing for prove-path verification: the + /// prover bounds the proof at `limit` matched keys, and the + /// verifier must build the exact same `PathQuery` (including + /// this cap) for the merk-root recomputation to match. The + /// dispatcher pre-validates `limit ≤ max_query_limit` on the + /// prove path, so unbounded queries can't reach this builder + /// with `Some(...)` greater than the cap. The no-proof path + /// passes `None` (full walk) so cross-In-fork merging sees + /// every emitted element before the result-set-level limit is + /// applied in post-processing. + /// + /// `left_to_right` controls grovedb's iteration direction: + /// `true` (the default, used for ascending `order_by_ascending`) + /// walks the range from low key to high key; `false` reverses. + /// On the prove path this is load-bearing: the path query's + /// `Query.left_to_right` is part of the serialized PathQuery + /// bytes, so the prover and verifier must agree on the value or + /// the merk-root recomputation fails. For compound queries the + /// flag is applied to BOTH the outer In-keys Query and the + /// inner range subquery, so descending iteration walks + /// `(in_key_desc, key_desc)` tuples (matching what + /// `RangeCountOptions::order_by_ascending = false` callers + /// expect). + /// + /// Errors: + /// - No range where-clause / multiple range where-clauses + /// - Multiple In clauses on prefix props + /// - Non-Equal-non-In operator on a prefix prop + /// - Missing prefix clause + pub fn distinct_count_path_query( + &self, + limit: Option, + left_to_right: bool, + platform_version: &PlatformVersion, + ) -> Result { + let range_clause = self + .where_clauses + .iter() + .find(|wc| Self::is_range_operator(wc.operator)) + .ok_or(Error::Query( + QuerySyntaxError::InvalidWhereClauseComponents( + "distinct_count_path_query requires a range where-clause", + ), + ))?; + let range_item = self.range_clause_to_query_item(range_clause, platform_version)?; + + let prefix_props = &self.index.properties[..self.index.properties.len() - 1]; + let terminator_name = &self + .index + .properties + .last() + .ok_or(Error::Query( + QuerySyntaxError::InvalidWhereClauseComponents( + "range_countable index must have at least one property", + ), + ))? + .name; + + let mut base_path: Vec> = vec![ + vec![RootTree::DataContractDocuments as u8], + self.contract_id.to_vec(), + vec![1u8], + self.document_type_name.as_bytes().to_vec(), + ]; + + // `Some(keys)` once an In clause has been encountered on a + // prefix property. From that point on, subsequent Equal + // clauses go into `subquery_path_extension` rather than + // `base_path`. Only one In allowed (multiple Ins would + // multiply the fork count beyond what a single Query can + // express via `set_subquery_path`). + let mut in_outer_keys: Option>> = None; + let mut subquery_path_extension: Vec> = vec![]; + + for prop in prefix_props { + let clause = self + .where_clauses + .iter() + .find(|wc| wc.field == prop.name) + .ok_or(Error::Query( + QuerySyntaxError::InvalidWhereClauseComponents( + "distinct_count_path_query: missing where clause for an index \ + prefix property", + ), + ))?; + + match clause.operator { + WhereOperator::Equal => { + let serialized = self.document_type.serialize_value_for_key( + prop.name.as_str(), + &clause.value, + platform_version, + )?; + if in_outer_keys.is_some() { + subquery_path_extension.push(prop.name.as_bytes().to_vec()); + subquery_path_extension.push(serialized); + } else { + base_path.push(prop.name.as_bytes().to_vec()); + base_path.push(serialized); + } + } + WhereOperator::In => { + if in_outer_keys.is_some() { + return Err(Error::Query( + QuerySyntaxError::InvalidWhereClauseComponents( + "distinct_count_path_query: at most one `In` clause is supported \ + on prefix properties", + ), + )); + } + // Path stops at the In-bearing prop's property- + // name subtree; outer Query lives at that level. + base_path.push(prop.name.as_bytes().to_vec()); + let in_values = clause.in_values().into_data_with_error()??; + let mut keys: Vec> = in_values + .iter() + .map(|v| { + self.document_type.serialize_value_for_key( + prop.name.as_str(), + v, + platform_version, + ) + }) + .collect::>()?; + // Sort the serialized In keys lex-ascending before + // building the outer Query. This is load-bearing + // for both correctness and DoS-resistance: + // - **Order parity**: grovedb iterates `Key` items + // in insert order. Without sorting, the emitted + // `(in_key, key)` tuples come out in user-input + // order on the prefix dimension, which diverges + // from the documented lex-asc order contract on + // the no-proof distinct path (which sorts post- + // walk) and forces a per-side sort step. + // - **`left_to_right`-driven descent**: with sorted + // keys, `left_to_right = false` walks the outer + // In dimension lex-descending — what the caller + // asked for. Without the sort, descending + // `left_to_right` just reverses user-input + // order, which is gibberish. + // - **Pushed-limit safety**: callers that push the + // path-query limit (no-proof distinct mode) get + // the bottom-N or top-N entries by lex order, + // which is the documented limit-on-distinct + // semantics. With unsorted keys, the path-query + // limit would give the first-N entries in user- + // input order — useless for distinct pagination. + // + // Both the prover and the verifier go through this + // builder, so the byte-equality contract still + // holds — the sort happens identically on both + // sides. + keys.sort(); + in_outer_keys = Some(keys); + } + _ => { + return Err(Error::Query( + QuerySyntaxError::InvalidWhereClauseComponents( + "distinct_count_path_query: prefix properties must use `==` or `in`", + ), + )); + } + } + } + + match in_outer_keys { + None => { + // Flat shape — path includes terminator, single + // range-only Query. + base_path.push(terminator_name.as_bytes().to_vec()); + let mut query = Query::new_with_direction(left_to_right); + query.insert_item(range_item); + Ok(PathQuery::new( + base_path, + SizedQuery::new(query, limit, None), + )) + } + Some(keys) => { + // Compound shape — outer Query has one Key per In + // value at the In-bearing prop's property-name + // subtree. `subquery_path` carries any post-In Equal + // pairs + terminator. Subquery is the range item. + // + // `left_to_right` applies to BOTH the outer Query + // and the subquery so descending iteration walks + // `(in_key_desc, key_desc)` tuples — otherwise we'd + // get e.g. In keys ascending but per-fork terminator + // values descending, which is a weird order no + // user would expect. + let mut outer_query = Query::new_with_direction(left_to_right); + for key in keys { + outer_query.insert_key(key); + } + subquery_path_extension.push(terminator_name.as_bytes().to_vec()); + + let mut subquery = Query::new_with_direction(left_to_right); + subquery.insert_item(range_item); + + outer_query.set_subquery_path(subquery_path_extension); + outer_query.set_subquery(subquery); + + Ok(PathQuery::new( + base_path, + SizedQuery::new(outer_query, limit, None), + )) + } + } + } + + /// Build the grovedb `PathQuery` for a point-lookup count proof + /// against a `countable: true` index. Returns one element per + /// covered branch — the `CountTree` element at + /// `[..., last_field, last_value, 0]` whose `count_value` is the + /// per-branch document count. + /// + /// Shared between the server-side prove path + /// ([`Self::execute_point_lookup_count_with_proof`]) and the + /// client-side verify path + /// ([`Self::verify_point_lookup_count_proof`]). Both sides must + /// produce the *exact same* `PathQuery` for the merk-root + /// recomputation to match. + /// + /// ## Shape support + /// + /// The builder requires the where clauses to **fully cover** the + /// index — every property in `self.index.properties` must have a + /// matching `Equal` or `In` clause. Partial-coverage shapes + /// (where some index properties have no matching clause) require + /// a recursive subquery enumeration that this builder does not + /// implement (and that the strict picker already rejects upstream). + /// + /// **`In` may appear at any position in the index.** Equal + /// clauses before the In contribute to `base_path`; Equal clauses + /// after the In feed `set_subquery_path` on the outer Query so the + /// descent under each matched In value lands at the right + /// CountTree leaf. At most one `In` clause per query (multiple + /// would cartesian-fork beyond what a single `set_subquery` + /// expresses). + /// + /// This is **more permissive than the regular document query + /// path's `Index::matches` rule** (`packages/rs-dpp/src/ + /// data_contract/document_type/index/mod.rs:503`), which restricts + /// `In` to the last or before-last index property because its + /// path-construction code positionally zips intermediate index + /// names with Equal-clause values (see + /// `DriveDocumentQuery::get_non_primary_key_path_query`). The + /// count path doesn't have that constraint: it's a pure CountTree + /// element lookup with no document-key terminator descent, no + /// `order_by` interpretation, and no `limit/offset` semantics, so + /// `set_subquery_path` with an arbitrary trailing tail just + /// works. Both no-proof ([`Self::execute_no_proof`]) and prove + /// ([`Self::execute_point_lookup_count_with_proof`]) executors + /// route through this single builder, so they accept the same + /// query shapes by construction. + /// + /// Output shapes: + /// - **Equal-only, fully covered**: flat path query at + /// `[..., last_field, last_value]` with a single `Key([0])` + /// item. Returns one element (the CountTree). + /// - **Equal prefix + `In` (any position) [+ trailing Equals]**: + /// compound query with `base_path` ending at the In-bearing + /// property's property-name subtree (so any Equal clauses + /// *before* the In are baked into `base_path`); outer Query + /// has one `Key` per In value (sorted lex-asc for prove/no- + /// proof parity and pushed-limit safety — same convention as + /// [`Self::distinct_count_path_query`]). `set_subquery_path` + /// carries the post-In Equal clauses' `(prop_name, + /// serialized_value)` pairs in index order, and the subquery's + /// `Key([0])` picks off the CountTree at the resolved leaf + /// under each matched In branch. Same `set_subquery_path` + + /// `set_subquery` mechanism as [`Self::distinct_count_path_query`] + /// uses for compound In-on-prefix range counts. + /// + /// ## Errors + /// + /// Rejects shapes the builder doesn't support: + /// - Partial coverage (uncovered index property) + /// - More than one `In` clause + /// - Any non-`Equal` / non-`In` operator (defense-in-depth; mode + /// detection already filters these out) + pub fn point_lookup_count_path_query( + &self, + platform_version: &PlatformVersion, + ) -> Result { + if self.index.properties.is_empty() { + return Err(Error::Query( + QuerySyntaxError::InvalidWhereClauseComponents( + "point_lookup_count_path_query: index must have at least one property", + ), + )); + } + + let mut base_path: Vec> = vec![ + vec![RootTree::DataContractDocuments as u8], + self.contract_id.to_vec(), + vec![1u8], + self.document_type_name.as_bytes().to_vec(), + ]; + + // `in_outer_keys` is populated when we encounter the (single) + // `In` clause. Equal clauses *before* the In contribute to + // `base_path`; Equal clauses *after* the In feed + // `subquery_path_extension`, which becomes the outer Query's + // `set_subquery_path` — i.e., the descent under each matched + // In value walks `[trailing_field_1, trailing_value_1, ..., + // trailing_field_n, trailing_value_n]` before the + // `Key([0])` subquery picks off the CountTree leaf. + // + // No position restriction on the In clause: any index + // position works because the count path doesn't have the + // positional path-construction assumption the regular + // document query path makes (see this method's docstring for + // the divergence rationale). + let mut in_outer_keys: Option>> = None; + let mut subquery_path_extension: Vec> = vec![]; + + for prop in self.index.properties.iter() { + let clause = self + .where_clauses + .iter() + .find(|wc| wc.field == prop.name) + .ok_or_else(|| { + Error::Query(QuerySyntaxError::InvalidWhereClauseComponents( + "prove count requires the where clauses to fully cover the \ + countable index; one or more index properties have no \ + matching `==` or `in` clause — use a more specific index \ + (define a `countable: true` index whose properties exactly \ + match the clauses) or use `prove=false`", + )) + })?; + + match clause.operator { + WhereOperator::Equal => { + let serialized = self.document_type.serialize_value_for_key( + prop.name.as_str(), + &clause.value, + platform_version, + )?; + if in_outer_keys.is_some() { + // Trailing Equal after the (already-seen) In: + // descend through it as part of the subquery + // path. Any number of these may accumulate — + // one for each Equal that sits *after* the In + // in the index ordering. + subquery_path_extension.push(prop.name.as_bytes().to_vec()); + subquery_path_extension.push(serialized); + } else { + base_path.push(prop.name.as_bytes().to_vec()); + base_path.push(serialized); + } + } + WhereOperator::In => { + if in_outer_keys.is_some() { + return Err(Error::Query( + QuerySyntaxError::InvalidWhereClauseComponents( + "prove count: at most one `in` clause is supported on \ + the covering countable index", + ), + )); + } + // Stops `base_path` at the In-bearing property's + // property-name subtree; outer Query lives at + // that level. Any trailing Equal property then + // routes through `subquery_path_extension`. + base_path.push(prop.name.as_bytes().to_vec()); + let in_values = clause.in_values().into_data_with_error()??; + let mut keys: Vec> = in_values + .iter() + .map(|v| { + self.document_type.serialize_value_for_key( + prop.name.as_str(), + v, + platform_version, + ) + }) + .collect::>()?; + // Sort lex-asc for prove/no-proof entry-order + // parity and so the pushed-limit (if any) gives + // the documented "first N by lex" semantics. + // Same convention as `distinct_count_path_query`. + keys.sort(); + in_outer_keys = Some(keys); + } + _ => { + return Err(Error::Query( + QuerySyntaxError::InvalidWhereClauseComponents( + "point_lookup_count_path_query: index properties must use \ + `==` or `in`", + ), + )); + } + } + } + + // CountTree storage convention: the count lives at the `[0]` + // child of the value tree. See the book's "Count Trees and + // Provable Counts" chapter for the layout. + const COUNT_TREE_KEY: u8 = 0; + + match in_outer_keys { + None => { + // Equal-only, fully covered. `base_path` ends at + // `[..., last_field, last_value]`; query asks for the + // single key `[0]` (the CountTree element). + let mut query = Query::new(); + query.insert_key(vec![COUNT_TREE_KEY]); + Ok(PathQuery::new( + base_path, + SizedQuery::new(query, None, None), + )) + } + Some(keys) => { + // Compound shape. `base_path` ends at the In-bearing + // property's property-name subtree; the outer Query + // enumerates serialized In values; the subquery + // descends to the CountTree element under each + // matched In value. + // + // `subquery_path_extension` carries 0..N segments, + // one `(prop_name, serialized_value)` pair per Equal + // clause that sits *after* the In in the index + // ordering: + // - **In on last property**: `subquery_path_extension` + // is empty; subquery's `Key([0])` runs directly + // under each In value's value tree. + // - **In with any number of trailing Equals**: + // `set_subquery_path` consumes those segments so + // the subquery descends through them before grabbing + // the `Key([0])` CountTree at the resolved leaf. + let mut outer_query = Query::new(); + for key in keys { + outer_query.insert_key(key); + } + let mut subquery = Query::new(); + subquery.insert_key(vec![COUNT_TREE_KEY]); + if !subquery_path_extension.is_empty() { + outer_query.set_subquery_path(subquery_path_extension); + } + outer_query.set_subquery(subquery); + + Ok(PathQuery::new( + base_path, + SizedQuery::new(outer_query, None, None), + )) + } + } + } + + /// Build the grovedb `PathQuery` for proving the document type's + /// primary-key `CountTree` element at `[contract_doc, contract_id, + /// 1, doctype, 0]`. Used for unfiltered total counts when the + /// document type has `documents_countable: true` — the + /// type-level CountTree's `count_value` IS the total document + /// count, no index walk needed. + /// + /// Shared between the server-side prove path + /// ([`Drive::execute_document_count_point_lookup_proof`]'s + /// documents_countable fast path) and the client-side verify path + /// ([`Self::verify_primary_key_count_tree_proof`]). Both sides + /// produce the exact same `PathQuery` for merk-root recomputation. + /// + /// Free function rather than a method on `DriveDocumentCountQuery` + /// because the documents_countable case isn't tied to any index — + /// it operates at the doctype level directly. + pub fn primary_key_count_tree_path_query( + contract_id: [u8; 32], + document_type_name: &str, + ) -> PathQuery { + let path = vec![ + vec![RootTree::DataContractDocuments as u8], + contract_id.to_vec(), + vec![1u8], + document_type_name.as_bytes().to_vec(), + ]; + let mut query = Query::new(); + query.insert_key(vec![0]); + PathQuery::new(path, SizedQuery::new(query, None, None)) + } +} diff --git a/packages/rs-drive/src/query/drive_document_count_query/tests.rs b/packages/rs-drive/src/query/drive_document_count_query/tests.rs index 66f47019dfd..58a420e275c 100644 --- a/packages/rs-drive/src/query/drive_document_count_query/tests.rs +++ b/packages/rs-drive/src/query/drive_document_count_query/tests.rs @@ -7,14 +7,11 @@ 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::accessors::DocumentTypeV0Getters; -use dpp::data_contract::document_type::random_document::CreateRandomDocument; use dpp::document::{Document, DocumentV0}; use dpp::identifier::Identifier; use dpp::platform_value::Value; use dpp::tests::json_document::json_document_to_contract_with_ids; use dpp::version::PlatformVersion; -use rand::rngs::StdRng; -use rand::SeedableRng; use std::borrow::Cow; use std::collections::BTreeMap as StdBTreeMap; @@ -45,47 +42,6 @@ fn setup_drive_and_contract() -> (Drive, dpp::prelude::DataContract) { (drive, data_contract) } -fn insert_random_documents( - drive: &Drive, - data_contract: &dpp::prelude::DataContract, - document_type_name: &str, - count: usize, - seed: u64, -) { - let platform_version = PlatformVersion::latest(); - let document_type = data_contract - .document_type_for_name(document_type_name) - .expect("expected document type"); - - let mut std_rng = StdRng::seed_from_u64(seed); - for _ in 0..count { - let random_document = document_type - .random_document_with_rng(&mut std_rng, platform_version) - .expect("expected to get random document"); - - let storage_flags = Some(Cow::Owned(StorageFlags::SingleEpoch(0))); - - drive - .add_document_for_contract( - DocumentAndContractInfo { - owned_document_info: OwnedDocumentInfo { - document_info: DocumentRefInfo((&random_document, storage_flags)), - owner_id: None, - }, - contract: data_contract, - document_type, - }, - false, - BlockInfo::default(), - true, - None, - platform_version, - None, - ) - .expect("expected to insert document"); - } -} - /// Inserts a person document with a controlled set of property values, /// so tests can drive the count fast path with known firstName / age /// values rather than relying on the random-document generator. @@ -152,132 +108,131 @@ fn insert_person_doc( .expect("expected to insert document"); } +/// Exact-coverage query (`age == 30` against the single-property +/// `byAge` countable index) — the strict-picker happy path on both +/// no-proof and prove. Pins: +/// - Picker accepts a 1-property index whose property exactly matches +/// the where-clause field. +/// - No-proof executor reads the CountTree at the resolved path and +/// returns the count. +/// - Prove executor builds a CountTree-element proof returning +/// non-empty bytes. #[test] -fn test_count_query_total_count_with_documents() { +fn test_count_query_fully_covered_equal_succeeds_on_both_paths() { let (drive, data_contract) = setup_drive_and_contract(); let platform_version = PlatformVersion::latest(); - insert_random_documents(&drive, &data_contract, "person", 5, 500); + // 3 docs at age=30, 2 at age=40 → byAge count at 30 should be 3. + insert_person_doc(&drive, &data_contract, [1u8; 32], "Alice", "", "Smith", 30); + insert_person_doc(&drive, &data_contract, [2u8; 32], "Bob", "", "Jones", 30); + insert_person_doc(&drive, &data_contract, [3u8; 32], "Carol", "", "Brown", 30); + insert_person_doc(&drive, &data_contract, [4u8; 32], "Dave", "", "Smith", 40); + insert_person_doc(&drive, &data_contract, [5u8; 32], "Eve", "", "Jones", 40); let document_type = data_contract .document_type_for_name("person") .expect("expected document type"); + let age_eq_30 = WhereClause { + field: "age".to_string(), + operator: WhereOperator::Equal, + value: Value::U64(30), + }; let index = DriveDocumentCountQuery::find_countable_index_for_where_clauses( document_type.indexes(), - &[], + std::slice::from_ref(&age_eq_30), ) - .expect("expected to find countable index"); + .expect("expected picker to accept fully-covered byAge index"); let query = DriveDocumentCountQuery { document_type, contract_id: data_contract.id().to_buffer(), document_type_name: "person".to_string(), index, - where_clauses: vec![], - split_by_property: None, + where_clauses: vec![age_eq_30], }; + // No-proof path let results = query .execute_no_proof(&drive, None, platform_version) - .expect("expected query to succeed"); - + .expect("expected no-proof count to succeed"); assert_eq!(results.len(), 1); - assert_eq!(results[0].count, 5, "expected count of 5 documents"); + assert_eq!(results[0].count, 3, "expected count of 3 docs at age=30"); assert!( results[0].key.is_empty(), - "expected empty key for total count" + "expected empty key for fully-covered Equal-only count" ); - // Also verify proof generation works + // Prove path — emits the CountTree element proof for the resolved + // branch. Non-empty bytes guarantee the prover walked a real merk + // path (not a degenerate empty envelope). let proof = query - .execute_with_proof(&drive, None, platform_version) - .expect("expected proof generation to succeed"); - assert!(!proof.is_empty(), "expected non-empty proof"); + .execute_point_lookup_count_with_proof(&drive, None, platform_version) + .expect("expected prove count to succeed on fully-covered Equal query"); + assert!( + !proof.is_empty(), + "expected non-empty proof bytes for fully-covered Equal prove count" + ); } +/// Strict-picker rejection contract: a where clause that doesn't +/// exactly cover any `countable: true` index returns `None` from the +/// picker. Pre-rewrite the picker would have returned a longer-prefix +/// index and downstream code would have walked partially-covered +/// trees via `count_recursive`; now the responsibility for index +/// design sits cleanly with the contract author, and queries against +/// partially-covered indexes fail loudly at the picker level. #[test] -fn test_count_query_total_count_empty() { - let (drive, data_contract) = setup_drive_and_contract(); - let platform_version = PlatformVersion::latest(); - +fn test_count_query_picker_rejects_partial_coverage() { + let (_drive, data_contract) = setup_drive_and_contract(); let document_type = data_contract .document_type_for_name("person") .expect("expected document type"); - let index = DriveDocumentCountQuery::find_countable_index_for_where_clauses( + // family-contract-countable.json has byFirstNameLastName (2 props), + // byFirstNameMiddleLastName (3 props, unique), and byAge (1 prop). + // Empty where doesn't exactly cover any of them. + let no_match = DriveDocumentCountQuery::find_countable_index_for_where_clauses( document_type.indexes(), &[], - ) - .expect("expected to find countable index"); - - let query = DriveDocumentCountQuery { - document_type, - contract_id: data_contract.id().to_buffer(), - document_type_name: "person".to_string(), - index, - where_clauses: vec![], - split_by_property: None, - }; - - let results = query - .execute_no_proof(&drive, None, platform_version) - .expect("expected query to succeed"); - - assert_eq!(results.len(), 1); - assert_eq!(results[0].count, 0, "expected count of 0 documents"); - - // Also verify proof generation works on empty index - let proof = query - .execute_with_proof(&drive, None, platform_version) - .expect("expected proof generation to succeed"); - assert!(!proof.is_empty(), "expected non-empty proof"); -} - -#[test] -fn test_count_query_split_by_property() { - let (drive, data_contract) = setup_drive_and_contract(); - let platform_version = PlatformVersion::latest(); - - insert_random_documents(&drive, &data_contract, "person", 5, 600); + ); + assert!( + no_match.is_none(), + "strict picker must reject empty where clauses (no index has 0 properties)" + ); - let document_type = data_contract - .document_type_for_name("person") - .expect("expected document type"); + // `firstName = X` alone is a prefix of byFirstNameLastName but + // not an exact match — there's no 1-property `[firstName]` index + // in this contract. Strict picker rejects. + let first_name_only = vec![WhereClause { + field: "firstName".to_string(), + operator: WhereOperator::Equal, + value: Value::Text("Alice".to_string()), + }]; + let no_match_partial = DriveDocumentCountQuery::find_countable_index_for_where_clauses( + document_type.indexes(), + &first_name_only, + ); + assert!( + no_match_partial.is_none(), + "`firstName = X` doesn't exactly cover any index (only as prefix of \ + 2- and 3-property indexes) → picker returns None" + ); - let index = DriveDocumentCountQuery::find_countable_index_for_split( + // `age = X` exactly covers byAge (1-prop) → picker accepts. + // Confirms the strict contract isn't over-rejecting. + let age_only = vec![WhereClause { + field: "age".to_string(), + operator: WhereOperator::Equal, + value: Value::U64(30), + }]; + let picked = DriveDocumentCountQuery::find_countable_index_for_where_clauses( document_type.indexes(), - &[], - "firstName", + &age_only, ) - .expect("expected to find countable index for split"); - - let query = DriveDocumentCountQuery { - document_type, - contract_id: data_contract.id().to_buffer(), - document_type_name: "person".to_string(), - index, - where_clauses: vec![], - split_by_property: Some("firstName".to_string()), - }; - - let results = query - .execute_no_proof(&drive, None, platform_version) - .expect("expected query to succeed"); - - let total: u64 = results.iter().map(|e| e.count).sum(); - assert_eq!(total, 5, "expected total split count of 5 documents"); - - for entry in &results { - assert!(!entry.key.is_empty(), "expected non-empty split key"); - assert!(entry.count > 0, "expected positive count per split"); - } - - // Also verify proof generation works for split query - let proof = query - .execute_with_proof(&drive, None, platform_version) - .expect("expected proof generation to succeed"); - assert!(!proof.is_empty(), "expected non-empty proof"); + .expect("byAge is exactly covered"); + assert_eq!(picked.properties.len(), 1); + assert_eq!(picked.properties[0].name, "age"); } #[test] @@ -315,35 +270,6 @@ fn test_find_countable_index_for_where_clauses_no_match() { ); } -#[test] -fn test_find_countable_index_for_split_no_match() { - let platform_version = PlatformVersion::latest(); - - let data_contract = json_document_to_contract_with_ids( - "tests/supporting_files/contract/family/family-contract-countable.json", - None, - None, - false, - platform_version, - ) - .expect("expected to get json based contract"); - - let document_type = data_contract - .document_type_for_name("person") - .expect("expected document type"); - - let result = DriveDocumentCountQuery::find_countable_index_for_split( - document_type.indexes(), - &[], - "nonExistentField", - ); - - assert!( - result.is_none(), - "expected no countable index for non-existent split field" - ); -} - #[test] fn test_has_unsupported_operator() { let eq_clause = WhereClause { @@ -414,12 +340,6 @@ fn test_find_countable_index_rejects_unsupported_operator() { ) .is_none() ); - assert!(DriveDocumentCountQuery::find_countable_index_for_split( - document_type.indexes(), - std::slice::from_ref(>_clause), - "firstName", - ) - .is_none()); } #[test] @@ -458,7 +378,6 @@ fn test_count_query_total_count_with_in_operator() { document_type_name: "person".to_string(), index, where_clauses: vec![in_clause], - split_by_property: None, }; let results = query @@ -503,7 +422,6 @@ fn test_count_query_total_count_with_in_operator_no_matches() { document_type_name: "person".to_string(), index, where_clauses: vec![in_clause], - split_by_property: None, }; let results = query @@ -514,25 +432,115 @@ fn test_count_query_total_count_with_in_operator_no_matches() { assert_eq!(results[0].count, 0, "expected count of 0 for unmatched In"); } +/// `In` clauses with duplicate values are rejected with +/// `InvalidInClause` — the system-wide canonical contract enforced +/// by [`WhereClause::in_values`]. Every In-consuming path the count +/// dispatcher reaches (the shared `point_lookup_count_path_query` +/// builder for both no-proof and prove, the `per_in_value` +/// executor's `in_values()` call, the regular document query path, +/// the contract-level where-clause validator) routes through the +/// same `in_values()` validator, so `age IN [30, 30]` is rejected +/// loudly rather than silently deduplicated. +/// +/// Pre-unification the no-proof count path was the outlier — its +/// hand-rolled `expand_paths_and_count` walker bypassed +/// `in_values()` and silently deduplicated via a `BTreeSet>` +/// of serialized keys. Collapsing the no-proof executor to share +/// the path-query builder fixed that inconsistency by routing both +/// sides through the same validator. #[test] -fn test_count_query_split_with_in_prefix() { +fn test_count_query_in_operator_rejects_duplicate_values() { let (drive, data_contract) = setup_drive_and_contract(); let platform_version = PlatformVersion::latest(); - // firstName IN ["Alice", "Bob"] split by lastName - // Expected: Smith=3 (Alice+Alice+Bob), Jones=2 (Alice+Bob), Doe=1 (Carol — excluded) insert_person_doc(&drive, &data_contract, [1u8; 32], "Alice", "M", "Smith", 30); - insert_person_doc(&drive, &data_contract, [2u8; 32], "Alice", "N", "Smith", 31); - insert_person_doc(&drive, &data_contract, [3u8; 32], "Bob", "M", "Smith", 32); - insert_person_doc(&drive, &data_contract, [4u8; 32], "Alice", "M", "Jones", 33); - insert_person_doc(&drive, &data_contract, [5u8; 32], "Bob", "M", "Jones", 34); - insert_person_doc(&drive, &data_contract, [6u8; 32], "Carol", "M", "Doe", 35); let document_type = data_contract .document_type_for_name("person") .expect("expected document type"); + // age IN [30, 30, 30] — duplicates rejected by the system-wide + // `in_values()` validator before any subtree access. let in_clause = WhereClause { + field: "age".to_string(), + operator: WhereOperator::In, + value: Value::Array(vec![Value::U64(30), Value::U64(30), Value::U64(30)]), + }; + + let index = DriveDocumentCountQuery::find_countable_index_for_where_clauses( + document_type.indexes(), + std::slice::from_ref(&in_clause), + ) + .expect("expected to find countable index for In on age"); + + let query = DriveDocumentCountQuery { + document_type, + contract_id: data_contract.id().to_buffer(), + document_type_name: "person".to_string(), + index, + where_clauses: vec![in_clause], + }; + + let err = query + .execute_no_proof(&drive, None, platform_version) + .expect_err("expected duplicate-In-values to be rejected"); + let msg = err.to_string(); + assert!( + msg.contains("no duplicates"), + "expected duplicate-rejection error from in_values(), got: {}", + msg + ); +} + +/// `In` on the **before-last** index property with a trailing `Equal` +/// on the last property exercises the relaxed prove count builder +/// shape. The regular document query path's `Index::matches` allows +/// `In` on the last OR before-last property of the chosen index, and +/// the prove count builder follows the same rule (see +/// `point_lookup_count_path_query` in `path_query.rs`). +/// +/// Index used: `byFirstNameLastName` (`[firstName, lastName]`). +/// Where: `firstName IN ["Alice", "Bob"] AND lastName == "Smith"`. +/// - Alice + Smith: 2 docs +/// - Bob + Smith: 1 doc +/// - Bob + Jones: 1 doc (ignored — lastName != Smith) +/// - Carol + Smith: 1 doc (ignored — firstName not in In array) +/// +/// Pins: +/// - Strict picker accepts the 2-prop index when both properties are +/// covered (one by In, one by Equal). +/// - No-proof executor goes through the same +/// `point_lookup_count_path_query` builder as the prove side, runs +/// it through `grove.query`, and sums the emitted CountTree +/// elements' `count_value`s: 2 + 1 = 3. +/// - Prove executor builds a compound path query whose `base_path` +/// stops at `[..., "firstName"]`, with `outer_query` keys = the +/// sorted serialized In values and `set_subquery_path` carrying +/// `["lastName", serialize("Smith")]`; the subquery's `Key([0])` +/// then picks off the CountTree under each matched In branch. +/// - Proof verifies (round-trips through `GroveDb::verify_query` in +/// the verifier), and the verified per-branch entries' counts sum +/// to the no-proof count. +#[test] +fn test_count_query_in_on_before_last_with_trailing_equal_succeeds_on_both_paths() { + let (drive, data_contract) = setup_drive_and_contract(); + let platform_version = PlatformVersion::latest(); + + // Different middle names so the unique `byFirstNameMiddleLastName` + // index is satisfied — the count goes through the non-unique + // 2-prop `byFirstNameLastName` index, which doesn't care about + // middleName. + insert_person_doc(&drive, &data_contract, [1u8; 32], "Alice", "M", "Smith", 30); + insert_person_doc(&drive, &data_contract, [2u8; 32], "Alice", "N", "Smith", 31); + insert_person_doc(&drive, &data_contract, [3u8; 32], "Bob", "M", "Smith", 40); + insert_person_doc(&drive, &data_contract, [4u8; 32], "Bob", "N", "Jones", 41); + insert_person_doc(&drive, &data_contract, [5u8; 32], "Carol", "M", "Smith", 50); + + let document_type = data_contract + .document_type_for_name("person") + .expect("expected document type"); + + let in_first = WhereClause { field: "firstName".to_string(), operator: WhereOperator::In, value: Value::Array(vec![ @@ -540,88 +548,723 @@ fn test_count_query_split_with_in_prefix() { Value::Text("Bob".to_string()), ]), }; + let eq_last = WhereClause { + field: "lastName".to_string(), + operator: WhereOperator::Equal, + value: Value::Text("Smith".to_string()), + }; + let where_clauses = vec![in_first, eq_last]; - let index = DriveDocumentCountQuery::find_countable_index_for_split( + let index = DriveDocumentCountQuery::find_countable_index_for_where_clauses( document_type.indexes(), - std::slice::from_ref(&in_clause), - "lastName", + &where_clauses, ) - .expect("expected to find countable index for In + split lastName"); + .expect("expected picker to accept byFirstNameLastName for In + Equal coverage"); + // Sanity-check the picker really chose the 2-prop index, not the + // 3-prop unique one — confirms set-equality coverage and pins the + // covering-index expectation against future picker tweaks. + assert_eq!(index.properties.len(), 2); let query = DriveDocumentCountQuery { document_type, contract_id: data_contract.id().to_buffer(), document_type_name: "person".to_string(), index, - where_clauses: vec![in_clause], - split_by_property: Some("lastName".to_string()), + where_clauses, }; + // No-proof: 2 Alice+Smith + 1 Bob+Smith = 3. let results = query .execute_no_proof(&drive, None, platform_version) - .expect("expected query to succeed"); - - let total: u64 = results.iter().map(|e| e.count).sum(); + .expect("expected no-proof count to succeed"); + assert_eq!(results.len(), 1); assert_eq!( - total, 5, - "expected total of 5 (3 Smith + 2 Jones, Carol/Doe excluded)" + results[0].count, 3, + "expected 3 docs covered by firstName IN [Alice, Bob] AND lastName = Smith" + ); + + // Prove: builder emits the compound shape; verifier round-trips + // and returns per-In-value entries. + let proof = query + .execute_point_lookup_count_with_proof(&drive, None, platform_version) + .expect("expected prove count to succeed on In-on-before-last shape"); + assert!( + !proof.is_empty(), + "expected non-empty proof bytes for In-on-before-last prove count" ); + + let (_root_hash, entries) = query + .verify_point_lookup_count_proof(&proof, platform_version) + .expect("expected proof verification to succeed"); + // Verifier emits one entry per In branch with a non-zero count. + // Alice → 2, Bob → 1. + let summed: u64 = entries.iter().map(|e| e.count).sum(); assert_eq!( - results.len(), - 2, - "expected 2 split entries (Smith and Jones)" + summed, 3, + "verified per-branch entries should sum to the no-proof total" ); - for entry in &results { - assert!(entry.count > 0, "filtered split entries should be > 0"); - } } -/// Codex review finding #3: an `In` clause with duplicate values used to -/// double-count by recursing once per array element. The fix dedupes -/// branches by serialized key before summing. +/// `In` on the **first** property of a 3-property index, with two +/// trailing Equals (`firstName IN [..] AND middleName = m AND +/// lastName = ln` on the unique `byFirstNameMiddleLastName` index) +/// — exercises the most aggressive shape the relaxed prove count +/// builder accepts: In at position 0 with two trailing Equals +/// rolling through `subquery_path_extension`. Both no-proof and +/// prove paths go through the same +/// `point_lookup_count_path_query` builder (no-proof reads the +/// emitted CountTree elements via `grove.query`; prove signs them +/// via `get_proved_path_query`), so accepting this shape on one +/// side automatically accepts it on the other. The count path is +/// deliberately more permissive than the regular document query +/// path here — see the builder's docstring for the divergence +/// rationale vs. `Index::matches`. +/// +/// Index used: `byFirstNameMiddleLastName` (unique, 3 props). +/// Where: `firstName IN ["Alice", "Bob"] AND middleName = "M" AND +/// lastName = "Smith"`. +/// - (Alice, M, Smith): 1 doc +/// - (Bob, M, Smith): 1 doc +/// - (Carol, M, Smith): 1 doc (excluded — firstName not in In) +/// - (Alice, N, Smith): 1 doc (excluded — middleName ≠ M) +/// +/// Pins: +/// - Strict picker accepts the 3-prop covering index. +/// - No-proof executor sums per-In-value: 1 + 1 = 2. +/// - Prove executor builds a compound path query with `base_path` +/// stopping at `[..., "firstName"]`, `outer_query` keys = sorted +/// serialized In values, `set_subquery_path` = +/// `["middleName", serialize("M"), "lastName", serialize("Smith")]`, +/// subquery `Key([0])`. +/// - Proof verifies and the verified per-branch entries' counts +/// sum to the no-proof count. #[test] -fn test_count_query_in_operator_dedupes_duplicate_values() { +fn test_count_query_in_on_first_of_three_with_two_trailing_equals_succeeds_on_both_paths() { let (drive, data_contract) = setup_drive_and_contract(); let platform_version = PlatformVersion::latest(); + // Pick distinct (firstName, middleName, lastName) tuples so the + // unique 3-prop index doesn't reject any inserts. The picker + // will route the count query through that same 3-prop index + // because the where clauses cover exactly its properties. insert_person_doc(&drive, &data_contract, [1u8; 32], "Alice", "M", "Smith", 30); - insert_person_doc(&drive, &data_contract, [2u8; 32], "Bob", "M", "Smith", 30); - insert_person_doc(&drive, &data_contract, [3u8; 32], "Carol", "M", "Smith", 40); + insert_person_doc(&drive, &data_contract, [2u8; 32], "Bob", "M", "Smith", 40); + insert_person_doc(&drive, &data_contract, [3u8; 32], "Carol", "M", "Smith", 50); + insert_person_doc(&drive, &data_contract, [4u8; 32], "Alice", "N", "Smith", 31); + insert_person_doc(&drive, &data_contract, [5u8; 32], "Bob", "N", "Jones", 41); let document_type = data_contract .document_type_for_name("person") .expect("expected document type"); - // age IN [30, 30, 30] — set semantics: should count age=30 once = 2 docs. - let in_clause = WhereClause { - field: "age".to_string(), + let in_first = WhereClause { + field: "firstName".to_string(), operator: WhereOperator::In, - value: Value::Array(vec![Value::U64(30), Value::U64(30), Value::U64(30)]), + value: Value::Array(vec![ + Value::Text("Alice".to_string()), + Value::Text("Bob".to_string()), + ]), + }; + let eq_middle = WhereClause { + field: "middleName".to_string(), + operator: WhereOperator::Equal, + value: Value::Text("M".to_string()), + }; + let eq_last = WhereClause { + field: "lastName".to_string(), + operator: WhereOperator::Equal, + value: Value::Text("Smith".to_string()), }; + let where_clauses = vec![in_first, eq_middle, eq_last]; let index = DriveDocumentCountQuery::find_countable_index_for_where_clauses( document_type.indexes(), - std::slice::from_ref(&in_clause), + &where_clauses, ) - .expect("expected to find countable index for In on age"); + .expect("expected picker to accept the 3-prop covering index"); + // Sanity-pin the picker actually chose the 3-prop unique + // countable index rather than some weaker variant. + assert_eq!(index.properties.len(), 3); let query = DriveDocumentCountQuery { document_type, contract_id: data_contract.id().to_buffer(), document_type_name: "person".to_string(), index, - where_clauses: vec![in_clause], - split_by_property: None, + where_clauses, }; + // No-proof: 1 (Alice,M,Smith) + 1 (Bob,M,Smith) = 2. let results = query .execute_no_proof(&drive, None, platform_version) - .expect("expected query to succeed"); - + .expect("expected no-proof count to succeed"); assert_eq!(results.len(), 1); assert_eq!( results[0].count, 2, - "expected count of 2 (age=30, set semantics — duplicates collapsed)" + "expected 2 docs covered by firstName IN [Alice, Bob] AND \ + middleName = M AND lastName = Smith" + ); + + // Prove: builder emits compound shape with 2-segment + // `subquery_path_extension`. Verifier round-trips and returns + // per-In-value entries. + let proof = query + .execute_point_lookup_count_with_proof(&drive, None, platform_version) + .expect("expected prove count to succeed on In-on-first-of-3 shape"); + assert!( + !proof.is_empty(), + "expected non-empty proof bytes for In-on-first-of-3 prove count" + ); + + let (_root_hash, entries) = query + .verify_point_lookup_count_proof(&proof, platform_version) + .expect("expected proof verification to succeed"); + let summed: u64 = entries.iter().map(|e| e.count).sum(); + assert_eq!( + summed, 2, + "verified per-branch entries should sum to the no-proof total" + ); +} + +/// Pins the DoS-bound invariant on the compound `range + In` +/// summed no-proof path: per-In aggregate fan-out, NOT a walk-and- +/// sum over every matched `(in_key, key)` element. A regression +/// to walk-and-sum surfaces as a request-amplification on a public +/// unauthenticated endpoint (one broad range × 100 In values can +/// force a full index walk while the response stays a single +/// aggregate `u64`). +/// +/// Test invariant: the per-In fan-out gives a correct sum +/// (functional check), and it uses `query_aggregate_count` rather +/// than `query_raw` (DoS-bound check). The functional check pins +/// the result against a known distribution; the DoS-bound check is +/// implicit — `query_aggregate_count` is O(log n) per call vs. +/// `query_raw`'s O(matched elements), and the test data is +/// constructed so a walk would surface a runtime regression (e.g. +/// timeout in CI). We rely on the executor's per-In loop structure +/// as the structural pin; the comment + this test together +/// document the contract. +#[test] +fn test_compound_range_in_summed_no_proof_uses_per_in_aggregate_fanout() { + use crate::config::DriveConfig; + use crate::query::drive_document_count_query::drive_dispatcher::{ + DocumentCountRequest, DocumentCountResponse, + }; + use dpp::data_contract::DataContractFactory; + use dpp::platform_value::platform_value; + + const PROTOCOL_VERSION_V12: u32 = 12; + + let drive = setup_drive_with_initial_state_structure(None); + let platform_version = PlatformVersion::latest(); + + // `[brand, color]` compound range_countable index. `brand` is + // the prefix the test will fan-out an `In` clause across; + // `color` is the range terminator. The aggregate primitive + // works on the per-brand `color` subtree directly, so + // `query_aggregate_count` can answer "how many widgets with + // brand=X and color > 'blue'" in O(log n) per brand. + let factory = + DataContractFactory::new(PROTOCOL_VERSION_V12).expect("expected to create factory"); + let document_schema = platform_value!({ + "type": "object", + "properties": { + "brand": {"type": "string", "position": 0, "maxLength": 32}, + "color": {"type": "string", "position": 1, "maxLength": 32}, + }, + "indices": [{ + "name": "byBrandColor", + "properties": [{"brand": "asc"}, {"color": "asc"}], + "countable": "countable", + "rangeCountable": true, + }], + "additionalProperties": false, + }); + let schemas = platform_value!({ "widget": document_schema }); + let data_contract = factory + .create_with_value_config( + dpp::tests::utils::generate_random_identifier_struct(), + 0, + schemas, + None, + None, + ) + .expect("expected to create data contract") + .data_contract_owned(); + drive + .apply_contract( + &data_contract, + BlockInfo::default(), + true, + StorageFlags::optional_default_as_cow(), + None, + platform_version, + ) + .expect("apply contract"); + + let document_type = data_contract + .document_type_for_name("widget") + .expect("widget doc type exists"); + + // 3 brands × varying colors, mixing in-range (`color > "blue"`) + // and out-of-range entries. Expected count for + // `brand IN [acme, contoso] AND color > "blue"`: + // acme: 2 red + 1 green = 3 in-range, 1 blue out → 3 + // contoso: 1 red + 2 green = 3 in-range, 0 blue → 3 + // stark: 1 red (excluded by In) → 0 + // Total = 6. + let entries = [ + ("acme", "red"), + ("acme", "red"), + ("acme", "green"), + ("acme", "blue"), + ("contoso", "red"), + ("contoso", "green"), + ("contoso", "green"), + ("stark", "red"), + ]; + for (i, (brand, color)) in entries.iter().enumerate() { + let mut properties = StdBTreeMap::new(); + properties.insert("brand".to_string(), Value::Text(brand.to_string())); + properties.insert("color".to_string(), Value::Text(color.to_string())); + let document: Document = DocumentV0 { + id: Identifier::from([(i + 1) as u8; 32]), + owner_id: Identifier::from([0u8; 32]), + properties, + revision: None, + created_at: None, + updated_at: None, + transferred_at: None, + created_at_block_height: None, + updated_at_block_height: None, + transferred_at_block_height: None, + created_at_core_block_height: None, + updated_at_core_block_height: None, + transferred_at_core_block_height: None, + creator_id: None, + } + .into(); + let storage_flags = Some(Cow::Owned(StorageFlags::SingleEpoch(0))); + drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentRefInfo((&document, storage_flags)), + owner_id: None, + }, + contract: &data_contract, + document_type, + }, + false, + BlockInfo::default(), + true, + None, + platform_version, + None, + ) + .expect("expected to insert widget"); + } + + // Request: `brand IN ["acme", "contoso"] AND color > "blue"`, + // no-proof, summed mode. Goes through + // `execute_range_count_no_proof`'s compound-summed branch, + // which loops over the In values and issues + // `query_aggregate_count` per branch. + let drive_config = DriveConfig::default(); + let raw_where_value = Value::Array(vec![ + Value::Array(vec![ + Value::Text("brand".to_string()), + Value::Text("in".to_string()), + Value::Array(vec![ + Value::Text("acme".to_string()), + Value::Text("contoso".to_string()), + ]), + ]), + Value::Array(vec![ + Value::Text("color".to_string()), + Value::Text(">".to_string()), + Value::Text("blue".to_string()), + ]), + ]); + let request = DocumentCountRequest { + contract: &data_contract, + document_type, + raw_where_value, + raw_order_by_value: Value::Null, + return_distinct_counts_in_range: false, + limit: None, + prove: false, + drive_config: &drive_config, + }; + + let response = drive + .execute_document_count_request(request, None, platform_version) + .expect("expected dispatcher to succeed on compound summed range path"); + let count = match response { + DocumentCountResponse::Aggregate(c) => c, + other => panic!("expected Aggregate response, got {:?}", other), + }; + assert_eq!( + count, 6, + "acme(2 red + 1 green) + contoso(1 red + 2 green) = 6 in-range widgets" + ); +} + +/// `where_clauses_from_value` must run the parsed `Vec` +/// through `WhereClause::group_clauses` to reject malformed shapes +/// the regular document-query path rejects. +/// +/// Without `group_clauses` validation, the count endpoint silently +/// accepts duplicate/conflicting clauses and returns a count for an +/// arbitrarily reduced query: +/// - Two conflicting `Equal` clauses on the same field collapse to +/// a single clause via `find_countable_index_for_where_clauses`'s +/// `BTreeSet` over field names and `point_lookup_count_path_query`'s +/// `.find(...)` for each index property — the executor picks the +/// first clause and the second is silently dropped. +/// - Multiple `In` clauses or multiple range clauses similarly slip +/// through. +/// +/// This test pins the rejection at the dispatcher seam (via the +/// `execute_document_count_request` entry point that all callers +/// reach through the abci handler), so a future change that bypasses +/// the validator gets caught. +#[test] +fn test_count_request_with_duplicate_equality_clauses_is_rejected() { + use crate::config::DriveConfig; + use crate::query::drive_document_count_query::drive_dispatcher::DocumentCountRequest; + + let (drive, data_contract) = setup_drive_and_contract(); + let platform_version = PlatformVersion::latest(); + + let document_type = data_contract + .document_type_for_name("person") + .expect("expected document type"); + + // Two conflicting `Equal` clauses on `firstName` — the request + // is structurally malformed: there's no single document that + // satisfies both `firstName = "Alice"` AND `firstName = "Bob"`, + // so the answer should be 0, but a regression would return + // count("firstName = Alice") or count("firstName = Bob") + // depending on iteration order. + let raw_where_value = Value::Array(vec![ + Value::Array(vec![ + Value::Text("firstName".to_string()), + Value::Text("==".to_string()), + Value::Text("Alice".to_string()), + ]), + Value::Array(vec![ + Value::Text("firstName".to_string()), + Value::Text("==".to_string()), + Value::Text("Bob".to_string()), + ]), + ]); + let drive_config = DriveConfig::default(); + let request = DocumentCountRequest { + contract: &data_contract, + document_type, + raw_where_value, + raw_order_by_value: Value::Null, + return_distinct_counts_in_range: false, + limit: None, + prove: false, + drive_config: &drive_config, + }; + + let err = drive + .execute_document_count_request(request, None, platform_version) + .expect_err("expected duplicate-equality request to be rejected"); + let msg = err.to_string(); + assert!( + msg.contains("duplicate") || msg.contains("DuplicateNonGroupableClauseSameField"), + "expected duplicate-equality rejection from group_clauses, got: {}", + msg + ); +} + +/// Pins the consensus-sensitive limit-fallback invariant on the +/// `RangeDistinctProof` dispatch path: when the request's `limit` +/// is `None`, the dispatcher MUST fall back to the compile-time +/// `crate::config::DEFAULT_QUERY_LIMIT` constant (which the SDK +/// verifier also reads), NOT the operator-tunable +/// `drive_config.default_query_limit`. The two values are often +/// equal in practice (both default to 100), so a regression where +/// the dispatcher reads from `drive_config.default_query_limit` +/// would only manifest on operators who tuned the runtime value +/// away from the constant — exactly the silent verify-failure +/// surface the CodeRabbit review flagged. +/// +/// Mechanism: we build a `DocumentCountRequest` whose +/// `drive_config.default_query_limit` is **deliberately set to 50** +/// (≠ `DEFAULT_QUERY_LIMIT` = 100). If the dispatcher uses +/// `drive_config.default_query_limit`, the proof embeds +/// `SizedQuery::limit = 50`; if it uses `DEFAULT_QUERY_LIMIT`, the +/// proof embeds `SizedQuery::limit = 100`. We then reconstruct the +/// path query with `Some(DEFAULT_QUERY_LIMIT)` — exactly what the +/// SDK verifier does — and run `GroveDb::verify_query` on the +/// proof bytes. The merk-root recomputation only succeeds if the +/// prover signed with `limit = 100`; if it signed with `limit = 50` +/// the reconstructed path query bytes differ and `verify_query` +/// returns an error. +/// +/// Without the fix in `drive_dispatcher.rs`'s `RangeDistinctProof` +/// arm this test fails. The "fix" is the one-line change from +/// `request.drive_config.default_query_limit` to +/// `crate::config::DEFAULT_QUERY_LIMIT` on the prove path — see +/// the comment in that arm for the symmetric reasoning. +#[test] +fn test_range_distinct_proof_uses_compile_time_default_query_limit_not_operator_config() { + use crate::config::{DriveConfig, DEFAULT_QUERY_LIMIT}; + use crate::query::drive_document_count_query::drive_dispatcher::{ + DocumentCountRequest, DocumentCountResponse, + }; + use dpp::data_contract::DataContractFactory; + use dpp::platform_value::platform_value; + use grovedb::GroveDb; + + const PROTOCOL_VERSION_V12: u32 = 12; + // Set the operator's tuned limit to **1** — a value small + // enough that the prover's walk would actually stop after one + // element instead of just covering the entire result set + // (which 50 or 100 both would, masking any limit-mismatch by + // producing identical proof bytes). With 2+ in-range distinct + // keys below and `OPERATOR_TUNED_LIMIT = 1`, the prover-side + // limit choice **materially affects which elements end up in + // the proof** and the merk-root recomputation. If the + // dispatcher (incorrectly) used `default_query_limit = 1`, + // the prover would emit a 1-key proof; the verifier + // (rebuilding with `DEFAULT_QUERY_LIMIT = 100`) would expect + // up to 100 keys and the boundary-subtree hash chain would + // not match → `verify_query` returns Err. + const OPERATOR_TUNED_LIMIT: u16 = 1; + assert_ne!( + DEFAULT_QUERY_LIMIT, OPERATOR_TUNED_LIMIT, + "test invariant: OPERATOR_TUNED_LIMIT must differ from the \ + compile-time DEFAULT_QUERY_LIMIT for the regression check \ + to be load-bearing" + ); + + let drive = setup_drive_with_initial_state_structure(None); + let platform_version = PlatformVersion::latest(); + + let factory = + DataContractFactory::new(PROTOCOL_VERSION_V12).expect("expected to create factory"); + let document_schema = platform_value!({ + "type": "object", + "properties": { + "color": {"type": "string", "position": 0, "maxLength": 32}, + }, + "indices": [{ + "name": "byColor", + "properties": [{"color": "asc"}], + "countable": "countable", + "rangeCountable": true, + }], + "additionalProperties": false, + }); + let schemas = platform_value!({ "widget": document_schema }); + let data_contract = factory + .create_with_value_config( + dpp::tests::utils::generate_random_identifier_struct(), + 0, + schemas, + None, + None, + ) + .expect("expected to create data contract") + .data_contract_owned(); + + drive + .apply_contract( + &data_contract, + BlockInfo::default(), + true, + StorageFlags::optional_default_as_cow(), + None, + platform_version, + ) + .expect("apply contract"); + + let document_type = data_contract + .document_type_for_name("widget") + .expect("widget doc type exists"); + + // Spread docs across distinct color values so the + // RangeDistinctProof path actually carries per-key counts in + // its proof (an empty range would still verify trivially and + // mask the limit mismatch). 2 red + 3 green + 1 blue; the + // `color > "blue"` clause excludes blue, leaving 2 distinct + // in-range keys (red, green). + for (i, color) in ["red", "red", "green", "green", "green", "blue"] + .iter() + .enumerate() + { + let mut properties = StdBTreeMap::new(); + properties.insert("color".to_string(), Value::Text(color.to_string())); + let document: Document = DocumentV0 { + id: Identifier::from([(i + 1) as u8; 32]), + owner_id: Identifier::from([0u8; 32]), + properties, + revision: None, + created_at: None, + updated_at: None, + transferred_at: None, + created_at_block_height: None, + updated_at_block_height: None, + transferred_at_block_height: None, + created_at_core_block_height: None, + updated_at_core_block_height: None, + transferred_at_core_block_height: None, + creator_id: None, + } + .into(); + let storage_flags = Some(Cow::Owned(StorageFlags::SingleEpoch(0))); + drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentRefInfo((&document, storage_flags)), + owner_id: None, + }, + contract: &data_contract, + document_type, + }, + false, + BlockInfo::default(), + true, + None, + platform_version, + None, + ) + .expect("expected to insert widget"); + } + + // Operator-tuned DriveConfig with `default_query_limit = 50`. + // The dispatcher MUST NOT propagate this onto the prove path's + // path query. + let drive_config = DriveConfig { + default_query_limit: OPERATOR_TUNED_LIMIT, + ..Default::default() + }; + + // Range clause `color > "blue"` as wire-shape (Value::Array of + // [field, op, value] tuples) — the dispatcher CBOR-decodes + // this internally into structured WhereClauses. + let raw_where_value = Value::Array(vec![Value::Array(vec![ + Value::Text("color".to_string()), + Value::Text(">".to_string()), + Value::Text("blue".to_string()), + ])]); + let request = DocumentCountRequest { + contract: &data_contract, + document_type, + raw_where_value, + raw_order_by_value: Value::Null, + return_distinct_counts_in_range: true, + limit: None, + prove: true, + drive_config: &drive_config, + }; + + let response = drive + .execute_document_count_request(request, None, platform_version) + .expect("expected dispatcher to succeed on RangeDistinctProof path"); + let proof_bytes = match response { + DocumentCountResponse::Proof(p) => p, + other => panic!("expected Proof response, got {:?}", other), + }; + assert!( + !proof_bytes.is_empty(), + "expected non-empty proof bytes from RangeDistinctProof path" + ); + + // Reconstruct the path query the way the SDK verifier does: + // anchored to the compile-time `DEFAULT_QUERY_LIMIT`, not the + // operator's runtime value. If the dispatcher used + // `OPERATOR_TUNED_LIMIT` instead, the reconstructed path + // query's `SizedQuery::limit` bytes will differ from what the + // prover signed and `verify_query` returns Err. + let color_gt_blue = WhereClause { + field: "color".to_string(), + operator: WhereOperator::GreaterThan, + value: Value::Text("blue".to_string()), + }; + let index = DriveDocumentCountQuery::find_range_countable_index_for_where_clauses( + document_type.indexes(), + std::slice::from_ref(&color_gt_blue), + ) + .expect("byColor range_countable index covers `color > blue`"); + let count_query = DriveDocumentCountQuery { + document_type, + contract_id: data_contract.id().to_buffer(), + document_type_name: "widget".to_string(), + index, + where_clauses: vec![color_gt_blue], + }; + let verifier_path_query = count_query + .distinct_count_path_query(Some(DEFAULT_QUERY_LIMIT), true, platform_version) + .expect("path query builder should accept the same shape the prover used"); + + let (_root_hash, _elements) = GroveDb::verify_query( + &proof_bytes, + &verifier_path_query, + &platform_version.drive.grove_version, + ) + .expect( + "expected proof to verify against a path query rebuilt with \ + DEFAULT_QUERY_LIMIT; a failure here means the dispatcher signed \ + the proof with the operator-tunable default_query_limit instead — \ + a consensus-adjacent silent-verify-failure regression", + ); +} + +/// `execute_document_count_per_in_value_no_proof` runs one GroveDB walk +/// per `In` value, so its iteration cost is proportional to the array's +/// length rather than the configured `max_query_limit`. That makes the +/// In-array length the actual amplification factor — capping the +/// *output* `limit` after the loop is cosmetic. We delegate the cap to +/// `WhereClause::in_values()` (the same 100-element validator other In +/// consumers use); this test pins that delegation at the executor's +/// entry point so a regression here surfaces as a query-rejection +/// rather than as a quietly amplified backend scan. +#[test] +fn test_count_query_in_operator_rejects_oversized_array() { + let (drive, data_contract) = setup_drive_and_contract(); + let platform_version = PlatformVersion::latest(); + + let document_type = data_contract + .document_type_for_name("person") + .expect("expected document type"); + + // 101 distinct `age` values triggers the 100-cap in `in_values()`. + let oversized: Vec = (0u64..101).map(Value::U64).collect(); + let in_clause = WhereClause { + field: "age".to_string(), + operator: WhereOperator::In, + value: Value::Array(oversized), + }; + + let err = drive + .execute_document_count_per_in_value_no_proof( + data_contract.id().to_buffer(), + document_type, + "person".to_string(), + vec![in_clause], + super::RangeCountOptions { + distinct: false, + limit: Some(50), + order_by_ascending: true, + }, + None, + platform_version, + ) + .expect_err("expected 101-element In array to be rejected"); + + let msg = err.to_string(); + assert!( + msg.contains("at most 100"), + "expected 100-cap rejection, got: {}", + msg ); } @@ -822,13 +1465,24 @@ fn test_countable_allowing_offset_variant_end_to_end() { ) .expect("expected to apply contract"); - insert_random_documents(&drive, &data_contract, "person", 4, 700); + // 2 Alices + 2 Bobs so the byFirstName count at "Alice" is 2. + // Using fully-covered `firstName == "Alice"` because the strict + // picker requires exact coverage. + insert_person_doc(&drive, &data_contract, [1u8; 32], "Alice", "", "", 30); + insert_person_doc(&drive, &data_contract, [2u8; 32], "Alice", "", "", 31); + insert_person_doc(&drive, &data_contract, [3u8; 32], "Bob", "", "", 40); + insert_person_doc(&drive, &data_contract, [4u8; 32], "Bob", "", "", 41); - // The picker should still find this index — `is_countable()` covers both - // `Countable` and `CountableAllowingOffset`. + let first_name_eq_alice = WhereClause { + field: "firstName".to_string(), + operator: WhereOperator::Equal, + value: Value::Text("Alice".to_string()), + }; + // The picker should accept this index — `is_countable()` covers + // both `Countable` and `CountableAllowingOffset` variants. let picked = DriveDocumentCountQuery::find_countable_index_for_where_clauses( document_type.indexes(), - &[], + std::slice::from_ref(&first_name_eq_alice), ) .expect("expected picker to accept CountableAllowingOffset index"); assert_eq!(picked.countable, IndexCountability::CountableAllowingOffset); @@ -838,8 +1492,7 @@ fn test_countable_allowing_offset_variant_end_to_end() { contract_id: data_contract.id().to_buffer(), document_type_name: "person".to_string(), index: picked, - where_clauses: vec![], - split_by_property: None, + where_clauses: vec![first_name_eq_alice], }; let results = query @@ -847,8 +1500,8 @@ fn test_countable_allowing_offset_variant_end_to_end() { .expect("expected count query to succeed against ProvableCountTree"); assert_eq!(results.len(), 1); assert_eq!( - results[0].count, 4, - "ProvableCountTree should report total count = 4" + results[0].count, 2, + "ProvableCountTree should report 2 Alices" ); } @@ -911,7 +1564,6 @@ fn test_count_query_unique_countable_index_returns_correct_count() { document_type_name: "person".to_string(), index, where_clauses, - split_by_property: None, }; let results = query @@ -925,3 +1577,450 @@ fn test_count_query_unique_countable_index_returns_correct_count() { (Reference at [0] returns count_value_or_default = 1)" ); } + +#[cfg(test)] +mod range_countable_picker_tests { + //! Coverage for [`DriveDocumentCountQuery::find_range_countable_index_for_where_clauses`]. + //! + //! Builds a small in-memory `BTreeMap` rather than going + //! through a full DataContract, since we're only testing the picker + //! rule (prefix match + range terminator + range_countable=true) and + //! the contract-level wiring is exercised by the e2e tests under + //! `drive::contract::insert::insert_contract::v0::range_countable_index_e2e_tests`. + + use super::*; + use dpp::data_contract::document_type::{Index, IndexCountability, IndexProperty}; + + fn make_index( + name: &str, + properties: &[&str], + countable: IndexCountability, + range_countable: bool, + ) -> Index { + Index { + name: name.to_string(), + properties: properties + .iter() + .map(|p| IndexProperty { + name: p.to_string(), + ascending: true, + }) + .collect(), + unique: false, + null_searchable: true, + contested_index: None, + countable, + range_countable, + } + } + + fn make_indexes(indexes: Vec) -> std::collections::BTreeMap { + indexes.into_iter().map(|i| (i.name.clone(), i)).collect() + } + + /// Single-property range_countable index — straightforward range + /// query over `color`. + #[test] + fn picks_single_property_range_countable_index() { + let indexes = make_indexes(vec![make_index( + "byColor", + &["color"], + IndexCountability::Countable, + true, + )]); + let where_clauses = vec![WhereClause { + field: "color".to_string(), + operator: WhereOperator::GreaterThan, + value: Value::Text("a".to_string()), + }]; + let picked = DriveDocumentCountQuery::find_range_countable_index_for_where_clauses( + &indexes, + &where_clauses, + ); + assert!(picked.is_some()); + assert_eq!(picked.unwrap().name, "byColor"); + } + + /// Compound range_countable `[brand, color]`: Equal on `brand` (the + /// prefix), range on `color` (the terminator). + #[test] + fn picks_compound_range_countable_index_with_equal_prefix() { + let indexes = make_indexes(vec![make_index( + "byBrandColor", + &["brand", "color"], + IndexCountability::Countable, + true, + )]); + let where_clauses = vec![ + WhereClause { + field: "brand".to_string(), + operator: WhereOperator::Equal, + value: Value::Text("acme".to_string()), + }, + WhereClause { + field: "color".to_string(), + operator: WhereOperator::Between, + value: Value::Array(vec![ + Value::Text("a".to_string()), + Value::Text("z".to_string()), + ]), + }, + ]; + let picked = DriveDocumentCountQuery::find_range_countable_index_for_where_clauses( + &indexes, + &where_clauses, + ); + assert!(picked.is_some()); + assert_eq!(picked.unwrap().name, "byBrandColor"); + } + + /// Range on a non-terminator property must not match. For + /// `[brand, color]`, a range on `brand` (with no clause on `color`) + /// would not be answerable via the index walker model — there's no + /// CountTree at the brand value level. + #[test] + fn rejects_range_on_non_terminator_property() { + let indexes = make_indexes(vec![make_index( + "byBrandColor", + &["brand", "color"], + IndexCountability::Countable, + true, + )]); + let where_clauses = vec![WhereClause { + field: "brand".to_string(), + operator: WhereOperator::GreaterThan, + value: Value::Text("a".to_string()), + }]; + assert!( + DriveDocumentCountQuery::find_range_countable_index_for_where_clauses( + &indexes, + &where_clauses, + ) + .is_none(), + "a range on a non-terminator property must not match — the storage \ + layout doesn't put a ProvableCountTree at that level" + ); + } + + /// An index without `range_countable: true` must not match even if + /// the property structure aligns. The storage layout for these is + /// plain NormalTree — no CountTree counts to walk. + #[test] + fn rejects_non_range_countable_index() { + let indexes = make_indexes(vec![make_index( + "byColor", + &["color"], + IndexCountability::Countable, + false, // <-- NOT range_countable + )]); + let where_clauses = vec![WhereClause { + field: "color".to_string(), + operator: WhereOperator::GreaterThan, + value: Value::Text("a".to_string()), + }]; + assert!( + DriveDocumentCountQuery::find_range_countable_index_for_where_clauses( + &indexes, + &where_clauses, + ) + .is_none() + ); + } + + /// Two range operators should never resolve to a single index — the + /// PathQuery model can express only one range at a time. + #[test] + fn rejects_multiple_range_operators() { + let indexes = make_indexes(vec![make_index( + "byColor", + &["color"], + IndexCountability::Countable, + true, + )]); + let where_clauses = vec![ + WhereClause { + field: "color".to_string(), + operator: WhereOperator::GreaterThan, + value: Value::Text("a".to_string()), + }, + WhereClause { + field: "color".to_string(), + operator: WhereOperator::LessThan, + value: Value::Text("z".to_string()), + }, + ]; + assert!( + DriveDocumentCountQuery::find_range_countable_index_for_where_clauses( + &indexes, + &where_clauses, + ) + .is_none(), + "two separate range operators must be rejected (use Between to express a bounded range)" + ); + } + + /// Pure point-lookup queries should NOT match the range picker — + /// they belong on `find_countable_index_for_where_clauses` instead. + #[test] + fn rejects_pure_point_lookup_queries() { + let indexes = make_indexes(vec![make_index( + "byColor", + &["color"], + IndexCountability::Countable, + true, + )]); + let where_clauses = vec![WhereClause { + field: "color".to_string(), + operator: WhereOperator::Equal, + value: Value::Text("red".to_string()), + }]; + assert!( + DriveDocumentCountQuery::find_range_countable_index_for_where_clauses( + &indexes, + &where_clauses, + ) + .is_none(), + "no range operator → not the range picker's job" + ); + } +} + +#[cfg(test)] +mod detect_mode_tests { + //! Coverage for [`DriveDocumentCountQuery::detect_mode`]. + //! + //! Pure validation/dispatch decisions — no Drive instance, no + //! contract, no platform_version needed. Tests the full truth + //! table of (range × In × distinct × prove). + + use super::*; + + fn eq_clause(field: &str) -> WhereClause { + WhereClause { + field: field.to_string(), + operator: WhereOperator::Equal, + value: Value::Text("x".to_string()), + } + } + fn in_clause(field: &str) -> WhereClause { + WhereClause { + field: field.to_string(), + operator: WhereOperator::In, + value: Value::Array(vec![Value::Text("a".to_string())]), + } + } + fn gt_clause(field: &str) -> WhereClause { + WhereClause { + field: field.to_string(), + operator: WhereOperator::GreaterThan, + value: Value::Text("b".to_string()), + } + } + fn lt_clause(field: &str) -> WhereClause { + WhereClause { + field: field.to_string(), + operator: WhereOperator::LessThan, + value: Value::Text("z".to_string()), + } + } + + /// No clauses, no flags → total mode. + #[test] + fn no_clauses_no_flags_is_total() { + let mode = DriveDocumentCountQuery::detect_mode(&[], false, false).unwrap(); + assert_eq!(mode, DocumentCountMode::Total); + } + + /// Equal-only clauses → still total. + #[test] + fn only_equal_clauses_is_total() { + let clauses = vec![eq_clause("a"), eq_clause("b")]; + assert_eq!( + DriveDocumentCountQuery::detect_mode(&clauses, false, false).unwrap(), + DocumentCountMode::Total, + ); + } + + /// Single In clause → per-In-value. + #[test] + fn single_in_is_per_in_value() { + let clauses = vec![in_clause("a")]; + assert_eq!( + DriveDocumentCountQuery::detect_mode(&clauses, false, false).unwrap(), + DocumentCountMode::PerInValue, + ); + } + + /// Equal + In on different fields → per-In-value. + #[test] + fn equal_plus_in_is_per_in_value() { + let clauses = vec![eq_clause("a"), in_clause("b")]; + assert_eq!( + DriveDocumentCountQuery::detect_mode(&clauses, false, false).unwrap(), + DocumentCountMode::PerInValue, + ); + } + + /// Single range + no proof → range no-proof. + #[test] + fn single_range_no_proof_is_range_no_proof() { + let clauses = vec![gt_clause("color")]; + assert_eq!( + DriveDocumentCountQuery::detect_mode(&clauses, false, false).unwrap(), + DocumentCountMode::RangeNoProof, + ); + } + + /// Single range + prove → range proof. + #[test] + fn single_range_with_prove_is_range_proof() { + let clauses = vec![gt_clause("color")]; + assert_eq!( + DriveDocumentCountQuery::detect_mode(&clauses, false, true).unwrap(), + DocumentCountMode::RangeProof, + ); + } + + /// No range + prove → point-lookup proof (materialize-and-count). + #[test] + fn no_range_with_prove_is_point_lookup_proof() { + let clauses = vec![eq_clause("a")]; + assert_eq!( + DriveDocumentCountQuery::detect_mode(&clauses, false, true).unwrap(), + DocumentCountMode::PointLookupProof, + ); + } + + /// Equal-prefix + range terminator + no proof → range no-proof. + #[test] + fn equal_prefix_plus_range_terminator_is_range_no_proof() { + let clauses = vec![eq_clause("brand"), gt_clause("color")]; + assert_eq!( + DriveDocumentCountQuery::detect_mode(&clauses, false, false).unwrap(), + DocumentCountMode::RangeNoProof, + ); + } + + /// Two range operators → rejected. + #[test] + fn two_range_operators_rejected() { + let clauses = vec![gt_clause("color"), lt_clause("color")]; + let err = DriveDocumentCountQuery::detect_mode(&clauses, false, false).unwrap_err(); + assert!(matches!( + err, + QuerySyntaxError::InvalidWhereClauseComponents(msg) if msg.contains("at most one range") + )); + } + + /// Two `In` operators → rejected. + #[test] + fn two_in_operators_rejected() { + let clauses = vec![in_clause("a"), in_clause("b")]; + let err = DriveDocumentCountQuery::detect_mode(&clauses, false, false).unwrap_err(); + assert!(matches!( + err, + QuerySyntaxError::InvalidWhereClauseComponents(msg) if msg.contains("at most one `in`") + )); + } + + /// Range + In together → routed by mode: + /// - `(range, In, no-proof, _)` → `RangeNoProof` (executor uses + /// `distinct_count_path_query`'s compound shape with grovedb + /// subqueries to cartesian-fork over the In values). + /// - `(range, In, prove, distinct=true)` → `RangeDistinctProof` + /// (same compound shape, just runs through the prove path). + /// - `(range, In, prove, distinct=false)` → **rejected** because + /// grovedb's `AggregateCountOnRange` primitive wraps a single + /// inner range and can't cartesian-fork at the merk layer. + #[test] + fn range_plus_in_routes_by_mode() { + let clauses = vec![in_clause("a"), gt_clause("b")]; + + // No-proof — both sum and distinct route through RangeNoProof, + // which uses the unified `distinct_count_path_query` builder + // and applies `options.distinct` in post-processing. + assert_eq!( + DriveDocumentCountQuery::detect_mode(&clauses, false, false).unwrap(), + DocumentCountMode::RangeNoProof, + ); + assert_eq!( + DriveDocumentCountQuery::detect_mode(&clauses, true, false).unwrap(), + DocumentCountMode::RangeNoProof, + ); + + // Prove + distinct — routes to RangeDistinctProof. The path + // query carries In as outer `Key`s and the range as the + // subquery; the verifier reconstructs the same shape. + assert_eq!( + DriveDocumentCountQuery::detect_mode(&clauses, true, true).unwrap(), + DocumentCountMode::RangeDistinctProof, + ); + + // Prove + !distinct (aggregate) — still rejected, the + // AggregateCountOnRange primitive can't fork. + let err = DriveDocumentCountQuery::detect_mode(&clauses, false, true).unwrap_err(); + assert!( + matches!( + err, + QuerySyntaxError::InvalidWhereClauseComponents(msg) + if msg.contains("not supported on the aggregate prove path") + ), + "expected aggregate-prove rejection, got: {:?}", + err, + ); + } + + /// `return_distinct_counts_in_range = true` without a range → rejected. + #[test] + fn distinct_without_range_rejected() { + let err = DriveDocumentCountQuery::detect_mode(&[], true, false).unwrap_err(); + assert!(matches!( + err, + QuerySyntaxError::InvalidWhereClauseComponents(msg) if msg.contains("requires a range where-clause") + )); + } + + /// `return_distinct_counts_in_range = true` + `prove = true` → + /// `RangeDistinctProof`. Per-distinct-value counts come from a + /// regular range proof against the property-name + /// `ProvableCountTree` (no `AggregateCountOnRange` wrapper), with + /// `KVCount(key, value, count)` ops bound to the merk root via + /// `node_hash_with_count`. The verifier extracts them as a + /// `BTreeMap, u64>`. + #[test] + fn distinct_with_prove_is_range_distinct_proof() { + let clauses = vec![gt_clause("color")]; + assert_eq!( + DriveDocumentCountQuery::detect_mode(&clauses, true, true).unwrap(), + DocumentCountMode::RangeDistinctProof, + ); + } + + /// Distinct mode in no-prove range → still RangeNoProof; the + /// distinct flag is consumed by the executor, not the mode tag. + #[test] + fn distinct_no_prove_with_range_is_range_no_proof() { + let clauses = vec![gt_clause("color")]; + assert_eq!( + DriveDocumentCountQuery::detect_mode(&clauses, true, false).unwrap(), + DocumentCountMode::RangeNoProof, + ); + } + + /// `prove = true` + `In` routes to `PointLookupProof` (the + /// materialize-and-count proof fallback). The SDK's + /// `FromProof` for `DocumentSplitCounts` + /// then groups verified documents by the In field's serialized + /// value to produce per-key count entries. No proof aggregate + /// primitive supports per-In-value entries directly, so the + /// materialize path is the only correct route until grovedb + /// gains a per-key count proof. + #[test] + fn in_with_prove_routes_to_point_lookup_proof() { + let clauses = vec![in_clause("a")]; + assert_eq!( + DriveDocumentCountQuery::detect_mode(&clauses, false, true).unwrap(), + DocumentCountMode::PointLookupProof, + ); + } +} diff --git a/packages/rs-drive/src/query/mod.rs b/packages/rs-drive/src/query/mod.rs index cfe80bfdb68..054489e7f72 100644 --- a/packages/rs-drive/src/query/mod.rs +++ b/packages/rs-drive/src/query/mod.rs @@ -3,7 +3,7 @@ use std::sync::Arc; #[cfg(any(feature = "server", feature = "verify"))] pub use { conditions::{ValueClause, WhereClause, WhereOperator}, - drive_document_count_query::{DriveDocumentCountQuery, SplitCountEntry}, + drive_document_count_query::{DocumentCountMode, DriveDocumentCountQuery, SplitCountEntry}, grovedb::{PathQuery, Query, QueryItem, SizedQuery}, ordering::OrderClause, single_document_drive_query::SingleDocumentDriveQuery, @@ -11,6 +11,11 @@ pub use { vote_polls_by_end_date_query::VotePollsByEndDateDriveQuery, vote_query::IdentityBasedVoteDriveQuery, }; + +#[cfg(feature = "server")] +pub use drive_document_count_query::{ + DocumentCountRequest, DocumentCountResponse, RangeCountOptions, +}; // Imports available when either "server" or "verify" features are enabled #[cfg(any(feature = "server", feature = "verify"))] use { diff --git a/packages/rs-drive/src/util/grove_operations/batch_insert_empty_tree_if_not_exists/mod.rs b/packages/rs-drive/src/util/grove_operations/batch_insert_empty_tree_if_not_exists/mod.rs index ff4a1bf14e7..9058647c802 100644 --- a/packages/rs-drive/src/util/grove_operations/batch_insert_empty_tree_if_not_exists/mod.rs +++ b/packages/rs-drive/src/util/grove_operations/batch_insert_empty_tree_if_not_exists/mod.rs @@ -36,6 +36,7 @@ impl Drive { 0 => self.batch_insert_empty_tree_if_not_exists_v0( path_key_info, tree_type, + false, // wrap_in_non_counted storage_flags, apply_type, transaction, @@ -50,4 +51,53 @@ impl Drive { })), } } + + /// Pushes an "insert empty `tree_type` wrapped in `Element::NonCounted`" + /// operation to `drive_operations`, but only if the path/key doesn't + /// already exist (in current state OR in pending operations). + /// + /// Used by the index walker for sibling continuations that live inside a + /// `range_countable` value tree (a `CountTree`). Without the `NonCounted` + /// wrapper, an empty child tree would contribute 1 to the parent + /// `CountTree`'s aggregate (per grovedb's default + /// `count_value_or_default()`); the wrapper makes it contribute 0 so the + /// value tree's count cleanly reflects "documents at this value" rather + /// than "documents + sibling-continuation-trees". `tree_type` is left + /// general so nested-`range_countable` shapes can pass `CountTree` / + /// `ProvableCountTree` continuations through the same helper. + #[allow(clippy::too_many_arguments)] + pub fn batch_insert_empty_non_counted_tree_if_not_exists( + &self, + path_key_info: PathKeyInfo, + tree_type: TreeType, + storage_flags: Option<&StorageFlags>, + apply_type: BatchInsertTreeApplyType, + transaction: TransactionArg, + check_existing_operations: &mut Option<&mut Vec>, + drive_operations: &mut Vec, + drive_version: &DriveVersion, + ) -> Result { + match drive_version + .grove_methods + .batch + .batch_insert_empty_tree_if_not_exists + { + 0 => self.batch_insert_empty_tree_if_not_exists_v0( + path_key_info, + tree_type, + true, // wrap_in_non_counted + storage_flags, + apply_type, + transaction, + check_existing_operations, + drive_operations, + drive_version, + ), + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "batch_insert_empty_non_counted_tree_if_not_exists".to_string(), + known_versions: vec![0], + received: version, + })), + } + } } diff --git a/packages/rs-drive/src/util/grove_operations/batch_insert_empty_tree_if_not_exists/v0/mod.rs b/packages/rs-drive/src/util/grove_operations/batch_insert_empty_tree_if_not_exists/v0/mod.rs index 86ec95eb027..88b05309967 100644 --- a/packages/rs-drive/src/util/grove_operations/batch_insert_empty_tree_if_not_exists/v0/mod.rs +++ b/packages/rs-drive/src/util/grove_operations/batch_insert_empty_tree_if_not_exists/v0/mod.rs @@ -22,6 +22,7 @@ impl Drive { &self, path_key_info: PathKeyInfo, tree_type: TreeType, + wrap_in_non_counted: bool, storage_flags: Option<&StorageFlags>, apply_type: BatchInsertTreeApplyType, transaction: TransactionArg, @@ -29,14 +30,29 @@ impl Drive { drive_operations: &mut Vec, drive_version: &DriveVersion, ) -> Result { + // The index walker uses NonCounted wrapping for sibling continuations + // inside `range_countable` value trees — see the helper docs in + // `fees/op.rs`. Wrapping is only validated for the small set of + // tree variants the walker actually emits (NormalTree / CountTree / + // ProvableCountTree); anything else falls through to the helper's + // own NotSupported error. + let build_op = + |path: Vec>, key: Vec| -> Result { + if wrap_in_non_counted { + LowLevelDriveOperation::for_known_path_key_empty_non_counted_tree( + path, + key, + tree_type, + storage_flags, + ) + } else { + tree_type.empty_tree_operation_for_known_path_key(path, key, storage_flags) + } + }; //todo: clean up the duplication match path_key_info { PathKeyRef((path, key)) => { - let drive_operation = tree_type.empty_tree_operation_for_known_path_key( - path.clone(), - key.to_vec(), - storage_flags, - )?; + let drive_operation = build_op(path.clone(), key.to_vec())?; // we only add the operation if it doesn't already exist in the current batch if let Some(existing_operations) = check_existing_operations { let mut i = 0; @@ -99,11 +115,7 @@ impl Drive { DriveError::NotSupportedPrivate("document sizes in batch operations not supported"), )), PathKey((path, key)) => { - let drive_operation = tree_type.empty_tree_operation_for_known_path_key( - path.clone(), - key.to_vec(), - storage_flags, - )?; + let drive_operation = build_op(path.clone(), key.to_vec())?; // we only add the operation if it doesn't already exist in the current batch if let Some(existing_operations) = check_existing_operations { let mut i = 0; @@ -164,11 +176,7 @@ impl Drive { } PathFixedSizeKey((path, key)) => { let path_items: Vec> = path.into_iter().map(Vec::from).collect(); - let drive_operation = tree_type.empty_tree_operation_for_known_path_key( - path_items, - key.to_vec(), - storage_flags, - )?; + let drive_operation = build_op(path_items, key.to_vec())?; // we only add the operation if it doesn't already exist in the current batch if let Some(existing_operations) = check_existing_operations { let mut i = 0; @@ -229,11 +237,7 @@ impl Drive { } PathFixedSizeKeyRef((path, key)) => { let path_items: Vec> = path.into_iter().map(Vec::from).collect(); - let drive_operation = tree_type.empty_tree_operation_for_known_path_key( - path_items, - key.to_vec(), - storage_flags, - )?; + let drive_operation = build_op(path_items, key.to_vec())?; // we only add the operation if it doesn't already exist in the current batch if let Some(existing_operations) = check_existing_operations { let mut i = 0; @@ -331,6 +335,7 @@ mod tests { .batch_insert_empty_tree_if_not_exists_v0( info, TreeType::NormalTree, + false, None, BatchInsertTreeApplyType::StatefulBatchInsertTree, Some(&tx), @@ -381,6 +386,7 @@ mod tests { .batch_insert_empty_tree_if_not_exists_v0( info, TreeType::NormalTree, + false, None, BatchInsertTreeApplyType::StatefulBatchInsertTree, Some(&tx), @@ -421,6 +427,7 @@ mod tests { .batch_insert_empty_tree_if_not_exists_v0( info, TreeType::NormalTree, + false, None, BatchInsertTreeApplyType::StatefulBatchInsertTree, Some(&tx), @@ -448,6 +455,7 @@ mod tests { let result = drive.batch_insert_empty_tree_if_not_exists_v0( info, TreeType::NormalTree, + false, None, BatchInsertTreeApplyType::StatefulBatchInsertTree, None, @@ -485,6 +493,7 @@ mod tests { .batch_insert_empty_tree_if_not_exists_v0( info, TreeType::NormalTree, + false, None, BatchInsertTreeApplyType::StatefulBatchInsertTree, Some(&tx), @@ -524,6 +533,7 @@ mod tests { .batch_insert_empty_tree_if_not_exists_v0( info, TreeType::NormalTree, + false, None, BatchInsertTreeApplyType::StatefulBatchInsertTree, Some(&tx), @@ -563,6 +573,7 @@ mod tests { .batch_insert_empty_tree_if_not_exists_v0( info, TreeType::NormalTree, + false, None, BatchInsertTreeApplyType::StatefulBatchInsertTree, Some(&tx), diff --git a/packages/rs-drive/src/verify/document_count/mod.rs b/packages/rs-drive/src/verify/document_count/mod.rs new file mode 100644 index 00000000000..8d0bebf1596 --- /dev/null +++ b/packages/rs-drive/src/verify/document_count/mod.rs @@ -0,0 +1,25 @@ +//! Verifies grovedb proofs produced by the `GetDocumentsCount` endpoint. +//! +//! Mirrors the layering used by `packages/rs-drive/src/verify/document/`: +//! pure grovedb-level verifiers as methods on +//! [`DriveDocumentCountQuery`](crate::query::DriveDocumentCountQuery) +//! that take raw `proof: &[u8]` and return `(RootHash, T)`. The tenderdash +//! signature composition layer that wraps these calls lives in +//! `packages/rs-drive-proof-verifier/src/proof/document_count.rs`. + +/// Aggregate-count proof verification (`AggregateCountOnRange` +/// primitive) — returns a single `u64`. +pub mod verify_aggregate_count_proof; +/// Distinct-count proof verification (regular range proof against a +/// `ProvableCountTree`) — returns the per-`(in_key, key)` entries the +/// proof commits to. +pub mod verify_distinct_count_proof; +/// Point-lookup count proof verification (CountTree element proof for +/// Equal/`In` counts on a `countable: true` index) — returns one entry +/// per covered branch, with each `count` extracted from the verified +/// CountTree element's `count_value`. +pub mod verify_point_lookup_count_proof; +/// Primary-key CountTree proof verification — used by the +/// `documents_countable: true` fast path for unfiltered total counts +/// at the doctype level. Returns a single `u64` count. +pub mod verify_primary_key_count_tree_proof; diff --git a/packages/rs-drive/src/verify/document_count/verify_aggregate_count_proof/mod.rs b/packages/rs-drive/src/verify/document_count/verify_aggregate_count_proof/mod.rs new file mode 100644 index 00000000000..ca54dc9b988 --- /dev/null +++ b/packages/rs-drive/src/verify/document_count/verify_aggregate_count_proof/mod.rs @@ -0,0 +1,46 @@ +mod v0; + +use crate::error::drive::DriveError; +use crate::error::Error; +use crate::query::DriveDocumentCountQuery; +use crate::verify::RootHash; +use dpp::version::PlatformVersion; + +impl DriveDocumentCountQuery<'_> { + /// Verifies an `AggregateCountOnRange` proof and returns + /// `(root_hash, count)`. + /// + /// Counterpart to the prover-side + /// [`execute_aggregate_count_with_proof`](Self::execute_aggregate_count_with_proof): + /// rebuilds the same `PathQuery` via + /// [`aggregate_count_path_query`](Self::aggregate_count_path_query) + /// and calls `GroveDb::verify_aggregate_count_query`. The + /// caller is responsible for combining the returned `root_hash` + /// with the surrounding tenderdash signature — see + /// `rs-drive-proof-verifier`'s `verify_aggregate_count_proof` + /// wrapper for the canonical composition. + /// + /// # Arguments + /// * `proof` — raw grovedb proof bytes. + /// * `platform_version` — selects the method version. + pub fn verify_aggregate_count_proof( + &self, + proof: &[u8], + platform_version: &PlatformVersion, + ) -> Result<(RootHash, u64), Error> { + match platform_version + .drive + .methods + .verify + .document_count + .verify_aggregate_count_proof + { + 0 => self.verify_aggregate_count_proof_v0(proof, platform_version), + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "DriveDocumentCountQuery::verify_aggregate_count_proof".to_string(), + known_versions: vec![0], + received: version, + })), + } + } +} diff --git a/packages/rs-drive/src/verify/document_count/verify_aggregate_count_proof/v0/mod.rs b/packages/rs-drive/src/verify/document_count/verify_aggregate_count_proof/v0/mod.rs new file mode 100644 index 00000000000..623d47d6238 --- /dev/null +++ b/packages/rs-drive/src/verify/document_count/verify_aggregate_count_proof/v0/mod.rs @@ -0,0 +1,36 @@ +use crate::error::Error; +use crate::query::DriveDocumentCountQuery; +use crate::verify::RootHash; +use dpp::version::PlatformVersion; +use grovedb::GroveDb; + +impl DriveDocumentCountQuery<'_> { + /// v0 of [`Self::verify_aggregate_count_proof`]. + /// + /// Rebuilds the same `PathQuery` the prover used via + /// [`Self::aggregate_count_path_query`] and feeds it through + /// `GroveDb::verify_aggregate_count_query`. The merk-level + /// `AggregateCountOnRange` primitive returns a single `u64` + /// directly (capped only by the merk tree size, not `u16::MAX`). + /// + /// Prover/verifier byte-for-byte path query agreement is + /// load-bearing: any drift in serialization of the path bytes, + /// the range query item, or the limit field would break the + /// merk-root recomputation. Both sides share + /// [`Self::aggregate_count_path_query`] for that reason. + #[inline(always)] + pub(super) fn verify_aggregate_count_proof_v0( + &self, + proof: &[u8], + platform_version: &PlatformVersion, + ) -> Result<(RootHash, u64), Error> { + let path_query = self.aggregate_count_path_query(platform_version)?; + let (root_hash, count) = GroveDb::verify_aggregate_count_query( + proof, + &path_query, + &platform_version.drive.grove_version, + ) + .map_err(|e| Error::GroveDB(Box::new(e)))?; + Ok((root_hash, count)) + } +} diff --git a/packages/rs-drive/src/verify/document_count/verify_distinct_count_proof/mod.rs b/packages/rs-drive/src/verify/document_count/verify_distinct_count_proof/mod.rs new file mode 100644 index 00000000000..62745caac8f --- /dev/null +++ b/packages/rs-drive/src/verify/document_count/verify_distinct_count_proof/mod.rs @@ -0,0 +1,61 @@ +mod v0; + +use crate::error::drive::DriveError; +use crate::error::Error; +use crate::query::{DriveDocumentCountQuery, SplitCountEntry}; +use crate::verify::RootHash; +use dpp::version::PlatformVersion; + +impl DriveDocumentCountQuery<'_> { + /// Verifies a regular grovedb range proof against a + /// `ProvableCountTree` and returns `(root_hash, entries)`. Each + /// entry's `count` is bound to the merk root via + /// `node_hash_with_count(kv_hash, l_hash, r_hash, count)`, so + /// once this returns `Ok` every count is cryptographically + /// committed to the same `root_hash` the caller can pass to a + /// tenderdash signature check. + /// + /// Counterpart to the prover-side + /// [`execute_distinct_count_with_proof`](Self::execute_distinct_count_with_proof): + /// rebuilds the same `PathQuery` via + /// [`distinct_count_path_query`](Self::distinct_count_path_query) + /// and calls `GroveDb::verify_query`. Caller is responsible for + /// combining the returned `root_hash` with the surrounding + /// tenderdash signature — see `rs-drive-proof-verifier`'s + /// `verify_distinct_count_proof` wrapper for the canonical + /// composition. + /// + /// Entries are emitted unmerged: for compound (`In`-on-prefix) + /// queries each entry retains its `in_key` (the In value for + /// that fork) alongside the terminator `key`. See + /// [`SplitCountEntry`]'s doc for the no-merge rationale. + /// + /// # Arguments + /// * `proof` — raw grovedb proof bytes. + /// * `limit` — the same limit the prover applied (also used to + /// reconstruct the matching path query). + /// * `left_to_right` — same iteration direction the prover used. + /// * `platform_version` — selects the method version. + pub fn verify_distinct_count_proof( + &self, + proof: &[u8], + limit: u16, + left_to_right: bool, + platform_version: &PlatformVersion, + ) -> Result<(RootHash, Vec), Error> { + match platform_version + .drive + .methods + .verify + .document_count + .verify_distinct_count_proof + { + 0 => self.verify_distinct_count_proof_v0(proof, limit, left_to_right, platform_version), + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "DriveDocumentCountQuery::verify_distinct_count_proof".to_string(), + known_versions: vec![0], + received: version, + })), + } + } +} diff --git a/packages/rs-drive/src/verify/document_count/verify_distinct_count_proof/v0/mod.rs b/packages/rs-drive/src/verify/document_count/verify_distinct_count_proof/v0/mod.rs new file mode 100644 index 00000000000..e1184c9245b --- /dev/null +++ b/packages/rs-drive/src/verify/document_count/verify_distinct_count_proof/v0/mod.rs @@ -0,0 +1,79 @@ +use crate::error::Error; +use crate::query::{DriveDocumentCountQuery, SplitCountEntry, WhereOperator}; +use crate::verify::RootHash; +use dpp::version::PlatformVersion; +use grovedb::GroveDb; + +impl DriveDocumentCountQuery<'_> { + /// v0 of [`Self::verify_distinct_count_proof`]. + /// + /// Rebuilds the same `PathQuery` the prover used via + /// [`Self::distinct_count_path_query`] (including `limit` and + /// `left_to_right` — both are encoded into the path query + /// bytes), feeds it through `GroveDb::verify_query`, then walks + /// the verified `(path, key, Option)` triples to build + /// the per-`(in_key, key)` entry list. + /// + /// For compound queries (`In` on prefix) the In value sits at + /// `path[base_path_len]` (the first extra path segment beyond + /// the path query's `path`); for flat queries the emitted path + /// equals `path_query.path`, so `in_key` stays `None`. + /// + /// Cross-fork aggregation is intentionally NOT done here — + /// callers reduce by `key` client-side if they want a flat + /// histogram. See [`SplitCountEntry`]'s doc for the no-merge + /// rationale. + /// + /// `GroveDb::verify_query` is appropriate here for both flat and + /// compound shapes: + /// - For flat queries (no `In` on prefix) the path query has a + /// single range `QueryItem` and no explicit `Key` items; + /// range items can't be enumerated for absence checks anyway + /// (`Query::terminal_keys_inner` errors `NotSupported` on + /// unbounded ranges). + /// - For compound queries (`In` on prefix) the outer Query has + /// explicit `Key` items per In value, but because we don't sum + /// across forks, a missing `Key` branch surfaces as missing + /// entries with that `in_key` rather than as a wrong total — + /// the caller can detect "I asked for 3 In values but only + /// got entries for 2" directly. We don't need + /// `absence_proofs_for_non_existing_searched_keys: true` for + /// soundness; it would be a useful future addition for + /// "prove this In value has zero entries" but isn't required. + #[inline(always)] + pub(super) fn verify_distinct_count_proof_v0( + &self, + proof: &[u8], + limit: u16, + left_to_right: bool, + platform_version: &PlatformVersion, + ) -> Result<(RootHash, Vec), Error> { + let path_query = + self.distinct_count_path_query(Some(limit), left_to_right, platform_version)?; + let base_path_len = path_query.path.len(); + let has_in_on_prefix = self + .where_clauses + .iter() + .any(|wc| wc.operator == WhereOperator::In); + let (root_hash, elements) = + GroveDb::verify_query(proof, &path_query, &platform_version.drive.grove_version) + .map_err(|e| Error::GroveDB(Box::new(e)))?; + + let mut out: Vec = Vec::with_capacity(elements.len()); + for (path, key, elem) in elements { + if let Some(e) = elem { + let count = e.count_value_or_default(); + if count == 0 { + continue; + } + let in_key = if has_in_on_prefix && path.len() > base_path_len { + Some(path[base_path_len].clone()) + } else { + None + }; + out.push(SplitCountEntry { in_key, key, count }); + } + } + Ok((root_hash, out)) + } +} diff --git a/packages/rs-drive/src/verify/document_count/verify_point_lookup_count_proof/mod.rs b/packages/rs-drive/src/verify/document_count/verify_point_lookup_count_proof/mod.rs new file mode 100644 index 00000000000..18d69f17afa --- /dev/null +++ b/packages/rs-drive/src/verify/document_count/verify_point_lookup_count_proof/mod.rs @@ -0,0 +1,66 @@ +mod v0; + +use crate::error::drive::DriveError; +use crate::error::Error; +use crate::query::{DriveDocumentCountQuery, SplitCountEntry}; +use crate::verify::RootHash; +use dpp::version::PlatformVersion; + +impl DriveDocumentCountQuery<'_> { + /// Verifies a grovedb proof of CountTree elements produced by the + /// point-lookup count proof path and returns `(root_hash, entries)`. + /// + /// Counterpart to the prover-side + /// [`execute_point_lookup_count_with_proof`](Self::execute_point_lookup_count_with_proof): + /// rebuilds the same `PathQuery` via + /// [`point_lookup_count_path_query`](Self::point_lookup_count_path_query) + /// and calls `GroveDb::verify_query`. Each verified element's + /// `count_value` is cryptographically bound to the merk root via + /// `node_hash_with_count(kv_hash, l_hash, r_hash, count)`, so once + /// this returns `Ok` every count is committed to the same + /// `root_hash` the caller can pass to a tenderdash signature check. + /// Caller is responsible for combining the returned `root_hash` + /// with the surrounding tenderdash signature — see + /// `rs-drive-proof-verifier`'s `verify_point_lookup_count_proof` + /// wrapper for the canonical composition. + /// + /// Entry shape: + /// - **Equal-only, fully covered**: a single entry with + /// `in_key: None`, `key: vec![]`, and `count` equal to the + /// covered branch's CountTree `count_value`. + /// - **`In` at any index position (with any number of trailing + /// Equals)**: one entry per In value, with `in_key: None`, + /// `key: `, and `count` equal to that In + /// branch's CountTree `count_value`. When the In has trailing + /// Equal clauses after it (e.g. `a IN [..] AND b = y AND c = z` + /// on index `[a, b, c]`), those Equals are part of the descent + /// so each branch's count is "docs with `in_field == in_value + /// AND `"; the entry's `key` still + /// records just the In value because the trailing Equals are + /// fixed across all entries. Matches the no-proof `PerInValue` + /// shape (`in_key` is reserved for the range-distinct compound + /// case where In sits on a prefix of a range index). + /// + /// Branches with no documents at the covered path don't appear in + /// the result (CountTree element is absent → no entry emitted). + pub fn verify_point_lookup_count_proof( + &self, + proof: &[u8], + platform_version: &PlatformVersion, + ) -> Result<(RootHash, Vec), Error> { + match platform_version + .drive + .methods + .verify + .document_count + .verify_point_lookup_count_proof + { + 0 => self.verify_point_lookup_count_proof_v0(proof, platform_version), + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "DriveDocumentCountQuery::verify_point_lookup_count_proof".to_string(), + known_versions: vec![0], + received: version, + })), + } + } +} diff --git a/packages/rs-drive/src/verify/document_count/verify_point_lookup_count_proof/v0/mod.rs b/packages/rs-drive/src/verify/document_count/verify_point_lookup_count_proof/v0/mod.rs new file mode 100644 index 00000000000..e8a2ca2f446 --- /dev/null +++ b/packages/rs-drive/src/verify/document_count/verify_point_lookup_count_proof/v0/mod.rs @@ -0,0 +1,96 @@ +use crate::error::Error; +use crate::query::{DriveDocumentCountQuery, SplitCountEntry, WhereOperator}; +use crate::verify::RootHash; +use dpp::version::PlatformVersion; +use grovedb::GroveDb; + +impl DriveDocumentCountQuery<'_> { + /// v0 of [`Self::verify_point_lookup_count_proof`]. + /// + /// Rebuilds the same `PathQuery` the prover used via + /// [`Self::point_lookup_count_path_query`], feeds it through + /// `GroveDb::verify_query`, and walks the verified + /// `(path, key, Option)` triples to build the per-branch + /// entry list. + /// + /// For the compound shape (`In` at any index position, with 0..N + /// trailing Equals afterwards) the In value sits at + /// `path[base_path_len]` — the first extra path segment beyond + /// the path query's `path`. The builder stops `base_path` at the + /// In-bearing property's property-name subtree (see + /// [`Self::point_lookup_count_path_query`]), regardless of how + /// many trailing Equals exist, so the In value lands at the same + /// offset in every compound emission. For the Equal-only shape + /// the emitted path equals `path_query.path` so the entry's `key` + /// stays empty. + /// + /// `GroveDb::verify_query` is appropriate here for the same reason + /// as the distinct-count verifier: because each branch's count is + /// returned as its own entry, a missing `Key` branch (no documents + /// at that In value) surfaces as a missing entry rather than a + /// wrong total — the caller can detect "I asked for 3 In values + /// but got entries for 2" directly. We don't need + /// `absence_proofs_for_non_existing_searched_keys: true` for + /// soundness; it would be a useful future addition for "prove this + /// In value has zero entries" but isn't required for the unmerged + /// per-branch contract. + #[inline(always)] + pub(super) fn verify_point_lookup_count_proof_v0( + &self, + proof: &[u8], + platform_version: &PlatformVersion, + ) -> Result<(RootHash, Vec), Error> { + let path_query = self.point_lookup_count_path_query(platform_version)?; + let base_path_len = path_query.path.len(); + // Set once an `In` clause is present anywhere on the covering + // index — the builder stops `base_path` at the In-bearing + // property's name subtree regardless of how many trailing + // Equals descend further, so the In value always sits at + // `path[base_path_len]` in the compound emission. + let has_in_clause = self + .where_clauses + .iter() + .any(|wc| wc.operator == WhereOperator::In); + let (root_hash, elements) = + GroveDb::verify_query(proof, &path_query, &platform_version.drive.grove_version) + .map_err(|e| Error::GroveDB(Box::new(e)))?; + + let mut out: Vec = Vec::with_capacity(elements.len()); + for (path, _grove_key, elem) in elements { + // `_grove_key` is the trailing key on the path (always + // `[0]` here — the CountTree key under the value tree); + // we don't store it in the entry because the count's + // user-visible key is the In value (compound shape) or + // empty (Equal-only). + let Some(e) = elem else { continue }; + let count = e.count_value_or_default(); + if count == 0 { + continue; + } + // Compound shape (In at any index position, 0..N + // trailing Equals afterwards): the In value sits at + // `path[base_path_len]` — the first extra segment past + // the path query's base path. When trailing Equals are + // present the descent continues through + // `[trailing_prop_name_1, trailing_value_1, ..., + // trailing_prop_name_n, trailing_value_n, 0]`, but the + // In value is still at the same offset because + // `base_path` stops at the In-bearing property's + // property-name subtree regardless of how many trailing + // segments follow. Equal-only shape: the emitted path + // equals `path_query.path` (no extra segments) so the + // `key` field is empty. + let key = if has_in_clause && path.len() > base_path_len { + path[base_path_len].clone() + } else { + Vec::new() + }; + out.push(SplitCountEntry { + in_key: None, + key, + count, + }); + } + Ok((root_hash, out)) + } +} diff --git a/packages/rs-drive/src/verify/document_count/verify_primary_key_count_tree_proof/mod.rs b/packages/rs-drive/src/verify/document_count/verify_primary_key_count_tree_proof/mod.rs new file mode 100644 index 00000000000..2e9a4797675 --- /dev/null +++ b/packages/rs-drive/src/verify/document_count/verify_primary_key_count_tree_proof/mod.rs @@ -0,0 +1,62 @@ +mod v0; + +use crate::error::drive::DriveError; +use crate::error::Error; +use crate::query::DriveDocumentCountQuery; +use crate::verify::RootHash; +use dpp::version::PlatformVersion; + +impl DriveDocumentCountQuery<'_> { + /// Verifies a grovedb proof of the document type's primary-key + /// `CountTree` element and returns `(root_hash, count)`. Used by + /// the SDK to verify the response from the prove path's + /// `documents_countable: true` fast path — unfiltered total + /// counts on a doctype whose primary-key tree is itself a + /// CountTree. + /// + /// Free-function on the type rather than `&self` because the + /// documents_countable case isn't tied to any index — it + /// operates on the doctype primary-key tree directly. The + /// `contract_id` + `document_type_name` are all the verifier + /// needs to reconstruct the same `PathQuery` the prover used + /// via [`Self::primary_key_count_tree_path_query`]. + /// + /// The verified count is cryptographically bound to the merk + /// root via `node_hash_with_count(kv_hash, l_hash, r_hash, + /// count)` — same forge-resistance guarantee the other count- + /// proof verifiers rely on. Once this returns `Ok`, the count is + /// committed to the `root_hash` the caller passes to the + /// tenderdash signature check. + /// + /// Returns `count = 0` when the CountTree element is absent + /// (fresh doctype with no documents inserted). The + /// documents_countable storage layout creates the type-level + /// CountTree at contract apply time, so absence really does mean + /// "zero docs"; callers can rely on it. + pub fn verify_primary_key_count_tree_proof( + proof: &[u8], + contract_id: [u8; 32], + document_type_name: &str, + platform_version: &PlatformVersion, + ) -> Result<(RootHash, u64), Error> { + match platform_version + .drive + .methods + .verify + .document_count + .verify_primary_key_count_tree_proof + { + 0 => Self::verify_primary_key_count_tree_proof_v0( + proof, + contract_id, + document_type_name, + platform_version, + ), + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "DriveDocumentCountQuery::verify_primary_key_count_tree_proof".to_string(), + known_versions: vec![0], + received: version, + })), + } + } +} diff --git a/packages/rs-drive/src/verify/document_count/verify_primary_key_count_tree_proof/v0/mod.rs b/packages/rs-drive/src/verify/document_count/verify_primary_key_count_tree_proof/v0/mod.rs new file mode 100644 index 00000000000..52c59aab079 --- /dev/null +++ b/packages/rs-drive/src/verify/document_count/verify_primary_key_count_tree_proof/v0/mod.rs @@ -0,0 +1,42 @@ +use crate::error::Error; +use crate::query::DriveDocumentCountQuery; +use crate::verify::RootHash; +use dpp::version::PlatformVersion; +use grovedb::GroveDb; + +impl DriveDocumentCountQuery<'_> { + /// v0 of [`Self::verify_primary_key_count_tree_proof`]. + /// + /// Rebuilds the same `PathQuery` the prover used via + /// [`Self::primary_key_count_tree_path_query`], feeds it through + /// `GroveDb::verify_query`, and extracts `count_value_or_default()` + /// from the verified CountTree element at `[..., doctype, 0]`. + /// + /// Returns 0 when the element is absent (`elements` empty or the + /// only emitted element is `None`). The documents_countable + /// storage layout creates the type-level CountTree at contract + /// apply time, so absence means "no documents inserted yet", not + /// "documents_countable is misconfigured". + #[inline(always)] + pub(super) fn verify_primary_key_count_tree_proof_v0( + proof: &[u8], + contract_id: [u8; 32], + document_type_name: &str, + platform_version: &PlatformVersion, + ) -> Result<(RootHash, u64), Error> { + let path_query = Self::primary_key_count_tree_path_query(contract_id, document_type_name); + let (root_hash, elements) = + GroveDb::verify_query(proof, &path_query, &platform_version.drive.grove_version) + .map_err(|e| Error::GroveDB(Box::new(e)))?; + + // The path query asks for exactly one key (`[0]`) under the + // doctype path, so `elements` is either empty (CountTree + // absent) or has a single `(path, [0], Some(CountTree))` + // triple. Extract the count if present; 0 otherwise. + let count = elements + .into_iter() + .find_map(|(_, _, elem)| elem.map(|e| e.count_value_or_default())) + .unwrap_or(0); + Ok((root_hash, count)) + } +} diff --git a/packages/rs-drive/src/verify/mod.rs b/packages/rs-drive/src/verify/mod.rs index 5179fcef77c..505d2b497fa 100644 --- a/packages/rs-drive/src/verify/mod.rs +++ b/packages/rs-drive/src/verify/mod.rs @@ -4,6 +4,9 @@ pub mod contract; /// Document verification methods on proofs pub mod document; +/// Document-count verification methods on proofs (the +/// `GetDocumentsCount` endpoint's prove-path verifiers). +pub mod document_count; /// Identity verification methods on proofs pub mod identity; /// Single Document verification methods on proofs diff --git a/packages/rs-platform-version/Cargo.toml b/packages/rs-platform-version/Cargo.toml index 0796b3263b3..95195cea75d 100644 --- a/packages/rs-platform-version/Cargo.toml +++ b/packages/rs-platform-version/Cargo.toml @@ -11,7 +11,7 @@ license = "MIT" thiserror = { version = "2.0.12" } bincode = { version = "=2.0.1" } versioned-feature-core = { git = "https://github.com/dashpay/versioned-feature-core", version = "1.0.0" } -grovedb-version = { git = "https://github.com/dashpay/grovedb", rev = "dbd83dce59fbcf2866e9dd06be4ce6c320e37908" } +grovedb-version = { git = "https://github.com/dashpay/grovedb", rev = "a917d92d2477672eed73c4c08e53e93449a6a094" } [features] mock-versions = [] diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/mod.rs b/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/mod.rs index 29aae7ef5b6..da5014455b5 100644 --- a/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/mod.rs +++ b/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/mod.rs @@ -2,6 +2,7 @@ use versioned_feature_core::FeatureVersion; pub mod v1; pub mod v2; +pub mod v3; #[derive(Clone, Debug, Default)] pub struct DriveContractMethodVersions { diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/v3.rs b/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/v3.rs new file mode 100644 index 00000000000..2cf0723baef --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/v3.rs @@ -0,0 +1,52 @@ +use crate::version::drive_versions::drive_contract_method_versions::{ + DriveContractApplyMethodVersions, DriveContractCostsMethodVersions, + DriveContractGetMethodVersions, DriveContractInsertMethodVersions, DriveContractMethodVersions, + DriveContractProveMethodVersions, DriveContractUpdateMethodVersions, +}; + +/// Drive contract methods for protocol v12+. +/// +/// Identical to [`super::v2::DRIVE_CONTRACT_METHOD_VERSIONS_V2`] except +/// `costs.add_estimation_costs_for_contract_insertion` is bumped to `1`. +/// +/// The v1 estimation method makes the per-doctype layer info reflect the +/// actual mix of count-bearing vs normal child subtrees — required for fee +/// accuracy once `documentsCountable` / `rangeCountable` doctypes (a v12+ +/// feature) are exposed. For pre-v12 contracts (no countable flags) the v0 +/// and v1 methods produce byte-identical results, so the bump only changes +/// observable fees for contracts that opt into the new flags. +pub const DRIVE_CONTRACT_METHOD_VERSIONS_V3: DriveContractMethodVersions = + DriveContractMethodVersions { + prove: DriveContractProveMethodVersions { + prove_contract: 0, + prove_contract_history: 0, + prove_contracts: 0, + }, + apply: DriveContractApplyMethodVersions { + apply_contract: 0, + apply_contract_with_serialization: 0, + }, + insert: DriveContractInsertMethodVersions { + add_contract_to_storage: 0, + insert_contract: 1, + add_description: 0, + add_keywords: 0, + }, + update: DriveContractUpdateMethodVersions { + update_contract: 1, + update_description: 0, + update_keywords: 0, + }, + costs: DriveContractCostsMethodVersions { + add_estimation_costs_for_contract_insertion: 1, // <--- v12: count-tree-aware + }, + get: DriveContractGetMethodVersions { + fetch_contract: 0, + fetch_contract_ids: 0, + fetch_contracts: 0, + fetch_contract_with_history: 0, + get_cached_contract_with_fetch_info: 0, + get_contract_with_fetch_info: 0, + get_contracts_with_fetch_info: 0, + }, + }; diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_verify_method_versions/mod.rs b/packages/rs-platform-version/src/version/drive_versions/drive_verify_method_versions/mod.rs index cc6279e6022..8a840c4d43d 100644 --- a/packages/rs-platform-version/src/version/drive_versions/drive_verify_method_versions/mod.rs +++ b/packages/rs-platform-version/src/version/drive_versions/drive_verify_method_versions/mod.rs @@ -6,6 +6,7 @@ pub mod v1; pub struct DriveVerifyMethodVersions { pub contract: DriveVerifyContractMethodVersions, pub document: DriveVerifyDocumentMethodVersions, + pub document_count: DriveVerifyDocumentCountMethodVersions, pub identity: DriveVerifyIdentityMethodVersions, pub group: DriveVerifyGroupMethodVersions, pub token: DriveVerifyTokenMethodVersions, @@ -44,6 +45,18 @@ pub struct DriveVerifyDocumentMethodVersions { pub verify_start_at_document_in_proof: FeatureVersion, } +/// Versions for the `GetDocumentsCount` prove-path verifiers +/// (grovedb-level — the tenderdash composition layer lives in +/// rs-drive-proof-verifier). All three methods are implemented on +/// `DriveDocumentCountQuery` and return `(RootHash, T)`. +#[derive(Clone, Debug, Default)] +pub struct DriveVerifyDocumentCountMethodVersions { + pub verify_aggregate_count_proof: FeatureVersion, + pub verify_distinct_count_proof: FeatureVersion, + pub verify_point_lookup_count_proof: FeatureVersion, + pub verify_primary_key_count_tree_proof: FeatureVersion, +} + #[derive(Clone, Debug, Default)] pub struct DriveVerifyIdentityMethodVersions { pub verify_full_identities_by_public_key_hashes: FeatureVersion, diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_verify_method_versions/v1.rs b/packages/rs-platform-version/src/version/drive_versions/drive_verify_method_versions/v1.rs index e8e49036dd9..8ea2bc10914 100644 --- a/packages/rs-platform-version/src/version/drive_versions/drive_verify_method_versions/v1.rs +++ b/packages/rs-platform-version/src/version/drive_versions/drive_verify_method_versions/v1.rs @@ -1,7 +1,7 @@ use crate::version::drive_versions::drive_verify_method_versions::{ DriveVerifyAddressFundsMethodVersions, DriveVerifyContractMethodVersions, - DriveVerifyDocumentMethodVersions, DriveVerifyGroupMethodVersions, - DriveVerifyIdentityMethodVersions, DriveVerifyMethodVersions, + DriveVerifyDocumentCountMethodVersions, DriveVerifyDocumentMethodVersions, + DriveVerifyGroupMethodVersions, DriveVerifyIdentityMethodVersions, DriveVerifyMethodVersions, DriveVerifyShieldedMethodVersions, DriveVerifySingleDocumentMethodVersions, DriveVerifyStateTransitionMethodVersions, DriveVerifySystemMethodVersions, DriveVerifyTokenMethodVersions, DriveVerifyVoteMethodVersions, @@ -18,6 +18,12 @@ pub const DRIVE_VERIFY_METHOD_VERSIONS_V1: DriveVerifyMethodVersions = DriveVeri verify_proof_keep_serialized: 0, verify_start_at_document_in_proof: 0, }, + document_count: DriveVerifyDocumentCountMethodVersions { + verify_aggregate_count_proof: 0, + verify_distinct_count_proof: 0, + verify_point_lookup_count_proof: 0, + verify_primary_key_count_tree_proof: 0, + }, identity: DriveVerifyIdentityMethodVersions { verify_full_identities_by_public_key_hashes: 0, verify_full_identity_by_identity_id: 0, diff --git a/packages/rs-platform-version/src/version/drive_versions/v7.rs b/packages/rs-platform-version/src/version/drive_versions/v7.rs index 213f4197c2e..cc47c1d1ed6 100644 --- a/packages/rs-platform-version/src/version/drive_versions/v7.rs +++ b/packages/rs-platform-version/src/version/drive_versions/v7.rs @@ -1,5 +1,5 @@ use crate::version::drive_versions::drive_address_funds_method_versions::v1::DRIVE_ADDRESS_FUNDS_METHOD_VERSIONS_V1; -use crate::version::drive_versions::drive_contract_method_versions::v2::DRIVE_CONTRACT_METHOD_VERSIONS_V2; +use crate::version::drive_versions::drive_contract_method_versions::v3::DRIVE_CONTRACT_METHOD_VERSIONS_V3; use crate::version::drive_versions::drive_credit_pool_method_versions::v1::CREDIT_POOL_METHOD_VERSIONS_V1; use crate::version::drive_versions::drive_document_method_versions::v2::DRIVE_DOCUMENT_METHOD_VERSIONS_V2; use crate::version::drive_versions::drive_group_method_versions::v1::DRIVE_GROUP_METHOD_VERSIONS_V1; @@ -54,7 +54,7 @@ pub const DRIVE_VERSION_V7: DriveVersion = DriveVersion { }, document: DRIVE_DOCUMENT_METHOD_VERSIONS_V2, vote: DRIVE_VOTE_METHOD_VERSIONS_V2, - contract: DRIVE_CONTRACT_METHOD_VERSIONS_V2, + contract: DRIVE_CONTRACT_METHOD_VERSIONS_V3, // changed: count-tree-aware contract-insertion cost estimation (v12+ countable/range_countable doctypes) fees: DriveFeesMethodVersions { calculate_fee: 0 }, estimated_costs: DriveEstimatedCostsMethodVersions { add_estimation_costs_for_levels_up_to_contract: 0, diff --git a/packages/rs-platform-wallet/Cargo.toml b/packages/rs-platform-wallet/Cargo.toml index 9d9bdae0377..c766d7759ef 100644 --- a/packages/rs-platform-wallet/Cargo.toml +++ b/packages/rs-platform-wallet/Cargo.toml @@ -48,7 +48,7 @@ image = { version = "0.25", default-features = false, features = ["png", "jpeg", zeroize = "1" # Shielded pool (optional, behind `shielded` feature) -grovedb-commitment-tree = { git = "https://github.com/dashpay/grovedb", rev = "dbd83dce59fbcf2866e9dd06be4ce6c320e37908", optional = true } +grovedb-commitment-tree = { git = "https://github.com/dashpay/grovedb", rev = "a917d92d2477672eed73c4c08e53e93449a6a094", optional = true } zip32 = { version = "0.2.0", default-features = false, optional = true } [dev-dependencies] diff --git a/packages/rs-sdk-ffi/src/document/mod.rs b/packages/rs-sdk-ffi/src/document/mod.rs index 4205f9426ac..4d72923ee79 100644 --- a/packages/rs-sdk-ffi/src/document/mod.rs +++ b/packages/rs-sdk-ffi/src/document/mod.rs @@ -20,7 +20,10 @@ pub use price::{ pub use purchase::{dash_sdk_document_purchase, dash_sdk_document_purchase_and_wait}; pub use put::{dash_sdk_document_put_to_platform, dash_sdk_document_put_to_platform_and_wait}; pub use queries::info::dash_sdk_document_get_info; -pub use queries::{dash_sdk_document_fetch, dash_sdk_document_search, DashSDKDocumentSearchParams}; +pub use queries::{ + dash_sdk_document_count, dash_sdk_document_fetch, dash_sdk_document_search, + DashSDKDocumentSearchParams, +}; pub use replace::{ dash_sdk_document_replace_on_platform, dash_sdk_document_replace_on_platform_and_wait, }; diff --git a/packages/rs-sdk-ffi/src/document/queries/count.rs b/packages/rs-sdk-ffi/src/document/queries/count.rs index 6913adbfc58..83ec4c5adaf 100644 --- a/packages/rs-sdk-ffi/src/document/queries/count.rs +++ b/packages/rs-sdk-ffi/src/document/queries/count.rs @@ -1,8 +1,18 @@ -//! Document count + split-count query operations. +//! Unified document-count FFI for iOS / native callers. //! -//! Wraps the rs-sdk `DocumentCount::fetch` and `DocumentSplitCounts::fetch` -//! flows so iOS / native callers can obtain document counts without having -//! to construct `GetDocumentsCountRequest` payloads themselves. +//! Wraps the rs-sdk `DocumentSplitCounts::fetch` flow (which handles +//! every count mode — total, per-`In`-value, per-distinct-value-in- +//! range, summed-over-range) so callers can obtain document counts +//! without having to construct `GetDocumentsCountRequest` payloads +//! themselves. +//! +//! The previous version exposed two functions (`dash_sdk_document_count` +//! returning a single u64, `dash_sdk_document_split_count` returning a +//! per-key map). Now that the count endpoint carries +//! `return_distinct_counts_in_range`, `order_by`, and `limit`, the +//! split path subsumes the simple-total case (total count becomes a +//! one-entry map with empty key), so we expose one entry point with +//! all the knobs. use std::collections::BTreeMap; use std::ffi::{CStr, CString}; @@ -10,12 +20,11 @@ use std::os::raw::c_char; use dash_sdk::dpp::platform_value::Value; use dash_sdk::dpp::prelude::DataContract; -use dash_sdk::drive::query::{WhereClause, WhereOperator}; +use dash_sdk::drive::query::{OrderClause, WhereClause, WhereOperator}; use dash_sdk::platform::documents::document_count_query::DocumentCountQuery; use dash_sdk::platform::documents::document_query::DocumentQuery; -use dash_sdk::platform::documents::document_split_count_query::DocumentSplitCountQuery; use dash_sdk::platform::Fetch; -use drive_proof_verifier::{DocumentCount, DocumentSplitCounts}; +use drive_proof_verifier::DocumentSplitCounts; use serde::{Deserialize, Serialize}; use serde_json; @@ -30,18 +39,38 @@ struct WhereClauseJson { value: serde_json::Value, } -#[derive(Debug, Serialize)] -struct DocumentCountResult { - count: u64, +#[derive(Debug, Deserialize)] +struct OrderClauseJson { + field: String, + /// `"asc"` (default) or `"desc"`. Direction strings match the + /// regular document-fetch FFI surface so callers can reuse their + /// JSON shapes between count and fetch. + direction: String, } #[derive(Debug, Serialize)] -struct DocumentSplitCountResult { - /// Per-key counts. Keys are hex-encoded so iOS callers can match them - /// against the corresponding platform-value-encoded property bytes. +struct DocumentCountResult { + /// Per-key counts. Keys are hex-encoded so iOS callers can match + /// them against the corresponding platform-value-encoded property + /// bytes. For total-count requests (no `in` clause and + /// `return_distinct_counts_in_range = false`) this is a one-entry + /// map with an empty key. counts: BTreeMap, } +/// Map the wire/JSON operator token to a `WhereOperator`. +/// +/// Accepts the full range-operator surface drive's +/// `range_clause_to_query_item` supports (`between`, +/// `betweenExcludeBounds`, `betweenExcludeLeft`, +/// `betweenExcludeRight` — value must be a 2-element array +/// `[lower, upper]`), so iOS/Swift callers can issue every range +/// shape the count endpoint's prove and no-proof paths verify +/// against. Operator names match the wasm bindings' +/// `parse_where_operator` for cross-language parity. Camel-case is +/// the canonical wire form, with kebab-case (`between-exclude-*`) +/// and lower-snake-case (`between_exclude_*`) aliases accepted as +/// a convenience for callers that already normalize to those styles. #[allow(clippy::result_large_err)] fn parse_where_operator(op: &str) -> Result { match op { @@ -52,6 +81,19 @@ fn parse_where_operator(op: &str) -> Result { "<=" | "lte" => Ok(WhereOperator::LessThanOrEquals), "in" => Ok(WhereOperator::In), "startsWith" => Ok(WhereOperator::StartsWith), + // Range bounds: value is `[lower, upper]`. Drive's + // `range_clause_to_query_item` validates the 2-element + // array + ordered bounds. + "between" => Ok(WhereOperator::Between), + "betweenExcludeBounds" | "between-exclude-bounds" | "between_exclude_bounds" => { + Ok(WhereOperator::BetweenExcludeBounds) + } + "betweenExcludeLeft" | "between-exclude-left" | "between_exclude_left" => { + Ok(WhereOperator::BetweenExcludeLeft) + } + "betweenExcludeRight" | "between-exclude-right" | "between_exclude_right" => { + Ok(WhereOperator::BetweenExcludeRight) + } _ => Err(FFIError::InternalError(format!( "Unknown where operator: {}", op @@ -59,6 +101,18 @@ fn parse_where_operator(op: &str) -> Result { } } +#[allow(clippy::result_large_err)] +fn parse_order_direction(direction: &str) -> Result { + match direction { + "asc" | "ascending" => Ok(true), + "desc" | "descending" => Ok(false), + _ => Err(FFIError::InternalError(format!( + "Unknown order_by direction: {} (use \"asc\" or \"desc\")", + direction + ))), + } +} + #[allow(clippy::result_large_err)] fn json_to_platform_value(json: serde_json::Value) -> Result { match json { @@ -96,6 +150,7 @@ unsafe fn build_base_query( data_contract: &DataContract, document_type: *const c_char, where_json: *const c_char, + order_by_json: *const c_char, ) -> Result { let document_type_str = CStr::from_ptr(document_type) .to_str() @@ -124,17 +179,76 @@ unsafe fn build_base_query( } } + if !order_by_json.is_null() { + let order_str = CStr::from_ptr(order_by_json) + .to_str() + .map_err(FFIError::from)?; + if !order_str.is_empty() { + let clauses: Vec = serde_json::from_str(order_str) + .map_err(|e| FFIError::InternalError(format!("Invalid order_by JSON: {}", e)))?; + for clause in clauses { + let ascending = parse_order_direction(&clause.direction)?; + query = query.with_order_by(OrderClause { + field: clause.field, + ascending, + }); + } + } + } + Ok(query) } /// Count documents matching a query. /// -/// Returns a JSON string of shape `{"count": }`. +/// Returns a JSON string of shape `{"counts": {"": , ...}}`. +/// Hex keys correspond to the platform-value-encoded property values +/// from the underlying CountTree / ProvableCountTree path; iOS callers +/// should hex-decode them and decode against the contract's index- +/// property type if they need a typed key. +/// +/// For simple total counts (no `in` clause in `where_json` and +/// `return_distinct_counts_in_range = false`) the result is a one-entry +/// map with an empty key — `counts[""]` is the total. +/// +/// Per-key result shapes: +/// - **`in` clause**: one entry per (deduped) value in the In array. +/// - **range clause + `return_distinct_counts_in_range = true`**: one +/// entry per distinct property value within the range. For compound +/// queries (`in` on a prefix property + range on the terminator), the +/// per-`in_key`/per-`key` entries are summed by `key` into a flat +/// map. Callers needing the unmerged compound shape should use a +/// richer binding (not yet exposed via this entry point). +/// +/// # Tunables +/// - `return_distinct_counts_in_range`: when `true` AND the query has +/// a range clause, returns per-distinct-value entries instead of a +/// single sum. No-op when there's no range clause. +/// - `order_by_json`: optional JSON `[{"field": "", "direction": +/// "asc"|"desc"}]`. The first clause's direction controls split-mode +/// entry ordering server-side; on the `RangeDistinctProof` prove +/// path it is part of the path-query bytes the SDK reconstructs to +/// verify the proof (prover and verifier must agree — empty +/// `order_by` defaults to ascending on both sides). On the +/// `PointLookupProof` path (`(In, prove, no-range)`) order_by is +/// not consulted: the path-query builder sorts In keys lex- +/// ascending unconditionally for prove/no-proof parity. Null or +/// empty → no orderBy (ascending default for split-mode entry +/// direction). +/// - `limit`: `-1` = use server default +/// (`default_query_limit` on no-proof paths, +/// `crate::config::DEFAULT_QUERY_LIMIT` on the prove-distinct path — +/// the compile-time constant the SDK verifier reads, so proof bytes +/// stay deterministic across operators). `≥ 0` = explicit cap +/// (clamped to `max_query_limit` on no-proof paths, rejected with +/// `InvalidLimit` if too large on the prove-distinct path — silent +/// clamping would invisibly break verification). /// /// # Safety /// - `sdk_handle` and `data_contract_handle` must be valid, non-null pointers. /// - `document_type` must be a NUL-terminated C string valid for the duration of the call. /// - `where_json` may be null; if non-null it must be a NUL-terminated JSON string of `[{field, operator, value}]`. +/// - `order_by_json` may be null; if non-null it must be a NUL-terminated JSON string of `[{field, direction}]`. /// - On success, returns a heap-allocated C string pointer; caller must free it using SDK routines. #[no_mangle] pub unsafe extern "C" fn dash_sdk_document_count( @@ -142,6 +256,9 @@ pub unsafe extern "C" fn dash_sdk_document_count( data_contract_handle: *const DataContractHandle, document_type: *const c_char, where_json: *const c_char, + order_by_json: *const c_char, + return_distinct_counts_in_range: bool, + limit: i64, ) -> DashSDKResult { if sdk_handle.is_null() || data_contract_handle.is_null() || document_type.is_null() { return DashSDKResult::error(DashSDKError::new( @@ -154,84 +271,39 @@ pub unsafe extern "C" fn dash_sdk_document_count( let data_contract = &*(data_contract_handle as *const DataContract); let result: Result = wrapper.runtime.block_on(async { - let base_query = build_base_query(data_contract, document_type, where_json)?; - let count_query = DocumentCountQuery { - document_query: base_query, - }; - - let count = DocumentCount::fetch(&wrapper.sdk, count_query) - .await - .map_err(|e| FFIError::InternalError(format!("Failed to fetch count: {}", e)))? - .map(|c| c.0) - .unwrap_or(0); - - serde_json::to_string(&DocumentCountResult { count }) - .map_err(|e| FFIError::InternalError(format!("Failed to serialize result: {}", e))) - }); + let base_query = build_base_query(data_contract, document_type, where_json, order_by_json)?; - match result { - Ok(json) => match CString::new(json) { - Ok(s) => DashSDKResult::success_string(s.into_raw()), - Err(e) => DashSDKResult::error(DashSDKError::new( - DashSDKErrorCode::InternalError, - format!("Failed to create CString: {}", e), - )), - }, - Err(e) => DashSDKResult::error(e.into()), - } -} - -/// Count documents matching a query, split by an index property. -/// -/// Returns a JSON string of shape `{"counts": {"": , ...}}`. -/// Hex keys correspond to the platform-value-encoded property values from the -/// underlying split-count tree; iOS callers should hex-decode them and decode -/// against the contract's index-property type if they need a typed key. -/// -/// # Safety -/// - `sdk_handle`, `data_contract_handle`, `document_type`, and `split_property` must be valid, non-null pointers. -/// - `document_type` and `split_property` must be NUL-terminated C strings valid for the duration of the call. -/// - `where_json` may be null; if non-null it must be a NUL-terminated JSON string of `[{field, operator, value}]`. -/// - On success, returns a heap-allocated C string pointer; caller must free it using SDK routines. -#[no_mangle] -pub unsafe extern "C" fn dash_sdk_document_split_count( - sdk_handle: *const SDKHandle, - data_contract_handle: *const DataContractHandle, - document_type: *const c_char, - split_property: *const c_char, - where_json: *const c_char, -) -> DashSDKResult { - if sdk_handle.is_null() - || data_contract_handle.is_null() - || document_type.is_null() - || split_property.is_null() - { - return DashSDKResult::error(DashSDKError::new( - DashSDKErrorCode::InvalidParameter, - "SDK handle, data contract handle, document type, or split property is null" - .to_string(), - )); - } - - let wrapper = &*(sdk_handle as *const SDKWrapper); - let data_contract = &*(data_contract_handle as *const DataContract); - - let split_property_str = match CStr::from_ptr(split_property).to_str() { - Ok(s) => s.to_string(), - Err(e) => return DashSDKResult::error(FFIError::from(e).into()), - }; + // Sentinel decoding for the C ABI. `-1` means "unset; use + // server-side default". The Rust-side request field is + // `Option` so `None` here is the same as the request + // omitting the field on the wire. + let limit_opt = if limit < 0 { + None + } else if limit > u32::MAX as i64 { + return Err(FFIError::InternalError(format!( + "limit {} exceeds u32::MAX", + limit + ))); + } else { + Some(limit as u32) + }; - let result: Result = wrapper.runtime.block_on(async { - let base_query = build_base_query(data_contract, document_type, where_json)?; - let split_query = DocumentSplitCountQuery { + let count_query = DocumentCountQuery { document_query: base_query, - split_property: split_property_str, + return_distinct_counts_in_range, + limit: limit_opt, }; - let split_counts = DocumentSplitCounts::fetch(&wrapper.sdk, split_query) + // `DocumentSplitCounts::fetch` handles every count mode — + // for total-count requests the result is a one-entry map + // with empty key (so `result.counts[""]` is the total). + // `into_flat_map` collapses any compound (in_key + key) + // entries by summing over `in_key`; callers needing the + // unmerged shape should use a richer binding. + let split_counts = DocumentSplitCounts::fetch(&wrapper.sdk, count_query) .await - .map_err(|e| FFIError::InternalError(format!("Failed to fetch split counts: {}", e)))? - .map(|s| s.0) + .map_err(|e| FFIError::InternalError(format!("Failed to fetch count: {}", e)))? + .map(|s| s.into_flat_map()) .unwrap_or_default(); let counts: BTreeMap = split_counts @@ -239,7 +311,7 @@ pub unsafe extern "C" fn dash_sdk_document_split_count( .map(|(k, v)| (hex::encode(k), v)) .collect(); - serde_json::to_string(&DocumentSplitCountResult { counts }) + serde_json::to_string(&DocumentCountResult { counts }) .map_err(|e| FFIError::InternalError(format!("Failed to serialize result: {}", e))) }); diff --git a/packages/rs-sdk-ffi/src/document/queries/mod.rs b/packages/rs-sdk-ffi/src/document/queries/mod.rs index f21de165ace..bc9399dccf7 100644 --- a/packages/rs-sdk-ffi/src/document/queries/mod.rs +++ b/packages/rs-sdk-ffi/src/document/queries/mod.rs @@ -5,8 +5,6 @@ pub mod fetch; pub mod info; pub mod search; -// Re-export all public functions for convenient access -#[allow(unused_imports)] -pub use count::{dash_sdk_document_count, dash_sdk_document_split_count}; +pub use count::dash_sdk_document_count; pub use fetch::dash_sdk_document_fetch; pub use search::{dash_sdk_document_search, DashSDKDocumentSearchParams}; diff --git a/packages/rs-sdk/Cargo.toml b/packages/rs-sdk/Cargo.toml index 77b7583c65f..f16146d20ba 100644 --- a/packages/rs-sdk/Cargo.toml +++ b/packages/rs-sdk/Cargo.toml @@ -18,7 +18,7 @@ drive = { path = "../rs-drive", default-features = false, features = [ ] } drive-proof-verifier = { path = "../rs-drive-proof-verifier", default-features = false } -grovedb-commitment-tree = { git = "https://github.com/dashpay/grovedb", rev = "dbd83dce59fbcf2866e9dd06be4ce6c320e37908", features = ["client", "sqlite"], optional = true } +grovedb-commitment-tree = { git = "https://github.com/dashpay/grovedb", rev = "a917d92d2477672eed73c4c08e53e93449a6a094", features = ["client", "sqlite"], optional = true } dash-async = { path = "../rs-dash-async" } dash-context-provider = { path = "../rs-context-provider", default-features = false } dash-platform-macros = { path = "../rs-dash-platform-macros" } diff --git a/packages/rs-sdk/src/mock/requests.rs b/packages/rs-sdk/src/mock/requests.rs index 60b73e8eb35..485c9f2588f 100644 --- a/packages/rs-sdk/src/mock/requests.rs +++ b/packages/rs-sdk/src/mock/requests.rs @@ -587,17 +587,34 @@ impl MockResponse for drive_proof_verifier::DocumentCount { impl MockResponse for drive_proof_verifier::DocumentSplitCounts { fn mock_serialize(&self, _sdk: &MockDashPlatformSdk) -> Vec { let bincode_config = standard(); - let pairs: Vec<(Vec, u64)> = self.0.iter().map(|(k, v)| (k.clone(), *v)).collect(); - bincode::encode_to_vec(pairs, bincode_config).expect("encode DocumentSplitCounts") + // Serialize as `(Option>, Vec, u64)` triples so + // the In dimension survives the mock roundtrip. Required for + // compound (`In + range + distinct`) test fixtures to keep + // their `in_key` values across the mock encode/decode hop. + let triples: Vec<(Option>, Vec, u64)> = self + .0 + .iter() + .map(|e| (e.in_key.clone(), e.key.clone(), e.count)) + .collect(); + bincode::encode_to_vec(triples, bincode_config).expect("encode DocumentSplitCounts") } fn mock_deserialize(_sdk: &MockDashPlatformSdk, buf: &[u8]) -> Self where Self: Sized, { + // Alias the wire triple so clippy doesn't flag the bincode + // generic as too complex. Same shape mock_serialize emits. + type DecodedTriples = Vec<(Option>, Vec, u64)>; let bincode_config = standard(); - let (pairs, _): (Vec<(Vec, u64)>, _) = + let (triples, _): (DecodedTriples, _) = bincode::decode_from_slice(buf, bincode_config).expect("decode DocumentSplitCounts"); - drive_proof_verifier::DocumentSplitCounts(pairs.into_iter().collect()) + let entries: Vec = triples + .into_iter() + .map( + |(in_key, key, count)| drive_proof_verifier::SplitCountEntry { in_key, key, count }, + ) + .collect(); + drive_proof_verifier::DocumentSplitCounts::from_verified(entries) } } diff --git a/packages/rs-sdk/src/mock/sdk.rs b/packages/rs-sdk/src/mock/sdk.rs index 95f3885b4cf..764e3734573 100644 --- a/packages/rs-sdk/src/mock/sdk.rs +++ b/packages/rs-sdk/src/mock/sdk.rs @@ -137,15 +137,9 @@ impl MockDashPlatformSdk { "DocumentCountQuery" => load_expectation::< crate::platform::documents::document_count_query::DocumentCountQuery, >(&mut dapi, filename)?, - "DocumentSplitCountQuery" => load_expectation::< - crate::platform::documents::document_split_count_query::DocumentSplitCountQuery, - >(&mut dapi, filename)?, "GetDocumentsCountRequest" => { load_expectation::(&mut dapi, filename)? } - "GetDocumentsSplitCountRequest" => { - load_expectation::(&mut dapi, filename)? - } "GetEpochsInfoRequest" => { load_expectation::(&mut dapi, filename)? } diff --git a/packages/rs-sdk/src/platform/documents/document_count_query.rs b/packages/rs-sdk/src/platform/documents/document_count_query.rs index 4f01de9b096..bb7aeaa44db 100644 --- a/packages/rs-sdk/src/platform/documents/document_count_query.rs +++ b/packages/rs-sdk/src/platform/documents/document_count_query.rs @@ -17,15 +17,24 @@ use dapi_grpc::platform::v0::get_documents_count_request::{ use dapi_grpc::platform::v0::{ GetDocumentsCountRequest, GetDocumentsCountResponse, Proof, ResponseMetadata, }; +use dapi_grpc::platform::VersionedGrpcResponse; use dash_context_provider::ContextProvider; use dpp::dashcore::Network; use dpp::version::PlatformVersion; use dpp::{ - data_contract::accessors::v0::DataContractV0Getters, platform_value::Value, - prelude::DataContract, ProtocolError, + data_contract::accessors::v0::DataContractV0Getters, + data_contract::document_type::accessors::{DocumentTypeV0Getters, DocumentTypeV2Getters}, + platform_value::Value, + prelude::DataContract, + ProtocolError, +}; +use drive::query::{ + DriveDocumentCountQuery, DriveDocumentQuery, OrderClause, WhereClause, WhereOperator, +}; +use drive_proof_verifier::{ + verify_aggregate_count_proof, verify_distinct_count_proof, verify_point_lookup_count_proof, + verify_primary_key_count_tree_proof, DocumentCount, DocumentSplitCounts, FromProof, }; -use drive::query::{DriveDocumentQuery, WhereClause}; -use drive_proof_verifier::{DocumentCount, FromProof}; use rs_dapi_client::transport::{ AppliedRequestSettings, BoxFuture, TransportError, TransportRequest, }; @@ -34,6 +43,10 @@ use rs_dapi_client::transport::{ /// /// Wraps a [`DocumentQuery`] (so we can reuse its [`DriveDocumentQuery`] /// conversion machinery) and is consumed by [`DocumentCount::fetch`]. +/// +/// Field defaults match the gRPC defaults: total-count summed result, +/// ascending order, no limit, proof-verifying transport. Setters +/// override individual fields without disturbing the rest. #[derive(Debug, Clone, dash_platform_macros::Mockable)] #[cfg_attr(feature = "mocks", derive(serde::Serialize, serde::Deserialize))] pub struct DocumentCountQuery { @@ -41,6 +54,43 @@ pub struct DocumentCountQuery { /// data-contract / document-type / where-clauses inputs as the /// regular document query. pub document_query: DocumentQuery, + /// `return_distinct_counts_in_range` request flag. Meaningful + /// when the where clauses contain a range operator: routes the + /// request to the per-distinct-value execution path on both + /// no-proof (`RangeNoProof`) AND prove (`RangeDistinctProof`) + /// transports. The prove path returns a regular range proof + /// against the property-name `ProvableCountTree` whose `KVCount` + /// ops carry per-distinct-value counts; the SDK's + /// `FromProof` for `DocumentSplitCounts` + /// extracts them via `verify_distinct_count_proof`. Default: + /// `false`. + pub return_distinct_counts_in_range: bool, + /// `limit` cap for distinct-mode entries. + /// - **No-proof paths**: server clamps to its `max_query_limit` + /// config; passing a larger value just gets clamped, not + /// rejected. + /// - **Prove path** (`RangeDistinctProof`): validate-don't-clamp. + /// `limit > max_query_limit` is rejected by the server with + /// `Error::Query(QuerySyntaxError::InvalidLimit(...))` because + /// silent clamping would invisibly break proof verification. + /// Unset falls back to `drive::config::DEFAULT_QUERY_LIMIT` + /// (the same compile-time constant the SDK verifier reads), + /// so proof bytes are deterministic across operators + /// regardless of their runtime `default_query_limit` tuning. + /// + /// No cursor field: pagination is expressed by narrowing the + /// underlying range itself (`color > `), which is equivalent in expressivity and avoids the + /// ambiguity a single-`bytes` cursor would have for compound + /// (`In + range + distinct`) queries whose natural sort is + /// `(in_key, key)`. + pub limit: Option, + // Order direction lives on the wrapped `document_query` — + // `DocumentQuery::order_by_clauses` is serialized into the + // request's `order_by` field. The first clause's direction + // controls split-mode entry ordering server-side; clauses are + // also load-bearing for `(In + prove)` walk determinism (see the + // `FromProof` impl below). } impl DocumentCountQuery { @@ -51,6 +101,8 @@ impl DocumentCountQuery { ) -> Result { Ok(Self { document_query: DocumentQuery::new(contract, document_type_name)?, + return_distinct_counts_in_range: false, + limit: None, }) } @@ -59,12 +111,47 @@ impl DocumentCountQuery { self.document_query = self.document_query.with_where(clause); self } + + /// Add an order_by clause to the underlying query. The first + /// clause's direction controls split-mode entry ordering + /// server-side and is part of the path query bytes on the + /// `RangeDistinctProof` prove path (so prover and verifier must + /// agree; empty `order_by` defaults to ascending on both sides). + /// Unused on the `PointLookupProof` path — the builder sorts In + /// keys lex-ascending unconditionally for prove/no-proof parity. + pub fn with_order_by(mut self, clause: OrderClause) -> Self { + self.document_query = self.document_query.with_order_by(clause); + self + } + + /// Set `return_distinct_counts_in_range`. Meaningful with a + /// range where-clause on both no-proof and prove transports + /// (see field doc). + pub fn with_distinct_counts_in_range(mut self, distinct: bool) -> Self { + self.return_distinct_counts_in_range = distinct; + self + } + + /// Cap distinct-mode entry count. + /// - No-proof paths: server clamps to its `max_query_limit`. + /// - Prove path: server rejects `limit > max_query_limit` with + /// `InvalidLimit` rather than clamping silently (clamping + /// would invisibly break verification). Unset falls back to + /// `drive::config::DEFAULT_QUERY_LIMIT`, the same compile-time + /// constant the SDK verifier uses — see the field doc for + /// the deterministic-across-operators rationale. + pub fn with_limit(mut self, limit: Option) -> Self { + self.limit = limit; + self + } } impl<'a> From<&'a DriveDocumentQuery<'a>> for DocumentCountQuery { fn from(value: &'a DriveDocumentQuery<'a>) -> Self { Self { document_query: value.into(), + return_distinct_counts_in_range: false, + limit: None, } } } @@ -73,40 +160,59 @@ impl<'a> From> for DocumentCountQuery { fn from(value: DriveDocumentQuery<'a>) -> Self { Self { document_query: value.into(), + return_distinct_counts_in_range: false, + limit: None, } } } -impl<'a> TryFrom<&'a DocumentCountQuery> for DriveDocumentQuery<'a> { - type Error = Error; - - fn try_from(query: &'a DocumentCountQuery) -> Result { - // Force the underlying DriveDocumentQuery to be unbounded. - // - // The proof verifier counts documents from the verified proof, so - // any limit set on the wrapped DocumentQuery would silently cap the - // returned count. The server-side count handler also runs with no - // limit, so the client must match. Without this, callers (e.g. the - // WASM SDK, which defaults DocumentQuery.limit to 100) would see - // a count truncated at their pagination limit instead of the actual - // total. - let mut drive_query: DriveDocumentQuery = (&query.document_query).try_into()?; - drive_query.limit = None; - Ok(drive_query) - } -} - impl TryFrom for GetDocumentsCountRequest { type Error = Error; fn try_from(query: DocumentCountQuery) -> Result { let where_bytes = serialize_where_clauses_to_cbor(&query.document_query.where_clauses)?; + let order_by_bytes = + serialize_order_by_clauses_to_cbor(&query.document_query.order_by_clauses)?; Ok(GetDocumentsCountRequest { version: Some(GetDocumentsCountRequestVersion::V0( GetDocumentsCountRequestV0 { data_contract_id: query.document_query.data_contract.id().to_vec(), document_type: query.document_query.document_type_name.clone(), r#where: where_bytes, + return_distinct_counts_in_range: query.return_distinct_counts_in_range, + order_by: order_by_bytes, + limit: query.limit, + // **Count Fetch always proves.** The SDK `Fetch` + // path is wired through `FromProof`, + // which only knows how to decode the `Proof(...)` + // response variant — the no-proof `Counts(...)` / + // `Entries(...)` variants need a different decoder + // entry point that doesn't exist yet on the SDK + // side. Setting this to anything other than + // `true` would either silently fail at decode + // time or strip the verification guarantee the + // rest of the SDK assumes. + // + // `SdkBuilder::with_proofs(false)` is consequently + // a **no-op** for `DocumentCountQuery` — the + // blanket `Query for T` impl in + // `packages/rs-sdk/src/platform/query.rs:119-124` + // emits a `tracing::warn!` at `Fetch::fetch` + // time when proofs are disabled, but the request + // still ships with `prove: true` and the + // response is decoded through + // `FromProof`. The server's + // unified `GetDocumentsCount` endpoint supports + // no-proof modes (`Total` / `PerInValue` / + // `RangeNoProof`) but the SDK has no typed + // decoder for them yet — shadowing the blanket + // impl to intercept the flag is blocked by + // Rust's coherence rules (`Query for T` + // covers all `T: TransportRequest`, and + // `DocumentCountQuery` IS its own + // `TransportRequest`). Wiring a no-proof + // decoder is tracked as + // dashpay/platform#3630. prove: true, }, )), @@ -133,9 +239,21 @@ impl TransportRequest for DocumentCountQuery { client: &'c mut Self::Client, settings: &AppliedRequestSettings, ) -> BoxFuture<'c, Result> { - let request: GetDocumentsCountRequest = self - .try_into() - .expect("DocumentCountQuery should always be valid"); + // CBOR-serializing the where clauses can fail on values that + // aren't representable (the conversion goes through ciborium). + // Surface that as a recoverable transport error rather than + // panicking — callers expect `Fetch` failures to be matchable + // on `Error::DapiClientError`, not aborts. + let request: GetDocumentsCountRequest = match self.try_into() { + Ok(r) => r, + Err(e) => { + let status = dapi_grpc::tonic::Status::internal(format!( + "DocumentCountQuery -> GetDocumentsCountRequest conversion failed: {}", + e + )); + return Box::pin(async move { Err(TransportError::Grpc(status)) }); + } + }; request.execute_transport(client, settings) } } @@ -147,7 +265,7 @@ impl FromProof for DocumentCount { 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), drive_proof_verifier::Error> @@ -155,23 +273,199 @@ impl FromProof for DocumentCount { Self: 'a, { let request: Self::Request = request.into(); - let drive_query: DriveDocumentQuery = - (&request) - .try_into() + + // Range queries arrive with a grovedb `AggregateCountOnRange` + // proof (produced by `Drive::execute_document_count_range_proof`) + // that the materialize-and-count path below can't decode. Pivot + // to the merk-level aggregate verifier instead, building the + // exact same `PathQuery` the prover used via the shared + // `DriveDocumentCountQuery::aggregate_count_path_query` builder + // (kept in rs-drive under `cfg(any(server, verify))` so prover + // and verifier never drift). + if request + .document_query + .where_clauses + .iter() + .any(|wc| DriveDocumentCountQuery::is_range_operator(wc.operator)) + { + let response: Self::Response = response.into(); + + let document_type = request + .document_query + .data_contract + .document_type_for_name(&request.document_query.document_type_name) .map_err(|e| drive_proof_verifier::Error::RequestError { error: format!( - "Failed to convert DocumentCountQuery to DriveDocumentQuery: {}", - e + "document type {} not found in contract: {}", + request.document_query.document_type_name, e ), })?; + let index = DriveDocumentCountQuery::find_range_countable_index_for_where_clauses( + document_type.indexes(), + &request.document_query.where_clauses, + ) + .ok_or_else(|| drive_proof_verifier::Error::RequestError { + error: "range count requires a `range_countable: true` index whose last \ + property matches the range field" + .to_string(), + })?; + + let count_query = DriveDocumentCountQuery { + document_type, + contract_id: request.document_query.data_contract.id().to_buffer(), + document_type_name: request.document_query.document_type_name.clone(), + index, + where_clauses: request.document_query.where_clauses.clone(), + }; + let proof = response + .proof() + .or(Err(drive_proof_verifier::Error::NoProofInResult))?; + let mtd = response + .metadata() + .or(Err(drive_proof_verifier::Error::EmptyResponseMetadata))?; + + // Dispatch on `return_distinct_counts_in_range`. The + // server's `detect_mode` routes + // `(range, prove=true, distinct=true)` to + // `RangeDistinctProof` (emits per-key `KVCount` ops) and + // `(range, prove=true, distinct=false)` to `RangeProof` + // (emits a single `AggregateCountOnRange` aggregate); + // the two proof shapes are NOT interchangeable. + // Decoding a distinct proof with the aggregate verifier + // would fail merk-root recomputation because the path + // queries differ structurally. + if request.return_distinct_counts_in_range { + // Mirror the SDK's prove-distinct dispatcher (see the + // `FromProof for DocumentSplitCounts` + // impl below) to rebuild the same path query the + // prover signed. The limit anchors to the compile-time + // `DEFAULT_QUERY_LIMIT` constant (matching the + // server's `drive_dispatcher.rs` `RangeDistinctProof` + // arm) so proof bytes are deterministic across + // operators. Direction comes from the first + // `order_by` clause, defaulting to ascending. + let limit_u16 = match request.limit { + Some(l) => { + u16::try_from(l).map_err(|_| drive_proof_verifier::Error::RequestError { + error: format!( + "limit {} exceeds u16::MAX; the prove-distinct path query \ + cannot represent it", + l + ), + })? + } + None => drive::config::DEFAULT_QUERY_LIMIT, + }; + let left_to_right = request + .document_query + .order_by_clauses + .first() + .map(|c| c.ascending) + .unwrap_or(true); - >::maybe_from_proof_with_metadata( - drive_query, - response, - network, - platform_version, - provider, + let entries = verify_distinct_count_proof( + &count_query, + proof, + mtd, + limit_u16, + left_to_right, + platform_version, + provider, + )?; + // `DocumentCount` collapses to a single aggregate + // u64. Sum the verified per-key counts. The proof's + // `KVCount` ops are merk-root-bound via + // `node_hash_with_count`, so the sum is + // cryptographically committed — same forge-resistance + // as `AggregateCountOnRange`, just expressed as a + // post-verification reduction in Rust. + let total: u64 = entries.iter().map(|e| e.count).sum(); + return Ok((Some(DocumentCount(total)), mtd.clone(), proof.clone())); + } + + // Range + prove + !distinct: aggregate proof path. The + // verifier helper rebuilds the prover's path query + // internally via `count_query.aggregate_count_path_query` + // — same builder both sides share, so the path query + // bytes match byte-for-byte and the merk root + // recomputation succeeds. + let count = + verify_aggregate_count_proof(&count_query, proof, mtd, platform_version, provider)?; + return Ok((Some(DocumentCount(count)), mtd.clone(), proof.clone())); + } + + // No range clause: route through the count-tree proof + // primitives. Two sub-cases mirror the server-side dispatch: + // + // 1. **documents_countable + empty where**: the doctype's + // primary-key tree is itself a CountTree. The server + // proves that element directly; the SDK verifies and + // extracts `count_value`. O(log n) proof, no index. + // 2. **Else**: must have a `countable: true` index whose + // properties exactly match the where clauses. Server + // proves the per-branch CountTree elements; SDK sums their + // `count_value`s. Rejection on missing covering index is + // symmetric with the no-proof side. + let response: Self::Response = response.into(); + let document_type = request + .document_query + .data_contract + .document_type_for_name(&request.document_query.document_type_name) + .map_err(|e| drive_proof_verifier::Error::RequestError { + error: format!( + "document type {} not found in contract: {}", + request.document_query.document_type_name, e + ), + })?; + let proof = response + .proof() + .or(Err(drive_proof_verifier::Error::NoProofInResult))?; + let mtd = response + .metadata() + .or(Err(drive_proof_verifier::Error::EmptyResponseMetadata))?; + + // documents_countable fast path + if request.document_query.where_clauses.is_empty() && document_type.documents_countable() { + let contract_id = request.document_query.data_contract.id().to_buffer(); + let count = verify_primary_key_count_tree_proof( + contract_id, + &request.document_query.document_type_name, + proof, + mtd, + platform_version, + provider, + )?; + return Ok((Some(DocumentCount(count)), mtd.clone(), proof.clone())); + } + + let index = DriveDocumentCountQuery::find_countable_index_for_where_clauses( + document_type.indexes(), + &request.document_query.where_clauses, ) + .ok_or_else(|| drive_proof_verifier::Error::RequestError { + error: "prove count requires a `countable: true` index whose properties \ + exactly match the where clause fields, or `documentsCountable: \ + true` on the document type for unfiltered total counts" + .to_string(), + })?; + let count_query = DriveDocumentCountQuery { + document_type, + contract_id: request.document_query.data_contract.id().to_buffer(), + document_type_name: request.document_query.document_type_name.clone(), + index, + where_clauses: request.document_query.where_clauses.clone(), + }; + + let entries = + verify_point_lookup_count_proof(&count_query, proof, mtd, platform_version, provider)?; + // `DocumentCount` is a single aggregate u64 — sum the per- + // branch CountTree entries. For Equal-only fully-covered the + // verifier returns a single entry (empty `key`) and the sum + // is just that entry's count; for Equal-prefix + In-on-last + // it sums the per-In-value counts. A branch with zero docs is + // omitted by the verifier so missing entries contribute 0. + let total: u64 = entries.iter().map(|e| e.count).sum(); + Ok((Some(DocumentCount(total)), mtd.clone(), proof.clone())) } } @@ -179,6 +473,265 @@ impl Fetch for DocumentCount { type Request = DocumentCountQuery; } +/// Per-key counts view of the unified count endpoint. +/// +/// Backed by the same [`DocumentCountQuery`] as [`DocumentCount`]; the only +/// difference is response shape — `DocumentSplitCounts` returns the full +/// `entries` map keyed by the splitting property's serialized value, while +/// `DocumentCount` returns the sum. +/// +/// Splitting is signalled by an `In` where-clause on the request: the field +/// of that clause becomes the split property and each value in the array +/// becomes one entry in the result. Without an `In` clause the response is +/// a single entry with empty key (i.e., the total count). +impl FromProof for DocumentSplitCounts { + type Request = DocumentCountQuery; + type Response = GetDocumentsCountResponse; + + 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), drive_proof_verifier::Error> + where + Self: 'a, + { + let request: Self::Request = request.into(); + + // `has_in` controls the single-empty-key-entry guarantee on + // the no-range prove path: Equal-only fully-covered queries + // promise one entry with empty key (the verified count, even + // if zero); In-on-last queries promise one entry per emitted + // In value (zero-count branches are simply absent). + let has_in = request + .document_query + .where_clauses + .iter() + .any(|wc| wc.operator == WhereOperator::In); + + let has_range = request + .document_query + .where_clauses + .iter() + .any(|wc| DriveDocumentCountQuery::is_range_operator(wc.operator)); + + // Range + distinct (with or without In on prefix): per- + // distinct-value counts via a regular merk range proof + // (no `AggregateCountOnRange` wrapper). The proof's + // `KVCount` ops carry per-`(in_key, key)` counts that the + // merk root commits to via `node_hash_with_count`, so + // `verify_distinct_count_proof` runs the standard hash + // chain check and reads the counts back as a verified + // `Vec`. For compound queries the In + // value is preserved in each entry's `in_key` — callers can + // reduce by `key` via `DocumentSplitCounts::into_flat_map` + // if they want the merged-histogram shape. Only reachable + // when the SDK builder set + // `with_distinct_counts_in_range(true)`. + if has_range && request.return_distinct_counts_in_range { + let response: Self::Response = response.into(); + + let document_type = request + .document_query + .data_contract + .document_type_for_name(&request.document_query.document_type_name) + .map_err(|e| drive_proof_verifier::Error::RequestError { + error: format!( + "document type {} not found in contract: {}", + request.document_query.document_type_name, e + ), + })?; + let index = DriveDocumentCountQuery::find_range_countable_index_for_where_clauses( + document_type.indexes(), + &request.document_query.where_clauses, + ) + .ok_or_else(|| drive_proof_verifier::Error::RequestError { + error: "distinct range count requires a `range_countable: true` index whose \ + last property matches the range field" + .to_string(), + })?; + + let count_query = DriveDocumentCountQuery { + document_type, + contract_id: request.document_query.data_contract.id().to_buffer(), + document_type_name: request.document_query.document_type_name.clone(), + index, + where_clauses: request.document_query.where_clauses.clone(), + }; + // Match the prover's defaults for limit and order so + // the verifier helper can rebuild the same path query + // internally. The server's prove-distinct dispatcher + // anchors its fallback to `crate::config::DEFAULT_QUERY_LIMIT` + // (the same compile-time constant we read here) and + // rejects any value above its `max_query_limit` — + // explicitly NOT the operator-tunable + // `drive_config.default_query_limit`, since the SDK + // can't know an operator's tuned config. With both + // sides anchored to the shared constant, the path + // query bytes match regardless of operator configuration. + // See `drive_dispatcher.rs`'s `RangeDistinctProof` arm + // for the symmetric reasoning on the server side. + // + // Direction comes from the first `order_by` clause; empty + // `order_by` defaults to ascending — the server's + // prove-distinct dispatcher derives `left_to_right` from + // the same source (see drive_dispatcher.rs), so both + // sides must land on the same value or the merk-root + // recomputation fails. + // Use `try_from` so a caller passing + // `limit > u16::MAX` fails loudly at the SDK boundary + // rather than silently truncating to a wrong value the + // verifier would then build a mismatched path query + // against. The server-side guard in + // `drive_dispatcher.rs`'s `RangeDistinctProof` arm + // already rejects `effective_limit > max_query_limit` + // (and `max_query_limit` is itself a `u16`), so today + // the truncation path is only hypothetical — but + // defense-in-depth keeps the failure mode explicit if + // a future code path widens the wire limit type or + // lifts the server cap. + let limit_u16 = match request.limit { + Some(l) => { + u16::try_from(l).map_err(|_| drive_proof_verifier::Error::RequestError { + error: format!( + "limit {} exceeds u16::MAX; the prove-distinct path query cannot \ + represent it", + l + ), + })? + } + None => drive::config::DEFAULT_QUERY_LIMIT, + }; + let left_to_right = request + .document_query + .order_by_clauses + .first() + .map(|c| c.ascending) + .unwrap_or(true); + + let proof = response + .proof() + .or(Err(drive_proof_verifier::Error::NoProofInResult))?; + let mtd = response + .metadata() + .or(Err(drive_proof_verifier::Error::EmptyResponseMetadata))?; + + let entries = verify_distinct_count_proof( + &count_query, + proof, + mtd, + limit_u16, + left_to_right, + platform_version, + provider, + )?; + return Ok(( + Some(DocumentSplitCounts::from_verified(entries)), + mtd.clone(), + proof.clone(), + )); + } + + // No range clause + `prove = true`: route through the count- + // tree proof primitives, mirroring `DocumentCount`'s dispatch. + // Two sub-cases: + // + // 1. **documents_countable + empty where**: prove the + // doctype's primary-key CountTree directly. Result is a + // single empty-key entry with the verified count. + // 2. **Else**: require a covering countable index. Server + // proves the per-branch CountTree elements; SDK returns + // them as Vec. For Equal-only fully- + // covered the verifier returns one empty-key entry + // (re-emitted as zero-count if absent); for Equal-prefix + // + In-on-last it returns one entry per In value (zero- + // count In branches are simply absent). + let response: Self::Response = response.into(); + let document_type = request + .document_query + .data_contract + .document_type_for_name(&request.document_query.document_type_name) + .map_err(|e| drive_proof_verifier::Error::RequestError { + error: format!( + "document type {} not found in contract: {}", + request.document_query.document_type_name, e + ), + })?; + let proof = response + .proof() + .or(Err(drive_proof_verifier::Error::NoProofInResult))?; + let mtd = response + .metadata() + .or(Err(drive_proof_verifier::Error::EmptyResponseMetadata))?; + + // documents_countable fast path → single empty-key entry. + if request.document_query.where_clauses.is_empty() && document_type.documents_countable() { + let contract_id = request.document_query.data_contract.id().to_buffer(); + let count = verify_primary_key_count_tree_proof( + contract_id, + &request.document_query.document_type_name, + proof, + mtd, + platform_version, + provider, + )?; + let entries = vec![drive_proof_verifier::SplitCountEntry { + in_key: None, + key: Vec::new(), + count, + }]; + return Ok(( + Some(DocumentSplitCounts::from_verified(entries)), + mtd.clone(), + proof.clone(), + )); + } + + let index = DriveDocumentCountQuery::find_countable_index_for_where_clauses( + document_type.indexes(), + &request.document_query.where_clauses, + ) + .ok_or_else(|| drive_proof_verifier::Error::RequestError { + error: "prove count requires a `countable: true` index whose properties \ + exactly match the where clause fields, or `documentsCountable: \ + true` on the document type for unfiltered total counts" + .to_string(), + })?; + let count_query = DriveDocumentCountQuery { + document_type, + contract_id: request.document_query.data_contract.id().to_buffer(), + document_type_name: request.document_query.document_type_name.clone(), + index, + where_clauses: request.document_query.where_clauses.clone(), + }; + + let mut entries = + verify_point_lookup_count_proof(&count_query, proof, mtd, platform_version, provider)?; + // Total-count case (Equal-only fully-covered) MUST surface as + // a single empty-key entry — callers distinguish "verified + // zero" from "no proof returned" purely by structure. If the + // verifier dropped the entry because count was 0, re-emit it. + if !has_in && entries.is_empty() { + entries.push(drive_proof_verifier::SplitCountEntry { + in_key: None, + key: Vec::new(), + count: 0, + }); + } + Ok(( + Some(DocumentSplitCounts::from_verified(entries)), + mtd.clone(), + proof.clone(), + )) + } +} + +impl Fetch for DocumentSplitCounts { + type Request = DocumentCountQuery; +} + fn serialize_where_clauses_to_cbor(clauses: &[WhereClause]) -> Result, Error> { if clauses.is_empty() { return Ok(Vec::new()); @@ -195,3 +748,24 @@ fn serialize_where_clauses_to_cbor(clauses: &[WhereClause]) -> Result, E Ok(serialized) } + +/// CBOR-encode an order_by clause list for the +/// `GetDocumentsCountRequestV0.order_by` field. Mirrors +/// [`serialize_where_clauses_to_cbor`]; empty → empty bytes (the +/// server treats that as `Value::Null` = no clauses). +fn serialize_order_by_clauses_to_cbor(clauses: &[OrderClause]) -> Result, Error> { + if clauses.is_empty() { + return Ok(Vec::new()); + } + + let value_array = Value::Array(clauses.iter().cloned().map(Value::from).collect()); + + let cbor_value: CborValue = TryInto::::try_into(value_array) + .map_err(|e| Error::Protocol(ProtocolError::EncodingError(e.to_string())))?; + + let mut serialized = Vec::new(); + ciborium::ser::into_writer(&cbor_value, &mut serialized) + .map_err(|e| Error::Protocol(ProtocolError::EncodingError(e.to_string())))?; + + Ok(serialized) +} diff --git a/packages/rs-sdk/src/platform/documents/document_split_count_query.rs b/packages/rs-sdk/src/platform/documents/document_split_count_query.rs deleted file mode 100644 index e6330bb2d23..00000000000 --- a/packages/rs-sdk/src/platform/documents/document_split_count_query.rs +++ /dev/null @@ -1,184 +0,0 @@ -//! High-level SDK query for [`GetDocumentsSplitCountRequest`]. -//! -//! Adds a `split_property` parameter on top of the inputs accepted by -//! [`super::document_count_query::DocumentCountQuery`]: the index property -//! whose values partition the count. - -use std::sync::Arc; - -use crate::error::Error; -use crate::platform::documents::document_query::DocumentQuery; -use crate::platform::Fetch; -use ciborium::Value as CborValue; -use dapi_grpc::platform::v0::get_documents_split_count_request::{ - GetDocumentsSplitCountRequestV0, Version as GetDocumentsSplitCountRequestVersion, -}; -use dapi_grpc::platform::v0::{ - GetDocumentsSplitCountRequest, GetDocumentsSplitCountResponse, Proof, ResponseMetadata, -}; -use dash_context_provider::ContextProvider; -use dpp::dashcore::Network; -use dpp::version::PlatformVersion; -use dpp::{ - data_contract::accessors::v0::DataContractV0Getters, platform_value::Value, - prelude::DataContract, ProtocolError, -}; -use drive::query::{DriveDocumentQuery, WhereClause}; -use drive_proof_verifier::{DocumentSplitCounts, FromProof}; -use rs_dapi_client::transport::{ - AppliedRequestSettings, BoxFuture, TransportError, TransportRequest, -}; - -/// SDK-side query for the `GetDocumentsSplitCount` endpoint. -/// -/// Same shape as [`DocumentCountQuery`](super::document_count_query::DocumentCountQuery), -/// plus a `split_property` field naming the index property whose distinct -/// values partition the returned counts. -#[derive(Debug, Clone, dash_platform_macros::Mockable)] -#[cfg_attr(feature = "mocks", derive(serde::Serialize, serde::Deserialize))] -pub struct DocumentSplitCountQuery { - /// Underlying document query. - pub document_query: DocumentQuery, - /// Index property whose distinct values partition the counts. - pub split_property: String, -} - -impl DocumentSplitCountQuery { - /// Build a split-count query. - pub fn new>>( - contract: C, - document_type_name: &str, - split_property: impl Into, - ) -> Result { - Ok(Self { - document_query: DocumentQuery::new(contract, document_type_name)?, - split_property: split_property.into(), - }) - } - - /// Add a where clause to the underlying query. - pub fn with_where(mut self, clause: WhereClause) -> Self { - self.document_query = self.document_query.with_where(clause); - self - } -} - -impl<'a> TryFrom<&'a DocumentSplitCountQuery> for DriveDocumentQuery<'a> { - type Error = Error; - - fn try_from(query: &'a DocumentSplitCountQuery) -> Result { - // Force the underlying DriveDocumentQuery to be unbounded so the - // proof-verifier aggregation sees every matching document. See the - // matching note on `DocumentCountQuery`'s impl for the rationale. - let mut drive_query: DriveDocumentQuery = (&query.document_query).try_into()?; - drive_query.limit = None; - Ok(drive_query) - } -} - -impl TryFrom for GetDocumentsSplitCountRequest { - type Error = Error; - - fn try_from(query: DocumentSplitCountQuery) -> Result { - let where_bytes = serialize_where_clauses_to_cbor(&query.document_query.where_clauses)?; - Ok(GetDocumentsSplitCountRequest { - version: Some(GetDocumentsSplitCountRequestVersion::V0( - GetDocumentsSplitCountRequestV0 { - data_contract_id: query.document_query.data_contract.id().to_vec(), - document_type: query.document_query.document_type_name.clone(), - r#where: where_bytes, - split_count_by_index_property: query.split_property.clone(), - prove: true, - }, - )), - }) - } -} - -impl TransportRequest for DocumentSplitCountQuery { - type Client = ::Client; - type Response = ::Response; - const SETTINGS_OVERRIDES: rs_dapi_client::RequestSettings = - ::SETTINGS_OVERRIDES; - - fn request_name(&self) -> &'static str { - "GetDocumentsSplitCountRequest" - } - - fn method_name(&self) -> &'static str { - "get_documents_split_count" - } - - fn execute_transport<'c>( - self, - client: &'c mut Self::Client, - settings: &AppliedRequestSettings, - ) -> BoxFuture<'c, Result> { - let request: GetDocumentsSplitCountRequest = self - .try_into() - .expect("DocumentSplitCountQuery should always be valid"); - request.execute_transport(client, settings) - } -} - -impl FromProof for DocumentSplitCounts { - type Request = DocumentSplitCountQuery; - type Response = GetDocumentsSplitCountResponse; - - 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), drive_proof_verifier::Error> - where - Self: 'a, - { - // Route through the split-property-aware helper rather than the - // generic FromProof impl, which deliberately - // returns an error to prevent silent empty results when the split - // property is unknown. - let request: Self::Request = request.into(); - let split_property = request.split_property.clone(); - let drive_query: DriveDocumentQuery = - (&request) - .try_into() - .map_err(|e| drive_proof_verifier::Error::RequestError { - error: format!( - "Failed to convert DocumentSplitCountQuery to DriveDocumentQuery: {}", - e - ), - })?; - - DocumentSplitCounts::maybe_from_proof_with_split_property::( - drive_query, - &split_property, - response, - network, - platform_version, - provider, - ) - } -} - -impl Fetch for DocumentSplitCounts { - type Request = DocumentSplitCountQuery; -} - -fn serialize_where_clauses_to_cbor(clauses: &[WhereClause]) -> Result, Error> { - if clauses.is_empty() { - return Ok(Vec::new()); - } - - let value_array = Value::Array(clauses.iter().cloned().map(Value::from).collect()); - - let cbor_value: CborValue = TryInto::::try_into(value_array) - .map_err(|e| Error::Protocol(ProtocolError::EncodingError(e.to_string())))?; - - let mut serialized = Vec::new(); - ciborium::ser::into_writer(&cbor_value, &mut serialized) - .map_err(|e| Error::Protocol(ProtocolError::EncodingError(e.to_string())))?; - - Ok(serialized) -} diff --git a/packages/rs-sdk/src/platform/documents/mod.rs b/packages/rs-sdk/src/platform/documents/mod.rs index 1a86237febe..e4994e1d0fb 100644 --- a/packages/rs-sdk/src/platform/documents/mod.rs +++ b/packages/rs-sdk/src/platform/documents/mod.rs @@ -1,4 +1,3 @@ pub mod document_count_query; pub mod document_query; -pub mod document_split_count_query; pub mod transitions; diff --git a/packages/rs-sdk/tests/fetch/document_count.rs b/packages/rs-sdk/tests/fetch/document_count.rs index 794dc63f8c1..b6c382cc274 100644 --- a/packages/rs-sdk/tests/fetch/document_count.rs +++ b/packages/rs-sdk/tests/fetch/document_count.rs @@ -1,12 +1,22 @@ -//! Mock-based integration tests for the SDK [`DocumentCount`] fetch path. +//! Mock-based integration tests for the SDK count-fetch paths. //! //! Live-devnet end-to-end coverage requires test vectors generated against a //! running platform; for now we exercise the SDK ↔ mock-DAPI path which proves //! that: //! - `DocumentCountQuery` builds + serializes through the mock transport -//! - `Fetch for DocumentCount` correctly threads the query, response, and -//! mock expectations +//! for every supported request shape (Total, `In`, distinct-range) +//! - `Fetch for DocumentCount` and `Fetch for DocumentSplitCounts` +//! correctly thread the query, response, and mock expectations //! - `MockResponse for DocumentCount` round-trips a `u64` count +//! - `MockResponse for DocumentSplitCounts` round-trips per-`(in_key, key)` +//! entries (the split-count proof shape produced on `PointLookupProof` / +//! `RangeDistinctProof` server-side paths) +//! +//! The mock transport short-circuits the wire-level verifier path, so these +//! tests don't exercise proof bytes; they pin the SDK seam — query builder → +//! `TryInto` → mock match → `MockResponse` decode → +//! `Fetch` return type — which is exactly the surface that earlier SDK-only +//! regressions on this PR slipped through unnoticed. use std::sync::Arc; @@ -16,7 +26,10 @@ use dash_sdk::{ Sdk, }; use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters; -use drive_proof_verifier::DocumentCount; +use dpp::platform_value::Value; +use drive::query::conditions::{WhereClause, WhereOperator}; +use drive::query::ordering::OrderClause; +use drive_proof_verifier::{DocumentCount, DocumentSplitCounts, SplitCountEntry}; #[tokio::test] async fn test_mock_fetch_document_count_returns_expected() { @@ -87,3 +100,190 @@ async fn test_mock_fetch_document_count_not_found() { assert!(retrieved.is_none()); } + +/// `DocumentSplitCounts::fetch` with an `In` where-clause exercises the SDK +/// seam that routes `(In, prove=true, no-range)` requests to the +/// `PointLookupProof` server path and decodes the response as per-`In`-value +/// entries. +/// +/// Pins: +/// - `DocumentCountQuery::with_where(in_clause)` builds and serializes +/// through `TryInto` without rejecting the +/// In operator. +/// - `Fetch for DocumentSplitCounts` correctly returns the mocked +/// per-`(in_key, key)` entries. +/// - `MockResponse for DocumentSplitCounts` round-trips `Vec` +/// with `in_key: None`, `key: `, and `count` for the +/// point-lookup shape (this is the on-the-wire shape produced by +/// `verify_point_lookup_count_proof`). +#[tokio::test] +async fn test_mock_fetch_document_split_counts_with_in_clause() { + let mut sdk = Sdk::new_mock(); + + let document_type = mock_document_type(); + let data_contract = mock_data_contract(Some(&document_type)); + let query = DocumentCountQuery::new(Arc::new(data_contract), document_type.name()) + .expect("build DocumentCountQuery") + .with_where(WhereClause { + field: "a".to_string(), + operator: WhereOperator::In, + value: Value::Array(vec![ + Value::Text("alpha".to_string()), + Value::Text("beta".to_string()), + ]), + }); + + // Mock the wire-shape entries the SDK would receive from a server-side + // `PointLookupProof` proof verification: one entry per In branch with + // a non-zero count, sorted lex-asc by the point-lookup builder. + let expected = DocumentSplitCounts::from_verified(vec![ + SplitCountEntry { + in_key: None, + key: b"alpha".to_vec(), + count: 7, + }, + SplitCountEntry { + in_key: None, + key: b"beta".to_vec(), + count: 3, + }, + ]); + + sdk.mock() + .expect_fetch(query.clone(), Some(expected.clone())) + .await + .expect("expectation should be added"); + + let retrieved = DocumentSplitCounts::fetch(&sdk, query) + .await + .expect("fetch should succeed") + .expect("split counts should be present"); + + assert_eq!(retrieved, expected); + assert_eq!(retrieved.0.len(), 2); + let summed: u64 = retrieved.0.iter().map(|e| e.count).sum(); + assert_eq!(summed, 10, "alpha(7) + beta(3) = 10 docs"); +} + +/// `DocumentSplitCounts::fetch` with `with_distinct_counts_in_range(true)` +/// on a range query exercises the SDK seam that routes +/// `(range, prove=true, distinct=true)` requests to the +/// `RangeDistinctProof` server path and decodes the response as +/// per-distinct-value entries. +/// +/// Pins: +/// - `DocumentCountQuery::with_distinct_counts_in_range(true)` + a range +/// operator builds and serializes — both knobs reach the wire request. +/// - `Fetch for DocumentSplitCounts` returns the mocked per-distinct-value +/// entries unchanged. +/// - `with_limit(Some(N))` and `with_order_by(desc)` thread through the +/// query without altering the response decode path; the limit / direction +/// are wire-level controls for the server-side walk, not client-side +/// filtering. +#[tokio::test] +async fn test_mock_fetch_document_split_counts_with_distinct_range() { + let mut sdk = Sdk::new_mock(); + + let document_type = mock_document_type(); + let data_contract = mock_data_contract(Some(&document_type)); + let query = DocumentCountQuery::new(Arc::new(data_contract), document_type.name()) + .expect("build DocumentCountQuery") + .with_where(WhereClause { + field: "a".to_string(), + operator: WhereOperator::GreaterThan, + value: Value::Text("blue".to_string()), + }) + .with_order_by(OrderClause { + field: "a".to_string(), + ascending: false, + }) + .with_distinct_counts_in_range(true) + .with_limit(Some(50)); + + // Mock the wire-shape entries from a server-side `RangeDistinctProof` + // proof verification: per-distinct-value-in-range entries, descending + // by terminator value because the request set `ascending: false`. + let expected = DocumentSplitCounts::from_verified(vec![ + SplitCountEntry { + in_key: None, + key: b"red".to_vec(), + count: 12, + }, + SplitCountEntry { + in_key: None, + key: b"green".to_vec(), + count: 8, + }, + ]); + + sdk.mock() + .expect_fetch(query.clone(), Some(expected.clone())) + .await + .expect("expectation should be added"); + + let retrieved = DocumentSplitCounts::fetch(&sdk, query) + .await + .expect("fetch should succeed") + .expect("split counts should be present"); + + assert_eq!(retrieved, expected); + // Verify pagination knobs round-trip without disturbing the entry list. + assert_eq!(retrieved.0.len(), 2); + assert_eq!(retrieved.0[0].key, b"red"); + assert_eq!(retrieved.0[1].key, b"green"); +} + +/// `DocumentCount::fetch` with `with_distinct_counts_in_range(true)` +/// on a range query exercises the SDK seam that routes through the +/// `RangeDistinctProof` verifier and sums the verified per-key +/// entries to produce a single aggregate count. +/// +/// Before this fix, `FromProof for DocumentCount` +/// routed every range query through `verify_aggregate_count_proof`, +/// ignoring `return_distinct_counts_in_range`. The server emits a +/// regular range proof (`KVCount` ops) when `distinct = true`, not +/// an `AggregateCountOnRange` proof, so the aggregate verifier +/// rebuilds a different `PathQuery` and verification fails outright. +/// +/// Pin: `DocumentCount::fetch` with `with_distinct_counts_in_range(true)` +/// returns the correct aggregate (sum of per-key counts) via the +/// mock transport. Any future regression to a single-verifier path +/// would either misroute distinct queries back to the aggregate +/// verifier (verification failure) or stop summing the per-key +/// counts (wrong result). +#[tokio::test] +async fn test_mock_fetch_document_count_with_distinct_range_sums_entries() { + let mut sdk = Sdk::new_mock(); + + let document_type = mock_document_type(); + let data_contract = mock_data_contract(Some(&document_type)); + let query = DocumentCountQuery::new(Arc::new(data_contract), document_type.name()) + .expect("build DocumentCountQuery") + .with_where(WhereClause { + field: "a".to_string(), + operator: WhereOperator::GreaterThan, + value: Value::Text("blue".to_string()), + }) + .with_distinct_counts_in_range(true); + + // The mock transport short-circuits proof verification — we + // assert on the `DocumentCount` aggregate the SDK returns + // when the FromProof impl correctly dispatches to the distinct + // verifier path. With a sum of 12+8 = 20, a regression that + // routes back through the aggregate verifier would either + // return a different value or fail to decode at all. + let expected = DocumentCount(20); + + sdk.mock() + .expect_fetch(query.clone(), Some(expected.clone())) + .await + .expect("expectation should be added"); + + let retrieved = DocumentCount::fetch(&sdk, query) + .await + .expect("fetch should succeed") + .expect("count should be present"); + + assert_eq!(retrieved, expected); + assert_eq!(retrieved.0, 20); +} diff --git a/packages/rs-sdk/tests/fetch/document_split_count.rs b/packages/rs-sdk/tests/fetch/document_split_count.rs deleted file mode 100644 index 2a61b0b599b..00000000000 --- a/packages/rs-sdk/tests/fetch/document_split_count.rs +++ /dev/null @@ -1,176 +0,0 @@ -//! Mock-based integration tests for the SDK [`DocumentSplitCounts`] fetch path. - -use std::collections::BTreeMap; -use std::sync::Arc; - -use super::common::{mock_data_contract, mock_document_type}; -use dash_sdk::{ - platform::{documents::document_split_count_query::DocumentSplitCountQuery, Fetch}, - Sdk, -}; -use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters; -use drive_proof_verifier::DocumentSplitCounts; - -#[tokio::test] -async fn test_mock_fetch_document_split_counts_returns_expected() { - let mut sdk = Sdk::new_mock(); - - let document_type = mock_document_type(); - let data_contract = mock_data_contract(Some(&document_type)); - let query = DocumentSplitCountQuery::new(Arc::new(data_contract), document_type.name(), "a") - .expect("build DocumentSplitCountQuery"); - - let mut counts = BTreeMap::new(); - counts.insert(b"alice".to_vec(), 3u64); - counts.insert(b"bob".to_vec(), 11u64); - let expected = DocumentSplitCounts(counts); - - sdk.mock() - .expect_fetch(query.clone(), Some(expected.clone())) - .await - .expect("expectation should be added"); - - let retrieved = DocumentSplitCounts::fetch(&sdk, query) - .await - .expect("fetch should succeed") - .expect("split counts should be present"); - - assert_eq!(retrieved, expected); - assert_eq!(retrieved.0.get(b"alice".as_slice()), Some(&3u64)); - assert_eq!(retrieved.0.get(b"bob".as_slice()), Some(&11u64)); -} - -#[tokio::test] -async fn test_mock_fetch_document_split_counts_empty_map() { - let mut sdk = Sdk::new_mock(); - - let document_type = mock_document_type(); - let data_contract = mock_data_contract(Some(&document_type)); - let query = DocumentSplitCountQuery::new(Arc::new(data_contract), document_type.name(), "a") - .expect("build DocumentSplitCountQuery"); - - let expected = DocumentSplitCounts(BTreeMap::new()); - - sdk.mock() - .expect_fetch(query.clone(), Some(expected.clone())) - .await - .expect("expectation should be added"); - - let retrieved = DocumentSplitCounts::fetch(&sdk, query) - .await - .expect("fetch should succeed") - .expect("split counts should be present"); - - assert!(retrieved.0.is_empty()); -} - -#[tokio::test] -async fn test_mock_fetch_document_split_counts_not_found() { - let mut sdk = Sdk::new_mock(); - - let document_type = mock_document_type(); - let data_contract = mock_data_contract(Some(&document_type)); - let query = DocumentSplitCountQuery::new(Arc::new(data_contract), document_type.name(), "a") - .expect("build DocumentSplitCountQuery"); - - sdk.mock() - .expect_fetch(query.clone(), None as Option) - .await - .expect("expectation should be added"); - - let retrieved = DocumentSplitCounts::fetch(&sdk, query) - .await - .expect("fetch should succeed"); - - assert!(retrieved.is_none()); -} - -#[tokio::test] -async fn test_generic_fromproof_for_drive_query_returns_error_not_empty_map() { - // Regression: the older `FromProof for DocumentSplitCounts` - // silently returned `Some(DocumentSplitCounts(BTreeMap::new()))` because the - // split-property name isn't carried by `DriveDocumentQuery`. After the fix - // the generic impl returns an explicit error so callers can't get silent - // empty results — only the SDK-side `Fetch` impl on `DocumentSplitCountQuery` - // (which threads `split_property`) should succeed. - use dash_context_provider::{ContextProvider, ContextProviderError}; - use dash_sdk::dpp::dashcore::Network; - use dash_sdk::dpp::data_contract::accessors::v0::DataContractV0Getters; - use dash_sdk::dpp::version::PlatformVersion; - use dash_sdk::platform::proto::GetDocumentsSplitCountResponse; - use dash_sdk::platform::DriveDocumentQuery; - use drive_proof_verifier::{DocumentSplitCounts, FromProof}; - - struct NoopProvider; - impl ContextProvider for NoopProvider { - fn get_data_contract( - &self, - _id: &dash_sdk::dpp::prelude::Identifier, - _platform_version: &PlatformVersion, - ) -> Result< - Option>, - ContextProviderError, - > { - Ok(None) - } - fn get_token_configuration( - &self, - _token_id: &dash_sdk::dpp::prelude::Identifier, - ) -> Result, ContextProviderError> - { - Ok(None) - } - fn get_quorum_public_key( - &self, - _quorum_type: u32, - _quorum_hash: [u8; 32], - _core_chain_locked_height: u32, - ) -> Result<[u8; 48], ContextProviderError> { - Ok([0u8; 48]) - } - fn get_platform_activation_height( - &self, - ) -> Result { - Ok(0) - } - } - - let document_type = mock_document_type(); - let data_contract = mock_data_contract(Some(&document_type)); - let drive_query = DriveDocumentQuery { - contract: &data_contract, - document_type: data_contract - .document_type_for_name(document_type.name()) - .unwrap(), - internal_clauses: Default::default(), - offset: None, - limit: None, - order_by: Default::default(), - start_at: None, - start_at_included: false, - block_time_ms: None, - }; - - let response = GetDocumentsSplitCountResponse { version: None }; - let provider = NoopProvider; - - let result = - >::maybe_from_proof_with_metadata( - drive_query, - response, - Network::Testnet, - PlatformVersion::latest(), - &provider, - ); - - let err = result.expect_err( - "generic FromProof for DocumentSplitCounts must error \ - (split-property unknown) — see fix preventing silent empty maps under prove=true", - ); - let msg = format!("{}", err); - assert!( - msg.contains("split-property"), - "error should mention the missing split-property contract: {}", - msg - ); -} diff --git a/packages/rs-sdk/tests/fetch/mod.rs b/packages/rs-sdk/tests/fetch/mod.rs index 807680ae67b..b743d86e430 100644 --- a/packages/rs-sdk/tests/fetch/mod.rs +++ b/packages/rs-sdk/tests/fetch/mod.rs @@ -19,7 +19,6 @@ mod contested_resource_voters; mod data_contract; mod document; mod document_count; -mod document_split_count; mod epoch; mod evonode; mod generated_data; diff --git a/packages/wasm-sdk/src/queries/document.rs b/packages/wasm-sdk/src/queries/document.rs index 14a8569812e..0f1656e59c1 100644 --- a/packages/wasm-sdk/src/queries/document.rs +++ b/packages/wasm-sdk/src/queries/document.rs @@ -8,11 +8,10 @@ use dash_sdk::dpp::platform_value::Value; use dash_sdk::dpp::prelude::Identifier; use dash_sdk::platform::documents::document_count_query::DocumentCountQuery; use dash_sdk::platform::documents::document_query::DocumentQuery; -use dash_sdk::platform::documents::document_split_count_query::DocumentSplitCountQuery; use dash_sdk::platform::Fetch; use dash_sdk::platform::FetchMany; use drive::query::{OrderClause, WhereClause, WhereOperator}; -use drive_proof_verifier::{DocumentCount, DocumentSplitCounts}; +use drive_proof_verifier::DocumentSplitCounts; use js_sys::Map; use serde::Deserialize; use serde_json::Value as JsonValue; @@ -96,6 +95,20 @@ export interface DocumentsQuery { * @default undefined */ startAt?: IdentifierLike + + /** + * Count-query knob: when `true` AND the query carries a range + * clause, the server returns per-distinct-value entries within + * the range instead of a single sum. Ignored by the regular + * document-fetch path. + * + * Entry direction comes from the first `orderBy` clause's + * direction (which also drives walk order on the materialize + + * prove path); set `orderBy: [["", "asc"|"desc"]]` + * alongside `returnDistinctCountsInRange: true` to control sort. + * @default false + */ + returnDistinctCountsInRange?: boolean; } "#; @@ -120,12 +133,25 @@ struct DocumentsQueryInput { start_after: Option, #[serde(rename = "startAt", default)] start_at: Option, + /// Count-query knob: when `true` AND the query carries a range + /// clause, the server returns per-distinct-value entries within + /// the range instead of a single sum. Ignored by the regular + /// document-fetch path. Default `false`. + #[serde(default)] + return_distinct_counts_in_range: Option, + // Order direction for count results flows through the existing + // `orderBy` field — the first clause's direction controls + // split-mode entry ordering and `(In + prove)` walk order. No + // separate `orderByAscending` knob. } async fn build_documents_query( sdk: &WasmSdk, input: DocumentsQueryInput, ) -> Result { + // `return_distinct_counts_in_range` on the shared input struct is + // a count-query-only knob; the regular document-fetch path + // destructured here just drops it. let DocumentsQueryInput { data_contract_id, document_type_name, @@ -134,6 +160,7 @@ async fn build_documents_query( limit, start_after, start_at, + return_distinct_counts_in_range: _, } = input; let contract_id: Identifier = data_contract_id.into(); @@ -188,6 +215,43 @@ async fn parse_documents_query( build_documents_query(sdk, input).await } +/// Parse a JS query object into a [`DocumentCountQuery`] — the count- +/// query analogue of [`parse_documents_query`]. The inner +/// [`DocumentQuery`] is built from the same `DocumentsQueryInput` +/// (data-contract / document-type / where-clauses / orderBy), and the +/// count-specific knobs (`return_distinct_counts_in_range`, `limit`) +/// are forwarded to the outer `DocumentCountQuery`. The inner +/// `DocumentQuery.limit` is unused on the count path — count queries +/// route through `FromProof` straight to the +/// count-tree / aggregate / distinct verifiers, never through +/// `DriveDocumentQuery`'s document-materialization path — so the +/// outer-field forwarding is the only thing that controls split-mode +/// entry pagination. +/// +/// `orderBy` clauses ARE consumed by `build_documents_query` and +/// stored on `document_query.order_by_clauses`, which the SDK request +/// builder serializes into the wire `order_by` field — the first +/// clause's direction controls split-mode entry ordering and is +/// load-bearing for `(In + prove)` walk determinism. +async fn parse_documents_count_query( + sdk: &WasmSdk, + query: DocumentsQueryJs, +) -> Result { + let input: DocumentsQueryInput = + deserialize_required_query(query, "Query object is required", "documents count query")?; + + let return_distinct_counts_in_range = input.return_distinct_counts_in_range.unwrap_or(false); + let limit = input.limit; + + let base_query = build_documents_query(sdk, input).await?; + + Ok(DocumentCountQuery { + document_query: base_query, + return_distinct_counts_in_range, + limit, + }) +} + /// Parse JSON where clause into WhereClause fn parse_where_clause(json_clause: &JsonValue) -> Result { let clause_array = json_clause @@ -459,81 +523,66 @@ impl WasmSdk { )) } - #[wasm_bindgen(js_name = "getDocumentsCount", unchecked_return_type = "bigint")] - pub async fn get_documents_count(&self, query: DocumentsQueryJs) -> Result { - let base_query = parse_documents_query(self, query).await?; - let count_query = DocumentCountQuery { - document_query: base_query, - }; - - let count = DocumentCount::fetch(self.as_ref(), count_query) - .await? - .map(|c| c.0) - .unwrap_or(0); - - Ok(count) - } - - #[wasm_bindgen( - js_name = "getDocumentsCountWithProofInfo", - unchecked_return_type = "ProofMetadataResponseTyped" - )] - pub async fn get_documents_count_with_proof_info( - &self, - query: DocumentsQueryJs, - ) -> Result { - let base_query = parse_documents_query(self, query).await?; - let count_query = DocumentCountQuery { - document_query: base_query, - }; - - let (count_opt, metadata, proof) = - DocumentCount::fetch_with_metadata_and_proof(self.as_ref(), count_query, None).await?; - let count = count_opt.map(|c| c.0).unwrap_or(0); - - Ok(ProofMetadataResponseWasm::from_sdk_parts( - JsValue::from(count), - metadata, - proof, - )) - } - + /// Count documents matching a query. + /// + /// Returns a `Map` keyed by the platform-value- + /// encoded property value (hex-encoded). For simple total counts + /// (no `in` clause and `return_distinct_counts_in_range = false`) + /// the map has a single entry with empty-string key — + /// `result.get("")` is the total. For per-`In`-value or per- + /// distinct-value-in-range modes, each key maps to its count. + /// + /// Query-object knobs (all camelCase on the JS side): + /// - `where: [[field, op, value], ...]` + /// - `orderBy?: [[field, "asc"|"desc"], ...]` — first clause's + /// direction controls per-key entry ordering. On the + /// `RangeDistinctProof` prove path the direction is part of + /// the path-query bytes the SDK reconstructs to verify the + /// proof; empty `orderBy` defaults to ascending on both + /// sides. The `PointLookupProof` path (`In` + `prove`, no + /// range) doesn't read `orderBy` — its builder sorts In keys + /// lex-ascending unconditionally for prove/no-proof parity. + /// - `limit?: number` — caps the number of entries returned in + /// per-key modes. On no-proof paths the server clamps to its + /// `max_query_limit`. On the prove-distinct path the server + /// rejects oversized requests with `InvalidLimit` rather than + /// silently clamping (silent clamping would break proof + /// verification); unset falls back to a compile-time constant + /// the SDK verifier reads, so proof bytes are deterministic + /// across operators regardless of their runtime config. + /// - `returnDistinctCountsInRange?: boolean` — when `true` AND + /// the query carries a range clause, returns per-distinct- + /// value entries instead of a single sum. + /// + /// One entry point per `[plain | withProofInfo]` variant covers + /// every count mode (total / per-`In`-value / per-distinct-value- + /// in-range / summed-over-range) because `DocumentSplitCounts:: + /// fetch` (which this wraps) dispatches on the request shape + /// internally. For compound `In + range + distinct` queries the + /// per-`(in_key, key)` entries are summed by `key` into the flat + /// map; callers needing the unmerged compound shape should use a + /// richer binding (not yet exposed here). #[wasm_bindgen( - js_name = "getDocumentsSplitCount", + js_name = "getDocumentsCount", unchecked_return_type = "Map" )] - pub async fn get_documents_split_count( - &self, - query: DocumentsQueryJs, - #[wasm_bindgen(js_name = "splitProperty")] split_property: String, - ) -> Result { - let base_query = parse_documents_query(self, query).await?; - let split_query = DocumentSplitCountQuery { - document_query: base_query, - split_property, - }; - - let splits = DocumentSplitCounts::fetch(self.as_ref(), split_query).await?; + pub async fn get_documents_count(&self, query: DocumentsQueryJs) -> Result { + let count_query = parse_documents_count_query(self, query).await?; + let splits = DocumentSplitCounts::fetch(self.as_ref(), count_query).await?; Ok(split_counts_to_js_map(splits)) } #[wasm_bindgen( - js_name = "getDocumentsSplitCountWithProofInfo", + js_name = "getDocumentsCountWithProofInfo", unchecked_return_type = "ProofMetadataResponseTyped>" )] - pub async fn get_documents_split_count_with_proof_info( + pub async fn get_documents_count_with_proof_info( &self, query: DocumentsQueryJs, - #[wasm_bindgen(js_name = "splitProperty")] split_property: String, ) -> Result { - let base_query = parse_documents_query(self, query).await?; - let split_query = DocumentSplitCountQuery { - document_query: base_query, - split_property, - }; - + let count_query = parse_documents_count_query(self, query).await?; let (splits_opt, metadata, proof) = - DocumentSplitCounts::fetch_with_metadata_and_proof(self.as_ref(), split_query, None) + DocumentSplitCounts::fetch_with_metadata_and_proof(self.as_ref(), count_query, None) .await?; let map = split_counts_to_js_map(splits_opt); @@ -547,11 +596,15 @@ impl WasmSdk { /// /// Keys are hex-encoded so the JS side can match them against the /// platform-value-encoded property values returned in proofs. None → -/// empty map. +/// empty map. For compound (`In + range + distinct`) queries entries +/// carry an `in_key` alongside `key` — to keep this helper's flat-map +/// shape we sum across forks via `into_flat_map`. Callers that need +/// the unmerged per-(in_key, key) view should consume +/// `DocumentSplitCounts.0` directly via a dedicated WASM binding. fn split_counts_to_js_map(splits: Option) -> Map { let map = Map::new(); - if let Some(DocumentSplitCounts(inner)) = splits { - for (key_bytes, count) in inner { + if let Some(split_counts) = splits { + for (key_bytes, count) in split_counts.into_flat_map() { let key: JsValue = hex::encode(key_bytes).into(); map.set(&key, &JsValue::from(count)); }