diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000000..e0a517ab06 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,59 @@ +# Use the official VS Code base image for dev containers +FROM mcr.microsoft.com/devcontainers/base:ubuntu + +# Install dependencies +RUN apt-get update && apt-get install -y \ + build-essential \ + libssl-dev \ + pkg-config \ + clang \ + cmake \ + llvm \ + curl \ + gnupg \ + lsb-release \ + software-properties-common \ + unzip + +# Switch to clang +RUN rm /usr/bin/cc && ln -s /usr/bin/clang /usr/bin/cc + +# Install protoc - protobuf compiler +# The one shipped with Alpine does not work +ARG TARGETARCH +ARG PROTOC_VERSION=27.3 +RUN if [[ "$TARGETARCH" == "arm64" ]] ; then export PROTOC_ARCH=aarch_64; else export PROTOC_ARCH=x86_64; fi; \ + curl -Ls https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-linux-${PROTOC_ARCH}.zip \ + -o /tmp/protoc.zip && \ + unzip -qd /opt/protoc /tmp/protoc.zip && \ + rm /tmp/protoc.zip && \ + ln -s /opt/protoc/bin/protoc /usr/bin/ + +# Install protoc +RUN curl -OL https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-linux-x86_64.zip \ + && unzip protoc-${PROTOC_VERSION}-linux-x86_64.zip -d /usr/local \ + && rm protoc-${PROTOC_VERSION}-linux-x86_64.zip + +# Switch to vscode user +USER vscode + +ENV CARGO_HOME=/home/vscode/.cargo +ENV PATH=$CARGO_HOME/bin:$PATH + +# TODO: It doesn't sharing PATH between stages, so we need "source $HOME/.cargo/env" everywhere +COPY rust-toolchain.toml . +RUN TOOLCHAIN_VERSION="$(grep channel rust-toolchain.toml | awk '{print $3}' | tr -d '"')" && \ + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- \ + --profile minimal \ + -y \ + --default-toolchain "${TOOLCHAIN_VERSION}" \ + --target wasm32-unknown-unknown + +# Install wasm-bindgen-cli in the same profile as other components, to sacrifice some performance & disk space to gain +# better build caching +RUN if [[ -z "${SCCACHE_MEMCACHED}" ]] ; then unset SCCACHE_MEMCACHED ; fi ; \ + RUSTFLAGS="-C target-feature=-crt-static" \ + # Meanwhile if you want to update wasm-bindgen you also need to update version in: + # - packages/wasm-dpp/Cargo.toml + # - packages/wasm-dpp/scripts/build-wasm.sh + cargo install wasm-bindgen-cli@0.2.86 --locked diff --git a/.devcontainer/devcontainer-build.json b/.devcontainer/devcontainer-build.json new file mode 100644 index 0000000000..df88d65934 --- /dev/null +++ b/.devcontainer/devcontainer-build.json @@ -0,0 +1,73 @@ +{ + "name": "Dash Platform Dev Container", + "build": { + "dockerfile": "Dockerfile", + "context": ".." + }, + "customizations": { + "vscode": { + "settings": {}, + "extensions": [ + "arcanis.vscode-zipfs", + "chrmarti.regex", + "davidanson.vscode-markdownlint", + "ms-vscode.cmake-tools", + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode", + "vadimcn.vscode-lldb", + "rust-lang.rust-analyzer", + "tamasfe.even-better-toml", + "zhangyue.rust-mod-generator", + "ms-azuretools.vscode-docker" + ] + } + }, + "remoteUser": "vscode", + "mounts": [ + { + "source": "devcontainer-platform-cargo-registry-index-${devcontainerId}", + "target": "/home/vscode/.cargo/registry", + "type": "volume" + }, + { + "source": "devcontainer-platform-cargo-registry-cache-${devcontainerId}", + "target": "/home/vscode/.cargo/registry/cache", + "type": "volume" + }, + { + "source": "devcontainer-platform-cargo-git-db-${devcontainerId}", + "target": "/home/vscode/.cargo/git/db", + "type": "volume" + }, + { + "source": "devcontainer-platform-target-${devcontainerId}", + "target": "${containerWorkspaceFolder}/target", + "type": "volume" + } + ], + "features": { + "ghcr.io/devcontainers/features/common-utils:2": { + "installZsh": "true", + "username": "vscode", + "userUid": "1000", + "userGid": "1000", + "upgradePackages": "true" + }, + "ghcr.io/devcontainers/features/git:1": { + "version": "latest", + "ppa": "false" + }, + "ghcr.io/devcontainers/features/github-cli:1": {}, + "ghcr.io/devcontainers/features/node:1": { + "version": 20, + "installYarnUsingApt": false + }, + "ghcr.io/eitsupi/devcontainer-features/jq-likes:2": {}, + "ghcr.io/devcontainers/features/docker-in-docker:2": {}, + "ghcr.io/schlich/devcontainer-features/starship:0": {}, + }, + "postCreateCommand": { + "git-safe": "git config --global --add safe.directory ${containerWorkspaceFolder}", + "cargo-permissions": "sudo chown -R vscode:vscode /home/vscode/.cargo ${containerWorkspaceFolder}/target" + } +} diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000000..586571ba2b --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,4 @@ +{ + "name": "Dash Platform Dev Container", + "image": "ghcr.io/dashpay/platform/devcontainer:0.1.0" +} diff --git a/.github/actions/rust/action.yaml b/.github/actions/rust/action.yaml index cdfc7e11e6..8854007013 100644 --- a/.github/actions/rust/action.yaml +++ b/.github/actions/rust/action.yaml @@ -79,7 +79,7 @@ runs: shell: bash run: | curl -Lo /tmp/protoc.zip \ - "https://github.com/protocolbuffers/protobuf/releases/download/v25.2/protoc-25.2-linux-${{ steps.protoc_arch.outputs.arch }}.zip" + "https://github.com/protocolbuffers/protobuf/releases/download/v27.3/protoc-27.3-linux-${{ steps.protoc_arch.outputs.arch }}.zip" unzip -o /tmp/protoc.zip -d ${HOME}/.local echo "PROTOC=${HOME}/.local/bin/protoc" >> $GITHUB_ENV export PATH="${PATH}:${HOME}/.local/bin" diff --git a/.github/workflows/prebuild-devcontainers.yml b/.github/workflows/prebuild-devcontainers.yml new file mode 100644 index 0000000000..794fa3d4a5 --- /dev/null +++ b/.github/workflows/prebuild-devcontainers.yml @@ -0,0 +1,58 @@ +name: Prebuild Dev Containers + +on: + push: + paths: + - '.devcontainer/**' + - '.github/workflows/prebuild-devcontainers.yml' + - rust-toolchain.toml + - Dockerfile + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build: + name: Build and push devcontainer + runs-on: ["self-hosted", "linux", "x64", "ubuntu-platform"] + timeout-minutes: 60 + steps: + - name: Checkout repo + uses: actions/checkout@v4 + + - name: Setup Node.JS + uses: actions/setup-node@v4 + with: + node-version: "20" + + - name: Install skopeo + run: | + sudo apt-get update + sudo apt-get install -y skopeo + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Setup Docker buildx + uses: docker/setup-buildx-action@v3 + with: + use: true + + - name: Login to GitHub Container Registry + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: dashpay + password: ${{ secrets.GHCR_TOKEN }} + + - name: Build and push Platform devcontainer + uses: devcontainers/ci@v0.3 + with: + imageName: ghcr.io/dashpay/platform/devcontainer + imageTag: 0.1.0 + platform: linux/amd64,linux/arm64 + configFile: .devcontainer/devcontainer-build.json + push: always + cacheFrom: ghcr.io/dashpay/platform/devcontainer diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3f6f9810a6..dba5d592f5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -214,7 +214,7 @@ jobs: - package_type: deb os: ubuntu-22.04 - package_type: macos - os: macos-12 + os: macos-14 steps: - name: Check out repo uses: actions/checkout@v4 @@ -242,9 +242,11 @@ jobs: - name: Install macOS build deps if: runner.os == 'macOS' run: | - brew install llvm docker colima coreutils - colima start - echo "/usr/local/opt/llvm/bin" >> $GITHUB_PATH + brew install llvm coreutils + + - name: Set up Docker for macOS + if: runner.os == 'macOS' + uses: docker-practice/actions-setup-docker@master - name: Install the Apple certificate if: runner.os == 'macOS' @@ -278,7 +280,7 @@ jobs: - name: Create package env: - OSX_KEYCHAIN: $RUNNER_TEMP/app-signing.keychain-db + OSX_KEYCHAIN: ${{ runner.temp }}/app-signing.keychain-db run: "${GITHUB_WORKSPACE}/scripts/pack_dashmate.sh ${{ matrix.package_type }}" - name: Upload artifacts to action summary diff --git a/.pnp.cjs b/.pnp.cjs index 7b11ce621c..0a13a010d1 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -2551,7 +2551,7 @@ const RAW_RUNTIME_STATE = "packageLocation": "./packages/bench-suite/",\ "packageDependencies": [\ ["@dashevo/bench-suite", "workspace:packages/bench-suite"],\ - ["@dashevo/dashcore-lib", "npm:0.21.3"],\ + ["@dashevo/dashcore-lib", "npm:0.22.0"],\ ["@dashevo/dpns-contract", "workspace:packages/dpns-contract"],\ ["@dashevo/wallet-lib", "workspace:packages/wallet-lib"],\ ["@dashevo/wasm-dpp", "workspace:packages/wasm-dpp"],\ @@ -2589,7 +2589,7 @@ const RAW_RUNTIME_STATE = ["@dashevo/bls", "npm:1.2.9"],\ ["@dashevo/dapi-client", "workspace:packages/js-dapi-client"],\ ["@dashevo/dapi-grpc", "workspace:packages/dapi-grpc"],\ - ["@dashevo/dashcore-lib", "npm:0.21.3"],\ + ["@dashevo/dashcore-lib", "npm:0.22.0"],\ ["@dashevo/dashd-rpc", "npm:19.0.0"],\ ["@dashevo/dp-services-ctl", "https://github.com/dashevo/js-dp-services-ctl.git#commit=3976076b0018c5b4632ceda4c752fc597f27a640"],\ ["@dashevo/grpc-common", "workspace:packages/js-grpc-common"],\ @@ -2634,7 +2634,7 @@ const RAW_RUNTIME_STATE = ["@babel/core", "npm:7.23.3"],\ ["@dashevo/dapi-grpc", "workspace:packages/dapi-grpc"],\ ["@dashevo/dash-spv", "workspace:packages/dash-spv"],\ - ["@dashevo/dashcore-lib", "npm:0.21.3"],\ + ["@dashevo/dashcore-lib", "npm:0.22.0"],\ ["@dashevo/grpc-common", "workspace:packages/js-grpc-common"],\ ["@dashevo/wasm-dpp", "workspace:packages/wasm-dpp"],\ ["assert-browserify", "npm:2.0.0"],\ @@ -2726,7 +2726,7 @@ const RAW_RUNTIME_STATE = ["@dashevo/dash-spv", "workspace:packages/dash-spv"],\ ["@dashevo/dark-gravity-wave", "npm:1.1.1"],\ ["@dashevo/dash-util", "npm:2.0.3"],\ - ["@dashevo/dashcore-lib", "npm:0.21.3"],\ + ["@dashevo/dashcore-lib", "npm:0.22.0"],\ ["chai", "npm:4.3.10"],\ ["eslint", "npm:8.53.0"],\ ["eslint-config-airbnb-base", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:15.0.0"],\ @@ -2753,10 +2753,10 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["@dashevo/dashcore-lib", [\ - ["npm:0.21.3", {\ - "packageLocation": "./.yarn/cache/@dashevo-dashcore-lib-npm-0.21.3-8c8abba924-28e2731ac6.zip/node_modules/@dashevo/dashcore-lib/",\ + ["npm:0.22.0", {\ + "packageLocation": "./.yarn/cache/@dashevo-dashcore-lib-npm-0.22.0-9a6dd273b9-ac9e268f6e.zip/node_modules/@dashevo/dashcore-lib/",\ "packageDependencies": [\ - ["@dashevo/dashcore-lib", "npm:0.21.3"],\ + ["@dashevo/dashcore-lib", "npm:0.22.0"],\ ["@dashevo/bls", "npm:1.2.9"],\ ["@dashevo/x11-hash-js", "npm:1.0.2"],\ ["@types/node", "npm:12.20.37"],\ @@ -2939,7 +2939,7 @@ const RAW_RUNTIME_STATE = "packageDependencies": [\ ["@dashevo/platform-test-suite", "workspace:packages/platform-test-suite"],\ ["@dashevo/dapi-client", "workspace:packages/js-dapi-client"],\ - ["@dashevo/dashcore-lib", "npm:0.21.3"],\ + ["@dashevo/dashcore-lib", "npm:0.22.0"],\ ["@dashevo/dpns-contract", "workspace:packages/dpns-contract"],\ ["@dashevo/feature-flags-contract", "workspace:packages/feature-flags-contract"],\ ["@dashevo/grpc-common", "workspace:packages/js-grpc-common"],\ @@ -3034,7 +3034,7 @@ const RAW_RUNTIME_STATE = ["@dashevo/wallet-lib", "workspace:packages/wallet-lib"],\ ["@dashevo/dapi-client", "workspace:packages/js-dapi-client"],\ ["@dashevo/dash-spv", "workspace:packages/dash-spv"],\ - ["@dashevo/dashcore-lib", "npm:0.21.3"],\ + ["@dashevo/dashcore-lib", "npm:0.22.0"],\ ["@dashevo/grpc-common", "workspace:packages/js-grpc-common"],\ ["@dashevo/wasm-dpp", "workspace:packages/wasm-dpp"],\ ["@yarnpkg/pnpify", "npm:4.0.0-rc.42"],\ @@ -3096,7 +3096,7 @@ const RAW_RUNTIME_STATE = ["@babel/core", "npm:7.23.3"],\ ["@babel/preset-env", "virtual:e2d057e7cc143d3cb9bec864f4a2d862441b5a09f81f8e6c46e7a098cbc89e4d07017cc6e2e2142d5704bb55da853cbec2d025ebc0b30e8696c31380c00f2c7d#npm:7.23.3"],\ ["@dashevo/bls", "npm:1.2.9"],\ - ["@dashevo/dashcore-lib", "npm:0.21.3"],\ + ["@dashevo/dashcore-lib", "npm:0.22.0"],\ ["@dashevo/dpns-contract", "workspace:packages/dpns-contract"],\ ["@types/bs58", "npm:4.0.1"],\ ["@types/node", "npm:14.17.34"],\ @@ -8269,10 +8269,10 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["cookie", [\ - ["npm:0.4.1", {\ - "packageLocation": "./.yarn/cache/cookie-npm-0.4.1-cc5e2ebb42-0f2defd60a.zip/node_modules/cookie/",\ + ["npm:0.7.1", {\ + "packageLocation": "./.yarn/cache/cookie-npm-0.7.1-f01524ff99-aec6a6aa07.zip/node_modules/cookie/",\ "packageDependencies": [\ - ["cookie", "npm:0.4.1"]\ + ["cookie", "npm:0.7.1"]\ ],\ "linkType": "HARD"\ }]\ @@ -8473,7 +8473,7 @@ const RAW_RUNTIME_STATE = ["@dashevo/bls", "npm:1.2.9"],\ ["@dashevo/dapi-client", "workspace:packages/js-dapi-client"],\ ["@dashevo/dapi-grpc", "workspace:packages/dapi-grpc"],\ - ["@dashevo/dashcore-lib", "npm:0.21.3"],\ + ["@dashevo/dashcore-lib", "npm:0.22.0"],\ ["@dashevo/dashpay-contract", "workspace:packages/dashpay-contract"],\ ["@dashevo/dpns-contract", "workspace:packages/dpns-contract"],\ ["@dashevo/grpc-common", "workspace:packages/js-grpc-common"],\ @@ -8552,7 +8552,7 @@ const RAW_RUNTIME_STATE = ["@babel/eslint-parser", "virtual:6c6296bde00603e266f7d80babe1e01aa0c19f626934f58fe08f890a291bb1a38fcee25bf30c24857d5cfba290f01209decc48384318fd6815c5a514cb48be25#npm:7.23.3"],\ ["@dashevo/bls", "npm:1.2.9"],\ ["@dashevo/dapi-client", "workspace:packages/js-dapi-client"],\ - ["@dashevo/dashcore-lib", "npm:0.21.3"],\ + ["@dashevo/dashcore-lib", "npm:0.22.0"],\ ["@dashevo/dashd-rpc", "npm:19.0.0"],\ ["@dashevo/docker-compose", "npm:0.24.4"],\ ["@dashevo/wallet-lib", "workspace:packages/wallet-lib"],\ @@ -9365,7 +9365,7 @@ const RAW_RUNTIME_STATE = ["@types/node", "npm:18.16.1"],\ ["accepts", "npm:1.3.7"],\ ["base64id", "npm:2.0.0"],\ - ["cookie", "npm:0.4.1"],\ + ["cookie", "npm:0.7.1"],\ ["cors", "npm:2.8.5"],\ ["debug", "virtual:4b12ba5111caf7e8338099bdbc7cb046a9f8e079a44e74d0c03dca469876e3071ebbe671c5e90ae6b78ae33e22c205fa5ed32169a4aabd1404b13c56d09986e1#npm:4.3.4"],\ ["engine.io-parser", "npm:5.0.4"],\ diff --git a/.yarn/cache/@dashevo-dashcore-lib-npm-0.21.3-8c8abba924-28e2731ac6.zip b/.yarn/cache/@dashevo-dashcore-lib-npm-0.21.3-8c8abba924-28e2731ac6.zip deleted file mode 100644 index f9ac0cfb72..0000000000 Binary files a/.yarn/cache/@dashevo-dashcore-lib-npm-0.21.3-8c8abba924-28e2731ac6.zip and /dev/null differ diff --git a/.yarn/cache/@dashevo-dashcore-lib-npm-0.22.0-9a6dd273b9-ac9e268f6e.zip b/.yarn/cache/@dashevo-dashcore-lib-npm-0.22.0-9a6dd273b9-ac9e268f6e.zip new file mode 100644 index 0000000000..909a68aca0 Binary files /dev/null and b/.yarn/cache/@dashevo-dashcore-lib-npm-0.22.0-9a6dd273b9-ac9e268f6e.zip differ diff --git a/.yarn/cache/cookie-npm-0.4.1-cc5e2ebb42-0f2defd60a.zip b/.yarn/cache/cookie-npm-0.4.1-cc5e2ebb42-0f2defd60a.zip deleted file mode 100644 index 2796ed2bc9..0000000000 Binary files a/.yarn/cache/cookie-npm-0.4.1-cc5e2ebb42-0f2defd60a.zip and /dev/null differ diff --git a/.yarn/cache/cookie-npm-0.7.1-f01524ff99-aec6a6aa07.zip b/.yarn/cache/cookie-npm-0.7.1-f01524ff99-aec6a6aa07.zip new file mode 100644 index 0000000000..26c6c93fd8 Binary files /dev/null and b/.yarn/cache/cookie-npm-0.7.1-f01524ff99-aec6a6aa07.zip differ diff --git a/.yarnrc.yml b/.yarnrc.yml index 34231a77e3..c59f803d7d 100644 --- a/.yarnrc.yml +++ b/.yarnrc.yml @@ -15,6 +15,8 @@ npmAuditExcludePackages: - "@humanwhocodes/config-array" # TODO: Update eslint - "@humanwhocodes/object-schema" # TODO: Update eslint - micromatch # TODO: remove when new micromatch will be released https://github.com/advisories/GHSA-952p-6rrq-rcjv + - eslint # TODO: Update eslint https://github.com/dashpay/platform/issues/2212 + - elliptic # TODO: Remove when elliptic >6.5.7 released packageExtensions: "@dashevo/protobufjs@*": diff --git a/CHANGELOG.md b/CHANGELOG.md index c6c0ab3ef0..c60d45c199 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,20 +1,398 @@ -### [1.3.1](https://github.com/dashpay/platform/compare/v1.3.0...v1.3.1) (2024-09-27) +## [1.5.0](https://github.com/dashpay/platform/compare/v1.4.1...v1.5.0) (2024-11-01) + +### ⚠ BREAKING CHANGES + +* **drive:** rotate always to top quorum. This is a breaking change requiring a HF. (#2290) +* **sdk:** SDK methods which broadcasting transactions will return `SdkError::Protocol(ProtocolError::Consensus(..))` instead of `DapiClientError(String)` in case of validation errors. (#2274) +* **sdk:** serialized consensus error moved to a separate gRPC header `dash-serialized-consensus-error-bin` (#2274) +* **sdk:** `DapiRequestExecutor::execute` and `DapiRequest::execute` now returns `ExecutionResult` (#2259) +* **sdk:** returned objects are `IndexMap/IndexSet` instead of previous `BTreeMap` (#2207) + + +### Features + +* **dashmate:** add protocol version to the status command ([#2255](https://github.com/dashpay/platform/issues/2255)) +* **sdk:** added transfer transition to rs-sdk ([#2289](https://github.com/dashpay/platform/issues/2289)) +* **sdk:** detect stale nodes ([#2254](https://github.com/dashpay/platform/issues/2254)) +* **sdk:** provide request execution information ([#2259](https://github.com/dashpay/platform/issues/2259)) +* **sdk:** return consensus errors from broadcast methods ([#2274](https://github.com/dashpay/platform/issues/2274)) +* **sdk:** sdk-level retry logic for `fetch` and `fetch_many` ([#2266](https://github.com/dashpay/platform/issues/2266)) +* **dashmate:** cleanup zerossl certs command ([#2298](https://github.com/dashpay/platform/issues/2298)) ### Bug Fixes +* **dashmate:** invalid mount path from helper ([#2296](https://github.com/dashpay/platform/issues/2296)) +* **dashmate:** zero ssl certificate draft not saved ([#2297](https://github.com/dashpay/platform/issues/2297)) +* **platform:** rotate always to top quorum ([#2290](https://github.com/dashpay/platform/issues/2290)) +* **dapi:** invalid state transition failed with already in chain error ([#2270](https://github.com/dashpay/platform/issues/2270)) +* **dashmate:** invalid drive status check ([#2248](https://github.com/dashpay/platform/issues/2248)) +* **dashmate:** invalid platform version in the status command ([#2249](https://github.com/dashpay/platform/issues/2249)) +* document query start to support pagination ([#2284](https://github.com/dashpay/platform/issues/2284)) +* **sdk:** `AddressListError` is private ([#2278](https://github.com/dashpay/platform/issues/2278)) +* **sdk:** opposite retry trigger ([#2265](https://github.com/dashpay/platform/issues/2265)) +* **sdk:** wrong order of objects returned by Drive ([#2207](https://github.com/dashpay/platform/issues/2207)) +* seed nodes aren't responding ([#2276](https://github.com/dashpay/platform/issues/2276)) + + +### Code Refactoring + +* platform version refactoring into sub versions ([#2269](https://github.com/dashpay/platform/issues/2269)) + + +### Miscellaneous Chores + +* add partial eq to document query ([#2253](https://github.com/dashpay/platform/issues/2253)) +* **dashmate:** report port check errors ([#2245](https://github.com/dashpay/platform/issues/2245)) +* move BLS Sigs import to Rust Dash Core ([#2252](https://github.com/dashpay/platform/issues/2252)) +* update to latest rust dash core with x11 optional ([#2251](https://github.com/dashpay/platform/issues/2251)) + + +## [1.5.0-rc.2](https://github.com/dashpay/platform/compare/v1.5.0-rc.1...v1.5.0-rc.2) (2024-10-31) + + +### ⚠ BREAKING CHANGES + +* **platform:** rotate always to top quorum (#2290) + +### Bug Fixes + +* **dashmate:** cleanup zerossl certs command ([#2298](https://github.com/dashpay/platform/issues/2298)) +* **dashmate:** invalid mount path from helper ([#2296](https://github.com/dashpay/platform/issues/2296)) +* **dashmate:** zero ssl certificate draft not saved ([#2297](https://github.com/dashpay/platform/issues/2297)) +* **platform:** rotate always to top quorum ([#2290](https://github.com/dashpay/platform/issues/2290)) + + +## [1.5.0-rc.1](https://github.com/dashpay/platform/compare/v1.4.1...v1.5.0-rc.1) (2024-10-30) + + +### ⚠ BREAKING CHANGES + +* **sdk:** return consensus errors from broadcast methods (#2274) +* **sdk:** provide request execution information (#2259) +* **sdk:** wrong order of objects returned by Drive (#2207) + +### Features + +* **dashmate:** add protocol version to the status command ([#2255](https://github.com/dashpay/platform/issues/2255)) +* **sdk:** added transfer transition to rs-sdk ([#2289](https://github.com/dashpay/platform/issues/2289)) +* **sdk:** detect stale nodes ([#2254](https://github.com/dashpay/platform/issues/2254)) +* **sdk:** provide request execution information ([#2259](https://github.com/dashpay/platform/issues/2259)) +* **sdk:** return consensus errors from broadcast methods ([#2274](https://github.com/dashpay/platform/issues/2274)) +* **sdk:** sdk-level retry logic for `fetch` and `fetch_many` ([#2266](https://github.com/dashpay/platform/issues/2266)) + + +### Bug Fixes + +* **dapi:** invalid state transition failed with already in chain error ([#2270](https://github.com/dashpay/platform/issues/2270)) +* **dashmate:** invalid drive status check ([#2248](https://github.com/dashpay/platform/issues/2248)) +* **dashmate:** invalid platform version in the status command ([#2249](https://github.com/dashpay/platform/issues/2249)) +* document query start to support pagination ([#2284](https://github.com/dashpay/platform/issues/2284)) +* **sdk:** `AddressListError` is private ([#2278](https://github.com/dashpay/platform/issues/2278)) +* **sdk:** opposite retry trigger ([#2265](https://github.com/dashpay/platform/issues/2265)) +* **sdk:** wrong order of objects returned by Drive ([#2207](https://github.com/dashpay/platform/issues/2207)) +* seed nodes aren't responding ([#2276](https://github.com/dashpay/platform/issues/2276)) + + +### Miscellaneous Chores + +* add partial eq to document query ([#2253](https://github.com/dashpay/platform/issues/2253)) +* **dashmate:** report port check errors ([#2245](https://github.com/dashpay/platform/issues/2245)) +* move BLS Sigs import to Rust Dash Core ([#2252](https://github.com/dashpay/platform/issues/2252)) +* update to latest rust dash core with x11 optional ([#2251](https://github.com/dashpay/platform/issues/2251)) + + +### Code Refactoring + +* platform version refactoring into sub versions ([#2269](https://github.com/dashpay/platform/issues/2269)) + + +### [1.4.1](https://github.com/dashpay/platform/compare/v1.4.0...v1.4.1) (2024-10-12) + + +### ⚠ BREAKING CHANGES + +* **sdk:** improve mock context provider async processing (#2232) + +### Bug Fixes + +* **sdk:** testnet chain sync failed ([#2236](https://github.com/dashpay/platform/issues/2236)) + + +### Miscellaneous Chores + +* add some extra unit tests + + +### Code Refactoring + +* minor fixes and extra comments +* **sdk:** improve mock context provider async processing ([#2232](https://github.com/dashpay/platform/issues/2232)) + +## [1.4.0](https://github.com/dashpay/platform/compare/v1.4.0-dev.8...v1.4.0) (2024-10-10) + + +### Features + +* **dpp:** added identity public key private key validation methods ([#2235](https://github.com/dashpay/platform/issues/2235)) +* **sdk:** fix client tls connections ([#2223](https://github.com/dashpay/platform/issues/2223)) +* **dpp:** add a convenience method to get the public key data for a private key depending on the key type ([#2214](https://github.com/dashpay/platform/issues/2214)) +* **platform:** add owner keys to identities, fixed verification of use of owner keys ([#2215](https://github.com/dashpay/platform/issues/2215)) +* **sdk:** enable withdrawals v1 in JS SDK ([#2201](https://github.com/dashpay/platform/issues/2201)) +* start network with latest version if genesis version not set ([#2206](https://github.com/dashpay/platform/issues/2206)) +* **dashmate:** confirm a node reset ([#2160](https://github.com/dashpay/platform/issues/2160)) +* **platform:** do not switch to oldest quorums in validator set update ([#2167](https://github.com/dashpay/platform/issues/2167)) +* **platform:** get current quorum info ([#2168](https://github.com/dashpay/platform/issues/2168)) +* **platform:** withdrawals polishing and fixes for mainnet ([#2166](https://github.com/dashpay/platform/issues/2166)) +* **sdk:** change default network to mainnet ([#2161](https://github.com/dashpay/platform/issues/2161)) + + +### Bug Fixes + +* **sdk:** added signing_withdrawal_key_to_use to withdraw sdk call ([#2234](https://github.com/dashpay/platform/issues/2234)) +* **platform:** fixed Platform State deserialization issue ([#2227](https://github.com/dashpay/platform/issues/2227)) +* cookie accepts cookie name, path, and domain with out of bounds characters ([#2211](https://github.com/dashpay/platform/issues/2211)) +* **drive:** set sign height when rebroadcasting ([#2210](https://github.com/dashpay/platform/issues/2210)) +* **sdk:** small sdk improvements and fixes for v1.4 ([#2200](https://github.com/dashpay/platform/issues/2200)) +* **drive-abci:** fix network upgrade to version 4 ([#2189](https://github.com/dashpay/platform/issues/2189)) +* **dashmate:** collect docker stats in the doctor command ([#2180](https://github.com/dashpay/platform/issues/2180)) +* **dashmate:** validate external IP ([#2183](https://github.com/dashpay/platform/issues/2183)) +* **platform:** matched withdrawal fees to actual processing cost ([#2186](https://github.com/dashpay/platform/issues/2186)) +* **platform:** withdrawal automatic retries after core rejection ([#2185](https://github.com/dashpay/platform/issues/2185)) +* **platform:** withdrawal limits ([#2182](https://github.com/dashpay/platform/issues/2182)) +* **sdk:** get node status ([#2139](https://github.com/dashpay/platform/issues/2139)) * **dapi:** getStatus cache invalidation ([#2155](https://github.com/dashpay/platform/issues/2155)) * **dapi:** invalid mainnet seed ports ([#2173](https://github.com/dashpay/platform/issues/2173)) * **dashmate:** cannot read properties of undefined (reading 'expires') ([#2164](https://github.com/dashpay/platform/issues/2164)) * **dashmate:** colors[updated] is not a function ([#2157](https://github.com/dashpay/platform/issues/2157)) * **dashmate:** doctor fails collecting to big logs ([#2158](https://github.com/dashpay/platform/issues/2158)) * **dashmate:** port marks as closed if ipv6 is not disabled ([#2162](https://github.com/dashpay/platform/issues/2162)) +* **dashmate:** remove confusing short flag name ([#2165](https://github.com/dashpay/platform/issues/2165)) + + +### Miscellaneous Chores + +* **dpp:** add method for decoding identifier with unknown string encoding ([#2230](https://github.com/dashpay/platform/issues/2230)) +* **drive:** log invalid state on deserialisation ([#2220](https://github.com/dashpay/platform/issues/2220)) +* **sdk:** expose drive module in public API for rs-sdk ([#2217](https://github.com/dashpay/platform/issues/2217)) +* update dependences ([#2072](https://github.com/dashpay/platform/issues/2072)) +* bump GroveDB dependency ([#2196](https://github.com/dashpay/platform/issues/2196)) +* **drive:** improve withdrawal logging ([#2203](https://github.com/dashpay/platform/issues/2203)) +* **drive:** logs and metrics for withdrawal daily limit ([#2192](https://github.com/dashpay/platform/issues/2192)) +* **release:** replace colima with native docker in macOS builds ([#2188](https://github.com/dashpay/platform/issues/2188)) +* **dashmate:** do not call mint on masternodes ([#2172](https://github.com/dashpay/platform/issues/2172)) +* **platform:** protocol version 4 creation ([#2153](https://github.com/dashpay/platform/issues/2153)) + + +### Code Refactoring + +* **sdk:** contested resource as struct type ([#2225](https://github.com/dashpay/platform/issues/2225)) +* **drive:** remove duplicated withdrawal amount validation ([#2191](https://github.com/dashpay/platform/issues/2191)) + + +### Build System + +* devcontainer support ([#2179](https://github.com/dashpay/platform/issues/2179)) + + +### Continuous Integration + +* prebuild dev containers ([#2184](https://github.com/dashpay/platform/issues/2184)) +* build dashmate on macos14 ### Tests +* **test-suite:** enable withdrawal tests ([#2202](https://github.com/dashpay/platform/issues/2202)) * **dashmate:** e2e tests failing due to DKG interval check ([#2171](https://github.com/dashpay/platform/issues/2171)) + +### Documentation + +* **dashmate:** document logging configuration ([#2156](https://github.com/dashpay/platform/issues/2156)) +* update README ([#2219](https://github.com/dashpay/platform/issues/2219)) + + +### ⚠ BREAKING CHANGES + +* **platform:** add owner keys to identities, fixed verification of use of owner keys. While these are breaking changes, they will only happen in Protocol V4. (#2215) +* **platform:** matched withdrawal fees to actual processing cost. Since fees change it is is a breaking change that will take effect in v4 of the protocol. (#2186) +* **platform:** withdrawal automatic retries after core rejection. This is a breaking change that will be marked as active in v1.4 (#2185) +* **platform:** withdrawal limits. This is breaking, and will be activated in version 1.4 (#2182) +* **sdk:** Now if network is not specified, JS SDK will connect to mainnet. (#2161) +* **dashmate:** confirm a node reset. This change will break any non interactive execution of reset command so now the force flag must be provided to skip the reset confirmation. (#2160) +* **platform:** withdrawals polishing and fixes for mainnet. Updating in V4 hard fork. (#2166) +* **platform:** do not switch to oldest quorums in validator set update. This is included as a change in protocol version 4. (#2167) + + +## [1.4.0-dev.8](https://github.com/dashpay/platform/compare/v1.4.0-dev.7...v1.4.0-dev.8) (2024-10-08) + + +### Features + +* **sdk:** fix client tls connections ([#2223](https://github.com/dashpay/platform/issues/2223)) + + +### Bug Fixes + +* **platform:** fixed Platform State deserialization issue ([#2227](https://github.com/dashpay/platform/issues/2227)) + +## [1.4.0-dev.7](https://github.com/dashpay/platform/compare/v1.4.0-dev.6...v1.4.0-dev.7) (2024-10-07) + + +### Miscellaneous Chores + +* **drive:** log invalid state on deserialisation ([#2220](https://github.com/dashpay/platform/issues/2220)) + +## [1.4.0-dev.6](https://github.com/dashpay/platform/compare/v1.4.0-dev.5...v1.4.0-dev.6) (2024-10-07) + + +### Miscellaneous Chores + +* **sdk:** expose drive module in public API for rs-sdk ([#2217](https://github.com/dashpay/platform/issues/2217)) +* update dependences ([#2072](https://github.com/dashpay/platform/issues/2072)) + +## [1.4.0-dev.5](https://github.com/dashpay/platform/compare/v1.4.0-dev.4...v1.4.0-dev.5) (2024-10-07) + + +### ⚠ BREAKING CHANGES + +* **platform:** add owner keys to identities, fixed verification of use of owner keys (#2215) + +### Features + +* **dpp:** add a convenience method to get the public key data for a private key depending on the key type ([#2214](https://github.com/dashpay/platform/issues/2214)) +* **platform:** add owner keys to identities, fixed verification of use of owner keys ([#2215](https://github.com/dashpay/platform/issues/2215)) + +## [1.4.0-dev.4](https://github.com/dashpay/platform/compare/v1.4.0-dev.3...v1.4.0-dev.4) (2024-10-05) + + +### Features + +* **sdk:** enable withdrawals v1 in JS SDK ([#2201](https://github.com/dashpay/platform/issues/2201)) +* start network with latest version if genesis version not set ([#2206](https://github.com/dashpay/platform/issues/2206)) + + +### Bug Fixes + +* cookie accepts cookie name, path, and domain with out of bounds characters ([#2211](https://github.com/dashpay/platform/issues/2211)) +* **drive:** set sign height when rebroadcasting ([#2210](https://github.com/dashpay/platform/issues/2210)) +* **sdk:** small sdk improvements and fixes for v1.4 ([#2200](https://github.com/dashpay/platform/issues/2200)) + + +### Code Refactoring + +* **drive:** remove duplicated withdrawal amount validation ([#2191](https://github.com/dashpay/platform/issues/2191)) + + +### Miscellaneous Chores + +* bump GroveDB dependency ([#2196](https://github.com/dashpay/platform/issues/2196)) +* **drive:** improve withdrawal logging ([#2203](https://github.com/dashpay/platform/issues/2203)) +* **drive:** logs and metrics for withdrawal daily limit ([#2192](https://github.com/dashpay/platform/issues/2192)) +* **release:** replace colima with native docker in macOS builds ([#2188](https://github.com/dashpay/platform/issues/2188)) + + +### Tests + +* **test-suite:** enable withdrawal tests ([#2202](https://github.com/dashpay/platform/issues/2202)) + +## [1.4.0-dev.2](https://github.com/dashpay/platform/compare/v1.4.0-dev.1...v1.4.0-dev.2) (2024-09-30) + + +### ⚠ BREAKING CHANGES + +* **platform:** matched withdrawal fees to actual processing cost (#2186) +* **platform:** withdrawal automatic retries after core rejection (#2185) +* **platform:** withdrawal limits (#2182) + +### Features + +* **dashmate:** collect docker stats in the doctor command ([#2180](https://github.com/dashpay/platform/issues/2180)) +* **dashmate:** validate external IP ([#2183](https://github.com/dashpay/platform/issues/2183)) +* **platform:** matched withdrawal fees to actual processing cost ([#2186](https://github.com/dashpay/platform/issues/2186)) +* **platform:** withdrawal automatic retries after core rejection ([#2185](https://github.com/dashpay/platform/issues/2185)) +* **platform:** withdrawal limits ([#2182](https://github.com/dashpay/platform/issues/2182)) +* **sdk:** get node status ([#2139](https://github.com/dashpay/platform/issues/2139)) + + +### Build System + +* devcontainer support ([#2179](https://github.com/dashpay/platform/issues/2179)) + + +### Continuous Integration + +* prebuild dev containers ([#2184](https://github.com/dashpay/platform/issues/2184)) + +## [1.4.0-dev.1](https://github.com/dashpay/platform/compare/v1.3.0...v1.4.0-dev.1) (2024-09-27) + + +### ⚠ BREAKING CHANGES + +* **sdk:** change default network to mainnet (#2161) +* **dashmate:** confirm a node reset (#2160) +* **platform:** withdrawals polishing and fixes for mainnet (#2166) +* **platform:** do not switch to oldest quorums in validator set update (#2167) + +### Features + +* **dashmate:** confirm a node reset ([#2160](https://github.com/dashpay/platform/issues/2160)) +* **platform:** do not switch to oldest quorums in validator set update ([#2167](https://github.com/dashpay/platform/issues/2167)) +* **platform:** get current quorum info ([#2168](https://github.com/dashpay/platform/issues/2168)) +* **platform:** withdrawals polishing and fixes for mainnet ([#2166](https://github.com/dashpay/platform/issues/2166)) +* **sdk:** change default network to mainnet ([#2161](https://github.com/dashpay/platform/issues/2161)) + + +### Bug Fixes + +* **dapi:** getStatus cache invalidation ([#2155](https://github.com/dashpay/platform/issues/2155)) +* **dapi:** invalid mainnet seed ports ([#2173](https://github.com/dashpay/platform/issues/2173)) +* **dashmate:** cannot read properties of undefined (reading 'expires') ([#2164](https://github.com/dashpay/platform/issues/2164)) +* **dashmate:** colors[updated] is not a function ([#2157](https://github.com/dashpay/platform/issues/2157)) +* **dashmate:** doctor fails collecting to big logs ([#2158](https://github.com/dashpay/platform/issues/2158)) +* **dashmate:** port marks as closed if ipv6 is not disabled ([#2162](https://github.com/dashpay/platform/issues/2162)) +* **dashmate:** remove confusing short flag name ([#2165](https://github.com/dashpay/platform/issues/2165)) + + +### Continuous integration + +* build dashmate package on macos14 + + +### Documentation + +* **dashmate:** document logging configuration ([#2156](https://github.com/dashpay/platform/issues/2156)) + + +### Tests + +* **dashmate:** e2e tests failing due to DKG interval check ([#2171](https://github.com/dashpay/platform/issues/2171)) + + +### Miscellaneous Chores + +* **dashmate:** do not call mint on masternodes ([#2172](https://github.com/dashpay/platform/issues/2172)) +* **platform:** protocol version 4 creation ([#2153](https://github.com/dashpay/platform/issues/2153)) + + +### [1.3.1](https://github.com/dashpay/platform/compare/v1.3.0...v1.3.1) (2024-09-27) + +### Bug Fixes + +* **dapi:** getStatus cache invalidation ([#2155](https://github.com/dashpay/platform/issues/2155)) +* **dapi:** invalid mainnet seed ports ([#2173](https://github.com/dashpay/platform/issues/2173)) +* **dashmate:** cannot read properties of undefined (reading 'expires') ([#2164](https://github.com/dashpay/platform/issues/2164)) +* **dashmate:** colors[updated] is not a function ([#2157](https://github.com/dashpay/platform/issues/2157)) +* **dashmate:** doctor fails collecting to big logs ([#2158](https://github.com/dashpay/platform/issues/2158)) +* **dashmate:** port marks as closed if ipv6 is not disabled ([#2162](https://github.com/dashpay/platform/issues/2162)) + + +### Tests + +* **dashmate:** e2e tests failing due to DKG interval check ([#2171](https://github.com/dashpay/platform/issues/2171)) + + ## [1.3.0](https://github.com/dashpay/platform/compare/v1.2.0...v1.3.0) (2024-09-19) ### Features diff --git a/Cargo.lock b/Cargo.lock index 6f25b0f27b..c59d07d2b4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -89,6 +89,12 @@ dependencies = [ "libc", ] +[[package]] +name = "anes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + [[package]] name = "anstream" version = "0.6.15" @@ -177,33 +183,15 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" -[[package]] -name = "async-io" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" -dependencies = [ - "async-lock", - "autocfg", - "cfg-if", - "concurrent-queue", - "futures-lite", - "log", - "parking", - "polling", - "rustix 0.37.27", - "slab", - "socket2 0.4.10", - "waker-fn", -] - [[package]] name = "async-lock" -version = "2.8.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" dependencies = [ "event-listener", + "event-listener-strategy", + "pin-project-lite", ] [[package]] @@ -230,9 +218,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.81" +version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", @@ -245,51 +233,12 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", -] - [[package]] name = "autocfg" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" -[[package]] -name = "axum" -version = "0.6.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" -dependencies = [ - "async-trait", - "axum-core 0.3.4", - "bitflags 1.3.2", - "bytes", - "futures-util", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.30", - "itoa", - "matchit", - "memchr", - "mime", - "percent-encoding", - "pin-project-lite", - "rustversion", - "serde", - "sync_wrapper 0.1.2", - "tower", - "tower-layer", - "tower-service", -] - [[package]] name = "axum" version = "0.7.5" @@ -297,14 +246,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" dependencies = [ "async-trait", - "axum-core 0.4.3", + "axum-core", "axum-macros", "bytes", "futures-util", - "http 1.1.0", - "http-body 1.0.1", + "http", + "http-body", "http-body-util", - "hyper 1.4.1", + "hyper", "hyper-util", "itoa", "matchit", @@ -325,23 +274,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "axum-core" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" -dependencies = [ - "async-trait", - "bytes", - "futures-util", - "http 0.2.12", - "http-body 0.4.6", - "mime", - "rustversion", - "tower-layer", - "tower-service", -] - [[package]] name = "axum-core" version = "0.4.3" @@ -351,8 +283,8 @@ dependencies = [ "async-trait", "bytes", "futures-util", - "http 1.1.0", - "http-body 1.0.1", + "http", + "http-body", "http-body-util", "mime", "pin-project-lite", @@ -377,13 +309,12 @@ dependencies = [ [[package]] name = "backon" -version = "0.4.4" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d67782c3f868daa71d3533538e98a8e13713231969def7536e8039606fc46bf0" +checksum = "e4fa97bb310c33c811334143cf64c5bb2b7b3c06e453db6b095d7061eff8f113" dependencies = [ - "fastrand 2.1.0", - "futures-core", - "pin-project", + "fastrand", + "gloo-timers", "tokio", ] @@ -464,7 +395,7 @@ dependencies = [ "lazycell", "log", "peeking_take_while", - "prettyplease 0.2.20", + "prettyplease", "proc-macro2", "quote", "regex", @@ -520,18 +451,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" [[package]] -name = "bitcoin-private" -version = "0.1.0" +name = "bitcoin-io" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73290177011694f38ec25e165d0387ab7ea749a4b81cd4c80dae5988229f7a57" +checksum = "340e09e8399c7bd8912f495af6aa58bea0c9214773417ffaa8f6460f93aaee56" [[package]] name = "bitcoin_hashes" -version = "0.12.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d7066118b13d4b20b23645932dfb3a81ce7e29f95726c2036fa33cd7b092501" +checksum = "bb18c03d0db0247e147a21a6faafd5a7eb851c743db062de72018b6b7e8e4d16" dependencies = [ - "bitcoin-private", + "bitcoin-io", + "hex-conservative", ] [[package]] @@ -583,7 +515,7 @@ dependencies = [ [[package]] name = "bls-dash-sys" version = "1.2.5" -source = "git+https://github.com/dashpay/bls-signatures?tag=v1.3.1#1c2fc79c19dc8041610c005e68d58bfb4bc32721" +source = "git+https://github.com/dashpay/bls-signatures?tag=1.3.3#4e070243aed142bc458472f8807ab77527dd879a" dependencies = [ "bindgen 0.65.1", "cc", @@ -593,7 +525,7 @@ dependencies = [ [[package]] name = "bls-signatures" version = "1.2.5" -source = "git+https://github.com/dashpay/bls-signatures?tag=v1.3.1#1c2fc79c19dc8041610c005e68d58bfb4bc32721" +source = "git+https://github.com/dashpay/bls-signatures?tag=1.3.3#4e070243aed142bc458472f8807ab77527dd879a" dependencies = [ "bls-dash-sys", "hex", @@ -625,12 +557,6 @@ dependencies = [ "syn_derive", ] -[[package]] -name = "bs58" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" - [[package]] name = "bs58" version = "0.5.1" @@ -710,37 +636,6 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "camino" -version = "1.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" -dependencies = [ - "serde", -] - -[[package]] -name = "cargo-platform" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" -dependencies = [ - "serde", -] - -[[package]] -name = "cargo_metadata" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa" -dependencies = [ - "camino", - "cargo-platform", - "semver", - "serde", - "serde_json", -] - [[package]] name = "cast" version = "0.3.0" @@ -781,7 +676,7 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "check-features" -version = "1.3.1" +version = "1.5.0" dependencies = [ "toml", ] @@ -806,8 +701,19 @@ name = "ciborium" version = "0.2.0" source = "git+https://github.com/qrayven/ciborium?branch=feat-ser-null-as-undefined#5fbba76d132caf04cd1f271336d9daafdc747f10" dependencies = [ - "ciborium-io", - "ciborium-ll", + "ciborium-io 0.2.0", + "ciborium-ll 0.2.0", + "serde", +] + +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io 0.2.2", + "ciborium-ll 0.2.2", "serde", ] @@ -816,13 +722,29 @@ name = "ciborium-io" version = "0.2.0" source = "git+https://github.com/qrayven/ciborium?branch=feat-ser-null-as-undefined#5fbba76d132caf04cd1f271336d9daafdc747f10" +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + [[package]] name = "ciborium-ll" version = "0.2.0" source = "git+https://github.com/qrayven/ciborium?branch=feat-ser-null-as-undefined#5fbba76d132caf04cd1f271336d9daafdc747f10" dependencies = [ - "ciborium-io", - "half", + "ciborium-io 0.2.0", + "half 1.8.3", +] + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io 0.2.2", + "half 2.4.1", ] [[package]] @@ -846,17 +768,6 @@ dependencies = [ "libloading", ] -[[package]] -name = "clap" -version = "2.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" -dependencies = [ - "bitflags 1.3.2", - "textwrap", - "unicode-width", -] - [[package]] name = "clap" version = "4.5.16" @@ -924,22 +835,22 @@ dependencies = [ [[package]] name = "console-api" -version = "0.6.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd326812b3fd01da5bb1af7d340d0d555fd3d4b641e7f1dfcf5962a902952787" +checksum = "86ed14aa9c9f927213c6e4f3ef75faaad3406134efe84ba2cb7983431d5f0931" dependencies = [ "futures-core", - "prost 0.12.6", - "prost-types 0.12.6", - "tonic 0.10.2", + "prost", + "prost-types", + "tonic", "tracing-core", ] [[package]] name = "console-subscriber" -version = "0.2.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7481d4c57092cd1c19dd541b92bdce883de840df30aa5d03fd48a3935c01842e" +checksum = "e2e3a111a37f3333946ebf9da370ba5c5577b18eb342ec683eb488dd21980302" dependencies = [ "console-api", "crossbeam-channel", @@ -947,13 +858,15 @@ dependencies = [ "futures-task", "hdrhistogram", "humantime", - "prost-types 0.12.6", + "hyper-util", + "prost", + "prost-types", "serde", "serde_json", "thread_local", "tokio", "tokio-stream", - "tonic 0.10.2", + "tonic", "tracing", "tracing-core", "tracing-subscriber", @@ -1019,24 +932,24 @@ dependencies = [ [[package]] name = "criterion" -version = "0.3.6" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b01d6de93b2b6c65e17c634a26653a29d107b3c98c607c765bf38d041531cd8f" +checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" dependencies = [ - "atty", + "anes", "cast", - "clap 2.34.0", + "ciborium 0.2.2", + "clap", "criterion-plot", - "csv", + "is-terminal", "itertools 0.10.5", - "lazy_static", "num-traits", + "once_cell", "oorandom", "plotters", "rayon", "regex", "serde", - "serde_cbor", "serde_derive", "serde_json", "tinytemplate", @@ -1045,9 +958,9 @@ dependencies = [ [[package]] name = "criterion-plot" -version = "0.4.5" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2673cc8207403546f45f5fd319a974b1e6983ad1a3ee7e6041650013be041876" +checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" dependencies = [ "cast", "itertools 0.10.5", @@ -1087,6 +1000,12 @@ version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "crypto-common" version = "0.1.6" @@ -1097,27 +1016,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "csv" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" -dependencies = [ - "csv-core", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "csv-core" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" -dependencies = [ - "memchr", -] - [[package]] name = "curve25519-dalek" version = "4.1.3" @@ -1147,23 +1045,23 @@ dependencies = [ [[package]] name = "dapi-grpc" -version = "1.3.1" +version = "1.5.0" dependencies = [ "dapi-grpc-macros", "futures-core", "platform-version", - "prost 0.12.6", + "prost", "serde", "serde_bytes", "serde_json", "tenderdash-proto", - "tonic 0.11.0", - "tonic-build 0.9.2", + "tonic", + "tonic-build", ] [[package]] name = "dapi-grpc-macros" -version = "1.3.1" +version = "1.5.0" dependencies = [ "dapi-grpc", "heck 0.5.0", @@ -1208,20 +1106,21 @@ dependencies = [ [[package]] name = "dash-sdk" -version = "1.3.1" +version = "1.5.0" dependencies = [ "arc-swap", "async-trait", + "backon", "base64 0.22.1", "bip37-bloom-filter", "chrono", - "ciborium", - "clap 4.5.16", + "ciborium 0.2.0", + "clap", "dapi-grpc", "dapi-grpc-macros", "dashcore-rpc", "data-contracts", - "derive_more", + "derive_more 1.0.0", "dotenvy", "dpp", "drive", @@ -1229,47 +1128,53 @@ dependencies = [ "envy", "futures", "hex", - "http 0.2.12", + "http", "lru", - "pollster", "rs-dapi-client", "sanitize-filename", "serde", "serde_json", - "test-case 3.3.1", + "test-case", "thiserror", "tokio", "tokio-test", "tokio-util", "tracing", "tracing-subscriber", + "zeroize", ] [[package]] name = "dashcore" -version = "0.30.0" -source = "git+https://github.com/dashpay/rust-dashcore?branch=master#a29315dbe56729be1be963fb6f7b60a22288663f" +version = "0.32.0" +source = "git+https://github.com/dashpay/rust-dashcore?tag=0.32.0#6a0ec164ca1bdcb8d19b29f40e946120e99473eb" dependencies = [ "anyhow", "bech32", + "bitflags 2.6.0", + "bls-signatures", "dashcore-private", "dashcore_hashes", + "ed25519-dalek", "hex", "hex_lit", + "lazy_static", "rustversion", "secp256k1", "serde", + "serde_repr", + "strum", ] [[package]] name = "dashcore-private" version = "0.1.0" -source = "git+https://github.com/dashpay/rust-dashcore?branch=master#a29315dbe56729be1be963fb6f7b60a22288663f" +source = "git+https://github.com/dashpay/rust-dashcore?tag=0.32.0#6a0ec164ca1bdcb8d19b29f40e946120e99473eb" [[package]] name = "dashcore-rpc" -version = "0.15.2" -source = "git+https://github.com/dashpay/rust-dashcore-rpc?tag=v0.15.4#bd6efdb850151f1dcd8e3f38d4796d18c5be518c" +version = "0.15.8" +source = "git+https://github.com/dashpay/rust-dashcore-rpc?tag=v0.15.8#4d4d5b1488daa7f083d254a1f5acf03b550d5b10" dependencies = [ "dashcore-private", "dashcore-rpc-json", @@ -1283,8 +1188,8 @@ dependencies = [ [[package]] name = "dashcore-rpc-json" -version = "0.15.2" -source = "git+https://github.com/dashpay/rust-dashcore-rpc?tag=v0.15.4#bd6efdb850151f1dcd8e3f38d4796d18c5be518c" +version = "0.15.8" +source = "git+https://github.com/dashpay/rust-dashcore-rpc?tag=v0.15.8#4d4d5b1488daa7f083d254a1f5acf03b550d5b10" dependencies = [ "bincode", "dashcore", @@ -1297,18 +1202,17 @@ dependencies = [ [[package]] name = "dashcore_hashes" -version = "0.12.0" -source = "git+https://github.com/dashpay/rust-dashcore?branch=master#a29315dbe56729be1be963fb6f7b60a22288663f" +version = "0.14.0" +source = "git+https://github.com/dashpay/rust-dashcore?tag=0.32.0#6a0ec164ca1bdcb8d19b29f40e946120e99473eb" dependencies = [ "dashcore-private", - "rs-x11-hash", "secp256k1", "serde", ] [[package]] name = "dashpay-contract" -version = "1.3.1" +version = "1.5.0" dependencies = [ "platform-value", "platform-version", @@ -1318,7 +1222,7 @@ dependencies = [ [[package]] name = "data-contracts" -version = "1.3.1" +version = "1.5.0" dependencies = [ "dashpay-contract", "dpns-contract", @@ -1333,13 +1237,13 @@ dependencies = [ [[package]] name = "delegate" -version = "0.9.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d358e0ec5c59a5e1603b933def447096886121660fc680dc1e64a0753981fe3c" +checksum = "5060bb0febb73fa907273f8a7ed17ab4bf831d585eac835b28ec24a1e2460956" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.75", ] [[package]] @@ -1387,16 +1291,31 @@ dependencies = [ ] [[package]] -name = "diff" -version = "0.1.13" +name = "derive_more" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl", +] [[package]] -name = "difflib" -version = "0.4.0" +name = "derive_more-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.75", + "unicode-xid", +] + +[[package]] +name = "diff" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" [[package]] name = "digest" @@ -1434,7 +1353,7 @@ checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" [[package]] name = "dpns-contract" -version = "1.3.1" +version = "1.5.0" dependencies = [ "platform-value", "platform-version", @@ -1444,35 +1363,33 @@ dependencies = [ [[package]] name = "dpp" -version = "1.3.1" +version = "1.5.0" dependencies = [ "anyhow", "assert_matches", "async-trait", "base64 0.22.1", "bincode", - "bls-signatures", - "bs58 0.4.0", + "bs58", "byteorder", "chrono", - "ciborium", + "ciborium 0.2.0", "dashcore", "data-contracts", - "derive_more", + "derive_more 1.0.0", "dpp", - "ed25519-dalek", - "env_logger 0.9.3", + "env_logger 0.11.5", "getrandom", "hex", - "indexmap 2.4.0", + "indexmap 2.6.0", "integer-encoding", - "itertools 0.12.1", + "itertools 0.13.0", "json-schema-compatibility-validator", "jsonschema", "lazy_static", "log", "nohash-hasher", - "num_enum", + "num_enum 0.7.3", "once_cell", "platform-serialization", "platform-serialization-derive", @@ -1488,25 +1405,26 @@ dependencies = [ "serde_json", "serde_repr", "sha2", - "strum 0.25.0", - "test-case 2.2.2", + "strum", + "test-case", "thiserror", "tokio", ] [[package]] name = "drive" -version = "1.3.1" +version = "1.5.0" dependencies = [ "arc-swap", + "assert_matches", "base64 0.22.1", "bincode", - "bs58 0.5.1", + "bs58", "byteorder", "chrono", - "ciborium", + "ciborium 0.2.0", "criterion", - "derive_more", + "derive_more 1.0.0", "dpp", "enum-map", "grovedb", @@ -1516,10 +1434,10 @@ dependencies = [ "grovedb-storage", "grovedb-version", "hex", - "indexmap 2.4.0", + "indexmap 2.6.0", "integer-encoding", "intmap", - "itertools 0.11.0", + "itertools 0.13.0", "moka", "nohash-hasher", "once_cell", @@ -1536,23 +1454,22 @@ dependencies = [ [[package]] name = "drive-abci" -version = "1.3.1" +version = "1.5.0" dependencies = [ "arc-swap", "assert_matches", "async-trait", - "atty", "base64 0.22.1", "bincode", - "bs58 0.5.1", + "bs58", "chrono", - "ciborium", - "clap 4.5.16", + "ciborium 0.2.0", + "clap", "console-subscriber", "dapi-grpc", "dashcore-rpc", "delegate", - "derive_more", + "derive_more 1.0.0", "dotenvy", "dpp", "drive", @@ -1560,15 +1477,15 @@ dependencies = [ "envy", "file-rotate", "hex", - "indexmap 2.4.0", + "indexmap 2.6.0", "integer-encoding", - "itertools 0.10.5", + "itertools 0.13.0", "lazy_static", "metrics", "metrics-exporter-prometheus", "mockall", "platform-version", - "prost 0.12.6", + "prost", "rand", "regex", "reopen", @@ -1586,20 +1503,20 @@ dependencies = [ "tokio-util", "tracing", "tracing-subscriber", - "ureq", "url", ] [[package]] name = "drive-proof-verifier" -version = "1.3.1" +version = "1.5.0" dependencies = [ "bincode", "dapi-grpc", - "derive_more", + "derive_more 1.0.0", "dpp", "drive", "hex", + "indexmap 2.6.0", "platform-serialization", "platform-serialization-derive", "serde", @@ -1691,16 +1608,13 @@ dependencies = [ ] [[package]] -name = "env_logger" -version = "0.9.3" +name = "env_filter" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" +checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" dependencies = [ - "atty", - "humantime", "log", "regex", - "termcolor", ] [[package]] @@ -1716,6 +1630,19 @@ dependencies = [ "termcolor", ] +[[package]] +name = "env_logger" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "humantime", + "log", +] + [[package]] name = "envy" version = "0.4.2" @@ -1742,19 +1669,25 @@ dependencies = [ ] [[package]] -name = "error-chain" -version = "0.12.4" +name = "event-listener" +version = "5.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" dependencies = [ - "version_check", + "concurrent-queue", + "parking", + "pin-project-lite", ] [[package]] -name = "event-listener" -version = "2.5.3" +name = "event-listener-strategy" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" +dependencies = [ + "event-listener", + "pin-project-lite", +] [[package]] name = "failure" @@ -1789,15 +1722,6 @@ dependencies = [ "regex-syntax 0.8.4", ] -[[package]] -name = "fastrand" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] - [[package]] name = "fastrand" version = "2.1.0" @@ -1806,7 +1730,7 @@ checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] name = "feature-flags-contract" -version = "1.3.1" +version = "1.5.0" dependencies = [ "platform-value", "platform-version", @@ -1855,15 +1779,6 @@ dependencies = [ "paste", ] -[[package]] -name = "float-cmp" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" -dependencies = [ - "num-traits", -] - [[package]] name = "fnv" version = "1.0.7" @@ -1970,21 +1885,6 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" -[[package]] -name = "futures-lite" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" -dependencies = [ - "fastrand 1.9.0", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite", - "waker-fn", -] - [[package]] name = "futures-macro" version = "0.3.30" @@ -2061,17 +1961,29 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +[[package]] +name = "gloo-timers" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + [[package]] name = "grovedb" -version = "2.0.3" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77097f0a4cc70c4a69fa400f633c5f18739e446eaed05269a3d76e17fa4d33d2" +checksum = "7d91e8f87926c834c7338d0c69a48816c043e0cddf0062a8a567483db2fb1e24" dependencies = [ - "axum 0.7.5", + "axum", "bincode", "bitvec", "blake3", - "derive_more", + "derive_more 0.99.18", "grovedb-costs", "grovedb-merk", "grovedb-path", @@ -2081,7 +1993,7 @@ dependencies = [ "grovedbg-types", "hex", "hex-literal", - "indexmap 2.4.0", + "indexmap 2.6.0", "integer-encoding", "intmap", "itertools 0.12.1", @@ -2091,15 +2003,16 @@ dependencies = [ "tempfile", "thiserror", "tokio", + "tokio-util", "tower-http", "zip-extensions", ] [[package]] name = "grovedb-costs" -version = "2.0.3" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0487d63a68621b910567a911b3708a8246501ae1912fa2f1920474dcb28a207" +checksum = "360f7c8d3b20beafcbf3cde8754bbcfd201ae2a30ec7594a4b9678fd2fa3c7a8" dependencies = [ "integer-encoding", "intmap", @@ -2108,9 +2021,9 @@ dependencies = [ [[package]] name = "grovedb-epoch-based-storage-flags" -version = "2.0.3" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53eb4b99b056e34bcceef2d604c883aee40daa688ceb7ec558456e10bef27c64" +checksum = "acec1b6962d99d7b079c0fd1532cd3a2c83a3d659ffd9fcf02edda4599334bb4" dependencies = [ "grovedb-costs", "hex", @@ -2121,9 +2034,9 @@ dependencies = [ [[package]] name = "grovedb-merk" -version = "2.0.3" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daedc296cac3093d244cbda0a11a5ef378bd4f747fcbe45b6cbed040c78cfb36" +checksum = "72057865f239fdd24f92eaa8668acc0d618da168f330546577a62eda1701210e" dependencies = [ "bincode", "blake3", @@ -2137,7 +2050,7 @@ dependencies = [ "grovedb-version", "grovedb-visualize", "hex", - "indexmap 2.4.0", + "indexmap 2.6.0", "integer-encoding", "num_cpus", "rand", @@ -2147,15 +2060,15 @@ dependencies = [ [[package]] name = "grovedb-path" -version = "2.0.3" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3552accddbfe6e586853f50a102d665efc0449a63504e5e2113389be924f98c" +checksum = "5d96cc6106e5ca88e548d66f130b877b664da78be226dfdba555fc210f8508f4" [[package]] name = "grovedb-storage" -version = "2.0.3" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1868d74460c6205563e7bc72549f3fa057ed8bd0f83d96e04b2286ca0a216149" +checksum = "e1c9b59bc9fa7123b8485f87f88a886dd109e7aff5f34a29a3812cb64eb897ff" dependencies = [ "blake3", "grovedb-costs", @@ -2166,16 +2079,16 @@ dependencies = [ "lazy_static", "num_cpus", "rocksdb", - "strum 0.26.3", + "strum", "tempfile", "thiserror", ] [[package]] name = "grovedb-version" -version = "2.0.3" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d62bd20c621681dfd8aa6ca128702de775c67560c1fe412f380c5278d5c48ba" +checksum = "f4be0c1a1ef97068fe93212e7b6f349e0b44a9fc90063c8c28e110cfb8c2fcb2" dependencies = [ "thiserror", "versioned-feature-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2183,9 +2096,9 @@ dependencies = [ [[package]] name = "grovedb-visualize" -version = "2.0.3" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6cd92c3a11055b1d841d071f801517b98575f9704f5a757a016fe83d35a37b8" +checksum = "5865f4335eb99644512a7d80d6b1698ba1099a8268fdfd3ffb1a3a32dcb4af28" dependencies = [ "hex", "itertools 0.12.1", @@ -2193,33 +2106,14 @@ dependencies = [ [[package]] name = "grovedbg-types" -version = "2.0.3" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "003e5066965932dbb617e5966df5f73a066eb721579840b30ddd46bf04311fc8" +checksum = "921b9a29facf9d3f0de667cd1da083a34695ede9e7bfacd74bb5bd29f8f7c178" dependencies = [ "serde", "serde_with 3.9.0", ] -[[package]] -name = "h2" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http 0.2.12", - "indexmap 2.4.0", - "slab", - "tokio", - "tokio-util", - "tracing", -] - [[package]] name = "h2" version = "0.4.6" @@ -2231,8 +2125,8 @@ dependencies = [ "fnv", "futures-core", "futures-sink", - "http 1.1.0", - "indexmap 2.4.0", + "http", + "indexmap 2.6.0", "slab", "tokio", "tokio-util", @@ -2245,6 +2139,16 @@ version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" +[[package]] +name = "half" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +dependencies = [ + "cfg-if", + "crunchy", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -2264,6 +2168,12 @@ dependencies = [ "allocator-api2", ] +[[package]] +name = "hashbrown" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" + [[package]] name = "hdrhistogram" version = "7.5.4" @@ -2289,15 +2199,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - [[package]] name = "hermit-abi" version = "0.3.9" @@ -2319,6 +2220,15 @@ dependencies = [ "serde", ] +[[package]] +name = "hex-conservative" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5313b072ce3c597065a808dbf612c4c8e8590bdbf8b579508bf7a762c5eae6cd" +dependencies = [ + "arrayvec", +] + [[package]] name = "hex-literal" version = "0.4.1" @@ -2349,17 +2259,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "http" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - [[package]] name = "http" version = "1.1.0" @@ -2371,17 +2270,6 @@ dependencies = [ "itoa", ] -[[package]] -name = "http-body" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" -dependencies = [ - "bytes", - "http 0.2.12", - "pin-project-lite", -] - [[package]] name = "http-body" version = "1.0.1" @@ -2389,7 +2277,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http 1.1.0", + "http", ] [[package]] @@ -2400,8 +2288,8 @@ checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", "futures-util", - "http 1.1.0", - "http-body 1.0.1", + "http", + "http-body", "pin-project-lite", ] @@ -2413,11 +2301,11 @@ checksum = "08a397c49fec283e3d6211adbe480be95aae5f304cfb923e9970e08956d5168a" [[package]] name = "http-serde" -version = "1.1.3" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f560b665ad9f1572cfcaf034f7fb84338a7ce945216d64a90fd81f046a3caee" +checksum = "0f056c8559e3757392c8d091e796416e4649d8e49e88b8d76df6c002f05027fd" dependencies = [ - "http 0.2.12", + "http", "serde", ] @@ -2439,30 +2327,6 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" -[[package]] -name = "hyper" -version = "0.14.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2 0.3.26", - "http 0.2.12", - "http-body 0.4.6", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2 0.5.7", - "tokio", - "tower-service", - "tracing", - "want", -] - [[package]] name = "hyper" version = "1.4.1" @@ -2472,9 +2336,9 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.6", - "http 1.1.0", - "http-body 1.0.1", + "h2", + "http", + "http-body", "httparse", "httpdate", "itoa", @@ -2491,26 +2355,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" dependencies = [ "futures-util", - "http 1.1.0", - "hyper 1.4.1", + "http", + "hyper", "hyper-util", - "rustls 0.23.12", + "rustls", "rustls-pki-types", "tokio", - "tokio-rustls 0.26.0", + "tokio-rustls", "tower-service", ] [[package]] name = "hyper-timeout" -version = "0.4.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793" dependencies = [ - "hyper 0.14.30", + "hyper", + "hyper-util", "pin-project-lite", "tokio", - "tokio-io-timeout", + "tower-service", ] [[package]] @@ -2521,7 +2386,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper 1.4.1", + "hyper", "hyper-util", "native-tls", "tokio", @@ -2538,11 +2403,11 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "http 1.1.0", - "http-body 1.0.1", - "hyper 1.4.1", + "http", + "http-body", + "hyper", "pin-project-lite", - "socket2 0.5.7", + "socket2", "tokio", "tower", "tower-service", @@ -2601,12 +2466,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.4.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.14.5", + "hashbrown 0.15.0", "serde", ] @@ -2619,15 +2484,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "instant" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" -dependencies = [ - "cfg-if", -] - [[package]] name = "integer-encoding" version = "4.0.2" @@ -2643,17 +2499,6 @@ dependencies = [ "serde", ] -[[package]] -name = "io-lifetimes" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" -dependencies = [ - "hermit-abi 0.3.9", - "libc", - "windows-sys 0.48.0", -] - [[package]] name = "ipnet" version = "2.9.0" @@ -2697,18 +2542,18 @@ dependencies = [ [[package]] name = "itertools" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" dependencies = [ "either", ] [[package]] name = "itertools" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ "either", ] @@ -2750,7 +2595,7 @@ dependencies = [ [[package]] name = "json-schema-compatibility-validator" -version = "1.3.1" +version = "1.5.0" dependencies = [ "assert_matches", "json-patch", @@ -2859,12 +2704,6 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "linux-raw-sys" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" - [[package]] name = "linux-raw-sys" version = "0.4.14" @@ -2912,18 +2751,9 @@ dependencies = [ "libc", ] -[[package]] -name = "mach2" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" -dependencies = [ - "libc", -] - [[package]] name = "masternode-reward-shares-contract" -version = "1.3.1" +version = "1.5.0" dependencies = [ "platform-value", "platform-version", @@ -2954,9 +2784,9 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "metrics" -version = "0.22.3" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2be3cbd384d4e955b231c895ce10685e3d8260c5ccffae898c96c723b0772835" +checksum = "884adb57038347dfbaf2d5065887b6cf4312330dc8e94bc30a1a839bd79d3261" dependencies = [ "ahash 0.8.11", "portable-atomic", @@ -2964,20 +2794,19 @@ dependencies = [ [[package]] name = "metrics-exporter-prometheus" -version = "0.14.0" +version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d58e362dc7206e9456ddbcdbd53c71ba441020e62104703075a69151e38d85f" +checksum = "b4f0c8427b39666bf970460908b213ec09b3b350f20c0c2eabcbba51704a08e6" dependencies = [ "base64 0.22.1", "http-body-util", - "hyper 1.4.1", - "hyper-tls", + "hyper", "hyper-util", - "indexmap 2.4.0", + "indexmap 2.6.0", "ipnet", "metrics", "metrics-util", - "quanta 0.12.3", + "quanta", "thiserror", "tokio", "tracing", @@ -2985,16 +2814,16 @@ dependencies = [ [[package]] name = "metrics-util" -version = "0.16.3" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b07a5eb561b8cbc16be2d216faf7757f9baf3bfb94dbb0fae3df8387a5bb47f" +checksum = "4259040465c955f9f2f1a4a8a16dc46726169bca0f88e8fb2dbeced487c3e828" dependencies = [ "crossbeam-epoch", "crossbeam-utils", "hashbrown 0.14.5", "metrics", "num_cpus", - "quanta 0.12.3", + "quanta", "sketches-ddsketch", ] @@ -3052,14 +2881,13 @@ dependencies = [ [[package]] name = "mockall" -version = "0.11.4" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c84490118f2ee2d74570d114f3d0493cbf02790df303d2707606c3e14e07c96" +checksum = "d4c28b3fb6d753d28c20e826cd46ee611fda1cf3cde03a443a974043247c065a" dependencies = [ "cfg-if", "downcast", "fragile", - "lazy_static", "mockall_derive", "predicates", "predicates-tree", @@ -3067,34 +2895,33 @@ dependencies = [ [[package]] name = "mockall_derive" -version = "0.11.4" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ce75669015c4f47b289fd4d4f56e894e4c96003ffdf3ac51313126f94c6cbb" +checksum = "341014e7f530314e9a1fdbc7400b244efea7122662c96bfa248c31da5bfb2020" dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.75", ] [[package]] name = "moka" -version = "0.11.3" +version = "0.12.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa6e72583bf6830c956235bff0d5afec8cf2952f579ebad18ae7821a917d950f" +checksum = "32cf62eb4dd975d2dde76432fb1075c49e3ee2331cf36f1f8fd4b66550d32b6f" dependencies = [ - "async-io", "async-lock", + "async-trait", "crossbeam-channel", "crossbeam-epoch", "crossbeam-utils", + "event-listener", "futures-util", "once_cell", "parking_lot", - "quanta 0.11.1", + "quanta", "rustc_version", - "scheduled-thread-pool", - "skeptic", "smallvec", "tagptr", "thiserror", @@ -3102,12 +2929,6 @@ dependencies = [ "uuid", ] -[[package]] -name = "multimap" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" - [[package]] name = "multimap" version = "0.10.0" @@ -3153,12 +2974,6 @@ dependencies = [ "minimal-lexical", ] -[[package]] -name = "normalize-line-endings" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" - [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -3281,7 +3096,16 @@ version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" dependencies = [ - "num_enum_derive", + "num_enum_derive 0.5.11", +] + +[[package]] +name = "num_enum" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" +dependencies = [ + "num_enum_derive 0.7.3", ] [[package]] @@ -3296,6 +3120,18 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "num_enum_derive" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" +dependencies = [ + "proc-macro-crate 3.1.0", + "proc-macro2", + "quote", + "syn 2.0.75", +] + [[package]] name = "object" version = "0.36.3" @@ -3444,7 +3280,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.4.0", + "indexmap 2.6.0", ] [[package]] @@ -3497,7 +3333,7 @@ checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "platform-serialization" -version = "1.3.1" +version = "1.5.0" dependencies = [ "bincode", "platform-version", @@ -3505,24 +3341,24 @@ dependencies = [ [[package]] name = "platform-serialization-derive" -version = "1.3.1" +version = "1.5.0" dependencies = [ "proc-macro2", "quote", "syn 2.0.75", - "virtue 0.0.14", + "virtue 0.0.17", ] [[package]] name = "platform-value" -version = "1.3.1" +version = "1.5.0" dependencies = [ "base64 0.22.1", "bincode", - "bs58 0.5.1", - "ciborium", + "bs58", + "ciborium 0.2.0", "hex", - "indexmap 2.4.0", + "indexmap 2.6.0", "lazy_static", "platform-serialization", "platform-version", @@ -3536,7 +3372,7 @@ dependencies = [ [[package]] name = "platform-value-convertible" -version = "1.3.1" +version = "1.5.0" dependencies = [ "quote", "syn 2.0.75", @@ -3544,7 +3380,7 @@ dependencies = [ [[package]] name = "platform-version" -version = "1.3.1" +version = "1.5.0" dependencies = [ "bincode", "grovedb-version", @@ -3555,7 +3391,7 @@ dependencies = [ [[package]] name = "platform-versioning" -version = "1.3.1" +version = "1.5.0" dependencies = [ "proc-macro2", "quote", @@ -3590,28 +3426,6 @@ dependencies = [ "plotters-backend", ] -[[package]] -name = "polling" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" -dependencies = [ - "autocfg", - "bitflags 1.3.2", - "cfg-if", - "concurrent-queue", - "libc", - "log", - "pin-project-lite", - "windows-sys 0.48.0", -] - -[[package]] -name = "pollster" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2" - [[package]] name = "portable-atomic" version = "1.7.0" @@ -3635,16 +3449,12 @@ dependencies = [ [[package]] name = "predicates" -version = "2.1.5" +version = "3.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59230a63c37f3e18569bdb90e4a89cbf5bf8b06fea0b84e65ea10cc4df47addd" +checksum = "7e9086cc7640c29a356d1a29fd134380bee9d8f79a17410aa76e7ad295f42c97" dependencies = [ - "difflib", - "float-cmp", - "itertools 0.10.5", - "normalize-line-endings", + "anstyle", "predicates-core", - "regex", ] [[package]] @@ -3665,24 +3475,14 @@ dependencies = [ [[package]] name = "pretty_assertions" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66" +checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" dependencies = [ "diff", "yansi", ] -[[package]] -name = "prettyplease" -version = "0.1.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" -dependencies = [ - "proc-macro2", - "syn 1.0.109", -] - [[package]] name = "prettyplease" version = "0.2.20" @@ -3721,7 +3521,6 @@ dependencies = [ "proc-macro-error-attr", "proc-macro2", "quote", - "syn 1.0.109", "version_check", ] @@ -3746,63 +3545,31 @@ dependencies = [ ] [[package]] -name = "prost" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" -dependencies = [ - "bytes", - "prost-derive 0.11.9", -] - -[[package]] -name = "prost" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" -dependencies = [ - "bytes", - "prost-derive 0.12.6", -] - -[[package]] -name = "prost-build" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270" -dependencies = [ - "bytes", - "heck 0.4.1", - "itertools 0.10.5", - "lazy_static", - "log", - "multimap 0.8.3", - "petgraph", - "prettyplease 0.1.25", - "prost 0.11.9", - "prost-types 0.11.9", - "regex", - "syn 1.0.109", - "tempfile", - "which", +name = "prost" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13db3d3fde688c61e2446b4d843bc27a7e8af269a69440c0308021dc92333cc" +dependencies = [ + "bytes", + "prost-derive", ] [[package]] name = "prost-build" -version = "0.12.6" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" +checksum = "5bb182580f71dd070f88d01ce3de9f4da5021db7115d2e1c3605a754153b77c1" dependencies = [ "bytes", "heck 0.5.0", - "itertools 0.12.1", + "itertools 0.13.0", "log", - "multimap 0.10.0", + "multimap", "once_cell", "petgraph", - "prettyplease 0.2.20", - "prost 0.12.6", - "prost-types 0.12.6", + "prettyplease", + "prost", + "prost-types", "regex", "syn 2.0.75", "tempfile", @@ -3810,25 +3577,12 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" -dependencies = [ - "anyhow", - "itertools 0.10.5", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "prost-derive" -version = "0.12.6" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" +checksum = "18bec9b0adc4eba778b33684b7ba3e7137789434769ee3ce3930463ef904cfca" dependencies = [ "anyhow", - "itertools 0.12.1", + "itertools 0.13.0", "proc-macro2", "quote", "syn 2.0.75", @@ -3836,20 +3590,11 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" -dependencies = [ - "prost 0.11.9", -] - -[[package]] -name = "prost-types" -version = "0.12.6" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" +checksum = "cee5168b05f49d4b0ca581206eb14a7b22fafd963efe729ac48eb03266e25cc2" dependencies = [ - "prost 0.12.6", + "prost", ] [[package]] @@ -3872,33 +3617,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "pulldown-cmark" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" -dependencies = [ - "bitflags 2.6.0", - "memchr", - "unicase", -] - -[[package]] -name = "quanta" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17e662a7a8291a865152364c20c7abc5e60486ab2001e8ec10b24862de0b9ab" -dependencies = [ - "crossbeam-utils", - "libc", - "mach2", - "once_cell", - "raw-cpuid 10.7.0", - "wasi", - "web-sys", - "winapi", -] - [[package]] name = "quanta" version = "0.12.3" @@ -3908,7 +3626,7 @@ dependencies = [ "crossbeam-utils", "libc", "once_cell", - "raw-cpuid 11.1.0", + "raw-cpuid", "wasi", "web-sys", "winapi", @@ -3959,15 +3677,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "raw-cpuid" -version = "10.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c297679cb867470fa8c9f67dbba74a78d78e3e98d7cf2b08d6d71540f797332" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "raw-cpuid" version = "11.1.0" @@ -4080,11 +3789,11 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2 0.4.6", - "http 1.1.0", - "http-body 1.0.1", + "h2", + "http", + "http-body", "http-body-util", - "hyper 1.4.1", + "hyper", "hyper-rustls", "hyper-tls", "hyper-util", @@ -4168,7 +3877,7 @@ dependencies = [ [[package]] name = "rs-dapi-client" -version = "1.3.1" +version = "1.5.0" dependencies = [ "backon", "chrono", @@ -4186,17 +3895,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "rs-x11-hash" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94ea852806513d6f5fd7750423300375bc8481a18ed033756c1a836257893a30" -dependencies = [ - "bindgen 0.65.1", - "cc", - "libc", -] - [[package]] name = "rust_decimal" version = "1.36.0" @@ -4244,20 +3942,6 @@ dependencies = [ "semver", ] -[[package]] -name = "rustix" -version = "0.37.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" -dependencies = [ - "bitflags 1.3.2", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys 0.3.8", - "windows-sys 0.48.0", -] - [[package]] name = "rustix" version = "0.38.34" @@ -4267,24 +3951,10 @@ dependencies = [ "bitflags 2.6.0", "errno", "libc", - "linux-raw-sys 0.4.14", + "linux-raw-sys", "windows-sys 0.52.0", ] -[[package]] -name = "rustls" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" -dependencies = [ - "log", - "ring", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - [[package]] name = "rustls" version = "0.23.12" @@ -4302,9 +3972,9 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.7.2" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04182dffc9091a404e0fc069ea5cd60e5b866c3adf881eff99a32d048242dffa" +checksum = "fcaf18a4f2be7326cd874a5fa579fae794320a0f388d365dca7e480e55f83f8a" dependencies = [ "openssl-probe", "rustls-pemfile", @@ -4380,15 +4050,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "scheduled-thread-pool" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cbc66816425a074528352f5789333ecff06ca41b36b0b0efdfbb29edc391a19" -dependencies = [ - "parking_lot", -] - [[package]] name = "scopeguard" version = "1.2.0" @@ -4403,9 +4064,9 @@ checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" [[package]] name = "secp256k1" -version = "0.27.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" +checksum = "b50c5943d326858130af85e049f2661ba3c78b26589b8ab98e65e80ae44a1252" dependencies = [ "bitcoin_hashes", "rand", @@ -4415,9 +4076,9 @@ dependencies = [ [[package]] name = "secp256k1-sys" -version = "0.8.1" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70a129b9e9efbfb223753b9163c4ab3b13cff7fd9c7f010fbac25ab4099fa07e" +checksum = "d4387882333d3aa8cb20530a17c69a3752e97837832f34f6dccc760e715001d9" dependencies = [ "cc", ] @@ -4450,9 +4111,6 @@ name = "semver" version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" -dependencies = [ - "serde", -] [[package]] name = "serde" @@ -4482,16 +4140,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_cbor" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" -dependencies = [ - "half", - "serde", -] - [[package]] name = "serde_derive" version = "1.0.208" @@ -4509,7 +4157,7 @@ version = "1.0.126" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3b863381a05ffefbc82571a2d893edf47b27fb0ebedbf582c39640e51abebef" dependencies = [ - "indexmap 2.4.0", + "indexmap 2.6.0", "itoa", "memchr", "ryu", @@ -4584,7 +4232,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.4.0", + "indexmap 2.6.0", "serde", "serde_derive", "serde_json", @@ -4685,7 +4333,7 @@ checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" [[package]] name = "simple-signer" -version = "1.3.1" +version = "1.5.0" dependencies = [ "base64 0.22.1", "bincode", @@ -4693,21 +4341,6 @@ dependencies = [ "dpp", ] -[[package]] -name = "skeptic" -version = "0.13.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16d23b015676c90a0f01c197bfdc786c20342c73a0afdda9025adb0bc42940a8" -dependencies = [ - "bytecount", - "cargo_metadata", - "error-chain", - "glob", - "pulldown-cmark", - "tempfile", - "walkdir", -] - [[package]] name = "sketches-ddsketch" version = "0.2.2" @@ -4729,16 +4362,6 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" -[[package]] -name = "socket2" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "socket2" version = "0.5.7" @@ -4776,7 +4399,7 @@ dependencies = [ [[package]] name = "strategy-tests" -version = "1.3.1" +version = "1.5.0" dependencies = [ "bincode", "dpp", @@ -4799,35 +4422,13 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" -[[package]] -name = "strum" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" -dependencies = [ - "strum_macros 0.25.3", -] - [[package]] name = "strum" version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" dependencies = [ - "strum_macros 0.26.4", -] - -[[package]] -name = "strum_macros" -version = "0.25.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" -dependencies = [ - "heck 0.4.1", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.75", + "strum_macros", ] [[package]] @@ -4959,22 +4560,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" dependencies = [ "cfg-if", - "fastrand 2.1.0", + "fastrand", "once_cell", - "rustix 0.38.34", + "rustix", "windows-sys 0.59.0", ] [[package]] name = "tenderdash-abci" -version = "1.2.0+1.3.0" -source = "git+https://github.com/dashpay/rs-tenderdash-abci?tag=v1.2.0+1.3.0#79b1bcc141f8285fe9b5022f8288b4c49ddfbb0c" +version = "1.2.1+1.3.0" +source = "git+https://github.com/dashpay/rs-tenderdash-abci?tag=v1.2.1+1.3.0#aad72f4d25816bdf0f584ee4ba3cd383addf8a33" dependencies = [ "bytes", "futures", "hex", "lhash", - "prost 0.12.6", "semver", "serde_json", "tenderdash-proto", @@ -4989,33 +4589,33 @@ dependencies = [ [[package]] name = "tenderdash-proto" -version = "1.2.0+1.3.0" -source = "git+https://github.com/dashpay/rs-tenderdash-abci?tag=v1.2.0+1.3.0#79b1bcc141f8285fe9b5022f8288b4c49ddfbb0c" +version = "1.2.1+1.3.0" +source = "git+https://github.com/dashpay/rs-tenderdash-abci?tag=v1.2.1+1.3.0#aad72f4d25816bdf0f584ee4ba3cd383addf8a33" dependencies = [ "bytes", "chrono", - "derive_more", + "derive_more 1.0.0", "flex-error", "num-derive", "num-traits", - "prost 0.12.6", + "prost", "serde", "subtle-encoding", "tenderdash-proto-compiler", "time", - "tonic 0.11.0", + "tonic", ] [[package]] name = "tenderdash-proto-compiler" -version = "1.2.0+1.3.0" -source = "git+https://github.com/dashpay/rs-tenderdash-abci?tag=v1.2.0+1.3.0#79b1bcc141f8285fe9b5022f8288b4c49ddfbb0c" +version = "1.2.1+1.3.0" +source = "git+https://github.com/dashpay/rs-tenderdash-abci?tag=v1.2.1+1.3.0#aad72f4d25816bdf0f584ee4ba3cd383addf8a33" dependencies = [ "fs_extra", - "prost-build 0.12.6", + "prost-build", "regex", "tempfile", - "tonic-build 0.11.0", + "tonic-build", "ureq", "walkdir", "zip 2.2.0", @@ -5036,22 +4636,13 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" -[[package]] -name = "test-case" -version = "2.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21d6cf5a7dffb3f9dceec8e6b8ca528d9bd71d36c9f074defb548ce161f598c0" -dependencies = [ - "test-case-macros 2.2.2", -] - [[package]] name = "test-case" version = "3.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb2550dd13afcd286853192af8601920d959b14c401fcece38071d53bf0768a8" dependencies = [ - "test-case-macros 3.3.1", + "test-case-macros", ] [[package]] @@ -5066,19 +4657,6 @@ dependencies = [ "syn 2.0.75", ] -[[package]] -name = "test-case-macros" -version = "2.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e45b7bf6e19353ddd832745c8fcf77a17a93171df7151187f26623f2b75b5b26" -dependencies = [ - "cfg-if", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "test-case-macros" version = "3.3.1" @@ -5091,29 +4669,20 @@ dependencies = [ "test-case-core", ] -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", @@ -5188,9 +4757,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.39.3" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" dependencies = [ "backtrace", "bytes", @@ -5199,22 +4768,12 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.7", + "socket2", "tokio-macros", "tracing", "windows-sys 0.52.0", ] -[[package]] -name = "tokio-io-timeout" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" -dependencies = [ - "pin-project-lite", - "tokio", -] - [[package]] name = "tokio-macros" version = "2.4.0" @@ -5236,33 +4795,22 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-rustls" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" -dependencies = [ - "rustls 0.22.4", - "rustls-pki-types", - "tokio", -] - [[package]] name = "tokio-rustls" version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.23.12", + "rustls", "rustls-pki-types", "tokio", ] [[package]] name = "tokio-stream" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" dependencies = [ "futures-core", "pin-project-lite", @@ -5284,9 +4832,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.11" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ "bytes", "futures-core", @@ -5322,7 +4870,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.4.0", + "indexmap 2.6.0", "toml_datetime", "winnow 0.5.40", ] @@ -5333,7 +4881,7 @@ version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ - "indexmap 2.4.0", + "indexmap 2.6.0", "toml_datetime", "winnow 0.5.40", ] @@ -5344,7 +4892,7 @@ version = "0.22.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" dependencies = [ - "indexmap 2.4.0", + "indexmap 2.6.0", "serde", "serde_spanned", "toml_datetime", @@ -5353,55 +4901,30 @@ dependencies = [ [[package]] name = "tonic" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d560933a0de61cf715926b9cac824d4c883c2c43142f787595e48280c40a1d0e" -dependencies = [ - "async-stream", - "async-trait", - "axum 0.6.20", - "base64 0.21.7", - "bytes", - "h2 0.3.26", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.30", - "hyper-timeout", - "percent-encoding", - "pin-project", - "prost 0.12.6", - "tokio", - "tokio-stream", - "tower", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tonic" -version = "0.11.0" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76c4eb7a4e9ef9d4763600161f12f5070b92a578e1b634db88a6887844c91a13" +checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52" dependencies = [ "async-stream", "async-trait", - "axum 0.6.20", - "base64 0.21.7", + "axum", + "base64 0.22.1", "bytes", - "h2 0.3.26", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.30", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", "hyper-timeout", + "hyper-util", "percent-encoding", "pin-project", - "prost 0.12.6", + "prost", "rustls-native-certs", "rustls-pemfile", - "rustls-pki-types", + "socket2", "tokio", - "tokio-rustls 0.25.0", + "tokio-rustls", "tokio-stream", "tower", "tower-layer", @@ -5412,26 +4935,13 @@ dependencies = [ [[package]] name = "tonic-build" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6fdaae4c2c638bb70fe42803a26fbd6fc6ac8c72f5c59f67ecc2a2dcabf4b07" -dependencies = [ - "prettyplease 0.1.25", - "proc-macro2", - "prost-build 0.11.9", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "tonic-build" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4ef6dd70a610078cb4e338a0f79d06bc759ff1b22d2120c2ff02ae264ba9c2" +checksum = "568392c5a2bd0020723e3f387891176aabafe36fd9fcd074ad309dfa0c8eb964" dependencies = [ - "prettyplease 0.2.20", + "prettyplease", "proc-macro2", - "prost-build 0.12.6", + "prost-build", "quote", "syn 2.0.75", ] @@ -5443,7 +4953,7 @@ source = "git+https://github.com/QuantumExplorer/tower?branch=fix/indexMap2OnV04 dependencies = [ "futures-core", "futures-util", - "indexmap 2.4.0", + "indexmap 2.6.0", "pin-project", "pin-project-lite", "rand", @@ -5464,8 +4974,8 @@ dependencies = [ "bitflags 2.6.0", "bytes", "futures-util", - "http 1.1.0", - "http-body 1.0.1", + "http", + "http-body", "http-body-util", "http-range-header", "httpdate", @@ -5573,9 +5083,9 @@ checksum = "e2ce481b2b7c2534fe7b5242cccebf37f9084392665c6a3783c414a1bada5432" [[package]] name = "triomphe" -version = "0.1.13" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6631e42e10b40c0690bf92f404ebcfe6e1fdb480391d15f17cc8e96eeed5369" +checksum = "859eb650cfee7434994602c3a68b25d77ad9e68c8a6cd491616ef86661382eb3" [[package]] name = "try-lock" @@ -5619,12 +5129,6 @@ dependencies = [ "tinyvec", ] -[[package]] -name = "unicode-width" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" - [[package]] name = "unicode-xid" version = "0.2.5" @@ -5647,7 +5151,7 @@ dependencies = [ "flate2", "log", "once_cell", - "rustls 0.23.12", + "rustls", "rustls-pki-types", "url", "webpki-roots", @@ -5717,15 +5221,9 @@ checksum = "9dcc60c0624df774c82a0ef104151231d37da4962957d691c011c852b2473314" [[package]] name = "virtue" -version = "0.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b522f715ead3537dc57c9907899a08e461a8f1e87fc8414a4a89bbd9854289ff" - -[[package]] -name = "waker-fn" -version = "1.2.0" +version = "0.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" +checksum = "7302ac74a033bf17b6e609ceec0f891ca9200d502d31f02dc7908d3d98767c9d" [[package]] name = "walkdir" @@ -5820,17 +5318,17 @@ checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93" [[package]] name = "wasm-dpp" -version = "1.3.1" +version = "1.5.0" dependencies = [ "anyhow", "async-trait", "bincode", "dpp", "hex", - "itertools 0.10.5", + "itertools 0.13.0", "js-sys", "log", - "num_enum", + "num_enum 0.7.3", "paste", "serde", "serde-wasm-bindgen", @@ -5881,7 +5379,7 @@ dependencies = [ "either", "home", "once_cell", - "rustix 0.38.34", + "rustix", ] [[package]] @@ -6122,9 +5620,9 @@ dependencies = [ [[package]] name = "withdrawals-contract" -version = "1.3.1" +version = "1.5.0" dependencies = [ - "num_enum", + "num_enum 0.5.11", "platform-value", "platform-version", "serde", @@ -6144,9 +5642,9 @@ dependencies = [ [[package]] name = "yansi" -version = "0.5.1" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[package]] name = "zerocopy" @@ -6174,6 +5672,21 @@ name = "zeroize" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +dependencies = [ + "serde", + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.75", +] [[package]] name = "zip" @@ -6206,7 +5719,7 @@ dependencies = [ "crossbeam-utils", "displaydoc", "flate2", - "indexmap 2.4.0", + "indexmap 2.6.0", "memchr", "thiserror", "zopfli", diff --git a/Dockerfile b/Dockerfile index a96488115b..5039a062b6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -30,7 +30,7 @@ # SCCACHE_SERVER_PORT port to avoid conflicts in case of parallel compilation ARG ALPINE_VERSION=3.18 -ARG PROTOC_VERSION=25.2 +ARG PROTOC_VERSION=27.3 ARG RUSTC_WRAPPER # diff --git a/README.md b/README.md index fd688fbc88..3b2bd65ecb 100644 --- a/README.md +++ b/README.md @@ -25,8 +25,6 @@ If you are looking for how to contribute to the project or need any help with building an app on the Dash Platform - message us on the [Devs Discord](https://chat.dashdevs.org/)! -## Note: Dash Platform is currently available on the Dash Testnet only - ## Intro This is a multi-package repository - sometimes also known as monorepository - @@ -41,9 +39,9 @@ Dash Platform is currently undergoing testing and final development necessary to support its release on the Dash production network (mainnet). The packages in this repository may be used on the following networks: -- [x] **Development networks** ([**devnets**](https://dashplatform.readme.io/docs/reference-glossary#devnet)) -- [x] [**Testnet**](https://dashplatform.readme.io/docs/reference-glossary#testnet) -- [x] [Mainnet](https://dashplatform.readme.io/docs/reference-glossary#mainnet) +- [x] **Development networks** ([**devnets**](https://docs.dash.org/projects/platform/en/stable/docs/reference/glossary.html#devnet)) +- [x] [**Testnet**](https://docs.dash.org/projects/platform/en/stable/docs/reference/glossary.html#testnet) +- [x] [Mainnet](https://docs.dash.org/projects/platform/en/stable/docs/reference/glossary.html#mainnet) ## FAQ @@ -54,7 +52,7 @@ this repository may be used on the following networks: - [node.js](https://nodejs.org/) v20 - [docker](https://docs.docker.com/get-docker/) v20.10+ - [rust](https://www.rust-lang.org/tools/install) v1.80+, with wasm32 target (`rustup target add wasm32-unknown-unknown`) - - [protoc - protobuf compiler](https://github.com/protocolbuffers/protobuf/releases) v25.2+ + - [protoc - protobuf compiler](https://github.com/protocolbuffers/protobuf/releases) v27.3+ - if needed, set PROTOC environment variable to location of `protoc` binary - [wasm-bingen toolchain](https://rustwasm.github.io/wasm-bindgen/): - **IMPORTANT (OSX only)**: built-in `llvm` on OSX does not work, needs to be installed from brew: @@ -89,7 +87,7 @@ Discord](https://chat.dashdevs.org/) ### Where are the docs? Our docs are hosted on -[readme.io](https://dashplatform.readme.io/docs/introduction-what-is-dash-platform). +[docs.dash.org](https://docs.dash.org/projects/platform/en/stable/docs/intro/what-is-dash-platform.html). You can create issues and feature requests in the [issues](https://github.com/dashpay/platform/issues) for this repository. diff --git a/package.json b/package.json index bb5f8aab73..bb50d240c5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@dashevo/platform", - "version": "1.3.1", + "version": "1.5.0", "private": true, "scripts": { "setup": "yarn install && yarn run build && yarn run configure", @@ -91,7 +91,8 @@ "socks": "^2.8.1", "ws": "^8.17.1", "body-parser": "^1.20.3", - "path-to-regexp": "^1.9.0" + "path-to-regexp": "^1.9.0", + "cookie": "^0.7.0" }, "dependencies": { "node-gyp": "^10.0.1" diff --git a/packages/bench-suite/package.json b/packages/bench-suite/package.json index dda7797805..9fd607c221 100644 --- a/packages/bench-suite/package.json +++ b/packages/bench-suite/package.json @@ -1,14 +1,14 @@ { "name": "@dashevo/bench-suite", "private": true, - "version": "1.3.1", + "version": "1.5.0", "description": "Dash Platform benchmark tool", "scripts": { "bench": "node ./bin/bench.js", "lint": "" }, "dependencies": { - "@dashevo/dashcore-lib": "~0.21.3", + "@dashevo/dashcore-lib": "~0.22.0", "@dashevo/dpns-contract": "workspace:*", "@dashevo/wallet-lib": "workspace:*", "@dashevo/wasm-dpp": "workspace:*", diff --git a/packages/check-features/Cargo.toml b/packages/check-features/Cargo.toml index 5ff237c365..59befe3fe4 100644 --- a/packages/check-features/Cargo.toml +++ b/packages/check-features/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "check-features" -version = "1.3.1" +version = "1.5.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/packages/dapi-grpc/Cargo.toml b/packages/dapi-grpc/Cargo.toml index c726d37ea4..611b01a94e 100644 --- a/packages/dapi-grpc/Cargo.toml +++ b/packages/dapi-grpc/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "dapi-grpc" description = "GRPC client for Dash Platform" -version = "1.3.1" +version = "1.5.0" authors = [ "Samuel Westrich ", "Igor Markin ", @@ -33,23 +33,23 @@ serde = ["dep:serde", "dep:serde_bytes"] mocks = ["serde", "dep:serde_json"] [dependencies] -prost = { version = "0.12.3" } +prost = { version = "0.13" } futures-core = "0.3.30" -tonic = { version = "0.11", features = [ +tonic = { version = "0.12", features = [ "codegen", "prost", ], default-features = false } serde = { version = "1.0.197", optional = true, features = ["derive"] } serde_bytes = { version = "0.11.12", optional = true } serde_json = { version = "1.0", optional = true } -tenderdash-proto = { git = "https://github.com/dashpay/rs-tenderdash-abci", version = "1.2.0+1.3.0", tag = "v1.2.0+1.3.0", default-features = false, features = [ +tenderdash-proto = { git = "https://github.com/dashpay/rs-tenderdash-abci", version = "1.2.1", tag = "v1.2.1+1.3.0", default-features = false, features = [ "grpc", ] } dapi-grpc-macros = { path = "../rs-dapi-grpc-macros" } platform-version = { path = "../rs-platform-version" } [build-dependencies] -tonic-build = { version = "0.9.2" } +tonic-build = { version = "0.12" } [lib] diff --git a/packages/dapi-grpc/build.rs b/packages/dapi-grpc/build.rs index 4bd36542e8..f70b685fbd 100644 --- a/packages/dapi-grpc/build.rs +++ b/packages/dapi-grpc/build.rs @@ -47,7 +47,7 @@ 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; 29] = [ + const VERSIONED_REQUESTS: [&str; 30] = [ "GetDataContractHistoryRequest", "GetDataContractRequest", "GetDataContractsRequest", @@ -77,9 +77,13 @@ fn configure_platform(mut platform: MappingConfig) -> MappingConfig { "GetTotalCreditsInPlatformRequest", "GetEvonodesProposedEpochBlocksByIdsRequest", "GetEvonodesProposedEpochBlocksByRangeRequest", + "GetStatusRequest", ]; - // "GetConsensusParamsResponse" is excluded as this message does not support proofs + // The following responses are excluded as they don't support proofs: + // - "GetConsensusParamsResponse" + // - "GetStatusResponse" + // // "GetEvonodesProposedEpochBlocksResponse" is used for 2 Requests const VERSIONED_RESPONSES: [&str; 29] = [ "GetDataContractHistoryResponse", @@ -213,6 +217,7 @@ impl MappingConfig { /// /// * `protobuf_file` - Path to the protobuf file to use as input. /// * `out_dir` - Output directory where subdirectories for generated files will be created. + /// /// Depending on the features, either `client`, `server` or `client_server` subdirectory /// will be created inside `out_dir`. fn new(protobuf_file: PathBuf, out_dir: PathBuf) -> Self { 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 035bb98138..26cf1818f9 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 @@ -976,6 +976,37 @@ org.dash.platform.dapi.v0.PlatformOuterClass.GetStatusResponse> getGetStatusMeth return getGetStatusMethod; } + private static volatile io.grpc.MethodDescriptor getGetCurrentQuorumsInfoMethod; + + @io.grpc.stub.annotations.RpcMethod( + fullMethodName = SERVICE_NAME + '/' + "getCurrentQuorumsInfo", + requestType = org.dash.platform.dapi.v0.PlatformOuterClass.GetCurrentQuorumsInfoRequest.class, + responseType = org.dash.platform.dapi.v0.PlatformOuterClass.GetCurrentQuorumsInfoResponse.class, + methodType = io.grpc.MethodDescriptor.MethodType.UNARY) + public static io.grpc.MethodDescriptor getGetCurrentQuorumsInfoMethod() { + io.grpc.MethodDescriptor getGetCurrentQuorumsInfoMethod; + if ((getGetCurrentQuorumsInfoMethod = PlatformGrpc.getGetCurrentQuorumsInfoMethod) == null) { + synchronized (PlatformGrpc.class) { + if ((getGetCurrentQuorumsInfoMethod = PlatformGrpc.getGetCurrentQuorumsInfoMethod) == null) { + PlatformGrpc.getGetCurrentQuorumsInfoMethod = getGetCurrentQuorumsInfoMethod = + io.grpc.MethodDescriptor.newBuilder() + .setType(io.grpc.MethodDescriptor.MethodType.UNARY) + .setFullMethodName(generateFullMethodName(SERVICE_NAME, "getCurrentQuorumsInfo")) + .setSampledToLocalTracing(true) + .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + org.dash.platform.dapi.v0.PlatformOuterClass.GetCurrentQuorumsInfoRequest.getDefaultInstance())) + .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + org.dash.platform.dapi.v0.PlatformOuterClass.GetCurrentQuorumsInfoResponse.getDefaultInstance())) + .setSchemaDescriptor(new PlatformMethodDescriptorSupplier("getCurrentQuorumsInfo")) + .build(); + } + } + } + return getGetCurrentQuorumsInfoMethod; + } + /** * Creates a new async stub that supports all call types for the service */ @@ -1256,6 +1287,13 @@ public void getStatus(org.dash.platform.dapi.v0.PlatformOuterClass.GetStatusRequ io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getGetStatusMethod(), responseObserver); } + /** + */ + public void getCurrentQuorumsInfo(org.dash.platform.dapi.v0.PlatformOuterClass.GetCurrentQuorumsInfoRequest request, + io.grpc.stub.StreamObserver responseObserver) { + io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getGetCurrentQuorumsInfoMethod(), responseObserver); + } + @java.lang.Override public final io.grpc.ServerServiceDefinition bindService() { return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor()) .addMethod( @@ -1475,6 +1513,13 @@ public void getStatus(org.dash.platform.dapi.v0.PlatformOuterClass.GetStatusRequ org.dash.platform.dapi.v0.PlatformOuterClass.GetStatusRequest, org.dash.platform.dapi.v0.PlatformOuterClass.GetStatusResponse>( this, METHODID_GET_STATUS))) + .addMethod( + getGetCurrentQuorumsInfoMethod(), + io.grpc.stub.ServerCalls.asyncUnaryCall( + new MethodHandlers< + org.dash.platform.dapi.v0.PlatformOuterClass.GetCurrentQuorumsInfoRequest, + org.dash.platform.dapi.v0.PlatformOuterClass.GetCurrentQuorumsInfoResponse>( + this, METHODID_GET_CURRENT_QUORUMS_INFO))) .build(); } } @@ -1755,6 +1800,14 @@ public void getStatus(org.dash.platform.dapi.v0.PlatformOuterClass.GetStatusRequ io.grpc.stub.ClientCalls.asyncUnaryCall( getChannel().newCall(getGetStatusMethod(), getCallOptions()), request, responseObserver); } + + /** + */ + public void getCurrentQuorumsInfo(org.dash.platform.dapi.v0.PlatformOuterClass.GetCurrentQuorumsInfoRequest request, + io.grpc.stub.StreamObserver responseObserver) { + io.grpc.stub.ClientCalls.asyncUnaryCall( + getChannel().newCall(getGetCurrentQuorumsInfoMethod(), getCallOptions()), request, responseObserver); + } } /** @@ -2002,6 +2055,13 @@ public org.dash.platform.dapi.v0.PlatformOuterClass.GetStatusResponse getStatus( return io.grpc.stub.ClientCalls.blockingUnaryCall( getChannel(), getGetStatusMethod(), getCallOptions(), request); } + + /** + */ + public org.dash.platform.dapi.v0.PlatformOuterClass.GetCurrentQuorumsInfoResponse getCurrentQuorumsInfo(org.dash.platform.dapi.v0.PlatformOuterClass.GetCurrentQuorumsInfoRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getGetCurrentQuorumsInfoMethod(), getCallOptions(), request); + } } /** @@ -2280,6 +2340,14 @@ public com.google.common.util.concurrent.ListenableFuture getCurrentQuorumsInfo( + org.dash.platform.dapi.v0.PlatformOuterClass.GetCurrentQuorumsInfoRequest request) { + return io.grpc.stub.ClientCalls.futureUnaryCall( + getChannel().newCall(getGetCurrentQuorumsInfoMethod(), getCallOptions()), request); + } } private static final int METHODID_BROADCAST_STATE_TRANSITION = 0; @@ -2313,6 +2381,7 @@ public com.google.common.util.concurrent.ListenableFuture implements io.grpc.stub.ServerCalls.UnaryMethod, @@ -2455,6 +2524,10 @@ public void invoke(Req request, io.grpc.stub.StreamObserver responseObserv serviceImpl.getStatus((org.dash.platform.dapi.v0.PlatformOuterClass.GetStatusRequest) request, (io.grpc.stub.StreamObserver) responseObserver); break; + case METHODID_GET_CURRENT_QUORUMS_INFO: + serviceImpl.getCurrentQuorumsInfo((org.dash.platform.dapi.v0.PlatformOuterClass.GetCurrentQuorumsInfoRequest) request, + (io.grpc.stub.StreamObserver) responseObserver); + break; default: throw new AssertionError(); } @@ -2547,6 +2620,7 @@ public static io.grpc.ServiceDescriptor getServiceDescriptor() { .addMethod(getGetTotalCreditsInPlatformMethod()) .addMethod(getGetPathElementsMethod()) .addMethod(getGetStatusMethod()) + .addMethod(getGetCurrentQuorumsInfoMethod()) .build(); } } 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 91ba238650..1818a68889 100644 --- a/packages/dapi-grpc/clients/platform/v0/nodejs/platform_pbjs.js +++ b/packages/dapi-grpc/clients/platform/v0/nodejs/platform_pbjs.js @@ -1109,6 +1109,39 @@ $root.org = (function() { * @variation 2 */ + /** + * Callback as used by {@link org.dash.platform.dapi.v0.Platform#getCurrentQuorumsInfo}. + * @memberof org.dash.platform.dapi.v0.Platform + * @typedef getCurrentQuorumsInfoCallback + * @type {function} + * @param {Error|null} error Error, if any + * @param {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse} [response] GetCurrentQuorumsInfoResponse + */ + + /** + * Calls getCurrentQuorumsInfo. + * @function getCurrentQuorumsInfo + * @memberof org.dash.platform.dapi.v0.Platform + * @instance + * @param {org.dash.platform.dapi.v0.IGetCurrentQuorumsInfoRequest} request GetCurrentQuorumsInfoRequest message or plain object + * @param {org.dash.platform.dapi.v0.Platform.getCurrentQuorumsInfoCallback} callback Node-style callback called with the error, if any, and GetCurrentQuorumsInfoResponse + * @returns {undefined} + * @variation 1 + */ + Object.defineProperty(Platform.prototype.getCurrentQuorumsInfo = function getCurrentQuorumsInfo(request, callback) { + return this.rpcCall(getCurrentQuorumsInfo, $root.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest, $root.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse, request, callback); + }, "name", { value: "getCurrentQuorumsInfo" }); + + /** + * Calls getCurrentQuorumsInfo. + * @function getCurrentQuorumsInfo + * @memberof org.dash.platform.dapi.v0.Platform + * @instance + * @param {org.dash.platform.dapi.v0.IGetCurrentQuorumsInfoRequest} request GetCurrentQuorumsInfoRequest message or plain object + * @returns {Promise} Promise + * @variation 2 + */ + return Platform; })(); @@ -13454,7 +13487,7 @@ $root.org = (function() { * Properties of a GetIdentitiesBalancesRequestV0. * @memberof org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest * @interface IGetIdentitiesBalancesRequestV0 - * @property {org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.IGetIdentitiesBalancesByKnownIdentityIds|null} [identitiesIds] GetIdentitiesBalancesRequestV0 identitiesIds + * @property {Array.|null} [ids] GetIdentitiesBalancesRequestV0 ids * @property {boolean|null} [prove] GetIdentitiesBalancesRequestV0 prove */ @@ -13467,6 +13500,7 @@ $root.org = (function() { * @param {org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.IGetIdentitiesBalancesRequestV0=} [properties] Properties to set */ function GetIdentitiesBalancesRequestV0(properties) { + this.ids = []; if (properties) for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) if (properties[keys[i]] != null) @@ -13474,12 +13508,12 @@ $root.org = (function() { } /** - * GetIdentitiesBalancesRequestV0 identitiesIds. - * @member {org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.IGetIdentitiesBalancesByKnownIdentityIds|null|undefined} identitiesIds + * GetIdentitiesBalancesRequestV0 ids. + * @member {Array.} ids * @memberof org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0 * @instance */ - GetIdentitiesBalancesRequestV0.prototype.identitiesIds = null; + GetIdentitiesBalancesRequestV0.prototype.ids = $util.emptyArray; /** * GetIdentitiesBalancesRequestV0 prove. @@ -13513,8 +13547,9 @@ $root.org = (function() { GetIdentitiesBalancesRequestV0.encode = function encode(message, writer) { if (!writer) writer = $Writer.create(); - if (message.identitiesIds != null && Object.hasOwnProperty.call(message, "identitiesIds")) - $root.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.encode(message.identitiesIds, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); + if (message.ids != null && message.ids.length) + for (var i = 0; i < message.ids.length; ++i) + writer.uint32(/* id 1, wireType 2 =*/10).bytes(message.ids[i]); if (message.prove != null && Object.hasOwnProperty.call(message, "prove")) writer.uint32(/* id 2, wireType 0 =*/16).bool(message.prove); return writer; @@ -13552,7 +13587,9 @@ $root.org = (function() { var tag = reader.uint32(); switch (tag >>> 3) { case 1: - message.identitiesIds = $root.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.decode(reader, reader.uint32()); + if (!(message.ids && message.ids.length)) + message.ids = []; + message.ids.push(reader.bytes()); break; case 2: message.prove = reader.bool(); @@ -13592,10 +13629,12 @@ $root.org = (function() { GetIdentitiesBalancesRequestV0.verify = function verify(message) { if (typeof message !== "object" || message === null) return "object expected"; - if (message.identitiesIds != null && message.hasOwnProperty("identitiesIds")) { - var error = $root.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.verify(message.identitiesIds); - if (error) - return "identitiesIds." + error; + if (message.ids != null && message.hasOwnProperty("ids")) { + if (!Array.isArray(message.ids)) + return "ids: array expected"; + for (var i = 0; i < message.ids.length; ++i) + if (!(message.ids[i] && typeof message.ids[i].length === "number" || $util.isString(message.ids[i]))) + return "ids: buffer[] expected"; } if (message.prove != null && message.hasOwnProperty("prove")) if (typeof message.prove !== "boolean") @@ -13615,10 +13654,15 @@ $root.org = (function() { if (object instanceof $root.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0) return object; var message = new $root.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0(); - if (object.identitiesIds != null) { - if (typeof object.identitiesIds !== "object") - throw TypeError(".org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.identitiesIds: object expected"); - message.identitiesIds = $root.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.fromObject(object.identitiesIds); + if (object.ids) { + if (!Array.isArray(object.ids)) + throw TypeError(".org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.ids: array expected"); + message.ids = []; + for (var i = 0; i < object.ids.length; ++i) + if (typeof object.ids[i] === "string") + $util.base64.decode(object.ids[i], message.ids[i] = $util.newBuffer($util.base64.length(object.ids[i])), 0); + else if (object.ids[i].length >= 0) + message.ids[i] = object.ids[i]; } if (object.prove != null) message.prove = Boolean(object.prove); @@ -13638,12 +13682,15 @@ $root.org = (function() { if (!options) options = {}; var object = {}; - if (options.defaults) { - object.identitiesIds = null; + if (options.arrays || options.defaults) + object.ids = []; + if (options.defaults) object.prove = false; + if (message.ids && message.ids.length) { + object.ids = []; + for (var j = 0; j < message.ids.length; ++j) + object.ids[j] = options.bytes === String ? $util.base64.encode(message.ids[j], 0, message.ids[j].length) : options.bytes === Array ? Array.prototype.slice.call(message.ids[j]) : message.ids[j]; } - if (message.identitiesIds != null && message.hasOwnProperty("identitiesIds")) - object.identitiesIds = $root.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.toObject(message.identitiesIds, options); if (message.prove != null && message.hasOwnProperty("prove")) object.prove = message.prove; return object; @@ -13660,212 +13707,6 @@ $root.org = (function() { return this.constructor.toObject(this, $protobuf.util.toJSONOptions); }; - GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds = (function() { - - /** - * Properties of a GetIdentitiesBalancesByKnownIdentityIds. - * @memberof org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0 - * @interface IGetIdentitiesBalancesByKnownIdentityIds - * @property {Array.|null} [identitiesIds] GetIdentitiesBalancesByKnownIdentityIds identitiesIds - */ - - /** - * Constructs a new GetIdentitiesBalancesByKnownIdentityIds. - * @memberof org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0 - * @classdesc Represents a GetIdentitiesBalancesByKnownIdentityIds. - * @implements IGetIdentitiesBalancesByKnownIdentityIds - * @constructor - * @param {org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.IGetIdentitiesBalancesByKnownIdentityIds=} [properties] Properties to set - */ - function GetIdentitiesBalancesByKnownIdentityIds(properties) { - this.identitiesIds = []; - 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]]; - } - - /** - * GetIdentitiesBalancesByKnownIdentityIds identitiesIds. - * @member {Array.} identitiesIds - * @memberof org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds - * @instance - */ - GetIdentitiesBalancesByKnownIdentityIds.prototype.identitiesIds = $util.emptyArray; - - /** - * Creates a new GetIdentitiesBalancesByKnownIdentityIds instance using the specified properties. - * @function create - * @memberof org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds - * @static - * @param {org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.IGetIdentitiesBalancesByKnownIdentityIds=} [properties] Properties to set - * @returns {org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds} GetIdentitiesBalancesByKnownIdentityIds instance - */ - GetIdentitiesBalancesByKnownIdentityIds.create = function create(properties) { - return new GetIdentitiesBalancesByKnownIdentityIds(properties); - }; - - /** - * Encodes the specified GetIdentitiesBalancesByKnownIdentityIds message. Does not implicitly {@link org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.verify|verify} messages. - * @function encode - * @memberof org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds - * @static - * @param {org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.IGetIdentitiesBalancesByKnownIdentityIds} message GetIdentitiesBalancesByKnownIdentityIds message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - GetIdentitiesBalancesByKnownIdentityIds.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.identitiesIds != null && message.identitiesIds.length) - for (var i = 0; i < message.identitiesIds.length; ++i) - writer.uint32(/* id 1, wireType 2 =*/10).bytes(message.identitiesIds[i]); - return writer; - }; - - /** - * Encodes the specified GetIdentitiesBalancesByKnownIdentityIds message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.verify|verify} messages. - * @function encodeDelimited - * @memberof org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds - * @static - * @param {org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.IGetIdentitiesBalancesByKnownIdentityIds} message GetIdentitiesBalancesByKnownIdentityIds message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - GetIdentitiesBalancesByKnownIdentityIds.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a GetIdentitiesBalancesByKnownIdentityIds message from the specified reader or buffer. - * @function decode - * @memberof org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds - * @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.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds} GetIdentitiesBalancesByKnownIdentityIds - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - GetIdentitiesBalancesByKnownIdentityIds.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.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - if (!(message.identitiesIds && message.identitiesIds.length)) - message.identitiesIds = []; - message.identitiesIds.push(reader.bytes()); - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a GetIdentitiesBalancesByKnownIdentityIds message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds} GetIdentitiesBalancesByKnownIdentityIds - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - GetIdentitiesBalancesByKnownIdentityIds.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a GetIdentitiesBalancesByKnownIdentityIds message. - * @function verify - * @memberof org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - GetIdentitiesBalancesByKnownIdentityIds.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.identitiesIds != null && message.hasOwnProperty("identitiesIds")) { - if (!Array.isArray(message.identitiesIds)) - return "identitiesIds: array expected"; - for (var i = 0; i < message.identitiesIds.length; ++i) - if (!(message.identitiesIds[i] && typeof message.identitiesIds[i].length === "number" || $util.isString(message.identitiesIds[i]))) - return "identitiesIds: buffer[] expected"; - } - return null; - }; - - /** - * Creates a GetIdentitiesBalancesByKnownIdentityIds message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds - * @static - * @param {Object.} object Plain object - * @returns {org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds} GetIdentitiesBalancesByKnownIdentityIds - */ - GetIdentitiesBalancesByKnownIdentityIds.fromObject = function fromObject(object) { - if (object instanceof $root.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds) - return object; - var message = new $root.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds(); - if (object.identitiesIds) { - if (!Array.isArray(object.identitiesIds)) - throw TypeError(".org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.identitiesIds: array expected"); - message.identitiesIds = []; - for (var i = 0; i < object.identitiesIds.length; ++i) - if (typeof object.identitiesIds[i] === "string") - $util.base64.decode(object.identitiesIds[i], message.identitiesIds[i] = $util.newBuffer($util.base64.length(object.identitiesIds[i])), 0); - else if (object.identitiesIds[i].length >= 0) - message.identitiesIds[i] = object.identitiesIds[i]; - } - return message; - }; - - /** - * Creates a plain object from a GetIdentitiesBalancesByKnownIdentityIds message. Also converts values to other types if specified. - * @function toObject - * @memberof org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds - * @static - * @param {org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds} message GetIdentitiesBalancesByKnownIdentityIds - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - GetIdentitiesBalancesByKnownIdentityIds.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.arrays || options.defaults) - object.identitiesIds = []; - if (message.identitiesIds && message.identitiesIds.length) { - object.identitiesIds = []; - for (var j = 0; j < message.identitiesIds.length; ++j) - object.identitiesIds[j] = options.bytes === String ? $util.base64.encode(message.identitiesIds[j], 0, message.identitiesIds[j].length) : options.bytes === Array ? Array.prototype.slice.call(message.identitiesIds[j]) : message.identitiesIds[j]; - } - return object; - }; - - /** - * Converts this GetIdentitiesBalancesByKnownIdentityIds to JSON. - * @function toJSON - * @memberof org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds - * @instance - * @returns {Object.} JSON object - */ - GetIdentitiesBalancesByKnownIdentityIds.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - return GetIdentitiesBalancesByKnownIdentityIds; - })(); - return GetIdentitiesBalancesRequestV0; })(); @@ -45293,6 +45134,1464 @@ $root.org = (function() { return GetStatusResponse; })(); + v0.GetCurrentQuorumsInfoRequest = (function() { + + /** + * Properties of a GetCurrentQuorumsInfoRequest. + * @memberof org.dash.platform.dapi.v0 + * @interface IGetCurrentQuorumsInfoRequest + * @property {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.IGetCurrentQuorumsInfoRequestV0|null} [v0] GetCurrentQuorumsInfoRequest v0 + */ + + /** + * Constructs a new GetCurrentQuorumsInfoRequest. + * @memberof org.dash.platform.dapi.v0 + * @classdesc Represents a GetCurrentQuorumsInfoRequest. + * @implements IGetCurrentQuorumsInfoRequest + * @constructor + * @param {org.dash.platform.dapi.v0.IGetCurrentQuorumsInfoRequest=} [properties] Properties to set + */ + function GetCurrentQuorumsInfoRequest(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]]; + } + + /** + * GetCurrentQuorumsInfoRequest v0. + * @member {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.IGetCurrentQuorumsInfoRequestV0|null|undefined} v0 + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest + * @instance + */ + GetCurrentQuorumsInfoRequest.prototype.v0 = null; + + // OneOf field names bound to virtual getters and setters + var $oneOfFields; + + /** + * GetCurrentQuorumsInfoRequest version. + * @member {"v0"|undefined} version + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest + * @instance + */ + Object.defineProperty(GetCurrentQuorumsInfoRequest.prototype, "version", { + get: $util.oneOfGetter($oneOfFields = ["v0"]), + set: $util.oneOfSetter($oneOfFields) + }); + + /** + * Creates a new GetCurrentQuorumsInfoRequest instance using the specified properties. + * @function create + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest + * @static + * @param {org.dash.platform.dapi.v0.IGetCurrentQuorumsInfoRequest=} [properties] Properties to set + * @returns {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest} GetCurrentQuorumsInfoRequest instance + */ + GetCurrentQuorumsInfoRequest.create = function create(properties) { + return new GetCurrentQuorumsInfoRequest(properties); + }; + + /** + * Encodes the specified GetCurrentQuorumsInfoRequest message. Does not implicitly {@link org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.verify|verify} messages. + * @function encode + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest + * @static + * @param {org.dash.platform.dapi.v0.IGetCurrentQuorumsInfoRequest} message GetCurrentQuorumsInfoRequest message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + GetCurrentQuorumsInfoRequest.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.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0.encode(message.v0, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified GetCurrentQuorumsInfoRequest message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.verify|verify} messages. + * @function encodeDelimited + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest + * @static + * @param {org.dash.platform.dapi.v0.IGetCurrentQuorumsInfoRequest} message GetCurrentQuorumsInfoRequest message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + GetCurrentQuorumsInfoRequest.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a GetCurrentQuorumsInfoRequest message from the specified reader or buffer. + * @function decode + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest + * @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.GetCurrentQuorumsInfoRequest} GetCurrentQuorumsInfoRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + GetCurrentQuorumsInfoRequest.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.GetCurrentQuorumsInfoRequest(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.v0 = $root.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0.decode(reader, reader.uint32()); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a GetCurrentQuorumsInfoRequest message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest} GetCurrentQuorumsInfoRequest + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + GetCurrentQuorumsInfoRequest.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a GetCurrentQuorumsInfoRequest message. + * @function verify + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + GetCurrentQuorumsInfoRequest.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.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0.verify(message.v0); + if (error) + return "v0." + error; + } + } + return null; + }; + + /** + * Creates a GetCurrentQuorumsInfoRequest message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest + * @static + * @param {Object.} object Plain object + * @returns {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest} GetCurrentQuorumsInfoRequest + */ + GetCurrentQuorumsInfoRequest.fromObject = function fromObject(object) { + if (object instanceof $root.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest) + return object; + var message = new $root.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest(); + if (object.v0 != null) { + if (typeof object.v0 !== "object") + throw TypeError(".org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.v0: object expected"); + message.v0 = $root.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0.fromObject(object.v0); + } + return message; + }; + + /** + * Creates a plain object from a GetCurrentQuorumsInfoRequest message. Also converts values to other types if specified. + * @function toObject + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest + * @static + * @param {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest} message GetCurrentQuorumsInfoRequest + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + GetCurrentQuorumsInfoRequest.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.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0.toObject(message.v0, options); + if (options.oneofs) + object.version = "v0"; + } + return object; + }; + + /** + * Converts this GetCurrentQuorumsInfoRequest to JSON. + * @function toJSON + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest + * @instance + * @returns {Object.} JSON object + */ + GetCurrentQuorumsInfoRequest.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0 = (function() { + + /** + * Properties of a GetCurrentQuorumsInfoRequestV0. + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest + * @interface IGetCurrentQuorumsInfoRequestV0 + */ + + /** + * Constructs a new GetCurrentQuorumsInfoRequestV0. + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest + * @classdesc Represents a GetCurrentQuorumsInfoRequestV0. + * @implements IGetCurrentQuorumsInfoRequestV0 + * @constructor + * @param {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.IGetCurrentQuorumsInfoRequestV0=} [properties] Properties to set + */ + function GetCurrentQuorumsInfoRequestV0(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]]; + } + + /** + * Creates a new GetCurrentQuorumsInfoRequestV0 instance using the specified properties. + * @function create + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0 + * @static + * @param {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.IGetCurrentQuorumsInfoRequestV0=} [properties] Properties to set + * @returns {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0} GetCurrentQuorumsInfoRequestV0 instance + */ + GetCurrentQuorumsInfoRequestV0.create = function create(properties) { + return new GetCurrentQuorumsInfoRequestV0(properties); + }; + + /** + * Encodes the specified GetCurrentQuorumsInfoRequestV0 message. Does not implicitly {@link org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0.verify|verify} messages. + * @function encode + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0 + * @static + * @param {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.IGetCurrentQuorumsInfoRequestV0} message GetCurrentQuorumsInfoRequestV0 message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + GetCurrentQuorumsInfoRequestV0.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + return writer; + }; + + /** + * Encodes the specified GetCurrentQuorumsInfoRequestV0 message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0.verify|verify} messages. + * @function encodeDelimited + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0 + * @static + * @param {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.IGetCurrentQuorumsInfoRequestV0} message GetCurrentQuorumsInfoRequestV0 message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + GetCurrentQuorumsInfoRequestV0.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a GetCurrentQuorumsInfoRequestV0 message from the specified reader or buffer. + * @function decode + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0 + * @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.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0} GetCurrentQuorumsInfoRequestV0 + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + GetCurrentQuorumsInfoRequestV0.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.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a GetCurrentQuorumsInfoRequestV0 message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0 + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0} GetCurrentQuorumsInfoRequestV0 + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + GetCurrentQuorumsInfoRequestV0.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a GetCurrentQuorumsInfoRequestV0 message. + * @function verify + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0 + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + GetCurrentQuorumsInfoRequestV0.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + return null; + }; + + /** + * Creates a GetCurrentQuorumsInfoRequestV0 message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0 + * @static + * @param {Object.} object Plain object + * @returns {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0} GetCurrentQuorumsInfoRequestV0 + */ + GetCurrentQuorumsInfoRequestV0.fromObject = function fromObject(object) { + if (object instanceof $root.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0) + return object; + return new $root.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0(); + }; + + /** + * Creates a plain object from a GetCurrentQuorumsInfoRequestV0 message. Also converts values to other types if specified. + * @function toObject + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0 + * @static + * @param {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0} message GetCurrentQuorumsInfoRequestV0 + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + GetCurrentQuorumsInfoRequestV0.toObject = function toObject() { + return {}; + }; + + /** + * Converts this GetCurrentQuorumsInfoRequestV0 to JSON. + * @function toJSON + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0 + * @instance + * @returns {Object.} JSON object + */ + GetCurrentQuorumsInfoRequestV0.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + return GetCurrentQuorumsInfoRequestV0; + })(); + + return GetCurrentQuorumsInfoRequest; + })(); + + v0.GetCurrentQuorumsInfoResponse = (function() { + + /** + * Properties of a GetCurrentQuorumsInfoResponse. + * @memberof org.dash.platform.dapi.v0 + * @interface IGetCurrentQuorumsInfoResponse + * @property {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.IGetCurrentQuorumsInfoResponseV0|null} [v0] GetCurrentQuorumsInfoResponse v0 + */ + + /** + * Constructs a new GetCurrentQuorumsInfoResponse. + * @memberof org.dash.platform.dapi.v0 + * @classdesc Represents a GetCurrentQuorumsInfoResponse. + * @implements IGetCurrentQuorumsInfoResponse + * @constructor + * @param {org.dash.platform.dapi.v0.IGetCurrentQuorumsInfoResponse=} [properties] Properties to set + */ + function GetCurrentQuorumsInfoResponse(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]]; + } + + /** + * GetCurrentQuorumsInfoResponse v0. + * @member {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.IGetCurrentQuorumsInfoResponseV0|null|undefined} v0 + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse + * @instance + */ + GetCurrentQuorumsInfoResponse.prototype.v0 = null; + + // OneOf field names bound to virtual getters and setters + var $oneOfFields; + + /** + * GetCurrentQuorumsInfoResponse version. + * @member {"v0"|undefined} version + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse + * @instance + */ + Object.defineProperty(GetCurrentQuorumsInfoResponse.prototype, "version", { + get: $util.oneOfGetter($oneOfFields = ["v0"]), + set: $util.oneOfSetter($oneOfFields) + }); + + /** + * Creates a new GetCurrentQuorumsInfoResponse instance using the specified properties. + * @function create + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse + * @static + * @param {org.dash.platform.dapi.v0.IGetCurrentQuorumsInfoResponse=} [properties] Properties to set + * @returns {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse} GetCurrentQuorumsInfoResponse instance + */ + GetCurrentQuorumsInfoResponse.create = function create(properties) { + return new GetCurrentQuorumsInfoResponse(properties); + }; + + /** + * Encodes the specified GetCurrentQuorumsInfoResponse message. Does not implicitly {@link org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.verify|verify} messages. + * @function encode + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse + * @static + * @param {org.dash.platform.dapi.v0.IGetCurrentQuorumsInfoResponse} message GetCurrentQuorumsInfoResponse message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + GetCurrentQuorumsInfoResponse.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.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.encode(message.v0, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified GetCurrentQuorumsInfoResponse message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.verify|verify} messages. + * @function encodeDelimited + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse + * @static + * @param {org.dash.platform.dapi.v0.IGetCurrentQuorumsInfoResponse} message GetCurrentQuorumsInfoResponse message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + GetCurrentQuorumsInfoResponse.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a GetCurrentQuorumsInfoResponse message from the specified reader or buffer. + * @function decode + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse + * @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.GetCurrentQuorumsInfoResponse} GetCurrentQuorumsInfoResponse + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + GetCurrentQuorumsInfoResponse.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.GetCurrentQuorumsInfoResponse(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.v0 = $root.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.decode(reader, reader.uint32()); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a GetCurrentQuorumsInfoResponse message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse} GetCurrentQuorumsInfoResponse + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + GetCurrentQuorumsInfoResponse.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a GetCurrentQuorumsInfoResponse message. + * @function verify + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + GetCurrentQuorumsInfoResponse.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.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.verify(message.v0); + if (error) + return "v0." + error; + } + } + return null; + }; + + /** + * Creates a GetCurrentQuorumsInfoResponse message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse + * @static + * @param {Object.} object Plain object + * @returns {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse} GetCurrentQuorumsInfoResponse + */ + GetCurrentQuorumsInfoResponse.fromObject = function fromObject(object) { + if (object instanceof $root.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse) + return object; + var message = new $root.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse(); + if (object.v0 != null) { + if (typeof object.v0 !== "object") + throw TypeError(".org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.v0: object expected"); + message.v0 = $root.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.fromObject(object.v0); + } + return message; + }; + + /** + * Creates a plain object from a GetCurrentQuorumsInfoResponse message. Also converts values to other types if specified. + * @function toObject + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse + * @static + * @param {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse} message GetCurrentQuorumsInfoResponse + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + GetCurrentQuorumsInfoResponse.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.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.toObject(message.v0, options); + if (options.oneofs) + object.version = "v0"; + } + return object; + }; + + /** + * Converts this GetCurrentQuorumsInfoResponse to JSON. + * @function toJSON + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse + * @instance + * @returns {Object.} JSON object + */ + GetCurrentQuorumsInfoResponse.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + GetCurrentQuorumsInfoResponse.ValidatorV0 = (function() { + + /** + * Properties of a ValidatorV0. + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse + * @interface IValidatorV0 + * @property {Uint8Array|null} [proTxHash] ValidatorV0 proTxHash + * @property {string|null} [nodeIp] ValidatorV0 nodeIp + * @property {boolean|null} [isBanned] ValidatorV0 isBanned + */ + + /** + * Constructs a new ValidatorV0. + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse + * @classdesc Represents a ValidatorV0. + * @implements IValidatorV0 + * @constructor + * @param {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.IValidatorV0=} [properties] Properties to set + */ + function ValidatorV0(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]]; + } + + /** + * ValidatorV0 proTxHash. + * @member {Uint8Array} proTxHash + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0 + * @instance + */ + ValidatorV0.prototype.proTxHash = $util.newBuffer([]); + + /** + * ValidatorV0 nodeIp. + * @member {string} nodeIp + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0 + * @instance + */ + ValidatorV0.prototype.nodeIp = ""; + + /** + * ValidatorV0 isBanned. + * @member {boolean} isBanned + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0 + * @instance + */ + ValidatorV0.prototype.isBanned = false; + + /** + * Creates a new ValidatorV0 instance using the specified properties. + * @function create + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0 + * @static + * @param {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.IValidatorV0=} [properties] Properties to set + * @returns {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0} ValidatorV0 instance + */ + ValidatorV0.create = function create(properties) { + return new ValidatorV0(properties); + }; + + /** + * Encodes the specified ValidatorV0 message. Does not implicitly {@link org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.verify|verify} messages. + * @function encode + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0 + * @static + * @param {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.IValidatorV0} message ValidatorV0 message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + ValidatorV0.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.proTxHash != null && Object.hasOwnProperty.call(message, "proTxHash")) + writer.uint32(/* id 1, wireType 2 =*/10).bytes(message.proTxHash); + if (message.nodeIp != null && Object.hasOwnProperty.call(message, "nodeIp")) + writer.uint32(/* id 2, wireType 2 =*/18).string(message.nodeIp); + if (message.isBanned != null && Object.hasOwnProperty.call(message, "isBanned")) + writer.uint32(/* id 3, wireType 0 =*/24).bool(message.isBanned); + return writer; + }; + + /** + * Encodes the specified ValidatorV0 message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.verify|verify} messages. + * @function encodeDelimited + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0 + * @static + * @param {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.IValidatorV0} message ValidatorV0 message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + ValidatorV0.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a ValidatorV0 message from the specified reader or buffer. + * @function decode + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0 + * @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.GetCurrentQuorumsInfoResponse.ValidatorV0} ValidatorV0 + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + ValidatorV0.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.GetCurrentQuorumsInfoResponse.ValidatorV0(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.proTxHash = reader.bytes(); + break; + case 2: + message.nodeIp = reader.string(); + break; + case 3: + message.isBanned = reader.bool(); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a ValidatorV0 message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0 + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0} ValidatorV0 + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + ValidatorV0.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a ValidatorV0 message. + * @function verify + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0 + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + ValidatorV0.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.proTxHash != null && message.hasOwnProperty("proTxHash")) + if (!(message.proTxHash && typeof message.proTxHash.length === "number" || $util.isString(message.proTxHash))) + return "proTxHash: buffer expected"; + if (message.nodeIp != null && message.hasOwnProperty("nodeIp")) + if (!$util.isString(message.nodeIp)) + return "nodeIp: string expected"; + if (message.isBanned != null && message.hasOwnProperty("isBanned")) + if (typeof message.isBanned !== "boolean") + return "isBanned: boolean expected"; + return null; + }; + + /** + * Creates a ValidatorV0 message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0 + * @static + * @param {Object.} object Plain object + * @returns {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0} ValidatorV0 + */ + ValidatorV0.fromObject = function fromObject(object) { + if (object instanceof $root.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0) + return object; + var message = new $root.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0(); + if (object.proTxHash != null) + if (typeof object.proTxHash === "string") + $util.base64.decode(object.proTxHash, message.proTxHash = $util.newBuffer($util.base64.length(object.proTxHash)), 0); + else if (object.proTxHash.length >= 0) + message.proTxHash = object.proTxHash; + if (object.nodeIp != null) + message.nodeIp = String(object.nodeIp); + if (object.isBanned != null) + message.isBanned = Boolean(object.isBanned); + return message; + }; + + /** + * Creates a plain object from a ValidatorV0 message. Also converts values to other types if specified. + * @function toObject + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0 + * @static + * @param {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0} message ValidatorV0 + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + ValidatorV0.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.defaults) { + if (options.bytes === String) + object.proTxHash = ""; + else { + object.proTxHash = []; + if (options.bytes !== Array) + object.proTxHash = $util.newBuffer(object.proTxHash); + } + object.nodeIp = ""; + object.isBanned = false; + } + if (message.proTxHash != null && message.hasOwnProperty("proTxHash")) + object.proTxHash = options.bytes === String ? $util.base64.encode(message.proTxHash, 0, message.proTxHash.length) : options.bytes === Array ? Array.prototype.slice.call(message.proTxHash) : message.proTxHash; + if (message.nodeIp != null && message.hasOwnProperty("nodeIp")) + object.nodeIp = message.nodeIp; + if (message.isBanned != null && message.hasOwnProperty("isBanned")) + object.isBanned = message.isBanned; + return object; + }; + + /** + * Converts this ValidatorV0 to JSON. + * @function toJSON + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0 + * @instance + * @returns {Object.} JSON object + */ + ValidatorV0.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + return ValidatorV0; + })(); + + GetCurrentQuorumsInfoResponse.ValidatorSetV0 = (function() { + + /** + * Properties of a ValidatorSetV0. + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse + * @interface IValidatorSetV0 + * @property {Uint8Array|null} [quorumHash] ValidatorSetV0 quorumHash + * @property {number|null} [coreHeight] ValidatorSetV0 coreHeight + * @property {Array.|null} [members] ValidatorSetV0 members + * @property {Uint8Array|null} [thresholdPublicKey] ValidatorSetV0 thresholdPublicKey + */ + + /** + * Constructs a new ValidatorSetV0. + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse + * @classdesc Represents a ValidatorSetV0. + * @implements IValidatorSetV0 + * @constructor + * @param {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.IValidatorSetV0=} [properties] Properties to set + */ + function ValidatorSetV0(properties) { + this.members = []; + 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]]; + } + + /** + * ValidatorSetV0 quorumHash. + * @member {Uint8Array} quorumHash + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0 + * @instance + */ + ValidatorSetV0.prototype.quorumHash = $util.newBuffer([]); + + /** + * ValidatorSetV0 coreHeight. + * @member {number} coreHeight + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0 + * @instance + */ + ValidatorSetV0.prototype.coreHeight = 0; + + /** + * ValidatorSetV0 members. + * @member {Array.} members + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0 + * @instance + */ + ValidatorSetV0.prototype.members = $util.emptyArray; + + /** + * ValidatorSetV0 thresholdPublicKey. + * @member {Uint8Array} thresholdPublicKey + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0 + * @instance + */ + ValidatorSetV0.prototype.thresholdPublicKey = $util.newBuffer([]); + + /** + * Creates a new ValidatorSetV0 instance using the specified properties. + * @function create + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0 + * @static + * @param {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.IValidatorSetV0=} [properties] Properties to set + * @returns {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0} ValidatorSetV0 instance + */ + ValidatorSetV0.create = function create(properties) { + return new ValidatorSetV0(properties); + }; + + /** + * Encodes the specified ValidatorSetV0 message. Does not implicitly {@link org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.verify|verify} messages. + * @function encode + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0 + * @static + * @param {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.IValidatorSetV0} message ValidatorSetV0 message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + ValidatorSetV0.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.quorumHash != null && Object.hasOwnProperty.call(message, "quorumHash")) + writer.uint32(/* id 1, wireType 2 =*/10).bytes(message.quorumHash); + if (message.coreHeight != null && Object.hasOwnProperty.call(message, "coreHeight")) + writer.uint32(/* id 2, wireType 0 =*/16).uint32(message.coreHeight); + if (message.members != null && message.members.length) + for (var i = 0; i < message.members.length; ++i) + $root.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.encode(message.members[i], writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim(); + if (message.thresholdPublicKey != null && Object.hasOwnProperty.call(message, "thresholdPublicKey")) + writer.uint32(/* id 4, wireType 2 =*/34).bytes(message.thresholdPublicKey); + return writer; + }; + + /** + * Encodes the specified ValidatorSetV0 message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.verify|verify} messages. + * @function encodeDelimited + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0 + * @static + * @param {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.IValidatorSetV0} message ValidatorSetV0 message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + ValidatorSetV0.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a ValidatorSetV0 message from the specified reader or buffer. + * @function decode + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0 + * @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.GetCurrentQuorumsInfoResponse.ValidatorSetV0} ValidatorSetV0 + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + ValidatorSetV0.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.GetCurrentQuorumsInfoResponse.ValidatorSetV0(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.quorumHash = reader.bytes(); + break; + case 2: + message.coreHeight = reader.uint32(); + break; + case 3: + if (!(message.members && message.members.length)) + message.members = []; + message.members.push($root.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.decode(reader, reader.uint32())); + break; + case 4: + message.thresholdPublicKey = reader.bytes(); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a ValidatorSetV0 message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0 + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0} ValidatorSetV0 + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + ValidatorSetV0.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a ValidatorSetV0 message. + * @function verify + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0 + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + ValidatorSetV0.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.quorumHash != null && message.hasOwnProperty("quorumHash")) + if (!(message.quorumHash && typeof message.quorumHash.length === "number" || $util.isString(message.quorumHash))) + return "quorumHash: buffer expected"; + if (message.coreHeight != null && message.hasOwnProperty("coreHeight")) + if (!$util.isInteger(message.coreHeight)) + return "coreHeight: integer expected"; + if (message.members != null && message.hasOwnProperty("members")) { + if (!Array.isArray(message.members)) + return "members: array expected"; + for (var i = 0; i < message.members.length; ++i) { + var error = $root.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.verify(message.members[i]); + if (error) + return "members." + error; + } + } + if (message.thresholdPublicKey != null && message.hasOwnProperty("thresholdPublicKey")) + if (!(message.thresholdPublicKey && typeof message.thresholdPublicKey.length === "number" || $util.isString(message.thresholdPublicKey))) + return "thresholdPublicKey: buffer expected"; + return null; + }; + + /** + * Creates a ValidatorSetV0 message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0 + * @static + * @param {Object.} object Plain object + * @returns {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0} ValidatorSetV0 + */ + ValidatorSetV0.fromObject = function fromObject(object) { + if (object instanceof $root.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0) + return object; + var message = new $root.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0(); + if (object.quorumHash != null) + if (typeof object.quorumHash === "string") + $util.base64.decode(object.quorumHash, message.quorumHash = $util.newBuffer($util.base64.length(object.quorumHash)), 0); + else if (object.quorumHash.length >= 0) + message.quorumHash = object.quorumHash; + if (object.coreHeight != null) + message.coreHeight = object.coreHeight >>> 0; + if (object.members) { + if (!Array.isArray(object.members)) + throw TypeError(".org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.members: array expected"); + message.members = []; + for (var i = 0; i < object.members.length; ++i) { + if (typeof object.members[i] !== "object") + throw TypeError(".org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.members: object expected"); + message.members[i] = $root.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.fromObject(object.members[i]); + } + } + if (object.thresholdPublicKey != null) + if (typeof object.thresholdPublicKey === "string") + $util.base64.decode(object.thresholdPublicKey, message.thresholdPublicKey = $util.newBuffer($util.base64.length(object.thresholdPublicKey)), 0); + else if (object.thresholdPublicKey.length >= 0) + message.thresholdPublicKey = object.thresholdPublicKey; + return message; + }; + + /** + * Creates a plain object from a ValidatorSetV0 message. Also converts values to other types if specified. + * @function toObject + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0 + * @static + * @param {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0} message ValidatorSetV0 + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + ValidatorSetV0.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.arrays || options.defaults) + object.members = []; + if (options.defaults) { + if (options.bytes === String) + object.quorumHash = ""; + else { + object.quorumHash = []; + if (options.bytes !== Array) + object.quorumHash = $util.newBuffer(object.quorumHash); + } + object.coreHeight = 0; + if (options.bytes === String) + object.thresholdPublicKey = ""; + else { + object.thresholdPublicKey = []; + if (options.bytes !== Array) + object.thresholdPublicKey = $util.newBuffer(object.thresholdPublicKey); + } + } + if (message.quorumHash != null && message.hasOwnProperty("quorumHash")) + object.quorumHash = options.bytes === String ? $util.base64.encode(message.quorumHash, 0, message.quorumHash.length) : options.bytes === Array ? Array.prototype.slice.call(message.quorumHash) : message.quorumHash; + if (message.coreHeight != null && message.hasOwnProperty("coreHeight")) + object.coreHeight = message.coreHeight; + if (message.members && message.members.length) { + object.members = []; + for (var j = 0; j < message.members.length; ++j) + object.members[j] = $root.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.toObject(message.members[j], options); + } + if (message.thresholdPublicKey != null && message.hasOwnProperty("thresholdPublicKey")) + object.thresholdPublicKey = options.bytes === String ? $util.base64.encode(message.thresholdPublicKey, 0, message.thresholdPublicKey.length) : options.bytes === Array ? Array.prototype.slice.call(message.thresholdPublicKey) : message.thresholdPublicKey; + return object; + }; + + /** + * Converts this ValidatorSetV0 to JSON. + * @function toJSON + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0 + * @instance + * @returns {Object.} JSON object + */ + ValidatorSetV0.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + return ValidatorSetV0; + })(); + + GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0 = (function() { + + /** + * Properties of a GetCurrentQuorumsInfoResponseV0. + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse + * @interface IGetCurrentQuorumsInfoResponseV0 + * @property {Array.|null} [quorumHashes] GetCurrentQuorumsInfoResponseV0 quorumHashes + * @property {Uint8Array|null} [currentQuorumHash] GetCurrentQuorumsInfoResponseV0 currentQuorumHash + * @property {Array.|null} [validatorSets] GetCurrentQuorumsInfoResponseV0 validatorSets + * @property {Uint8Array|null} [lastBlockProposer] GetCurrentQuorumsInfoResponseV0 lastBlockProposer + * @property {org.dash.platform.dapi.v0.IResponseMetadata|null} [metadata] GetCurrentQuorumsInfoResponseV0 metadata + */ + + /** + * Constructs a new GetCurrentQuorumsInfoResponseV0. + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse + * @classdesc Represents a GetCurrentQuorumsInfoResponseV0. + * @implements IGetCurrentQuorumsInfoResponseV0 + * @constructor + * @param {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.IGetCurrentQuorumsInfoResponseV0=} [properties] Properties to set + */ + function GetCurrentQuorumsInfoResponseV0(properties) { + this.quorumHashes = []; + this.validatorSets = []; + 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]]; + } + + /** + * GetCurrentQuorumsInfoResponseV0 quorumHashes. + * @member {Array.} quorumHashes + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0 + * @instance + */ + GetCurrentQuorumsInfoResponseV0.prototype.quorumHashes = $util.emptyArray; + + /** + * GetCurrentQuorumsInfoResponseV0 currentQuorumHash. + * @member {Uint8Array} currentQuorumHash + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0 + * @instance + */ + GetCurrentQuorumsInfoResponseV0.prototype.currentQuorumHash = $util.newBuffer([]); + + /** + * GetCurrentQuorumsInfoResponseV0 validatorSets. + * @member {Array.} validatorSets + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0 + * @instance + */ + GetCurrentQuorumsInfoResponseV0.prototype.validatorSets = $util.emptyArray; + + /** + * GetCurrentQuorumsInfoResponseV0 lastBlockProposer. + * @member {Uint8Array} lastBlockProposer + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0 + * @instance + */ + GetCurrentQuorumsInfoResponseV0.prototype.lastBlockProposer = $util.newBuffer([]); + + /** + * GetCurrentQuorumsInfoResponseV0 metadata. + * @member {org.dash.platform.dapi.v0.IResponseMetadata|null|undefined} metadata + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0 + * @instance + */ + GetCurrentQuorumsInfoResponseV0.prototype.metadata = null; + + /** + * Creates a new GetCurrentQuorumsInfoResponseV0 instance using the specified properties. + * @function create + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0 + * @static + * @param {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.IGetCurrentQuorumsInfoResponseV0=} [properties] Properties to set + * @returns {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0} GetCurrentQuorumsInfoResponseV0 instance + */ + GetCurrentQuorumsInfoResponseV0.create = function create(properties) { + return new GetCurrentQuorumsInfoResponseV0(properties); + }; + + /** + * Encodes the specified GetCurrentQuorumsInfoResponseV0 message. Does not implicitly {@link org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.verify|verify} messages. + * @function encode + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0 + * @static + * @param {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.IGetCurrentQuorumsInfoResponseV0} message GetCurrentQuorumsInfoResponseV0 message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + GetCurrentQuorumsInfoResponseV0.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.quorumHashes != null && message.quorumHashes.length) + for (var i = 0; i < message.quorumHashes.length; ++i) + writer.uint32(/* id 1, wireType 2 =*/10).bytes(message.quorumHashes[i]); + if (message.currentQuorumHash != null && Object.hasOwnProperty.call(message, "currentQuorumHash")) + writer.uint32(/* id 2, wireType 2 =*/18).bytes(message.currentQuorumHash); + if (message.validatorSets != null && message.validatorSets.length) + for (var i = 0; i < message.validatorSets.length; ++i) + $root.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.encode(message.validatorSets[i], writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim(); + if (message.lastBlockProposer != null && Object.hasOwnProperty.call(message, "lastBlockProposer")) + writer.uint32(/* id 4, wireType 2 =*/34).bytes(message.lastBlockProposer); + if (message.metadata != null && Object.hasOwnProperty.call(message, "metadata")) + $root.org.dash.platform.dapi.v0.ResponseMetadata.encode(message.metadata, writer.uint32(/* id 5, wireType 2 =*/42).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified GetCurrentQuorumsInfoResponseV0 message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.verify|verify} messages. + * @function encodeDelimited + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0 + * @static + * @param {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.IGetCurrentQuorumsInfoResponseV0} message GetCurrentQuorumsInfoResponseV0 message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + GetCurrentQuorumsInfoResponseV0.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a GetCurrentQuorumsInfoResponseV0 message from the specified reader or buffer. + * @function decode + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0 + * @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.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0} GetCurrentQuorumsInfoResponseV0 + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + GetCurrentQuorumsInfoResponseV0.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.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + if (!(message.quorumHashes && message.quorumHashes.length)) + message.quorumHashes = []; + message.quorumHashes.push(reader.bytes()); + break; + case 2: + message.currentQuorumHash = reader.bytes(); + break; + case 3: + if (!(message.validatorSets && message.validatorSets.length)) + message.validatorSets = []; + message.validatorSets.push($root.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.decode(reader, reader.uint32())); + break; + case 4: + message.lastBlockProposer = reader.bytes(); + break; + case 5: + message.metadata = $root.org.dash.platform.dapi.v0.ResponseMetadata.decode(reader, reader.uint32()); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a GetCurrentQuorumsInfoResponseV0 message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0 + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0} GetCurrentQuorumsInfoResponseV0 + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + GetCurrentQuorumsInfoResponseV0.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a GetCurrentQuorumsInfoResponseV0 message. + * @function verify + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0 + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + GetCurrentQuorumsInfoResponseV0.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.quorumHashes != null && message.hasOwnProperty("quorumHashes")) { + if (!Array.isArray(message.quorumHashes)) + return "quorumHashes: array expected"; + for (var i = 0; i < message.quorumHashes.length; ++i) + if (!(message.quorumHashes[i] && typeof message.quorumHashes[i].length === "number" || $util.isString(message.quorumHashes[i]))) + return "quorumHashes: buffer[] expected"; + } + if (message.currentQuorumHash != null && message.hasOwnProperty("currentQuorumHash")) + if (!(message.currentQuorumHash && typeof message.currentQuorumHash.length === "number" || $util.isString(message.currentQuorumHash))) + return "currentQuorumHash: buffer expected"; + if (message.validatorSets != null && message.hasOwnProperty("validatorSets")) { + if (!Array.isArray(message.validatorSets)) + return "validatorSets: array expected"; + for (var i = 0; i < message.validatorSets.length; ++i) { + var error = $root.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.verify(message.validatorSets[i]); + if (error) + return "validatorSets." + error; + } + } + if (message.lastBlockProposer != null && message.hasOwnProperty("lastBlockProposer")) + if (!(message.lastBlockProposer && typeof message.lastBlockProposer.length === "number" || $util.isString(message.lastBlockProposer))) + return "lastBlockProposer: buffer expected"; + 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 GetCurrentQuorumsInfoResponseV0 message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0 + * @static + * @param {Object.} object Plain object + * @returns {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0} GetCurrentQuorumsInfoResponseV0 + */ + GetCurrentQuorumsInfoResponseV0.fromObject = function fromObject(object) { + if (object instanceof $root.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0) + return object; + var message = new $root.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0(); + if (object.quorumHashes) { + if (!Array.isArray(object.quorumHashes)) + throw TypeError(".org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.quorumHashes: array expected"); + message.quorumHashes = []; + for (var i = 0; i < object.quorumHashes.length; ++i) + if (typeof object.quorumHashes[i] === "string") + $util.base64.decode(object.quorumHashes[i], message.quorumHashes[i] = $util.newBuffer($util.base64.length(object.quorumHashes[i])), 0); + else if (object.quorumHashes[i].length >= 0) + message.quorumHashes[i] = object.quorumHashes[i]; + } + if (object.currentQuorumHash != null) + if (typeof object.currentQuorumHash === "string") + $util.base64.decode(object.currentQuorumHash, message.currentQuorumHash = $util.newBuffer($util.base64.length(object.currentQuorumHash)), 0); + else if (object.currentQuorumHash.length >= 0) + message.currentQuorumHash = object.currentQuorumHash; + if (object.validatorSets) { + if (!Array.isArray(object.validatorSets)) + throw TypeError(".org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.validatorSets: array expected"); + message.validatorSets = []; + for (var i = 0; i < object.validatorSets.length; ++i) { + if (typeof object.validatorSets[i] !== "object") + throw TypeError(".org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.validatorSets: object expected"); + message.validatorSets[i] = $root.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.fromObject(object.validatorSets[i]); + } + } + if (object.lastBlockProposer != null) + if (typeof object.lastBlockProposer === "string") + $util.base64.decode(object.lastBlockProposer, message.lastBlockProposer = $util.newBuffer($util.base64.length(object.lastBlockProposer)), 0); + else if (object.lastBlockProposer.length >= 0) + message.lastBlockProposer = object.lastBlockProposer; + if (object.metadata != null) { + if (typeof object.metadata !== "object") + throw TypeError(".org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.metadata: object expected"); + message.metadata = $root.org.dash.platform.dapi.v0.ResponseMetadata.fromObject(object.metadata); + } + return message; + }; + + /** + * Creates a plain object from a GetCurrentQuorumsInfoResponseV0 message. Also converts values to other types if specified. + * @function toObject + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0 + * @static + * @param {org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0} message GetCurrentQuorumsInfoResponseV0 + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + GetCurrentQuorumsInfoResponseV0.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.arrays || options.defaults) { + object.quorumHashes = []; + object.validatorSets = []; + } + if (options.defaults) { + if (options.bytes === String) + object.currentQuorumHash = ""; + else { + object.currentQuorumHash = []; + if (options.bytes !== Array) + object.currentQuorumHash = $util.newBuffer(object.currentQuorumHash); + } + if (options.bytes === String) + object.lastBlockProposer = ""; + else { + object.lastBlockProposer = []; + if (options.bytes !== Array) + object.lastBlockProposer = $util.newBuffer(object.lastBlockProposer); + } + object.metadata = null; + } + if (message.quorumHashes && message.quorumHashes.length) { + object.quorumHashes = []; + for (var j = 0; j < message.quorumHashes.length; ++j) + object.quorumHashes[j] = options.bytes === String ? $util.base64.encode(message.quorumHashes[j], 0, message.quorumHashes[j].length) : options.bytes === Array ? Array.prototype.slice.call(message.quorumHashes[j]) : message.quorumHashes[j]; + } + if (message.currentQuorumHash != null && message.hasOwnProperty("currentQuorumHash")) + object.currentQuorumHash = options.bytes === String ? $util.base64.encode(message.currentQuorumHash, 0, message.currentQuorumHash.length) : options.bytes === Array ? Array.prototype.slice.call(message.currentQuorumHash) : message.currentQuorumHash; + if (message.validatorSets && message.validatorSets.length) { + object.validatorSets = []; + for (var j = 0; j < message.validatorSets.length; ++j) + object.validatorSets[j] = $root.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.toObject(message.validatorSets[j], options); + } + if (message.lastBlockProposer != null && message.hasOwnProperty("lastBlockProposer")) + object.lastBlockProposer = options.bytes === String ? $util.base64.encode(message.lastBlockProposer, 0, message.lastBlockProposer.length) : options.bytes === Array ? Array.prototype.slice.call(message.lastBlockProposer) : message.lastBlockProposer; + if (message.metadata != null && message.hasOwnProperty("metadata")) + object.metadata = $root.org.dash.platform.dapi.v0.ResponseMetadata.toObject(message.metadata, options); + return object; + }; + + /** + * Converts this GetCurrentQuorumsInfoResponseV0 to JSON. + * @function toJSON + * @memberof org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0 + * @instance + * @returns {Object.} JSON object + */ + GetCurrentQuorumsInfoResponseV0.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + return GetCurrentQuorumsInfoResponseV0; + })(); + + return GetCurrentQuorumsInfoResponse; + })(); + return v0; })(); 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 746f5210fd..ca80ce2ad7 100644 --- a/packages/dapi-grpc/clients/platform/v0/nodejs/platform_protoc.js +++ b/packages/dapi-grpc/clients/platform/v0/nodejs/platform_protoc.js @@ -75,6 +75,14 @@ goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetContestedResourcesResponse goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetContestedResourcesResponse.GetContestedResourcesResponseV0.ContestedResourceValues', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetContestedResourcesResponse.GetContestedResourcesResponseV0.ResultCase', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetContestedResourcesResponse.VersionCase', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.VersionCase', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.VersionCase', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.GetDataContractHistoryRequestV0', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.VersionCase', null, { proto }); @@ -133,7 +141,6 @@ goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlock goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksResponse.VersionCase', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0', null, { proto }); -goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.VersionCase', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesResponse', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesResponse.GetIdentitiesBalancesResponseV0', null, { proto }); @@ -1404,7 +1411,7 @@ if (goog.DEBUG && !COMPILED) { * @constructor */ proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0 = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, null, null); + jspb.Message.initialize(this, opt_data, 0, -1, proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.repeatedFields_, null); }; goog.inherits(proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0, jspb.Message); if (goog.DEBUG && !COMPILED) { @@ -1414,27 +1421,6 @@ if (goog.DEBUG && !COMPILED) { */ proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.displayName = 'proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0'; } -/** - * 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.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.repeatedFields_, null); -}; -goog.inherits(proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.displayName = 'proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds'; -} /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a @@ -4144,6 +4130,132 @@ if (goog.DEBUG && !COMPILED) { */ proto.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.StateSync.displayName = 'proto.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.StateSync'; } +/** + * 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.GetCurrentQuorumsInfoRequest = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.oneofGroups_); +}; +goog.inherits(proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.displayName = 'proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest'; +} +/** + * 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.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0 = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0.displayName = 'proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0'; +} +/** + * 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.GetCurrentQuorumsInfoResponse = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.oneofGroups_); +}; +goog.inherits(proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.displayName = 'proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse'; +} +/** + * 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.GetCurrentQuorumsInfoResponse.ValidatorV0 = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.displayName = 'proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0'; +} +/** + * 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.GetCurrentQuorumsInfoResponse.ValidatorSetV0 = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.repeatedFields_, null); +}; +goog.inherits(proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.displayName = 'proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0'; +} +/** + * 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.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0 = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.repeatedFields_, null); +}; +goog.inherits(proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.displayName = 'proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0'; +} @@ -13367,8 +13479,8 @@ proto.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByIdsRequest.GetEv */ proto.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByIdsRequest.GetEvonodesProposedEpochBlocksByIdsRequestV0.serializeBinaryToWriter = function(message, writer) { var f = undefined; - f = message.getEpoch(); - if (f !== 0) { + f = /** @type {number} */ (jspb.Message.getField(message, 1)); + if (f != null) { writer.writeUint32( 1, f @@ -13405,7 +13517,25 @@ proto.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByIdsRequest.GetEv * @return {!proto.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByIdsRequest.GetEvonodesProposedEpochBlocksByIdsRequestV0} returns this */ proto.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByIdsRequest.GetEvonodesProposedEpochBlocksByIdsRequestV0.prototype.setEpoch = function(value) { - return jspb.Message.setProto3IntField(this, 1, value); + return jspb.Message.setField(this, 1, value); +}; + + +/** + * Clears the field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByIdsRequest.GetEvonodesProposedEpochBlocksByIdsRequestV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByIdsRequest.GetEvonodesProposedEpochBlocksByIdsRequestV0.prototype.clearEpoch = function() { + return jspb.Message.setField(this, 1, undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByIdsRequest.GetEvonodesProposedEpochBlocksByIdsRequestV0.prototype.hasEpoch = function() { + return jspb.Message.getField(this, 1) != null; }; @@ -14611,8 +14741,8 @@ proto.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByRangeRequest.Get */ proto.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByRangeRequest.GetEvonodesProposedEpochBlocksByRangeRequestV0.serializeBinaryToWriter = function(message, writer) { var f = undefined; - f = message.getEpoch(); - if (f !== 0) { + f = /** @type {number} */ (jspb.Message.getField(message, 1)); + if (f != null) { writer.writeUint32( 1, f @@ -14663,7 +14793,25 @@ proto.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByRangeRequest.Get * @return {!proto.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByRangeRequest.GetEvonodesProposedEpochBlocksByRangeRequestV0} returns this */ proto.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByRangeRequest.GetEvonodesProposedEpochBlocksByRangeRequestV0.prototype.setEpoch = function(value) { - return jspb.Message.setProto3IntField(this, 1, value); + return jspb.Message.setField(this, 1, value); +}; + + +/** + * Clears the field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByRangeRequest.GetEvonodesProposedEpochBlocksByRangeRequestV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByRangeRequest.GetEvonodesProposedEpochBlocksByRangeRequestV0.prototype.clearEpoch = function() { + return jspb.Message.setField(this, 1, undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByRangeRequest.GetEvonodesProposedEpochBlocksByRangeRequestV0.prototype.hasEpoch = function() { + return jspb.Message.getField(this, 1) != null; }; @@ -15018,6 +15166,13 @@ proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.serializeBinaryToWr +/** + * List of repeated fields within this message type. + * @private {!Array} + * @const + */ +proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.repeatedFields_ = [1]; + if (jspb.Message.GENERATE_TO_OBJECT) { @@ -15049,7 +15204,7 @@ proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalanc */ proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.toObject = function(includeInstance, msg) { var f, obj = { - identitiesIds: (f = msg.getIdentitiesIds()) && proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.toObject(includeInstance, f), + idsList: msg.getIdsList_asB64(), prove: jspb.Message.getBooleanFieldWithDefault(msg, 2, false) }; @@ -15088,9 +15243,8 @@ proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalanc var field = reader.getFieldNumber(); switch (field) { case 1: - var value = new proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds; - reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.deserializeBinaryFromReader); - msg.setIdentitiesIds(value); + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.addIds(value); break; case 2: var value = /** @type {boolean} */ (reader.readBool()); @@ -15125,12 +15279,11 @@ proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalanc */ proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.serializeBinaryToWriter = function(message, writer) { var f = undefined; - f = message.getIdentitiesIds(); - if (f != null) { - writer.writeMessage( + f = message.getIdsList_asU8(); + if (f.length > 0) { + writer.writeRepeatedBytes( 1, - f, - proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.serializeBinaryToWriter + f ); } f = message.getProve(); @@ -15143,163 +15296,44 @@ proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalanc }; - -/** - * List of repeated fields within this message type. - * @private {!Array} - * @const - */ -proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.repeatedFields_ = [1]; - - - -if (jspb.Message.GENERATE_TO_OBJECT) { -/** - * Creates an object representation of this proto. - * Field names that are reserved in JavaScript and will be renamed to pb_name. - * Optional fields that are not set will be set to undefined. - * To access a reserved field use, foo.pb_, eg, foo.pb_default. - * For the list of reserved names please see: - * net/proto2/compiler/js/internal/generator.cc#kKeyword. - * @param {boolean=} opt_includeInstance Deprecated. whether to include the - * JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @return {!Object} - */ -proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.prototype.toObject = function(opt_includeInstance) { - return proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.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.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.toObject = function(includeInstance, msg) { - var f, obj = { - identitiesIdsList: msg.getIdentitiesIdsList_asB64() - }; - - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; -}; -} - - -/** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds} - */ -proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds; - return proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.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.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds} - */ -proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.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.addIdentitiesIds(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.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.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.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getIdentitiesIdsList_asU8(); - if (f.length > 0) { - writer.writeRepeatedBytes( - 1, - f - ); - } -}; - - /** - * repeated bytes identities_ids = 1; + * repeated bytes ids = 1; * @return {!Array} */ -proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.prototype.getIdentitiesIdsList = function() { +proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.prototype.getIdsList = function() { return /** @type {!Array} */ (jspb.Message.getRepeatedField(this, 1)); }; /** - * repeated bytes identities_ids = 1; - * This is a type-conversion wrapper around `getIdentitiesIdsList()` + * repeated bytes ids = 1; + * This is a type-conversion wrapper around `getIdsList()` * @return {!Array} */ -proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.prototype.getIdentitiesIdsList_asB64 = function() { +proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.prototype.getIdsList_asB64 = function() { return /** @type {!Array} */ (jspb.Message.bytesListAsB64( - this.getIdentitiesIdsList())); + this.getIdsList())); }; /** - * repeated bytes identities_ids = 1; + * repeated bytes ids = 1; * Note that Uint8Array is not supported on all browsers. * @see http://caniuse.com/Uint8Array - * This is a type-conversion wrapper around `getIdentitiesIdsList()` + * This is a type-conversion wrapper around `getIdsList()` * @return {!Array} */ -proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.prototype.getIdentitiesIdsList_asU8 = function() { +proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.prototype.getIdsList_asU8 = function() { return /** @type {!Array} */ (jspb.Message.bytesListAsU8( - this.getIdentitiesIdsList())); + this.getIdsList())); }; /** * @param {!(Array|Array)} value - * @return {!proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds} returns this + * @return {!proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0} returns this */ -proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.prototype.setIdentitiesIdsList = function(value) { +proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.prototype.setIdsList = function(value) { return jspb.Message.setField(this, 1, value || []); }; @@ -15307,56 +15341,19 @@ proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalanc /** * @param {!(string|Uint8Array)} value * @param {number=} opt_index - * @return {!proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds} returns this + * @return {!proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0} returns this */ -proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.prototype.addIdentitiesIds = function(value, opt_index) { +proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.prototype.addIds = function(value, opt_index) { return jspb.Message.addToRepeatedField(this, 1, value, opt_index); }; /** * Clears the list making it empty but non-null. - * @return {!proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds} returns this - */ -proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.prototype.clearIdentitiesIdsList = function() { - return this.setIdentitiesIdsList([]); -}; - - -/** - * optional GetIdentitiesBalancesByKnownIdentityIds identities_ids = 1; - * @return {?proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds} - */ -proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.prototype.getIdentitiesIds = function() { - return /** @type{?proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds} */ ( - jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds, 1)); -}; - - -/** - * @param {?proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds|undefined} value - * @return {!proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0} returns this -*/ -proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.prototype.setIdentitiesIds = function(value) { - return jspb.Message.setWrapperField(this, 1, value); -}; - - -/** - * Clears the message field making it undefined. * @return {!proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0} returns this */ -proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.prototype.clearIdentitiesIds = function() { - return this.setIdentitiesIds(undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.prototype.hasIdentitiesIds = function() { - return jspb.Message.getField(this, 1) != null; +proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.prototype.clearIdsList = function() { + return this.setIdsList([]); }; @@ -44168,6 +44165,1363 @@ proto.org.dash.platform.dapi.v0.GetStatusResponse.prototype.hasV0 = function() { }; + +/** + * 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.GetCurrentQuorumsInfoRequest.oneofGroups_ = [[1]]; + +/** + * @enum {number} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.VersionCase = { + VERSION_NOT_SET: 0, + V0: 1 +}; + +/** + * @return {proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.VersionCase} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.prototype.getVersionCase = function() { + return /** @type {proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.VersionCase} */(jspb.Message.computeOneofCase(this, proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.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.GetCurrentQuorumsInfoRequest.prototype.toObject = function(opt_includeInstance) { + return proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.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.GetCurrentQuorumsInfoRequest} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.toObject = function(includeInstance, msg) { + var f, obj = { + v0: (f = msg.getV0()) && proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0.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.GetCurrentQuorumsInfoRequest} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest; + return proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.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.GetCurrentQuorumsInfoRequest} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.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.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0.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.GetCurrentQuorumsInfoRequest.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.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.GetCurrentQuorumsInfoRequest} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getV0(); + if (f != null) { + writer.writeMessage( + 1, + f, + proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0.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.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0.prototype.toObject = function(opt_includeInstance) { + return proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0.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.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0.toObject = function(includeInstance, msg) { + var f, obj = { + + }; + + 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.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0; + return proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0.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.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0.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.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0.serializeBinaryToWriter = function(message, writer) { + var f = undefined; +}; + + +/** + * optional GetCurrentQuorumsInfoRequestV0 v0 = 1; + * @return {?proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.prototype.getV0 = function() { + return /** @type{?proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0} */ ( + jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0, 1)); +}; + + +/** + * @param {?proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0|undefined} value + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest} returns this +*/ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.prototype.setV0 = function(value) { + return jspb.Message.setOneofWrapperField(this, 1, proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.oneofGroups_[0], value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest} returns this + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.prototype.clearV0 = function() { + return this.setV0(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.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.GetCurrentQuorumsInfoResponse.oneofGroups_ = [[1]]; + +/** + * @enum {number} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.VersionCase = { + VERSION_NOT_SET: 0, + V0: 1 +}; + +/** + * @return {proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.VersionCase} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.prototype.getVersionCase = function() { + return /** @type {proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.VersionCase} */(jspb.Message.computeOneofCase(this, proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.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.GetCurrentQuorumsInfoResponse.prototype.toObject = function(opt_includeInstance) { + return proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.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.GetCurrentQuorumsInfoResponse} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.toObject = function(includeInstance, msg) { + var f, obj = { + v0: (f = msg.getV0()) && proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.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.GetCurrentQuorumsInfoResponse} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse; + return proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.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.GetCurrentQuorumsInfoResponse} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.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.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.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.GetCurrentQuorumsInfoResponse.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.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.GetCurrentQuorumsInfoResponse} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getV0(); + if (f != null) { + writer.writeMessage( + 1, + f, + proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.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.GetCurrentQuorumsInfoResponse.ValidatorV0.prototype.toObject = function(opt_includeInstance) { + return proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.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.GetCurrentQuorumsInfoResponse.ValidatorV0} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.toObject = function(includeInstance, msg) { + var f, obj = { + proTxHash: msg.getProTxHash_asB64(), + nodeIp: jspb.Message.getFieldWithDefault(msg, 2, ""), + isBanned: jspb.Message.getBooleanFieldWithDefault(msg, 3, 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.GetCurrentQuorumsInfoResponse.ValidatorV0} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0; + return proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.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.GetCurrentQuorumsInfoResponse.ValidatorV0} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.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.setProTxHash(value); + break; + case 2: + var value = /** @type {string} */ (reader.readString()); + msg.setNodeIp(value); + break; + case 3: + var value = /** @type {boolean} */ (reader.readBool()); + msg.setIsBanned(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.GetCurrentQuorumsInfoResponse.ValidatorV0.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.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.GetCurrentQuorumsInfoResponse.ValidatorV0} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getProTxHash_asU8(); + if (f.length > 0) { + writer.writeBytes( + 1, + f + ); + } + f = message.getNodeIp(); + if (f.length > 0) { + writer.writeString( + 2, + f + ); + } + f = message.getIsBanned(); + if (f) { + writer.writeBool( + 3, + f + ); + } +}; + + +/** + * optional bytes pro_tx_hash = 1; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.prototype.getProTxHash = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * optional bytes pro_tx_hash = 1; + * This is a type-conversion wrapper around `getProTxHash()` + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.prototype.getProTxHash_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getProTxHash())); +}; + + +/** + * optional bytes pro_tx_hash = 1; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getProTxHash()` + * @return {!Uint8Array} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.prototype.getProTxHash_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getProTxHash())); +}; + + +/** + * @param {!(string|Uint8Array)} value + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.prototype.setProTxHash = function(value) { + return jspb.Message.setProto3BytesField(this, 1, value); +}; + + +/** + * optional string node_ip = 2; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.prototype.getNodeIp = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * @param {string} value + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.prototype.setNodeIp = function(value) { + return jspb.Message.setProto3StringField(this, 2, value); +}; + + +/** + * optional bool is_banned = 3; + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.prototype.getIsBanned = function() { + return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 3, false)); +}; + + +/** + * @param {boolean} value + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.prototype.setIsBanned = function(value) { + return jspb.Message.setProto3BooleanField(this, 3, value); +}; + + + +/** + * List of repeated fields within this message type. + * @private {!Array} + * @const + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.repeatedFields_ = [3]; + + + +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.GetCurrentQuorumsInfoResponse.ValidatorSetV0.prototype.toObject = function(opt_includeInstance) { + return proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.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.GetCurrentQuorumsInfoResponse.ValidatorSetV0} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.toObject = function(includeInstance, msg) { + var f, obj = { + quorumHash: msg.getQuorumHash_asB64(), + coreHeight: jspb.Message.getFieldWithDefault(msg, 2, 0), + membersList: jspb.Message.toObjectList(msg.getMembersList(), + proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.toObject, includeInstance), + thresholdPublicKey: msg.getThresholdPublicKey_asB64() + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0; + return proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.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.GetCurrentQuorumsInfoResponse.ValidatorSetV0} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.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.setQuorumHash(value); + break; + case 2: + var value = /** @type {number} */ (reader.readUint32()); + msg.setCoreHeight(value); + break; + case 3: + var value = new proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.deserializeBinaryFromReader); + msg.addMembers(value); + break; + case 4: + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setThresholdPublicKey(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.GetCurrentQuorumsInfoResponse.ValidatorSetV0.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.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.GetCurrentQuorumsInfoResponse.ValidatorSetV0} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getQuorumHash_asU8(); + if (f.length > 0) { + writer.writeBytes( + 1, + f + ); + } + f = message.getCoreHeight(); + if (f !== 0) { + writer.writeUint32( + 2, + f + ); + } + f = message.getMembersList(); + if (f.length > 0) { + writer.writeRepeatedMessage( + 3, + f, + proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.serializeBinaryToWriter + ); + } + f = message.getThresholdPublicKey_asU8(); + if (f.length > 0) { + writer.writeBytes( + 4, + f + ); + } +}; + + +/** + * optional bytes quorum_hash = 1; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.prototype.getQuorumHash = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * optional bytes quorum_hash = 1; + * This is a type-conversion wrapper around `getQuorumHash()` + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.prototype.getQuorumHash_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getQuorumHash())); +}; + + +/** + * optional bytes quorum_hash = 1; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getQuorumHash()` + * @return {!Uint8Array} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.prototype.getQuorumHash_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getQuorumHash())); +}; + + +/** + * @param {!(string|Uint8Array)} value + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.prototype.setQuorumHash = function(value) { + return jspb.Message.setProto3BytesField(this, 1, value); +}; + + +/** + * optional uint32 core_height = 2; + * @return {number} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.prototype.getCoreHeight = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.prototype.setCoreHeight = function(value) { + return jspb.Message.setProto3IntField(this, 2, value); +}; + + +/** + * repeated ValidatorV0 members = 3; + * @return {!Array} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.prototype.getMembersList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0, 3)); +}; + + +/** + * @param {!Array} value + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0} returns this +*/ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.prototype.setMembersList = function(value) { + return jspb.Message.setRepeatedWrapperField(this, 3, value); +}; + + +/** + * @param {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0=} opt_value + * @param {number=} opt_index + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.prototype.addMembers = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 3, opt_value, proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0, opt_index); +}; + + +/** + * Clears the list making it empty but non-null. + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.prototype.clearMembersList = function() { + return this.setMembersList([]); +}; + + +/** + * optional bytes threshold_public_key = 4; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.prototype.getThresholdPublicKey = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 4, "")); +}; + + +/** + * optional bytes threshold_public_key = 4; + * This is a type-conversion wrapper around `getThresholdPublicKey()` + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.prototype.getThresholdPublicKey_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getThresholdPublicKey())); +}; + + +/** + * optional bytes threshold_public_key = 4; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getThresholdPublicKey()` + * @return {!Uint8Array} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.prototype.getThresholdPublicKey_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getThresholdPublicKey())); +}; + + +/** + * @param {!(string|Uint8Array)} value + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.prototype.setThresholdPublicKey = function(value) { + return jspb.Message.setProto3BytesField(this, 4, value); +}; + + + +/** + * List of repeated fields within this message type. + * @private {!Array} + * @const + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.repeatedFields_ = [1,3]; + + + +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.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.toObject = function(opt_includeInstance) { + return proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.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.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.toObject = function(includeInstance, msg) { + var f, obj = { + quorumHashesList: msg.getQuorumHashesList_asB64(), + currentQuorumHash: msg.getCurrentQuorumHash_asB64(), + validatorSetsList: jspb.Message.toObjectList(msg.getValidatorSetsList(), + proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.toObject, includeInstance), + lastBlockProposer: msg.getLastBlockProposer_asB64(), + metadata: (f = msg.getMetadata()) && proto.org.dash.platform.dapi.v0.ResponseMetadata.toObject(includeInstance, f) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0; + return proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.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.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.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.addQuorumHashes(value); + break; + case 2: + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setCurrentQuorumHash(value); + break; + case 3: + var value = new proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.deserializeBinaryFromReader); + msg.addValidatorSets(value); + break; + case 4: + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setLastBlockProposer(value); + break; + case 5: + var value = new proto.org.dash.platform.dapi.v0.ResponseMetadata; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.ResponseMetadata.deserializeBinaryFromReader); + msg.setMetadata(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.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.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getQuorumHashesList_asU8(); + if (f.length > 0) { + writer.writeRepeatedBytes( + 1, + f + ); + } + f = message.getCurrentQuorumHash_asU8(); + if (f.length > 0) { + writer.writeBytes( + 2, + f + ); + } + f = message.getValidatorSetsList(); + if (f.length > 0) { + writer.writeRepeatedMessage( + 3, + f, + proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.serializeBinaryToWriter + ); + } + f = message.getLastBlockProposer_asU8(); + if (f.length > 0) { + writer.writeBytes( + 4, + f + ); + } + f = message.getMetadata(); + if (f != null) { + writer.writeMessage( + 5, + f, + proto.org.dash.platform.dapi.v0.ResponseMetadata.serializeBinaryToWriter + ); + } +}; + + +/** + * repeated bytes quorum_hashes = 1; + * @return {!Array} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.getQuorumHashesList = function() { + return /** @type {!Array} */ (jspb.Message.getRepeatedField(this, 1)); +}; + + +/** + * repeated bytes quorum_hashes = 1; + * This is a type-conversion wrapper around `getQuorumHashesList()` + * @return {!Array} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.getQuorumHashesList_asB64 = function() { + return /** @type {!Array} */ (jspb.Message.bytesListAsB64( + this.getQuorumHashesList())); +}; + + +/** + * repeated bytes quorum_hashes = 1; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getQuorumHashesList()` + * @return {!Array} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.getQuorumHashesList_asU8 = function() { + return /** @type {!Array} */ (jspb.Message.bytesListAsU8( + this.getQuorumHashesList())); +}; + + +/** + * @param {!(Array|Array)} value + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.setQuorumHashesList = function(value) { + return jspb.Message.setField(this, 1, value || []); +}; + + +/** + * @param {!(string|Uint8Array)} value + * @param {number=} opt_index + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.addQuorumHashes = function(value, opt_index) { + return jspb.Message.addToRepeatedField(this, 1, value, opt_index); +}; + + +/** + * Clears the list making it empty but non-null. + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.clearQuorumHashesList = function() { + return this.setQuorumHashesList([]); +}; + + +/** + * optional bytes current_quorum_hash = 2; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.getCurrentQuorumHash = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * optional bytes current_quorum_hash = 2; + * This is a type-conversion wrapper around `getCurrentQuorumHash()` + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.getCurrentQuorumHash_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getCurrentQuorumHash())); +}; + + +/** + * optional bytes current_quorum_hash = 2; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getCurrentQuorumHash()` + * @return {!Uint8Array} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.getCurrentQuorumHash_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getCurrentQuorumHash())); +}; + + +/** + * @param {!(string|Uint8Array)} value + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.setCurrentQuorumHash = function(value) { + return jspb.Message.setProto3BytesField(this, 2, value); +}; + + +/** + * repeated ValidatorSetV0 validator_sets = 3; + * @return {!Array} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.getValidatorSetsList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0, 3)); +}; + + +/** + * @param {!Array} value + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0} returns this +*/ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.setValidatorSetsList = function(value) { + return jspb.Message.setRepeatedWrapperField(this, 3, value); +}; + + +/** + * @param {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0=} opt_value + * @param {number=} opt_index + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.addValidatorSets = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 3, opt_value, proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0, opt_index); +}; + + +/** + * Clears the list making it empty but non-null. + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.clearValidatorSetsList = function() { + return this.setValidatorSetsList([]); +}; + + +/** + * optional bytes last_block_proposer = 4; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.getLastBlockProposer = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 4, "")); +}; + + +/** + * optional bytes last_block_proposer = 4; + * This is a type-conversion wrapper around `getLastBlockProposer()` + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.getLastBlockProposer_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getLastBlockProposer())); +}; + + +/** + * optional bytes last_block_proposer = 4; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getLastBlockProposer()` + * @return {!Uint8Array} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.getLastBlockProposer_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getLastBlockProposer())); +}; + + +/** + * @param {!(string|Uint8Array)} value + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.setLastBlockProposer = function(value) { + return jspb.Message.setProto3BytesField(this, 4, value); +}; + + +/** + * optional ResponseMetadata metadata = 5; + * @return {?proto.org.dash.platform.dapi.v0.ResponseMetadata} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.getMetadata = function() { + return /** @type{?proto.org.dash.platform.dapi.v0.ResponseMetadata} */ ( + jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.ResponseMetadata, 5)); +}; + + +/** + * @param {?proto.org.dash.platform.dapi.v0.ResponseMetadata|undefined} value + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0} returns this +*/ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.setMetadata = function(value) { + return jspb.Message.setWrapperField(this, 5, value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.clearMetadata = function() { + return this.setMetadata(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.hasMetadata = function() { + return jspb.Message.getField(this, 5) != null; +}; + + +/** + * optional GetCurrentQuorumsInfoResponseV0 v0 = 1; + * @return {?proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.prototype.getV0 = function() { + return /** @type{?proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0} */ ( + jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0, 1)); +}; + + +/** + * @param {?proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0|undefined} value + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse} returns this +*/ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.prototype.setV0 = function(value) { + return jspb.Message.setOneofWrapperField(this, 1, proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.oneofGroups_[0], value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse} returns this + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.prototype.clearV0 = function() { + return this.setV0(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.prototype.hasV0 = function() { + return jspb.Message.getField(this, 1) != null; +}; + + /** * @enum {number} */ 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 d6a635ad22..bafa69fcb7 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 @@ -54,6 +54,10 @@ CF_EXTERN_C_BEGIN @class GetContestedResourcesRequest_GetContestedResourcesRequestV0_StartAtValueInfo; @class GetContestedResourcesResponse_GetContestedResourcesResponseV0; @class GetContestedResourcesResponse_GetContestedResourcesResponseV0_ContestedResourceValues; +@class GetCurrentQuorumsInfoRequest_GetCurrentQuorumsInfoRequestV0; +@class GetCurrentQuorumsInfoResponse_GetCurrentQuorumsInfoResponseV0; +@class GetCurrentQuorumsInfoResponse_ValidatorSetV0; +@class GetCurrentQuorumsInfoResponse_ValidatorV0; @class GetDataContractHistoryRequest_GetDataContractHistoryRequestV0; @class GetDataContractHistoryResponse_GetDataContractHistoryResponseV0; @class GetDataContractHistoryResponse_GetDataContractHistoryResponseV0_DataContractHistory; @@ -77,7 +81,6 @@ CF_EXTERN_C_BEGIN @class GetEvonodesProposedEpochBlocksResponse_GetEvonodesProposedEpochBlocksResponseV0_EvonodeProposedBlocks; @class GetEvonodesProposedEpochBlocksResponse_GetEvonodesProposedEpochBlocksResponseV0_EvonodesProposedBlocks; @class GetIdentitiesBalancesRequest_GetIdentitiesBalancesRequestV0; -@class GetIdentitiesBalancesRequest_GetIdentitiesBalancesRequestV0_GetIdentitiesBalancesByKnownIdentityIds; @class GetIdentitiesBalancesResponse_GetIdentitiesBalancesResponseV0; @class GetIdentitiesBalancesResponse_GetIdentitiesBalancesResponseV0_IdentitiesBalances; @class GetIdentitiesBalancesResponse_GetIdentitiesBalancesResponseV0_IdentityBalance; @@ -1396,8 +1399,10 @@ typedef GPB_ENUM(GetEvonodesProposedEpochBlocksByIdsRequest_GetEvonodesProposedE GPB_FINAL @interface GetEvonodesProposedEpochBlocksByIdsRequest_GetEvonodesProposedEpochBlocksByIdsRequestV0 : GPBMessage +/** The epoch we are querying for, if none is set, get current epoch */ @property(nonatomic, readwrite) uint32_t epoch; +@property(nonatomic, readwrite) BOOL hasEpoch; /** IDs of the evonodes for which we want to get their proposed blocks */ @property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *idsArray; /** The number of items in @c idsArray without causing the array to be created. */ @@ -1539,9 +1544,10 @@ typedef GPB_ENUM(GetEvonodesProposedEpochBlocksByRangeRequest_GetEvonodesPropose GPB_FINAL @interface GetEvonodesProposedEpochBlocksByRangeRequest_GetEvonodesProposedEpochBlocksByRangeRequestV0 : GPBMessage -/** The epoch we are querying for */ +/** The epoch we are querying for, if none is set, get current epoch */ @property(nonatomic, readwrite) uint32_t epoch; +@property(nonatomic, readwrite) BOOL hasEpoch; /** Maximum number of evonodes proposed epoch blocks to return */ @property(nonatomic, readwrite) uint32_t limit; @@ -1591,34 +1597,20 @@ void GetIdentitiesBalancesRequest_ClearVersionOneOfCase(GetIdentitiesBalancesReq #pragma mark - GetIdentitiesBalancesRequest_GetIdentitiesBalancesRequestV0 typedef GPB_ENUM(GetIdentitiesBalancesRequest_GetIdentitiesBalancesRequestV0_FieldNumber) { - GetIdentitiesBalancesRequest_GetIdentitiesBalancesRequestV0_FieldNumber_IdentitiesIds = 1, + GetIdentitiesBalancesRequest_GetIdentitiesBalancesRequestV0_FieldNumber_IdsArray = 1, GetIdentitiesBalancesRequest_GetIdentitiesBalancesRequestV0_FieldNumber_Prove = 2, }; GPB_FINAL @interface GetIdentitiesBalancesRequest_GetIdentitiesBalancesRequestV0 : GPBMessage -@property(nonatomic, readwrite, strong, null_resettable) GetIdentitiesBalancesRequest_GetIdentitiesBalancesRequestV0_GetIdentitiesBalancesByKnownIdentityIds *identitiesIds; -/** Test to see if @c identitiesIds has been set. */ -@property(nonatomic, readwrite) BOOL hasIdentitiesIds; +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *idsArray; +/** The number of items in @c idsArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger idsArray_Count; @property(nonatomic, readwrite) BOOL prove; @end -#pragma mark - GetIdentitiesBalancesRequest_GetIdentitiesBalancesRequestV0_GetIdentitiesBalancesByKnownIdentityIds - -typedef GPB_ENUM(GetIdentitiesBalancesRequest_GetIdentitiesBalancesRequestV0_GetIdentitiesBalancesByKnownIdentityIds_FieldNumber) { - GetIdentitiesBalancesRequest_GetIdentitiesBalancesRequestV0_GetIdentitiesBalancesByKnownIdentityIds_FieldNumber_IdentitiesIdsArray = 1, -}; - -GPB_FINAL @interface GetIdentitiesBalancesRequest_GetIdentitiesBalancesRequestV0_GetIdentitiesBalancesByKnownIdentityIds : GPBMessage - -@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *identitiesIdsArray; -/** The number of items in @c identitiesIdsArray without causing the array to be created. */ -@property(nonatomic, readonly) NSUInteger identitiesIdsArray_Count; - -@end - #pragma mark - GetIdentitiesBalancesResponse typedef GPB_ENUM(GetIdentitiesBalancesResponse_FieldNumber) { @@ -4845,6 +4837,131 @@ GPB_FINAL @interface GetStatusResponse_GetStatusResponseV0_StateSync : GPBMessag @end +#pragma mark - GetCurrentQuorumsInfoRequest + +typedef GPB_ENUM(GetCurrentQuorumsInfoRequest_FieldNumber) { + GetCurrentQuorumsInfoRequest_FieldNumber_V0 = 1, +}; + +typedef GPB_ENUM(GetCurrentQuorumsInfoRequest_Version_OneOfCase) { + GetCurrentQuorumsInfoRequest_Version_OneOfCase_GPBUnsetOneOfCase = 0, + GetCurrentQuorumsInfoRequest_Version_OneOfCase_V0 = 1, +}; + +GPB_FINAL @interface GetCurrentQuorumsInfoRequest : GPBMessage + +@property(nonatomic, readonly) GetCurrentQuorumsInfoRequest_Version_OneOfCase versionOneOfCase; + +@property(nonatomic, readwrite, strong, null_resettable) GetCurrentQuorumsInfoRequest_GetCurrentQuorumsInfoRequestV0 *v0; + +@end + +/** + * Clears whatever value was set for the oneof 'version'. + **/ +void GetCurrentQuorumsInfoRequest_ClearVersionOneOfCase(GetCurrentQuorumsInfoRequest *message); + +#pragma mark - GetCurrentQuorumsInfoRequest_GetCurrentQuorumsInfoRequestV0 + +GPB_FINAL @interface GetCurrentQuorumsInfoRequest_GetCurrentQuorumsInfoRequestV0 : GPBMessage + +@end + +#pragma mark - GetCurrentQuorumsInfoResponse + +typedef GPB_ENUM(GetCurrentQuorumsInfoResponse_FieldNumber) { + GetCurrentQuorumsInfoResponse_FieldNumber_V0 = 1, +}; + +typedef GPB_ENUM(GetCurrentQuorumsInfoResponse_Version_OneOfCase) { + GetCurrentQuorumsInfoResponse_Version_OneOfCase_GPBUnsetOneOfCase = 0, + GetCurrentQuorumsInfoResponse_Version_OneOfCase_V0 = 1, +}; + +GPB_FINAL @interface GetCurrentQuorumsInfoResponse : GPBMessage + +@property(nonatomic, readonly) GetCurrentQuorumsInfoResponse_Version_OneOfCase versionOneOfCase; + +@property(nonatomic, readwrite, strong, null_resettable) GetCurrentQuorumsInfoResponse_GetCurrentQuorumsInfoResponseV0 *v0; + +@end + +/** + * Clears whatever value was set for the oneof 'version'. + **/ +void GetCurrentQuorumsInfoResponse_ClearVersionOneOfCase(GetCurrentQuorumsInfoResponse *message); + +#pragma mark - GetCurrentQuorumsInfoResponse_ValidatorV0 + +typedef GPB_ENUM(GetCurrentQuorumsInfoResponse_ValidatorV0_FieldNumber) { + GetCurrentQuorumsInfoResponse_ValidatorV0_FieldNumber_ProTxHash = 1, + GetCurrentQuorumsInfoResponse_ValidatorV0_FieldNumber_NodeIp = 2, + GetCurrentQuorumsInfoResponse_ValidatorV0_FieldNumber_IsBanned = 3, +}; + +GPB_FINAL @interface GetCurrentQuorumsInfoResponse_ValidatorV0 : GPBMessage + +@property(nonatomic, readwrite, copy, null_resettable) NSData *proTxHash; + +@property(nonatomic, readwrite, copy, null_resettable) NSString *nodeIp; + +@property(nonatomic, readwrite) BOOL isBanned; + +@end + +#pragma mark - GetCurrentQuorumsInfoResponse_ValidatorSetV0 + +typedef GPB_ENUM(GetCurrentQuorumsInfoResponse_ValidatorSetV0_FieldNumber) { + GetCurrentQuorumsInfoResponse_ValidatorSetV0_FieldNumber_QuorumHash = 1, + GetCurrentQuorumsInfoResponse_ValidatorSetV0_FieldNumber_CoreHeight = 2, + GetCurrentQuorumsInfoResponse_ValidatorSetV0_FieldNumber_MembersArray = 3, + GetCurrentQuorumsInfoResponse_ValidatorSetV0_FieldNumber_ThresholdPublicKey = 4, +}; + +GPB_FINAL @interface GetCurrentQuorumsInfoResponse_ValidatorSetV0 : GPBMessage + +@property(nonatomic, readwrite, copy, null_resettable) NSData *quorumHash; + +@property(nonatomic, readwrite) uint32_t coreHeight; + +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *membersArray; +/** The number of items in @c membersArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger membersArray_Count; + +@property(nonatomic, readwrite, copy, null_resettable) NSData *thresholdPublicKey; + +@end + +#pragma mark - GetCurrentQuorumsInfoResponse_GetCurrentQuorumsInfoResponseV0 + +typedef GPB_ENUM(GetCurrentQuorumsInfoResponse_GetCurrentQuorumsInfoResponseV0_FieldNumber) { + GetCurrentQuorumsInfoResponse_GetCurrentQuorumsInfoResponseV0_FieldNumber_QuorumHashesArray = 1, + GetCurrentQuorumsInfoResponse_GetCurrentQuorumsInfoResponseV0_FieldNumber_CurrentQuorumHash = 2, + GetCurrentQuorumsInfoResponse_GetCurrentQuorumsInfoResponseV0_FieldNumber_ValidatorSetsArray = 3, + GetCurrentQuorumsInfoResponse_GetCurrentQuorumsInfoResponseV0_FieldNumber_LastBlockProposer = 4, + GetCurrentQuorumsInfoResponse_GetCurrentQuorumsInfoResponseV0_FieldNumber_Metadata = 5, +}; + +GPB_FINAL @interface GetCurrentQuorumsInfoResponse_GetCurrentQuorumsInfoResponseV0 : GPBMessage + +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *quorumHashesArray; +/** The number of items in @c quorumHashesArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger quorumHashesArray_Count; + +@property(nonatomic, readwrite, copy, null_resettable) NSData *currentQuorumHash; + +@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray *validatorSetsArray; +/** The number of items in @c validatorSetsArray without causing the array to be created. */ +@property(nonatomic, readonly) NSUInteger validatorSetsArray_Count; + +@property(nonatomic, readwrite, copy, null_resettable) NSData *lastBlockProposer; + +@property(nonatomic, readwrite, strong, null_resettable) ResponseMetadata *metadata; +/** Test to see if @c metadata has been set. */ +@property(nonatomic, readwrite) BOOL hasMetadata; + +@end + NS_ASSUME_NONNULL_END CF_EXTERN_C_END diff --git a/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbobjc.m b/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbobjc.m index 7d1ef92f7a..e0bff0f273 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 @@ -64,6 +64,12 @@ GPBObjCClassDeclaration(GetContestedResourcesResponse); GPBObjCClassDeclaration(GetContestedResourcesResponse_GetContestedResourcesResponseV0); GPBObjCClassDeclaration(GetContestedResourcesResponse_GetContestedResourcesResponseV0_ContestedResourceValues); +GPBObjCClassDeclaration(GetCurrentQuorumsInfoRequest); +GPBObjCClassDeclaration(GetCurrentQuorumsInfoRequest_GetCurrentQuorumsInfoRequestV0); +GPBObjCClassDeclaration(GetCurrentQuorumsInfoResponse); +GPBObjCClassDeclaration(GetCurrentQuorumsInfoResponse_GetCurrentQuorumsInfoResponseV0); +GPBObjCClassDeclaration(GetCurrentQuorumsInfoResponse_ValidatorSetV0); +GPBObjCClassDeclaration(GetCurrentQuorumsInfoResponse_ValidatorV0); GPBObjCClassDeclaration(GetDataContractHistoryRequest); GPBObjCClassDeclaration(GetDataContractHistoryRequest_GetDataContractHistoryRequestV0); GPBObjCClassDeclaration(GetDataContractHistoryResponse); @@ -101,7 +107,6 @@ GPBObjCClassDeclaration(GetEvonodesProposedEpochBlocksResponse_GetEvonodesProposedEpochBlocksResponseV0_EvonodesProposedBlocks); GPBObjCClassDeclaration(GetIdentitiesBalancesRequest); GPBObjCClassDeclaration(GetIdentitiesBalancesRequest_GetIdentitiesBalancesRequestV0); -GPBObjCClassDeclaration(GetIdentitiesBalancesRequest_GetIdentitiesBalancesRequestV0_GetIdentitiesBalancesByKnownIdentityIds); GPBObjCClassDeclaration(GetIdentitiesBalancesResponse); GPBObjCClassDeclaration(GetIdentitiesBalancesResponse_GetIdentitiesBalancesResponseV0); GPBObjCClassDeclaration(GetIdentitiesBalancesResponse_GetIdentitiesBalancesResponseV0_IdentitiesBalances); @@ -3065,7 +3070,7 @@ void GetEvonodesProposedEpochBlocksByIdsRequest_ClearVersionOneOfCase(GetEvonode @implementation GetEvonodesProposedEpochBlocksByIdsRequest_GetEvonodesProposedEpochBlocksByIdsRequestV0 -@dynamic epoch; +@dynamic hasEpoch, epoch; @dynamic idsArray, idsArray_Count; @dynamic prove; @@ -3087,7 +3092,7 @@ + (GPBDescriptor *)descriptor { .number = GetEvonodesProposedEpochBlocksByIdsRequest_GetEvonodesProposedEpochBlocksByIdsRequestV0_FieldNumber_Epoch, .hasIndex = 0, .offset = (uint32_t)offsetof(GetEvonodesProposedEpochBlocksByIdsRequest_GetEvonodesProposedEpochBlocksByIdsRequestV0__storage_, epoch), - .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .flags = GPBFieldOptional, .dataType = GPBDataTypeUInt32, }, { @@ -3430,7 +3435,7 @@ void GetEvonodesProposedEpochBlocksByRangeRequest_ClearVersionOneOfCase(GetEvono @implementation GetEvonodesProposedEpochBlocksByRangeRequest_GetEvonodesProposedEpochBlocksByRangeRequestV0 @dynamic startOneOfCase; -@dynamic epoch; +@dynamic hasEpoch, epoch; @dynamic hasLimit, limit; @dynamic startAfter; @dynamic startAt; @@ -3456,7 +3461,7 @@ + (GPBDescriptor *)descriptor { .number = GetEvonodesProposedEpochBlocksByRangeRequest_GetEvonodesProposedEpochBlocksByRangeRequestV0_FieldNumber_Epoch, .hasIndex = 0, .offset = (uint32_t)offsetof(GetEvonodesProposedEpochBlocksByRangeRequest_GetEvonodesProposedEpochBlocksByRangeRequestV0__storage_, epoch), - .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .flags = GPBFieldOptional, .dataType = GPBDataTypeUInt32, }, { @@ -3587,12 +3592,12 @@ void GetIdentitiesBalancesRequest_ClearVersionOneOfCase(GetIdentitiesBalancesReq @implementation GetIdentitiesBalancesRequest_GetIdentitiesBalancesRequestV0 -@dynamic hasIdentitiesIds, identitiesIds; +@dynamic idsArray, idsArray_Count; @dynamic prove; typedef struct GetIdentitiesBalancesRequest_GetIdentitiesBalancesRequestV0__storage_ { uint32_t _has_storage_[1]; - GetIdentitiesBalancesRequest_GetIdentitiesBalancesRequestV0_GetIdentitiesBalancesByKnownIdentityIds *identitiesIds; + NSMutableArray *idsArray; } GetIdentitiesBalancesRequest_GetIdentitiesBalancesRequestV0__storage_; // This method is threadsafe because it is initially called @@ -3602,20 +3607,20 @@ + (GPBDescriptor *)descriptor { if (!descriptor) { static GPBMessageFieldDescription fields[] = { { - .name = "identitiesIds", - .dataTypeSpecific.clazz = GPBObjCClass(GetIdentitiesBalancesRequest_GetIdentitiesBalancesRequestV0_GetIdentitiesBalancesByKnownIdentityIds), - .number = GetIdentitiesBalancesRequest_GetIdentitiesBalancesRequestV0_FieldNumber_IdentitiesIds, - .hasIndex = 0, - .offset = (uint32_t)offsetof(GetIdentitiesBalancesRequest_GetIdentitiesBalancesRequestV0__storage_, identitiesIds), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeMessage, + .name = "idsArray", + .dataTypeSpecific.clazz = Nil, + .number = GetIdentitiesBalancesRequest_GetIdentitiesBalancesRequestV0_FieldNumber_IdsArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GetIdentitiesBalancesRequest_GetIdentitiesBalancesRequestV0__storage_, idsArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeBytes, }, { .name = "prove", .dataTypeSpecific.clazz = Nil, .number = GetIdentitiesBalancesRequest_GetIdentitiesBalancesRequestV0_FieldNumber_Prove, - .hasIndex = 1, - .offset = 2, // Stored in _has_storage_ to save space. + .hasIndex = 0, + .offset = 1, // Stored in _has_storage_ to save space. .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeBool, }, @@ -3639,52 +3644,6 @@ + (GPBDescriptor *)descriptor { @end -#pragma mark - GetIdentitiesBalancesRequest_GetIdentitiesBalancesRequestV0_GetIdentitiesBalancesByKnownIdentityIds - -@implementation GetIdentitiesBalancesRequest_GetIdentitiesBalancesRequestV0_GetIdentitiesBalancesByKnownIdentityIds - -@dynamic identitiesIdsArray, identitiesIdsArray_Count; - -typedef struct GetIdentitiesBalancesRequest_GetIdentitiesBalancesRequestV0_GetIdentitiesBalancesByKnownIdentityIds__storage_ { - uint32_t _has_storage_[1]; - NSMutableArray *identitiesIdsArray; -} GetIdentitiesBalancesRequest_GetIdentitiesBalancesRequestV0_GetIdentitiesBalancesByKnownIdentityIds__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 = "identitiesIdsArray", - .dataTypeSpecific.clazz = Nil, - .number = GetIdentitiesBalancesRequest_GetIdentitiesBalancesRequestV0_GetIdentitiesBalancesByKnownIdentityIds_FieldNumber_IdentitiesIdsArray, - .hasIndex = GPBNoHasBit, - .offset = (uint32_t)offsetof(GetIdentitiesBalancesRequest_GetIdentitiesBalancesRequestV0_GetIdentitiesBalancesByKnownIdentityIds__storage_, identitiesIdsArray), - .flags = GPBFieldRepeated, - .dataType = GPBDataTypeBytes, - }, - }; - GPBDescriptor *localDescriptor = - [GPBDescriptor allocDescriptorForClass:[GetIdentitiesBalancesRequest_GetIdentitiesBalancesRequestV0_GetIdentitiesBalancesByKnownIdentityIds class] - rootClass:[PlatformRoot class] - file:PlatformRoot_FileDescriptor() - fields:fields - fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) - storageSize:sizeof(GetIdentitiesBalancesRequest_GetIdentitiesBalancesRequestV0_GetIdentitiesBalancesByKnownIdentityIds__storage_) - flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; - [localDescriptor setupContainingMessageClass:GPBObjCClass(GetIdentitiesBalancesRequest_GetIdentitiesBalancesRequestV0)]; - #if defined(DEBUG) && DEBUG - NSAssert(descriptor == nil, @"Startup recursed!"); - #endif // DEBUG - descriptor = localDescriptor; - } - return descriptor; -} - -@end - #pragma mark - GetIdentitiesBalancesResponse @implementation GetIdentitiesBalancesResponse @@ -12484,6 +12443,389 @@ + (GPBDescriptor *)descriptor { @end +#pragma mark - GetCurrentQuorumsInfoRequest + +@implementation GetCurrentQuorumsInfoRequest + +@dynamic versionOneOfCase; +@dynamic v0; + +typedef struct GetCurrentQuorumsInfoRequest__storage_ { + uint32_t _has_storage_[2]; + GetCurrentQuorumsInfoRequest_GetCurrentQuorumsInfoRequestV0 *v0; +} GetCurrentQuorumsInfoRequest__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(GetCurrentQuorumsInfoRequest_GetCurrentQuorumsInfoRequestV0), + .number = GetCurrentQuorumsInfoRequest_FieldNumber_V0, + .hasIndex = -1, + .offset = (uint32_t)offsetof(GetCurrentQuorumsInfoRequest__storage_, v0), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GetCurrentQuorumsInfoRequest class] + rootClass:[PlatformRoot class] + file:PlatformRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GetCurrentQuorumsInfoRequest__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 GetCurrentQuorumsInfoRequest_ClearVersionOneOfCase(GetCurrentQuorumsInfoRequest *message) { + GPBDescriptor *descriptor = [GetCurrentQuorumsInfoRequest descriptor]; + GPBOneofDescriptor *oneof = [descriptor.oneofs objectAtIndex:0]; + GPBClearOneof(message, oneof); +} +#pragma mark - GetCurrentQuorumsInfoRequest_GetCurrentQuorumsInfoRequestV0 + +@implementation GetCurrentQuorumsInfoRequest_GetCurrentQuorumsInfoRequestV0 + + +typedef struct GetCurrentQuorumsInfoRequest_GetCurrentQuorumsInfoRequestV0__storage_ { + uint32_t _has_storage_[1]; +} GetCurrentQuorumsInfoRequest_GetCurrentQuorumsInfoRequestV0__storage_; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = nil; + if (!descriptor) { + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GetCurrentQuorumsInfoRequest_GetCurrentQuorumsInfoRequestV0 class] + rootClass:[PlatformRoot class] + file:PlatformRoot_FileDescriptor() + fields:NULL + fieldCount:0 + storageSize:sizeof(GetCurrentQuorumsInfoRequest_GetCurrentQuorumsInfoRequestV0__storage_) + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; + [localDescriptor setupContainingMessageClass:GPBObjCClass(GetCurrentQuorumsInfoRequest)]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GetCurrentQuorumsInfoResponse + +@implementation GetCurrentQuorumsInfoResponse + +@dynamic versionOneOfCase; +@dynamic v0; + +typedef struct GetCurrentQuorumsInfoResponse__storage_ { + uint32_t _has_storage_[2]; + GetCurrentQuorumsInfoResponse_GetCurrentQuorumsInfoResponseV0 *v0; +} GetCurrentQuorumsInfoResponse__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(GetCurrentQuorumsInfoResponse_GetCurrentQuorumsInfoResponseV0), + .number = GetCurrentQuorumsInfoResponse_FieldNumber_V0, + .hasIndex = -1, + .offset = (uint32_t)offsetof(GetCurrentQuorumsInfoResponse__storage_, v0), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GetCurrentQuorumsInfoResponse class] + rootClass:[PlatformRoot class] + file:PlatformRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GetCurrentQuorumsInfoResponse__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 GetCurrentQuorumsInfoResponse_ClearVersionOneOfCase(GetCurrentQuorumsInfoResponse *message) { + GPBDescriptor *descriptor = [GetCurrentQuorumsInfoResponse descriptor]; + GPBOneofDescriptor *oneof = [descriptor.oneofs objectAtIndex:0]; + GPBClearOneof(message, oneof); +} +#pragma mark - GetCurrentQuorumsInfoResponse_ValidatorV0 + +@implementation GetCurrentQuorumsInfoResponse_ValidatorV0 + +@dynamic proTxHash; +@dynamic nodeIp; +@dynamic isBanned; + +typedef struct GetCurrentQuorumsInfoResponse_ValidatorV0__storage_ { + uint32_t _has_storage_[1]; + NSData *proTxHash; + NSString *nodeIp; +} GetCurrentQuorumsInfoResponse_ValidatorV0__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 = "proTxHash", + .dataTypeSpecific.clazz = Nil, + .number = GetCurrentQuorumsInfoResponse_ValidatorV0_FieldNumber_ProTxHash, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GetCurrentQuorumsInfoResponse_ValidatorV0__storage_, proTxHash), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeBytes, + }, + { + .name = "nodeIp", + .dataTypeSpecific.clazz = Nil, + .number = GetCurrentQuorumsInfoResponse_ValidatorV0_FieldNumber_NodeIp, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GetCurrentQuorumsInfoResponse_ValidatorV0__storage_, nodeIp), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeString, + }, + { + .name = "isBanned", + .dataTypeSpecific.clazz = Nil, + .number = GetCurrentQuorumsInfoResponse_ValidatorV0_FieldNumber_IsBanned, + .hasIndex = 2, + .offset = 3, // Stored in _has_storage_ to save space. + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeBool, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GetCurrentQuorumsInfoResponse_ValidatorV0 class] + rootClass:[PlatformRoot class] + file:PlatformRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GetCurrentQuorumsInfoResponse_ValidatorV0__storage_) + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; + [localDescriptor setupContainingMessageClass:GPBObjCClass(GetCurrentQuorumsInfoResponse)]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GetCurrentQuorumsInfoResponse_ValidatorSetV0 + +@implementation GetCurrentQuorumsInfoResponse_ValidatorSetV0 + +@dynamic quorumHash; +@dynamic coreHeight; +@dynamic membersArray, membersArray_Count; +@dynamic thresholdPublicKey; + +typedef struct GetCurrentQuorumsInfoResponse_ValidatorSetV0__storage_ { + uint32_t _has_storage_[1]; + uint32_t coreHeight; + NSData *quorumHash; + NSMutableArray *membersArray; + NSData *thresholdPublicKey; +} GetCurrentQuorumsInfoResponse_ValidatorSetV0__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 = "quorumHash", + .dataTypeSpecific.clazz = Nil, + .number = GetCurrentQuorumsInfoResponse_ValidatorSetV0_FieldNumber_QuorumHash, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GetCurrentQuorumsInfoResponse_ValidatorSetV0__storage_, quorumHash), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeBytes, + }, + { + .name = "coreHeight", + .dataTypeSpecific.clazz = Nil, + .number = GetCurrentQuorumsInfoResponse_ValidatorSetV0_FieldNumber_CoreHeight, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GetCurrentQuorumsInfoResponse_ValidatorSetV0__storage_, coreHeight), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeUInt32, + }, + { + .name = "membersArray", + .dataTypeSpecific.clazz = GPBObjCClass(GetCurrentQuorumsInfoResponse_ValidatorV0), + .number = GetCurrentQuorumsInfoResponse_ValidatorSetV0_FieldNumber_MembersArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GetCurrentQuorumsInfoResponse_ValidatorSetV0__storage_, membersArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "thresholdPublicKey", + .dataTypeSpecific.clazz = Nil, + .number = GetCurrentQuorumsInfoResponse_ValidatorSetV0_FieldNumber_ThresholdPublicKey, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GetCurrentQuorumsInfoResponse_ValidatorSetV0__storage_, thresholdPublicKey), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeBytes, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GetCurrentQuorumsInfoResponse_ValidatorSetV0 class] + rootClass:[PlatformRoot class] + file:PlatformRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GetCurrentQuorumsInfoResponse_ValidatorSetV0__storage_) + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; + [localDescriptor setupContainingMessageClass:GPBObjCClass(GetCurrentQuorumsInfoResponse)]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + +#pragma mark - GetCurrentQuorumsInfoResponse_GetCurrentQuorumsInfoResponseV0 + +@implementation GetCurrentQuorumsInfoResponse_GetCurrentQuorumsInfoResponseV0 + +@dynamic quorumHashesArray, quorumHashesArray_Count; +@dynamic currentQuorumHash; +@dynamic validatorSetsArray, validatorSetsArray_Count; +@dynamic lastBlockProposer; +@dynamic hasMetadata, metadata; + +typedef struct GetCurrentQuorumsInfoResponse_GetCurrentQuorumsInfoResponseV0__storage_ { + uint32_t _has_storage_[1]; + NSMutableArray *quorumHashesArray; + NSData *currentQuorumHash; + NSMutableArray *validatorSetsArray; + NSData *lastBlockProposer; + ResponseMetadata *metadata; +} GetCurrentQuorumsInfoResponse_GetCurrentQuorumsInfoResponseV0__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 = "quorumHashesArray", + .dataTypeSpecific.clazz = Nil, + .number = GetCurrentQuorumsInfoResponse_GetCurrentQuorumsInfoResponseV0_FieldNumber_QuorumHashesArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GetCurrentQuorumsInfoResponse_GetCurrentQuorumsInfoResponseV0__storage_, quorumHashesArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeBytes, + }, + { + .name = "currentQuorumHash", + .dataTypeSpecific.clazz = Nil, + .number = GetCurrentQuorumsInfoResponse_GetCurrentQuorumsInfoResponseV0_FieldNumber_CurrentQuorumHash, + .hasIndex = 0, + .offset = (uint32_t)offsetof(GetCurrentQuorumsInfoResponse_GetCurrentQuorumsInfoResponseV0__storage_, currentQuorumHash), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeBytes, + }, + { + .name = "validatorSetsArray", + .dataTypeSpecific.clazz = GPBObjCClass(GetCurrentQuorumsInfoResponse_ValidatorSetV0), + .number = GetCurrentQuorumsInfoResponse_GetCurrentQuorumsInfoResponseV0_FieldNumber_ValidatorSetsArray, + .hasIndex = GPBNoHasBit, + .offset = (uint32_t)offsetof(GetCurrentQuorumsInfoResponse_GetCurrentQuorumsInfoResponseV0__storage_, validatorSetsArray), + .flags = GPBFieldRepeated, + .dataType = GPBDataTypeMessage, + }, + { + .name = "lastBlockProposer", + .dataTypeSpecific.clazz = Nil, + .number = GetCurrentQuorumsInfoResponse_GetCurrentQuorumsInfoResponseV0_FieldNumber_LastBlockProposer, + .hasIndex = 1, + .offset = (uint32_t)offsetof(GetCurrentQuorumsInfoResponse_GetCurrentQuorumsInfoResponseV0__storage_, lastBlockProposer), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeBytes, + }, + { + .name = "metadata", + .dataTypeSpecific.clazz = GPBObjCClass(ResponseMetadata), + .number = GetCurrentQuorumsInfoResponse_GetCurrentQuorumsInfoResponseV0_FieldNumber_Metadata, + .hasIndex = 2, + .offset = (uint32_t)offsetof(GetCurrentQuorumsInfoResponse_GetCurrentQuorumsInfoResponseV0__storage_, metadata), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeMessage, + }, + }; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GetCurrentQuorumsInfoResponse_GetCurrentQuorumsInfoResponseV0 class] + rootClass:[PlatformRoot class] + file:PlatformRoot_FileDescriptor() + fields:fields + fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) + storageSize:sizeof(GetCurrentQuorumsInfoResponse_GetCurrentQuorumsInfoResponseV0__storage_) + flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; + [localDescriptor setupContainingMessageClass:GPBObjCClass(GetCurrentQuorumsInfoResponse)]; + #if defined(DEBUG) && DEBUG + NSAssert(descriptor == nil, @"Startup recursed!"); + #endif // DEBUG + descriptor = localDescriptor; + } + return descriptor; +} + +@end + #pragma clang diagnostic pop 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 fb69ec2af8..9bfcd4ba16 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 @@ -26,6 +26,8 @@ @class GetContestedResourceVotersForIdentityResponse; @class GetContestedResourcesRequest; @class GetContestedResourcesResponse; +@class GetCurrentQuorumsInfoRequest; +@class GetCurrentQuorumsInfoResponse; @class GetDataContractHistoryRequest; @class GetDataContractHistoryResponse; @class GetDataContractRequest; @@ -244,6 +246,10 @@ NS_ASSUME_NONNULL_BEGIN - (GRPCUnaryProtoCall *)getStatusWithMessage:(GetStatusRequest *)message responseHandler:(id)handler callOptions:(GRPCCallOptions *_Nullable)callOptions; +#pragma mark getCurrentQuorumsInfo(GetCurrentQuorumsInfoRequest) returns (GetCurrentQuorumsInfoResponse) + +- (GRPCUnaryProtoCall *)getCurrentQuorumsInfoWithMessage:(GetCurrentQuorumsInfoRequest *)message responseHandler:(id)handler callOptions:(GRPCCallOptions *_Nullable)callOptions; + @end /** @@ -519,6 +525,13 @@ NS_ASSUME_NONNULL_BEGIN - (GRPCProtoCall *)RPCTogetStatusWithRequest:(GetStatusRequest *)request handler:(void(^)(GetStatusResponse *_Nullable response, NSError *_Nullable error))handler; +#pragma mark getCurrentQuorumsInfo(GetCurrentQuorumsInfoRequest) returns (GetCurrentQuorumsInfoResponse) + +- (void)getCurrentQuorumsInfoWithRequest:(GetCurrentQuorumsInfoRequest *)request handler:(void(^)(GetCurrentQuorumsInfoResponse *_Nullable response, NSError *_Nullable error))handler; + +- (GRPCProtoCall *)RPCTogetCurrentQuorumsInfoWithRequest:(GetCurrentQuorumsInfoRequest *)request handler:(void(^)(GetCurrentQuorumsInfoResponse *_Nullable response, NSError *_Nullable error))handler; + + @end 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 df7dcb06e0..b8e6852fe6 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 @@ -755,5 +755,25 @@ - (GRPCUnaryProtoCall *)getStatusWithMessage:(GetStatusRequest *)message respons responseClass:[GetStatusResponse class]]; } +#pragma mark getCurrentQuorumsInfo(GetCurrentQuorumsInfoRequest) returns (GetCurrentQuorumsInfoResponse) + +- (void)getCurrentQuorumsInfoWithRequest:(GetCurrentQuorumsInfoRequest *)request handler:(void(^)(GetCurrentQuorumsInfoResponse *_Nullable response, NSError *_Nullable error))handler{ + [[self RPCTogetCurrentQuorumsInfoWithRequest:request handler:handler] start]; +} +// Returns a not-yet-started RPC object. +- (GRPCProtoCall *)RPCTogetCurrentQuorumsInfoWithRequest:(GetCurrentQuorumsInfoRequest *)request handler:(void(^)(GetCurrentQuorumsInfoResponse *_Nullable response, NSError *_Nullable error))handler{ + return [self RPCToMethod:@"getCurrentQuorumsInfo" + requestsWriter:[GRXWriter writerWithValue:request] + responseClass:[GetCurrentQuorumsInfoResponse class] + responsesWriteable:[GRXWriteable writeableWithSingleHandler:handler]]; +} +- (GRPCUnaryProtoCall *)getCurrentQuorumsInfoWithMessage:(GetCurrentQuorumsInfoRequest *)message responseHandler:(id)handler callOptions:(GRPCCallOptions *_Nullable)callOptions { + return [self RPCToMethod:@"getCurrentQuorumsInfo" + message:message + responseHandler:handler + callOptions:callOptions + responseClass:[GetCurrentQuorumsInfoResponse class]]; +} + @end #endif 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 e28c4f3249..be8a64f309 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\"\x90\x01\n\x10ResponseMetadata\x12\x0e\n\x06height\x18\x01 \x01(\x04\x12 \n\x18\x63ore_chain_locked_height\x18\x02 \x01(\r\x12\r\n\x05\x65poch\x18\x03 \x01(\r\x12\x0f\n\x07time_ms\x18\x04 \x01(\x04\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\"\xb8\x02\n\x18GetIdentityNonceResponse\x12\\\n\x02v0\x18\x01 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetIdentityNonceResponse.GetIdentityNonceResponseV0H\x00\x1a\xb2\x01\n\x1aGetIdentityNonceResponseV0\x12\x18\n\x0eidentity_nonce\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\"\xe1\x02\n GetIdentityContractNonceResponse\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetIdentityContractNonceResponse.GetIdentityContractNonceResponseV0H\x00\x1a\xc3\x01\n\"GetIdentityContractNonceResponseV0\x12!\n\x17identity_contract_nonce\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\"\xb9\x02\n\x1aGetIdentityBalanceResponse\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetIdentityBalanceResponse.GetIdentityBalanceResponseV0H\x00\x1a\xad\x01\n\x1cGetIdentityBalanceResponseV0\x12\x11\n\x07\x62\x61lance\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\"\xa9\x04\n%GetIdentityBalanceAndRevisionResponse\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionResponse.GetIdentityBalanceAndRevisionResponseV0H\x00\x1a\xfc\x02\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\x37\n\x12\x42\x61lanceAndRevision\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\x12\x10\n\x08revision\x18\x02 \x01(\x04\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\"\x95\x02\n*GetEvonodesProposedEpochBlocksByIdsRequest\x12\x80\x01\n\x02v0\x18\x01 \x01(\x0b\x32r.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByIdsRequest.GetEvonodesProposedEpochBlocksByIdsRequestV0H\x00\x1aY\n,GetEvonodesProposedEpochBlocksByIdsRequestV0\x12\r\n\x05\x65poch\x18\x01 \x01(\r\x12\x0b\n\x03ids\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\x8e\x06\n&GetEvonodesProposedEpochBlocksResponse\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksResponse.GetEvonodesProposedEpochBlocksResponseV0H\x00\x1a\xde\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\r\n\x05\x63ount\x18\x02 \x01(\x04\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\"\xe3\x02\n,GetEvonodesProposedEpochBlocksByRangeRequest\x12\x84\x01\n\x02v0\x18\x01 \x01(\x0b\x32v.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByRangeRequest.GetEvonodesProposedEpochBlocksByRangeRequestV0H\x00\x1a\xa0\x01\n.GetEvonodesProposedEpochBlocksByRangeRequestV0\x12\r\n\x05\x65poch\x18\x01 \x01(\r\x12\x12\n\x05limit\x18\x02 \x01(\rH\x01\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_limitB\t\n\x07version\"\x9d\x03\n\x1cGetIdentitiesBalancesRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0H\x00\x1a\x8b\x02\n\x1eGetIdentitiesBalancesRequestV0\x12\x96\x01\n\x0eidentities_ids\x18\x01 \x01(\x0b\x32~.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds\x12\r\n\x05prove\x18\x02 \x01(\x08\x1a\x41\n\'GetIdentitiesBalancesByKnownIdentityIds\x12\x16\n\x0eidentities_ids\x18\x01 \x03(\x0c\x42\t\n\x07version\"\x9b\x05\n\x1dGetIdentitiesBalancesResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetIdentitiesBalancesResponse.GetIdentitiesBalancesResponseV0H\x00\x1a\x86\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\x1aH\n\x0fIdentityBalance\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\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\"\xcb\x0b\n\x10GetProofsRequest\x12L\n\x02v0\x18\x01 \x01(\x0b\x32>.org.dash.platform.dapi.v0.GetProofsRequest.GetProofsRequestV0H\x00\x1a\xdd\n\n\x12GetProofsRequestV0\x12\x62\n\nidentities\x18\x01 \x03(\x0b\x32N.org.dash.platform.dapi.v0.GetProofsRequest.GetProofsRequestV0.IdentityRequest\x12\x61\n\tcontracts\x18\x02 \x03(\x0b\x32N.org.dash.platform.dapi.v0.GetProofsRequest.GetProofsRequestV0.ContractRequest\x12\x61\n\tdocuments\x18\x03 \x03(\x0b\x32N.org.dash.platform.dapi.v0.GetProofsRequest.GetProofsRequestV0.DocumentRequest\x12_\n\x05votes\x18\x04 \x03(\x0b\x32P.org.dash.platform.dapi.v0.GetProofsRequest.GetProofsRequestV0.VoteStatusRequest\x1a\xd5\x02\n\x0f\x44ocumentRequest\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x15\n\rdocument_type\x18\x02 \x01(\t\x12#\n\x1b\x64ocument_type_keeps_history\x18\x03 \x01(\x08\x12\x13\n\x0b\x64ocument_id\x18\x04 \x01(\x0c\x12\x89\x01\n\x19\x64ocument_contested_status\x18\x05 \x01(\x0e\x32\x66.org.dash.platform.dapi.v0.GetProofsRequest.GetProofsRequestV0.DocumentRequest.DocumentContestedStatus\"P\n\x17\x44ocumentContestedStatus\x12\x11\n\rNOT_CONTESTED\x10\x00\x12\x13\n\x0fMAYBE_CONTESTED\x10\x01\x12\r\n\tCONTESTED\x10\x02\x1a\xd1\x01\n\x0fIdentityRequest\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12i\n\x0crequest_type\x18\x02 \x01(\x0e\x32S.org.dash.platform.dapi.v0.GetProofsRequest.GetProofsRequestV0.IdentityRequest.Type\">\n\x04Type\x12\x11\n\rFULL_IDENTITY\x10\x00\x12\x0b\n\x07\x42\x41LANCE\x10\x01\x12\x08\n\x04KEYS\x10\x02\x12\x0c\n\x08REVISION\x10\x03\x1a&\n\x0f\x43ontractRequest\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x1a\xe7\x02\n\x11VoteStatusRequest\x12\xa5\x01\n&contested_resource_vote_status_request\x18\x01 \x01(\x0b\x32s.org.dash.platform.dapi.v0.GetProofsRequest.GetProofsRequestV0.VoteStatusRequest.ContestedResourceVoteStatusRequestH\x00\x1a\x99\x01\n\"ContestedResourceVoteStatusRequest\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\x18\n\x10voter_identifier\x18\x05 \x01(\x0c\x42\x0e\n\x0crequest_typeB\t\n\x07version\"\x82\x02\n\x11GetProofsResponse\x12N\n\x02v0\x18\x01 \x01(\x0b\x32@.org.dash.platform.dapi.v0.GetProofsResponse.GetProofsResponseV0H\x00\x1a\x91\x01\n\x13GetProofsResponseV0\x12\x31\n\x05proof\x18\x01 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x02 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\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\"\xc1\x02\n\x1dGetDataContractHistoryRequest\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.GetDataContractHistoryRequestV0H\x00\x1a\xac\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\x13\n\x0bstart_at_ms\x18\x04 \x01(\x04\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\t\n\x07version\"\xae\x05\n\x1eGetDataContractHistoryResponse\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.GetDataContractHistoryResponseV0H\x00\x1a\x96\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\x37\n\x18\x44\x61taContractHistoryEntry\x12\x0c\n\x04\x64\x61te\x18\x01 \x01(\x04\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\"\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\"\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\"\x91\x05\n\x15GetEpochsInfoResponse\x12V\n\x02v0\x18\x01 \x01(\x0b\x32H.org.dash.platform.dapi.v0.GetEpochsInfoResponse.GetEpochsInfoResponseV0H\x00\x1a\x94\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\x9e\x01\n\tEpochInfo\x12\x0e\n\x06number\x18\x01 \x01(\r\x12\x1a\n\x12\x66irst_block_height\x18\x02 \x01(\x04\x12\x1f\n\x17\x66irst_core_block_height\x18\x03 \x01(\r\x12\x12\n\nstart_time\x18\x04 \x01(\x04\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\"\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\"\xca\x05\n\x1cGetVotePollsByEndDateRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetVotePollsByEndDateRequest.GetVotePollsByEndDateRequestV0H\x00\x1a\xb8\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\x1a\x45\n\x0fStartAtTimeInfo\x12\x15\n\rstart_time_ms\x18\x01 \x01(\x04\x12\x1b\n\x13start_time_included\x18\x02 \x01(\x08\x1a?\n\rEndAtTimeInfo\x12\x13\n\x0b\x65nd_time_ms\x18\x01 \x01(\x04\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\"\xff\x05\n\x1dGetVotePollsByEndDateResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetVotePollsByEndDateResponse.GetVotePollsByEndDateResponseV0H\x00\x1a\xea\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\x1aR\n\x1eSerializedVotePollsByTimestamp\x12\x11\n\ttimestamp\x18\x01 \x01(\x04\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\"\x8c\x0c\n%GetContestedResourceVoteStateResponse\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0H\x00\x1a\xdf\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\xd2\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\x12%\n\x1d\x66inished_at_core_block_height\x18\x04 \x01(\r\x12!\n\x19\x66inished_at_block_time_ms\x18\x05 \x01(\x04\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\"\xe9\x02\n&GetPrefundedSpecializedBalanceResponse\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetPrefundedSpecializedBalanceResponse.GetPrefundedSpecializedBalanceResponseV0H\x00\x1a\xb9\x01\n(GetPrefundedSpecializedBalanceResponseV0\x12\x11\n\x07\x62\x61lance\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\"\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\"\xd5\x02\n!GetTotalCreditsInPlatformResponse\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetTotalCreditsInPlatformResponse.GetTotalCreditsInPlatformResponseV0H\x00\x1a\xb4\x01\n#GetTotalCreditsInPlatformResponseV0\x12\x11\n\x07\x63redits\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\"\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\"\x9c\x10\n\x11GetStatusResponse\x12N\n\x02v0\x18\x01 \x01(\x0b\x32@.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0H\x00\x1a\xab\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\xee\x04\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\xb8\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\x1as\n\x04Time\x12\r\n\x05local\x18\x01 \x01(\x04\x12\x12\n\x05\x62lock\x18\x02 \x01(\x04H\x00\x88\x01\x01\x12\x14\n\x07genesis\x18\x03 \x01(\x04H\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\xa7\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\x1b\n\x13latest_block_height\x18\x04 \x01(\x04\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\x1d\n\x15\x65\x61rliest_block_height\x18\x07 \x01(\x04\x12\x1d\n\x15max_peer_block_height\x18\t \x01(\x04\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\xe9\x01\n\tStateSync\x12\x19\n\x11total_synced_time\x18\x01 \x01(\x04\x12\x16\n\x0eremaining_time\x18\x02 \x01(\x04\x12\x17\n\x0ftotal_snapshots\x18\x03 \x01(\r\x12\x1e\n\x16\x63hunk_process_avg_time\x18\x04 \x01(\x04\x12\x17\n\x0fsnapshot_height\x18\x05 \x01(\x04\x12\x1d\n\x15snapshot_chunks_count\x18\x06 \x01(\x04\x12\x19\n\x11\x62\x61\x63kfilled_blocks\x18\x07 \x01(\x04\x12\x1d\n\x15\x62\x61\x63kfill_blocks_total\x18\x08 \x01(\x04\x42\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\x97#\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\x12\x66\n\tgetProofs\x12+.org.dash.platform.dapi.v0.GetProofsRequest\x1a,.org.dash.platform.dapi.v0.GetProofsResponse\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\x99\x01\n\x1agetIdentityByPublicKeyHash\x12<.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashRequest\x1a=.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashResponse\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\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.GetStatusResponseb\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\"\x90\x01\n\x10ResponseMetadata\x12\x0e\n\x06height\x18\x01 \x01(\x04\x12 \n\x18\x63ore_chain_locked_height\x18\x02 \x01(\r\x12\r\n\x05\x65poch\x18\x03 \x01(\r\x12\x0f\n\x07time_ms\x18\x04 \x01(\x04\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\"\xb8\x02\n\x18GetIdentityNonceResponse\x12\\\n\x02v0\x18\x01 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetIdentityNonceResponse.GetIdentityNonceResponseV0H\x00\x1a\xb2\x01\n\x1aGetIdentityNonceResponseV0\x12\x18\n\x0eidentity_nonce\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\"\xe1\x02\n GetIdentityContractNonceResponse\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetIdentityContractNonceResponse.GetIdentityContractNonceResponseV0H\x00\x1a\xc3\x01\n\"GetIdentityContractNonceResponseV0\x12!\n\x17identity_contract_nonce\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\"\xb9\x02\n\x1aGetIdentityBalanceResponse\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetIdentityBalanceResponse.GetIdentityBalanceResponseV0H\x00\x1a\xad\x01\n\x1cGetIdentityBalanceResponseV0\x12\x11\n\x07\x62\x61lance\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\"\xa9\x04\n%GetIdentityBalanceAndRevisionResponse\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionResponse.GetIdentityBalanceAndRevisionResponseV0H\x00\x1a\xfc\x02\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\x37\n\x12\x42\x61lanceAndRevision\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\x12\x10\n\x08revision\x18\x02 \x01(\x04\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\"\x8e\x06\n&GetEvonodesProposedEpochBlocksResponse\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksResponse.GetEvonodesProposedEpochBlocksResponseV0H\x00\x1a\xde\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\r\n\x05\x63ount\x18\x02 \x01(\x04\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\"\x9b\x05\n\x1dGetIdentitiesBalancesResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetIdentitiesBalancesResponse.GetIdentitiesBalancesResponseV0H\x00\x1a\x86\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\x1aH\n\x0fIdentityBalance\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\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\"\xcb\x0b\n\x10GetProofsRequest\x12L\n\x02v0\x18\x01 \x01(\x0b\x32>.org.dash.platform.dapi.v0.GetProofsRequest.GetProofsRequestV0H\x00\x1a\xdd\n\n\x12GetProofsRequestV0\x12\x62\n\nidentities\x18\x01 \x03(\x0b\x32N.org.dash.platform.dapi.v0.GetProofsRequest.GetProofsRequestV0.IdentityRequest\x12\x61\n\tcontracts\x18\x02 \x03(\x0b\x32N.org.dash.platform.dapi.v0.GetProofsRequest.GetProofsRequestV0.ContractRequest\x12\x61\n\tdocuments\x18\x03 \x03(\x0b\x32N.org.dash.platform.dapi.v0.GetProofsRequest.GetProofsRequestV0.DocumentRequest\x12_\n\x05votes\x18\x04 \x03(\x0b\x32P.org.dash.platform.dapi.v0.GetProofsRequest.GetProofsRequestV0.VoteStatusRequest\x1a\xd5\x02\n\x0f\x44ocumentRequest\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x15\n\rdocument_type\x18\x02 \x01(\t\x12#\n\x1b\x64ocument_type_keeps_history\x18\x03 \x01(\x08\x12\x13\n\x0b\x64ocument_id\x18\x04 \x01(\x0c\x12\x89\x01\n\x19\x64ocument_contested_status\x18\x05 \x01(\x0e\x32\x66.org.dash.platform.dapi.v0.GetProofsRequest.GetProofsRequestV0.DocumentRequest.DocumentContestedStatus\"P\n\x17\x44ocumentContestedStatus\x12\x11\n\rNOT_CONTESTED\x10\x00\x12\x13\n\x0fMAYBE_CONTESTED\x10\x01\x12\r\n\tCONTESTED\x10\x02\x1a\xd1\x01\n\x0fIdentityRequest\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12i\n\x0crequest_type\x18\x02 \x01(\x0e\x32S.org.dash.platform.dapi.v0.GetProofsRequest.GetProofsRequestV0.IdentityRequest.Type\">\n\x04Type\x12\x11\n\rFULL_IDENTITY\x10\x00\x12\x0b\n\x07\x42\x41LANCE\x10\x01\x12\x08\n\x04KEYS\x10\x02\x12\x0c\n\x08REVISION\x10\x03\x1a&\n\x0f\x43ontractRequest\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x1a\xe7\x02\n\x11VoteStatusRequest\x12\xa5\x01\n&contested_resource_vote_status_request\x18\x01 \x01(\x0b\x32s.org.dash.platform.dapi.v0.GetProofsRequest.GetProofsRequestV0.VoteStatusRequest.ContestedResourceVoteStatusRequestH\x00\x1a\x99\x01\n\"ContestedResourceVoteStatusRequest\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\x18\n\x10voter_identifier\x18\x05 \x01(\x0c\x42\x0e\n\x0crequest_typeB\t\n\x07version\"\x82\x02\n\x11GetProofsResponse\x12N\n\x02v0\x18\x01 \x01(\x0b\x32@.org.dash.platform.dapi.v0.GetProofsResponse.GetProofsResponseV0H\x00\x1a\x91\x01\n\x13GetProofsResponseV0\x12\x31\n\x05proof\x18\x01 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x02 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\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\"\xc1\x02\n\x1dGetDataContractHistoryRequest\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.GetDataContractHistoryRequestV0H\x00\x1a\xac\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\x13\n\x0bstart_at_ms\x18\x04 \x01(\x04\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\t\n\x07version\"\xae\x05\n\x1eGetDataContractHistoryResponse\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.GetDataContractHistoryResponseV0H\x00\x1a\x96\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\x37\n\x18\x44\x61taContractHistoryEntry\x12\x0c\n\x04\x64\x61te\x18\x01 \x01(\x04\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\"\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\"\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\"\x91\x05\n\x15GetEpochsInfoResponse\x12V\n\x02v0\x18\x01 \x01(\x0b\x32H.org.dash.platform.dapi.v0.GetEpochsInfoResponse.GetEpochsInfoResponseV0H\x00\x1a\x94\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\x9e\x01\n\tEpochInfo\x12\x0e\n\x06number\x18\x01 \x01(\r\x12\x1a\n\x12\x66irst_block_height\x18\x02 \x01(\x04\x12\x1f\n\x17\x66irst_core_block_height\x18\x03 \x01(\r\x12\x12\n\nstart_time\x18\x04 \x01(\x04\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\"\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\"\xca\x05\n\x1cGetVotePollsByEndDateRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetVotePollsByEndDateRequest.GetVotePollsByEndDateRequestV0H\x00\x1a\xb8\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\x1a\x45\n\x0fStartAtTimeInfo\x12\x15\n\rstart_time_ms\x18\x01 \x01(\x04\x12\x1b\n\x13start_time_included\x18\x02 \x01(\x08\x1a?\n\rEndAtTimeInfo\x12\x13\n\x0b\x65nd_time_ms\x18\x01 \x01(\x04\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\"\xff\x05\n\x1dGetVotePollsByEndDateResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetVotePollsByEndDateResponse.GetVotePollsByEndDateResponseV0H\x00\x1a\xea\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\x1aR\n\x1eSerializedVotePollsByTimestamp\x12\x11\n\ttimestamp\x18\x01 \x01(\x04\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\"\x8c\x0c\n%GetContestedResourceVoteStateResponse\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0H\x00\x1a\xdf\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\xd2\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\x12%\n\x1d\x66inished_at_core_block_height\x18\x04 \x01(\r\x12!\n\x19\x66inished_at_block_time_ms\x18\x05 \x01(\x04\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\"\xe9\x02\n&GetPrefundedSpecializedBalanceResponse\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetPrefundedSpecializedBalanceResponse.GetPrefundedSpecializedBalanceResponseV0H\x00\x1a\xb9\x01\n(GetPrefundedSpecializedBalanceResponseV0\x12\x11\n\x07\x62\x61lance\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\"\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\"\xd5\x02\n!GetTotalCreditsInPlatformResponse\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetTotalCreditsInPlatformResponse.GetTotalCreditsInPlatformResponseV0H\x00\x1a\xb4\x01\n#GetTotalCreditsInPlatformResponseV0\x12\x11\n\x07\x63redits\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\"\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\"\x9c\x10\n\x11GetStatusResponse\x12N\n\x02v0\x18\x01 \x01(\x0b\x32@.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0H\x00\x1a\xab\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\xee\x04\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\xb8\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\x1as\n\x04Time\x12\r\n\x05local\x18\x01 \x01(\x04\x12\x12\n\x05\x62lock\x18\x02 \x01(\x04H\x00\x88\x01\x01\x12\x14\n\x07genesis\x18\x03 \x01(\x04H\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\xa7\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\x1b\n\x13latest_block_height\x18\x04 \x01(\x04\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\x1d\n\x15\x65\x61rliest_block_height\x18\x07 \x01(\x04\x12\x1d\n\x15max_peer_block_height\x18\t \x01(\x04\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\xe9\x01\n\tStateSync\x12\x19\n\x11total_synced_time\x18\x01 \x01(\x04\x12\x16\n\x0eremaining_time\x18\x02 \x01(\x04\x12\x17\n\x0ftotal_snapshots\x18\x03 \x01(\r\x12\x1e\n\x16\x63hunk_process_avg_time\x18\x04 \x01(\x04\x12\x17\n\x0fsnapshot_height\x18\x05 \x01(\x04\x12\x1d\n\x15snapshot_chunks_count\x18\x06 \x01(\x04\x12\x19\n\x11\x62\x61\x63kfilled_blocks\x18\x07 \x01(\x04\x12\x1d\n\x15\x62\x61\x63kfill_blocks_total\x18\x08 \x01(\x04\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*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\xa4$\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\x12\x66\n\tgetProofs\x12+.org.dash.platform.dapi.v0.GetProofsRequest\x1a,.org.dash.platform.dapi.v0.GetProofsResponse\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\x99\x01\n\x1agetIdentityByPublicKeyHash\x12<.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashRequest\x1a=.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashResponse\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\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.GetCurrentQuorumsInfoResponseb\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=30834, - serialized_end=30924, + serialized_start=31512, + serialized_end=31602, ) _sym_db.RegisterEnumDescriptor(_KEYPURPOSE) @@ -125,8 +125,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=9520, - serialized_end=9600, + serialized_start=9342, + serialized_end=9422, ) _sym_db.RegisterEnumDescriptor(_GETPROOFSREQUEST_GETPROOFSREQUESTV0_DOCUMENTREQUEST_DOCUMENTCONTESTEDSTATUS) @@ -160,8 +160,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=9750, - serialized_end=9812, + serialized_start=9572, + serialized_end=9634, ) _sym_db.RegisterEnumDescriptor(_GETPROOFSREQUEST_GETPROOFSREQUESTV0_IDENTITYREQUEST_TYPE) @@ -190,8 +190,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=21765, - serialized_end=21838, + serialized_start=21587, + serialized_end=21660, ) _sym_db.RegisterEnumDescriptor(_GETCONTESTEDRESOURCEVOTESTATEREQUEST_GETCONTESTEDRESOURCEVOTESTATEREQUESTV0_RESULTTYPE) @@ -220,8 +220,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=22752, - serialized_end=22831, + serialized_start=22574, + serialized_end=22653, ) _sym_db.RegisterEnumDescriptor(_GETCONTESTEDRESOURCEVOTESTATERESPONSE_GETCONTESTEDRESOURCEVOTESTATERESPONSEV0_FINISHEDVOTEINFO_FINISHEDVOTEOUTCOME) @@ -250,8 +250,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=26460, - serialized_end=26521, + serialized_start=26282, + serialized_end=26343, ) _sym_db.RegisterEnumDescriptor(_GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSE_GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSEV0_RESOURCEVOTECHOICE_VOTECHOICETYPE) @@ -2146,9 +2146,14 @@ syntax='proto3', extension_ranges=[], oneofs=[ + _descriptor.OneofDescriptor( + name='_epoch', full_name='org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByIdsRequest.GetEvonodesProposedEpochBlocksByIdsRequestV0._epoch', + index=0, containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[]), ], serialized_start=6410, - serialized_end=6499, + serialized_end=6514, ) _GETEVONODESPROPOSEDEPOCHBLOCKSBYIDSREQUEST = _descriptor.Descriptor( @@ -2184,7 +2189,7 @@ fields=[]), ], serialized_start=6233, - serialized_end=6510, + serialized_end=6525, ) @@ -2222,8 +2227,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7016, - serialized_end=7075, + serialized_start=7031, + serialized_end=7090, ) _GETEVONODESPROPOSEDEPOCHBLOCKSRESPONSE_GETEVONODESPROPOSEDEPOCHBLOCKSRESPONSEV0_EVONODESPROPOSEDBLOCKS = _descriptor.Descriptor( @@ -2253,8 +2258,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7078, - serialized_end=7274, + serialized_start=7093, + serialized_end=7289, ) _GETEVONODESPROPOSEDEPOCHBLOCKSRESPONSE_GETEVONODESPROPOSEDEPOCHBLOCKSRESPONSEV0 = _descriptor.Descriptor( @@ -2303,8 +2308,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=6678, - serialized_end=7284, + serialized_start=6693, + serialized_end=7299, ) _GETEVONODESPROPOSEDEPOCHBLOCKSRESPONSE = _descriptor.Descriptor( @@ -2339,8 +2344,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=6513, - serialized_end=7295, + serialized_start=6528, + serialized_end=7310, ) @@ -2404,13 +2409,18 @@ create_key=_descriptor._internal_create_key, fields=[]), _descriptor.OneofDescriptor( - name='_limit', full_name='org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByRangeRequest.GetEvonodesProposedEpochBlocksByRangeRequestV0._limit', + name='_epoch', full_name='org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByRangeRequest.GetEvonodesProposedEpochBlocksByRangeRequestV0._epoch', index=1, containing_type=None, create_key=_descriptor._internal_create_key, fields=[]), + _descriptor.OneofDescriptor( + name='_limit', full_name='org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByRangeRequest.GetEvonodesProposedEpochBlocksByRangeRequestV0._limit', + index=2, containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[]), ], - serialized_start=7482, - serialized_end=7642, + serialized_start=7497, + serialized_end=7672, ) _GETEVONODESPROPOSEDEPOCHBLOCKSBYRANGEREQUEST = _descriptor.Descriptor( @@ -2445,42 +2455,11 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=7298, - serialized_end=7653, + serialized_start=7313, + serialized_end=7683, ) -_GETIDENTITIESBALANCESREQUEST_GETIDENTITIESBALANCESREQUESTV0_GETIDENTITIESBALANCESBYKNOWNIDENTITYIDS = _descriptor.Descriptor( - name='GetIdentitiesBalancesByKnownIdentityIds', - full_name='org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='identities_ids', full_name='org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.identities_ids', index=0, - number=1, type=12, cpp_type=9, 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), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=7993, - serialized_end=8058, -) - _GETIDENTITIESBALANCESREQUEST_GETIDENTITIESBALANCESREQUESTV0 = _descriptor.Descriptor( name='GetIdentitiesBalancesRequestV0', full_name='org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0', @@ -2490,9 +2469,9 @@ create_key=_descriptor._internal_create_key, fields=[ _descriptor.FieldDescriptor( - name='identities_ids', full_name='org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.identities_ids', index=0, - number=1, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, + name='ids', full_name='org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.ids', index=0, + number=1, type=12, cpp_type=9, 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), @@ -2506,7 +2485,7 @@ ], extensions=[ ], - nested_types=[_GETIDENTITIESBALANCESREQUEST_GETIDENTITIESBALANCESREQUESTV0_GETIDENTITIESBALANCESBYKNOWNIDENTITYIDS, ], + nested_types=[], enum_types=[ ], serialized_options=None, @@ -2515,8 +2494,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7791, - serialized_end=8058, + serialized_start=7820, + serialized_end=7880, ) _GETIDENTITIESBALANCESREQUEST = _descriptor.Descriptor( @@ -2551,8 +2530,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=7656, - serialized_end=8069, + serialized_start=7686, + serialized_end=7891, ) @@ -2595,8 +2574,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=8500, - serialized_end=8572, + serialized_start=8322, + serialized_end=8394, ) _GETIDENTITIESBALANCESRESPONSE_GETIDENTITIESBALANCESRESPONSEV0_IDENTITIESBALANCES = _descriptor.Descriptor( @@ -2626,8 +2605,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8575, - serialized_end=8718, + serialized_start=8397, + serialized_end=8540, ) _GETIDENTITIESBALANCESRESPONSE_GETIDENTITIESBALANCESRESPONSEV0 = _descriptor.Descriptor( @@ -2676,8 +2655,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=8210, - serialized_end=8728, + serialized_start=8032, + serialized_end=8550, ) _GETIDENTITIESBALANCESRESPONSE = _descriptor.Descriptor( @@ -2712,8 +2691,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=8072, - serialized_end=8739, + serialized_start=7894, + serialized_end=8561, ) @@ -2773,8 +2752,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=9259, - serialized_end=9600, + serialized_start=9081, + serialized_end=9422, ) _GETPROOFSREQUEST_GETPROOFSREQUESTV0_IDENTITYREQUEST = _descriptor.Descriptor( @@ -2812,8 +2791,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=9603, - serialized_end=9812, + serialized_start=9425, + serialized_end=9634, ) _GETPROOFSREQUEST_GETPROOFSREQUESTV0_CONTRACTREQUEST = _descriptor.Descriptor( @@ -2843,8 +2822,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=9814, - serialized_end=9852, + serialized_start=9636, + serialized_end=9674, ) _GETPROOFSREQUEST_GETPROOFSREQUESTV0_VOTESTATUSREQUEST_CONTESTEDRESOURCEVOTESTATUSREQUEST = _descriptor.Descriptor( @@ -2902,8 +2881,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10045, - serialized_end=10198, + serialized_start=9867, + serialized_end=10020, ) _GETPROOFSREQUEST_GETPROOFSREQUESTV0_VOTESTATUSREQUEST = _descriptor.Descriptor( @@ -2938,8 +2917,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=9855, - serialized_end=10214, + serialized_start=9677, + serialized_end=10036, ) _GETPROOFSREQUEST_GETPROOFSREQUESTV0 = _descriptor.Descriptor( @@ -2990,8 +2969,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8841, - serialized_end=10214, + serialized_start=8663, + serialized_end=10036, ) _GETPROOFSREQUEST = _descriptor.Descriptor( @@ -3026,8 +3005,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=8742, - serialized_end=10225, + serialized_start=8564, + serialized_end=10047, ) @@ -3070,8 +3049,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=10330, - serialized_end=10475, + serialized_start=10152, + serialized_end=10297, ) _GETPROOFSRESPONSE = _descriptor.Descriptor( @@ -3106,8 +3085,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=10228, - serialized_end=10486, + serialized_start=10050, + serialized_end=10308, ) @@ -3145,8 +3124,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=10605, - serialized_end=10658, + serialized_start=10427, + serialized_end=10480, ) _GETDATACONTRACTREQUEST = _descriptor.Descriptor( @@ -3181,8 +3160,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=10489, - serialized_end=10669, + serialized_start=10311, + serialized_end=10491, ) @@ -3232,8 +3211,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=10792, - serialized_end=10968, + serialized_start=10614, + serialized_end=10790, ) _GETDATACONTRACTRESPONSE = _descriptor.Descriptor( @@ -3268,8 +3247,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=10672, - serialized_end=10979, + serialized_start=10494, + serialized_end=10801, ) @@ -3307,8 +3286,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=11101, - serialized_end=11156, + serialized_start=10923, + serialized_end=10978, ) _GETDATACONTRACTSREQUEST = _descriptor.Descriptor( @@ -3343,8 +3322,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=10982, - serialized_end=11167, + serialized_start=10804, + serialized_end=10989, ) @@ -3382,8 +3361,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=11292, - serialized_end=11383, + serialized_start=11114, + serialized_end=11205, ) _GETDATACONTRACTSRESPONSE_DATACONTRACTS = _descriptor.Descriptor( @@ -3413,8 +3392,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=11385, - serialized_end=11502, + serialized_start=11207, + serialized_end=11324, ) _GETDATACONTRACTSRESPONSE_GETDATACONTRACTSRESPONSEV0 = _descriptor.Descriptor( @@ -3463,8 +3442,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=11505, - serialized_end=11750, + serialized_start=11327, + serialized_end=11572, ) _GETDATACONTRACTSRESPONSE = _descriptor.Descriptor( @@ -3499,8 +3478,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=11170, - serialized_end=11761, + serialized_start=10992, + serialized_end=11583, ) @@ -3559,8 +3538,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=11902, - serialized_end=12074, + serialized_start=11724, + serialized_end=11896, ) _GETDATACONTRACTHISTORYREQUEST = _descriptor.Descriptor( @@ -3595,8 +3574,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=11764, - serialized_end=12085, + serialized_start=11586, + serialized_end=11907, ) @@ -3634,8 +3613,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12525, - serialized_end=12580, + serialized_start=12347, + serialized_end=12402, ) _GETDATACONTRACTHISTORYRESPONSE_GETDATACONTRACTHISTORYRESPONSEV0_DATACONTRACTHISTORY = _descriptor.Descriptor( @@ -3665,8 +3644,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=12583, - serialized_end=12753, + serialized_start=12405, + serialized_end=12575, ) _GETDATACONTRACTHISTORYRESPONSE_GETDATACONTRACTHISTORYRESPONSEV0 = _descriptor.Descriptor( @@ -3715,8 +3694,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=12229, - serialized_end=12763, + serialized_start=12051, + serialized_end=12585, ) _GETDATACONTRACTHISTORYRESPONSE = _descriptor.Descriptor( @@ -3751,8 +3730,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=12088, - serialized_end=12774, + serialized_start=11910, + serialized_end=12596, ) @@ -3837,8 +3816,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=12885, - serialized_end=13072, + serialized_start=12707, + serialized_end=12894, ) _GETDOCUMENTSREQUEST = _descriptor.Descriptor( @@ -3873,8 +3852,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=12777, - serialized_end=13083, + serialized_start=12599, + serialized_end=12905, ) @@ -3905,8 +3884,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13440, - serialized_end=13470, + serialized_start=13262, + serialized_end=13292, ) _GETDOCUMENTSRESPONSE_GETDOCUMENTSRESPONSEV0 = _descriptor.Descriptor( @@ -3955,8 +3934,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=13197, - serialized_end=13480, + serialized_start=13019, + serialized_end=13302, ) _GETDOCUMENTSRESPONSE = _descriptor.Descriptor( @@ -3991,8 +3970,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=13086, - serialized_end=13491, + serialized_start=12908, + serialized_end=13313, ) @@ -4030,8 +4009,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=13643, - serialized_end=13720, + serialized_start=13465, + serialized_end=13542, ) _GETIDENTITYBYPUBLICKEYHASHREQUEST = _descriptor.Descriptor( @@ -4066,8 +4045,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=13494, - serialized_end=13731, + serialized_start=13316, + serialized_end=13553, ) @@ -4117,8 +4096,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=13887, - serialized_end=14069, + serialized_start=13709, + serialized_end=13891, ) _GETIDENTITYBYPUBLICKEYHASHRESPONSE = _descriptor.Descriptor( @@ -4153,8 +4132,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=13734, - serialized_end=14080, + serialized_start=13556, + serialized_end=13902, ) @@ -4192,8 +4171,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14238, - serialized_end=14323, + serialized_start=14060, + serialized_end=14145, ) _WAITFORSTATETRANSITIONRESULTREQUEST = _descriptor.Descriptor( @@ -4228,8 +4207,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=14083, - serialized_end=14334, + serialized_start=13905, + serialized_end=14156, ) @@ -4279,8 +4258,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=14496, - serialized_end=14735, + serialized_start=14318, + serialized_end=14557, ) _WAITFORSTATETRANSITIONRESULTRESPONSE = _descriptor.Descriptor( @@ -4315,8 +4294,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=14337, - serialized_end=14746, + serialized_start=14159, + serialized_end=14568, ) @@ -4354,8 +4333,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14874, - serialized_end=14934, + serialized_start=14696, + serialized_end=14756, ) _GETCONSENSUSPARAMSREQUEST = _descriptor.Descriptor( @@ -4390,8 +4369,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=14749, - serialized_end=14945, + serialized_start=14571, + serialized_end=14767, ) @@ -4436,8 +4415,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=15076, - serialized_end=15156, + serialized_start=14898, + serialized_end=14978, ) _GETCONSENSUSPARAMSRESPONSE_CONSENSUSPARAMSEVIDENCE = _descriptor.Descriptor( @@ -4481,8 +4460,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=15158, - serialized_end=15256, + serialized_start=14980, + serialized_end=15078, ) _GETCONSENSUSPARAMSRESPONSE_GETCONSENSUSPARAMSRESPONSEV0 = _descriptor.Descriptor( @@ -4519,8 +4498,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=15259, - serialized_end=15477, + serialized_start=15081, + serialized_end=15299, ) _GETCONSENSUSPARAMSRESPONSE = _descriptor.Descriptor( @@ -4555,8 +4534,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=14948, - serialized_end=15488, + serialized_start=14770, + serialized_end=15310, ) @@ -4587,8 +4566,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=15652, - serialized_end=15708, + serialized_start=15474, + serialized_end=15530, ) _GETPROTOCOLVERSIONUPGRADESTATEREQUEST = _descriptor.Descriptor( @@ -4623,8 +4602,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=15491, - serialized_end=15719, + serialized_start=15313, + serialized_end=15541, ) @@ -4655,8 +4634,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=16184, - serialized_end=16334, + serialized_start=16006, + serialized_end=16156, ) _GETPROTOCOLVERSIONUPGRADESTATERESPONSE_GETPROTOCOLVERSIONUPGRADESTATERESPONSEV0_VERSIONENTRY = _descriptor.Descriptor( @@ -4693,8 +4672,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=16336, - serialized_end=16394, + serialized_start=16158, + serialized_end=16216, ) _GETPROTOCOLVERSIONUPGRADESTATERESPONSE_GETPROTOCOLVERSIONUPGRADESTATERESPONSEV0 = _descriptor.Descriptor( @@ -4743,8 +4722,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=15887, - serialized_end=16404, + serialized_start=15709, + serialized_end=16226, ) _GETPROTOCOLVERSIONUPGRADESTATERESPONSE = _descriptor.Descriptor( @@ -4779,8 +4758,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=15722, - serialized_end=16415, + serialized_start=15544, + serialized_end=16237, ) @@ -4825,8 +4804,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=16595, - serialized_end=16698, + serialized_start=16417, + serialized_end=16520, ) _GETPROTOCOLVERSIONUPGRADEVOTESTATUSREQUEST = _descriptor.Descriptor( @@ -4861,8 +4840,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=16418, - serialized_end=16709, + serialized_start=16240, + serialized_end=16531, ) @@ -4893,8 +4872,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=17212, - serialized_end=17387, + serialized_start=17034, + serialized_end=17209, ) _GETPROTOCOLVERSIONUPGRADEVOTESTATUSRESPONSE_GETPROTOCOLVERSIONUPGRADEVOTESTATUSRESPONSEV0_VERSIONSIGNAL = _descriptor.Descriptor( @@ -4931,8 +4910,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=17389, - serialized_end=17442, + serialized_start=17211, + serialized_end=17264, ) _GETPROTOCOLVERSIONUPGRADEVOTESTATUSRESPONSE_GETPROTOCOLVERSIONUPGRADEVOTESTATUSRESPONSEV0 = _descriptor.Descriptor( @@ -4981,8 +4960,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=16893, - serialized_end=17452, + serialized_start=16715, + serialized_end=17274, ) _GETPROTOCOLVERSIONUPGRADEVOTESTATUSRESPONSE = _descriptor.Descriptor( @@ -5017,8 +4996,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=16712, - serialized_end=17463, + serialized_start=16534, + serialized_end=17285, ) @@ -5070,8 +5049,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=17576, - serialized_end=17700, + serialized_start=17398, + serialized_end=17522, ) _GETEPOCHSINFOREQUEST = _descriptor.Descriptor( @@ -5106,8 +5085,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=17466, - serialized_end=17711, + serialized_start=17288, + serialized_end=17533, ) @@ -5138,8 +5117,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=18072, - serialized_end=18189, + serialized_start=17894, + serialized_end=18011, ) _GETEPOCHSINFORESPONSE_GETEPOCHSINFORESPONSEV0_EPOCHINFO = _descriptor.Descriptor( @@ -5204,8 +5183,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=18192, - serialized_end=18350, + serialized_start=18014, + serialized_end=18172, ) _GETEPOCHSINFORESPONSE_GETEPOCHSINFORESPONSEV0 = _descriptor.Descriptor( @@ -5254,8 +5233,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=17828, - serialized_end=18360, + serialized_start=17650, + serialized_end=18182, ) _GETEPOCHSINFORESPONSE = _descriptor.Descriptor( @@ -5290,8 +5269,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=17714, - serialized_end=18371, + serialized_start=17536, + serialized_end=18193, ) @@ -5329,8 +5308,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=18866, - serialized_end=18935, + serialized_start=18688, + serialized_end=18757, ) _GETCONTESTEDRESOURCESREQUEST_GETCONTESTEDRESOURCESREQUESTV0 = _descriptor.Descriptor( @@ -5426,8 +5405,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=18509, - serialized_end=18969, + serialized_start=18331, + serialized_end=18791, ) _GETCONTESTEDRESOURCESREQUEST = _descriptor.Descriptor( @@ -5462,8 +5441,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=18374, - serialized_end=18980, + serialized_start=18196, + serialized_end=18802, ) @@ -5494,8 +5473,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=19422, - serialized_end=19482, + serialized_start=19244, + serialized_end=19304, ) _GETCONTESTEDRESOURCESRESPONSE_GETCONTESTEDRESOURCESRESPONSEV0 = _descriptor.Descriptor( @@ -5544,8 +5523,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=19121, - serialized_end=19492, + serialized_start=18943, + serialized_end=19314, ) _GETCONTESTEDRESOURCESRESPONSE = _descriptor.Descriptor( @@ -5580,8 +5559,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=18983, - serialized_end=19503, + serialized_start=18805, + serialized_end=19325, ) @@ -5619,8 +5598,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=20016, - serialized_end=20085, + serialized_start=19838, + serialized_end=19907, ) _GETVOTEPOLLSBYENDDATEREQUEST_GETVOTEPOLLSBYENDDATEREQUESTV0_ENDATTIMEINFO = _descriptor.Descriptor( @@ -5657,8 +5636,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=20087, - serialized_end=20150, + serialized_start=19909, + serialized_end=19972, ) _GETVOTEPOLLSBYENDDATEREQUEST_GETVOTEPOLLSBYENDDATEREQUESTV0 = _descriptor.Descriptor( @@ -5743,8 +5722,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=19641, - serialized_end=20209, + serialized_start=19463, + serialized_end=20031, ) _GETVOTEPOLLSBYENDDATEREQUEST = _descriptor.Descriptor( @@ -5779,8 +5758,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=19506, - serialized_end=20220, + serialized_start=19328, + serialized_end=20042, ) @@ -5818,8 +5797,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=20669, - serialized_end=20751, + serialized_start=20491, + serialized_end=20573, ) _GETVOTEPOLLSBYENDDATERESPONSE_GETVOTEPOLLSBYENDDATERESPONSEV0_SERIALIZEDVOTEPOLLSBYTIMESTAMPS = _descriptor.Descriptor( @@ -5856,8 +5835,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=20754, - serialized_end=20969, + serialized_start=20576, + serialized_end=20791, ) _GETVOTEPOLLSBYENDDATERESPONSE_GETVOTEPOLLSBYENDDATERESPONSEV0 = _descriptor.Descriptor( @@ -5906,8 +5885,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=20361, - serialized_end=20979, + serialized_start=20183, + serialized_end=20801, ) _GETVOTEPOLLSBYENDDATERESPONSE = _descriptor.Descriptor( @@ -5942,8 +5921,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=20223, - serialized_end=20990, + serialized_start=20045, + serialized_end=20812, ) @@ -5981,8 +5960,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=21679, - serialized_end=21763, + serialized_start=21501, + serialized_end=21585, ) _GETCONTESTEDRESOURCEVOTESTATEREQUEST_GETCONTESTEDRESOURCEVOTESTATEREQUESTV0 = _descriptor.Descriptor( @@ -6079,8 +6058,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=21152, - serialized_end=21877, + serialized_start=20974, + serialized_end=21699, ) _GETCONTESTEDRESOURCEVOTESTATEREQUEST = _descriptor.Descriptor( @@ -6115,8 +6094,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=20993, - serialized_end=21888, + serialized_start=20815, + serialized_end=21710, ) @@ -6188,8 +6167,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=22388, - serialized_end=22854, + serialized_start=22210, + serialized_end=22676, ) _GETCONTESTEDRESOURCEVOTESTATERESPONSE_GETCONTESTEDRESOURCEVOTESTATERESPONSEV0_CONTESTEDRESOURCECONTENDERS = _descriptor.Descriptor( @@ -6255,8 +6234,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=22857, - serialized_end=23309, + serialized_start=22679, + serialized_end=23131, ) _GETCONTESTEDRESOURCEVOTESTATERESPONSE_GETCONTESTEDRESOURCEVOTESTATERESPONSEV0_CONTENDER = _descriptor.Descriptor( @@ -6310,8 +6289,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=23311, - serialized_end=23418, + serialized_start=23133, + serialized_end=23240, ) _GETCONTESTEDRESOURCEVOTESTATERESPONSE_GETCONTESTEDRESOURCEVOTESTATERESPONSEV0 = _descriptor.Descriptor( @@ -6360,8 +6339,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=22053, - serialized_end=23428, + serialized_start=21875, + serialized_end=23250, ) _GETCONTESTEDRESOURCEVOTESTATERESPONSE = _descriptor.Descriptor( @@ -6396,8 +6375,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=21891, - serialized_end=23439, + serialized_start=21713, + serialized_end=23261, ) @@ -6435,8 +6414,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=21679, - serialized_end=21763, + serialized_start=21501, + serialized_end=21585, ) _GETCONTESTEDRESOURCEVOTERSFORIDENTITYREQUEST_GETCONTESTEDRESOURCEVOTERSFORIDENTITYREQUESTV0 = _descriptor.Descriptor( @@ -6532,8 +6511,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=23626, - serialized_end=24156, + serialized_start=23448, + serialized_end=23978, ) _GETCONTESTEDRESOURCEVOTERSFORIDENTITYREQUEST = _descriptor.Descriptor( @@ -6568,8 +6547,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=23442, - serialized_end=24167, + serialized_start=23264, + serialized_end=23989, ) @@ -6607,8 +6586,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=24707, - serialized_end=24774, + serialized_start=24529, + serialized_end=24596, ) _GETCONTESTEDRESOURCEVOTERSFORIDENTITYRESPONSE_GETCONTESTEDRESOURCEVOTERSFORIDENTITYRESPONSEV0 = _descriptor.Descriptor( @@ -6657,8 +6636,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=24357, - serialized_end=24784, + serialized_start=24179, + serialized_end=24606, ) _GETCONTESTEDRESOURCEVOTERSFORIDENTITYRESPONSE = _descriptor.Descriptor( @@ -6693,8 +6672,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=24170, - serialized_end=24795, + serialized_start=23992, + serialized_end=24617, ) @@ -6732,8 +6711,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=25344, - serialized_end=25441, + serialized_start=25166, + serialized_end=25263, ) _GETCONTESTEDRESOURCEIDENTITYVOTESREQUEST_GETCONTESTEDRESOURCEIDENTITYVOTESREQUESTV0 = _descriptor.Descriptor( @@ -6803,8 +6782,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=24969, - serialized_end=25472, + serialized_start=24791, + serialized_end=25294, ) _GETCONTESTEDRESOURCEIDENTITYVOTESREQUEST = _descriptor.Descriptor( @@ -6839,8 +6818,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=24798, - serialized_end=25483, + serialized_start=24620, + serialized_end=25305, ) @@ -6878,8 +6857,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=25986, - serialized_end=26233, + serialized_start=25808, + serialized_end=26055, ) _GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSE_GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSEV0_RESOURCEVOTECHOICE = _descriptor.Descriptor( @@ -6922,8 +6901,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=26236, - serialized_end=26537, + serialized_start=26058, + serialized_end=26359, ) _GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSE_GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSEV0_CONTESTEDRESOURCEIDENTITYVOTE = _descriptor.Descriptor( @@ -6974,8 +6953,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=26540, - serialized_end=26817, + serialized_start=26362, + serialized_end=26639, ) _GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSE_GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSEV0 = _descriptor.Descriptor( @@ -7024,8 +7003,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=25660, - serialized_end=26827, + serialized_start=25482, + serialized_end=26649, ) _GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSE = _descriptor.Descriptor( @@ -7060,8 +7039,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=25486, - serialized_end=26838, + serialized_start=25308, + serialized_end=26660, ) @@ -7099,8 +7078,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=27002, - serialized_end=27070, + serialized_start=26824, + serialized_end=26892, ) _GETPREFUNDEDSPECIALIZEDBALANCEREQUEST = _descriptor.Descriptor( @@ -7135,8 +7114,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=26841, - serialized_end=27081, + serialized_start=26663, + serialized_end=26903, ) @@ -7186,8 +7165,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=27249, - serialized_end=27434, + serialized_start=27071, + serialized_end=27256, ) _GETPREFUNDEDSPECIALIZEDBALANCERESPONSE = _descriptor.Descriptor( @@ -7222,8 +7201,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=27084, - serialized_end=27445, + serialized_start=26906, + serialized_end=27267, ) @@ -7254,8 +7233,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=27594, - serialized_end=27645, + serialized_start=27416, + serialized_end=27467, ) _GETTOTALCREDITSINPLATFORMREQUEST = _descriptor.Descriptor( @@ -7290,8 +7269,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=27448, - serialized_end=27656, + serialized_start=27270, + serialized_end=27478, ) @@ -7341,8 +7320,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=27809, - serialized_end=27989, + serialized_start=27631, + serialized_end=27811, ) _GETTOTALCREDITSINPLATFORMRESPONSE = _descriptor.Descriptor( @@ -7377,8 +7356,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=27659, - serialized_end=28000, + serialized_start=27481, + serialized_end=27822, ) @@ -7423,8 +7402,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=28119, - serialized_end=28188, + serialized_start=27941, + serialized_end=28010, ) _GETPATHELEMENTSREQUEST = _descriptor.Descriptor( @@ -7459,8 +7438,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=28003, - serialized_end=28199, + serialized_start=27825, + serialized_end=28021, ) @@ -7491,8 +7470,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=28572, - serialized_end=28600, + serialized_start=28394, + serialized_end=28422, ) _GETPATHELEMENTSRESPONSE_GETPATHELEMENTSRESPONSEV0 = _descriptor.Descriptor( @@ -7541,8 +7520,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=28322, - serialized_end=28610, + serialized_start=28144, + serialized_end=28432, ) _GETPATHELEMENTSRESPONSE = _descriptor.Descriptor( @@ -7577,8 +7556,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=28202, - serialized_end=28621, + serialized_start=28024, + serialized_end=28443, ) @@ -7602,8 +7581,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=28722, - serialized_end=28742, + serialized_start=28544, + serialized_end=28564, ) _GETSTATUSREQUEST = _descriptor.Descriptor( @@ -7638,8 +7617,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=28624, - serialized_end=28753, + serialized_start=28446, + serialized_end=28575, ) @@ -7694,8 +7673,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=29630, - serialized_end=29724, + serialized_start=29452, + serialized_end=29546, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_VERSION_PROTOCOL_TENDERDASH = _descriptor.Descriptor( @@ -7732,8 +7711,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=29957, - serialized_end=29997, + serialized_start=29779, + serialized_end=29819, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_VERSION_PROTOCOL_DRIVE = _descriptor.Descriptor( @@ -7770,8 +7749,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=29999, - serialized_end=30039, + serialized_start=29821, + serialized_end=29861, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_VERSION_PROTOCOL = _descriptor.Descriptor( @@ -7808,8 +7787,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=29727, - serialized_end=30039, + serialized_start=29549, + serialized_end=29861, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_VERSION = _descriptor.Descriptor( @@ -7846,8 +7825,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=29417, - serialized_end=30039, + serialized_start=29239, + serialized_end=29861, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_TIME = _descriptor.Descriptor( @@ -7913,8 +7892,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=30041, - serialized_end=30156, + serialized_start=29863, + serialized_end=29978, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_NODE = _descriptor.Descriptor( @@ -7956,8 +7935,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=30158, - serialized_end=30218, + serialized_start=29980, + serialized_end=30040, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_CHAIN = _descriptor.Descriptor( @@ -8048,8 +8027,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=30221, - serialized_end=30516, + serialized_start=30043, + serialized_end=30338, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_NETWORK = _descriptor.Descriptor( @@ -8093,8 +8072,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=30518, - serialized_end=30585, + serialized_start=30340, + serialized_end=30407, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_STATESYNC = _descriptor.Descriptor( @@ -8173,8 +8152,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=30588, - serialized_end=30821, + serialized_start=30410, + serialized_end=30643, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0 = _descriptor.Descriptor( @@ -8239,8 +8218,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=28858, - serialized_end=30821, + serialized_start=28680, + serialized_end=30643, ) _GETSTATUSRESPONSE = _descriptor.Descriptor( @@ -8275,8 +8254,262 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=28756, - serialized_end=30832, + serialized_start=28578, + serialized_end=30654, +) + + +_GETCURRENTQUORUMSINFOREQUEST_GETCURRENTQUORUMSINFOREQUESTV0 = _descriptor.Descriptor( + name='GetCurrentQuorumsInfoRequestV0', + full_name='org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=30791, + serialized_end=30823, +) + +_GETCURRENTQUORUMSINFOREQUEST = _descriptor.Descriptor( + name='GetCurrentQuorumsInfoRequest', + full_name='org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest', + 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.GetCurrentQuorumsInfoRequest.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=[_GETCURRENTQUORUMSINFOREQUEST_GETCURRENTQUORUMSINFOREQUESTV0, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='version', full_name='org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.version', + index=0, containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[]), + ], + serialized_start=30657, + serialized_end=30834, +) + + +_GETCURRENTQUORUMSINFORESPONSE_VALIDATORV0 = _descriptor.Descriptor( + name='ValidatorV0', + full_name='org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='pro_tx_hash', full_name='org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.pro_tx_hash', 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='node_ip', full_name='org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.node_ip', 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='is_banned', full_name='org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.is_banned', index=2, + number=3, 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=30974, + serialized_end=31044, +) + +_GETCURRENTQUORUMSINFORESPONSE_VALIDATORSETV0 = _descriptor.Descriptor( + name='ValidatorSetV0', + full_name='org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='quorum_hash', full_name='org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.quorum_hash', 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='core_height', full_name='org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.core_height', index=1, + number=2, 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='members', full_name='org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.members', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='threshold_public_key', full_name='org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.threshold_public_key', index=3, + number=4, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=b"", + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=31047, + serialized_end=31222, +) + +_GETCURRENTQUORUMSINFORESPONSE_GETCURRENTQUORUMSINFORESPONSEV0 = _descriptor.Descriptor( + name='GetCurrentQuorumsInfoResponseV0', + full_name='org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='quorum_hashes', full_name='org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.quorum_hashes', index=0, + number=1, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='current_quorum_hash', full_name='org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.current_quorum_hash', 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='validator_sets', full_name='org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.validator_sets', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='last_block_proposer', full_name='org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.last_block_proposer', index=3, + number=4, 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='metadata', full_name='org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.metadata', index=4, + number=5, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=31225, + serialized_end=31499, +) + +_GETCURRENTQUORUMSINFORESPONSE = _descriptor.Descriptor( + name='GetCurrentQuorumsInfoResponse', + full_name='org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse', + 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.GetCurrentQuorumsInfoResponse.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=[_GETCURRENTQUORUMSINFORESPONSE_VALIDATORV0, _GETCURRENTQUORUMSINFORESPONSE_VALIDATORSETV0, _GETCURRENTQUORUMSINFORESPONSE_GETCURRENTQUORUMSINFORESPONSEV0, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='version', full_name='org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.version', + index=0, containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[]), + ], + serialized_start=30837, + serialized_end=31510, ) _GETIDENTITYREQUEST_GETIDENTITYREQUESTV0.containing_type = _GETIDENTITYREQUEST @@ -8443,6 +8676,9 @@ _GETIDENTITIESCONTRACTKEYSRESPONSE.fields_by_name['v0']) _GETIDENTITIESCONTRACTKEYSRESPONSE.fields_by_name['v0'].containing_oneof = _GETIDENTITIESCONTRACTKEYSRESPONSE.oneofs_by_name['version'] _GETEVONODESPROPOSEDEPOCHBLOCKSBYIDSREQUEST_GETEVONODESPROPOSEDEPOCHBLOCKSBYIDSREQUESTV0.containing_type = _GETEVONODESPROPOSEDEPOCHBLOCKSBYIDSREQUEST +_GETEVONODESPROPOSEDEPOCHBLOCKSBYIDSREQUEST_GETEVONODESPROPOSEDEPOCHBLOCKSBYIDSREQUESTV0.oneofs_by_name['_epoch'].fields.append( + _GETEVONODESPROPOSEDEPOCHBLOCKSBYIDSREQUEST_GETEVONODESPROPOSEDEPOCHBLOCKSBYIDSREQUESTV0.fields_by_name['epoch']) +_GETEVONODESPROPOSEDEPOCHBLOCKSBYIDSREQUEST_GETEVONODESPROPOSEDEPOCHBLOCKSBYIDSREQUESTV0.fields_by_name['epoch'].containing_oneof = _GETEVONODESPROPOSEDEPOCHBLOCKSBYIDSREQUEST_GETEVONODESPROPOSEDEPOCHBLOCKSBYIDSREQUESTV0.oneofs_by_name['_epoch'] _GETEVONODESPROPOSEDEPOCHBLOCKSBYIDSREQUEST.fields_by_name['v0'].message_type = _GETEVONODESPROPOSEDEPOCHBLOCKSBYIDSREQUEST_GETEVONODESPROPOSEDEPOCHBLOCKSBYIDSREQUESTV0 _GETEVONODESPROPOSEDEPOCHBLOCKSBYIDSREQUEST.oneofs_by_name['version'].fields.append( _GETEVONODESPROPOSEDEPOCHBLOCKSBYIDSREQUEST.fields_by_name['v0']) @@ -8471,6 +8707,9 @@ _GETEVONODESPROPOSEDEPOCHBLOCKSBYRANGEREQUEST_GETEVONODESPROPOSEDEPOCHBLOCKSBYRANGEREQUESTV0.oneofs_by_name['start'].fields.append( _GETEVONODESPROPOSEDEPOCHBLOCKSBYRANGEREQUEST_GETEVONODESPROPOSEDEPOCHBLOCKSBYRANGEREQUESTV0.fields_by_name['start_at']) _GETEVONODESPROPOSEDEPOCHBLOCKSBYRANGEREQUEST_GETEVONODESPROPOSEDEPOCHBLOCKSBYRANGEREQUESTV0.fields_by_name['start_at'].containing_oneof = _GETEVONODESPROPOSEDEPOCHBLOCKSBYRANGEREQUEST_GETEVONODESPROPOSEDEPOCHBLOCKSBYRANGEREQUESTV0.oneofs_by_name['start'] +_GETEVONODESPROPOSEDEPOCHBLOCKSBYRANGEREQUEST_GETEVONODESPROPOSEDEPOCHBLOCKSBYRANGEREQUESTV0.oneofs_by_name['_epoch'].fields.append( + _GETEVONODESPROPOSEDEPOCHBLOCKSBYRANGEREQUEST_GETEVONODESPROPOSEDEPOCHBLOCKSBYRANGEREQUESTV0.fields_by_name['epoch']) +_GETEVONODESPROPOSEDEPOCHBLOCKSBYRANGEREQUEST_GETEVONODESPROPOSEDEPOCHBLOCKSBYRANGEREQUESTV0.fields_by_name['epoch'].containing_oneof = _GETEVONODESPROPOSEDEPOCHBLOCKSBYRANGEREQUEST_GETEVONODESPROPOSEDEPOCHBLOCKSBYRANGEREQUESTV0.oneofs_by_name['_epoch'] _GETEVONODESPROPOSEDEPOCHBLOCKSBYRANGEREQUEST_GETEVONODESPROPOSEDEPOCHBLOCKSBYRANGEREQUESTV0.oneofs_by_name['_limit'].fields.append( _GETEVONODESPROPOSEDEPOCHBLOCKSBYRANGEREQUEST_GETEVONODESPROPOSEDEPOCHBLOCKSBYRANGEREQUESTV0.fields_by_name['limit']) _GETEVONODESPROPOSEDEPOCHBLOCKSBYRANGEREQUEST_GETEVONODESPROPOSEDEPOCHBLOCKSBYRANGEREQUESTV0.fields_by_name['limit'].containing_oneof = _GETEVONODESPROPOSEDEPOCHBLOCKSBYRANGEREQUEST_GETEVONODESPROPOSEDEPOCHBLOCKSBYRANGEREQUESTV0.oneofs_by_name['_limit'] @@ -8478,8 +8717,6 @@ _GETEVONODESPROPOSEDEPOCHBLOCKSBYRANGEREQUEST.oneofs_by_name['version'].fields.append( _GETEVONODESPROPOSEDEPOCHBLOCKSBYRANGEREQUEST.fields_by_name['v0']) _GETEVONODESPROPOSEDEPOCHBLOCKSBYRANGEREQUEST.fields_by_name['v0'].containing_oneof = _GETEVONODESPROPOSEDEPOCHBLOCKSBYRANGEREQUEST.oneofs_by_name['version'] -_GETIDENTITIESBALANCESREQUEST_GETIDENTITIESBALANCESREQUESTV0_GETIDENTITIESBALANCESBYKNOWNIDENTITYIDS.containing_type = _GETIDENTITIESBALANCESREQUEST_GETIDENTITIESBALANCESREQUESTV0 -_GETIDENTITIESBALANCESREQUEST_GETIDENTITIESBALANCESREQUESTV0.fields_by_name['identities_ids'].message_type = _GETIDENTITIESBALANCESREQUEST_GETIDENTITIESBALANCESREQUESTV0_GETIDENTITIESBALANCESBYKNOWNIDENTITYIDS _GETIDENTITIESBALANCESREQUEST_GETIDENTITIESBALANCESREQUESTV0.containing_type = _GETIDENTITIESBALANCESREQUEST _GETIDENTITIESBALANCESREQUEST.fields_by_name['v0'].message_type = _GETIDENTITIESBALANCESREQUEST_GETIDENTITIESBALANCESREQUESTV0 _GETIDENTITIESBALANCESREQUEST.oneofs_by_name['version'].fields.append( @@ -9037,6 +9274,21 @@ _GETSTATUSRESPONSE.oneofs_by_name['version'].fields.append( _GETSTATUSRESPONSE.fields_by_name['v0']) _GETSTATUSRESPONSE.fields_by_name['v0'].containing_oneof = _GETSTATUSRESPONSE.oneofs_by_name['version'] +_GETCURRENTQUORUMSINFOREQUEST_GETCURRENTQUORUMSINFOREQUESTV0.containing_type = _GETCURRENTQUORUMSINFOREQUEST +_GETCURRENTQUORUMSINFOREQUEST.fields_by_name['v0'].message_type = _GETCURRENTQUORUMSINFOREQUEST_GETCURRENTQUORUMSINFOREQUESTV0 +_GETCURRENTQUORUMSINFOREQUEST.oneofs_by_name['version'].fields.append( + _GETCURRENTQUORUMSINFOREQUEST.fields_by_name['v0']) +_GETCURRENTQUORUMSINFOREQUEST.fields_by_name['v0'].containing_oneof = _GETCURRENTQUORUMSINFOREQUEST.oneofs_by_name['version'] +_GETCURRENTQUORUMSINFORESPONSE_VALIDATORV0.containing_type = _GETCURRENTQUORUMSINFORESPONSE +_GETCURRENTQUORUMSINFORESPONSE_VALIDATORSETV0.fields_by_name['members'].message_type = _GETCURRENTQUORUMSINFORESPONSE_VALIDATORV0 +_GETCURRENTQUORUMSINFORESPONSE_VALIDATORSETV0.containing_type = _GETCURRENTQUORUMSINFORESPONSE +_GETCURRENTQUORUMSINFORESPONSE_GETCURRENTQUORUMSINFORESPONSEV0.fields_by_name['validator_sets'].message_type = _GETCURRENTQUORUMSINFORESPONSE_VALIDATORSETV0 +_GETCURRENTQUORUMSINFORESPONSE_GETCURRENTQUORUMSINFORESPONSEV0.fields_by_name['metadata'].message_type = _RESPONSEMETADATA +_GETCURRENTQUORUMSINFORESPONSE_GETCURRENTQUORUMSINFORESPONSEV0.containing_type = _GETCURRENTQUORUMSINFORESPONSE +_GETCURRENTQUORUMSINFORESPONSE.fields_by_name['v0'].message_type = _GETCURRENTQUORUMSINFORESPONSE_GETCURRENTQUORUMSINFORESPONSEV0 +_GETCURRENTQUORUMSINFORESPONSE.oneofs_by_name['version'].fields.append( + _GETCURRENTQUORUMSINFORESPONSE.fields_by_name['v0']) +_GETCURRENTQUORUMSINFORESPONSE.fields_by_name['v0'].containing_oneof = _GETCURRENTQUORUMSINFORESPONSE.oneofs_by_name['version'] DESCRIPTOR.message_types_by_name['Proof'] = _PROOF DESCRIPTOR.message_types_by_name['ResponseMetadata'] = _RESPONSEMETADATA DESCRIPTOR.message_types_by_name['StateTransitionBroadcastError'] = _STATETRANSITIONBROADCASTERROR @@ -9106,6 +9358,8 @@ DESCRIPTOR.message_types_by_name['GetPathElementsResponse'] = _GETPATHELEMENTSRESPONSE DESCRIPTOR.message_types_by_name['GetStatusRequest'] = _GETSTATUSREQUEST DESCRIPTOR.message_types_by_name['GetStatusResponse'] = _GETSTATUSRESPONSE +DESCRIPTOR.message_types_by_name['GetCurrentQuorumsInfoRequest'] = _GETCURRENTQUORUMSINFOREQUEST +DESCRIPTOR.message_types_by_name['GetCurrentQuorumsInfoResponse'] = _GETCURRENTQUORUMSINFORESPONSE DESCRIPTOR.enum_types_by_name['KeyPurpose'] = _KEYPURPOSE _sym_db.RegisterFileDescriptor(DESCRIPTOR) @@ -9509,13 +9763,6 @@ GetIdentitiesBalancesRequest = _reflection.GeneratedProtocolMessageType('GetIdentitiesBalancesRequest', (_message.Message,), { 'GetIdentitiesBalancesRequestV0' : _reflection.GeneratedProtocolMessageType('GetIdentitiesBalancesRequestV0', (_message.Message,), { - - 'GetIdentitiesBalancesByKnownIdentityIds' : _reflection.GeneratedProtocolMessageType('GetIdentitiesBalancesByKnownIdentityIds', (_message.Message,), { - 'DESCRIPTOR' : _GETIDENTITIESBALANCESREQUEST_GETIDENTITIESBALANCESREQUESTV0_GETIDENTITIESBALANCESBYKNOWNIDENTITYIDS, - '__module__' : 'platform_pb2' - # @@protoc_insertion_point(class_scope:org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds) - }) - , 'DESCRIPTOR' : _GETIDENTITIESBALANCESREQUEST_GETIDENTITIESBALANCESREQUESTV0, '__module__' : 'platform_pb2' # @@protoc_insertion_point(class_scope:org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0) @@ -9527,7 +9774,6 @@ }) _sym_db.RegisterMessage(GetIdentitiesBalancesRequest) _sym_db.RegisterMessage(GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0) -_sym_db.RegisterMessage(GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds) GetIdentitiesBalancesResponse = _reflection.GeneratedProtocolMessageType('GetIdentitiesBalancesResponse', (_message.Message,), { @@ -10520,6 +10766,52 @@ _sym_db.RegisterMessage(GetStatusResponse.GetStatusResponseV0.Network) _sym_db.RegisterMessage(GetStatusResponse.GetStatusResponseV0.StateSync) +GetCurrentQuorumsInfoRequest = _reflection.GeneratedProtocolMessageType('GetCurrentQuorumsInfoRequest', (_message.Message,), { + + 'GetCurrentQuorumsInfoRequestV0' : _reflection.GeneratedProtocolMessageType('GetCurrentQuorumsInfoRequestV0', (_message.Message,), { + 'DESCRIPTOR' : _GETCURRENTQUORUMSINFOREQUEST_GETCURRENTQUORUMSINFOREQUESTV0, + '__module__' : 'platform_pb2' + # @@protoc_insertion_point(class_scope:org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0) + }) + , + 'DESCRIPTOR' : _GETCURRENTQUORUMSINFOREQUEST, + '__module__' : 'platform_pb2' + # @@protoc_insertion_point(class_scope:org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest) + }) +_sym_db.RegisterMessage(GetCurrentQuorumsInfoRequest) +_sym_db.RegisterMessage(GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0) + +GetCurrentQuorumsInfoResponse = _reflection.GeneratedProtocolMessageType('GetCurrentQuorumsInfoResponse', (_message.Message,), { + + 'ValidatorV0' : _reflection.GeneratedProtocolMessageType('ValidatorV0', (_message.Message,), { + 'DESCRIPTOR' : _GETCURRENTQUORUMSINFORESPONSE_VALIDATORV0, + '__module__' : 'platform_pb2' + # @@protoc_insertion_point(class_scope:org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0) + }) + , + + 'ValidatorSetV0' : _reflection.GeneratedProtocolMessageType('ValidatorSetV0', (_message.Message,), { + 'DESCRIPTOR' : _GETCURRENTQUORUMSINFORESPONSE_VALIDATORSETV0, + '__module__' : 'platform_pb2' + # @@protoc_insertion_point(class_scope:org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0) + }) + , + + 'GetCurrentQuorumsInfoResponseV0' : _reflection.GeneratedProtocolMessageType('GetCurrentQuorumsInfoResponseV0', (_message.Message,), { + 'DESCRIPTOR' : _GETCURRENTQUORUMSINFORESPONSE_GETCURRENTQUORUMSINFORESPONSEV0, + '__module__' : 'platform_pb2' + # @@protoc_insertion_point(class_scope:org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0) + }) + , + 'DESCRIPTOR' : _GETCURRENTQUORUMSINFORESPONSE, + '__module__' : 'platform_pb2' + # @@protoc_insertion_point(class_scope:org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse) + }) +_sym_db.RegisterMessage(GetCurrentQuorumsInfoResponse) +_sym_db.RegisterMessage(GetCurrentQuorumsInfoResponse.ValidatorV0) +_sym_db.RegisterMessage(GetCurrentQuorumsInfoResponse.ValidatorSetV0) +_sym_db.RegisterMessage(GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0) + _SEARCHKEY_PURPOSEMAPENTRY._options = None _SECURITYLEVELMAP_SECURITYLEVELMAPENTRY._options = None @@ -10531,8 +10823,8 @@ index=0, serialized_options=None, create_key=_descriptor._internal_create_key, - serialized_start=30927, - serialized_end=35430, + serialized_start=31605, + serialized_end=36249, methods=[ _descriptor.MethodDescriptor( name='broadcastStateTransition', @@ -10844,6 +11136,16 @@ serialized_options=None, create_key=_descriptor._internal_create_key, ), + _descriptor.MethodDescriptor( + name='getCurrentQuorumsInfo', + full_name='org.dash.platform.dapi.v0.Platform.getCurrentQuorumsInfo', + index=31, + containing_service=None, + input_type=_GETCURRENTQUORUMSINFOREQUEST, + output_type=_GETCURRENTQUORUMSINFORESPONSE, + serialized_options=None, + create_key=_descriptor._internal_create_key, + ), ]) _sym_db.RegisterServiceDescriptor(_PLATFORM) 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 4c1c93e835..b8c3847869 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 @@ -169,6 +169,11 @@ def __init__(self, channel): request_serializer=platform__pb2.GetStatusRequest.SerializeToString, response_deserializer=platform__pb2.GetStatusResponse.FromString, ) + self.getCurrentQuorumsInfo = channel.unary_unary( + '/org.dash.platform.dapi.v0.Platform/getCurrentQuorumsInfo', + request_serializer=platform__pb2.GetCurrentQuorumsInfoRequest.SerializeToString, + response_deserializer=platform__pb2.GetCurrentQuorumsInfoResponse.FromString, + ) class PlatformServicer(object): @@ -365,6 +370,12 @@ def getStatus(self, request, context): context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') + def getCurrentQuorumsInfo(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 add_PlatformServicer_to_server(servicer, server): rpc_method_handlers = { @@ -523,6 +534,11 @@ def add_PlatformServicer_to_server(servicer, server): request_deserializer=platform__pb2.GetStatusRequest.FromString, response_serializer=platform__pb2.GetStatusResponse.SerializeToString, ), + 'getCurrentQuorumsInfo': grpc.unary_unary_rpc_method_handler( + servicer.getCurrentQuorumsInfo, + request_deserializer=platform__pb2.GetCurrentQuorumsInfoRequest.FromString, + response_serializer=platform__pb2.GetCurrentQuorumsInfoResponse.SerializeToString, + ), } generic_handler = grpc.method_handlers_generic_handler( 'org.dash.platform.dapi.v0.Platform', rpc_method_handlers) @@ -1059,3 +1075,20 @@ def getStatus(request, platform__pb2.GetStatusResponse.FromString, options, channel_credentials, insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + + @staticmethod + def getCurrentQuorumsInfo(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/getCurrentQuorumsInfo', + platform__pb2.GetCurrentQuorumsInfoRequest.SerializeToString, + platform__pb2.GetCurrentQuorumsInfoResponse.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) 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 b017271418..e9028523b9 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 @@ -1343,6 +1343,8 @@ export namespace GetEvonodesProposedEpochBlocksByIdsRequest { } export class GetEvonodesProposedEpochBlocksByIdsRequestV0 extends jspb.Message { + hasEpoch(): boolean; + clearEpoch(): void; getEpoch(): number; setEpoch(value: number): void; @@ -1520,6 +1522,8 @@ export namespace GetEvonodesProposedEpochBlocksByRangeRequest { } export class GetEvonodesProposedEpochBlocksByRangeRequestV0 extends jspb.Message { + hasEpoch(): boolean; + clearEpoch(): void; getEpoch(): number; setEpoch(value: number): void; @@ -1601,10 +1605,12 @@ export namespace GetIdentitiesBalancesRequest { } export class GetIdentitiesBalancesRequestV0 extends jspb.Message { - hasIdentitiesIds(): boolean; - clearIdentitiesIds(): void; - getIdentitiesIds(): GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds | undefined; - setIdentitiesIds(value?: GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds): void; + clearIdsList(): void; + getIdsList(): Array; + getIdsList_asU8(): Array; + getIdsList_asB64(): Array; + setIdsList(value: Array): void; + addIds(value: Uint8Array | string, index?: number): Uint8Array | string; getProve(): boolean; setProve(value: boolean): void; @@ -1621,33 +1627,9 @@ export namespace GetIdentitiesBalancesRequest { export namespace GetIdentitiesBalancesRequestV0 { export type AsObject = { - identitiesIds?: GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.AsObject, + idsList: Array, prove: boolean, } - - export class GetIdentitiesBalancesByKnownIdentityIds extends jspb.Message { - clearIdentitiesIdsList(): void; - getIdentitiesIdsList(): Array; - getIdentitiesIdsList_asU8(): Array; - getIdentitiesIdsList_asB64(): Array; - setIdentitiesIdsList(value: Array): void; - addIdentitiesIds(value: Uint8Array | string, index?: number): Uint8Array | string; - - serializeBinary(): Uint8Array; - toObject(includeInstance?: boolean): GetIdentitiesBalancesByKnownIdentityIds.AsObject; - static toObject(includeInstance: boolean, msg: GetIdentitiesBalancesByKnownIdentityIds): GetIdentitiesBalancesByKnownIdentityIds.AsObject; - static extensions: {[key: number]: jspb.ExtensionFieldInfo}; - static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; - static serializeBinaryToWriter(message: GetIdentitiesBalancesByKnownIdentityIds, writer: jspb.BinaryWriter): void; - static deserializeBinary(bytes: Uint8Array): GetIdentitiesBalancesByKnownIdentityIds; - static deserializeBinaryFromReader(message: GetIdentitiesBalancesByKnownIdentityIds, reader: jspb.BinaryReader): GetIdentitiesBalancesByKnownIdentityIds; - } - - export namespace GetIdentitiesBalancesByKnownIdentityIds { - export type AsObject = { - identitiesIdsList: Array, - } - } } export enum VersionCase { @@ -5834,6 +5816,194 @@ export namespace GetStatusResponse { } } +export class GetCurrentQuorumsInfoRequest extends jspb.Message { + hasV0(): boolean; + clearV0(): void; + getV0(): GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0 | undefined; + setV0(value?: GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0): void; + + getVersionCase(): GetCurrentQuorumsInfoRequest.VersionCase; + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): GetCurrentQuorumsInfoRequest.AsObject; + static toObject(includeInstance: boolean, msg: GetCurrentQuorumsInfoRequest): GetCurrentQuorumsInfoRequest.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: GetCurrentQuorumsInfoRequest, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): GetCurrentQuorumsInfoRequest; + static deserializeBinaryFromReader(message: GetCurrentQuorumsInfoRequest, reader: jspb.BinaryReader): GetCurrentQuorumsInfoRequest; +} + +export namespace GetCurrentQuorumsInfoRequest { + export type AsObject = { + v0?: GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0.AsObject, + } + + export class GetCurrentQuorumsInfoRequestV0 extends jspb.Message { + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): GetCurrentQuorumsInfoRequestV0.AsObject; + static toObject(includeInstance: boolean, msg: GetCurrentQuorumsInfoRequestV0): GetCurrentQuorumsInfoRequestV0.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: GetCurrentQuorumsInfoRequestV0, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): GetCurrentQuorumsInfoRequestV0; + static deserializeBinaryFromReader(message: GetCurrentQuorumsInfoRequestV0, reader: jspb.BinaryReader): GetCurrentQuorumsInfoRequestV0; + } + + export namespace GetCurrentQuorumsInfoRequestV0 { + export type AsObject = { + } + } + + export enum VersionCase { + VERSION_NOT_SET = 0, + V0 = 1, + } +} + +export class GetCurrentQuorumsInfoResponse extends jspb.Message { + hasV0(): boolean; + clearV0(): void; + getV0(): GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0 | undefined; + setV0(value?: GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0): void; + + getVersionCase(): GetCurrentQuorumsInfoResponse.VersionCase; + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): GetCurrentQuorumsInfoResponse.AsObject; + static toObject(includeInstance: boolean, msg: GetCurrentQuorumsInfoResponse): GetCurrentQuorumsInfoResponse.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: GetCurrentQuorumsInfoResponse, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): GetCurrentQuorumsInfoResponse; + static deserializeBinaryFromReader(message: GetCurrentQuorumsInfoResponse, reader: jspb.BinaryReader): GetCurrentQuorumsInfoResponse; +} + +export namespace GetCurrentQuorumsInfoResponse { + export type AsObject = { + v0?: GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.AsObject, + } + + export class ValidatorV0 extends jspb.Message { + getProTxHash(): Uint8Array | string; + getProTxHash_asU8(): Uint8Array; + getProTxHash_asB64(): string; + setProTxHash(value: Uint8Array | string): void; + + getNodeIp(): string; + setNodeIp(value: string): void; + + getIsBanned(): boolean; + setIsBanned(value: boolean): void; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): ValidatorV0.AsObject; + static toObject(includeInstance: boolean, msg: ValidatorV0): ValidatorV0.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: ValidatorV0, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): ValidatorV0; + static deserializeBinaryFromReader(message: ValidatorV0, reader: jspb.BinaryReader): ValidatorV0; + } + + export namespace ValidatorV0 { + export type AsObject = { + proTxHash: Uint8Array | string, + nodeIp: string, + isBanned: boolean, + } + } + + export class ValidatorSetV0 extends jspb.Message { + getQuorumHash(): Uint8Array | string; + getQuorumHash_asU8(): Uint8Array; + getQuorumHash_asB64(): string; + setQuorumHash(value: Uint8Array | string): void; + + getCoreHeight(): number; + setCoreHeight(value: number): void; + + clearMembersList(): void; + getMembersList(): Array; + setMembersList(value: Array): void; + addMembers(value?: GetCurrentQuorumsInfoResponse.ValidatorV0, index?: number): GetCurrentQuorumsInfoResponse.ValidatorV0; + + getThresholdPublicKey(): Uint8Array | string; + getThresholdPublicKey_asU8(): Uint8Array; + getThresholdPublicKey_asB64(): string; + setThresholdPublicKey(value: Uint8Array | string): void; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): ValidatorSetV0.AsObject; + static toObject(includeInstance: boolean, msg: ValidatorSetV0): ValidatorSetV0.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: ValidatorSetV0, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): ValidatorSetV0; + static deserializeBinaryFromReader(message: ValidatorSetV0, reader: jspb.BinaryReader): ValidatorSetV0; + } + + export namespace ValidatorSetV0 { + export type AsObject = { + quorumHash: Uint8Array | string, + coreHeight: number, + membersList: Array, + thresholdPublicKey: Uint8Array | string, + } + } + + export class GetCurrentQuorumsInfoResponseV0 extends jspb.Message { + clearQuorumHashesList(): void; + getQuorumHashesList(): Array; + getQuorumHashesList_asU8(): Array; + getQuorumHashesList_asB64(): Array; + setQuorumHashesList(value: Array): void; + addQuorumHashes(value: Uint8Array | string, index?: number): Uint8Array | string; + + getCurrentQuorumHash(): Uint8Array | string; + getCurrentQuorumHash_asU8(): Uint8Array; + getCurrentQuorumHash_asB64(): string; + setCurrentQuorumHash(value: Uint8Array | string): void; + + clearValidatorSetsList(): void; + getValidatorSetsList(): Array; + setValidatorSetsList(value: Array): void; + addValidatorSets(value?: GetCurrentQuorumsInfoResponse.ValidatorSetV0, index?: number): GetCurrentQuorumsInfoResponse.ValidatorSetV0; + + getLastBlockProposer(): Uint8Array | string; + getLastBlockProposer_asU8(): Uint8Array; + getLastBlockProposer_asB64(): string; + setLastBlockProposer(value: Uint8Array | string): void; + + hasMetadata(): boolean; + clearMetadata(): void; + getMetadata(): ResponseMetadata | undefined; + setMetadata(value?: ResponseMetadata): void; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): GetCurrentQuorumsInfoResponseV0.AsObject; + static toObject(includeInstance: boolean, msg: GetCurrentQuorumsInfoResponseV0): GetCurrentQuorumsInfoResponseV0.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: GetCurrentQuorumsInfoResponseV0, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): GetCurrentQuorumsInfoResponseV0; + static deserializeBinaryFromReader(message: GetCurrentQuorumsInfoResponseV0, reader: jspb.BinaryReader): GetCurrentQuorumsInfoResponseV0; + } + + export namespace GetCurrentQuorumsInfoResponseV0 { + export type AsObject = { + quorumHashesList: Array, + currentQuorumHash: Uint8Array | string, + validatorSetsList: Array, + lastBlockProposer: Uint8Array | string, + metadata?: ResponseMetadata.AsObject, + } + } + + export enum VersionCase { + VERSION_NOT_SET = 0, + V0 = 1, + } +} + export interface KeyPurposeMap { AUTHENTICATION: 0; ENCRYPTION: 1; 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 746f5210fd..ca80ce2ad7 100644 --- a/packages/dapi-grpc/clients/platform/v0/web/platform_pb.js +++ b/packages/dapi-grpc/clients/platform/v0/web/platform_pb.js @@ -75,6 +75,14 @@ goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetContestedResourcesResponse goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetContestedResourcesResponse.GetContestedResourcesResponseV0.ContestedResourceValues', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetContestedResourcesResponse.GetContestedResourcesResponseV0.ResultCase', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetContestedResourcesResponse.VersionCase', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.VersionCase', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0', null, { proto }); +goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.VersionCase', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.GetDataContractHistoryRequestV0', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.VersionCase', null, { proto }); @@ -133,7 +141,6 @@ goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlock goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksResponse.VersionCase', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0', null, { proto }); -goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.VersionCase', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesResponse', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesResponse.GetIdentitiesBalancesResponseV0', null, { proto }); @@ -1404,7 +1411,7 @@ if (goog.DEBUG && !COMPILED) { * @constructor */ proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0 = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, null, null); + jspb.Message.initialize(this, opt_data, 0, -1, proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.repeatedFields_, null); }; goog.inherits(proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0, jspb.Message); if (goog.DEBUG && !COMPILED) { @@ -1414,27 +1421,6 @@ if (goog.DEBUG && !COMPILED) { */ proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.displayName = 'proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0'; } -/** - * 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.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.repeatedFields_, null); -}; -goog.inherits(proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.displayName = 'proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds'; -} /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a @@ -4144,6 +4130,132 @@ if (goog.DEBUG && !COMPILED) { */ proto.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.StateSync.displayName = 'proto.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.StateSync'; } +/** + * 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.GetCurrentQuorumsInfoRequest = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.oneofGroups_); +}; +goog.inherits(proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.displayName = 'proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest'; +} +/** + * 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.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0 = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0.displayName = 'proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0'; +} +/** + * 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.GetCurrentQuorumsInfoResponse = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.oneofGroups_); +}; +goog.inherits(proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.displayName = 'proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse'; +} +/** + * 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.GetCurrentQuorumsInfoResponse.ValidatorV0 = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.displayName = 'proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0'; +} +/** + * 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.GetCurrentQuorumsInfoResponse.ValidatorSetV0 = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.repeatedFields_, null); +}; +goog.inherits(proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.displayName = 'proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0'; +} +/** + * 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.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0 = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.repeatedFields_, null); +}; +goog.inherits(proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.displayName = 'proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0'; +} @@ -13367,8 +13479,8 @@ proto.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByIdsRequest.GetEv */ proto.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByIdsRequest.GetEvonodesProposedEpochBlocksByIdsRequestV0.serializeBinaryToWriter = function(message, writer) { var f = undefined; - f = message.getEpoch(); - if (f !== 0) { + f = /** @type {number} */ (jspb.Message.getField(message, 1)); + if (f != null) { writer.writeUint32( 1, f @@ -13405,7 +13517,25 @@ proto.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByIdsRequest.GetEv * @return {!proto.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByIdsRequest.GetEvonodesProposedEpochBlocksByIdsRequestV0} returns this */ proto.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByIdsRequest.GetEvonodesProposedEpochBlocksByIdsRequestV0.prototype.setEpoch = function(value) { - return jspb.Message.setProto3IntField(this, 1, value); + return jspb.Message.setField(this, 1, value); +}; + + +/** + * Clears the field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByIdsRequest.GetEvonodesProposedEpochBlocksByIdsRequestV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByIdsRequest.GetEvonodesProposedEpochBlocksByIdsRequestV0.prototype.clearEpoch = function() { + return jspb.Message.setField(this, 1, undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByIdsRequest.GetEvonodesProposedEpochBlocksByIdsRequestV0.prototype.hasEpoch = function() { + return jspb.Message.getField(this, 1) != null; }; @@ -14611,8 +14741,8 @@ proto.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByRangeRequest.Get */ proto.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByRangeRequest.GetEvonodesProposedEpochBlocksByRangeRequestV0.serializeBinaryToWriter = function(message, writer) { var f = undefined; - f = message.getEpoch(); - if (f !== 0) { + f = /** @type {number} */ (jspb.Message.getField(message, 1)); + if (f != null) { writer.writeUint32( 1, f @@ -14663,7 +14793,25 @@ proto.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByRangeRequest.Get * @return {!proto.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByRangeRequest.GetEvonodesProposedEpochBlocksByRangeRequestV0} returns this */ proto.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByRangeRequest.GetEvonodesProposedEpochBlocksByRangeRequestV0.prototype.setEpoch = function(value) { - return jspb.Message.setProto3IntField(this, 1, value); + return jspb.Message.setField(this, 1, value); +}; + + +/** + * Clears the field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByRangeRequest.GetEvonodesProposedEpochBlocksByRangeRequestV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByRangeRequest.GetEvonodesProposedEpochBlocksByRangeRequestV0.prototype.clearEpoch = function() { + return jspb.Message.setField(this, 1, undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByRangeRequest.GetEvonodesProposedEpochBlocksByRangeRequestV0.prototype.hasEpoch = function() { + return jspb.Message.getField(this, 1) != null; }; @@ -15018,6 +15166,13 @@ proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.serializeBinaryToWr +/** + * List of repeated fields within this message type. + * @private {!Array} + * @const + */ +proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.repeatedFields_ = [1]; + if (jspb.Message.GENERATE_TO_OBJECT) { @@ -15049,7 +15204,7 @@ proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalanc */ proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.toObject = function(includeInstance, msg) { var f, obj = { - identitiesIds: (f = msg.getIdentitiesIds()) && proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.toObject(includeInstance, f), + idsList: msg.getIdsList_asB64(), prove: jspb.Message.getBooleanFieldWithDefault(msg, 2, false) }; @@ -15088,9 +15243,8 @@ proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalanc var field = reader.getFieldNumber(); switch (field) { case 1: - var value = new proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds; - reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.deserializeBinaryFromReader); - msg.setIdentitiesIds(value); + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.addIds(value); break; case 2: var value = /** @type {boolean} */ (reader.readBool()); @@ -15125,12 +15279,11 @@ proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalanc */ proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.serializeBinaryToWriter = function(message, writer) { var f = undefined; - f = message.getIdentitiesIds(); - if (f != null) { - writer.writeMessage( + f = message.getIdsList_asU8(); + if (f.length > 0) { + writer.writeRepeatedBytes( 1, - f, - proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.serializeBinaryToWriter + f ); } f = message.getProve(); @@ -15143,163 +15296,44 @@ proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalanc }; - -/** - * List of repeated fields within this message type. - * @private {!Array} - * @const - */ -proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.repeatedFields_ = [1]; - - - -if (jspb.Message.GENERATE_TO_OBJECT) { -/** - * Creates an object representation of this proto. - * Field names that are reserved in JavaScript and will be renamed to pb_name. - * Optional fields that are not set will be set to undefined. - * To access a reserved field use, foo.pb_, eg, foo.pb_default. - * For the list of reserved names please see: - * net/proto2/compiler/js/internal/generator.cc#kKeyword. - * @param {boolean=} opt_includeInstance Deprecated. whether to include the - * JSPB instance for transitional soy proto support: - * http://goto/soy-param-migration - * @return {!Object} - */ -proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.prototype.toObject = function(opt_includeInstance) { - return proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.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.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.toObject = function(includeInstance, msg) { - var f, obj = { - identitiesIdsList: msg.getIdentitiesIdsList_asB64() - }; - - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; -}; -} - - -/** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds} - */ -proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds; - return proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.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.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds} - */ -proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.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.addIdentitiesIds(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.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.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.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getIdentitiesIdsList_asU8(); - if (f.length > 0) { - writer.writeRepeatedBytes( - 1, - f - ); - } -}; - - /** - * repeated bytes identities_ids = 1; + * repeated bytes ids = 1; * @return {!Array} */ -proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.prototype.getIdentitiesIdsList = function() { +proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.prototype.getIdsList = function() { return /** @type {!Array} */ (jspb.Message.getRepeatedField(this, 1)); }; /** - * repeated bytes identities_ids = 1; - * This is a type-conversion wrapper around `getIdentitiesIdsList()` + * repeated bytes ids = 1; + * This is a type-conversion wrapper around `getIdsList()` * @return {!Array} */ -proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.prototype.getIdentitiesIdsList_asB64 = function() { +proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.prototype.getIdsList_asB64 = function() { return /** @type {!Array} */ (jspb.Message.bytesListAsB64( - this.getIdentitiesIdsList())); + this.getIdsList())); }; /** - * repeated bytes identities_ids = 1; + * repeated bytes ids = 1; * Note that Uint8Array is not supported on all browsers. * @see http://caniuse.com/Uint8Array - * This is a type-conversion wrapper around `getIdentitiesIdsList()` + * This is a type-conversion wrapper around `getIdsList()` * @return {!Array} */ -proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.prototype.getIdentitiesIdsList_asU8 = function() { +proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.prototype.getIdsList_asU8 = function() { return /** @type {!Array} */ (jspb.Message.bytesListAsU8( - this.getIdentitiesIdsList())); + this.getIdsList())); }; /** * @param {!(Array|Array)} value - * @return {!proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds} returns this + * @return {!proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0} returns this */ -proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.prototype.setIdentitiesIdsList = function(value) { +proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.prototype.setIdsList = function(value) { return jspb.Message.setField(this, 1, value || []); }; @@ -15307,56 +15341,19 @@ proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalanc /** * @param {!(string|Uint8Array)} value * @param {number=} opt_index - * @return {!proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds} returns this + * @return {!proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0} returns this */ -proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.prototype.addIdentitiesIds = function(value, opt_index) { +proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.prototype.addIds = function(value, opt_index) { return jspb.Message.addToRepeatedField(this, 1, value, opt_index); }; /** * Clears the list making it empty but non-null. - * @return {!proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds} returns this - */ -proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds.prototype.clearIdentitiesIdsList = function() { - return this.setIdentitiesIdsList([]); -}; - - -/** - * optional GetIdentitiesBalancesByKnownIdentityIds identities_ids = 1; - * @return {?proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds} - */ -proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.prototype.getIdentitiesIds = function() { - return /** @type{?proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds} */ ( - jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds, 1)); -}; - - -/** - * @param {?proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.GetIdentitiesBalancesByKnownIdentityIds|undefined} value - * @return {!proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0} returns this -*/ -proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.prototype.setIdentitiesIds = function(value) { - return jspb.Message.setWrapperField(this, 1, value); -}; - - -/** - * Clears the message field making it undefined. * @return {!proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0} returns this */ -proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.prototype.clearIdentitiesIds = function() { - return this.setIdentitiesIds(undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.prototype.hasIdentitiesIds = function() { - return jspb.Message.getField(this, 1) != null; +proto.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0.prototype.clearIdsList = function() { + return this.setIdsList([]); }; @@ -44168,6 +44165,1363 @@ proto.org.dash.platform.dapi.v0.GetStatusResponse.prototype.hasV0 = function() { }; + +/** + * 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.GetCurrentQuorumsInfoRequest.oneofGroups_ = [[1]]; + +/** + * @enum {number} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.VersionCase = { + VERSION_NOT_SET: 0, + V0: 1 +}; + +/** + * @return {proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.VersionCase} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.prototype.getVersionCase = function() { + return /** @type {proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.VersionCase} */(jspb.Message.computeOneofCase(this, proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.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.GetCurrentQuorumsInfoRequest.prototype.toObject = function(opt_includeInstance) { + return proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.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.GetCurrentQuorumsInfoRequest} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.toObject = function(includeInstance, msg) { + var f, obj = { + v0: (f = msg.getV0()) && proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0.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.GetCurrentQuorumsInfoRequest} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest; + return proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.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.GetCurrentQuorumsInfoRequest} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.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.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0.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.GetCurrentQuorumsInfoRequest.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.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.GetCurrentQuorumsInfoRequest} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getV0(); + if (f != null) { + writer.writeMessage( + 1, + f, + proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0.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.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0.prototype.toObject = function(opt_includeInstance) { + return proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0.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.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0.toObject = function(includeInstance, msg) { + var f, obj = { + + }; + + 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.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0; + return proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0.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.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0.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.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0.serializeBinaryToWriter = function(message, writer) { + var f = undefined; +}; + + +/** + * optional GetCurrentQuorumsInfoRequestV0 v0 = 1; + * @return {?proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.prototype.getV0 = function() { + return /** @type{?proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0} */ ( + jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0, 1)); +}; + + +/** + * @param {?proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0|undefined} value + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest} returns this +*/ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.prototype.setV0 = function(value) { + return jspb.Message.setOneofWrapperField(this, 1, proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.oneofGroups_[0], value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest} returns this + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.prototype.clearV0 = function() { + return this.setV0(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.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.GetCurrentQuorumsInfoResponse.oneofGroups_ = [[1]]; + +/** + * @enum {number} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.VersionCase = { + VERSION_NOT_SET: 0, + V0: 1 +}; + +/** + * @return {proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.VersionCase} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.prototype.getVersionCase = function() { + return /** @type {proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.VersionCase} */(jspb.Message.computeOneofCase(this, proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.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.GetCurrentQuorumsInfoResponse.prototype.toObject = function(opt_includeInstance) { + return proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.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.GetCurrentQuorumsInfoResponse} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.toObject = function(includeInstance, msg) { + var f, obj = { + v0: (f = msg.getV0()) && proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.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.GetCurrentQuorumsInfoResponse} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse; + return proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.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.GetCurrentQuorumsInfoResponse} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.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.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.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.GetCurrentQuorumsInfoResponse.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.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.GetCurrentQuorumsInfoResponse} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getV0(); + if (f != null) { + writer.writeMessage( + 1, + f, + proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.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.GetCurrentQuorumsInfoResponse.ValidatorV0.prototype.toObject = function(opt_includeInstance) { + return proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.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.GetCurrentQuorumsInfoResponse.ValidatorV0} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.toObject = function(includeInstance, msg) { + var f, obj = { + proTxHash: msg.getProTxHash_asB64(), + nodeIp: jspb.Message.getFieldWithDefault(msg, 2, ""), + isBanned: jspb.Message.getBooleanFieldWithDefault(msg, 3, 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.GetCurrentQuorumsInfoResponse.ValidatorV0} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0; + return proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.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.GetCurrentQuorumsInfoResponse.ValidatorV0} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.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.setProTxHash(value); + break; + case 2: + var value = /** @type {string} */ (reader.readString()); + msg.setNodeIp(value); + break; + case 3: + var value = /** @type {boolean} */ (reader.readBool()); + msg.setIsBanned(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.GetCurrentQuorumsInfoResponse.ValidatorV0.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.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.GetCurrentQuorumsInfoResponse.ValidatorV0} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getProTxHash_asU8(); + if (f.length > 0) { + writer.writeBytes( + 1, + f + ); + } + f = message.getNodeIp(); + if (f.length > 0) { + writer.writeString( + 2, + f + ); + } + f = message.getIsBanned(); + if (f) { + writer.writeBool( + 3, + f + ); + } +}; + + +/** + * optional bytes pro_tx_hash = 1; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.prototype.getProTxHash = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * optional bytes pro_tx_hash = 1; + * This is a type-conversion wrapper around `getProTxHash()` + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.prototype.getProTxHash_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getProTxHash())); +}; + + +/** + * optional bytes pro_tx_hash = 1; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getProTxHash()` + * @return {!Uint8Array} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.prototype.getProTxHash_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getProTxHash())); +}; + + +/** + * @param {!(string|Uint8Array)} value + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.prototype.setProTxHash = function(value) { + return jspb.Message.setProto3BytesField(this, 1, value); +}; + + +/** + * optional string node_ip = 2; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.prototype.getNodeIp = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * @param {string} value + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.prototype.setNodeIp = function(value) { + return jspb.Message.setProto3StringField(this, 2, value); +}; + + +/** + * optional bool is_banned = 3; + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.prototype.getIsBanned = function() { + return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 3, false)); +}; + + +/** + * @param {boolean} value + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.prototype.setIsBanned = function(value) { + return jspb.Message.setProto3BooleanField(this, 3, value); +}; + + + +/** + * List of repeated fields within this message type. + * @private {!Array} + * @const + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.repeatedFields_ = [3]; + + + +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.GetCurrentQuorumsInfoResponse.ValidatorSetV0.prototype.toObject = function(opt_includeInstance) { + return proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.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.GetCurrentQuorumsInfoResponse.ValidatorSetV0} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.toObject = function(includeInstance, msg) { + var f, obj = { + quorumHash: msg.getQuorumHash_asB64(), + coreHeight: jspb.Message.getFieldWithDefault(msg, 2, 0), + membersList: jspb.Message.toObjectList(msg.getMembersList(), + proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.toObject, includeInstance), + thresholdPublicKey: msg.getThresholdPublicKey_asB64() + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0; + return proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.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.GetCurrentQuorumsInfoResponse.ValidatorSetV0} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.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.setQuorumHash(value); + break; + case 2: + var value = /** @type {number} */ (reader.readUint32()); + msg.setCoreHeight(value); + break; + case 3: + var value = new proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.deserializeBinaryFromReader); + msg.addMembers(value); + break; + case 4: + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setThresholdPublicKey(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.GetCurrentQuorumsInfoResponse.ValidatorSetV0.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.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.GetCurrentQuorumsInfoResponse.ValidatorSetV0} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getQuorumHash_asU8(); + if (f.length > 0) { + writer.writeBytes( + 1, + f + ); + } + f = message.getCoreHeight(); + if (f !== 0) { + writer.writeUint32( + 2, + f + ); + } + f = message.getMembersList(); + if (f.length > 0) { + writer.writeRepeatedMessage( + 3, + f, + proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0.serializeBinaryToWriter + ); + } + f = message.getThresholdPublicKey_asU8(); + if (f.length > 0) { + writer.writeBytes( + 4, + f + ); + } +}; + + +/** + * optional bytes quorum_hash = 1; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.prototype.getQuorumHash = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * optional bytes quorum_hash = 1; + * This is a type-conversion wrapper around `getQuorumHash()` + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.prototype.getQuorumHash_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getQuorumHash())); +}; + + +/** + * optional bytes quorum_hash = 1; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getQuorumHash()` + * @return {!Uint8Array} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.prototype.getQuorumHash_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getQuorumHash())); +}; + + +/** + * @param {!(string|Uint8Array)} value + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.prototype.setQuorumHash = function(value) { + return jspb.Message.setProto3BytesField(this, 1, value); +}; + + +/** + * optional uint32 core_height = 2; + * @return {number} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.prototype.getCoreHeight = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.prototype.setCoreHeight = function(value) { + return jspb.Message.setProto3IntField(this, 2, value); +}; + + +/** + * repeated ValidatorV0 members = 3; + * @return {!Array} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.prototype.getMembersList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0, 3)); +}; + + +/** + * @param {!Array} value + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0} returns this +*/ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.prototype.setMembersList = function(value) { + return jspb.Message.setRepeatedWrapperField(this, 3, value); +}; + + +/** + * @param {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0=} opt_value + * @param {number=} opt_index + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.prototype.addMembers = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 3, opt_value, proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0, opt_index); +}; + + +/** + * Clears the list making it empty but non-null. + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.prototype.clearMembersList = function() { + return this.setMembersList([]); +}; + + +/** + * optional bytes threshold_public_key = 4; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.prototype.getThresholdPublicKey = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 4, "")); +}; + + +/** + * optional bytes threshold_public_key = 4; + * This is a type-conversion wrapper around `getThresholdPublicKey()` + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.prototype.getThresholdPublicKey_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getThresholdPublicKey())); +}; + + +/** + * optional bytes threshold_public_key = 4; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getThresholdPublicKey()` + * @return {!Uint8Array} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.prototype.getThresholdPublicKey_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getThresholdPublicKey())); +}; + + +/** + * @param {!(string|Uint8Array)} value + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.prototype.setThresholdPublicKey = function(value) { + return jspb.Message.setProto3BytesField(this, 4, value); +}; + + + +/** + * List of repeated fields within this message type. + * @private {!Array} + * @const + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.repeatedFields_ = [1,3]; + + + +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.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.toObject = function(opt_includeInstance) { + return proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.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.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.toObject = function(includeInstance, msg) { + var f, obj = { + quorumHashesList: msg.getQuorumHashesList_asB64(), + currentQuorumHash: msg.getCurrentQuorumHash_asB64(), + validatorSetsList: jspb.Message.toObjectList(msg.getValidatorSetsList(), + proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.toObject, includeInstance), + lastBlockProposer: msg.getLastBlockProposer_asB64(), + metadata: (f = msg.getMetadata()) && proto.org.dash.platform.dapi.v0.ResponseMetadata.toObject(includeInstance, f) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0; + return proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.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.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.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.addQuorumHashes(value); + break; + case 2: + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setCurrentQuorumHash(value); + break; + case 3: + var value = new proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.deserializeBinaryFromReader); + msg.addValidatorSets(value); + break; + case 4: + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setLastBlockProposer(value); + break; + case 5: + var value = new proto.org.dash.platform.dapi.v0.ResponseMetadata; + reader.readMessage(value,proto.org.dash.platform.dapi.v0.ResponseMetadata.deserializeBinaryFromReader); + msg.setMetadata(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.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.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getQuorumHashesList_asU8(); + if (f.length > 0) { + writer.writeRepeatedBytes( + 1, + f + ); + } + f = message.getCurrentQuorumHash_asU8(); + if (f.length > 0) { + writer.writeBytes( + 2, + f + ); + } + f = message.getValidatorSetsList(); + if (f.length > 0) { + writer.writeRepeatedMessage( + 3, + f, + proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0.serializeBinaryToWriter + ); + } + f = message.getLastBlockProposer_asU8(); + if (f.length > 0) { + writer.writeBytes( + 4, + f + ); + } + f = message.getMetadata(); + if (f != null) { + writer.writeMessage( + 5, + f, + proto.org.dash.platform.dapi.v0.ResponseMetadata.serializeBinaryToWriter + ); + } +}; + + +/** + * repeated bytes quorum_hashes = 1; + * @return {!Array} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.getQuorumHashesList = function() { + return /** @type {!Array} */ (jspb.Message.getRepeatedField(this, 1)); +}; + + +/** + * repeated bytes quorum_hashes = 1; + * This is a type-conversion wrapper around `getQuorumHashesList()` + * @return {!Array} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.getQuorumHashesList_asB64 = function() { + return /** @type {!Array} */ (jspb.Message.bytesListAsB64( + this.getQuorumHashesList())); +}; + + +/** + * repeated bytes quorum_hashes = 1; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getQuorumHashesList()` + * @return {!Array} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.getQuorumHashesList_asU8 = function() { + return /** @type {!Array} */ (jspb.Message.bytesListAsU8( + this.getQuorumHashesList())); +}; + + +/** + * @param {!(Array|Array)} value + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.setQuorumHashesList = function(value) { + return jspb.Message.setField(this, 1, value || []); +}; + + +/** + * @param {!(string|Uint8Array)} value + * @param {number=} opt_index + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.addQuorumHashes = function(value, opt_index) { + return jspb.Message.addToRepeatedField(this, 1, value, opt_index); +}; + + +/** + * Clears the list making it empty but non-null. + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.clearQuorumHashesList = function() { + return this.setQuorumHashesList([]); +}; + + +/** + * optional bytes current_quorum_hash = 2; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.getCurrentQuorumHash = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * optional bytes current_quorum_hash = 2; + * This is a type-conversion wrapper around `getCurrentQuorumHash()` + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.getCurrentQuorumHash_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getCurrentQuorumHash())); +}; + + +/** + * optional bytes current_quorum_hash = 2; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getCurrentQuorumHash()` + * @return {!Uint8Array} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.getCurrentQuorumHash_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getCurrentQuorumHash())); +}; + + +/** + * @param {!(string|Uint8Array)} value + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.setCurrentQuorumHash = function(value) { + return jspb.Message.setProto3BytesField(this, 2, value); +}; + + +/** + * repeated ValidatorSetV0 validator_sets = 3; + * @return {!Array} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.getValidatorSetsList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0, 3)); +}; + + +/** + * @param {!Array} value + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0} returns this +*/ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.setValidatorSetsList = function(value) { + return jspb.Message.setRepeatedWrapperField(this, 3, value); +}; + + +/** + * @param {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0=} opt_value + * @param {number=} opt_index + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.addValidatorSets = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 3, opt_value, proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0, opt_index); +}; + + +/** + * Clears the list making it empty but non-null. + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.clearValidatorSetsList = function() { + return this.setValidatorSetsList([]); +}; + + +/** + * optional bytes last_block_proposer = 4; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.getLastBlockProposer = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 4, "")); +}; + + +/** + * optional bytes last_block_proposer = 4; + * This is a type-conversion wrapper around `getLastBlockProposer()` + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.getLastBlockProposer_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getLastBlockProposer())); +}; + + +/** + * optional bytes last_block_proposer = 4; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getLastBlockProposer()` + * @return {!Uint8Array} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.getLastBlockProposer_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getLastBlockProposer())); +}; + + +/** + * @param {!(string|Uint8Array)} value + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.setLastBlockProposer = function(value) { + return jspb.Message.setProto3BytesField(this, 4, value); +}; + + +/** + * optional ResponseMetadata metadata = 5; + * @return {?proto.org.dash.platform.dapi.v0.ResponseMetadata} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.getMetadata = function() { + return /** @type{?proto.org.dash.platform.dapi.v0.ResponseMetadata} */ ( + jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.ResponseMetadata, 5)); +}; + + +/** + * @param {?proto.org.dash.platform.dapi.v0.ResponseMetadata|undefined} value + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0} returns this +*/ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.setMetadata = function(value) { + return jspb.Message.setWrapperField(this, 5, value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0} returns this + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.clearMetadata = function() { + return this.setMetadata(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0.prototype.hasMetadata = function() { + return jspb.Message.getField(this, 5) != null; +}; + + +/** + * optional GetCurrentQuorumsInfoResponseV0 v0 = 1; + * @return {?proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.prototype.getV0 = function() { + return /** @type{?proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0} */ ( + jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0, 1)); +}; + + +/** + * @param {?proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0|undefined} value + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse} returns this +*/ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.prototype.setV0 = function(value) { + return jspb.Message.setOneofWrapperField(this, 1, proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.oneofGroups_[0], value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse} returns this + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.prototype.clearV0 = function() { + return this.setV0(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.prototype.hasV0 = function() { + return jspb.Message.getField(this, 1) != null; +}; + + /** * @enum {number} */ 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 6488351eb1..11bc954b2d 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 @@ -283,6 +283,15 @@ type PlatformgetStatus = { readonly responseType: typeof platform_pb.GetStatusResponse; }; +type PlatformgetCurrentQuorumsInfo = { + readonly methodName: string; + readonly service: typeof Platform; + readonly requestStream: false; + readonly responseStream: false; + readonly requestType: typeof platform_pb.GetCurrentQuorumsInfoRequest; + readonly responseType: typeof platform_pb.GetCurrentQuorumsInfoResponse; +}; + export class Platform { static readonly serviceName: string; static readonly broadcastStateTransition: PlatformbroadcastStateTransition; @@ -316,6 +325,7 @@ export class Platform { static readonly getTotalCreditsInPlatform: PlatformgetTotalCreditsInPlatform; static readonly getPathElements: PlatformgetPathElements; static readonly getStatus: PlatformgetStatus; + static readonly getCurrentQuorumsInfo: PlatformgetCurrentQuorumsInfo; } export type ServiceError = { message: string, code: number; metadata: grpc.Metadata } @@ -629,5 +639,14 @@ export class PlatformClient { requestMessage: platform_pb.GetStatusRequest, callback: (error: ServiceError|null, responseMessage: platform_pb.GetStatusResponse|null) => void ): UnaryResponse; + getCurrentQuorumsInfo( + requestMessage: platform_pb.GetCurrentQuorumsInfoRequest, + metadata: grpc.Metadata, + callback: (error: ServiceError|null, responseMessage: platform_pb.GetCurrentQuorumsInfoResponse|null) => void + ): UnaryResponse; + getCurrentQuorumsInfo( + requestMessage: platform_pb.GetCurrentQuorumsInfoRequest, + callback: (error: ServiceError|null, responseMessage: platform_pb.GetCurrentQuorumsInfoResponse|null) => void + ): UnaryResponse; } 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 103a394fea..5ba77dbcd4 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 @@ -289,6 +289,15 @@ Platform.getStatus = { responseType: platform_pb.GetStatusResponse }; +Platform.getCurrentQuorumsInfo = { + methodName: "getCurrentQuorumsInfo", + service: Platform, + requestStream: false, + responseStream: false, + requestType: platform_pb.GetCurrentQuorumsInfoRequest, + responseType: platform_pb.GetCurrentQuorumsInfoResponse +}; + exports.Platform = Platform; function PlatformClient(serviceHost, options) { @@ -1257,5 +1266,36 @@ PlatformClient.prototype.getStatus = function getStatus(requestMessage, metadata }; }; +PlatformClient.prototype.getCurrentQuorumsInfo = function getCurrentQuorumsInfo(requestMessage, metadata, callback) { + if (arguments.length === 2) { + callback = arguments[1]; + } + var client = grpc.unary(Platform.getCurrentQuorumsInfo, { + 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(); + } + }; +}; + exports.PlatformClient = PlatformClient; diff --git a/packages/dapi-grpc/package.json b/packages/dapi-grpc/package.json index 0ee80a485f..e2481688bd 100644 --- a/packages/dapi-grpc/package.json +++ b/packages/dapi-grpc/package.json @@ -1,6 +1,6 @@ { "name": "@dashevo/dapi-grpc", - "version": "1.3.1", + "version": "1.5.0", "description": "DAPI GRPC definition file and generated clients", "browser": "browser.js", "main": "node.js", diff --git a/packages/dapi-grpc/protos/platform/v0/platform.proto b/packages/dapi-grpc/protos/platform/v0/platform.proto index b690d3f7cc..b46d784ceb 100644 --- a/packages/dapi-grpc/protos/platform/v0/platform.proto +++ b/packages/dapi-grpc/protos/platform/v0/platform.proto @@ -54,6 +54,7 @@ service Platform { rpc getTotalCreditsInPlatform(GetTotalCreditsInPlatformRequest) returns (GetTotalCreditsInPlatformResponse); rpc getPathElements(GetPathElementsRequest) returns (GetPathElementsResponse); rpc getStatus(GetStatusRequest) returns (GetStatusResponse); + rpc getCurrentQuorumsInfo(GetCurrentQuorumsInfoRequest) returns (GetCurrentQuorumsInfoResponse); } // Proof message includes cryptographic proofs for validating responses @@ -1184,3 +1185,33 @@ message GetStatusResponse { oneof version { GetStatusResponseV0 v0 = 1; } } + +message GetCurrentQuorumsInfoRequest { + message GetCurrentQuorumsInfoRequestV0 { + } + + oneof version { GetCurrentQuorumsInfoRequestV0 v0 = 1; } +} + +message GetCurrentQuorumsInfoResponse { + message ValidatorV0 { + bytes pro_tx_hash = 1; + string node_ip = 2; + bool is_banned = 3; + } + message ValidatorSetV0 { + bytes quorum_hash = 1; + uint32 core_height = 2; + repeated ValidatorV0 members = 3; + bytes threshold_public_key = 4; + } + + message GetCurrentQuorumsInfoResponseV0 { + repeated bytes quorum_hashes = 1; + bytes current_quorum_hash = 2; + repeated ValidatorSetV0 validator_sets = 3; + bytes last_block_proposer = 4; + ResponseMetadata metadata = 5; + } + oneof version { GetCurrentQuorumsInfoResponseV0 v0 = 1; } +} diff --git a/packages/dapi/lib/externalApis/tenderdash/requestTenderRpc.js b/packages/dapi/lib/externalApis/tenderdash/requestTenderRpc.js new file mode 100644 index 0000000000..efdec5962f --- /dev/null +++ b/packages/dapi/lib/externalApis/tenderdash/requestTenderRpc.js @@ -0,0 +1,55 @@ +const UnavailableGrpcError = require('@dashevo/grpc-common/lib/server/error/UnavailableGrpcError'); +const ResourceExhaustedGrpcError = require('@dashevo/grpc-common/lib/server/error/ResourceExhaustedGrpcError'); +const RPCError = require('../../rpcServer/RPCError'); + +/** + * @param {jaysonClient} rpcClient + * @return {requestTenderRpc} A function to make RPC requests to Tenderdash. + */ +function requestTenderRpcFactory(rpcClient) { + /** + * @function + * @typedef requestTenderRpc + * @param {string} uri + * @param {Object} [params={}] + * @return {Promise} + */ + async function requestTenderRpc(uri, params = {}) { + let response; + try { + response = await rpcClient.request(uri, params); + } catch (e) { + if (e.code === 'ECONNRESET' || e.message === 'socket hang up') { + throw new UnavailableGrpcError('Tenderdash is not available'); + } + + throw new RPCError( + e.code || -32602, + `Failed to request ${uri}: ${e.message}`, + e, + ); + } + + const { result, error: jsonRpcError } = response; + + if (jsonRpcError) { + if (typeof jsonRpcError.data === 'string') { + if (jsonRpcError.data.includes('too_many_resets')) { + throw new ResourceExhaustedGrpcError('tenderdash is not responding: too many requests'); + } + } + + throw new RPCError( + jsonRpcError.code || -32602, + jsonRpcError.message || 'Internal error', + jsonRpcError.data, + ); + } + + return result; + } + + return requestTenderRpc; +} + +module.exports = requestTenderRpcFactory; diff --git a/packages/dapi/lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js b/packages/dapi/lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js index b6e7032f85..a156d9c266 100644 --- a/packages/dapi/lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js +++ b/packages/dapi/lib/grpcServer/handlers/createGrpcErrorFromDriveResponse.js @@ -64,6 +64,9 @@ async function createGrpcErrorFromDriveResponse(code, info) { const message = decodedInfo.message; const data = decodedInfo.data || {}; + const serializedConsensusError = data.serializedError; + delete data.serializedError; + // gRPC error codes if (code <= 16) { const CommonErrorClass = COMMON_ERROR_CLASSES[code.toString()]; @@ -111,9 +114,15 @@ async function createGrpcErrorFromDriveResponse(code, info) { // DPP errors if (code >= 10000 && code < 50000) { + const consensusMetadata = { + ...createRawMetadata(data), + code, + 'dash-serialized-consensus-error-bin': Buffer.from(serializedConsensusError), + }; + let consensusError; try { - consensusError = deserializeConsensusError(data.serializedError || []); + consensusError = deserializeConsensusError(serializedConsensusError); } catch (e) { logger.error({ err: e, @@ -128,7 +137,7 @@ async function createGrpcErrorFromDriveResponse(code, info) { if (code >= 10000 && code < 20000) { return new InvalidArgumentGrpcError( consensusError.message, - { code, ...createRawMetadata(data) }, + consensusMetadata, ); } @@ -137,7 +146,7 @@ async function createGrpcErrorFromDriveResponse(code, info) { return new GrpcError( GrpcErrorCodes.UNAUTHENTICATED, consensusError.message, - { code, ...createRawMetadata(data) }, + consensusMetadata, ); } @@ -145,7 +154,7 @@ async function createGrpcErrorFromDriveResponse(code, info) { if (code >= 30000 && code < 40000) { return new FailedPreconditionGrpcError( consensusError.message, - { code, ...createRawMetadata(data) }, + consensusMetadata, ); } @@ -153,7 +162,7 @@ async function createGrpcErrorFromDriveResponse(code, info) { if (code >= 40000 && code < 50000) { return new InvalidArgumentGrpcError( consensusError.message, - { code, ...createRawMetadata(data) }, + consensusMetadata, ); } } diff --git a/packages/dapi/lib/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js b/packages/dapi/lib/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js index ad77276042..a17d496918 100644 --- a/packages/dapi/lib/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js +++ b/packages/dapi/lib/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js @@ -2,9 +2,10 @@ const { server: { error: { InvalidArgumentGrpcError, - AlreadyExistsGrpcError, ResourceExhaustedGrpcError, UnavailableGrpcError, + AlreadyExistsGrpcError, + InternalGrpcError, }, }, } = require('@dashevo/grpc-common'); @@ -14,15 +15,23 @@ const { BroadcastStateTransitionResponse, }, } = require('@dashevo/dapi-grpc'); + +const crypto = require('crypto'); + const logger = require('../../../logger'); /** * @param {jaysonClient} rpcClient * @param {createGrpcErrorFromDriveResponse} createGrpcErrorFromDriveResponse + * @param {requestTenderRpc} requestTenderRpc * * @returns {broadcastStateTransitionHandler} */ -function broadcastStateTransitionHandlerFactory(rpcClient, createGrpcErrorFromDriveResponse) { +function broadcastStateTransitionHandlerFactory( + rpcClient, + createGrpcErrorFromDriveResponse, + requestTenderRpc, +) { /** * @typedef broadcastStateTransitionHandler * @@ -38,7 +47,9 @@ function broadcastStateTransitionHandlerFactory(rpcClient, createGrpcErrorFromDr throw new InvalidArgumentGrpcError('State Transition is not specified'); } - const tx = Buffer.from(stByteArray) + const stBytes = Buffer.from(stByteArray); + + const tx = stBytes .toString('base64'); let response; @@ -46,7 +57,7 @@ function broadcastStateTransitionHandlerFactory(rpcClient, createGrpcErrorFromDr try { response = await rpcClient.request('broadcast_tx', { tx }); } catch (e) { - if (e.message === 'socket hang up') { + if (e.code === 'ECONNRESET' || e.message === 'socket hang up') { throw new UnavailableGrpcError('Tenderdash is not available'); } @@ -55,15 +66,65 @@ function broadcastStateTransitionHandlerFactory(rpcClient, createGrpcErrorFromDr throw e; } - const { - result, - error: jsonRpcError, - } = response; + const { result, error: jsonRpcError } = response; if (jsonRpcError) { if (typeof jsonRpcError.data === 'string') { if (jsonRpcError.data === 'tx already exists in cache') { - throw new AlreadyExistsGrpcError('state transition already in chain'); + // We need to figure out and report to user why the ST cached + const stHash = crypto.createHash('sha256') + .update(stBytes) + .digest(); + + // TODO: Apply search filter to fetch specific state transition + // Throw an already exist in mempool error if the ST in mempool + const unconfirmedTxsResponse = await requestTenderRpc('unconfirmed_txs', { limit: 100 }); + + if (unconfirmedTxsResponse?.txs?.includes(stBytes.toString('base64'))) { + throw new AlreadyExistsGrpcError('state transition already in mempool'); + } + + // Throw an already exist in chain error if the ST is committed + let txResponse; + try { + txResponse = await requestTenderRpc('tx', { hash: stHash.toString('base64') }); + } catch (e) { + if (typeof e.data !== 'string' || !e.data.includes('not found')) { + throw e; + } + } + + if (txResponse?.tx_result) { + throw new AlreadyExistsGrpcError('state transition already in chain'); + } + + // If the ST not in mempool and not in the state but still in the cache + // it means it was invalidated by CheckTx so we run CheckTx again to provide + // the validation error + const checkTxResponse = await requestTenderRpc('check_tx', { tx }); + + if (checkTxResponse?.code !== 0) { + // Return validation error + throw await createGrpcErrorFromDriveResponse( + checkTxResponse.code, + checkTxResponse.info, + ); + } else { + // CheckTx passes for the ST, it means we have a bug in Drive so ST is passing check + // tx and then removed from the block. The removal from the block doesn't remove ST + // from the cache because it's happening only one proposer and other nodes do not know + // that this ST was processed and keep it in the cache + // The best what we can do is to return an internal error and and log the transaction + logger.warn({ + tx, + }, `State transition ${stHash.toString('hex')} is passing CheckTx but removed from the block by proposal`); + + const error = new Error('State Transition processing error. Please report' + + ' faulty state transition and try to create a new state transition with different' + + ' hash as a workaround.'); + + throw new InternalGrpcError(error); + } } if (jsonRpcError.data.startsWith('Tx too large.')) { diff --git a/packages/dapi/lib/grpcServer/handlers/platform/platformHandlersFactory.js b/packages/dapi/lib/grpcServer/handlers/platform/platformHandlersFactory.js index 641071d357..8288583ab7 100644 --- a/packages/dapi/lib/grpcServer/handlers/platform/platformHandlersFactory.js +++ b/packages/dapi/lib/grpcServer/handlers/platform/platformHandlersFactory.js @@ -55,6 +55,7 @@ const waitForTransactionToBeProvableFactory = require('../../../externalApis/ten const waitForTransactionResult = require('../../../externalApis/tenderdash/waitForTransactionToBeProvable/waitForTransactionResult'); const getExistingTransactionResultFactory = require('../../../externalApis/tenderdash/waitForTransactionToBeProvable/getExistingTransactionResult'); const getConsensusParamsFactory = require('../../../externalApis/tenderdash/getConsensusParamsFactory'); +const requestTenderRpcFactory = require('../../../externalApis/tenderdash/requestTenderRpc'); /** * @param {jaysonClient} rpcClient @@ -73,10 +74,13 @@ function platformHandlersFactory( ) { const wrapInErrorHandler = wrapInErrorHandlerFactory(logger, isProductionEnvironment); + const requestTenderRpc = requestTenderRpcFactory(rpcClient); + // broadcastStateTransition const broadcastStateTransitionHandler = broadcastStateTransitionHandlerFactory( rpcClient, createGrpcErrorFromDriveResponse, + requestTenderRpc, ); const wrappedBroadcastStateTransition = jsonToProtobufHandlerWrapper( diff --git a/packages/dapi/package.json b/packages/dapi/package.json index 704d97788c..79d23a958e 100644 --- a/packages/dapi/package.json +++ b/packages/dapi/package.json @@ -1,7 +1,7 @@ { "name": "@dashevo/dapi", "private": true, - "version": "1.3.1", + "version": "1.5.0", "description": "A decentralized API for the Dash network", "scripts": { "api": "node scripts/api.js", @@ -35,7 +35,7 @@ "dependencies": { "@dashevo/bls": "~1.2.9", "@dashevo/dapi-grpc": "workspace:*", - "@dashevo/dashcore-lib": "~0.21.3", + "@dashevo/dashcore-lib": "~0.22.0", "@dashevo/dashd-rpc": "^19.0.0", "@dashevo/grpc-common": "workspace:*", "@dashevo/wasm-dpp": "workspace:*", diff --git a/packages/dapi/test/unit/grpcServer/handlers/createGrpcErrorFromDriveResponse.spec.js b/packages/dapi/test/unit/grpcServer/handlers/createGrpcErrorFromDriveResponse.spec.js index 48a4c32e78..563d23a045 100644 --- a/packages/dapi/test/unit/grpcServer/handlers/createGrpcErrorFromDriveResponse.spec.js +++ b/packages/dapi/test/unit/grpcServer/handlers/createGrpcErrorFromDriveResponse.spec.js @@ -69,7 +69,8 @@ describe('createGrpcErrorFromDriveResponse', () => { it('should throw basic consensus error if error code = 10000', async () => { const consensusError = new ProtocolVersionParsingError('test'); - const data = { serializedError: consensusError.serialize() }; + const serializedError = consensusError.serialize(); + const data = { serializedError }; info = { data }; const error = await createGrpcErrorFromDriveResponse(10000, cbor.encode(info).toString('base64')); @@ -78,7 +79,7 @@ describe('createGrpcErrorFromDriveResponse', () => { expect(error.message).to.be.equals(consensusError.message); expect(error.getRawMetadata()).to.deep.equal({ code: 10000, - 'drive-error-data-bin': cbor.encode(data), + 'dash-serialized-consensus-error-bin': serializedError, }); }); @@ -87,7 +88,8 @@ describe('createGrpcErrorFromDriveResponse', () => { const consensusError = new IdentityNotFoundError(id); - const data = { serializedError: consensusError.serialize() }; + const serializedError = consensusError.serialize(); + const data = { serializedError }; info = { data }; const error = await createGrpcErrorFromDriveResponse( @@ -100,14 +102,15 @@ describe('createGrpcErrorFromDriveResponse', () => { expect(error.getCode()).to.equal(GrpcErrorCodes.UNAUTHENTICATED); expect(error.getRawMetadata()).to.deep.equal({ code: 20000, - 'drive-error-data-bin': cbor.encode(data), + 'dash-serialized-consensus-error-bin': serializedError, }); }); it('should throw fee consensus error if error code = 30000', async () => { const consensusError = new BalanceIsNotEnoughError(BigInt(20), BigInt(10)); - const data = { serializedError: consensusError.serialize() }; + const serializedError = consensusError.serialize(); + const data = { serializedError }; info = { data }; const error = await createGrpcErrorFromDriveResponse(30000, cbor.encode(info).toString('base64')); @@ -115,7 +118,7 @@ describe('createGrpcErrorFromDriveResponse', () => { expect(error).to.be.an.instanceOf(FailedPreconditionGrpcError); expect(error.getRawMetadata()).to.deep.equal({ code: 30000, - 'drive-error-data-bin': cbor.encode(data), + 'dash-serialized-consensus-error-bin': serializedError, }); }); @@ -124,7 +127,8 @@ describe('createGrpcErrorFromDriveResponse', () => { const consensusError = new DataContractAlreadyPresentError(dataContractId); - const data = { serializedError: consensusError.serialize() }; + const serializedError = consensusError.serialize(); + const data = { serializedError }; info = { data }; const error = await createGrpcErrorFromDriveResponse( @@ -135,7 +139,7 @@ describe('createGrpcErrorFromDriveResponse', () => { expect(error).to.be.an.instanceOf(InvalidArgumentGrpcError); expect(error.getRawMetadata()).to.deep.equal({ code: 40000, - 'drive-error-data-bin': cbor.encode(data), + 'dash-serialized-consensus-error-bin': serializedError, }); }); diff --git a/packages/dapi/test/unit/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.spec.js b/packages/dapi/test/unit/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.spec.js index 3dc61b2eb4..de1152d015 100644 --- a/packages/dapi/test/unit/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.spec.js +++ b/packages/dapi/test/unit/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.spec.js @@ -5,6 +5,7 @@ const { AlreadyExistsGrpcError, UnavailableGrpcError, ResourceExhaustedGrpcError, + InternalGrpcError, }, }, } = require('@dashevo/grpc-common'); @@ -36,6 +37,7 @@ describe('broadcastStateTransitionHandlerFactory', () => { let log; let code; let createGrpcErrorFromDriveResponseMock; + let requestTenderRpcMock; before(async () => { await loadWasmDpp(); @@ -82,11 +84,14 @@ describe('broadcastStateTransitionHandlerFactory', () => { request: this.sinon.stub().resolves(response), }; + requestTenderRpcMock = this.sinon.stub(); + createGrpcErrorFromDriveResponseMock = this.sinon.stub(); broadcastStateTransitionHandler = broadcastStateTransitionHandlerFactory( rpcClientMock, createGrpcErrorFromDriveResponseMock, + requestTenderRpcMock, ); }); @@ -182,13 +187,38 @@ describe('broadcastStateTransitionHandlerFactory', () => { } }); - it('should throw AlreadyExistsGrpcError if transaction was broadcasted twice', async () => { + it('should throw AlreadyExistsGrpcError if transaction in mempool', async () => { + response.error = { + code: -32603, + message: 'Internal error', + data: 'tx already exists in cache', + }; + + requestTenderRpcMock.withArgs('unconfirmed_txs').resolves({ + txs: [stateTransitionFixture.toBuffer().toString('base64')], + }); + + try { + await broadcastStateTransitionHandler(call); + + expect.fail('should throw AlreadyExistsGrpcError'); + } catch (e) { + expect(e).to.be.an.instanceOf(AlreadyExistsGrpcError); + expect(e.getMessage()).to.equal('state transition already in mempool'); + } + }); + + it('should throw AlreadyExistsGrpcError if transaction in chain', async () => { response.error = { code: -32603, message: 'Internal error', data: 'tx already exists in cache', }; + requestTenderRpcMock.withArgs('tx').resolves({ + tx_result: { }, + }); + try { await broadcastStateTransitionHandler(call); @@ -199,6 +229,52 @@ describe('broadcastStateTransitionHandlerFactory', () => { } }); + it('should throw consensus result for invalid transition in cache', async () => { + response.error = { + code: -32603, + message: 'Internal error', + data: 'tx already exists in cache', + }; + + requestTenderRpcMock.withArgs('check_tx').resolves({ + code: 1, + info: 'some info', + }); + + const error = new Error('some error'); + + createGrpcErrorFromDriveResponseMock.resolves(error); + + try { + await broadcastStateTransitionHandler(call); + + expect.fail('should throw consensus error'); + } catch (e) { + expect(e).to.equal(error); + } + }); + + it('should throw internal error for transition in cache that passing check tx', async () => { + response.error = { + code: -32603, + message: 'Internal error', + data: 'tx already exists in cache', + }; + + requestTenderRpcMock.withArgs('check_tx').resolves({ + code: 0, + }); + + try { + await broadcastStateTransitionHandler(call); + + expect.fail('should throw InternalError'); + } catch (e) { + expect(e).to.be.an.instanceOf(InternalGrpcError); + expect(e.getMessage()).to.equal('Internal error'); + } + }); + it('should throw a gRPC error based on drive\'s response', async () => { const message = 'not found'; const metadata = { diff --git a/packages/dash-spv/package.json b/packages/dash-spv/package.json index 438a422726..9769bf2791 100644 --- a/packages/dash-spv/package.json +++ b/packages/dash-spv/package.json @@ -1,6 +1,6 @@ { "name": "@dashevo/dash-spv", - "version": "2.3.1", + "version": "2.5.0", "description": "Repository containing SPV functions used by @dashevo", "main": "index.js", "scripts": { @@ -14,7 +14,7 @@ "dependencies": { "@dashevo/dark-gravity-wave": "^1.1.1", "@dashevo/dash-util": "^2.0.3", - "@dashevo/dashcore-lib": "~0.21.3", + "@dashevo/dashcore-lib": "~0.22.0", "levelup": "^4.4.0", "memdown": "^5.1.0", "wasm-x11-hash": "~0.0.2" diff --git a/packages/dashmate/configs/defaults/getBaseConfigFactory.js b/packages/dashmate/configs/defaults/getBaseConfigFactory.js index f1e9237ba9..e26e67ca50 100644 --- a/packages/dashmate/configs/defaults/getBaseConfigFactory.js +++ b/packages/dashmate/configs/defaults/getBaseConfigFactory.js @@ -11,7 +11,6 @@ import { const { version } = JSON.parse(fs.readFileSync(path.join(PACKAGE_ROOT_DIR, 'package.json'), 'utf8')); /** - * @param {HomeDir} homeDir * @returns {getBaseConfig} */ export default function getBaseConfigFactory() { @@ -398,9 +397,6 @@ export default function getBaseConfigFactory() { validator: { pub_key_types: ['bls12381'], }, - version: { - app_version: '1', - }, timeout: { propose: '50000000000', propose_delta: '5000000000', diff --git a/packages/dashmate/configs/defaults/getMainnetConfigFactory.js b/packages/dashmate/configs/defaults/getMainnetConfigFactory.js index 0f83c4a7a1..3c780168d5 100644 --- a/packages/dashmate/configs/defaults/getMainnetConfigFactory.js +++ b/packages/dashmate/configs/defaults/getMainnetConfigFactory.js @@ -53,6 +53,11 @@ export default function getMainnetConfigFactory(homeDir, getBaseConfig) { host: '152.42.151.147', port: 26656, }, + { + id: 'fdc2239c1e0e62f3a192823d6e068d012620a2d1', + host: 'seed-1.pshenmic.dev', + port: 26656, + }, ], }, mempool: { @@ -66,6 +71,11 @@ export default function getMainnetConfigFactory(homeDir, getBaseConfig) { genesis: { chain_id: 'evo1', validator_quorum_type: 4, + consensus_params: { + version: { + app_version: '1', + }, + }, }, }, abci: { diff --git a/packages/dashmate/configs/defaults/getTestnetConfigFactory.js b/packages/dashmate/configs/defaults/getTestnetConfigFactory.js index a8aec0152b..3422ad2438 100644 --- a/packages/dashmate/configs/defaults/getTestnetConfigFactory.js +++ b/packages/dashmate/configs/defaults/getTestnetConfigFactory.js @@ -86,6 +86,11 @@ export default function getTestnetConfigFactory(homeDir, getBaseConfig) { host: '35.92.64.72', port: 36656, }, + { + id: 'de3a73fc78e5c828151454156b492e4a2d985849', + host: 'seed-1.pshenmic.dev', + port: 36656, + }, ], port: 36656, }, @@ -110,6 +115,11 @@ export default function getTestnetConfigFactory(homeDir, getBaseConfig) { genesis: { chain_id: 'dash-testnet-51', validator_quorum_type: 6, + consensus_params: { + version: { + app_version: '1', + }, + }, }, }, }, diff --git a/packages/dashmate/configs/getConfigFileMigrationsFactory.js b/packages/dashmate/configs/getConfigFileMigrationsFactory.js index 3131f435a0..862f3abee3 100644 --- a/packages/dashmate/configs/getConfigFileMigrationsFactory.js +++ b/packages/dashmate/configs/getConfigFileMigrationsFactory.js @@ -448,12 +448,63 @@ export default function getConfigFileMigrationsFactory(homeDir, defaultConfigs) return configFile; }, '1.0.0-dev.2': (configFile) => { + const consensusParams = { + block: { + max_bytes: '2097152', + max_gas: '57631392000', + time_iota_ms: '5000', + }, + evidence: { + max_age: '100000', + max_age_num_blocks: '100000', + max_age_duration: '172800000000000', + }, + validator: { + pub_key_types: ['bls12381'], + }, + timeout: { + propose: '50000000000', + propose_delta: '5000000000', + vote: '10000000000', + vote_delta: '1000000000', + }, + synchrony: { + message_delay: '70000000000', + precision: '1000000000', + }, + abci: { + recheck_tx: true, + }, + version: { + app_version: '1', + }, + }; + + const genesis = { + base: { + consensus_params: lodash.cloneDeep(consensusParams), + }, + local: { + consensus_params: lodash.cloneDeep(consensusParams), + }, + testnet: { + chain_id: 'dash-testnet-51', + validator_quorum_type: 6, + consensus_params: lodash.cloneDeep(consensusParams), + }, + mainnet: { + chain_id: 'evo1', + validator_quorum_type: 4, + consensus_params: lodash.cloneDeep(consensusParams), + }, + }; + Object.entries(configFile.configs) .forEach(([name, options]) => { - if (defaultConfigs.has(name)) { - options.platform.drive.tenderdash.genesis = defaultConfigs.get(name) - .get('platform.drive.tenderdash.genesis'); + if (genesis[name]) { + options.platform.drive.tenderdash.genesis = genesis[name]; } + options.platform.dapi.api.docker.deploy = base.get('platform.dapi.api.docker.deploy'); let baseConfigName = name; @@ -774,6 +825,38 @@ export default function getConfigFileMigrationsFactory(homeDir, defaultConfigs) return configFile; }, '1.1.0-dev.1': (configFile) => { + const consensusParams = { + block: { + max_bytes: '2097152', + max_gas: '57631392000', + time_iota_ms: '5000', + }, + evidence: { + max_age: '100000', + max_age_num_blocks: '100000', + max_age_duration: '172800000000000', + }, + validator: { + pub_key_types: ['bls12381'], + }, + timeout: { + propose: '50000000000', + propose_delta: '5000000000', + vote: '10000000000', + vote_delta: '1000000000', + }, + synchrony: { + message_delay: '70000000000', + precision: '1000000000', + }, + abci: { + recheck_tx: true, + }, + version: { + app_version: '1', + }, + }; + Object.entries(configFile.configs) .forEach(([name, options]) => { if (name === 'local') { @@ -792,8 +875,12 @@ export default function getConfigFileMigrationsFactory(homeDir, defaultConfigs) options.platform.drive.tenderdash.p2p.maxConnections = 64; options.platform.drive.tenderdash.p2p.maxOutgoingConnections = 30; - options.platform.drive.tenderdash.genesis - .consensus_params = base.get('platform.drive.tenderdash.genesis.consensus_params'); + + if (defaultConfigs.has(name)) { + options.platform.drive.tenderdash.genesis + .consensus_params = lodash.cloneDeep(consensusParams); + } + options.platform.drive.tenderdash.docker.image = base.get('platform.drive.tenderdash.docker.image'); }); return configFile; @@ -902,6 +989,49 @@ export default function getConfigFileMigrationsFactory(homeDir, defaultConfigs) }); return configFile; }, + '1.4.0-dev.1': (configFile) => { + Object.entries(configFile.configs) + .forEach(([, options]) => { + options.platform.drive.tenderdash.docker.image = 'dashpay/tenderdash:1.3'; + options.platform.drive.abci.docker.image = 'dashpay/drive:1-dev'; + options.platform.dapi.api.docker.image = 'dashpay/dapi:1-dev'; + }); + return configFile; + }, + '1.4.0-dev.4': (configFile) => { + Object.entries(configFile.configs) + .forEach(([name, options]) => { + if (name === 'base' || name === 'local') { + delete options.platform.drive.tenderdash.genesis.consensus_params.version; + } else if (options.network === NETWORK_TESTNET) { + options.platform.drive.tenderdash.genesis.consensus_params.version = { + app_version: '1', + }; + } + }); + return configFile; + }, + '1.4.0': (configFile) => { + Object.entries(configFile.configs) + .forEach(([, options]) => { + options.platform.drive.abci.docker.image = 'dashpay/drive:1'; + options.platform.dapi.api.docker.image = 'dashpay/dapi:1'; + }); + return configFile; + }, + '1.5.0': (configFile) => { + Object.entries(configFile.configs) + .forEach(([name, options]) => { + if (options.network === NETWORK_MAINNET && name !== 'base') { + options.platform.drive.tenderdash.p2p.seeds = mainnet.get('platform.drive.tenderdash.p2p.seeds'); + } + + if (options.network === NETWORK_TESTNET && name !== 'base') { + options.platform.drive.tenderdash.p2p.seeds = testnet.get('platform.drive.tenderdash.p2p.seeds'); + } + }); + return configFile; + }, }; } diff --git a/packages/dashmate/docker-compose.yml b/packages/dashmate/docker-compose.yml index 67aae0bfa9..fb4cb02b0f 100644 --- a/packages/dashmate/docker-compose.yml +++ b/packages/dashmate/docker-compose.yml @@ -17,13 +17,14 @@ services: environment: - LOCAL_UID=${LOCAL_UID:?err} - LOCAL_GID=${LOCAL_GID:?err} + - DASHMATE_HOME_DIR=${DASHMATE_HOME_DIR:?err} ports: - 127.0.0.1:${DASHMATE_HELPER_API_PORT:?err}:${DASHMATE_HELPER_API_PORT:?err} command: yarn workspace dashmate helper ${CONFIG_NAME:?err} expose: - ${DASHMATE_HELPER_API_PORT:?err} volumes: - - ${DASHMATE_HOME_DIR:?err}:/home/dashmate/.dashmate + - ${DASHMATE_HOME_DIR:?err}:${DASHMATE_HOME_DIR:?err} - /var/run/docker.sock:/var/run/docker.sock core: diff --git a/packages/dashmate/docker/entrypoint.sh b/packages/dashmate/docker/entrypoint.sh index 773f337a2f..852dcb4095 100755 --- a/packages/dashmate/docker/entrypoint.sh +++ b/packages/dashmate/docker/entrypoint.sh @@ -31,4 +31,4 @@ fi echo "Starting with UID: $USER_ID, GID: $GROUP_ID, USER: $USERNAME, GROUP: $GROUP" -exec su - $USERNAME -c "cd /platform;DASHMATE_HELPER=1 DASHMATE_HOME_DIR=/home/dashmate/.dashmate $*" +exec su $USERNAME -c "cd /platform;DASHMATE_HELPER=1 DASHMATE_HOME_DIR=$DASHMATE_HOME_DIR $*" diff --git a/packages/dashmate/package.json b/packages/dashmate/package.json index 5ea94a4509..4ef6feac3f 100644 --- a/packages/dashmate/package.json +++ b/packages/dashmate/package.json @@ -1,6 +1,6 @@ { "name": "dashmate", - "version": "1.3.1", + "version": "1.5.0", "description": "Distribution package for Dash node installation", "scripts": { "lint": "eslint .", @@ -56,7 +56,7 @@ "dependencies": { "@dashevo/bls": "~1.2.9", "@dashevo/dapi-client": "workspace:*", - "@dashevo/dashcore-lib": "~0.21.3", + "@dashevo/dashcore-lib": "~0.22.0", "@dashevo/dashd-rpc": "^19.0.0", "@dashevo/docker-compose": "^0.24.4", "@dashevo/wallet-lib": "workspace:*", diff --git a/packages/dashmate/src/commands/group/status.js b/packages/dashmate/src/commands/group/status.js index d3edbd8800..f9c20f800f 100644 --- a/packages/dashmate/src/commands/group/status.js +++ b/packages/dashmate/src/commands/group/status.js @@ -86,7 +86,7 @@ export default class GroupStatusCommand extends GroupBaseCommand { plain['Platform Status'] = colors.status(scope.platform.tenderdash.serviceStatus)(scope.platform.tenderdash.serviceStatus) || 'n/a'; } else { plain['Platform Status'] = colors.status(scope.platform.tenderdash.serviceStatus)(scope.platform.tenderdash.serviceStatus) || 'n/a'; - plain['Platform Version'] = scope.platform.tenderdash.version || 'n/a'; + plain['Platform Version'] = scope.platform.drive.version || 'n/a'; plain['Platform Block Height'] = scope.platform.tenderdash.latestBlockHeight || 'n/a'; plain['Platform Peers'] = scope.platform.tenderdash.peers || 'n/a'; plain['Platform Network'] = scope.platform.tenderdash.network || 'n/a'; diff --git a/packages/dashmate/src/commands/reset.js b/packages/dashmate/src/commands/reset.js index 99b640cdfc..571b3b2ff3 100644 --- a/packages/dashmate/src/commands/reset.js +++ b/packages/dashmate/src/commands/reset.js @@ -9,7 +9,7 @@ export default class ResetCommand extends ConfigBaseCommand { static flags = { ...ConfigBaseCommand.flags, - hard: Flags.boolean({ char: 'h', description: 'reset config as well as services and data', default: false }), + hard: Flags.boolean({ description: 'reset config as well as services and data', default: false }), force: Flags.boolean({ char: 'f', description: 'skip running services check', default: false }), platform: Flags.boolean({ char: 'p', description: 'reset platform services and data only', default: false }), verbose: Flags.boolean({ char: 'v', description: 'use verbose mode for output', default: false }), @@ -38,6 +38,49 @@ export default class ResetCommand extends ConfigBaseCommand { ) { const tasks = new Listr( [ + { + enabled: (ctx) => !ctx.isForce, + task: async (ctx, task) => { + let message; + if (ctx.isHardReset) { + if (ctx.keepData) { + message = 'Are you sure you want to reset your node configuration? Data will be' + + ' kept.'; + if (ctx.isPlatformOnlyReset) { + message = 'Are you sure you want to reset platform related configuration? Data' + + ' will be kept'; + } + } else { + message = 'Are you sure you want to reset your node data and configuration?'; + if (ctx.isPlatformOnlyReset) { + message = 'Are you sure you want to reset platform related data and configuration?'; + } + } + } else if (ctx.keepData) { + message = 'Are you sure you want to reset docker containers?'; + if (ctx.isPlatformOnlyReset) { + message = 'Are you sure you want to reset platform related docker containers?'; + } + } else { + message = 'Are you sure you want to reset your node data?'; + if (ctx.isPlatformOnlyReset) { + message = 'Are you sure you want to reset platform related data?'; + } + } + + const agreement = await task.prompt({ + type: 'toggle', + name: 'confirm', + message, + enabled: 'Yes', + disabled: 'No', + }); + + if (!agreement) { + throw new Error('Reset operation was declined'); + } + }, + }, { title: `Reset ${config.getName()} node`, task: () => resetNodeTask(config), diff --git a/packages/dashmate/src/commands/ssl/cleanup.js b/packages/dashmate/src/commands/ssl/cleanup.js new file mode 100644 index 0000000000..eaef76cf49 --- /dev/null +++ b/packages/dashmate/src/commands/ssl/cleanup.js @@ -0,0 +1,58 @@ +import { Listr } from 'listr2'; +import { Flags } from '@oclif/core'; +import ConfigBaseCommand from '../../oclif/command/ConfigBaseCommand.js'; +import MuteOneLineError from '../../oclif/errors/MuteOneLineError.js'; + +export default class CleanupCommand extends ConfigBaseCommand { + static description = `Cleanup Zero SSL certificate + +Cancel all drafted or pending validation certificates on ZeroSSL +`; + + static flags = { + ...ConfigBaseCommand.flags, + verbose: Flags.boolean({ char: 'v', description: 'use verbose mode for output', default: false }), + }; + + /** + * @param {Object} args + * @param {Object} flags + * @param {boolean} flags.verbose + * @param {Config} config + * @param {cleanupZeroSSLCertificatesTask} cleanupZeroSSLCertificatesTask + * @return {Promise} + */ + async runWithDependencies( + args, + { + verbose: isVerbose, + }, + config, + cleanupZeroSSLCertificatesTask, + ) { + const tasks = new Listr( + [ + { + title: 'Cleanup ZeroSSL certificate', + task: () => cleanupZeroSSLCertificatesTask(config), + }, + ], + { + renderer: isVerbose ? 'verbose' : 'default', + rendererOptions: { + showTimer: isVerbose, + clearOutput: false, + collapse: false, + showSubtasks: true, + removeEmptyLines: false, + }, + }, + ); + + try { + await tasks.run(); + } catch (e) { + throw new MuteOneLineError(e); + } + } +} diff --git a/packages/dashmate/src/commands/ssl/obtain.js b/packages/dashmate/src/commands/ssl/obtain.js index cc39f1a47a..4dbfcd3561 100644 --- a/packages/dashmate/src/commands/ssl/obtain.js +++ b/packages/dashmate/src/commands/ssl/obtain.js @@ -45,7 +45,7 @@ Certificate will be renewed if it is about to expire (see 'expiration-days' flag [ { title: 'Obtain ZeroSSL certificate', - task: async () => obtainZeroSSLCertificateTask(config), + task: () => obtainZeroSSLCertificateTask(config), }, ], { diff --git a/packages/dashmate/src/commands/status/index.js b/packages/dashmate/src/commands/status/index.js index 6276bb9796..defeb7b80d 100644 --- a/packages/dashmate/src/commands/status/index.js +++ b/packages/dashmate/src/commands/status/index.js @@ -108,11 +108,15 @@ export default class StatusCommand extends ConfigBaseCommand { plain['Platform Enabled'] = platform.enabled || 'n/a'; + const platformStatus = platform.tenderdash.serviceStatus !== ServiceStatusEnum.up + ? platform.tenderdash.serviceStatus + : platform.drive.serviceStatus; + if (platform.enabled) { - plain['Platform Status'] = colors.status(platform.tenderdash.serviceStatus)(platform.tenderdash.serviceStatus) || 'n/a'; + plain['Platform Status'] = colors.status(platformStatus)(platformStatus) || 'n/a'; if (platform.tenderdash.serviceStatus === ServiceStatusEnum.up) { - plain['Platform Version'] = platform.tenderdash.version || 'n/a'; + plain['Platform Version'] = platform.drive.version || 'n/a'; plain['Platform Block Height'] = platform.tenderdash.latestBlockHeight || 'n/a'; plain['Platform Peers'] = platform.tenderdash.peers || 'n/a'; plain['Platform Network'] = platform.tenderdash.network || 'n/a'; diff --git a/packages/dashmate/src/commands/status/platform.js b/packages/dashmate/src/commands/status/platform.js index 2c0e401f18..17abfcdf1e 100644 --- a/packages/dashmate/src/commands/status/platform.js +++ b/packages/dashmate/src/commands/status/platform.js @@ -32,7 +32,6 @@ export default class PlatformStatusCommand extends ConfigBaseCommand { flags, dockerCompose, createRpcClient, - getConnectionHost, config, getPlatformScope, ) { @@ -48,6 +47,8 @@ export default class PlatformStatusCommand extends ConfigBaseCommand { 'Drive Service Status': 'n/a', 'Network': 'n/a', 'Tenderdash Version': 'n/a', + 'Protocol Version': 'n/a', + 'Desired Protocol Version': 'n/a', 'Block height': 'n/a', 'Peer count': 'n/a', 'App hash': 'n/a', @@ -93,6 +94,8 @@ export default class PlatformStatusCommand extends ConfigBaseCommand { if (tenderdash.version) { const { version: tenderdashVersion, + protocolVersion, + desiredProtocolVersion, latestBlockHeight: platformBlockHeight, latestAppHash: platformLatestAppHash, peers: platformPeers, @@ -101,6 +104,8 @@ export default class PlatformStatusCommand extends ConfigBaseCommand { plain['Network'] = tenderdashNetwork || 'n/a'; plain['Tenderdash Version'] = tenderdashVersion || 'n/a'; + plain['Protocol Version'] = protocolVersion || 'n/a'; + plain['Desired Protocol Version'] = desiredProtocolVersion || 'n/a'; plain['Block height'] = platformBlockHeight || 'n/a'; plain['Peer count'] = platformPeers || 'n/a'; plain['App hash'] = platformLatestAppHash || 'n/a'; diff --git a/packages/dashmate/src/commands/wallet/mint.js b/packages/dashmate/src/commands/wallet/mint.js index 2eeacabd35..0f06ad0ecd 100644 --- a/packages/dashmate/src/commands/wallet/mint.js +++ b/packages/dashmate/src/commands/wallet/mint.js @@ -51,6 +51,10 @@ Mint given amount of tDash to a new or specified address throw new Error('Only local network supports generation of dash'); } + if (config.get('core.masternode.enable')) { + throw new Error('A masternode doesn\'t support generation of dash'); + } + const tasks = new Listr( [ { diff --git a/packages/dashmate/src/config/configJsonSchema.js b/packages/dashmate/src/config/configJsonSchema.js index 8da6b4ce48..ed77019f29 100644 --- a/packages/dashmate/src/config/configJsonSchema.js +++ b/packages/dashmate/src/config/configJsonSchema.js @@ -404,28 +404,40 @@ export default { filePath: { type: ['null', 'string'], minLength: 1, + description: 'Write logs only to stdout if null. Provide an absolute file path on' + + ' the host machine to also write to a log file there. Use a log file if logs must be' + + ' retained since stdout logs are stored inside the docker container' + + ' and removed if the container is removed.', }, debug: { type: 'object', properties: { enabled: { type: 'boolean', + description: 'Enable debug logging. Equivalent to setting "debug=1" in the Core configuration file)', }, ips: { type: 'boolean', + description: 'Include IP addresses in debug output', }, sourceLocations: { type: 'boolean', + description: 'Prepend debug output with name of the originating source' + + ' location (source file, line number and function name)', }, threadNames: { type: 'boolean', + description: 'Prepend debug output with name of the originating thread (only' + + ' available on platforms supporting thread_local)', }, timeMicros: { type: 'boolean', + description: 'Add microsecond precision to debug timestamps', }, includeOnly: { type: 'array', uniqueItems: true, + description: 'Log all categories if empty. Otherwise, log only the specified categories.', items: { type: 'string', enum: ['net', 'tor', 'mempool', 'http', 'bench', 'zmq', 'walletdb', 'rpc', 'estimatefee', @@ -437,6 +449,7 @@ export default { }, exclude: { type: 'array', + description: 'Exclude debugging information for one or more categories.', uniqueItems: true, items: { type: 'string', @@ -654,10 +667,12 @@ export default { properties: { level: { type: 'string', + description: 'Log level for gateway container logs', enum: ['trace', 'debug', 'info', 'warn', 'error', 'critical', 'off'], }, accessLogs: { type: 'array', + description: 'Envoy access logs', items: { oneOf: [ { @@ -667,7 +682,8 @@ export default { type: 'string', minLength: 1, enum: ['stdout', 'stderr'], - description: 'Access log type: stdout, stderr or file', + description: 'stdout, stderr or file (absolute file path on host' + + ' machine)', }, format: { type: 'string', @@ -693,7 +709,9 @@ export default { additionalProperties: { type: 'string', }, - description: 'JSON fields and values. If null, default template is used.', + description: 'JSON fields and values. If null, default template is' + + ' used. More info:' + + ' https://www.envoyproxy.io/docs/envoy/latest/configuration/observability/access_log/usage#format-dictionaries', }, }, required: ['template'], @@ -703,7 +721,9 @@ export default { properties: { template: { type: ['null', 'string'], - description: 'Template string. If null, default template is used.', + description: 'Template string. If null, default template is used.' + + ' More info:' + + ' https://www.envoyproxy.io/docs/envoy/latest/configuration/observability/access_log/usage#format-strings', }, }, required: ['template'], @@ -827,6 +847,7 @@ export default { }, logs: { type: 'object', + description: 'Define Drive logs', propertyNames: { type: 'string', minLength: 1, @@ -847,10 +868,13 @@ export default { }, format: { type: 'string', + description: 'Log format:' + + ' https://docs.rs/tracing-subscriber/latest/tracing_subscriber/fmt/format/index.html', enum: ['full', 'compact', 'pretty', 'json'], }, color: { type: ['boolean', 'null'], + description: 'Whether or not to use colorful output; defaults to autodetect', }, }, required: ['destination', 'level', 'format', 'color'], @@ -1115,17 +1139,21 @@ export default { level: { type: 'string', enum: ['trace', 'debug', 'info', 'warn', 'error'], + description: 'Log verbosity level', }, format: { type: 'string', enum: ['plain', 'json'], + description: 'Log format: text or json', }, path: { type: ['string', 'null'], minLength: 1, + description: 'Write to stdout only if null or to stdout and specified log' + + ' file (absolute file path on host machine)', }, }, - required: ['level', 'format'], + required: ['level', 'format', 'path'], additionalProperties: false, }, rpc: { diff --git a/packages/dashmate/src/config/generateEnvsFactory.js b/packages/dashmate/src/config/generateEnvsFactory.js index 781ef7bdaa..8d7823db07 100644 --- a/packages/dashmate/src/config/generateEnvsFactory.js +++ b/packages/dashmate/src/config/generateEnvsFactory.js @@ -69,6 +69,7 @@ export default function generateEnvsFactory(configFile, homeDir, getConfigProfil let driveAbciMetricsUrl = ''; if (config.get('platform.drive.abci.metrics.enabled')) { + // IP and port inside container driveAbciMetricsUrl = 'http://0.0.0.0:29090'; } diff --git a/packages/dashmate/src/createDIContainer.js b/packages/dashmate/src/createDIContainer.js index 9f3b861623..3b2e657d2b 100644 --- a/packages/dashmate/src/createDIContainer.js +++ b/packages/dashmate/src/createDIContainer.js @@ -23,6 +23,9 @@ import analyseSystemResourcesFactory from './doctor/analyse/analyseSystemResourc import analyseSamplesFactory from './doctor/analyseSamplesFactory.js'; import archiveSamples from './doctor/archiveSamples.js'; import unarchiveSamplesFactory from './doctor/unarchiveSamplesFactory.js'; +import cleanupZeroSSLCertificatesTaskFactory + from './listr/tasks/ssl/zerossl/cleanupZeroSSLCertificatesTaskFactory.js'; +import cancelCertificate from './ssl/zerossl/cancelCertificate.js'; import renderTemplateFactory from './templates/renderTemplateFactory.js'; import renderServiceTemplatesFactory from './templates/renderServiceTemplatesFactory.js'; @@ -206,6 +209,7 @@ export default async function createDIContainer(options = {}) { downloadCertificate: asValue(downloadCertificate), getCertificate: asValue(getCertificate), listCertificates: asValue(listCertificates), + cancelCertificate: asValue(cancelCertificate), createSelfSignedCertificate: asValue(createSelfSignedCertificate), verificationServer: asClass(VerificationServer).singleton(), }); @@ -299,6 +303,7 @@ export default async function createDIContainer(options = {}) { enableCoreQuorumsTask: asFunction(enableCoreQuorumsTaskFactory).singleton(), registerMasternodeGuideTask: asFunction(registerMasternodeGuideTaskFactory).singleton(), obtainZeroSSLCertificateTask: asFunction(obtainZeroSSLCertificateTaskFactory).singleton(), + cleanupZeroSSLCertificatesTask: asFunction(cleanupZeroSSLCertificatesTaskFactory).singleton(), obtainSelfSignedCertificateTask: asFunction(obtainSelfSignedCertificateTaskFactory).singleton(), saveCertificateTask: asFunction(saveCertificateTaskFactory), reindexNodeTask: asFunction(reindexNodeTaskFactory).singleton(), diff --git a/packages/dashmate/src/doctor/analyse/analyseConfigFactory.js b/packages/dashmate/src/doctor/analyse/analyseConfigFactory.js index 4bb65d0ffb..32c4355bde 100644 --- a/packages/dashmate/src/doctor/analyse/analyseConfigFactory.js +++ b/packages/dashmate/src/doctor/analyse/analyseConfigFactory.js @@ -160,13 +160,25 @@ and revoke the previous certificate in the ZeroSSL dashboard`, if (coreP2pPort && coreP2pPort !== 'OPEN') { const port = config.get('core.p2p.port'); const externalIp = config.get('externalIp'); - const problem = new Problem( - 'Core P2P port is unavailable for incoming connections.', - chalk`Please ensure that port ${port} on your public IP address ${externalIp} is open + + let solution = chalk`Please ensure that port ${port} on your public IP address ${externalIp} is open +for incoming connections. You may need to configure your firewall to +ensure this port is accessible from the public internet. If you are using +Network Address Translation (NAT), please enable port forwarding for port 80 +and all Dash service ports listed above.`; + if (externalIp) { + solution = chalk`Please ensure your configured IP address ${externalIp} is your public IP. +You can change it using {bold.cyanBright dashmate config set externalIp [IP]}. +Also, ensure that port ${port} on your public IP address is open for incoming connections. You may need to configure your firewall to ensure this port is accessible from the public internet. If you are using Network Address Translation (NAT), please enable port forwarding for port 80 -and all Dash service ports listed above.`, +and all Dash service ports listed above.`; + } + + const problem = new Problem( + 'Core P2P port is unavailable for incoming connections.', + solution, SEVERITY.HIGH, ); @@ -178,13 +190,25 @@ and all Dash service ports listed above.`, if (gatewayHttpPort && gatewayHttpPort !== 'OPEN') { const port = config.get('platform.gateway.listeners.dapiAndDrive.port'); const externalIp = config.get('externalIp'); - const problem = new Problem( - 'Gateway HTTP port is unavailable for incoming connections.', - chalk`Please ensure that port ${port} on your public IP address ${externalIp} is open + + let solution = chalk`Please ensure that port ${port} on your public IP address ${externalIp} is open +for incoming connections. You may need to configure your firewall to +ensure this port is accessible from the public internet. If you are using +Network Address Translation (NAT), please enable port forwarding for port 80 +and all Dash service ports listed above.`; + if (externalIp) { + solution = chalk`Please ensure your configured IP address ${externalIp} is your public IP. +You can change it using {bold.cyanBright dashmate config set externalIp [IP]}. +Also, ensure that port ${port} on your public IP address is open for incoming connections. You may need to configure your firewall to ensure this port is accessible from the public internet. If you are using Network Address Translation (NAT), please enable port forwarding for port 80 -and all Dash service ports listed above.`, +and all Dash service ports listed above.`; + } + + const problem = new Problem( + 'Gateway HTTP port is unavailable for incoming connections.', + solution, SEVERITY.HIGH, ); @@ -196,13 +220,25 @@ and all Dash service ports listed above.`, if (tenderdashP2pPort && tenderdashP2pPort !== 'OPEN') { const port = config.get('platform.drive.tenderdash.p2p.port'); const externalIp = config.get('externalIp'); - const problem = new Problem( - 'Tenderdash P2P port is unavailable for incoming connections.', - chalk`Please ensure that port ${port} on your public IP address ${externalIp} is open + + let solution = chalk`Please ensure that port ${port} on your public IP address ${externalIp} is open for incoming connections. You may need to configure your firewall to ensure this port is accessible from the public internet. If you are using Network Address Translation (NAT), please enable port forwarding for port 80 -and all Dash service ports listed above.`, +and all Dash service ports listed above.`; + if (externalIp) { + solution = chalk`Please ensure your configured IP address ${externalIp} is your public IP. +You can change it using {bold.cyanBright dashmate config set externalIp [IP]}. +Also, ensure that port ${port} on your public IP address is open +for incoming connections. You may need to configure your firewall to +ensure this port is accessible from the public internet. If you are using +Network Address Translation (NAT), please enable port forwarding for port 80 +and all Dash service ports listed above.`; + } + + const problem = new Problem( + 'Tenderdash P2P port is unavailable for incoming connections.', + solution, SEVERITY.HIGH, ); diff --git a/packages/dashmate/src/doctor/analyse/analyseServiceContainersFactory.js b/packages/dashmate/src/doctor/analyse/analyseServiceContainersFactory.js index 7cf6b6c696..4edd993b62 100644 --- a/packages/dashmate/src/doctor/analyse/analyseServiceContainersFactory.js +++ b/packages/dashmate/src/doctor/analyse/analyseServiceContainersFactory.js @@ -20,9 +20,12 @@ export default function analyseServiceContainersFactory( const servicesNotStarted = []; const servicesFailed = []; const servicesOOMKilled = []; + const servicesHighCpuUsage = []; + const servicesHighMemoryUsage = []; for (const service of services) { const dockerInspect = samples.getServiceInfo(service.name, 'dockerInspect'); + const dockerStats = samples.getServiceInfo(service.name, 'dockerStats'); if (!dockerInspect) { continue; @@ -47,6 +50,34 @@ export default function analyseServiceContainersFactory( service, }); } + + const cpuSystemUsage = dockerStats?.cpuStats?.system_cpu_usage ?? 0; + const cpuServiceUsage = dockerStats?.cpuStats?.cpu_usage?.total_usage ?? 0; + + if (cpuSystemUsage > 0) { + const cpuUsage = cpuServiceUsage / cpuSystemUsage; + + if (cpuUsage > 0.8) { + servicesHighCpuUsage.push({ + service, + cpuUsage, + }); + } + } + + const memoryLimit = dockerStats?.memoryStats?.limit ?? 0; + const memoryServiceUsage = dockerStats?.memoryStats?.usage ?? 0; + + if (memoryLimit > 0) { + const memoryUsage = memoryServiceUsage / memoryLimit; + + if (memoryUsage > 0.8) { + servicesHighMemoryUsage.push({ + service, + memoryUsage, + }); + } + } } const problems = []; @@ -103,6 +134,34 @@ export default function analyseServiceContainersFactory( problems.push(problem); } + if (servicesHighCpuUsage.length > 0) { + for (const highCpuService of servicesHighCpuUsage) { + const description = `Service ${highCpuService.service.title} is consuming ${(highCpuService.cpuUsage * 100).toFixed(2)}% CPU.`; + + const problem = new Problem( + description, + 'Consider upgrading CPU or report in case of misbehaviour.', + SEVERITY.MEDIUM, + ); + + problems.push(problem); + } + } + + if (servicesHighMemoryUsage.length > 0) { + for (const highMemoryService of servicesHighMemoryUsage) { + const description = `Service ${highMemoryService.service.title} is consuming ${(highMemoryService.memoryUsage * 100).toFixed(2)}% RAM.`; + + const problem = new Problem( + description, + 'Consider upgrading RAM or report in case of misbehaviour.', + SEVERITY.MEDIUM, + ); + + problems.push(problem); + } + } + return problems; } diff --git a/packages/dashmate/src/helper/scheduleRenewZeroSslCertificateFactory.js b/packages/dashmate/src/helper/scheduleRenewZeroSslCertificateFactory.js index c403c2bef3..8d741511dd 100644 --- a/packages/dashmate/src/helper/scheduleRenewZeroSslCertificateFactory.js +++ b/packages/dashmate/src/helper/scheduleRenewZeroSslCertificateFactory.js @@ -51,7 +51,7 @@ export default function scheduleRenewZeroSslCertificateFactory( } const job = new CronJob(expiresAt, async () => { - const tasks = await obtainZeroSSLCertificateTask(config); + const tasks = obtainZeroSSLCertificateTask(config); await tasks.run({ expirationDays: Certificate.EXPIRATION_LIMIT_DAYS, diff --git a/packages/dashmate/src/listr/tasks/doctor/collectSamplesTaskFactory.js b/packages/dashmate/src/listr/tasks/doctor/collectSamplesTaskFactory.js index 8e4ae5794a..3909edff78 100644 --- a/packages/dashmate/src/listr/tasks/doctor/collectSamplesTaskFactory.js +++ b/packages/dashmate/src/listr/tasks/doctor/collectSamplesTaskFactory.js @@ -2,6 +2,7 @@ import fs from 'fs'; import { Listr } from 'listr2'; import path from 'path'; import process from 'process'; +import si from 'systeminformation'; import obfuscateConfig from '../../../config/obfuscateConfig.js'; import { DASHMATE_VERSION } from '../../../constants.js'; import Certificate from '../../../ssl/zerossl/Certificate.js'; @@ -166,7 +167,8 @@ export default function collectSamplesTaskFactory( title: 'Core P2P port', task: async () => { const port = config.get('core.p2p.port'); - const response = await providers.mnowatch.checkPortStatus(port); + const response = await providers.mnowatch.checkPortStatus(port, config.get('externalIp')) + .catch((e) => e.toString()); ctx.samples.setServiceInfo('core', 'p2pPort', response); }, @@ -176,7 +178,8 @@ export default function collectSamplesTaskFactory( enabled: () => config.get('platform.enable'), task: async () => { const port = config.get('platform.gateway.listeners.dapiAndDrive.port'); - const response = await providers.mnowatch.checkPortStatus(port); + const response = await providers.mnowatch.checkPortStatus(port, config.get('externalIp')) + .catch((e) => e.toString()); ctx.samples.setServiceInfo('gateway', 'httpPort', response); }, @@ -185,7 +188,8 @@ export default function collectSamplesTaskFactory( title: 'Tenderdash P2P port', task: async () => { const port = config.get('platform.drive.tenderdash.p2p.port'); - const response = await providers.mnowatch.checkPortStatus(port); + const response = await providers.mnowatch.checkPortStatus(port, config.get('externalIp')) + .catch((e) => e.toString()); ctx.samples.setServiceInfo('drive_tenderdash', 'p2pPort', response); }, @@ -312,13 +316,10 @@ export default function collectSamplesTaskFactory( }, }, { - title: 'Logs', - task: async (ctx, task) => { + title: 'Docker containers info', + task: async (ctx) => { const services = await getServiceList(config); - // eslint-disable-next-line no-param-reassign - task.output = `Pulling logs from ${services.map((e) => e.name)}`; - await Promise.all( services.map(async (service) => { const [inspect, logs] = (await Promise.allSettled([ @@ -326,6 +327,12 @@ export default function collectSamplesTaskFactory( dockerCompose.logs(config, [service.name], { tail: 300000 }), ])).map((e) => e.value || e.reason); + const containerId = inspect?.Id; + let dockerStats; + if (containerId) { + dockerStats = await si.dockerContainerStats(containerId); + } + if (logs?.out) { // Hide username & external ip from logs logs.out = logs.out.replaceAll( @@ -354,6 +361,7 @@ export default function collectSamplesTaskFactory( ctx.samples.setServiceInfo(service.name, 'stdOut', logs?.out); ctx.samples.setServiceInfo(service.name, 'stdErr', logs?.err); ctx.samples.setServiceInfo(service.name, 'dockerInspect', inspect); + ctx.samples.setServiceInfo(service.name, 'dockerStats', dockerStats); }), ); }, diff --git a/packages/dashmate/src/listr/tasks/ssl/zerossl/cleanupZeroSSLCertificatesTaskFactory.js b/packages/dashmate/src/listr/tasks/ssl/zerossl/cleanupZeroSSLCertificatesTaskFactory.js new file mode 100644 index 0000000000..f38d62562d --- /dev/null +++ b/packages/dashmate/src/listr/tasks/ssl/zerossl/cleanupZeroSSLCertificatesTaskFactory.js @@ -0,0 +1,98 @@ +import chalk from 'chalk'; +import { Listr } from 'listr2'; +import { Observable } from 'rxjs'; +import wait from '../../../../util/wait.js'; + +/** + * @param {listCertificates} listCertificates + * @param {cancelCertificate} cancelCertificate + * @return {cleanupZeroSSLCertificatesTask} + */ +export default function cleanupZeroSSLCertificatesTaskFactory( + listCertificates, + cancelCertificate, +) { + /** + * @typedef {cleanupZeroSSLCertificatesTask} + * @param {Config} config + * @return {Listr} + */ + function cleanupZeroSSLCertificatesTask(config) { + const apiKey = config.get('platform.gateway.ssl.providerConfigs.zerossl.apiKey', true); + + return new Listr([ + { + title: 'Collect drafted and pending validation certificates', + // Skips the check if force flag is set + task: async (ctx, task) => { + ctx.certificates = []; + + let certificatesPerRequest = []; + let page = 1; + + // Fetch all certificates in draft or pending validation status + // with pagination + do { + certificatesPerRequest = await listCertificates(apiKey, ['draft', 'pending_validation'], page); + + ctx.certificates = ctx.certificates.concat(certificatesPerRequest); + + page += 1; + + // eslint-disable-next-line no-param-reassign + task.output = `Found ${ctx.certificates.length} certificates`; + } while (certificatesPerRequest.length === 1000); + + ctx.total = ctx.certificates.length; + }, + }, + { + title: 'Cancel certificates', + skip: (ctx) => ctx.certificates.length === 0, + task: async (ctx, task) => { + // eslint-disable-next-line no-param-reassign + task.title = `Cancel ${ctx.certificates.length} certificates`; + ctx.canceled = 0; + ctx.errored = 0; + return new Observable(async (observer) => { + for (const certificate of ctx.certificates) { + try { + await cancelCertificate(apiKey, certificate.id); + + ctx.canceled += 1; + } catch (e) { + ctx.errored += 1; + + if (process.env.DEBUG) { + // eslint-disable-next-line no-console + console.warn(e); + } + } + + observer.next(chalk`{green ${ctx.canceled}} / {red ${ctx.errored}} / ${ctx.total}`); + + await wait(100); + } + + if (ctx.errored > 0) { + observer.error(new Error('Some certificates were not canceled. Please try again.')); + } else { + observer.complete(); + } + + return this; + }); + }, + options: { + persistentOutput: true, + }, + }, + ], { + rendererOptions: { + showErrorMessage: true, + }, + }); + } + + return cleanupZeroSSLCertificatesTask; +} diff --git a/packages/dashmate/src/listr/tasks/ssl/zerossl/obtainZeroSSLCertificateTaskFactory.js b/packages/dashmate/src/listr/tasks/ssl/zerossl/obtainZeroSSLCertificateTaskFactory.js index ca679233d0..71d7b7809b 100644 --- a/packages/dashmate/src/listr/tasks/ssl/zerossl/obtainZeroSSLCertificateTaskFactory.js +++ b/packages/dashmate/src/listr/tasks/ssl/zerossl/obtainZeroSSLCertificateTaskFactory.js @@ -18,6 +18,8 @@ import { ERRORS } from '../../../../ssl/zerossl/validateZeroSslCertificateFactor * @param {VerificationServer} verificationServer * @param {HomeDir} homeDir * @param {validateZeroSslCertificate} validateZeroSslCertificate + * @param {ConfigFileJsonRepository} configFileRepository + * @param {ConfigFile} configFile * @return {obtainZeroSSLCertificateTask} */ export default function obtainZeroSSLCertificateTaskFactory( @@ -32,13 +34,15 @@ export default function obtainZeroSSLCertificateTaskFactory( verificationServer, homeDir, validateZeroSslCertificate, + configFileRepository, + configFile, ) { /** * @typedef {obtainZeroSSLCertificateTask} * @param {Config} config - * @return {Promise} + * @return {Listr} */ - async function obtainZeroSSLCertificateTask(config) { + function obtainZeroSSLCertificateTask(config) { return new Listr([ { title: 'Check if certificate already exists and not expiring soon', @@ -141,6 +145,9 @@ export default function obtainZeroSSLCertificateTaskFactory( config.set('platform.gateway.ssl.enabled', true); config.set('platform.gateway.ssl.provider', 'zerossl'); config.set('platform.gateway.ssl.providerConfigs.zerossl.id', ctx.certificate.id); + + // Save config file + configFileRepository.write(configFile); }, }, { diff --git a/packages/dashmate/src/ssl/zerossl/cancelCertificate.js b/packages/dashmate/src/ssl/zerossl/cancelCertificate.js index 5a4e131674..2d8f9dfa9b 100644 --- a/packages/dashmate/src/ssl/zerossl/cancelCertificate.js +++ b/packages/dashmate/src/ssl/zerossl/cancelCertificate.js @@ -1,4 +1,4 @@ -import requestApi from './requestApi'; +import requestApi from './requestApi.js'; /** * Get ZeroSSL certificate diff --git a/packages/dashmate/src/ssl/zerossl/listCertificates.js b/packages/dashmate/src/ssl/zerossl/listCertificates.js index 63dad29283..f7530cee4c 100644 --- a/packages/dashmate/src/ssl/zerossl/listCertificates.js +++ b/packages/dashmate/src/ssl/zerossl/listCertificates.js @@ -8,12 +8,18 @@ import Certificate from './Certificate.js'; * @param {string} apiKey * @param {String[]} [statuses] - possible values: draft, pending_validation, issued, cancelled, * revoked, expired. + * @param {number} [page] * @param {string} [search] * @return {Promise} */ -export default async function listCertificates(apiKey, statuses = [], search = undefined) { - let url = `https://api.zerossl.com/certificates?access_key=${apiKey}&limit=1000`; +export default async function listCertificates( + apiKey, + statuses = [], + page = 1, + search = undefined, +) { + let url = `https://api.zerossl.com/certificates?access_key=${apiKey}&limit=1000&page=${page}`; if (statuses.length > 0) { url += `&statuses=${statuses.join(',')}`; diff --git a/packages/dashmate/src/ssl/zerossl/validateZeroSslCertificateFactory.js b/packages/dashmate/src/ssl/zerossl/validateZeroSslCertificateFactory.js index 20b221216c..53f3da5b56 100644 --- a/packages/dashmate/src/ssl/zerossl/validateZeroSslCertificateFactory.js +++ b/packages/dashmate/src/ssl/zerossl/validateZeroSslCertificateFactory.js @@ -104,10 +104,7 @@ export default function validateZeroSslCertificateFactory(homeDir, getCertificat } if (['pending_validation', 'draft'].includes(data.certificate.status)) { - // Certificate is already created, so we just need to pass validation - // and download certificate file - - // We need to download new certificate bundle + // We need to validate and download new certificate bundle data.isBundleFilePresent = false; return { @@ -116,6 +113,9 @@ export default function validateZeroSslCertificateFactory(homeDir, getCertificat }; } + // Certificate is already created at this point, so we just need to pass validation + // and download certificate file + if (data.certificate.status !== 'issued' || data.isExpiresSoon) { // Certificate is going to expire soon, or current certificate is not valid // we need to obtain a new one diff --git a/packages/dashmate/src/status/determineStatus.js b/packages/dashmate/src/status/determineStatus.js index 723302a006..b089f1f7f7 100644 --- a/packages/dashmate/src/status/determineStatus.js +++ b/packages/dashmate/src/status/determineStatus.js @@ -49,6 +49,10 @@ export default { return coreIsSynced ? ServiceStatusEnum.up : ServiceStatusEnum.wait_for_core; } + if (dockerStatus === DockerStatusEnum.not_started) { + return ServiceStatusEnum.stopped; + } + return ServiceStatusEnum.error; }, }; diff --git a/packages/dashmate/src/status/providers.js b/packages/dashmate/src/status/providers.js index 2eee8a72f5..24594477c1 100644 --- a/packages/dashmate/src/status/providers.js +++ b/packages/dashmate/src/status/providers.js @@ -1,5 +1,4 @@ import https from 'https'; -import { PortStateEnum } from './enums/portState.js'; const MAX_REQUEST_TIMEOUT = 5000; const MAX_RESPONSE_SIZE = 1 * 1024 * 1024; // 1 MB @@ -63,7 +62,14 @@ export default { }, }, mnowatch: { - checkPortStatus: async (port) => { + /** + * Check the status of a port and optionally validate an IP address. + * + * @param {number} port - The port number to check. + * @param {string} [ip] - Optional. The IP address to validate. + * @returns {Promise} A promise that resolves to the port status. + */ + checkPortStatus: async (port, ip = undefined) => { // We use http request instead fetch function to force // using IPv4 otherwise mnwatch could try to connect to IPv6 node address // and fail (Core listens for IPv4 only) @@ -72,13 +78,12 @@ export default { const options = { hostname: 'mnowatch.org', port: 443, - path: `/${port}/`, + path: ip ? `/${port}/?validateIp=${ip}` : `/${port}/`, method: 'GET', family: 4, // Force IPv4 - timeout: MAX_REQUEST_TIMEOUT, }; - return new Promise((resolve) => { + return new Promise((resolve, reject) => { const req = https.request(options, (res) => { let data = ''; @@ -88,9 +93,12 @@ export default { // eslint-disable-next-line no-console console.warn(`Port check request failed with status code ${res.statusCode}`); } - // Consume response data to free up memory - res.resume(); - resolve(PortStateEnum.ERROR); + + const error = new Error(`Invalid status code ${res.statusCode}`); + + res.destroy(error); + + // Do not handle request further return; } @@ -102,14 +110,14 @@ export default { data += chunk; if (data.length > MAX_RESPONSE_SIZE) { - resolve(PortStateEnum.ERROR); - if (process.env.DEBUG) { // eslint-disable-next-line no-console console.warn('Port check response size exceeded'); } - req.destroy(); + const error = new Error('Response size exceeded'); + + req.destroy(error); } }); @@ -119,13 +127,19 @@ export default { }); }); + req.setTimeout(MAX_REQUEST_TIMEOUT, () => { + const error = new Error('Port check timed out'); + + req.destroy(error); + }); + req.on('error', (e) => { if (process.env.DEBUG) { // eslint-disable-next-line no-console console.warn(`Port check request failed: ${e}`); } - resolve(PortStateEnum.ERROR); + reject(e); }); req.end(); diff --git a/packages/dashmate/src/status/scopes/core.js b/packages/dashmate/src/status/scopes/core.js index d983bcd67c..63132d77f5 100644 --- a/packages/dashmate/src/status/scopes/core.js +++ b/packages/dashmate/src/status/scopes/core.js @@ -1,4 +1,5 @@ /* eslint-disable camelcase */ +import { PortStateEnum } from '../enums/portState.js'; import providers from '../providers.js'; import { ServiceStatusEnum } from '../enums/serviceStatus.js'; import { DockerStatusEnum } from '../enums/dockerStatus.js'; @@ -116,7 +117,8 @@ export default function getCoreScopeFactory( const providersResult = await Promise.allSettled([ providers.github.release('dashpay/dash'), - providers.mnowatch.checkPortStatus(config.get('core.p2p.port')), + providers.mnowatch.checkPortStatus(config.get('core.p2p.port'), config.get('externalIp')) + .catch(() => PortStateEnum.ERROR), providers.insight(config.get('network')).status(), ]); diff --git a/packages/dashmate/src/status/scopes/overview.js b/packages/dashmate/src/status/scopes/overview.js index a38d9ffb5e..2a56bd3678 100644 --- a/packages/dashmate/src/status/scopes/overview.js +++ b/packages/dashmate/src/status/scopes/overview.js @@ -57,8 +57,9 @@ export default function getOverviewScopeFactory( } if (config.get('platform.enable')) { - const { tenderdash } = await getPlatformScope(config); + const { drive, tenderdash } = await getPlatformScope(config); + platform.drive = drive; platform.tenderdash = tenderdash; } diff --git a/packages/dashmate/src/status/scopes/platform.js b/packages/dashmate/src/status/scopes/platform.js index f18b291549..c3fe48d8e8 100644 --- a/packages/dashmate/src/status/scopes/platform.js +++ b/packages/dashmate/src/status/scopes/platform.js @@ -1,4 +1,6 @@ import prettyMs from 'pretty-ms'; +import { PortStateEnum } from '../enums/portState.js'; +import DockerComposeError from '../../docker/errors/DockerComposeError.js'; import providers from '../providers.js'; import { DockerStatusEnum } from '../enums/dockerStatus.js'; import { ServiceStatusEnum } from '../enums/serviceStatus.js'; @@ -51,6 +53,8 @@ export default function getPlatformScopeFactory( dockerStatus: null, serviceStatus: null, version: null, + protocolVersion: null, + desiredProtocolVersion: null, listening: null, catchingUp: null, latestBlockHash: null, @@ -89,8 +93,10 @@ export default function getPlatformScopeFactory( // Collecting platform data fails if Tenderdash is waiting for core to sync if (info.serviceStatus === ServiceStatusEnum.up) { const portStatusResult = await Promise.allSettled([ - providers.mnowatch.checkPortStatus(config.get('platform.gateway.listeners.dapiAndDrive.port')), - providers.mnowatch.checkPortStatus(config.get('platform.drive.tenderdash.p2p.port')), + providers.mnowatch.checkPortStatus(config.get('platform.gateway.listeners.dapiAndDrive.port'), config.get('externalIp')) + .catch(() => PortStateEnum.ERROR), + providers.mnowatch.checkPortStatus(config.get('platform.drive.tenderdash.p2p.port'), config.get('externalIp')) + .catch(() => PortStateEnum.ERROR), ]); const [httpPortState, p2pPortState] = portStatusResult.map((result) => (result.status === 'fulfilled' ? result.value : null)); @@ -106,14 +112,20 @@ export default function getPlatformScopeFactory( const port = config.get('platform.drive.tenderdash.rpc.port'); - const [tenderdashStatusResponse, tenderdashNetInfoResponse] = await Promise.all([ + const [ + tenderdashStatusResponse, + tenderdashNetInfoResponse, + tenderdashAbciInfoResponse, + ] = await Promise.all([ fetch(`http://${tenderdashHost}:${port}/status`), fetch(`http://${tenderdashHost}:${port}/net_info`), + fetch(`http://${tenderdashHost}:${port}/abci_info`), ]); - const [tenderdashStatus, tenderdashNetInfo] = await Promise.all([ + const [tenderdashStatus, tenderdashNetInfo, tenderdashAbciInfo] = await Promise.all([ tenderdashStatusResponse.json(), tenderdashNetInfoResponse.json(), + tenderdashAbciInfoResponse.json(), ]); const { version, network, moniker } = tenderdashStatus.node_info; @@ -132,6 +144,8 @@ export default function getPlatformScopeFactory( } info.version = version; + info.protocolVersion = parseInt(tenderdashStatus.node_info.protocol_version.app, 10); + info.desiredProtocolVersion = tenderdashAbciInfo.response.app_version; info.listening = listening; info.latestBlockHeight = latestBlockHeight; info.latestBlockTime = latestBlockTime; @@ -158,35 +172,58 @@ export default function getPlatformScopeFactory( const info = { dockerStatus: null, serviceStatus: null, + version: null, }; try { info.dockerStatus = await determineStatus.docker(dockerCompose, config, 'drive_abci'); - info.serviceStatus = determineStatus.platform(info.dockerStatus, isCoreSynced, mnRRSoftFork); + } catch (e) { + if (e instanceof ContainerIsNotPresentError) { + info.dockerStatus = DockerStatusEnum.not_started; + } else { + throw e; + } + } + + info.serviceStatus = determineStatus.platform(info.dockerStatus, isCoreSynced, mnRRSoftFork); - if (info.serviceStatus === ServiceStatusEnum.up) { - const driveEchoResult = await dockerCompose.execCommand( + // Get Drive status to make sure it's responding + if (info.serviceStatus === ServiceStatusEnum.up) { + try { + await dockerCompose.execCommand( config, 'drive_abci', 'drive-abci status', ); - - if (driveEchoResult.exitCode !== 0) { + } catch (e) { + if (e instanceof DockerComposeError + && e.dockerComposeExecutionResult + && e.dockerComposeExecutionResult.exitCode !== 0) { info.serviceStatus = ServiceStatusEnum.error; + } else { + throw e; } } + } - return info; + try { + const driveVersionResult = await dockerCompose.execCommand( + config, + 'drive_abci', + 'drive-abci version', + ); + + info.version = driveVersionResult.out.trim(); } catch (e) { - if (e instanceof ContainerIsNotPresentError) { - return { - dockerStatus: DockerStatusEnum.not_started, - serviceStatus: ServiceStatusEnum.stopped, - }; + // Throw an error if it's not a Drive issue + if (!(e instanceof DockerComposeError + && e.dockerComposeExecutionResult + && e.dockerComposeExecutionResult.exitCode !== 0)) { + throw e; } - - return info; } + + return info; }; /** @@ -221,6 +258,8 @@ export default function getPlatformScopeFactory( dockerStatus: null, serviceStatus: null, version: null, + protocolVersion: null, + desiredProtocolVersion: null, listening: null, catchingUp: null, latestBlockHash: null, @@ -234,6 +273,7 @@ export default function getPlatformScopeFactory( drive: { dockerStatus: null, serviceStatus: null, + version: null, }, }; diff --git a/packages/dashmate/test/e2e/localNetwork.spec.js b/packages/dashmate/test/e2e/localNetwork.spec.js index d1f8c7bb7b..ab44a55991 100644 --- a/packages/dashmate/test/e2e/localNetwork.spec.js +++ b/packages/dashmate/test/e2e/localNetwork.spec.js @@ -129,6 +129,7 @@ describe('Local Network', function main() { const task = restartNodeTask(config); await task.run({ isVerbose: true, + isForce: true, }); } @@ -146,6 +147,7 @@ describe('Local Network', function main() { const task = stopNodeTask(config); await task.run({ isVerbose: true, + isForce: true, }); } diff --git a/packages/dashmate/test/e2e/testnetEvonode.spec.js b/packages/dashmate/test/e2e/testnetEvonode.spec.js index 1e8f90d5ab..5ffd9e3f94 100644 --- a/packages/dashmate/test/e2e/testnetEvonode.spec.js +++ b/packages/dashmate/test/e2e/testnetEvonode.spec.js @@ -148,7 +148,7 @@ describe('Testnet Evonode', function main() { await task.run({ isVerbose: true, - isSafe: true, + isForce: true, }); // TODO: Assert all services are running @@ -232,7 +232,7 @@ describe('Testnet Evonode', function main() { await task.run({ isVerbose: true, - isSafe: true, + isForce: true, }); // TODO: Assert all services are running diff --git a/packages/dashmate/test/unit/status/scopes/core.spec.js b/packages/dashmate/test/unit/status/scopes/core.spec.js index b9c5c0de55..9587684f7f 100644 --- a/packages/dashmate/test/unit/status/scopes/core.spec.js +++ b/packages/dashmate/test/unit/status/scopes/core.spec.js @@ -78,7 +78,7 @@ describe('getCoreScopeFactory', () => { }); mockGithubProvider.returns('v1337-dev'); - mockMNOWatchProvider.returns('OPEN'); + mockMNOWatchProvider.resolves('OPEN'); mockInsightProvider.returns({ status: this.sinon.stub().returns({ info: { blocks: 1337 }, @@ -219,7 +219,7 @@ describe('getCoreScopeFactory', () => { }); mockGithubProvider.returns('v1337-dev'); - mockMNOWatchProvider.returns('OPEN'); + mockMNOWatchProvider.resolves('OPEN'); mockInsightProvider.returns({ status: this.sinon.stub().returns({ info: { blocks: 1337 }, @@ -271,7 +271,7 @@ describe('getCoreScopeFactory', () => { }); mockGithubProvider.returns(Promise.reject()); - mockMNOWatchProvider.returns(PortStateEnum.ERROR); + mockMNOWatchProvider.rejects(PortStateEnum.ERROR); mockInsightProvider.returns({ status: () => Promise.reject(), }); diff --git a/packages/dashmate/test/unit/status/scopes/platform.spec.js b/packages/dashmate/test/unit/status/scopes/platform.spec.js index c3a1c28ff1..14f0d88cff 100644 --- a/packages/dashmate/test/unit/status/scopes/platform.spec.js +++ b/packages/dashmate/test/unit/status/scopes/platform.spec.js @@ -1,3 +1,6 @@ +import ContainerIsNotPresentError + from '../../../../src/docker/errors/ContainerIsNotPresentError.js'; +import DockerComposeError from '../../../../src/docker/errors/DockerComposeError.js'; import providers from '../../../../src/status/providers.js'; import determineStatus from '../../../../src/status/determineStatus.js'; import getConfigMock from '../../../../src/test/mock/getConfigMock.js'; @@ -71,11 +74,17 @@ describe('getPlatformScopeFactory', () => { }, }); mockDockerCompose.isServiceRunning.returns(true); - mockDockerCompose.execCommand.returns({ exitCode: 0, out: '' }); + mockDockerCompose.execCommand.withArgs(config, 'drive_abci', 'drive-abci status').resolves({ exitCode: 0, out: '' }); + mockDockerCompose.execCommand.withArgs(config, 'drive_abci', 'drive-abci version').resolves({ exitCode: 0, out: '1.4.1' }); mockMNOWatchProvider.returns(Promise.resolve('OPEN')); const mockStatus = { node_info: { + protocol_version: { + p2p: '10', + block: '14', + app: '3', + }, version: '0', network: 'test', moniker: 'test', @@ -90,6 +99,15 @@ describe('getPlatformScopeFactory', () => { }; const mockNetInfo = { n_peers: 6, listening: true }; + const mockAbciInfo = { + response: { + version: '1.4.1', + app_version: 4, + last_block_height: 90, + last_block_app_hash: 's0CySQxgRg96DrnJ7HCsql+k/Sk4JiT3y0psCaUI3TI=', + }, + }; + const expectedScope = { platformActivation: 'Activated (at height 1337)', coreIsSynced: true, @@ -105,6 +123,8 @@ describe('getPlatformScopeFactory', () => { p2pPortState: PortStateEnum.OPEN, dockerStatus: DockerStatusEnum.running, serviceStatus: ServiceStatusEnum.up, + protocolVersion: 3, + desiredProtocolVersion: 4, version: '0', listening: true, catchingUp: false, @@ -119,6 +139,7 @@ describe('getPlatformScopeFactory', () => { drive: { dockerStatus: DockerStatusEnum.running, serviceStatus: ServiceStatusEnum.up, + version: '1.4.1', }, }; @@ -126,7 +147,9 @@ describe('getPlatformScopeFactory', () => { .onFirstCall() .returns(Promise.resolve({ json: () => Promise.resolve(mockStatus) })) .onSecondCall() - .returns(Promise.resolve({ json: () => Promise.resolve(mockNetInfo) })); + .returns(Promise.resolve({ json: () => Promise.resolve(mockNetInfo) })) + .onThirdCall() + .resolves({ json: () => Promise.resolve(mockAbciInfo) }); mockMNOWatchProvider.returns(Promise.resolve('OPEN')); const scope = await getPlatformScope(config); @@ -145,11 +168,16 @@ describe('getPlatformScopeFactory', () => { }, }); mockDockerCompose.isServiceRunning.returns(true); - mockDockerCompose.execCommand.returns({ exitCode: 0, out: '' }); + mockDockerCompose.execCommand.withArgs(config, 'drive_abci', 'drive-abci version').resolves({ exitCode: 0, out: '1.4.1' }); mockMNOWatchProvider.returns(Promise.resolve('OPEN')); const mockStatus = { node_info: { + protocol_version: { + p2p: '10', + block: '14', + app: '3', + }, version: '0', network: 'test', moniker: 'test', @@ -164,6 +192,15 @@ describe('getPlatformScopeFactory', () => { }; const mockNetInfo = { n_peers: 6, listening: true }; + const mockAbciInfo = { + response: { + version: '1.4.1', + app_version: 4, + last_block_height: 90, + last_block_app_hash: 's0CySQxgRg96DrnJ7HCsql+k/Sk4JiT3y0psCaUI3TI=', + }, + }; + const expectedScope = { platformActivation: 'Activated (at height 1337)', coreIsSynced: true, @@ -180,6 +217,8 @@ describe('getPlatformScopeFactory', () => { dockerStatus: DockerStatusEnum.running, serviceStatus: ServiceStatusEnum.syncing, version: '0', + protocolVersion: 3, + desiredProtocolVersion: 4, listening: true, catchingUp: true, latestBlockHash: 'DEADBEEF', @@ -193,6 +232,7 @@ describe('getPlatformScopeFactory', () => { drive: { dockerStatus: DockerStatusEnum.running, serviceStatus: ServiceStatusEnum.up, + version: '1.4.1', }, }; @@ -200,7 +240,9 @@ describe('getPlatformScopeFactory', () => { .onFirstCall() .returns(Promise.resolve({ json: () => Promise.resolve(mockStatus) })) .onSecondCall() - .returns(Promise.resolve({ json: () => Promise.resolve(mockNetInfo) })); + .returns(Promise.resolve({ json: () => Promise.resolve(mockNetInfo) })) + .onThirdCall() + .resolves({ json: () => Promise.resolve(mockAbciInfo) }); mockMNOWatchProvider.returns(Promise.resolve('OPEN')); const scope = await getPlatformScope(config); @@ -210,7 +252,6 @@ describe('getPlatformScopeFactory', () => { it('should return empty scope if error during request to core', async () => { mockRpcClient.mnsync.withArgs('status').throws(new Error()); - mockDockerCompose.execCommand.returns({ exitCode: 0, out: '' }); mockDockerCompose.isServiceRunning.returns(true); mockDetermineDockerStatus.withArgs(mockDockerCompose, config, 'drive_tenderdash') .returns(DockerStatusEnum.running); @@ -233,6 +274,8 @@ describe('getPlatformScopeFactory', () => { dockerStatus: null, serviceStatus: null, version: null, + protocolVersion: null, + desiredProtocolVersion: null, listening: null, catchingUp: null, latestBlockHash: null, @@ -246,6 +289,7 @@ describe('getPlatformScopeFactory', () => { drive: { dockerStatus: null, serviceStatus: null, + version: null, }, }; @@ -266,7 +310,7 @@ describe('getPlatformScopeFactory', () => { }, }, }); - mockDockerCompose.execCommand.returns({ exitCode: 1, out: '' }); + mockDockerCompose.execCommand.withArgs(config, 'drive_abci', 'drive-abci version').resolves({ exitCode: 0, out: '1.4.1' }); mockMNOWatchProvider.returns(Promise.resolve('OPEN')); const expectedScope = { @@ -285,6 +329,8 @@ describe('getPlatformScopeFactory', () => { dockerStatus: DockerStatusEnum.running, serviceStatus: ServiceStatusEnum.wait_for_core, version: null, + protocolVersion: null, + desiredProtocolVersion: null, listening: null, catchingUp: null, latestBlockHash: null, @@ -298,6 +344,7 @@ describe('getPlatformScopeFactory', () => { drive: { dockerStatus: DockerStatusEnum.running, serviceStatus: ServiceStatusEnum.wait_for_core, + version: '1.4.1', }, }; @@ -322,7 +369,7 @@ describe('getPlatformScopeFactory', () => { .returns(DockerStatusEnum.running); mockDetermineDockerStatus.withArgs(mockDockerCompose, config, 'drive_abci') .returns(DockerStatusEnum.running); - mockDockerCompose.execCommand.returns({ exitCode: 0, out: '' }); + mockDockerCompose.execCommand.withArgs(config, 'drive_abci', 'drive-abci version').resolves({ exitCode: 0, out: '1.4.1' }); mockMNOWatchProvider.returns(Promise.resolve('OPEN')); const expectedScope = { @@ -341,6 +388,8 @@ describe('getPlatformScopeFactory', () => { dockerStatus: DockerStatusEnum.running, serviceStatus: ServiceStatusEnum.error, version: null, + protocolVersion: null, + desiredProtocolVersion: null, listening: null, catchingUp: null, latestBlockHash: null, @@ -354,6 +403,7 @@ describe('getPlatformScopeFactory', () => { drive: { dockerStatus: DockerStatusEnum.running, serviceStatus: ServiceStatusEnum.up, + version: '1.4.1', }, }; @@ -377,12 +427,20 @@ describe('getPlatformScopeFactory', () => { mockDetermineDockerStatus.withArgs(mockDockerCompose, config, 'drive_tenderdash') .returns(DockerStatusEnum.running); mockDetermineDockerStatus.withArgs(mockDockerCompose, config, 'drive_abci') - .throws(); - mockDockerCompose.execCommand.returns({ exitCode: 0, out: '' }); + .throws(new ContainerIsNotPresentError('drive_abci')); mockMNOWatchProvider.returns(Promise.resolve('OPEN')); + const error = new DockerComposeError({ + exitCode: 1, + }); + mockDockerCompose.execCommand.withArgs(config, 'drive_abci', 'drive-abci version').rejects(error); const mockStatus = { node_info: { + protocol_version: { + p2p: '10', + block: '14', + app: '3', + }, version: '0', network: 'test', moniker: 'test', @@ -397,11 +455,22 @@ describe('getPlatformScopeFactory', () => { }; const mockNetInfo = { n_peers: 6, listening: true }; + const mockAbciInfo = { + response: { + version: '1.4.1', + app_version: 4, + last_block_height: 90, + last_block_app_hash: 's0CySQxgRg96DrnJ7HCsql+k/Sk4JiT3y0psCaUI3TI=', + }, + }; + mockFetch .onFirstCall() .returns(Promise.resolve({ json: () => Promise.resolve(mockStatus) })) .onSecondCall() - .returns(Promise.resolve({ json: () => Promise.resolve(mockNetInfo) })); + .returns(Promise.resolve({ json: () => Promise.resolve(mockNetInfo) })) + .onThirdCall() + .resolves({ json: () => Promise.resolve(mockAbciInfo) }); const expectedScope = { platformActivation: 'Activated (at height 1337)', @@ -419,6 +488,8 @@ describe('getPlatformScopeFactory', () => { dockerStatus: DockerStatusEnum.running, serviceStatus: ServiceStatusEnum.up, version: '0', + protocolVersion: 3, + desiredProtocolVersion: 4, listening: true, catchingUp: false, latestBlockHash: 'DEADBEEF', @@ -430,8 +501,9 @@ describe('getPlatformScopeFactory', () => { network: 'test', }, drive: { - dockerStatus: null, - serviceStatus: null, + dockerStatus: DockerStatusEnum.not_started, + serviceStatus: ServiceStatusEnum.stopped, + version: null, }, }; @@ -452,7 +524,8 @@ describe('getPlatformScopeFactory', () => { mockDockerCompose.isServiceRunning .withArgs(config, 'drive_tenderdash') .returns(true); - mockDockerCompose.execCommand.returns({ exitCode: 0, out: '' }); + mockDockerCompose.execCommand.withArgs(config, 'drive_abci', 'drive-abci status').resolves({ exitCode: 0, out: '' }); + mockDockerCompose.execCommand.withArgs(config, 'drive_abci', 'drive-abci version').resolves({ exitCode: 0, out: '1.4.1' }); mockDetermineDockerStatus.returns(DockerStatusEnum.running); mockMNOWatchProvider.returns(Promise.resolve('OPEN')); mockFetch.returns(Promise.reject(new Error('FetchError'))); @@ -473,6 +546,8 @@ describe('getPlatformScopeFactory', () => { dockerStatus: DockerStatusEnum.running, serviceStatus: ServiceStatusEnum.error, version: null, + protocolVersion: null, + desiredProtocolVersion: null, listening: null, catchingUp: null, latestBlockHash: null, @@ -486,6 +561,7 @@ describe('getPlatformScopeFactory', () => { drive: { dockerStatus: DockerStatusEnum.running, serviceStatus: ServiceStatusEnum.up, + version: '1.4.1', }, }; diff --git a/packages/dashpay-contract/Cargo.toml b/packages/dashpay-contract/Cargo.toml index c1ad4fa8b1..234be65b39 100644 --- a/packages/dashpay-contract/Cargo.toml +++ b/packages/dashpay-contract/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "dashpay-contract" description = "DashPay data contract schema and tools" -version = "1.3.1" +version = "1.5.0" edition = "2021" rust-version.workspace = true license = "MIT" [dependencies] platform-version = { path = "../rs-platform-version" } -thiserror = "1.0.58" +thiserror = "1.0.64" serde_json = { version = "1.0" } platform-value = { path = "../rs-platform-value" } diff --git a/packages/dashpay-contract/package.json b/packages/dashpay-contract/package.json index a7a2812837..02f96b5e84 100644 --- a/packages/dashpay-contract/package.json +++ b/packages/dashpay-contract/package.json @@ -1,6 +1,6 @@ { "name": "@dashevo/dashpay-contract", - "version": "1.3.1", + "version": "1.5.0", "description": "Reference contract of the DashPay DPA on Dash Evolution", "scripts": { "lint": "eslint .", diff --git a/packages/data-contracts/Cargo.toml b/packages/data-contracts/Cargo.toml index 34b7f51289..248f8886e2 100644 --- a/packages/data-contracts/Cargo.toml +++ b/packages/data-contracts/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "data-contracts" description = "Dash Platform system data contracts" -version = "1.3.1" +version = "1.5.0" edition = "2021" rust-version.workspace = true license = "MIT" [dependencies] -thiserror = "1.0.58" +thiserror = "1.0.64" platform-version = { path = "../rs-platform-version" } serde_json = { version = "1.0" } withdrawals-contract = { path = "../withdrawals-contract" } diff --git a/packages/dpns-contract/Cargo.toml b/packages/dpns-contract/Cargo.toml index 1befba9482..a50b3b6786 100644 --- a/packages/dpns-contract/Cargo.toml +++ b/packages/dpns-contract/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "dpns-contract" description = "DPNS data contract schema and tools" -version = "1.3.1" +version = "1.5.0" edition = "2021" rust-version.workspace = true license = "MIT" [dependencies] -thiserror = "1.0.58" +thiserror = "1.0.64" platform-version = { path = "../rs-platform-version" } serde_json = { version = "1.0" } platform-value = { path = "../rs-platform-value" } diff --git a/packages/dpns-contract/package.json b/packages/dpns-contract/package.json index ac85feb319..ea08d1101a 100644 --- a/packages/dpns-contract/package.json +++ b/packages/dpns-contract/package.json @@ -1,6 +1,6 @@ { "name": "@dashevo/dpns-contract", - "version": "1.3.1", + "version": "1.5.0", "description": "A contract and helper scripts for DPNS DApp", "scripts": { "lint": "eslint .", diff --git a/packages/feature-flags-contract/Cargo.toml b/packages/feature-flags-contract/Cargo.toml index ebccb71d06..a4bd7a3d1b 100644 --- a/packages/feature-flags-contract/Cargo.toml +++ b/packages/feature-flags-contract/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "feature-flags-contract" description = "Feature flags data contract schema and tools" -version = "1.3.1" +version = "1.5.0" edition = "2021" rust-version.workspace = true license = "MIT" [dependencies] -thiserror = "1.0.58" +thiserror = "1.0.64" platform-version = { path = "../rs-platform-version" } serde_json = { version = "1.0" } platform-value = { path = "../rs-platform-value" } diff --git a/packages/feature-flags-contract/package.json b/packages/feature-flags-contract/package.json index fadaf4eb8b..6258be19c7 100644 --- a/packages/feature-flags-contract/package.json +++ b/packages/feature-flags-contract/package.json @@ -1,6 +1,6 @@ { "name": "@dashevo/feature-flags-contract", - "version": "1.3.1", + "version": "1.5.0", "description": "Data Contract to store Dash Platform feature flags", "scripts": { "build": "", diff --git a/packages/js-dapi-client/lib/networkConfigs.js b/packages/js-dapi-client/lib/networkConfigs.js index 4bc7c83213..4400daa8d1 100644 --- a/packages/js-dapi-client/lib/networkConfigs.js +++ b/packages/js-dapi-client/lib/networkConfigs.js @@ -6,6 +6,7 @@ module.exports = { 'seed-3.testnet.networks.dash.org:1443', 'seed-4.testnet.networks.dash.org:1443', 'seed-5.testnet.networks.dash.org:1443', + 'seed-1.pshenmic.dev:1443', ], network: 'testnet', // Since we don't have PoSe atm, 3rd party masternodes sometimes provide wrong data @@ -57,6 +58,7 @@ module.exports = { 'seed-2.mainnet.networks.dash.org', 'seed-3.mainnet.networks.dash.org', 'seed-4.mainnet.networks.dash.org', + 'seed-1.pshenmic.dev', ], network: 'mainnet', }, diff --git a/packages/js-dapi-client/lib/transport/GrpcTransport/createGrpcTransportError.js b/packages/js-dapi-client/lib/transport/GrpcTransport/createGrpcTransportError.js index 103c37bb39..e5cae56b75 100644 --- a/packages/js-dapi-client/lib/transport/GrpcTransport/createGrpcTransportError.js +++ b/packages/js-dapi-client/lib/transport/GrpcTransport/createGrpcTransportError.js @@ -119,7 +119,13 @@ async function createGrpcTransportError(grpcError, dapiAddress) { // DPP consensus errors if (code >= 10000 && code < 50000) { - const consensusError = deserializeConsensusError(data.serializedError || []); + const consensusErrorString = metadata['dash-serialized-consensus-error-bin']; + if (!consensusErrorString) { + throw new Error(`Can't deserialize consensus error ${code}: serialized data is missing`); + } + + const consensusErrorBytes = Buffer.from(consensusErrorString, 'base64'); + const consensusError = deserializeConsensusError(consensusErrorBytes); delete data.serializedError; diff --git a/packages/js-dapi-client/package.json b/packages/js-dapi-client/package.json index 1d1f132e16..d957664bd9 100644 --- a/packages/js-dapi-client/package.json +++ b/packages/js-dapi-client/package.json @@ -1,6 +1,6 @@ { "name": "@dashevo/dapi-client", - "version": "1.3.1", + "version": "1.5.0", "description": "Client library used to access Dash DAPI endpoints", "main": "lib/index.js", "contributors": [ @@ -28,7 +28,7 @@ "dependencies": { "@dashevo/dapi-grpc": "workspace:*", "@dashevo/dash-spv": "workspace:*", - "@dashevo/dashcore-lib": "~0.21.3", + "@dashevo/dashcore-lib": "~0.22.0", "@dashevo/grpc-common": "workspace:*", "@dashevo/wasm-dpp": "workspace:*", "bs58": "^4.0.1", diff --git a/packages/js-dapi-client/test/unit/transport/GrpcTransport/createGrpcTransportError.spec.js b/packages/js-dapi-client/test/unit/transport/GrpcTransport/createGrpcTransportError.spec.js index 13205f6e0c..b3731276d1 100644 --- a/packages/js-dapi-client/test/unit/transport/GrpcTransport/createGrpcTransportError.spec.js +++ b/packages/js-dapi-client/test/unit/transport/GrpcTransport/createGrpcTransportError.spec.js @@ -155,17 +155,14 @@ describe('createGrpcTransportError', () => { it('should return InvalidRequestDPPError', async () => { // grpc-js expects Buffer - let driveErrorDataBin = cbor.encode({ - serializedError: new ProtocolVersionParsingError('test').serialize(), - ...errorData, - }); + let serializedError = new ProtocolVersionParsingError('test').serialize(); // and grpc-web expects string // TODO: remove when we switch to single grpc implementation for both Node and Web if (typeof window !== 'undefined') { - driveErrorDataBin = driveErrorDataBin.toString('base64'); + serializedError = serializedError.toString('base64'); } - metadata.set('drive-error-data-bin', driveErrorDataBin); + metadata.set('dash-serialized-consensus-error-bin', serializedError); const grpcError = new GrpcError( 10001, diff --git a/packages/js-dash-sdk/package.json b/packages/js-dash-sdk/package.json index a19ec9dc34..975bb90107 100644 --- a/packages/js-dash-sdk/package.json +++ b/packages/js-dash-sdk/package.json @@ -1,6 +1,6 @@ { "name": "dash", - "version": "4.3.1", + "version": "4.5.0", "description": "Dash library for JavaScript/TypeScript ecosystem (Wallet, DAPI, Primitives, BLS, ...)", "main": "build/index.js", "unpkg": "dist/dash.min.js", @@ -41,7 +41,7 @@ "@dashevo/bls": "~1.2.9", "@dashevo/dapi-client": "workspace:*", "@dashevo/dapi-grpc": "workspace:*", - "@dashevo/dashcore-lib": "~0.21.3", + "@dashevo/dashcore-lib": "~0.22.0", "@dashevo/dashpay-contract": "workspace:*", "@dashevo/dpns-contract": "workspace:*", "@dashevo/grpc-common": "workspace:*", diff --git a/packages/js-dash-sdk/src/SDK/Client/Client.spec.ts b/packages/js-dash-sdk/src/SDK/Client/Client.spec.ts index b44f7cd02f..bc6fa96bd4 100644 --- a/packages/js-dash-sdk/src/SDK/Client/Client.spec.ts +++ b/packages/js-dash-sdk/src/SDK/Client/Client.spec.ts @@ -37,6 +37,7 @@ describe('Dash - Client', function suite() { testHDKey = 'tprv8ZgxMBicQKsPeGi4CikhacVPz6UmErenu1PoD3S4XcEDSPP8auRaS8hG3DQtsQ2i9HACgohHwF5sgMVJNksoKqYoZbis8o75Pp1koCme2Yo'; client = new Client({ + network: 'testnet', wallet: { HDPrivateKey: testHDKey, }, @@ -77,7 +78,7 @@ describe('Dash - Client', function suite() { it('should be instantiable', () => { client = new Client(); expect(client).to.exist; - expect(client.network).to.be.equal('testnet'); + expect(client.network).to.be.equal('mainnet'); expect(client.getDAPIClient().constructor.name).to.be.equal('DAPIClient'); }); @@ -111,7 +112,7 @@ describe('Dash - Client', function suite() { wallet: { mnemonic: testMnemonic, offlineMode: true, - network: 'evonet', + network: 'mainnet', }, }); diff --git a/packages/js-dash-sdk/src/SDK/Client/Client.ts b/packages/js-dash-sdk/src/SDK/Client/Client.ts index 7f185677ea..ee641901df 100644 --- a/packages/js-dash-sdk/src/SDK/Client/Client.ts +++ b/packages/js-dash-sdk/src/SDK/Client/Client.ts @@ -48,7 +48,7 @@ export interface ClientOpts { * and the Dash Platform (layer 2). */ export class Client extends EventEmitter { - public network: string = 'testnet'; + public network: string = 'mainnet'; public wallet: Wallet | undefined; @@ -74,7 +74,7 @@ export class Client extends EventEmitter { this.options = options; - this.network = this.options.network ? this.options.network.toString() : 'testnet'; + this.network = this.options.network ? this.options.network.toString() : 'mainnet'; // Initialize DAPI Client const dapiClientOptions = { diff --git a/packages/js-dash-sdk/src/SDK/Client/Platform/methods/identities/creditWithdrawal.ts b/packages/js-dash-sdk/src/SDK/Client/Platform/methods/identities/creditWithdrawal.ts index a2bd513397..359c569b4b 100644 --- a/packages/js-dash-sdk/src/SDK/Client/Platform/methods/identities/creditWithdrawal.ts +++ b/packages/js-dash-sdk/src/SDK/Client/Platform/methods/identities/creditWithdrawal.ts @@ -28,37 +28,50 @@ const MIN_ASSET_UNLOCK_CORE_FEE_PER_BYTE = 1; const MINIMAL_WITHDRAWAL_AMOUNT = ASSET_UNLOCK_TX_SIZE * MIN_ASSET_UNLOCK_CORE_FEE_PER_BYTE * 1000; type WithdrawalOptions = { - signingKeyIndex: number + signingKeyIndex?: number + toAddress?: string }; /** Creates platform credits withdrawal request * @param identity - identity to withdraw from * @param amount - amount of credits to withdraw - * @param to - Dash L1 address * @param options - withdrawal options + * @param [options] - withdrawal options + * @param [options.toAddress] - withdrawal destination address */ export async function creditWithdrawal( this: Platform, identity: Identity, amount: number, - to: string, - options: WithdrawalOptions = { - signingKeyIndex: 3, - }, + options: WithdrawalOptions = { }, ): Promise { await this.initialize(); + // eslint-disable-next-line no-param-reassign + options = { + signingKeyIndex: 3, + ...options, + }; + const { dpp } = this; - let toAddress: Address; - try { - toAddress = new Address(to, this.client.network); - } catch (e) { - throw new Error(`Invalid core recipient "${to}" for network ${this.client.network}`); + let outputScriptBytes: Buffer | undefined; + if (options.toAddress) { + let toAddress: Address; + try { + toAddress = new Address(options.toAddress, this.client.network); + } catch (e) { + throw new Error(`Invalid core recipient "${options.toAddress}" for network ${this.client.network}`); + } + + const outputScript = Script.buildPublicKeyHashOut(toAddress); + // @ts-ignore + outputScriptBytes = outputScript.toBuffer(); + + this.logger.debug(`[Identity#creditWithdrawal] credits withdrawal from ${identity.getId().toString()} to ${toAddress.toString()} with amount ${amount}`); + } else { + this.logger.debug(`[Identity#creditWithdrawal] credits withdrawal from ${identity.getId().toString()} to recent withdrawal address with amount ${amount}`); } - this.logger.debug(`[Identity#creditWithdrawal] credits withdrawal from ${identity.getId().toString()} to ${toAddress.toString()} with amount ${amount}`); - - const outputScript = Script.buildPublicKeyHashOut(toAddress); const balance = identity.getBalance(); if (amount > balance) { @@ -88,8 +101,7 @@ export async function creditWithdrawal( BigInt(amount), coreFeePerByte, DEFAULT_POOLING, - // @ts-ignore - outputScript.toBuffer(), + outputScriptBytes, BigInt(identityNonce), ); diff --git a/packages/js-grpc-common/package.json b/packages/js-grpc-common/package.json index 775ebc514a..8c7b895f09 100644 --- a/packages/js-grpc-common/package.json +++ b/packages/js-grpc-common/package.json @@ -1,6 +1,6 @@ { "name": "@dashevo/grpc-common", - "version": "1.3.1", + "version": "1.5.0", "description": "Common GRPC library", "main": "index.js", "scripts": { diff --git a/packages/masternode-reward-shares-contract/Cargo.toml b/packages/masternode-reward-shares-contract/Cargo.toml index 1296868527..71dc15cc61 100644 --- a/packages/masternode-reward-shares-contract/Cargo.toml +++ b/packages/masternode-reward-shares-contract/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "masternode-reward-shares-contract" description = "Masternode reward shares data contract schema and tools" -version = "1.3.1" +version = "1.5.0" edition = "2021" rust-version.workspace = true license = "MIT" [dependencies] -thiserror = "1.0.58" +thiserror = "1.0.64" platform-version = { path = "../rs-platform-version" } serde_json = { version = "1.0" } platform-value = { path = "../rs-platform-value" } diff --git a/packages/masternode-reward-shares-contract/package.json b/packages/masternode-reward-shares-contract/package.json index 086c4cdb3f..3f1899f461 100644 --- a/packages/masternode-reward-shares-contract/package.json +++ b/packages/masternode-reward-shares-contract/package.json @@ -1,6 +1,6 @@ { "name": "@dashevo/masternode-reward-shares-contract", - "version": "1.3.1", + "version": "1.5.0", "description": "A contract and helper scripts for reward sharing", "scripts": { "lint": "eslint .", diff --git a/packages/platform-test-suite/package.json b/packages/platform-test-suite/package.json index 849fb5c4fd..5497d529f0 100644 --- a/packages/platform-test-suite/package.json +++ b/packages/platform-test-suite/package.json @@ -1,7 +1,7 @@ { "name": "@dashevo/platform-test-suite", "private": true, - "version": "1.3.1", + "version": "1.5.0", "description": "Dash Network end-to-end tests", "scripts": { "test": "yarn exec bin/test.sh", @@ -24,7 +24,7 @@ "homepage": "https://github.com/dashevo/platform-test-suite#readme", "dependencies": { "@dashevo/dapi-client": "workspace:*", - "@dashevo/dashcore-lib": "~0.21.3", + "@dashevo/dashcore-lib": "~0.22.0", "@dashevo/dpns-contract": "workspace:*", "@dashevo/feature-flags-contract": "workspace:*", "@dashevo/grpc-common": "workspace:*", diff --git a/packages/platform-test-suite/test/e2e/withdrawals.spec.js b/packages/platform-test-suite/test/e2e/withdrawals.spec.js index ecbac9b8de..f2a80ee433 100644 --- a/packages/platform-test-suite/test/e2e/withdrawals.spec.js +++ b/packages/platform-test-suite/test/e2e/withdrawals.spec.js @@ -8,7 +8,7 @@ const waitForSTPropagated = require('../../lib/waitForSTPropagated'); // TODO: temporary disabled due to flakiness. These tests aren't important for now, since we are // going to release v1.0.0 with withdrawals disabled. -describe.skip('Withdrawals', function withdrawalsTest() { +describe('Withdrawals', function withdrawalsTest() { this.bail(true); let client; @@ -38,7 +38,7 @@ describe.skip('Withdrawals', function withdrawalsTest() { }); describe('Any Identity', () => { - const INITIAL_BALANCE = 1000000; + const INITIAL_BALANCE = 2000000; before(async () => { identity = await client.platform.identities.register(INITIAL_BALANCE); @@ -57,7 +57,9 @@ describe.skip('Withdrawals', function withdrawalsTest() { await client.platform.identities.withdrawCredits( identity, BigInt(amountToWithdraw), - withdrawTo.address, + { + toAddress: withdrawTo.address, + }, ); // Re-fetch identity to obtain latest core chain lock height @@ -125,7 +127,9 @@ describe.skip('Withdrawals', function withdrawalsTest() { const { height: withdrawalHeight } = await client.platform.identities.withdrawCredits( identity, BigInt(amountToWithdraw), - withdrawTo.address, + { + toAddress: withdrawTo.address, + }, ); let withdrawalBroadcasted = false; @@ -173,11 +177,13 @@ describe.skip('Withdrawals', function withdrawalsTest() { await expect(client.platform.identities.withdrawCredits( identity, BigInt(amountToWithdraw), - withdrawTo.address, + { + toAddress: withdrawTo.address, + }, )).to.be.rejectedWith(`Withdrawal amount "${amountToWithdraw}" is bigger that identity balance "${identityBalanceBefore}"`); }); - it('should not allow to create withdrawal with wrong security key type', async () => { + it('should not allow to create withdrawal with authentication key purpose', async () => { const account = await client.getWalletAccount(); const identityBalanceBefore = identity.getBalance(); const withdrawTo = await account.getUnusedAddress(); @@ -186,11 +192,11 @@ describe.skip('Withdrawals', function withdrawalsTest() { await expect(client.platform.identities.withdrawCredits( identity, BigInt(amountToWithdraw), - withdrawTo.address, { + toAddress: withdrawTo.address, signingKeyIndex: 1, }, - )).to.be.rejectedWith('Error conversion not implemented: Invalid public key security level HIGH. The state transition requires one of CRITICAL'); + )).to.be.rejectedWith('Error conversion not implemented: Invalid identity key purpose AUTHENTICATION. This state transition requires TRANSFER | OWNER'); }); // TODO: Figure out how to overcome client-side validation and implement @@ -227,7 +233,9 @@ describe.skip('Withdrawals', function withdrawalsTest() { await client.platform.identities.withdrawCredits( identity, BigInt(1000000), - withdrawTo.address, + { + toAddress: withdrawTo.address, + }, ); await waitForSTPropagated(); diff --git a/packages/rs-dapi-client/Cargo.toml b/packages/rs-dapi-client/Cargo.toml index b97439c8f6..28cd8936b9 100644 --- a/packages/rs-dapi-client/Cargo.toml +++ b/packages/rs-dapi-client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rs-dapi-client" -version = "1.3.1" +version = "1.5.0" edition = "2021" [features] @@ -18,16 +18,19 @@ dump = ["mocks"] # skip tests that require connection to the platform; enabled by default offline-testing = [] - [dependencies] -backon = "0.4.1" -dapi-grpc = { path = "../dapi-grpc" } +backon = { version = "1.2", features = ["tokio-sleep"] } +dapi-grpc = { path = "../dapi-grpc", features = [ + "core", + "platform", + "client", +], default-features = false } futures = "0.3.28" -http-serde = { version = "1.1.3", optional = true } +http-serde = { version = "2.1", optional = true } rand = { version = "0.8.5", features = ["small_rng"] } -thiserror = "1.0.58" +thiserror = "1.0.64" tracing = "0.1.40" -tokio = { version = "1.32.0", default-features = false } +tokio = { version = "1.40", default-features = false } sha2 = { version = "0.10", optional = true } hex = { version = "0.4.3", optional = true } lru = { version = "0.12.3" } @@ -35,4 +38,4 @@ serde = { version = "1.0.197", optional = true, features = ["derive"] } serde_json = { version = "1.0.120", optional = true } chrono = { version = "0.4.38", features = ["serde"] } [dev-dependencies] -tokio = { version = "1.32.0", features = ["macros"] } +tokio = { version = "1.40", features = ["macros"] } diff --git a/packages/rs-dapi-client/src/address_list.rs b/packages/rs-dapi-client/src/address_list.rs index ab4e2ba0eb..0c21ecc0b1 100644 --- a/packages/rs-dapi-client/src/address_list.rs +++ b/packages/rs-dapi-client/src/address_list.rs @@ -1,6 +1,7 @@ //! Subsystem to manage DAPI nodes. use chrono::Utc; +use dapi_grpc::tonic::codegen::http; use dapi_grpc::tonic::transport::Uri; use rand::{rngs::SmallRng, seq::IteratorRandom, SeedableRng}; use std::collections::HashSet; @@ -20,6 +21,16 @@ pub struct Address { uri: Uri, } +impl FromStr for Address { + type Err = AddressListError; + + fn from_str(s: &str) -> Result { + Uri::from_str(s) + .map(Address::from) + .map_err(AddressListError::from) + } +} + impl PartialEq for Address { fn eq(&self, other: &Self) -> bool { self.uri == other.uri @@ -79,13 +90,18 @@ impl Address { #[derive(Debug, thiserror::Error)] #[cfg_attr(feature = "mocks", derive(serde::Serialize, serde::Deserialize))] pub enum AddressListError { + /// Specified address is not present in the list #[error("address {0} not found in the list")] AddressNotFound(#[cfg_attr(feature = "mocks", serde(with = "http_serde::uri"))] Uri), + /// A valid uri is required to create an Address + #[error("unable parse address: {0}")] + #[cfg_attr(feature = "mocks", serde(skip))] + InvalidAddressUri(#[from] http::uri::InvalidUri), } /// A structure to manage DAPI addresses to select from /// for [DapiRequest](crate::DapiRequest) execution. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct AddressList { addresses: HashSet
, base_ban_period: Duration, @@ -200,6 +216,7 @@ impl AddressList { } } +// TODO: Must be changed to FromStr impl From<&str> for AddressList { fn from(value: &str) -> Self { let uri_list: Vec = value @@ -221,3 +238,12 @@ impl FromIterator for AddressList { address_list } } + +impl IntoIterator for AddressList { + type Item = Address; + type IntoIter = std::collections::hash_set::IntoIter
; + + fn into_iter(self) -> Self::IntoIter { + self.addresses.into_iter() + } +} diff --git a/packages/rs-dapi-client/src/connection_pool.rs b/packages/rs-dapi-client/src/connection_pool.rs index 16d8cf030d..97dd991d50 100644 --- a/packages/rs-dapi-client/src/connection_pool.rs +++ b/packages/rs-dapi-client/src/connection_pool.rs @@ -67,19 +67,21 @@ impl ConnectionPool { /// * `prefix` - Prefix for the item in the pool. Used to distinguish between Core and Platform clients. /// * `uri` - URI of the node. /// * `settings` - Applied request settings. - pub fn get_or_create( + pub fn get_or_create( &self, prefix: PoolPrefix, uri: &Uri, settings: Option<&AppliedRequestSettings>, - create: impl FnOnce() -> PoolItem, - ) -> PoolItem { + create: impl FnOnce() -> Result, + ) -> Result { if let Some(cli) = self.get(prefix, uri, settings) { - return cli; + return Ok(cli); } let cli = create(); - self.put(uri, settings, cli.clone()); + if let Ok(cli) = &cli { + self.put(uri, settings, cli.clone()); + } cli } diff --git a/packages/rs-dapi-client/src/dapi_client.rs b/packages/rs-dapi-client/src/dapi_client.rs index 8e5a3d660b..579c62e015 100644 --- a/packages/rs-dapi-client/src/dapi_client.rs +++ b/packages/rs-dapi-client/src/dapi_client.rs @@ -1,29 +1,32 @@ //! [DapiClient] definition. -use backon::{ExponentialBuilder, Retryable}; +use backon::{ConstantBuilder, Retryable}; use dapi_grpc::mock::Mockable; use dapi_grpc::tonic::async_trait; use std::fmt::Debug; +use std::sync::atomic::AtomicUsize; use std::sync::{Arc, RwLock}; use std::time::Duration; use tracing::Instrument; use crate::address_list::AddressListError; use crate::connection_pool::ConnectionPool; +use crate::transport::TransportError; use crate::{ transport::{TransportClient, TransportRequest}, - Address, AddressList, CanRetry, RequestSettings, + AddressList, CanRetry, DapiRequestExecutor, ExecutionError, ExecutionResponse, ExecutionResult, + RequestSettings, }; /// General DAPI request error type. #[derive(Debug, thiserror::Error)] #[cfg_attr(feature = "mocks", derive(serde::Serialize, serde::Deserialize))] -pub enum DapiClientError { +pub enum DapiClientError { /// The error happened on transport layer - #[error("transport error with {1}: {0}")] + #[error("transport error: {0}")] Transport( - #[cfg_attr(feature = "mocks", serde(with = "dapi_grpc::mock::serde_mockable"))] TE, - Address, + #[cfg_attr(feature = "mocks", serde(with = "dapi_grpc::mock::serde_mockable"))] + TransportError, ), /// There are no valid DAPI addresses to use. #[error("no available addresses to use")] @@ -38,12 +41,12 @@ pub enum DapiClientError { Mock(#[from] crate::mock::MockError), } -impl CanRetry for DapiClientError { - fn is_node_failure(&self) -> bool { +impl CanRetry for DapiClientError { + fn can_retry(&self) -> bool { use DapiClientError::*; match self { NoAvailableAddresses => false, - Transport(transport_error, _) => transport_error.is_node_failure(), + Transport(transport_error) => transport_error.can_retry(), AddressList(_) => false, #[cfg(feature = "mocks")] Mock(_) => false, @@ -51,17 +54,10 @@ impl CanRetry for DapiClientError { } } -#[cfg(feature = "mocks")] -#[derive(serde::Serialize, serde::Deserialize)] -struct TransportErrorData { - transport_error: Vec, - address: Address, -} - /// Serialization of [DapiClientError]. /// /// We need to do manual serialization because of the generic type parameter which doesn't support serde derive. -impl Mockable for DapiClientError { +impl Mockable for DapiClientError { #[cfg(feature = "mocks")] fn mock_serialize(&self) -> Option> { Some(serde_json::to_vec(self).expect("serialize DAPI client error")) @@ -73,21 +69,6 @@ impl Mockable for DapiClientError { } } -#[async_trait] -/// DAPI client executor trait. -pub trait DapiRequestExecutor { - /// Execute request using this DAPI client. - async fn execute( - &self, - request: R, - settings: RequestSettings, - ) -> Result::Error>> - where - R: TransportRequest + Mockable, - R::Response: Mockable, - ::Error: Mockable; -} - /// Access point to DAPI. #[derive(Debug, Clone)] pub struct DapiClient { @@ -112,6 +93,11 @@ impl DapiClient { dump_dir: None, } } + + /// Return the [DapiClient] address list. + pub fn address_list(&self) -> &Arc> { + &self.address_list + } } #[async_trait] @@ -121,11 +107,11 @@ impl DapiRequestExecutor for DapiClient { &self, request: R, settings: RequestSettings, - ) -> Result::Error>> + ) -> ExecutionResult where R: TransportRequest + Mockable, R::Response: Mockable, - ::Error: Mockable, + TransportError: Mockable, { // Join settings of different sources to get final version of the settings for this execution: let applied_settings = self @@ -135,12 +121,9 @@ impl DapiRequestExecutor for DapiClient { .finalize(); // Setup retry policy: - let retry_settings = ExponentialBuilder::default() + let retry_settings = ConstantBuilder::default() .with_max_times(applied_settings.retries) - // backon doesn't accept 1.0 - .with_factor(1.001) - .with_min_delay(Duration::from_secs(0)) - .with_max_delay(Duration::from_secs(0)); + .with_delay(Duration::from_millis(10)); // Save dump dir for later use, as self is moved into routine #[cfg(feature = "dump")] @@ -148,19 +131,24 @@ impl DapiRequestExecutor for DapiClient { #[cfg(feature = "dump")] let dump_request = request.clone(); + let retries_counter_arc = Arc::new(AtomicUsize::new(0)); + let retries_counter_arc_ref = &retries_counter_arc; + // Setup DAPI request execution routine future. It's a closure that will be called // more once to build new future on each retry. let routine = move || { - // Try to get an address to initialize transport on: + let retries_counter = Arc::clone(retries_counter_arc_ref); + // Try to get an address to initialize transport on: let address_list = self .address_list .read() .expect("can't get address list for read"); - let address_result = address_list.get_live_address().cloned().ok_or( - DapiClientError::<::Error>::NoAvailableAddresses, - ); + let address_result = address_list + .get_live_address() + .cloned() + .ok_or(DapiClientError::NoAvailableAddresses); drop(address_list); @@ -187,24 +175,29 @@ impl DapiRequestExecutor for DapiClient { async move { // It stays wrapped in `Result` since we want to return // `impl Future`, not a `Result` itself. - let address = address_result?; + let address = address_result.map_err(|inner| ExecutionError { + inner, + retries: retries_counter.load(std::sync::atomic::Ordering::Acquire), + address: None, + })?; + let pool = self.pool.clone(); let mut transport_client = R::Client::with_uri_and_settings( address.uri().clone(), &applied_settings, &pool, - ); + ) + .map_err(|error| ExecutionError { + inner: DapiClientError::Transport(error), + retries: retries_counter.load(std::sync::atomic::Ordering::Acquire), + address: Some(address.clone()), + })?; let response = transport_request .execute_transport(&mut transport_client, &applied_settings) .await - .map_err(|e| { - DapiClientError::<::Error>::Transport( - e, - address.clone(), - ) - }); + .map_err(DapiClientError::Transport); match &response { Ok(_) => { @@ -215,22 +208,34 @@ impl DapiRequestExecutor for DapiClient { .write() .expect("can't get address list for write"); - address_list.unban_address(&address) - .map_err(DapiClientError::<::Error>::AddressList)?; + address_list.unban_address(&address).map_err(|error| { + ExecutionError { + inner: DapiClientError::AddressList(error), + retries: retries_counter + .load(std::sync::atomic::Ordering::Acquire), + address: Some(address.clone()), + } + })?; } tracing::trace!(?response, "received {} response", response_name); } Err(error) => { - if error.is_node_failure() { + if error.can_retry() { if applied_settings.ban_failed_address { let mut address_list = self .address_list .write() .expect("can't get address list for write"); - address_list.ban_address(&address) - .map_err(DapiClientError::<::Error>::AddressList)?; + address_list.ban_address(&address).map_err(|error| { + ExecutionError { + inner: DapiClientError::AddressList(error), + retries: retries_counter + .load(std::sync::atomic::Ordering::Acquire), + address: Some(address.clone()), + } + })?; } } else { tracing::trace!(?error, "received error"); @@ -238,27 +243,42 @@ impl DapiRequestExecutor for DapiClient { } }; + let retries = retries_counter.load(std::sync::atomic::Ordering::Acquire); + response + .map(|inner| ExecutionResponse { + inner, + retries, + address: address.clone(), + }) + .map_err(|inner| ExecutionError { + inner, + retries, + address: Some(address), + }) } }; // Start the routine with retry policy applied: // We allow let_and_return because `result` is used later if dump feature is enabled let result = routine - .retry(&retry_settings) + .retry(retry_settings) .notify(|error, duration| { + let retries_counter = Arc::clone(&retries_counter_arc); + retries_counter.fetch_add(1, std::sync::atomic::Ordering::AcqRel); + tracing::warn!( ?error, "retrying error with sleeping {} secs", duration.as_secs_f32() - ) + ); }) - .when(|e| e.is_node_failure()) + .when(|e| e.can_retry()) .instrument(tracing::info_span!("request routine")) .await; if let Err(error) = &result { - if error.is_node_failure() { + if !error.can_retry() { tracing::error!(?error, "request failed"); } } diff --git a/packages/rs-dapi-client/src/dump.rs b/packages/rs-dapi-client/src/dump.rs index c81399395b..a1e23d1ff2 100644 --- a/packages/rs-dapi-client/src/dump.rs +++ b/packages/rs-dapi-client/src/dump.rs @@ -189,7 +189,6 @@ impl DapiClient { response: &MockResult, dump_dir: Option, ) where - R: Mockable, ::Response: Mockable, { let path = match dump_dir { diff --git a/packages/rs-dapi-client/src/executor.rs b/packages/rs-dapi-client/src/executor.rs new file mode 100644 index 0000000000..e1b5dca2f9 --- /dev/null +++ b/packages/rs-dapi-client/src/executor.rs @@ -0,0 +1,147 @@ +use crate::transport::TransportRequest; +use crate::{Address, CanRetry, DapiClientError, RequestSettings}; +use dapi_grpc::mock::Mockable; +use dapi_grpc::tonic::async_trait; +use std::fmt::Debug; + +#[async_trait] +/// DAPI client executor trait. +pub trait DapiRequestExecutor { + /// Execute request using this DAPI client. + async fn execute( + &self, + request: R, + settings: RequestSettings, + ) -> ExecutionResult + where + R: TransportRequest + Mockable, + R::Response: Mockable; +} + +/// Unwrap wrapped types +pub trait IntoInner { + /// Unwrap the inner type. + /// + /// This function returns inner type, dropping additional context information. + /// It is lossy operation, so it should be used with caution. + fn into_inner(self) -> T; +} + +/// Convert inner type without loosing additional context information of the wrapper. +pub trait InnerInto { + /// Convert inner type without loosing additional context information of the wrapper. + fn inner_into(self) -> T; +} + +/// Error happened during request execution. +#[derive(Debug, Clone, thiserror::Error, Eq, PartialEq)] +#[error("{inner}")] +pub struct ExecutionError { + /// The cause of error + pub inner: E, + /// How many times the request was retried + pub retries: usize, + /// The address of the node that was used for the request + pub address: Option
, +} + +impl InnerInto> for ExecutionError +where + F: Into, +{ + /// Convert inner error type without loosing retries and address + fn inner_into(self) -> ExecutionError { + ExecutionError { + inner: self.inner.into(), + retries: self.retries, + address: self.address, + } + } +} + +impl IntoInner for ExecutionError +where + E: Into, +{ + /// Unwrap the error cause + fn into_inner(self) -> I { + self.inner.into() + } +} + +impl CanRetry for ExecutionError { + fn can_retry(&self) -> bool { + self.inner.can_retry() + } +} + +/// Request execution response. +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct ExecutionResponse { + /// The response from the request + pub inner: R, + /// How many times the request was retried + pub retries: usize, + /// The address of the node that was used for the request + pub address: Address, +} + +#[cfg(feature = "mocks")] +impl Default for ExecutionResponse { + fn default() -> Self { + Self { + retries: Default::default(), + address: "http://127.0.0.1".parse().expect("create mock address"), + inner: Default::default(), + } + } +} + +impl IntoInner for ExecutionResponse +where + R: Into, +{ + /// Unwrap the response + fn into_inner(self) -> I { + self.inner.into() + } +} + +impl InnerInto> for ExecutionResponse +where + F: Into, +{ + /// Convert inner response type without loosing retries and address + fn inner_into(self) -> ExecutionResponse { + ExecutionResponse { + inner: self.inner.into(), + retries: self.retries, + address: self.address, + } + } +} + +/// Result of request execution +pub type ExecutionResult = Result, ExecutionError>; + +impl IntoInner> for ExecutionResult { + fn into_inner(self) -> Result { + match self { + Ok(response) => Ok(response.into_inner()), + Err(error) => Err(error.into_inner()), + } + } +} + +impl InnerInto> for ExecutionResult +where + F: Into, + FE: Into, +{ + fn inner_into(self) -> ExecutionResult { + match self { + Ok(response) => Ok(response.inner_into()), + Err(error) => Err(error.inner_into()), + } + } +} diff --git a/packages/rs-dapi-client/src/lib.rs b/packages/rs-dapi-client/src/lib.rs index e4f5836e29..2ce4a9da43 100644 --- a/packages/rs-dapi-client/src/lib.rs +++ b/packages/rs-dapi-client/src/lib.rs @@ -7,6 +7,7 @@ mod connection_pool; mod dapi_client; #[cfg(feature = "dump")] pub mod dump; +mod executor; #[cfg(feature = "mocks")] pub mod mock; mod request_settings; @@ -14,11 +15,14 @@ pub mod transport; pub use address_list::Address; pub use address_list::AddressList; -pub use dapi_client::DapiRequestExecutor; +pub use address_list::AddressListError; +pub use connection_pool::ConnectionPool; pub use dapi_client::{DapiClient, DapiClientError}; -use dapi_grpc::mock::Mockable; #[cfg(feature = "dump")] pub use dump::DumpData; +pub use executor::{ + DapiRequestExecutor, ExecutionError, ExecutionResponse, ExecutionResult, InnerInto, IntoInner, +}; use futures::{future::BoxFuture, FutureExt}; pub use request_settings::RequestSettings; @@ -26,28 +30,26 @@ pub use request_settings::RequestSettings; /// /// # Examples /// ``` -/// use rs_dapi_client::{RequestSettings, AddressList, mock::MockDapiClient, DapiClientError, DapiRequest}; +/// use rs_dapi_client::{RequestSettings, AddressList, mock::MockDapiClient, DapiClientError, DapiRequest, ExecutionError}; /// use dapi_grpc::platform::v0::{self as proto}; /// /// # let _ = async { /// let mut client = MockDapiClient::new(); /// let request: proto::GetIdentityRequest = proto::get_identity_request::GetIdentityRequestV0 { id: b"0".to_vec(), prove: true }.into(); /// let response = request.execute(&mut client, RequestSettings::default()).await?; -/// # Ok::<(), DapiClientError<_>>(()) +/// # Ok::<(), ExecutionError>(()) /// # }; /// ``` pub trait DapiRequest { /// Response from DAPI for this specific request. type Response; - /// An error type for the transport this request uses. - type TransportError: Mockable; /// Executes the request. fn execute<'c, D: DapiRequestExecutor>( self, dapi_client: &'c D, settings: RequestSettings, - ) -> BoxFuture<'c, Result>> + ) -> BoxFuture<'c, ExecutionResult> where Self: 'c; } @@ -56,13 +58,11 @@ pub trait DapiRequest { impl DapiRequest for T { type Response = T::Response; - type TransportError = ::Error; - fn execute<'c, D: DapiRequestExecutor>( self, dapi_client: &'c D, settings: RequestSettings, - ) -> BoxFuture<'c, Result>> + ) -> BoxFuture<'c, ExecutionResult> where Self: 'c, { @@ -70,9 +70,16 @@ impl DapiRequest for T { } } -/// Allows to flag the transport error variant how tolerant we are of it and whether we can -/// try to do a request again. +/// Returns true if the operation can be retried. pub trait CanRetry { + /// Returns true if the operation can be retried safely. + fn can_retry(&self) -> bool; + /// Get boolean flag that indicates if the error is retryable. - fn is_node_failure(&self) -> bool; + /// + /// Depreacted in favor of [CanRetry::can_retry]. + #[deprecated = "Use !can_retry() instead"] + fn is_node_failure(&self) -> bool { + !self.can_retry() + } } diff --git a/packages/rs-dapi-client/src/mock.rs b/packages/rs-dapi-client/src/mock.rs index 813546686d..3031e47d54 100644 --- a/packages/rs-dapi-client/src/mock.rs +++ b/packages/rs-dapi-client/src/mock.rs @@ -12,8 +12,8 @@ //! See `tests/mock_dapi_client.rs` for an example. use crate::{ - transport::{TransportClient, TransportRequest}, - DapiClientError, DapiRequestExecutor, RequestSettings, + transport::TransportRequest, DapiClientError, DapiRequestExecutor, ExecutionError, + ExecutionResponse, ExecutionResult, RequestSettings, }; use dapi_grpc::mock::Mockable; use dapi_grpc::tonic::async_trait; @@ -35,10 +35,7 @@ pub struct MockDapiClient { expectations: Expectations, } /// Result of executing a mock request -pub type MockResult = Result< - ::Response, - DapiClientError<<::Client as TransportClient>::Error>, ->; +pub type MockResult = ExecutionResult<::Response, DapiClientError>; impl MockDapiClient { /// Create a new mock client @@ -47,16 +44,12 @@ impl MockDapiClient { } /// Add a new expectation for a request - pub fn expect( - &mut self, - request: &R, - response: &MockResult, - ) -> Result<&mut Self, MockError> + pub fn expect(&mut self, request: &R, result: &MockResult) -> Result<&mut Self, MockError> where R: TransportRequest + Mockable, R::Response: Mockable, { - let key = self.expectations.add(request, response)?; + let key = self.expectations.add(request, result)?; tracing::trace!( %key, @@ -77,12 +70,12 @@ impl MockDapiClient { /// /// Panics if the file can't be read or the data can't be parsed. #[cfg(feature = "dump")] - pub fn load>( + pub fn load>( &mut self, file: P, ) -> Result<(T, MockResult), std::io::Error> where - T: Mockable, + T: TransportRequest + Mockable, T::Response: Mockable, { use crate::DumpData; @@ -124,15 +117,20 @@ impl DapiRequestExecutor for MockDapiClient { "mock execute" ); - return if let Some(response) = response { + if let Some(response) = response { response } else { - Err(MockError::MockExpectationNotFound(format!( + let error = MockError::MockExpectationNotFound(format!( "unexpected mock request with key {}, use MockDapiClient::expect(): {:?}", key, request - )) - .into()) - }; + )); + + Err(ExecutionError { + inner: DapiClientError::Mock(error), + retries: 0, + address: None, + }) + } } } @@ -200,9 +198,9 @@ pub enum MockError { #[derive(Debug)] /// Wrapper that encapsulated serialized form of expected response for a request -struct ExpectedResponse(Vec); +struct ExpectedResult(Vec); -impl ExpectedResponse { +impl ExpectedResult { fn serialize(request: &I) -> Self { // We use json because bincode sometimes fail to deserialize Self(request.mock_serialize().expect("encode value")) @@ -217,7 +215,7 @@ impl ExpectedResponse { #[derive(Default, Debug)] /// Requests expected by a mock and their responses. struct Expectations { - expectations: HashMap, + expectations: HashMap, } impl Expectations { @@ -227,10 +225,10 @@ impl Expectations { pub fn add( &mut self, request: &I, - response: &O, + result: &O, ) -> Result { let key = Key::new(request); - let value = ExpectedResponse::serialize(response); + let value = ExpectedResult::serialize(result); if self.expectations.contains_key(&key) { return Err(MockError::MockExpectationConflict(format!( @@ -256,3 +254,60 @@ impl Expectations { (key, response) } } + +impl Mockable for ExecutionResponse { + fn mock_serialize(&self) -> Option> { + R::mock_serialize(&self.inner) + } + + fn mock_deserialize(data: &[u8]) -> Option { + // TODO: We need serialize retries and address too + R::mock_deserialize(data).map(|inner| ExecutionResponse { + inner, + retries: 0, + address: "http://127.0.0.1:9000" + .parse() + .expect("failed to parse address"), + }) + } +} + +impl Mockable for ExecutionError { + fn mock_serialize(&self) -> Option> { + E::mock_serialize(&self.inner) + } + + fn mock_deserialize(data: &[u8]) -> Option { + // TODO: We need serialize retries and address too + E::mock_deserialize(data).map(|inner| ExecutionError { + inner, + retries: 0, + address: None, + }) + } +} + +/// Create full wrapping object from inner type, using defaults for +/// fields that cannot be derived from the inner type. +pub trait FromInner +where + Self: Default, +{ + /// Create full wrapping object from inner type, using defaults for + /// fields that cannot be derived from the inner type. + /// + /// Note this is imprecise conversion and should be avoided outside of tests. + fn from_inner(inner: R) -> Self; +} + +impl FromInner for ExecutionResponse +where + Self: Default, +{ + fn from_inner(inner: R) -> Self { + Self { + inner, + ..Default::default() + } + } +} diff --git a/packages/rs-dapi-client/src/request_settings.rs b/packages/rs-dapi-client/src/request_settings.rs index 7c900a7829..21a1f69b38 100644 --- a/packages/rs-dapi-client/src/request_settings.rs +++ b/packages/rs-dapi-client/src/request_settings.rs @@ -21,7 +21,8 @@ pub struct RequestSettings { pub connect_timeout: Option, /// Timeout for a request. pub timeout: Option, - /// Number of retries until returning the last error. + /// Number of retries in case of failed requests. If max retries reached, the last error is returned. + /// 1 means one request and one retry in case of error, etc. pub retries: Option, /// Ban DAPI address if node not responded or responded with error. pub ban_failed_address: Option, diff --git a/packages/rs-dapi-client/src/transport.rs b/packages/rs-dapi-client/src/transport.rs index a5459834e1..26c394ff03 100644 --- a/packages/rs-dapi-client/src/transport.rs +++ b/packages/rs-dapi-client/src/transport.rs @@ -42,21 +42,54 @@ pub trait TransportRequest: Clone + Send + Sync + Debug + Mockable { self, client: &'c mut Self::Client, settings: &AppliedRequestSettings, - ) -> BoxFuture<'c, Result::Error>>; + ) -> BoxFuture<'c, Result>; +} + +/// Transport error type. +#[derive(Debug, thiserror::Error)] +#[cfg_attr(feature = "mocks", derive(serde::Serialize, serde::Deserialize))] +pub enum TransportError { + /// gRPC error + #[error("grpc error: {0}")] + Grpc( + #[from] + #[cfg_attr(feature = "mocks", serde(with = "dapi_grpc::mock::serde_mockable"))] + dapi_grpc::tonic::Status, + ), +} + +impl CanRetry for TransportError { + fn can_retry(&self) -> bool { + match self { + TransportError::Grpc(status) => status.can_retry(), + } + } +} + +/// Serialization of [TransportError]. +/// +/// We need to do manual serialization because of the generic type parameter which doesn't support serde derive. +impl Mockable for TransportError { + #[cfg(feature = "mocks")] + fn mock_serialize(&self) -> Option> { + Some(serde_json::to_vec(self).expect("serialize Transport error")) + } + + #[cfg(feature = "mocks")] + fn mock_deserialize(data: &[u8]) -> Option { + Some(serde_json::from_slice(data).expect("deserialize Transport error")) + } } /// Generic way to create a transport client from provided [Uri]. pub trait TransportClient: Send + Sized { - /// Error type for the specific client. - type Error: CanRetry + Send + Debug + Mockable; - /// Build client using node's url. - fn with_uri(uri: Uri, pool: &ConnectionPool) -> Self; + fn with_uri(uri: Uri, pool: &ConnectionPool) -> Result; /// Build client using node's url and [AppliedRequestSettings]. fn with_uri_and_settings( uri: Uri, settings: &AppliedRequestSettings, pool: &ConnectionPool, - ) -> Self; + ) -> Result; } diff --git a/packages/rs-dapi-client/src/transport/grpc.rs b/packages/rs-dapi-client/src/transport/grpc.rs index 9350696e75..fb1f08c842 100644 --- a/packages/rs-dapi-client/src/transport/grpc.rs +++ b/packages/rs-dapi-client/src/transport/grpc.rs @@ -2,13 +2,13 @@ use std::time::Duration; -use super::{CanRetry, TransportClient, TransportRequest}; +use super::{CanRetry, TransportClient, TransportError, TransportRequest}; use crate::connection_pool::{ConnectionPool, PoolPrefix}; use crate::{request_settings::AppliedRequestSettings, RequestSettings}; use dapi_grpc::core::v0::core_client::CoreClient; use dapi_grpc::core::v0::{self as core_proto}; use dapi_grpc::platform::v0::{self as platform_proto, platform_client::PlatformClient}; -use dapi_grpc::tonic::transport::Uri; +use dapi_grpc::tonic::transport::{ClientTlsConfig, Uri}; use dapi_grpc::tonic::Streaming; use dapi_grpc::tonic::{transport::Channel, IntoRequest}; use futures::{future::BoxFuture, FutureExt, TryFutureExt}; @@ -18,8 +18,16 @@ pub type PlatformGrpcClient = PlatformClient; /// Core Client using gRPC transport. pub type CoreGrpcClient = CoreClient; -fn create_channel(uri: Uri, settings: Option<&AppliedRequestSettings>) -> Channel { - let mut builder = Channel::builder(uri); +fn create_channel( + uri: Uri, + settings: Option<&AppliedRequestSettings>, +) -> Result { + let mut builder = Channel::builder(uri).tls_config( + ClientTlsConfig::new() + .with_native_roots() + .with_webpki_roots() + .assume_http2(true), + )?; if let Some(settings) = settings { if let Some(timeout) = settings.connect_timeout { @@ -27,58 +35,89 @@ fn create_channel(uri: Uri, settings: Option<&AppliedRequestSettings>) -> Channe } } - builder.connect_lazy() + Ok(builder.connect_lazy()) } impl TransportClient for PlatformGrpcClient { - type Error = dapi_grpc::tonic::Status; - - fn with_uri(uri: Uri, pool: &ConnectionPool) -> Self { - pool.get_or_create(PoolPrefix::Platform, &uri, None, || { - Self::new(create_channel(uri.clone(), None)).into() - }) - .into() + fn with_uri(uri: Uri, pool: &ConnectionPool) -> Result { + Ok(pool + .get_or_create(PoolPrefix::Platform, &uri, None, || { + match create_channel(uri.clone(), None) { + Ok(channel) => Ok(Self::new(channel).into()), + Err(e) => Err(dapi_grpc::tonic::Status::failed_precondition(format!( + "Channel creation failed: {}", + e + ))), + } + })? + .into()) } fn with_uri_and_settings( uri: Uri, settings: &AppliedRequestSettings, pool: &ConnectionPool, - ) -> Self { - pool.get_or_create(PoolPrefix::Platform, &uri, Some(settings), || { - Self::new(create_channel(uri.clone(), Some(settings))).into() - }) - .into() + ) -> Result { + Ok(pool + .get_or_create( + PoolPrefix::Platform, + &uri, + Some(settings), + || match create_channel(uri.clone(), Some(settings)) { + Ok(channel) => Ok(Self::new(channel).into()), + Err(e) => Err(dapi_grpc::tonic::Status::failed_precondition(format!( + "Channel creation failed: {}", + e + ))), + }, + )? + .into()) } } impl TransportClient for CoreGrpcClient { - type Error = dapi_grpc::tonic::Status; - - fn with_uri(uri: Uri, pool: &ConnectionPool) -> Self { - pool.get_or_create(PoolPrefix::Core, &uri, None, || { - Self::new(create_channel(uri.clone(), None)).into() - }) - .into() + fn with_uri(uri: Uri, pool: &ConnectionPool) -> Result { + Ok(pool + .get_or_create(PoolPrefix::Core, &uri, None, || { + match create_channel(uri.clone(), None) { + Ok(channel) => Ok(Self::new(channel).into()), + Err(e) => Err(dapi_grpc::tonic::Status::failed_precondition(format!( + "Channel creation failed: {}", + e + ))), + } + })? + .into()) } fn with_uri_and_settings( uri: Uri, settings: &AppliedRequestSettings, pool: &ConnectionPool, - ) -> Self { - pool.get_or_create(PoolPrefix::Core, &uri, Some(settings), || { - Self::new(create_channel(uri.clone(), Some(settings))).into() - }) - .into() + ) -> Result { + Ok(pool + .get_or_create( + PoolPrefix::Core, + &uri, + Some(settings), + || match create_channel(uri.clone(), Some(settings)) { + Ok(channel) => Ok(Self::new(channel).into()), + Err(e) => Err(dapi_grpc::tonic::Status::failed_precondition(format!( + "Channel creation failed: {}", + e + ))), + }, + )? + .into()) } } impl CanRetry for dapi_grpc::tonic::Status { - fn is_node_failure(&self) -> bool { + fn can_retry(&self) -> bool { let code = self.code(); use dapi_grpc::tonic::Code::*; + matches!( code, Ok | DataLoss @@ -112,7 +151,7 @@ macro_rules! impl_transport_request_grpc { self, client: &'c mut Self::Client, settings: &AppliedRequestSettings, - ) -> BoxFuture<'c, Result::Error>> + ) -> BoxFuture<'c, Result> { let mut grpc_request = self.into_request(); @@ -122,6 +161,7 @@ macro_rules! impl_transport_request_grpc { client .$($method)+(grpc_request) + .map_err(TransportError::Grpc) .map_ok(|response| response.into_inner()) .boxed() } @@ -376,6 +416,15 @@ impl_transport_request_grpc!( get_total_credits_in_platform ); +// rpc getCurrentQuorumsInfo(GetCurrentQuorumsInfoRequest) returns (GetCurrentQuorumsInfoResponse); +impl_transport_request_grpc!( + platform_proto::GetCurrentQuorumsInfoRequest, + platform_proto::GetCurrentQuorumsInfoResponse, + PlatformGrpcClient, + RequestSettings::default(), + get_current_quorums_info +); + // Link to each core gRPC request what client and method to use: impl_transport_request_grpc!( @@ -412,3 +461,12 @@ impl_transport_request_grpc!( }, subscribe_to_transactions_with_proofs ); + +// rpc getStatus(GetStatusRequest) returns (GetStatusResponse); +impl_transport_request_grpc!( + platform_proto::GetStatusRequest, + platform_proto::GetStatusResponse, + PlatformGrpcClient, + RequestSettings::default(), + get_status +); diff --git a/packages/rs-dapi-client/tests/mock_dapi_client.rs b/packages/rs-dapi-client/tests/mock_dapi_client.rs index f069c4e47a..7e733ae435 100644 --- a/packages/rs-dapi-client/tests/mock_dapi_client.rs +++ b/packages/rs-dapi-client/tests/mock_dapi_client.rs @@ -1,7 +1,9 @@ #[cfg(feature = "mocks")] use { dapi_grpc::platform::v0::{GetIdentityRequest, GetIdentityResponse, Proof}, - rs_dapi_client::{mock::MockDapiClient, DapiRequest, DapiRequestExecutor, RequestSettings}, + rs_dapi_client::{ + mock::MockDapiClient, DapiRequest, DapiRequestExecutor, ExecutionResponse, RequestSettings, + }, }; #[tokio::test] @@ -10,7 +12,7 @@ async fn test_mock_get_identity_dapi_client() { let mut dapi = MockDapiClient::new(); let request = GetIdentityRequest::default(); - let response: GetIdentityResponse = GetIdentityResponse { + let inner: GetIdentityResponse = GetIdentityResponse { version: Some(dapi_grpc::platform::v0::get_identity_response::Version::V0(dapi_grpc::platform::v0::get_identity_response::GetIdentityResponseV0 { result: Some( dapi_grpc::platform::v0::get_identity_response::get_identity_response_v0::Result::Proof(Proof { @@ -21,8 +23,15 @@ async fn test_mock_get_identity_dapi_client() { metadata: Default::default(), })) }; + let execution_response = ExecutionResponse { + inner, + retries: 0, + address: "http://127.0.0.1:9000" + .parse() + .expect("failed to parse address"), + }; - dapi.expect(&request, &Ok(response.clone())) + dapi.expect(&request, &Ok(execution_response.clone())) .expect("expectation added"); let settings = RequestSettings::default(); @@ -31,6 +40,6 @@ async fn test_mock_get_identity_dapi_client() { let result2 = request.execute(&dapi, settings).await.unwrap(); - assert_eq!(result, response); - assert_eq!(result2, response); + assert_eq!(result, execution_response); + assert_eq!(result2, execution_response); } diff --git a/packages/rs-dapi-grpc-macros/Cargo.toml b/packages/rs-dapi-grpc-macros/Cargo.toml index f32b42b320..ce2aef48c4 100644 --- a/packages/rs-dapi-grpc-macros/Cargo.toml +++ b/packages/rs-dapi-grpc-macros/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "dapi-grpc-macros" -version = "1.3.1" +version = "1.5.0" edition = "2021" description = "Macros used by dapi-grpc. Internal use only." @@ -9,8 +9,8 @@ description = "Macros used by dapi-grpc. Internal use only." proc-macro = true [dependencies] -quote = "1.0.33" -syn = "2.0.38" +quote = "1.0.37" +syn = "2.0.75" heck = "0.5.0" [dev-dependencies] diff --git a/packages/rs-dpp/Cargo.toml b/packages/rs-dpp/Cargo.toml index f0a7c25664..ff377de748 100644 --- a/packages/rs-dpp/Cargo.toml +++ b/packages/rs-dpp/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dpp" -version = "1.3.1" +version = "1.5.0" edition = "2021" rust-version.workspace = true authors = [ @@ -15,8 +15,7 @@ authors = [ anyhow = { version = "1.0.81" } async-trait = { version = "0.1.79" } base64 = "0.22.1" -bls-signatures = { git = "https://github.com/dashpay/bls-signatures", tag = "v1.3.1", optional = true } -bs58 = "0.4.0" +bs58 = "0.5" byteorder = { version = "1.4" } chrono = { version = "0.4.35", default-features = false, features = [ "wasmbind", @@ -29,20 +28,22 @@ dashcore = { git = "https://github.com/dashpay/rust-dashcore", features = [ "rand", "signer", "serde", -], default-features = false, branch = "master" } -env_logger = { version = "0.9" } + "bls", + "eddsa" +], default-features = false, tag = "0.32.0" } +env_logger = { version = "0.11" } getrandom = { version = "0.2", features = ["js"] } hex = { version = "0.4" } integer-encoding = { version = "4.0.0" } -itertools = { version = "0.12.1" } +itertools = { version = "0.13" } jsonschema = { git = "https://github.com/dashpay/jsonschema-rs", branch = "configure_regexp", default-features = false, features = [ "draft202012", ], optional = true } lazy_static = { version = "1.4" } log = { version = "0.4.6" } -num_enum = "0.5.7" +num_enum = "0.7" bincode = { version = "2.0.0-rc.3", features = ["serde"] } -rand = { version = "0.8.4", features = ["small_rng"] } +rand = { version = "0.8.5", features = ["small_rng"] } regex = { version = "1.10.4" } serde = { version = "1.0.197", features = ["derive"] } serde_json = { version = "1.0", features = ["preserve_order"] } @@ -55,28 +56,27 @@ platform-version = { path = "../rs-platform-version" } platform-versioning = { path = "../rs-platform-versioning" } platform-serialization = { path = "../rs-platform-serialization" } platform-serialization-derive = { path = "../rs-platform-serialization-derive" } -derive_more = "0.99.17" -ed25519-dalek = { version = "2.0.0-rc.2", features = [ - "rand_core", -], optional = true } +derive_more = { version = "1.0", features = ["from", "display"] } nohash-hasher = "0.2.0" rust_decimal = "1.29.1" rust_decimal_macros = "1.29.1" indexmap = { version = "2.0.2", features = ["serde"] } -strum = { version = "0.25.0", features = ["derive"] } +strum = { version = "0.26", features = ["derive"] } json-schema-compatibility-validator = { path = '../rs-json-schema-compatibility-validator' } once_cell = "1.19.0" [dev-dependencies] -test-case = { version = "2.0" } -tokio = { version = "1.17", features = ["full"] } -pretty_assertions = { version = "1.3.0" } +test-case = { version = "3.3" } +tokio = { version = "1.40", features = ["full"] } +pretty_assertions = { version = "1.4.1" } dpp = { path = ".", features = ["all_features_without_client"] } assert_matches = "1.5.0" once_cell = "1.7" [features] default = ["platform-value", "state-transitions"] +bls-signatures = ["dashcore/bls"] +ed25519-dalek = ["dashcore/eddsa"] all_features = [ "json-object", "platform-value", @@ -89,6 +89,9 @@ all_features = [ "identity-hashing", "identity-serialization", "ciborium", + "core-types", + "core-types-serialization", + "core-types-serde-conversion", "document-serde-conversion", "document-value-conversion", "document-json-conversion", @@ -131,6 +134,9 @@ dash-sdk-features = [ "document-value-conversion", "data-contract-value-conversion", "identity-value-conversion", + "core-types", + "core-types-serialization", + "core-types-serde-conversion", "state-transition-serde-conversion", "state-transition-value-conversion", "state-transition-json-conversion", @@ -152,6 +158,9 @@ all_features_without_client = [ "identity-hashing", "identity-serialization", "ciborium", + "core-types", + "core-types-serialization", + "core-types-serde-conversion", "document-serde-conversion", "document-value-conversion", "document-json-conversion", @@ -189,6 +198,9 @@ abci = [ "identity-serialization", "vote-serialization", "platform-value-cbor", + "core-types", + "core-types-serialization", + "core-types-serde-conversion", ] cbor = ["ciborium"] validation = [ @@ -261,6 +273,9 @@ state-transition-signing = [ ] vote-serialization = [] vote-serde-conversion = [] +core-types = ["bls-signatures"] +core-types-serialization = ["core-types"] +core-types-serde-conversion = ["core-types"] state-transitions = [] system_contracts = ["factories", "data-contracts", "platform-value-json"] fixtures-and-mocks = ["system_contracts", "platform-value/json"] diff --git a/packages/rs-dpp/src/bls/native_bls.rs b/packages/rs-dpp/src/bls/native_bls.rs index f613284266..5dc7e2bc82 100644 --- a/packages/rs-dpp/src/bls/native_bls.rs +++ b/packages/rs-dpp/src/bls/native_bls.rs @@ -1,6 +1,6 @@ use crate::{BlsModule, ProtocolError, PublicKeyValidationError}; use anyhow::anyhow; -use bls_signatures::{PrivateKey, PublicKey}; +use dashcore::bls_signatures::{self, PrivateKey, PublicKey}; #[derive(Default)] pub struct NativeBlsModule; diff --git a/packages/rs-dpp/src/core_types/mod.rs b/packages/rs-dpp/src/core_types/mod.rs new file mode 100644 index 0000000000..10572cdf0f --- /dev/null +++ b/packages/rs-dpp/src/core_types/mod.rs @@ -0,0 +1,2 @@ +pub mod validator; +pub mod validator_set; diff --git a/packages/rs-dpp/src/core_types/validator/mod.rs b/packages/rs-dpp/src/core_types/validator/mod.rs new file mode 100644 index 0000000000..2261bac56f --- /dev/null +++ b/packages/rs-dpp/src/core_types/validator/mod.rs @@ -0,0 +1,119 @@ +use crate::bls_signatures::PublicKey as BlsPublicKey; +use crate::core_types::validator::v0::{ValidatorV0, ValidatorV0Getters, ValidatorV0Setters}; +use dashcore::{ProTxHash, PubkeyHash}; +#[cfg(feature = "core-types-serde-conversion")] +use serde::{Deserialize, Serialize}; + +/// Version 0 +pub mod v0; + +/// A validator in the context of a quorum +#[derive(Clone, Debug, Eq, PartialEq)] +#[cfg_attr( + feature = "core-types-serde-conversion", + derive(Serialize, Deserialize) +)] +pub enum Validator { + /// Version 0 + V0(ValidatorV0), +} + +impl ValidatorV0Getters for Validator { + fn pro_tx_hash(&self) -> &ProTxHash { + match self { + Validator::V0(v0) => v0.pro_tx_hash(), + } + } + + fn public_key(&self) -> &Option { + match self { + Validator::V0(v0) => v0.public_key(), + } + } + + fn node_ip(&self) -> &String { + match self { + Validator::V0(v0) => v0.node_ip(), + } + } + + fn node_id(&self) -> &PubkeyHash { + match self { + Validator::V0(v0) => v0.node_id(), + } + } + + fn core_port(&self) -> u16 { + match self { + Validator::V0(v0) => v0.core_port(), + } + } + + fn platform_http_port(&self) -> u16 { + match self { + Validator::V0(v0) => v0.platform_http_port(), + } + } + + fn platform_p2p_port(&self) -> u16 { + match self { + Validator::V0(v0) => v0.platform_p2p_port(), + } + } + + fn is_banned(&self) -> bool { + match self { + Validator::V0(v0) => v0.is_banned(), + } + } +} + +impl ValidatorV0Setters for Validator { + fn set_pro_tx_hash(&mut self, pro_tx_hash: ProTxHash) { + match self { + Validator::V0(v0) => v0.set_pro_tx_hash(pro_tx_hash), + } + } + + fn set_public_key(&mut self, public_key: Option) { + match self { + Validator::V0(v0) => v0.set_public_key(public_key), + } + } + + fn set_node_ip(&mut self, node_ip: String) { + match self { + Validator::V0(v0) => v0.set_node_ip(node_ip), + } + } + + fn set_node_id(&mut self, node_id: PubkeyHash) { + match self { + Validator::V0(v0) => v0.set_node_id(node_id), + } + } + + fn set_core_port(&mut self, core_port: u16) { + match self { + Validator::V0(v0) => v0.set_core_port(core_port), + } + } + + fn set_platform_http_port(&mut self, platform_http_port: u16) { + match self { + Validator::V0(v0) => v0.set_platform_http_port(platform_http_port), + } + } + + fn set_platform_p2p_port(&mut self, platform_p2p_port: u16) { + match self { + Validator::V0(v0) => v0.set_platform_p2p_port(platform_p2p_port), + } + } + + fn set_is_banned(&mut self, is_banned: bool) { + match self { + Validator::V0(v0) => v0.set_is_banned(is_banned), + } + } +} diff --git a/packages/rs-dpp/src/core_types/validator/v0/mod.rs b/packages/rs-dpp/src/core_types/validator/v0/mod.rs new file mode 100644 index 0000000000..b427431a04 --- /dev/null +++ b/packages/rs-dpp/src/core_types/validator/v0/mod.rs @@ -0,0 +1,296 @@ +use dashcore::{ProTxHash, PubkeyHash}; +use std::fmt::{Debug, Formatter}; + +use crate::bls_signatures::PublicKey as BlsPublicKey; +#[cfg(feature = "core-types-serde-conversion")] +use serde::{Deserialize, Serialize}; + +#[cfg(feature = "core-types-serialization")] +use bincode::de::Decoder; +#[cfg(feature = "core-types-serialization")] +use bincode::enc::Encoder; +#[cfg(feature = "core-types-serialization")] +use bincode::error::{DecodeError, EncodeError}; +#[cfg(feature = "core-types-serialization")] +use bincode::{Decode, Encode}; +#[cfg(feature = "core-types-serialization")] +use dashcore::hashes::Hash; + +/// A validator in the context of a quorum +#[derive(Clone, Eq, PartialEq)] +#[cfg_attr( + feature = "core-types-serde-conversion", + derive(Serialize, Deserialize) +)] +pub struct ValidatorV0 { + /// The proTxHash + pub pro_tx_hash: ProTxHash, + /// The public key share of this validator for this quorum + pub public_key: Option, + /// The node address + pub node_ip: String, + /// The node id + pub node_id: PubkeyHash, + /// Core port + pub core_port: u16, + /// Http port + pub platform_http_port: u16, + /// Tenderdash port + pub platform_p2p_port: u16, + /// Is the validator banned + pub is_banned: bool, +} + +#[cfg(feature = "core-types-serialization")] +impl Encode for ValidatorV0 { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + // Encode each field in the order they appear in the struct + + // Encode ProTxHash + let pro_tx_hash_bytes = self.pro_tx_hash.as_byte_array(); + pro_tx_hash_bytes.encode(encoder)?; + + // Encode Option + match &self.public_key { + Some(public_key) => { + true.encode(encoder)?; // Indicate that public_key is present + public_key.to_bytes().encode(encoder)?; + } + None => { + false.encode(encoder)?; // Indicate that public_key is not present + } + } + + // Encode node_ip as a string + self.node_ip.encode(encoder)?; + + // Encode node_id + let node_id_bytes = self.node_id.as_byte_array(); + node_id_bytes.encode(encoder)?; + + // Encode core_port, platform_http_port, and platform_p2p_port as u16 + self.core_port.encode(encoder)?; + self.platform_http_port.encode(encoder)?; + self.platform_p2p_port.encode(encoder)?; + + // Encode is_banned as a boolean + self.is_banned.encode(encoder)?; + + Ok(()) + } +} + +#[cfg(feature = "core-types-serialization")] +impl Decode for ValidatorV0 { + fn decode(decoder: &mut D) -> Result { + // Decode each field in the same order as they were encoded + + // Decode ProTxHash + let pro_tx_hash_bytes = <[u8; 32]>::decode(decoder)?; + let pro_tx_hash = ProTxHash::from_slice(&pro_tx_hash_bytes) + .map_err(|_| DecodeError::OtherString("Failed to decode ProTxHash".to_string()))?; + + // Decode Option + let has_public_key = bool::decode(decoder)?; + let public_key = if has_public_key { + let public_key_bytes = <[u8; 48]>::decode(decoder)?; + Some(BlsPublicKey::from_bytes(&public_key_bytes).map_err(|_| { + DecodeError::OtherString("Failed to decode BlsPublicKey".to_string()) + })?) + } else { + None + }; + + // Decode node_ip as a string + let node_ip = String::decode(decoder)?; + + // Decode node_id + let node_id_bytes = <[u8; 20]>::decode(decoder)?; + let node_id = PubkeyHash::from_slice(&node_id_bytes) + .map_err(|_| DecodeError::OtherString("Failed to decode NodeId".to_string()))?; + + // Decode core_port, platform_http_port, and platform_p2p_port as u16 + let core_port = u16::decode(decoder)?; + let platform_http_port = u16::decode(decoder)?; + let platform_p2p_port = u16::decode(decoder)?; + + // Decode is_banned as a boolean + let is_banned = bool::decode(decoder)?; + + Ok(ValidatorV0 { + pro_tx_hash, + public_key, + node_ip, + node_id, + core_port, + platform_http_port, + platform_p2p_port, + is_banned, + }) + } +} + +impl Debug for ValidatorV0 { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.debug_struct("ValidatorV0") + .field("pro_tx_hash", &self.pro_tx_hash.to_string()) + .field("public_key", &self.public_key) + .field("node_ip", &self.node_ip) + .field("node_id", &self.node_id) + .field("core_port", &self.core_port) + .field("platform_http_port", &self.platform_http_port) + .field("platform_p2p_port", &self.platform_p2p_port) + .field("is_banned", &self.is_banned) + .finish() + } +} + +/// Traits to get properties of a validator. +pub trait ValidatorV0Getters { + /// Returns the proTxHash of the validator. + fn pro_tx_hash(&self) -> &ProTxHash; + /// Returns the public key share of this validator for this quorum. + fn public_key(&self) -> &Option; + /// Returns the node address of the validator. + fn node_ip(&self) -> &String; + /// Returns the node id of the validator. + fn node_id(&self) -> &PubkeyHash; + /// Returns the core port of the validator. + fn core_port(&self) -> u16; + /// Returns the Http port of the validator. + fn platform_http_port(&self) -> u16; + /// Returns the Tenderdash port of the validator. + fn platform_p2p_port(&self) -> u16; + /// Returns the status of the validator whether it's banned or not. + fn is_banned(&self) -> bool; +} + +/// Traits to set properties of a validator. +pub trait ValidatorV0Setters { + /// Sets the proTxHash of the validator. + fn set_pro_tx_hash(&mut self, pro_tx_hash: ProTxHash); + /// Sets the public key share of this validator for this quorum. + fn set_public_key(&mut self, public_key: Option); + /// Sets the node address of the validator. + fn set_node_ip(&mut self, node_ip: String); + /// Sets the node id of the validator. + fn set_node_id(&mut self, node_id: PubkeyHash); + /// Sets the core port of the validator. + fn set_core_port(&mut self, core_port: u16); + /// Sets the Http port of the validator. + fn set_platform_http_port(&mut self, platform_http_port: u16); + /// Sets the Tenderdash port of the validator. + fn set_platform_p2p_port(&mut self, platform_p2p_port: u16); + /// Sets the status of the validator whether it's banned or not. + fn set_is_banned(&mut self, is_banned: bool); +} + +impl ValidatorV0Getters for ValidatorV0 { + fn pro_tx_hash(&self) -> &ProTxHash { + &self.pro_tx_hash + } + + fn public_key(&self) -> &Option { + &self.public_key + } + + fn node_ip(&self) -> &String { + &self.node_ip + } + + fn node_id(&self) -> &PubkeyHash { + &self.node_id + } + + fn core_port(&self) -> u16 { + self.core_port + } + + fn platform_http_port(&self) -> u16 { + self.platform_http_port + } + + fn platform_p2p_port(&self) -> u16 { + self.platform_p2p_port + } + + fn is_banned(&self) -> bool { + self.is_banned + } +} + +impl ValidatorV0Setters for ValidatorV0 { + fn set_pro_tx_hash(&mut self, pro_tx_hash: ProTxHash) { + self.pro_tx_hash = pro_tx_hash; + } + + fn set_public_key(&mut self, public_key: Option) { + self.public_key = public_key; + } + + fn set_node_ip(&mut self, node_ip: String) { + self.node_ip = node_ip; + } + + fn set_node_id(&mut self, node_id: PubkeyHash) { + self.node_id = node_id; + } + + fn set_core_port(&mut self, core_port: u16) { + self.core_port = core_port; + } + + fn set_platform_http_port(&mut self, platform_http_port: u16) { + self.platform_http_port = platform_http_port; + } + + fn set_platform_p2p_port(&mut self, platform_p2p_port: u16) { + self.platform_p2p_port = platform_p2p_port; + } + + fn set_is_banned(&mut self, is_banned: bool) { + self.is_banned = is_banned; + } +} + +#[cfg(test)] +mod tests { + use super::*; + use bincode::config; + + #[test] + fn test_serialize_deserialize_validator_v0() { + // Sample data for testing + let pro_tx_hash = ProTxHash::from_slice(&[1; 32]).unwrap(); + let public_key = Some(BlsPublicKey::generate()); + let node_ip = "127.0.0.1".to_string(); + let node_id = PubkeyHash::from_slice(&[3; 20]).unwrap(); + let core_port = 9999; + let platform_http_port = 8888; + let platform_p2p_port = 7777; + let is_banned = false; + + // Create a ValidatorV0 instance + let validator = ValidatorV0 { + pro_tx_hash, + public_key, + node_ip, + node_id, + core_port, + platform_http_port, + platform_p2p_port, + is_banned, + }; + + // Serialize the ValidatorV0 instance + let encoded = bincode::encode_to_vec(&validator, config::standard()).unwrap(); + + // Deserialize the data back into a ValidatorV0 instance + let decoded: ValidatorV0 = bincode::decode_from_slice(&encoded, config::standard()) + .unwrap() + .0; + + // Verify that the deserialized instance matches the original instance + assert_eq!(validator, decoded); + } +} diff --git a/packages/rs-dpp/src/core_types/validator_set/mod.rs b/packages/rs-dpp/src/core_types/validator_set/mod.rs new file mode 100644 index 0000000000..74b78fca05 --- /dev/null +++ b/packages/rs-dpp/src/core_types/validator_set/mod.rs @@ -0,0 +1,120 @@ +use crate::bls_signatures::PublicKey as BlsPublicKey; +use crate::core_types::validator::v0::ValidatorV0; +use crate::core_types::validator_set::v0::{ + ValidatorSetV0, ValidatorSetV0Getters, ValidatorSetV0Setters, +}; +#[cfg(feature = "core-types-serialization")] +use crate::ProtocolError; +#[cfg(feature = "core-types-serialization")] +use bincode::{Decode, Encode}; +use dashcore::{ProTxHash, QuorumHash}; +#[cfg(feature = "core-types-serialization")] +use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; +#[cfg(feature = "core-types-serde-conversion")] +use serde::{Deserialize, Serialize}; +use std::collections::BTreeMap; +use std::fmt::{Display, Formatter}; + +/// Version 0 +pub mod v0; + +/// The validator set is only slightly different from a quorum as it does not contain non valid +/// members +#[derive(Clone, Debug, Eq, PartialEq)] +#[cfg_attr( + feature = "core-types-serde-conversion", + derive(Serialize, Deserialize) +)] +#[cfg_attr( + feature = "core-types-serialization", + derive(Encode, Decode, PlatformDeserialize, PlatformSerialize), + platform_serialize(limit = 15000, unversioned) +)] +pub enum ValidatorSet { + /// Version 0 + V0(ValidatorSetV0), +} + +impl Display for ValidatorSet { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + ValidatorSet::V0(v0) => write!(f, "{}", v0), + } + } +} + +impl ValidatorSetV0Getters for ValidatorSet { + fn quorum_hash(&self) -> &QuorumHash { + match self { + ValidatorSet::V0(v0) => v0.quorum_hash(), + } + } + + fn quorum_index(&self) -> Option { + match self { + ValidatorSet::V0(v0) => v0.quorum_index(), + } + } + + fn core_height(&self) -> u32 { + match self { + ValidatorSet::V0(v0) => v0.core_height(), + } + } + + fn members(&self) -> &BTreeMap { + match self { + ValidatorSet::V0(v0) => v0.members(), + } + } + + fn members_mut(&mut self) -> &mut BTreeMap { + match self { + ValidatorSet::V0(v0) => v0.members_mut(), + } + } + + fn members_owned(self) -> BTreeMap { + match self { + ValidatorSet::V0(v0) => v0.members_owned(), + } + } + + fn threshold_public_key(&self) -> &BlsPublicKey { + match self { + ValidatorSet::V0(v0) => v0.threshold_public_key(), + } + } +} + +impl ValidatorSetV0Setters for ValidatorSet { + fn set_quorum_hash(&mut self, quorum_hash: QuorumHash) { + match self { + ValidatorSet::V0(v0) => v0.set_quorum_hash(quorum_hash), + } + } + + fn set_quorum_index(&mut self, index: Option) { + match self { + ValidatorSet::V0(v0) => v0.set_quorum_index(index), + } + } + + fn set_core_height(&mut self, core_height: u32) { + match self { + ValidatorSet::V0(v0) => v0.set_core_height(core_height), + } + } + + fn set_members(&mut self, members: BTreeMap) { + match self { + ValidatorSet::V0(v0) => v0.set_members(members), + } + } + + fn set_threshold_public_key(&mut self, threshold_public_key: BlsPublicKey) { + match self { + ValidatorSet::V0(v0) => v0.set_threshold_public_key(threshold_public_key), + } + } +} diff --git a/packages/rs-dpp/src/core_types/validator_set/v0/mod.rs b/packages/rs-dpp/src/core_types/validator_set/v0/mod.rs new file mode 100644 index 0000000000..dba9180e24 --- /dev/null +++ b/packages/rs-dpp/src/core_types/validator_set/v0/mod.rs @@ -0,0 +1,340 @@ +use crate::bls_signatures::PublicKey as BlsPublicKey; +use crate::core_types::validator::v0::ValidatorV0; +#[cfg(feature = "core-types-serialization")] +use bincode::de::Decoder; +#[cfg(feature = "core-types-serialization")] +use bincode::enc::Encoder; +#[cfg(feature = "core-types-serialization")] +use bincode::error::EncodeError; +#[cfg(feature = "core-types-serialization")] +use bincode::{BorrowDecode, Decode, Encode}; +use dashcore::hashes::Hash; +use dashcore::{ProTxHash, QuorumHash}; +use itertools::Itertools; +#[cfg(feature = "core-types-serde-conversion")] +use serde::{Deserialize, Serialize}; +use std::collections::BTreeMap; +use std::fmt; +use std::fmt::{Debug, Display, Formatter}; + +/// The validator set is only slightly different from a quorum as it does not contain non valid +/// members +#[derive(Clone, Eq, PartialEq)] +#[cfg_attr( + feature = "core-types-serde-conversion", + derive(Serialize, Deserialize) +)] +pub struct ValidatorSetV0 { + /// The quorum hash + pub quorum_hash: QuorumHash, + /// Rotation quorum index is available only for DIP24 quorums + pub quorum_index: Option, + /// Active height + pub core_height: u32, + /// The list of masternodes + pub members: BTreeMap, + /// The threshold quorum public key + pub threshold_public_key: BlsPublicKey, +} + +impl Display for ValidatorSetV0 { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!( + f, + "ValidatorSet {{ + quorum_hash: {}, + quorum_index: {}, + core_height: {}, + members: [{}], + threshold_public_key: {} +}}", + hex::encode(self.quorum_hash), // Assuming QuorumHash is a byte array and should be in hex format + match self.quorum_index { + Some(index) => index.to_string(), + None => "None".to_string(), + }, + self.core_height, + self.members + .iter() + .map(|(pro_tx_hash, validator)| format!( + "{{{}: {}}}", + pro_tx_hash, validator.node_ip + )) + .join(", "), + hex::encode(self.threshold_public_key.to_bytes().as_slice()) // Assuming BlsPublicKey is a byte array + ) + } +} + +#[cfg(feature = "core-types-serialization")] +impl Encode for ValidatorSetV0 { + fn encode(&self, encoder: &mut E) -> Result<(), EncodeError> { + // Encode each field in the order they appear in the struct + let quorum_hash_bytes = self.quorum_hash.as_byte_array(); + quorum_hash_bytes.encode(encoder)?; + self.quorum_index.encode(encoder)?; + self.core_height.encode(encoder)?; + + // Convert BTreeMap to Vec<(Vec, ValidatorV0)> and encode it + let members_as_vec: Vec<(Vec, ValidatorV0)> = self + .members + .iter() + .map(|(key, value)| (key.as_byte_array().to_vec(), value.clone())) + .collect(); + members_as_vec.encode(encoder)?; + + // Custom encoding for BlsPublicKey if needed + // Assuming BlsPublicKey can be serialized to a byte slice + let public_key_bytes = *self.threshold_public_key.to_bytes(); + public_key_bytes.encode(encoder)?; + + Ok(()) + } +} + +#[cfg(feature = "core-types-serialization")] +impl Decode for ValidatorSetV0 { + fn decode(decoder: &mut D) -> Result { + // Decode the quorum hash directly as a [u8; 32] array + let quorum_hash = <[u8; 32]>::decode(decoder)?; + let quorum_index = Option::::decode(decoder)?; + let core_height = u32::decode(decoder)?; + + // Decode Vec<(Vec, ValidatorV0)> and convert it back to BTreeMap + let members_as_vec = Vec::<(Vec, ValidatorV0)>::decode(decoder)?; + let members: BTreeMap = members_as_vec + .into_iter() + .map(|(key_bytes, value)| { + let key = ProTxHash::from_slice(&key_bytes).map_err(|_| { + bincode::error::DecodeError::OtherString( + "Failed to decode ProTxHash".to_string(), + ) + })?; + Ok((key, value)) + }) + .collect::>()?; + + // Decode the [u8; 48] directly + let mut public_key_bytes = [0u8; 48]; + let bytes = <[u8; 48]>::decode(decoder)?; + public_key_bytes.copy_from_slice(&bytes); + let threshold_public_key = BlsPublicKey::from_bytes(&public_key_bytes).map_err(|_| { + bincode::error::DecodeError::OtherString("Failed to decode BlsPublicKey".to_string()) + })?; + + Ok(ValidatorSetV0 { + quorum_hash: QuorumHash::from_byte_array(quorum_hash), + quorum_index, + core_height, + members, + threshold_public_key, + }) + } +} + +#[cfg(feature = "core-types-serialization")] +impl<'de> BorrowDecode<'de> for ValidatorSetV0 { + fn borrow_decode(decoder: &mut D) -> Result { + // Decode each field in the same order as they were encoded + + // Decode the quorum hash directly as a [u8; 32] array + let quorum_hash = <[u8; 32]>::decode(decoder)?; + // Decode quorum_index as Option + let quorum_index = Option::::decode(decoder)?; + // Decode core_height as u32 + let core_height = u32::decode(decoder)?; + + // Decode Vec<(Vec, ValidatorV0)> and convert it back to BTreeMap + let members_as_vec = Vec::<(Vec, ValidatorV0)>::decode(decoder)?; + let members: BTreeMap = members_as_vec + .into_iter() + .map(|(key_bytes, value)| { + let key = ProTxHash::from_slice(&key_bytes).map_err(|_| { + bincode::error::DecodeError::OtherString( + "Failed to decode ProTxHash".to_string(), + ) + })?; + Ok((key, value)) + }) + .collect::>()?; + + // Custom decoding for BlsPublicKey if needed + let mut public_key_bytes = [0u8; 48]; + let bytes = <[u8; 48]>::decode(decoder)?; + public_key_bytes.copy_from_slice(&bytes); + let threshold_public_key = BlsPublicKey::from_bytes(&public_key_bytes).map_err(|_| { + bincode::error::DecodeError::OtherString( + "Failed to decode BlsPublicKey in borrow decode".to_string(), + ) + })?; + + Ok(ValidatorSetV0 { + quorum_hash: QuorumHash::from_byte_array(quorum_hash), + quorum_index, + core_height, + members, + threshold_public_key, + }) + } +} + +impl Debug for ValidatorSetV0 { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.debug_struct("ValidatorSetV0") + .field("quorum_hash", &self.quorum_hash.to_string()) + .field("core_height", &self.core_height) + .field( + "members", + &self + .members + .iter() + .map(|(k, v)| (k.to_string(), v)) + .collect::>(), + ) + .field("threshold_public_key", &self.threshold_public_key) + .finish() + } +} + +/// Trait providing getter methods for `ValidatorSetV0` struct +pub trait ValidatorSetV0Getters { + /// Returns the quorum hash of the validator set. + fn quorum_hash(&self) -> &QuorumHash; + /// Returns rotation quorum index. It's available only for DIP24 quorums + fn quorum_index(&self) -> Option; + /// Returns the active height of the validator set. + fn core_height(&self) -> u32; + /// Returns the members of the validator set. + fn members(&self) -> &BTreeMap; + /// Returns the members of the validator set. + fn members_mut(&mut self) -> &mut BTreeMap; + /// Returns the members of the validator set. + fn members_owned(self) -> BTreeMap; + /// Returns the threshold public key of the validator set. + fn threshold_public_key(&self) -> &BlsPublicKey; +} + +/// Trait providing setter methods for `ValidatorSetV0` struct +pub trait ValidatorSetV0Setters { + /// Sets the quorum hash of the validator set. + fn set_quorum_hash(&mut self, quorum_hash: QuorumHash); + /// Sets the quorum index of the validator set. + fn set_quorum_index(&mut self, index: Option); + /// Sets the active height of the validator set. + fn set_core_height(&mut self, core_height: u32); + /// Sets the members of the validator set. + fn set_members(&mut self, members: BTreeMap); + /// Sets the threshold public key of the validator set. + fn set_threshold_public_key(&mut self, threshold_public_key: BlsPublicKey); +} + +impl ValidatorSetV0Getters for ValidatorSetV0 { + fn quorum_hash(&self) -> &QuorumHash { + &self.quorum_hash + } + + fn quorum_index(&self) -> Option { + self.quorum_index + } + + fn core_height(&self) -> u32 { + self.core_height + } + + fn members(&self) -> &BTreeMap { + &self.members + } + + fn members_mut(&mut self) -> &mut BTreeMap { + &mut self.members + } + + fn members_owned(self) -> BTreeMap { + self.members + } + + fn threshold_public_key(&self) -> &BlsPublicKey { + &self.threshold_public_key + } +} + +impl ValidatorSetV0Setters for ValidatorSetV0 { + fn set_quorum_hash(&mut self, quorum_hash: QuorumHash) { + self.quorum_hash = quorum_hash; + } + + fn set_quorum_index(&mut self, index: Option) { + self.quorum_index = index; + } + + fn set_core_height(&mut self, core_height: u32) { + self.core_height = core_height; + } + + fn set_members(&mut self, members: BTreeMap) { + self.members = members; + } + + fn set_threshold_public_key(&mut self, threshold_public_key: BlsPublicKey) { + self.threshold_public_key = threshold_public_key; + } +} + +#[cfg(test)] +mod tests { + use super::*; + use bincode::config; + use dashcore::PubkeyHash; + use std::collections::BTreeMap; + + #[test] + fn test_serialize_deserialize_validator_set_v0() { + // Sample data for testing + let quorum_hash = QuorumHash::from_slice(&[1; 32]).unwrap(); + let quorum_index = Some(42); + let core_height = 1000; + + // Create a sample ProTxHash and ValidatorV0 instance + let pro_tx_hash = ProTxHash::from_slice(&[2; 32]).unwrap(); + let public_key = Some(BlsPublicKey::generate()); + let node_ip = "192.168.1.1".to_string(); + let node_id = PubkeyHash::from_slice(&[4; 20]).unwrap(); + let validator = ValidatorV0 { + pro_tx_hash: pro_tx_hash.clone(), + public_key, + node_ip, + node_id, + core_port: 8080, + platform_http_port: 9090, + platform_p2p_port: 10010, + is_banned: false, + }; + + // Create a BTreeMap with one entry for the ValidatorSetV0 + let mut members = BTreeMap::new(); + members.insert(pro_tx_hash, validator); + + // Create a sample threshold public key + let threshold_public_key = BlsPublicKey::generate(); + + // Create the ValidatorSetV0 instance + let validator_set = ValidatorSetV0 { + quorum_hash, + quorum_index, + core_height, + members, + threshold_public_key, + }; + + // Serialize the ValidatorSetV0 instance + let encoded = bincode::encode_to_vec(&validator_set, config::standard()).unwrap(); + + // Deserialize the data back into a ValidatorSetV0 instance + let decoded: ValidatorSetV0 = bincode::decode_from_slice(&encoded, config::standard()) + .unwrap() + .0; + + // Verify that the deserialized instance matches the original instance + assert_eq!(validator_set, decoded); + } +} diff --git a/packages/rs-dpp/src/data_contract/document_type/methods/contested_vote_poll_for_document/v0/mod.rs b/packages/rs-dpp/src/data_contract/document_type/methods/contested_vote_poll_for_document/v0/mod.rs index d8f419a1a4..ac9911fe5b 100644 --- a/packages/rs-dpp/src/data_contract/document_type/methods/contested_vote_poll_for_document/v0/mod.rs +++ b/packages/rs-dpp/src/data_contract/document_type/methods/contested_vote_poll_for_document/v0/mod.rs @@ -3,12 +3,22 @@ use crate::data_contract::document_type::v0::DocumentTypeV0; use crate::document::{Document, DocumentV0Getters}; use crate::voting::vote_polls::contested_document_resource_vote_poll::ContestedDocumentResourceVotePoll; use crate::voting::vote_polls::VotePoll; +use platform_value::btreemap_extensions::BTreeValueMapPathHelper; +use platform_value::Value; +use std::collections::BTreeMap; impl DocumentTypeV0 { /// Figures out the prefunded voting balance (v0) for a document in a document type pub(in crate::data_contract::document_type) fn contested_vote_poll_for_document_v0( &self, document: &Document, + ) -> Option { + self.contested_vote_poll_for_document_properties_v0(document.properties()) + } + + pub(in crate::data_contract::document_type) fn contested_vote_poll_for_document_properties_v0( + &self, + document_properties: &BTreeMap, ) -> Option { self.indexes() .values() @@ -18,7 +28,11 @@ impl DocumentTypeV0 { .field_matches .iter() .all(|(field, field_match)| { - if let Some(value) = document.get(field) { + if let Some(value) = document_properties + .get_optional_at_path(field) + .ok() + .flatten() + { field_match.matches(value) } else { false @@ -29,7 +43,7 @@ impl DocumentTypeV0 { } }) .map(|index| { - let index_values = index.extract_values(document.properties()); + let index_values = index.extract_values(document_properties); VotePoll::ContestedDocumentResourceVotePoll(ContestedDocumentResourceVotePoll { contract_id: self.data_contract_id, document_type_name: self.name.clone(), diff --git a/packages/rs-dpp/src/data_contract/document_type/methods/mod.rs b/packages/rs-dpp/src/data_contract/document_type/methods/mod.rs index ca83589ccc..1c05a45304 100644 --- a/packages/rs-dpp/src/data_contract/document_type/methods/mod.rs +++ b/packages/rs-dpp/src/data_contract/document_type/methods/mod.rs @@ -138,6 +138,12 @@ pub trait DocumentTypeV0Methods { document: &Document, platform_version: &PlatformVersion, ) -> Result, ProtocolError>; + /// Gets the vote poll associated with a document + fn contested_vote_poll_for_document_properties( + &self, + document_properties: &BTreeMap, + platform_version: &PlatformVersion, + ) -> Result, ProtocolError>; } impl DocumentTypeV0Methods for DocumentTypeV0 { @@ -399,4 +405,26 @@ impl DocumentTypeV0Methods for DocumentTypeV0 { }), } } + + /// Gets the vote poll associated with a document + fn contested_vote_poll_for_document_properties( + &self, + document_properties: &BTreeMap, + platform_version: &PlatformVersion, + ) -> Result, ProtocolError> { + match platform_version + .dpp + .contract_versions + .document_type_versions + .methods + .contested_vote_poll_for_document + { + 0 => Ok(self.contested_vote_poll_for_document_properties_v0(document_properties)), + version => Err(ProtocolError::UnknownVersionMismatch { + method: "contested_vote_poll_for_document_properties".to_string(), + known_versions: vec![0], + received: version, + }), + } + } } diff --git a/packages/rs-dpp/src/data_contract/document_type/mod.rs b/packages/rs-dpp/src/data_contract/document_type/mod.rs index 89143a89a5..a87ceb3c9c 100644 --- a/packages/rs-dpp/src/data_contract/document_type/mod.rs +++ b/packages/rs-dpp/src/data_contract/document_type/mod.rs @@ -268,4 +268,14 @@ impl<'a> DocumentTypeV0Methods for DocumentTypeRef<'a> { } } } + fn contested_vote_poll_for_document_properties( + &self, + document_properties: &BTreeMap, + platform_version: &PlatformVersion, + ) -> Result, ProtocolError> { + match self { + DocumentTypeRef::V0(v0) => v0 + .contested_vote_poll_for_document_properties(document_properties, platform_version), + } + } } diff --git a/packages/rs-dpp/src/data_contract/document_type/schema/find_identifier_and_binary_paths/mod.rs b/packages/rs-dpp/src/data_contract/document_type/schema/find_identifier_and_binary_paths/mod.rs index a8f97466e7..ccd1e64fed 100644 --- a/packages/rs-dpp/src/data_contract/document_type/schema/find_identifier_and_binary_paths/mod.rs +++ b/packages/rs-dpp/src/data_contract/document_type/schema/find_identifier_and_binary_paths/mod.rs @@ -1,9 +1,9 @@ use crate::data_contract::document_type::property::DocumentProperty; use crate::data_contract::document_type::v0::DocumentTypeV0; use crate::data_contract::document_type::DocumentType; -use crate::version::dpp_versions::DocumentTypeVersions; use crate::ProtocolError; use indexmap::IndexMap; +use platform_version::version::dpp_versions::dpp_contract_versions::DocumentTypeVersions; use std::collections::BTreeSet; mod v0; diff --git a/packages/rs-dpp/src/data_contract/factory/mod.rs b/packages/rs-dpp/src/data_contract/factory/mod.rs index ff3a11ec2e..0953489760 100644 --- a/packages/rs-dpp/src/data_contract/factory/mod.rs +++ b/packages/rs-dpp/src/data_contract/factory/mod.rs @@ -39,7 +39,8 @@ impl DataContractFactory { pub fn new(protocol_version: u32) -> Result { let platform_version = PlatformVersion::get(protocol_version)?; match platform_version - .platform_architecture + .dpp + .factory_versions .data_contract_factory_structure_version { 0 => Ok(DataContractFactoryV0::new(protocol_version).into()), diff --git a/packages/rs-dpp/src/document/document_factory/mod.rs b/packages/rs-dpp/src/document/document_factory/mod.rs index b026e80551..75db720fd5 100644 --- a/packages/rs-dpp/src/document/document_factory/mod.rs +++ b/packages/rs-dpp/src/document/document_factory/mod.rs @@ -42,7 +42,8 @@ impl DocumentFactory { pub fn new(protocol_version: u32) -> Result { let platform_version = PlatformVersion::get(protocol_version)?; match platform_version - .platform_architecture + .dpp + .factory_versions .document_factory_structure_version { 0 => Ok(DocumentFactoryV0::new(protocol_version).into()), @@ -60,7 +61,8 @@ impl DocumentFactory { ) -> Result { let platform_version = PlatformVersion::get(protocol_version)?; match platform_version - .platform_architecture + .dpp + .factory_versions .document_factory_structure_version { 0 => Ok(DocumentFactoryV0::new_with_entropy_generator( diff --git a/packages/rs-dpp/src/document/specialized_document_factory/mod.rs b/packages/rs-dpp/src/document/specialized_document_factory/mod.rs index 2e8cd371cd..8a9c438804 100644 --- a/packages/rs-dpp/src/document/specialized_document_factory/mod.rs +++ b/packages/rs-dpp/src/document/specialized_document_factory/mod.rs @@ -42,7 +42,8 @@ impl SpecializedDocumentFactory { pub fn new(protocol_version: u32, data_contract: DataContract) -> Result { let platform_version = PlatformVersion::get(protocol_version)?; match platform_version - .platform_architecture + .dpp + .factory_versions .document_factory_structure_version { 0 => Ok(SpecializedDocumentFactoryV0::new(protocol_version, data_contract).into()), @@ -61,7 +62,8 @@ impl SpecializedDocumentFactory { ) -> Result { let platform_version = PlatformVersion::get(protocol_version)?; match platform_version - .platform_architecture + .dpp + .factory_versions .document_factory_structure_version { 0 => Ok(SpecializedDocumentFactoryV0::new_with_entropy_generator( diff --git a/packages/rs-dpp/src/errors/consensus/basic/basic_error.rs b/packages/rs-dpp/src/errors/consensus/basic/basic_error.rs index ea33077b76..2b24a1e280 100644 --- a/packages/rs-dpp/src/errors/consensus/basic/basic_error.rs +++ b/packages/rs-dpp/src/errors/consensus/basic/basic_error.rs @@ -52,7 +52,7 @@ use crate::consensus::basic::identity::{ InvalidIdentityUpdateTransitionDisableKeysError, InvalidIdentityUpdateTransitionEmptyError, InvalidInstantAssetLockProofError, InvalidInstantAssetLockProofSignatureError, MissingMasterPublicKeyError, NotImplementedIdentityCreditWithdrawalTransitionPoolingError, - TooManyMasterPublicKeyError, + TooManyMasterPublicKeyError, WithdrawalOutputScriptNotAllowedWhenSigningWithOwnerKeyError, }; use crate::consensus::basic::invalid_identifier_error::InvalidIdentifierError; use crate::consensus::basic::state_transition::{ @@ -335,6 +335,11 @@ pub enum BasicError { InvalidIdentityCreditWithdrawalTransitionOutputScriptError, ), + #[error(transparent)] + WithdrawalOutputScriptNotAllowedWhenSigningWithOwnerKeyError( + WithdrawalOutputScriptNotAllowedWhenSigningWithOwnerKeyError, + ), + #[error(transparent)] InvalidIdentityCreditWithdrawalTransitionCoreFeeError( InvalidIdentityCreditWithdrawalTransitionCoreFeeError, diff --git a/packages/rs-dpp/src/errors/consensus/basic/identity/invalid_identity_credit_withdrawal_transition_amount_error.rs b/packages/rs-dpp/src/errors/consensus/basic/identity/invalid_identity_credit_withdrawal_transition_amount_error.rs index 666c8ff299..11b91aba7e 100644 --- a/packages/rs-dpp/src/errors/consensus/basic/identity/invalid_identity_credit_withdrawal_transition_amount_error.rs +++ b/packages/rs-dpp/src/errors/consensus/basic/identity/invalid_identity_credit_withdrawal_transition_amount_error.rs @@ -10,7 +10,7 @@ use bincode::{Decode, Encode}; #[derive( Error, Debug, Clone, PartialEq, Eq, Encode, Decode, PlatformSerialize, PlatformDeserialize, )] -#[error("Credit withdrawal amount {amount} must be greater or equal to {min_amount}")] +#[error("Credit withdrawal amount {amount} must be greater or equal to {min_amount} and less than {max_amount}")] #[platform_serialize(unversioned)] pub struct InvalidIdentityCreditWithdrawalTransitionAmountError { /* @@ -20,11 +20,16 @@ pub struct InvalidIdentityCreditWithdrawalTransitionAmountError { */ pub amount: u64, pub min_amount: u64, + pub max_amount: u64, } impl InvalidIdentityCreditWithdrawalTransitionAmountError { - pub fn new(amount: u64, min_amount: u64) -> Self { - Self { amount, min_amount } + pub fn new(amount: u64, min_amount: u64, max_amount: u64) -> Self { + Self { + amount, + min_amount, + max_amount, + } } pub fn amount(&self) -> u64 { @@ -34,6 +39,10 @@ impl InvalidIdentityCreditWithdrawalTransitionAmountError { pub fn min_amount(&self) -> u64 { self.min_amount } + + pub fn max_amount(&self) -> u64 { + self.max_amount + } } impl From for ConsensusError { diff --git a/packages/rs-dpp/src/errors/consensus/basic/identity/invalid_identity_credit_withdrawal_transition_output_script_error.rs b/packages/rs-dpp/src/errors/consensus/basic/identity/invalid_identity_credit_withdrawal_transition_output_script_error.rs index 337cc1908c..9af57eb8be 100644 --- a/packages/rs-dpp/src/errors/consensus/basic/identity/invalid_identity_credit_withdrawal_transition_output_script_error.rs +++ b/packages/rs-dpp/src/errors/consensus/basic/identity/invalid_identity_credit_withdrawal_transition_output_script_error.rs @@ -29,6 +29,7 @@ impl InvalidIdentityCreditWithdrawalTransitionOutputScriptError { } pub fn output_script(&self) -> CoreScript { + // TODO: We shouldn't clone in getter 🤦 self.output_script.clone() } } diff --git a/packages/rs-dpp/src/errors/consensus/basic/identity/mod.rs b/packages/rs-dpp/src/errors/consensus/basic/identity/mod.rs index aafc111b85..3b411457fa 100644 --- a/packages/rs-dpp/src/errors/consensus/basic/identity/mod.rs +++ b/packages/rs-dpp/src/errors/consensus/basic/identity/mod.rs @@ -29,6 +29,7 @@ pub use invalid_instant_asset_lock_proof_signature_error::*; pub use missing_master_public_key_error::*; pub use not_implemented_identity_credit_withdrawal_transition_pooling_error::*; pub use too_many_master_public_key_error::*; +pub use withdrawal_output_script_not_allowed_when_signing_with_owner_key::*; mod data_contract_bounds_not_present_error; mod disabling_key_id_also_being_added_in_same_transition_error; @@ -62,3 +63,4 @@ mod invalid_instant_asset_lock_proof_signature_error; mod missing_master_public_key_error; mod not_implemented_identity_credit_withdrawal_transition_pooling_error; mod too_many_master_public_key_error; +mod withdrawal_output_script_not_allowed_when_signing_with_owner_key; diff --git a/packages/rs-dpp/src/errors/consensus/basic/identity/withdrawal_output_script_not_allowed_when_signing_with_owner_key.rs b/packages/rs-dpp/src/errors/consensus/basic/identity/withdrawal_output_script_not_allowed_when_signing_with_owner_key.rs new file mode 100644 index 0000000000..70f4c68b5d --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/basic/identity/withdrawal_output_script_not_allowed_when_signing_with_owner_key.rs @@ -0,0 +1,50 @@ +use crate::errors::ProtocolError; +use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; +use thiserror::Error; + +use crate::consensus::basic::BasicError; +use crate::consensus::ConsensusError; +use crate::identity::core_script::CoreScript; + +use crate::identity::KeyID; +use bincode::{Decode, Encode}; + +#[derive( + Error, Debug, Clone, PartialEq, Eq, Encode, Decode, PlatformSerialize, PlatformDeserialize, +)] +#[error("Withdrawal output script not allowed when signing with owner key {key_id}")] +#[platform_serialize(unversioned)] +pub struct WithdrawalOutputScriptNotAllowedWhenSigningWithOwnerKeyError { + output_script: CoreScript, + key_id: KeyID, +} + +/* + +DO NOT CHANGE ORDER OF FIELDS WITHOUT INTRODUCING OF NEW VERSION + +*/ + +impl WithdrawalOutputScriptNotAllowedWhenSigningWithOwnerKeyError { + pub fn new(output_script: CoreScript, key_id: KeyID) -> Self { + Self { + output_script, + key_id, + } + } + + pub fn output_script(&self) -> &CoreScript { + &self.output_script + } + + pub fn key_id(&self) -> KeyID { + self.key_id + } +} +impl From for ConsensusError { + fn from(err: WithdrawalOutputScriptNotAllowedWhenSigningWithOwnerKeyError) -> Self { + Self::BasicError( + BasicError::WithdrawalOutputScriptNotAllowedWhenSigningWithOwnerKeyError(err), + ) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/codes.rs b/packages/rs-dpp/src/errors/consensus/codes.rs index b425853896..b238f55c02 100644 --- a/packages/rs-dpp/src/errors/consensus/codes.rs +++ b/packages/rs-dpp/src/errors/consensus/codes.rs @@ -153,6 +153,7 @@ impl ErrorWithCode for BasicError { Self::MasterPublicKeyUpdateError(_) => 10529, Self::IdentityAssetLockTransactionOutPointNotEnoughBalanceError(_) => 10530, Self::IdentityAssetLockStateTransitionReplayError(_) => 10531, + Self::WithdrawalOutputScriptNotAllowedWhenSigningWithOwnerKeyError(_) => 10532, // State Transition Errors: 10600-10699 Self::InvalidStateTransitionTypeError { .. } => 10600, @@ -215,6 +216,7 @@ impl ErrorWithCode for StateError { Self::DocumentContestNotJoinableError(_) => 40111, Self::DocumentContestIdentityAlreadyContestantError(_) => 40112, Self::DocumentContestDocumentWithSameIdAlreadyPresentError(_) => 40113, + Self::DocumentContestNotPaidForError(_) => 40114, // Identity Errors: 40200-40299 Self::IdentityAlreadyExistsError(_) => 40200, @@ -231,6 +233,8 @@ impl ErrorWithCode for StateError { Self::IdentityPublicKeyAlreadyExistsForUniqueContractBoundsError(_) => 40211, Self::DocumentTypeUpdateError(_) => 40212, Self::DataContractUpdatePermissionError(_) => 40213, + Self::MissingTransferKeyError(_) => 40214, + Self::NoTransferKeyForCoreWithdrawalAvailableError(_) => 40215, // Voting Errors: 40300-40399 Self::MasternodeNotFoundError(_) => 40300, diff --git a/packages/rs-dpp/src/errors/consensus/signature/invalid_signature_public_key_purpose_error.rs b/packages/rs-dpp/src/errors/consensus/signature/invalid_signature_public_key_purpose_error.rs index 55a0596439..1477f7b1d9 100644 --- a/packages/rs-dpp/src/errors/consensus/signature/invalid_signature_public_key_purpose_error.rs +++ b/packages/rs-dpp/src/errors/consensus/signature/invalid_signature_public_key_purpose_error.rs @@ -8,11 +8,12 @@ use crate::errors::ProtocolError; use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; use bincode::{Decode, Encode}; +use itertools::Itertools; #[derive( Error, Debug, Clone, PartialEq, Eq, Encode, Decode, PlatformSerialize, PlatformDeserialize, )] -#[error("Invalid public key purpose {public_key_purpose}. The state transition requires {allowed_key_purpose}")] +#[error("Invalid public key purpose {public_key_purpose}. The state transition requires {}", allowed_key_purposes.iter().map(|s| s.to_string()).join(" | "))] #[platform_serialize(unversioned)] pub struct InvalidSignaturePublicKeyPurposeError { /* @@ -21,22 +22,22 @@ pub struct InvalidSignaturePublicKeyPurposeError { */ public_key_purpose: Purpose, - allowed_key_purpose: Purpose, + allowed_key_purposes: Vec, } impl InvalidSignaturePublicKeyPurposeError { - pub fn new(public_key_purpose: Purpose, allowed_key_purpose: Purpose) -> Self { + pub fn new(public_key_purpose: Purpose, allowed_key_purposes: Vec) -> Self { Self { public_key_purpose, - allowed_key_purpose, + allowed_key_purposes, } } pub fn public_key_purpose(&self) -> Purpose { self.public_key_purpose } - pub fn allowed_key_purpose(&self) -> Purpose { - self.allowed_key_purpose + pub fn allowed_key_purposes(&self) -> &Vec { + &self.allowed_key_purposes } } diff --git a/packages/rs-dpp/src/errors/consensus/signature/wrong_public_key_purpose_error.rs b/packages/rs-dpp/src/errors/consensus/signature/wrong_public_key_purpose_error.rs index 501cf0d64b..4ea2b0c246 100644 --- a/packages/rs-dpp/src/errors/consensus/signature/wrong_public_key_purpose_error.rs +++ b/packages/rs-dpp/src/errors/consensus/signature/wrong_public_key_purpose_error.rs @@ -8,11 +8,12 @@ use crate::errors::ProtocolError; use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; use bincode::{Decode, Encode}; +use itertools::Itertools; #[derive( Error, Debug, Clone, PartialEq, Eq, Encode, Decode, PlatformSerialize, PlatformDeserialize, )] -#[error("Invalid identity key purpose {public_key_purpose}. This state transition requires {key_purpose_requirement}")] +#[error("Invalid identity key purpose {public_key_purpose}. This state transition requires {}", allowed_key_purposes.iter().map(|s| s.to_string()).join(" | "))] #[platform_serialize(unversioned)] pub struct WrongPublicKeyPurposeError { /* @@ -21,22 +22,22 @@ pub struct WrongPublicKeyPurposeError { */ public_key_purpose: Purpose, - key_purpose_requirement: Purpose, + allowed_key_purposes: Vec, } impl WrongPublicKeyPurposeError { - pub fn new(public_key_purpose: Purpose, key_purpose_requirement: Purpose) -> Self { + pub fn new(public_key_purpose: Purpose, allowed_key_purposes: Vec) -> Self { Self { public_key_purpose, - key_purpose_requirement, + allowed_key_purposes, } } pub fn public_key_purpose(&self) -> Purpose { self.public_key_purpose } - pub fn key_purpose_requirement(&self) -> Purpose { - self.key_purpose_requirement + pub fn allowed_key_purposes(&self) -> &Vec { + &self.allowed_key_purposes } } @@ -56,7 +57,7 @@ impl From for Conse Self::SignatureError(SignatureError::WrongPublicKeyPurposeError( WrongPublicKeyPurposeError::new( value.public_key_purpose(), - value.key_purpose_requirement(), + value.allowed_key_purposes().clone(), ), )) } diff --git a/packages/rs-dpp/src/errors/consensus/state/document/document_contest_not_paid_for_error.rs b/packages/rs-dpp/src/errors/consensus/state/document/document_contest_not_paid_for_error.rs new file mode 100644 index 0000000000..9e6138c7a5 --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/state/document/document_contest_not_paid_for_error.rs @@ -0,0 +1,54 @@ +use crate::consensus::state::state_error::StateError; +use crate::consensus::ConsensusError; +use crate::errors::ProtocolError; +use crate::fee::Credits; +use bincode::{Decode, Encode}; +use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; +use platform_value::Identifier; +use thiserror::Error; + +#[derive( + Error, Debug, Clone, PartialEq, Eq, Encode, Decode, PlatformSerialize, PlatformDeserialize, +)] +#[error("Contest for document {document_id} was not paid for, needs payment of {expected_amount} Credits")] +#[platform_serialize(unversioned)] +pub struct DocumentContestNotPaidForError { + /* + + DO NOT CHANGE ORDER OF FIELDS WITHOUT INTRODUCING OF NEW VERSION + + */ + document_id: Identifier, + + expected_amount: Credits, + + paid_amount: Credits, +} + +impl DocumentContestNotPaidForError { + pub fn new(document_id: Identifier, expected_amount: Credits, paid_amount: Credits) -> Self { + Self { + document_id, + expected_amount, + paid_amount, + } + } + + pub fn document_id(&self) -> &Identifier { + &self.document_id + } + + pub fn expected_amount(&self) -> Credits { + self.expected_amount + } + + pub fn paid_amount(&self) -> Credits { + self.paid_amount + } +} + +impl From for ConsensusError { + fn from(err: DocumentContestNotPaidForError) -> Self { + Self::StateError(StateError::DocumentContestNotPaidForError(err)) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/state/document/mod.rs b/packages/rs-dpp/src/errors/consensus/state/document/mod.rs index 2a3441fe12..0c59e8741c 100644 --- a/packages/rs-dpp/src/errors/consensus/state/document/mod.rs +++ b/packages/rs-dpp/src/errors/consensus/state/document/mod.rs @@ -3,6 +3,7 @@ pub mod document_contest_currently_locked_error; pub mod document_contest_document_with_same_id_already_present_error; pub mod document_contest_identity_already_contestant; pub mod document_contest_not_joinable_error; +pub mod document_contest_not_paid_for_error; pub mod document_incorrect_purchase_price_error; pub mod document_not_for_sale_error; pub mod document_not_found_error; diff --git a/packages/rs-dpp/src/errors/consensus/state/identity/missing_transfer_key_error.rs b/packages/rs-dpp/src/errors/consensus/state/identity/missing_transfer_key_error.rs new file mode 100644 index 0000000000..2f14ccacbc --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/state/identity/missing_transfer_key_error.rs @@ -0,0 +1,36 @@ +use crate::consensus::state::state_error::StateError; +use crate::consensus::ConsensusError; +use crate::errors::ProtocolError; +use bincode::{Decode, Encode}; +use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; +use platform_value::Identifier; +use thiserror::Error; + +#[derive( + Error, Debug, Clone, PartialEq, Eq, Encode, Decode, PlatformSerialize, PlatformDeserialize, +)] +#[error("Identity {identity_id} does not have a key for transferring funds")] +#[platform_serialize(unversioned)] +pub struct MissingTransferKeyError { + /* + + DO NOT CHANGE ORDER OF FIELDS WITHOUT INTRODUCING OF NEW VERSION + + */ + identity_id: Identifier, +} + +impl MissingTransferKeyError { + pub fn new(identity_id: Identifier) -> Self { + Self { identity_id } + } + + pub fn identity_id(&self) -> &Identifier { + &self.identity_id + } +} +impl From for ConsensusError { + fn from(err: MissingTransferKeyError) -> Self { + Self::StateError(StateError::MissingTransferKeyError(err)) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/state/identity/mod.rs b/packages/rs-dpp/src/errors/consensus/state/identity/mod.rs index 53a60d0ed4..35e6f7f79a 100644 --- a/packages/rs-dpp/src/errors/consensus/state/identity/mod.rs +++ b/packages/rs-dpp/src/errors/consensus/state/identity/mod.rs @@ -14,3 +14,5 @@ pub mod invalid_identity_revision_error; pub mod master_public_key_update_error; pub mod max_identity_public_key_limit_reached_error; pub mod missing_identity_public_key_ids_error; +pub mod missing_transfer_key_error; +pub mod no_transfer_key_for_core_withdrawal_available_error; diff --git a/packages/rs-dpp/src/errors/consensus/state/identity/no_transfer_key_for_core_withdrawal_available_error.rs b/packages/rs-dpp/src/errors/consensus/state/identity/no_transfer_key_for_core_withdrawal_available_error.rs new file mode 100644 index 0000000000..77f5d52305 --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/state/identity/no_transfer_key_for_core_withdrawal_available_error.rs @@ -0,0 +1,38 @@ +use crate::consensus::state::state_error::StateError; +use crate::consensus::ConsensusError; +use crate::errors::ProtocolError; +use bincode::{Decode, Encode}; +use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}; +use platform_value::Identifier; +use thiserror::Error; + +#[derive( + Error, Debug, Clone, PartialEq, Eq, Encode, Decode, PlatformSerialize, PlatformDeserialize, +)] +#[error("There is no transfer key that can be used for a withdrawal")] +#[platform_serialize(unversioned)] +pub struct NoTransferKeyForCoreWithdrawalAvailableError { + /* + + DO NOT CHANGE ORDER OF FIELDS WITHOUT INTRODUCING OF NEW VERSION + + */ + identity_id: Identifier, +} + +impl NoTransferKeyForCoreWithdrawalAvailableError { + pub fn new(identity_id: Identifier) -> Self { + Self { identity_id } + } + + pub fn identity_id(&self) -> &Identifier { + &self.identity_id + } +} +impl From for ConsensusError { + fn from(err: NoTransferKeyForCoreWithdrawalAvailableError) -> Self { + Self::StateError(StateError::NoTransferKeyForCoreWithdrawalAvailableError( + err, + )) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/state/state_error.rs b/packages/rs-dpp/src/errors/consensus/state/state_error.rs index 4cc4991c6c..8b0ac2b26b 100644 --- a/packages/rs-dpp/src/errors/consensus/state/state_error.rs +++ b/packages/rs-dpp/src/errors/consensus/state/state_error.rs @@ -33,10 +33,13 @@ use crate::consensus::state::document::document_contest_currently_locked_error:: use crate::consensus::state::document::document_contest_document_with_same_id_already_present_error::DocumentContestDocumentWithSameIdAlreadyPresentError; use crate::consensus::state::document::document_contest_identity_already_contestant::DocumentContestIdentityAlreadyContestantError; use crate::consensus::state::document::document_contest_not_joinable_error::DocumentContestNotJoinableError; +use crate::consensus::state::document::document_contest_not_paid_for_error::DocumentContestNotPaidForError; use crate::consensus::state::document::document_incorrect_purchase_price_error::DocumentIncorrectPurchasePriceError; use crate::consensus::state::document::document_not_for_sale_error::DocumentNotForSaleError; use crate::consensus::state::identity::identity_public_key_already_exists_for_unique_contract_bounds_error::IdentityPublicKeyAlreadyExistsForUniqueContractBoundsError; use crate::consensus::state::identity::invalid_identity_contract_nonce_error::InvalidIdentityNonceError; +use crate::consensus::state::identity::missing_transfer_key_error::MissingTransferKeyError; +use crate::consensus::state::identity::no_transfer_key_for_core_withdrawal_available_error::NoTransferKeyForCoreWithdrawalAvailableError; use crate::consensus::state::prefunded_specialized_balances::prefunded_specialized_balance_insufficient_error::PrefundedSpecializedBalanceInsufficientError; use crate::consensus::state::prefunded_specialized_balances::prefunded_specialized_balance_not_found_error::PrefundedSpecializedBalanceNotFoundError; use crate::consensus::state::voting::masternode_incorrect_voter_identity_id_error::MasternodeIncorrectVoterIdentityIdError; @@ -79,6 +82,9 @@ pub enum StateError { #[error(transparent)] DocumentContestIdentityAlreadyContestantError(DocumentContestIdentityAlreadyContestantError), + #[error(transparent)] + DocumentContestNotPaidForError(DocumentContestNotPaidForError), + #[error(transparent)] DocumentContestDocumentWithSameIdAlreadyPresentError( DocumentContestDocumentWithSameIdAlreadyPresentError, @@ -122,6 +128,12 @@ pub enum StateError { #[error(transparent)] MissingIdentityPublicKeyIdsError(MissingIdentityPublicKeyIdsError), + #[error(transparent)] + MissingTransferKeyError(MissingTransferKeyError), + + #[error(transparent)] + NoTransferKeyForCoreWithdrawalAvailableError(NoTransferKeyForCoreWithdrawalAvailableError), + #[error(transparent)] InvalidIdentityPublicKeyIdError(InvalidIdentityPublicKeyIdError), diff --git a/packages/rs-dpp/src/fee/default_costs/mod.rs b/packages/rs-dpp/src/fee/default_costs/mod.rs index 9af68bb143..b1ad372c07 100644 --- a/packages/rs-dpp/src/fee/default_costs/mod.rs +++ b/packages/rs-dpp/src/fee/default_costs/mod.rs @@ -1,32 +1,3 @@ -// MIT LICENSE -// -// Copyright (c) 2021 Dash Core Group -// -// Permission is hereby granted, free of charge, to any -// person obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the -// Software without restriction, including without -// limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software -// is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice -// shall be included in all copies or substantial portions -// of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. -// - //! Fee costs //! //! Fee costs for Known Platform operations @@ -34,13 +5,22 @@ use crate::block::epoch::{Epoch, EpochIndex}; use crate::fee::Credits; -use platform_version::version::fee::FeeVersion; -use platform_version::version::PlatformVersion; +use platform_version::version::fee::{ + FeeVersion, FeeVersionFieldsBeforeVersion4, FeeVersionNumber, +}; use std::collections::BTreeMap; pub mod constants; -pub type CachedEpochIndexFeeVersions = BTreeMap; +pub type CachedEpochIndexFeeVersions = BTreeMap; +pub type EpochIndexFeeVersionsForStorage = BTreeMap; + +// This is type only meant for deserialization because of an issue +// The issue was that the platform state was stored with FeeVersions in it before version 1.4 +// When we would add new fields we would be unable to deserialize +// This FeeProcessingVersionFieldsBeforeVersion4 is how things were before version 1.4 was released +pub type CachedEpochIndexFeeVersionsFieldsBeforeVersion4 = + BTreeMap; /// A Known Cost Item is an item that changes costs depending on the Epoch #[derive(Eq, PartialEq, Copy, Clone, Hash)] @@ -143,7 +123,10 @@ impl KnownCostItem { pub trait EpochCosts { /// Get the closest epoch in the past that has a cost table /// This is where the base costs last changed - fn active_fee_version(&self, cached_fee_version: &CachedEpochIndexFeeVersions) -> FeeVersion; + fn active_fee_version( + &self, + cached_fee_version: &CachedEpochIndexFeeVersions, + ) -> &'static FeeVersion; /// Get the cost for the known cost item fn cost_for_known_cost_item( &self, @@ -154,18 +137,20 @@ pub trait EpochCosts { impl EpochCosts for Epoch { /// Get the active fee version for an epoch - fn active_fee_version(&self, cached_fee_version: &CachedEpochIndexFeeVersions) -> FeeVersion { + fn active_fee_version( + &self, + cached_fee_version: &CachedEpochIndexFeeVersions, + ) -> &'static FeeVersion { // If the exact EpochIndex is matching to a FeeVersion update if let Some(fee_version) = cached_fee_version.get(&self.index) { - return fee_version.clone(); + return fee_version; } // else return the FeeVersion at lower adjacent EpochIndex (if available, else the FeeVersion of first PlatformVersion) cached_fee_version .range(..=self.index) .next_back() - .map(|(_, fee_version)| fee_version) - .unwrap_or_else(|| &PlatformVersion::first().fee_version) - .clone() + .map(|(_, fee_version)| *fee_version) + .unwrap_or_else(|| FeeVersion::first()) } /// Get the cost for the known cost item diff --git a/packages/rs-dpp/src/fee/fee_result/refunds.rs b/packages/rs-dpp/src/fee/fee_result/refunds.rs index f95fd379d2..90b93159a4 100644 --- a/packages/rs-dpp/src/fee/fee_result/refunds.rs +++ b/packages/rs-dpp/src/fee/fee_result/refunds.rs @@ -182,10 +182,10 @@ impl IntoIterator for FeeRefunds { mod tests { use super::*; use once_cell::sync::Lazy; - use platform_version::version::PlatformVersion; + use platform_version::version::fee::FeeVersion; static EPOCH_CHANGE_FEE_VERSION_TEST: Lazy = - Lazy::new(|| BTreeMap::from([(0, PlatformVersion::first().fee_version.clone())])); + Lazy::new(|| BTreeMap::from([(0, FeeVersion::first())])); mod from_storage_removal { use super::*; diff --git a/packages/rs-dpp/src/identity/core_script.rs b/packages/rs-dpp/src/identity/core_script.rs index 96cea532c7..ff43e44571 100644 --- a/packages/rs-dpp/src/identity/core_script.rs +++ b/packages/rs-dpp/src/identity/core_script.rs @@ -39,27 +39,35 @@ impl CoreScript { Self(bytes.into()) } - pub fn random_p2pkh(rng: &mut StdRng) -> Self { + pub fn new_p2pkh(key_hash: [u8; 20]) -> Self { let mut bytes: Vec = vec![ opcodes::all::OP_DUP.to_u8(), opcodes::all::OP_HASH160.to_u8(), opcodes::all::OP_PUSHBYTES_20.to_u8(), ]; - bytes.append(&mut rng.gen::<[u8; 20]>().to_vec()); + bytes.extend_from_slice(&key_hash); bytes.push(opcodes::all::OP_EQUALVERIFY.to_u8()); bytes.push(opcodes::all::OP_CHECKSIG.to_u8()); Self::from_bytes(bytes) } - pub fn random_p2sh(rng: &mut StdRng) -> Self { + pub fn new_p2sh(script_hash: [u8; 20]) -> Self { let mut bytes = vec![ opcodes::all::OP_HASH160.to_u8(), opcodes::all::OP_PUSHBYTES_20.to_u8(), ]; - bytes.append(&mut rng.gen::<[u8; 20]>().to_vec()); + bytes.extend_from_slice(&script_hash); bytes.push(opcodes::all::OP_EQUAL.to_u8()); Self::from_bytes(bytes) } + + pub fn random_p2sh(rng: &mut StdRng) -> Self { + Self::new_p2sh(rng.gen()) + } + + pub fn random_p2pkh(rng: &mut StdRng) -> Self { + Self::new_p2pkh(rng.gen()) + } } impl From> for CoreScript { diff --git a/packages/rs-dpp/src/identity/identity_facade.rs b/packages/rs-dpp/src/identity/identity_facade.rs index 919c68c624..eecdf45e6e 100644 --- a/packages/rs-dpp/src/identity/identity_facade.rs +++ b/packages/rs-dpp/src/identity/identity_facade.rs @@ -123,7 +123,7 @@ impl IdentityFacade { amount: u64, core_fee_per_byte: u32, pooling: Pooling, - output_script: CoreScript, + output_script: Option, identity_nonce: u64, ) -> Result { self.factory.create_identity_credit_withdrawal_transition( diff --git a/packages/rs-dpp/src/identity/identity_factory.rs b/packages/rs-dpp/src/identity/identity_factory.rs index c6aface591..48f7369818 100644 --- a/packages/rs-dpp/src/identity/identity_factory.rs +++ b/packages/rs-dpp/src/identity/identity_factory.rs @@ -43,6 +43,8 @@ use crate::state_transition::identity_credit_transfer_transition::IdentityCredit #[cfg(all(feature = "state-transitions", feature = "client"))] use crate::state_transition::identity_credit_withdrawal_transition::v0::IdentityCreditWithdrawalTransitionV0; #[cfg(all(feature = "state-transitions", feature = "client"))] +use crate::state_transition::identity_credit_withdrawal_transition::v1::IdentityCreditWithdrawalTransitionV1; +#[cfg(all(feature = "state-transitions", feature = "client"))] use crate::state_transition::identity_credit_withdrawal_transition::IdentityCreditWithdrawalTransition; #[cfg(all(feature = "state-transitions", feature = "client"))] use crate::state_transition::identity_topup_transition::accessors::IdentityTopUpTransitionAccessorsV0; @@ -233,22 +235,61 @@ impl IdentityFactory { amount: u64, core_fee_per_byte: u32, pooling: Pooling, - output_script: CoreScript, + output_script: Option, identity_nonce: IdentityNonce, ) -> Result { - let identity_credit_withdrawal_transition = IdentityCreditWithdrawalTransitionV0 { - identity_id, - amount, - core_fee_per_byte, - pooling, - output_script, - nonce: identity_nonce, - ..Default::default() + let platform_version = PlatformVersion::get(self.protocol_version)?; + + let identity_credit_withdrawal_transition = match platform_version + .dpp + .state_transitions + .identities + .credit_withdrawal + .default_constructor + { + 0 => { + let output_script = output_script.ok_or_else(|| { + ProtocolError::Generic( + "Output script is required for IdentityCreditWithdrawalTransitionV0" + .to_string(), + ) + })?; + + let transition = IdentityCreditWithdrawalTransitionV0 { + identity_id, + amount, + core_fee_per_byte, + pooling, + output_script, + nonce: identity_nonce, + ..Default::default() + }; + + IdentityCreditWithdrawalTransition::from(transition) + } + 1 => { + let transition = IdentityCreditWithdrawalTransitionV1 { + identity_id, + amount, + core_fee_per_byte, + pooling, + output_script, + nonce: identity_nonce, + ..Default::default() + }; + + IdentityCreditWithdrawalTransition::from(transition) + } + version => { + return Err(ProtocolError::UnknownVersionMismatch { + method: "create_identity_credit_withdrawal_transition".to_string(), + known_versions: vec![0, 1], + received: version, + }); + } }; - Ok(IdentityCreditWithdrawalTransition::from( - identity_credit_withdrawal_transition, - )) + Ok(identity_credit_withdrawal_transition) } #[cfg(all(feature = "state-transitions", feature = "client"))] diff --git a/packages/rs-dpp/src/identity/identity_public_key/key_type.rs b/packages/rs-dpp/src/identity/identity_public_key/key_type.rs index 0e469272da..e40437a33e 100644 --- a/packages/rs-dpp/src/identity/identity_public_key/key_type.rs +++ b/packages/rs-dpp/src/identity/identity_public_key/key_type.rs @@ -1,4 +1,3 @@ -#[cfg(feature = "random-public-keys")] use crate::util::hash::ripemd160_sha256; use anyhow::bail; use bincode::{Decode, Encode}; @@ -8,16 +7,14 @@ use ciborium::value::Value as CborValue; use dashcore::secp256k1::rand::rngs::StdRng as EcdsaRng; #[cfg(feature = "random-public-keys")] use dashcore::secp256k1::rand::SeedableRng; -#[cfg(feature = "random-public-keys")] use dashcore::secp256k1::Secp256k1; -#[cfg(feature = "random-public-keys")] -use dashcore::Network; +use dashcore::{bls_signatures, ed25519_dalek, Network}; use itertools::Itertools; use lazy_static::lazy_static; use crate::fee::Credits; use crate::version::PlatformVersion; -use crate::ProtocolError; +use crate::{InvalidVectorSizeError, ProtocolError}; #[cfg(feature = "random-public-keys")] use rand::rngs::StdRng; #[cfg(feature = "random-public-keys")] @@ -100,6 +97,17 @@ impl KeyType { } } + /// Can this key type be understood as an address on the Core chain? + pub fn is_core_address_key_type(&self) -> bool { + match self { + KeyType::ECDSA_SECP256K1 => false, + KeyType::BLS12_381 => false, + KeyType::ECDSA_HASH160 => true, + KeyType::BIP13_SCRIPT_HASH => true, + KeyType::EDDSA_25519_HASH160 => false, + } + } + pub fn signature_verify_cost( &self, platform_version: &PlatformVersion, @@ -193,6 +201,73 @@ impl KeyType { } } + /// Gets the public key data for a private key depending on the key type + pub fn public_key_data_from_private_key_data( + &self, + private_key_bytes: &[u8], + network: Network, + ) -> Result, ProtocolError> { + match self { + KeyType::ECDSA_SECP256K1 => { + let secp = Secp256k1::new(); + let secret_key = dashcore::secp256k1::SecretKey::from_slice(private_key_bytes) + .map_err(|e| ProtocolError::Generic(e.to_string()))?; + let private_key = dashcore::PrivateKey::new(secret_key, network); + + Ok(private_key.public_key(&secp).to_bytes()) + } + KeyType::BLS12_381 => { + #[cfg(feature = "bls-signatures")] + { + let private_key = + bls_signatures::PrivateKey::from_bytes(private_key_bytes, false) + .map_err(|e| ProtocolError::Generic(e.to_string()))?; + let public_key_bytes = private_key + .g1_element() + .expect("expected to get a public key from a bls private key") + .to_bytes() + .to_vec(); + Ok(public_key_bytes) + } + #[cfg(not(feature = "bls-signatures"))] + return Err(ProtocolError::NotSupported( + "Converting a private key to a bls public key is not supported without the bls-signatures feature".to_string(), + )); + } + KeyType::ECDSA_HASH160 => { + let secp = Secp256k1::new(); + let secret_key = dashcore::secp256k1::SecretKey::from_slice(private_key_bytes) + .map_err(|e| ProtocolError::Generic(e.to_string()))?; + let private_key = dashcore::PrivateKey::new(secret_key, network); + + Ok(ripemd160_sha256(private_key.public_key(&secp).to_bytes().as_slice()).to_vec()) + } + KeyType::EDDSA_25519_HASH160 => { + #[cfg(feature = "ed25519-dalek")] + { + let key_pair = ed25519_dalek::SigningKey::from_bytes( + &private_key_bytes.try_into().map_err(|_| { + ProtocolError::InvalidVectorSizeError(InvalidVectorSizeError::new( + 32, + private_key_bytes.len(), + )) + })?, + ); + Ok(ripemd160_sha256(key_pair.verifying_key().to_bytes().as_slice()).to_vec()) + } + #[cfg(not(feature = "ed25519-dalek"))] + return Err(ProtocolError::NotSupported( + "Converting a private key to a eddsa hash 160 is not supported without the ed25519-dalek feature".to_string(), + )); + } + KeyType::BIP13_SCRIPT_HASH => { + return Err(ProtocolError::NotSupported( + "Converting a private key to a script hash is not supported".to_string(), + )); + } + } + } + #[cfg(feature = "random-public-keys")] /// Gets the default size of the public key pub fn random_public_and_private_key_data_v0(&self, rng: &mut StdRng) -> (Vec, Vec) { @@ -230,7 +305,7 @@ impl KeyType { KeyType::EDDSA_25519_HASH160 => { let key_pair = ed25519_dalek::SigningKey::generate(rng); ( - key_pair.verifying_key().to_bytes().to_vec(), + ripemd160_sha256(key_pair.verifying_key().to_bytes().as_slice()).to_vec(), key_pair.to_bytes().to_vec(), ) } diff --git a/packages/rs-dpp/src/identity/identity_public_key/methods/hash/mod.rs b/packages/rs-dpp/src/identity/identity_public_key/methods/hash/mod.rs index 6978a3035d..b22a3f0c26 100644 --- a/packages/rs-dpp/src/identity/identity_public_key/methods/hash/mod.rs +++ b/packages/rs-dpp/src/identity/identity_public_key/methods/hash/mod.rs @@ -2,6 +2,7 @@ mod v0; use crate::identity::IdentityPublicKey; use crate::ProtocolError; +use dashcore::Network; pub use v0::*; impl IdentityPublicKeyHashMethodsV0 for IdentityPublicKey { @@ -10,4 +11,14 @@ impl IdentityPublicKeyHashMethodsV0 for IdentityPublicKey { IdentityPublicKey::V0(v0) => v0.public_key_hash(), } } + + fn validate_private_key_bytes( + &self, + private_key_bytes: &[u8], + network: Network, + ) -> Result { + match self { + IdentityPublicKey::V0(v0) => v0.validate_private_key_bytes(private_key_bytes, network), + } + } } diff --git a/packages/rs-dpp/src/identity/identity_public_key/methods/hash/v0/mod.rs b/packages/rs-dpp/src/identity/identity_public_key/methods/hash/v0/mod.rs index 7b656292e3..b11c79c31f 100644 --- a/packages/rs-dpp/src/identity/identity_public_key/methods/hash/v0/mod.rs +++ b/packages/rs-dpp/src/identity/identity_public_key/methods/hash/v0/mod.rs @@ -1,6 +1,14 @@ use crate::ProtocolError; +use dashcore::Network; pub trait IdentityPublicKeyHashMethodsV0 { /// Get the original public key hash fn public_key_hash(&self) -> Result<[u8; 20], ProtocolError>; + + /// Verifies that the private key bytes match this identity public key + fn validate_private_key_bytes( + &self, + private_key_bytes: &[u8], + network: Network, + ) -> Result; } diff --git a/packages/rs-dpp/src/identity/identity_public_key/purpose.rs b/packages/rs-dpp/src/identity/identity_public_key/purpose.rs index dbadfa5748..36255fdc45 100644 --- a/packages/rs-dpp/src/identity/identity_public_key/purpose.rs +++ b/packages/rs-dpp/src/identity/identity_public_key/purpose.rs @@ -1,4 +1,6 @@ -use crate::identity::Purpose::{AUTHENTICATION, DECRYPTION, ENCRYPTION, SYSTEM, TRANSFER, VOTING}; +use crate::identity::Purpose::{ + AUTHENTICATION, DECRYPTION, ENCRYPTION, OWNER, SYSTEM, TRANSFER, VOTING, +}; use anyhow::bail; use bincode::{Decode, Encode}; #[cfg(feature = "cbor")] @@ -37,6 +39,8 @@ pub enum Purpose { SYSTEM = 4, /// this key cannot be used for signing documents VOTING = 5, + /// this key is used to prove ownership of a masternode or evonode + OWNER = 6, } impl From for [u8; 1] { @@ -54,6 +58,7 @@ impl From for &'static [u8; 1] { TRANSFER => &[3], SYSTEM => &[4], VOTING => &[5], + OWNER => &[6], } } } @@ -68,6 +73,7 @@ impl TryFrom for Purpose { 3 => Ok(TRANSFER), 4 => Ok(SYSTEM), 5 => Ok(VOTING), + 6 => Ok(OWNER), value => bail!("unrecognized purpose: {}", value), } } @@ -83,6 +89,7 @@ impl TryFrom for Purpose { 3 => Ok(TRANSFER), 4 => Ok(SYSTEM), 5 => Ok(VOTING), + 6 => Ok(OWNER), value => bail!("unrecognized purpose: {}", value), } } @@ -102,8 +109,15 @@ impl std::fmt::Display for Purpose { impl Purpose { /// The full range of purposes - pub fn full_range() -> [Purpose; 5] { - [AUTHENTICATION, ENCRYPTION, DECRYPTION, TRANSFER, VOTING] + pub fn full_range() -> [Purpose; 6] { + [ + AUTHENTICATION, + ENCRYPTION, + DECRYPTION, + TRANSFER, + VOTING, + OWNER, + ] } /// Just the authentication and withdraw purposes pub fn searchable_purposes() -> [Purpose; 3] { @@ -113,8 +127,4 @@ impl Purpose { pub fn encryption_decryption() -> [Purpose; 2] { [ENCRYPTION, DECRYPTION] } - /// The last purpose - pub fn last() -> Purpose { - Self::TRANSFER - } } diff --git a/packages/rs-dpp/src/identity/identity_public_key/random.rs b/packages/rs-dpp/src/identity/identity_public_key/random.rs index 0dea7a5dee..dec286b927 100644 --- a/packages/rs-dpp/src/identity/identity_public_key/random.rs +++ b/packages/rs-dpp/src/identity/identity_public_key/random.rs @@ -467,6 +467,149 @@ impl IdentityPublicKey { } } + /// Generates a random ECDSA critical-level authentication key for a masternode owner. + /// + /// This function generates a random key that can be used for owner authentication in a masternode context. + /// The function accepts an optional seed for deterministic key generation, or uses entropy-based randomness if no seed is provided. + /// + /// # Parameters + /// + /// * `id`: The identifier (`KeyID`) for the masternode owner key. + /// * `seed`: An optional `u64` value used to seed the random number generator. If `None`, the RNG will be seeded from entropy. + /// * `platform_version`: A reference to the `PlatformVersion` struct, which is used to determine the correct key structure version. + /// + /// # Returns + /// + /// Returns a tuple containing the generated `IdentityPublicKey` for the masternode owner and the corresponding private key as a byte vector. + /// + /// # Errors + /// + /// Returns a `ProtocolError` if the platform version is not supported. + pub fn random_masternode_owner_key( + id: KeyID, + seed: Option, + platform_version: &PlatformVersion, + ) -> Result<(Self, Vec), ProtocolError> { + let mut rng = match seed { + None => StdRng::from_entropy(), + Some(seed_value) => StdRng::seed_from_u64(seed_value), + }; + Self::random_masternode_owner_key_with_rng(id, &mut rng, platform_version) + } + + /// Generates a random ECDSA critical-level authentication key for a masternode owner using a custom RNG. + /// + /// This function generates a random key using a given random number generator (RNG). This is useful when specific control over the randomness is needed. + /// + /// # Parameters + /// + /// * `id`: The identifier (`KeyID`) for the masternode owner key. + /// * `rng`: A mutable reference to a `StdRng` instance used to generate randomness. + /// * `platform_version`: A reference to the `PlatformVersion` struct, which is used to determine the correct key structure version. + /// + /// # Returns + /// + /// Returns a tuple containing the generated `IdentityPublicKey` for the masternode owner and the corresponding private key as a byte vector. + /// + /// # Errors + /// + /// Returns a `ProtocolError` if the platform version is not supported. + pub fn random_masternode_owner_key_with_rng( + id: KeyID, + rng: &mut StdRng, + platform_version: &PlatformVersion, + ) -> Result<(Self, Vec), ProtocolError> { + match platform_version + .dpp + .identity_versions + .identity_key_structure_version + { + 0 => { + let (key, private_key) = + IdentityPublicKeyV0::random_owner_key_with_rng(id, rng, platform_version)?; + Ok((key.into(), private_key)) + } + version => Err(ProtocolError::UnknownVersionMismatch { + method: "IdentityPublicKey::random_masternode_owner_key_with_rng".to_string(), + known_versions: vec![0], + received: version, + }), + } + } + + /// Generates a random ECDSA critical-level transfer key for a masternode. + /// + /// This function generates a random key for use in transferring ownership of a masternode. An optional seed can be provided for deterministic key generation, or entropy-based randomness is used if no seed is given. + /// + /// # Parameters + /// + /// * `id`: The identifier (`KeyID`) for the masternode transfer key. + /// * `seed`: An optional `u64` value used to seed the random number generator. If `None`, the RNG will be seeded from entropy. + /// * `platform_version`: A reference to the `PlatformVersion` struct, which is used to determine the correct key structure version. + /// + /// # Returns + /// + /// Returns a tuple containing the generated `IdentityPublicKey` for the masternode transfer key and the corresponding private key as a byte vector. + /// + /// # Errors + /// + /// Returns a `ProtocolError` if the platform version is not supported. + pub fn random_masternode_transfer_key( + id: KeyID, + seed: Option, + platform_version: &PlatformVersion, + ) -> Result<(Self, Vec), ProtocolError> { + let mut rng = match seed { + None => StdRng::from_entropy(), + Some(seed_value) => StdRng::seed_from_u64(seed_value), + }; + Self::random_masternode_transfer_key_with_rng(id, &mut rng, platform_version) + } + + /// Generates a random ECDSA critical-level transfer key for a masternode using a custom RNG. + /// + /// This function generates a random key for masternode transfers using a given random number generator (RNG). + /// + /// # Parameters + /// + /// * `id`: The identifier (`KeyID`) for the masternode transfer key. + /// * `rng`: A mutable reference to a `StdRng` instance used to generate randomness. + /// * `platform_version`: A reference to the `PlatformVersion` struct, which is used to determine the correct key structure version. + /// + /// # Returns + /// + /// Returns a tuple containing the generated `IdentityPublicKey` for the masternode transfer key and the corresponding private key as a byte vector. + /// + /// # Errors + /// + /// Returns a `ProtocolError` if the platform version is not supported. + pub fn random_masternode_transfer_key_with_rng( + id: KeyID, + rng: &mut StdRng, + platform_version: &PlatformVersion, + ) -> Result<(Self, Vec), ProtocolError> { + match platform_version + .dpp + .identity_versions + .identity_key_structure_version + { + 0 => { + let (key, private_key) = + IdentityPublicKeyV0::random_masternode_transfer_key_with_rng( + id, + rng, + platform_version, + )?; + Ok((key.into(), private_key)) + } + version => Err(ProtocolError::UnknownVersionMismatch { + method: "IdentityPublicKey::random_masternode_transfer_key_with_rng".to_string(), + known_versions: vec![0], + received: version, + }), + } + } + /// Generates a random ECDSA high-level authentication public key along with its corresponding private key. /// /// This method constructs a random ECDSA (using the secp256k1 curve) high-level authentication public key diff --git a/packages/rs-dpp/src/identity/identity_public_key/security_level.rs b/packages/rs-dpp/src/identity/identity_public_key/security_level.rs index 978134016b..4cd9f0d2ed 100644 --- a/packages/rs-dpp/src/identity/identity_public_key/security_level.rs +++ b/packages/rs-dpp/src/identity/identity_public_key/security_level.rs @@ -35,6 +35,23 @@ pub enum SecurityLevel { MEDIUM = 3, } +impl From for [u8; 1] { + fn from(security_level: SecurityLevel) -> Self { + [security_level as u8] + } +} + +impl From for &'static [u8; 1] { + fn from(security_level: SecurityLevel) -> Self { + match security_level { + SecurityLevel::MASTER => &[0], + SecurityLevel::CRITICAL => &[1], + SecurityLevel::HIGH => &[2], + SecurityLevel::MEDIUM => &[3], + } + } +} + #[cfg(feature = "cbor")] impl Into for SecurityLevel { fn into(self) -> CborValue { diff --git a/packages/rs-dpp/src/identity/identity_public_key/v0/methods/mod.rs b/packages/rs-dpp/src/identity/identity_public_key/v0/methods/mod.rs index 05232ed22a..470dc92b9b 100644 --- a/packages/rs-dpp/src/identity/identity_public_key/v0/methods/mod.rs +++ b/packages/rs-dpp/src/identity/identity_public_key/v0/methods/mod.rs @@ -5,7 +5,9 @@ use crate::util::hash::ripemd160_sha256; use crate::ProtocolError; use anyhow::anyhow; use dashcore::hashes::Hash; -use dashcore::PublicKey as ECDSAPublicKey; +use dashcore::key::Secp256k1; +use dashcore::secp256k1::SecretKey; +use dashcore::{bls_signatures, ed25519_dalek, Network, PublicKey as ECDSAPublicKey}; use platform_value::Bytes20; impl IdentityPublicKeyHashMethodsV0 for IdentityPublicKeyV0 { @@ -45,4 +47,213 @@ impl IdentityPublicKeyHashMethodsV0 for IdentityPublicKeyV0 { } } } + + fn validate_private_key_bytes( + &self, + private_key_bytes: &[u8], + network: Network, + ) -> Result { + match self.key_type { + KeyType::ECDSA_SECP256K1 => { + let secp = Secp256k1::new(); + let secret_key = match SecretKey::from_slice(private_key_bytes) { + Ok(secret_key) => secret_key, + Err(_) => return Ok(false), + }; + let private_key = dashcore::PrivateKey::new(secret_key, network); + + Ok(private_key.public_key(&secp).to_bytes() == self.data.as_slice()) + } + KeyType::BLS12_381 => { + #[cfg(feature = "bls-signatures")] + { + let private_key = + match bls_signatures::PrivateKey::from_bytes(private_key_bytes, false) { + Ok(secret_key) => secret_key, + Err(_) => return Ok(false), + }; + let g1_element = match private_key.g1_element() { + Ok(g1_element) => g1_element, + Err(_) => return Ok(false), + }; + + Ok(g1_element.to_bytes().as_slice() == self.data.as_slice()) + } + #[cfg(not(feature = "bls-signatures"))] + return Err(ProtocolError::NotSupported( + "Converting a private key to a bls public key is not supported without the bls-signatures feature".to_string(), + )); + } + KeyType::ECDSA_HASH160 => { + let secp = Secp256k1::new(); + let secret_key = match SecretKey::from_slice(private_key_bytes) { + Ok(secret_key) => secret_key, + Err(_) => return Ok(false), + }; + let private_key = dashcore::PrivateKey::new(secret_key, network); + + Ok( + ripemd160_sha256(private_key.public_key(&secp).to_bytes().as_slice()) + .as_slice() + == self.data.as_slice(), + ) + } + KeyType::EDDSA_25519_HASH160 => { + #[cfg(feature = "ed25519-dalek")] + { + let secret_key = match private_key_bytes.try_into() { + Ok(secret_key) => secret_key, + Err(_) => return Ok(false), + }; + let key_pair = ed25519_dalek::SigningKey::from_bytes(&secret_key); + Ok( + ripemd160_sha256(key_pair.verifying_key().to_bytes().as_slice()).as_slice() + == self.data.as_slice(), + ) + } + #[cfg(not(feature = "ed25519-dalek"))] + return Err(ProtocolError::NotSupported( + "Converting a private key to a eddsa hash 160 is not supported without the ed25519-dalek feature".to_string(), + )); + } + KeyType::BIP13_SCRIPT_HASH => { + return Err(ProtocolError::NotSupported( + "Converting a private key to a script hash is not supported".to_string(), + )); + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::identity::{Purpose, SecurityLevel}; + use dashcore::Network; + use dpp::version::PlatformVersion; + use rand::rngs::StdRng; + use rand::SeedableRng; + + #[cfg(feature = "random-public-keys")] + #[test] + fn test_validate_private_key_bytes_with_random_keys() { + let platform_version = PlatformVersion::latest(); + let mut rng = StdRng::from_entropy(); + + // Test for ECDSA_SECP256K1 + let key_type = KeyType::ECDSA_SECP256K1; + let (public_key_data, private_key_data) = key_type + .random_public_and_private_key_data(&mut rng, &platform_version) + .expect("expected to generate random keys"); + + let identity_public_key = IdentityPublicKeyV0 { + id: 1, + purpose: Purpose::AUTHENTICATION, + security_level: SecurityLevel::HIGH, + contract_bounds: None, + key_type, + data: public_key_data.into(), + read_only: false, + disabled_at: None, + }; + + // Validate that the private key matches the public key + assert_eq!( + identity_public_key + .validate_private_key_bytes(&private_key_data, Network::Testnet) + .unwrap(), + true + ); + + // Test with an invalid private key + let invalid_private_key_bytes = vec![0u8; private_key_data.len()]; + assert_eq!( + identity_public_key + .validate_private_key_bytes(&invalid_private_key_bytes, Network::Testnet) + .unwrap(), + false + ); + } + + #[cfg(all(feature = "random-public-keys", feature = "bls-signatures"))] + #[test] + fn test_validate_private_key_bytes_with_random_keys_bls12_381() { + let platform_version = PlatformVersion::latest(); + let mut rng = StdRng::from_entropy(); + + // Test for BLS12_381 + let key_type = KeyType::BLS12_381; + let (public_key_data, private_key_data) = key_type + .random_public_and_private_key_data(&mut rng, &platform_version) + .expect("expected to generate random keys"); + + let identity_public_key = IdentityPublicKeyV0 { + id: 2, + purpose: Purpose::AUTHENTICATION, + security_level: SecurityLevel::HIGH, + contract_bounds: None, + key_type, + data: public_key_data.into(), + read_only: false, + disabled_at: None, + }; + + // Validate that the private key matches the public key + assert_eq!( + identity_public_key + .validate_private_key_bytes(&private_key_data, Network::Testnet) + .unwrap(), + true + ); + + // Test with an invalid private key + let invalid_private_key_bytes = vec![0u8; private_key_data.len()]; + assert_eq!( + identity_public_key + .validate_private_key_bytes(&invalid_private_key_bytes, Network::Testnet) + .unwrap(), + false + ); + } + + #[cfg(all(feature = "random-public-keys", feature = "ed25519-dalek"))] + #[test] + fn test_validate_private_key_bytes_with_random_keys_eddsa_25519_hash160() { + let platform_version = PlatformVersion::latest(); + let mut rng = StdRng::from_entropy(); + + // Test for EDDSA_25519_HASH160 + let key_type = KeyType::EDDSA_25519_HASH160; + let (public_key_data, private_key_data) = key_type + .random_public_and_private_key_data(&mut rng, &platform_version) + .expect("expected to generate random keys"); + + let identity_public_key = IdentityPublicKeyV0 { + id: 3, + purpose: Purpose::AUTHENTICATION, + security_level: SecurityLevel::HIGH, + contract_bounds: None, + key_type, + data: public_key_data.into(), + read_only: false, + disabled_at: None, + }; + + // Validate that the private key matches the public key + assert_eq!( + identity_public_key + .validate_private_key_bytes(&private_key_data, Network::Testnet) + .unwrap(), + true + ); + + // Test with an invalid private key + let invalid_private_key_bytes = vec![0u8; private_key_data.len()]; + assert_eq!( + identity_public_key + .validate_private_key_bytes(&invalid_private_key_bytes, Network::Testnet) + .unwrap(), + false + ); + } } diff --git a/packages/rs-dpp/src/identity/identity_public_key/v0/random.rs b/packages/rs-dpp/src/identity/identity_public_key/v0/random.rs index 13afdd673f..162e836e1b 100644 --- a/packages/rs-dpp/src/identity/identity_public_key/v0/random.rs +++ b/packages/rs-dpp/src/identity/identity_public_key/v0/random.rs @@ -1,7 +1,7 @@ use crate::identity::contract_bounds::ContractBounds; use crate::identity::identity_public_key::v0::IdentityPublicKeyV0; use crate::identity::KeyType::{ECDSA_HASH160, ECDSA_SECP256K1}; -use crate::identity::Purpose::{AUTHENTICATION, VOTING}; +use crate::identity::Purpose::{AUTHENTICATION, OWNER, TRANSFER, VOTING}; use crate::identity::SecurityLevel::{CRITICAL, HIGH, MASTER, MEDIUM}; use crate::identity::{KeyCount, KeyID, KeyType, Purpose, SecurityLevel}; use crate::version::PlatformVersion; @@ -245,6 +245,58 @@ impl IdentityPublicKeyV0 { )) } + pub fn random_owner_key_with_rng( + id: KeyID, + rng: &mut StdRng, + platform_version: &PlatformVersion, + ) -> Result<(Self, Vec), ProtocolError> { + let key_type = ECDSA_HASH160; + let purpose = OWNER; + let security_level = CRITICAL; + let read_only = true; + let (data, private_data) = + key_type.random_public_and_private_key_data(rng, platform_version)?; + Ok(( + IdentityPublicKeyV0 { + id, + key_type, + purpose, + security_level, + read_only, + disabled_at: None, + data: data.into(), + contract_bounds: None, + }, + private_data, + )) + } + + pub fn random_masternode_transfer_key_with_rng( + id: KeyID, + rng: &mut StdRng, + platform_version: &PlatformVersion, + ) -> Result<(Self, Vec), ProtocolError> { + let key_type = ECDSA_HASH160; + let purpose = TRANSFER; + let security_level = CRITICAL; + let read_only = true; + let (data, private_data) = + key_type.random_public_and_private_key_data(rng, platform_version)?; + Ok(( + IdentityPublicKeyV0 { + id, + key_type, + purpose, + security_level, + read_only, + disabled_at: None, + data: data.into(), + contract_bounds: None, + }, + private_data, + )) + } + pub fn random_ecdsa_critical_level_authentication_key_with_rng( id: KeyID, rng: &mut StdRng, diff --git a/packages/rs-dpp/src/identity/signer.rs b/packages/rs-dpp/src/identity/signer.rs index 549a55da42..e069e43a11 100644 --- a/packages/rs-dpp/src/identity/signer.rs +++ b/packages/rs-dpp/src/identity/signer.rs @@ -10,4 +10,7 @@ pub trait Signer: Sync + Debug { identity_public_key: &IdentityPublicKey, data: &[u8], ) -> Result; + + /// do we have this identity public key in the signer? + fn can_sign_with(&self, identity_public_key: &IdentityPublicKey) -> bool; } diff --git a/packages/rs-dpp/src/lib.rs b/packages/rs-dpp/src/lib.rs index d2dc8b7f6e..a5d4ec177e 100644 --- a/packages/rs-dpp/src/lib.rs +++ b/packages/rs-dpp/src/lib.rs @@ -52,6 +52,9 @@ pub mod signing; #[cfg(feature = "system_contracts")] pub mod system_data_contracts; pub mod voting; + +#[cfg(feature = "core-types")] +pub mod core_types; pub mod withdrawal; pub use async_trait; @@ -87,11 +90,11 @@ pub mod prelude { pub use bincode; #[cfg(all(not(target_arch = "wasm32"), feature = "bls-signatures"))] -pub use bls_signatures; +pub use dashcore::bls_signatures; +#[cfg(feature = "ed25519-dalek")] +pub use dashcore::ed25519_dalek; #[cfg(feature = "system_contracts")] pub use data_contracts; -#[cfg(feature = "ed25519-dalek")] -pub use ed25519_dalek; #[cfg(feature = "jsonschema")] pub use jsonschema; pub use platform_serialization; diff --git a/packages/rs-dpp/src/signing.rs b/packages/rs-dpp/src/signing.rs index 96c810ff36..d4f69942b6 100644 --- a/packages/rs-dpp/src/signing.rs +++ b/packages/rs-dpp/src/signing.rs @@ -8,7 +8,7 @@ use crate::serialization::PlatformMessageSignable; use crate::validation::SimpleConsensusValidationResult; #[cfg(feature = "message-signing")] use crate::{BlsModule, ProtocolError}; -use dashcore::signer; +use dashcore::{bls_signatures, signer}; impl PlatformMessageSignable for &[u8] { #[cfg(feature = "message-signature-verification")] diff --git a/packages/rs-dpp/src/state_transition/errors/wrong_public_key_purpose_error.rs b/packages/rs-dpp/src/state_transition/errors/wrong_public_key_purpose_error.rs index 7f1fdb8522..5b469e2fa9 100644 --- a/packages/rs-dpp/src/state_transition/errors/wrong_public_key_purpose_error.rs +++ b/packages/rs-dpp/src/state_transition/errors/wrong_public_key_purpose_error.rs @@ -2,27 +2,28 @@ use thiserror::Error; use crate::identity::Purpose; use crate::ProtocolError; +use itertools::Itertools; #[derive(Error, Debug, Clone, PartialEq, Eq)] -#[error("Invalid identity key purpose {public_key_purpose}. This state transition requires {key_purpose_requirement}")] +#[error("Invalid identity key purpose {public_key_purpose}. This state transition requires {}", allowed_key_purposes.iter().map(|s| s.to_string()).join(" | "))] pub struct WrongPublicKeyPurposeError { public_key_purpose: Purpose, - key_purpose_requirement: Purpose, + allowed_key_purposes: Vec, } impl WrongPublicKeyPurposeError { - pub fn new(public_key_purpose: Purpose, key_purpose_requirement: Purpose) -> Self { + pub fn new(public_key_purpose: Purpose, allowed_key_purposes: Vec) -> Self { Self { public_key_purpose, - key_purpose_requirement, + allowed_key_purposes, } } pub fn public_key_purpose(&self) -> Purpose { self.public_key_purpose } - pub fn key_purpose_requirement(&self) -> Purpose { - self.key_purpose_requirement + pub fn allowed_key_purposes(&self) -> &Vec { + &self.allowed_key_purposes } } diff --git a/packages/rs-dpp/src/state_transition/mod.rs b/packages/rs-dpp/src/state_transition/mod.rs index 879bb6e871..cd97cae4ae 100644 --- a/packages/rs-dpp/src/state_transition/mod.rs +++ b/packages/rs-dpp/src/state_transition/mod.rs @@ -152,8 +152,8 @@ macro_rules! call_getter_method_identity_signed { StateTransition::DataContractCreate(st) => Some(st.$method($args)), StateTransition::DataContractUpdate(st) => Some(st.$method($args)), StateTransition::DocumentsBatch(st) => Some(st.$method($args)), - StateTransition::IdentityCreate(st) => None, - StateTransition::IdentityTopUp(st) => None, + StateTransition::IdentityCreate(_) => None, + StateTransition::IdentityTopUp(_) => None, StateTransition::IdentityCreditWithdrawal(st) => Some(st.$method($args)), StateTransition::IdentityUpdate(st) => Some(st.$method($args)), StateTransition::IdentityCreditTransfer(st) => Some(st.$method($args)), @@ -165,8 +165,8 @@ macro_rules! call_getter_method_identity_signed { StateTransition::DataContractCreate(st) => Some(st.$method()), StateTransition::DataContractUpdate(st) => Some(st.$method()), StateTransition::DocumentsBatch(st) => Some(st.$method()), - StateTransition::IdentityCreate(_st) => None, - StateTransition::IdentityTopUp(_st) => None, + StateTransition::IdentityCreate(_) => None, + StateTransition::IdentityTopUp(_) => None, StateTransition::IdentityCreditWithdrawal(st) => Some(st.$method()), StateTransition::IdentityUpdate(st) => Some(st.$method()), StateTransition::IdentityCreditTransfer(st) => Some(st.$method()), @@ -400,12 +400,12 @@ impl StateTransition { } /// returns the key security level requirement for the state transition - pub fn security_level_requirement(&self) -> Option> { - call_getter_method_identity_signed!(self, security_level_requirement) + pub fn security_level_requirement(&self, purpose: Purpose) -> Option> { + call_getter_method_identity_signed!(self, security_level_requirement, purpose) } /// returns the key purpose requirement for the state transition - pub fn purpose_requirement(&self) -> Option { + pub fn purpose_requirement(&self) -> Option> { call_getter_method_identity_signed!(self, purpose_requirement) } @@ -457,7 +457,7 @@ impl StateTransition { return Err(ProtocolError::WrongPublicKeyPurposeError( WrongPublicKeyPurposeError::new( identity_public_key.purpose(), - Purpose::AUTHENTICATION, + vec![Purpose::AUTHENTICATION], ), )); } diff --git a/packages/rs-dpp/src/state_transition/state_transitions/contract/data_contract_create_transition/identity_signed.rs b/packages/rs-dpp/src/state_transition/state_transitions/contract/data_contract_create_transition/identity_signed.rs index fe0bff68c7..4b2704c07d 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/contract/data_contract_create_transition/identity_signed.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/contract/data_contract_create_transition/identity_signed.rs @@ -1,4 +1,4 @@ -use crate::identity::{KeyID, SecurityLevel}; +use crate::identity::{KeyID, Purpose, SecurityLevel}; use crate::state_transition::data_contract_create_transition::DataContractCreateTransition; use crate::state_transition::StateTransitionIdentitySigned; @@ -17,9 +17,11 @@ impl StateTransitionIdentitySigned for DataContractCreateTransition { } } - fn security_level_requirement(&self) -> Vec { + fn security_level_requirement(&self, purpose: Purpose) -> Vec { match self { - DataContractCreateTransition::V0(transition) => transition.security_level_requirement(), + DataContractCreateTransition::V0(transition) => { + transition.security_level_requirement(purpose) + } } } } diff --git a/packages/rs-dpp/src/state_transition/state_transitions/contract/data_contract_create_transition/v0/identity_signed.rs b/packages/rs-dpp/src/state_transition/state_transitions/contract/data_contract_create_transition/v0/identity_signed.rs index c7b4464dec..be2682bc82 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/contract/data_contract_create_transition/v0/identity_signed.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/contract/data_contract_create_transition/v0/identity_signed.rs @@ -1,5 +1,5 @@ use crate::identity::SecurityLevel::{CRITICAL, HIGH}; -use crate::identity::{KeyID, SecurityLevel}; +use crate::identity::{KeyID, Purpose, SecurityLevel}; use crate::state_transition::data_contract_create_transition::DataContractCreateTransitionV0; use crate::state_transition::StateTransitionIdentitySigned; @@ -12,7 +12,7 @@ impl StateTransitionIdentitySigned for DataContractCreateTransitionV0 { self.signature_public_key_id = key_id } - fn security_level_requirement(&self) -> Vec { + fn security_level_requirement(&self, _purpose: Purpose) -> Vec { vec![CRITICAL, HIGH] } } diff --git a/packages/rs-dpp/src/state_transition/state_transitions/contract/data_contract_create_transition/v0/v0_methods.rs b/packages/rs-dpp/src/state_transition/state_transitions/contract/data_contract_create_transition/v0/v0_methods.rs index ca6fe4e148..f1ed8c9b36 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/contract/data_contract_create_transition/v0/v0_methods.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/contract/data_contract_create_transition/v0/v0_methods.rs @@ -65,11 +65,11 @@ impl DataContractCreateTransitionMethodsV0 for DataContractCreateTransitionV0 { )), )?; - let security_level_requirements = state_transition.security_level_requirement().ok_or( - ProtocolError::CorruptedCodeExecution( + let security_level_requirements = state_transition + .security_level_requirement(public_key.purpose()) + .ok_or(ProtocolError::CorruptedCodeExecution( "expected security level requirements".to_string(), - ), - )?; + ))?; if !security_level_requirements.contains(&public_key.security_level()) { return Err(ProtocolError::ConsensusError(Box::new( diff --git a/packages/rs-dpp/src/state_transition/state_transitions/contract/data_contract_update_transition/identity_signed.rs b/packages/rs-dpp/src/state_transition/state_transitions/contract/data_contract_update_transition/identity_signed.rs index b56e0dd30b..50c8cb9ce4 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/contract/data_contract_update_transition/identity_signed.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/contract/data_contract_update_transition/identity_signed.rs @@ -1,4 +1,4 @@ -use crate::identity::{KeyID, SecurityLevel}; +use crate::identity::{KeyID, Purpose, SecurityLevel}; use crate::state_transition::data_contract_update_transition::DataContractUpdateTransition; use crate::state_transition::StateTransitionIdentitySigned; @@ -18,9 +18,11 @@ impl StateTransitionIdentitySigned for DataContractUpdateTransition { } } - fn security_level_requirement(&self) -> Vec { + fn security_level_requirement(&self, purpose: Purpose) -> Vec { match self { - DataContractUpdateTransition::V0(transition) => transition.security_level_requirement(), + DataContractUpdateTransition::V0(transition) => { + transition.security_level_requirement(purpose) + } } } } diff --git a/packages/rs-dpp/src/state_transition/state_transitions/contract/data_contract_update_transition/v0/identity_signed.rs b/packages/rs-dpp/src/state_transition/state_transitions/contract/data_contract_update_transition/v0/identity_signed.rs index 6508a9ab76..3c39e2d90a 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/contract/data_contract_update_transition/v0/identity_signed.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/contract/data_contract_update_transition/v0/identity_signed.rs @@ -1,5 +1,5 @@ use crate::identity::SecurityLevel::CRITICAL; -use crate::identity::{KeyID, SecurityLevel}; +use crate::identity::{KeyID, Purpose, SecurityLevel}; use crate::state_transition::data_contract_update_transition::DataContractUpdateTransitionV0; use crate::state_transition::StateTransitionIdentitySigned; @@ -12,7 +12,7 @@ impl StateTransitionIdentitySigned for DataContractUpdateTransitionV0 { self.signature_public_key_id = key_id } - fn security_level_requirement(&self) -> Vec { + fn security_level_requirement(&self, _purpose: Purpose) -> Vec { vec![CRITICAL] } } diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_base_transition/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_base_transition/mod.rs index 25dd569fb3..6d80cc2d87 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_base_transition/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_base_transition/mod.rs @@ -37,7 +37,7 @@ use std::collections::BTreeMap; derive(Serialize, Deserialize) )] pub enum DocumentBaseTransition { - #[display(fmt = "V0({})", "_0")] + #[display("V0({})", "_0")] V0(DocumentBaseTransitionV0), } diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_base_transition/v0/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_base_transition/v0/mod.rs index 8392b81223..f5b245bece 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_base_transition/v0/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_base_transition/v0/mod.rs @@ -35,7 +35,7 @@ use crate::{data_contract::DataContract, errors::ProtocolError}; serde(rename_all = "camelCase") )] #[display( - fmt = "ID: {}, Type: {}, Contract ID: {}", + "ID: {}, Type: {}, Contract ID: {}", "id", "document_type_name", "data_contract_id" diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_create_transition/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_create_transition/mod.rs index 2af4a2174f..cde6d5ae29 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_create_transition/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_create_transition/mod.rs @@ -22,7 +22,7 @@ pub use v0::DocumentCreateTransitionV0; derive(Serialize, Deserialize) )] pub enum DocumentCreateTransition { - #[display(fmt = "V0({})", "_0")] + #[display("V0({})", "_0")] V0(DocumentCreateTransitionV0), } diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_create_transition/v0/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_create_transition/v0/mod.rs index b15cdf0e59..27c968b20b 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_create_transition/v0/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_create_transition/v0/mod.rs @@ -52,7 +52,7 @@ pub use super::super::document_base_transition::IDENTIFIER_FIELDS; derive(Serialize, Deserialize), serde(rename_all = "camelCase") )] -#[display(fmt = "Base: {}, Entropy: {:?}, Data: {:?}", "base", "entropy", "data")] +#[display("Base: {}, Entropy: {:?}, Data: {:?}", "base", "entropy", "data")] pub struct DocumentCreateTransitionV0 { /// Document Base Transition #[cfg_attr(feature = "state-transition-serde-conversion", serde(flatten))] diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_delete_transition/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_delete_transition/mod.rs index 7a0f8fb2a6..0ca94ce886 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_delete_transition/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_delete_transition/mod.rs @@ -14,6 +14,6 @@ pub use v0::*; derive(Serialize, Deserialize) )] pub enum DocumentDeleteTransition { - #[display(fmt = "V0({})", "_0")] + #[display("V0({})", "_0")] V0(DocumentDeleteTransitionV0), } diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_delete_transition/v0/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_delete_transition/v0/mod.rs index 813ea0b2dd..34d4ac9855 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_delete_transition/v0/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_delete_transition/v0/mod.rs @@ -17,7 +17,7 @@ pub use super::super::document_base_transition::IDENTIFIER_FIELDS; derive(Serialize, Deserialize), serde(rename_all = "camelCase") )] -#[display(fmt = "Base: {}", "base")] +#[display("Base: {}", "base")] pub struct DocumentDeleteTransitionV0 { #[cfg_attr(feature = "state-transition-serde-conversion", serde(flatten))] pub base: DocumentBaseTransition, diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_purchase_transition/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_purchase_transition/mod.rs index 9a5664cfaa..97ee83ec73 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_purchase_transition/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_purchase_transition/mod.rs @@ -14,6 +14,6 @@ pub use v0::*; derive(Serialize, Deserialize) )] pub enum DocumentPurchaseTransition { - #[display(fmt = "V0({})", "_0")] + #[display("V0({})", "_0")] V0(DocumentPurchaseTransitionV0), } diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_purchase_transition/v0/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_purchase_transition/v0/mod.rs index 255310c394..5a4ca1e8ba 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_purchase_transition/v0/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_purchase_transition/v0/mod.rs @@ -19,7 +19,7 @@ pub use super::super::document_base_transition::IDENTIFIER_FIELDS; derive(Serialize, Deserialize), serde(rename_all = "camelCase") )] -#[display(fmt = "Base: {}", "base")] +#[display("Base: {}", "base")] pub struct DocumentPurchaseTransitionV0 { #[cfg_attr(feature = "state-transition-serde-conversion", serde(flatten))] pub base: DocumentBaseTransition, diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_replace_transition/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_replace_transition/mod.rs index 8e805318b5..e5dd1e7715 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_replace_transition/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_replace_transition/mod.rs @@ -21,7 +21,7 @@ pub use v0::*; derive(Serialize, Deserialize) )] pub enum DocumentReplaceTransition { - #[display(fmt = "V0({})", "_0")] + #[display("V0({})", "_0")] V0(DocumentReplaceTransitionV0), } diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_replace_transition/v0/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_replace_transition/v0/mod.rs index 2c7f96e8e4..13833cabaf 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_replace_transition/v0/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_replace_transition/v0/mod.rs @@ -31,7 +31,7 @@ mod property_names { derive(Serialize, Deserialize), serde(rename_all = "camelCase") )] -#[display(fmt = "Base: {}, Revision: {}, Data: {:?}", "base", "revision", "data")] +#[display("Base: {}, Revision: {}, Data: {:?}", "base", "revision", "data")] pub struct DocumentReplaceTransitionV0 { #[cfg_attr(feature = "state-transition-serde-conversion", serde(flatten))] pub base: DocumentBaseTransition, diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_transfer_transition/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_transfer_transition/mod.rs index e2185f76b0..d784dca011 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_transfer_transition/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_transfer_transition/mod.rs @@ -14,6 +14,6 @@ pub use v0::*; derive(Serialize, Deserialize) )] pub enum DocumentTransferTransition { - #[display(fmt = "V0({})", "_0")] + #[display("V0({})", "_0")] V0(DocumentTransferTransitionV0), } diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_transfer_transition/v0/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_transfer_transition/v0/mod.rs index c51f80cdb7..3708794cf7 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_transfer_transition/v0/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_transfer_transition/v0/mod.rs @@ -25,7 +25,7 @@ mod property_names { serde(rename_all = "camelCase") )] #[display( - fmt = "Base: {}, Revision: {}, Recipient: {:?}", + "Base: {}, Revision: {}, Recipient: {:?}", "base", "revision", "recipient_owner_id" diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_update_price_transition/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_update_price_transition/mod.rs index 25a16a09ae..e85c1513db 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_update_price_transition/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_update_price_transition/mod.rs @@ -14,6 +14,6 @@ pub use v0::*; derive(Serialize, Deserialize) )] pub enum DocumentUpdatePriceTransition { - #[display(fmt = "V0({})", "_0")] + #[display("V0({})", "_0")] V0(DocumentUpdatePriceTransitionV0), } diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_update_price_transition/v0/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_update_price_transition/v0/mod.rs index fe1e11cae1..8e264bba97 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_update_price_transition/v0/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/document_update_price_transition/v0/mod.rs @@ -23,7 +23,7 @@ mod property_names { derive(Serialize, Deserialize), serde(rename_all = "camelCase") )] -#[display(fmt = "Base: {}, Revision: {}, Price: {}", "base", "revision", "price")] +#[display("Base: {}, Revision: {}, Price: {}", "base", "revision", "price")] pub struct DocumentUpdatePriceTransitionV0 { #[cfg_attr(feature = "state-transition-serde-conversion", serde(flatten))] pub base: DocumentBaseTransition, diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/mod.rs index 00e566b2a8..448dffcfea 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/document_transition/mod.rs @@ -76,22 +76,22 @@ pub trait DocumentTransitionV0Methods { derive(Serialize, Deserialize) )] pub enum DocumentTransition { - #[display(fmt = "CreateDocumentTransition({})", "_0")] + #[display("CreateDocumentTransition({})", "_0")] Create(DocumentCreateTransition), - #[display(fmt = "ReplaceDocumentTransition({})", "_0")] + #[display("ReplaceDocumentTransition({})", "_0")] Replace(DocumentReplaceTransition), - #[display(fmt = "DeleteDocumentTransition({})", "_0")] + #[display("DeleteDocumentTransition({})", "_0")] Delete(DocumentDeleteTransition), - #[display(fmt = "TransferDocumentTransition({})", "_0")] + #[display("TransferDocumentTransition({})", "_0")] Transfer(DocumentTransferTransition), - #[display(fmt = "UpdatePriceDocumentTransition({})", "_0")] + #[display("UpdatePriceDocumentTransition({})", "_0")] UpdatePrice(DocumentUpdatePriceTransition), - #[display(fmt = "PurchaseDocumentTransition({})", "_0")] + #[display("PurchaseDocumentTransition({})", "_0")] Purchase(DocumentPurchaseTransition), } diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/identity_signed.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/identity_signed.rs index f5d5f967aa..3d8a2d1486 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/identity_signed.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/identity_signed.rs @@ -1,4 +1,4 @@ -use crate::identity::{KeyID, SecurityLevel}; +use crate::identity::{KeyID, Purpose, SecurityLevel}; use crate::state_transition::documents_batch_transition::DocumentsBatchTransition; use crate::state_transition::StateTransitionIdentitySigned; @@ -17,9 +17,11 @@ impl StateTransitionIdentitySigned for DocumentsBatchTransition { } } - fn security_level_requirement(&self) -> Vec { + fn security_level_requirement(&self, purpose: Purpose) -> Vec { match self { - DocumentsBatchTransition::V0(transition) => transition.security_level_requirement(), + DocumentsBatchTransition::V0(transition) => { + transition.security_level_requirement(purpose) + } } } } diff --git a/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/v0/identity_signed.rs b/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/v0/identity_signed.rs index fd4916864a..bdc0fe583a 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/v0/identity_signed.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/document/documents_batch_transition/v0/identity_signed.rs @@ -1,5 +1,5 @@ use crate::identity::SecurityLevel::{CRITICAL, HIGH, MEDIUM}; -use crate::identity::{KeyID, SecurityLevel}; +use crate::identity::{KeyID, Purpose, SecurityLevel}; use crate::state_transition::documents_batch_transition::DocumentsBatchTransitionV0; use crate::state_transition::StateTransitionIdentitySigned; @@ -13,7 +13,7 @@ impl StateTransitionIdentitySigned for DocumentsBatchTransitionV0 { self.signature_public_key_id = key_id } - fn security_level_requirement(&self) -> Vec { + fn security_level_requirement(&self, _purpose: Purpose) -> Vec { // These are the available key levels that must sign the state transition // However the fact that it is signed by one of these does not guarantee that it // meets the security level requirement, as that is dictated from within the data diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/identity_signed.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/identity_signed.rs index 4b3b448eb5..60dd03cf6f 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/identity_signed.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/identity_signed.rs @@ -19,15 +19,15 @@ impl StateTransitionIdentitySigned for IdentityCreditTransferTransition { } } - fn security_level_requirement(&self) -> Vec { + fn security_level_requirement(&self, purpose: Purpose) -> Vec { match self { IdentityCreditTransferTransition::V0(transition) => { - transition.security_level_requirement() + transition.security_level_requirement(purpose) } } } - fn purpose_requirement(&self) -> Purpose { + fn purpose_requirement(&self) -> Vec { match self { IdentityCreditTransferTransition::V0(transition) => transition.purpose_requirement(), } diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/methods/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/methods/mod.rs index 2bea2328d7..43790f371d 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/methods/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/methods/mod.rs @@ -1,7 +1,57 @@ mod v0; - pub use v0::*; use crate::state_transition::identity_credit_transfer_transition::IdentityCreditTransferTransition; +#[cfg(feature = "state-transition-signing")] +use crate::{ + identity::{signer::Signer, Identity, IdentityPublicKey}, + prelude::{IdentityNonce, UserFeeIncrease}, + state_transition::{ + identity_credit_transfer_transition::v0::IdentityCreditTransferTransitionV0, + StateTransition, + }, + ProtocolError, +}; +#[cfg(feature = "state-transition-signing")] +use platform_value::Identifier; +#[cfg(feature = "state-transition-signing")] +use platform_version::version::{FeatureVersion, PlatformVersion}; -impl IdentityCreditTransferTransitionMethodsV0 for IdentityCreditTransferTransition {} +impl IdentityCreditTransferTransitionMethodsV0 for IdentityCreditTransferTransition { + #[cfg(feature = "state-transition-signing")] + fn try_from_identity( + identity: &Identity, + to_identity_with_identifier: Identifier, + amount: u64, + user_fee_increase: UserFeeIncrease, + signer: S, + signing_withdrawal_key_to_use: Option<&IdentityPublicKey>, + nonce: IdentityNonce, + platform_version: &PlatformVersion, + version: Option, + ) -> Result { + match version.unwrap_or( + platform_version + .dpp + .state_transition_conversion_versions + .identity_to_identity_transfer_transition, + ) { + 0 => Ok(IdentityCreditTransferTransitionV0::try_from_identity( + identity, + to_identity_with_identifier, + amount, + user_fee_increase, + signer, + signing_withdrawal_key_to_use, + nonce, + platform_version, + version, + )?), + version => Err(ProtocolError::UnknownVersionMismatch { + method: "IdentityCreditTransferTransition::try_from_identity".to_string(), + known_versions: vec![0], + received: version, + }), + } + } +} diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/methods/v0/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/methods/v0/mod.rs index caa6ad6560..eeb7104420 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/methods/v0/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/methods/v0/mod.rs @@ -1,6 +1,30 @@ +#[cfg(feature = "state-transition-signing")] +use crate::{ + identity::{signer::Signer, Identity, IdentityPublicKey}, + prelude::{IdentityNonce, UserFeeIncrease}, + state_transition::StateTransition, + ProtocolError, +}; +use platform_value::Identifier; +#[cfg(feature = "state-transition-signing")] +use platform_version::version::{FeatureVersion, PlatformVersion}; + use crate::state_transition::StateTransitionType; pub trait IdentityCreditTransferTransitionMethodsV0 { + #[cfg(feature = "state-transition-signing")] + fn try_from_identity( + identity: &Identity, + to_identity_with_identifier: Identifier, + amount: u64, + user_fee_increase: UserFeeIncrease, + signer: S, + signing_withdrawal_key_to_use: Option<&IdentityPublicKey>, + nonce: IdentityNonce, + platform_version: &PlatformVersion, + version: Option, + ) -> Result; + /// Get State Transition Type fn get_type() -> StateTransitionType { StateTransitionType::IdentityCreditTransfer diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/v0/identity_signed.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/v0/identity_signed.rs index bcab635e22..acc328d274 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/v0/identity_signed.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/v0/identity_signed.rs @@ -12,11 +12,11 @@ impl StateTransitionIdentitySigned for IdentityCreditTransferTransitionV0 { self.signature_public_key_id = key_id } - fn security_level_requirement(&self) -> Vec { + fn security_level_requirement(&self, _purpose: Purpose) -> Vec { vec![CRITICAL] } - fn purpose_requirement(&self) -> Purpose { - Purpose::TRANSFER + fn purpose_requirement(&self) -> Vec { + vec![Purpose::TRANSFER] } } diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/v0/v0_methods.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/v0/v0_methods.rs index 0060a25a2c..e04e061f67 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/v0/v0_methods.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/v0/v0_methods.rs @@ -1,4 +1,80 @@ +#[cfg(feature = "state-transition-signing")] +use crate::{ + identity::{ + accessors::IdentityGettersV0, signer::Signer, Identity, IdentityPublicKey, KeyType, + Purpose, SecurityLevel, + }, + prelude::{IdentityNonce, UserFeeIncrease}, + state_transition::StateTransition, + ProtocolError, +}; +use platform_value::Identifier; + use crate::state_transition::identity_credit_transfer_transition::methods::IdentityCreditTransferTransitionMethodsV0; use crate::state_transition::identity_credit_transfer_transition::v0::IdentityCreditTransferTransitionV0; +use crate::state_transition::GetDataContractSecurityLevelRequirementFn; +#[cfg(feature = "state-transition-signing")] +use platform_version::version::{FeatureVersion, PlatformVersion}; + +impl IdentityCreditTransferTransitionMethodsV0 for IdentityCreditTransferTransitionV0 { + #[cfg(feature = "state-transition-signing")] + fn try_from_identity( + identity: &Identity, + to_identity_with_identifier: Identifier, + amount: u64, + user_fee_increase: UserFeeIncrease, + signer: S, + signing_withdrawal_key_to_use: Option<&IdentityPublicKey>, + nonce: IdentityNonce, + _platform_version: &PlatformVersion, + _version: Option, + ) -> Result { + let mut transition: StateTransition = IdentityCreditTransferTransitionV0 { + identity_id: identity.id(), + recipient_id: to_identity_with_identifier, + amount, + nonce, + user_fee_increase, + signature_public_key_id: 0, + signature: Default::default(), + } + .into(); + + let identity_public_key = match signing_withdrawal_key_to_use { + Some(key) => { + if signer.can_sign_with(key) { + key + } else { + return Err( + ProtocolError::DesiredKeyWithTypePurposeSecurityLevelMissing( + "specified transfer public key cannot be used for signing".to_string(), + ), + ); + } + } + None => { + let key = identity + .get_first_public_key_matching( + Purpose::TRANSFER, + SecurityLevel::full_range().into(), + KeyType::all_key_types().into(), + true, + ) + .ok_or_else(|| { + ProtocolError::DesiredKeyWithTypePurposeSecurityLevelMissing( + "no transfer public key".to_string(), + ) + })?; + key + } + }; + + transition.sign_external( + identity_public_key, + &signer, + None::, + )?; -impl IdentityCreditTransferTransitionMethodsV0 for IdentityCreditTransferTransitionV0 {} + Ok(transition) + } +} diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/accessors/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/accessors/mod.rs index dbf33c5a56..eb952d6509 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/accessors/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/accessors/mod.rs @@ -13,6 +13,7 @@ impl IdentityCreditWithdrawalTransitionAccessorsV0 for IdentityCreditWithdrawalT fn identity_id(&self) -> Identifier { match self { IdentityCreditWithdrawalTransition::V0(transition) => transition.identity_id, + IdentityCreditWithdrawalTransition::V1(transition) => transition.identity_id, } } @@ -21,12 +22,16 @@ impl IdentityCreditWithdrawalTransitionAccessorsV0 for IdentityCreditWithdrawalT IdentityCreditWithdrawalTransition::V0(transition) => { transition.identity_id = identity_id; } + IdentityCreditWithdrawalTransition::V1(transition) => { + transition.identity_id = identity_id; + } } } fn amount(&self) -> u64 { match self { IdentityCreditWithdrawalTransition::V0(transition) => transition.amount, + IdentityCreditWithdrawalTransition::V1(transition) => transition.amount, } } @@ -35,24 +40,30 @@ impl IdentityCreditWithdrawalTransitionAccessorsV0 for IdentityCreditWithdrawalT IdentityCreditWithdrawalTransition::V0(transition) => { transition.amount = amount; } + IdentityCreditWithdrawalTransition::V1(transition) => { + transition.amount = amount; + } } } fn set_nonce(&mut self, nonce: IdentityNonce) { match self { IdentityCreditWithdrawalTransition::V0(transition) => transition.nonce = nonce, + IdentityCreditWithdrawalTransition::V1(transition) => transition.nonce = nonce, } } fn nonce(&self) -> IdentityNonce { match self { IdentityCreditWithdrawalTransition::V0(transition) => transition.nonce, + IdentityCreditWithdrawalTransition::V1(transition) => transition.nonce, } } fn pooling(&self) -> Pooling { match self { IdentityCreditWithdrawalTransition::V0(transition) => transition.pooling, + IdentityCreditWithdrawalTransition::V1(transition) => transition.pooling, } } @@ -61,12 +72,16 @@ impl IdentityCreditWithdrawalTransitionAccessorsV0 for IdentityCreditWithdrawalT IdentityCreditWithdrawalTransition::V0(transition) => { transition.pooling = pooling; } + IdentityCreditWithdrawalTransition::V1(transition) => { + transition.pooling = pooling; + } } } fn core_fee_per_byte(&self) -> u32 { match self { IdentityCreditWithdrawalTransition::V0(transition) => transition.core_fee_per_byte, + IdentityCreditWithdrawalTransition::V1(transition) => transition.core_fee_per_byte, } } @@ -75,18 +90,29 @@ impl IdentityCreditWithdrawalTransitionAccessorsV0 for IdentityCreditWithdrawalT IdentityCreditWithdrawalTransition::V0(transition) => { transition.core_fee_per_byte = core_fee_per_byte; } + IdentityCreditWithdrawalTransition::V1(transition) => { + transition.core_fee_per_byte = core_fee_per_byte; + } } } - fn output_script(&self) -> CoreScript { + fn output_script(&self) -> Option { match self { - IdentityCreditWithdrawalTransition::V0(transition) => transition.output_script.clone(), + IdentityCreditWithdrawalTransition::V0(transition) => { + Some(transition.output_script.clone()) + } + IdentityCreditWithdrawalTransition::V1(transition) => transition.output_script.clone(), } } - fn set_output_script(&mut self, output_script: CoreScript) { + fn set_output_script(&mut self, output_script: Option) { match self { IdentityCreditWithdrawalTransition::V0(transition) => { + if let Some(output_script) = output_script { + transition.output_script = output_script; + } + } + IdentityCreditWithdrawalTransition::V1(transition) => { transition.output_script = output_script; } } diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/accessors/v0/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/accessors/v0/mod.rs index 1bcd8b2945..2e666ac1c7 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/accessors/v0/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/accessors/v0/mod.rs @@ -14,6 +14,6 @@ pub trait IdentityCreditWithdrawalTransitionAccessorsV0 { fn set_pooling(&mut self, pooling: Pooling); fn core_fee_per_byte(&self) -> u32; fn set_core_fee_per_byte(&mut self, amount: u32); - fn output_script(&self) -> CoreScript; - fn set_output_script(&mut self, output_script: CoreScript); + fn output_script(&self) -> Option; + fn set_output_script(&mut self, output_script: Option); } diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/identity_signed.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/identity_signed.rs index 2dd369f3b3..75165fbb7d 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/identity_signed.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/identity_signed.rs @@ -8,6 +8,9 @@ impl StateTransitionIdentitySigned for IdentityCreditWithdrawalTransition { IdentityCreditWithdrawalTransition::V0(transition) => { transition.signature_public_key_id() } + IdentityCreditWithdrawalTransition::V1(transition) => { + transition.signature_public_key_id() + } } } @@ -16,20 +19,27 @@ impl StateTransitionIdentitySigned for IdentityCreditWithdrawalTransition { IdentityCreditWithdrawalTransition::V0(transition) => { transition.set_signature_public_key_id(key_id) } + IdentityCreditWithdrawalTransition::V1(transition) => { + transition.set_signature_public_key_id(key_id) + } } } - fn security_level_requirement(&self) -> Vec { + fn security_level_requirement(&self, purpose: Purpose) -> Vec { match self { IdentityCreditWithdrawalTransition::V0(transition) => { - transition.security_level_requirement() + transition.security_level_requirement(purpose) + } + IdentityCreditWithdrawalTransition::V1(transition) => { + transition.security_level_requirement(purpose) } } } - fn purpose_requirement(&self) -> Purpose { + fn purpose_requirement(&self) -> Vec { match self { IdentityCreditWithdrawalTransition::V0(transition) => transition.purpose_requirement(), + IdentityCreditWithdrawalTransition::V1(transition) => transition.purpose_requirement(), } } } diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/json_conversion.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/json_conversion.rs index b5a5946e62..ada6044e54 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/json_conversion.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/json_conversion.rs @@ -22,6 +22,15 @@ impl<'a> StateTransitionJsonConvert<'a> for IdentityCreditWithdrawalTransition { ); Ok(value) } + IdentityCreditWithdrawalTransition::V1(transition) => { + let mut value = transition.to_json(options)?; + let map_value = value.as_object_mut().expect("expected an object"); + map_value.insert( + STATE_TRANSITION_PROTOCOL_VERSION.to_string(), + JsonValue::Number(Number::from(1)), + ); + Ok(value) + } } } } diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/methods/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/methods/mod.rs index 96b2654046..acab5d8f3c 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/methods/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/methods/mod.rs @@ -17,7 +17,7 @@ use crate::identity::IdentityPublicKey; #[cfg(feature = "state-transition-signing")] use crate::prelude::{IdentityNonce, UserFeeIncrease}; #[cfg(feature = "state-transition-signing")] -use crate::state_transition::identity_credit_withdrawal_transition::v0::IdentityCreditWithdrawalTransitionV0; +use crate::state_transition::identity_credit_withdrawal_transition::v1::IdentityCreditWithdrawalTransitionV1; #[cfg(feature = "state-transition-signing")] use crate::state_transition::StateTransition; #[cfg(feature = "state-transition-signing")] @@ -31,13 +31,14 @@ impl IdentityCreditWithdrawalTransitionMethodsV0 for IdentityCreditWithdrawalTra #[cfg(feature = "state-transition-signing")] fn try_from_identity( identity: &Identity, - withdrawal_key_to_use: Option<&IdentityPublicKey>, - output_script: CoreScript, + output_script: Option, amount: u64, pooling: Pooling, core_fee_per_byte: u32, user_fee_increase: UserFeeIncrease, signer: S, + signing_withdrawal_key_to_use: Option<&IdentityPublicKey>, + preferred_key_purpose_for_signing_withdrawal: PreferredKeyPurposeForSigningWithdrawal, nonce: IdentityNonce, platform_version: &PlatformVersion, version: Option, @@ -48,22 +49,25 @@ impl IdentityCreditWithdrawalTransitionMethodsV0 for IdentityCreditWithdrawalTra .state_transition_conversion_versions .identity_to_identity_withdrawal_transition, ) { - 0 => Ok(IdentityCreditWithdrawalTransitionV0::try_from_identity( + 1 => Ok(IdentityCreditWithdrawalTransitionV1::try_from_identity( identity, - withdrawal_key_to_use, output_script, amount, pooling, core_fee_per_byte, user_fee_increase, signer, + signing_withdrawal_key_to_use, + preferred_key_purpose_for_signing_withdrawal, nonce, platform_version, version, )?), - v => Err(ProtocolError::UnknownVersionError(format!( - "Unknown IdentityCreditWithdrawalTransition version for try_from_identity {v}" - ))), + version => Err(ProtocolError::UnknownVersionMismatch { + method: "IdentityCreditWithdrawalTransition::try_from_identity".to_string(), + known_versions: vec![1], + received: version, + }), } } } diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/methods/v0/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/methods/v0/mod.rs index 0341f253f1..2836b96cc6 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/methods/v0/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/methods/v0/mod.rs @@ -1,34 +1,43 @@ #[cfg(feature = "state-transition-signing")] -use crate::identity::core_script::CoreScript; -#[cfg(feature = "state-transition-signing")] -use crate::identity::signer::Signer; -#[cfg(feature = "state-transition-signing")] -use crate::identity::Identity; -#[cfg(feature = "state-transition-signing")] -use crate::identity::IdentityPublicKey; -#[cfg(feature = "state-transition-signing")] -use crate::prelude::{IdentityNonce, UserFeeIncrease}; -#[cfg(feature = "state-transition-signing")] -use crate::state_transition::StateTransition; +use crate::{ + identity::{core_script::CoreScript, signer::Signer, Identity, IdentityPublicKey}, + prelude::{IdentityNonce, UserFeeIncrease}, + state_transition::StateTransition, + withdrawal::Pooling, + ProtocolError, +}; + use crate::state_transition::StateTransitionType; #[cfg(feature = "state-transition-signing")] -use crate::withdrawal::Pooling; -#[cfg(feature = "state-transition-signing")] -use crate::ProtocolError; -#[cfg(feature = "state-transition-signing")] use platform_version::version::{FeatureVersion, PlatformVersion}; +/// The key purpose that is preferred for signing the withdrawal +#[cfg(feature = "state-transition-signing")] +pub enum PreferredKeyPurposeForSigningWithdrawal { + /// Use any key + Any, + /// Use the owner key, then the transfer key + OwnerPreferred, + /// Use the transfer key, then the owner key + TransferPreferred, + /// Only use the owner key + OwnerOnly, + /// Only use the transfer key + TransferOnly, +} + pub trait IdentityCreditWithdrawalTransitionMethodsV0 { #[cfg(feature = "state-transition-signing")] fn try_from_identity( identity: &Identity, - withdrawal_key_to_use: Option<&IdentityPublicKey>, - output_script: CoreScript, + output_script: Option, amount: u64, pooling: Pooling, core_fee_per_byte: u32, user_fee_increase: UserFeeIncrease, signer: S, + signing_withdrawal_key_to_use: Option<&IdentityPublicKey>, + preferred_key_purpose_for_signing_withdrawal: PreferredKeyPurposeForSigningWithdrawal, nonce: IdentityNonce, platform_version: &PlatformVersion, version: Option, diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/mod.rs index f773296936..0badee88b9 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/mod.rs @@ -8,6 +8,7 @@ mod json_conversion; pub mod methods; mod state_transition_like; pub mod v0; +pub mod v1; #[cfg(feature = "state-transition-value-conversion")] mod value_conversion; mod version; @@ -15,9 +16,14 @@ mod version; use crate::state_transition::identity_credit_withdrawal_transition::v0::IdentityCreditWithdrawalTransitionV0Signable; use crate::state_transition::StateTransitionFieldTypes; +use crate::balances::credits::CREDITS_PER_DUFF; use crate::identity::state_transition::OptionallyAssetLockProved; +use crate::state_transition::identity_credit_withdrawal_transition::v1::{ + IdentityCreditWithdrawalTransitionV1, IdentityCreditWithdrawalTransitionV1Signable, +}; use crate::ProtocolError; use bincode::{Decode, Encode}; +use dashcore::transaction::special_transaction::asset_unlock::qualified_asset_unlock::ASSET_UNLOCK_TX_SIZE; use derive_more::From; use fields::*; use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize, PlatformSignable}; @@ -26,7 +32,14 @@ use platform_versioning::PlatformVersioned; #[cfg(feature = "state-transition-serde-conversion")] use serde::{Deserialize, Serialize}; -pub type IdentityCreditWithdrawalTransitionLatest = IdentityCreditWithdrawalTransitionV0; +/// Minimal core per byte. Must be a fibonacci number +pub const MIN_CORE_FEE_PER_BYTE: u32 = 1; + +/// Minimal amount in credits (x1000) to avoid "dust" error in Core +pub const MIN_WITHDRAWAL_AMOUNT: u64 = + (ASSET_UNLOCK_TX_SIZE as u64) * (MIN_CORE_FEE_PER_BYTE as u64) * CREDITS_PER_DUFF; + +pub type IdentityCreditWithdrawalTransitionLatest = IdentityCreditWithdrawalTransitionV1; #[derive( Debug, @@ -52,21 +65,28 @@ pub type IdentityCreditWithdrawalTransitionLatest = IdentityCreditWithdrawalTran pub enum IdentityCreditWithdrawalTransition { #[cfg_attr(feature = "state-transition-serde-conversion", serde(rename = "0"))] V0(IdentityCreditWithdrawalTransitionV0), + #[cfg_attr(feature = "state-transition-serde-conversion", serde(rename = "1"))] + V1(IdentityCreditWithdrawalTransitionV1), } impl IdentityCreditWithdrawalTransition { pub fn default_versioned(platform_version: &PlatformVersion) -> Result { match platform_version .dpp - .identity_versions - .identity_structure_version + .state_transitions + .identities + .credit_withdrawal + .default_constructor { 0 => Ok(IdentityCreditWithdrawalTransition::V0( IdentityCreditWithdrawalTransitionV0::default(), )), + 1 => Ok(IdentityCreditWithdrawalTransition::V1( + IdentityCreditWithdrawalTransitionV1::default(), + )), version => Err(ProtocolError::UnknownVersionMismatch { method: "IdentityCreditWithdrawalTransition::default_versioned".to_string(), - known_versions: vec![0], + known_versions: vec![0, 1], received: version, }), } diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/state_transition_like.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/state_transition_like.rs index 022294a3a6..165d071b4b 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/state_transition_like.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/state_transition_like.rs @@ -9,12 +9,14 @@ impl StateTransitionLike for IdentityCreditWithdrawalTransition { fn modified_data_ids(&self) -> Vec { match self { IdentityCreditWithdrawalTransition::V0(transition) => transition.modified_data_ids(), + IdentityCreditWithdrawalTransition::V1(transition) => transition.modified_data_ids(), } } fn state_transition_protocol_version(&self) -> FeatureVersion { match self { IdentityCreditWithdrawalTransition::V0(_) => 0, + IdentityCreditWithdrawalTransition::V1(_) => 0, } } /// returns the type of State Transition @@ -23,12 +25,16 @@ impl StateTransitionLike for IdentityCreditWithdrawalTransition { IdentityCreditWithdrawalTransition::V0(transition) => { transition.state_transition_type() } + IdentityCreditWithdrawalTransition::V1(transition) => { + transition.state_transition_type() + } } } /// returns the signature as a byte-array fn signature(&self) -> &BinaryData { match self { IdentityCreditWithdrawalTransition::V0(transition) => transition.signature(), + IdentityCreditWithdrawalTransition::V1(transition) => transition.signature(), } } /// set a new signature @@ -37,6 +43,9 @@ impl StateTransitionLike for IdentityCreditWithdrawalTransition { IdentityCreditWithdrawalTransition::V0(transition) => { transition.set_signature(signature) } + IdentityCreditWithdrawalTransition::V1(transition) => { + transition.set_signature(signature) + } } } @@ -44,6 +53,7 @@ impl StateTransitionLike for IdentityCreditWithdrawalTransition { fn user_fee_increase(&self) -> UserFeeIncrease { match self { IdentityCreditWithdrawalTransition::V0(transition) => transition.user_fee_increase(), + IdentityCreditWithdrawalTransition::V1(transition) => transition.user_fee_increase(), } } /// set a fee multiplier @@ -52,6 +62,9 @@ impl StateTransitionLike for IdentityCreditWithdrawalTransition { IdentityCreditWithdrawalTransition::V0(transition) => { transition.set_user_fee_increase(user_fee_increase) } + IdentityCreditWithdrawalTransition::V1(transition) => { + transition.set_user_fee_increase(user_fee_increase) + } } } @@ -60,18 +73,23 @@ impl StateTransitionLike for IdentityCreditWithdrawalTransition { IdentityCreditWithdrawalTransition::V0(transition) => { transition.set_signature_bytes(signature) } + IdentityCreditWithdrawalTransition::V1(transition) => { + transition.set_signature_bytes(signature) + } } } fn owner_id(&self) -> Identifier { match self { IdentityCreditWithdrawalTransition::V0(transition) => transition.owner_id(), + IdentityCreditWithdrawalTransition::V1(transition) => transition.owner_id(), } } fn unique_identifiers(&self) -> Vec { match self { IdentityCreditWithdrawalTransition::V0(transition) => transition.unique_identifiers(), + IdentityCreditWithdrawalTransition::V1(transition) => transition.unique_identifiers(), } } } diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/v0/identity_signed.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/v0/identity_signed.rs index 2c8011f2fd..122a1b4534 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/v0/identity_signed.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/v0/identity_signed.rs @@ -13,11 +13,11 @@ impl StateTransitionIdentitySigned for IdentityCreditWithdrawalTransitionV0 { self.signature_public_key_id = key_id } - fn security_level_requirement(&self) -> Vec { + fn security_level_requirement(&self, _purpose: Purpose) -> Vec { vec![CRITICAL] } - fn purpose_requirement(&self) -> Purpose { - Purpose::TRANSFER + fn purpose_requirement(&self) -> Vec { + vec![Purpose::TRANSFER] } } diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/v0/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/v0/mod.rs index 2a5246b9ab..2be39083e0 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/v0/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/v0/mod.rs @@ -3,19 +3,16 @@ mod identity_signed; mod json_conversion; mod state_transition_like; mod types; -mod v0_methods; #[cfg(feature = "state-transition-value-conversion")] mod value_conversion; mod version; use bincode::{Decode, Encode}; -use dashcore::transaction::special_transaction::asset_unlock::qualified_asset_unlock::ASSET_UNLOCK_TX_SIZE; use platform_serialization_derive::PlatformSignable; use platform_value::BinaryData; #[cfg(feature = "state-transition-serde-conversion")] use serde::{Deserialize, Serialize}; -use crate::balances::credits::CREDITS_PER_DUFF; use crate::prelude::{IdentityNonce, UserFeeIncrease}; use crate::{ identity::{core_script::CoreScript, KeyID}, @@ -24,14 +21,6 @@ use crate::{ ProtocolError, }; -// TODO: unsafe - we must use actual relay fee from core -/// Minimal core per byte. Must be a fibonacci number -pub const MIN_CORE_FEE_PER_BYTE: u32 = 1; - -/// Minimal amount in credits (x1000) to avoid "dust" error in Core -pub const MIN_WITHDRAWAL_AMOUNT: u64 = - (ASSET_UNLOCK_TX_SIZE as u64) * (MIN_CORE_FEE_PER_BYTE as u64) * CREDITS_PER_DUFF; - #[derive(Debug, Clone, Encode, Decode, PlatformSignable, PartialEq)] #[cfg_attr( feature = "state-transition-serde-conversion", diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/v0/v0_methods.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/v0/v0_methods.rs deleted file mode 100644 index 8d4f813231..0000000000 --- a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/v0/v0_methods.rs +++ /dev/null @@ -1,76 +0,0 @@ -#[cfg(feature = "state-transition-signing")] -use crate::identity::accessors::IdentityGettersV0; -#[cfg(feature = "state-transition-signing")] -use crate::identity::core_script::CoreScript; -#[cfg(feature = "state-transition-signing")] -use crate::identity::signer::Signer; -#[cfg(feature = "state-transition-signing")] -use crate::identity::IdentityPublicKey; -#[cfg(feature = "state-transition-signing")] -use crate::identity::{Identity, KeyType, Purpose, SecurityLevel}; -#[cfg(feature = "state-transition-signing")] -use crate::prelude::{IdentityNonce, UserFeeIncrease}; -use crate::state_transition::identity_credit_withdrawal_transition::methods::IdentityCreditWithdrawalTransitionMethodsV0; -use crate::state_transition::identity_credit_withdrawal_transition::v0::IdentityCreditWithdrawalTransitionV0; -#[cfg(feature = "state-transition-signing")] -use crate::state_transition::{GetDataContractSecurityLevelRequirementFn, StateTransition}; -#[cfg(feature = "state-transition-signing")] -use crate::withdrawal::Pooling; -#[cfg(feature = "state-transition-signing")] -use crate::ProtocolError; -#[cfg(feature = "state-transition-signing")] -use platform_version::version::{FeatureVersion, PlatformVersion}; - -impl IdentityCreditWithdrawalTransitionMethodsV0 for IdentityCreditWithdrawalTransitionV0 { - #[cfg(feature = "state-transition-signing")] - fn try_from_identity( - identity: &Identity, - withdrawal_key_to_use: Option<&IdentityPublicKey>, - output_script: CoreScript, - amount: u64, - pooling: Pooling, - core_fee_per_byte: u32, - user_fee_increase: UserFeeIncrease, - signer: S, - nonce: IdentityNonce, - _platform_version: &PlatformVersion, - _version: Option, - ) -> Result { - let mut transition: StateTransition = IdentityCreditWithdrawalTransitionV0 { - identity_id: identity.id(), - amount, - core_fee_per_byte, - pooling, - output_script, - nonce, - user_fee_increase, - signature_public_key_id: 0, - signature: Default::default(), - } - .into(); - - let identity_public_key = match withdrawal_key_to_use { - Some(key) => key, - None => identity - .get_first_public_key_matching( - Purpose::TRANSFER, - SecurityLevel::full_range().into(), - KeyType::all_key_types().into(), - true, - ) - .ok_or_else(|| { - ProtocolError::DesiredKeyWithTypePurposeSecurityLevelMissing( - "no withdrawal public key".to_string(), - ) - })?, - }; - - transition.sign_external( - identity_public_key, - &signer, - None::, - )?; - - Ok(transition) - } -} diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/v1/identity_signed.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/v1/identity_signed.rs new file mode 100644 index 0000000000..bc541c4b3c --- /dev/null +++ b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/v1/identity_signed.rs @@ -0,0 +1,23 @@ +use crate::identity::SecurityLevel::CRITICAL; +use crate::identity::{KeyID, Purpose, SecurityLevel}; +use crate::state_transition::identity_credit_withdrawal_transition::v1::IdentityCreditWithdrawalTransitionV1; +use crate::state_transition::StateTransitionIdentitySigned; + +impl StateTransitionIdentitySigned for IdentityCreditWithdrawalTransitionV1 { + fn signature_public_key_id(&self) -> KeyID { + self.signature_public_key_id + } + + fn set_signature_public_key_id(&mut self, key_id: KeyID) { + self.signature_public_key_id = key_id + } + + fn security_level_requirement(&self, _purpose: Purpose) -> Vec { + // critical is used for both transfer and owner + vec![CRITICAL] + } + + fn purpose_requirement(&self) -> Vec { + vec![Purpose::TRANSFER, Purpose::OWNER] + } +} diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/v1/json_conversion.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/v1/json_conversion.rs new file mode 100644 index 0000000000..10b835cfc0 --- /dev/null +++ b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/v1/json_conversion.rs @@ -0,0 +1,4 @@ +use crate::state_transition::identity_credit_withdrawal_transition::v1::IdentityCreditWithdrawalTransitionV1; +use crate::state_transition::StateTransitionJsonConvert; + +impl<'a> StateTransitionJsonConvert<'a> for IdentityCreditWithdrawalTransitionV1 {} diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/v1/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/v1/mod.rs new file mode 100644 index 0000000000..ef18ac89a3 --- /dev/null +++ b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/v1/mod.rs @@ -0,0 +1,45 @@ +mod identity_signed; +#[cfg(feature = "state-transition-json-conversion")] +mod json_conversion; +mod state_transition_like; +mod types; +mod v0_methods; +#[cfg(feature = "state-transition-value-conversion")] +mod value_conversion; +mod version; + +use bincode::{Decode, Encode}; +use platform_serialization_derive::PlatformSignable; +use platform_value::BinaryData; +#[cfg(feature = "state-transition-serde-conversion")] +use serde::{Deserialize, Serialize}; + +use crate::prelude::{IdentityNonce, UserFeeIncrease}; +use crate::{ + identity::{core_script::CoreScript, KeyID}, + prelude::Identifier, + withdrawal::Pooling, + ProtocolError, +}; + +#[derive(Debug, Clone, Encode, Decode, PlatformSignable, PartialEq)] +#[cfg_attr( + feature = "state-transition-serde-conversion", + derive(Serialize, Deserialize), + serde(rename_all = "camelCase") +)] +#[derive(Default)] +pub struct IdentityCreditWithdrawalTransitionV1 { + pub identity_id: Identifier, + pub amount: u64, + pub core_fee_per_byte: u32, + pub pooling: Pooling, + /// If the send to output script is None, then we send the withdrawal to the address set by core + pub output_script: Option, + pub nonce: IdentityNonce, + pub user_fee_increase: UserFeeIncrease, + #[platform_signable(exclude_from_sig_hash)] + pub signature_public_key_id: KeyID, + #[platform_signable(exclude_from_sig_hash)] + pub signature: BinaryData, +} diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/v1/state_transition_like.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/v1/state_transition_like.rs new file mode 100644 index 0000000000..14462d0c28 --- /dev/null +++ b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/v1/state_transition_like.rs @@ -0,0 +1,72 @@ +use base64::prelude::BASE64_STANDARD; +use base64::Engine; +use platform_value::BinaryData; + +use crate::prelude::UserFeeIncrease; +use crate::{ + prelude::Identifier, + state_transition::{StateTransitionLike, StateTransitionType}, +}; + +use crate::state_transition::identity_credit_withdrawal_transition::v1::IdentityCreditWithdrawalTransitionV1; +use crate::state_transition::identity_credit_withdrawal_transition::IdentityCreditWithdrawalTransition; +use crate::state_transition::StateTransition; +use crate::state_transition::StateTransitionType::IdentityCreditWithdrawal; +use crate::version::FeatureVersion; + +impl From for StateTransition { + fn from(value: IdentityCreditWithdrawalTransitionV1) -> Self { + let identity_credit_withdrawal_transition: IdentityCreditWithdrawalTransition = + value.into(); + identity_credit_withdrawal_transition.into() + } +} + +impl StateTransitionLike for IdentityCreditWithdrawalTransitionV1 { + fn state_transition_protocol_version(&self) -> FeatureVersion { + 0 + } + + /// returns the type of State Transition + fn state_transition_type(&self) -> StateTransitionType { + IdentityCreditWithdrawal + } + /// returns the signature as a byte-array + fn signature(&self) -> &BinaryData { + &self.signature + } + /// set a new signature + fn set_signature(&mut self, signature: BinaryData) { + self.signature = signature + } + /// Returns ID of the created contract + fn modified_data_ids(&self) -> Vec { + vec![self.identity_id] + } + + fn set_signature_bytes(&mut self, signature: Vec) { + self.signature = BinaryData::new(signature) + } + + /// Get owner ID + fn owner_id(&self) -> Identifier { + self.identity_id + } + + /// We want things to be unique based on the nonce, so we don't add the transition type + fn unique_identifiers(&self) -> Vec { + vec![format!( + "{}-{:x}", + BASE64_STANDARD.encode(self.identity_id), + self.nonce + )] + } + + fn user_fee_increase(&self) -> UserFeeIncrease { + self.user_fee_increase + } + + fn set_user_fee_increase(&mut self, user_fee_increase: UserFeeIncrease) { + self.user_fee_increase = user_fee_increase + } +} diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/v1/types.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/v1/types.rs new file mode 100644 index 0000000000..3273e62c92 --- /dev/null +++ b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/v1/types.rs @@ -0,0 +1,17 @@ +use crate::state_transition::identity_credit_withdrawal_transition::fields::*; +use crate::state_transition::identity_credit_withdrawal_transition::v1::IdentityCreditWithdrawalTransitionV1; +use crate::state_transition::StateTransitionFieldTypes; + +impl StateTransitionFieldTypes for IdentityCreditWithdrawalTransitionV1 { + fn signature_property_paths() -> Vec<&'static str> { + vec![SIGNATURE, SIGNATURE_PUBLIC_KEY_ID] + } + + fn identifiers_property_paths() -> Vec<&'static str> { + vec![IDENTITY_ID] + } + + fn binary_property_paths() -> Vec<&'static str> { + vec![SIGNATURE, OUTPUT_SCRIPT] + } +} diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/v1/v0_methods.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/v1/v0_methods.rs new file mode 100644 index 0000000000..8f20f27494 --- /dev/null +++ b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/v1/v0_methods.rs @@ -0,0 +1,137 @@ +#[cfg(feature = "state-transition-signing")] +use crate::{ + identity::{ + accessors::IdentityGettersV0, core_script::CoreScript, signer::Signer, Identity, + IdentityPublicKey, KeyType, Purpose, SecurityLevel, + }, + prelude::{IdentityNonce, UserFeeIncrease}, + state_transition::{ + identity_credit_withdrawal_transition::methods::PreferredKeyPurposeForSigningWithdrawal, + GetDataContractSecurityLevelRequirementFn, StateTransition, + }, + withdrawal::Pooling, + ProtocolError, +}; + +#[cfg(feature = "state-transition-signing")] +use platform_version::version::{FeatureVersion, PlatformVersion}; + +use crate::state_transition::identity_credit_withdrawal_transition::methods::IdentityCreditWithdrawalTransitionMethodsV0; +use crate::state_transition::identity_credit_withdrawal_transition::v1::IdentityCreditWithdrawalTransitionV1; + +impl IdentityCreditWithdrawalTransitionMethodsV0 for IdentityCreditWithdrawalTransitionV1 { + #[cfg(feature = "state-transition-signing")] + fn try_from_identity( + identity: &Identity, + output_script: Option, + amount: u64, + pooling: Pooling, + core_fee_per_byte: u32, + user_fee_increase: UserFeeIncrease, + signer: S, + signing_withdrawal_key_to_use: Option<&IdentityPublicKey>, + preferred_key_purpose_for_signing_withdrawal: PreferredKeyPurposeForSigningWithdrawal, + nonce: IdentityNonce, + _platform_version: &PlatformVersion, + _version: Option, + ) -> Result { + let mut transition: StateTransition = IdentityCreditWithdrawalTransitionV1 { + identity_id: identity.id(), + amount, + core_fee_per_byte, + pooling, + output_script, + nonce, + user_fee_increase, + signature_public_key_id: 0, + signature: Default::default(), + } + .into(); + + let identity_public_key = match signing_withdrawal_key_to_use { + Some(key) => { + if signer.can_sign_with(key) { + key + } else { + return Err( + ProtocolError::DesiredKeyWithTypePurposeSecurityLevelMissing( + "specified withdrawal public key cannot be used for signing" + .to_string(), + ), + ); + } + } + None => { + let mut key: Option<&IdentityPublicKey>; + + match preferred_key_purpose_for_signing_withdrawal { + PreferredKeyPurposeForSigningWithdrawal::OwnerPreferred => { + key = identity.get_first_public_key_matching( + Purpose::OWNER, + SecurityLevel::full_range().into(), + KeyType::all_key_types().into(), + true, + ); + + if key.is_none() || !signer.can_sign_with(key.unwrap()) { + key = identity.get_first_public_key_matching( + Purpose::TRANSFER, + SecurityLevel::full_range().into(), + KeyType::all_key_types().into(), + true, + ); + } + } + PreferredKeyPurposeForSigningWithdrawal::TransferPreferred + | PreferredKeyPurposeForSigningWithdrawal::Any => { + key = identity.get_first_public_key_matching( + Purpose::TRANSFER, + SecurityLevel::full_range().into(), + KeyType::all_key_types().into(), + true, + ); + + if key.is_none() || !signer.can_sign_with(key.unwrap()) { + key = identity.get_first_public_key_matching( + Purpose::OWNER, + SecurityLevel::full_range().into(), + KeyType::all_key_types().into(), + true, + ); + } + } + PreferredKeyPurposeForSigningWithdrawal::OwnerOnly => { + key = identity.get_first_public_key_matching( + Purpose::OWNER, + SecurityLevel::full_range().into(), + KeyType::all_key_types().into(), + true, + ); + } + PreferredKeyPurposeForSigningWithdrawal::TransferOnly => { + key = identity.get_first_public_key_matching( + Purpose::TRANSFER, + SecurityLevel::full_range().into(), + KeyType::all_key_types().into(), + true, + ); + } + } + + key.ok_or_else(|| { + ProtocolError::DesiredKeyWithTypePurposeSecurityLevelMissing( + "no withdrawal public key".to_string(), + ) + })? + } + }; + + transition.sign_external( + identity_public_key, + &signer, + None::, + )?; + + Ok(transition) + } +} diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/v1/value_conversion.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/v1/value_conversion.rs new file mode 100644 index 0000000000..6ef90c689a --- /dev/null +++ b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/v1/value_conversion.rs @@ -0,0 +1,60 @@ +use std::collections::BTreeMap; + +use platform_value::{IntegerReplacementType, ReplacementType, Value}; + +use crate::{state_transition::StateTransitionFieldTypes, ProtocolError}; + +use crate::state_transition::identity_credit_withdrawal_transition::fields::*; +use crate::state_transition::StateTransitionValueConvert; + +use crate::state_transition::identity_credit_withdrawal_transition::v1::IdentityCreditWithdrawalTransitionV1; +use platform_version::version::PlatformVersion; + +impl<'a> StateTransitionValueConvert<'a> for IdentityCreditWithdrawalTransitionV1 { + fn from_object( + raw_object: Value, + _platform_version: &PlatformVersion, + ) -> Result { + platform_value::from_value(raw_object).map_err(ProtocolError::ValueError) + } + + fn clean_value(value: &mut Value) -> Result<(), ProtocolError> { + value.replace_at_paths(IDENTIFIER_FIELDS, ReplacementType::Identifier)?; + value.replace_at_paths(BINARY_FIELDS, ReplacementType::BinaryBytes)?; + value.replace_integer_type_at_paths(U32_FIELDS, IntegerReplacementType::U32)?; + Ok(()) + } + + fn from_value_map( + raw_value_map: BTreeMap, + platform_version: &PlatformVersion, + ) -> Result { + let value: Value = raw_value_map.into(); + Self::from_object(value, platform_version) + } + + fn to_object(&self, skip_signature: bool) -> Result { + let mut value = platform_value::to_value(self)?; + if skip_signature { + value + .remove_values_matching_paths(Self::signature_property_paths()) + .map_err(ProtocolError::ValueError)?; + } + Ok(value) + } + + fn to_cleaned_object(&self, skip_signature: bool) -> Result { + let mut value = platform_value::to_value(self)?; + if skip_signature { + value + .remove_values_matching_paths(Self::signature_property_paths()) + .map_err(ProtocolError::ValueError)?; + } + Ok(value) + } + + // Override to_canonical_cleaned_object to manage add_public_keys individually + fn to_canonical_cleaned_object(&self, skip_signature: bool) -> Result { + self.to_cleaned_object(skip_signature) + } +} diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/v1/version.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/v1/version.rs new file mode 100644 index 0000000000..cfff287e9d --- /dev/null +++ b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/v1/version.rs @@ -0,0 +1,9 @@ +use crate::state_transition::identity_credit_withdrawal_transition::v1::IdentityCreditWithdrawalTransitionV1; +use crate::state_transition::FeatureVersioned; +use crate::version::FeatureVersion; + +impl FeatureVersioned for IdentityCreditWithdrawalTransitionV1 { + fn feature_version(&self) -> FeatureVersion { + 1 + } +} diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/value_conversion.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/value_conversion.rs index 365d747ea8..a62a4a184f 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/value_conversion.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/value_conversion.rs @@ -9,6 +9,7 @@ use crate::state_transition::identity_credit_withdrawal_transition::IdentityCred use crate::state_transition::state_transitions::identity_credit_withdrawal_transition::fields::*; use crate::state_transition::StateTransitionValueConvert; +use crate::state_transition::identity_credit_withdrawal_transition::v1::IdentityCreditWithdrawalTransitionV1; use platform_value::btreemap_extensions::BTreeValueRemoveFromMapHelper; use platform_version::version::{FeatureVersion, PlatformVersion}; @@ -20,6 +21,11 @@ impl<'a> StateTransitionValueConvert<'a> for IdentityCreditWithdrawalTransition value.insert(STATE_TRANSITION_PROTOCOL_VERSION.to_string(), Value::U16(0))?; Ok(value) } + IdentityCreditWithdrawalTransition::V1(transition) => { + let mut value = transition.to_object(skip_signature)?; + value.insert(STATE_TRANSITION_PROTOCOL_VERSION.to_string(), Value::U16(1))?; + Ok(value) + } } } @@ -30,6 +36,11 @@ impl<'a> StateTransitionValueConvert<'a> for IdentityCreditWithdrawalTransition value.insert(STATE_TRANSITION_PROTOCOL_VERSION.to_string(), Value::U16(0))?; Ok(value) } + IdentityCreditWithdrawalTransition::V1(transition) => { + let mut value = transition.to_canonical_object(skip_signature)?; + value.insert(STATE_TRANSITION_PROTOCOL_VERSION.to_string(), Value::U16(1))?; + Ok(value) + } } } @@ -40,6 +51,11 @@ impl<'a> StateTransitionValueConvert<'a> for IdentityCreditWithdrawalTransition value.insert(STATE_TRANSITION_PROTOCOL_VERSION.to_string(), Value::U16(0))?; Ok(value) } + IdentityCreditWithdrawalTransition::V1(transition) => { + let mut value = transition.to_canonical_cleaned_object(skip_signature)?; + value.insert(STATE_TRANSITION_PROTOCOL_VERSION.to_string(), Value::U16(1))?; + Ok(value) + } } } @@ -50,6 +66,11 @@ impl<'a> StateTransitionValueConvert<'a> for IdentityCreditWithdrawalTransition value.insert(STATE_TRANSITION_PROTOCOL_VERSION.to_string(), Value::U16(0))?; Ok(value) } + IdentityCreditWithdrawalTransition::V1(transition) => { + let mut value = transition.to_cleaned_object(skip_signature)?; + value.insert(STATE_TRANSITION_PROTOCOL_VERSION.to_string(), Value::U16(1))?; + Ok(value) + } } } @@ -74,6 +95,11 @@ impl<'a> StateTransitionValueConvert<'a> for IdentityCreditWithdrawalTransition platform_version, )? .into()), + 1 => Ok(IdentityCreditWithdrawalTransitionV1::from_object( + raw_object, + platform_version, + )? + .into()), n => Err(ProtocolError::UnknownVersionError(format!( "Unknown IdentityCreditWithdrawalTransition version {n}" ))), @@ -101,6 +127,11 @@ impl<'a> StateTransitionValueConvert<'a> for IdentityCreditWithdrawalTransition platform_version, )? .into()), + 1 => Ok(IdentityCreditWithdrawalTransitionV1::from_value_map( + raw_value_map, + platform_version, + )? + .into()), n => Err(ProtocolError::UnknownVersionError(format!( "Unknown IdentityCreditWithdrawalTransition version {n}" ))), @@ -114,6 +145,7 @@ impl<'a> StateTransitionValueConvert<'a> for IdentityCreditWithdrawalTransition match version { 0 => IdentityCreditWithdrawalTransitionV0::clean_value(value), + 1 => IdentityCreditWithdrawalTransitionV1::clean_value(value), n => Err(ProtocolError::UnknownVersionError(format!( "Unknown IdentityCreditWithdrawalTransition version {n}" ))), diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/version.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/version.rs index d4afb75657..d0f7ab1687 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/version.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_withdrawal_transition/version.rs @@ -6,6 +6,7 @@ impl FeatureVersioned for IdentityCreditWithdrawalTransition { fn feature_version(&self) -> FeatureVersion { match self { IdentityCreditWithdrawalTransition::V0(v0) => v0.feature_version(), + IdentityCreditWithdrawalTransition::V1(v1) => v1.feature_version(), } } } diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_update_transition/identity_signed.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_update_transition/identity_signed.rs index 471f0884e2..ce74927344 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_update_transition/identity_signed.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_update_transition/identity_signed.rs @@ -1,4 +1,4 @@ -use crate::identity::{KeyID, SecurityLevel}; +use crate::identity::{KeyID, Purpose, SecurityLevel}; use crate::state_transition::identity_update_transition::IdentityUpdateTransition; use crate::state_transition::StateTransitionIdentitySigned; @@ -17,9 +17,11 @@ impl StateTransitionIdentitySigned for IdentityUpdateTransition { } } - fn security_level_requirement(&self) -> Vec { + fn security_level_requirement(&self, purpose: Purpose) -> Vec { match self { - IdentityUpdateTransition::V0(transition) => transition.security_level_requirement(), + IdentityUpdateTransition::V0(transition) => { + transition.security_level_requirement(purpose) + } } } } diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_update_transition/v0/identity_signed.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_update_transition/v0/identity_signed.rs index 0b6c85a50a..54d384be93 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_update_transition/v0/identity_signed.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/identity/identity_update_transition/v0/identity_signed.rs @@ -1,5 +1,5 @@ use crate::identity::SecurityLevel::MASTER; -use crate::identity::{KeyID, SecurityLevel}; +use crate::identity::{KeyID, Purpose, SecurityLevel}; use crate::state_transition::identity_update_transition::v0::IdentityUpdateTransitionV0; use crate::state_transition::StateTransitionIdentitySigned; @@ -12,7 +12,7 @@ impl StateTransitionIdentitySigned for IdentityUpdateTransitionV0 { self.signature_public_key_id = key_id } - fn security_level_requirement(&self) -> Vec { + fn security_level_requirement(&self, _purpose: Purpose) -> Vec { vec![MASTER] } } diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/masternode_vote_transition/identity_signed.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/masternode_vote_transition/identity_signed.rs index cfc6f9d65b..9a02b8ddf2 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/identity/masternode_vote_transition/identity_signed.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/identity/masternode_vote_transition/identity_signed.rs @@ -17,13 +17,15 @@ impl StateTransitionIdentitySigned for MasternodeVoteTransition { } } - fn security_level_requirement(&self) -> Vec { + fn security_level_requirement(&self, purpose: Purpose) -> Vec { match self { - MasternodeVoteTransition::V0(transition) => transition.security_level_requirement(), + MasternodeVoteTransition::V0(transition) => { + transition.security_level_requirement(purpose) + } } } - fn purpose_requirement(&self) -> Purpose { + fn purpose_requirement(&self) -> Vec { match self { MasternodeVoteTransition::V0(transition) => transition.purpose_requirement(), } diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/masternode_vote_transition/v0/identity_signed.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/masternode_vote_transition/v0/identity_signed.rs index 47531db013..7b5d731676 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/identity/masternode_vote_transition/v0/identity_signed.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/identity/masternode_vote_transition/v0/identity_signed.rs @@ -12,11 +12,11 @@ impl StateTransitionIdentitySigned for MasternodeVoteTransitionV0 { self.signature_public_key_id = key_id } - fn security_level_requirement(&self) -> Vec { + fn security_level_requirement(&self, _purpose: Purpose) -> Vec { vec![CRITICAL, HIGH, MEDIUM] } - fn purpose_requirement(&self) -> Purpose { - Purpose::VOTING + fn purpose_requirement(&self) -> Vec { + vec![Purpose::VOTING] } } diff --git a/packages/rs-dpp/src/state_transition/state_transitions/identity/public_key_in_creation/methods/validate_identity_public_keys_structure/v0/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/identity/public_key_in_creation/methods/validate_identity_public_keys_structure/v0/mod.rs index 81b489092b..6b02b2e645 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/identity/public_key_in_creation/methods/validate_identity_public_keys_structure/v0/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/identity/public_key_in_creation/methods/validate_identity_public_keys_structure/v0/mod.rs @@ -19,7 +19,7 @@ use crate::ProtocolError; use platform_version::version::PlatformVersion; lazy_static! { - static ref ALLOWED_SECURITY_LEVELS: HashMap> = { + static ref ALLOWED_SECURITY_LEVELS_FOR_EXTERNALLY_ADDED_KEYS: HashMap> = { let mut m = HashMap::new(); m.insert( Purpose::AUTHENTICATION, @@ -119,8 +119,8 @@ impl IdentityPublicKeyInCreation { let validation_errors = identity_public_keys_with_witness .iter() .filter_map(|identity_public_key| { - let allowed_security_levels = - ALLOWED_SECURITY_LEVELS.get(&identity_public_key.purpose()); + let allowed_security_levels = ALLOWED_SECURITY_LEVELS_FOR_EXTERNALLY_ADDED_KEYS + .get(&identity_public_key.purpose()); if let Some(levels) = allowed_security_levels { if !levels.contains(&identity_public_key.security_level()) { Some( diff --git a/packages/rs-dpp/src/state_transition/traits/state_transition_identity_signed.rs b/packages/rs-dpp/src/state_transition/traits/state_transition_identity_signed.rs index c81029a7fe..4da43f68c8 100644 --- a/packages/rs-dpp/src/state_transition/traits/state_transition_identity_signed.rs +++ b/packages/rs-dpp/src/state_transition/traits/state_transition_identity_signed.rs @@ -45,24 +45,25 @@ pub trait StateTransitionIdentitySigned: StateTransitionLike { &self, public_key: &IdentityPublicKey, ) -> Result<(), ProtocolError> { + if !self.purpose_requirement().contains(&public_key.purpose()) { + return Err(ProtocolError::WrongPublicKeyPurposeError( + WrongPublicKeyPurposeError::new(public_key.purpose(), self.purpose_requirement()), + )); + } + // Otherwise, key security level should be less than MASTER but more or equal than required if !self - .security_level_requirement() + .security_level_requirement(public_key.purpose()) .contains(&public_key.security_level()) { return Err(ProtocolError::InvalidSignaturePublicKeySecurityLevelError( InvalidSignaturePublicKeySecurityLevelError::new( public_key.security_level(), - self.security_level_requirement(), + self.security_level_requirement(public_key.purpose()), ), )); } - if public_key.purpose() != self.purpose_requirement() { - return Err(ProtocolError::WrongPublicKeyPurposeError( - WrongPublicKeyPurposeError::new(public_key.purpose(), self.purpose_requirement()), - )); - } Ok(()) } @@ -85,13 +86,13 @@ pub trait StateTransitionIdentitySigned: StateTransitionLike { /// Returns minimal key security level that can be used to sign this ST. /// Override this method if the ST requires a different security level. - fn security_level_requirement(&self) -> Vec; + fn security_level_requirement(&self, purpose: Purpose) -> Vec; /// The purpose requirement for the signing key /// The default is authentication /// However for Withdrawals and Fund Transfers the requirement is TRANSFER - fn purpose_requirement(&self) -> Purpose { - Purpose::AUTHENTICATION + fn purpose_requirement(&self) -> Vec { + vec![Purpose::AUTHENTICATION] } } diff --git a/packages/rs-dpp/src/util/units.rs b/packages/rs-dpp/src/util/units.rs index ca00561cf0..83af5e8976 100644 --- a/packages/rs-dpp/src/util/units.rs +++ b/packages/rs-dpp/src/util/units.rs @@ -27,3 +27,33 @@ macro_rules! dash_to_credits { credits as u64 }}; } + +#[macro_export] +macro_rules! dash_to_duffs { + // The macro takes a string literal representing the Dash amount. + ($dash:expr) => {{ + let dash_str = stringify!($dash); + + // Parsing the input string to separate the whole and fractional parts. + let parts: Vec<&str> = dash_str.split('.').collect(); + let mut credits: u128 = 0; + + // Process the whole number part if it exists. + if let Some(whole) = parts.get(0) { + if let Ok(whole_number) = whole.parse::() { + credits += whole_number * 100_000_000; // Whole Dash amount to credits + } + } + + // Process the fractional part if it exists. + if let Some(fraction) = parts.get(1) { + let fraction_length = fraction.len(); + let fraction_number = fraction.parse::().unwrap_or(0); + // Calculate the multiplier based on the number of digits in the fraction. + let multiplier = 10u128.pow(8 - fraction_length as u32); + credits += fraction_number * multiplier; // Fractional Dash to credits + } + + credits as u64 + }}; +} diff --git a/packages/rs-dpp/src/withdrawal/daily_withdrawal_limit/mod.rs b/packages/rs-dpp/src/withdrawal/daily_withdrawal_limit/mod.rs new file mode 100644 index 0000000000..b1cd0a477d --- /dev/null +++ b/packages/rs-dpp/src/withdrawal/daily_withdrawal_limit/mod.rs @@ -0,0 +1,18 @@ +use crate::fee::Credits; +use crate::withdrawal::daily_withdrawal_limit::v0::daily_withdrawal_limit_v0; +use crate::ProtocolError; +use platform_version::version::PlatformVersion; + +mod v0; + +pub fn daily_withdrawal_limit( + total_credits_in_platform: Credits, + platform_version: &PlatformVersion, +) -> Result { + match platform_version.dpp.methods.daily_withdrawal_limit { + 0 => Ok(daily_withdrawal_limit_v0(total_credits_in_platform)), + v => Err(ProtocolError::UnknownVersionError(format!( + "Unknown daily_withdrawal_limit version {v}" + ))), + } +} diff --git a/packages/rs-dpp/src/withdrawal/daily_withdrawal_limit/v0/mod.rs b/packages/rs-dpp/src/withdrawal/daily_withdrawal_limit/v0/mod.rs new file mode 100644 index 0000000000..c50b89e152 --- /dev/null +++ b/packages/rs-dpp/src/withdrawal/daily_withdrawal_limit/v0/mod.rs @@ -0,0 +1,54 @@ +use crate::fee::Credits; + +/// Calculates the daily withdrawal limit based on the total credits available in the platform. +/// +/// The function enforces the following rules: +/// +/// 1. If the total credits are 1000 Dash in Credits or more: +/// - The withdrawal limit is set to 10% of the total credits. +/// 2. If the total credits are between 100 and 999 Dash in Credits: +/// - The withdrawal limit is capped at 100 credits. +/// 3. If the total credits are less than 100 Dash in Credits: +/// - The withdrawal limit is the total available credits, as no more than the available amount can be withdrawn. +/// +/// # Parameters +/// +/// * `total_credits_in_platform`: The total amount of credits available in the platform. +/// +/// # Returns +/// +/// * `Credits`: The calculated daily withdrawal limit based on the available credits. +/// +pub fn daily_withdrawal_limit_v0(total_credits_in_platform: Credits) -> Credits { + if total_credits_in_platform >= 100_000_000_000_000 { + // 1000 Dash + total_credits_in_platform / 10 + } else if total_credits_in_platform >= 10_000_000_000_000 { + // 100 Dash + 10_000_000_000_000 + } else { + total_credits_in_platform + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::dash_to_credits; + + #[test] + fn test_daily_withdrawal_limit() { + assert_eq!( + daily_withdrawal_limit_v0(dash_to_credits!(2000)), + dash_to_credits!(200) + ); + assert_eq!( + daily_withdrawal_limit_v0(dash_to_credits!(500)), + dash_to_credits!(100) + ); + assert_eq!( + daily_withdrawal_limit_v0(dash_to_credits!(50)), + dash_to_credits!(50) + ); + } +} diff --git a/packages/rs-dpp/src/withdrawal/document_try_into_asset_unlock_base_transaction_info/mod.rs b/packages/rs-dpp/src/withdrawal/document_try_into_asset_unlock_base_transaction_info/mod.rs new file mode 100644 index 0000000000..1ca292303d --- /dev/null +++ b/packages/rs-dpp/src/withdrawal/document_try_into_asset_unlock_base_transaction_info/mod.rs @@ -0,0 +1,25 @@ +use crate::document::Document; +use crate::withdrawal::WithdrawalTransactionIndex; +use crate::ProtocolError; +use dashcore::transaction::special_transaction::asset_unlock::unqualified_asset_unlock::AssetUnlockBaseTransactionInfo; +use platform_version::version::PlatformVersion; +mod v0; +impl Document { + pub fn try_into_asset_unlock_base_transaction_info( + &self, + transaction_index: WithdrawalTransactionIndex, + platform_version: &PlatformVersion, + ) -> Result { + match platform_version + .dpp + .document_versions + .document_method_versions + .try_into_asset_unlock_base_transaction_info + { + 0 => self.try_into_asset_unlock_base_transaction_info_v0(transaction_index), + v => Err(ProtocolError::UnknownVersionError(format!( + "Unknown IdentityCreateTransition version for try_from_identity_with_signer {v}" + ))), + } + } +} diff --git a/packages/rs-dpp/src/withdrawal/document_try_into_asset_unlock_base_transaction_info/v0/mod.rs b/packages/rs-dpp/src/withdrawal/document_try_into_asset_unlock_base_transaction_info/v0/mod.rs new file mode 100644 index 0000000000..f28b9dcf8b --- /dev/null +++ b/packages/rs-dpp/src/withdrawal/document_try_into_asset_unlock_base_transaction_info/v0/mod.rs @@ -0,0 +1,45 @@ +use crate::document::{Document, DocumentV0Getters}; +use crate::identity::convert_credits_to_duffs; +use crate::system_data_contracts::withdrawals_contract::v1::document_types::withdrawal; +use crate::withdrawal::WithdrawalTransactionIndex; +use crate::ProtocolError; +use dashcore::transaction::special_transaction::asset_unlock::qualified_asset_unlock::ASSET_UNLOCK_TX_SIZE; +use dashcore::transaction::special_transaction::asset_unlock::unqualified_asset_unlock::{ + AssetUnlockBasePayload, AssetUnlockBaseTransactionInfo, +}; +use dashcore::{ScriptBuf, TxOut}; +use platform_value::btreemap_extensions::BTreeValueMapHelper; + +impl Document { + pub(super) fn try_into_asset_unlock_base_transaction_info_v0( + &self, + transaction_index: WithdrawalTransactionIndex, + ) -> Result { + let properties = self.properties(); + + let output_script_bytes = properties.get_bytes(withdrawal::properties::OUTPUT_SCRIPT)?; + + let amount = properties.get_integer(withdrawal::properties::AMOUNT)?; + + let core_fee_per_byte: u32 = + properties.get_integer(withdrawal::properties::CORE_FEE_PER_BYTE)?; + + let output_script = ScriptBuf::from_bytes(output_script_bytes); + + let tx_out = TxOut { + value: convert_credits_to_duffs(amount)?, + script_pubkey: output_script, + }; + + Ok(AssetUnlockBaseTransactionInfo { + version: 1, + lock_time: 0, + output: vec![tx_out], + base_payload: AssetUnlockBasePayload { + version: 1, + index: transaction_index, + fee: ASSET_UNLOCK_TX_SIZE as u32 * core_fee_per_byte, + }, + }) + } +} diff --git a/packages/rs-dpp/src/withdrawal/mod.rs b/packages/rs-dpp/src/withdrawal/mod.rs index be31e49559..6ce0f25811 100644 --- a/packages/rs-dpp/src/withdrawal/mod.rs +++ b/packages/rs-dpp/src/withdrawal/mod.rs @@ -1,3 +1,7 @@ +pub mod daily_withdrawal_limit; +#[cfg(feature = "system_contracts")] +mod document_try_into_asset_unlock_base_transaction_info; + use bincode::{Decode, Encode}; use serde_repr::{Deserialize_repr, Serialize_repr}; @@ -11,3 +15,10 @@ pub enum Pooling { IfAvailable = 1, Standard = 2, } + +/// Transaction index type +pub type WithdrawalTransactionIndex = u64; + +/// Simple type alias for withdrawal transaction with it's index + +pub type WithdrawalTransactionIndexAndBytes = (WithdrawalTransactionIndex, Vec); diff --git a/packages/rs-drive-abci/Cargo.toml b/packages/rs-drive-abci/Cargo.toml index 989f9b2b4c..b1762b8706 100644 --- a/packages/rs-drive-abci/Cargo.toml +++ b/packages/rs-drive-abci/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "drive-abci" -version = "1.3.1" +version = "1.5.0" authors = [ "Samuel Westrich ", "Ivan Shumkov ", @@ -23,18 +23,18 @@ drive = { path = "../rs-drive", default-features = false, features = [ "server", "grovedb_operations_logging", ] } -thiserror = "1.0.58" +thiserror = "1.0.64" rand = "0.8.5" tempfile = "3.3.0" hex = "0.4.3" indexmap = { version = "2.2.6", features = ["serde"] } -dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore-rpc", tag = "v0.15.4" } +dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore-rpc", tag = "v0.15.8" } dpp = { path = "../rs-dpp", features = ["abci"] } simple-signer = { path = "../simple-signer" } rust_decimal = "1.2.5" rust_decimal_macros = "1.25.0" -mockall = { version = "0.11", optional = true } -prost = { version = "0.12", default-features = false } +mockall = { version = "0.13", optional = true } +prost = { version = "0.13", default-features = false } tracing = { version = "0.1.37", default-features = false, features = [] } clap = { version = "4.4.10", features = ["derive"] } envy = { version = "0.4.2" } @@ -49,30 +49,30 @@ tracing-subscriber = { version = "0.3.16", default-features = false, features = "registry", "tracing-log", ], optional = false } -atty = { version = "0.2.14", optional = false } -tenderdash-abci = { git = "https://github.com/dashpay/rs-tenderdash-abci", version = "1.2.0+1.3.0", tag = "v1.2.0+1.3.0", features = [ +tenderdash-abci = { git = "https://github.com/dashpay/rs-tenderdash-abci", version = "1.2.1", tag = "v1.2.1+1.3.0", features = [ "grpc", ] } lazy_static = "1.4.0" -itertools = { version = "0.10.5" } +itertools = { version = "0.13" } file-rotate = { version = "0.7.3" } reopen = { version = "1.0.3" } -delegate = { version = "0.9.0" } +delegate = { version = "0.13" } regex = { version = "1.8.1" } -metrics = { version = "0.22.3" } -metrics-exporter-prometheus = { version = "0.14.0" } +metrics = { version = "0.23" } +metrics-exporter-prometheus = { version = "0.15", default-features = false, features = [ + "http-listener", +] } url = { version = "2.3.1" } -ureq = { "version" = "2.6.2" } -tokio = { version = "1.36", features = [ +tokio = { version = "1.40", features = [ "macros", "signal", "rt-multi-thread", "time", ] } -tokio-util = { version = "0.7.8" } -derive_more = "0.99.17" +tokio-util = { version = "0.7" } +derive_more = { version = "1.0", features = ["from", "deref", "deref_mut"] } async-trait = "0.1.77" -console-subscriber = { version = "0.2.0", optional = true } +console-subscriber = { version = "0.4", optional = true } [dev-dependencies] bs58 = { version = "0.5.0" } diff --git a/packages/rs-drive-abci/src/abci/handler/prepare_proposal.rs b/packages/rs-drive-abci/src/abci/handler/prepare_proposal.rs index 9a59463bea..18252d0d45 100644 --- a/packages/rs-drive-abci/src/abci/handler/prepare_proposal.rs +++ b/packages/rs-drive-abci/src/abci/handler/prepare_proposal.rs @@ -163,10 +163,26 @@ where // Such state transitions must be invalidated by check tx, but they might // still be added to mempool due to inconsistency between check tx and tx processing // (fees calculation) or malicious proposer. - StateTransitionExecutionResult::UnpaidConsensusError(..) => TxAction::Removed, + StateTransitionExecutionResult::UnpaidConsensusError(consensus_error) => { + tracing::trace!( + "UnpaidConsensusError at height {}, round {}: {:?}", + request.height, + request.round, + consensus_error + ); + TxAction::Removed + } // We shouldn't include in the block any state transitions that produced an internal error // during execution - StateTransitionExecutionResult::InternalError(..) => TxAction::Removed, + StateTransitionExecutionResult::InternalError(error_message) => { + tracing::debug!( + "InternalError at height {}, round {}: {}", + request.height, + request.round, + error_message + ); + TxAction::Removed + } // State Transition was not executed as it reached the maximum time limit StateTransitionExecutionResult::NotExecuted(..) => TxAction::Delayed, }; diff --git a/packages/rs-drive-abci/src/config.rs b/packages/rs-drive-abci/src/config.rs index ad0cfdbce5..1e8f5f3c26 100644 --- a/packages/rs-drive-abci/src/config.rs +++ b/packages/rs-drive-abci/src/config.rs @@ -180,14 +180,11 @@ pub struct PlatformConfig { /// Approximately how often are blocks produced pub block_spacing_ms: u64, - /// Initial protocol version - pub initial_protocol_version: ProtocolVersion, - /// Path to data storage pub db_path: PathBuf, /// Path to store rejected / invalid items (like transactions). - /// Used mainly for debuggig. + /// Used mainly for debugging. /// /// If not set, rejected and invalid items will not be stored. pub rejections_path: Option, @@ -276,7 +273,6 @@ impl<'de> Deserialize<'de> for PlatformConfig { chain_lock: config.chain_lock, instant_lock: config.instant_lock, block_spacing_ms: config.block_spacing_ms, - initial_protocol_version: config.initial_protocol_version, db_path: config.db_path, rejections_path: config.rejections_path, #[cfg(feature = "testing-config")] @@ -734,7 +730,6 @@ impl PlatformConfig { tokio_console_enabled: false, tokio_console_address: PlatformConfig::default_tokio_console_address(), tokio_console_retention_secs: PlatformConfig::default_tokio_console_retention_secs(), - initial_protocol_version: Self::default_initial_protocol_version(), prometheus_bind_address: None, grpc_bind_address: "127.0.0.1:26670".to_string(), } @@ -777,7 +772,6 @@ impl PlatformConfig { tokio_console_enabled: false, tokio_console_address: PlatformConfig::default_tokio_console_address(), tokio_console_retention_secs: PlatformConfig::default_tokio_console_retention_secs(), - initial_protocol_version: Self::default_initial_protocol_version(), prometheus_bind_address: None, grpc_bind_address: "127.0.0.1:26670".to_string(), } @@ -817,7 +811,6 @@ impl PlatformConfig { rejections_path: Some(PathBuf::from("/var/log/dash/rejected")), #[cfg(feature = "testing-config")] testing_configs: PlatformTestConfig::default(), - initial_protocol_version: Self::default_initial_protocol_version(), prometheus_bind_address: None, grpc_bind_address: "127.0.0.1:26670".to_string(), tokio_console_enabled: false, @@ -860,7 +853,6 @@ impl PlatformConfig { rejections_path: Some(PathBuf::from("/var/log/dash/rejected")), #[cfg(feature = "testing-config")] testing_configs: PlatformTestConfig::default(), - initial_protocol_version: Self::default_initial_protocol_version(), prometheus_bind_address: None, grpc_bind_address: "127.0.0.1:26670".to_string(), tokio_console_enabled: false, diff --git a/packages/rs-drive-abci/src/execution/check_tx/v0/mod.rs b/packages/rs-drive-abci/src/execution/check_tx/v0/mod.rs index d24ce2361d..acfb7fca04 100644 --- a/packages/rs-drive-abci/src/execution/check_tx/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/check_tx/v0/mod.rs @@ -213,7 +213,7 @@ mod tests { use dpp::consensus::ConsensusError; use dpp::dashcore::secp256k1::Secp256k1; - use dpp::dashcore::{key::KeyPair, signer, Network, PrivateKey}; + use dpp::dashcore::{key::Keypair, signer, Network, PrivateKey}; use dpp::data_contract::accessors::v0::{DataContractV0Getters, DataContractV0Setters}; use dpp::data_contract::document_type::random_document::{ @@ -2659,7 +2659,7 @@ mod tests { let secp = Secp256k1::new(); - let new_key_pair = KeyPair::new(&secp, &mut rng); + let new_key_pair = Keypair::new(&secp, &mut rng); let mut new_key = IdentityPublicKeyInCreationV0 { id: 2, @@ -2760,7 +2760,7 @@ mod tests { let platform_state = platform.state.load(); - let new_key_pair = KeyPair::new(&secp, &mut rng); + let new_key_pair = Keypair::new(&secp, &mut rng); let new_key = IdentityPublicKeyInCreationV0 { id: 2, diff --git a/packages/rs-drive-abci/src/execution/engine/consensus_params_update/mod.rs b/packages/rs-drive-abci/src/execution/engine/consensus_params_update/mod.rs index 16319d7746..e3163039f1 100644 --- a/packages/rs-drive-abci/src/execution/engine/consensus_params_update/mod.rs +++ b/packages/rs-drive-abci/src/execution/engine/consensus_params_update/mod.rs @@ -7,6 +7,8 @@ use dpp::version::PlatformVersion; use tenderdash_abci::proto::types::ConsensusParams; mod v0; +mod v1; + pub(crate) fn consensus_params_update( network: Network, original_platform_version: &PlatformVersion, @@ -25,9 +27,15 @@ pub(crate) fn consensus_params_update( new_platform_version, epoch_info, )), + 1 => Ok(v1::consensus_params_update_v1( + network, + original_platform_version, + new_platform_version, + epoch_info, + )), version => Err(Error::Execution(ExecutionError::UnknownVersionMismatch { method: "consensus_params_update".to_string(), - known_versions: vec![0], + known_versions: vec![0, 1], received: version, })), } diff --git a/packages/rs-drive-abci/src/execution/engine/consensus_params_update/v1/mod.rs b/packages/rs-drive-abci/src/execution/engine/consensus_params_update/v1/mod.rs new file mode 100644 index 0000000000..85e9d40180 --- /dev/null +++ b/packages/rs-drive-abci/src/execution/engine/consensus_params_update/v1/mod.rs @@ -0,0 +1,74 @@ +use crate::platform_types::epoch_info::v0::EpochInfoV0Methods; +use crate::platform_types::epoch_info::EpochInfo; +use dpp::dashcore::Network; +use dpp::version::PlatformVersion; +use tenderdash_abci::proto::types::{ConsensusParams, VersionParams}; + +#[inline(always)] +pub(super) fn consensus_params_update_v1( + network: Network, + original_platform_version: &PlatformVersion, + new_platform_version: &PlatformVersion, + epoch_info: &EpochInfo, +) -> Option { + // These are emergency consensus updates + match network { + Network::Dash => { + if epoch_info.is_first_block_of_epoch(3) { + return Some(ConsensusParams { + block: None, + evidence: None, + validator: None, + version: Some(VersionParams { + app_version: new_platform_version.protocol_version as u64, + consensus_version: 1, + }), + synchrony: None, + timeout: None, + abci: None, + }); + } + } + Network::Testnet => { + if epoch_info.is_first_block_of_epoch(1480) { + return Some(ConsensusParams { + block: None, + evidence: None, + validator: None, + version: Some(VersionParams { + app_version: new_platform_version.protocol_version as u64, + consensus_version: 1, + }), + synchrony: None, + timeout: None, + abci: None, + }); + } + } + _ => {} + } + + // Update versions if any of them changed + if original_platform_version + .consensus + .tenderdash_consensus_version + == new_platform_version.consensus.tenderdash_consensus_version + && original_platform_version.protocol_version == new_platform_version.protocol_version + { + None + } else { + Some(ConsensusParams { + block: None, + evidence: None, + validator: None, + version: Some(VersionParams { + app_version: new_platform_version.protocol_version as u64, + consensus_version: new_platform_version.consensus.tenderdash_consensus_version + as i32, + }), + synchrony: None, + timeout: None, + abci: None, + }) + } +} diff --git a/packages/rs-drive-abci/src/execution/engine/finalize_block_proposal/v0/mod.rs b/packages/rs-drive-abci/src/execution/engine/finalize_block_proposal/v0/mod.rs index c56272b61d..ecfc3d6edf 100644 --- a/packages/rs-drive-abci/src/execution/engine/finalize_block_proposal/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/engine/finalize_block_proposal/v0/mod.rs @@ -8,8 +8,6 @@ use dpp::block::block_info::BlockInfo; use dpp::block::extended_block_info::v0::ExtendedBlockInfoV0; use dpp::version::PlatformVersion; -use dpp::dashcore::bls_sig_utils::BLSSignature; - use tenderdash_abci::{ proto::{serializers::timestamp::ToMilis, types::BlockId as ProtoBlockId}, signatures::Hashable, @@ -19,8 +17,7 @@ use crate::abci::AbciError; use crate::error::Error; use crate::execution::types::block_execution_context::v0::{ - BlockExecutionContextV0Getters, BlockExecutionContextV0MutableGetters, - BlockExecutionContextV0OwnedGetters, + BlockExecutionContextV0Getters, BlockExecutionContextV0OwnedGetters, }; use crate::execution::types::block_execution_context::BlockExecutionContext; use crate::execution::types::block_state_info::v0::{ @@ -62,7 +59,7 @@ where pub(super) fn finalize_block_proposal_v0( &self, request_finalize_block: FinalizeBlockCleanedRequest, - mut block_execution_context: BlockExecutionContext, + block_execution_context: BlockExecutionContext, transaction: &Transaction, platform_version: &PlatformVersion, ) -> Result { @@ -74,7 +71,7 @@ where // Let's decompose the request let FinalizeBlockCleanedRequest { - commit: mut commit_info, + commit: commit_info, misbehavior: _, hash, height, @@ -143,16 +140,16 @@ where let expected_withdrawal_transactions = block_execution_context.unsigned_withdrawal_transactions(); - if !expected_withdrawal_transactions - .are_matching_with_vote_extensions(&commit_info.threshold_vote_extensions) - { + let Some(transaction_to_extension_matches) = expected_withdrawal_transactions + .verify_and_match_with_vote_extensions(&commit_info.threshold_vote_extensions) + else { validation_result.add_error(AbciError::VoteExtensionMismatchReceived { got: commit_info.threshold_vote_extensions, - expected: expected_withdrawal_transactions.into(), + expected: (&expected_withdrawal_transactions.clone()).into(), }); return Ok(validation_result.into()); - } + }; // Verify commit @@ -202,34 +199,9 @@ where to_commit_block_info.core_height = block_header.core_chain_locked_height; - // Append signatures and broadcast asset unlock transactions to Core - - // Drain withdrawal transaction instead of cloning - let unsigned_withdrawal_transactions = block_execution_context - .unsigned_withdrawal_transactions_mut() - .drain(); - - if !unsigned_withdrawal_transactions.is_empty() { - // Drain signatures instead of cloning - let signatures = commit_info - .threshold_vote_extensions - .drain(..) - .map(|vote_extension| { - let signature_bytes: [u8; 96] = - vote_extension.signature.try_into().map_err(|e| { - AbciError::BadRequestDataSize(format!( - "invalid votes extension signature size: {}", - hex::encode(e) - )) - })?; - - Ok(BLSSignature::from(signature_bytes)) - }) - .collect::>()?; - + if !transaction_to_extension_matches.is_empty() { self.append_signatures_and_broadcast_withdrawal_transactions( - unsigned_withdrawal_transactions, - signatures, + transaction_to_extension_matches, platform_version, )?; } diff --git a/packages/rs-drive-abci/src/execution/engine/initialization/init_chain/mod.rs b/packages/rs-drive-abci/src/execution/engine/initialization/init_chain/mod.rs index 57ec814c04..1b580ba38d 100644 --- a/packages/rs-drive-abci/src/execution/engine/initialization/init_chain/mod.rs +++ b/packages/rs-drive-abci/src/execution/engine/initialization/init_chain/mod.rs @@ -5,8 +5,10 @@ use crate::platform_types::platform::Platform; use crate::rpc::core::CoreRPCLike; +use crate::abci::AbciError; use crate::error::execution::ExecutionError; use dpp::version::PlatformVersion; +use dpp::version::ProtocolVersion; use drive::grovedb::Transaction; use tenderdash_abci::proto::abci::{RequestInitChain, ResponseInitChain}; @@ -22,8 +24,31 @@ where ) -> Result { // We don't have platform state at this point, so we should // use initial protocol version from genesis - let protocol_version = self.config.initial_protocol_version; - let platform_version = PlatformVersion::get(protocol_version)?; + let consensus_params = request + .consensus_params + .as_ref() + .ok_or(AbciError::BadRequest( + "consensus params are required in init chain".to_string(), + ))?; + + let tenderdash_abci::proto::types::VersionParams { + app_version: protocol_version, + .. + } = consensus_params + .version + .as_ref() + .ok_or(AbciError::BadRequest( + "consensus params version is required in init chain".to_string(), + ))?; + + let platform_version = if *protocol_version == 0 { + // Protocol version is not set. + // We are starting the chain with the desired version + PlatformVersion::desired() + } else { + // Use the version from the genesis + PlatformVersion::get(*protocol_version as ProtocolVersion)? + }; match platform_version.drive_abci.methods.engine.init_chain { 0 => self.init_chain_v0(request, transaction, platform_version), diff --git a/packages/rs-drive-abci/src/execution/engine/initialization/init_chain/v0/mod.rs b/packages/rs-drive-abci/src/execution/engine/initialization/init_chain/v0/mod.rs index 398d4c111f..b67cd01253 100644 --- a/packages/rs-drive-abci/src/execution/engine/initialization/init_chain/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/engine/initialization/init_chain/v0/mod.rs @@ -7,12 +7,16 @@ use dpp::block::block_info::BlockInfo; use drive::error::Error::GroveDB; use drive::grovedb::Transaction; +use crate::execution::engine::consensus_params_update::consensus_params_update; use crate::platform_types::cleaned_abci_messages::request_init_chain_cleaned_params; +use crate::platform_types::epoch_info::v0::EpochInfoV0; +use crate::platform_types::epoch_info::EpochInfo; use crate::platform_types::platform_state::v0::PlatformStateV0Methods; use crate::platform_types::platform_state::PlatformState; +use crate::platform_types::validator_set::ValidatorSetExt; use dpp::version::PlatformVersion; use std::sync::Arc; -use tenderdash_abci::proto::abci::{RequestInitChain, ResponseInitChain, ValidatorSetUpdate}; +use tenderdash_abci::proto::abci::{RequestInitChain, ResponseInitChain}; use tenderdash_abci::proto::google::protobuf::Timestamp; use tenderdash_abci::proto::serializers::timestamp::FromMilis; @@ -67,8 +71,8 @@ where // Create platform execution state let mut initial_platform_state = PlatformState::default_with_protocol_versions( - request.initial_protocol_version, - request.initial_protocol_version, + platform_version.protocol_version, + platform_version.protocol_version, &self.config, )?; @@ -105,19 +109,13 @@ where ExecutionError::InitializationError("we should have at least one quorum"), )?; - ( - *validator_set_inner.0, - ValidatorSetUpdate::from(validator_set_inner.1), - ) + (*validator_set_inner.0, validator_set_inner.1.to_update()) }; initial_platform_state.set_current_validator_set_quorum_hash(quorum_hash); initial_platform_state.set_genesis_block_info(Some(genesis_block_info)); - initial_platform_state - .set_current_protocol_version_in_consensus(request.initial_protocol_version); - if tracing::enabled!(tracing::Level::TRACE) { tracing::trace!( platform_state_fingerprint = hex::encode(initial_platform_state.fingerprint()?), @@ -134,8 +132,24 @@ where .unwrap() .map_err(GroveDB)?; + // We use first platform version because Tenderdash starts genesis with first versions + // by default + let first_platform_version = PlatformVersion::first(); + + let epoch_info = EpochInfo::V0(EpochInfoV0::calculate( + genesis_time, + genesis_time, + None, + self.config.execution.epoch_time_length_s, + )?); + Ok(ResponseInitChain { - consensus_params: None, + consensus_params: consensus_params_update( + self.config.network, + first_platform_version, + platform_version, + &epoch_info, + )?, app_hash: app_hash.to_vec(), validator_set_update: Some(validator_set), next_core_chain_lock_update: None, diff --git a/packages/rs-drive-abci/src/execution/engine/run_block_proposal/mod.rs b/packages/rs-drive-abci/src/execution/engine/run_block_proposal/mod.rs index a8420b34b0..43712c7feb 100644 --- a/packages/rs-drive-abci/src/execution/engine/run_block_proposal/mod.rs +++ b/packages/rs-drive-abci/src/execution/engine/run_block_proposal/mod.rs @@ -1,12 +1,15 @@ use crate::error::execution::ExecutionError; use crate::error::Error; +use crate::execution::types::block_state_info; +use crate::execution::types::block_state_info::v0::BlockStateInfoV0Methods; use crate::metrics::HistogramTiming; -use crate::platform_types::epoch_info::v0::EpochInfoV0Methods; +use crate::platform_types::epoch_info::v0::{EpochInfoV0Getters, EpochInfoV0Methods}; use crate::platform_types::platform::Platform; use crate::platform_types::platform_state::v0::PlatformStateV0Methods; use crate::platform_types::platform_state::PlatformState; use crate::platform_types::{block_execution_outcome, block_proposal}; use crate::rpc::core::CoreRPCLike; +use dpp::block::epoch::Epoch; use dpp::validation::ValidationResult; use dpp::version::PlatformVersion; use drive::grovedb::Transaction; @@ -91,8 +94,35 @@ Your software version: {}, latest supported protocol version: {}."#, ); }; - // Set current protocol version to the block platform state - block_platform_state.set_current_protocol_version_in_consensus(next_protocol_version); + let old_protocol_version = block_platform_state.current_protocol_version_in_consensus(); + + if old_protocol_version != next_protocol_version { + // Set current protocol version to the block platform state + block_platform_state + .set_current_protocol_version_in_consensus(next_protocol_version); + + let last_block_time_ms = platform_state.last_committed_block_time_ms(); + + // Init block execution context + let block_state_info = block_state_info::v0::BlockStateInfoV0::from_block_proposal( + &block_proposal, + last_block_time_ms, + ); + + let block_info = block_state_info.to_block_info( + Epoch::new(epoch_info.current_epoch_index()) + .expect("current epoch index should be in range"), + ); + + // This is for events like adding stuff to the root tree, or making structural changes/fixes + self.perform_events_on_first_block_of_protocol_change( + platform_state, + &block_info, + transaction, + old_protocol_version, + next_platform_version, + )?; + } next_platform_version } else { diff --git a/packages/rs-drive-abci/src/execution/engine/run_block_proposal/v0/mod.rs b/packages/rs-drive-abci/src/execution/engine/run_block_proposal/v0/mod.rs index 5a5d36780b..9c45694f6c 100644 --- a/packages/rs-drive-abci/src/execution/engine/run_block_proposal/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/engine/run_block_proposal/v0/mod.rs @@ -269,6 +269,14 @@ where Error::Execution(ExecutionError::UpdateValidatorProposedAppVersionError(e)) })?; // This is a system error + // Rebroadcast expired withdrawals if they exist + self.rebroadcast_expired_withdrawal_documents( + &block_info, + &last_committed_platform_state, + transaction, + platform_version, + )?; + // Mark all previously broadcasted and chainlocked withdrawals as complete // only when we are on a new core height if block_state_info.core_chain_locked_height() != last_block_core_height { @@ -285,6 +293,8 @@ where // required for signature verification (core height and quorum hash) // Then we save unsigned transaction bytes to block execution context // to be signed (on extend_vote), verified (on verify_vote) and broadcasted (on finalize_block) + // Also, the dequeued untiled transaction added to the broadcasted transaction queue to for further + // resigning in case of failures. let unsigned_withdrawal_transaction_bytes = self .dequeue_and_build_unsigned_withdrawal_transactions( validator_set_quorum_hash, @@ -321,16 +331,29 @@ where // Corresponding withdrawal documents are changed from queued to pooled self.pool_withdrawals_into_transactions_queue( &block_info, + last_committed_platform_state, Some(transaction), platform_version, )?; + // Cleans up the expired locks for withdrawal amounts + // to update daily withdrawal limit + // This is for example when we make a withdrawal for 30 Dash + // But we can only withdraw 1000 Dash a day + // after the withdrawal we should only be able to withdraw 970 Dash + // But 24 hours later that locked 30 comes back + self.clean_up_expired_locks_of_withdrawal_amounts( + &block_info, + transaction, + platform_version, + )?; + // Create a new block execution context let mut block_execution_context: BlockExecutionContext = block_execution_context::v0::BlockExecutionContextV0 { block_state_info: block_state_info.into(), - epoch_info: epoch_info.clone(), + epoch_info, unsigned_withdrawal_transactions: unsigned_withdrawal_transaction_bytes, block_platform_state, proposer_results: None, diff --git a/packages/rs-drive-abci/src/execution/platform_events/block_end/validator_set_update/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/block_end/validator_set_update/mod.rs index ebfe6c3fdf..25922cdf19 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/block_end/validator_set_update/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/block_end/validator_set_update/mod.rs @@ -1,4 +1,6 @@ mod v0; +mod v1; +mod v2; use crate::error::execution::ExecutionError; use crate::error::Error; @@ -52,9 +54,19 @@ where platform_state, block_execution_context, ), + 1 => self.validator_set_update_v1( + proposer_pro_tx_hash, + platform_state, + block_execution_context, + ), + 2 => self.validator_set_update_v2( + proposer_pro_tx_hash, + platform_state, + block_execution_context, + ), version => Err(Error::Execution(ExecutionError::UnknownVersionMismatch { method: "validator_set_update".to_string(), - known_versions: vec![0], + known_versions: vec![0, 1, 2], received: version, })), } diff --git a/packages/rs-drive-abci/src/execution/platform_events/block_end/validator_set_update/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/block_end/validator_set_update/v0/mod.rs index efc6251880..9d713e04cd 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/block_end/validator_set_update/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/block_end/validator_set_update/v0/mod.rs @@ -11,6 +11,7 @@ use crate::platform_types::validator_set::v0::ValidatorSetV0Getters; use crate::rpc::core::CoreRPCLike; use itertools::Itertools; +use crate::platform_types::validator_set::ValidatorSetExt; use dpp::dashcore::hashes::Hash; use tenderdash_abci::proto::abci::ValidatorSetUpdate; @@ -92,7 +93,7 @@ where // we also need to perform a rotation if the validator set is being removed tracing::debug!( method = "validator_set_update_v0", - "rotation: new quorums not containing current quorum current {:?}, {}. quorum rotation expected˚", + "rotation: new quorums not containing current quorum current {:?}, {}. quorum rotation expected", block_execution_context .block_platform_state() .validator_sets() @@ -144,7 +145,7 @@ where &quorum_hash, new_validator_set.members().len() ); - let validator_set_update = new_validator_set.into(); + let validator_set_update = new_validator_set.to_update(); block_execution_context .block_platform_state_mut() .set_next_validator_set_quorum_hash(Some(*quorum_hash)); @@ -163,7 +164,7 @@ where "rotation: all quorums changed, rotation to new quorum: {}", &quorum_hash ); - let validator_set_update = new_validator_set.into(); + let validator_set_update = new_validator_set.to_update(); let new_quorum_hash = *quorum_hash; block_execution_context .block_platform_state_mut() @@ -185,7 +186,7 @@ where method = "validator_set_update_v0", "validator set update without rotation" ); - Ok(Some(current_validator_set.into())) + Ok(Some(current_validator_set.to_update())) } else { tracing::debug!( method = "validator_set_update_v0", diff --git a/packages/rs-drive-abci/src/execution/platform_events/block_end/validator_set_update/v1/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/block_end/validator_set_update/v1/mod.rs new file mode 100644 index 0000000000..b7b8f1372f --- /dev/null +++ b/packages/rs-drive-abci/src/execution/platform_events/block_end/validator_set_update/v1/mod.rs @@ -0,0 +1,217 @@ +use crate::error::execution::ExecutionError; +use crate::error::Error; +use crate::execution::types::block_execution_context::v0::{ + BlockExecutionContextV0Getters, BlockExecutionContextV0MutableGetters, +}; +use crate::execution::types::block_execution_context::BlockExecutionContext; +use crate::platform_types::platform::Platform; +use crate::platform_types::platform_state::v0::PlatformStateV0Methods; +use crate::platform_types::platform_state::PlatformState; +use crate::platform_types::validator_set::v0::ValidatorSetV0Getters; +use crate::rpc::core::CoreRPCLike; +use itertools::Itertools; + +use crate::platform_types::validator_set::ValidatorSetExt; +use dpp::dashcore::hashes::Hash; +use tenderdash_abci::proto::abci::ValidatorSetUpdate; + +impl Platform +where + C: CoreRPCLike, +{ + /// We need to validate against the platform state for rotation and not the block execution + /// context state + /// We introduced v1 because the end quorums could be rotating out, giving a small advantage + /// to proposers with a smaller pro_tx_hash + /// To understand this imagine we have proposers + /// `a b c d e f g h i j k` in quorum 24 + /// c is the current proposer + /// Quorum 24 no longer is valid + /// We jump to quorum 0. + /// a b and c just got paid, but the rest did not. + #[inline(always)] + pub(super) fn validator_set_update_v1( + &self, + proposer_pro_tx_hash: [u8; 32], + platform_state: &PlatformState, + block_execution_context: &mut BlockExecutionContext, + ) -> Result, Error> { + let mut perform_rotation = false; + + if let Some(validator_set) = block_execution_context + .block_platform_state() + .validator_sets() + .get(&platform_state.current_validator_set_quorum_hash()) + { + if let Some((last_member_pro_tx_hash, _)) = validator_set.members().last_key_value() { + // we should also perform a rotation if the validator set went through all quorum members + // this means we are at the last member of the quorum + if last_member_pro_tx_hash.as_byte_array() == &proposer_pro_tx_hash { + tracing::debug!( + method = "validator_set_update_v1", + "rotation: quorum finished as we hit last member {} of quorum {}. All known quorums are: [{}]. quorum rotation expected", + hex::encode(proposer_pro_tx_hash), + hex::encode(platform_state.current_validator_set_quorum_hash().as_byte_array()), + block_execution_context + .block_platform_state() + .validator_sets() + .keys() + .map(hex::encode).collect::>().join(" | "), + ); + perform_rotation = true; + } + } else { + // the validator set has no members, very weird, but let's just perform a rotation + tracing::debug!( + method = "validator_set_update_v1", + "rotation: validator set has no members", + ); + perform_rotation = true; + } + + // We should also perform a rotation if there are more than one quorum in the system + // and that the new proposer is on the same quorum and the last proposer but is before + // them in the list of proposers. + // This only works if Tenderdash goes through proposers properly + if &platform_state.last_committed_quorum_hash() + == platform_state + .current_validator_set_quorum_hash() + .as_byte_array() + && platform_state.last_committed_block_proposer_pro_tx_hash() > proposer_pro_tx_hash + && platform_state.validator_sets().len() > 1 + { + // 1 - We haven't changed quorums + // 2 - The new proposer is before the old proposer + // 3 - There are more than one quorum in the system + tracing::debug!( + method = "validator_set_update_v1", + "rotation: quorum finished as we hit last an earlier member {} than last block proposer {} for quorum {}. All known quorums are: [{}]. quorum rotation expected", + hex::encode(proposer_pro_tx_hash), + hex::encode(block_execution_context.block_platform_state().last_committed_block_proposer_pro_tx_hash()), + hex::encode(platform_state.current_validator_set_quorum_hash().as_byte_array()), + block_execution_context + .block_platform_state() + .validator_sets() + .keys() + .map(hex::encode).collect::>().join(" | "), + ); + perform_rotation = true; + } + } else { + // we also need to perform a rotation if the validator set is being removed + tracing::debug!( + method = "validator_set_update_v1", + "rotation: new quorums not containing current quorum current {:?}, {}. quorum rotation expected", + block_execution_context + .block_platform_state() + .validator_sets() + .keys() + .map(|quorum_hash| format!("{}", quorum_hash)), + &platform_state.current_validator_set_quorum_hash() + ); + perform_rotation = true; + } + + //todo: (maybe) perform a rotation if quorum health is low + + if perform_rotation { + // get the index of the previous quorum + let mut index = platform_state + .validator_sets() + .get_index_of(&platform_state.current_validator_set_quorum_hash()) + .ok_or(Error::Execution(ExecutionError::CorruptedCachedState( + format!("perform_rotation: current validator set quorum hash {} not in current known validator sets [{}] processing block {}", platform_state.current_validator_set_quorum_hash(), platform_state + .validator_sets().keys().map(|quorum_hash| quorum_hash.to_string()).join(" | "), + platform_state.last_committed_block_height() + 1, + ))))?; + // we should rotate the quorum + let quorum_count = platform_state.validator_sets().len(); + match quorum_count { + 0 => Err(Error::Execution(ExecutionError::CorruptedCachedState( + "no current quorums".to_string(), + ))), + 1 => Ok(None), // no rotation as we are the only quorum + count => { + let start_index = index; + let oldest_quorum_index_we_can_go_to = if count > 10 { + // if we have a lot of quorums (like on testnet and mainnet) + // we shouldn't start using the last ones as they could cycle out + count - 2 + } else { + count + }; + index = (index + 1) % oldest_quorum_index_we_can_go_to; + // We can't just take the next item because it might no longer be in the state + for _i in 0..oldest_quorum_index_we_can_go_to { + let (quorum_hash, _) = platform_state + .validator_sets() + .get_index(index) + .expect("expected next validator set"); + + // We still have it in the state + if let Some(new_validator_set) = block_execution_context + .block_platform_state() + .validator_sets() + .get(quorum_hash) + { + tracing::debug!( + method = "validator_set_update_v1", + "rotation: to new quorum: {} with {} members", + &quorum_hash, + new_validator_set.members().len() + ); + let validator_set_update = new_validator_set.to_update(); + block_execution_context + .block_platform_state_mut() + .set_next_validator_set_quorum_hash(Some(*quorum_hash)); + return Ok(Some(validator_set_update)); + } + index = (index + 1) % oldest_quorum_index_we_can_go_to; + if index == start_index { + break; + } + } + // All quorums changed + if let Some((quorum_hash, new_validator_set)) = block_execution_context + .block_platform_state() + .validator_sets() + .first() + { + tracing::debug!( + method = "validator_set_update_v1", + "rotation: all quorums changed, rotation to new quorum: {}", + &quorum_hash + ); + let validator_set_update = new_validator_set.to_update(); + let new_quorum_hash = *quorum_hash; + block_execution_context + .block_platform_state_mut() + .set_next_validator_set_quorum_hash(Some(new_quorum_hash)); + return Ok(Some(validator_set_update)); + } + tracing::debug!("no new quorums to choose from"); + Ok(None) + } + } + } else { + let current_validator_set = block_execution_context + .block_platform_state() + .current_validator_set()?; + if current_validator_set != platform_state.current_validator_set()? { + // Something changed, for example the IP of a validator changed, or someone's ban status + + tracing::debug!( + method = "validator_set_update_v1", + "validator set update without rotation" + ); + Ok(Some(current_validator_set.to_update())) + } else { + tracing::debug!( + method = "validator_set_update_v1", + "no validator set update", + ); + Ok(None) + } + } + } +} diff --git a/packages/rs-drive-abci/src/execution/platform_events/block_end/validator_set_update/v2/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/block_end/validator_set_update/v2/mod.rs new file mode 100644 index 0000000000..6fc9f86b7d --- /dev/null +++ b/packages/rs-drive-abci/src/execution/platform_events/block_end/validator_set_update/v2/mod.rs @@ -0,0 +1,221 @@ +use crate::error::execution::ExecutionError; +use crate::error::Error; +use crate::execution::types::block_execution_context::v0::{ + BlockExecutionContextV0Getters, BlockExecutionContextV0MutableGetters, +}; +use crate::execution::types::block_execution_context::BlockExecutionContext; +use crate::platform_types::platform::Platform; +use crate::platform_types::platform_state::v0::PlatformStateV0Methods; +use crate::platform_types::platform_state::PlatformState; +use crate::platform_types::validator_set::v0::ValidatorSetV0Getters; +use crate::rpc::core::CoreRPCLike; +use itertools::Itertools; + +use crate::platform_types::validator_set::ValidatorSetExt; +use dpp::dashcore::hashes::Hash; +use tenderdash_abci::proto::abci::ValidatorSetUpdate; + +impl Platform +where + C: CoreRPCLike, +{ + /// We need to validate against the platform state for rotation and not the block execution + /// context state + /// We introduced v1 because the end quorums could be rotating out, giving a small advantage + /// to proposers with a smaller pro_tx_hash + /// To understand this imagine we have proposers + /// `a b c d e f g h i j k` in quorum 24 + /// c is the current proposer + /// Quorum 24 no longer is valid + /// We jump to quorum 0. + /// a b and c just got paid, but the rest did not. + #[inline(always)] + pub(super) fn validator_set_update_v2( + &self, + proposer_pro_tx_hash: [u8; 32], + platform_state: &PlatformState, + block_execution_context: &mut BlockExecutionContext, + ) -> Result, Error> { + let mut perform_rotation = false; + + if let Some(validator_set) = block_execution_context + .block_platform_state() + .validator_sets() + .get(&platform_state.current_validator_set_quorum_hash()) + { + if let Some((last_member_pro_tx_hash, _)) = validator_set.members().last_key_value() { + // we should also perform a rotation if the validator set went through all quorum members + // this means we are at the last member of the quorum + if last_member_pro_tx_hash.as_byte_array() == &proposer_pro_tx_hash { + tracing::debug!( + method = "validator_set_update_v2", + "rotation: quorum finished as we hit last member {} of quorum {}. All known quorums are: [{}]. quorum rotation expected", + hex::encode(proposer_pro_tx_hash), + hex::encode(platform_state.current_validator_set_quorum_hash().as_byte_array()), + block_execution_context + .block_platform_state() + .validator_sets() + .keys() + .map(hex::encode).collect::>().join(" | "), + ); + perform_rotation = true; + } + } else { + // the validator set has no members, very weird, but let's just perform a rotation + tracing::debug!( + method = "validator_set_update_v2", + "rotation: validator set has no members", + ); + perform_rotation = true; + } + + // We should also perform a rotation if there are more than one quorum in the system + // and that the new proposer is on the same quorum and the last proposer but is before + // them in the list of proposers. + // This only works if Tenderdash goes through proposers properly + if &platform_state.last_committed_quorum_hash() + == platform_state + .current_validator_set_quorum_hash() + .as_byte_array() + && platform_state.last_committed_block_proposer_pro_tx_hash() > proposer_pro_tx_hash + && platform_state.validator_sets().len() > 1 + { + // 1 - We haven't changed quorums + // 2 - The new proposer is before the old proposer + // 3 - There are more than one quorum in the system + tracing::debug!( + method = "validator_set_update_v2", + "rotation: quorum finished as we hit last an earlier member {} than last block proposer {} for quorum {}. All known quorums are: [{}]. quorum rotation expected", + hex::encode(proposer_pro_tx_hash), + hex::encode(block_execution_context.block_platform_state().last_committed_block_proposer_pro_tx_hash()), + hex::encode(platform_state.current_validator_set_quorum_hash().as_byte_array()), + block_execution_context + .block_platform_state() + .validator_sets() + .keys() + .map(hex::encode).collect::>().join(" | "), + ); + perform_rotation = true; + } + } else { + // we also need to perform a rotation if the validator set is being removed + tracing::debug!( + method = "validator_set_update_v2", + "rotation: new quorums not containing current quorum current {:?}, {}. quorum rotation expected", + block_execution_context + .block_platform_state() + .validator_sets() + .keys() + .map(|quorum_hash| format!("{}", quorum_hash)), + &platform_state.current_validator_set_quorum_hash() + ); + perform_rotation = true; + } + + //todo: (maybe) perform a rotation if quorum health is low + + if perform_rotation { + // get the index of the previous quorum + let mut index = platform_state + .validator_sets() + .get_index_of(&platform_state.current_validator_set_quorum_hash()) + .ok_or(Error::Execution(ExecutionError::CorruptedCachedState( + format!("perform_rotation: current validator set quorum hash {} not in current known validator sets [{}] processing block {}", platform_state.current_validator_set_quorum_hash(), platform_state + .validator_sets().keys().map(|quorum_hash| quorum_hash.to_string()).join(" | "), + platform_state.last_committed_block_height() + 1, + ))))?; + // we should rotate the quorum + let quorum_count = platform_state.validator_sets().len(); + match quorum_count { + 0 => Err(Error::Execution(ExecutionError::CorruptedCachedState( + "no current quorums".to_string(), + ))), + 1 => Ok(None), // no rotation as we are the only quorum + count => { + let start_index = index; + let oldest_quorum_index_we_can_go_to = if count > 10 { + // if we have a lot of quorums (like on testnet and mainnet) + // we shouldn't start using the last ones as they could cycle out + count - 2 + } else { + count + }; + index = if index + 1 >= oldest_quorum_index_we_can_go_to { + 0 + } else { + index + 1 + }; + // We can't just take the next item because it might no longer be in the state + for _i in 0..oldest_quorum_index_we_can_go_to { + let (quorum_hash, _) = platform_state + .validator_sets() + .get_index(index) + .expect("expected next validator set"); + + // We still have it in the state + if let Some(new_validator_set) = block_execution_context + .block_platform_state() + .validator_sets() + .get(quorum_hash) + { + tracing::debug!( + method = "validator_set_update_v2", + "rotation: to new quorum: {} with {} members", + &quorum_hash, + new_validator_set.members().len() + ); + let validator_set_update = new_validator_set.to_update(); + block_execution_context + .block_platform_state_mut() + .set_next_validator_set_quorum_hash(Some(*quorum_hash)); + return Ok(Some(validator_set_update)); + } + index = (index + 1) % oldest_quorum_index_we_can_go_to; + if index == start_index { + break; + } + } + // All quorums changed + if let Some((quorum_hash, new_validator_set)) = block_execution_context + .block_platform_state() + .validator_sets() + .first() + { + tracing::debug!( + method = "validator_set_update_v2", + "rotation: all quorums changed, rotation to new quorum: {}", + &quorum_hash + ); + let validator_set_update = new_validator_set.to_update(); + let new_quorum_hash = *quorum_hash; + block_execution_context + .block_platform_state_mut() + .set_next_validator_set_quorum_hash(Some(new_quorum_hash)); + return Ok(Some(validator_set_update)); + } + tracing::debug!("no new quorums to choose from"); + Ok(None) + } + } + } else { + let current_validator_set = block_execution_context + .block_platform_state() + .current_validator_set()?; + if current_validator_set != platform_state.current_validator_set()? { + // Something changed, for example the IP of a validator changed, or someone's ban status + + tracing::debug!( + method = "validator_set_update_v2", + "validator set update without rotation" + ); + Ok(Some(current_validator_set.to_update())) + } else { + tracing::debug!( + method = "validator_set_update_v2", + "no validator set update", + ); + Ok(None) + } + } + } +} diff --git a/packages/rs-drive-abci/src/execution/platform_events/block_fee_processing/tests.rs b/packages/rs-drive-abci/src/execution/platform_events/block_fee_processing/tests.rs index fcbf1e8314..1cbac74c74 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/block_fee_processing/tests.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/block_fee_processing/tests.rs @@ -795,7 +795,7 @@ mod refund_tests { platform_state .previous_fee_versions_mut() - .insert(5, platform_version_with_higher_fees.fee_version.clone()); + .insert(5, platform_version_with_higher_fees.fee_version.as_static()); let (mut fee_results, _) = process_state_transitions( &platform, diff --git a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/create_owner_identity/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/create_owner_identity/mod.rs index 042b35c5ca..048ea1266a 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/create_owner_identity/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/create_owner_identity/mod.rs @@ -1,4 +1,5 @@ mod v0; +mod v1; use crate::error::execution::ExecutionError; use crate::error::Error; @@ -38,9 +39,10 @@ where .create_owner_identity { 0 => Self::create_owner_identity_v0(masternode, platform_version), + 1 => Self::create_owner_identity_v1(masternode, platform_version), version => Err(Error::Execution(ExecutionError::UnknownVersionMismatch { method: "create_owner_identity".to_string(), - known_versions: vec![0], + known_versions: vec![0, 1], received: version, })), } diff --git a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/create_owner_identity/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/create_owner_identity/v0/mod.rs index 18028f7a31..176b6d90db 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/create_owner_identity/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/create_owner_identity/v0/mod.rs @@ -25,7 +25,9 @@ where Ok(identity) } - fn get_owner_identifier(masternode: &MasternodeListItem) -> Result { + pub(crate) fn get_owner_identifier( + masternode: &MasternodeListItem, + ) -> Result { let masternode_identifier: [u8; 32] = masternode.pro_tx_hash.into(); Ok(masternode_identifier.into()) } diff --git a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/create_owner_identity/v1/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/create_owner_identity/v1/mod.rs new file mode 100644 index 0000000000..da89aaafc7 --- /dev/null +++ b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/create_owner_identity/v1/mod.rs @@ -0,0 +1,33 @@ +use crate::error::Error; +use crate::platform_types::platform::Platform; +use crate::rpc::core::CoreRPCLike; +use dashcore_rpc::dashcore_rpc_json::MasternodeListItem; +use dpp::identity::accessors::IdentityGettersV0; +use dpp::identity::Identity; +use dpp::version::PlatformVersion; + +impl Platform +where + C: CoreRPCLike, +{ + pub(super) fn create_owner_identity_v1( + masternode: &MasternodeListItem, + platform_version: &PlatformVersion, + ) -> Result { + let owner_identifier = Self::get_owner_identifier(masternode)?; + let mut identity = Identity::create_basic_identity(owner_identifier, platform_version)?; + identity.add_public_keys([ + Self::get_owner_identity_withdrawal_key( + masternode.state.payout_address, + 0, + platform_version, + )?, + Self::get_owner_identity_owner_key( + masternode.state.owner_address, + 1, + platform_version, + )?, + ]); + Ok(identity) + } +} diff --git a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/get_owner_identity_owner_key/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/get_owner_identity_owner_key/mod.rs new file mode 100644 index 0000000000..8b76f02566 --- /dev/null +++ b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/get_owner_identity_owner_key/mod.rs @@ -0,0 +1,45 @@ +mod v0; + +use crate::error::execution::ExecutionError; +use crate::error::Error; +use crate::platform_types::platform::Platform; + +use dpp::identity::{IdentityPublicKey, KeyID}; + +use dpp::version::PlatformVersion; + +impl Platform { + /// Retrieves an identity public key using the provided owner key and key ID. + /// + /// This function derives the identity public key and delegates to a version-specific method depending on the platform version. + /// + /// # Arguments + /// + /// * owner_public_key_address - The public key address of the owner. + /// * key_id - The KeyID for the identity public key. + /// * platform_version - The version of the platform to determine which method to delegate to. + /// + /// # Returns + /// + /// * Result - Returns the derived identity public key if successful. Otherwise, returns an error. + pub(crate) fn get_owner_identity_owner_key( + owner_public_key_address: [u8; 20], + key_id: KeyID, + platform_version: &PlatformVersion, + ) -> Result { + match platform_version + .drive_abci + .methods + .core_based_updates + .masternode_updates + .get_owner_identity_owner_key + { + 0 => Self::get_owner_identity_owner_key_v0(owner_public_key_address, key_id), + version => Err(Error::Execution(ExecutionError::UnknownVersionMismatch { + method: "get_owner_identity_owner_key".to_string(), + known_versions: vec![0], + received: version, + })), + } + } +} diff --git a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/get_owner_identity_owner_key/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/get_owner_identity_owner_key/v0/mod.rs new file mode 100644 index 0000000000..ba099e99ed --- /dev/null +++ b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/get_owner_identity_owner_key/v0/mod.rs @@ -0,0 +1,24 @@ +use crate::error::Error; +use crate::platform_types::platform::Platform; +use dpp::identity::identity_public_key::v0::IdentityPublicKeyV0; +use dpp::identity::{IdentityPublicKey, KeyID, KeyType, Purpose, SecurityLevel}; +use dpp::platform_value::BinaryData; + +impl Platform { + pub(super) fn get_owner_identity_owner_key_v0( + owner_public_key_address: [u8; 20], + key_id: KeyID, + ) -> Result { + Ok(IdentityPublicKeyV0 { + id: key_id, + key_type: KeyType::ECDSA_HASH160, + purpose: Purpose::OWNER, + security_level: SecurityLevel::CRITICAL, + read_only: true, + data: BinaryData::new(owner_public_key_address.to_vec()), + disabled_at: None, + contract_bounds: None, + } + .into()) + } +} diff --git a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/get_owner_identity_key/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/get_owner_identity_withdrawal_key/mod.rs similarity index 100% rename from packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/get_owner_identity_key/mod.rs rename to packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/get_owner_identity_withdrawal_key/mod.rs diff --git a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/get_owner_identity_key/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/get_owner_identity_withdrawal_key/v0/mod.rs similarity index 100% rename from packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/get_owner_identity_key/v0/mod.rs rename to packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/get_owner_identity_withdrawal_key/v0/mod.rs diff --git a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/mod.rs index e3168a64e7..e2a9176d3c 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/mod.rs @@ -4,14 +4,14 @@ mod create_voter_identity; mod disable_identity_keys; mod get_operator_identifier; mod get_operator_identity_keys; -mod get_owner_identity_key; +mod get_owner_identity_owner_key; +mod get_owner_identity_withdrawal_key; mod get_voter_identifier; mod get_voter_identity_key; mod update_masternode_identities; mod update_operator_identity; mod update_owner_withdrawal_address; mod update_voter_identity; - // // // #[cfg(test)] diff --git a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/update_owner_withdrawal_address/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/update_owner_withdrawal_address/mod.rs index f2f5b5c708..1f81d17c0b 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/update_owner_withdrawal_address/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/update_owner_withdrawal_address/mod.rs @@ -11,6 +11,7 @@ use drive::util::batch::DriveOperation; use drive::grovedb::Transaction; mod v0; +mod v1; impl Platform where @@ -61,11 +62,286 @@ where drive_operations, platform_version, ), + 1 => self.update_owner_withdrawal_address_v1( + owner_identifier, + new_withdrawal_address, + block_info, + transaction, + drive_operations, + platform_version, + ), version => Err(Error::Execution(ExecutionError::UnknownVersionMismatch { method: "update_owner_withdrawal_address".to_string(), - known_versions: vec![0], + known_versions: vec![0, 1], received: version, })), } } } + +#[cfg(test)] +mod tests { + use crate::test::helpers::setup::TestPlatformBuilder; + use dpp::block::block_info::BlockInfo; + use dpp::identity::accessors::IdentityGettersV0; + use dpp::identity::identity_public_key::v0::IdentityPublicKeyV0; + use dpp::identity::{Identity, IdentityV0, KeyType, Purpose, SecurityLevel}; + use dpp::platform_value::BinaryData; + use dpp::prelude::{Identifier, IdentityPublicKey}; + use platform_version::version::PlatformVersion; + use rand::prelude::StdRng; + use rand::Rng; + use rand::SeedableRng; + use std::collections::BTreeMap; + + #[test] + fn test_update_withdrawal_address() { + let platform_version = PlatformVersion::latest(); + let platform = TestPlatformBuilder::new() + .build_with_mock_rpc() + .set_genesis_state(); + + let block_info = BlockInfo::default(); + + let mut rng = StdRng::seed_from_u64(5); + + let payout_address: [u8; 20] = rng.gen(); + + let withdrawal_key: IdentityPublicKey = IdentityPublicKeyV0 { + id: 0, + key_type: KeyType::ECDSA_HASH160, + purpose: Purpose::TRANSFER, + security_level: SecurityLevel::CRITICAL, + read_only: true, + data: BinaryData::new(payout_address.to_vec()), + disabled_at: None, + contract_bounds: None, + } + .into(); + + let identity: Identity = IdentityV0 { + id: Identifier::random_with_rng(&mut rng), + public_keys: BTreeMap::from([(0, withdrawal_key.clone())]), + balance: 0, + revision: 0, + } + .into(); + + // We just add this identity to the system first + + platform + .drive + .add_new_identity( + identity.clone(), + true, + &block_info, + true, + None, + platform_version, + ) + .expect("expected to add a new identity"); + + let transaction = platform.drive.grove.start_transaction(); + + let mut drive_operations = vec![]; + + platform + .update_owner_withdrawal_address( + identity.id().to_buffer(), + [0; 20], + &block_info, + &transaction, + &mut drive_operations, + platform_version, + ) + .expect("expected to update owner withdrawal address"); + + platform + .drive + .apply_drive_operations( + drive_operations, + true, + &block_info, + Some(&transaction), + platform_version, + None, + ) + .expect("expected to apply drive operations"); + } + + #[test] + fn test_update_to_same_withdrawal_address() { + let platform_version = PlatformVersion::latest(); + let platform = TestPlatformBuilder::new() + .build_with_mock_rpc() + .set_genesis_state(); + + let block_info = BlockInfo::default(); + + let mut rng = StdRng::seed_from_u64(5); + + let payout_address: [u8; 20] = rng.gen(); + + let withdrawal_key: IdentityPublicKey = IdentityPublicKeyV0 { + id: 0, + key_type: KeyType::ECDSA_HASH160, + purpose: Purpose::TRANSFER, + security_level: SecurityLevel::CRITICAL, + read_only: true, + data: BinaryData::new(payout_address.to_vec()), + disabled_at: None, + contract_bounds: None, + } + .into(); + + let identity: Identity = IdentityV0 { + id: Identifier::random_with_rng(&mut rng), + public_keys: BTreeMap::from([(0, withdrawal_key.clone())]), + balance: 0, + revision: 0, + } + .into(); + + // We just add this identity to the system first + + platform + .drive + .add_new_identity( + identity.clone(), + true, + &block_info, + true, + None, + platform_version, + ) + .expect("expected to add a new identity"); + + let transaction = platform.drive.grove.start_transaction(); + + let mut drive_operations = vec![]; + + platform + .update_owner_withdrawal_address( + identity.id().to_buffer(), + payout_address, + &block_info, + &transaction, + &mut drive_operations, + platform_version, + ) + .expect("expected to update owner withdrawal address"); + + platform + .drive + .apply_drive_operations( + drive_operations, + true, + &block_info, + Some(&transaction), + platform_version, + None, + ) + .expect("expected to apply drive operations"); + } + #[test] + fn test_update_to_previously_disabled_withdrawal_address() { + let platform_version = PlatformVersion::latest(); + let platform = TestPlatformBuilder::new() + .build_with_mock_rpc() + .set_genesis_state(); + + let block_info = BlockInfo::default(); + + let mut rng = StdRng::seed_from_u64(5); + + let payout_address: [u8; 20] = rng.gen(); + + let withdrawal_key: IdentityPublicKey = IdentityPublicKeyV0 { + id: 0, + key_type: KeyType::ECDSA_HASH160, + purpose: Purpose::TRANSFER, + security_level: SecurityLevel::CRITICAL, + read_only: true, + data: BinaryData::new(payout_address.to_vec()), + disabled_at: None, + contract_bounds: None, + } + .into(); + + let identity: Identity = IdentityV0 { + id: Identifier::random_with_rng(&mut rng), + public_keys: BTreeMap::from([(0, withdrawal_key.clone())]), + balance: 0, + revision: 0, + } + .into(); + + // We just add this identity to the system first + + platform + .drive + .add_new_identity( + identity.clone(), + true, + &block_info, + true, + None, + platform_version, + ) + .expect("expected to add a new identity"); + + let transaction = platform.drive.grove.start_transaction(); + + let mut drive_operations = vec![]; + + platform + .update_owner_withdrawal_address( + identity.id().to_buffer(), + [0; 20], + &block_info, + &transaction, + &mut drive_operations, + platform_version, + ) + .expect("expected to update owner withdrawal address"); + + platform + .drive + .apply_drive_operations( + drive_operations, + true, + &block_info, + Some(&transaction), + platform_version, + None, + ) + .expect("expected to apply drive operations"); + + let transaction = platform.drive.grove.start_transaction(); + + let mut drive_operations = vec![]; + + platform + .update_owner_withdrawal_address( + identity.id().to_buffer(), + payout_address, + &block_info, + &transaction, + &mut drive_operations, + platform_version, + ) + .expect("expected to update owner withdrawal address"); + + platform + .drive + .apply_drive_operations( + drive_operations, + true, + &block_info, + Some(&transaction), + platform_version, + None, + ) + .expect("expected to apply drive operations"); + } +} diff --git a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/update_owner_withdrawal_address/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/update_owner_withdrawal_address/v0/mod.rs index 8484f4436d..640a038160 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/update_owner_withdrawal_address/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/update_owner_withdrawal_address/v0/mod.rs @@ -124,270 +124,3 @@ where Ok(()) } } - -#[cfg(test)] -mod tests { - use crate::test::helpers::setup::TestPlatformBuilder; - use dpp::block::block_info::BlockInfo; - use dpp::identity::accessors::IdentityGettersV0; - use dpp::identity::identity_public_key::v0::IdentityPublicKeyV0; - use dpp::identity::{Identity, IdentityV0, KeyType, Purpose, SecurityLevel}; - use dpp::platform_value::BinaryData; - use dpp::prelude::{Identifier, IdentityPublicKey}; - use platform_version::version::PlatformVersion; - use rand::prelude::StdRng; - use rand::Rng; - use rand::SeedableRng; - use std::collections::BTreeMap; - - #[test] - fn test_update_withdrawal_address() { - let platform_version = PlatformVersion::latest(); - let platform = TestPlatformBuilder::new() - .build_with_mock_rpc() - .set_genesis_state(); - - let block_info = BlockInfo::default(); - - let mut rng = StdRng::seed_from_u64(5); - - let payout_address: [u8; 20] = rng.gen(); - - let withdrawal_key: IdentityPublicKey = IdentityPublicKeyV0 { - id: 0, - key_type: KeyType::ECDSA_HASH160, - purpose: Purpose::TRANSFER, - security_level: SecurityLevel::CRITICAL, - read_only: true, - data: BinaryData::new(payout_address.to_vec()), - disabled_at: None, - contract_bounds: None, - } - .into(); - - let identity: Identity = IdentityV0 { - id: Identifier::random_with_rng(&mut rng), - public_keys: BTreeMap::from([(0, withdrawal_key.clone())]), - balance: 0, - revision: 0, - } - .into(); - - // We just add this identity to the system first - - platform - .drive - .add_new_identity( - identity.clone(), - true, - &block_info, - true, - None, - platform_version, - ) - .expect("expected to add a new identity"); - - let transaction = platform.drive.grove.start_transaction(); - - let mut drive_operations = vec![]; - - platform - .update_owner_withdrawal_address( - identity.id().to_buffer(), - [0; 20], - &block_info, - &transaction, - &mut drive_operations, - platform_version, - ) - .expect("expected to update owner withdrawal address"); - - platform - .drive - .apply_drive_operations( - drive_operations, - true, - &block_info, - Some(&transaction), - platform_version, - None, - ) - .expect("expected to apply drive operations"); - } - - #[test] - fn test_update_to_same_withdrawal_address() { - let platform_version = PlatformVersion::latest(); - let platform = TestPlatformBuilder::new() - .build_with_mock_rpc() - .set_genesis_state(); - - let block_info = BlockInfo::default(); - - let mut rng = StdRng::seed_from_u64(5); - - let payout_address: [u8; 20] = rng.gen(); - - let withdrawal_key: IdentityPublicKey = IdentityPublicKeyV0 { - id: 0, - key_type: KeyType::ECDSA_HASH160, - purpose: Purpose::TRANSFER, - security_level: SecurityLevel::CRITICAL, - read_only: true, - data: BinaryData::new(payout_address.to_vec()), - disabled_at: None, - contract_bounds: None, - } - .into(); - - let identity: Identity = IdentityV0 { - id: Identifier::random_with_rng(&mut rng), - public_keys: BTreeMap::from([(0, withdrawal_key.clone())]), - balance: 0, - revision: 0, - } - .into(); - - // We just add this identity to the system first - - platform - .drive - .add_new_identity( - identity.clone(), - true, - &block_info, - true, - None, - platform_version, - ) - .expect("expected to add a new identity"); - - let transaction = platform.drive.grove.start_transaction(); - - let mut drive_operations = vec![]; - - platform - .update_owner_withdrawal_address( - identity.id().to_buffer(), - payout_address, - &block_info, - &transaction, - &mut drive_operations, - platform_version, - ) - .expect("expected to update owner withdrawal address"); - - platform - .drive - .apply_drive_operations( - drive_operations, - true, - &block_info, - Some(&transaction), - platform_version, - None, - ) - .expect("expected to apply drive operations"); - } - #[test] - fn test_update_to_previously_disabled_withdrawal_address() { - let platform_version = PlatformVersion::latest(); - let platform = TestPlatformBuilder::new() - .build_with_mock_rpc() - .set_genesis_state(); - - let block_info = BlockInfo::default(); - - let mut rng = StdRng::seed_from_u64(5); - - let payout_address: [u8; 20] = rng.gen(); - - let withdrawal_key: IdentityPublicKey = IdentityPublicKeyV0 { - id: 0, - key_type: KeyType::ECDSA_HASH160, - purpose: Purpose::TRANSFER, - security_level: SecurityLevel::CRITICAL, - read_only: true, - data: BinaryData::new(payout_address.to_vec()), - disabled_at: None, - contract_bounds: None, - } - .into(); - - let identity: Identity = IdentityV0 { - id: Identifier::random_with_rng(&mut rng), - public_keys: BTreeMap::from([(0, withdrawal_key.clone())]), - balance: 0, - revision: 0, - } - .into(); - - // We just add this identity to the system first - - platform - .drive - .add_new_identity( - identity.clone(), - true, - &block_info, - true, - None, - platform_version, - ) - .expect("expected to add a new identity"); - - let transaction = platform.drive.grove.start_transaction(); - - let mut drive_operations = vec![]; - - platform - .update_owner_withdrawal_address( - identity.id().to_buffer(), - [0; 20], - &block_info, - &transaction, - &mut drive_operations, - platform_version, - ) - .expect("expected to update owner withdrawal address"); - - platform - .drive - .apply_drive_operations( - drive_operations, - true, - &block_info, - Some(&transaction), - platform_version, - None, - ) - .expect("expected to apply drive operations"); - - let transaction = platform.drive.grove.start_transaction(); - - let mut drive_operations = vec![]; - - platform - .update_owner_withdrawal_address( - identity.id().to_buffer(), - payout_address, - &block_info, - &transaction, - &mut drive_operations, - platform_version, - ) - .expect("expected to update owner withdrawal address"); - - platform - .drive - .apply_drive_operations( - drive_operations, - true, - &block_info, - Some(&transaction), - platform_version, - None, - ) - .expect("expected to apply drive operations"); - } -} diff --git a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/update_owner_withdrawal_address/v1/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/update_owner_withdrawal_address/v1/mod.rs new file mode 100644 index 0000000000..40e074193a --- /dev/null +++ b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/update_owner_withdrawal_address/v1/mod.rs @@ -0,0 +1,136 @@ +use crate::error::execution::ExecutionError; +use crate::error::Error; +use crate::platform_types::platform::Platform; + +use crate::rpc::core::CoreRPCLike; +use dpp::block::block_info::BlockInfo; + +use dpp::identity::identity_public_key::accessors::v0::IdentityPublicKeyGettersV0; +use dpp::identity::{KeyID, Purpose}; + +use dpp::version::PlatformVersion; +use drive::drive::identity::key::fetch::{ + IdentityKeysRequest, KeyIDIdentityPublicKeyPairBTreeMap, KeyRequestType, +}; +use drive::grovedb::Transaction; +use drive::util::batch::DriveOperation; +use drive::util::batch::DriveOperation::IdentityOperation; +use drive::util::batch::IdentityOperationType::{ + AddNewKeysToIdentity, DisableIdentityKeys, ReEnableIdentityKeys, +}; +impl Platform +where + C: CoreRPCLike, +{ + /// In this version we change how the new key_id is found, as there might also be an owner key + pub(super) fn update_owner_withdrawal_address_v1( + &self, + owner_identifier: [u8; 32], + new_withdrawal_address: [u8; 20], + block_info: &BlockInfo, + transaction: &Transaction, + drive_operations: &mut Vec, + platform_version: &PlatformVersion, + ) -> Result<(), Error> { + let key_request = IdentityKeysRequest { + identity_id: owner_identifier, + request_type: KeyRequestType::AllKeys, + limit: None, + offset: None, + }; + + let old_withdrawal_identity_keys = self + .drive + .fetch_identity_keys::( + key_request, + Some(transaction), + platform_version, + )?; + + if old_withdrawal_identity_keys.is_empty() { + return Err(Error::Execution(ExecutionError::DriveMissingData( + "expected masternode owner identity to be in state".to_string(), + ))); + } + + let key_ids_to_disable: Vec = old_withdrawal_identity_keys + .iter() + .filter_map(|(key_id, key)| { + if key.disabled_at().is_some() + || key.data().as_slice() == &new_withdrawal_address + || key.purpose() == Purpose::OWNER + { + // We should not disable the owner key + // Also no need to disable withdrawal keys again + // Or if we are adding the same key we already had + None + } else { + Some(*key_id) + } + }) + .collect(); + + if !key_ids_to_disable.is_empty() { + tracing::trace!( + identity_id = ?owner_identifier, + keys_ids = ?key_ids_to_disable, + disable_at = ?block_info.time_ms, + method = "update_owner_withdrawal_address_v1", + "disable old withdrawal keys in owner identity" + ); + + drive_operations.push(IdentityOperation(DisableIdentityKeys { + identity_id: owner_identifier, + keys_ids: key_ids_to_disable, + })); + } + + if let Some((key_id, previously_disabled_old_key)) = old_withdrawal_identity_keys + .iter() + .find(|(_, key)| key.data().as_slice() == new_withdrawal_address) + { + // there might be a situation where we should do nothing as well + if previously_disabled_old_key.is_disabled() { + // We need to re-enable the withdrawal key + tracing::trace!( + identity_id = ?owner_identifier, + withdrawal_key = ?previously_disabled_old_key, + method = "update_owner_withdrawal_address_v0", + "re-enabled withdrawal key to owner identity" + ); + + drive_operations.push(IdentityOperation(ReEnableIdentityKeys { + identity_id: owner_identifier, + keys_ids: vec![*key_id], + })); + } + } else { + let last_key_id = *old_withdrawal_identity_keys + .keys() + .max() + .expect("there must be keys, we already checked"); + + // add the new key + let new_owner_withdrawal_key = Self::get_owner_identity_withdrawal_key( + new_withdrawal_address, + last_key_id + 1, + platform_version, + )?; + + tracing::trace!( + identity_id = ?owner_identifier, + withdrawal_key = ?new_owner_withdrawal_key, + method = "update_owner_withdrawal_address_v1", + "add new withdrawal key to owner identity" + ); + + drive_operations.push(IdentityOperation(AddNewKeysToIdentity { + identity_id: owner_identifier, + unique_keys_to_add: vec![], + non_unique_keys_to_add: vec![new_owner_withdrawal_key], + })); + } + + Ok(()) + } +} diff --git a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_quorum_info/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_quorum_info/v0/mod.rs index bcc65582d7..5ca6ce4070 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_quorum_info/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_quorum_info/v0/mod.rs @@ -7,7 +7,9 @@ use dashcore_rpc::json::{ExtendedQuorumListResult, QuorumType}; use std::collections::BTreeMap; use std::fmt::Display; -use crate::platform_types::validator_set::v0::{ValidatorSetV0, ValidatorSetV0Getters}; +use crate::platform_types::validator_set::v0::{ + ValidatorSetMethodsV0, ValidatorSetV0, ValidatorSetV0Getters, +}; use crate::platform_types::validator_set::ValidatorSet; use crate::rpc::core::CoreRPCLike; diff --git a/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/mod.rs index b2e1e826d4..588f34d169 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/mod.rs @@ -1,2 +1,3 @@ mod check_for_desired_protocol_upgrade; +mod perform_events_on_first_block_of_protocol_change; mod upgrade_protocol_version; diff --git a/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/perform_events_on_first_block_of_protocol_change/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/perform_events_on_first_block_of_protocol_change/mod.rs new file mode 100644 index 0000000000..56c1e17c6a --- /dev/null +++ b/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/perform_events_on_first_block_of_protocol_change/mod.rs @@ -0,0 +1,72 @@ +mod v0; + +use crate::error::execution::ExecutionError; +use crate::error::Error; +use crate::platform_types::platform::Platform; +use crate::platform_types::platform_state::PlatformState; +use dpp::block::block_info::BlockInfo; +use dpp::version::PlatformVersion; +use dpp::version::ProtocolVersion; +use drive::grovedb::Transaction; + +impl Platform { + /// Executes protocol-specific events on the first block after a protocol version change. + /// + /// This function is triggered when there is a protocol version upgrade detected in the network. + /// It checks if the current protocol version has transitioned from an earlier version to version 4, + /// and if so, performs the necessary setup or migration tasks associated with version 4. + /// + /// Currently, the function handles the transition to version 4 by initializing new structures + /// or states required for the new protocol version. + /// + /// # Parameters + /// + /// * `transaction`: A reference to the transaction context in which the changes should be applied. + /// * `previous_protocol_version`: The protocol version prior to the upgrade. + /// * `platform_version`: The current platform version containing the updated protocol version and relevant configuration details. + /// + /// # Returns + /// + /// * `Ok(())`: If all events related to the protocol change were successfully executed. + /// * `Err(Error)`: If there was an issue executing the protocol-specific events. + /// + /// # Versioning + /// + /// This function uses the `platform_version` parameter to determine which version-specific implementation + /// of the protocol change events should be executed: + /// + /// - If the version is `0`, it calls the `perform_events_on_first_block_of_protocol_change_v0` function, + /// which contains the logic for version `0`. + /// - If no version is specified (`None`), the function does nothing and returns `Ok(())`. + /// - If a different version is specified, it returns an error indicating an unknown version mismatch. + /// + pub fn perform_events_on_first_block_of_protocol_change( + &self, + platform_state: &PlatformState, + block_info: &BlockInfo, + transaction: &Transaction, + previous_protocol_version: ProtocolVersion, + platform_version: &PlatformVersion, + ) -> Result<(), Error> { + match platform_version + .drive_abci + .methods + .protocol_upgrade + .perform_events_on_first_block_of_protocol_change + { + Some(0) => self.perform_events_on_first_block_of_protocol_change_v0( + platform_state, + block_info, + transaction, + previous_protocol_version, + platform_version, + ), + None => return Ok(()), + Some(version) => Err(Error::Execution(ExecutionError::UnknownVersionMismatch { + method: "perform_events_on_first_block_of_protocol_change".to_string(), + known_versions: vec![0], + received: version, + })), + } + } +} diff --git a/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/perform_events_on_first_block_of_protocol_change/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/perform_events_on_first_block_of_protocol_change/v0/mod.rs new file mode 100644 index 0000000000..f5cf202665 --- /dev/null +++ b/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/perform_events_on_first_block_of_protocol_change/v0/mod.rs @@ -0,0 +1,151 @@ +use crate::error::Error; +use crate::platform_types::platform::Platform; +use crate::platform_types::platform_state::v0::PlatformStateV0Methods; +use crate::platform_types::platform_state::PlatformState; +use dpp::block::block_info::BlockInfo; +use dpp::dashcore::hashes::Hash; +use dpp::version::PlatformVersion; +use dpp::version::ProtocolVersion; +use drive::drive::identity::key::fetch::{ + IdentityKeysRequest, KeyIDIdentityPublicKeyPairBTreeMap, KeyRequestType, +}; +use drive::drive::identity::withdrawals::paths::{ + get_withdrawal_root_path, WITHDRAWAL_TRANSACTIONS_BROADCASTED_KEY, + WITHDRAWAL_TRANSACTIONS_SUM_AMOUNT_TREE_KEY, +}; +use drive::grovedb::{Element, Transaction}; + +impl Platform { + /// Executes protocol-specific events on the first block after a protocol version change. + /// + /// This function is triggered when there is a protocol version upgrade detected in the network. + /// It checks if the current protocol version has transitioned from an earlier version to version 4, + /// and if so, performs the necessary setup or migration tasks associated with version 4. + /// + /// Currently, the function handles the transition to version 4 by initializing new structures + /// or states required for the new protocol version. + /// + /// # Parameters + /// + /// * `transaction`: A reference to the transaction context in which the changes should be applied. + /// * `previous_protocol_version`: The protocol version prior to the upgrade. + /// * `platform_version`: The current platform version containing the updated protocol version and relevant configuration details. + /// + /// # Returns + /// + /// * `Ok(())`: If all events related to the protocol change were successfully executed. + /// * `Err(Error)`: If there was an issue executing the protocol-specific events. + pub(super) fn perform_events_on_first_block_of_protocol_change_v0( + &self, + platform_state: &PlatformState, + block_info: &BlockInfo, + transaction: &Transaction, + previous_protocol_version: ProtocolVersion, + platform_version: &PlatformVersion, + ) -> Result<(), Error> { + if previous_protocol_version < 4 && platform_version.protocol_version >= 4 { + self.transition_to_version_4( + platform_state, + block_info, + transaction, + platform_version, + )?; + } + + Ok(()) + } + + /// Initializes an empty sum tree for withdrawal transactions required for protocol version 4. + /// + /// This function is called during the transition to protocol version 4 to set up + /// an empty sum tree at the specified path if it does not already exist. + /// + /// # Parameters + /// + /// * `transaction`: A reference to the transaction context in which the changes should be applied. + /// * `platform_version`: The current platform version containing the updated protocol version and relevant configuration details. + /// + /// # Returns + /// + /// * `Ok(())`: If the transition to version 4 was successful. + /// * `Err(Error)`: If there was an issue creating or updating the necessary data structures. + fn transition_to_version_4( + &self, + platform_state: &PlatformState, + block_info: &BlockInfo, + transaction: &Transaction, + platform_version: &PlatformVersion, + ) -> Result<(), Error> { + // We are adding the withdrawal transactions sum amount tree + let path = get_withdrawal_root_path(); + self.drive.grove_insert_if_not_exists( + (&path).into(), + &WITHDRAWAL_TRANSACTIONS_SUM_AMOUNT_TREE_KEY, + Element::empty_sum_tree(), + Some(transaction), + None, + &platform_version.drive, + )?; + // We are adding a tree to store broadcasted transactions that might expire + self.drive.grove_insert_if_not_exists( + (&path).into(), + &WITHDRAWAL_TRANSACTIONS_BROADCASTED_KEY, + Element::empty_tree(), + Some(transaction), + None, + &platform_version.drive, + )?; + // We need to add all masternode owner keys + // This is because owner identities only had a withdrawal key + // But no owner key + for masternode in platform_state.full_masternode_list().values() { + let masternode_id = masternode.pro_tx_hash.to_byte_array(); + let key_request = IdentityKeysRequest { + identity_id: masternode_id, + request_type: KeyRequestType::AllKeys, + limit: None, + offset: None, + }; + + let old_owner_identity_keys = self + .drive + .fetch_identity_keys::( + key_request, + Some(transaction), + platform_version, + )?; + + if old_owner_identity_keys.is_empty() { + continue; + } + + let last_key_id = *old_owner_identity_keys + .keys() + .max() + .expect("there must be keys, we already checked"); + + let new_owner_key = Self::get_owner_identity_owner_key( + masternode.state.owner_address, + last_key_id + 1, + platform_version, + )?; + + tracing::trace!( + identity_id = ?masternode_id, + withdrawal_key = ?new_owner_key, + method = "transition_to_version_4", + "add new owner key to owner identity" + ); + + self.drive.add_new_non_unique_keys_to_identity( + masternode_id, + vec![new_owner_key], + block_info, + true, + Some(transaction), + platform_version, + )?; + } + Ok(()) + } +} diff --git a/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/upgrade_protocol_version/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/upgrade_protocol_version/v0/mod.rs index 79b6ce27cd..d8dd13e441 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/upgrade_protocol_version/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/upgrade_protocol_version/v0/mod.rs @@ -99,17 +99,19 @@ impl Platform { // If cached_fee_version is non-empty if let Some((_, last_fee_version)) = previous_fee_versions_map.iter().last() { // Insert the new (epoch_index, fee_version) only if the new fee_version is different from the last_fee_version. - if *last_fee_version != platform_version.fee_version { + if last_fee_version.fee_version_number + != platform_version.fee_version.fee_version_number + { previous_fee_versions_map.insert( epoch_info.current_epoch_index(), - platform_version.fee_version.clone(), + &platform_version.fee_version, ); } // In case of empty cached_fee_version, insert the new (epoch_index, fee_version) } else { previous_fee_versions_map.insert( epoch_info.current_epoch_index(), - platform_version.fee_version.clone(), + &platform_version.fee_version, ); } diff --git a/packages/rs-drive-abci/src/execution/platform_events/withdrawals/append_signatures_and_broadcast_withdrawal_transactions/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/withdrawals/append_signatures_and_broadcast_withdrawal_transactions/mod.rs index de42c73bda..3601bd9640 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/withdrawals/append_signatures_and_broadcast_withdrawal_transactions/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/withdrawals/append_signatures_and_broadcast_withdrawal_transactions/mod.rs @@ -1,10 +1,11 @@ use crate::error::execution::ExecutionError; use crate::error::Error; use crate::platform_types::platform::Platform; -use crate::platform_types::withdrawal::unsigned_withdrawal_txs::v0::UnsignedWithdrawalTxs; use crate::rpc::core::CoreRPCLike; -use dpp::dashcore::bls_sig_utils::BLSSignature; +use dpp::dashcore::Transaction; use dpp::version::PlatformVersion; +use std::collections::BTreeMap; +use tenderdash_abci::proto::types::VoteExtension; mod v0; @@ -15,8 +16,7 @@ where /// Appends signatures to unsigned withdrawal transactions and broadcast them to Core pub(in crate::execution) fn append_signatures_and_broadcast_withdrawal_transactions( &self, - unsigned_withdrawal_transactions: UnsignedWithdrawalTxs, - signatures: Vec, + withdrawal_transactions_with_vote_extensions: BTreeMap<&Transaction, &VoteExtension>, platform_version: &PlatformVersion, ) -> Result<(), Error> { match platform_version @@ -26,8 +26,7 @@ where .append_signatures_and_broadcast_withdrawal_transactions { 0 => self.append_signatures_and_broadcast_withdrawal_transactions_v0( - unsigned_withdrawal_transactions, - signatures, + withdrawal_transactions_with_vote_extensions, ), version => Err(Error::Execution(ExecutionError::UnknownVersionMismatch { method: "append_signatures_and_broadcast_withdrawal_transactions".to_string(), diff --git a/packages/rs-drive-abci/src/execution/platform_events/withdrawals/append_signatures_and_broadcast_withdrawal_transactions/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/withdrawals/append_signatures_and_broadcast_withdrawal_transactions/v0/mod.rs index 22a3c4d555..1f6cacbc2b 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/withdrawals/append_signatures_and_broadcast_withdrawal_transactions/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/withdrawals/append_signatures_and_broadcast_withdrawal_transactions/v0/mod.rs @@ -1,7 +1,6 @@ use crate::error::execution::ExecutionError; use crate::error::Error; use crate::platform_types::platform::Platform; -use crate::platform_types::withdrawal::unsigned_withdrawal_txs::v0::UnsignedWithdrawalTxs; use crate::rpc::core::{ CoreRPCLike, CORE_RPC_ERROR_ASSET_UNLOCK_EXPIRED, CORE_RPC_ERROR_ASSET_UNLOCK_NO_ACTIVE_QUORUM, CORE_RPC_TX_ALREADY_IN_CHAIN, @@ -10,12 +9,14 @@ use dashcore_rpc::jsonrpc; use dashcore_rpc::Error as CoreRPCError; use dpp::dashcore::bls_sig_utils::BLSSignature; use dpp::dashcore::transaction::special_transaction::TransactionPayload::AssetUnlockPayloadType; -use dpp::dashcore::{consensus, Txid}; +use dpp::dashcore::{consensus, Transaction, Txid}; +use std::collections::BTreeMap; use std::fs::{self, File}; use std::io::Write; use std::path::Path; use std::time::{SystemTime, UNIX_EPOCH}; +use tenderdash_abci::proto::types::VoteExtension; impl Platform where @@ -23,79 +24,98 @@ where { pub(super) fn append_signatures_and_broadcast_withdrawal_transactions_v0( &self, - unsigned_withdrawal_transactions: UnsignedWithdrawalTxs, - signatures: Vec, + withdrawal_transactions_with_vote_extensions: BTreeMap<&Transaction, &VoteExtension>, ) -> Result<(), Error> { - if unsigned_withdrawal_transactions.is_empty() { + if withdrawal_transactions_with_vote_extensions.is_empty() { return Ok(()); } - if unsigned_withdrawal_transactions.len() != signatures.len() { - return Err(Error::Execution(ExecutionError::CorruptedCodeExecution( - "number of signatures must match number of withdrawal transactions", - ))); - } - tracing::debug!( - "Broadcasting {} withdrawal transactions", - unsigned_withdrawal_transactions.len(), + "Broadcasting {} asset unlock transactions", + withdrawal_transactions_with_vote_extensions.len(), ); let mut transaction_submission_failures = vec![]; - for (mut transaction, signature) in - unsigned_withdrawal_transactions.into_iter().zip(signatures) - { + for (transaction_ref, vote_extension) in withdrawal_transactions_with_vote_extensions { + // Clone the transaction to get an owned, mutable transaction + let mut transaction = transaction_ref.clone(); + + // Extract the signature from the vote extension + let signature_bytes: [u8; 96] = vote_extension + .signature + .as_slice() + .try_into() + .map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "invalid votes extension signature size", + )) + })?; + + let signature = BLSSignature::from(signature_bytes); + + // Modify the transaction's payload let Some(AssetUnlockPayloadType(mut payload)) = transaction.special_transaction_payload else { - return Err(Error::Execution(ExecutionError::CorruptedCodeExecution( - "withdrawal transaction payload must be AssetUnlockPayloadType", + return Err(Error::Execution(ExecutionError::CorruptedCachedState( + "withdrawal transaction payload must be AssetUnlockPayloadType".to_string(), ))); }; + // Assign the quorum signature payload.quorum_sig = signature; - let index = payload.base.index; + let tx_index = payload.base.index; + // Assign the modified payload back to the transaction transaction.special_transaction_payload = Some(AssetUnlockPayloadType(payload)); + // Serialize the transaction let tx_bytes = consensus::serialize(&transaction); - // TODO: We need to broadcast all or none of the transactions (in case of error) - // will be fixed in upcoming PR + // Send the transaction match self.core_rpc.send_raw_transaction(&tx_bytes) { Ok(_) => { tracing::debug!( tx_id = transaction.txid().to_hex(), - index, - "Successfully broadcasted withdrawal transaction with index {}", - index + tx_index, + "Successfully broadcasted asset unlock transaction with index {tx_index}", ); } - // Ignore errors that can happen during blockchain synchronization. - // They will be logged with dashcore_rpc + // Handle specific errors + Err(CoreRPCError::JsonRpc(jsonrpc::error::Error::Rpc(e))) + if e.code == CORE_RPC_TX_ALREADY_IN_CHAIN => + { + // Transaction already in chain; no action needed + } Err(CoreRPCError::JsonRpc(jsonrpc::error::Error::Rpc(e))) - if e.code == CORE_RPC_TX_ALREADY_IN_CHAIN - || e.message == CORE_RPC_ERROR_ASSET_UNLOCK_NO_ACTIVE_QUORUM + if e.message == CORE_RPC_ERROR_ASSET_UNLOCK_NO_ACTIVE_QUORUM || e.message == CORE_RPC_ERROR_ASSET_UNLOCK_EXPIRED => { - // These will never work again + tracing::debug!( + tx_id = transaction.txid().to_string(), + tx_index, + error = ?e, + "Asset unlock transaction with index {tx_index} is expired or has no active quorum: {}", + e.message + ); + transaction_submission_failures.push((transaction.txid(), tx_bytes)); } - // Errors that can happen if we created invalid tx or Core isn't responding + // Handle other errors Err(e) => { tracing::warn!( tx_id = transaction.txid().to_string(), - index, - "Failed to broadcast asset unlock transaction {}: {}", - index, + tx_index, + "Failed to broadcast asset unlock transaction with index {tx_index}: {}", e ); - // These errors might allow the state transition to be broadcast in the future + // Collect failed transactions for potential future retries transaction_submission_failures.push((transaction.txid(), tx_bytes)); } } } + // Store transaction submission failures if let Some(ref rejections_path) = self.config.rejections_path { store_transaction_failures(transaction_submission_failures, rejections_path) .map_err(|e| Error::Execution(e.into()))?; diff --git a/packages/rs-drive-abci/src/execution/platform_events/withdrawals/build_untied_withdrawal_transactions_from_documents/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/withdrawals/build_untied_withdrawal_transactions_from_documents/mod.rs index e4cd110298..fb6717b7b8 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/withdrawals/build_untied_withdrawal_transactions_from_documents/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/withdrawals/build_untied_withdrawal_transactions_from_documents/mod.rs @@ -2,13 +2,11 @@ use crate::error::execution::ExecutionError; use crate::error::Error; use crate::platform_types::platform::Platform; use crate::rpc::core::CoreRPCLike; +use dpp::block::block_info::BlockInfo; use dpp::document::Document; -use dpp::identifier::Identifier; +use dpp::fee::Credits; use dpp::version::PlatformVersion; -use drive::drive::identity::withdrawals::{ - WithdrawalTransactionIndex, WithdrawalTransactionIndexAndBytes, -}; -use std::collections::HashMap; +use dpp::withdrawal::{WithdrawalTransactionIndex, WithdrawalTransactionIndexAndBytes}; mod v0; @@ -16,35 +14,41 @@ impl Platform where C: CoreRPCLike, { - /// Builds a list of Core transactions from withdrawal documents. This function is a version handler that - /// directs to specific version implementations of the `build_withdrawal_transactions_from_documents` function. + /// Builds a list of withdrawal transactions from the provided withdrawal documents. + /// Each withdrawal document is converted into a Core transaction, starting from the specified index. + /// The function encodes the transaction and updates the document with the transaction index, status, + /// updated time, and revision. /// /// # Arguments /// - /// * `documents` - A slice of `Document`. - /// * `drive_operation_types` - A mutable reference to `Vec`. - /// * `transaction` - A `TransactionArg` reference. - /// * `platform_version` - A `PlatformVersion` reference that dictates which version of - /// the method to call. + /// * `documents` - A mutable reference to a vector of `Document` representing the withdrawal requests. + /// * `start_index` - The starting index for the transaction, of type `WithdrawalTransactionIndex`. + /// * `block_info` - A reference to the `BlockInfo`, which provides the current block's timestamp. + /// * `platform_version` - A reference to the `PlatformVersion` that specifies the version of the platform being used. /// /// # Returns /// - /// * `Result, Error>` - Returns a HashMap containing withdrawal transactions if found, otherwise returns an `Error`. + /// * `Result, Error>` - On success, returns a vector of tuples containing the + /// transaction index and the encoded transaction bytes. On failure, returns an `Error`. pub(in crate::execution::platform_events::withdrawals) fn build_untied_withdrawal_transactions_from_documents( &self, - documents: &[Document], + documents: &mut Vec, start_index: WithdrawalTransactionIndex, + block_info: &BlockInfo, platform_version: &PlatformVersion, - ) -> Result, Error> { + ) -> Result<(Vec, Credits), Error> { match platform_version .drive_abci .methods .withdrawals .build_untied_withdrawal_transactions_from_documents { - 0 => { - self.build_untied_withdrawal_transactions_from_documents_v0(documents, start_index) - } + 0 => self.build_untied_withdrawal_transactions_from_documents_v0( + documents, + start_index, + block_info, + platform_version, + ), version => Err(Error::Execution(ExecutionError::UnknownVersionMismatch { method: "build_untied_withdrawal_transactions_from_documents".to_string(), known_versions: vec![0], diff --git a/packages/rs-drive-abci/src/execution/platform_events/withdrawals/build_untied_withdrawal_transactions_from_documents/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/withdrawals/build_untied_withdrawal_transactions_from_documents/v0/mod.rs index ea63771c63..13da6e72f1 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/withdrawals/build_untied_withdrawal_transactions_from_documents/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/withdrawals/build_untied_withdrawal_transactions_from_documents/v0/mod.rs @@ -1,28 +1,19 @@ -use std::collections::HashMap; - -use dashcore_rpc::dashcore::{ - blockdata::transaction::special_transaction::asset_unlock::{ - qualified_asset_unlock::ASSET_UNLOCK_TX_SIZE, - unqualified_asset_unlock::{AssetUnlockBasePayload, AssetUnlockBaseTransactionInfo}, - }, - consensus::Encodable, - ScriptBuf, TxOut, -}; -use dpp::document::{Document, DocumentV0Getters}; +use dashcore_rpc::dashcore::consensus::Encodable; +use dpp::block::block_info::BlockInfo; +use dpp::data_contracts::withdrawals_contract; +use dpp::data_contracts::withdrawals_contract::v1::document_types::withdrawal; +use dpp::document::document_methods::DocumentMethodsV0; +use dpp::document::{Document, DocumentV0Getters, DocumentV0Setters}; +use dpp::fee::Credits; use dpp::platform_value::btreemap_extensions::BTreeValueMapHelper; -use dpp::system_data_contracts::withdrawals_contract::v1::document_types::withdrawal; - -use drive::dpp::identifier::Identifier; -use drive::dpp::identity::convert_credits_to_duffs; -use drive::drive::identity::withdrawals::{ - WithdrawalTransactionIndex, WithdrawalTransactionIndexAndBytes, -}; +use dpp::withdrawal::{WithdrawalTransactionIndex, WithdrawalTransactionIndexAndBytes}; use crate::{ error::{execution::ExecutionError, Error}, platform_types::platform::Platform, rpc::core::CoreRPCLike, }; +use dpp::version::PlatformVersion; impl Platform where @@ -31,101 +22,91 @@ where /// Build list of Core transactions from withdrawal documents pub(super) fn build_untied_withdrawal_transactions_from_documents_v0( &self, - documents: &[Document], + documents: &mut Vec, start_index: WithdrawalTransactionIndex, - ) -> Result, Error> { - let mut withdrawals: HashMap = - HashMap::new(); - - for (i, document) in documents.iter().enumerate() { - let output_script_bytes = document - .properties() - .get_bytes(withdrawal::properties::OUTPUT_SCRIPT) - .map_err(|_| { - Error::Execution(ExecutionError::CorruptedCodeExecution( - "Can't get outputScript from withdrawal document", - )) - })?; - - let amount = document - .properties() - .get_integer(withdrawal::properties::AMOUNT) - .map_err(|_| { - Error::Execution(ExecutionError::CorruptedCodeExecution( - "Can't get amount from withdrawal document", + block_info: &BlockInfo, + platform_version: &PlatformVersion, + ) -> Result<(Vec, Credits), Error> { + documents.iter_mut().enumerate().try_fold( + (Vec::new(), 0u64), // Start with an empty vector for transactions and 0 for total amount. + |(mut transactions, mut total_amount), (i, document)| { + // Calculate the transaction index. + let transaction_index = start_index + i as WithdrawalTransactionIndex; + + // Convert the document into the withdrawal transaction information. + let withdrawal_transaction = document.try_into_asset_unlock_base_transaction_info( + transaction_index, + platform_version, + )?; + + // Create a buffer to hold the encoded transaction. + let mut transaction_buffer: Vec = vec![]; + + // Get the withdrawal amount from the document properties. + let amount: u64 = document + .properties() + .get_integer(withdrawal::properties::AMOUNT)?; + + // Add the amount to the total, checking for overflow. + total_amount = total_amount.checked_add(amount).ok_or_else(|| { + Error::Execution(ExecutionError::Overflow( + "Overflow while calculating total amount", )) })?; - let core_fee_per_byte: u32 = document - .properties() - .get_integer(withdrawal::properties::CORE_FEE_PER_BYTE) - .map_err(|_| { - Error::Execution(ExecutionError::CorruptedCodeExecution( - "Can't get coreFeePerByte from withdrawal document", + // Consensus encode the withdrawal transaction into the buffer. + withdrawal_transaction + .consensus_encode(&mut transaction_buffer) + .map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't consensus encode a withdrawal transaction", + )) + })?; + + // Update the document properties. + document.set_u64(withdrawal::properties::TRANSACTION_INDEX, transaction_index); + document.set_u8( + withdrawal::properties::STATUS, + withdrawals_contract::WithdrawalStatus::POOLED as u8, + ); + document.set_updated_at(Some(block_info.time_ms)); + + // Increment the document revision, handle error if it fails. + document.increment_revision().map_err(|_| { + Error::Execution(ExecutionError::Overflow( + "Overflow when adding to document revision for withdrawals", )) })?; - let output_script = ScriptBuf::from_bytes(output_script_bytes); - - let tx_out = TxOut { - value: convert_credits_to_duffs(amount)?, - script_pubkey: output_script, - }; - - let transaction_index = start_index + i as WithdrawalTransactionIndex; - - let withdrawal_transaction = AssetUnlockBaseTransactionInfo { - version: 1, - lock_time: 0, - output: vec![tx_out], - base_payload: AssetUnlockBasePayload { - version: 1, - index: transaction_index, - fee: ASSET_UNLOCK_TX_SIZE as u32 * core_fee_per_byte, - }, - }; - - let mut transaction_buffer: Vec = vec![]; - - withdrawal_transaction - .consensus_encode(&mut transaction_buffer) - .map_err(|_| { - Error::Execution(ExecutionError::CorruptedCodeExecution( - "Can't consensus encode a withdrawal transaction", - )) - })?; - - withdrawals.insert(document.id(), (transaction_index, transaction_buffer)); - } + // Add the transaction index and encoded transaction to the result. + transactions.push((transaction_index, transaction_buffer)); - Ok(withdrawals) + // Return the updated accumulator. + Ok((transactions, total_amount)) + }, + ) } } #[cfg(test)] mod tests { - - use dpp::withdrawal::Pooling; - use dpp::{ - data_contracts::withdrawals_contract, tests::fixtures::get_withdrawal_document_fixture, - }; + use dpp::tests::fixtures::get_withdrawal_document_fixture; use drive::util::test_helpers::setup::setup_document; mod build_withdrawal_transactions_from_documents { + use super::*; + use crate::test::helpers::setup::TestPlatformBuilder; + use dpp::block::block_info::BlockInfo; use dpp::data_contract::accessors::v0::DataContractV0Getters; use dpp::data_contracts::withdrawals_contract::v1::document_types::withdrawal; use dpp::identity::core_script::CoreScript; use dpp::platform_value::platform_value; use dpp::prelude::Identifier; + use dpp::system_data_contracts::withdrawals_contract::WithdrawalStatus; use dpp::system_data_contracts::{load_system_data_contract, SystemDataContract}; use dpp::version::PlatformVersion; - use drive::drive::identity::withdrawals::WithdrawalTransactionIndexAndBytes; + use dpp::withdrawal::Pooling; use drive::util::test_helpers::setup::setup_system_data_contract; - use itertools::Itertools; - - use crate::test::helpers::setup::TestPlatformBuilder; - - use super::*; #[test] fn test_build() { @@ -152,7 +133,7 @@ mod tests { "coreFeePerByte": 1u32, "pooling": Pooling::Never as u8, "outputScript": CoreScript::from_bytes((0..23).collect::>()), - "status": withdrawals_contract::WithdrawalStatus::POOLED as u8, + "status": WithdrawalStatus::POOLED as u8, "transactionIndex": 1u64, }), None, @@ -180,7 +161,7 @@ mod tests { "coreFeePerByte": 1u32, "pooling": Pooling::Never as u8, "outputScript": CoreScript::from_bytes((0..23).collect::>()), - "status": withdrawals_contract::WithdrawalStatus::POOLED as u8, + "status": WithdrawalStatus::POOLED as u8, "transactionIndex": 2u64, }), None, @@ -196,18 +177,21 @@ mod tests { Some(&transaction), ); - let documents = vec![document_1, document_2]; + let mut documents = vec![document_1, document_2]; - let transactions = platform - .build_untied_withdrawal_transactions_from_documents_v0(&documents, 50) + let block_info = BlockInfo::default_with_time(50); + + let (transactions, credits) = platform + .build_untied_withdrawal_transactions_from_documents_v0( + &mut documents, + 50, + &block_info, + platform_version, + ) .expect("to build transactions from documents"); assert_eq!( - transactions - .values() - .cloned() - .sorted() - .collect::>(), + transactions, vec![ ( 50, @@ -226,10 +210,9 @@ mod tests { ], ), ] - .into_iter() - .sorted() - .collect::>(), ); + + assert_eq!(credits, 2000); } } } diff --git a/packages/rs-drive-abci/src/execution/platform_events/withdrawals/cleanup_expired_locks_of_withdrawal_amounts/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/withdrawals/cleanup_expired_locks_of_withdrawal_amounts/mod.rs new file mode 100644 index 0000000000..837ffd1bf9 --- /dev/null +++ b/packages/rs-drive-abci/src/execution/platform_events/withdrawals/cleanup_expired_locks_of_withdrawal_amounts/mod.rs @@ -0,0 +1,58 @@ +use crate::error::execution::ExecutionError; +use crate::error::Error; +use crate::platform_types::platform::Platform; + +use crate::rpc::core::CoreRPCLike; +use dpp::block::block_info::BlockInfo; + +use dpp::version::PlatformVersion; +use drive::grovedb::Transaction; + +mod v0; + +impl Platform +where + C: CoreRPCLike, +{ + /// Cleans up expired locks of withdrawal amounts based on the protocol version. + /// + /// This function determines the appropriate versioned function to call for cleaning up expired + /// withdrawal locks according to the provided platform version. It deletes expired withdrawal locks + /// that have surpassed their allowed time limit, ensuring that only valid withdrawal entries remain. + /// + /// # Parameters + /// * `block_info`: Information about the current block, including the timestamp used to identify expired locks. + /// * `transaction`: The transaction under which this operation should be performed. + /// * `platform_version`: The version of the platform to ensure compatibility with the appropriate cleanup method. + /// + /// # Returns + /// * `Ok(())`: If the cleanup was performed successfully. + /// * `Err(Error::Execution(ExecutionError::UnknownVersionMismatch))`: If the platform version does not match known versions. + /// + /// # Errors + /// Returns an error if the platform version is unknown or if the cleanup process encounters an issue. + pub fn clean_up_expired_locks_of_withdrawal_amounts( + &self, + block_info: &BlockInfo, + transaction: &Transaction, + platform_version: &PlatformVersion, + ) -> Result<(), Error> { + match platform_version + .drive_abci + .methods + .withdrawals + .cleanup_expired_locks_of_withdrawal_amounts + { + 0 => self.cleanup_expired_locks_of_withdrawal_amounts_v0( + block_info, + transaction, + platform_version, + ), + version => Err(Error::Execution(ExecutionError::UnknownVersionMismatch { + method: "cleanup_expired_locks_of_withdrawal_amounts".to_string(), + known_versions: vec![0], + received: version, + })), + } + } +} diff --git a/packages/rs-drive-abci/src/execution/platform_events/withdrawals/cleanup_expired_locks_of_withdrawal_amounts/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/withdrawals/cleanup_expired_locks_of_withdrawal_amounts/v0/mod.rs new file mode 100644 index 0000000000..74315a1d6c --- /dev/null +++ b/packages/rs-drive-abci/src/execution/platform_events/withdrawals/cleanup_expired_locks_of_withdrawal_amounts/v0/mod.rs @@ -0,0 +1,69 @@ +use crate::error::Error; +use crate::platform_types::platform::Platform; + +use crate::rpc::core::CoreRPCLike; +use dpp::block::block_info::BlockInfo; + +use dpp::version::PlatformVersion; +use drive::drive::identity::withdrawals::paths::get_withdrawal_transactions_sum_tree_path_vec; +use drive::grovedb::{PathQuery, QueryItem, Transaction}; +use drive::util::grove_operations::BatchDeleteApplyType; + +impl Platform +where + C: CoreRPCLike, +{ + pub(super) fn cleanup_expired_locks_of_withdrawal_amounts_v0( + &self, + block_info: &BlockInfo, + transaction: &Transaction, + platform_version: &PlatformVersion, + ) -> Result<(), Error> { + if platform_version + .drive_abci + .withdrawal_constants + .cleanup_expired_locks_of_withdrawal_amounts_limit + == 0 + { + // No clean up + return Ok(()); + } + let mut batch_operations = vec![]; + + let sum_path = get_withdrawal_transactions_sum_tree_path_vec(); + + let mut path_query = PathQuery::new_single_query_item( + sum_path, + QueryItem::RangeTo(..block_info.time_ms.to_be_bytes().to_vec()), + ); + + path_query.query.limit = Some( + platform_version + .drive_abci + .withdrawal_constants + .cleanup_expired_locks_of_withdrawal_amounts_limit, + ); + + self.drive.batch_delete_items_in_path_query( + &path_query, + true, + // we know that we are not deleting a subtree + BatchDeleteApplyType::StatefulBatchDelete { + is_known_to_be_subtree_with_sum: Some((false, false)), + }, + Some(transaction), + &mut batch_operations, + &platform_version.drive, + )?; + + self.drive.apply_batch_low_level_drive_operations( + None, + Some(transaction), + batch_operations, + &mut vec![], + &platform_version.drive, + )?; + + Ok(()) + } +} diff --git a/packages/rs-drive-abci/src/execution/platform_events/withdrawals/dequeue_and_build_unsigned_withdrawal_transactions/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/withdrawals/dequeue_and_build_unsigned_withdrawal_transactions/v0/mod.rs index 33edd09927..7a37525de6 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/withdrawals/dequeue_and_build_unsigned_withdrawal_transactions/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/withdrawals/dequeue_and_build_unsigned_withdrawal_transactions/v0/mod.rs @@ -13,7 +13,7 @@ use dpp::version::PlatformVersion; use drive::dpp::system_data_contracts::withdrawals_contract; use drive::dpp::system_data_contracts::withdrawals_contract::v1::document_types::withdrawal; -use drive::drive::identity::withdrawals::WithdrawalTransactionIndex; +use dpp::withdrawal::WithdrawalTransactionIndex; use drive::query::TransactionArg; use drive::util::batch::DriveOperation; @@ -28,8 +28,6 @@ use dpp::errors::ProtocolError; use drive::config::DEFAULT_QUERY_LIMIT; -const WITHDRAWAL_TRANSACTIONS_QUERY_LIMIT: u16 = 16; - impl Platform where C: CoreRPCLike, @@ -44,9 +42,11 @@ where ) -> Result { let mut drive_operations: Vec = vec![]; - // Get 16 latest withdrawal transactions from the queue + // Get withdrawal_transactions_per_block_limit (normally 4) latest withdrawal transactions from the queue let untied_withdrawal_transactions = self.drive.dequeue_untied_withdrawal_transactions( - WITHDRAWAL_TRANSACTIONS_QUERY_LIMIT, + platform_version + .system_limits + .withdrawal_transactions_per_block_limit, transaction, &mut drive_operations, platform_version, @@ -150,8 +150,8 @@ where document.set_updated_at(Some(block_info.time_ms)); document.increment_revision().map_err(|_| { - Error::Execution(ExecutionError::CorruptedCodeExecution( - "Could not increment document revision", + Error::Execution(ExecutionError::Overflow( + "Overflow when adding to document revision for withdrawals", )) })?; diff --git a/packages/rs-drive-abci/src/execution/platform_events/withdrawals/fetch_transactions_block_inclusion_status/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/withdrawals/fetch_transactions_block_inclusion_status/mod.rs index 0a4b17062e..726a86eef0 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/withdrawals/fetch_transactions_block_inclusion_status/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/withdrawals/fetch_transactions_block_inclusion_status/mod.rs @@ -4,7 +4,7 @@ use crate::platform_types::platform::Platform; use crate::rpc::core::CoreRPCLike; use dashcore_rpc::json::AssetUnlockStatus; use dpp::version::PlatformVersion; -use drive::drive::identity::withdrawals::WithdrawalTransactionIndex; +use dpp::withdrawal::WithdrawalTransactionIndex; use std::collections::BTreeMap; mod v0; diff --git a/packages/rs-drive-abci/src/execution/platform_events/withdrawals/fetch_transactions_block_inclusion_status/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/withdrawals/fetch_transactions_block_inclusion_status/v0/mod.rs index 86433d8c03..d284be086d 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/withdrawals/fetch_transactions_block_inclusion_status/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/withdrawals/fetch_transactions_block_inclusion_status/v0/mod.rs @@ -1,9 +1,8 @@ +use crate::{error::Error, platform_types::platform::Platform, rpc::core::CoreRPCLike}; use dashcore_rpc::dashcore_rpc_json::AssetUnlockStatus; -use drive::drive::identity::withdrawals::WithdrawalTransactionIndex; +use dpp::withdrawal::WithdrawalTransactionIndex; use std::collections::BTreeMap; -use crate::{error::Error, platform_types::platform::Platform, rpc::core::CoreRPCLike}; - impl Platform where C: CoreRPCLike, diff --git a/packages/rs-drive-abci/src/execution/platform_events/withdrawals/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/withdrawals/mod.rs index 7541211056..d7779c47b0 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/withdrawals/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/withdrawals/mod.rs @@ -1,6 +1,8 @@ pub(in crate::execution) mod append_signatures_and_broadcast_withdrawal_transactions; pub(in crate::execution) mod build_untied_withdrawal_transactions_from_documents; +pub(in crate::execution) mod cleanup_expired_locks_of_withdrawal_amounts; pub(in crate::execution) mod dequeue_and_build_unsigned_withdrawal_transactions; pub(in crate::execution) mod fetch_transactions_block_inclusion_status; pub(in crate::execution) mod pool_withdrawals_into_transactions_queue; +pub(in crate::execution) mod rebroadcast_expired_withdrawal_documents; pub(in crate::execution) mod update_broadcasted_withdrawal_statuses; diff --git a/packages/rs-drive-abci/src/execution/platform_events/withdrawals/pool_withdrawals_into_transactions_queue/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/withdrawals/pool_withdrawals_into_transactions_queue/mod.rs index 910445fe32..66be57e5e0 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/withdrawals/pool_withdrawals_into_transactions_queue/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/withdrawals/pool_withdrawals_into_transactions_queue/mod.rs @@ -2,12 +2,14 @@ use crate::error::execution::ExecutionError; use crate::error::Error; use crate::platform_types::platform::Platform; +use crate::platform_types::platform_state::PlatformState; use crate::rpc::core::CoreRPCLike; use dpp::block::block_info::BlockInfo; use dpp::version::PlatformVersion; use drive::grovedb::TransactionArg; mod v0; +mod v1; impl Platform where @@ -29,6 +31,7 @@ where pub(in crate::execution) fn pool_withdrawals_into_transactions_queue( &self, block_info: &BlockInfo, + last_committed_platform_state: &PlatformState, transaction: TransactionArg, platform_version: &PlatformVersion, ) -> Result<(), Error> { @@ -39,13 +42,19 @@ where .pool_withdrawals_into_transactions_queue { 0 => self.pool_withdrawals_into_transactions_queue_v0( + block_info, + last_committed_platform_state, + transaction, + platform_version, + ), + 1 => self.pool_withdrawals_into_transactions_queue_v1( block_info, transaction, platform_version, ), version => Err(Error::Execution(ExecutionError::UnknownVersionMismatch { method: "pool_withdrawals_into_transactions_queue".to_string(), - known_versions: vec![0], + known_versions: vec![0, 1], received: version, })), } diff --git a/packages/rs-drive-abci/src/execution/platform_events/withdrawals/pool_withdrawals_into_transactions_queue/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/withdrawals/pool_withdrawals_into_transactions_queue/v0/mod.rs index 9540d42f12..610d8e3fcc 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/withdrawals/pool_withdrawals_into_transactions_queue/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/withdrawals/pool_withdrawals_into_transactions_queue/v0/mod.rs @@ -1,23 +1,10 @@ use dpp::block::block_info::BlockInfo; - -use dpp::data_contract::accessors::v0::DataContractV0Getters; -use dpp::document::document_methods::DocumentMethodsV0; -use dpp::document::{DocumentV0Getters, DocumentV0Setters}; - use dpp::version::PlatformVersion; - -use drive::drive::identity::withdrawals::WithdrawalTransactionIndexAndBytes; use drive::grovedb::TransactionArg; -use dpp::system_data_contracts::withdrawals_contract; -use dpp::system_data_contracts::withdrawals_contract::v1::document_types::withdrawal; -use drive::config::DEFAULT_QUERY_LIMIT; - -use crate::{ - error::{execution::ExecutionError, Error}, - platform_types::platform::Platform, - rpc::core::CoreRPCLike, -}; +use crate::platform_types::platform_state::v0::PlatformStateV0Methods; +use crate::platform_types::platform_state::PlatformState; +use crate::{error::Error, platform_types::platform::Platform, rpc::core::CoreRPCLike}; impl Platform where @@ -27,115 +14,30 @@ where pub(super) fn pool_withdrawals_into_transactions_queue_v0( &self, block_info: &BlockInfo, + last_committed_platform_state: &PlatformState, transaction: TransactionArg, platform_version: &PlatformVersion, ) -> Result<(), Error> { - let mut documents = self.drive.fetch_oldest_withdrawal_documents_by_status( - withdrawals_contract::WithdrawalStatus::QUEUED.into(), - DEFAULT_QUERY_LIMIT, - transaction, - platform_version, - )?; + // Currently Core only supports using the first 2 quorums (out of 24 for mainnet). + // For extra safety, we use only the first quorum because our quorum info based + // on core chain locked height which is always late comparing with Core. + let Some(position_of_current_quorum) = + last_committed_platform_state.current_validator_set_position_in_list_by_most_recent() + else { + tracing::warn!("Current quorum not in current validator set, do not pool withdrawals"); - if documents.is_empty() { return Ok(()); - } - - let start_transaction_index = self - .drive - .fetch_next_withdrawal_transaction_index(transaction, platform_version)?; - - let untied_withdrawal_transactions = self - .build_untied_withdrawal_transactions_from_documents( - &documents, - start_transaction_index, - platform_version, - )?; - - for document in documents.iter_mut() { - let Some((transaction_index, _)) = untied_withdrawal_transactions.get(&document.id()) - else { - return Err(Error::Execution(ExecutionError::CorruptedCodeExecution( - "transactions must contain a transaction", - ))); - }; - - document.set_u64( - withdrawal::properties::TRANSACTION_INDEX, - *transaction_index, - ); - - document.set_u8( - withdrawal::properties::STATUS, - withdrawals_contract::WithdrawalStatus::POOLED as u8, + }; + if position_of_current_quorum != 0 { + tracing::debug!( + "Current quorum is not most recent, it is in position {}, do not pool withdrawals", + position_of_current_quorum ); - document.set_updated_at(Some(block_info.time_ms)); - - document.increment_revision().map_err(|_| { - Error::Execution(ExecutionError::CorruptedCodeExecution( - "Could not increment document revision", - )) - })?; + return Ok(()); } - - let withdrawal_transactions: Vec = - untied_withdrawal_transactions.into_values().collect(); - - let withdrawal_transactions_count = withdrawal_transactions.len(); - - let mut drive_operations = Vec::new(); - - self.drive - .add_enqueue_untied_withdrawal_transaction_operations( - withdrawal_transactions, - &mut drive_operations, - platform_version, - )?; - - let end_transaction_index = start_transaction_index + withdrawal_transactions_count as u64; - - self.drive - .add_update_next_withdrawal_transaction_index_operation( - end_transaction_index, - &mut drive_operations, - platform_version, - )?; - - tracing::debug!( - "Pooled {} withdrawal documents into {} transactions with indices from {} to {}", - documents.len(), - withdrawal_transactions_count, - start_transaction_index, - end_transaction_index, - ); - - let withdrawals_contract = self.drive.cache.system_data_contracts.load_withdrawals(); - - self.drive.add_update_multiple_documents_operations( - &documents, - &withdrawals_contract, - withdrawals_contract - .document_type_for_name(withdrawal::NAME) - .map_err(|_| { - Error::Execution(ExecutionError::CorruptedCodeExecution( - "Can't fetch withdrawal data contract", - )) - })?, - &mut drive_operations, - &platform_version.drive, - )?; - - self.drive.apply_drive_operations( - drive_operations, - true, - block_info, - transaction, - platform_version, - None, - )?; - - Ok(()) + // Just use the v1 as to not duplicate code + self.pool_withdrawals_into_transactions_queue_v1(block_info, transaction, platform_version) } } @@ -143,20 +45,23 @@ where mod tests { use super::*; use dpp::block::epoch::Epoch; - use itertools::Itertools; - + use dpp::data_contract::accessors::v0::DataContractV0Getters; use dpp::data_contracts::SystemDataContract; use dpp::identifier::Identifier; use dpp::identity::core_script::CoreScript; use dpp::tests::fixtures::get_withdrawal_document_fixture; use dpp::withdrawal::Pooling; use drive::util::test_helpers::setup::{setup_document, setup_system_data_contract}; + use itertools::Itertools; use crate::test::helpers::setup::TestPlatformBuilder; + use dpp::document::DocumentV0Getters; use dpp::platform_value::btreemap_extensions::BTreeValueMapHelper; use dpp::platform_value::platform_value; - use dpp::system_data_contracts::load_system_data_contract; + use dpp::system_data_contracts::withdrawals_contract::v1::document_types::withdrawal; + use dpp::system_data_contracts::{load_system_data_contract, withdrawals_contract}; use dpp::version::PlatformVersion; + use drive::config::DEFAULT_QUERY_LIMIT; #[test] fn test_pooling() { @@ -234,9 +139,12 @@ mod tests { Some(&transaction), ); + let platform_state = platform.state.load(); + platform .pool_withdrawals_into_transactions_queue_v0( &block_info, + &platform_state, Some(&transaction), platform_version, ) diff --git a/packages/rs-drive-abci/src/execution/platform_events/withdrawals/pool_withdrawals_into_transactions_queue/v1/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/withdrawals/pool_withdrawals_into_transactions_queue/v1/mod.rs new file mode 100644 index 0000000000..b0b0f99e65 --- /dev/null +++ b/packages/rs-drive-abci/src/execution/platform_events/withdrawals/pool_withdrawals_into_transactions_queue/v1/mod.rs @@ -0,0 +1,311 @@ +use dpp::block::block_info::BlockInfo; +use metrics::gauge; + +use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::document::DocumentV0Getters; +use dpp::platform_value::btreemap_extensions::BTreeValueMapHelper; +use dpp::version::PlatformVersion; +use drive::grovedb::TransactionArg; + +use dpp::system_data_contracts::withdrawals_contract; +use dpp::system_data_contracts::withdrawals_contract::v1::document_types::withdrawal; + +use crate::metrics::{ + GAUGE_CREDIT_WITHDRAWAL_LIMIT_AVAILABLE, GAUGE_CREDIT_WITHDRAWAL_LIMIT_TOTAL, +}; +use crate::{ + error::{execution::ExecutionError, Error}, + platform_types::platform::Platform, + rpc::core::CoreRPCLike, +}; + +impl Platform +where + C: CoreRPCLike, +{ + /// Pool withdrawal documents into transactions + /// Version 1 changes on Version 0, by not having the Core 2 Quorum limit. + /// We should switch to Version 1 once Core has fixed the issue + pub(super) fn pool_withdrawals_into_transactions_queue_v1( + &self, + block_info: &BlockInfo, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result<(), Error> { + let documents = self.drive.fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::QUEUED.into(), + platform_version + .system_limits + .withdrawal_transactions_per_block_limit, + transaction, + platform_version, + )?; + + if documents.is_empty() { + return Ok(()); + } + + // Only take documents up to the withdrawal amount + let withdrawals_info = self + .drive + .calculate_current_withdrawal_limit(transaction, platform_version)?; + + let current_withdrawal_limit = withdrawals_info.available(); + + // Store prometheus metrics + gauge!(GAUGE_CREDIT_WITHDRAWAL_LIMIT_AVAILABLE).set(current_withdrawal_limit as f64); + gauge!(GAUGE_CREDIT_WITHDRAWAL_LIMIT_TOTAL).set(withdrawals_info.daily_maximum as f64); + + // Only process documents up to the current withdrawal limit. + let mut total_withdrawal_amount = 0u64; + + // Iterate over the documents and accumulate their withdrawal amounts. + let mut documents_to_process = vec![]; + for document in documents { + // Get the withdrawal amount from the document properties. + let amount: u64 = document + .properties() + .get_integer(withdrawal::properties::AMOUNT)?; + + // Check if adding this amount would exceed the current withdrawal limit. + let potential_total_withdrawal_amount = + total_withdrawal_amount.checked_add(amount).ok_or_else(|| { + Error::Execution(ExecutionError::Overflow( + "overflow in total withdrawal amount", + )) + })?; + + // If adding this withdrawal would exceed the limit, stop processing further. + if potential_total_withdrawal_amount > current_withdrawal_limit { + tracing::debug!( + "Pooling is limited due to daily withdrawals limit. {} credits left", + current_withdrawal_limit + ); + break; + } + + total_withdrawal_amount = potential_total_withdrawal_amount; + + // Add this document to the list of documents to be processed. + documents_to_process.push(document); + } + + if documents_to_process.is_empty() { + return Ok(()); + } + + let start_transaction_index = self + .drive + .fetch_next_withdrawal_transaction_index(transaction, platform_version)?; + + let (withdrawal_transactions, total_amount) = self + .build_untied_withdrawal_transactions_from_documents( + &mut documents_to_process, + start_transaction_index, + block_info, + platform_version, + )?; + + let withdrawal_transactions_count = withdrawal_transactions.len(); + + let mut drive_operations = vec![]; + + self.drive + .add_enqueue_untied_withdrawal_transaction_operations( + withdrawal_transactions, + total_amount, + &mut drive_operations, + platform_version, + )?; + + let end_transaction_index = start_transaction_index + withdrawal_transactions_count as u64; + + self.drive + .add_update_next_withdrawal_transaction_index_operation( + end_transaction_index, + &mut drive_operations, + platform_version, + )?; + + tracing::debug!( + "Pooled {} withdrawal documents into {} transactions with indices from {} to {}", + documents_to_process.len(), + withdrawal_transactions_count, + start_transaction_index, + end_transaction_index, + ); + + let withdrawals_contract = self.drive.cache.system_data_contracts.load_withdrawals(); + + self.drive.add_update_multiple_documents_operations( + &documents_to_process, + &withdrawals_contract, + withdrawals_contract + .document_type_for_name(withdrawal::NAME) + .map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't fetch withdrawal data contract", + )) + })?, + &mut drive_operations, + &platform_version.drive, + )?; + + self.drive.apply_drive_operations( + drive_operations, + true, + block_info, + transaction, + platform_version, + None, + )?; + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use dpp::block::epoch::Epoch; + use itertools::Itertools; + + use dpp::data_contracts::SystemDataContract; + use dpp::identifier::Identifier; + use dpp::identity::core_script::CoreScript; + use dpp::tests::fixtures::get_withdrawal_document_fixture; + use dpp::withdrawal::Pooling; + use drive::util::test_helpers::setup::{setup_document, setup_system_data_contract}; + + use crate::test::helpers::setup::TestPlatformBuilder; + use dpp::document::DocumentV0Getters; + use dpp::platform_value::btreemap_extensions::BTreeValueMapHelper; + use dpp::platform_value::platform_value; + use dpp::system_data_contracts::load_system_data_contract; + use dpp::version::PlatformVersion; + use drive::config::DEFAULT_QUERY_LIMIT; + + #[test] + fn test_pooling() { + let platform_version = PlatformVersion::latest(); + let platform = TestPlatformBuilder::new() + .build_with_mock_rpc() + .set_initial_state_structure(); + + let transaction = platform.drive.grove.start_transaction(); + + let block_info = BlockInfo { + time_ms: 1, + height: 1, + core_height: 96, + epoch: Epoch::default(), + }; + + let data_contract = + load_system_data_contract(SystemDataContract::Withdrawals, platform_version) + .expect("to load system data contract"); + + setup_system_data_contract(&platform.drive, &data_contract, Some(&transaction)); + + let owner_id = Identifier::new([1u8; 32]); + + let document_1 = get_withdrawal_document_fixture( + &data_contract, + owner_id, + platform_value!({ + "amount": 1000u64, + "coreFeePerByte": 1u32, + "pooling": Pooling::Never as u8, + "outputScript": CoreScript::from_bytes((0..23).collect::>()), + "status": withdrawals_contract::WithdrawalStatus::QUEUED as u8, + "transactionIndex": 1u64, + }), + None, + platform_version.protocol_version, + ) + .expect("expected withdrawal document"); + + let document_type = data_contract + .document_type_for_name(withdrawal::NAME) + .expect("expected to get document type"); + + setup_document( + &platform.drive, + &document_1, + &data_contract, + document_type, + Some(&transaction), + ); + + let document_2 = get_withdrawal_document_fixture( + &data_contract, + owner_id, + platform_value!({ + "amount": 1000u64, + "coreFeePerByte": 1u32, + "pooling": Pooling::Never as u8, + "outputScript": CoreScript::from_bytes((0..23).collect::>()), + "status": withdrawals_contract::WithdrawalStatus::QUEUED as u8, + "transactionIndex": 2u64, + }), + None, + platform_version.protocol_version, + ) + .expect("expected withdrawal document"); + + setup_document( + &platform.drive, + &document_2, + &data_contract, + document_type, + Some(&transaction), + ); + + let platform_state = platform.state.load(); + + platform + .pool_withdrawals_into_transactions_queue_v0( + &block_info, + &platform_state, + Some(&transaction), + platform_version, + ) + .expect("to pool withdrawal documents into transactions"); + + let updated_documents = platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::POOLED.into(), + DEFAULT_QUERY_LIMIT, + Some(&transaction), + platform_version, + ) + .expect("to fetch withdrawal documents"); + + for (i, document) in updated_documents + .into_iter() + // Sort by index because updated_at is the same for all documents within batch + .sorted_by(|a, b| { + let a_index = a + .properties() + .get_u64(withdrawal::properties::TRANSACTION_INDEX) + .expect("to get transactionIndex"); + let b_index = b + .properties() + .get_u64(withdrawal::properties::TRANSACTION_INDEX) + .expect("to get transactionIndex"); + a_index.cmp(&b_index) + }) + .enumerate() + { + assert_eq!(document.revision(), Some(2)); + + let tx_index = document + .properties() + .get_u64(withdrawal::properties::TRANSACTION_INDEX) + .expect("to get transactionIndex"); + + assert_eq!(tx_index, i as u64); + } + } +} diff --git a/packages/rs-drive-abci/src/execution/platform_events/withdrawals/rebroadcast_expired_withdrawal_documents/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/withdrawals/rebroadcast_expired_withdrawal_documents/mod.rs new file mode 100644 index 0000000000..cb01272fdc --- /dev/null +++ b/packages/rs-drive-abci/src/execution/platform_events/withdrawals/rebroadcast_expired_withdrawal_documents/mod.rs @@ -0,0 +1,65 @@ +use crate::error::execution::ExecutionError; +use crate::error::Error; +use crate::platform_types::platform::Platform; + +use crate::rpc::core::CoreRPCLike; +use dpp::block::block_info::BlockInfo; + +use crate::platform_types::platform_state::PlatformState; +use dpp::version::PlatformVersion; +use drive::grovedb::Transaction; + +mod v0; +mod v1; + +impl Platform +where + C: CoreRPCLike, +{ + /// Rebroadcasts expired withdrawal documents if any exist. + /// + /// This function attempts to rebroadcast expired withdrawal documents by checking if there are + /// any documents with the status `EXPIRED`. It updates the status of such documents to + /// `BROADCASTED`, increments their revision, and reschedules them for broadcasting. + /// + /// # Parameters + /// - `block_info`: Information about the current block (e.g., timestamp). + /// - `last_committed_platform_state`: The last committed platform state needed to check active validator set. + /// - `transaction`: The transaction within which the rebroadcast should be executed. + /// - `platform_version`: The version of the platform, used to determine the correct method implementation. + /// + /// # Returns + /// - `Ok(())` if the rebroadcast process succeeds without issues. + /// - `Err(ExecutionError::UnknownVersionMismatch)` if the platform version is unsupported. + pub fn rebroadcast_expired_withdrawal_documents( + &self, + block_info: &BlockInfo, + last_committed_platform_state: &PlatformState, + transaction: &Transaction, + platform_version: &PlatformVersion, + ) -> Result<(), Error> { + match platform_version + .drive_abci + .methods + .withdrawals + .rebroadcast_expired_withdrawal_documents + { + 0 => self.rebroadcast_expired_withdrawal_documents_v0( + block_info, + last_committed_platform_state, + transaction, + platform_version, + ), + 1 => self.rebroadcast_expired_withdrawal_documents_v1( + block_info, + transaction, + platform_version, + ), + version => Err(Error::Execution(ExecutionError::UnknownVersionMismatch { + method: "rebroadcast_expired_withdrawal_documents".to_string(), + known_versions: vec![0, 1], + received: version, + })), + } + } +} diff --git a/packages/rs-drive-abci/src/execution/platform_events/withdrawals/rebroadcast_expired_withdrawal_documents/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/withdrawals/rebroadcast_expired_withdrawal_documents/v0/mod.rs new file mode 100644 index 0000000000..d8949a06a0 --- /dev/null +++ b/packages/rs-drive-abci/src/execution/platform_events/withdrawals/rebroadcast_expired_withdrawal_documents/v0/mod.rs @@ -0,0 +1,39 @@ +use crate::error::Error; +use crate::platform_types::platform_state::v0::PlatformStateV0Methods; +use crate::platform_types::platform_state::PlatformState; +use crate::{platform_types::platform::Platform, rpc::core::CoreRPCLike}; +use dpp::block::block_info::BlockInfo; +use dpp::version::PlatformVersion; +use drive::grovedb::Transaction; + +impl Platform +where + C: CoreRPCLike, +{ + pub(super) fn rebroadcast_expired_withdrawal_documents_v0( + &self, + block_info: &BlockInfo, + last_committed_platform_state: &PlatformState, + transaction: &Transaction, + platform_version: &PlatformVersion, + ) -> Result<(), Error> { + // Currently Core only supports using the first 2 quorums (out of 24 for mainnet). + // For us, we just use the latest quorum to be extra safe. + let Some(position_of_current_quorum) = + last_committed_platform_state.current_validator_set_position_in_list_by_most_recent() + else { + tracing::warn!("Current quorum not in current validator set, do not re-broadcast expired withdrawals"); + return Ok(()); + }; + if position_of_current_quorum != 0 { + tracing::debug!( + "Current quorum is not most recent, it is in position {}, do not re-broadcast expired withdrawals", + position_of_current_quorum + ); + return Ok(()); + } + // Version 1 changes on Version 0, by not having the Core 2 Quorum limit. + // Hence we can just use the v1 here after the extra logic of v0 + self.rebroadcast_expired_withdrawal_documents_v1(block_info, transaction, platform_version) + } +} diff --git a/packages/rs-drive-abci/src/execution/platform_events/withdrawals/rebroadcast_expired_withdrawal_documents/v1/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/withdrawals/rebroadcast_expired_withdrawal_documents/v1/mod.rs new file mode 100644 index 0000000000..e2e50b3e5b --- /dev/null +++ b/packages/rs-drive-abci/src/execution/platform_events/withdrawals/rebroadcast_expired_withdrawal_documents/v1/mod.rs @@ -0,0 +1,124 @@ +use dpp::block::block_info::BlockInfo; +use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::data_contracts::withdrawals_contract::WithdrawalStatus; +use dpp::document::document_methods::DocumentMethodsV0; +use dpp::document::{DocumentV0Getters, DocumentV0Setters}; +use dpp::platform_value::btreemap_extensions::BTreeValueMapHelper; + +use dpp::system_data_contracts::withdrawals_contract::v1::document_types::withdrawal; +use dpp::version::PlatformVersion; +use std::collections::BTreeSet; + +use crate::{ + error::{execution::ExecutionError, Error}, + platform_types::platform::Platform, + rpc::core::CoreRPCLike, +}; +use dpp::withdrawal::WithdrawalTransactionIndex; +use drive::grovedb::Transaction; +use drive::util::batch::DriveOperation; + +impl Platform +where + C: CoreRPCLike, +{ + /// Version 1 changes on Version 0, by not having the Core 2 Quorum limit. + /// We should switch to Version 1 once Core has fixed the issue + pub(super) fn rebroadcast_expired_withdrawal_documents_v1( + &self, + block_info: &BlockInfo, + transaction: &Transaction, + platform_version: &PlatformVersion, + ) -> Result<(), Error> { + let expired_withdrawal_documents_to_retry_signing = + self.drive.fetch_oldest_withdrawal_documents_by_status( + WithdrawalStatus::EXPIRED.into(), + platform_version + .system_limits + .retry_signing_expired_withdrawal_documents_per_block_limit, + transaction.into(), + platform_version, + )?; + + if expired_withdrawal_documents_to_retry_signing.is_empty() { + return Ok(()); + } + + // Collecting unique withdrawal indices of expired documents + let expired_withdrawal_indices: Vec = + expired_withdrawal_documents_to_retry_signing + .iter() + .map(|document| { + document + .properties() + .get_optional_u64(withdrawal::properties::TRANSACTION_INDEX)? + .ok_or(Error::Execution(ExecutionError::CorruptedDriveResponse( + "Can't get transaction index from withdrawal document".to_string(), + ))) + }) + .collect::, Error>>()? + .into_iter() + .collect(); + + let mut drive_operations: Vec = vec![]; + + // Collecting only documents that have been updated + let mut documents_to_update = Vec::new(); + + for mut document in expired_withdrawal_documents_to_retry_signing { + document.set_u8( + withdrawal::properties::STATUS, + WithdrawalStatus::BROADCASTED as u8, + ); + + document.set_u64( + withdrawal::properties::TRANSACTION_SIGN_HEIGHT, + block_info.core_height as u64, + ); + + document.set_updated_at(Some(block_info.time_ms)); + + document.increment_revision().map_err(Error::Protocol)?; + + documents_to_update.push(document); + } + + if documents_to_update.is_empty() { + return Ok(()); + } + + self.drive + .move_broadcasted_withdrawal_transactions_back_to_queue_operations( + expired_withdrawal_indices, + &mut drive_operations, + platform_version, + )?; + + let withdrawals_contract = self.drive.cache.system_data_contracts.load_withdrawals(); + + self.drive.add_update_multiple_documents_operations( + &documents_to_update, + &withdrawals_contract, + withdrawals_contract + .document_type_for_name(withdrawal::NAME) + .map_err(|_| { + Error::Execution(ExecutionError::CorruptedCodeExecution( + "Can't fetch withdrawal data contract", + )) + })?, + &mut drive_operations, + &platform_version.drive, + )?; + + self.drive.apply_drive_operations( + drive_operations, + true, + block_info, + transaction.into(), + platform_version, + None, + )?; + + Ok(()) + } +} diff --git a/packages/rs-drive-abci/src/execution/platform_events/withdrawals/update_broadcasted_withdrawal_statuses/v0/mod.rs b/packages/rs-drive-abci/src/execution/platform_events/withdrawals/update_broadcasted_withdrawal_statuses/v0/mod.rs index 0257f29351..470d234939 100644 --- a/packages/rs-drive-abci/src/execution/platform_events/withdrawals/update_broadcasted_withdrawal_statuses/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/platform_events/withdrawals/update_broadcasted_withdrawal_statuses/v0/mod.rs @@ -8,21 +8,17 @@ use dpp::platform_value::btreemap_extensions::BTreeValueMapHelper; use dpp::system_data_contracts::withdrawals_contract::v1::document_types::withdrawal; use dpp::version::PlatformVersion; -use itertools::Itertools; -use std::collections::HashSet; - -use drive::config::DEFAULT_QUERY_LIMIT; -use drive::drive::identity::withdrawals::WithdrawalTransactionIndex; -use drive::grovedb::Transaction; -use drive::util::batch::DriveOperation; +use std::collections::BTreeSet; use crate::{ error::{execution::ExecutionError, Error}, platform_types::platform::Platform, rpc::core::CoreRPCLike, }; - -const NUMBER_OF_BLOCKS_BEFORE_EXPIRED: u32 = 48; +use dpp::withdrawal::WithdrawalTransactionIndex; +use drive::config::DEFAULT_QUERY_LIMIT; +use drive::grovedb::Transaction; +use drive::util::batch::DriveOperation; impl Platform where @@ -47,20 +43,21 @@ where return Ok(()); } - // Collecting unique withdrawal indices - let broadcasted_withdrawal_indices = broadcasted_withdrawal_documents - .iter() - .map(|document| { - document - .properties() - .get_optional_u64(withdrawal::properties::TRANSACTION_INDEX)? - .ok_or(Error::Execution(ExecutionError::CorruptedDriveResponse( - "Can't get transaction index from withdrawal document".to_string(), - ))) - }) - .collect::, Error>>()? - .into_iter() - .collect_vec(); + // Collecting unique withdrawal indices of broadcasted documents + let broadcasted_withdrawal_indices: Vec = + broadcasted_withdrawal_documents + .iter() + .map(|document| { + document + .properties() + .get_optional_u64(withdrawal::properties::TRANSACTION_INDEX)? + .ok_or(Error::Execution(ExecutionError::CorruptedDriveResponse( + "Can't get transaction index from withdrawal document".to_string(), + ))) + }) + .collect::, Error>>()? + .into_iter() + .collect(); let withdrawal_transaction_statuses = self.fetch_transactions_block_inclusion_status( block_info.core_height, @@ -70,6 +67,18 @@ where let mut drive_operations: Vec = vec![]; + // Let's remove broadcasted withdrawal transactions that are now chainlocked + let chainlocked_indexes = withdrawal_transaction_statuses + .iter() + .filter_map(|(index, status)| { + if *status == AssetUnlockStatus::Chainlocked { + Some(*index) + } else { + None + } + }) + .collect::>(); + // Collecting only documents that have been updated let mut documents_to_update = Vec::new(); @@ -109,13 +118,17 @@ where ); WithdrawalStatus::COMPLETE - } else if block_height_difference > NUMBER_OF_BLOCKS_BEFORE_EXPIRED { + } else if block_height_difference + > platform_version + .drive_abci + .withdrawal_constants + .core_expiration_blocks + { tracing::debug!( transaction_sign_height, "Withdrawal with transaction index {} is marked as expired", withdrawal_index ); - WithdrawalStatus::EXPIRED } else { continue; @@ -134,6 +147,13 @@ where return Ok(()); } + self.drive + .remove_broadcasted_withdrawal_transactions_after_completion_operations( + chainlocked_indexes, + &mut drive_operations, + platform_version, + )?; + let withdrawals_contract = self.drive.cache.system_data_contracts.load_withdrawals(); self.drive.add_update_multiple_documents_operations( diff --git a/packages/rs-drive-abci/src/execution/storage/fetch_platform_state/v0/mod.rs b/packages/rs-drive-abci/src/execution/storage/fetch_platform_state/v0/mod.rs index 25960bf5b3..a815e0266a 100644 --- a/packages/rs-drive-abci/src/execution/storage/fetch_platform_state/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/storage/fetch_platform_state/v0/mod.rs @@ -16,8 +16,18 @@ impl Platform { .fetch_platform_state_bytes(transaction, platform_version) .map_err(Error::Drive)? .map(|bytes| { - PlatformState::versioned_deserialize(&bytes, platform_version) - .map_err(Error::Protocol) + let result = PlatformState::versioned_deserialize(&bytes, platform_version) + .map_err(Error::Protocol); + + if result.is_err() { + tracing::error!( + bytes = hex::encode(&bytes), + "Unable deserialize platform state for version {}", + platform_version.protocol_version + ); + } + + result }) .transpose() } diff --git a/packages/rs-drive-abci/src/execution/types/block_execution_context/v0/mod.rs b/packages/rs-drive-abci/src/execution/types/block_execution_context/v0/mod.rs index ec71d6f20d..de6e1ddc33 100644 --- a/packages/rs-drive-abci/src/execution/types/block_execution_context/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/types/block_execution_context/v0/mod.rs @@ -1,32 +1,3 @@ -// MIT LICENSE -// -// Copyright (c) 2021 Dash Core Group -// -// Permission is hereby granted, free of charge, to any -// person obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the -// Software without restriction, including without -// limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software -// is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice -// shall be included in all copies or substantial portions -// of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. -// - use crate::execution::types::block_state_info::BlockStateInfo; use crate::platform_types::epoch_info::EpochInfo; diff --git a/packages/rs-drive-abci/src/execution/types/execution_operation/mod.rs b/packages/rs-drive-abci/src/execution/types/execution_operation/mod.rs index 4024224e2e..d44b854495 100644 --- a/packages/rs-drive-abci/src/execution/types/execution_operation/mod.rs +++ b/packages/rs-drive-abci/src/execution/types/execution_operation/mod.rs @@ -67,6 +67,7 @@ pub enum ValidationOperation { Protocol(ProtocolValidationOperation), RetrieveIdentity(RetrieveIdentityInfo), RetrievePrefundedSpecializedBalance, + PerformNetworkThresholdSigning, SingleSha256(HashBlockCount), DoubleSha256(HashBlockCount), ValidateKeyStructure(KeyCount), // This is extremely cheap @@ -210,6 +211,19 @@ impl ValidationOperation { "execution processing fee overflow error", ))?; } + ValidationOperation::PerformNetworkThresholdSigning => { + let operation_cost = platform_version + .fee_version + .processing + .perform_network_threshold_signing; + + fee_result.processing_fee = fee_result + .processing_fee + .checked_add(operation_cost) + .ok_or(ExecutionError::Overflow( + "execution processing fee overflow error", + ))?; + } } } Ok(()) diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/check_tx_verification/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/check_tx_verification/v0/mod.rs index dde9c1e1f3..acd1515749 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/check_tx_verification/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/check_tx_verification/v0/mod.rs @@ -135,6 +135,8 @@ pub(super) fn state_transition_to_execution_event_for_check_tx_v0<'a, C: CoreRPC // Validating structure let result = state_transition.validate_advanced_structure_from_state( + platform.state.last_block_info(), + platform.config.network, &action, maybe_identity.as_ref(), &mut state_transition_execution_context, diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/common/validate_state_transition_identity_signed/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/common/validate_state_transition_identity_signed/v0/mod.rs index 4e316a7af0..5d411c02a2 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/common/validate_state_transition_identity_signed/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/common/validate_state_transition_identity_signed/v0/mod.rs @@ -74,18 +74,12 @@ impl<'a> ValidateStateTransitionIdentitySignatureV0<'a> for StateTransition { let owner_id = self.owner_id(); - let security_levels = - self.security_level_requirement() + let allowed_purposes = + self.purpose_requirement() .ok_or(ProtocolError::CorruptedCodeExecution( - "state_transition does not have security level".to_string(), + "state_transition does not have a key purpose requirement".to_string(), ))?; - let purpose = self - .purpose_requirement() - .ok_or(ProtocolError::CorruptedCodeExecution( - "state_transition does not have a key purpose requirement".to_string(), - ))?; - let key_request = IdentityKeysRequest::new_specific_key_query(owner_id.as_bytes(), key_id); let maybe_partial_identity = match (request_identity_balance, request_identity_revision) { @@ -169,13 +163,19 @@ impl<'a> ValidateStateTransitionIdentitySignatureV0<'a> for StateTransition { return Ok(validation_result); } - if purpose != public_key.purpose() { + if !allowed_purposes.contains(&public_key.purpose()) { validation_result.add_error(SignatureError::InvalidSignaturePublicKeyPurposeError( - InvalidSignaturePublicKeyPurposeError::new(public_key.purpose(), purpose), + InvalidSignaturePublicKeyPurposeError::new(public_key.purpose(), allowed_purposes), )); return Ok(validation_result); } + let security_levels = self + .security_level_requirement(public_key.purpose()) + .ok_or(ProtocolError::CorruptedCodeExecution( + "state_transition does not have security level".to_string(), + ))?; + if !security_levels.contains(&public_key.security_level()) { validation_result.add_error( SignatureError::InvalidSignaturePublicKeySecurityLevelError( diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/processor/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/processor/v0/mod.rs index 46ab19c2fd..f1210e3c0f 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/processor/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/processor/v0/mod.rs @@ -1,3 +1,4 @@ +use crate::error::execution::ExecutionError; use crate::error::Error; use crate::execution::types::execution_event::ExecutionEvent; use crate::execution::validation::state_transition::transformer::StateTransitionActionTransformerV0; @@ -5,21 +6,20 @@ use crate::platform_types::platform::{PlatformRef, PlatformStateRef}; use crate::platform_types::platform_state::v0::PlatformStateV0Methods; use crate::rpc::core::CoreRPCLike; use dpp::block::block_info::BlockInfo; +use dpp::dashcore::Network; use dpp::fee::Credits; use dpp::identity::PartialIdentity; use dpp::prefunded_specialized_balance::PrefundedSpecializedBalanceIdentifier; use dpp::prelude::ConsensusValidationResult; -use dpp::ProtocolError; -use std::collections::BTreeMap; - -use crate::error::execution::ExecutionError; use dpp::serialization::Signable; use dpp::state_transition::StateTransition; use dpp::validation::SimpleConsensusValidationResult; use dpp::version::{DefaultForPlatformVersion, PlatformVersion}; +use dpp::ProtocolError; use drive::drive::Drive; use drive::grovedb::TransactionArg; use drive::state_transition_action::StateTransitionAction; +use std::collections::BTreeMap; use crate::execution::types::state_transition_execution_context::{StateTransitionExecutionContext}; use crate::execution::validation::state_transition::common::validate_simple_pre_check_balance::ValidateSimplePreCheckBalance; @@ -29,6 +29,7 @@ use crate::execution::validation::state_transition::identity_top_up::StateTransi use crate::execution::validation::state_transition::state_transitions::identity_update::advanced_structure::v0::IdentityUpdateStateTransitionIdentityAndSignaturesValidationV0; use crate::execution::validation::state_transition::state_transitions::identity_top_up::identity_retrieval::v0::IdentityTopUpStateTransitionIdentityRetrievalV0; use crate::execution::validation::state_transition::ValidationMode; +use crate::execution::validation::state_transition::state_transitions::identity_credit_withdrawal::signature_purpose_matches_requirements::IdentityCreditWithdrawalStateTransitionSignaturePurposeMatchesRequirementsValidation; pub(super) fn process_state_transition_v0<'a, C: CoreRPCLike>( platform: &'a PlatformRef, block_info: &BlockInfo, @@ -214,6 +215,8 @@ pub(super) fn process_state_transition_v0<'a, C: CoreRPCLike>( // Validating structure let result = state_transition.validate_advanced_structure_from_state( + block_info, + platform.config.network, &action, maybe_identity.as_ref(), &mut state_transition_execution_context, @@ -402,6 +405,8 @@ pub(crate) trait StateTransitionStructureKnownInStateValidationV0 { /// * `Result` - A result with either a SimpleConsensusValidationResult or an Error. fn validate_advanced_structure_from_state( &self, + block_info: &BlockInfo, + network: Network, action: &StateTransitionAction, maybe_identity: Option<&PartialIdentity>, execution_context: &mut StateTransitionExecutionContext, @@ -745,6 +750,8 @@ impl StateTransitionAdvancedStructureValidationV0 for StateTransition { impl StateTransitionStructureKnownInStateValidationV0 for StateTransition { fn validate_advanced_structure_from_state( &self, + block_info: &BlockInfo, + network: Network, action: &StateTransitionAction, maybe_identity: Option<&PartialIdentity>, execution_context: &mut StateTransitionExecutionContext, @@ -752,6 +759,8 @@ impl StateTransitionStructureKnownInStateValidationV0 for StateTransition { ) -> Result, Error> { match self { StateTransition::DocumentsBatch(st) => st.validate_advanced_structure_from_state( + block_info, + network, action, maybe_identity, execution_context, @@ -773,6 +782,8 @@ impl StateTransitionStructureKnownInStateValidationV0 for StateTransition { ) } StateTransition::MasternodeVote(st) => st.validate_advanced_structure_from_state( + block_info, + network, action, maybe_identity, execution_context, @@ -810,7 +821,6 @@ impl StateTransitionIdentityBasedSignatureValidationV0 for StateTransition { match self { StateTransition::DataContractCreate(_) | StateTransition::DataContractUpdate(_) - | StateTransition::IdentityCreditWithdrawal(_) | StateTransition::IdentityCreditTransfer(_) | StateTransition::DocumentsBatch(_) => { //Basic signature verification @@ -823,6 +833,29 @@ impl StateTransitionIdentityBasedSignatureValidationV0 for StateTransition { platform_version, )?) } + StateTransition::IdentityCreditWithdrawal(credit_withdrawal) => { + let mut consensus_validation_result = self + .validate_state_transition_identity_signed( + drive, + true, + false, + tx, + execution_context, + platform_version, + )?; + + if consensus_validation_result.is_valid_with_data() { + let validation_result = credit_withdrawal + .validate_signature_purpose_matches_requirements( + consensus_validation_result.data.as_ref().unwrap(), + platform_version, + )?; + if !validation_result.is_valid() { + consensus_validation_result.add_errors(validation_result.errors); + } + } + Ok(consensus_validation_result) + } StateTransition::IdentityUpdate(_) => { //Basic signature verification Ok(self.validate_state_transition_identity_signed( diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/action_validation/document_create_transition_action/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/action_validation/document_create_transition_action/mod.rs index bff6309b3d..7dfa5e8eba 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/action_validation/document_create_transition_action/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/action_validation/document_create_transition_action/mod.rs @@ -1,3 +1,4 @@ +use dashcore_rpc::dashcore::Network; use dpp::block::block_info::BlockInfo; use dpp::identifier::Identifier; use dpp::validation::SimpleConsensusValidationResult; @@ -20,6 +21,8 @@ pub trait DocumentCreateTransitionActionValidation { fn validate_structure( &self, owner_id: Identifier, + block_info: &BlockInfo, + network: Network, platform_version: &PlatformVersion, ) -> Result; @@ -38,6 +41,8 @@ impl DocumentCreateTransitionActionValidation for DocumentCreateTransitionAction fn validate_structure( &self, owner_id: Identifier, + block_info: &BlockInfo, + network: Network, platform_version: &PlatformVersion, ) -> Result { match platform_version @@ -47,7 +52,7 @@ impl DocumentCreateTransitionActionValidation for DocumentCreateTransitionAction .documents_batch_state_transition .document_create_transition_structure_validation { - 0 => self.validate_structure_v0(owner_id, platform_version), + 0 => self.validate_structure_v0(owner_id, block_info, network, platform_version), version => Err(Error::Execution(ExecutionError::UnknownVersionMismatch { method: "DocumentCreateTransitionAction::validate_structure".to_string(), known_versions: vec![0], diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/action_validation/document_create_transition_action/structure_v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/action_validation/document_create_transition_action/structure_v0/mod.rs index 1fbfb2096a..7ae98cf477 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/action_validation/document_create_transition_action/structure_v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/action_validation/document_create_transition_action/structure_v0/mod.rs @@ -1,6 +1,10 @@ +use dpp::block::block_info::BlockInfo; use dpp::consensus::basic::document::{DocumentCreationNotAllowedError, InvalidDocumentTypeError}; +use dpp::consensus::state::document::document_contest_not_paid_for_error::DocumentContestNotPaidForError; +use dpp::dashcore::Network; use dpp::data_contract::accessors::v0::DataContractV0Getters; use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters; +use dpp::data_contract::document_type::methods::DocumentTypeV0Methods; use dpp::data_contract::document_type::restricted_creation::CreationRestrictionMode; use dpp::data_contract::validate_document::DataContractDocumentValidationMethodsV0; use dpp::identifier::Identifier; @@ -14,6 +18,8 @@ pub(super) trait DocumentCreateTransitionActionStructureValidationV0 { fn validate_structure_v0( &self, owner_id: Identifier, + block_info: &BlockInfo, + network: Network, platform_version: &PlatformVersion, ) -> Result; } @@ -21,6 +27,8 @@ impl DocumentCreateTransitionActionStructureValidationV0 for DocumentCreateTrans fn validate_structure_v0( &self, owner_id: Identifier, + block_info: &BlockInfo, + network: Network, platform_version: &PlatformVersion, ) -> Result { let contract_fetch_info = self.base().data_contract_fetch_info(); @@ -36,6 +44,40 @@ impl DocumentCreateTransitionActionStructureValidationV0 for DocumentCreateTrans )); }; + // Don't do the following validation on testnet before epoch 2080 + // As state transitions already happened that would break this validation + // We want to keep both if-s for better readability + #[allow(clippy::collapsible_if)] + if !(network == Network::Testnet && block_info.epoch.index < 2080) { + // Only for contested documents + if document_type + .contested_vote_poll_for_document_properties(self.data(), platform_version)? + .is_some() + { + let expected_amount = platform_version + .fee_version + .vote_resolution_fund_fees + .contested_document_vote_resolution_fund_required_amount; + if let Some((_, paid_amount)) = self.prefunded_voting_balance() { + if expected_amount != *paid_amount { + return Ok(SimpleConsensusValidationResult::new_with_error( + DocumentContestNotPaidForError::new( + self.base().id(), + expected_amount, + *paid_amount, + ) + .into(), + )); + } + } else { + return Ok(SimpleConsensusValidationResult::new_with_error( + DocumentContestNotPaidForError::new(self.base().id(), expected_amount, 0) + .into(), + )); + } + } + } + match document_type.creation_restriction_mode() { CreationRestrictionMode::NoRestrictions => {} CreationRestrictionMode::OwnerOnly => { diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/advanced_structure/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/advanced_structure/v0/mod.rs index 6c9f7b93b4..5ac5d1630d 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/advanced_structure/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/advanced_structure/v0/mod.rs @@ -1,6 +1,8 @@ use crate::error::Error; +use dpp::block::block_info::BlockInfo; use dpp::consensus::basic::document::InvalidDocumentTransitionIdError; use dpp::consensus::signature::{InvalidSignaturePublicKeySecurityLevelError, SignatureError}; +use dpp::dashcore::Network; use dpp::document::Document; use dpp::identity::identity_public_key::accessors::v0::IdentityPublicKeyGettersV0; use dpp::identity::PartialIdentity; @@ -36,6 +38,8 @@ pub(in crate::execution::validation::state_transition::state_transitions::docume { fn validate_advanced_structure_from_state_v0( &self, + block_info: &BlockInfo, + network: Network, action: &DocumentsBatchTransitionAction, identity: &PartialIdentity, execution_context: &mut StateTransitionExecutionContext, @@ -46,6 +50,8 @@ pub(in crate::execution::validation::state_transition::state_transitions::docume impl DocumentsBatchStateTransitionStructureValidationV0 for DocumentsBatchTransition { fn validate_advanced_structure_from_state_v0( &self, + block_info: &BlockInfo, + network: Network, action: &DocumentsBatchTransitionAction, identity: &PartialIdentity, execution_context: &mut StateTransitionExecutionContext, @@ -119,7 +125,12 @@ impl DocumentsBatchStateTransitionStructureValidationV0 for DocumentsBatchTransi for transition in action.transitions() { match transition { DocumentTransitionAction::CreateAction(create_action) => { - let result = create_action.validate_structure(identity.id, platform_version)?; + let result = create_action.validate_structure( + identity.id, + block_info, + network, + platform_version, + )?; if !result.is_valid() { let bump_action = StateTransitionAction::BumpIdentityDataContractNonceAction( BumpIdentityDataContractNonceAction::from_borrowed_document_base_transition_action(transition.base().expect("there is always a base for the create action"), self.owner_id(), self.user_fee_increase()), diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/mod.rs index eaa0f93bcc..1cb7c26a62 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/documents_batch/mod.rs @@ -8,6 +8,7 @@ mod state; mod transformer; use dpp::block::block_info::BlockInfo; +use dpp::dashcore::Network; use dpp::identity::PartialIdentity; use dpp::prelude::*; use dpp::state_transition::documents_batch_transition::DocumentsBatchTransition; @@ -137,6 +138,8 @@ impl StateTransitionNonceValidationV0 for DocumentsBatchTransition { impl StateTransitionStructureKnownInStateValidationV0 for DocumentsBatchTransition { fn validate_advanced_structure_from_state( &self, + block_info: &BlockInfo, + network: Network, action: &StateTransitionAction, identity: Option<&PartialIdentity>, execution_context: &mut StateTransitionExecutionContext, @@ -162,6 +165,8 @@ impl StateTransitionStructureKnownInStateValidationV0 for DocumentsBatchTransiti ))); }; self.validate_advanced_structure_from_state_v0( + block_info, + network, documents_batch_transition_action, identity, execution_context, @@ -299,6 +304,14 @@ mod tests { use crate::platform_types::state_transitions_processing_result::StateTransitionExecutionResult::PaidConsensusError; use crate::test::helpers::fast_forward_to_block::fast_forward_to_block; use dpp::consensus::state::state_error::StateError; + use dpp::dashcore::Network; + use dpp::dashcore::Network::Testnet; + use dpp::identity::SecurityLevel; + use dpp::state_transition::documents_batch_transition::document_base_transition::DocumentBaseTransition; + use dpp::state_transition::documents_batch_transition::document_create_transition::DocumentCreateTransitionV0; + use dpp::state_transition::documents_batch_transition::{DocumentCreateTransition, DocumentsBatchTransitionV0}; + use dpp::state_transition::StateTransition; + use crate::config::PlatformConfig; #[test] fn test_document_creation() { @@ -1111,6 +1124,557 @@ mod tests { assert_eq!(second_contender.vote_tally(), Some(0)); } + #[test] + fn test_document_creation_on_contested_unique_index_should_fail_if_not_paying_for_it() { + let platform_version = PlatformVersion::latest(); + let platform_config = PlatformConfig { + network: Network::Dash, + ..Default::default() + }; + let mut platform = TestPlatformBuilder::new() + .with_latest_protocol_version() + .with_config(platform_config) + .build_with_mock_rpc() + .set_genesis_state(); + + let mut rng = StdRng::seed_from_u64(433); + + let platform_state = platform.state.load(); + + let (identity_1, signer_1, key_1) = + setup_identity(&mut platform, 958, dash_to_credits!(0.5)); + + let dpns = platform.drive.cache.system_data_contracts.load_dpns(); + let dpns_contract = dpns.clone(); + + let preorder = dpns_contract + .document_type_for_name("preorder") + .expect("expected a profile document type"); + + assert!(!preorder.documents_mutable()); + assert!(preorder.documents_can_be_deleted()); + assert!(!preorder.documents_transferable().is_transferable()); + + let domain = dpns_contract + .document_type_for_name("domain") + .expect("expected a profile document type"); + + assert!(!domain.documents_mutable()); + // Deletion is disabled with data trigger + assert!(domain.documents_can_be_deleted()); + assert!(domain.documents_transferable().is_transferable()); + + let entropy = Bytes32::random_with_rng(&mut rng); + + let mut preorder_document_1 = preorder + .random_document_with_identifier_and_entropy( + &mut rng, + identity_1.id(), + entropy, + DocumentFieldFillType::FillIfNotRequired, + DocumentFieldFillSize::AnyDocumentFillSize, + platform_version, + ) + .expect("expected a random document"); + + let mut document_1 = domain + .random_document_with_identifier_and_entropy( + &mut rng, + identity_1.id(), + entropy, + DocumentFieldFillType::FillIfNotRequired, + DocumentFieldFillSize::AnyDocumentFillSize, + platform_version, + ) + .expect("expected a random document"); + + document_1.set("parentDomainName", "dash".into()); + document_1.set("normalizedParentDomainName", "dash".into()); + document_1.set("label", "quantum".into()); + document_1.set("normalizedLabel", "quantum".into()); + document_1.set("records.identity", document_1.owner_id().into()); + document_1.set("subdomainRules.allowSubdomains", false.into()); + + let salt_1: [u8; 32] = rng.gen(); + + let mut salted_domain_buffer_1: Vec = vec![]; + salted_domain_buffer_1.extend(salt_1); + salted_domain_buffer_1.extend("quantum.dash".as_bytes()); + + let salted_domain_hash_1 = hash_double(salted_domain_buffer_1); + + preorder_document_1.set("saltedDomainHash", salted_domain_hash_1.into()); + + document_1.set("preorderSalt", salt_1.into()); + + let documents_batch_create_preorder_transition_1 = + DocumentsBatchTransition::new_document_creation_transition_from_document( + preorder_document_1, + preorder, + entropy.0, + &key_1, + 2, + 0, + &signer_1, + platform_version, + None, + None, + None, + ) + .expect("expect to create documents batch transition"); + + let documents_batch_create_serialized_preorder_transition_1 = + documents_batch_create_preorder_transition_1 + .serialize_to_bytes() + .expect("expected documents batch serialized state transition"); + + let owner_id = document_1.owner_id(); + let create_transition: DocumentCreateTransition = DocumentCreateTransitionV0 { + base: DocumentBaseTransition::from_document( + &document_1, + domain, + 3, + platform_version, + None, + ) + .expect("expected a base transition"), + entropy: entropy.0, + data: document_1.clone().properties_consumed(), + // Sending 0 balance that should not be valid + prefunded_voting_balance: None, + } + .into(); + let documents_batch_inner_create_transition_1: DocumentsBatchTransition = + DocumentsBatchTransitionV0 { + owner_id, + transitions: vec![create_transition.into()], + user_fee_increase: 0, + signature_public_key_id: 0, + signature: Default::default(), + } + .into(); + let mut documents_batch_create_transition_1: StateTransition = + documents_batch_inner_create_transition_1.into(); + documents_batch_create_transition_1 + .sign_external(&key_1, &signer_1, Some(|_, _| Ok(SecurityLevel::HIGH))) + .expect("expected to sign"); + + let documents_batch_create_serialized_transition_1 = + documents_batch_create_transition_1 + .serialize_to_bytes() + .expect("expected documents batch serialized state transition"); + + let transaction = platform.drive.grove.start_transaction(); + + let processing_result = platform + .platform + .process_raw_state_transitions( + &vec![documents_batch_create_serialized_preorder_transition_1.clone()], + &platform_state, + &BlockInfo::default(), + &transaction, + platform_version, + false, + None, + ) + .expect("expected to process state transition"); + + platform + .drive + .grove + .commit_transaction(transaction) + .unwrap() + .expect("expected to commit transaction"); + + assert_eq!(processing_result.valid_count(), 1); + + let transaction = platform.drive.grove.start_transaction(); + + let processing_result = platform + .platform + .process_raw_state_transitions( + &vec![documents_batch_create_serialized_transition_1.clone()], + &platform_state, + &BlockInfo::default(), + &transaction, + platform_version, + false, + None, + ) + .expect("expected to process state transition"); + + platform + .drive + .grove + .commit_transaction(transaction) + .unwrap() + .expect("expected to commit transaction"); + + assert_matches!( + processing_result.execution_results().as_slice(), + [PaidConsensusError( + ConsensusError::StateError(StateError::DocumentContestNotPaidForError(_)), + _ + )] + ); + + // Now let's run a query for the vote totals + + let config = bincode::config::standard() + .with_big_endian() + .with_no_limit(); + + let dash_encoded = bincode::encode_to_vec(Value::Text("dash".to_string()), config) + .expect("expected to encode the word dash"); + + let quantum_encoded = + bincode::encode_to_vec(Value::Text("quantum".to_string()), config) + .expect("expected to encode the word quantum"); + + let index_name = "parentNameAndLabel".to_string(); + + let query_validation_result = platform + .query_contested_resource_vote_state( + GetContestedResourceVoteStateRequest { + version: Some(get_contested_resource_vote_state_request::Version::V0( + GetContestedResourceVoteStateRequestV0 { + contract_id: dpns_contract.id().to_vec(), + document_type_name: domain.name().clone(), + index_name: index_name.clone(), + index_values: vec![dash_encoded.clone(), quantum_encoded.clone()], + result_type: ResultType::DocumentsAndVoteTally as i32, + allow_include_locked_and_abstaining_vote_tally: false, + start_at_identifier_info: None, + count: None, + prove: false, + }, + )), + }, + &platform_state, + platform_version, + ) + .expect("expected to execute query") + .into_data() + .expect("expected query to be valid"); + + let get_contested_resource_vote_state_response::Version::V0( + GetContestedResourceVoteStateResponseV0 { + metadata: _, + result, + }, + ) = query_validation_result.version.expect("expected a version"); + + let Some( + get_contested_resource_vote_state_response_v0::Result::ContestedResourceContenders( + get_contested_resource_vote_state_response_v0::ContestedResourceContenders { + contenders, + abstain_vote_tally, + lock_vote_tally, + finished_vote_info, + }, + ), + ) = result + else { + panic!("expected contenders") + }; + + assert_eq!(abstain_vote_tally, None); + + assert_eq!(lock_vote_tally, None); + + assert_eq!(finished_vote_info, None); + + assert_eq!(contenders.len(), 0); + + let drive_query = DriveDocumentQuery::new_primary_key_single_item_query( + &dpns, + domain, + document_1.id(), + ); + + let documents = platform + .drive + .query_documents(drive_query, None, false, None, None) + .expect("expected to get back documents") + .documents_owned(); + + assert!(documents.first().is_none()); + } + + #[test] + fn test_document_creation_on_contested_unique_index_should_not_fail_if_not_paying_for_it_on_testnet_before_epoch_2080( + ) { + let platform_version = PlatformVersion::latest(); + let platform_config = PlatformConfig { + network: Testnet, + ..Default::default() + }; + let mut platform = TestPlatformBuilder::new() + .with_latest_protocol_version() + .with_config(platform_config) + .build_with_mock_rpc() + .set_genesis_state(); + + let mut rng = StdRng::seed_from_u64(433); + + let platform_state = platform.state.load(); + + let (identity_1, signer_1, key_1) = + setup_identity(&mut platform, 958, dash_to_credits!(0.5)); + + let dpns = platform.drive.cache.system_data_contracts.load_dpns(); + let dpns_contract = dpns.clone(); + + let preorder = dpns_contract + .document_type_for_name("preorder") + .expect("expected a profile document type"); + + assert!(!preorder.documents_mutable()); + assert!(preorder.documents_can_be_deleted()); + assert!(!preorder.documents_transferable().is_transferable()); + + let domain = dpns_contract + .document_type_for_name("domain") + .expect("expected a profile document type"); + + assert!(!domain.documents_mutable()); + // Deletion is disabled with data trigger + assert!(domain.documents_can_be_deleted()); + assert!(domain.documents_transferable().is_transferable()); + + let entropy = Bytes32::random_with_rng(&mut rng); + + let mut preorder_document_1 = preorder + .random_document_with_identifier_and_entropy( + &mut rng, + identity_1.id(), + entropy, + DocumentFieldFillType::FillIfNotRequired, + DocumentFieldFillSize::AnyDocumentFillSize, + platform_version, + ) + .expect("expected a random document"); + + let mut document_1 = domain + .random_document_with_identifier_and_entropy( + &mut rng, + identity_1.id(), + entropy, + DocumentFieldFillType::FillIfNotRequired, + DocumentFieldFillSize::AnyDocumentFillSize, + platform_version, + ) + .expect("expected a random document"); + + document_1.set("parentDomainName", "dash".into()); + document_1.set("normalizedParentDomainName", "dash".into()); + document_1.set("label", "quantum".into()); + document_1.set("normalizedLabel", "quantum".into()); + document_1.set("records.identity", document_1.owner_id().into()); + document_1.set("subdomainRules.allowSubdomains", false.into()); + + let salt_1: [u8; 32] = rng.gen(); + + let mut salted_domain_buffer_1: Vec = vec![]; + salted_domain_buffer_1.extend(salt_1); + salted_domain_buffer_1.extend("quantum.dash".as_bytes()); + + let salted_domain_hash_1 = hash_double(salted_domain_buffer_1); + + preorder_document_1.set("saltedDomainHash", salted_domain_hash_1.into()); + + document_1.set("preorderSalt", salt_1.into()); + + let documents_batch_create_preorder_transition_1 = + DocumentsBatchTransition::new_document_creation_transition_from_document( + preorder_document_1, + preorder, + entropy.0, + &key_1, + 2, + 0, + &signer_1, + platform_version, + None, + None, + None, + ) + .expect("expect to create documents batch transition"); + + let documents_batch_create_serialized_preorder_transition_1 = + documents_batch_create_preorder_transition_1 + .serialize_to_bytes() + .expect("expected documents batch serialized state transition"); + + let owner_id = document_1.owner_id(); + let create_transition: DocumentCreateTransition = DocumentCreateTransitionV0 { + base: DocumentBaseTransition::from_document( + &document_1, + domain, + 3, + platform_version, + None, + ) + .expect("expected a base transition"), + entropy: entropy.0, + data: document_1.clone().properties_consumed(), + prefunded_voting_balance: None, + } + .into(); + let documents_batch_inner_create_transition_1: DocumentsBatchTransition = + DocumentsBatchTransitionV0 { + owner_id, + transitions: vec![create_transition.into()], + user_fee_increase: 0, + signature_public_key_id: 0, + signature: Default::default(), + } + .into(); + let mut documents_batch_create_transition_1: StateTransition = + documents_batch_inner_create_transition_1.into(); + documents_batch_create_transition_1 + .sign_external(&key_1, &signer_1, Some(|_, _| Ok(SecurityLevel::HIGH))) + .expect("expected to sign"); + + let documents_batch_create_serialized_transition_1 = + documents_batch_create_transition_1 + .serialize_to_bytes() + .expect("expected documents batch serialized state transition"); + + let transaction = platform.drive.grove.start_transaction(); + + let processing_result = platform + .platform + .process_raw_state_transitions( + &vec![documents_batch_create_serialized_preorder_transition_1.clone()], + &platform_state, + &BlockInfo::default(), + &transaction, + platform_version, + false, + None, + ) + .expect("expected to process state transition"); + + platform + .drive + .grove + .commit_transaction(transaction) + .unwrap() + .expect("expected to commit transaction"); + + assert_eq!(processing_result.valid_count(), 1); + + let transaction = platform.drive.grove.start_transaction(); + + let processing_result = platform + .platform + .process_raw_state_transitions( + &vec![documents_batch_create_serialized_transition_1.clone()], + &platform_state, + &BlockInfo::default(), + &transaction, + platform_version, + false, + None, + ) + .expect("expected to process state transition"); + + platform + .drive + .grove + .commit_transaction(transaction) + .unwrap() + .expect("expected to commit transaction"); + + assert_matches!( + processing_result.execution_results().as_slice(), + [StateTransitionExecutionResult::SuccessfulExecution(..)] + ); + + // Now let's run a query for the vote totals + + let config = bincode::config::standard() + .with_big_endian() + .with_no_limit(); + + let dash_encoded = bincode::encode_to_vec(Value::Text("dash".to_string()), config) + .expect("expected to encode the word dash"); + + let quantum_encoded = + bincode::encode_to_vec(Value::Text("quantum".to_string()), config) + .expect("expected to encode the word quantum"); + + let index_name = "parentNameAndLabel".to_string(); + + let query_validation_result = platform + .query_contested_resource_vote_state( + GetContestedResourceVoteStateRequest { + version: Some(get_contested_resource_vote_state_request::Version::V0( + GetContestedResourceVoteStateRequestV0 { + contract_id: dpns_contract.id().to_vec(), + document_type_name: domain.name().clone(), + index_name: index_name.clone(), + index_values: vec![dash_encoded.clone(), quantum_encoded.clone()], + result_type: ResultType::DocumentsAndVoteTally as i32, + allow_include_locked_and_abstaining_vote_tally: false, + start_at_identifier_info: None, + count: None, + prove: false, + }, + )), + }, + &platform_state, + platform_version, + ) + .expect("expected to execute query") + .into_data() + .expect("expected query to be valid"); + + let get_contested_resource_vote_state_response::Version::V0( + GetContestedResourceVoteStateResponseV0 { + metadata: _, + result, + }, + ) = query_validation_result.version.expect("expected a version"); + + let Some( + get_contested_resource_vote_state_response_v0::Result::ContestedResourceContenders( + get_contested_resource_vote_state_response_v0::ContestedResourceContenders { + contenders, + abstain_vote_tally, + lock_vote_tally, + finished_vote_info, + }, + ), + ) = result + else { + panic!("expected contenders") + }; + + assert_eq!(abstain_vote_tally, None); + + assert_eq!(lock_vote_tally, None); + + assert_eq!(finished_vote_info, None); + + assert_eq!(contenders.len(), 0); // no contenders should have been created the document should just exist + + let drive_query = DriveDocumentQuery::new_primary_key_single_item_query( + &dpns, + domain, + document_1.id(), + ); + + let documents = platform + .drive + .query_documents(drive_query, None, false, None, None) + .expect("expected to get back documents") + .documents_owned(); + + assert!(documents.first().is_some()); + } + #[test] fn test_document_creation_on_contested_unique_index_should_fail_if_reusing_entropy() { let platform_version = PlatformVersion::latest(); diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/identity_credit_withdrawal/balance/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/identity_credit_withdrawal/balance/v0/mod.rs index 0c1b879b0f..0843ed7ec1 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/identity_credit_withdrawal/balance/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/identity_credit_withdrawal/balance/v0/mod.rs @@ -30,7 +30,11 @@ impl IdentityCreditTransferTransitionBalanceValidationV0 for IdentityCreditWithd "expected to have a balance on identity for credit withdrawal transition", )))?; - if balance < self.amount().checked_add(platform_version.fee_version.state_transition_min_fees.credit_withdrawal).ok_or(Error::Execution(ExecutionError::Overflow("overflow when adding amount and min_leftover_credits_before_processing in identity credit withdrawal")))? { + let amount_and_fees = self.amount() + .checked_add(platform_version.fee_version.state_transition_min_fees.credit_withdrawal) + .ok_or_else(|| Error::Execution(ExecutionError::Overflow("overflow when adding amount and min_leftover_credits_before_processing in identity credit withdrawal")))?; + + if balance < amount_and_fees { return Ok(SimpleConsensusValidationResult::new_with_error( IdentityInsufficientBalanceError::new(self.identity_id(), balance, self.amount()) .into(), @@ -40,3 +44,96 @@ impl IdentityCreditTransferTransitionBalanceValidationV0 for IdentityCreditWithd Ok(SimpleConsensusValidationResult::new()) } } + +#[cfg(test)] +mod tests { + use super::*; + + use assert_matches::assert_matches; + use dpp::consensus::state::state_error::StateError; + use dpp::consensus::ConsensusError; + use dpp::prelude::Identifier; + use dpp::state_transition::identity_credit_withdrawal_transition::v0::IdentityCreditWithdrawalTransitionV0; + use platform_version::version::v1::PLATFORM_V1; + + mod validate_advanced_minimum_balance_pre_check_v0 { + use super::*; + + #[test] + fn should_return_invalid_result_if_balance_is_less_than_amount_and_fees() { + let balance = 100; + + let amount = 200; + + let identity = PartialIdentity { + id: Identifier::random(), + loaded_public_keys: Default::default(), + balance: Some(balance), + revision: None, + not_found_public_keys: Default::default(), + }; + + let transaction = + IdentityCreditWithdrawalTransition::V0(IdentityCreditWithdrawalTransitionV0 { + identity_id: identity.id, + amount, + core_fee_per_byte: 0, + pooling: Default::default(), + output_script: Default::default(), + nonce: 0, + user_fee_increase: 0, + signature_public_key_id: 0, + signature: Default::default(), + }); + + let platform_version = &PLATFORM_V1; + + let result = transaction + .validate_advanced_minimum_balance_pre_check_v0(&identity, platform_version) + .expect("failed to validate minimum balance"); + + assert_matches!( + result.errors.as_slice(), + [ConsensusError::StateError( + StateError::IdentityInsufficientBalanceError(err) + )] if err.balance() == balance && err.required_balance() == amount && err.identity_id() == &identity.id + ); + } + + #[test] + fn should_return_valid_result() { + let balance = 200000000000; + + let amount = 100; + + let identity = PartialIdentity { + id: Identifier::random(), + loaded_public_keys: Default::default(), + balance: Some(balance), + revision: None, + not_found_public_keys: Default::default(), + }; + + let transaction = + IdentityCreditWithdrawalTransition::V0(IdentityCreditWithdrawalTransitionV0 { + identity_id: Default::default(), + amount, + core_fee_per_byte: 0, + pooling: Default::default(), + output_script: Default::default(), + nonce: 0, + user_fee_increase: 0, + signature_public_key_id: 0, + signature: Default::default(), + }); + + let platform_version = &PLATFORM_V1; + + let result = transaction + .validate_advanced_minimum_balance_pre_check_v0(&identity, platform_version) + .expect("failed to validate minimum balance"); + + assert_matches!(result.errors.as_slice(), []); + } + } +} diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/identity_credit_withdrawal/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/identity_credit_withdrawal/mod.rs index 8e5f5155f2..3b42e8e744 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/identity_credit_withdrawal/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/identity_credit_withdrawal/mod.rs @@ -1,5 +1,6 @@ mod balance; mod nonce; +pub(crate) mod signature_purpose_matches_requirements; mod state; mod structure; @@ -31,10 +32,10 @@ impl StateTransitionActionTransformerV0 for IdentityCreditWithdrawalTransition { fn transform_into_action( &self, platform: &PlatformRef, - _block_info: &BlockInfo, + block_info: &BlockInfo, _validation_mode: ValidationMode, - _execution_context: &mut StateTransitionExecutionContext, - _tx: TransactionArg, + execution_context: &mut StateTransitionExecutionContext, + tx: TransactionArg, ) -> Result, Error> { let platform_version = platform.state.current_platform_version()?; @@ -45,7 +46,13 @@ impl StateTransitionActionTransformerV0 for IdentityCreditWithdrawalTransition { .identity_credit_withdrawal_state_transition .transform_into_action { - 0 => self.transform_into_action_v0(platform), + 0 => self.transform_into_action_v0( + platform, + block_info, + execution_context, + tx, + platform_version, + ), version => Err(Error::Execution(ExecutionError::UnknownVersionMismatch { method: "identity credit withdrawal transition: transform_into_action".to_string(), known_versions: vec![0], @@ -71,7 +78,7 @@ impl StateTransitionBasicStructureValidationV0 for IdentityCreditWithdrawalTrans // Returns not supported self.validate_basic_structure_v0(platform_version) } - Some(1) => self.validate_basic_structure_v1(), + Some(1) => self.validate_basic_structure_v1(platform_version), Some(version) => Err(Error::Execution(ExecutionError::UnknownVersionMismatch { method: "identity credit withdrawal transition: validate_basic_structure" .to_string(), @@ -93,8 +100,8 @@ impl StateTransitionStateValidationV0 for IdentityCreditWithdrawalTransition { _action: Option, platform: &PlatformRef, _validation_mode: ValidationMode, - _block_info: &BlockInfo, - _execution_context: &mut StateTransitionExecutionContext, + block_info: &BlockInfo, + execution_context: &mut StateTransitionExecutionContext, tx: TransactionArg, ) -> Result, Error> { let platform_version = platform.state.current_platform_version()?; @@ -106,7 +113,13 @@ impl StateTransitionStateValidationV0 for IdentityCreditWithdrawalTransition { .identity_credit_withdrawal_state_transition .state { - 0 => self.validate_state_v0(platform, tx), + 0 => self.validate_state_v0( + platform, + block_info, + execution_context, + tx, + platform_version, + ), version => Err(Error::Execution(ExecutionError::UnknownVersionMismatch { method: "identity credit withdrawal transition: validate_state".to_string(), known_versions: vec![0], @@ -119,7 +132,9 @@ impl StateTransitionStateValidationV0 for IdentityCreditWithdrawalTransition { #[cfg(test)] mod tests { use crate::config::{PlatformConfig, PlatformTestConfig}; - use crate::execution::validation::state_transition::tests::setup_identity_with_withdrawal_key_and_system_credits; + use crate::execution::validation::state_transition::tests::{ + setup_identity_with_withdrawal_key_and_system_credits, setup_masternode_owner_identity, + }; use crate::platform_types::state_transitions_processing_result::StateTransitionExecutionResult; use crate::test::helpers::fast_forward_to_block::fast_forward_to_block; use crate::test::helpers::setup::TestPlatformBuilder; @@ -129,10 +144,14 @@ mod tests { use dpp::consensus::ConsensusError; use dpp::dash_to_credits; use dpp::identity::core_script::CoreScript; + use dpp::identity::KeyType::{ECDSA_HASH160, ECDSA_SECP256K1}; use dpp::serialization::PlatformSerializable; - use dpp::state_transition::identity_credit_withdrawal_transition::methods::IdentityCreditWithdrawalTransitionMethodsV0; + use dpp::state_transition::identity_credit_withdrawal_transition::methods::{ + IdentityCreditWithdrawalTransitionMethodsV0, PreferredKeyPurposeForSigningWithdrawal, + }; use dpp::state_transition::identity_credit_withdrawal_transition::IdentityCreditWithdrawalTransition; use dpp::withdrawal::Pooling; + use platform_version::version::v1::PROTOCOL_VERSION_1; use platform_version::version::PlatformVersion; use rand::prelude::StdRng; use rand::{Rng, SeedableRng}; @@ -152,6 +171,7 @@ mod tests { let mut platform = TestPlatformBuilder::new() .with_config(platform_config) + .with_initial_protocol_version(PROTOCOL_VERSION_1) .build_with_mock_rpc() .set_initial_state_structure(); @@ -161,6 +181,7 @@ mod tests { setup_identity_with_withdrawal_key_and_system_credits( &mut platform, rng.gen(), + ECDSA_SECP256K1, dash_to_credits!(0.5), ); @@ -170,16 +191,17 @@ mod tests { let credit_withdrawal_transition = IdentityCreditWithdrawalTransition::try_from_identity( &identity, - Some(&withdrawal_key), - CoreScript::random_p2pkh(&mut rng), + Some(CoreScript::random_p2pkh(&mut rng)), withdrawal_amount, Pooling::Never, 1, 0, signer, + Some(&withdrawal_key), + PreferredKeyPurposeForSigningWithdrawal::Any, 2, platform_version, - None, + Some(1), ) .expect("expected a credit withdrawal transition"); @@ -209,4 +231,462 @@ mod tests { )] ); } + + #[test] + fn test_identity_credit_withdrawal_with_withdrawal_address_creates_withdrawal_document() { + let platform_version = PlatformVersion::latest(); + let platform_config = PlatformConfig { + testing_configs: PlatformTestConfig { + disable_instant_lock_signature_verification: true, + ..Default::default() + }, + ..Default::default() + }; + + let mut rng = StdRng::seed_from_u64(567); + + let mut platform = TestPlatformBuilder::new() + .with_config(platform_config) + .with_latest_protocol_version() + .build_with_mock_rpc() + .set_genesis_state(); + + fast_forward_to_block(&platform, 1_200_000_000, 900, 42, 1, false); //next epoch + + let (identity, signer, _, withdrawal_key) = + setup_identity_with_withdrawal_key_and_system_credits( + &mut platform, + rng.gen(), + ECDSA_SECP256K1, + dash_to_credits!(0.5), + ); + + let platform_state = platform.state.load(); + + let withdrawal_amount = dash_to_credits!(0.1); + + let credit_withdrawal_transition = IdentityCreditWithdrawalTransition::try_from_identity( + &identity, + Some(CoreScript::random_p2pkh(&mut rng)), + withdrawal_amount, + Pooling::Never, + 1, + 0, + signer, + Some(&withdrawal_key), + PreferredKeyPurposeForSigningWithdrawal::Any, + 2, + platform_version, + None, + ) + .expect("expected a credit withdrawal transition"); + + let credit_withdrawal_transition_serialized_transition = credit_withdrawal_transition + .serialize_to_bytes() + .expect("expected documents batch serialized state transition"); + + let transaction = platform.drive.grove.start_transaction(); + + let processing_result = platform + .platform + .process_raw_state_transitions( + &vec![credit_withdrawal_transition_serialized_transition.clone()], + &platform_state, + &BlockInfo::default_with_time(1_200_001_000), + &transaction, + platform_version, + false, + None, + ) + .expect("expected to process state transition"); + + assert_matches!( + processing_result.execution_results().as_slice(), + [StateTransitionExecutionResult::SuccessfulExecution(..)] + ); + } + + #[test] + fn test_identity_credit_withdrawal_without_withdrawal_address_creates_withdrawal_document_when_signing_with_withdrawal_key( + ) { + let platform_version = PlatformVersion::latest(); + let platform_config = PlatformConfig { + testing_configs: PlatformTestConfig { + disable_instant_lock_signature_verification: true, + ..Default::default() + }, + ..Default::default() + }; + + let mut rng = StdRng::seed_from_u64(567); + + let mut platform = TestPlatformBuilder::new() + .with_config(platform_config) + .with_latest_protocol_version() + .build_with_mock_rpc() + .set_genesis_state(); + + fast_forward_to_block(&platform, 1_200_000_000, 900, 42, 1, false); //next epoch + + let (identity, signer, _, withdrawal_key) = + setup_identity_with_withdrawal_key_and_system_credits( + &mut platform, + rng.gen(), + ECDSA_HASH160, + dash_to_credits!(0.5), + ); + + let platform_state = platform.state.load(); + + let withdrawal_amount = dash_to_credits!(0.1); + + let credit_withdrawal_transition = IdentityCreditWithdrawalTransition::try_from_identity( + &identity, + None, + withdrawal_amount, + Pooling::Never, + 1, + 0, + signer, + Some(&withdrawal_key), + PreferredKeyPurposeForSigningWithdrawal::TransferOnly, + 2, + platform_version, + None, + ) + .expect("expected a credit withdrawal transition"); + + let credit_withdrawal_transition_serialized_transition = credit_withdrawal_transition + .serialize_to_bytes() + .expect("expected documents batch serialized state transition"); + + let transaction = platform.drive.grove.start_transaction(); + + let processing_result = platform + .platform + .process_raw_state_transitions( + &vec![credit_withdrawal_transition_serialized_transition.clone()], + &platform_state, + &BlockInfo::default_with_time(1_200_001_000), + &transaction, + platform_version, + false, + None, + ) + .expect("expected to process state transition"); + + assert_matches!( + processing_result.execution_results().as_slice(), + [StateTransitionExecutionResult::SuccessfulExecution(..)] + ); + } + + #[test] + fn test_masternode_credit_withdrawal_without_withdrawal_address_creates_withdrawal_document_when_signing_with_withdrawal_key( + ) { + let platform_version = PlatformVersion::latest(); + let platform_config = PlatformConfig { + testing_configs: PlatformTestConfig { + disable_instant_lock_signature_verification: true, + ..Default::default() + }, + ..Default::default() + }; + + let mut rng = StdRng::seed_from_u64(529); + + let mut platform = TestPlatformBuilder::new() + .with_config(platform_config) + .with_latest_protocol_version() + .build_with_mock_rpc() + .set_genesis_state(); + + fast_forward_to_block(&platform, 1_200_000_000, 900, 42, 1, false); //next epoch + + let (identity, signer, _, _) = setup_masternode_owner_identity( + &mut platform, + rng.gen(), + dash_to_credits!(0.5), + platform_version, + ); + + let platform_state = platform.state.load(); + + let withdrawal_amount = dash_to_credits!(0.1); + + let credit_withdrawal_transition = IdentityCreditWithdrawalTransition::try_from_identity( + &identity, + None, + withdrawal_amount, + Pooling::Never, + 1, + 0, + signer, + None, + PreferredKeyPurposeForSigningWithdrawal::TransferOnly, + 2, + platform_version, + None, + ) + .expect("expected a credit withdrawal transition"); + + let credit_withdrawal_transition_serialized_transition = credit_withdrawal_transition + .serialize_to_bytes() + .expect("expected documents batch serialized state transition"); + + let transaction = platform.drive.grove.start_transaction(); + + let processing_result = platform + .platform + .process_raw_state_transitions( + &vec![credit_withdrawal_transition_serialized_transition.clone()], + &platform_state, + &BlockInfo::default_with_time(1_200_001_000), + &transaction, + platform_version, + false, + None, + ) + .expect("expected to process state transition"); + + assert_matches!( + processing_result.execution_results().as_slice(), + [StateTransitionExecutionResult::SuccessfulExecution(..)] + ); + } + + #[test] + fn test_masternode_credit_withdrawal_without_withdrawal_address_creates_withdrawal_document_when_signing_with_owner_key( + ) { + let platform_version = PlatformVersion::latest(); + let platform_config = PlatformConfig { + testing_configs: PlatformTestConfig { + disable_instant_lock_signature_verification: true, + ..Default::default() + }, + ..Default::default() + }; + + let mut rng = StdRng::seed_from_u64(529); + + let mut platform = TestPlatformBuilder::new() + .with_config(platform_config) + .with_latest_protocol_version() + .build_with_mock_rpc() + .set_genesis_state(); + + fast_forward_to_block(&platform, 1_200_000_000, 900, 42, 1, false); //next epoch + + let (identity, signer, _, _) = setup_masternode_owner_identity( + &mut platform, + rng.gen(), + dash_to_credits!(0.5), + platform_version, + ); + + let platform_state = platform.state.load(); + + let withdrawal_amount = dash_to_credits!(0.1); + + let credit_withdrawal_transition = IdentityCreditWithdrawalTransition::try_from_identity( + &identity, + None, + withdrawal_amount, + Pooling::Never, + 1, + 0, + signer, + None, + PreferredKeyPurposeForSigningWithdrawal::OwnerOnly, + 2, + platform_version, + None, + ) + .expect("expected a credit withdrawal transition"); + + let credit_withdrawal_transition_serialized_transition = credit_withdrawal_transition + .serialize_to_bytes() + .expect("expected documents batch serialized state transition"); + + let transaction = platform.drive.grove.start_transaction(); + + let processing_result = platform + .platform + .process_raw_state_transitions( + &vec![credit_withdrawal_transition_serialized_transition.clone()], + &platform_state, + &BlockInfo::default_with_time(1_200_001_000), + &transaction, + platform_version, + false, + None, + ) + .expect("expected to process state transition"); + + assert_matches!( + processing_result.execution_results().as_slice(), + [StateTransitionExecutionResult::SuccessfulExecution(..)] + ); + } + + mod errors { + use super::*; + use dpp::consensus::state::state_error::StateError; + #[test] + fn test_credit_withdrawal_without_withdrawal_address_with_a_non_payable_transfer_key() { + let platform_version = PlatformVersion::latest(); + let platform_config = PlatformConfig { + testing_configs: PlatformTestConfig { + disable_instant_lock_signature_verification: true, + ..Default::default() + }, + ..Default::default() + }; + + let mut rng = StdRng::seed_from_u64(567); + + let mut platform = TestPlatformBuilder::new() + .with_config(platform_config) + .with_latest_protocol_version() + .build_with_mock_rpc() + .set_genesis_state(); + + fast_forward_to_block(&platform, 1_200_000_000, 900, 42, 1, false); //next epoch + + let (identity, signer, _, withdrawal_key) = + setup_identity_with_withdrawal_key_and_system_credits( + &mut platform, + rng.gen(), + ECDSA_SECP256K1, + dash_to_credits!(0.5), + ); + + let platform_state = platform.state.load(); + + let withdrawal_amount = dash_to_credits!(0.1); + + let credit_withdrawal_transition = + IdentityCreditWithdrawalTransition::try_from_identity( + &identity, + None, + withdrawal_amount, + Pooling::Never, + 1, + 0, + signer, + Some(&withdrawal_key), + PreferredKeyPurposeForSigningWithdrawal::TransferOnly, + 2, + platform_version, + None, + ) + .expect("expected a credit withdrawal transition"); + + let credit_withdrawal_transition_serialized_transition = credit_withdrawal_transition + .serialize_to_bytes() + .expect("expected documents batch serialized state transition"); + + let transaction = platform.drive.grove.start_transaction(); + + let processing_result = platform + .platform + .process_raw_state_transitions( + &vec![credit_withdrawal_transition_serialized_transition.clone()], + &platform_state, + &BlockInfo::default_with_time(1_200_001_000), + &transaction, + platform_version, + false, + None, + ) + .expect("expected to process state transition"); + assert_matches!( + processing_result.execution_results().as_slice(), + [StateTransitionExecutionResult::UnpaidConsensusError( + ConsensusError::StateError( + StateError::NoTransferKeyForCoreWithdrawalAvailableError(_) + ) + )] + ); + } + + #[test] + fn test_masternode_credit_withdrawal_with_withdrawal_address_creates_when_signing_with_owner_key_should_fail( + ) { + let platform_version = PlatformVersion::latest(); + let platform_config = PlatformConfig { + testing_configs: PlatformTestConfig { + disable_instant_lock_signature_verification: true, + ..Default::default() + }, + ..Default::default() + }; + + let mut rng = StdRng::seed_from_u64(529); + + let mut platform = TestPlatformBuilder::new() + .with_config(platform_config) + .with_latest_protocol_version() + .build_with_mock_rpc() + .set_genesis_state(); + + fast_forward_to_block(&platform, 1_200_000_000, 900, 42, 1, false); //next epoch + + let (identity, signer, _, _) = setup_masternode_owner_identity( + &mut platform, + rng.gen(), + dash_to_credits!(0.5), + platform_version, + ); + + let platform_state = platform.state.load(); + + let withdrawal_amount = dash_to_credits!(0.1); + + let credit_withdrawal_transition = + IdentityCreditWithdrawalTransition::try_from_identity( + &identity, + Some(CoreScript::random_p2pkh(&mut rng)), + withdrawal_amount, + Pooling::Never, + 1, + 0, + signer, + None, + PreferredKeyPurposeForSigningWithdrawal::OwnerOnly, + 2, + platform_version, + None, + ) + .expect("expected a credit withdrawal transition"); + + let credit_withdrawal_transition_serialized_transition = credit_withdrawal_transition + .serialize_to_bytes() + .expect("expected documents batch serialized state transition"); + + let transaction = platform.drive.grove.start_transaction(); + + let processing_result = platform + .platform + .process_raw_state_transitions( + &vec![credit_withdrawal_transition_serialized_transition.clone()], + &platform_state, + &BlockInfo::default_with_time(1_200_001_000), + &transaction, + platform_version, + false, + None, + ) + .expect("expected to process state transition"); + + assert_matches!( + processing_result.execution_results().as_slice(), + [StateTransitionExecutionResult::UnpaidConsensusError( + ConsensusError::BasicError( + BasicError::WithdrawalOutputScriptNotAllowedWhenSigningWithOwnerKeyError(_) + ) + )] + ); + } + } } diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/identity_credit_withdrawal/signature_purpose_matches_requirements/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/identity_credit_withdrawal/signature_purpose_matches_requirements/mod.rs new file mode 100644 index 0000000000..d82846f84e --- /dev/null +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/identity_credit_withdrawal/signature_purpose_matches_requirements/mod.rs @@ -0,0 +1,45 @@ +pub(crate) mod v0; + +use crate::error::Error; +use dpp::identity::PartialIdentity; +use dpp::state_transition::identity_credit_withdrawal_transition::IdentityCreditWithdrawalTransition; +use dpp::validation::SimpleConsensusValidationResult; +use dpp::version::PlatformVersion; +use crate::error::execution::ExecutionError; +use crate::execution::validation::state_transition::identity_credit_withdrawal::signature_purpose_matches_requirements::v0::IdentityCreditWithdrawalStateTransitionSignaturePurposeMatchesRequirementsValidationV0; + +pub(in crate::execution::validation::state_transition) trait IdentityCreditWithdrawalStateTransitionSignaturePurposeMatchesRequirementsValidation +{ + fn validate_signature_purpose_matches_requirements( + &self, + identity: &PartialIdentity, + platform_version: &PlatformVersion, + ) -> Result; +} + +impl IdentityCreditWithdrawalStateTransitionSignaturePurposeMatchesRequirementsValidation + for IdentityCreditWithdrawalTransition +{ + fn validate_signature_purpose_matches_requirements( + &self, + identity: &PartialIdentity, + platform_version: &PlatformVersion, + ) -> Result { + match platform_version + .drive_abci + .validation_and_processing + .state_transitions + .identity_credit_withdrawal_state_transition_purpose_matches_requirements + { + 0 => self.validate_signature_purpose_matches_requirements_v0( + identity, + platform_version, + ), + version => Err(Error::Execution(ExecutionError::UnknownVersionMismatch { + method: "identity credit withdrawal transition: validate_signature_purpose_matches_requirements".to_string(), + known_versions: vec![0], + received: version, + })), + } + } +} diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/identity_credit_withdrawal/signature_purpose_matches_requirements/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/identity_credit_withdrawal/signature_purpose_matches_requirements/v0/mod.rs new file mode 100644 index 0000000000..4bdd1ff1a2 --- /dev/null +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/identity_credit_withdrawal/signature_purpose_matches_requirements/v0/mod.rs @@ -0,0 +1,53 @@ +use crate::error::execution::ExecutionError; +use crate::error::Error; +use dpp::consensus::basic::identity::WithdrawalOutputScriptNotAllowedWhenSigningWithOwnerKeyError; +use dpp::identity::identity_public_key::accessors::v0::IdentityPublicKeyGettersV0; +use dpp::identity::{PartialIdentity, Purpose}; +use dpp::state_transition::identity_credit_withdrawal_transition::accessors::IdentityCreditWithdrawalTransitionAccessorsV0; +use dpp::state_transition::identity_credit_withdrawal_transition::IdentityCreditWithdrawalTransition; +use dpp::state_transition::StateTransitionIdentitySigned; +use dpp::validation::SimpleConsensusValidationResult; +use dpp::version::PlatformVersion; + +pub(super) trait IdentityCreditWithdrawalStateTransitionSignaturePurposeMatchesRequirementsValidationV0 +{ + fn validate_signature_purpose_matches_requirements_v0( + &self, + identity: &PartialIdentity, + platform_version: &PlatformVersion, + ) -> Result; +} + +impl IdentityCreditWithdrawalStateTransitionSignaturePurposeMatchesRequirementsValidationV0 + for IdentityCreditWithdrawalTransition +{ + fn validate_signature_purpose_matches_requirements_v0( + &self, + identity: &PartialIdentity, + _platform_version: &PlatformVersion, + ) -> Result { + let mut result = SimpleConsensusValidationResult::default(); + + if let Some(output_script) = self.output_script() { + let Some(signing_key) = identity + .loaded_public_keys + .get(&self.signature_public_key_id()) + else { + return Err(Error::Execution(ExecutionError::CorruptedCodeExecution( + "we should have a loaded key at this point", + ))); + }; + + if signing_key.purpose() == Purpose::OWNER { + result.add_error( + WithdrawalOutputScriptNotAllowedWhenSigningWithOwnerKeyError::new( + output_script.clone(), + signing_key.id(), + ), + ); + } + } + + Ok(result) + } +} diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/identity_credit_withdrawal/state/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/identity_credit_withdrawal/state/v0/mod.rs index cecf5edb3d..87eff3dbaa 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/identity_credit_withdrawal/state/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/identity_credit_withdrawal/state/v0/mod.rs @@ -1,15 +1,16 @@ -use crate::error::execution::ExecutionError; use crate::error::Error; use crate::platform_types::platform::PlatformRef; use crate::rpc::core::CoreRPCLike; +use dpp::block::block_info::BlockInfo; -use crate::platform_types::platform_state::v0::PlatformStateV0Methods; -use dpp::consensus::signature::IdentityNotFoundError; -use dpp::consensus::state::identity::IdentityInsufficientBalanceError; use dpp::prelude::ConsensusValidationResult; -use dpp::state_transition::identity_credit_withdrawal_transition::accessors::IdentityCreditWithdrawalTransitionAccessorsV0; use dpp::state_transition::identity_credit_withdrawal_transition::IdentityCreditWithdrawalTransition; +use crate::execution::types::execution_operation::ValidationOperation; +use crate::execution::types::state_transition_execution_context::{ + StateTransitionExecutionContext, StateTransitionExecutionContextMethodsV0, +}; +use dpp::version::PlatformVersion; use drive::grovedb::TransactionArg; use drive::state_transition_action::identity::identity_credit_withdrawal::IdentityCreditWithdrawalTransitionAction; use drive::state_transition_action::StateTransitionAction; @@ -18,12 +19,19 @@ pub(in crate::execution::validation::state_transition::state_transitions::identi fn validate_state_v0( &self, platform: &PlatformRef, + block_info: &BlockInfo, + execution_context: &mut StateTransitionExecutionContext, tx: TransactionArg, + platform_version: &PlatformVersion, ) -> Result, Error>; fn transform_into_action_v0( &self, platform: &PlatformRef, + block_info: &BlockInfo, + execution_context: &mut StateTransitionExecutionContext, + tx: TransactionArg, + platform_version: &PlatformVersion, ) -> Result, Error>; } @@ -33,53 +41,43 @@ impl IdentityCreditWithdrawalStateTransitionStateValidationV0 fn validate_state_v0( &self, platform: &PlatformRef, + block_info: &BlockInfo, + execution_context: &mut StateTransitionExecutionContext, tx: TransactionArg, + platform_version: &PlatformVersion, ) -> Result, Error> { - let platform_version = platform.state.current_platform_version()?; - let maybe_existing_identity_balance = platform.drive.fetch_identity_balance( - self.identity_id().to_buffer(), + self.transform_into_action_v0( + platform, + block_info, + execution_context, tx, platform_version, - )?; - - let Some(existing_identity_balance) = maybe_existing_identity_balance else { - return Ok(ConsensusValidationResult::new_with_error( - IdentityNotFoundError::new(self.identity_id()).into(), - )); - }; - - if existing_identity_balance < self.amount() { - return Ok(ConsensusValidationResult::new_with_error( - IdentityInsufficientBalanceError::new( - self.identity_id(), - existing_identity_balance, - self.amount(), - ) - .into(), - )); - } - - self.transform_into_action_v0(platform) + ) } fn transform_into_action_v0( &self, platform: &PlatformRef, + block_info: &BlockInfo, + execution_context: &mut StateTransitionExecutionContext, + tx: TransactionArg, + platform_version: &PlatformVersion, ) -> Result, Error> { - let last_block_time = - platform - .state - .last_committed_block_time_ms() - .ok_or(Error::Execution(ExecutionError::StateNotInitialized( - "expected a last platform block during identity update validation", - )))?; - - Ok(ConsensusValidationResult::new_with_data( - IdentityCreditWithdrawalTransitionAction::from_identity_credit_withdrawal( + let consensus_validation_result = + IdentityCreditWithdrawalTransitionAction::try_from_identity_credit_withdrawal( + platform.drive, + tx, self, - last_block_time, + block_info, + platform_version, ) - .into(), - )) + .map(|consensus_validation_result| { + consensus_validation_result.map(|withdrawal| withdrawal.into()) + })?; + if consensus_validation_result.is_valid() { + // If this is valid then we will apply the action and eventually perform network threshold signing + execution_context.add_operation(ValidationOperation::PerformNetworkThresholdSigning); + } + Ok(consensus_validation_result) } } diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/identity_credit_withdrawal/structure/v1/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/identity_credit_withdrawal/structure/v1/mod.rs index b89b35655c..f3898d0b0d 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/identity_credit_withdrawal/structure/v1/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/identity_credit_withdrawal/structure/v1/mod.rs @@ -8,29 +8,36 @@ use dpp::consensus::ConsensusError; use crate::error::Error; use dpp::state_transition::identity_credit_withdrawal_transition::accessors::IdentityCreditWithdrawalTransitionAccessorsV0; -use dpp::state_transition::identity_credit_withdrawal_transition::v0::{ - MIN_CORE_FEE_PER_BYTE, MIN_WITHDRAWAL_AMOUNT, +use dpp::state_transition::identity_credit_withdrawal_transition::{ + IdentityCreditWithdrawalTransition, MIN_CORE_FEE_PER_BYTE, MIN_WITHDRAWAL_AMOUNT, }; -use dpp::state_transition::identity_credit_withdrawal_transition::IdentityCreditWithdrawalTransition; use dpp::util::is_fibonacci_number::is_fibonacci_number; use dpp::validation::SimpleConsensusValidationResult; +use dpp::version::PlatformVersion; use dpp::withdrawal::Pooling; pub(in crate::execution::validation::state_transition::state_transitions::identity_credit_withdrawal) trait IdentityCreditWithdrawalStateTransitionStructureValidationV1 { - fn validate_basic_structure_v1(&self) -> Result; + fn validate_basic_structure_v1(&self, platform_version: &PlatformVersion) -> Result; } impl IdentityCreditWithdrawalStateTransitionStructureValidationV1 for IdentityCreditWithdrawalTransition { - fn validate_basic_structure_v1(&self) -> Result { + fn validate_basic_structure_v1( + &self, + platform_version: &PlatformVersion, + ) -> Result { let mut result = SimpleConsensusValidationResult::default(); - if self.amount() < MIN_WITHDRAWAL_AMOUNT { + let amount = self.amount(); + if amount < MIN_WITHDRAWAL_AMOUNT + || amount > platform_version.system_limits.max_withdrawal_amount + { result.add_error(ConsensusError::from( InvalidIdentityCreditWithdrawalTransitionAmountError::new( self.amount(), MIN_WITHDRAWAL_AMOUNT, + platform_version.system_limits.max_withdrawal_amount, ), )); } @@ -57,15 +64,274 @@ impl IdentityCreditWithdrawalStateTransitionStructureValidationV1 return Ok(result); } - // validate output_script types - if !self.output_script().is_p2pkh() && !self.output_script().is_p2sh() { - result.add_error( - InvalidIdentityCreditWithdrawalTransitionOutputScriptError::new( - self.output_script().clone(), - ), - ); + if let Some(output_script) = self.output_script() { + // validate output_script types + if !output_script.is_p2pkh() && !output_script.is_p2sh() { + result.add_error( + InvalidIdentityCreditWithdrawalTransitionOutputScriptError::new( + output_script.clone(), + ), + ); + } } Ok(result) } } + +#[cfg(test)] +mod tests { + use super::*; + + use assert_matches::assert_matches; + use dpp::consensus::basic::BasicError; + use dpp::dashcore::ScriptBuf; + use dpp::identity::core_script::CoreScript; + use dpp::state_transition::identity_credit_withdrawal_transition::v1::IdentityCreditWithdrawalTransitionV1; + use platform_version::version::v1::PLATFORM_V1; + use rand::SeedableRng; + + mod validate_basic_structure_v1 { + use super::*; + use rand::prelude::StdRng; + + #[test] + fn should_return_invalid_result_if_amount_too_low() { + let amount = 18000; + + let transition = + IdentityCreditWithdrawalTransition::V1(IdentityCreditWithdrawalTransitionV1 { + identity_id: Default::default(), + amount, + core_fee_per_byte: 1, + pooling: Default::default(), + output_script: None, + nonce: 0, + user_fee_increase: 0, + signature_public_key_id: 0, + signature: Default::default(), + }); + + let platform_version = &PLATFORM_V1; + + let result = transition + .validate_basic_structure_v1(platform_version) + .expect("failed to validate basic structure"); + + assert_matches!( + result.errors.as_slice(), + [ConsensusError::BasicError( + BasicError::InvalidIdentityCreditWithdrawalTransitionAmountError( + InvalidIdentityCreditWithdrawalTransitionAmountError { + amount: a, + min_amount: 190000, + max_amount: 50000000000000, + }, + ), + )] if *a == amount + ); + } + + #[test] + fn should_return_invalid_result_if_amount_too_high() { + let amount = 60000000000000; + + let transition = + IdentityCreditWithdrawalTransition::V1(IdentityCreditWithdrawalTransitionV1 { + identity_id: Default::default(), + amount, + core_fee_per_byte: 1, + pooling: Default::default(), + output_script: None, + nonce: 0, + user_fee_increase: 0, + signature_public_key_id: 0, + signature: Default::default(), + }); + + let platform_version = &PLATFORM_V1; + + let result = transition + .validate_basic_structure_v1(platform_version) + .expect("failed to validate basic structure"); + + assert_matches!( + result.errors.as_slice(), + [ConsensusError::BasicError( + BasicError::InvalidIdentityCreditWithdrawalTransitionAmountError( + InvalidIdentityCreditWithdrawalTransitionAmountError { + amount: a, + min_amount: 190000, + max_amount: 50000000000000, + }, + ), + )] if *a == amount + ); + } + + #[test] + fn should_return_invalid_result_if_pooling_not_never() { + let transition = + IdentityCreditWithdrawalTransition::V1(IdentityCreditWithdrawalTransitionV1 { + identity_id: Default::default(), + amount: 200000, + core_fee_per_byte: 1, + pooling: Pooling::Standard, + output_script: None, + nonce: 0, + user_fee_increase: 0, + signature_public_key_id: 0, + signature: Default::default(), + }); + + let platform_version = &PLATFORM_V1; + + let result = transition + .validate_basic_structure_v1(platform_version) + .expect("failed to validate basic structure"); + + assert_matches!( + result.errors.as_slice(), + [ConsensusError::BasicError( + BasicError::NotImplementedIdentityCreditWithdrawalTransitionPoolingError(err), + )] if err.pooling() == Pooling::Standard as u8 + ); + } + + #[test] + fn should_return_invalid_result_if_core_fee_not_fibonacci() { + let transition = + IdentityCreditWithdrawalTransition::V1(IdentityCreditWithdrawalTransitionV1 { + identity_id: Default::default(), + amount: 200000, + core_fee_per_byte: 0, + pooling: Pooling::Never, + output_script: None, + nonce: 0, + user_fee_increase: 0, + signature_public_key_id: 0, + signature: Default::default(), + }); + + let platform_version = &PLATFORM_V1; + + let result = transition + .validate_basic_structure_v1(platform_version) + .expect("failed to validate basic structure"); + + assert_matches!( + result.errors.as_slice(), + [ConsensusError::BasicError( + BasicError::InvalidIdentityCreditWithdrawalTransitionCoreFeeError(err) + )] if err.min_core_fee_per_byte() == 1 && err.core_fee_per_byte() == 0 + ); + } + + #[test] + fn should_return_invalid_result_if_output_script_is_not_p2pkh_or_p2sh() { + let output_script = CoreScript::new(ScriptBuf::new()); + + let transition = + IdentityCreditWithdrawalTransition::V1(IdentityCreditWithdrawalTransitionV1 { + identity_id: Default::default(), + amount: 200000, + core_fee_per_byte: 1, + pooling: Pooling::Never, + output_script: Some(output_script.clone()), + nonce: 0, + user_fee_increase: 0, + signature_public_key_id: 0, + signature: Default::default(), + }); + + let platform_version = &PLATFORM_V1; + + let result = transition + .validate_basic_structure_v1(platform_version) + .expect("failed to validate basic structure"); + + assert_matches!( + result.errors.as_slice(), + [ConsensusError::BasicError( + BasicError::InvalidIdentityCreditWithdrawalTransitionOutputScriptError(err) + )] if err.output_script() == output_script + ); + } + + #[test] + fn should_return_valid_result_if_output_script_is_p2pkh() { + let rng = &mut StdRng::from_entropy(); + + let transition = + IdentityCreditWithdrawalTransition::V1(IdentityCreditWithdrawalTransitionV1 { + identity_id: Default::default(), + amount: 200000, + core_fee_per_byte: 1, + pooling: Pooling::Never, + output_script: Some(CoreScript::random_p2pkh(rng)), + nonce: 0, + user_fee_increase: 0, + signature_public_key_id: 0, + signature: Default::default(), + }); + + let platform_version = &PLATFORM_V1; + + let result = transition + .validate_basic_structure_v1(platform_version) + .expect("failed to validate basic structure"); + + assert!(result.is_valid()); + } + + #[test] + fn should_return_valid_result_if_output_script_is_p2sh() { + let rng = &mut StdRng::from_entropy(); + + let transition = + IdentityCreditWithdrawalTransition::V1(IdentityCreditWithdrawalTransitionV1 { + identity_id: Default::default(), + amount: 200000, + core_fee_per_byte: 1, + pooling: Pooling::Never, + output_script: Some(CoreScript::random_p2sh(rng)), + nonce: 0, + user_fee_increase: 0, + signature_public_key_id: 0, + signature: Default::default(), + }); + + let platform_version = &PLATFORM_V1; + + let result = transition + .validate_basic_structure_v1(platform_version) + .expect("failed to validate basic structure"); + + assert!(result.is_valid()); + } + + #[test] + fn should_return_valid_result_without_output_script() { + let transition = + IdentityCreditWithdrawalTransition::V1(IdentityCreditWithdrawalTransitionV1 { + identity_id: Default::default(), + amount: 200000, + core_fee_per_byte: 1, + pooling: Pooling::Never, + output_script: None, + nonce: 0, + user_fee_increase: 0, + signature_public_key_id: 0, + signature: Default::default(), + }); + + let platform_version = &PLATFORM_V1; + + let result = transition + .validate_basic_structure_v1(platform_version) + .expect("failed to validate basic structure"); + + assert!(result.is_valid()); + } + } +} diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/identity_update/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/identity_update/mod.rs index 0b6adcdf0d..fd1cdba343 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/identity_update/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/identity_update/mod.rs @@ -116,9 +116,13 @@ mod tests { use crate::execution::validation::state_transition::tests::{ setup_add_key_to_identity, setup_identity_return_master_key, }; + use crate::platform_types::state_transitions_processing_result::StateTransitionExecutionResult; use crate::test::helpers::setup::TestPlatformBuilder; + use assert_matches::assert_matches; use dpp::block::block_info::BlockInfo; + use dpp::consensus::ConsensusError; use dpp::dash_to_credits; + use dpp::dashcore::key::{Keypair, Secp256k1}; use dpp::data_contract::accessors::v0::DataContractV0Getters; use dpp::identity::accessors::IdentityGettersV0; use dpp::identity::contract_bounds::ContractBounds; @@ -128,8 +132,11 @@ mod tests { use dpp::serialization::{PlatformSerializable, Signable}; use dpp::state_transition::identity_update_transition::v0::IdentityUpdateTransitionV0; use dpp::state_transition::identity_update_transition::IdentityUpdateTransition; + use dpp::state_transition::public_key_in_creation::v0::IdentityPublicKeyInCreationV0; use dpp::state_transition::StateTransition; use platform_version::version::PlatformVersion; + use rand::rngs::StdRng; + use rand::SeedableRng; #[test] fn test_identity_update_that_disables_an_authentication_key() { @@ -337,4 +344,109 @@ mod tests { .join(" | ") ); } + + #[test] + fn test_identity_update_adding_owner_key_not_allowed() { + let platform_config = PlatformConfig { + testing_configs: PlatformTestConfig { + disable_instant_lock_signature_verification: true, + ..Default::default() + }, + ..Default::default() + }; + + let platform_version = PlatformVersion::latest(); + + let mut platform = TestPlatformBuilder::new() + .with_config(platform_config) + .build_with_mock_rpc() + .set_genesis_state(); + + let (identity, signer, key) = + setup_identity_return_master_key(&mut platform, 958, dash_to_credits!(0.1)); + + let platform_state = platform.state.load(); + + let secp = Secp256k1::new(); + + let mut rng = StdRng::seed_from_u64(1292); + + let new_key_pair = Keypair::new(&secp, &mut rng); + + let new_key = IdentityPublicKeyInCreationV0 { + id: 2, + purpose: Purpose::OWNER, + security_level: SecurityLevel::HIGH, + key_type: KeyType::ECDSA_SECP256K1, + read_only: false, + data: new_key_pair.public_key().serialize().to_vec().into(), + signature: Default::default(), + contract_bounds: None, + }; + + let update_transition: IdentityUpdateTransition = IdentityUpdateTransitionV0 { + identity_id: identity.id(), + revision: 1, + nonce: 1, + add_public_keys: vec![new_key.into()], + disable_public_keys: vec![], + user_fee_increase: 0, + signature_public_key_id: key.id(), + signature: Default::default(), + } + .into(); + + let mut update_transition: StateTransition = update_transition.into(); + + let data = update_transition + .signable_bytes() + .expect("expected signable bytes"); + update_transition.set_signature( + signer + .sign(&key, data.as_slice()) + .expect("expected to sign"), + ); + + let update_transition_bytes = update_transition + .serialize_to_bytes() + .expect("expected to serialize"); + + let transaction = platform.drive.grove.start_transaction(); + + let processing_result = platform + .platform + .process_raw_state_transitions( + &vec![update_transition_bytes.clone()], + &platform_state, + &BlockInfo::default(), + &transaction, + platform_version, + true, + None, + ) + .expect("expected to process state transition"); + + // We expect there to be an error because you should not be able to add owner keys + assert_matches!( + processing_result.execution_results().as_slice(), + [StateTransitionExecutionResult::UnpaidConsensusError( + ConsensusError::BasicError(_) + )] + ); + + platform + .drive + .grove + .commit_transaction(transaction) + .unwrap() + .expect("expected to commit"); + + let issues = platform + .drive + .grove + .visualize_verify_grovedb(None, true, false, &platform_version.drive.grove_version) + .expect("expected to have no issues"); + + assert_eq!(issues.len(), 0); + } } diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/advanced_structure/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/advanced_structure/mod.rs index b44732c3d0..40cc8ef3c5 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/advanced_structure/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/advanced_structure/mod.rs @@ -3,6 +3,8 @@ use crate::error::Error; use crate::execution::types::state_transition_execution_context::StateTransitionExecutionContext; use crate::execution::validation::state_transition::masternode_vote::advanced_structure::v0::MasternodeVoteStateTransitionAdvancedStructureValidationV0; use crate::execution::validation::state_transition::processor::v0::StateTransitionStructureKnownInStateValidationV0; +use dpp::block::block_info::BlockInfo; +use dpp::dashcore::Network; use dpp::identity::PartialIdentity; use dpp::prelude::ConsensusValidationResult; use dpp::state_transition::masternode_vote_transition::MasternodeVoteTransition; @@ -14,6 +16,8 @@ pub(crate) mod v0; impl StateTransitionStructureKnownInStateValidationV0 for MasternodeVoteTransition { fn validate_advanced_structure_from_state( &self, + _block_info: &BlockInfo, + _network: Network, action: &StateTransitionAction, identity: Option<&PartialIdentity>, execution_context: &mut StateTransitionExecutionContext, diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/mod.rs index 9ef53ddfb0..fe7d8095b8 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/mod.rs @@ -5777,7 +5777,6 @@ mod tests { use crate::execution::validation::state_transition::tests::{ create_dpns_contract_name_contest, create_dpns_identity_name_contest_skip_creating_identities, - setup_identity_without_adding_it, }; use assert_matches::assert_matches; use dapi_grpc::platform::v0::get_contested_resource_vote_state_request::GetContestedResourceVoteStateRequestV0; @@ -9949,7 +9948,7 @@ mod tests { // The alpha document should not exist at all { - let (contenders, abstaining, locking, finished_vote_info) = get_vote_states( + let (contenders, _abstaining, _locking, finished_vote_info) = get_vote_states( &platform, &platform_state, &dpns_contract, @@ -10730,7 +10729,7 @@ mod tests { // The alpha document should not exist at all { - let (contenders, abstaining, locking, finished_vote_info) = get_vote_states( + let (contenders, _abstaining, _locking, finished_vote_info) = get_vote_states( &platform, &platform_state, &dpns_contract, diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs index 4c091f8ad3..b0986e026d 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs @@ -345,6 +345,7 @@ pub(in crate::execution) mod tests { pub(in crate::execution) fn setup_identity_with_withdrawal_key_and_system_credits( platform: &mut TempPlatform, seed: u64, + withdrawal_key_type: KeyType, credits: Credits, ) -> (Identity, SimpleSigner, IdentityPublicKey, IdentityPublicKey) { let platform_version = PlatformVersion::latest(); @@ -382,7 +383,7 @@ pub(in crate::execution) mod tests { &mut rng, Purpose::TRANSFER, SecurityLevel::CRITICAL, - KeyType::ECDSA_SECP256K1, + withdrawal_key_type, None, platform_version, ) @@ -511,6 +512,111 @@ pub(in crate::execution) mod tests { ); } + pub(in crate::execution) fn setup_masternode_owner_identity( + platform: &mut TempPlatform, + seed: u64, + credits: Credits, + platform_version: &PlatformVersion, + ) -> (Identity, SimpleSigner, IdentityPublicKey, IdentityPublicKey) { + let mut signer = SimpleSigner::default(); + + platform + .drive + .add_to_system_credits(credits, None, platform_version) + .expect("expected to add to system credits"); + + let mut rng = StdRng::seed_from_u64(seed); + + let (transfer_key, transfer_private_key) = + IdentityPublicKey::random_masternode_transfer_key_with_rng( + 0, + &mut rng, + platform_version, + ) + .expect("expected to get key pair"); + + let (owner_key, owner_private_key) = + IdentityPublicKey::random_masternode_owner_key_with_rng(1, &mut rng, platform_version) + .expect("expected to get key pair"); + + let owner_address = owner_key + .public_key_hash() + .expect("expected a public key hash"); + + let payout_address = transfer_key + .public_key_hash() + .expect("expected a public key hash"); + + signer.add_key(transfer_key.clone(), transfer_private_key.clone()); + signer.add_key(owner_key.clone(), owner_private_key.clone()); + + let pro_tx_hash_bytes: [u8; 32] = rng.gen(); + + let identity: Identity = IdentityV0 { + id: pro_tx_hash_bytes.into(), + public_keys: BTreeMap::from([(0, transfer_key.clone()), (1, owner_key.clone())]), + balance: credits, + revision: 0, + } + .into(); + + // We just add this identity to the system first + + platform + .drive + .add_new_identity( + identity.clone(), + true, + &BlockInfo::default(), + true, + None, + platform_version, + ) + .expect("expected to add a new identity"); + + let mut platform_state = platform.state.load().clone().deref().clone(); + + let pro_tx_hash = ProTxHash::from_byte_array(pro_tx_hash_bytes); + + let random_ip = Ipv4Addr::new( + rng.gen_range(0..255), + rng.gen_range(0..255), + rng.gen_range(0..255), + rng.gen_range(0..255), + ); + + platform_state.full_masternode_list_mut().insert( + pro_tx_hash, + MasternodeListItem { + node_type: MasternodeType::Regular, + pro_tx_hash, + collateral_hash: Txid::from_byte_array(rng.gen()), + collateral_index: 0, + collateral_address: rng.gen(), + operator_reward: 0.0, + state: DMNState { + service: SocketAddr::new(IpAddr::V4(random_ip), 19999), + registered_height: 0, + pose_revived_height: None, + pose_ban_height: None, + revocation_reason: 0, + owner_address, + voting_address: rng.gen(), + payout_address, + pub_key_operator: vec![], + operator_payout_address: None, + platform_node_id: None, + platform_p2p_port: None, + platform_http_port: None, + }, + }, + ); + + platform.state.store(Arc::new(platform_state)); + + (identity, signer, owner_key, transfer_key) + } + pub(in crate::execution) fn setup_masternode_voting_identity( platform: &mut TempPlatform, seed: u64, diff --git a/packages/rs-drive-abci/src/logging/logger.rs b/packages/rs-drive-abci/src/logging/logger.rs index 121ce76b93..6646a783c8 100644 --- a/packages/rs-drive-abci/src/logging/logger.rs +++ b/packages/rs-drive-abci/src/logging/logger.rs @@ -5,7 +5,7 @@ use crate::logging::{LogConfigs, LogFormat, LogLevel}; use lazy_static::__Deref; use std::collections::HashMap; use std::fmt::Debug; -use std::io::Write; +use std::io::{IsTerminal, Write}; use std::sync::Arc; use std::sync::Mutex; use tracing_subscriber::fmt; @@ -305,9 +305,9 @@ impl Logger { fn layer(&self) -> Result, Error> { let ansi = self .color - .unwrap_or(match self.destination.lock().unwrap().deref() { - LogDestinationWriter::StdOut => atty::is(atty::Stream::Stdout), - LogDestinationWriter::StdErr => atty::is(atty::Stream::Stderr), + .unwrap_or_else(|| match self.destination.lock().unwrap().deref() { + LogDestinationWriter::StdOut => std::io::stdout().is_terminal(), + LogDestinationWriter::StdErr => std::io::stderr().is_terminal(), _ => false, }); diff --git a/packages/rs-drive-abci/src/main.rs b/packages/rs-drive-abci/src/main.rs index aab50e3e06..a8ae1adccd 100644 --- a/packages/rs-drive-abci/src/main.rs +++ b/packages/rs-drive-abci/src/main.rs @@ -3,11 +3,15 @@ //! RS-Drive-ABCI server starts a single-threaded server and listens to connections from Tenderdash. use clap::{Parser, Subcommand}; +use dapi_grpc::platform::v0::get_status_request; +use dapi_grpc::platform::v0::get_status_request::GetStatusRequestV0; +use dapi_grpc::platform::v0::platform_client::PlatformClient; +use dapi_grpc::tonic::transport::Uri; use dpp::version::PlatformVersion; use drive_abci::config::{FromEnv, PlatformConfig}; use drive_abci::core::wait_for_core_to_sync::v0::wait_for_core_to_sync_v0; use drive_abci::logging::{LogBuilder, LogConfig, LogDestination, Loggers}; -use drive_abci::metrics::{Prometheus, DEFAULT_PROMETHEUS_PORT}; +use drive_abci::metrics::Prometheus; use drive_abci::platform_types::platform::Platform; use drive_abci::rpc::core::DefaultCoreRPC; use drive_abci::{logging, server}; @@ -17,6 +21,7 @@ use std::fs::remove_file; use std::net::SocketAddr; use std::path::PathBuf; use std::process::ExitCode; +use std::str::FromStr; use std::sync::Arc; use tokio::runtime::{Builder, Runtime}; use tokio::signal::unix::{signal, SignalKind}; @@ -54,6 +59,10 @@ enum Commands { /// by creating `.fsck` file in database directory (`DB_PATH`). #[command()] Verify, + + /// Print current software version + #[command()] + Version, } /// Server that accepts connections from Tenderdash, and @@ -98,6 +107,13 @@ impl Cli { ) -> Result<(), String> { match self.command { Commands::Start => { + tracing::info!( + version = env!("CARGO_PKG_VERSION"), + features = list_enabled_features().join(","), + rust = env!("CARGO_PKG_RUST_VERSION"), + "drive-abci server initializing", + ); + if config.drive.grovedb_verify_on_startup { verify_grovedb(&config.db_path, false)?; } @@ -129,11 +145,14 @@ impl Cli { server::start(runtime, Arc::new(platform), config, cancel); + tracing::info!("drive-abci server is stopped"); + return Ok(()); } Commands::Config => dump_config(&config)?, - Commands::Status => check_status(&config)?, + Commands::Status => runtime.block_on(check_status(&config))?, Commands::Verify => verify_grovedb(&config.db_path, true)?, + Commands::Version => print_version(), }; Ok(()) @@ -202,32 +221,18 @@ fn main() -> Result<(), ExitCode> { install_panic_hook(cancel.clone()); // Start runtime in the main thread - tracing::info!( - version = env!("CARGO_PKG_VERSION"), - features = list_enabled_features().join(","), - rust = env!("CARGO_PKG_RUST_VERSION"), - "drive-abci server initializing", - ); - let runtime_guard = runtime.enter(); runtime.spawn(handle_signals(cancel.clone(), loggers)); - let result = match cli.run(&runtime, config, cancel) { - Ok(()) => { - tracing::debug!("shutdown complete"); - Ok(()) - } - Err(e) => { - tracing::error!(error = e, "drive-abci failed"); - Err(ExitCode::FAILURE) - } - }; + let result = cli.run(&runtime, config, cancel).map_err(|e| { + tracing::error!(error = e, "drive-abci failed: {e}"); + + ExitCode::FAILURE + }); drop(runtime_guard); runtime.shutdown_timeout(Duration::from_millis(SHUTDOWN_TIMEOUT_MILIS)); - tracing::info!("drive-abci server is stopped"); - result } @@ -303,31 +308,27 @@ fn list_enabled_features() -> Vec<&'static str> { } /// Check status of ABCI server. -fn check_status(config: &PlatformConfig) -> Result<(), String> { - if let Some(prometheus_addr) = &config.prometheus_bind_address { - let url = - url::Url::parse(prometheus_addr).expect("cannot parse ABCI_PROMETHEUS_BIND_ADDRESS"); - - let addr = format!( - "{}://{}:{}/metrics", - url.scheme(), - url.host() - .ok_or("ABCI_PROMETHEUS_BIND_ADDRESS must contain valid host".to_string())?, - url.port().unwrap_or(DEFAULT_PROMETHEUS_PORT) - ); - - let body: String = ureq::get(&addr) - .set("Content-type", "text/plain") - .call() - .map_err(|e| e.to_string())? - .into_string() - .map_err(|e| e.to_string())?; +async fn check_status(config: &PlatformConfig) -> Result<(), String> { + // Convert the gRPC bind address string to a Uri + let uri = Uri::from_str(&format!("http://{}", config.grpc_bind_address)) + .map_err(|e| format!("invalid url: {e}"))?; + + // Connect to the gRPC server + let mut client = PlatformClient::connect(uri.clone()) + .await + .map_err(|e| format!("can't connect to grpc server {uri}: {e}"))?; + + // Make a request to the server + let request = dapi_grpc::platform::v0::GetStatusRequest { + version: Some(get_status_request::Version::V0(GetStatusRequestV0 {})), + }; - println!("{}", body); - Ok(()) - } else { - Err("ABCI_PROMETHEUS_BIND_ADDRESS not defined, cannot check status".to_string()) - } + // Should return non-zero error code if Drive is not responding + client + .get_status(request) + .await + .map(|_| ()) + .map_err(|e| format!("can't request status: {e}")) } /// Verify GroveDB integrity. @@ -386,6 +387,11 @@ fn verify_grovedb(db_path: &PathBuf, force: bool) -> Result<(), String> { } } +/// Print current software version. +fn print_version() { + println!("{}", env!("CARGO_PKG_VERSION")); +} + fn load_config(path: &Option) -> PlatformConfig { if let Some(path) = path { if let Err(e) = dotenvy::from_path(path) { @@ -415,7 +421,7 @@ fn configure_logging(cli: &Cli, config: &PlatformConfig) -> Result 0 { let cli_config = LogConfig { destination: LogDestination::StdOut, - level: cli.verbose.try_into().unwrap(), + level: cli.verbose.try_into()?, color: cli.color, ..Default::default() }; @@ -442,15 +448,14 @@ fn install_panic_hook(cancel: CancellationToken) { #[cfg(test)] mod test { + use ::drive::{drive::Drive, query::Element}; + use dpp::block::epoch::Epoch; + use drive::drive::credit_pools::epochs::epoch_key_constants; use std::{ fs, path::{Path, PathBuf}, }; - use ::drive::{drive::Drive, query::Element}; - use dpp::block::epoch::Epoch; - use drive::drive::credit_pools::epochs::epoch_key_constants; - use dpp::version::PlatformVersion; use drive::drive::credit_pools::epochs::paths::EpochProposers; use drive_abci::logging::LogLevel; diff --git a/packages/rs-drive-abci/src/metrics.rs b/packages/rs-drive-abci/src/metrics.rs index 5c90ec2501..943f0d5aae 100644 --- a/packages/rs-drive-abci/src/metrics.rs +++ b/packages/rs-drive-abci/src/metrics.rs @@ -6,7 +6,7 @@ use std::time::Duration; use std::{sync::Once, time::Instant}; use dapi_grpc::tonic::Code; -use metrics::{counter, describe_counter, describe_histogram, histogram, Label}; +use metrics::{counter, describe_counter, describe_gauge, describe_histogram, histogram, Label}; use metrics_exporter_prometheus::PrometheusBuilder; /// Default Prometheus port (29090) @@ -29,6 +29,10 @@ pub const LABEL_STATE_TRANSITION_NAME: &str = "st_name"; const LABEL_STATE_TRANSITION_EXECUTION_CODE: &str = "st_exec_code"; /// Metrics label to specify check tx mode: 0 - first time check, 1 - recheck pub const LABEL_CHECK_TX_MODE: &str = "check_tx_mode"; +/// Withdrawal daily limit available credits +pub const GAUGE_CREDIT_WITHDRAWAL_LIMIT_AVAILABLE: &str = "credit_withdrawal_limit_available"; +/// Total withdrawal daily limit in credits +pub const GAUGE_CREDIT_WITHDRAWAL_LIMIT_TOTAL: &str = "credit_withdrawal_limit_total"; /// Error returned by metrics subsystem #[derive(thiserror::Error, Debug)] @@ -210,7 +214,17 @@ impl Prometheus { HISTOGRAM_QUERY_DURATION, metrics::Unit::Seconds, "Duration of query request execution inside Drive per endpoint, in seconds" - ) + ); + + describe_gauge!( + GAUGE_CREDIT_WITHDRAWAL_LIMIT_AVAILABLE, + "Available withdrawal limit for last 24 hours in credits" + ); + + describe_gauge!( + GAUGE_CREDIT_WITHDRAWAL_LIMIT_TOTAL, + "Total withdrawal limit for last 24 hours in credits" + ); }); } } diff --git a/packages/rs-drive-abci/src/platform_types/platform_state/mod.rs b/packages/rs-drive-abci/src/platform_types/platform_state/mod.rs index e937924c94..d2236ef84c 100644 --- a/packages/rs-drive-abci/src/platform_types/platform_state/mod.rs +++ b/packages/rs-drive-abci/src/platform_types/platform_state/mod.rs @@ -4,8 +4,8 @@ pub mod v0; use crate::error::Error; use crate::platform_types::platform_state::v0::{ - MasternodeListChanges, PlatformStateForSavingV0, PlatformStateV0, PlatformStateV0Methods, - PlatformStateV0PrivateMethods, + MasternodeListChanges, PlatformStateForSavingV0, PlatformStateForSavingV1, PlatformStateV0, + PlatformStateV0Methods, PlatformStateV0PrivateMethods, }; use crate::platform_types::validator_set::ValidatorSet; @@ -42,23 +42,8 @@ pub enum PlatformState { pub enum PlatformStateForSaving { /// Version 0 V0(PlatformStateForSavingV0), -} - -impl PlatformStateForSaving { - /// Retrieves the current protocol version used in consensus. - /// - /// Matches against `PlatformStateForSaving` variants to extract the protocol version. - /// - /// # Returns - /// A `ProtocolVersion` indicating the current consensus protocol version. - #[allow(dead_code)] - #[deprecated(note = "This function is marked as unused.")] - #[allow(deprecated)] - pub fn current_protocol_version_in_consensus(&self) -> ProtocolVersion { - match self { - PlatformStateForSaving::V0(v0) => v0.current_protocol_version_in_consensus, - } - } + /// Version 1 + V1(PlatformStateForSavingV1), } impl PlatformSerializable for PlatformState { @@ -153,11 +138,11 @@ impl TryFromPlatformVersioned for PlatformStateForSaving { match platform_version .drive_abci .structs - .platform_state_for_saving_structure + .platform_state_for_saving_structure_default { 0 => { - let saving_v0: PlatformStateForSavingV0 = v0.try_into()?; - Ok(saving_v0.into()) + let saving_v1: PlatformStateForSavingV1 = v0.try_into()?; + Ok(saving_v1.into()) } version => Err(Error::Execution(ExecutionError::UnknownVersionMismatch { method: @@ -189,7 +174,23 @@ impl TryFromPlatformVersioned for PlatformState { } version => Err(Error::Execution(ExecutionError::UnknownVersionMismatch { method: - "PlatformState::try_from_platform_versioned(PlatformStateForSaving)" + "PlatformState::try_from_platform_versioned(PlatformStateForSavingV0)" + .to_string(), + known_versions: vec![0], + received: version, + })), + } + } + PlatformStateForSaving::V1(v1) => { + match platform_version.drive_abci.structs.platform_state_structure { + 0 => { + let platform_state_v0 = PlatformStateV0::from(v1); + + Ok(platform_state_v0.into()) + } + version => Err(Error::Execution(ExecutionError::UnknownVersionMismatch { + method: + "PlatformState::try_from_platform_versioned(PlatformStateForSavingV1)" .to_string(), known_versions: vec![0], received: version, @@ -547,3 +548,24 @@ impl PlatformStateV0Methods for PlatformState { } } } + +#[cfg(test)] +mod tests { + use super::*; + + mod versioned_deserialize { + use super::*; + use crate::test::fixture::platform_state::PLATFORM_STATE_V3_TESTNET; + use platform_version::version::v3::PLATFORM_V3; + use std::ops::Deref; + + #[test] + fn should_deserialize_state_stored_in_version_0_from_testnet() { + let serialized_state = + hex::decode(PLATFORM_STATE_V3_TESTNET.deref()).expect("failed to decode hex"); + + PlatformState::versioned_deserialize(&serialized_state, &PLATFORM_V3) + .expect("failed to deserialize state"); + } + } +} diff --git a/packages/rs-drive-abci/src/platform_types/platform_state/v0/mod.rs b/packages/rs-drive-abci/src/platform_types/platform_state/v0/mod.rs index 61bc6b8d7d..d1c2ccd464 100644 --- a/packages/rs-drive-abci/src/platform_types/platform_state/v0/mod.rs +++ b/packages/rs-drive-abci/src/platform_types/platform_state/v0/mod.rs @@ -20,11 +20,15 @@ use dpp::block::extended_block_info::v0::ExtendedBlockInfoV0Getters; use dpp::version::{PlatformVersion, TryIntoPlatformVersioned}; use crate::config::PlatformConfig; -use crate::platform_types::platform_state::PlatformState; use crate::platform_types::signature_verification_quorum_set::{ SignatureVerificationQuorumSet, SignatureVerificationQuorumSetForSaving, }; -use dpp::fee::default_costs::CachedEpochIndexFeeVersions; +use crate::platform_types::validator_set::v0::ValidatorSetV0Getters; +use dpp::fee::default_costs::{ + CachedEpochIndexFeeVersions, CachedEpochIndexFeeVersionsFieldsBeforeVersion4, + EpochIndexFeeVersionsForStorage, +}; +use dpp::version::fee::FeeVersion; use itertools::Itertools; use std::collections::BTreeMap; use std::fmt::{Debug, Formatter}; @@ -154,15 +158,51 @@ pub struct PlatformStateForSavingV0 { pub hpmn_masternode_list: BTreeMap, /// previous FeeVersions - pub previous_fee_versions: CachedEpochIndexFeeVersions, + pub previous_fee_versions: CachedEpochIndexFeeVersionsFieldsBeforeVersion4, +} + +/// Platform state +#[derive(Clone, Debug, Encode, Decode)] +pub struct PlatformStateForSavingV1 { + /// Information about the genesis block + pub genesis_block_info: Option, + /// Information about the last block + pub last_committed_block_info: Option, + /// Current Version + pub current_protocol_version_in_consensus: ProtocolVersion, + /// upcoming protocol version + pub next_epoch_protocol_version: ProtocolVersion, + /// current quorum + pub current_validator_set_quorum_hash: Bytes32, + /// next quorum + pub next_validator_set_quorum_hash: Option, + /// current validator set quorums + /// The validator set quorums are a subset of the quorums, but they also contain the list of + /// all members + pub validator_sets: Vec<(Bytes32, ValidatorSet)>, + + /// The quorums used for validating chain locks + pub chain_lock_validating_quorums: SignatureVerificationQuorumSetForSaving, + + /// The quorums used for validating instant locks + pub instant_lock_validating_quorums: SignatureVerificationQuorumSetForSaving, + + /// current full masternode list + pub full_masternode_list: BTreeMap, + + /// current HPMN masternode list + pub hpmn_masternode_list: BTreeMap, + + /// previous FeeVersions + pub previous_fee_versions: EpochIndexFeeVersionsForStorage, } -impl TryFrom for PlatformStateForSavingV0 { +impl TryFrom for PlatformStateForSavingV1 { type Error = Error; fn try_from(value: PlatformStateV0) -> Result { let platform_version = value.current_platform_version()?; - Ok(PlatformStateForSavingV0 { + Ok(PlatformStateForSavingV1 { genesis_block_info: value.genesis_block_info, last_committed_block_info: value.last_committed_block_info, current_protocol_version_in_consensus: value.current_protocol_version_in_consensus, @@ -201,7 +241,11 @@ impl TryFrom for PlatformStateForSavingV0 { )) }) .collect::, Error>>()?, - previous_fee_versions: value.previous_fee_versions, + previous_fee_versions: value + .previous_fee_versions + .into_iter() + .map(|(epoch_index, fee_version)| (epoch_index, fee_version.fee_version_number)) + .collect(), }) } } @@ -237,7 +281,57 @@ impl From for PlatformStateV0 { .into_iter() .map(|(k, v)| (ProTxHash::from_byte_array(k.to_buffer()), v.into())) .collect(), - previous_fee_versions: value.previous_fee_versions, + previous_fee_versions: value + .previous_fee_versions + .into_iter() + .map(|(epoch_index, _)| (epoch_index, FeeVersion::first())) + .collect(), + } + } +} + +impl From for PlatformStateV0 { + fn from(value: PlatformStateForSavingV1) -> Self { + PlatformStateV0 { + genesis_block_info: value.genesis_block_info, + last_committed_block_info: value.last_committed_block_info, + current_protocol_version_in_consensus: value.current_protocol_version_in_consensus, + next_epoch_protocol_version: value.next_epoch_protocol_version, + current_validator_set_quorum_hash: QuorumHash::from_byte_array( + value.current_validator_set_quorum_hash.to_buffer(), + ), + next_validator_set_quorum_hash: value + .next_validator_set_quorum_hash + .map(|bytes| QuorumHash::from_byte_array(bytes.to_buffer())), + patched_platform_version: None, + validator_sets: value + .validator_sets + .into_iter() + .map(|(k, v)| (QuorumHash::from_byte_array(k.to_buffer()), v)) + .collect(), + chain_lock_validating_quorums: value.chain_lock_validating_quorums.into(), + instant_lock_validating_quorums: value.instant_lock_validating_quorums.into(), + full_masternode_list: value + .full_masternode_list + .into_iter() + .map(|(k, v)| (ProTxHash::from_byte_array(k.to_buffer()), v.into())) + .collect(), + hpmn_masternode_list: value + .hpmn_masternode_list + .into_iter() + .map(|(k, v)| (ProTxHash::from_byte_array(k.to_buffer()), v.into())) + .collect(), + previous_fee_versions: value + .previous_fee_versions + .into_iter() + .map(|(epoch_index, fee_version_number)| { + ( + epoch_index, + FeeVersion::get(fee_version_number) + .expect("expected fee version number to exist"), + ) + }) + .collect(), } } } @@ -345,6 +439,32 @@ pub trait PlatformStateV0Methods { /// Returns the quorum hash of the current validator set. fn current_validator_set_quorum_hash(&self) -> QuorumHash; + /// Get validator sets sorted by their core height by most recent order coming first + fn validator_sets_sorted_by_core_height_by_most_recent(&self) -> Vec<&ValidatorSet> { + // Get the validator sets and collect them into a vector for sorting + let mut validator_sets: Vec<&ValidatorSet> = self.validator_sets().values().collect(); + + // Sort the validator sets by core height in descending order + validator_sets.sort_by(|a, b| b.core_height().cmp(&a.core_height())); + + validator_sets + } + + /// Where is the current validator set in the list + fn current_validator_set_position_in_list_by_most_recent(&self) -> Option { + // Get the current quorum hash + let current_quorum_hash = self.current_validator_set_quorum_hash(); + + // Get the validator sets by post recent + let validator_sets = self.validator_sets_sorted_by_core_height_by_most_recent(); + + // Find the position of the current validator set in the sorted list + validator_sets + .iter() + .position(|&validator_set| validator_set.quorum_hash() == ¤t_quorum_hash) + .map(|position| position as u16) // Convert position to u16 + } + /// Returns the quorum hash of the next validator set, if it exists. fn next_validator_set_quorum_hash(&self) -> &Option; diff --git a/packages/rs-drive-abci/src/platform_types/validator/mod.rs b/packages/rs-drive-abci/src/platform_types/validator/mod.rs index 3ad5264d5d..10144bf53f 100644 --- a/packages/rs-drive-abci/src/platform_types/validator/mod.rs +++ b/packages/rs-drive-abci/src/platform_types/validator/mod.rs @@ -1,114 +1,3 @@ -use crate::platform_types::validator::v0::{ValidatorV0, ValidatorV0Getters, ValidatorV0Setters}; -use dashcore_rpc::dashcore::{ProTxHash, PubkeyHash}; -use dpp::bls_signatures::PublicKey as BlsPublicKey; -use serde::{Deserialize, Serialize}; - /// Version 0 pub mod v0; - -/// A validator in the context of a quorum -#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] -pub enum Validator { - /// Version 0 - V0(ValidatorV0), -} - -impl ValidatorV0Getters for Validator { - fn pro_tx_hash(&self) -> &ProTxHash { - match self { - Validator::V0(v0) => v0.pro_tx_hash(), - } - } - - fn public_key(&self) -> &Option { - match self { - Validator::V0(v0) => v0.public_key(), - } - } - - fn node_ip(&self) -> &String { - match self { - Validator::V0(v0) => v0.node_ip(), - } - } - - fn node_id(&self) -> &PubkeyHash { - match self { - Validator::V0(v0) => v0.node_id(), - } - } - - fn core_port(&self) -> u16 { - match self { - Validator::V0(v0) => v0.core_port(), - } - } - - fn platform_http_port(&self) -> u16 { - match self { - Validator::V0(v0) => v0.platform_http_port(), - } - } - - fn platform_p2p_port(&self) -> u16 { - match self { - Validator::V0(v0) => v0.platform_p2p_port(), - } - } - - fn is_banned(&self) -> bool { - match self { - Validator::V0(v0) => v0.is_banned(), - } - } -} - -impl ValidatorV0Setters for Validator { - fn set_pro_tx_hash(&mut self, pro_tx_hash: ProTxHash) { - match self { - Validator::V0(v0) => v0.set_pro_tx_hash(pro_tx_hash), - } - } - - fn set_public_key(&mut self, public_key: Option) { - match self { - Validator::V0(v0) => v0.set_public_key(public_key), - } - } - - fn set_node_ip(&mut self, node_ip: String) { - match self { - Validator::V0(v0) => v0.set_node_ip(node_ip), - } - } - - fn set_node_id(&mut self, node_id: PubkeyHash) { - match self { - Validator::V0(v0) => v0.set_node_id(node_id), - } - } - - fn set_core_port(&mut self, core_port: u16) { - match self { - Validator::V0(v0) => v0.set_core_port(core_port), - } - } - - fn set_platform_http_port(&mut self, platform_http_port: u16) { - match self { - Validator::V0(v0) => v0.set_platform_http_port(platform_http_port), - } - } - - fn set_platform_p2p_port(&mut self, platform_p2p_port: u16) { - match self { - Validator::V0(v0) => v0.set_platform_p2p_port(platform_p2p_port), - } - } - - fn set_is_banned(&mut self, is_banned: bool) { - match self { - Validator::V0(v0) => v0.set_is_banned(is_banned), - } - } -} +pub use dpp::core_types::validator::*; diff --git a/packages/rs-drive-abci/src/platform_types/validator/v0/mod.rs b/packages/rs-drive-abci/src/platform_types/validator/v0/mod.rs index 665c48c3dc..433fe506bf 100644 --- a/packages/rs-drive-abci/src/platform_types/validator/v0/mod.rs +++ b/packages/rs-drive-abci/src/platform_types/validator/v0/mod.rs @@ -1,52 +1,21 @@ use crate::platform_types::platform_state::v0::PlatformStateV0Methods; -use dashcore_rpc::dashcore::hashes::Hash; -use dashcore_rpc::dashcore::{ProTxHash, PubkeyHash}; -use dashcore_rpc::dashcore_rpc_json::{DMNState, MasternodeListItem}; -use std::fmt::{Debug, Formatter}; - use crate::platform_types::platform_state::PlatformState; +use dashcore_rpc::json::{DMNState, MasternodeListItem}; use dpp::bls_signatures::PublicKey as BlsPublicKey; -use serde::{Deserialize, Serialize}; - -/// A validator in the context of a quorum -#[derive(Clone, Serialize, Deserialize, Eq, PartialEq)] -pub struct ValidatorV0 { - /// The proTxHash - pub pro_tx_hash: ProTxHash, - /// The public key share of this validator for this quorum - pub public_key: Option, - /// The node address - pub node_ip: String, - /// The node id - pub node_id: PubkeyHash, - /// Core port - pub core_port: u16, - /// Http port - pub platform_http_port: u16, - /// Tenderdash port - pub platform_p2p_port: u16, - /// Is the validator banned - pub is_banned: bool, -} - -impl Debug for ValidatorV0 { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - f.debug_struct("ValidatorV0") - .field("pro_tx_hash", &self.pro_tx_hash.to_string()) - .field("public_key", &self.public_key) - .field("node_ip", &self.node_ip) - .field("node_id", &self.node_id) - .field("core_port", &self.core_port) - .field("platform_http_port", &self.platform_http_port) - .field("platform_p2p_port", &self.platform_p2p_port) - .field("is_banned", &self.is_banned) - .finish() - } +pub use dpp::core_types::validator::v0::*; +use dpp::dashcore::hashes::Hash; +use dpp::dashcore::{ProTxHash, PubkeyHash}; +pub(crate) trait NewValidatorIfMasternodeInState { + fn new_validator_if_masternode_in_state( + pro_tx_hash: ProTxHash, + public_key: Option, + state: &PlatformState, + ) -> Option; } -impl ValidatorV0 { +impl NewValidatorIfMasternodeInState for ValidatorV0 { /// Makes a validator if the masternode is in the list and is valid - pub fn new_validator_if_masternode_in_state( + fn new_validator_if_masternode_in_state( pro_tx_hash: ProTxHash, public_key: Option, state: &PlatformState, @@ -80,111 +49,3 @@ impl ValidatorV0 { }) } } - -/// Traits to get properties of a validator. -pub trait ValidatorV0Getters { - /// Returns the proTxHash of the validator. - fn pro_tx_hash(&self) -> &ProTxHash; - /// Returns the public key share of this validator for this quorum. - fn public_key(&self) -> &Option; - /// Returns the node address of the validator. - fn node_ip(&self) -> &String; - /// Returns the node id of the validator. - fn node_id(&self) -> &PubkeyHash; - /// Returns the core port of the validator. - fn core_port(&self) -> u16; - /// Returns the Http port of the validator. - fn platform_http_port(&self) -> u16; - /// Returns the Tenderdash port of the validator. - fn platform_p2p_port(&self) -> u16; - /// Returns the status of the validator whether it's banned or not. - fn is_banned(&self) -> bool; -} - -/// Traits to set properties of a validator. -pub trait ValidatorV0Setters { - /// Sets the proTxHash of the validator. - fn set_pro_tx_hash(&mut self, pro_tx_hash: ProTxHash); - /// Sets the public key share of this validator for this quorum. - fn set_public_key(&mut self, public_key: Option); - /// Sets the node address of the validator. - fn set_node_ip(&mut self, node_ip: String); - /// Sets the node id of the validator. - fn set_node_id(&mut self, node_id: PubkeyHash); - /// Sets the core port of the validator. - fn set_core_port(&mut self, core_port: u16); - /// Sets the Http port of the validator. - fn set_platform_http_port(&mut self, platform_http_port: u16); - /// Sets the Tenderdash port of the validator. - fn set_platform_p2p_port(&mut self, platform_p2p_port: u16); - /// Sets the status of the validator whether it's banned or not. - fn set_is_banned(&mut self, is_banned: bool); -} - -impl ValidatorV0Getters for ValidatorV0 { - fn pro_tx_hash(&self) -> &ProTxHash { - &self.pro_tx_hash - } - - fn public_key(&self) -> &Option { - &self.public_key - } - - fn node_ip(&self) -> &String { - &self.node_ip - } - - fn node_id(&self) -> &PubkeyHash { - &self.node_id - } - - fn core_port(&self) -> u16 { - self.core_port - } - - fn platform_http_port(&self) -> u16 { - self.platform_http_port - } - - fn platform_p2p_port(&self) -> u16 { - self.platform_p2p_port - } - - fn is_banned(&self) -> bool { - self.is_banned - } -} - -impl ValidatorV0Setters for ValidatorV0 { - fn set_pro_tx_hash(&mut self, pro_tx_hash: ProTxHash) { - self.pro_tx_hash = pro_tx_hash; - } - - fn set_public_key(&mut self, public_key: Option) { - self.public_key = public_key; - } - - fn set_node_ip(&mut self, node_ip: String) { - self.node_ip = node_ip; - } - - fn set_node_id(&mut self, node_id: PubkeyHash) { - self.node_id = node_id; - } - - fn set_core_port(&mut self, core_port: u16) { - self.core_port = core_port; - } - - fn set_platform_http_port(&mut self, platform_http_port: u16) { - self.platform_http_port = platform_http_port; - } - - fn set_platform_p2p_port(&mut self, platform_p2p_port: u16) { - self.platform_p2p_port = platform_p2p_port; - } - - fn set_is_banned(&mut self, is_banned: bool) { - self.is_banned = is_banned; - } -} diff --git a/packages/rs-drive-abci/src/platform_types/validator_set/mod.rs b/packages/rs-drive-abci/src/platform_types/validator_set/mod.rs index 5dd9adb1f8..414fbe0c8f 100644 --- a/packages/rs-drive-abci/src/platform_types/validator_set/mod.rs +++ b/packages/rs-drive-abci/src/platform_types/validator_set/mod.rs @@ -1,114 +1,27 @@ -use crate::platform_types::validator::v0::ValidatorV0; -use crate::platform_types::validator_set::v0::{ - ValidatorSetV0, ValidatorSetV0Getters, ValidatorSetV0Setters, -}; -use dashcore_rpc::dashcore::{ProTxHash, QuorumHash}; -use dpp::bls_signatures::PublicKey as BlsPublicKey; -use serde::{Deserialize, Serialize}; -use std::collections::BTreeMap; +use crate::platform_types::validator_set::v0::ValidatorSetMethodsV0; use tenderdash_abci::proto::abci::ValidatorSetUpdate; -/// Version 0 -pub mod v0; - -/// The validator set is only slightly different from a quorum as it does not contain non valid -/// members -#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] -pub enum ValidatorSet { - /// Version 0 - V0(ValidatorSetV0), -} - -impl ValidatorSetV0Getters for ValidatorSet { - fn quorum_hash(&self) -> &QuorumHash { - match self { - ValidatorSet::V0(v0) => v0.quorum_hash(), - } - } +pub use dpp::core_types::validator_set::*; - fn quorum_index(&self) -> Option { - match self { - ValidatorSet::V0(v0) => v0.quorum_index(), - } - } - - fn core_height(&self) -> u32 { - match self { - ValidatorSet::V0(v0) => v0.core_height(), - } - } - - fn members(&self) -> &BTreeMap { - match self { - ValidatorSet::V0(v0) => v0.members(), - } - } - - fn members_mut(&mut self) -> &mut BTreeMap { - match self { - ValidatorSet::V0(v0) => v0.members_mut(), - } - } - - fn members_owned(self) -> BTreeMap { - match self { - ValidatorSet::V0(v0) => v0.members_owned(), - } - } +/// v0 +pub mod v0; - fn threshold_public_key(&self) -> &BlsPublicKey { - match self { - ValidatorSet::V0(v0) => v0.threshold_public_key(), - } - } +pub(crate) trait ValidatorSetExt { + fn to_update(&self) -> ValidatorSetUpdate; + #[allow(unused)] + fn to_update_owned(self) -> ValidatorSetUpdate; } -impl ValidatorSetV0Setters for ValidatorSet { - fn set_quorum_hash(&mut self, quorum_hash: QuorumHash) { - match self { - ValidatorSet::V0(v0) => v0.set_quorum_hash(quorum_hash), - } - } - - fn set_quorum_index(&mut self, index: Option) { - match self { - ValidatorSet::V0(v0) => v0.set_quorum_index(index), - } - } - - fn set_core_height(&mut self, core_height: u32) { +impl ValidatorSetExt for ValidatorSet { + fn to_update(&self) -> ValidatorSetUpdate { match self { - ValidatorSet::V0(v0) => v0.set_core_height(core_height), + ValidatorSet::V0(v0) => v0.to_update(), } } - fn set_members(&mut self, members: BTreeMap) { + fn to_update_owned(self) -> ValidatorSetUpdate { match self { - ValidatorSet::V0(v0) => v0.set_members(members), - } - } - - fn set_threshold_public_key(&mut self, threshold_public_key: BlsPublicKey) { - match self { - ValidatorSet::V0(v0) => v0.set_threshold_public_key(threshold_public_key), - } - } -} - -/// In this case we are changing to this validator set from another validator set and there are no -/// changes -impl From for ValidatorSetUpdate { - fn from(value: ValidatorSet) -> Self { - match value { - ValidatorSet::V0(v0) => v0.into(), - } - } -} - -impl From<&ValidatorSet> for ValidatorSetUpdate { - fn from(value: &ValidatorSet) -> Self { - match value { - ValidatorSet::V0(v0) => v0.into(), + ValidatorSet::V0(v0) => v0.to_update_owned(), } } } diff --git a/packages/rs-drive-abci/src/platform_types/validator_set/v0/mod.rs b/packages/rs-drive-abci/src/platform_types/validator_set/v0/mod.rs index 7574a5d31d..f7141d1ff4 100644 --- a/packages/rs-drive-abci/src/platform_types/validator_set/v0/mod.rs +++ b/packages/rs-drive-abci/src/platform_types/validator_set/v0/mod.rs @@ -1,62 +1,38 @@ use crate::error::execution::ExecutionError; use crate::error::Error; -use crate::platform_types::validator::v0::ValidatorV0; use dashcore_rpc::dashcore::hashes::Hash; -use dashcore_rpc::dashcore::{ProTxHash, QuorumHash}; +use dashcore_rpc::dashcore::ProTxHash; use crate::platform_types::platform_state::PlatformState; +use crate::platform_types::validator::v0::NewValidatorIfMasternodeInState; use dashcore_rpc::json::QuorumInfoResult; use dpp::bls_signatures::PublicKey as BlsPublicKey; -use serde::{Deserialize, Serialize}; +use dpp::core_types::validator::v0::ValidatorV0; +pub use dpp::core_types::validator_set::v0::*; use std::collections::BTreeMap; -use std::fmt::{Debug, Formatter}; use tenderdash_abci::proto::abci::ValidatorSetUpdate; use tenderdash_abci::proto::crypto::public_key::Sum::Bls12381; use tenderdash_abci::proto::{abci, crypto}; -/// The validator set is only slightly different from a quorum as it does not contain non valid -/// members -#[derive(Clone, Serialize, Deserialize, Eq, PartialEq)] -pub struct ValidatorSetV0 { - /// The quorum hash - pub quorum_hash: QuorumHash, - /// Rotation quorum index is available only for DIP24 quorums - pub quorum_index: Option, - /// Active height - pub core_height: u32, - /// The list of masternodes - pub members: BTreeMap, - /// The threshold quorum public key - pub threshold_public_key: BlsPublicKey, -} +pub(crate) trait ValidatorSetMethodsV0 { + #[allow(unused)] + fn update_difference(&self, rhs: &ValidatorSetV0) -> Result; -impl Debug for ValidatorSetV0 { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - f.debug_struct("ValidatorSetV0") - .field("quorum_hash", &self.quorum_hash.to_string()) - .field("core_height", &self.core_height) - .field( - "members", - &self - .members - .iter() - .map(|(k, v)| (k.to_string(), v)) - .collect::>(), - ) - .field("threshold_public_key", &self.threshold_public_key) - .finish() - } + fn to_update(&self) -> ValidatorSetUpdate; + fn to_update_owned(self) -> ValidatorSetUpdate; + /// Try to create a quorum from info from the Masternode list (given with state), + /// and for information return for quorum members + fn try_from_quorum_info_result( + value: QuorumInfoResult, + state: &PlatformState, + ) -> Result; } -impl ValidatorSetV0 { +impl ValidatorSetMethodsV0 for ValidatorSetV0 { /// For changes between two validator sets, we take the new (rhs) element if is different /// for every validator - #[allow(dead_code)] - pub(crate) fn update_difference( - &self, - rhs: &ValidatorSetV0, - ) -> Result { + fn update_difference(&self, rhs: &ValidatorSetV0) -> Result { if self.quorum_hash != rhs.quorum_hash { return Err(Error::Execution(ExecutionError::CorruptedCachedState( format!( @@ -127,7 +103,7 @@ impl ValidatorSetV0 { } }), power: 100, - pro_tx_hash: reverse(pro_tx_hash.as_byte_array()), + pro_tx_hash: pro_tx_hash.as_byte_array().to_vec(), node_address, })) } @@ -159,7 +135,7 @@ impl ValidatorSetV0 { } }), power: 100, - pro_tx_hash: reverse(&pro_tx_hash.to_byte_array()), + pro_tx_hash: pro_tx_hash.to_byte_array().to_vec(), node_address, })) } @@ -174,35 +150,21 @@ impl ValidatorSetV0 { threshold_public_key: Some(crypto::PublicKey { sum: Some(Bls12381(self.threshold_public_key.to_bytes().to_vec())), }), - quorum_hash: reverse(&self.quorum_hash.to_byte_array()), + quorum_hash: self.quorum_hash.to_byte_array().to_vec(), }) } -} - -/// Reverse bytes -/// -/// TODO: This is a workaround for reversed data returned by dashcore_rpc (little endian / big endian handling issue). -/// We need to decide on a consistent approach to endianness and follow it. -fn reverse(data: &[u8]) -> Vec { - // data.reverse(); - data.to_vec() -} - -/// In this case we are changing to this validator set from another validator set and there are no -/// changes -impl From for ValidatorSetUpdate { - fn from(value: ValidatorSetV0) -> Self { + fn to_update(&self) -> ValidatorSetUpdate { let ValidatorSetV0 { quorum_hash, members: validator_set, threshold_public_key, .. - } = value; + } = self; ValidatorSetUpdate { validator_updates: validator_set - .into_values() - .filter_map(|validator| { + .iter() + .filter_map(|(_, validator)| { let ValidatorV0 { pro_tx_hash, public_key, @@ -212,7 +174,8 @@ impl From for ValidatorSetUpdate { is_banned, .. } = validator; - if is_banned { + + if *is_banned { return None; } let node_address = format!( @@ -221,13 +184,12 @@ impl From for ValidatorSetUpdate { node_ip, platform_p2p_port ); - Some(abci::ValidatorUpdate { - pub_key: public_key.map(|public_key| crypto::PublicKey { + pub_key: public_key.as_ref().map(|public_key| crypto::PublicKey { sum: Some(Bls12381(public_key.to_bytes().to_vec())), }), power: 100, - pro_tx_hash: reverse(&pro_tx_hash.to_byte_array()), + pro_tx_hash: pro_tx_hash.to_byte_array().to_vec(), node_address, }) }) @@ -235,23 +197,21 @@ impl From for ValidatorSetUpdate { threshold_public_key: Some(crypto::PublicKey { sum: Some(Bls12381(threshold_public_key.to_bytes().to_vec())), }), - quorum_hash: reverse(&quorum_hash.to_byte_array()), + quorum_hash: quorum_hash.to_byte_array().to_vec(), } } -} -impl From<&ValidatorSetV0> for ValidatorSetUpdate { - fn from(value: &ValidatorSetV0) -> Self { + fn to_update_owned(self) -> ValidatorSetUpdate { let ValidatorSetV0 { quorum_hash, members: validator_set, threshold_public_key, .. - } = value; + } = self; ValidatorSetUpdate { validator_updates: validator_set - .iter() - .filter_map(|(_, validator)| { + .into_values() + .filter_map(|validator| { let ValidatorV0 { pro_tx_hash, public_key, @@ -261,8 +221,7 @@ impl From<&ValidatorSetV0> for ValidatorSetUpdate { is_banned, .. } = validator; - - if *is_banned { + if is_banned { return None; } let node_address = format!( @@ -271,12 +230,13 @@ impl From<&ValidatorSetV0> for ValidatorSetUpdate { node_ip, platform_p2p_port ); + Some(abci::ValidatorUpdate { - pub_key: public_key.as_ref().map(|public_key| crypto::PublicKey { + pub_key: public_key.map(|public_key| crypto::PublicKey { sum: Some(Bls12381(public_key.to_bytes().to_vec())), }), power: 100, - pro_tx_hash: reverse(&pro_tx_hash.to_byte_array()), + pro_tx_hash: pro_tx_hash.to_byte_array().to_vec(), node_address, }) }) @@ -284,15 +244,13 @@ impl From<&ValidatorSetV0> for ValidatorSetUpdate { threshold_public_key: Some(crypto::PublicKey { sum: Some(Bls12381(threshold_public_key.to_bytes().to_vec())), }), - quorum_hash: reverse(&quorum_hash.to_byte_array()), + quorum_hash: quorum_hash.to_byte_array().to_vec(), } } -} -impl ValidatorSetV0 { /// Try to create a quorum from info from the Masternode list (given with state), /// and for information return for quorum members - pub fn try_from_quorum_info_result( + fn try_from_quorum_info_result( value: QuorumInfoResult, state: &PlatformState, ) -> Result { @@ -350,87 +308,3 @@ impl ValidatorSetV0 { }) } } - -/// Trait providing getter methods for `ValidatorSetV0` struct -pub trait ValidatorSetV0Getters { - /// Returns the quorum hash of the validator set. - fn quorum_hash(&self) -> &QuorumHash; - /// Returns rotation quorum index. It's available only for DIP24 quorums - fn quorum_index(&self) -> Option; - /// Returns the active height of the validator set. - fn core_height(&self) -> u32; - /// Returns the members of the validator set. - fn members(&self) -> &BTreeMap; - /// Returns the members of the validator set. - fn members_mut(&mut self) -> &mut BTreeMap; - /// Returns the members of the validator set. - fn members_owned(self) -> BTreeMap; - /// Returns the threshold public key of the validator set. - fn threshold_public_key(&self) -> &BlsPublicKey; -} - -/// Trait providing setter methods for `ValidatorSetV0` struct -pub trait ValidatorSetV0Setters { - /// Sets the quorum hash of the validator set. - fn set_quorum_hash(&mut self, quorum_hash: QuorumHash); - /// Sets the quorum index of the validator set. - fn set_quorum_index(&mut self, index: Option); - /// Sets the active height of the validator set. - fn set_core_height(&mut self, core_height: u32); - /// Sets the members of the validator set. - fn set_members(&mut self, members: BTreeMap); - /// Sets the threshold public key of the validator set. - fn set_threshold_public_key(&mut self, threshold_public_key: BlsPublicKey); -} - -impl ValidatorSetV0Getters for ValidatorSetV0 { - fn quorum_hash(&self) -> &QuorumHash { - &self.quorum_hash - } - - fn quorum_index(&self) -> Option { - self.quorum_index - } - - fn core_height(&self) -> u32 { - self.core_height - } - - fn members(&self) -> &BTreeMap { - &self.members - } - - fn members_mut(&mut self) -> &mut BTreeMap { - &mut self.members - } - - fn members_owned(self) -> BTreeMap { - self.members - } - - fn threshold_public_key(&self) -> &BlsPublicKey { - &self.threshold_public_key - } -} - -impl ValidatorSetV0Setters for ValidatorSetV0 { - fn set_quorum_hash(&mut self, quorum_hash: QuorumHash) { - self.quorum_hash = quorum_hash; - } - - fn set_quorum_index(&mut self, index: Option) { - self.quorum_index = index; - } - - fn set_core_height(&mut self, core_height: u32) { - self.core_height = core_height; - } - - fn set_members(&mut self, members: BTreeMap) { - self.members = members; - } - - fn set_threshold_public_key(&mut self, threshold_public_key: BlsPublicKey) { - self.threshold_public_key = threshold_public_key; - } -} diff --git a/packages/rs-drive-abci/src/platform_types/withdrawal/unsigned_withdrawal_txs/v0/mod.rs b/packages/rs-drive-abci/src/platform_types/withdrawal/unsigned_withdrawal_txs/v0/mod.rs index 0d61d4e471..1143c0aa09 100644 --- a/packages/rs-drive-abci/src/platform_types/withdrawal/unsigned_withdrawal_txs/v0/mod.rs +++ b/packages/rs-drive-abci/src/platform_types/withdrawal/unsigned_withdrawal_txs/v0/mod.rs @@ -1,8 +1,10 @@ //! Withdrawal transactions definitions and processing + use dpp::dashcore::consensus::Encodable; use dpp::dashcore::hashes::Hash; use dpp::dashcore::transaction::special_transaction::TransactionPayload::AssetUnlockPayloadType; use dpp::dashcore::{Transaction, VarInt}; +use std::collections::{BTreeMap, HashMap}; use std::fmt::Display; use tenderdash_abci::proto::types::VoteExtension; use tenderdash_abci::proto::{abci::ExtendVoteExtension, types::VoteExtensionType}; @@ -48,19 +50,64 @@ impl UnsignedWithdrawalTxs { } /// Verifies that the collection of unsigned withdrawal transactions matches the given votes extensions - /// created based on these transactions - pub fn are_matching_with_vote_extensions(&self, other: &[VoteExtension]) -> bool { + /// created based on these transactions. + /// Returns a mapping from transactions to their corresponding vote extensions if they match, or `None` if they don't. + pub fn verify_and_match_with_vote_extensions<'a>( + &'a self, + other: &'a [VoteExtension], + ) -> Option> { if self.0.len() != other.len() { - return false; - }; + return None; + } - !self.0.iter().zip(other.iter()).any(|(tx, vote_extension)| { + // Build a map from sign_request_id to VoteExtension + let mut vote_extension_map = HashMap::new(); + for vote_extension in other { + // Ensure that each signature is 96 bytes (size of a bls sig) + if vote_extension.signature.len() != 96 { + return None; + } + // Ensure sign_request_id is Some + if let Some(sign_request_id) = &vote_extension.sign_request_id { + vote_extension_map.insert(sign_request_id.clone(), vote_extension); + } else { + // If sign_request_id is None, we cannot match, return None + return None; + } + } + + let mut tx_to_vote_extension_map = BTreeMap::new(); + + // For each transaction, check if a matching vote extension exists + for tx in &self.0 { let extend_vote_extension = tx_to_extend_vote_extension(tx); + let sign_request_id = match &extend_vote_extension.sign_request_id { + Some(id) => id, + None => { + // If sign_request_id is None, we cannot match, return None + return None; + } + }; + + match vote_extension_map.get(sign_request_id) { + Some(vote_extension) => { + if vote_extension.r#type != extend_vote_extension.r#type + || vote_extension.extension != extend_vote_extension.extension + { + return None; + } else { + // All good, insert into map + tx_to_vote_extension_map.insert(tx, *vote_extension); + } + } + None => { + // No matching vote extension found + return None; + } + } + } - vote_extension.r#type != extend_vote_extension.r#type - || vote_extension.sign_request_id != extend_vote_extension.sign_request_id - || vote_extension.extension != extend_vote_extension.extension - }) + Some(tx_to_vote_extension_map) } } @@ -112,7 +159,7 @@ impl From<&UnsignedWithdrawalTxs> for Vec { } } -fn tx_to_extend_vote_extension(tx: &Transaction) -> ExtendVoteExtension { +pub(crate) fn tx_to_extend_vote_extension(tx: &Transaction) -> ExtendVoteExtension { let request_id = make_extend_vote_request_id(tx); let extension = tx.txid().as_byte_array().to_vec(); diff --git a/packages/rs-drive-abci/src/query/document_query/v0/mod.rs b/packages/rs-drive-abci/src/query/document_query/v0/mod.rs index 8af82e39cc..d4177878bc 100644 --- a/packages/rs-drive-abci/src/query/document_query/v0/mod.rs +++ b/packages/rs-drive-abci/src/query/document_query/v0/mod.rs @@ -180,9 +180,20 @@ impl Platform { #[cfg(test)] mod tests { use super::*; - use crate::query::tests::{assert_invalid_identifier, setup_platform, store_data_contract}; + use crate::query::tests::{ + assert_invalid_identifier, setup_platform, store_data_contract, store_document, + }; + use assert_matches::assert_matches; + use ciborium::value::Value as CborValue; use dpp::dashcore::Network; + use dpp::data_contract::document_type::random_document::CreateRandomDocument; + use dpp::document::{Document, DocumentV0, DocumentV0Getters}; use dpp::tests::fixtures::get_data_contract_fixture; + use drive::query::{InternalClauses, OrderClause, WhereClause, WhereOperator}; + use indexmap::IndexMap; + use rand::rngs::StdRng; + use rand::SeedableRng; + use std::collections::BTreeMap; #[test] fn test_invalid_document_id() { @@ -479,4 +490,1087 @@ mod tests { }) )); } + + #[test] + fn test_documents_single_item_proof() { + let (platform, state, version) = setup_platform(None, Network::Testnet, None); + + let platform_version = PlatformVersion::latest(); + let created_data_contract = get_data_contract_fixture(None, 0, version.protocol_version); + store_data_contract(&platform, created_data_contract.data_contract(), version); + + let data_contract_id = created_data_contract.data_contract().id(); + let document_type_name = "niceDocument"; + let document_type = created_data_contract + .data_contract() + .document_type_for_name(document_type_name) + .expect("expected document type"); + + let random_document = document_type + .random_document(Some(4), platform_version) + .expect("expected to get random document"); + + store_document( + &platform, + created_data_contract.data_contract(), + document_type, + &random_document, + platform_version, + ); + + let drive_document_query = DriveDocumentQuery { + contract: &created_data_contract.data_contract(), + document_type, + internal_clauses: Default::default(), + offset: None, + limit: Some(1), + order_by: Default::default(), + start_at: None, + start_at_included: false, + block_time_ms: None, + }; + + let request = GetDocumentsRequestV0 { + data_contract_id: data_contract_id.to_vec(), + document_type: document_type_name.to_string(), + r#where: vec![], + limit: 1, + order_by: vec![], + prove: true, + start: None, + }; + + let result = platform + .query_documents_v0(request, &state, version) + .expect("expected query to succeed"); + + let Some(GetDocumentsResponseV0 { + result: Some(get_documents_response_v0::Result::Proof(proof)), + metadata: Some(_), + }) = result.data + else { + panic!("expected proof") + }; + + let (_, documents) = drive_document_query + .verify_proof(&proof.grovedb_proof, platform_version) + .expect("expected to verify proof"); + + assert_eq!(documents.len(), 1); + assert_eq!(documents.get(0).expect("first"), &random_document); + } + + #[test] + fn test_documents_range_proof() { + let (platform, state, version) = setup_platform(None, Network::Testnet, None); + + let platform_version = PlatformVersion::latest(); + let created_data_contract = get_data_contract_fixture(None, 0, version.protocol_version); + store_data_contract(&platform, created_data_contract.data_contract(), version); + + let data_contract_id = created_data_contract.data_contract().id(); + let document_type_name = "niceDocument"; + let document_type = created_data_contract + .data_contract() + .document_type_for_name(document_type_name) + .expect("expected document type"); + + let mut std_rng = StdRng::seed_from_u64(393); + let mut documents_by_id = BTreeMap::new(); + for _i in 0..20 { + let random_document = document_type + .random_document_with_rng(&mut std_rng, platform_version) + .expect("expected to get random document"); + store_document( + &platform, + created_data_contract.data_contract(), + document_type, + &random_document, + platform_version, + ); + documents_by_id.insert(random_document.id(), random_document); + } + + let drive_document_query = DriveDocumentQuery { + contract: &created_data_contract.data_contract(), + document_type, + internal_clauses: Default::default(), + offset: None, + limit: Some(10), + order_by: Default::default(), + start_at: None, + start_at_included: false, + block_time_ms: None, + }; + + let request = GetDocumentsRequestV0 { + data_contract_id: data_contract_id.to_vec(), + document_type: document_type_name.to_string(), + r#where: vec![], + limit: 10, + order_by: vec![], + prove: true, + start: None, + }; + + let result = platform + .query_documents_v0(request, &state, version) + .expect("expected query to succeed"); + + let Some(GetDocumentsResponseV0 { + result: Some(get_documents_response_v0::Result::Proof(proof)), + metadata: Some(_), + }) = result.data + else { + panic!("expected proof") + }; + + let (_, queried_documents) = drive_document_query + .verify_proof(&proof.grovedb_proof, platform_version) + .expect("expected to verify proof"); + + assert_eq!(queried_documents.len(), 10); + assert_eq!( + queried_documents.get(9).expect("first"), + documents_by_id + .values() + .nth(9) + .expect("expected to get 9th document") + ); + } + + #[test] + fn test_documents_start_after_proof_primary_index() { + let (platform, state, version) = setup_platform(None, Network::Testnet, None); + + let platform_version = PlatformVersion::latest(); + let created_data_contract = get_data_contract_fixture(None, 0, version.protocol_version); + store_data_contract(&platform, created_data_contract.data_contract(), version); + + let data_contract_id = created_data_contract.data_contract().id(); + let document_type_name = "niceDocument"; + let document_type = created_data_contract + .data_contract() + .document_type_for_name(document_type_name) + .expect("expected document type"); + + let mut std_rng = StdRng::seed_from_u64(393); + let mut documents_by_id = BTreeMap::new(); + for _i in 0..20 { + let random_document = document_type + .random_document_with_rng(&mut std_rng, platform_version) + .expect("expected to get random document"); + store_document( + &platform, + created_data_contract.data_contract(), + document_type, + &random_document, + platform_version, + ); + documents_by_id.insert(random_document.id(), random_document); + } + + let after = documents_by_id + .keys() + .nth(9) + .expect("expected to get 9th document") + .to_buffer(); + + let drive_document_query = DriveDocumentQuery { + contract: &created_data_contract.data_contract(), + document_type, + internal_clauses: Default::default(), + offset: None, + limit: Some(10), + order_by: Default::default(), + start_at: Some(after), + start_at_included: false, + block_time_ms: None, + }; + + let request = GetDocumentsRequestV0 { + data_contract_id: data_contract_id.to_vec(), + document_type: document_type_name.to_string(), + r#where: vec![], + limit: 10, + order_by: vec![], + prove: true, + start: Some(Start::StartAfter(after.to_vec())), + }; + + let result = platform + .query_documents_v0(request, &state, version) + .expect("expected query to succeed"); + + let Some(GetDocumentsResponseV0 { + result: Some(get_documents_response_v0::Result::Proof(proof)), + metadata: Some(_), + }) = result.data + else { + panic!("expected proof") + }; + + let (_, queried_documents) = drive_document_query + .verify_proof(&proof.grovedb_proof, platform_version) + .expect("expected to verify proof"); + + assert_eq!(queried_documents.len(), 10); + assert_eq!( + queried_documents.get(9).expect("last"), + documents_by_id + .values() + .nth(19) + .expect("expected to get 9th document") + ); + } + + fn serialize_vec_to_cbor>(input: Vec) -> Result, Error> { + let values = Value::Array( + input + .into_iter() + .map(|v| v.into() as Value) + .collect::>(), + ); + + let cbor_values: CborValue = TryInto::::try_into(values) + .map_err(|e| Error::Protocol(dpp::ProtocolError::EncodingError(e.to_string())))?; + + let mut serialized = Vec::new(); + ciborium::ser::into_writer(&cbor_values, &mut serialized) + .map_err(|e| Error::Protocol(dpp::ProtocolError::EncodingError(e.to_string())))?; + + Ok(serialized) + } + + #[test] + fn test_documents_start_after_proof_secondary_index() { + let (platform, state, version) = setup_platform(Some((1, 1)), Network::Testnet, None); + + let platform_version = PlatformVersion::latest(); + let withdrawals = platform + .drive + .cache + .system_data_contracts + .load_withdrawals(); + + let data_contract_id = withdrawals.id(); + let document_type_name = "withdrawal"; + let document_type = withdrawals + .document_type_for_name(document_type_name) + .expect("expected document type"); + + let mut std_rng = StdRng::seed_from_u64(393); + let mut documents_by_created_at = BTreeMap::new(); + + // Define the base time as the current system time + let base_time = 1730028481000; + + for i in 0..20 { + let created_at = base_time + i * 20000; + // Create a Document with the desired properties + let random_document: Document = DocumentV0 { + id: Identifier::random_with_rng(&mut std_rng), + owner_id: Identifier::random_with_rng(&mut std_rng), + properties: { + let mut properties = BTreeMap::new(); + properties.insert("status".to_string(), Value::I64(0)); // Always queued + properties.insert("pooling".to_string(), Value::I64(0)); // Always 0 + properties.insert("coreFeePerByte".to_string(), Value::I64(1)); // Always 1 + properties.insert("amount".to_string(), Value::I64(1000)); // Set a minimum amount of 1000 + properties.insert("outputScript".to_string(), Value::Bytes(vec![])); // Set an empty output script + properties + }, + revision: Some(1), // Example revision + created_at: Some(created_at), // Set created_at + updated_at: Some(created_at), // Set updated_at + 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, + } + .into(); + store_document( + &platform, + &withdrawals, + document_type, + &random_document, + platform_version, + ); + documents_by_created_at.insert(created_at, random_document); + } + + let after = documents_by_created_at + .values() + .nth(9) + .expect("expected to get 9th document") + .id(); + + let drive_document_query = DriveDocumentQuery { + contract: &withdrawals, + document_type, + internal_clauses: InternalClauses { + primary_key_in_clause: None, + primary_key_equal_clause: None, + in_clause: None, + range_clause: None, + equal_clauses: BTreeMap::from([ + ( + "status".to_string(), + WhereClause { + field: "status".to_string(), + operator: WhereOperator::Equal, + value: Value::I64(0), + }, + ), + ( + "pooling".to_string(), + WhereClause { + field: "pooling".to_string(), + operator: WhereOperator::Equal, + value: Value::I64(0), + }, + ), + ( + "coreFeePerByte".to_string(), + WhereClause { + field: "coreFeePerByte".to_string(), + operator: WhereOperator::Equal, + value: Value::I64(1), + }, + ), + ]), + }, + offset: None, + limit: Some(10), + order_by: IndexMap::from([( + "$updatedAt".to_string(), + OrderClause { + field: "$updatedAt".to_string(), + ascending: true, + }, + )]), + start_at: Some(after.to_buffer()), + start_at_included: false, + block_time_ms: None, + }; + + let where_clauses = serialize_vec_to_cbor( + drive_document_query + .internal_clauses + .equal_clauses + .values() + .cloned() + .collect(), + ) + .expect("where clauses serialization should never fail"); + let order_by = + serialize_vec_to_cbor(drive_document_query.order_by.values().cloned().collect()) + .expect("order by clauses serialization should never fail"); + + let request = GetDocumentsRequestV0 { + data_contract_id: data_contract_id.to_vec(), + document_type: document_type_name.to_string(), + r#where: where_clauses, + limit: 10, + order_by, + prove: true, + start: Some(Start::StartAfter(after.to_vec())), + }; + + let result = platform + .query_documents_v0(request, &state, version) + .expect("expected query to succeed"); + + let Some(GetDocumentsResponseV0 { + result: Some(get_documents_response_v0::Result::Proof(proof)), + metadata: Some(_), + }) = result.data + else { + panic!("expected proof") + }; + + let (_, queried_documents) = drive_document_query + .verify_proof(&proof.grovedb_proof, platform_version) + .expect("expected to verify proof"); + + assert_eq!(queried_documents.len(), 10); + assert_eq!( + queried_documents.get(9).expect("last"), + documents_by_created_at + .values() + .nth(19) + .expect("expected to get 9th document") + ); + } + + #[test] + fn test_documents_start_after_proof_secondary_index_many_statuses() { + let (platform, state, version) = setup_platform(Some((1, 1)), Network::Testnet, None); + + let platform_version = PlatformVersion::latest(); + let withdrawals = platform + .drive + .cache + .system_data_contracts + .load_withdrawals(); + + let data_contract_id = withdrawals.id(); + let document_type_name = "withdrawal"; + let document_type = withdrawals + .document_type_for_name(document_type_name) + .expect("expected document type"); + + let mut std_rng = StdRng::seed_from_u64(393); + let mut documents_by_created_at = BTreeMap::new(); + + // Define the base time as the current system time + let base_time = 1730028481000; + + for i in 0..20 { + let created_at = base_time + i * 20000; + // Create a Document with the desired properties + let random_document: Document = DocumentV0 { + id: Identifier::random_with_rng(&mut std_rng), + owner_id: Identifier::random_with_rng(&mut std_rng), + properties: { + let mut properties = BTreeMap::new(); + properties.insert("status".to_string(), Value::I64(i as i64 % 4)); // Always queued + properties.insert("pooling".to_string(), Value::I64(0)); // Always 0 + properties.insert("coreFeePerByte".to_string(), Value::I64(1)); // Always 1 + properties.insert("amount".to_string(), Value::I64(1000)); // Set a minimum amount of 1000 + properties.insert("outputScript".to_string(), Value::Bytes(vec![])); // Set an empty output script + properties + }, + revision: Some(1), // Example revision + created_at: Some(created_at), // Set created_at + updated_at: Some(created_at), // Set updated_at + 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, + } + .into(); + store_document( + &platform, + &withdrawals, + document_type, + &random_document, + platform_version, + ); + documents_by_created_at.insert(created_at, random_document); + } + + let after = documents_by_created_at + .values() + .nth(9) + .expect("expected to get 9th document") + .id(); + + let drive_document_query = DriveDocumentQuery { + contract: &withdrawals, + document_type, + internal_clauses: InternalClauses { + primary_key_in_clause: None, + primary_key_equal_clause: None, + in_clause: None, + range_clause: None, + equal_clauses: BTreeMap::from([ + ( + "status".to_string(), + WhereClause { + field: "status".to_string(), + operator: WhereOperator::Equal, + value: Value::I64(0), + }, + ), + ( + "pooling".to_string(), + WhereClause { + field: "pooling".to_string(), + operator: WhereOperator::Equal, + value: Value::I64(0), + }, + ), + ( + "coreFeePerByte".to_string(), + WhereClause { + field: "coreFeePerByte".to_string(), + operator: WhereOperator::Equal, + value: Value::I64(1), + }, + ), + ]), + }, + offset: None, + limit: Some(3), + order_by: IndexMap::from([( + "$updatedAt".to_string(), + OrderClause { + field: "$updatedAt".to_string(), + ascending: true, + }, + )]), + start_at: Some(after.to_buffer()), + start_at_included: false, + block_time_ms: None, + }; + + let where_clauses = serialize_vec_to_cbor( + drive_document_query + .internal_clauses + .equal_clauses + .values() + .cloned() + .collect(), + ) + .expect("where clauses serialization should never fail"); + let order_by = + serialize_vec_to_cbor(drive_document_query.order_by.values().cloned().collect()) + .expect("order by clauses serialization should never fail"); + + let request = GetDocumentsRequestV0 { + data_contract_id: data_contract_id.to_vec(), + document_type: document_type_name.to_string(), + r#where: where_clauses, + limit: 3, + order_by, + prove: true, + start: Some(Start::StartAfter(after.to_vec())), + }; + + let result = platform + .query_documents_v0(request, &state, version) + .expect("expected query to succeed"); + + let Some(GetDocumentsResponseV0 { + result: Some(get_documents_response_v0::Result::Proof(proof)), + metadata: Some(_), + }) = result.data + else { + panic!("expected proof") + }; + + let (_, queried_documents) = drive_document_query + .verify_proof(&proof.grovedb_proof, platform_version) + .expect("expected to verify proof"); + + assert_eq!(queried_documents.len(), 2); + assert_eq!( + queried_documents.get(1).expect("last"), + documents_by_created_at + .values() + .nth(16) + .expect("expected to get 2nd document") + ); + } + + #[test] + fn test_documents_proof_secondary_index_in_query() { + let (platform, state, version) = setup_platform(Some((1, 1)), Network::Testnet, None); + + let platform_version = PlatformVersion::latest(); + let withdrawals = platform + .drive + .cache + .system_data_contracts + .load_withdrawals(); + + let data_contract_id = withdrawals.id(); + let document_type_name = "withdrawal"; + let document_type = withdrawals + .document_type_for_name(document_type_name) + .expect("expected document type"); + + let mut std_rng = StdRng::seed_from_u64(393); + let mut documents_by_id = BTreeMap::new(); + + // Define the base time as the current system time + let base_time = 1730028481000; + + for i in 0..20 { + let created_at = base_time + i * 20000; + // Create a Document with the desired properties + let random_document: Document = DocumentV0 { + id: Identifier::random_with_rng(&mut std_rng), + owner_id: Identifier::random_with_rng(&mut std_rng), + properties: { + let mut properties = BTreeMap::new(); + properties.insert("status".to_string(), Value::I64(i as i64 % 4)); // Always queued + properties.insert("pooling".to_string(), Value::I64(0)); // Always 0 + properties.insert("coreFeePerByte".to_string(), Value::I64(1)); // Always 1 + properties.insert("amount".to_string(), Value::I64(1000)); // Set a minimum amount of 1000 + properties.insert("outputScript".to_string(), Value::Bytes(vec![])); // Set an empty output script + properties + }, + revision: Some(1), // Example revision + created_at: Some(created_at), // Set created_at + updated_at: Some(created_at), // Set updated_at + 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, + } + .into(); + store_document( + &platform, + &withdrawals, + document_type, + &random_document, + platform_version, + ); + documents_by_id.insert(random_document.id(), random_document); + } + + let drive_document_query = DriveDocumentQuery { + contract: &withdrawals, + document_type, + internal_clauses: InternalClauses { + primary_key_in_clause: None, + primary_key_equal_clause: None, + in_clause: Some(WhereClause { + field: "status".to_string(), + operator: WhereOperator::In, + value: Value::Array(vec![ + Value::I64(0), + Value::I64(1), + Value::I64(2), + Value::I64(3), + Value::I64(4), + ]), + }), + range_clause: None, + equal_clauses: BTreeMap::default(), + }, + offset: None, + limit: Some(3), + order_by: IndexMap::from([ + ( + "status".to_string(), + OrderClause { + field: "status".to_string(), + ascending: true, + }, + ), + ( + "transactionIndex".to_string(), + OrderClause { + field: "transactionIndex".to_string(), + ascending: true, + }, + ), + ]), + start_at: None, + start_at_included: false, + block_time_ms: None, + }; + + let mut where_clauses: Vec<_> = drive_document_query + .internal_clauses + .equal_clauses + .values() + .cloned() + .collect(); + + where_clauses.insert( + 0, + drive_document_query + .internal_clauses + .in_clause + .clone() + .unwrap(), + ); + + let where_clauses_serialized = serialize_vec_to_cbor(where_clauses) + .expect("where clauses serialization should never fail"); + let order_by = + serialize_vec_to_cbor(drive_document_query.order_by.values().cloned().collect()) + .expect("order by clauses serialization should never fail"); + + let request = GetDocumentsRequestV0 { + data_contract_id: data_contract_id.to_vec(), + document_type: document_type_name.to_string(), + r#where: where_clauses_serialized, + limit: 3, + order_by, + prove: true, + start: None, + }; + + let result = platform + .query_documents_v0(request, &state, version) + .expect("expected query to succeed"); + + assert!(result.errors.is_empty(), "errors are {:?}", result.errors); + + let Some(GetDocumentsResponseV0 { + result: Some(get_documents_response_v0::Result::Proof(proof)), + metadata: Some(_), + }) = result.data + else { + panic!("expected proof") + }; + + let (_, queried_documents) = drive_document_query + .verify_proof(&proof.grovedb_proof, platform_version) + .expect("expected to verify proof"); + + assert_eq!(queried_documents.len(), 3); + } + + #[test] + fn test_documents_start_after_proof_secondary_index_in_query() { + let (platform, state, version) = setup_platform(Some((1, 1)), Network::Testnet, None); + + let platform_version = PlatformVersion::latest(); + let withdrawals = platform + .drive + .cache + .system_data_contracts + .load_withdrawals(); + + let data_contract_id = withdrawals.id(); + let document_type_name = "withdrawal"; + let document_type = withdrawals + .document_type_for_name(document_type_name) + .expect("expected document type"); + + let mut std_rng = StdRng::seed_from_u64(393); + let mut documents_by_created_at = BTreeMap::new(); + + // Define the base time as the current system time + let base_time = 1730028481000; + + for i in 0..20 { + let created_at = base_time + i * 20000; + // Create a Document with the desired properties + let random_document: Document = DocumentV0 { + id: Identifier::random_with_rng(&mut std_rng), + owner_id: Identifier::random_with_rng(&mut std_rng), + properties: { + let mut properties = BTreeMap::new(); + properties.insert("status".to_string(), Value::I64(i as i64 % 4)); // Always queued + properties.insert("pooling".to_string(), Value::I64(0)); // Always 0 + properties.insert("coreFeePerByte".to_string(), Value::I64(1)); // Always 1 + properties.insert("amount".to_string(), Value::I64(1000)); // Set a minimum amount of 1000 + properties.insert("outputScript".to_string(), Value::Bytes(vec![])); // Set an empty output script + properties + }, + revision: Some(1), // Example revision + created_at: Some(created_at), // Set created_at + updated_at: Some(created_at), // Set updated_at + 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, + } + .into(); + store_document( + &platform, + &withdrawals, + document_type, + &random_document, + platform_version, + ); + documents_by_created_at.insert(created_at, random_document); + } + + let after = documents_by_created_at + .values() + .nth(4) + .expect("expected to get 9th document") + .id(); + + let drive_document_query = DriveDocumentQuery { + contract: &withdrawals, + document_type, + internal_clauses: InternalClauses { + primary_key_in_clause: None, + primary_key_equal_clause: None, + in_clause: Some(WhereClause { + field: "status".to_string(), + operator: WhereOperator::In, + value: Value::Array(vec![ + Value::I64(0), + Value::I64(1), + Value::I64(2), + Value::I64(3), + Value::I64(4), + ]), + }), + range_clause: None, + equal_clauses: BTreeMap::default(), + }, + offset: None, + limit: Some(3), + order_by: IndexMap::from([ + ( + "status".to_string(), + OrderClause { + field: "status".to_string(), + ascending: true, + }, + ), + ( + "transactionIndex".to_string(), + OrderClause { + field: "transactionIndex".to_string(), + ascending: true, + }, + ), + ]), + start_at: Some(after.to_buffer()), + start_at_included: false, + block_time_ms: None, + }; + + let mut where_clauses: Vec<_> = drive_document_query + .internal_clauses + .equal_clauses + .values() + .cloned() + .collect(); + + where_clauses.insert( + 0, + drive_document_query + .internal_clauses + .in_clause + .clone() + .unwrap(), + ); + + let where_clauses_serialized = serialize_vec_to_cbor(where_clauses) + .expect("where clauses serialization should never fail"); + let order_by = + serialize_vec_to_cbor(drive_document_query.order_by.values().cloned().collect()) + .expect("order by clauses serialization should never fail"); + + let request = GetDocumentsRequestV0 { + data_contract_id: data_contract_id.to_vec(), + document_type: document_type_name.to_string(), + r#where: where_clauses_serialized, + limit: 3, + order_by, + prove: true, + start: Some(Start::StartAfter(after.to_vec())), + }; + + let result = platform + .query_documents_v0(request, &state, version) + .expect("expected query to succeed"); + + assert!(result.errors.is_empty(), "errors are {:?}", result.errors); + + let Some(GetDocumentsResponseV0 { + result: Some(get_documents_response_v0::Result::Proof(proof)), + metadata: Some(_), + }) = result.data + else { + panic!("expected proof") + }; + + let (_, queried_documents) = drive_document_query + .verify_proof(&proof.grovedb_proof, platform_version) + .expect("expected to verify proof"); + + assert_eq!(queried_documents.len(), 3); + assert_eq!( + queried_documents.get(1).expect("last"), + documents_by_created_at + .values() + .nth(16) + .expect("expected to get 2nd document") + ); + } + + //todo: this should be possible + #[test] + #[ignore] + fn test_documents_start_after_proof_secondary_index_in_query_2() { + let (platform, state, version) = setup_platform(Some((1, 1)), Network::Testnet, None); + + let platform_version = PlatformVersion::latest(); + let withdrawals = platform + .drive + .cache + .system_data_contracts + .load_withdrawals(); + + let data_contract_id = withdrawals.id(); + let document_type_name = "withdrawal"; + let document_type = withdrawals + .document_type_for_name(document_type_name) + .expect("expected document type"); + + let mut std_rng = StdRng::seed_from_u64(393); + let mut documents_by_created_at = BTreeMap::new(); + + // Define the base time as the current system time + let base_time = 1730028481000; + + for i in 0..20 { + let created_at = base_time + i * 20000; + // Create a Document with the desired properties + let random_document: Document = DocumentV0 { + id: Identifier::random_with_rng(&mut std_rng), + owner_id: Identifier::random_with_rng(&mut std_rng), + properties: { + let mut properties = BTreeMap::new(); + properties.insert("status".to_string(), Value::I64(i as i64 % 4)); // Always queued + properties.insert("pooling".to_string(), Value::I64(0)); // Always 0 + properties.insert("coreFeePerByte".to_string(), Value::I64(1)); // Always 1 + properties.insert("amount".to_string(), Value::I64(1000)); // Set a minimum amount of 1000 + properties.insert("outputScript".to_string(), Value::Bytes(vec![])); // Set an empty output script + properties + }, + revision: Some(1), // Example revision + created_at: Some(created_at), // Set created_at + updated_at: Some(created_at), // Set updated_at + 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, + } + .into(); + store_document( + &platform, + &withdrawals, + document_type, + &random_document, + platform_version, + ); + documents_by_created_at.insert(created_at, random_document); + } + + let after = documents_by_created_at + .values() + .nth(9) + .expect("expected to get 9th document") + .id(); + + let drive_document_query = DriveDocumentQuery { + contract: &withdrawals, + document_type, + internal_clauses: InternalClauses { + primary_key_in_clause: None, + primary_key_equal_clause: None, + in_clause: Some(WhereClause { + field: "status".to_string(), + operator: WhereOperator::In, + value: Value::Array(vec![ + Value::I64(0), + Value::I64(1), + Value::I64(2), + Value::I64(3), + Value::I64(4), + ]), + }), + range_clause: None, + equal_clauses: BTreeMap::from([ + ( + "pooling".to_string(), + WhereClause { + field: "pooling".to_string(), + operator: WhereOperator::Equal, + value: Value::I64(0), + }, + ), + ( + "coreFeePerByte".to_string(), + WhereClause { + field: "coreFeePerByte".to_string(), + operator: WhereOperator::Equal, + value: Value::I64(1), + }, + ), + ]), + }, + offset: None, + limit: Some(3), + order_by: IndexMap::from([( + "$updatedAt".to_string(), + OrderClause { + field: "$updatedAt".to_string(), + ascending: true, + }, + )]), + start_at: Some(after.to_buffer()), + start_at_included: false, + block_time_ms: None, + }; + + let mut where_clauses: Vec<_> = drive_document_query + .internal_clauses + .equal_clauses + .values() + .cloned() + .collect(); + + where_clauses.insert( + 0, + drive_document_query + .internal_clauses + .in_clause + .clone() + .unwrap(), + ); + + let where_clauses_serialized = serialize_vec_to_cbor(where_clauses) + .expect("where clauses serialization should never fail"); + let order_by = + serialize_vec_to_cbor(drive_document_query.order_by.values().cloned().collect()) + .expect("order by clauses serialization should never fail"); + + let request = GetDocumentsRequestV0 { + data_contract_id: data_contract_id.to_vec(), + document_type: document_type_name.to_string(), + r#where: where_clauses_serialized, + limit: 3, + order_by, + prove: true, + start: Some(Start::StartAfter(after.to_vec())), + }; + + let result = platform + .query_documents_v0(request, &state, version) + .expect("expected query to succeed"); + + assert!(result.errors.is_empty(), "errors are {:?}", result.errors); + + let Some(GetDocumentsResponseV0 { + result: Some(get_documents_response_v0::Result::Proof(proof)), + metadata: Some(_), + }) = result.data + else { + panic!("expected proof") + }; + + let (_, queried_documents) = drive_document_query + .verify_proof(&proof.grovedb_proof, platform_version) + .expect("expected to verify proof"); + + assert_eq!(queried_documents.len(), 2); + assert_eq!( + queried_documents.get(1).expect("last"), + documents_by_created_at + .values() + .nth(16) + .expect("expected to get 2nd document") + ); + } } diff --git a/packages/rs-drive-abci/src/query/mod.rs b/packages/rs-drive-abci/src/query/mod.rs index a7d58c7358..6be97cc1cf 100644 --- a/packages/rs-drive-abci/src/query/mod.rs +++ b/packages/rs-drive-abci/src/query/mod.rs @@ -32,9 +32,15 @@ pub(crate) mod tests { use crate::config::PlatformConfig; use dpp::dashcore::Network; + use dpp::data_contract::document_type::DocumentTypeRef; + use dpp::document::Document; use dpp::prelude::{CoreBlockHeight, TimestampMillis}; - use drive::util::batch::DataContractOperationType; - use drive::util::batch::DriveOperation::DataContractOperation; + use drive::util::batch::DriveOperation::{DataContractOperation, DocumentOperation}; + use drive::util::batch::{DataContractOperationType, DocumentOperationType}; + use drive::util::object_size_info::{ + DataContractInfo, DocumentInfo, DocumentTypeInfo, OwnedDocumentInfo, + }; + use drive::util::storage_flags::StorageFlags; use platform_version::version::{PlatformVersion, ProtocolVersion}; use std::borrow::Cow; use std::sync::Arc; @@ -108,6 +114,40 @@ pub(crate) mod tests { .expect("expected to apply drive operations"); } + pub fn store_document( + platform: &Platform, + data_contract: &DataContract, + document_type: DocumentTypeRef, + document: &Document, + platform_version: &PlatformVersion, + ) { + let storage_flags = Some(Cow::Owned(StorageFlags::SingleEpoch(0))); + + let operation = DocumentOperation(DocumentOperationType::AddDocument { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentInfo::DocumentRefInfo((document, storage_flags)), + owner_id: None, + }, + contract_info: DataContractInfo::BorrowedDataContract(data_contract), + document_type_info: DocumentTypeInfo::DocumentTypeRef(document_type), + override_document: false, + }); + + let block_info = BlockInfo::genesis(); + + platform + .drive + .apply_drive_operations( + vec![operation], + true, + &block_info, + None, + platform_version, + None, + ) + .expect("expected to apply drive operations"); + } + pub fn assert_invalid_identifier( validation_result: QueryValidationResult, ) { diff --git a/packages/rs-drive-abci/src/query/service.rs b/packages/rs-drive-abci/src/query/service.rs index 218b1f6f69..54e51348c0 100644 --- a/packages/rs-drive-abci/src/query/service.rs +++ b/packages/rs-drive-abci/src/query/service.rs @@ -15,12 +15,13 @@ use dapi_grpc::platform::v0::{ GetContestedResourceIdentityVotesResponse, GetContestedResourceVoteStateRequest, GetContestedResourceVoteStateResponse, GetContestedResourceVotersForIdentityRequest, GetContestedResourceVotersForIdentityResponse, GetContestedResourcesRequest, - GetContestedResourcesResponse, GetDataContractHistoryRequest, GetDataContractHistoryResponse, - GetDataContractRequest, GetDataContractResponse, GetDataContractsRequest, - GetDataContractsResponse, GetDocumentsRequest, GetDocumentsResponse, GetEpochsInfoRequest, - GetEpochsInfoResponse, GetEvonodesProposedEpochBlocksByIdsRequest, - GetEvonodesProposedEpochBlocksByRangeRequest, GetEvonodesProposedEpochBlocksResponse, - GetIdentitiesBalancesRequest, GetIdentitiesBalancesResponse, GetIdentitiesContractKeysRequest, + GetContestedResourcesResponse, GetCurrentQuorumsInfoRequest, GetCurrentQuorumsInfoResponse, + GetDataContractHistoryRequest, GetDataContractHistoryResponse, GetDataContractRequest, + GetDataContractResponse, GetDataContractsRequest, GetDataContractsResponse, + GetDocumentsRequest, GetDocumentsResponse, GetEpochsInfoRequest, GetEpochsInfoResponse, + GetEvonodesProposedEpochBlocksByIdsRequest, GetEvonodesProposedEpochBlocksByRangeRequest, + GetEvonodesProposedEpochBlocksResponse, GetIdentitiesBalancesRequest, + GetIdentitiesBalancesResponse, GetIdentitiesContractKeysRequest, GetIdentitiesContractKeysResponse, GetIdentityBalanceAndRevisionRequest, GetIdentityBalanceAndRevisionResponse, GetIdentityBalanceRequest, GetIdentityBalanceResponse, GetIdentityByPublicKeyHashRequest, GetIdentityByPublicKeyHashResponse, @@ -596,6 +597,18 @@ impl PlatformService for QueryService { ) .await } + + async fn get_current_quorums_info( + &self, + request: Request, + ) -> Result, Status> { + self.handle_blocking_query( + request, + Platform::::query_current_quorums_info, + "query_current_quorums_info", + ) + .await + } } fn query_error_into_status(error: QueryError) -> Status { diff --git a/packages/rs-drive-abci/src/query/system/current_quorums_info/mod.rs b/packages/rs-drive-abci/src/query/system/current_quorums_info/mod.rs new file mode 100644 index 0000000000..85ac929687 --- /dev/null +++ b/packages/rs-drive-abci/src/query/system/current_quorums_info/mod.rs @@ -0,0 +1,59 @@ +mod v0; + +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_current_quorums_info_request::Version as RequestVersion; +use dapi_grpc::platform::v0::get_current_quorums_info_response::Version as ResponseVersion; +use dapi_grpc::platform::v0::{GetCurrentQuorumsInfoRequest, GetCurrentQuorumsInfoResponse}; +use dpp::version::PlatformVersion; + +impl Platform { + /// Querying of current quorums info + pub fn query_current_quorums_info( + &self, + GetCurrentQuorumsInfoRequest { version }: GetCurrentQuorumsInfoRequest, + platform_state: &PlatformState, + platform_version: &PlatformVersion, + ) -> Result, Error> { + let Some(version) = version else { + return Ok(QueryValidationResult::new_with_error( + QueryError::DecodingError( + "could not decode current quorums info request".to_string(), + ), + )); + }; + + let feature_version_bounds = &platform_version + .drive_abci + .query + .system + .current_quorums_info; + + let feature_version = match &version { + RequestVersion::V0(_) => 0, + }; + if !feature_version_bounds.check_version(feature_version) { + return Ok(QueryValidationResult::new_with_error( + QueryError::UnsupportedQueryVersion( + "current_quorums_info".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_current_quorums_info_v0(request_v0, platform_state)?; + + Ok(result.map(|response_v0| GetCurrentQuorumsInfoResponse { + version: Some(ResponseVersion::V0(response_v0)), + })) + } + } + } +} diff --git a/packages/rs-drive-abci/src/query/system/current_quorums_info/v0/mod.rs b/packages/rs-drive-abci/src/query/system/current_quorums_info/v0/mod.rs new file mode 100644 index 0000000000..f512f4b8f0 --- /dev/null +++ b/packages/rs-drive-abci/src/query/system/current_quorums_info/v0/mod.rs @@ -0,0 +1,68 @@ +use crate::error::Error; +use crate::platform_types::platform::Platform; +use crate::platform_types::platform_state::v0::PlatformStateV0Methods; +use crate::platform_types::platform_state::PlatformState; +use crate::platform_types::validator_set::v0::ValidatorSetV0Getters; +use crate::query::QueryValidationResult; +use dapi_grpc::platform::v0::get_current_quorums_info_request::GetCurrentQuorumsInfoRequestV0; +use dapi_grpc::platform::v0::get_current_quorums_info_response::{ + GetCurrentQuorumsInfoResponseV0, ValidatorSetV0, ValidatorV0, +}; +use dpp::dashcore::hashes::Hash; + +impl Platform { + pub(super) fn query_current_quorums_info_v0( + &self, + GetCurrentQuorumsInfoRequestV0 {}: GetCurrentQuorumsInfoRequestV0, + platform_state: &PlatformState, + ) -> Result, Error> { + // Get all validator sets sorted by core height + let validator_sets_sorted = + platform_state.validator_sets_sorted_by_core_height_by_most_recent(); + + // Collect the validator sets in the desired format + let validator_sets: Vec = validator_sets_sorted + .iter() + .map(|validator_set| { + // Map each ProTxHash to a ValidatorV0 object + let members: Vec = validator_set + .members() + .iter() + .map(|(pro_tx_hash, validator)| ValidatorV0 { + pro_tx_hash: pro_tx_hash.as_byte_array().to_vec(), + node_ip: validator.node_ip.clone(), + is_banned: validator.is_banned, + }) + .collect(); + + // Construct a ValidatorSetV0 object + ValidatorSetV0 { + quorum_hash: validator_set.quorum_hash().as_byte_array().to_vec(), + core_height: validator_set.core_height(), + members, + threshold_public_key: validator_set.threshold_public_key().to_bytes().to_vec(), + } + }) + .collect(); + + // Get the current proposer index and current quorum index, if applicable + let current_quorum_index = platform_state.current_validator_set_quorum_hash(); + let last_committed_block_proposer_pro_tx_hash = + platform_state.last_committed_block_proposer_pro_tx_hash(); + + // Construct the response + let response = GetCurrentQuorumsInfoResponseV0 { + quorum_hashes: validator_sets_sorted + .iter() + .map(|validator_set| validator_set.quorum_hash().as_byte_array().to_vec()) + .collect(), + validator_sets, + last_block_proposer: last_committed_block_proposer_pro_tx_hash.to_vec(), + current_quorum_hash: current_quorum_index.as_byte_array().to_vec(), + metadata: Some(self.response_metadata_v0(platform_state)), + }; + + // Return the response wrapped in a QueryValidationResult + Ok(QueryValidationResult::new_with_data(response)) + } +} diff --git a/packages/rs-drive-abci/src/query/system/mod.rs b/packages/rs-drive-abci/src/query/system/mod.rs index 8eb018a513..6eecfed910 100644 --- a/packages/rs-drive-abci/src/query/system/mod.rs +++ b/packages/rs-drive-abci/src/query/system/mod.rs @@ -1,3 +1,4 @@ +mod current_quorums_info; mod epoch_infos; mod path_elements; mod status; diff --git a/packages/rs-drive-abci/src/query/system/path_elements/mod.rs b/packages/rs-drive-abci/src/query/system/path_elements/mod.rs index 1a91523602..cf056e84b2 100644 --- a/packages/rs-drive-abci/src/query/system/path_elements/mod.rs +++ b/packages/rs-drive-abci/src/query/system/path_elements/mod.rs @@ -20,7 +20,7 @@ impl Platform { ) -> Result, Error> { let Some(version) = version else { return Ok(QueryValidationResult::new_with_error( - QueryError::DecodingError("could not decode epoch info request".to_string()), + QueryError::DecodingError("could not decode path elements".to_string()), )); }; diff --git a/packages/rs-drive-abci/src/query/system/total_credits_in_platform/mod.rs b/packages/rs-drive-abci/src/query/system/total_credits_in_platform/mod.rs index 1bb352103f..f0d126b0d0 100644 --- a/packages/rs-drive-abci/src/query/system/total_credits_in_platform/mod.rs +++ b/packages/rs-drive-abci/src/query/system/total_credits_in_platform/mod.rs @@ -22,7 +22,7 @@ impl Platform { ) -> Result, Error> { let Some(version) = version else { return Ok(QueryValidationResult::new_with_error( - QueryError::DecodingError("could not decode epoch info request".to_string()), + QueryError::DecodingError("could not decode total credits in platform".to_string()), )); }; diff --git a/packages/rs-drive-abci/src/test/fixture/abci.rs b/packages/rs-drive-abci/src/test/fixture/abci.rs index 26a7803a6e..45abd250ca 100644 --- a/packages/rs-drive-abci/src/test/fixture/abci.rs +++ b/packages/rs-drive-abci/src/test/fixture/abci.rs @@ -3,14 +3,18 @@ use crate::config::PlatformConfig; use dpp::version::PlatformVersion; +use dpp::version::ProtocolVersion; use tenderdash_abci::proto::abci::RequestInitChain; use tenderdash_abci::proto::google::protobuf::Timestamp; use tenderdash_abci::proto::types::{ConsensusParams, VersionParams}; /// Creates static init chain request fixture -pub fn static_init_chain_request(config: &PlatformConfig) -> RequestInitChain { - let platform_version = PlatformVersion::get(config.initial_protocol_version) - .expect("expected to get platform version"); +pub fn static_init_chain_request( + config: &PlatformConfig, + protocol_version: ProtocolVersion, +) -> RequestInitChain { + let platform_version = + PlatformVersion::get(protocol_version).expect("expected to get platform version"); RequestInitChain { time: Some(Timestamp { seconds: 0, @@ -19,7 +23,7 @@ pub fn static_init_chain_request(config: &PlatformConfig) -> RequestInitChain { chain_id: "strategy_tests".to_string(), consensus_params: Some(ConsensusParams { version: Some(VersionParams { - app_version: config.initial_protocol_version as u64, + app_version: protocol_version as u64, consensus_version: platform_version.consensus.tenderdash_consensus_version as i32, }), ..Default::default() diff --git a/packages/rs-drive-abci/src/test/fixture/mod.rs b/packages/rs-drive-abci/src/test/fixture/mod.rs index c52eb0a4c2..4df7078f8c 100644 --- a/packages/rs-drive-abci/src/test/fixture/mod.rs +++ b/packages/rs-drive-abci/src/test/fixture/mod.rs @@ -1 +1,2 @@ pub mod abci; +pub mod platform_state; diff --git a/packages/rs-drive-abci/src/test/fixture/platform_state.rs b/packages/rs-drive-abci/src/test/fixture/platform_state.rs new file mode 100644 index 0000000000..7c8ae424fd --- /dev/null +++ b/packages/rs-drive-abci/src/test/fixture/platform_state.rs @@ -0,0 +1,9 @@ +//! Platform execution state fiixtures +//! + +use std::cell::LazyCell; + +/// Platform execution state v3 from testnet +pub const PLATFORM_STATE_V3_TESTNET: LazyCell<&str> = LazyCell::new(|| { + "00000100fd00000192670b9514fb78b1fc00110ab7fb078b34bbc2a6b045158657746dc5db1105bdd6cb6b28a3adcd8735e91dc2e78d8253000000b91e2a2fe9ab4c3899dc7d2d85c9e00e068603afe59058d5415a84773de28aaaab739907a87bba3ff79428d1c8ef5c2a1f8ae5e8f95dfb32a3e07a767440784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d8a7a96ca935bbc898e4a56cd3865874a44134f0cccff168f01a38d25c03aa3bbfe4234869a8f0e57fbe611139cd6d7ac0a310f08ab1583ed6e70afd63ac3649faff1682184939d0a32f5abf1fbc8eeb487c29332191033d1c156f863c09d34b0000303000000b91e2a2fe9ab4c3899dc7d2d85c9e00e068603afe59058d5415a84773d001820000000f1187cb12e35cb2a20fa7ebaad86a10a07f37a26d91068fcbde0ee462d0020000000f1187cb12e35cb2a20fa7ebaad86a10a07f37a26d91068fcbde0ee462d00fc00110aa8192005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea82005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea80130b15b76938c54f51b8386980eb3b8631b34ccd35c6884830a43ae3e52ff5a273aa5026d4adf2ebb33cf7c678b72eab8bb0d35322e32342e3132342e313632148feb00404d6f765856c95e587b2523a365bc7258fb4e1ffb05a3fb8f30002012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a22012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a201308897e2f392f0e1f2aad3ab24051db60ec4863b99d031c8c8c97b55156547d55cced5bfe08996a05ee652418ea98151870e3231322e32342e3130332e31343914c1161c96de3dae28cd7f20ff8c2aa7b94b866d76fb4e1ffb05a3fb8f300020143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f11320143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f11301308dd61f6d77efbc7a1f689fed01dbab0566c71a2acf19a0d26b19a4c3daa582ca5d21c5e137df714d513bef879f0bdb040d33352e3136342e32332e32343514b5f25f8f70cf8d05c2d2970bdf186c994431d84efb4e1ffb05a3fb8f30002020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c2020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c0130b661002db656ba258788a2f9af91710a2e91c0d138b2edddde50d651a5173b3f8e248c4c7e22beee609072fc81ac89f30c33352e38352e32312e3137391435d9eb76397d05b43b5cd8da7ccfa8408bc89ab3fb4e1ffb05a3fb8f3000202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb0130a3ad85022b69916fa555be50d6b8d77d5b91f8ca72cc91f106b7f4b9fb806478362d5976a34a5e2b9361262e32defff50d35342e3134392e33332e313637141ffbf1d32541dcb8f5555305295704a9ff9adc24fb4e1ffb05a3fb8f3000203971dab9691efac06e4ce7a5483131373e84726458924fe48b7d541791693be1203971dab9691efac06e4ce7a5483131373e84726458924fe48b7d541791693be10130b0a6419f2650de0abe6cefbe8305b31e5cac7cb80f23472036009076904bb40a7282aae4b3fb6025d437813c3619691b0d39322e36332e3137362e3230321461c274080f47a95be5372ef8c69bb60ab1d4ca82fb4e1ffb05a3fb8f30002040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d2040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d0130b309f7e2254b0d55fd6e75be528f7b05ed8623dcaf0addf51ff50b13cec0312ec15d00b6394981ef2a9c7fcea3549a9b0c35322e31302e3232392e3131143e8b10646ee9d6c28d75c280b357dd3a9ae9f962fb4e1ffb05a3fb8f3000205b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a23205b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a230130b6f7f4e44b06e8f588473c21d6aa2645b6638eeecdb5f0290889ef7cb3d94b138bd46a4d91b5b56cf9bf96777a13579d0d33352e3136352e35302e31323614f460a07a2b0dc932e1d8ff2dee2b984ac415dcebfb4e1ffb05a3fb8f3000205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef436205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef4360130a743d1bf6e3165cb7450b97a907b4b524de83538c85b2110f59bfde026cdce7104c91715e254b77b25175b9c28d8ec9c0d34342e3233392e33392e31353314972a33056d57359de8acfa4fb8b29dc1c14f76b8fb4e1ffb05a3fb8f30002061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb2061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb0130b5286eded79114127ddc14075e3cc71e179f5247c88059e574416224da0e8c2b0cd65f2d1941dc9dfeaa22873e8339880c35322e31322e3137362e3930147ada3e486409b39c94a0833c8d782f35bc24e96afb4e1ffb05a3fb8f3000206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e52863320966206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e5286332096601308261037fde2ea2c99bc904ae23c6cb827177aa9dbc70119e1cffa0716681f0e92da1639df91d91c6fd194c128a8add900e34342e3232382e3234322e31383114c374f016ea61e76aab79b8bb95a1ba0e6e3eee6ffb4e1ffb05a3fb8f3000207135069642e1a72807a383fb5a14b9af6758292fee53fe2a7f7ac6f528bf7019207135069642e1a72807a383fb5a14b9af6758292fee53fe2a7f7ac6f528bf7019013099d894f15fd6a36a44f56a48502b6da8315ce203e8b7908105eab9fcf1e8fca01ee40bbf1a67a2828541a0da9e3d21fb0d35342e3138392e3136342e333914f9956e70daffa263e8cf29fa6557b7b630a595a8fb4e1ffb05a3fb8f300020754b89dae8db20fc4cee5e3adb07b146d7efe508a66fa0a8e1094675b9daa35e20754b89dae8db20fc4cee5e3adb07b146d7efe508a66fa0a8e1094675b9daa35e0130a8a91ee2617de812f7f1cc2c4fbbf2cea408edaf225a8da74761f6ca6cbed60b2054ff1730f54298e82af67d888042470c34342e3233332e34342e39351446d938862af6d9a291e26c0048177db2892a710bfb4e1ffb05a3fb8f3000207718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be4290207718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be42900130b2631ef598d8bebfbcb40b6653250d25d07e42be82709160b1d01e4d3e59af5c3be2262d88ee86c91385ba3b35ce15b10d34342e3232372e3133372e3737140498ade3c80045c2a7520e921180ae1c39da5c57fb4e1ffb05a3fb8f30002085f15a31d3838293a9c1d72a1a0fa21e66110ce20878bd4c1024c4ae1d5be8242085f15a31d3838293a9c1d72a1a0fa21e66110ce20878bd4c1024c4ae1d5be8240130b84771f8c123270fcee41986222050294edde00dbbc2abdb2e24dfdcbed36383ea34261eecdf4684e9be3339c235a44c0d35342e3230312e33322e3133311468c506d43816d1a8389c860c1d162be44d1e777cfb4e1ffb05a3fb8f3000208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc4208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc40130961e707780b035e2bf7d82ad6a98a82b81615d31129f9be4a43b7ac0e91a7a4f408836b1a067605bc4cb8bb1699c8d190c35322e34332e38362e32333114337b7fb5d2c531825c3e0123ac3354018085b302fb4e1ffb05a3fb8f3000208eca4bcbb3a124ab283afd42dad3bdb2077b3809659788a0f1daffce5b9f001f208eca4bcbb3a124ab283afd42dad3bdb2077b3809659788a0f1daffce5b9f001f0130ae4d8adbece1973d8625d725a644a1dbeb36dcda498040abc45392caa46f515be917ea83400be5342cad96304dc321460d35342e36382e3233352e32303114c075993a8336f93a13bb7bbb7e0e89928be4aafbfb4e1ffb05a3fb8f3000209712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df54209712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df540130ab0a7879ee8ad513c0633490d3e86ab2645ff07701f24cd887b9f3bcf1c38baef517a76b2641d0fa47f0be61d368b5d20d33352e38322e3139372e31393714ed1131823bcea23ac78af8c01e4d24683d6ecf88fb4e1ffb05a3fb8f30002098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba0920962098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba09209601308bd3c1a90462ec65d5df7e3e8f93b67f57e174c1c272d7a33bf6faabc28daccd899f88e208379378be95ac500d7713570c34342e3233322e3139362e3614d6ece912cbf02627a4efc3dd37e6833cf3671551fb4e1ffb05a3fb8f3000209cb04f271ba050132c00cc5838fb69e77bc55b5689f9d2d850dc528935f8145c209cb04f271ba050132c00cc5838fb69e77bc55b5689f9d2d850dc528935f8145c01308b10630f61ec66b84180ad865634e62a22448b595d8f1876da42c87dcc63c5601f393fccfed6bfb17cbe0c0db125c86a0c33342e3231342e34382e36381462e960a3f6b650feed98a266b3ccdf6e363562cffb4e1ffb05a3fb8f300020ba8ce1dc72857b4168e33272571df7fbaf84c316dfe48217addcf6595e25421620ba8ce1dc72857b4168e33272571df7fbaf84c316dfe48217addcf6595e2542160130a668ab57cd5700686114d03df153295640e5939144d84fb386ee9811ac459cc48876013df04ad44cca5d27461492e95b0d35322e34322e3230322e3132381462e0104ce0aafc1f06bde37c73702fe84b307f05fb4e1ffb05a3fb8f300020c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba820c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba8013094ea96483a36db9fb9647a2fbaf2bf3df39a9e375ae7a8a8b81c71d4ef5e33f704e69ad50d20ca9a1164484ffd5289a00d35342e3231332e3230342e383514fdae7cdf38811659ce9481975b326a5d07236bc5fb4e1ffb05a3fb8f300020d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f8920d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f8901308ceddd73271ab74091fe496bea3786f10d49b68eeb5357300fd5e71c295b726666da80631ad29a5d7cee5ff9eba6b1e10d34342e3234302e39382e313032147034f0d3853c5351fb8e0ffd3c1daf12c51c2d89fb4e1ffb05a3fb8f300020f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba786399038120f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba78639903810130adef1c638134ebeb1fe996643698f056c4f0c90c2f122d70dbdccc83abc04f9c558d9dd95084443f3c238c0ecff2977b0d35322e31332e3235302e31383214fe2d4798df3e9b41a6823bc0b3f020478e87925dfb4e1ffb05a3fb8f300020ff261d2c1c76907a2ad8aeb6c5611796f03b5cbd88ae92452a4727e13f4f4ac920ff261d2c1c76907a2ad8aeb6c5611796f03b5cbd88ae92452a4727e13f4f4ac90130a9b37ba5ebf8695acb31339b2200e7b34881d809654003fb2845e48e24819cfaae2833da5fec3547d51869acaef931290d35342e3138372e31342e3233321467e05b1b52c7c896adf20035036fe1d30dcefc9cfb4e1ffb05a3fb8f300030a6cbd47ba3201352f0e23d2434f83e1e2029b2514e7273280f9c0a746ce81624e99290d62ddd96097068ef7999d326e4200000004689a842c049d460ee314df1bbfa36530ff86632142fe3b6eee824003400200000004689a842c049d460ee314df1bbfa36530ff86632142fe3b6eee824003400fc00110a90192005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea82005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea8013084d7ad239563f639a16a9cdb055a81e683f2a0c654f882c9a54d38c2bc10c110da7829f313e9f4b2c70651207cb273110d35322e32342e3132342e313632148feb00404d6f765856c95e587b2523a365bc7258fb4e1ffb05a3fb8f30002012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a22012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a201308942b5fe5ab5b6636bc0ebfff21dc7a21f0397cc2ea9362e9b476b10b5668aae608dbf5f1ece54a479747634d74041ea0e3231322e32342e3130332e31343914c1161c96de3dae28cd7f20ff8c2aa7b94b866d76fb4e1ffb05a3fb8f300020143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f11320143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f113013084cd7e8744a28e4036feedf3b6f3d691c8ea21e8e69f0c862215e51a15a51205799f0fa0516c7b7cf02b691dca89d2f50d33352e3136342e32332e32343514b5f25f8f70cf8d05c2d2970bdf186c994431d84efb4e1ffb05a3fb8f30002020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c2020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c01308de99ca88d7256389dd5c27ac00b98b95bbead6c7b3008fd8dc6bdaec9f4fe1110f7ffe0fc7ad40aefa37919df04968d0c33352e38352e32312e3137391435d9eb76397d05b43b5cd8da7ccfa8408bc89ab3fb4e1ffb05a3fb8f3000202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb0130aaf815d4d59789b72527426251177acf276c39c3113810b9e6614fc866ae21a3f65cbde04edccd8bf791940b73fa84ea0d35342e3134392e33332e313637141ffbf1d32541dcb8f5555305295704a9ff9adc24fb4e1ffb05a3fb8f30002040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d2040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d0130a4cad187d6efd489b5bac71f56ec6b91e8ed6965bbdd4bebe898678716ddc8a6b7d4e6a0a6fa17bc91a4c1c16d1e64930c35322e31302e3232392e3131143e8b10646ee9d6c28d75c280b357dd3a9ae9f962fb4e1ffb05a3fb8f3000205b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a23205b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a230130b222d9014e083f3b542bae5c3daaa94ab024b602e39e045a279d101c128214d1a7d9742e8afa7a6140de6ad61eaf421a0d33352e3136352e35302e31323614f460a07a2b0dc932e1d8ff2dee2b984ac415dcebfb4e1ffb05a3fb8f30002061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb2061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb0130aa2538b75155fe0304fde0c908be3deacc9abae62bcc0e0336f9cc0c24583d55ff3959963affeb7afcf2a6a0bd6d61410c35322e31322e3137362e3930147ada3e486409b39c94a0833c8d782f35bc24e96afb4e1ffb05a3fb8f3000206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e52863320966206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e52863320966013099f0aa551bd2df9baf3eb6adf0261df8a749a9413f62dd8473fd6ab03b3a6917157a1b5d3b01307d4b32d65fd495be8f0e34342e3232382e3234322e31383114c374f016ea61e76aab79b8bb95a1ba0e6e3eee6ffb4e1ffb05a3fb8f3000207718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be4290207718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be429001308a81e53c43f6ecb09730e937d44984c697938ad776c58424eb626580507642977097ce8daee7ca61e0e8e052fcc44a820d34342e3232372e3133372e3737140498ade3c80045c2a7520e921180ae1c39da5c57fb4e1ffb05a3fb8f30002087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d6789182087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d6789180130b361d2179cadf86c3d4788078a5380afe844c3b354a4336a35ef6fb774a565f3c1319e597841f87182d6dbce0527ec180e33352e3136372e3134352e313439149b9cdbfe3568cc0b37f136b00a634c75653f05e3fb4e1ffb05a3fb8f3000208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f234208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f2340130aa71b13016a1a1fee60d1db3d6987aafcbb813e7cb4ade9766f0b9ea92a89eaefbf540af24d4b7fd021565041edd1ade0d35322e31332e3133322e313436145bdbf34a0dad860c6ec71523ae39373325225cc1fb4e1ffb05a3fb8f3000208b8d1193afd22e538ce0c9fb50fee155d0f6176ca68e65da684c5dce2d1e0815208b8d1193afd22e538ce0c9fb50fee155d0f6176ca68e65da684c5dce2d1e08150130b886ecda081643bc5e24dfe7d0403bd2639afebf056cbde277b5558e2d497837f26c0acc02d3742e298c5e8ad3f83a650c35322e33342e3134342e353014a0a0e17bfe82a484fefe348b7569a6d77d29d2c2fb4e1ffb05a3fb8f3000208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc4208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc4013091b43a2470e00f9aa20ca5f759bfc2181a9822830f057c299ed9f5324f5266c7f3fbc934a4a20baa9a01563a12632fc60c35322e34332e38362e32333114337b7fb5d2c531825c3e0123ac3354018085b302fb4e1ffb05a3fb8f3000208eca4bcbb3a124ab283afd42dad3bdb2077b3809659788a0f1daffce5b9f001f208eca4bcbb3a124ab283afd42dad3bdb2077b3809659788a0f1daffce5b9f001f0130b35c64527fbc2578fd2723311fe76a4ef602f9314596f9133a2626aa2bd818a828d067946799b3150e25324e0e77e4790d35342e36382e3233352e32303114c075993a8336f93a13bb7bbb7e0e89928be4aafbfb4e1ffb05a3fb8f30002091bbce94c34ebde0d099c0a2cb7635c0c31425ebabcec644f4f1a0854bfa605d2091bbce94c34ebde0d099c0a2cb7635c0c31425ebabcec644f4f1a0854bfa605d01308b8a33b1554491346591a0147b376489af1adac664b6a0b2b4c542627553429c6dfde43048681ae55cd12ea84806fa880c35322e34302e3231392e34311402aa69f8ef6666e7cad6d9323755a0ef3c1b6bd9fb4e1ffb05a3fb8f3000209712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df54209712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df54013099cc490e6796af6a93c03be74e46603ee8d597a40c53fee0ef58cde0dd5c70526c6da8b633d2f231d4a1b6ab12329e330d33352e38322e3139372e31393714ed1131823bcea23ac78af8c01e4d24683d6ecf88fb4e1ffb05a3fb8f30002098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba0920962098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba092096013097309058064a4efd3dac7d1f83e0c9acaf820cc26be3844e38260203eb9de1ab343b85663df57db01030231a58fe51300c34342e3233322e3139362e3614d6ece912cbf02627a4efc3dd37e6833cf3671551fb4e1ffb05a3fb8f3000209cb04f271ba050132c00cc5838fb69e77bc55b5689f9d2d850dc528935f8145c209cb04f271ba050132c00cc5838fb69e77bc55b5689f9d2d850dc528935f8145c013091408bdb75e94dcd5f529e04d40e1338cdd59105e20f644f30035345bd8a1abb4f26a30ed33a5f718fc0651d5e3ea17e0c33342e3231342e34382e36381462e960a3f6b650feed98a266b3ccdf6e363562cffb4e1ffb05a3fb8f300020b3b5748571b60fe9ad112715d6a51725d6e5a52a9c3af5fd36a1724cf50d862f20b3b5748571b60fe9ad112715d6a51725d6e5a52a9c3af5fd36a1724cf50d862f0130804761ed1300c056087c87255d97a6163b5583f9db147b4c13a302783e03ccb91b9c41bd85b5749e6ac1cd66618ee2c80b35322e34332e31332e39321441b308f737ca9e39f67b553158903198a88c516efb4e1ffb05a3fb8f300020ba8ce1dc72857b4168e33272571df7fbaf84c316dfe48217addcf6595e25421620ba8ce1dc72857b4168e33272571df7fbaf84c316dfe48217addcf6595e2542160130b18bb95e55a3159681810e3bba2d820554605bbe094863d2175a58a729ccb5d5c4005668ad5e1568a5a4e6fc9e44868a0d35322e34322e3230322e3132381462e0104ce0aafc1f06bde37c73702fe84b307f05fb4e1ffb05a3fb8f300020c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba820c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba80130ac27a016518e3768ba8fdcb01af7a6c3668e2594d90f2d199491cd82b4bd1b8f46f869aa9ca3b82c592360222cded8690d35342e3231332e3230342e383514fdae7cdf38811659ce9481975b326a5d07236bc5fb4e1ffb05a3fb8f300020d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f8920d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f890130aaab1fef4dd9ec25e263524b62b04151d74a51f94bd0bd1d96a69ec372827c0c4e5a3f157e6bcbc5bc9c8f52119e670b0d34342e3234302e39382e313032147034f0d3853c5351fb8e0ffd3c1daf12c51c2d89fb4e1ffb05a3fb8f300020f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba786399038120f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba78639903810130a3eb4ba1d46723c1321ae975611049a27cffa5de8a9d86348c8f8e00432f515b71e6846a26c466d559db3d0fb24bc70a0d35322e31332e3235302e31383214fe2d4798df3e9b41a6823bc0b3f020478e87925dfb4e1ffb05a3fb8f300020ff261d2c1c76907a2ad8aeb6c5611796f03b5cbd88ae92452a4727e13f4f4ac920ff261d2c1c76907a2ad8aeb6c5611796f03b5cbd88ae92452a4727e13f4f4ac9013093fecca26bf5ad7a125463e41ec77a3e3fc962672fd71ae5982bfb3c0b0dda2276c9a8df4b42795034bf6642c9043b140d35342e3138372e31342e3233321467e05b1b52c7c896adf20035036fe1d30dcefc9cfb4e1ffb05a3fb8f300030b3c85502f9c7789d7ce97199d4b411ee93a771c0209bc6a6b61e3b637eb8f2de1778f8a9c2bbd18ef27a07ac2b7f2121200000010832789d4cdff3cc8a63fad668ccac708af7433c42e189ada6c6e5e66e00200000010832789d4cdff3cc8a63fad668ccac708af7433c42e189ada6c6e5e66e00fc00110a78192005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea82005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea80130a9f8fc1cbb8413542a88a12c2bd8ed37d164176e3ec69ef1da36b17732e9edfe26d5a4637b714871c0969e85c5ed49340d35322e32342e3132342e313632148feb00404d6f765856c95e587b2523a365bc7258fb4e1ffb05a3fb8f300020143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f11320143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f1130130b77c254aa8967f93938cccda412ff4cc2ae33c1632fdf22d6d6e01e350bee7cda4293fcf7bdd08421a89d89d31f3d3700d33352e3136342e32332e32343514b5f25f8f70cf8d05c2d2970bdf186c994431d84efb4e1ffb05a3fb8f30002020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c2020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c0130a95cfa0fb3e2b7405577f766f10f8a527b4f0ea8da4fd9e308eaef910c82b6bfe395ebac71d7344db812de815e0b7a6e0c33352e38352e32312e3137391435d9eb76397d05b43b5cd8da7ccfa8408bc89ab3fb4e1ffb05a3fb8f3000203971dab9691efac06e4ce7a5483131373e84726458924fe48b7d541791693be1203971dab9691efac06e4ce7a5483131373e84726458924fe48b7d541791693be10130972fa1195e580291865db0045df4ca36e3775c91bc14107259ecde0fbbabaa90c965949a00cd11e9a7c288d9b325edb00d39322e36332e3137362e3230321461c274080f47a95be5372ef8c69bb60ab1d4ca82fb4e1ffb05a3fb8f30002039741ad83dd791e1e738f19edae82d6c0322972e6a455981424da3769b3dbd4a2039741ad83dd791e1e738f19edae82d6c0322972e6a455981424da3769b3dbd4a01308ce9094c3230172b326a5ee57a2f76413371a66bda5c34c6ef0f0f62cef8fab9fa44b9423c182ca2e8779d17b77bb14a0e33352e3136332e3134342e32333014ec7bf3b9bc72eda38c80bb7cf16e294e763e56b4fb4e1ffb05a3fb8f30002040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d2040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d0130b5b6cda330445e2e8ae0289b476aab0b925f0f6f62975c2af939512ab2ecb00a669a099c9d1a9f3b1c322eed82a0a6430c35322e31302e3232392e3131143e8b10646ee9d6c28d75c280b357dd3a9ae9f962fb4e1ffb05a3fb8f3000205b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a23205b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a230130a99d91eda26d9a436188ecfce2df4f7afc9954764a421234713f1083fd445abd9733e0b8bbf0e6fe43db02cfa07fb11f0d33352e3136352e35302e31323614f460a07a2b0dc932e1d8ff2dee2b984ac415dcebfb4e1ffb05a3fb8f3000205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef436205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef43601308c2bf1a5c7782b57c78edc0c9a780bb03fd12b563b43cdf7f0b1e1e96081f8d11d3e131988f37ebe2799eaaedbd065c40d34342e3233392e33392e31353314972a33056d57359de8acfa4fb8b29dc1c14f76b8fb4e1ffb05a3fb8f3000206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e52863320966206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e528633209660130a2a5775aec8818a7914b1a610d095343e5e54e3834a51fe0c2c8b0d85e5e347bbc205a2cc19d665da624996f5c797a520e34342e3232382e3234322e31383114c374f016ea61e76aab79b8bb95a1ba0e6e3eee6ffb4e1ffb05a3fb8f3000207135069642e1a72807a383fb5a14b9af6758292fee53fe2a7f7ac6f528bf7019207135069642e1a72807a383fb5a14b9af6758292fee53fe2a7f7ac6f528bf70190130b2613f4f71b8cb2d6d5d40312bb676bf0272fcb4d141e2aa23dfe8698655a4c1c93150b244488a13f5cf60dc3301c1830d35342e3138392e3136342e333914f9956e70daffa263e8cf29fa6557b7b630a595a8fb4e1ffb05a3fb8f300020754b89dae8db20fc4cee5e3adb07b146d7efe508a66fa0a8e1094675b9daa35e20754b89dae8db20fc4cee5e3adb07b146d7efe508a66fa0a8e1094675b9daa35e0130ae815e003eeb65606f18a624ca248f83c1a70c168b15a75d935127fa479ba75a30d734d40b008c4f26e6b384957837fc0c34342e3233332e34342e39351446d938862af6d9a291e26c0048177db2892a710bfb4e1ffb05a3fb8f3000207718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be4290207718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be42900130b0b9f5db3633b48d5359d5b8d9e99f2eaf5e6603fae01746602f538e8d9e923ff1f47a5f84ff0be24d24d6e80d2710df0d34342e3232372e3133372e3737140498ade3c80045c2a7520e921180ae1c39da5c57fb4e1ffb05a3fb8f30002087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d6789182087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d6789180130a36373377b1befa6f35aec8f2c56b95433324e2526748116338d7cda1274090cca1c69959b02e3f9c97a1787798e05ac0e33352e3136372e3134352e313439149b9cdbfe3568cc0b37f136b00a634c75653f05e3fb4e1ffb05a3fb8f3000208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f234208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f2340130ab3ac53a601829b7d999c55095069f25b6df87616d2276386b3eb28c68a861ce46352a008ce967f2a9b68c06a41cab1a0d35322e31332e3133322e313436145bdbf34a0dad860c6ec71523ae39373325225cc1fb4e1ffb05a3fb8f3000208b8d1193afd22e538ce0c9fb50fee155d0f6176ca68e65da684c5dce2d1e0815208b8d1193afd22e538ce0c9fb50fee155d0f6176ca68e65da684c5dce2d1e08150130a42e3e2fdf2fe5c7f368e695f0649831a6817d8670f895c9b1475836a284ae985703ef520b369adff6a4fc00edc4cfff0c35322e33342e3134342e353014a0a0e17bfe82a484fefe348b7569a6d77d29d2c2fb4e1ffb05a3fb8f3000208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc4208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc40130a1172e43ca64a94af9ebc84191b9a8d071c4ef72f2d20a1d4982753e6a875821784dfd5b81f9670fd3c88ba79bfd74800c35322e34332e38362e32333114337b7fb5d2c531825c3e0123ac3354018085b302fb4e1ffb05a3fb8f3000208e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c0208e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c00130b9f7bdfe0077e3a924a4d881683a3a51aa4204329451ce160c83c78a908eae5614e965220e26daff6894bcad781c06250c35322e38392e3135342e3438146d57707c196e06487d326094c964f258f5b77c35fb4e1ffb05a3fb8f3000209712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df54209712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df5401309362f6b7585fe368cd6e82e0ac831ebfb04d65663a3f997db0c55b6397e73565f691f4968ba9e60418b94f6e1b8466430d33352e38322e3139372e31393714ed1131823bcea23ac78af8c01e4d24683d6ecf88fb4e1ffb05a3fb8f30002098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba0920962098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba0920960130a8f426b9e58b4448cb7fcc01f05196567b7cca3ae0b601dbe096853916cab1c4c3e6e77fb59d0e944d5546fb3e74099e0c34342e3233322e3139362e3614d6ece912cbf02627a4efc3dd37e6833cf3671551fb4e1ffb05a3fb8f3000209cb04f271ba050132c00cc5838fb69e77bc55b5689f9d2d850dc528935f8145c209cb04f271ba050132c00cc5838fb69e77bc55b5689f9d2d850dc528935f8145c013088e2df5210ce24801f4fd9fed061152862ac4bf8209ce7a9635581d9e204ad2aca8dac837a392f2e692fffd2bd18d8890c33342e3231342e34382e36381462e960a3f6b650feed98a266b3ccdf6e363562cffb4e1ffb05a3fb8f300020b3b5748571b60fe9ad112715d6a51725d6e5a52a9c3af5fd36a1724cf50d862f20b3b5748571b60fe9ad112715d6a51725d6e5a52a9c3af5fd36a1724cf50d862f0130a3079ebff53a2eaa226c29515eb1f2f83c32a9f8730c1cfd22af38823153046ec09afdd6439b21de4c0ec7943e3ff5640b35322e34332e31332e39321441b308f737ca9e39f67b553158903198a88c516efb4e1ffb05a3fb8f300020bbfd0ac1977011267a7032641ef5487fe15a4de798faa485b156fb3b7eb0acb820bbfd0ac1977011267a7032641ef5487fe15a4de798faa485b156fb3b7eb0acb80130b6083baad99daa8ef067cbaa396436591c52f338cb89ecdf76ab9804c4b02ee9934df13205c483167edaaf446609e6420c33352e38322e34392e31393614dbbebbc52a5bae21b818e0487311041c91b2683bfb4e1ffb05a3fb8f300020c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba820c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba80130a87180e5349d3e6f9472bf19021fb38c8363b36d53feae8f57754e68676b2ba1ceb7680879981cb63fbf51c8f96323790d35342e3231332e3230342e383514fdae7cdf38811659ce9481975b326a5d07236bc5fb4e1ffb05a3fb8f300020d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f8920d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f890130a5b8be704d75fba99633db0e207603eacf3fc51a77b15d3f73ce6b75de19dcce4b5a3ca86b247b1414cb13bfd21d67c80d34342e3234302e39382e313032147034f0d3853c5351fb8e0ffd3c1daf12c51c2d89fb4e1ffb05a3fb8f300020f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba786399038120f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba786399038101308ed36f99ba583e180b66367374229462d8f7826abbff8c3422107d5c17a2c624bd3a154c0eae0e44f3f56d06b4da4d0e0d35322e31332e3235302e31383214fe2d4798df3e9b41a6823bc0b3f020478e87925dfb4e1ffb05a3fb8f300030b10b6159372531cd813094527b17eef8a077d4300503c6fc147e07abb40ed05a32fcfdd166e91d1c54a388d0d0f5df4f2000000072da33f586cdd86a566cb30268f411dad855dc3fd18c5669410c7cdaea002000000072da33f586cdd86a566cb30268f411dad855dc3fd18c5669410c7cdaea00fc00110a60192012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a22012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a2000e3231322e32342e3130332e31343914c1161c96de3dae28cd7f20ff8c2aa7b94b866d76fb4e1ffb05a3fb8f300020143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f11320143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f113000d33352e3136342e32332e32343514b5f25f8f70cf8d05c2d2970bdf186c994431d84efb4e1ffb05a3fb8f30002020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c2020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c000c33352e38352e32312e3137391435d9eb76397d05b43b5cd8da7ccfa8408bc89ab3fb4e1ffb05a3fb8f3000202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb000d35342e3134392e33332e313637141ffbf1d32541dcb8f5555305295704a9ff9adc24fb4e1ffb05a3fb8f3000203971dab9691efac06e4ce7a5483131373e84726458924fe48b7d541791693be1203971dab9691efac06e4ce7a5483131373e84726458924fe48b7d541791693be1000d39322e36332e3137362e3230321461c274080f47a95be5372ef8c69bb60ab1d4ca82fb4e1ffb05a3fb8f30002039741ad83dd791e1e738f19edae82d6c0322972e6a455981424da3769b3dbd4a2039741ad83dd791e1e738f19edae82d6c0322972e6a455981424da3769b3dbd4a000e33352e3136332e3134342e32333014ec7bf3b9bc72eda38c80bb7cf16e294e763e56b4fb4e1ffb05a3fb8f3000205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef436205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef436000d34342e3233392e33392e31353314972a33056d57359de8acfa4fb8b29dc1c14f76b8fb4e1ffb05a3fb8f30002061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb2061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb000c35322e31322e3137362e3930147ada3e486409b39c94a0833c8d782f35bc24e96afb4e1ffb05a3fb8f3000206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e52863320966206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e52863320966000e34342e3232382e3234322e31383114c374f016ea61e76aab79b8bb95a1ba0e6e3eee6ffb4e1ffb05a3fb8f3000207135069642e1a72807a383fb5a14b9af6758292fee53fe2a7f7ac6f528bf7019207135069642e1a72807a383fb5a14b9af6758292fee53fe2a7f7ac6f528bf7019000d35342e3138392e3136342e333914f9956e70daffa263e8cf29fa6557b7b630a595a8fb4e1ffb05a3fb8f300020754b89dae8db20fc4cee5e3adb07b146d7efe508a66fa0a8e1094675b9daa35e20754b89dae8db20fc4cee5e3adb07b146d7efe508a66fa0a8e1094675b9daa35e000c34342e3233332e34342e39351446d938862af6d9a291e26c0048177db2892a710bfb4e1ffb05a3fb8f30002085f15a31d3838293a9c1d72a1a0fa21e66110ce20878bd4c1024c4ae1d5be8242085f15a31d3838293a9c1d72a1a0fa21e66110ce20878bd4c1024c4ae1d5be824000d35342e3230312e33322e3133311468c506d43816d1a8389c860c1d162be44d1e777cfb4e1ffb05a3fb8f30002087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d6789182087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d678918000e33352e3136372e3134352e313439149b9cdbfe3568cc0b37f136b00a634c75653f05e3fb4e1ffb05a3fb8f30002088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f2088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f000b35322e33332e32382e343714711fd9548ae19b2e91c7a9b4067000467ccdd2b5fb4e1ffb05a3fb8f3000208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f234208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f234000d35322e31332e3133322e313436145bdbf34a0dad860c6ec71523ae39373325225cc1fb4e1ffb05a3fb8f3000208b8d1193afd22e538ce0c9fb50fee155d0f6176ca68e65da684c5dce2d1e0815208b8d1193afd22e538ce0c9fb50fee155d0f6176ca68e65da684c5dce2d1e0815000c35322e33342e3134342e353014a0a0e17bfe82a484fefe348b7569a6d77d29d2c2fb4e1ffb05a3fb8f3000208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc4208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc4000c35322e34332e38362e32333114337b7fb5d2c531825c3e0123ac3354018085b302fb4e1ffb05a3fb8f3000208e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c0208e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c0000c35322e38392e3135342e3438146d57707c196e06487d326094c964f258f5b77c35fb4e1ffb05a3fb8f3000209712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df54209712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df54000d33352e38322e3139372e31393714ed1131823bcea23ac78af8c01e4d24683d6ecf88fb4e1ffb05a3fb8f30002098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba0920962098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba092096000c34342e3233322e3139362e3614d6ece912cbf02627a4efc3dd37e6833cf3671551fb4e1ffb05a3fb8f300020b3b5748571b60fe9ad112715d6a51725d6e5a52a9c3af5fd36a1724cf50d862f20b3b5748571b60fe9ad112715d6a51725d6e5a52a9c3af5fd36a1724cf50d862f000b35322e34332e31332e39321441b308f737ca9e39f67b553158903198a88c516efb4e1ffb05a3fb8f300020bbfd0ac1977011267a7032641ef5487fe15a4de798faa485b156fb3b7eb0acb820bbfd0ac1977011267a7032641ef5487fe15a4de798faa485b156fb3b7eb0acb8000c33352e38322e34392e31393614dbbebbc52a5bae21b818e0487311041c91b2683bfb4e1ffb05a3fb8f300020c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba820c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba8000d35342e3231332e3230342e383514fdae7cdf38811659ce9481975b326a5d07236bc5fb4e1ffb05a3fb8f300020f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba786399038120f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba7863990381000d35322e31332e3235302e31383214fe2d4798df3e9b41a6823bc0b3f020478e87925dfb4e1ffb05a3fb8f300020ff261d2c1c76907a2ad8aeb6c5611796f03b5cbd88ae92452a4727e13f4f4ac920ff261d2c1c76907a2ad8aeb6c5611796f03b5cbd88ae92452a4727e13f4f4ac9000d35342e3138372e31342e3233321467e05b1b52c7c896adf20035036fe1d30dcefc9cfb4e1ffb05a3fb8f3000308363bb90232bac7a56c8a751b0e92029974d09eb0d894ddfa56e2cead1d7204e820692844e3ddbe248f477633e0c903b20000000e5d8948d2c695de557f1327a8f323fe00ea463ab53d415589456cae5430020000000e5d8948d2c695de557f1327a8f323fe00ea463ab53d415589456cae54300fc00110a48192005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea82005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea80130969e860529b2ff3468eb673067a839e89cb70cd1d945192b91965bd36d5d3fa4fe504619892c15f98225e79a3a7d47090d35322e32342e3132342e313632148feb00404d6f765856c95e587b2523a365bc7258fb4e1ffb05a3fb8f300020143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f11320143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f113013084cd37a5e9a78f8b1dd5642869b38051aeb448e0fd7f1d3848e33d649fc4631d4d49ff0931a050d59790bd0531f397200d33352e3136342e32332e32343514b5f25f8f70cf8d05c2d2970bdf186c994431d84efb4e1ffb05a3fb8f3000202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb01308deb2b0dff4093f71fbafc7bae4b29b17ea30485ece48b32470952f9126356b873514122831c2951e7a3abb6f9a81bbe0d35342e3134392e33332e313637141ffbf1d32541dcb8f5555305295704a9ff9adc24fb4e1ffb05a3fb8f3000203971dab9691efac06e4ce7a5483131373e84726458924fe48b7d541791693be1203971dab9691efac06e4ce7a5483131373e84726458924fe48b7d541791693be10130a5f030ce39676a17427193f0ca4cc9ee43a4f902e107773cfa1e540b26cad7f267e8c3079b8cdf4c0add74a2e84dcea30d39322e36332e3137362e3230321461c274080f47a95be5372ef8c69bb60ab1d4ca82fb4e1ffb05a3fb8f30002039741ad83dd791e1e738f19edae82d6c0322972e6a455981424da3769b3dbd4a2039741ad83dd791e1e738f19edae82d6c0322972e6a455981424da3769b3dbd4a01308ebbe8af7fc4642314003a46929b4099c64842f64f9e69e6da327632aba34d40b35aea294ee5cb61d3d9acdaae8cd38b0e33352e3136332e3134342e32333014ec7bf3b9bc72eda38c80bb7cf16e294e763e56b4fb4e1ffb05a3fb8f3000205b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a23205b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a230130a63effa991db7f60139f66d7ce6d9b009b50415bea8a473e308d23b984e95c16e65dd19080c9dd203f0ff7a73a5946540d33352e3136352e35302e31323614f460a07a2b0dc932e1d8ff2dee2b984ac415dcebfb4e1ffb05a3fb8f3000207135069642e1a72807a383fb5a14b9af6758292fee53fe2a7f7ac6f528bf7019207135069642e1a72807a383fb5a14b9af6758292fee53fe2a7f7ac6f528bf701901308227fa4a5a3770831ee93c7f52edb284567beaf78c37ae47c6731589cafe50efd98478cb2b078310199b36b08a8c3e670d35342e3138392e3136342e333914f9956e70daffa263e8cf29fa6557b7b630a595a8fb4e1ffb05a3fb8f300020754b89dae8db20fc4cee5e3adb07b146d7efe508a66fa0a8e1094675b9daa35e20754b89dae8db20fc4cee5e3adb07b146d7efe508a66fa0a8e1094675b9daa35e0130aefc5fd6504acb6801a3531e8ca8c42a57c9891f61a505114dec9f0607aaa15ac5f1ab94f5b46c3bff9b12a31ee82b7b0c34342e3233332e34342e39351446d938862af6d9a291e26c0048177db2892a710bfb4e1ffb05a3fb8f3000207718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be4290207718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be4290013085d05de36a1b5ed656048a64569cf42a5807ce65c29a91c2b3a00f8bf9bdabe99715d3d62b8aab75b7173fcb36862abd0d34342e3232372e3133372e3737140498ade3c80045c2a7520e921180ae1c39da5c57fb4e1ffb05a3fb8f30002085f15a31d3838293a9c1d72a1a0fa21e66110ce20878bd4c1024c4ae1d5be8242085f15a31d3838293a9c1d72a1a0fa21e66110ce20878bd4c1024c4ae1d5be8240130a7c71dc1a14889412cd99e7c2714560d81fc63ec74ce9e6aff290503d28e4283fa41c09f7f33a0fa039cfdfeac4e71d70d35342e3230312e33322e3133311468c506d43816d1a8389c860c1d162be44d1e777cfb4e1ffb05a3fb8f30002087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d6789182087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d6789180130a858472dffbc0aabf6e25b30037d38a71a563359fce61c7f8636e15c16ed7373fef2ce7e476761c6c8f5c8d945fd976b0e33352e3136372e3134352e313439149b9cdbfe3568cc0b37f136b00a634c75653f05e3fb4e1ffb05a3fb8f30002088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f2088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f01308b0b6b19ffd7b384cc664de9d04e0bc65d75374df2ae888489812b122294904372b8df973d58795578e2f960692b46650b35322e33332e32382e343714711fd9548ae19b2e91c7a9b4067000467ccdd2b5fb4e1ffb05a3fb8f3000208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f234208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f2340130844d1bba28048dd41472b1c2b663cc37dbbe7633ce65d6d514a99b13234760ed0df5644596438d4ac52570742bcb564d0d35322e31332e3133322e313436145bdbf34a0dad860c6ec71523ae39373325225cc1fb4e1ffb05a3fb8f3000208b8d1193afd22e538ce0c9fb50fee155d0f6176ca68e65da684c5dce2d1e0815208b8d1193afd22e538ce0c9fb50fee155d0f6176ca68e65da684c5dce2d1e08150130a04e60f14500bec7d0a9dd2800de360694d7557767791090c96a271e854f74ec3cb9b6f77bf73a8ac6a8385b14f684850c35322e33342e3134342e353014a0a0e17bfe82a484fefe348b7569a6d77d29d2c2fb4e1ffb05a3fb8f3000208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc4208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc40130b122c5d8c54ed1f6697988003e6cf37ab70b25bd700e3c5217d85f56af1454b9e03a3ebf8882af455650e1ec1cf6e02f0c35322e34332e38362e32333114337b7fb5d2c531825c3e0123ac3354018085b302fb4e1ffb05a3fb8f3000208e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c0208e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c00130b5a22609f0513b65e2157a13109628f1b5a58802347518e7b16edc63d7f555e9218c437b67cef2f5c2e0852fa39f2ead0c35322e38392e3135342e3438146d57707c196e06487d326094c964f258f5b77c35fb4e1ffb05a3fb8f3000208eca4bcbb3a124ab283afd42dad3bdb2077b3809659788a0f1daffce5b9f001f208eca4bcbb3a124ab283afd42dad3bdb2077b3809659788a0f1daffce5b9f001f0130b52c68fe953aa91acadea41238e533cf63e0fe775d9bfad8cf300d746517e9141e1e09ed9470f50f599fc3726108a3a80d35342e36382e3233352e32303114c075993a8336f93a13bb7bbb7e0e89928be4aafbfb4e1ffb05a3fb8f30002091bbce94c34ebde0d099c0a2cb7635c0c31425ebabcec644f4f1a0854bfa605d2091bbce94c34ebde0d099c0a2cb7635c0c31425ebabcec644f4f1a0854bfa605d013090d6d5f5e92a3cf42953447fc2993da64507785ab28e8d800f24a203759ec184ecb4581bf4bc797265d159db56ad21130c35322e34302e3231392e34311402aa69f8ef6666e7cad6d9323755a0ef3c1b6bd9fb4e1ffb05a3fb8f30002098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba0920962098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba09209601308ce455a85113cbb3f226996c42cffe8ec3c18879e7f3351844b36bd6f455d092f26e1593c67847077b794e9b9338df500c34342e3233322e3139362e3614d6ece912cbf02627a4efc3dd37e6833cf3671551fb4e1ffb05a3fb8f3000209cb04f271ba050132c00cc5838fb69e77bc55b5689f9d2d850dc528935f8145c209cb04f271ba050132c00cc5838fb69e77bc55b5689f9d2d850dc528935f8145c01308bde4bc57ed1376b3c1ea5cbfa427aa4e7f5458d3bb7bbcdd3edf5ff1316d636082ecf6adf8d91a6b1f294743e09e0e40c33342e3231342e34382e36381462e960a3f6b650feed98a266b3ccdf6e363562cffb4e1ffb05a3fb8f300020ba8ce1dc72857b4168e33272571df7fbaf84c316dfe48217addcf6595e25421620ba8ce1dc72857b4168e33272571df7fbaf84c316dfe48217addcf6595e2542160130b5c487a28336e7e237dc06a260855ccadac81c0befca82d851f59a62dd037dbf4245a9c8d3851993c39b831a4ae41e800d35322e34322e3230322e3132381462e0104ce0aafc1f06bde37c73702fe84b307f05fb4e1ffb05a3fb8f300020bbfd0ac1977011267a7032641ef5487fe15a4de798faa485b156fb3b7eb0acb820bbfd0ac1977011267a7032641ef5487fe15a4de798faa485b156fb3b7eb0acb80130b1538d4316211a05c7e88931ab8c9ac68bf59f3a157be38c7c59db2e0edd27ab4acf632546aaaf74da4c3c52da02c3a90c33352e38322e34392e31393614dbbebbc52a5bae21b818e0487311041c91b2683bfb4e1ffb05a3fb8f300020c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba820c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba80130a042172d66535219d6616449610f3257ea2a1661ab700ad8e242f56e708fdd4328005f7a256e90c48b58660d73c895e20d35342e3231332e3230342e383514fdae7cdf38811659ce9481975b326a5d07236bc5fb4e1ffb05a3fb8f300020f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba786399038120f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba78639903810130b1897a9037794f448cb3d65fcfe458a68af52b1193075b21f5c54ceb480b50aacafc12c705ecbeab07655a5db52344920d35322e31332e3235302e31383214fe2d4798df3e9b41a6823bc0b3f020478e87925dfb4e1ffb05a3fb8f300020ff261d2c1c76907a2ad8aeb6c5611796f03b5cbd88ae92452a4727e13f4f4ac920ff261d2c1c76907a2ad8aeb6c5611796f03b5cbd88ae92452a4727e13f4f4ac90130ac6b9425d33076bd863a8331058733b29ec6da69d70936e7af23576e747971d7e1f54ecbcbe92e70cc9a4ea725d9bffa0d35342e3138372e31342e3233321467e05b1b52c7c896adf20035036fe1d30dcefc9cfb4e1ffb05a3fb8f300030b9b745e239b0131f2ae8386bf2512c0548e499cbcb27d722b29982c464f3f4854dffd934fc633ca893a8b20b76b4b5cd200000000b8cd4ead1ee12d25126921d918020cd77745d9cce5b59f7287a2a296e00200000000b8cd4ead1ee12d25126921d918020cd77745d9cce5b59f7287a2a296e00fc00110a301920143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f11320143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f1130130804fb84c41e4ef70fa136be9e1b4a1de7509d51d4f4f48ad0be8b6689cfb888b3376611201c88f8d2ff4b8bbc8859ab10d33352e3136342e32332e32343514b5f25f8f70cf8d05c2d2970bdf186c994431d84efb4e1ffb05a3fb8f30002020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c2020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c0130966937f030398b1e57153a449a48f5a8cc4b17782b4553075050498ed6acae479e1b8f053ba7fea2dcdb8511b01cc8330c33352e38352e32312e3137391435d9eb76397d05b43b5cd8da7ccfa8408bc89ab3fb4e1ffb05a3fb8f3000202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb0130a0e490268a9ac6f614abda6d2c9773f78027df23205e51319d26e4a59e6226dbd2d44dadf21a7fc2af9bfa4491436e0e0d35342e3134392e33332e313637141ffbf1d32541dcb8f5555305295704a9ff9adc24fb4e1ffb05a3fb8f30002039741ad83dd791e1e738f19edae82d6c0322972e6a455981424da3769b3dbd4a2039741ad83dd791e1e738f19edae82d6c0322972e6a455981424da3769b3dbd4a013088e19fb0f79180331d93d2e1a9bd84a2b35505cc72aefef50d427196df3025478cf19f15478dc4f8e36379a2c762946d0e33352e3136332e3134342e32333014ec7bf3b9bc72eda38c80bb7cf16e294e763e56b4fb4e1ffb05a3fb8f3000205b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a23205b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a230130995b7089c977df3b5855d481b20dddfc3a203a0b28c0d899929948e3c634138d0d6e4166b95a62bf2aeb7bfb77b33b430d33352e3136352e35302e31323614f460a07a2b0dc932e1d8ff2dee2b984ac415dcebfb4e1ffb05a3fb8f3000205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef436205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef4360130a8cddde49c1a90c2977def8b0cb06bf1f1545163c01accb8d5b489c6a57b86da38fe13ad211315efb16065d049edb6d90d34342e3233392e33392e31353314972a33056d57359de8acfa4fb8b29dc1c14f76b8fb4e1ffb05a3fb8f30002061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb2061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb0130a979e9907653676d99ad236d9d7ad7f1caa7b8c145a631e86e9a3c7f217bf1af6c96f591860661775bd0703bad1be8c50c35322e31322e3137362e3930147ada3e486409b39c94a0833c8d782f35bc24e96afb4e1ffb05a3fb8f3000206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e52863320966206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e528633209660130b2af25880010cc44b694bfd03af48b1d67d1c8f7799aba3803537d66bad445b5a9ade42f1a169d82e29ec29d5b509e670e34342e3232382e3234322e31383114c374f016ea61e76aab79b8bb95a1ba0e6e3eee6ffb4e1ffb05a3fb8f3000207135069642e1a72807a383fb5a14b9af6758292fee53fe2a7f7ac6f528bf7019207135069642e1a72807a383fb5a14b9af6758292fee53fe2a7f7ac6f528bf7019013097d6313c96e3d4a72866547f8b6946b0b16027404c3941645533649fab02ce8c68c1b1fe153ebfc450ac4f0c197de8220d35342e3138392e3136342e333914f9956e70daffa263e8cf29fa6557b7b630a595a8fb4e1ffb05a3fb8f300020754b89dae8db20fc4cee5e3adb07b146d7efe508a66fa0a8e1094675b9daa35e20754b89dae8db20fc4cee5e3adb07b146d7efe508a66fa0a8e1094675b9daa35e0130985bda42120b76d3118d53f76ff49f8f1056a6d9044c165498acd2449afcf0f04928090aacce43f95bb1130f1774c2a10c34342e3233332e34342e39351446d938862af6d9a291e26c0048177db2892a710bfb4e1ffb05a3fb8f3000207718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be4290207718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be429001308c99f0600654d103f2cc2e8afd413f92ce0b1703e4b2695e441ea6ca41c04aa02b17a417f537c3738fc2d55c9d7c465c0d34342e3232372e3133372e3737140498ade3c80045c2a7520e921180ae1c39da5c57fb4e1ffb05a3fb8f30002085f15a31d3838293a9c1d72a1a0fa21e66110ce20878bd4c1024c4ae1d5be8242085f15a31d3838293a9c1d72a1a0fa21e66110ce20878bd4c1024c4ae1d5be8240130b3ebfc2a01c5e5f81e5b751db91cbbb2dd28a8125221d91c7cabe348abea7140ba157311cb0706e8b2a021ca4b9df7980d35342e3230312e33322e3133311468c506d43816d1a8389c860c1d162be44d1e777cfb4e1ffb05a3fb8f30002088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f2088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f0130a9a7425ddeee5373c8dc48863d1c7a9abd856a95d26f4146dd818c0b8d8e7669d4a35837b83e1fc1c32ed951dcd179350b35322e33332e32382e343714711fd9548ae19b2e91c7a9b4067000467ccdd2b5fb4e1ffb05a3fb8f3000208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f234208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f2340130b98ebc6724479085f5da42cb91861d1449a3ca648d955751f5c3b91b096a840f092676c348f2f00b5039481dca12b9630d35322e31332e3133322e313436145bdbf34a0dad860c6ec71523ae39373325225cc1fb4e1ffb05a3fb8f3000208b8d1193afd22e538ce0c9fb50fee155d0f6176ca68e65da684c5dce2d1e0815208b8d1193afd22e538ce0c9fb50fee155d0f6176ca68e65da684c5dce2d1e08150130a61f28db421160121dfc7c0fb707c0a28d7ee8bbf0f3ae522029783af248144b8ff12015083e6cc7f7dcf42c0f7455710c35322e33342e3134342e353014a0a0e17bfe82a484fefe348b7569a6d77d29d2c2fb4e1ffb05a3fb8f3000208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc4208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc40130b2cad9ab34e5a8d11dc038e34918476731a014a4d250e087c0231690acce6eb1dc5aee354356f83eb0171f5269c9b8820c35322e34332e38362e32333114337b7fb5d2c531825c3e0123ac3354018085b302fb4e1ffb05a3fb8f3000208e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c0208e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c0013083bdc72d5ba2383a5fcd5b3f69df233b38363c98a191de6ab39375b6a88b529a150a314d448714ea7908433c9bf2cfd90c35322e38392e3135342e3438146d57707c196e06487d326094c964f258f5b77c35fb4e1ffb05a3fb8f3000209712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df54209712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df540130a13129fdef659fc1d53aeebb283e3dfaf398ded529cd03046faa4452c09f0dd3b9507c128a8fff1379f41f6dc3f3dca40d33352e38322e3139372e31393714ed1131823bcea23ac78af8c01e4d24683d6ecf88fb4e1ffb05a3fb8f30002098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba0920962098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba0920960130a02732ceeb00cbc22c6a3513e33364fbbe668f9b18d6d179a0ae8a624e54d6e70313ee5d114f4a90934c558046d7778b0c34342e3233322e3139362e3614d6ece912cbf02627a4efc3dd37e6833cf3671551fb4e1ffb05a3fb8f3000209cb04f271ba050132c00cc5838fb69e77bc55b5689f9d2d850dc528935f8145c209cb04f271ba050132c00cc5838fb69e77bc55b5689f9d2d850dc528935f8145c0130b8b9bde8dd4ada170f591c79c7799b3a3110da70e66a5d9bd958c0ee09aa9318b66a51b6e848f9d89ebdc95aa03f98890c33342e3231342e34382e36381462e960a3f6b650feed98a266b3ccdf6e363562cffb4e1ffb05a3fb8f300020b3b5748571b60fe9ad112715d6a51725d6e5a52a9c3af5fd36a1724cf50d862f20b3b5748571b60fe9ad112715d6a51725d6e5a52a9c3af5fd36a1724cf50d862f0130b066eb4def83361ffc67185aa1e0d731674c29b63f6094195e51fcd538ea20d92dd4a8d565fa5a4952d7003a6dc6ae860b35322e34332e31332e39321441b308f737ca9e39f67b553158903198a88c516efb4e1ffb05a3fb8f300020ba8ce1dc72857b4168e33272571df7fbaf84c316dfe48217addcf6595e25421620ba8ce1dc72857b4168e33272571df7fbaf84c316dfe48217addcf6595e2542160130a6e8c59c8ca50f24d6ba38e9c2170eb7e7ecb218025bf5b872e7757127dff5e358f8996cedeffb73183d75e0da1ce2a80d35322e34322e3230322e3132381462e0104ce0aafc1f06bde37c73702fe84b307f05fb4e1ffb05a3fb8f300020bbfd0ac1977011267a7032641ef5487fe15a4de798faa485b156fb3b7eb0acb820bbfd0ac1977011267a7032641ef5487fe15a4de798faa485b156fb3b7eb0acb80130b02657330749afaba1d7f537a8d7a2f7f5d769dfeb35c611997de1fde5aeee25a2b36cd5b29658a99bfa26ac11295ef10c33352e38322e34392e31393614dbbebbc52a5bae21b818e0487311041c91b2683bfb4e1ffb05a3fb8f300020c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba820c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba8013096b913b9291edf58bd3dcaa9d4ca9a22cbcfdb8aa5ca6e3f0be4b9c84f251ab1a4dedc2eb735aab46559e71d81d34d580d35342e3231332e3230342e383514fdae7cdf38811659ce9481975b326a5d07236bc5fb4e1ffb05a3fb8f300020d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f8920d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f89013085fc1d0b5171e799df05263801d116cb5091e8b61a6dedaeb7d555acc70faebf8888c32892877db163f92fb3d37697510d34342e3234302e39382e313032147034f0d3853c5351fb8e0ffd3c1daf12c51c2d89fb4e1ffb05a3fb8f30003098dbb9b35974480142186275c072950c403c009244f48be412f76d3fdbbb079126b9a3e2d9902d74fb3fcf571179c8ba200000013b5860da205d4132c60deedcd2f06f18c77718fc9f96a5473d05e596fa00200000013b5860da205d4132c60deedcd2f06f18c77718fc9f96a5473d05e596fa00fc00110a18192005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea82005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea80130aefbe4d19c74f3038be0d800cecadf43701500341a07b66c54780eff1d919af02df5981f40298d42d71a21203f5861830d35322e32342e3132342e313632148feb00404d6f765856c95e587b2523a365bc7258fb4e1ffb05a3fb8f30002020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c2020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c0130a6318708e3cf020d9a4d6acc99290e20852673b3fd56111a41f768d62c774cf7634621e292811aadacba01405ee0dd4c0c33352e38352e32312e3137391435d9eb76397d05b43b5cd8da7ccfa8408bc89ab3fb4e1ffb05a3fb8f3000203971dab9691efac06e4ce7a5483131373e84726458924fe48b7d541791693be1203971dab9691efac06e4ce7a5483131373e84726458924fe48b7d541791693be10130932daaeb7b3d00c345c7928cf668dd5b93f00c8ae932c3b02ec60a32f3bc70a06d54de27ebcd7d754ba8ab457d4220fe0d39322e36332e3137362e3230321461c274080f47a95be5372ef8c69bb60ab1d4ca82fb4e1ffb05a3fb8f30002039741ad83dd791e1e738f19edae82d6c0322972e6a455981424da3769b3dbd4a2039741ad83dd791e1e738f19edae82d6c0322972e6a455981424da3769b3dbd4a0130b6dc1e01c3c5adf1c45d2ffdc8b3e2bb191ddc96155093c44d2ea4dbf825a1b58c2a9b2f352ea9bfb82069224dfc12a20e33352e3136332e3134342e32333014ec7bf3b9bc72eda38c80bb7cf16e294e763e56b4fb4e1ffb05a3fb8f30002040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d2040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d0130aacc0b07512ca510f795d08610bb19b86765fab3ebe38247bc66894bb487873517751be72d6623aa4c6f0de8b9fb86300c35322e31302e3232392e3131143e8b10646ee9d6c28d75c280b357dd3a9ae9f962fb4e1ffb05a3fb8f3000205b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a23205b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a230130b2386d3b8287a94917087b2214107fb7604a296aaa68ad405c267cfe0ac50254edc13916213526c93ae969da3e2e19dd0d33352e3136352e35302e31323614f460a07a2b0dc932e1d8ff2dee2b984ac415dcebfb4e1ffb05a3fb8f3000205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef436205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef436013089a560690e28c68c6503d32257037db0901e0e7e58e2a49502f27ef146faf9785c3a6d0d7a83f51f54e8a416b8fc5d5a0d34342e3233392e33392e31353314972a33056d57359de8acfa4fb8b29dc1c14f76b8fb4e1ffb05a3fb8f30002061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb2061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb01308123b9c30ea0afee794b67b78633b351d4e8a6861f9089db1eddaea2063052b4b8e6fe6d7aa8adaa8d14daee571921190c35322e31322e3137362e3930147ada3e486409b39c94a0833c8d782f35bc24e96afb4e1ffb05a3fb8f3000206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e52863320966206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e5286332096601308784b66c8bacc5e407ba4388af1ce9634c0c65fae5ccb415d99622e2568fddd81860551836c6857651b7e68bf777051e0e34342e3232382e3234322e31383114c374f016ea61e76aab79b8bb95a1ba0e6e3eee6ffb4e1ffb05a3fb8f3000207135069642e1a72807a383fb5a14b9af6758292fee53fe2a7f7ac6f528bf7019207135069642e1a72807a383fb5a14b9af6758292fee53fe2a7f7ac6f528bf7019013088ca8aaf57cc7e2af48b2036bc3ce08b729115792ddd891d748809feb5131a78834a444d4bf5d682372030bdef0aeef60d35342e3138392e3136342e333914f9956e70daffa263e8cf29fa6557b7b630a595a8fb4e1ffb05a3fb8f3000207718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be4290207718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be429001308a1844847acbbd40ed0102cf8978803b46626cf1ff053d3962dc017bcf9274ac64016269ed9c4cbaaea230cd582ce7c10d34342e3232372e3133372e3737140498ade3c80045c2a7520e921180ae1c39da5c57fb4e1ffb05a3fb8f30002087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d6789182087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d6789180130b2bb87347b1d029ee08969d8b183be7cb5bb7030333e7b1ebc590ef95bbdea0060106943d82fe1287e66b0a6ea9fbda70e33352e3136372e3134352e313439149b9cdbfe3568cc0b37f136b00a634c75653f05e3fb4e1ffb05a3fb8f30002088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f2088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f0130902b68a0d6aaaa88f5448e7847aa844ca290312883ccc45d513b6f55c186a66b430d9be46a39b36d65968f35e21672c50b35322e33332e32382e343714711fd9548ae19b2e91c7a9b4067000467ccdd2b5fb4e1ffb05a3fb8f3000208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f234208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f2340130b02ec92b3976b32d0fe09a82c478f9ad352a176b4af5c95c14021a39068e8e0f0ee3a9665a7347dadcc5495a6c54be830d35322e31332e3133322e313436145bdbf34a0dad860c6ec71523ae39373325225cc1fb4e1ffb05a3fb8f3000208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc4208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc40130a8b4baf7a0ad0776ad239d4795d86e25d77a4f59d054ed7c4dcc31f97ded0485e6a0b1475d744f20b491438d2e53937f0c35322e34332e38362e32333114337b7fb5d2c531825c3e0123ac3354018085b302fb4e1ffb05a3fb8f3000208e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c0208e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c00130a220d7da059c4f6129c623b728dd3f59f9e12f4d6cb81a7291ed72323f48906c411cf04b926906323e4fcf9c64a7afa20c35322e38392e3135342e3438146d57707c196e06487d326094c964f258f5b77c35fb4e1ffb05a3fb8f30002091bbce94c34ebde0d099c0a2cb7635c0c31425ebabcec644f4f1a0854bfa605d2091bbce94c34ebde0d099c0a2cb7635c0c31425ebabcec644f4f1a0854bfa605d013090dc1560bf0fee4e480e85565e796ba90608bcdc82c5be50a17a0276126b3011c0b05c53d5b57971677ee6dc4065e2620c35322e34302e3231392e34311402aa69f8ef6666e7cad6d9323755a0ef3c1b6bd9fb4e1ffb05a3fb8f3000209712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df54209712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df540130a280d0efc97a9f5877d4d5d26842c2b1eb5a972f6721ad04f59379ceeee8eea2279b41c55b2d91f326d1a081e2308b2c0d33352e38322e3139372e31393714ed1131823bcea23ac78af8c01e4d24683d6ecf88fb4e1ffb05a3fb8f30002098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba0920962098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba0920960130ae50333bb9c084b8235209009bc79e95ac93ea7e720f645f40210985cacb95d938359f1c2054c54f8ffecc46b46c72520c34342e3233322e3139362e3614d6ece912cbf02627a4efc3dd37e6833cf3671551fb4e1ffb05a3fb8f3000209cb04f271ba050132c00cc5838fb69e77bc55b5689f9d2d850dc528935f8145c209cb04f271ba050132c00cc5838fb69e77bc55b5689f9d2d850dc528935f8145c0130902df93b14e13fa8c2bc56f8dd885933e7664a040742e9db1944c022a362f1f59bf392c8f2b619b6aa902751a0d97eb60c33342e3231342e34382e36381462e960a3f6b650feed98a266b3ccdf6e363562cffb4e1ffb05a3fb8f300020b3b5748571b60fe9ad112715d6a51725d6e5a52a9c3af5fd36a1724cf50d862f20b3b5748571b60fe9ad112715d6a51725d6e5a52a9c3af5fd36a1724cf50d862f0130b846359de05b4e141f1bf41c6f11a74858fead3a20c0b197f25eb081056520000a8e5f665d2504b0c3722d07fe9d48390b35322e34332e31332e39321441b308f737ca9e39f67b553158903198a88c516efb4e1ffb05a3fb8f300020bbfd0ac1977011267a7032641ef5487fe15a4de798faa485b156fb3b7eb0acb820bbfd0ac1977011267a7032641ef5487fe15a4de798faa485b156fb3b7eb0acb80130b64ffd3afa423be6e3c703eba0a16b25c86ec60e391d005bf47a73d33c66bcf7d0b2172d0f55041ee8d7869f7c6f352c0c33352e38322e34392e31393614dbbebbc52a5bae21b818e0487311041c91b2683bfb4e1ffb05a3fb8f300020d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f8920d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f890130a6314c087034d4edfdb09dee1471a52b7906905da4510346d1a4c932c40174a753d2658cdbc734b83430d9a19fde876b0d34342e3234302e39382e313032147034f0d3853c5351fb8e0ffd3c1daf12c51c2d89fb4e1ffb05a3fb8f300020f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba786399038120f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba78639903810130a3c22f17c427c3f66373ab1eada7d9288fcb81114eaed49edd48647aada20c6d439f2d603cc9f4d00e92cbe844f432910d35322e31332e3235302e31383214fe2d4798df3e9b41a6823bc0b3f020478e87925dfb4e1ffb05a3fb8f300020ff261d2c1c76907a2ad8aeb6c5611796f03b5cbd88ae92452a4727e13f4f4ac920ff261d2c1c76907a2ad8aeb6c5611796f03b5cbd88ae92452a4727e13f4f4ac90130b5ea66b9c53fbbe4159192277264bfec6873a97e5c585a7adf5a62cbae4481aceface1dff0868ea001ed514810a75fe60d35342e3138372e31342e3233321467e05b1b52c7c896adf20035036fe1d30dcefc9cfb4e1ffb05a3fb8f30003082d71ec73b651ee1603038edce0b1b453e6cdf03a7c5dae542ecfa36e8e646ad5f8b2c6fd2947ebf3504a1e9aa36a3112000000050b5530a426cc3a37ae64b7e37879c0905cd90391226fd7395a19cad2b002000000050b5530a426cc3a37ae64b7e37879c0905cd90391226fd7395a19cad2b00fc00110a00192005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea82005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea8000d35322e32342e3132342e313632148feb00404d6f765856c95e587b2523a365bc7258fb4e1ffb05a3fb8f30002012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a22012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a2000e3231322e32342e3130332e31343914c1161c96de3dae28cd7f20ff8c2aa7b94b866d76fb4e1ffb05a3fb8f300020143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f11320143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f113000d33352e3136342e32332e32343514b5f25f8f70cf8d05c2d2970bdf186c994431d84efb4e1ffb05a3fb8f30002020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c2020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c000c33352e38352e32312e3137391435d9eb76397d05b43b5cd8da7ccfa8408bc89ab3fb4e1ffb05a3fb8f3000202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb000d35342e3134392e33332e313637141ffbf1d32541dcb8f5555305295704a9ff9adc24fb4e1ffb05a3fb8f30002040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d2040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d000c35322e31302e3232392e3131143e8b10646ee9d6c28d75c280b357dd3a9ae9f962fb4e1ffb05a3fb8f3000205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef436205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef436000d34342e3233392e33392e31353314972a33056d57359de8acfa4fb8b29dc1c14f76b8fb4e1ffb05a3fb8f30002061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb2061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb000c35322e31322e3137362e3930147ada3e486409b39c94a0833c8d782f35bc24e96afb4e1ffb05a3fb8f3000206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e52863320966206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e52863320966000e34342e3232382e3234322e31383114c374f016ea61e76aab79b8bb95a1ba0e6e3eee6ffb4e1ffb05a3fb8f300020754b89dae8db20fc4cee5e3adb07b146d7efe508a66fa0a8e1094675b9daa35e20754b89dae8db20fc4cee5e3adb07b146d7efe508a66fa0a8e1094675b9daa35e000c34342e3233332e34342e39351446d938862af6d9a291e26c0048177db2892a710bfb4e1ffb05a3fb8f3000207718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be4290207718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be4290000d34342e3232372e3133372e3737140498ade3c80045c2a7520e921180ae1c39da5c57fb4e1ffb05a3fb8f30002085f15a31d3838293a9c1d72a1a0fa21e66110ce20878bd4c1024c4ae1d5be8242085f15a31d3838293a9c1d72a1a0fa21e66110ce20878bd4c1024c4ae1d5be824000d35342e3230312e33322e3133311468c506d43816d1a8389c860c1d162be44d1e777cfb4e1ffb05a3fb8f30002087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d6789182087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d678918000e33352e3136372e3134352e313439149b9cdbfe3568cc0b37f136b00a634c75653f05e3fb4e1ffb05a3fb8f30002088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f2088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f000b35322e33332e32382e343714711fd9548ae19b2e91c7a9b4067000467ccdd2b5fb4e1ffb05a3fb8f3000208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f234208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f234000d35322e31332e3133322e313436145bdbf34a0dad860c6ec71523ae39373325225cc1fb4e1ffb05a3fb8f3000208b8d1193afd22e538ce0c9fb50fee155d0f6176ca68e65da684c5dce2d1e0815208b8d1193afd22e538ce0c9fb50fee155d0f6176ca68e65da684c5dce2d1e0815000c35322e33342e3134342e353014a0a0e17bfe82a484fefe348b7569a6d77d29d2c2fb4e1ffb05a3fb8f3000208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc4208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc4000c35322e34332e38362e32333114337b7fb5d2c531825c3e0123ac3354018085b302fb4e1ffb05a3fb8f3000208eca4bcbb3a124ab283afd42dad3bdb2077b3809659788a0f1daffce5b9f001f208eca4bcbb3a124ab283afd42dad3bdb2077b3809659788a0f1daffce5b9f001f000d35342e36382e3233352e32303114c075993a8336f93a13bb7bbb7e0e89928be4aafbfb4e1ffb05a3fb8f3000209712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df54209712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df54000d33352e38322e3139372e31393714ed1131823bcea23ac78af8c01e4d24683d6ecf88fb4e1ffb05a3fb8f30002098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba0920962098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba092096000c34342e3233322e3139362e3614d6ece912cbf02627a4efc3dd37e6833cf3671551fb4e1ffb05a3fb8f3000209cb04f271ba050132c00cc5838fb69e77bc55b5689f9d2d850dc528935f8145c209cb04f271ba050132c00cc5838fb69e77bc55b5689f9d2d850dc528935f8145c000c33342e3231342e34382e36381462e960a3f6b650feed98a266b3ccdf6e363562cffb4e1ffb05a3fb8f300020bbfd0ac1977011267a7032641ef5487fe15a4de798faa485b156fb3b7eb0acb820bbfd0ac1977011267a7032641ef5487fe15a4de798faa485b156fb3b7eb0acb8000c33352e38322e34392e31393614dbbebbc52a5bae21b818e0487311041c91b2683bfb4e1ffb05a3fb8f300020c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba820c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba8000d35342e3231332e3230342e383514fdae7cdf38811659ce9481975b326a5d07236bc5fb4e1ffb05a3fb8f300020d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f8920d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f89000d34342e3234302e39382e313032147034f0d3853c5351fb8e0ffd3c1daf12c51c2d89fb4e1ffb05a3fb8f300020f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba786399038120f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba7863990381000d35322e31332e3235302e31383214fe2d4798df3e9b41a6823bc0b3f020478e87925dfb4e1ffb05a3fb8f3000309115ebe490480078d6ed0b6cbb6b14a67e8c87a481a9b899ad9b69df05b58319a845f03c8b12333714e40cd371e867842000000029787a10cbbd05260d3c7a8114746b568d0a5fbd2fdb9f080ac12c5acd002000000029787a10cbbd05260d3c7a8114746b568d0a5fbd2fdb9f080ac12c5acd00fc001109e8192005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea82005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea80130970d7b81b480412fc43ea1f788843b1d09f0dc907586b3e260b050c7644f6d41fb27b1a42c480e34004c32c09977e93f0d35322e32342e3132342e313632148feb00404d6f765856c95e587b2523a365bc7258fb4e1ffb05a3fb8f30002012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a22012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a20130a820e13b8769adac09e564cd1cb18bc063cfcf3924f15636b0760c4f5b0fe84cf2fb570335b9f5a480e175a1d3bf271c0e3231322e32342e3130332e31343914c1161c96de3dae28cd7f20ff8c2aa7b94b866d76fb4e1ffb05a3fb8f300020143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f11320143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f113013098a0e5d3895c330ff366206535e6868f2b68d9a187883d14a20d439471981e61b208ab0e8a3550b3a9b896864e2e97630d33352e3136342e32332e32343514b5f25f8f70cf8d05c2d2970bdf186c994431d84efb4e1ffb05a3fb8f30002020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c2020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c0130a5873d03f1d4625d480393ef389ef41c6c64d996285ffa796cc08208824d35dccf69f861d6adc1692fb714c09031a02b0c33352e38352e32312e3137391435d9eb76397d05b43b5cd8da7ccfa8408bc89ab3fb4e1ffb05a3fb8f3000202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb0130b202608dae582e081fddaf3e2a6a79cb3f843fb9af4edcc5c5ca173c3802851be056b863ca2e7f754d6ebd7273dce89c0d35342e3134392e33332e313637141ffbf1d32541dcb8f5555305295704a9ff9adc24fb4e1ffb05a3fb8f3000203971dab9691efac06e4ce7a5483131373e84726458924fe48b7d541791693be1203971dab9691efac06e4ce7a5483131373e84726458924fe48b7d541791693be101308292b344b60fc7e2a7039a8d36fad7680caa319305f1a48bf517c70d669145757311e299990b96f2a1725d8d15122c210d39322e36332e3137362e3230321461c274080f47a95be5372ef8c69bb60ab1d4ca82fb4e1ffb05a3fb8f30002040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d2040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d01308022bb20ab0892ac7fceddccffafed851a6b99462fe1fbc8ed302eb13dcd34104e8b640d6863e22b3c0334c65bb1353d0c35322e31302e3232392e3131143e8b10646ee9d6c28d75c280b357dd3a9ae9f962fb4e1ffb05a3fb8f3000205b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a23205b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a230130a8d80210f5a8421b7d0e7aefb73de90996043824f763ba7ba2f2bccf65fe2692a843be92a6c948e3ec379cc4873ab8620d33352e3136352e35302e31323614f460a07a2b0dc932e1d8ff2dee2b984ac415dcebfb4e1ffb05a3fb8f3000205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef436205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef43601308b71e75c86b6dbe16c8d77b58c54c3046b879c9b2870ad5978bd66822a5495c088be770cbaa7b07606e4bea48f1d57520d34342e3233392e33392e31353314972a33056d57359de8acfa4fb8b29dc1c14f76b8fb4e1ffb05a3fb8f3000207135069642e1a72807a383fb5a14b9af6758292fee53fe2a7f7ac6f528bf7019207135069642e1a72807a383fb5a14b9af6758292fee53fe2a7f7ac6f528bf70190130a5db974fcc27c6e6659be41f6e60cda5595e476219e92f1a42891a2129efa57e7168cb1ed7e910567b28b50f49ec89580d35342e3138392e3136342e333914f9956e70daffa263e8cf29fa6557b7b630a595a8fb4e1ffb05a3fb8f300020754b89dae8db20fc4cee5e3adb07b146d7efe508a66fa0a8e1094675b9daa35e20754b89dae8db20fc4cee5e3adb07b146d7efe508a66fa0a8e1094675b9daa35e01308a0faa9aa37cb733914dcb2f0238e7ecd1cc6e1bca84ea82f40f56ac676cfbfdddfebb17145fd119724acbac6526925d0c34342e3233332e34342e39351446d938862af6d9a291e26c0048177db2892a710bfb4e1ffb05a3fb8f3000207718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be4290207718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be42900130a43cce1d88a28cce331807a9d82ebb836e179712045ecb44f4d9e30e3dadd1fd56eb794e1ff4b77f6389cf070ab4335e0d34342e3232372e3133372e3737140498ade3c80045c2a7520e921180ae1c39da5c57fb4e1ffb05a3fb8f30002085f15a31d3838293a9c1d72a1a0fa21e66110ce20878bd4c1024c4ae1d5be8242085f15a31d3838293a9c1d72a1a0fa21e66110ce20878bd4c1024c4ae1d5be8240130ac38307fb06ab201fad2e7d995746ca822aa65b3efacdb2944840dc49cae820ef8cda959b3022fa5825aa6c185b2d2e80d35342e3230312e33322e3133311468c506d43816d1a8389c860c1d162be44d1e777cfb4e1ffb05a3fb8f30002088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f2088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f0130b0a830cc01b28f5268aae63f37e8edee59c0cf638e56add0f8fc6a63fa67754d550acb8c1844fe49dd969384b3e47d4d0b35322e33332e32382e343714711fd9548ae19b2e91c7a9b4067000467ccdd2b5fb4e1ffb05a3fb8f3000208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f234208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f2340130897c23a6f47c9459e7c374ab0fa826f27a035794b8aeb965fd6ee02bac15546e4c74b4dc878f9aeca6811ee30376479a0d35322e31332e3133322e313436145bdbf34a0dad860c6ec71523ae39373325225cc1fb4e1ffb05a3fb8f3000208b8d1193afd22e538ce0c9fb50fee155d0f6176ca68e65da684c5dce2d1e0815208b8d1193afd22e538ce0c9fb50fee155d0f6176ca68e65da684c5dce2d1e08150130923d83d963dcad047de4b636c1002972099365c6ca34d86b2b0c4d9d5f1e3c76a82a4775b6973933f08b4efca67c39140c35322e33342e3134342e353014a0a0e17bfe82a484fefe348b7569a6d77d29d2c2fb4e1ffb05a3fb8f3000208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc4208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc40130acf9fca5575dd9432d04bf48208d4d6233327efd892d7dc8a19c221875b19150e386e59c596a26f805c51b782266ed2d0c35322e34332e38362e32333114337b7fb5d2c531825c3e0123ac3354018085b302fb4e1ffb05a3fb8f3000208e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c0208e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c001309656eb5ec24456fafd42a36eaaa7777a1a07126cdba616f306f5922962edb86c84eb63eb1c4fe73b77c2c125c03e0e8a0c35322e38392e3135342e3438146d57707c196e06487d326094c964f258f5b77c35fb4e1ffb05a3fb8f3000208eca4bcbb3a124ab283afd42dad3bdb2077b3809659788a0f1daffce5b9f001f208eca4bcbb3a124ab283afd42dad3bdb2077b3809659788a0f1daffce5b9f001f01308458cd94f39953a2cbe980f26296dbc935f5bfa0c51840267d34529a14c40a62dbbcde39372748c0c555169d692852dd0d35342e36382e3233352e32303114c075993a8336f93a13bb7bbb7e0e89928be4aafbfb4e1ffb05a3fb8f3000209712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df54209712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df540130b8986d8ccb4735db954e68d32a0d544778f631523e347b673ec19f522241a4a78e842d21e3dbafaf7c1dde9b7a87af610d33352e38322e3139372e31393714ed1131823bcea23ac78af8c01e4d24683d6ecf88fb4e1ffb05a3fb8f3000209cb04f271ba050132c00cc5838fb69e77bc55b5689f9d2d850dc528935f8145c209cb04f271ba050132c00cc5838fb69e77bc55b5689f9d2d850dc528935f8145c0130a4922f49f620b1db38fa2ee28facca3aa818e29858e47d8afa467f1f6e78512f7f81b09ec5debc0d6ba820c5afcf730a0c33342e3231342e34382e36381462e960a3f6b650feed98a266b3ccdf6e363562cffb4e1ffb05a3fb8f300020b3b5748571b60fe9ad112715d6a51725d6e5a52a9c3af5fd36a1724cf50d862f20b3b5748571b60fe9ad112715d6a51725d6e5a52a9c3af5fd36a1724cf50d862f0130b0bd0eaedab09436d694b6fbfd5d7ff130d10a5b0793363383556d4d4e203892d50c6d7ff5fd418c113e46dd03e680f90b35322e34332e31332e39321441b308f737ca9e39f67b553158903198a88c516efb4e1ffb05a3fb8f300020ba8ce1dc72857b4168e33272571df7fbaf84c316dfe48217addcf6595e25421620ba8ce1dc72857b4168e33272571df7fbaf84c316dfe48217addcf6595e254216013096b15178f4a27b4e2c957fba6321c9e0c6a52cc181b78bdff133af13378578429140857bcd7bef984123d4a0c1bb0a0f0d35322e34322e3230322e3132381462e0104ce0aafc1f06bde37c73702fe84b307f05fb4e1ffb05a3fb8f300020d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f8920d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f890130a92fbcf877ae8f1126dd2000c14f94e984b0b8417ef08a5d41e8e4f25b1c4345d604ea4d5628cb3b465c0f133c1680ea0d34342e3234302e39382e313032147034f0d3853c5351fb8e0ffd3c1daf12c51c2d89fb4e1ffb05a3fb8f300020f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba786399038120f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba7863990381013080cf4159f981ea771039b37a355c87b1b63d08f5ca1fe187b43dab3d69aba34c296486fbe95169d4e86aff8e5b7d4ec10d35322e31332e3235302e31383214fe2d4798df3e9b41a6823bc0b3f020478e87925dfb4e1ffb05a3fb8f300030b9cbddb5cb09af2419de553627792b168d70fec7f4b86455fad63931bd68cef1eb7aee5d8b52e592167c2b5e2b7778b420000000ca47540e3e2bbbfc91ad3581df6b5f730ea457841a3544e2ab3c54c2450020000000ca47540e3e2bbbfc91ad3581df6b5f730ea457841a3544e2ab3c54c24500fc001109d0192005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea82005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea80130b8b06499c583a0fd22b6891f1b2fbc982c65889f34a41303a4e6add3335e6f03de51013907906849ae0606f4642546e90d35322e32342e3132342e313632148feb00404d6f765856c95e587b2523a365bc7258fb4e1ffb05a3fb8f30002012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a22012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a20130a74f5ce985df2786c2aff01e9030ac94d60a087d9bb7e67f6ed82fd2bfdec5ffa365fa0234cc36cffe48ed7a891566f40e3231322e32342e3130332e31343914c1161c96de3dae28cd7f20ff8c2aa7b94b866d76fb4e1ffb05a3fb8f300020143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f11320143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f113013089c4a5d69af324ffe22e0c8d9b8b0dd4ebcc23a8947dbefa423dd21d6bca38d83903018bd19233fdf82db3cf58b121120d33352e3136342e32332e32343514b5f25f8f70cf8d05c2d2970bdf186c994431d84efb4e1ffb05a3fb8f30002020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c2020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c0130a97a7c20f8e962e0f42eb82a8574a40d592a6c045e2d0dd022d30ae7580f63121f1b127de8c8fdbc0a09be310be140630c33352e38352e32312e3137391435d9eb76397d05b43b5cd8da7ccfa8408bc89ab3fb4e1ffb05a3fb8f3000202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb013095b29cd5c1260dad12e00db7df6264adf1e129db92db275c512024ef882d525bc76aae7b91e98cc50f02b467b729a4230d35342e3134392e33332e313637141ffbf1d32541dcb8f5555305295704a9ff9adc24fb4e1ffb05a3fb8f3000203971dab9691efac06e4ce7a5483131373e84726458924fe48b7d541791693be1203971dab9691efac06e4ce7a5483131373e84726458924fe48b7d541791693be10130b36395d295eb39ab7a37a6dbae201d69783252554528616a2cd694ece2bcfa1c228bfbe9f11189e58464f1f818222cb80d39322e36332e3137362e3230321461c274080f47a95be5372ef8c69bb60ab1d4ca82fb4e1ffb05a3fb8f30002039741ad83dd791e1e738f19edae82d6c0322972e6a455981424da3769b3dbd4a2039741ad83dd791e1e738f19edae82d6c0322972e6a455981424da3769b3dbd4a0130a5c5eb179bcfa04fff58a455c31a4434d2956ee64992ad90fa984e22bb0271349b34ed391adb5d14e92fe4e909e66fed0e33352e3136332e3134342e32333014ec7bf3b9bc72eda38c80bb7cf16e294e763e56b4fb4e1ffb05a3fb8f30002040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d2040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d0130990581eeaa1de281b5b427562103f13d36926683d2fd547c9594ef7814b4eae5d1873a8935db2014270fbf6a8324a0650c35322e31302e3232392e3131143e8b10646ee9d6c28d75c280b357dd3a9ae9f962fb4e1ffb05a3fb8f3000205b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a23205b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a23013092859d855e078b0d51bb59700c2f97084b7b9cb756877df99999a141599e2398a1d801ba447e87243666bfccda43b3a80d33352e3136352e35302e31323614f460a07a2b0dc932e1d8ff2dee2b984ac415dcebfb4e1ffb05a3fb8f3000205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef436205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef4360130a517a483d86831f719bea10f0fd570a991d4d31f842eacdb7bcedd2b4574832c8c9f8faffdf3dd5855b958fab30f28ea0d34342e3233392e33392e31353314972a33056d57359de8acfa4fb8b29dc1c14f76b8fb4e1ffb05a3fb8f30002061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb2061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb01308d6b47b552e835caf543b4e12228069e2b017e9697e9a53769477a17f911ebb6d60902335c80dbc5f8a3f1fddb901a2d0c35322e31322e3137362e3930147ada3e486409b39c94a0833c8d782f35bc24e96afb4e1ffb05a3fb8f30002085f15a31d3838293a9c1d72a1a0fa21e66110ce20878bd4c1024c4ae1d5be8242085f15a31d3838293a9c1d72a1a0fa21e66110ce20878bd4c1024c4ae1d5be8240130959e4b96408015ba5f09b91b6075879d793c8e23ac87c8c7bfb488570359603a5555912d439396eff96196a8a48509350d35342e3230312e33322e3133311468c506d43816d1a8389c860c1d162be44d1e777cfb4e1ffb05a3fb8f30002087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d6789182087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d6789180130b48413f0072f49e797ac6d1e24416a891a045f9381882ee222801da1872c6edc1f96b10d5fc1e35ac986dabbe1a6bebb0e33352e3136372e3134352e313439149b9cdbfe3568cc0b37f136b00a634c75653f05e3fb4e1ffb05a3fb8f30002088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f2088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f013080b9a527a7102ef8fa92958d687466a5e660408c19aa20631b5ba92e6ad6c05ce0756df6fb5ddef9f3541096b1a507c60b35322e33332e32382e343714711fd9548ae19b2e91c7a9b4067000467ccdd2b5fb4e1ffb05a3fb8f3000208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f234208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f234013096224eff9b71fa242635fc530e66dc5a352d930491a7f6835420101c3f5f9ded42b8b81342d46430e7cc2a7d2c6118640d35322e31332e3133322e313436145bdbf34a0dad860c6ec71523ae39373325225cc1fb4e1ffb05a3fb8f3000208e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c0208e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c001308b083dafad8abb0439badd1bee47c8c40ff94d9b0cb3a170e80b79d7291eff897897984cb854f731777298d9a4c53ff70c35322e38392e3135342e3438146d57707c196e06487d326094c964f258f5b77c35fb4e1ffb05a3fb8f3000208eca4bcbb3a124ab283afd42dad3bdb2077b3809659788a0f1daffce5b9f001f208eca4bcbb3a124ab283afd42dad3bdb2077b3809659788a0f1daffce5b9f001f013099ec50553765cb873f210513dc1f50cf370711af9283042cfa0047b50de960c54343213a10f86443605e72c8158fbdbe0d35342e36382e3233352e32303114c075993a8336f93a13bb7bbb7e0e89928be4aafbfb4e1ffb05a3fb8f30002091bbce94c34ebde0d099c0a2cb7635c0c31425ebabcec644f4f1a0854bfa605d2091bbce94c34ebde0d099c0a2cb7635c0c31425ebabcec644f4f1a0854bfa605d01309418730d55f9813b944c857e73544681bfb28cfb0cb8f80cc6853b060ce980d5124c451302681fd64507973dafd4fe050c35322e34302e3231392e34311402aa69f8ef6666e7cad6d9323755a0ef3c1b6bd9fb4e1ffb05a3fb8f3000209712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df54209712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df5401309373b16af5c5922151307961ff6ba2932577a762412ddcecd8ea5e9d9de353687517a99179641a64867412dfa02b30e50d33352e38322e3139372e31393714ed1131823bcea23ac78af8c01e4d24683d6ecf88fb4e1ffb05a3fb8f30002098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba0920962098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba0920960130aa42f5cc6c6b0b157ebbccb51c179e6da1f657aa975cfe316bba65bb795d27c1a36fc89f277310e10d648b4eb2f3a4d70c34342e3233322e3139362e3614d6ece912cbf02627a4efc3dd37e6833cf3671551fb4e1ffb05a3fb8f300020b3b5748571b60fe9ad112715d6a51725d6e5a52a9c3af5fd36a1724cf50d862f20b3b5748571b60fe9ad112715d6a51725d6e5a52a9c3af5fd36a1724cf50d862f0130b9b68ea1d8c99b7cf1241fe98bbb671d4503b181af78d2cdd3b6c26717c5bbcc0f9977fd5e1ba2a89681f2c7193b30590b35322e34332e31332e39321441b308f737ca9e39f67b553158903198a88c516efb4e1ffb05a3fb8f300020bbfd0ac1977011267a7032641ef5487fe15a4de798faa485b156fb3b7eb0acb820bbfd0ac1977011267a7032641ef5487fe15a4de798faa485b156fb3b7eb0acb80130b9b9b9d80cac56a2354054847aad75cac16f3e004983c4287887ce67fe9151dc85ca64efced2acbb2fe1249edb97aeaa0c33352e38322e34392e31393614dbbebbc52a5bae21b818e0487311041c91b2683bfb4e1ffb05a3fb8f300020d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f8920d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f8901308c5fe2277f8f09c710ebc292b57abae1db9fb98a55db37c6d84d22d28616b0241a136a89addfbcf6d40a7cca5fbeb7020d34342e3234302e39382e313032147034f0d3853c5351fb8e0ffd3c1daf12c51c2d89fb4e1ffb05a3fb8f300020f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba786399038120f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba78639903810130b29a3615c31170fc5065b8c97c12db5f6dc30a6f7d3d851f7e8b5794dd4868b72eac1cf8e0938af1818f36eccf96b7560d35322e31332e3235302e31383214fe2d4798df3e9b41a6823bc0b3f020478e87925dfb4e1ffb05a3fb8f300020ff261d2c1c76907a2ad8aeb6c5611796f03b5cbd88ae92452a4727e13f4f4ac920ff261d2c1c76907a2ad8aeb6c5611796f03b5cbd88ae92452a4727e13f4f4ac90130a7219c2a26bf3628b8dad42325c9e2d03dd265015c2552990081ac3461f49b1ffc0e89f32fe01155655b12f2e5a2869f0d35342e3138372e31342e3233321467e05b1b52c7c896adf20035036fe1d30dcefc9cfb4e1ffb05a3fb8f300030b16ea424860dc0726c5e7215e1e982a42eab9330137b9fc25cb52f631237c875a75c2f1f601750686e417f0ccbdf398120000000e7654d577ec30cf6779bb7f025807118c9ee33113ea249fa1ce94906460020000000e7654d577ec30cf6779bb7f025807118c9ee33113ea249fa1ce949064600fc001109b8192005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea82005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea801308b962de6fb2b78ecd4a0d38a1e6599629e2f2ee7cf9bf120d2a42a5187f6b7bff3ad999d489ad01402952e13a7b2a0cd0d35322e32342e3132342e313632148feb00404d6f765856c95e587b2523a365bc7258fb4e1ffb05a3fb8f30002012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a22012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a201308f075ac06941ccf4426e74cca625cba70aa51383684e5b2ca68a5969980c577692a2a4fc04eaf6d75e06d46d47789d8a0e3231322e32342e3130332e31343914c1161c96de3dae28cd7f20ff8c2aa7b94b866d76fb4e1ffb05a3fb8f300020143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f11320143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f113013094ef996c8d9e5d050b0eb315c2953b3e7a6a2c0c814a4f091b0a899758193809d59932a177bb4bfe3612795c1cb1af180d33352e3136342e32332e32343514b5f25f8f70cf8d05c2d2970bdf186c994431d84efb4e1ffb05a3fb8f30002020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c2020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c0130b5c4608e61eec256009dced5e14f32abea62323bf9afc6bd3aa94775a69deffb4fbe7ced991719ae42f0464143739c050c33352e38352e32312e3137391435d9eb76397d05b43b5cd8da7ccfa8408bc89ab3fb4e1ffb05a3fb8f3000202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb0130af4e360b85ba0e07ff4daf222828646b8553d34e13d27e0c0ab73b8d0819a7de542c8b75b908f2a522783805e98161ed0d35342e3134392e33332e313637141ffbf1d32541dcb8f5555305295704a9ff9adc24fb4e1ffb05a3fb8f3000203971dab9691efac06e4ce7a5483131373e84726458924fe48b7d541791693be1203971dab9691efac06e4ce7a5483131373e84726458924fe48b7d541791693be10130b3c583538cd672a8811fd6ad676f0ab86fb20142cde7318f6821ab80c747d667e65aac29cad1642220484b528e2b97a60d39322e36332e3137362e3230321461c274080f47a95be5372ef8c69bb60ab1d4ca82fb4e1ffb05a3fb8f30002039741ad83dd791e1e738f19edae82d6c0322972e6a455981424da3769b3dbd4a2039741ad83dd791e1e738f19edae82d6c0322972e6a455981424da3769b3dbd4a01308fa018aa37212ef01b6736ed5642f2e72bee1de375bfa8b8b670d3f91c6740d603d4d28712b4bf20a9823816dc0395220e33352e3136332e3134342e32333014ec7bf3b9bc72eda38c80bb7cf16e294e763e56b4fb4e1ffb05a3fb8f30002040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d2040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d0130864d618197d9c45ce9466461c76b2a7706c7651d52fd0a9c66dacea54359b82788580f51c44144d13d03924a2f231a6b0c35322e31302e3232392e3131143e8b10646ee9d6c28d75c280b357dd3a9ae9f962fb4e1ffb05a3fb8f3000205b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a23205b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a230130b7e90c414091b2b3fc3167cdf880027601fa23caacd4d806e561dd60368f4926fbf2794ed7256d2b9cae61cdd37cf61a0d33352e3136352e35302e31323614f460a07a2b0dc932e1d8ff2dee2b984ac415dcebfb4e1ffb05a3fb8f30002061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb2061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb01308062ad18e48955d3c60465639795e5eb5d06a307710278c033336338e1f165bb3f38d8193b331e7b8e5c7174f1bcc3290c35322e31322e3137362e3930147ada3e486409b39c94a0833c8d782f35bc24e96afb4e1ffb05a3fb8f3000206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e52863320966206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e528633209660130a3c4dc99f61b79db373f2cbb31282dab6c9f1e061d3ae149f292e7d2a57867af64dbaff63d8209eb2eae7bc4d19f18ba0e34342e3232382e3234322e31383114c374f016ea61e76aab79b8bb95a1ba0e6e3eee6ffb4e1ffb05a3fb8f3000207135069642e1a72807a383fb5a14b9af6758292fee53fe2a7f7ac6f528bf7019207135069642e1a72807a383fb5a14b9af6758292fee53fe2a7f7ac6f528bf70190130b0d3a176e29c34f594cd740859a21fdeddea237d66b706439b745b64da4bc910a6454a6c24766007bef5fddc60025aa00d35342e3138392e3136342e333914f9956e70daffa263e8cf29fa6557b7b630a595a8fb4e1ffb05a3fb8f300020754b89dae8db20fc4cee5e3adb07b146d7efe508a66fa0a8e1094675b9daa35e20754b89dae8db20fc4cee5e3adb07b146d7efe508a66fa0a8e1094675b9daa35e01308f9b3c93f75c54aaa7e94af920af8d570dbeccc8f03976a95aa6cd4956c57c4320ff54d3b9a6383801d78f3e89e842880c34342e3233332e34342e39351446d938862af6d9a291e26c0048177db2892a710bfb4e1ffb05a3fb8f30002087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d6789182087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d678918013098bacabb7caa139502f082638a2c5557402755a734420a4170e0625ba4cc6a90236624023c697478134010ecf2a024710e33352e3136372e3134352e313439149b9cdbfe3568cc0b37f136b00a634c75653f05e3fb4e1ffb05a3fb8f30002088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f2088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f01308f176c317a778eb340cbff32a482253eccade757f6be7ce3264efb3cc6bae9a49f44ac1634dbd916280d1f935f4da87c0b35322e33332e32382e343714711fd9548ae19b2e91c7a9b4067000467ccdd2b5fb4e1ffb05a3fb8f3000208b8d1193afd22e538ce0c9fb50fee155d0f6176ca68e65da684c5dce2d1e0815208b8d1193afd22e538ce0c9fb50fee155d0f6176ca68e65da684c5dce2d1e081501309861cc2ef8a3969143f1b32a715a6e10c3c2d7ba46cb7bc54e4e8101f08b85589f3ad825896c5b21e5d608d9200496840c35322e33342e3134342e353014a0a0e17bfe82a484fefe348b7569a6d77d29d2c2fb4e1ffb05a3fb8f3000208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc4208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc40130a45b1a6bffa54f659e58329868160e6e4503756ebffe1cc7bba724987832f81811883638133ef1b55a877a0650e6c4d10c35322e34332e38362e32333114337b7fb5d2c531825c3e0123ac3354018085b302fb4e1ffb05a3fb8f3000208e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c0208e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c0013085ae9000f50f53adb25405b339df3a86c180a2312ba857d94c077e474a3a577e3dc4eb53a0cd2b1b1e880383d3680af80c35322e38392e3135342e3438146d57707c196e06487d326094c964f258f5b77c35fb4e1ffb05a3fb8f3000208eca4bcbb3a124ab283afd42dad3bdb2077b3809659788a0f1daffce5b9f001f208eca4bcbb3a124ab283afd42dad3bdb2077b3809659788a0f1daffce5b9f001f0130a8534f9a11dda86ea001342d7166778b70849462281cf7a5f92bcb82044900b5abb42f7301ff900e62915898bf8835710d35342e36382e3233352e32303114c075993a8336f93a13bb7bbb7e0e89928be4aafbfb4e1ffb05a3fb8f30002091bbce94c34ebde0d099c0a2cb7635c0c31425ebabcec644f4f1a0854bfa605d2091bbce94c34ebde0d099c0a2cb7635c0c31425ebabcec644f4f1a0854bfa605d0130b080fa15ef37262f5c499bdf9c9487a0e8f3419c3a809aa794af4cae7cde22052eb8323559da812edce33431f0d826020c35322e34302e3231392e34311402aa69f8ef6666e7cad6d9323755a0ef3c1b6bd9fb4e1ffb05a3fb8f30002098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba0920962098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba0920960130add41989d620cc7df4eafbc7b268d334953c1e8ba5608f454c9d0a427b58721950c46f79c0b22038b12eebc7e6ec83100c34342e3233322e3139362e3614d6ece912cbf02627a4efc3dd37e6833cf3671551fb4e1ffb05a3fb8f300020b3b5748571b60fe9ad112715d6a51725d6e5a52a9c3af5fd36a1724cf50d862f20b3b5748571b60fe9ad112715d6a51725d6e5a52a9c3af5fd36a1724cf50d862f0130872c5ed02a4b12f4131bd64f4c59271102507c9a96dbd531b35cf3c1d10b285b8edb0dc6d6f641c5868f1ec065ab08050b35322e34332e31332e39321441b308f737ca9e39f67b553158903198a88c516efb4e1ffb05a3fb8f300020ba8ce1dc72857b4168e33272571df7fbaf84c316dfe48217addcf6595e25421620ba8ce1dc72857b4168e33272571df7fbaf84c316dfe48217addcf6595e2542160130b0c7d63093cb1972c8aa94c78045cff4973d79ae141365aa6392aba6939d7cf6f5a7395fc57ac6045781acaae05f67cd0d35322e34322e3230322e3132381462e0104ce0aafc1f06bde37c73702fe84b307f05fb4e1ffb05a3fb8f300020c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba820c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba8013092ae2a2792e73608a20d7b12888d2582d6647b43eb8ee8f61e09e9520732dfdd7160dfe5c6f3386a32955171b59e9b230d35342e3231332e3230342e383514fdae7cdf38811659ce9481975b326a5d07236bc5fb4e1ffb05a3fb8f300020ff261d2c1c76907a2ad8aeb6c5611796f03b5cbd88ae92452a4727e13f4f4ac920ff261d2c1c76907a2ad8aeb6c5611796f03b5cbd88ae92452a4727e13f4f4ac9013086abcf53a568276f5dace92dbdaf038d5f959742360527941a2e3b320334bff61c9e36af902b6332e667d54b4e43f20f0d35342e3138372e31342e3233321467e05b1b52c7c896adf20035036fe1d30dcefc9cfb4e1ffb05a3fb8f3000308624b652c48f38d61cda305260bff8d679d8d4194d3f94263f4be2b109b459fd257d09b21daea3ce5d607f5cf329fcc020000001d6bd1fcac1f64325a6a26b0a3a02d1e3b61267d50f855984a873c3d6890020000001d6bd1fcac1f64325a6a26b0a3a02d1e3b61267d50f855984a873c3d68900fc001109a0192005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea82005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea80130801d1caeb0249874c51e6aef9c319b3260af3a7f4abd77e44f7f2794be2b1f1211ac2e06d951dc1102541944767bf70b0d35322e32342e3132342e313632148feb00404d6f765856c95e587b2523a365bc7258fb4e1ffb05a3fb8f30002012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a22012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a201308959077c75d865f18eb0e6da55e1685c071b16b2ebc6ae717d9ecb15c40783a22cfc80283ec15b1b58d011f5d211de470e3231322e32342e3130332e31343914c1161c96de3dae28cd7f20ff8c2aa7b94b866d76fb4e1ffb05a3fb8f300020143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f11320143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f1130130964add28e4e033a83073203713210ba9451300e370901e24c64c170c9c714df36bcdfee02c6358c7e9348cc2193c1c790d33352e3136342e32332e32343514b5f25f8f70cf8d05c2d2970bdf186c994431d84efb4e1ffb05a3fb8f3000202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb01308dd74a742631dd039ae8b11e2f3f2f1fc2503ba590ee5487a9af71d4713c0b7df9c91e730f246c5b012d682623bfe5980d35342e3134392e33332e313637141ffbf1d32541dcb8f5555305295704a9ff9adc24fb4e1ffb05a3fb8f3000203971dab9691efac06e4ce7a5483131373e84726458924fe48b7d541791693be1203971dab9691efac06e4ce7a5483131373e84726458924fe48b7d541791693be10130839b06bd3faa0249a1de9e490de0ae9b1f687f01748000720b6181271185e83deb5ee39085aacb7a19164e2c7995b9510d39322e36332e3137362e3230321461c274080f47a95be5372ef8c69bb60ab1d4ca82fb4e1ffb05a3fb8f30002039741ad83dd791e1e738f19edae82d6c0322972e6a455981424da3769b3dbd4a2039741ad83dd791e1e738f19edae82d6c0322972e6a455981424da3769b3dbd4a01308ad035bbe534c684bcc4edd241a3ae3710ff2484e4cbfdd7e2778574a4a10a038716232d4645f6a0986116156930da2d0e33352e3136332e3134342e32333014ec7bf3b9bc72eda38c80bb7cf16e294e763e56b4fb4e1ffb05a3fb8f30002040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d2040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d0130a48d35c8976bdb0d6feaed8a7fafecd6c9790eca8cc5a1e576e1ab1081caaddc5d35dbed22462b065da699d9796470030c35322e31302e3232392e3131143e8b10646ee9d6c28d75c280b357dd3a9ae9f962fb4e1ffb05a3fb8f3000205b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a23205b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a2301309761664a2d48424101e4d22d0ddb7bf68a1a51d10278418bfa86125eddbf53a73116d8e11d35fc56dcdf7dd1cbc198340d33352e3136352e35302e31323614f460a07a2b0dc932e1d8ff2dee2b984ac415dcebfb4e1ffb05a3fb8f3000205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef436205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef43601309444afcc0ef76d51219a693687d3373ae2d63cf0f2982ac364cde53ea5f3f4aad1abd2e9236848dd229fcc7bd461f4e70d34342e3233392e33392e31353314972a33056d57359de8acfa4fb8b29dc1c14f76b8fb4e1ffb05a3fb8f30002061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb2061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb01308f6f64001871f148e8f2befa5562d682e5ea35b15d651c1e5632a9ec007897ae1accdb7c771935efaadb053584f0f0ec0c35322e31322e3137362e3930147ada3e486409b39c94a0833c8d782f35bc24e96afb4e1ffb05a3fb8f3000206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e52863320966206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e528633209660130b2bdf73ed77b5ee1eba76d9597269b9acb54c53483f48d8a96724a8d41c77a7b54853ef41561c95823ae001fe226cd070e34342e3232382e3234322e31383114c374f016ea61e76aab79b8bb95a1ba0e6e3eee6ffb4e1ffb05a3fb8f3000207135069642e1a72807a383fb5a14b9af6758292fee53fe2a7f7ac6f528bf7019207135069642e1a72807a383fb5a14b9af6758292fee53fe2a7f7ac6f528bf70190130ac23ec29fa032506a8a1f534c0dbbfe234ab8c4a2492c6513a7a0cf8b9ba8ee80c2b8677acbe1005e9552608eef4c74f0d35342e3138392e3136342e333914f9956e70daffa263e8cf29fa6557b7b630a595a8fb4e1ffb05a3fb8f300020754b89dae8db20fc4cee5e3adb07b146d7efe508a66fa0a8e1094675b9daa35e20754b89dae8db20fc4cee5e3adb07b146d7efe508a66fa0a8e1094675b9daa35e0130a806786c7e246db9861c45ddbc16849415da9abbca80b2a92f07aa09b19c258598c62dce654153b5815b50ce21506e970c34342e3233332e34342e39351446d938862af6d9a291e26c0048177db2892a710bfb4e1ffb05a3fb8f30002085f15a31d3838293a9c1d72a1a0fa21e66110ce20878bd4c1024c4ae1d5be8242085f15a31d3838293a9c1d72a1a0fa21e66110ce20878bd4c1024c4ae1d5be824013091096939bbbc3b696e76a7def9734e8afd250c49b307930f2be484a5cfb353cfb08aee953809cfa8e25138c9230bece70d35342e3230312e33322e3133311468c506d43816d1a8389c860c1d162be44d1e777cfb4e1ffb05a3fb8f30002087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d6789182087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d6789180130a64af69f8174bf8a7f8398cba7e349b62b2fd2ecf61446a10a16a9e71cd67c8f2eb725d4cbd1c2081a5200cc2016e74a0e33352e3136372e3134352e313439149b9cdbfe3568cc0b37f136b00a634c75653f05e3fb4e1ffb05a3fb8f30002088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f2088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f01308e7b3b55424d3b06d8aa1c4ca3af5de96b8af54adb860d22f6b857cf836038ef9b711dc3a1c47cb0f0bd31e553904de50b35322e33332e32382e343714711fd9548ae19b2e91c7a9b4067000467ccdd2b5fb4e1ffb05a3fb8f3000208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f234208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f23401308d003529801f709ead3ed646f86e29eefd3563fd10eb48c5814929970e48691da65986d9d798cb084b085327e3e2210e0d35322e31332e3133322e313436145bdbf34a0dad860c6ec71523ae39373325225cc1fb4e1ffb05a3fb8f3000208b8d1193afd22e538ce0c9fb50fee155d0f6176ca68e65da684c5dce2d1e0815208b8d1193afd22e538ce0c9fb50fee155d0f6176ca68e65da684c5dce2d1e08150130b5d56dbd660b42d9c79be5d94912c86001c7c0118508e90ea71113f81b7ef412a56ed53bf635f8463495db374ad105b20c35322e33342e3134342e353014a0a0e17bfe82a484fefe348b7569a6d77d29d2c2fb4e1ffb05a3fb8f3000208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc4208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc4013091557309e257281d2910e7914b80bb4cfa78a74530d8c0a54b088ca244380e3f248f95e3d716b2e8043d0e74d3c362460c35322e34332e38362e32333114337b7fb5d2c531825c3e0123ac3354018085b302fb4e1ffb05a3fb8f3000208e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c0208e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c00130874f7d242343c8a96748110a12dbb246a3fcc772e25e1ad6a7dcae333ae99c205c9a85ef73441097f8b88ff2253bdb680c35322e38392e3135342e3438146d57707c196e06487d326094c964f258f5b77c35fb4e1ffb05a3fb8f30002091bbce94c34ebde0d099c0a2cb7635c0c31425ebabcec644f4f1a0854bfa605d2091bbce94c34ebde0d099c0a2cb7635c0c31425ebabcec644f4f1a0854bfa605d01308bc0894362a31bb574775fb54873f6f4b231df32e8142bc2f18839bfb54422df8f6295590fc51fab1c27040c2b34b51a0c35322e34302e3231392e34311402aa69f8ef6666e7cad6d9323755a0ef3c1b6bd9fb4e1ffb05a3fb8f3000209712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df54209712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df5401308ccc32d24ef5626ddcd2b28e9736617e4674fe9108af2a67f3ab4d88857d8e932cad9abe7f37a81cb42e00b5a23924c20d33352e38322e3139372e31393714ed1131823bcea23ac78af8c01e4d24683d6ecf88fb4e1ffb05a3fb8f300020ba8ce1dc72857b4168e33272571df7fbaf84c316dfe48217addcf6595e25421620ba8ce1dc72857b4168e33272571df7fbaf84c316dfe48217addcf6595e2542160130b12d38eb7f5de9b145b9f9e14e97e0e624ff91e61c9ef66e50366df4439e1f5936494e12b4216352919679e4d759c0e00d35322e34322e3230322e3132381462e0104ce0aafc1f06bde37c73702fe84b307f05fb4e1ffb05a3fb8f300020c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba820c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba801308654755a932cc93d963a2d802cabae33db99828405fe03a3838f73a05ae88c0733f9170f77f92b66d3291d7c8675dc6b0d35342e3231332e3230342e383514fdae7cdf38811659ce9481975b326a5d07236bc5fb4e1ffb05a3fb8f300020f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba786399038120f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba7863990381013084980eccb0d1103b2ca52e2180e96c26b287ff0dbe1038e495bb6e77bfe339a5890f7d3c10c40aa756c72c1349dd27be0d35322e31332e3235302e31383214fe2d4798df3e9b41a6823bc0b3f020478e87925dfb4e1ffb05a3fb8f30003087087556f670d7bc712e350d4b5afbf9ef0224447ac207a2ee76e040c468605d8b9cabbabe620278d01a8da30ee7026b20000000b6ebee5a8f801f7b66c32a3454b12513c76ab58b121a4e9c579bcd4e8c0020000000b6ebee5a8f801f7b66c32a3454b12513c76ab58b121a4e9c579bcd4e8c00fc00110988192005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea82005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea80130a703c06bb0c06e1af4dc7396d1f19f8959c5a56e99717647a91b65cc8aa543fd700b7ec561e3050ef9e868104f3c6b790d35322e32342e3132342e313632148feb00404d6f765856c95e587b2523a365bc7258fb4e1ffb05a3fb8f30002012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a22012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a20130a324d275351dad7c90e3a9a94f6efbd8ea6b865f34a09a20fb82ed55134c45982f798e26a4e80e1fb0a8c50813b86d280e3231322e32342e3130332e31343914c1161c96de3dae28cd7f20ff8c2aa7b94b866d76fb4e1ffb05a3fb8f300020143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f11320143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f1130130ad5a967b04be6266f12c245cb62edb02873a37f72d2de496d8d1f1cc92905786be7aa7c24c7941ca80b11675f44fd48f0d33352e3136342e32332e32343514b5f25f8f70cf8d05c2d2970bdf186c994431d84efb4e1ffb05a3fb8f30002020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c2020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c01308aa08b567a66acb8356e54f688575350edd7f2d9efa7e1c9a3897011f83caa03a7deac4146592b8ca527263332e4d0840c33352e38352e32312e3137391435d9eb76397d05b43b5cd8da7ccfa8408bc89ab3fb4e1ffb05a3fb8f3000202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb0130ac508c0feb7d9b38e641298a71e6f10f3a8a30fa42c01856b6cfded1b452d802b6196e4b66602ea8cfafae03a37e57a00d35342e3134392e33332e313637141ffbf1d32541dcb8f5555305295704a9ff9adc24fb4e1ffb05a3fb8f30002040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d2040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d0130940b0a12e79c9c2b8889e6cf84f1d2c64277587471a8eecd7abec19c9f9a558791199c8fc6f07abd9b0459527e9625fd0c35322e31302e3232392e3131143e8b10646ee9d6c28d75c280b357dd3a9ae9f962fb4e1ffb05a3fb8f3000205b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a23205b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a230130b32376df0aa47f5bc41d383d00ba171eae10e87eb5dec1ffa8cb498dacdf98462e3f562e8c4901acde83da95d0d454780d33352e3136352e35302e31323614f460a07a2b0dc932e1d8ff2dee2b984ac415dcebfb4e1ffb05a3fb8f3000205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef436205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef4360130a50f2b1af92150d81387393503c15a485518b8375578b721e52bd84b1124e9a265e985681eb76e15c6a478d5b529f5ed0d34342e3233392e33392e31353314972a33056d57359de8acfa4fb8b29dc1c14f76b8fb4e1ffb05a3fb8f30002061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb2061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb0130b4c6e2f51056f17dc3cce763ea819a77770edc7122c39e68a0d8629ea8f36937468761952d9fca90a7c2c7f78f8b85770c35322e31322e3137362e3930147ada3e486409b39c94a0833c8d782f35bc24e96afb4e1ffb05a3fb8f3000206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e52863320966206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e52863320966013080266707faf18059f5040438724f9f46921d5f600dd837dc1aea1f08f3dc2a7d12247a3ca0feff3ebde6855e221503c30e34342e3232382e3234322e31383114c374f016ea61e76aab79b8bb95a1ba0e6e3eee6ffb4e1ffb05a3fb8f3000207135069642e1a72807a383fb5a14b9af6758292fee53fe2a7f7ac6f528bf7019207135069642e1a72807a383fb5a14b9af6758292fee53fe2a7f7ac6f528bf70190130976e8ee23029edeaae45c1737a2ab7e440145fc145a2410aff4a0735335c6d73320c6dc5425449c00458fe214f10f0c70d35342e3138392e3136342e333914f9956e70daffa263e8cf29fa6557b7b630a595a8fb4e1ffb05a3fb8f30002085f15a31d3838293a9c1d72a1a0fa21e66110ce20878bd4c1024c4ae1d5be8242085f15a31d3838293a9c1d72a1a0fa21e66110ce20878bd4c1024c4ae1d5be8240130b311bf70f84c1332681af71fe6d684933be12807de50e6a3eed260d649891e3b409c75fff910381db43f5e5cc3eec96b0d35342e3230312e33322e3133311468c506d43816d1a8389c860c1d162be44d1e777cfb4e1ffb05a3fb8f30002087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d6789182087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d6789180130a57c0905911f436b83521d87ef76513c25e1c7177050b62ce038c0c485c7d7286b86822a1db20ee50e14c7bbca115e2f0e33352e3136372e3134352e313439149b9cdbfe3568cc0b37f136b00a634c75653f05e3fb4e1ffb05a3fb8f30002088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f2088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f0130b642e74f36ecfc0984377db6259e30010d61d4b4b309668af59718d570c8f9f253baa2ac00dc6041b12c79b77eb646af0b35322e33332e32382e343714711fd9548ae19b2e91c7a9b4067000467ccdd2b5fb4e1ffb05a3fb8f3000208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f234208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f2340130b5f63cf0be89e8e46af538e71e1a98d33173f83131572bff054c5fc3855fdd8f4d2359b91f164a082f65232960a6bb8b0d35322e31332e3133322e313436145bdbf34a0dad860c6ec71523ae39373325225cc1fb4e1ffb05a3fb8f3000208b8d1193afd22e538ce0c9fb50fee155d0f6176ca68e65da684c5dce2d1e0815208b8d1193afd22e538ce0c9fb50fee155d0f6176ca68e65da684c5dce2d1e08150130a201efcc30db8655f99be543485d749efaaf164e222370f9dd50a3ecb0a428a07a16f7d9f9d7be5182e0974f926405f20c35322e33342e3134342e353014a0a0e17bfe82a484fefe348b7569a6d77d29d2c2fb4e1ffb05a3fb8f3000208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc4208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc40130b54279aae2009b7651c29c87d6a00bace24b0112690401ac71c935ba79c637ebab1dd1b6c8e5dd70c002846b87c580430c35322e34332e38362e32333114337b7fb5d2c531825c3e0123ac3354018085b302fb4e1ffb05a3fb8f3000208eca4bcbb3a124ab283afd42dad3bdb2077b3809659788a0f1daffce5b9f001f208eca4bcbb3a124ab283afd42dad3bdb2077b3809659788a0f1daffce5b9f001f01308b55bd02dd900fc8f513373fc4275474e3c64f489463a2d167d93eb81cd6e41c54f06554d280ac71bd80b12f93c386e30d35342e36382e3233352e32303114c075993a8336f93a13bb7bbb7e0e89928be4aafbfb4e1ffb05a3fb8f30002091bbce94c34ebde0d099c0a2cb7635c0c31425ebabcec644f4f1a0854bfa605d2091bbce94c34ebde0d099c0a2cb7635c0c31425ebabcec644f4f1a0854bfa605d0130b847c83b10bac91203bd0ffbdee778131803975467db2d0889defa1f4671ab9207d330e944772f7ac7b7b05c04b59d5c0c35322e34302e3231392e34311402aa69f8ef6666e7cad6d9323755a0ef3c1b6bd9fb4e1ffb05a3fb8f3000209cb04f271ba050132c00cc5838fb69e77bc55b5689f9d2d850dc528935f8145c209cb04f271ba050132c00cc5838fb69e77bc55b5689f9d2d850dc528935f8145c0130a76f59dad02d335374150895bcda911a1c8f77fc49938a60fc913ac1b01dca06eaf67c34145efa68f02d8ed5aacf60980c33342e3231342e34382e36381462e960a3f6b650feed98a266b3ccdf6e363562cffb4e1ffb05a3fb8f300020ba8ce1dc72857b4168e33272571df7fbaf84c316dfe48217addcf6595e25421620ba8ce1dc72857b4168e33272571df7fbaf84c316dfe48217addcf6595e2542160130a510330a7be7301de1872e3fb864ce4a6d9e6faad494159a5a29476c7110dc8fa10921c63d3e93f4181845c7fabd2c7f0d35322e34322e3230322e3132381462e0104ce0aafc1f06bde37c73702fe84b307f05fb4e1ffb05a3fb8f300020bbfd0ac1977011267a7032641ef5487fe15a4de798faa485b156fb3b7eb0acb820bbfd0ac1977011267a7032641ef5487fe15a4de798faa485b156fb3b7eb0acb80130b29f367ac0aa1c4a047507c039c7b406ddd38256b55fcc636ed00badef8240e50905b96d810b2eefc2ff0a82d0434a5f0c33352e38322e34392e31393614dbbebbc52a5bae21b818e0487311041c91b2683bfb4e1ffb05a3fb8f300020c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba820c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba80130b04058eaf4d337cdc95914d77fbc9f22be1dadd3fce162bf4bf3f67372383b7cc287eef82634ba9f69182c9e615b83ce0d35342e3231332e3230342e383514fdae7cdf38811659ce9481975b326a5d07236bc5fb4e1ffb05a3fb8f300020f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba786399038120f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba78639903810130a190aad82d3d99b77ba2ec6019caa72e82575fb72cf05d9eb97ef0f8d3f088c7350fbeb19c8a13c95f7e68073ef64fb20d35322e31332e3235302e31383214fe2d4798df3e9b41a6823bc0b3f020478e87925dfb4e1ffb05a3fb8f300020ff261d2c1c76907a2ad8aeb6c5611796f03b5cbd88ae92452a4727e13f4f4ac920ff261d2c1c76907a2ad8aeb6c5611796f03b5cbd88ae92452a4727e13f4f4ac901308d0c12f1fc8ee77846153c42e78d2e420358de9478058680d0c1019b33e65b1da765e8a369620e06145a573f46d5d6a70d35342e3138372e31342e3233321467e05b1b52c7c896adf20035036fe1d30dcefc9cfb4e1ffb05a3fb8f300030a6ece569edd51a503a2cfe5b2be0e24c33179ee6f8afa152d185b19f87fccb8ce5ecff6300fc600bd0418b69dcc3f4f220000000e78672b7a792c03ffc5e06c6512e0ae64c4b5410a2e41b6b871036e5d30020000000e78672b7a792c03ffc5e06c6512e0ae64c4b5410a2e41b6b871036e5d300fc00110970192005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea82005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea8000d35322e32342e3132342e313632148feb00404d6f765856c95e587b2523a365bc7258fb4e1ffb05a3fb8f30002012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a22012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a2000e3231322e32342e3130332e31343914c1161c96de3dae28cd7f20ff8c2aa7b94b866d76fb4e1ffb05a3fb8f30002020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c2020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c000c33352e38352e32312e3137391435d9eb76397d05b43b5cd8da7ccfa8408bc89ab3fb4e1ffb05a3fb8f30002039741ad83dd791e1e738f19edae82d6c0322972e6a455981424da3769b3dbd4a2039741ad83dd791e1e738f19edae82d6c0322972e6a455981424da3769b3dbd4a000e33352e3136332e3134342e32333014ec7bf3b9bc72eda38c80bb7cf16e294e763e56b4fb4e1ffb05a3fb8f30002040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d2040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d000c35322e31302e3232392e3131143e8b10646ee9d6c28d75c280b357dd3a9ae9f962fb4e1ffb05a3fb8f30002061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb2061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb000c35322e31322e3137362e3930147ada3e486409b39c94a0833c8d782f35bc24e96afb4e1ffb05a3fb8f3000206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e52863320966206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e52863320966000e34342e3232382e3234322e31383114c374f016ea61e76aab79b8bb95a1ba0e6e3eee6ffb4e1ffb05a3fb8f3000207135069642e1a72807a383fb5a14b9af6758292fee53fe2a7f7ac6f528bf7019207135069642e1a72807a383fb5a14b9af6758292fee53fe2a7f7ac6f528bf7019000d35342e3138392e3136342e333914f9956e70daffa263e8cf29fa6557b7b630a595a8fb4e1ffb05a3fb8f300020754b89dae8db20fc4cee5e3adb07b146d7efe508a66fa0a8e1094675b9daa35e20754b89dae8db20fc4cee5e3adb07b146d7efe508a66fa0a8e1094675b9daa35e000c34342e3233332e34342e39351446d938862af6d9a291e26c0048177db2892a710bfb4e1ffb05a3fb8f3000207718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be4290207718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be4290000d34342e3232372e3133372e3737140498ade3c80045c2a7520e921180ae1c39da5c57fb4e1ffb05a3fb8f30002085f15a31d3838293a9c1d72a1a0fa21e66110ce20878bd4c1024c4ae1d5be8242085f15a31d3838293a9c1d72a1a0fa21e66110ce20878bd4c1024c4ae1d5be824000d35342e3230312e33322e3133311468c506d43816d1a8389c860c1d162be44d1e777cfb4e1ffb05a3fb8f30002087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d6789182087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d678918000e33352e3136372e3134352e313439149b9cdbfe3568cc0b37f136b00a634c75653f05e3fb4e1ffb05a3fb8f30002088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f2088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f000b35322e33332e32382e343714711fd9548ae19b2e91c7a9b4067000467ccdd2b5fb4e1ffb05a3fb8f3000208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f234208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f234000d35322e31332e3133322e313436145bdbf34a0dad860c6ec71523ae39373325225cc1fb4e1ffb05a3fb8f3000208b8d1193afd22e538ce0c9fb50fee155d0f6176ca68e65da684c5dce2d1e0815208b8d1193afd22e538ce0c9fb50fee155d0f6176ca68e65da684c5dce2d1e0815000c35322e33342e3134342e353014a0a0e17bfe82a484fefe348b7569a6d77d29d2c2fb4e1ffb05a3fb8f3000208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc4208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc4000c35322e34332e38362e32333114337b7fb5d2c531825c3e0123ac3354018085b302fb4e1ffb05a3fb8f3000208e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c0208e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c0000c35322e38392e3135342e3438146d57707c196e06487d326094c964f258f5b77c35fb4e1ffb05a3fb8f3000208eca4bcbb3a124ab283afd42dad3bdb2077b3809659788a0f1daffce5b9f001f208eca4bcbb3a124ab283afd42dad3bdb2077b3809659788a0f1daffce5b9f001f000d35342e36382e3233352e32303114c075993a8336f93a13bb7bbb7e0e89928be4aafbfb4e1ffb05a3fb8f30002091bbce94c34ebde0d099c0a2cb7635c0c31425ebabcec644f4f1a0854bfa605d2091bbce94c34ebde0d099c0a2cb7635c0c31425ebabcec644f4f1a0854bfa605d000c35322e34302e3231392e34311402aa69f8ef6666e7cad6d9323755a0ef3c1b6bd9fb4e1ffb05a3fb8f30002098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba0920962098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba092096000c34342e3233322e3139362e3614d6ece912cbf02627a4efc3dd37e6833cf3671551fb4e1ffb05a3fb8f3000209cb04f271ba050132c00cc5838fb69e77bc55b5689f9d2d850dc528935f8145c209cb04f271ba050132c00cc5838fb69e77bc55b5689f9d2d850dc528935f8145c000c33342e3231342e34382e36381462e960a3f6b650feed98a266b3ccdf6e363562cffb4e1ffb05a3fb8f300020b3b5748571b60fe9ad112715d6a51725d6e5a52a9c3af5fd36a1724cf50d862f20b3b5748571b60fe9ad112715d6a51725d6e5a52a9c3af5fd36a1724cf50d862f000b35322e34332e31332e39321441b308f737ca9e39f67b553158903198a88c516efb4e1ffb05a3fb8f300020c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba820c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba8000d35342e3231332e3230342e383514fdae7cdf38811659ce9481975b326a5d07236bc5fb4e1ffb05a3fb8f300020d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f8920d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f89000d34342e3234302e39382e313032147034f0d3853c5351fb8e0ffd3c1daf12c51c2d89fb4e1ffb05a3fb8f300020f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba786399038120f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba7863990381000d35322e31332e3235302e31383214fe2d4798df3e9b41a6823bc0b3f020478e87925dfb4e1ffb05a3fb8f300030952b5f1b8f31ad775ba1420d465e22b9db941245eacc8d738bee5b8e4704771d461a42949afe7e2ae91d49e795cf9ba22000000021160aae5b92562c94a5d6735c5dff3a92aa0a8d9b02aa0c614ca7154a002000000021160aae5b92562c94a5d6735c5dff3a92aa0a8d9b02aa0c614ca7154a00fc00110958192005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea82005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea8000d35322e32342e3132342e313632148feb00404d6f765856c95e587b2523a365bc7258fb4e1ffb05a3fb8f30002012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a22012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a2000e3231322e32342e3130332e31343914c1161c96de3dae28cd7f20ff8c2aa7b94b866d76fb4e1ffb05a3fb8f300020143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f11320143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f113000d33352e3136342e32332e32343514b5f25f8f70cf8d05c2d2970bdf186c994431d84efb4e1ffb05a3fb8f30002020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c2020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c000c33352e38352e32312e3137391435d9eb76397d05b43b5cd8da7ccfa8408bc89ab3fb4e1ffb05a3fb8f3000202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb000d35342e3134392e33332e313637141ffbf1d32541dcb8f5555305295704a9ff9adc24fb4e1ffb05a3fb8f30002039741ad83dd791e1e738f19edae82d6c0322972e6a455981424da3769b3dbd4a2039741ad83dd791e1e738f19edae82d6c0322972e6a455981424da3769b3dbd4a000e33352e3136332e3134342e32333014ec7bf3b9bc72eda38c80bb7cf16e294e763e56b4fb4e1ffb05a3fb8f30002040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d2040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d000c35322e31302e3232392e3131143e8b10646ee9d6c28d75c280b357dd3a9ae9f962fb4e1ffb05a3fb8f3000205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef436205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef436000d34342e3233392e33392e31353314972a33056d57359de8acfa4fb8b29dc1c14f76b8fb4e1ffb05a3fb8f30002061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb2061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb000c35322e31322e3137362e3930147ada3e486409b39c94a0833c8d782f35bc24e96afb4e1ffb05a3fb8f3000206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e52863320966206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e52863320966000e34342e3232382e3234322e31383114c374f016ea61e76aab79b8bb95a1ba0e6e3eee6ffb4e1ffb05a3fb8f3000207718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be4290207718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be4290000d34342e3232372e3133372e3737140498ade3c80045c2a7520e921180ae1c39da5c57fb4e1ffb05a3fb8f30002088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f2088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f000b35322e33332e32382e343714711fd9548ae19b2e91c7a9b4067000467ccdd2b5fb4e1ffb05a3fb8f3000208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f234208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f234000d35322e31332e3133322e313436145bdbf34a0dad860c6ec71523ae39373325225cc1fb4e1ffb05a3fb8f3000208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc4208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc4000c35322e34332e38362e32333114337b7fb5d2c531825c3e0123ac3354018085b302fb4e1ffb05a3fb8f3000208e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c0208e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c0000c35322e38392e3135342e3438146d57707c196e06487d326094c964f258f5b77c35fb4e1ffb05a3fb8f3000208eca4bcbb3a124ab283afd42dad3bdb2077b3809659788a0f1daffce5b9f001f208eca4bcbb3a124ab283afd42dad3bdb2077b3809659788a0f1daffce5b9f001f000d35342e36382e3233352e32303114c075993a8336f93a13bb7bbb7e0e89928be4aafbfb4e1ffb05a3fb8f30002091bbce94c34ebde0d099c0a2cb7635c0c31425ebabcec644f4f1a0854bfa605d2091bbce94c34ebde0d099c0a2cb7635c0c31425ebabcec644f4f1a0854bfa605d000c35322e34302e3231392e34311402aa69f8ef6666e7cad6d9323755a0ef3c1b6bd9fb4e1ffb05a3fb8f3000209712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df54209712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df54000d33352e38322e3139372e31393714ed1131823bcea23ac78af8c01e4d24683d6ecf88fb4e1ffb05a3fb8f300020b3b5748571b60fe9ad112715d6a51725d6e5a52a9c3af5fd36a1724cf50d862f20b3b5748571b60fe9ad112715d6a51725d6e5a52a9c3af5fd36a1724cf50d862f000b35322e34332e31332e39321441b308f737ca9e39f67b553158903198a88c516efb4e1ffb05a3fb8f300020ba8ce1dc72857b4168e33272571df7fbaf84c316dfe48217addcf6595e25421620ba8ce1dc72857b4168e33272571df7fbaf84c316dfe48217addcf6595e254216000d35322e34322e3230322e3132381462e0104ce0aafc1f06bde37c73702fe84b307f05fb4e1ffb05a3fb8f300020bbfd0ac1977011267a7032641ef5487fe15a4de798faa485b156fb3b7eb0acb820bbfd0ac1977011267a7032641ef5487fe15a4de798faa485b156fb3b7eb0acb8000c33352e38322e34392e31393614dbbebbc52a5bae21b818e0487311041c91b2683bfb4e1ffb05a3fb8f300020c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba820c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba8000d35342e3231332e3230342e383514fdae7cdf38811659ce9481975b326a5d07236bc5fb4e1ffb05a3fb8f300020d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f8920d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f89000d34342e3234302e39382e313032147034f0d3853c5351fb8e0ffd3c1daf12c51c2d89fb4e1ffb05a3fb8f300020f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba786399038120f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba7863990381000d35322e31332e3235302e31383214fe2d4798df3e9b41a6823bc0b3f020478e87925dfb4e1ffb05a3fb8f300020ff261d2c1c76907a2ad8aeb6c5611796f03b5cbd88ae92452a4727e13f4f4ac920ff261d2c1c76907a2ad8aeb6c5611796f03b5cbd88ae92452a4727e13f4f4ac9000d35342e3138372e31342e3233321467e05b1b52c7c896adf20035036fe1d30dcefc9cfb4e1ffb05a3fb8f300030afe32c814088749bdf90012b78f156d0bea19ba06a56d4d6a22e80fbe9444d64c5b1545b55bb0f1c92fd79a1eae4e29d20000001561ac909f7762f03b801661c0ab46943d603d2883b36535ad5f6344cb80020000001561ac909f7762f03b801661c0ab46943d603d2883b36535ad5f6344cb800fc00110940192005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea82005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea8000d35322e32342e3132342e313632148feb00404d6f765856c95e587b2523a365bc7258fb4e1ffb05a3fb8f30002012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a22012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a2000e3231322e32342e3130332e31343914c1161c96de3dae28cd7f20ff8c2aa7b94b866d76fb4e1ffb05a3fb8f300020143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f11320143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f113000d33352e3136342e32332e32343514b5f25f8f70cf8d05c2d2970bdf186c994431d84efb4e1ffb05a3fb8f3000202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb000d35342e3134392e33332e313637141ffbf1d32541dcb8f5555305295704a9ff9adc24fb4e1ffb05a3fb8f30002039741ad83dd791e1e738f19edae82d6c0322972e6a455981424da3769b3dbd4a2039741ad83dd791e1e738f19edae82d6c0322972e6a455981424da3769b3dbd4a000e33352e3136332e3134342e32333014ec7bf3b9bc72eda38c80bb7cf16e294e763e56b4fb4e1ffb05a3fb8f30002040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d2040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d000c35322e31302e3232392e3131143e8b10646ee9d6c28d75c280b357dd3a9ae9f962fb4e1ffb05a3fb8f3000205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef436205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef436000d34342e3233392e33392e31353314972a33056d57359de8acfa4fb8b29dc1c14f76b8fb4e1ffb05a3fb8f30002061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb2061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb000c35322e31322e3137362e3930147ada3e486409b39c94a0833c8d782f35bc24e96afb4e1ffb05a3fb8f3000206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e52863320966206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e52863320966000e34342e3232382e3234322e31383114c374f016ea61e76aab79b8bb95a1ba0e6e3eee6ffb4e1ffb05a3fb8f300020754b89dae8db20fc4cee5e3adb07b146d7efe508a66fa0a8e1094675b9daa35e20754b89dae8db20fc4cee5e3adb07b146d7efe508a66fa0a8e1094675b9daa35e000c34342e3233332e34342e39351446d938862af6d9a291e26c0048177db2892a710bfb4e1ffb05a3fb8f3000207718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be4290207718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be4290000d34342e3232372e3133372e3737140498ade3c80045c2a7520e921180ae1c39da5c57fb4e1ffb05a3fb8f30002085f15a31d3838293a9c1d72a1a0fa21e66110ce20878bd4c1024c4ae1d5be8242085f15a31d3838293a9c1d72a1a0fa21e66110ce20878bd4c1024c4ae1d5be824000d35342e3230312e33322e3133311468c506d43816d1a8389c860c1d162be44d1e777cfb4e1ffb05a3fb8f30002088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f2088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f000b35322e33332e32382e343714711fd9548ae19b2e91c7a9b4067000467ccdd2b5fb4e1ffb05a3fb8f3000208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f234208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f234000d35322e31332e3133322e313436145bdbf34a0dad860c6ec71523ae39373325225cc1fb4e1ffb05a3fb8f3000208b8d1193afd22e538ce0c9fb50fee155d0f6176ca68e65da684c5dce2d1e0815208b8d1193afd22e538ce0c9fb50fee155d0f6176ca68e65da684c5dce2d1e0815000c35322e33342e3134342e353014a0a0e17bfe82a484fefe348b7569a6d77d29d2c2fb4e1ffb05a3fb8f3000208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc4208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc4000c35322e34332e38362e32333114337b7fb5d2c531825c3e0123ac3354018085b302fb4e1ffb05a3fb8f3000208e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c0208e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c0000c35322e38392e3135342e3438146d57707c196e06487d326094c964f258f5b77c35fb4e1ffb05a3fb8f3000208eca4bcbb3a124ab283afd42dad3bdb2077b3809659788a0f1daffce5b9f001f208eca4bcbb3a124ab283afd42dad3bdb2077b3809659788a0f1daffce5b9f001f000d35342e36382e3233352e32303114c075993a8336f93a13bb7bbb7e0e89928be4aafbfb4e1ffb05a3fb8f3000209712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df54209712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df54000d33352e38322e3139372e31393714ed1131823bcea23ac78af8c01e4d24683d6ecf88fb4e1ffb05a3fb8f30002098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba0920962098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba092096000c34342e3233322e3139362e3614d6ece912cbf02627a4efc3dd37e6833cf3671551fb4e1ffb05a3fb8f300020b3b5748571b60fe9ad112715d6a51725d6e5a52a9c3af5fd36a1724cf50d862f20b3b5748571b60fe9ad112715d6a51725d6e5a52a9c3af5fd36a1724cf50d862f000b35322e34332e31332e39321441b308f737ca9e39f67b553158903198a88c516efb4e1ffb05a3fb8f300020bbfd0ac1977011267a7032641ef5487fe15a4de798faa485b156fb3b7eb0acb820bbfd0ac1977011267a7032641ef5487fe15a4de798faa485b156fb3b7eb0acb8000c33352e38322e34392e31393614dbbebbc52a5bae21b818e0487311041c91b2683bfb4e1ffb05a3fb8f300020c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba820c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba8000d35342e3231332e3230342e383514fdae7cdf38811659ce9481975b326a5d07236bc5fb4e1ffb05a3fb8f300020d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f8920d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f89000d34342e3234302e39382e313032147034f0d3853c5351fb8e0ffd3c1daf12c51c2d89fb4e1ffb05a3fb8f300020f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba786399038120f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba7863990381000d35322e31332e3235302e31383214fe2d4798df3e9b41a6823bc0b3f020478e87925dfb4e1ffb05a3fb8f3000308759c691df7b1ba670491acca647d6b73b22357fdd6bc666f9ff12e0b05386c9b448b2565acc758f8200037776704fd120000000c9c3825db4b9a1751e94ef41634a33e2df66e8f9ddcd56dd435232f48f0020000000c9c3825db4b9a1751e94ef41634a33e2df66e8f9ddcd56dd435232f48f00fc00110928192005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea82005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea80130924ad656b10ed6bb91d0e3d628dcdb849ea66d25e377f2371bfd491c40e74788c859ad024da1d5cf4949834b7e79f2ee0d35322e32342e3132342e313632148feb00404d6f765856c95e587b2523a365bc7258fb4e1ffb05a3fb8f30002012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a22012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a20130aac9ede908775e57d5b1bce4b6b7fc2b1c50c8ac8353232620e979fb669b1af81690c2739bc60f35a8958764496946280e3231322e32342e3130332e31343914c1161c96de3dae28cd7f20ff8c2aa7b94b866d76fb4e1ffb05a3fb8f300020143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f11320143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f113013083ce4eb1e593141192a2453ca0ed4cfe462af4c2f564099e1defb49bc7febbb62b5f2dfd1e64e9a57e65354df6327d1c0d33352e3136342e32332e32343514b5f25f8f70cf8d05c2d2970bdf186c994431d84efb4e1ffb05a3fb8f30002020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c2020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c0130adc8f74781a33cc6773cdce95d58a3c2cbe36a40c4f971987226a8027787d5ddf82bfb51dbd48023b5cfacb152029c970c33352e38352e32312e3137391435d9eb76397d05b43b5cd8da7ccfa8408bc89ab3fb4e1ffb05a3fb8f3000202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb0130b5ac90f960f003df563d7d8dc350e26e218efbc993f9cb52a59290579da516e83a69b56dea7be3f0d29f6266b9caa2b50d35342e3134392e33332e313637141ffbf1d32541dcb8f5555305295704a9ff9adc24fb4e1ffb05a3fb8f3000205b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a23205b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a230130aa742f3326d38b837ef98fb9736469642f166926f7961859c5d01dd49bfc66904b49edabf995b8e0a3b6389387614a2c0d33352e3136352e35302e31323614f460a07a2b0dc932e1d8ff2dee2b984ac415dcebfb4e1ffb05a3fb8f3000205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef436205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef4360130976d7f5ed93385d48d42851930ed313180a8a9be816085db2763dfcc233c8cf07a78ce2f3e90a48ae48f3c6203f3766f0d34342e3233392e33392e31353314972a33056d57359de8acfa4fb8b29dc1c14f76b8fb4e1ffb05a3fb8f30002061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb2061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb013083dd7663c78d21bda4652a64bd714dc888a76b8e60da2d3cccb5530b73722ec81e67815668af7a71ed484347b60586320c35322e31322e3137362e3930147ada3e486409b39c94a0833c8d782f35bc24e96afb4e1ffb05a3fb8f3000206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e52863320966206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e52863320966013083bcb86817efb833569855c921422c2bf1b091def65d4ad85e19e668720c238bbfed72b10f46c2a4018acdf170007d080e34342e3232382e3234322e31383114c374f016ea61e76aab79b8bb95a1ba0e6e3eee6ffb4e1ffb05a3fb8f3000207135069642e1a72807a383fb5a14b9af6758292fee53fe2a7f7ac6f528bf7019207135069642e1a72807a383fb5a14b9af6758292fee53fe2a7f7ac6f528bf70190130971f8a04797eaaa9b3b9dd3d693cd306521e1cf500952419a34b1977d086a3df182a700b02872dff3cb290a04208a9c50d35342e3138392e3136342e333914f9956e70daffa263e8cf29fa6557b7b630a595a8fb4e1ffb05a3fb8f300020754b89dae8db20fc4cee5e3adb07b146d7efe508a66fa0a8e1094675b9daa35e20754b89dae8db20fc4cee5e3adb07b146d7efe508a66fa0a8e1094675b9daa35e013081b9ffd0d23314602ccc44eaaa8f2c40583963c2100106341900d1280850b4e84f7a31950c2279d43202348c3c857f330c34342e3233332e34342e39351446d938862af6d9a291e26c0048177db2892a710bfb4e1ffb05a3fb8f3000207718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be4290207718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be42900130acd93627366f7f42ef27d343f9c57a8db738e45db943c10fcd26f960a1a23a8ea25d4a3202a7ed7cc194b75f47d35c100d34342e3232372e3133372e3737140498ade3c80045c2a7520e921180ae1c39da5c57fb4e1ffb05a3fb8f30002087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d6789182087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d6789180130b6c4b5c7ce4c90a8f2c49558894d88400f82cc709c639c0331ae0e576f37548d54bdad91e49445ec9e68881cb392e9220e33352e3136372e3134352e313439149b9cdbfe3568cc0b37f136b00a634c75653f05e3fb4e1ffb05a3fb8f30002088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f2088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f013099419898f07b65df952ce60727b69493cae876e624d268710df77535afd899f6a02cdcba635b8ad3cc9842ae140e7fc90b35322e33332e32382e343714711fd9548ae19b2e91c7a9b4067000467ccdd2b5fb4e1ffb05a3fb8f3000208e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c0208e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c0013083d49c9014f9cf4a73ec9166c321ec4dffe9d7610ae2690141470fa2906dc8b8b0b65c38b881f4c87d5ba273a36476460c35322e38392e3135342e3438146d57707c196e06487d326094c964f258f5b77c35fb4e1ffb05a3fb8f30002091bbce94c34ebde0d099c0a2cb7635c0c31425ebabcec644f4f1a0854bfa605d2091bbce94c34ebde0d099c0a2cb7635c0c31425ebabcec644f4f1a0854bfa605d0130a5b2b14324b75a8f03645434878fd9b78326125ca9a5479b3a63fc9c3e269f07e0914101476f0f7a81ce74db682df2330c35322e34302e3231392e34311402aa69f8ef6666e7cad6d9323755a0ef3c1b6bd9fb4e1ffb05a3fb8f30002098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba0920962098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba0920960130a910e926ae8a2a9ac7130053e40ff33f8a6b05f465619eaeea156550ef956c663797d5096f7db4eb1db5bf328ba963440c34342e3233322e3139362e3614d6ece912cbf02627a4efc3dd37e6833cf3671551fb4e1ffb05a3fb8f3000209cb04f271ba050132c00cc5838fb69e77bc55b5689f9d2d850dc528935f8145c209cb04f271ba050132c00cc5838fb69e77bc55b5689f9d2d850dc528935f8145c0130ad328fa477cf797787c60fb91c2cb603896d04de19515bfa94fcf6dcd943a5dfe09f3341ca7ca0872cd8da59e68d72b10c33342e3231342e34382e36381462e960a3f6b650feed98a266b3ccdf6e363562cffb4e1ffb05a3fb8f300020b3b5748571b60fe9ad112715d6a51725d6e5a52a9c3af5fd36a1724cf50d862f20b3b5748571b60fe9ad112715d6a51725d6e5a52a9c3af5fd36a1724cf50d862f0130b123e19529c06f90a4c62c60fa86a64681ad3d93a0ada42ebc496f1643448819bed2a94b1ff5e5ff32ca3a9589fc37590b35322e34332e31332e39321441b308f737ca9e39f67b553158903198a88c516efb4e1ffb05a3fb8f300020ba8ce1dc72857b4168e33272571df7fbaf84c316dfe48217addcf6595e25421620ba8ce1dc72857b4168e33272571df7fbaf84c316dfe48217addcf6595e2542160130a3e517adf8333dfc0ae60504cfaa02dc1387a5c2d59cbf8d9cf07a84bedbea0b0b40821152f18a17529e2bf1fece004c0d35322e34322e3230322e3132381462e0104ce0aafc1f06bde37c73702fe84b307f05fb4e1ffb05a3fb8f300020bbfd0ac1977011267a7032641ef5487fe15a4de798faa485b156fb3b7eb0acb820bbfd0ac1977011267a7032641ef5487fe15a4de798faa485b156fb3b7eb0acb80130b345c75d74bd26b8c95f30eb1e23a2a892b507269f5f5416faefd7f4ce9e721210246dc074f6b2a42129a1f8dce17dfc0c33352e38322e34392e31393614dbbebbc52a5bae21b818e0487311041c91b2683bfb4e1ffb05a3fb8f300020c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba820c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba80130a556c58a4ceca86bf6e7c7cec01ecea90d9ddabc76eaa64de7e15d71ec4463d0712ddb7fc27afcf9328348e9b4555d320d35342e3231332e3230342e383514fdae7cdf38811659ce9481975b326a5d07236bc5fb4e1ffb05a3fb8f300020d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f8920d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f890130b97076e5170bae287a101f96a2a57c43d88d28f24c74eb3b5f19dbe8e9b0556abcaed75ff70b48f0a742afbdc32f368f0d34342e3234302e39382e313032147034f0d3853c5351fb8e0ffd3c1daf12c51c2d89fb4e1ffb05a3fb8f300020f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba786399038120f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba78639903810130b720e1f87cdd506feece2e0778a91d716671c7c7f19e766e5e13541074c9e053406f59816566cf4a67239d9e8101ff8d0d35322e31332e3235302e31383214fe2d4798df3e9b41a6823bc0b3f020478e87925dfb4e1ffb05a3fb8f300020ff261d2c1c76907a2ad8aeb6c5611796f03b5cbd88ae92452a4727e13f4f4ac920ff261d2c1c76907a2ad8aeb6c5611796f03b5cbd88ae92452a4727e13f4f4ac90130875fe89958bd413087ee35b99293b326b5b505482a25a3bfab04e5ac59ee2c0687c01febceffc2cc50cab76bce3cad510d35342e3138372e31342e3233321467e05b1b52c7c896adf20035036fe1d30dcefc9cfb4e1ffb05a3fb8f300030875f8e47eb3ef86e27ad3a5b0003289cdf445aed6ee7ab0f21c24e595c1f19fe9d969fdc6c5a6eeb66d712bf75846cf720000000b91e2a2fe9ab4c3899dc7d2d85c9e00e068603afe59058d5415a84773d0020000000b91e2a2fe9ab4c3899dc7d2d85c9e00e068603afe59058d5415a84773d00fc00110910192005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea82005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea8000d35322e32342e3132342e313632148feb00404d6f765856c95e587b2523a365bc7258fb4e1ffb05a3fb8f30002012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a22012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a2000e3231322e32342e3130332e31343914c1161c96de3dae28cd7f20ff8c2aa7b94b866d76fb4e1ffb05a3fb8f30002020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c2020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c000c33352e38352e32312e3137391435d9eb76397d05b43b5cd8da7ccfa8408bc89ab3fb4e1ffb05a3fb8f3000202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb000d35342e3134392e33332e313637141ffbf1d32541dcb8f5555305295704a9ff9adc24fb4e1ffb05a3fb8f30002039741ad83dd791e1e738f19edae82d6c0322972e6a455981424da3769b3dbd4a2039741ad83dd791e1e738f19edae82d6c0322972e6a455981424da3769b3dbd4a000e33352e3136332e3134342e32333014ec7bf3b9bc72eda38c80bb7cf16e294e763e56b4fb4e1ffb05a3fb8f30002040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d2040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d000c35322e31302e3232392e3131143e8b10646ee9d6c28d75c280b357dd3a9ae9f962fb4e1ffb05a3fb8f3000205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef436205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef436000d34342e3233392e33392e31353314972a33056d57359de8acfa4fb8b29dc1c14f76b8fb4e1ffb05a3fb8f30002061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb2061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb000c35322e31322e3137362e3930147ada3e486409b39c94a0833c8d782f35bc24e96afb4e1ffb05a3fb8f3000206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e52863320966206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e52863320966000e34342e3232382e3234322e31383114c374f016ea61e76aab79b8bb95a1ba0e6e3eee6ffb4e1ffb05a3fb8f300020754b89dae8db20fc4cee5e3adb07b146d7efe508a66fa0a8e1094675b9daa35e20754b89dae8db20fc4cee5e3adb07b146d7efe508a66fa0a8e1094675b9daa35e000c34342e3233332e34342e39351446d938862af6d9a291e26c0048177db2892a710bfb4e1ffb05a3fb8f3000207718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be4290207718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be4290000d34342e3232372e3133372e3737140498ade3c80045c2a7520e921180ae1c39da5c57fb4e1ffb05a3fb8f30002087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d6789182087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d678918000e33352e3136372e3134352e313439149b9cdbfe3568cc0b37f136b00a634c75653f05e3fb4e1ffb05a3fb8f3000208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f234208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f234000d35322e31332e3133322e313436145bdbf34a0dad860c6ec71523ae39373325225cc1fb4e1ffb05a3fb8f3000208b8d1193afd22e538ce0c9fb50fee155d0f6176ca68e65da684c5dce2d1e0815208b8d1193afd22e538ce0c9fb50fee155d0f6176ca68e65da684c5dce2d1e0815000c35322e33342e3134342e353014a0a0e17bfe82a484fefe348b7569a6d77d29d2c2fb4e1ffb05a3fb8f3000208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc4208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc4000c35322e34332e38362e32333114337b7fb5d2c531825c3e0123ac3354018085b302fb4e1ffb05a3fb8f3000208e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c0208e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c0000c35322e38392e3135342e3438146d57707c196e06487d326094c964f258f5b77c35fb4e1ffb05a3fb8f3000209712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df54209712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df54000d33352e38322e3139372e31393714ed1131823bcea23ac78af8c01e4d24683d6ecf88fb4e1ffb05a3fb8f30002098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba0920962098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba092096000c34342e3233322e3139362e3614d6ece912cbf02627a4efc3dd37e6833cf3671551fb4e1ffb05a3fb8f3000209cb04f271ba050132c00cc5838fb69e77bc55b5689f9d2d850dc528935f8145c209cb04f271ba050132c00cc5838fb69e77bc55b5689f9d2d850dc528935f8145c000c33342e3231342e34382e36381462e960a3f6b650feed98a266b3ccdf6e363562cffb4e1ffb05a3fb8f300020b3b5748571b60fe9ad112715d6a51725d6e5a52a9c3af5fd36a1724cf50d862f20b3b5748571b60fe9ad112715d6a51725d6e5a52a9c3af5fd36a1724cf50d862f000b35322e34332e31332e39321441b308f737ca9e39f67b553158903198a88c516efb4e1ffb05a3fb8f300020ba8ce1dc72857b4168e33272571df7fbaf84c316dfe48217addcf6595e25421620ba8ce1dc72857b4168e33272571df7fbaf84c316dfe48217addcf6595e254216000d35322e34322e3230322e3132381462e0104ce0aafc1f06bde37c73702fe84b307f05fb4e1ffb05a3fb8f300020bbfd0ac1977011267a7032641ef5487fe15a4de798faa485b156fb3b7eb0acb820bbfd0ac1977011267a7032641ef5487fe15a4de798faa485b156fb3b7eb0acb8000c33352e38322e34392e31393614dbbebbc52a5bae21b818e0487311041c91b2683bfb4e1ffb05a3fb8f300020c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba820c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba8000d35342e3231332e3230342e383514fdae7cdf38811659ce9481975b326a5d07236bc5fb4e1ffb05a3fb8f300020d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f8920d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f89000d34342e3234302e39382e313032147034f0d3853c5351fb8e0ffd3c1daf12c51c2d89fb4e1ffb05a3fb8f300020f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba786399038120f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba7863990381000d35322e31332e3235302e31383214fe2d4798df3e9b41a6823bc0b3f020478e87925dfb4e1ffb05a3fb8f300030811c99ba6830312caf298444f81f4cf1007ddb18aafc86c3b07709355078e76b5c6dc4986f90e3ab4c49eb3277e8f05820000000503099f9f7fc49ca9350ce1951c09325670b8b459f3a55ebe6811f13e10020000000503099f9f7fc49ca9350ce1951c09325670b8b459f3a55ebe6811f13e100fc001108f8192005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea82005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea80130ade4f9ac0bf7a220bd7931db817cfe4a1948c980bda2b9fa47f388094c433ae05f4ca9336b866f1f0ad1df11d84d9aa40d35322e32342e3132342e313632148feb00404d6f765856c95e587b2523a365bc7258fb4e1ffb05a3fb8f30002012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a22012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a20130a0aae269176730e5448cb9f9ad9112e5d8ecf10e7cd60749573096bce1f92a8c54ab971b159b181b2e77d91f03a163420e3231322e32342e3130332e31343914c1161c96de3dae28cd7f20ff8c2aa7b94b866d76fb4e1ffb05a3fb8f300020143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f11320143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f11301308f158752c7ec2792ed365eb5452ffb7284baa0daaccabc0a373fe93e4437ac914e99fa3585ee13b2233ea957a7b875f30d33352e3136342e32332e32343514b5f25f8f70cf8d05c2d2970bdf186c994431d84efb4e1ffb05a3fb8f3000202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb0130a61711a34d191e0c70f0f357c9ef6c12f0933031d2d5364ad77f2d2139232bba8450d3dd947923639669dbcb2cdc77000d35342e3134392e33332e313637141ffbf1d32541dcb8f5555305295704a9ff9adc24fb4e1ffb05a3fb8f30002039741ad83dd791e1e738f19edae82d6c0322972e6a455981424da3769b3dbd4a2039741ad83dd791e1e738f19edae82d6c0322972e6a455981424da3769b3dbd4a013095fe0a1e5cec63ada905498014c403049ee0fac572b21ff7d9bfc64e0c58bfc04ec29aa4567fcaf9af431b8925d001e40e33352e3136332e3134342e32333014ec7bf3b9bc72eda38c80bb7cf16e294e763e56b4fb4e1ffb05a3fb8f30002040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d2040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d0130b504e0534e88aeb51c3a3f7ca3d6668753ad6502218f173eee918767286822d99f4ee80bf7c07e717d2b107745d63fd70c35322e31302e3232392e3131143e8b10646ee9d6c28d75c280b357dd3a9ae9f962fb4e1ffb05a3fb8f3000205b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a23205b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a230130a16d937e47da149a8c71d34c552c98585faafa99c2986397fc8455e45adf1573dd4535806a8a084b7fa34bbeea9253a80d33352e3136352e35302e31323614f460a07a2b0dc932e1d8ff2dee2b984ac415dcebfb4e1ffb05a3fb8f3000205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef436205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef4360130a547a8172171c9ddaeae2eb272e92184a751a53d51476684342c06f6968c32dd9a23742df2e9194613934c5e58ef7e620d34342e3233392e33392e31353314972a33056d57359de8acfa4fb8b29dc1c14f76b8fb4e1ffb05a3fb8f30002061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb2061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb0130a5374524f11f982d5bc082567c60fa9c1bc5be1510eeb42b0f6c2810c8e6da16e609603ce456f17df3636c5407ca5d160c35322e31322e3137362e3930147ada3e486409b39c94a0833c8d782f35bc24e96afb4e1ffb05a3fb8f3000206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e52863320966206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e528633209660130972f1c4070d037808f22be8a28ec2b12a4737a70d803498b39b9c1cd5f060a3c14b8682c484517e66b10f8a339e1f1900e34342e3232382e3234322e31383114c374f016ea61e76aab79b8bb95a1ba0e6e3eee6ffb4e1ffb05a3fb8f3000207135069642e1a72807a383fb5a14b9af6758292fee53fe2a7f7ac6f528bf7019207135069642e1a72807a383fb5a14b9af6758292fee53fe2a7f7ac6f528bf70190130843e716b0c02fff03ab196cf7807890ea4135b104698007370fbaad68eda6926588a2252c8716fbcff2f2e18de92da4e0d35342e3138392e3136342e333914f9956e70daffa263e8cf29fa6557b7b630a595a8fb4e1ffb05a3fb8f300020754b89dae8db20fc4cee5e3adb07b146d7efe508a66fa0a8e1094675b9daa35e20754b89dae8db20fc4cee5e3adb07b146d7efe508a66fa0a8e1094675b9daa35e0130ace190d30463989a24b517945d94dc45894993e493cd32be40bc8b0d0946801af5be6ce4cd0bdf1189436bf085ed96df0c34342e3233332e34342e39351446d938862af6d9a291e26c0048177db2892a710bfb4e1ffb05a3fb8f3000207718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be4290207718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be429001308a393458f5158095c5b380e1bc1a19ebc9060d6322422bcebf338382de0accb2d24783a33ad9f0bd06f0b522ce9b2dfa0d34342e3232372e3133372e3737140498ade3c80045c2a7520e921180ae1c39da5c57fb4e1ffb05a3fb8f30002085f15a31d3838293a9c1d72a1a0fa21e66110ce20878bd4c1024c4ae1d5be8242085f15a31d3838293a9c1d72a1a0fa21e66110ce20878bd4c1024c4ae1d5be8240130868eea59f1f6748680f0513feec4c06fbc416c3a37a45494fc1a8aab3982c3c0dd206af2d6bdfd28f3f88be4fd3b2f080d35342e3230312e33322e3133311468c506d43816d1a8389c860c1d162be44d1e777cfb4e1ffb05a3fb8f30002087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d6789182087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d6789180130862184496a4ed2deea7ad130bca509f8ca0ebda660ab7b5189f3c40e8f3e62c665e0031ccc7bffdc32a5fb921a022e930e33352e3136372e3134352e313439149b9cdbfe3568cc0b37f136b00a634c75653f05e3fb4e1ffb05a3fb8f30002088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f2088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f013097f08edddfd65e13651bf00b0f3485e2d81a477f45d9b46bdda40a416178cb0fb16199a2f8e969cfb37ed37c234a9cd20b35322e33332e32382e343714711fd9548ae19b2e91c7a9b4067000467ccdd2b5fb4e1ffb05a3fb8f3000208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f234208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f2340130a8e6429fd5e3e981383c03637e707d3b313fbc1606a8023a40e48bf071e45db9b451a3fd2760d28d75a43417e958e7830d35322e31332e3133322e313436145bdbf34a0dad860c6ec71523ae39373325225cc1fb4e1ffb05a3fb8f3000208e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c0208e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c00130b2fad499c0eced2e83c79ea1c2b03ec399b2fb7411fe2a744979277b75d401b039dbcece4d9d3c0e035c339901d7a6330c35322e38392e3135342e3438146d57707c196e06487d326094c964f258f5b77c35fb4e1ffb05a3fb8f3000208eca4bcbb3a124ab283afd42dad3bdb2077b3809659788a0f1daffce5b9f001f208eca4bcbb3a124ab283afd42dad3bdb2077b3809659788a0f1daffce5b9f001f0130990f8dfc1e064ccb5c1dae252c390fc0ca792e730cada8ca1bd9a0b87a22bd08692827b19e614886125734d25bdbbb1c0d35342e36382e3233352e32303114c075993a8336f93a13bb7bbb7e0e89928be4aafbfb4e1ffb05a3fb8f30002091bbce94c34ebde0d099c0a2cb7635c0c31425ebabcec644f4f1a0854bfa605d2091bbce94c34ebde0d099c0a2cb7635c0c31425ebabcec644f4f1a0854bfa605d013082743c519fc81d9496a0b6b5dea3010daebd5d07e7819fdca3a7b9763c9cc96554f45243e4f3dd3bd550556630ea0e4c0c35322e34302e3231392e34311402aa69f8ef6666e7cad6d9323755a0ef3c1b6bd9fb4e1ffb05a3fb8f3000209cb04f271ba050132c00cc5838fb69e77bc55b5689f9d2d850dc528935f8145c209cb04f271ba050132c00cc5838fb69e77bc55b5689f9d2d850dc528935f8145c0130a87c6b9f8d841bac3ad961c636f6112def93e8f1444da8ed44fb45eb8b8f76c64c4eb56f2d6a4c73bfc7bebbe388bff60c33342e3231342e34382e36381462e960a3f6b650feed98a266b3ccdf6e363562cffb4e1ffb05a3fb8f300020c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba820c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba80130821654a83db6fda5da7398f8caf30cec37f572cbb06ab2c16087b5a10f5bc02ecb9b577282b56be8efd15dd743d3a49a0d35342e3231332e3230342e383514fdae7cdf38811659ce9481975b326a5d07236bc5fb4e1ffb05a3fb8f300020d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f8920d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f890130b95ef4d4f00f59a98abefd80d26838fa5e6ebbbf7f53708cea1e4bb5bc29b4db8df9a2b212915bce9c6c9243335695150d34342e3234302e39382e313032147034f0d3853c5351fb8e0ffd3c1daf12c51c2d89fb4e1ffb05a3fb8f300020f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba786399038120f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba7863990381013082799988066eb079178da860dea57e31e6908b1395b7ff048078d62c21a8c1a8d3356aaedfa3946054ef8803b04d82700d35322e31332e3235302e31383214fe2d4798df3e9b41a6823bc0b3f020478e87925dfb4e1ffb05a3fb8f300020ff261d2c1c76907a2ad8aeb6c5611796f03b5cbd88ae92452a4727e13f4f4ac920ff261d2c1c76907a2ad8aeb6c5611796f03b5cbd88ae92452a4727e13f4f4ac90130b99743b53234d7c72f44f464edf915d5ede43f8864b8c5224c7b2ff1f3d3afe29ee1313bd1d24eb20ea9436fd59d0e5c0d35342e3138372e31342e3233321467e05b1b52c7c896adf20035036fe1d30dcefc9cfb4e1ffb05a3fb8f300030b5da956497c5d4f39fca6f5b1c03f6c05992d1d654f226cf79019376aa64597614dd570190e16958718b9941acd718a1200000004d43bd84ac6be16b9b7e352b3e9905e1337d7d4d6dd0b8a0ff92a89f1c00200000004d43bd84ac6be16b9b7e352b3e9905e1337d7d4d6dd0b8a0ff92a89f1c00fc001108e01920143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f11320143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f11301308b460fcb3cc7ee796175caa6f052d3bdc69e818d74112b2ab846c918669bf638c7ee40ed205995a29033acc18d59ddb80d33352e3136342e32332e32343514b5f25f8f70cf8d05c2d2970bdf186c994431d84efb4e1ffb05a3fb8f30002020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c2020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c0130ae54bad16d671bc5c15961a2831600a97d2d45656a05d3ff23e1dfbca7b7ffaf3f6849b963d7c6da2207bc45f82149180c33352e38352e32312e3137391435d9eb76397d05b43b5cd8da7ccfa8408bc89ab3fb4e1ffb05a3fb8f30002039741ad83dd791e1e738f19edae82d6c0322972e6a455981424da3769b3dbd4a2039741ad83dd791e1e738f19edae82d6c0322972e6a455981424da3769b3dbd4a0130a754aef784851c7b33edc0672fdc4acbbb5b68d18cc599d5ea0f90dc18f1d0f9b240852300bb4897a840c3ad75ad92720e33352e3136332e3134342e32333014ec7bf3b9bc72eda38c80bb7cf16e294e763e56b4fb4e1ffb05a3fb8f30002040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d2040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d0130997667cb4a12ed8a163f798d3adb2ce58fd6893a43f6076aaa4361fb72252e0b199e4ec1ce8a5f7c28cd4569f22811760c35322e31302e3232392e3131143e8b10646ee9d6c28d75c280b357dd3a9ae9f962fb4e1ffb05a3fb8f3000205b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a23205b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a2301308f7f1b73f23c47a901bc0fcafee3390f1814082c6ba58fbe8ff3bfb2d8ae59e166b9bf4cafeb73ab84f8c92bf025d5680d33352e3136352e35302e31323614f460a07a2b0dc932e1d8ff2dee2b984ac415dcebfb4e1ffb05a3fb8f30002061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb2061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb0130af907e5db8f2044c7439fcf769805a1cb6d6fe054dcc0143f1fc016887fa3e5d118d00ee3915a17232d4d3399fe72d5b0c35322e31322e3137362e3930147ada3e486409b39c94a0833c8d782f35bc24e96afb4e1ffb05a3fb8f3000206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e52863320966206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e528633209660130a09832716c65b1546e347932ef900e805a201ce2dcc0f63f9a4134f0f63e1f1a8fe21c73c8bb611f8be20e39534e083c0e34342e3232382e3234322e31383114c374f016ea61e76aab79b8bb95a1ba0e6e3eee6ffb4e1ffb05a3fb8f3000207135069642e1a72807a383fb5a14b9af6758292fee53fe2a7f7ac6f528bf7019207135069642e1a72807a383fb5a14b9af6758292fee53fe2a7f7ac6f528bf70190130b08d9d26e9e4be1c5126efd8ddb59794fd773a02842acc3d3da4bac6c0c617e6d7252eb8b6cf39c31768046f428d2ce20d35342e3138392e3136342e333914f9956e70daffa263e8cf29fa6557b7b630a595a8fb4e1ffb05a3fb8f300020754b89dae8db20fc4cee5e3adb07b146d7efe508a66fa0a8e1094675b9daa35e20754b89dae8db20fc4cee5e3adb07b146d7efe508a66fa0a8e1094675b9daa35e013097532b6be5b41d239a8645d8d64afb5cef699c098a67b4a9937821bc1dd20b5bdee4c1e426c5a7f8052eb3952190cfa70c34342e3233332e34342e39351446d938862af6d9a291e26c0048177db2892a710bfb4e1ffb05a3fb8f3000207718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be4290207718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be42900130ab556ce9c2e2700225559ec1959d45c83253cb296dce2b6b33cbfe9b874dbfe9dbe904fa2dcea902415fc1ecfc39474a0d34342e3232372e3133372e3737140498ade3c80045c2a7520e921180ae1c39da5c57fb4e1ffb05a3fb8f30002085f15a31d3838293a9c1d72a1a0fa21e66110ce20878bd4c1024c4ae1d5be8242085f15a31d3838293a9c1d72a1a0fa21e66110ce20878bd4c1024c4ae1d5be8240130b54b2015b5e21346dbc940cc84bf51b4e6ff48dde45eee42fda6fd2e52ecb69a3a59583d4f07abcb116277878de85d590d35342e3230312e33322e3133311468c506d43816d1a8389c860c1d162be44d1e777cfb4e1ffb05a3fb8f30002087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d6789182087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d6789180130b07b9e19df45bab4886e1725af1ceb51c9ec8d6b7de345396996a5d541f0360fde8b4cd19e09c01fb82bf36460c9ce060e33352e3136372e3134352e313439149b9cdbfe3568cc0b37f136b00a634c75653f05e3fb4e1ffb05a3fb8f3000208b8d1193afd22e538ce0c9fb50fee155d0f6176ca68e65da684c5dce2d1e0815208b8d1193afd22e538ce0c9fb50fee155d0f6176ca68e65da684c5dce2d1e08150130a2578e7fa88cdd15a5eaf6f627d5180fb2c5867b1a63435e6cc69087b219012d39fdd00bed9c975a4692ef5b55212ba20c35322e33342e3134342e353014a0a0e17bfe82a484fefe348b7569a6d77d29d2c2fb4e1ffb05a3fb8f3000208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc4208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc4013088f04eb6df9fd7339e63ceb4eebc70de145b4013dd6df67e22de136983e4065a5afe874be3352522a801c2c20a7f90cd0c35322e34332e38362e32333114337b7fb5d2c531825c3e0123ac3354018085b302fb4e1ffb05a3fb8f3000208e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c0208e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c0013089ef74e90f14b3548986e55bf793a404f6c6c51d37ac118fe09f8869c71fd25aeba2f6c6951cf41fd5ca240907a760690c35322e38392e3135342e3438146d57707c196e06487d326094c964f258f5b77c35fb4e1ffb05a3fb8f3000208eca4bcbb3a124ab283afd42dad3bdb2077b3809659788a0f1daffce5b9f001f208eca4bcbb3a124ab283afd42dad3bdb2077b3809659788a0f1daffce5b9f001f01309796d4499f58876deedf4904e96de7c6f308aea15e7f1495db988e1dd70c5703fc3338127dd6fbaa638fd09d9a2495440d35342e36382e3233352e32303114c075993a8336f93a13bb7bbb7e0e89928be4aafbfb4e1ffb05a3fb8f30002091bbce94c34ebde0d099c0a2cb7635c0c31425ebabcec644f4f1a0854bfa605d2091bbce94c34ebde0d099c0a2cb7635c0c31425ebabcec644f4f1a0854bfa605d0130a28553f210bcac6400cfae3cf36294b373acdd4d66b92bd30c0c7230f5cc080e6546eb961f6432e51e0d88d1449185f70c35322e34302e3231392e34311402aa69f8ef6666e7cad6d9323755a0ef3c1b6bd9fb4e1ffb05a3fb8f3000209712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df54209712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df540130a04038f4955841d76aae11e2c4b51c4efbf4bbc4c5af0a6132d9d8d5134ea141ed2e791cff5056981015b9eb03f96d790d33352e38322e3139372e31393714ed1131823bcea23ac78af8c01e4d24683d6ecf88fb4e1ffb05a3fb8f30002098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba0920962098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba0920960130a883d1e8398a8cf66ff2c695422b1caaaa7df58efc0637b38b48621c2e3357d25618b6e54335a311fba33c1a60fa8c540c34342e3233322e3139362e3614d6ece912cbf02627a4efc3dd37e6833cf3671551fb4e1ffb05a3fb8f3000209cb04f271ba050132c00cc5838fb69e77bc55b5689f9d2d850dc528935f8145c209cb04f271ba050132c00cc5838fb69e77bc55b5689f9d2d850dc528935f8145c0130aab78e91fd352d70ed1c717c4d69726dc6cfeba4c6047040fb52cb0b6eb06aacba7c11e780f17e29da8886d5207d7d2d0c33342e3231342e34382e36381462e960a3f6b650feed98a266b3ccdf6e363562cffb4e1ffb05a3fb8f300020b3b5748571b60fe9ad112715d6a51725d6e5a52a9c3af5fd36a1724cf50d862f20b3b5748571b60fe9ad112715d6a51725d6e5a52a9c3af5fd36a1724cf50d862f013092d3231b5c4ca6ad3957123950f519f38d5a03a65161eadfddbe218afc12a9845ada84209325149769949c8870a25d4a0b35322e34332e31332e39321441b308f737ca9e39f67b553158903198a88c516efb4e1ffb05a3fb8f300020ba8ce1dc72857b4168e33272571df7fbaf84c316dfe48217addcf6595e25421620ba8ce1dc72857b4168e33272571df7fbaf84c316dfe48217addcf6595e254216013083f05b849c08d76c2b699210c780112ef7ee1d76ae57cb216afc4a0a97ebe696e723f4c0f885a5329c8efd2727ee9f9f0d35322e34322e3230322e3132381462e0104ce0aafc1f06bde37c73702fe84b307f05fb4e1ffb05a3fb8f300020bbfd0ac1977011267a7032641ef5487fe15a4de798faa485b156fb3b7eb0acb820bbfd0ac1977011267a7032641ef5487fe15a4de798faa485b156fb3b7eb0acb8013086283e5e604d24192e21ce9a909afbc49045776ee5145aeccdedd7b52e4a0ebb184ca3c9d837f2d4d6a1b0e91104fd2b0c33352e38322e34392e31393614dbbebbc52a5bae21b818e0487311041c91b2683bfb4e1ffb05a3fb8f300020c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba820c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba801308c9d01a4115483815958f4a125dfbf62d7ec434070e27d4aa68900709d9e6c178b1d4109fc9b6de2c7485cfc0e8597f30d35342e3231332e3230342e383514fdae7cdf38811659ce9481975b326a5d07236bc5fb4e1ffb05a3fb8f300020d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f8920d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f890130a4ed1dc172bcaed49303cf1fc09c8b7307cd3a6ce73813c7ad4771f165e11c091a5f6b89f1faaca3596e70dd23a81cdd0d34342e3234302e39382e313032147034f0d3853c5351fb8e0ffd3c1daf12c51c2d89fb4e1ffb05a3fb8f30003094c59ea9aec7e4e60572a74af7ccb95127fb165f09adc32178ad80e4bc58f63161d9f02833a9980c23db78640cd67e8320000000d4b6e3c3b706bd8941885c8fb46dee63ffbe116888d8892b7f53a0a0da0020000000d4b6e3c3b706bd8941885c8fb46dee63ffbe116888d8892b7f53a0a0da00fc001108c8192005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea82005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea80130a05b8b13fdcc6917524714eb250387f6330775cb97dbc6724a73246a480c1504469a777d03478de1d3bb535baeef5c7f0d35322e32342e3132342e313632148feb00404d6f765856c95e587b2523a365bc7258fb4e1ffb05a3fb8f30002012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a22012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a20130a726d33bb1b575eef918031911618076c72b24b7c00e0f093feb2c2f14d1fd83d3ef4e4351d329afa693264644dd220c0e3231322e32342e3130332e31343914c1161c96de3dae28cd7f20ff8c2aa7b94b866d76fb4e1ffb05a3fb8f300020143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f11320143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f1130130af03210533c4b3b2200dbc65961590904b19e8132fc759c0bd6ab38c88078ce9f1ded55e4c46e8f000f5744e5927fcd80d33352e3136342e32332e32343514b5f25f8f70cf8d05c2d2970bdf186c994431d84efb4e1ffb05a3fb8f30002020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c2020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c0130a7740f3302e48e88527030630d7c776cd4f0738a0413fa26b1acd1053e24eb42aad8c606f24b226fdae48a25db7b62d00c33352e38352e32312e3137391435d9eb76397d05b43b5cd8da7ccfa8408bc89ab3fb4e1ffb05a3fb8f3000202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb0130967b38cebd11a41fc82acb6739a375e5459c51804ed58be7e7eb384481dc6631ebb32ad78ed5c21624ea6af1202ef03a0d35342e3134392e33332e313637141ffbf1d32541dcb8f5555305295704a9ff9adc24fb4e1ffb05a3fb8f30002039741ad83dd791e1e738f19edae82d6c0322972e6a455981424da3769b3dbd4a2039741ad83dd791e1e738f19edae82d6c0322972e6a455981424da3769b3dbd4a01308b5e034afabfc19434e05306ed05e611efba5eb2b6e199114266d60f315a9d3aba5e913d20dd060478d58667cda4c6290e33352e3136332e3134342e32333014ec7bf3b9bc72eda38c80bb7cf16e294e763e56b4fb4e1ffb05a3fb8f30002040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d2040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d01309398faf325dbac5f84b53d53dc0118e187ef1cfab954a1f41e5474d893e779fad2cf9206df0f28ba31938a07543ae1c00c35322e31302e3232392e3131143e8b10646ee9d6c28d75c280b357dd3a9ae9f962fb4e1ffb05a3fb8f3000205b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a23205b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a230130abc8583618c7a847a00a0d2164a28ebdcead0d7a23df00553f9e0fdca2a8049f0504d9a4d472131e671de8fc1d4e99960d33352e3136352e35302e31323614f460a07a2b0dc932e1d8ff2dee2b984ac415dcebfb4e1ffb05a3fb8f3000205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef436205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef4360130a6d31c009e09302a3d19f5dd1c56ad3e8b9205a1a23c49e93721599d6623be423bf85f72aa3ada53bcbfe0d9da1a93fc0d34342e3233392e33392e31353314972a33056d57359de8acfa4fb8b29dc1c14f76b8fb4e1ffb05a3fb8f30002061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb2061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb0130a0ff36d3273675e24d02d0f3e4083f99388b3561333abbeea8a46ad84e06e536f595382ca44aefc370ca7d64ef88b5b90c35322e31322e3137362e3930147ada3e486409b39c94a0833c8d782f35bc24e96afb4e1ffb05a3fb8f300020754b89dae8db20fc4cee5e3adb07b146d7efe508a66fa0a8e1094675b9daa35e20754b89dae8db20fc4cee5e3adb07b146d7efe508a66fa0a8e1094675b9daa35e0130b56355b74fbe62ca05d14bdf3d1896465cd5b41e897da999c08ad39e7a4fafe32c46fee3536dce92db32347a0fcebc5e0c34342e3233332e34342e39351446d938862af6d9a291e26c0048177db2892a710bfb4e1ffb05a3fb8f30002085f15a31d3838293a9c1d72a1a0fa21e66110ce20878bd4c1024c4ae1d5be8242085f15a31d3838293a9c1d72a1a0fa21e66110ce20878bd4c1024c4ae1d5be8240130ae8ea031f0c46ea23fe6c45199e9e089283dd1003d6eeac30541b20b45989756052e943853f83e015e7060fdffae94c80d35342e3230312e33322e3133311468c506d43816d1a8389c860c1d162be44d1e777cfb4e1ffb05a3fb8f30002087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d6789182087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d678918013088c024a804b1cd694b087c8648789fbb3b4653784a1bbfab88db8afc2c8fb87cfdff5aed6eb6561d301e4cff2336c9060e33352e3136372e3134352e313439149b9cdbfe3568cc0b37f136b00a634c75653f05e3fb4e1ffb05a3fb8f30002088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f2088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f013093aae6cf15f02ce0939bad8f654d85a724c70b8bbffeccb336bcdf7cae780057ed4e579d25511d3dc8c79700f7902c8a0b35322e33332e32382e343714711fd9548ae19b2e91c7a9b4067000467ccdd2b5fb4e1ffb05a3fb8f3000208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f234208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f23401308596fa5844b472ff7e62d6a083c2c37dbced2d8279d617392f79329539a30606f24f072a6f89119f8580c031867c97750d35322e31332e3133322e313436145bdbf34a0dad860c6ec71523ae39373325225cc1fb4e1ffb05a3fb8f3000208b8d1193afd22e538ce0c9fb50fee155d0f6176ca68e65da684c5dce2d1e0815208b8d1193afd22e538ce0c9fb50fee155d0f6176ca68e65da684c5dce2d1e0815013095e700df712726032efacc015206cc8905c6a262d2a09f39c0c4947186778dad1c7e7c0bbd994a828ebf7381297e5a090c35322e33342e3134342e353014a0a0e17bfe82a484fefe348b7569a6d77d29d2c2fb4e1ffb05a3fb8f3000208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc4208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc40130acc4a68d6a4a1a02f015c149e62943d6e2d03699bba71092bb324abdc68a78cd05d28f570ed6517edb456a38cbc20b860c35322e34332e38362e32333114337b7fb5d2c531825c3e0123ac3354018085b302fb4e1ffb05a3fb8f30002091bbce94c34ebde0d099c0a2cb7635c0c31425ebabcec644f4f1a0854bfa605d2091bbce94c34ebde0d099c0a2cb7635c0c31425ebabcec644f4f1a0854bfa605d0130a95f3700cbeb45904f7c09df31e142193aa9b277ec80da5458136a0b4c4c1bf26eb9b8f420b788779d2d92a5db71a4360c35322e34302e3231392e34311402aa69f8ef6666e7cad6d9323755a0ef3c1b6bd9fb4e1ffb05a3fb8f3000209712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df54209712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df540130944d564c8f03423d7923069004a0ff33a9febb61295158fb95ada04745f8070410e4f22041d6c5ab1227c8ca7ec5d2b00d33352e38322e3139372e31393714ed1131823bcea23ac78af8c01e4d24683d6ecf88fb4e1ffb05a3fb8f30002098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba0920962098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba09209601308b6c3bd1b6d10f712dcdc043287608210e64357e44076bae3f630063f27a00134479b06655305d4dfc14d783c610ef190c34342e3233322e3139362e3614d6ece912cbf02627a4efc3dd37e6833cf3671551fb4e1ffb05a3fb8f300020ba8ce1dc72857b4168e33272571df7fbaf84c316dfe48217addcf6595e25421620ba8ce1dc72857b4168e33272571df7fbaf84c316dfe48217addcf6595e2542160130a4545d995258e0c25eaa5395cdd85aba924c7653248c79e9b6d54c5c95457f9c383aec10e9c7135910efc896a552cb400d35322e34322e3230322e3132381462e0104ce0aafc1f06bde37c73702fe84b307f05fb4e1ffb05a3fb8f300020bbfd0ac1977011267a7032641ef5487fe15a4de798faa485b156fb3b7eb0acb820bbfd0ac1977011267a7032641ef5487fe15a4de798faa485b156fb3b7eb0acb80130a963c8918e33ab77885122c7e72dc5d5ed58747b6341d055c36af803af19b674eaacfa397368cfe31e50e0458663a7700c33352e38322e34392e31393614dbbebbc52a5bae21b818e0487311041c91b2683bfb4e1ffb05a3fb8f300020c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba820c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba80130b09a36c2cd9523f2036fe71755ce02b4722467eabbe2d9606ddcaf5c1c73f8dd21c1d697c9bece75d952f13adac2b9670d35342e3231332e3230342e383514fdae7cdf38811659ce9481975b326a5d07236bc5fb4e1ffb05a3fb8f300020d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f8920d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f890130a0f49df8abdbc389ab1bbb99ca45a4268d7858301b259652dfc699795db7f35113f2d29f4c41cd0029faa88df14c549d0d34342e3234302e39382e313032147034f0d3853c5351fb8e0ffd3c1daf12c51c2d89fb4e1ffb05a3fb8f300020ff261d2c1c76907a2ad8aeb6c5611796f03b5cbd88ae92452a4727e13f4f4ac920ff261d2c1c76907a2ad8aeb6c5611796f03b5cbd88ae92452a4727e13f4f4ac90130864a2eb7c4019522c831b28bb8c84ec256556f06d90e71f05d12cebd6cc3e8a9360749637e9f7acd2c8bf08d438eaead0d35342e3138372e31342e3233321467e05b1b52c7c896adf20035036fe1d30dcefc9cfb4e1ffb05a3fb8f300030a89b8a9e053bcedea6d6c29e63526edf069639d25ec8ceb1f6f127e3259c71769f1e54d867ca5b8449c8d55c19248cd720000000ceb90097be7a897c47be4752340dab3c394e860cac4f03f7bce60caa860020000000ceb90097be7a897c47be4752340dab3c394e860cac4f03f7bce60caa8600fc001108b0192012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a22012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a2013088a4d69c5ae7263da2494237b4eb77db4cc5e59d3a3f1413a35c96684b858db2be1f22203712c93a51befaf591bd972c0e3231322e32342e3130332e31343914c1161c96de3dae28cd7f20ff8c2aa7b94b866d76fb4e1ffb05a3fb8f30002020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c2020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c0130aebaa7d29121c7845ae2aa701eea659f2d54c0151eabaf7f2069ffed57a846deb657e6376f5f5f6aed9c3060e2ffeb030c33352e38352e32312e3137391435d9eb76397d05b43b5cd8da7ccfa8408bc89ab3fb4e1ffb05a3fb8f3000202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb01308e081ac0afd47eb31e2e796c69a3cba48c4a7f5c63b71ff5ad946c6b193bd0c921fe3ae922eb0e8d5c6123907ca66ba60d35342e3134392e33332e313637141ffbf1d32541dcb8f5555305295704a9ff9adc24fb4e1ffb05a3fb8f3000205b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a23205b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a230130a1814ef35a03c54d6ea3170d794a4dd10bd6d49aea8fe03d1607a240c94083dceb3a69e1dad6ec2f3f49f818b9ee462a0d33352e3136352e35302e31323614f460a07a2b0dc932e1d8ff2dee2b984ac415dcebfb4e1ffb05a3fb8f3000205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef436205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef4360130a71ce89bb92a4730672b2c774de958dd4c85dc53461cb41105d7766aabe1b473722a483585603c3323e2bf7bfb3d47e90d34342e3233392e33392e31353314972a33056d57359de8acfa4fb8b29dc1c14f76b8fb4e1ffb05a3fb8f3000206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e52863320966206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e52863320966013093bec6a7ba821198140ab7a1d0ea93a96d8a2b961f7a09b594ec768b0e99bbb74e8ef075efc43943f7f4d2c73d967ed00e34342e3232382e3234322e31383114c374f016ea61e76aab79b8bb95a1ba0e6e3eee6ffb4e1ffb05a3fb8f3000207135069642e1a72807a383fb5a14b9af6758292fee53fe2a7f7ac6f528bf7019207135069642e1a72807a383fb5a14b9af6758292fee53fe2a7f7ac6f528bf70190130b8de15f05a0fa8b4606fc7aa14fef15c5c9ac74b8b8de56761fd870c40d1fe9f0a1e0e75fd05ce23989acd3002aa54100d35342e3138392e3136342e333914f9956e70daffa263e8cf29fa6557b7b630a595a8fb4e1ffb05a3fb8f3000207718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be4290207718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be429001308cc7fc20d72fbad37344f1f22fd028878f9eb1ce487464d8bb7e88511703289b03f636cbe329bc724d1fd7a5e0e228950d34342e3232372e3133372e3737140498ade3c80045c2a7520e921180ae1c39da5c57fb4e1ffb05a3fb8f30002085f15a31d3838293a9c1d72a1a0fa21e66110ce20878bd4c1024c4ae1d5be8242085f15a31d3838293a9c1d72a1a0fa21e66110ce20878bd4c1024c4ae1d5be8240130826005c487974a10dfc6c0e9b81d36d01f7868f28cd41bcbf1c70ea40085d054e1c466f7e3481fed2c051bcf3f2e8ffb0d35342e3230312e33322e3133311468c506d43816d1a8389c860c1d162be44d1e777cfb4e1ffb05a3fb8f30002087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d6789182087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d6789180130ab28bc9b23df49c4dab9d8ed5dce583172aa6115c64f4799b640337b8f789d1776e8dd2a54fef6cb688421f4f4405f540e33352e3136372e3134352e313439149b9cdbfe3568cc0b37f136b00a634c75653f05e3fb4e1ffb05a3fb8f30002088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f2088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f0130a69dd93e9acc2df9091efdbb6af018914c02610ecba8f9a87d0072bcb905e69f2f86ef5b0a9db53fe9e0468ea8b47bf10b35322e33332e32382e343714711fd9548ae19b2e91c7a9b4067000467ccdd2b5fb4e1ffb05a3fb8f3000208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f234208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f2340130a28b26c15833231fb3e4f819803c6c197c9ca4666d6bae08c684ec87d36f087d3f7311db12c1d316aa48807a38389af70d35322e31332e3133322e313436145bdbf34a0dad860c6ec71523ae39373325225cc1fb4e1ffb05a3fb8f3000208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc4208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc401309576536e85632411c5464c48458c59388447399d11717b8fb9bd08654efaf40d2c4263574eee84333c569a01186f3cbe0c35322e34332e38362e32333114337b7fb5d2c531825c3e0123ac3354018085b302fb4e1ffb05a3fb8f3000208e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c0208e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c001308b16d7e9c9d09f4c1c68a485a842c42df657993e39852ecf497a343e2e4091244d6c54426765ed3b35fa5428c56c42060c35322e38392e3135342e3438146d57707c196e06487d326094c964f258f5b77c35fb4e1ffb05a3fb8f3000208eca4bcbb3a124ab283afd42dad3bdb2077b3809659788a0f1daffce5b9f001f208eca4bcbb3a124ab283afd42dad3bdb2077b3809659788a0f1daffce5b9f001f0130a723e5361a30fa8b8abe2ada16f6355bef4426fa666248b1e7acc1166b9c771327a26d8476219366264af23d3690c6850d35342e36382e3233352e32303114c075993a8336f93a13bb7bbb7e0e89928be4aafbfb4e1ffb05a3fb8f30002091bbce94c34ebde0d099c0a2cb7635c0c31425ebabcec644f4f1a0854bfa605d2091bbce94c34ebde0d099c0a2cb7635c0c31425ebabcec644f4f1a0854bfa605d0130a0c9d56c59553573bfd2820e100c32677a0f8acef152aec3a9ba26de65f5c00111e607f84f06054fd9715d53467923a60c35322e34302e3231392e34311402aa69f8ef6666e7cad6d9323755a0ef3c1b6bd9fb4e1ffb05a3fb8f3000209712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df54209712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df540130b7da304a882b4b043fb3c9f4b3f1a95b712348df94041029612a987e91eb902dcd12b287747776fec40ca8920df8fe5f0d33352e38322e3139372e31393714ed1131823bcea23ac78af8c01e4d24683d6ecf88fb4e1ffb05a3fb8f30002098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba0920962098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba0920960130ad516ec8101f2b352444645838f496ef4d3d692cc4f7058175c3dae158625f3a735d78da982faab68d89909392595ddd0c34342e3233322e3139362e3614d6ece912cbf02627a4efc3dd37e6833cf3671551fb4e1ffb05a3fb8f3000209cb04f271ba050132c00cc5838fb69e77bc55b5689f9d2d850dc528935f8145c209cb04f271ba050132c00cc5838fb69e77bc55b5689f9d2d850dc528935f8145c0130adf3ec0568e65c42c340b3dbc03145486abb34af601372b30a992aa66ca5800247e4e3df8c14a74933e7dcbb25f271dd0c33342e3231342e34382e36381462e960a3f6b650feed98a266b3ccdf6e363562cffb4e1ffb05a3fb8f300020b3b5748571b60fe9ad112715d6a51725d6e5a52a9c3af5fd36a1724cf50d862f20b3b5748571b60fe9ad112715d6a51725d6e5a52a9c3af5fd36a1724cf50d862f0130982d001eb233cd0e83f9112eb853945033cee76decb4618ee280bf6125fd082c179639ad92154990877e9d63a55637400b35322e34332e31332e39321441b308f737ca9e39f67b553158903198a88c516efb4e1ffb05a3fb8f300020ba8ce1dc72857b4168e33272571df7fbaf84c316dfe48217addcf6595e25421620ba8ce1dc72857b4168e33272571df7fbaf84c316dfe48217addcf6595e254216013090980e5b0b2050070d1217dbd9694f7c58f00f67827613c3b045897c7fbbdd18e30a9068fb0dff2b73c76946f979ab1c0d35322e34322e3230322e3132381462e0104ce0aafc1f06bde37c73702fe84b307f05fb4e1ffb05a3fb8f300020bbfd0ac1977011267a7032641ef5487fe15a4de798faa485b156fb3b7eb0acb820bbfd0ac1977011267a7032641ef5487fe15a4de798faa485b156fb3b7eb0acb80130ad04595d1ecbded5cc553eca173eea397c402aab1fc08eb46e38013ebb7a4f859fe1f2b32d922bab2fd628d38b9f541f0c33352e38322e34392e31393614dbbebbc52a5bae21b818e0487311041c91b2683bfb4e1ffb05a3fb8f300020d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f8920d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f8901308478b47312f9b93e9d7fc2262c286b0ff0f14edc2fab154c5b6739f849d9257a5c767c06db8e9d27ffec3084ab645fcf0d34342e3234302e39382e313032147034f0d3853c5351fb8e0ffd3c1daf12c51c2d89fb4e1ffb05a3fb8f300020f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba786399038120f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba7863990381013082e166338742861b258ef7ba49636a4f1b0febeb9a19216c758465c4e6d0822ed3f7887e9f474ed474ffad65d86496ee0d35322e31332e3235302e31383214fe2d4798df3e9b41a6823bc0b3f020478e87925dfb4e1ffb05a3fb8f300020ff261d2c1c76907a2ad8aeb6c5611796f03b5cbd88ae92452a4727e13f4f4ac920ff261d2c1c76907a2ad8aeb6c5611796f03b5cbd88ae92452a4727e13f4f4ac90130a58ac81821f89a959b0e3feb0768e7301b918a348227704a7685deb45c29196e4f4a1c2715327a127d08fb5d33a731240d35342e3138372e31342e3233321467e05b1b52c7c896adf20035036fe1d30dcefc9cfb4e1ffb05a3fb8f300030b3601dc016ef030a4707e2afd8669eaf547aed29a43a3c3f0a1f5da0f50d3ccf3717876623efaaf4fd01d56d4f19c4af200000007672f63d6d54737b0dc862fe00a4c146100e922c39e2b8349a48088d5200200000007672f63d6d54737b0dc862fe00a4c146100e922c39e2b8349a48088d5200fc00110898192012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a22012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a20130b868374061b0f68d2c262e87dc45c2bf048a9f3a9f6e91f51cb1b7fe623deb3709b439cdaec9a48519201cfaceaa3bf40e3231322e32342e3130332e31343914c1161c96de3dae28cd7f20ff8c2aa7b94b866d76fb4e1ffb05a3fb8f300020143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f11320143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f1130130b4915f6d8f4ddb2132ddeaa39ac3c7ee6a6e4e026d1a634c146c705a0a1e5303939da3957af20e322f32bdeeda3bf78c0d33352e3136342e32332e32343514b5f25f8f70cf8d05c2d2970bdf186c994431d84efb4e1ffb05a3fb8f30002020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c2020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c0130a962184d452a61d4adf3d719cda3a02eb6eaf1b7838144b2e0bd9fe8db237c14912369484d2eeed76159e9592604cf150c33352e38352e32312e3137391435d9eb76397d05b43b5cd8da7ccfa8408bc89ab3fb4e1ffb05a3fb8f3000202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb0130ad0d7d5ef86215650c75e1b9b6773db96a06835508dd97590f56f8b678313f8fe082112bb8ced61e0ae797981ede6f7a0d35342e3134392e33332e313637141ffbf1d32541dcb8f5555305295704a9ff9adc24fb4e1ffb05a3fb8f30002039741ad83dd791e1e738f19edae82d6c0322972e6a455981424da3769b3dbd4a2039741ad83dd791e1e738f19edae82d6c0322972e6a455981424da3769b3dbd4a0130adcefadcab21ba07c09f07eaedaf087adf5b674028af47d1251bdc3cfcf032b79ea71e530caccb20361b9a5c25a440460e33352e3136332e3134342e32333014ec7bf3b9bc72eda38c80bb7cf16e294e763e56b4fb4e1ffb05a3fb8f30002040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d2040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d01308abf30d7c88c6104d05ca58f08fb61c70c3d655576b559a27c2b1baff75802b6bc99fb206db5473ebabda0bdf79bad400c35322e31302e3232392e3131143e8b10646ee9d6c28d75c280b357dd3a9ae9f962fb4e1ffb05a3fb8f3000205b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a23205b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a230130ae3b8d52b37ae8382811cf52d9b29fddd46fd66c098dc03df1857a50effa2c85674e195d4ae0ac22d25df111b9289cd50d33352e3136352e35302e31323614f460a07a2b0dc932e1d8ff2dee2b984ac415dcebfb4e1ffb05a3fb8f3000205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef436205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef4360130916c39a7d78a348ce8c99f798ed84d7368601612dce992277e945ee3d34308a70e92b08635258ca6cac8539355779f0c0d34342e3233392e33392e31353314972a33056d57359de8acfa4fb8b29dc1c14f76b8fb4e1ffb05a3fb8f30002061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb2061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb0130ac518d843f4893fb55f7db299c2fba948107223385f82981dd8aa4e073731029efbb116b85ebd2912f69e8a20b898ec30c35322e31322e3137362e3930147ada3e486409b39c94a0833c8d782f35bc24e96afb4e1ffb05a3fb8f3000206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e52863320966206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e52863320966013081730f2f8ca06b21e037e1413f4e07286daa61effdddffedb1e3d37be25be8f724a2c5cedd2267bc712e09ecc864b94f0e34342e3232382e3234322e31383114c374f016ea61e76aab79b8bb95a1ba0e6e3eee6ffb4e1ffb05a3fb8f3000207135069642e1a72807a383fb5a14b9af6758292fee53fe2a7f7ac6f528bf7019207135069642e1a72807a383fb5a14b9af6758292fee53fe2a7f7ac6f528bf70190130a666c20f678260e6cf732ca2d9c335aa7eee07e9a48f15fc52bc70a0e91bbbb601235905a7c2e94f7b73d4be85684fb50d35342e3138392e3136342e333914f9956e70daffa263e8cf29fa6557b7b630a595a8fb4e1ffb05a3fb8f3000207718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be4290207718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be4290013094813102a7c65673c8421b5098bdb3527a6374488c6e4005077589ea6d88cb978149246858b01f5c043b0db861bfd7710d34342e3232372e3133372e3737140498ade3c80045c2a7520e921180ae1c39da5c57fb4e1ffb05a3fb8f30002087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d6789182087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d6789180130a4e5e437e79ca948abb1c47d227e0cf431223858e232efc678f2f44c01b8f03fc8bfc783de1c9aa25fa33ff26e34683b0e33352e3136372e3134352e313439149b9cdbfe3568cc0b37f136b00a634c75653f05e3fb4e1ffb05a3fb8f30002088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f2088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f0130b96bbcd66fe7998497d85b794b7ac3db4f6aa623cda276bd5794ef34e187556fda94f0a79e9f821ef4c75c27366cd7480b35322e33332e32382e343714711fd9548ae19b2e91c7a9b4067000467ccdd2b5fb4e1ffb05a3fb8f3000208b8d1193afd22e538ce0c9fb50fee155d0f6176ca68e65da684c5dce2d1e0815208b8d1193afd22e538ce0c9fb50fee155d0f6176ca68e65da684c5dce2d1e081501308f492b943a251501373b176dfb18a0f7870823efe32b9cff53992283704048e8760a9000f26b94dd297621f8d8deba080c35322e33342e3134342e353014a0a0e17bfe82a484fefe348b7569a6d77d29d2c2fb4e1ffb05a3fb8f3000208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc4208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc40130b2079d4be290c58b34c9c14fbfd01bb9f1aaef01d002b319925a243335c52878ac883f9b7e0127271590188df43119f60c35322e34332e38362e32333114337b7fb5d2c531825c3e0123ac3354018085b302fb4e1ffb05a3fb8f3000208eca4bcbb3a124ab283afd42dad3bdb2077b3809659788a0f1daffce5b9f001f208eca4bcbb3a124ab283afd42dad3bdb2077b3809659788a0f1daffce5b9f001f0130a92f9d9f46f6c9553c28adbe4855f42298c48953fdceec62c7382ec7ded8e0bbff64efe7df4db32c7829f41719d340690d35342e36382e3233352e32303114c075993a8336f93a13bb7bbb7e0e89928be4aafbfb4e1ffb05a3fb8f30002091bbce94c34ebde0d099c0a2cb7635c0c31425ebabcec644f4f1a0854bfa605d2091bbce94c34ebde0d099c0a2cb7635c0c31425ebabcec644f4f1a0854bfa605d0130aef0a3f51cd505157dcdf018bf77412f70236117262a69892b426c48ccb906614b68adbb916310fbfe770b29c0e109ad0c35322e34302e3231392e34311402aa69f8ef6666e7cad6d9323755a0ef3c1b6bd9fb4e1ffb05a3fb8f3000209712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df54209712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df540130813f9716f1fefada2d1a750779935e9571bded5f0a2a0a08b19edbf4d821538999d4acdd537755599eff93717fa071430d33352e38322e3139372e31393714ed1131823bcea23ac78af8c01e4d24683d6ecf88fb4e1ffb05a3fb8f3000209cb04f271ba050132c00cc5838fb69e77bc55b5689f9d2d850dc528935f8145c209cb04f271ba050132c00cc5838fb69e77bc55b5689f9d2d850dc528935f8145c013095202e363e72de2c2f1824d118a6b19243808d4bf3090cd6ce1bcf0c92937f6b2665f05e497f0dd27586452f9e1507230c33342e3231342e34382e36381462e960a3f6b650feed98a266b3ccdf6e363562cffb4e1ffb05a3fb8f300020ba8ce1dc72857b4168e33272571df7fbaf84c316dfe48217addcf6595e25421620ba8ce1dc72857b4168e33272571df7fbaf84c316dfe48217addcf6595e2542160130b5ad25d83182aea77532834687bab1d6240b7b40a55ca27e60259c1e4f5077ffb26c3b1a0434d9eef529596d632c9b710d35322e34322e3230322e3132381462e0104ce0aafc1f06bde37c73702fe84b307f05fb4e1ffb05a3fb8f300020c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba820c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba80130b9a2cdce8e51b6a514e599ab5edda00e6d69fc0cc43c380915149abe7159f9c856e5ad391e7eb443ff8a5bfeed2659d10d35342e3231332e3230342e383514fdae7cdf38811659ce9481975b326a5d07236bc5fb4e1ffb05a3fb8f300020d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f8920d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f890130a5d068fa707cd7a1dae2b4e30f384a516e4b86bd69ea0ae40204f35235fe866a3f54e1f7460ed9744485b7744b58c4850d34342e3234302e39382e313032147034f0d3853c5351fb8e0ffd3c1daf12c51c2d89fb4e1ffb05a3fb8f300020f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba786399038120f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba78639903810130b11e5897513333cacd8b5761d884b08699da6d8dac9e965a366599813ab7599ea6ac86f064060761559940e2e1fad3ad0d35322e31332e3235302e31383214fe2d4798df3e9b41a6823bc0b3f020478e87925dfb4e1ffb05a3fb8f300020ff261d2c1c76907a2ad8aeb6c5611796f03b5cbd88ae92452a4727e13f4f4ac920ff261d2c1c76907a2ad8aeb6c5611796f03b5cbd88ae92452a4727e13f4f4ac90130b006eca834e243cfa364f0b6a127aa221306b1d3f51d29b99e673d69a2e6fe60e27dbe859bcd85ac786430a8cbd6775b0d35342e3138372e31342e3233321467e05b1b52c7c896adf20035036fe1d30dcefc9cfb4e1ffb05a3fb8f300030a8aa56233bd002f4e294ab97dd212cbca4f79aea9cf6e80ff7a568ed5668569cfb5dac816a3f8561ef04251a28fd530c20000000251c6293f36145e149a75179d723b88d675332f8efd1667cf871d246710020000000251c6293f36145e149a75179d723b88d675332f8efd1667cf871d2467100fc00110880192005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea82005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea80130990f9bdf2dc93b6566cc92ebeff39bdcc062a37575b737848ef93f040e09d8fc7104116a48c83376d050ef245e90fdf50d35322e32342e3132342e313632148feb00404d6f765856c95e587b2523a365bc7258fb4e1ffb05a3fb8f300020143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f11320143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f1130130a306779bbe3f86d7b731176aa1a86a6ee080adf527953a6844e02e668b67fab78e859690844d72aad89602d175150e3e0d33352e3136342e32332e32343514b5f25f8f70cf8d05c2d2970bdf186c994431d84efb4e1ffb05a3fb8f30002039741ad83dd791e1e738f19edae82d6c0322972e6a455981424da3769b3dbd4a2039741ad83dd791e1e738f19edae82d6c0322972e6a455981424da3769b3dbd4a01308db9d17923c5acb439a2ca05d6b8a9b8e4b68a0554b1a0325c926e92e13ea0a8c4c9a6f38bb16b9d7807532ef96064490e33352e3136332e3134342e32333014ec7bf3b9bc72eda38c80bb7cf16e294e763e56b4fb4e1ffb05a3fb8f30002040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d2040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d0130a660a964938e90ba91e8f1bcf46f5b61edf9e7bd1c974e7f58ece9f6806f9e6e6fa06301e75cdffd923089c78ecf5a610c35322e31302e3232392e3131143e8b10646ee9d6c28d75c280b357dd3a9ae9f962fb4e1ffb05a3fb8f3000205b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a23205b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a2301308e64b6456c41e771170854d8415bb95fd47c597373c00a55a4beeea43d6a22830e2e4c6dbe4dc03794e0c8786d9a040b0d33352e3136352e35302e31323614f460a07a2b0dc932e1d8ff2dee2b984ac415dcebfb4e1ffb05a3fb8f3000205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef436205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef43601308317d15d474b38602d5e3ec6d1c3da6284da53b47b5084534b65debf30c2018a048b3561c38429530a53f2ea5583de9a0d34342e3233392e33392e31353314972a33056d57359de8acfa4fb8b29dc1c14f76b8fb4e1ffb05a3fb8f30002061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb2061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb0130b09010ae7148d6459b2e3821ee2ea2e8c2077bd948a16ded93977f4865ba6d04a3e82ece2da5703d04e0d68fcec043610c35322e31322e3137362e3930147ada3e486409b39c94a0833c8d782f35bc24e96afb4e1ffb05a3fb8f3000206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e52863320966206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e52863320966013088412ab841f7b0951d6f0d035a9e91472983c1f66801e14ded8f71f7e6ffbf4d37ad1097cf4b2df332b4bf30ff5f45430e34342e3232382e3234322e31383114c374f016ea61e76aab79b8bb95a1ba0e6e3eee6ffb4e1ffb05a3fb8f3000207135069642e1a72807a383fb5a14b9af6758292fee53fe2a7f7ac6f528bf7019207135069642e1a72807a383fb5a14b9af6758292fee53fe2a7f7ac6f528bf70190130aec0362b40aff3bd20153844977a6b5178c8f4a0b59d13c3331c1713a984d9d0fe4e33bd73892fc7b9db0276f04822dc0d35342e3138392e3136342e333914f9956e70daffa263e8cf29fa6557b7b630a595a8fb4e1ffb05a3fb8f300020754b89dae8db20fc4cee5e3adb07b146d7efe508a66fa0a8e1094675b9daa35e20754b89dae8db20fc4cee5e3adb07b146d7efe508a66fa0a8e1094675b9daa35e01309757740efe454850a7e553e29ec92082f41c8559c209738e4bf2622856ce8a25c982715ab6b6b51224ae7b98f822e4b80c34342e3233332e34342e39351446d938862af6d9a291e26c0048177db2892a710bfb4e1ffb05a3fb8f3000207718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be4290207718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be429001308c41f9e11ecb851812be5235cd0cee625e9bebb624583096ff39a673d20f589021c6f3870191bbdafc32ed5245738b520d34342e3232372e3133372e3737140498ade3c80045c2a7520e921180ae1c39da5c57fb4e1ffb05a3fb8f30002085f15a31d3838293a9c1d72a1a0fa21e66110ce20878bd4c1024c4ae1d5be8242085f15a31d3838293a9c1d72a1a0fa21e66110ce20878bd4c1024c4ae1d5be8240130af5da56ee0a828c4ba881d28c2adc2ae288690fe37535a075ba54b72c6532c26095cc71d80f681d725e063d1f500e06d0d35342e3230312e33322e3133311468c506d43816d1a8389c860c1d162be44d1e777cfb4e1ffb05a3fb8f30002088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f2088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f0130a51dbf35096235fe2018a7f1ff00c3c18e541e6e5ae2a81c0952ed5a3c8800e1e6b5632ec1dad41af24c0d9bd8cdd2b00b35322e33332e32382e343714711fd9548ae19b2e91c7a9b4067000467ccdd2b5fb4e1ffb05a3fb8f3000208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f234208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f2340130b8f10efb4b60b6a2cc781c0f894151e0053e764175e261c75af516ec1cdab766de87b69453a73be3c234e6f4aefee6fe0d35322e31332e3133322e313436145bdbf34a0dad860c6ec71523ae39373325225cc1fb4e1ffb05a3fb8f3000208b8d1193afd22e538ce0c9fb50fee155d0f6176ca68e65da684c5dce2d1e0815208b8d1193afd22e538ce0c9fb50fee155d0f6176ca68e65da684c5dce2d1e08150130afa10520f621ca2cf4ee8ac229f9ffafdf0837f802eada2a823255235841f08544fcdb989fb4bff6348de6bb6cce8a0d0c35322e33342e3134342e353014a0a0e17bfe82a484fefe348b7569a6d77d29d2c2fb4e1ffb05a3fb8f3000208e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c0208e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c00130b1bf5c07ab8dbc65148edb38632459cc79b85290185b7bd6870f9352bde07980986a5427f783cbe3ec3946a5eeddc3300c35322e38392e3135342e3438146d57707c196e06487d326094c964f258f5b77c35fb4e1ffb05a3fb8f3000208eca4bcbb3a124ab283afd42dad3bdb2077b3809659788a0f1daffce5b9f001f208eca4bcbb3a124ab283afd42dad3bdb2077b3809659788a0f1daffce5b9f001f0130a56d524c550f683ffa4aa0be33fdd59b3b02b6c46bcf4696283da657d2d7581cc4ee52a38671b310d7d7e526f7f4557c0d35342e36382e3233352e32303114c075993a8336f93a13bb7bbb7e0e89928be4aafbfb4e1ffb05a3fb8f30002091bbce94c34ebde0d099c0a2cb7635c0c31425ebabcec644f4f1a0854bfa605d2091bbce94c34ebde0d099c0a2cb7635c0c31425ebabcec644f4f1a0854bfa605d0130a818137a518d06c03a98e2bdf2fe4fbef96ebcda3042504d109feab8c28692fc8d521de2f3cf75e3a412e09f9dbf17a30c35322e34302e3231392e34311402aa69f8ef6666e7cad6d9323755a0ef3c1b6bd9fb4e1ffb05a3fb8f3000209712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df54209712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df540130a94edfaa78eadaa7cad31be5997fba9465def62ae4e6abd5b94483b67836e61b418ec9288e3e5d928cfbd70a739928530d33352e38322e3139372e31393714ed1131823bcea23ac78af8c01e4d24683d6ecf88fb4e1ffb05a3fb8f30002098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba0920962098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba0920960130b59b4cef03be4158392249c56d61e50a21785005ba8982c4afa93d271bc4d0b7c19415013cdea9403c23c4a814aa1b920c34342e3233322e3139362e3614d6ece912cbf02627a4efc3dd37e6833cf3671551fb4e1ffb05a3fb8f3000209cb04f271ba050132c00cc5838fb69e77bc55b5689f9d2d850dc528935f8145c209cb04f271ba050132c00cc5838fb69e77bc55b5689f9d2d850dc528935f8145c0130885910160755543c1bbe191ccc79fc8eea5d6683a2186fa7666ad88caf4fb08c6c92b7baf1db457cdc11956e35b8a2050c33342e3231342e34382e36381462e960a3f6b650feed98a266b3ccdf6e363562cffb4e1ffb05a3fb8f300020ba8ce1dc72857b4168e33272571df7fbaf84c316dfe48217addcf6595e25421620ba8ce1dc72857b4168e33272571df7fbaf84c316dfe48217addcf6595e2542160130ae0682a10deb1a2c80076b617e220491c372ec9b62870789b419914c56f998ff30fc260ed11569e6ed864ef5774d95ee0d35322e34322e3230322e3132381462e0104ce0aafc1f06bde37c73702fe84b307f05fb4e1ffb05a3fb8f300020bbfd0ac1977011267a7032641ef5487fe15a4de798faa485b156fb3b7eb0acb820bbfd0ac1977011267a7032641ef5487fe15a4de798faa485b156fb3b7eb0acb80130a9eb13ce08f590b3346f9f6f36ec10a7860e3c1eae70c9df7663772224a60c7773f83ea2f080d0f74ae67ba223a9dec90c33352e38322e34392e31393614dbbebbc52a5bae21b818e0487311041c91b2683bfb4e1ffb05a3fb8f300020c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba820c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba8013095e62cf6ff14e6d8ef16761cde3384fc19533ea21e46001b57181b7af678eecaed015cdc58d10c4de4acfc937b5f18ac0d35342e3231332e3230342e383514fdae7cdf38811659ce9481975b326a5d07236bc5fb4e1ffb05a3fb8f300020ff261d2c1c76907a2ad8aeb6c5611796f03b5cbd88ae92452a4727e13f4f4ac920ff261d2c1c76907a2ad8aeb6c5611796f03b5cbd88ae92452a4727e13f4f4ac901309338650338a17c01b5b225d5618187861fdfb4ecee36d56c141ffc55a5b1f31120fd0148f8f50bb071734375ac888afb0d35342e3138372e31342e3233321467e05b1b52c7c896adf20035036fe1d30dcefc9cfb4e1ffb05a3fb8f3000308bbe3bb70f3f0e4204b96c4ab65ee2574d35ced1d63e67379d9dda4017504767ac94148797747faf41a1532578e2ad400000180018180000000b8cd4ead1ee12d25126921d918020cd77745d9cce5b59f7287a2a296e309860460119622e94b562c3dcec8445e63d04f8f88d4d0835358f79ced0342b43822e32a35c32ebdf76eca5d940a999480000000021160aae5b92562c94a5d6735c5dff3a92aa0a8d9b02aa0c614ca7154a30b450abf6838c0026c4a8526d7dcb44426b02f225d98ec9d43bbbf91a204b9c50252b2e3c9af4c237dc117d73fd60345100000000251c6293f36145e149a75179d723b88d675332f8efd1667cf871d246713086fb47b84caacf7734799c2106fa87d8dac68bcceefa3fd33dd568ecbd7bae3fe312835eff8d68b9bfefa852d12589cc0000000029787a10cbbd05260d3c7a8114746b568d0a5fbd2fdb9f080ac12c5acd30a53f79f722b98c47ce515144b41daa3a97cc7176c456b05fee6d5fd0216e123c07b1c0ae5eccb6d637d88e9d45bd544c000000004689a842c049d460ee314df1bbfa36530ff86632142fe3b6eee824003430a0fc274fc7b00cebe08b5a91f39ff7435b0d944ba82abb5a3df6a768051b674fcda0c9ed7478801f58abb1d081319e3c000000004d43bd84ac6be16b9b7e352b3e9905e1337d7d4d6dd0b8a0ff92a89f1c30844a36bc9a23cadfc278a9cd6df42b375ce2080c106c8ce01b3aefcac3f81ac3ba2abd5208165ff95039bed9d8ff94ab00000000503099f9f7fc49ca9350ce1951c09325670b8b459f3a55ebe6811f13e1308c43a90fc0e9a3b85297dfc221a1edd2b791c03bb2f5cda875a8844edfb73d8548bcc3be5ac5cf6548b9023fc551dffa0000000050b5530a426cc3a37ae64b7e37879c0905cd90391226fd7395a19cad2b30a99406603295d31f2f2bac6c2cf95a3b950b7abbdf74928010514d2ec53a5c4d3111fde6eb703f6e5599bddfb6ef2de30000000072da33f586cdd86a566cb30268f411dad855dc3fd18c5669410c7cdaea30935e67335f895fc17481cb14a4cf7976d449446bc45714c8c33888228d1a8833b372f0bf5e57d3da8d8b46a3df24ba18000000007672f63d6d54737b0dc862fe00a4c146100e922c39e2b8349a48088d523084fd520baf70c5d1f099f89c30e4824cf9307db2d50d04ad055a3cd4b1ca382e097615cb41a814d6c8af1df3f41ea40e00000000b6ebee5a8f801f7b66c32a3454b12513c76ab58b121a4e9c579bcd4e8c30a073fdd826b6f0528d57640ed2c442f427ae50365c8ee533aea561a43f0a847535d1de724b4cb33d8f1ebb1b7ec1fee800000000b91e2a2fe9ab4c3899dc7d2d85c9e00e068603afe59058d5415a84773d30acdda79998aa4a7c8db61e4de0c0033a6ad68b8e898017a0a1e478204a9fff434dc7d874a4346ff3f0cad0e6d6a7f0cc00000000c9c3825db4b9a1751e94ef41634a33e2df66e8f9ddcd56dd435232f48f3097fbe82232f01d505db016f9acedd89b3b64aeebe3ee42c618a70940c223b44702d47289706c066001f399911b13e5d900000000ca47540e3e2bbbfc91ad3581df6b5f730ea457841a3544e2ab3c54c24530b81e791bfd854cadc0ade4456d2eb225c921545d3c6511771be3e41f96b828e14fb560a4c8d86eab9935b6b3f7dfa0e000000000ceb90097be7a897c47be4752340dab3c394e860cac4f03f7bce60caa8630b594ee3dce15b395606f54f5269d69688c38b90958253f6f75897a312849d64f5f991600032a11b4f44162d429a08b9b00000000d4b6e3c3b706bd8941885c8fb46dee63ffbe116888d8892b7f53a0a0da3085a9c445b48a8fd3703c240ac3c838f65f78f6208698dc651d1a24ea3f09a72dc43389bea4e65f4576708b39f139b9f100000000e5d8948d2c695de557f1327a8f323fe00ea463ab53d415589456cae543309428bbc401fabb4f3e7c3a6a5bcc139a4ae581645729bd4dee7f272446357cb0c4064ffde38e5eed63720df03259ca7e00000000e7654d577ec30cf6779bb7f025807118c9ee33113ea249fa1ce949064630aee6aa85f79fefcde7fb71a8c880f6474fde2cbfd5cb6d1afe1cec9506fb25b1f8908e1934648898c79dc403f2094d6300000000e78672b7a792c03ffc5e06c6512e0ae64c4b5410a2e41b6b871036e5d330a89228f3c8f7b8cc5080b6721668c5f6ffa0c6b7c7fbd6182e968882e6676a436d47ea673c2ddc83aa6692c44972a6fa00000000f1187cb12e35cb2a20fa7ebaad86a10a07f37a26d91068fcbde0ee462d30a7bbbc25d144e31734003aa26cbb696ff91d5895c67110369dd24998e7da857bbe7a40a9086b96752c1e35e19a485594000000010832789d4cdff3cc8a63fad668ccac708af7433c42e189ada6c6e5e66e3083e592e3320143c10ef29d05f6094f428fbeec17671057917f2bc2f6d71f8151e3c22379c9414e41f568a0dad43a49a2000000013b5860da205d4132c60deedcd2f06f18c77718fc9f96a5473d05e596fa30b64e26f35b32ed7fcdbf760a3806137ee21208642ee072e3284df4a1f9197b2b2c1036a355d2fc670b37f6d06631195600000001561ac909f7762f03b801661c0ab46943d603d2883b36535ad5f6344cb830a9c57b1671efe72ccf52577b20fdee42c4f93c2098dcce5e0589b4eced2a1403c4834084b950f775a23745c73f85edfe00000001d6bd1fcac1f64325a6a26b0a3a02d1e3b61267d50f855984a873c3d689308c3f90fa3b27af67e8f0b3078169ea2cc61ef13b075fd8e0d2d6a7e83ccf0c59370020e5c753a0ad1a684efcfd68499a0001180000000b8cd4ead1ee12d25126921d918020cd77745d9cce5b59f7287a2a296e309860460119622e94b562c3dcec8445e63d04f8f88d4d0835358f79ced0342b43822e32a35c32ebdf76eca5d940a999480000000021160aae5b92562c94a5d6735c5dff3a92aa0a8d9b02aa0c614ca7154a30b450abf6838c0026c4a8526d7dcb44426b02f225d98ec9d43bbbf91a204b9c50252b2e3c9af4c237dc117d73fd60345100000000251c6293f36145e149a75179d723b88d675332f8efd1667cf871d246713086fb47b84caacf7734799c2106fa87d8dac68bcceefa3fd33dd568ecbd7bae3fe312835eff8d68b9bfefa852d12589cc0000000029787a10cbbd05260d3c7a8114746b568d0a5fbd2fdb9f080ac12c5acd30a53f79f722b98c47ce515144b41daa3a97cc7176c456b05fee6d5fd0216e123c07b1c0ae5eccb6d637d88e9d45bd544c000000004689a842c049d460ee314df1bbfa36530ff86632142fe3b6eee824003430a0fc274fc7b00cebe08b5a91f39ff7435b0d944ba82abb5a3df6a768051b674fcda0c9ed7478801f58abb1d081319e3c000000004d43bd84ac6be16b9b7e352b3e9905e1337d7d4d6dd0b8a0ff92a89f1c30844a36bc9a23cadfc278a9cd6df42b375ce2080c106c8ce01b3aefcac3f81ac3ba2abd5208165ff95039bed9d8ff94ab00000000503099f9f7fc49ca9350ce1951c09325670b8b459f3a55ebe6811f13e1308c43a90fc0e9a3b85297dfc221a1edd2b791c03bb2f5cda875a8844edfb73d8548bcc3be5ac5cf6548b9023fc551dffa0000000050b5530a426cc3a37ae64b7e37879c0905cd90391226fd7395a19cad2b30a99406603295d31f2f2bac6c2cf95a3b950b7abbdf74928010514d2ec53a5c4d3111fde6eb703f6e5599bddfb6ef2de30000000072da33f586cdd86a566cb30268f411dad855dc3fd18c5669410c7cdaea30935e67335f895fc17481cb14a4cf7976d449446bc45714c8c33888228d1a8833b372f0bf5e57d3da8d8b46a3df24ba18000000007672f63d6d54737b0dc862fe00a4c146100e922c39e2b8349a48088d523084fd520baf70c5d1f099f89c30e4824cf9307db2d50d04ad055a3cd4b1ca382e097615cb41a814d6c8af1df3f41ea40e00000000a9510131c07fb58ce1f572165af5af245f7be594245cdc40b7b4b95cc7308ab76c9e9a341d200635323b462be31199e93cd43bfeecdc1243d7c8d1ba41910edc07cf6f197d55da1f5c760dd661fc00000000b6ebee5a8f801f7b66c32a3454b12513c76ab58b121a4e9c579bcd4e8c30a073fdd826b6f0528d57640ed2c442f427ae50365c8ee533aea561a43f0a847535d1de724b4cb33d8f1ebb1b7ec1fee800000000b91e2a2fe9ab4c3899dc7d2d85c9e00e068603afe59058d5415a84773d30acdda79998aa4a7c8db61e4de0c0033a6ad68b8e898017a0a1e478204a9fff434dc7d874a4346ff3f0cad0e6d6a7f0cc00000000c9c3825db4b9a1751e94ef41634a33e2df66e8f9ddcd56dd435232f48f3097fbe82232f01d505db016f9acedd89b3b64aeebe3ee42c618a70940c223b44702d47289706c066001f399911b13e5d900000000ca47540e3e2bbbfc91ad3581df6b5f730ea457841a3544e2ab3c54c24530b81e791bfd854cadc0ade4456d2eb225c921545d3c6511771be3e41f96b828e14fb560a4c8d86eab9935b6b3f7dfa0e000000000ceb90097be7a897c47be4752340dab3c394e860cac4f03f7bce60caa8630b594ee3dce15b395606f54f5269d69688c38b90958253f6f75897a312849d64f5f991600032a11b4f44162d429a08b9b00000000d4b6e3c3b706bd8941885c8fb46dee63ffbe116888d8892b7f53a0a0da3085a9c445b48a8fd3703c240ac3c838f65f78f6208698dc651d1a24ea3f09a72dc43389bea4e65f4576708b39f139b9f100000000e5d8948d2c695de557f1327a8f323fe00ea463ab53d415589456cae543309428bbc401fabb4f3e7c3a6a5bcc139a4ae581645729bd4dee7f272446357cb0c4064ffde38e5eed63720df03259ca7e00000000e7654d577ec30cf6779bb7f025807118c9ee33113ea249fa1ce949064630aee6aa85f79fefcde7fb71a8c880f6474fde2cbfd5cb6d1afe1cec9506fb25b1f8908e1934648898c79dc403f2094d6300000000e78672b7a792c03ffc5e06c6512e0ae64c4b5410a2e41b6b871036e5d330a89228f3c8f7b8cc5080b6721668c5f6ffa0c6b7c7fbd6182e968882e6676a436d47ea673c2ddc83aa6692c44972a6fa000000010832789d4cdff3cc8a63fad668ccac708af7433c42e189ada6c6e5e66e3083e592e3320143c10ef29d05f6094f428fbeec17671057917f2bc2f6d71f8151e3c22379c9414e41f568a0dad43a49a2000000013b5860da205d4132c60deedcd2f06f18c77718fc9f96a5473d05e596fa30b64e26f35b32ed7fcdbf760a3806137ee21208642ee072e3284df4a1f9197b2b2c1036a355d2fc670b37f6d06631195600000001561ac909f7762f03b801661c0ab46943d603d2883b36535ad5f6344cb830a9c57b1671efe72ccf52577b20fdee42c4f93c2098dcce5e0589b4eced2a1403c4834084b950f775a23745c73f85edfe00000001d6bd1fcac1f64325a6a26b0a3a02d1e3b61267d50f855984a873c3d689308c3f90fa3b27af67e8f0b3078169ea2cc61ef13b075fd8e0d2d6a7e83ccf0c59370020e5c753a0ad1a684efcfd68499a00fc00110ab1fc00110ab301fc00110a9c00042001fb0120200000001c17557b0aa6d56b745b60fd4c3c53f2beba8fce58a6a01fc50fce1cd630919fdb493c7492c92651b5b48643001974e9c6c08dc38d201e914672732b7e237f81a9a883cdc12b446548823fc52769011600000024dd142c3b883d9653935780d82dfa760af504be48745a9ccfeb87f95e3080fb2822996190c9ebe6ef941f7b9c2cf140117614926c516865791a2713ea6a773751e9753b0ed63849763e435d027d0102000000372aeb94a3ad89154fc41c296b1bfbd2f744934dec354ac9f121a3c2f730ab6d16078b0190e779e516e9119abcc0623d14034dd8cac836d9114239251a0d10a77e498c92db7894d8359ebb8fc628011d00000037608455165b3d7f752e5576bb9e3fdb54af8c9f6aea8c5c39f607ebeb3091199e5de7deeb39bf99ff557a5267ee0fc5e4297089e1ce03afbe27d7a4ef75196c6e599e4b15314213368b00c3cee4010b00000037e2a2a37e026777d2ba67371b1dd0c7d49044c5a566f0469be085c16f30a184eebcce47f63dae0e2a55a74afbe53b671b6fb9954936fbd17bc890ca3f0e769983b188a22469c394c9bc1dba8a6b011f000000411dd2ec65ed0f979acff00da0df586357e715de8ca3b2d42cd39614573095598b486466ed807f4306968b15410d4a55cd1e38f7bc3a489b1056ba8eae9a6dd5e1ed9e59c772cbf5da7e8b8c293e01090000004be4965bcf4d4e63c8250f81c617a58a5a268dc8ea3c3f86de0b3a806d308734df8c4bb9757e5157ef809535296800a14c76a4c925dcc26f74efd78bb45974590efe53d6d12eea41c1cfaaf5dd90011e0000004c4be4ac378bff06fc33e9677589e9cd45fe403dfc27c7874f95d42a6b30ade14cd45e426734de61d95bb6ffbb1e64e7c3dd3e046d3fc0d39edc28e1f047c07e44ca7fda141356d35119dcea53210119000000504bcfbaaf0684b5f9e5b43925497de07e93444da15568fd67daa3e3ca30b885843723894347bc0bb59761178e34b5ed29b879e23ce3bf84d60de0fab9e4d2272106f7c83799a1350ed11859df1c01030000005634442336d250bc6f41a1beb3150bf00c4386e29c782c86f64e524af7308422c8690ea530d4c1c13d841bbe24ec66d82f1b962ce39241ad45c13a62ba4aec66bc80b9d3ba52642b9ec7d471fe06010f0000005a8b5ca058cba2953dc80aa4485f2acced3922c29d3388b167cf78b35730965fd8b4db515a89e27c43dc591d47e343edb967d52fb8f1423fbefaa91b97fadb131b99dbcc28235ff0879dbb6a42df010c00000066677ad0a47afd2836cfd9b29a60f2a5f5b76e27cfc5fadfbd9a56a0d33092517556cba9e44f944d656e0bd15062b41d172f9a3ecc7fee1d79909e3dd9929f5120dadb0d6650a92b0ddc4e4d1fd6010a00000097e09e2749e43066a7ec3e08da9786b4597ec68aa764a5b12fa994209430a03cc310e3d46343430851204829272c534ceb7b9bf0b774f8e00148932d1c6d7e9bf4e1616cb943aa44fd6010b147e1011300000099f4ba9b8f567066725e949ae6d15af33124f288930c05f29e5b9c63ed30a473df3015852e967e3365b140353ce5800e15abdf8c7736e2df5304a779b7e588b7d72423c9901004182809f64008990107000000a8d450eefbf6324878ad6e6203ca409d206772a0e83910352e76e5478e30b72a08760cb1af67a0881b13d87f4f746b7e782f9c4dd8f61f7e25ab359fae768a25cbab2004fe9a095e9e97d8fc6f3b0114000000a946faee14ef3fe5b06dde3132766c3edafcae89fdb534c2c2d0be155c30822fc04e42baae578281253c438dd9d8611f0bc325b9a9e39a2ec8b952c963401dedf25fa2cbc8ef26c7a5783c2372f80106000000bce166b1ab589a089dcf9ea84bbf00c42f3b2699aa067c53ac6a942ae63093025ddc9b3f01449f67864c0b9cc26db0e8526d0c08035ce8151aacdb204b0d0c33aa7b6462a5d09b3b00f1783183b5011c000000cac98a5ab2a2156e2648bc99a6eb514aba8d1a46167cdd21baa11488033090c1cbb77a5995d55907bab10d33eaa999219dd3751385d9259dec972208a6789b2ba31e2c254889895508fc077212bd0104000000e2113e90d0ec07975c2aec2c8afe986477d1eba19a7811d5d33b1d448630b9cc6d95122f1c1ccdc7b5d3171427fd2b3de05835649902ace1f73788e4939aee450e72209b9c6d28910eefecb7335e011b000000e3b9c3ac893562d87389c0255c7f95a51db2960302fb8d6c9d82972567308b82f0157d4eecdca9a865abccf6ead67a65478b29c4021e15b26210880552bc61cd7762c8203d6b7cac79f6ec11db930112000000e42610cff0fc6648d1cd6d4d54dc3ffcecb374e945db637b7fc7e1094f30acb1a3b40966809d190d78514794ec2062ac3a567cf878513f8c2793bd555ae2107a1be0e09e4c35029aeb5104d8e5be0117000000e7654d577ec30cf6779bb7f025807118c9ee33113ea249fa1ce949064630b51b3d77bad620570ddfc765e459c508e780168c1e76c2ba6b3312a21a0e9da0b54c7f26331d962c30097ac89f4590dc0118000000e8528886d471e749c483155d887f9c8a50625b0263103e18dd0771d8aa3086ece6336903315a8e34688eff6f5534bacd3ab8f6b3364738467a7b26079acca871dded3d3b402cf90f2f9f71375fa70115000000e90fdf133f8cc78262509b2dd44809d0cfce8c8d895145fb76aa72994730b20fdbe02732421192ed34d58bbcc7252869c16480638a4d4f95fa35b39ecfc914960b1f883a3503e43ae29913ba8a33011a000000f4fee40e6c8b309743319b89d273476ce3f480adf035ffe6d35680c03530a51f0d204efa8aac21d376a7fe892d270ac5ac1d8b6bb2f2633c358937ebc950a120acfa13d51358e2edf9d31099b5090108000001027d7fd3b22fb92e73d2148ce965d2e3684a7dd241215bd01be45764943091c2b79dcb3d7493c35b41838867fc468d5c691c8835f643acb2a75eb438d8fe64d44ecafe51373514f2b2bdb8c1e55e010e000001082689584968c870268b47d0d3d3c7ae0655fd1ab678ed72d359cf1a67308b44174aada80c6112c7d703a4e60a76a837432a45142f02eaab5f5b7ca558e5bef1c82f7554af04394201960fa7ec0c010100000133375fb619887caee8dfe8c764a3ccfb10a2896075d79b55e00833182f308f11d173cd8faa2a60f2160205ac5a327c62b5b0796eb5f479eeb08873039c52c619d5066f30625bf757f01ec4885b4c01110000013337cca3c54b9ee0d086cf98c4ad8fbf2912a8281d31b5bb675b9ce1e73089a581df737b98b4ee8329a7ca0c38684dd6c6bbdfdeaa415dd7f26251b0571f9a33f25d9e83e55661918ec38fc752ad010d00000135fec3b0a50d647054092ac6dbdf51f4b86bcfb108cbba6d6f3deec30030ae5fa9750ead0aecee2ed5ab68056870a6cc8ba46e9580080325a8c418eb1e747bc165e504beb9ddc5ed4ec168516ad30110000001d60371889ab189c71d65fab144450f460ca502c1fc0236947a11e69715308f00f47f5a43d0c0f1f3c34ed98e9570b2db010ea6586e49b72bf68060b926ffdbef76c2bc4fcd53116a26c02bbc3ed00105000001d6bd1fcac1f64325a6a26b0a3a02d1e3b61267d50f855984a873c3d68930a51f3fcd0dbcfb1a8283e2e476a24dd722da031ad8c800ae359757c57ec4f939cf1562f5337c6863140b862d7aed3eb80100012000000003b8ac2b8c34bb5c5e581b140305c9213f8e269d075f7c3ce35058657730938107a9ea8b35489dde14f2d2107fe95a9c6a6aebf73f4133a5e8a7896434fd44f8770d6ca3901938ba36bc244079d801100000000ebfb3fd8682d13b42d76227518da219365299bf25f60e060228c3c4f03088234afd114926aa4b1e7c279f29bd6b929b332025998236811a4afc1a64a8bf319580bcab4d21f0281c090583122352010b0000000efb7bdfeab3aa6b9a7aade1624bfe5139dc053648fde77414e5d0d26a3082a519cc0363d0b7525fc99c81ab531a06d4008d1371e9b9bfb0326a39a35250e71c6f546d48502e529a9904afe1f8de010900000015c1b422d89b76d662e8878f1e898e0e52bf1c7e4c8b5a5d84819e58bd309585750dd1e0e508b8cb449030845947a2cc2ba0fe61ab0d0d42cd4d3369789d9baa599618886ccf46d672ca96fa0177010a000000239040f5760172bf089991bdd423d77fe12ed94c6d6cce4e4ebaeea24030b1804746481f8b92b0f9031caabccc24ac90f83d050208a6d634a6e91612627c7ebd6862ee169b010e66c139c92192190116000000251c6293f36145e149a75179d723b88d675332f8efd1667cf871d24671309452257af9160aae311e167e55120f056c1ecaab2d83c920e5ad61904c7d308eb7309b207e91ab891a211ee4170b7d77010000000027d6c573e287f6815e8d549b7533b43d565f194fa4707c2c452c5efd71309992d9ae0daec52bd07358f00829c9e3146e1e43aa093670a89793feefee6668526097480e2840781f18e35565a106a601010000002864d8f7a309572aa28f644fe14b35996a6e4a277b7e2d4a61c869df6e308a37b3962e6a9bceb12c0456e65fbcdc8bbc1ce74a93f3be699c0608253a3674a8a4b6581576b57e288082732ceeba1501110000002f841c6f9980ac707036873109f38a5dea30d9b7b4440b5f39da05a69930a13ced5397b305ffb410d814d7a13d1f2d9e4cb246d2a9c1b67c6d00abd8fbd8ebc3a95255b3878366fce78f8446bf62011900000038975f7c98f3b1d4520cff75e2cd2fa8cdc1b2ae5ec173e8e3526fbf3e30a2f847e67c532dd711760aacb2ab1014655c197abb1969d2a35906fbcdc1df36f4653d0867a8ba0245f377a30d49c30f01120000003fc35bec19e30621f4df1807cdbdd46e7c2ee5fa7e3d16373604222b693099ef5fee5370fa30abb6aebddf9d70fcaccb586405ec9b0db02d068bdba05aff6d31a00cb7327a98df9b43543fb7b4990105000000568e1d35844bf5d087f1e09cfba371602447652743af5405fbd011418c30892f812b0354223bfd407a021e7ddada119fad9a78577ab35f7470b296b1447f813782c20cba5f7704f25c860601cd8d010300000058d4f48f9b03d5f56a1bfeac784020bec3fb8a158d5db64edbe3ec1d2330b261c3f2146141eb69446088de98875b7de7fd24b33bd411ea0bc2b1ae81057503afc3680af273dda36bc16e0c009cfa01130000005daaf8a7fdd8cf47fe818294ee93ffc2f3152bdb8d3cbf6defdbdc42ee30b9428acd63393effd14cafebe45395dd1fd1fa629760b9865dcb2e439d18c1624a3b0e4275ea86ef397078442866f9a501020000005f1c7c759087736e3790693baeed92291652f555159fca5df6ead3e3e430b66abbb198f79e638f60a65b2e8fa5d16b69fd86745aade4f1646d3ef6b9310a143cfc9f2d34f74185e01ad49b859a3101060000006c001fa7195e51d929c1007cb5529543fc5bd3e5e5f3d04fa580a118cb308c7271e6b940b60ee8779d1e17f9e4af1cbfe4002ec3f56485d1e126862d0bd67a30fedf00b79d1f7c33b2b9c6928f31011c0000007672f63d6d54737b0dc862fe00a4c146100e922c39e2b8349a48088d5230a14bcb0c1c0ba486a22e7f949c5d2001bb19574d61c7978e7652ee0b87579836cea127d01f2b30cf13a468cdcc9e56a30118000000923d006513e9f6f37a420a38601150bc26d58e5fc2fa90ef3de096ad6f30aabfe8dfc0aaf0f181eb03d5e6a8f3582fe0e87bcd0a6058c60ea4087a3f30bb71254212b5bce14217812204b58dc2500115000000a61f54580c3b3aedfadbdb39930754eb59740e06878c4b21e077b1779430a3133fb93de26128c7bc8558c07a701dfd34a8e7fd27c314e8200b84b90a3b8a51b90f028fa19c9b968494f1dc2a7897010d000000a7e630c41fc945da3e67a106656547bd01bb26a94664cfd9fa939f5b213089c5b215e5fec1fe83d2981940189f99f0bc5b4ba486061b76ac78d3eadd91fd75b4fff44af75302c889c6f05d3ecb080114000000a8995453aa34952a7b6a36d6668b30a5a60c552463546daf9fbac737b330afa30a9e33607a758b18ea83bf64da1564f374e6c92860bfaaaf9951489bacd7dc1e939cf8ec833a58b5f5d9e606c98a011a000000a900df280c8aae91f937784f000311185df27d367735d38819e417f27230848e2ce2f08bd3b353728ccad3b745f1ce0ad43a9bf09fa84197777b874d8cbfdb6d5281e478835e656b1c25aa294306011f000000a98c40586e7e085eb8d9c5cff72b242266ed2c422950e03b3b6324c15f3095a2759d436fbd36219acc6ad722cb88cda15acb23452bfc80adff6d81501ac7c2d6699fd7f19c60baf141a545fdf65e010f000000ab19860011844cbc2b934da040a0905e91cd35c37704ff8ceee8d0823530a87362c64e1d3e7a56a82005512bfa53ead93ec50cbd20b316708a2e826524138a4d31cc3c156027608079226de7246a010e000000b88bba6c313f883b01ce114e6ec70d6c4e41846d16eb44e06e49d543a23094b6e8291c5a475ed15351e29b983b396ed28e67e6c6e3d9bbd0c82b99aabd1bbd4522d664ab75172bf1b1dfe2d784bd0108000000e8a99b7e41ab9e02d32c6753100a2dea5017a9779637ca7130a977a95730ac1f0e94b8813aa30abad4706d95bece76775b64d7969a4dc2f2e5c483768b2e8e3ca4eadca1bae00413c8a285612ab2010c000000eaf3661e56b8cec97c193a3ad4e3d5f8cb37d705a1c174c978b416d7de308117dd50ff24ec61c520e41613735160802fa2152243a6a4d5a639a236b68ab731b7b9bea06a030ae060a865135ee66e011e000001027c75a5e4f11e783325731c111a76d945df2f5614291c703b67dcfa2c30917b41386bf28e1a947006a1ecafcf6e6fcb0f59214095d78c070e75feeaf63b9f12b71aa2daf423f4bb5cd47b1c1ee4010400000104ff1afc8929aa90902f74f8b84959f56f53bf85e8274d590d3793118c3082b15f8072faec35371f7b62f5ef89a67de7504aff13f1a6b3928da68f276ee2b38a7e1a0697dfc2eb8e418b8ac3d7c6011b00000105ab5699c9f8fe76ddf1926a37c5f6b3e51be4eeb193a8eb2d4c28504e30a1ce4ac97fdfffd7eaa24438995b6c9e47309c2170aff3521fa1bd3da88eaf651d4f6a66918ec46cf9789562160c251c01070000010a27199898d02e56af922c456e32c4a919c21c33816cbedeba92630dc630a2a6d644970fd77c8ac18fcd70530c956686f7e97ac99eb155232df3b65467fac075bf22d480eb18cb723dc43d056cd5011d00000139d670e3c5a70b07b89fa3ee670b7ba3211c8c61ba8b1cb07d0039861e3081038507c58da0174ca63f45e8fa7eeb1c1529883ba24046ca56948de5172fd0e86f3b50d3ee4795a1684aa95b305be60117fc001109c7fc001109ca01fc001108aafb020c00850daffb0c2c6d85e766cd1540ab6384ef345187201df1fce9f6392abb152f00002000850daffb0c2c6d85e766cd1540ab6384ef345187201df1fce9f6392abb152f2030fcd315cee833f41272d6285560c7e738c6c0b267061d1d8e3ee7387221a09101ab35421915e3ea320ee07071957cf4cd0ecd8a0100000000005fb3bd75fb752ffc000977ff0001fc0009785300d36a190c0296d43164e19fa84c5e07b099800160b278c771d9cadb83d08cbd822125e04bf704f547b14cd2568f910b8f00de48144592d8ec9dbc809130027b568db397773d473e1e7c5a06af5254ea184be9e0e648f96969c662fb10eb6d559fcfc9ddc7ab8649e360d7db6e59000000000139ef5468acdc98c786a23397a0abc167110f46bf7a33cba29de48f7597cded0000200139ef5468acdc98c786a23397a0abc167110f46bf7a33cba29de48f7597cded20edcd97758fe49da2cb337abf460f1167c1aba09733a286c798dcac6854ef39010014315246edc109d76d15bcc5e24da55d453931860000000000ae22e971fb4e1ffc000cf03e01fc000cf13601fc000cf6cb00fad60b7fee893ef0b8a4602a2250ffdedaad6dd3ce7f101b7f075273c892063b1b8571311737a5767f95c0f808aff27883260bfaf9cfe2b84519a6b2300d4b5e1f48d7a77746676f09e2b995389d0f1c18601a6f909a4b542fccce87d9f5f30695d078a9181e142602d2e93f8f0000000001bbb58bd974fb622e39f7cf717d8942e210a84534ef9561087339e79181299200002001bbb58bd974fb622e39f7cf717d8942e210a84534ef9561087339e79181299220a3262f49c21c338fda802a6ac34fe12156d45e83bfc153b96d1631eb8b7c8ba300d5ce05217d6eb331ee3567e65e0229b5ea0d20510000000000235acda9fb4e1ffc000bb3b40001fc000bc76b0026a40a8e5da5d14302d09c58ac9ace45b54b1c5a26a40a8e5da5d14302d09c58ac9ace45b54b1c5a1ec5c66e9789c655ae068d35088b4073345fe0b030048a9403592bfa7ff82749de976c5e67a36c9d6b00a6665ae7281ec87572cd4643f15e78daa4cc251d5f2dd4611e37da0000000001f023a48ba1d046f980800d8c39b239e21d04855876700421f36e716a91f9fa00002001f023a48ba1d046f980800d8c39b239e21d04855876700421f36e716a91f9fa2026da1ea7d012875ece7ceb8e7b0f0beeb31c79a0ce9d97a2da25a2a6a7c5277b0008d98f95a7cf2eb4acf392bd81733e94c3f61dea000000000036bcc146fb4e1ffc0006567a0001fc000bd99b00b8fc46281e0f858dca3ba911af267d0ba2145249b8fc46281e0f858dca3ba911af267d0ba21452491ec5c66e9789c655ae068d35088b4073345fe0b0308f2ad27c0cb7b64b6e1aa5205f78e466b70ef61c6d529202c7b7d8ca9450d08d46234fc8aed1bb6594525d300ee931cd00000000021d46a532f0610618aa12d1dca47921623ec9db0b6397b90abe63967551bb3e000020021d46a532f0610618aa12d1dca47921623ec9db0b6397b90abe63967551bb3e20d83d93971aabeb80314062415c801838c3476d30e88a185a8fc621f45cd3c780009fb125d219bc182a771e7f3b7a910fd2c0cb5c0f000000000047c6dc84fb4e1ffc000722600001fc000722ab0057124732477195239cee3a968c4923f5f8adb96157124732477195239cee3a968c4923f5f8adb961c2610f8892172b3d1cb171d0c9bae78576b38379301135af6f4c73cd6f45513a9bdbf919fc9dcf76b18c0a3256b4aee0ed48360fa88637cd113502e4f6027232c2ed5de3b8000000000264e34848ae0fffb92a5f0fb446468fcd4c18014f66212529f2a3c585709b1a0000200264e34848ae0fffb92a5f0fb446468fcd4c18014f66212529f2a3c585709b1a206cac8d4777288a5504b95c30030aab85079cbbb9dbc106b0817459c66ee4f745015b5de31b03ba63480ddd09689f9eb5a33bdb78d4000000000012eca4cbfb4e1ffc000bb3b40001fc000bd233009260f93ba7145509852239781f4f83e02fe7d3ba9260f93ba7145509852239781f4f83e02fe7d3ba1ec5c66e9789c655ae068d35088b4073345fe0b0309532b2b80bbf0241d4e35a803eee7a70a1f6c016be57daa0602d180b7969409e8518d860ae8b9c403a36dfc821fbc12d00000000037db07b953e2196d659075376e7ba9d85baebed5c49577a898c0ace2515c1ca000020037db07b953e2196d659075376e7ba9d85baebed5c49577a898c0ace2515c1ca20661dc5aa428875848e4d049e053010747c592204575036a2505345b34dd3e0bb006cae25f986f4a1e14498c3f5a8517606a0b2b8da000000000080c763bffb4e1ffb5f7e0001fc00011b13008fa9e72582f9dc7882e0e40c932d98d3026765918fa9e72582f9dc7882e0e40c932d98d3026765916cae25f986f4a1e14498c3f5a8517606a0b2b8da308f3afb0dbbfec8610efdb4089f1b163e7f55325f6c0503470e8d49ecf439c848ff9448749e0a383980824994aa5dc50d000000000428147f6fe14b66e31c953141e884b5f7075adeea7bb8d1ec85297e594dd8b10000200428147f6fe14b66e31c953141e884b5f7075adeea7bb8d1ec85297e594dd8b120d2fa36682b5c4f47ac2f5b75ad137997110f677329e8b66cfccd06df324ad897010e421caec046e5b6106f222d32d987b094441a6c000000000040b0c6a1fb4e1ffc0010ddf70001fc0010de2b0022e16c08c8f80616d040b0dc6cc6ec9bc04b467aa2c6189093918db0942b8ad5c215989cef4d367cf440eb4f521312677cf98771dc52789eb9039fc3308510cbaaeb8d82f2cf1fe1c6e6d3e7fe3d9e6ef58a5cf1c135a0d39194c457fbc8921dbcda07fce72e6aef5b54f9b06000000000044b879c7014a715eb1bd98c79e6137f45011a0cfe3d21b24edee3c1650eabd9000020044b879c7014a715eb1bd98c79e6137f45011a0cfe3d21b24edee3c1650eabd920a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e182c84bc3be703bce7915fd9e65780589f11d9e708000000000023a59c9ffb4e1ffc000ccadd000000cc93037f5cdf14ebd273fc3d4999b9cdf81865d9cc93037f5cdf14ebd273fc3d4999b9cdf81865d964f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d730002a2e19ac4b986e20f55ddb19cdfa69cbd5f76c5e2d66ac6d9c8418aa1f0836e61b643bf48eeb004ccf3f3f0f03b82a00000000045678f95d95679868cc84d96299a0b58e123e9c94088e10ae9fb54ec93bf20a000020045678f95d95679868cc84d96299a0b58e123e9c94088e10ae9fb54ec93bf20a200af23bc94eb59fae108e08949c3e128eb5a09962d984cc689867955df978560401457e250622793189bce9372839a4be7c32717f42412000000045454445fb07cffc0010644801fc0010645001fc001064630013cfc3d991d28803909680da446febc9d5b51c74542a58cb756c3edab85a715297c77ff4e02c9bcf42b5c40299408be68d22cca757ef58cf74f77c9f3085a8e547858c3772041317eac7dcd53f61fca75a5595870b44081a6bb83e78d28c397222c3c2b3015e651e163f62880b000000000569ce8b1a5fddf85850b5415b0435c46e198a8f146b1344bd618c8fc6e9e5410000200569ce8b1a5fddf85850b5415b0435c46e198a8f146b1344bd618c8fc6e9e54120027869aab3935227b4fb89499f881af9bc48c20157d1d897866e21eb4b1c3a210168688f2bafcec3f41d3c087722fc60e45a7dc96700000000010000000000000000000000000000000000fc0001653b01fc0001653c01fc00022f9b007dbc4d6ed0c5a83f528d03638e7fd3ff633a8e4d5a3086c1c6e57c19d3613870421059d308d5b16fd7c588a531c364e9462b46397e5dca10aa10dd9d300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea800012005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea820593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c093de7795dfedb896cb65547535ed92f27489d8df3000000000034187ca2fb4e1ffc000cf99e000000ec83a5f23ec17737f590153eb7eed16f7b2f1327ec83a5f23ec17737f590153eb7eed16f7b2f1327c69a0bda7daaae481be8def95e5f347a1d00a4b43080f8efb42f65ed9650078785be5d13e6e90eb9df87a99261d4de34df2b4b79a9c9b8c5e1aec7ac068ebef14636ceac4c00018feb00404d6f765856c95e587b2523a365bc725801fb8f3001fb05a30631c61e2ebf3d2f3b5022022b304492e935dfa25f9f52d13a45b448a61dea4d0000200631c61e2ebf3d2f3b5022022b304492e935dfa25f9f52d13a45b448a61dea4d2057468a144f4909b986f268cb90e353e7ab55b2c5ae55718362760a3afcb2f7e4002c89477d74bbf943461baf67ad023440a6c585ba000000000074cbc507fb4e1ffc0002d62e0001fc0002d7d400383f1034f0693df2fc8b166d242b00917b7fec07383f1034f0693df2fc8b166d242b00917b7fec072c89477d74bbf943461baf67ad023440a6c585ba30186053ffd90c84db8fb369e1178492b3a0a3941d33c43cd84b839d92668203b6501c786486083eff2b229cec3e0a190d00000000063b57f59d1ff9847f08a7f06d14a5dde1686cb43b6269e2500b2445f83aea7d000020063b57f59d1ff9847f08a7f06d14a5dde1686cb43b6269e2500b2445f83aea7d20112c24c30b2452394fb6ab5c0f9102813f19bc4e47066079329c150b567bfcd3019e735807e679a83188b4ec1b3b65192c62d4bf0000000000002d4dde3cfb4e1ffc000615a50001fc000615fb00766423d2a57121314b7b8dbea06fb83e5bb32d57555ac4d7829d25f1fb6c3abb84a180f5cf746f3e9e735807e679a83188b4ec1b3b65192c62d4bf00300c1c54b5377e920076f2fec26824a5d15ff6144dc106185a614e60fd9722d7577609ae202168a02a50ec45e01f5b7e6b0000000006a45723cb72c6dac0d839223ffb9a9ebba95d257a92537dcb7baada7fa744b300002006a45723cb72c6dac0d839223ffb9a9ebba95d257a92537dcb7baada7fa744b320a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e40841087a740cb6221d73791c04f925366d62815ad0000000000235ac1a9fb4e1ffc000ccadd000000eee87111a02be65095125160059b010ac7ca3d30eee87111a02be65095125160059b010ac7ca3d3064f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d7300e9855b2ee991f988e446b60dcd637f33a782baf1e755785ca058f0398133bf3a95e4e77d4168c13c47d7e3fb1e3ecfc0000000006ae5ed69b8a8eee0cd37f7b642989834cd1e139d1aa9de23db9a627c2fb95ad00002006ae5ed69b8a8eee0cd37f7b642989834cd1e139d1aa9de23db9a627c2fb95ad20ef3191fca4f21577e7acf2af43a36ad7f2fc0112c86ecc24e9985136201cf8b100a84773e6457d1e33d424b397108e9f462aed85cf000000000034287e22fb4e1ffc000bb3b40001fc000bc76b003db48f21a053984465132097e8e9e8b049a3d0133db48f21a053984465132097e8e9e8b049a3d0131ec5c66e9789c655ae068d35088b4073345fe0b03019bfb0fe221451734fa025e4c778fce35e56f89a1595df9cb6c0f94b76deafc6ec438c83834c9e9cf3363ee48d749c23000000000742f64ec887a0ca73a4bfbce78eb34845cee638ab574921ca260f8e218f34d10000200742f64ec887a0ca73a4bfbce78eb34845cee638ab574921ca260f8e218f34d1209602ae8d8c7e8d90259c444837e3f7bb39a5e6b4f1b2cc2b963fd42cd6b23d6f018125767a2e37003a592c97e8c4522269989e236900000000004d173304fb4e1ffc000ca6e001fc000cb48f01fc000cb5a30071a28ebfc5b60e77b6e5b853f8e0e47dfd21bb719fadaadbe9448ec9a703912e80e3b90f36519de2b802ee81026bdd6abe5b6296b993c8b4c02cbd153012271e7f58e6f7d3e2b7bf724729808642a16369b4ad22de438ed38df62b415a92bdcbe7923a858532eeedb44bf12c120000000007d22e8dadd5aa686a7b3bf833eb9bdddf4aad71a79992cbb99bf52f1e42609c00002007d22e8dadd5aa686a7b3bf833eb9bdddf4aad71a79992cbb99bf52f1e42609c204dea6406996a98efea88a66bddbe7f9568093185b08c865b1b664ae0e594c7be09eaeb400fc58666b81179de7c181cea9c63ba55f400000000010000000000000000000000000000000000fc000cf6350001fc000cf8890086a16b7ebc0c836151f6fcd1d21594cd050180bc86a16b7ebc0c836151f6fcd1d21594cd050180bcc69a0bda7daaae481be8def95e5f347a1d00a4b430000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000867e1018f1de184690af3586fc3b4e17cf61614cd926532cc13f9ecf12445230000200867e1018f1de184690af3586fc3b4e17cf61614cd926532cc13f9ecf124452320ba2a81e3cc15c2f44ba26ed842c034219c7070a07e03ad29f6177bf1afa0f3bb0171cc985fc2a69592a7be596af81beded7b914ad00000000000a516d595fb4e1ffc00025b4601fc000266ac01fc00040524006de6137f220482eab495340caf21f19261b1e8416de6137f220482eab495340caf21f19261b1e84186cf2c5c943a6d1d8364fc87e8d859f86de1524030881cec3eab18eaeb916d3f234fae24363b68faa705f51a6efb06f83adef70f73fe28ee70bf4c8300ec4f77f017dbf7f00000000009214af325b2129b52873d9e42fc94ac127aa14da17b1e579d0bee746739136c00002009214af325b2129b52873d9e42fc94ac127aa14da17b1e579d0bee746739136c20aeb90c01cdc9753256874b7e3c8dcd88388b4f5a180608b6a84fb4b5304ea69f0091e45b373304666fd45136542848ca9264f1be72000000000036d4e686fb4e1ffc000bb3b40001fc000bce5b0075400fca445584e71127ad1393fd82a37a82b60a75400fca445584e71127ad1393fd82a37a82b60a1ec5c66e9789c655ae068d35088b4073345fe0b0308d42f142045c5ab515ccc12f2ebbb43f84c822cdd8f98eb5e707d3b334c45018e40b1e2701fcd42ee1189bba2d1d8894000000000ae71d42a6b2956f22a11d20e12dbe309a20fec575aa6023b983fe1b8976ac530000200ae71d42a6b2956f22a11d20e12dbe309a20fec575aa6023b983fe1b8976ac5320eb475a0049470e4629de778010cfc0b305e70d7c5ff6e6731398e26b8fa9ff98018caf465181f5759bf9aa46aa56d8acc5666e460100000000000d3be7c5fb2715fc0003a9520001fc0003a9d300b0bd96751e06b5f3f3bb00dbbeab1576fc941f5fb0bd96751e06b5f3f3bb00dbbeab1576fc941f5f0af0fa3c6b4cfb31f4667e98c4441ec4a72c635e301438959163472114ebd0f4e72e984527894a871063cefbc8cc492593a7afbf4214538c0618ff8477590f40a3b2155aee000000000b4b33aadb8095af383a8c9c5e63750b8ef4abb5d9c091360d788cf18267fe9e0000200b4b33aadb8095af383a8c9c5e63750b8ef4abb5d9c091360d788cf18267fe9e2032048e6d7e2751d4029bfddd77d06ea72c07fffb2d2a67b73ac1cc499fd10cf9010363c23a16386411774051c4dcfd52af186bfe1e000000000091efeb11fb4e1ffc000153460001fc000241bb009e1a38143b4dffb85126ea5a1d78f957327ddde69e1a38143b4dffb85126ea5a1d78f957327ddde62588a17ab3f917f19afeb8c32fa7c486ab4105a33011d05fff5f406fd207bc8984188894b6bbd32098e58244136519a51c183c70db3d713a33c9a55f8d6993f644fb34ff2d000000000b53cea62f79dbd8b43ef803b9eb1d47a1dec3611f460dba83ba9dc32483f9c60000200b53cea62f79dbd8b43ef803b9eb1d47a1dec3611f460dba83ba9dc32483f9c620eb2272deb86efc72e1f06244693d51f169c565fd32bf3d84125ce3f6b5df327000a1d87fa55ec32af91687a166746b992beff2c41000000000005fb3fbb6fb4e1ffc0004c8340001fc00052d9300eaa8b45af937c2eefe766f3bc3ab753329aa4438eaa8b45af937c2eefe766f3bc3ab753329aa4438382477245731a85b4a1b2ca6af9e904517d07e973090403255a5c2aef92a899cf01080a78446f07e0a25fe391a81791c37eddba6e82aee9b8b86b7aa4f44129637146221c9000000000bb4178501da3646c2ac908c25dc6d890bcee788bde6b8391ccde7c6486075900000200bb4178501da3646c2ac908c25dc6d890bcee788bde6b8391ccde7c648607590204e98d6d8591e28eff43f5b3d7b8577a632df86aa7b9705eede76fdde90544c5c0141307e80a8d668b0bf3cc98a52f8d85ec8cf5ae2000000000074ca448efb4e1ffc0001fe8b0001fc0002ab7b00408fea2918afc5688ce5093b789cf08823a57ae1408fea2918afc5688ce5093b789cf08823a57ae1c0a84112810ea249524c9060518b76dbee8b86cd308ef072018a444bc1f30885a199087d2e2200ea31acc4659eb0c05cca30f83e4bd940ed27873458fb605c92556883933b000000000c807e5e4c96d56008c2e3de266027c7232d070710868e6751c2ff907a4dba970000200c807e5e4c96d56008c2e3de266027c7232d070710868e6751c2ff907a4dba972087b9b1f14a8ab17354e7504b46b9b654a7e21975f37d4bd3cdad9b6f58a1beb9010c45984a63e92bc430d99a4ecfd2e715b56b8e6a00000000006b9679d9fb4e1ffc0001939c0001fc000194ab00d3f9cdef09c63434024f1da8554f5d0ea8f2c0200df5db4ce6161b24565f0e90a154cb4e38751eebaf5f151f150e533b675c159dda83d2cd6b22c89030088f0bea4590c29e0a8657faea9d5f2e0f79cbe8f1cae3cf9111e84ecace1443ed8dfe136c539019684d9511d1bba807000000000c90176ebed8489ad010c0429751dd46ec7463589ae9023795cc49f98274f8520000200c90176ebed8489ad010c0429751dd46ec7463589ae9023795cc49f98274f852200237cc9e407352476436f36492b64e09d13d7d6acd6725965f5b368fdd55d13c01308e3fe247704d2b44831bfe98d6421c6880e5d241a0000000cebd93f0fb4e1ffc0007675301fc00076a8001fc000af0bb009ce9b000c1432c3b5ad66db07c99e97cec08e568e1668a2c23b7a257d3e1acfe926e7fb5d64b24ea022d6bcddcd53b3ce77c5afe910cad2e92c3cce4300128cccd87ee9fa75531c9d8db129ecdec0931b57d3d521d35df8af82f6972bbca75f3861faecd3b701bf4aa678b18e5017fcbdbc8ad21929157bc68c6ce50170f41bbcc5d0000000cb486a3f478e2baccb3bc755f87b241e9ffe05dd693ba92e4777dd2175b5a160000200cb486a3f478e2baccb3bc755f87b241e9ffe05dd693ba92e4777dd2175b5a1620165a5b17d27d77e492ba93d65de0ffe941b2875f75bcb3ccbae278f4a386b40c00da952b3b45775c0af85fbe2e2ab21549d86beb0a41000000010000000000000000000000000000000000fc000541050001fc0005410700864b42ecaf278c146420dd46bb2c4914328b38827200be0fcbcb2c10e968ea0b5508bc3424c9c68bda952b3b45775c0af85fbe2e2ab21549d86beb0a30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cee39f44c73a6e829fe53ee34a37ee4358ae31c2bbbae2877949ae8729276020000200cee39f44c73a6e829fe53ee34a37ee4358ae31c2bbbae2877949ae87292760220a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e1a2dd7c9995b2e03f9795f30ba18c95833f6ec3eba000000000036bd7debfb4e1ffc000ccadd000000b73068d00c048915c175450c366478f783bc455bb73068d00c048915c175450c366478f783bc455b64f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d730880f24b5e040dcbf86c3f468dd28bf45d9e41fbcd127fad56669d9afe358dcdc26e42f0f8b19997b1741dbb99c553aa6000000000d20e20e6a7ed1999b25f2dee0a53893a462e92170bc13a8b321f25c87d997280000200d20e20e6a7ed1999b25f2dee0a53893a462e92170bc13a8b321f25c87d99728202897d9875cf221b3a813bc7021e962a49338a5e0def2259b99d17e6a0ee2200d019bec606b655f5b5bbd68207755e614a79dbf4db300000000009f4145f5fb4e1ffc000129d80001fc00012a74008442f1717c0be09dd835dcf2e7383c9f1bff46c93e6504110505f16171693fa5f8582c03d7e0450a9bec606b655f5b5bbd68207755e614a79dbf4db33014bf71456476fa02cfe3de9735eaa10513e943db4576667128051f34692ce042c90cbb9dbb268d3ebf89205e5c8e2afc000000000d685a3c70d983d5668e63e80c3a756b10e19228d943fc478bcb9e2e37f97ee20000200d685a3c70d983d5668e63e80c3a756b10e19228d943fc478bcb9e2e37f97ee220cfafd40a2b9ad8fd3ace89a7a408dfe19b93696d6ced7957c2b424937849540000b1317409f33b2b7166f3e3f0651d0c0b93c0e86000000000002359990ffb4e1ffc000bb3b40001fc000bc7b3000d0cc1e8d68b1d6dc7b746ca1dae2a99a5e252760d0cc1e8d68b1d6dc7b746ca1dae2a99a5e252761ec5c66e9789c655ae068d35088b4073345fe0b030989e7cc1586c9cdc8c55cdcf122ef91481fa3d344fb313c1909d3a70e675cdc805378116b48829d287c8e27792c7ea68000000000d862fc048631f81cabda9446c5f94c8c9a559d2107db383379697381816d66a0000200d862fc048631f81cabda9446c5f94c8c9a559d2107db383379697381816d66a20818115fe0e0e7d78b05f07f774480a6e1e7cc609f071e3aa4d7ce41ba05a7a5e01eae7576cf57e066d9a46c1fafd95b339698687ff000000000074cbcc78fb4e1ffc00044ea30001fc0004c97300a86191b01824b41f452f494a6d62026fcfc373f7a86191b01824b41f452f494a6d62026fcfc373f7eae7576cf57e066d9a46c1fafd95b339698687ff30028f3d9ff027351da67047d78254333d5430c022f800ce5530835d1f048721a82d87bfe959b74aa447908e3c3cacb63a000000000e5ed7d2e33f2e0b221648c3f99735afd6762270ff6a35978df389a7f82976d90000200e5ed7d2e33f2e0b221648c3f99735afd6762270ff6a35978df389a7f82976d920a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e6ff44b8561fe1997ac3bd7d42baa68bc1e2d22e77f000000000036d48a4bfb4e1ffc000ccadd0000007d0138cea5135b7e0d5ff96c57483eb5c155f1447d0138cea5135b7e0d5ff96c57483eb5c155f14464f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d73001f24418ec73b09b00514dba8fb18d6d8af1dc2ff93d594bf987911f3b98d659eb43286cd450b7e1ee5978b361660d73000000000e72e0c50a6516ce833427d6100a83eb6f3e0e80234e126fdacf96aa669e206c0000200e72e0c50a6516ce833427d6100a83eb6f3e0e80234e126fdacf96aa669e206c2059902572f2a755ca1892ad551bb5444b4de7be0df294e2dc7f2884940d5f21eb008c7a89bc1f8f97177251dbc8aa45a53e83f7734a0000000000ae22e970fb4e1ffc000cf03e01fc000cf16701fc000cf6e30060800eb548f8267927a424fbcc75e67aad0653bfce7f101b7f075273c892063b1b8571311737a5767f95c0f808aff27883260bfaf9cfe2b84519a6b2308d29637a7883deac9d725e72cc5a1c366ea0dea49bb61dc118d2c2afe7f0916ac7b2516a4ad4bdbe7dfe68533867a866000000000ecf23a896fc8062fc373acbe0dc218c508e3e6fb0bf6d3ac8cbb3f09edd3e4f0000200ecf23a896fc8062fc373acbe0dc218c508e3e6fb0bf6d3ac8cbb3f09edd3e4f20dda17bc4e0a6ddb04f8a833c1fe9fb3aae484bc435452fd8db27cc90d0ae2511016de8fd61834a14f28d1981f188901bca0c6150a3000000000036be1b70fb4e1ffc000bb3b40001fc000bd20300e3ffb4d81895df6f9c29b45115faa19327a44d18e3ffb4d81895df6f9c29b45115faa19327a44d181ec5c66e9789c655ae068d35088b4073345fe0b03085960dddf69493f1302342857508ae1d2f02441ce7d43336d5829fa868e80ed94d77a0008ffe76b16354067952aa5b2e000000000fbea7792604319890cf39e6afed9e0866f33c38bb56424cba1cc27ff462f9470000200fbea7792604319890cf39e6afed9e0866f33c38bb56424cba1cc27ff462f9472047f962f47fc21cba4c4256bb383cf366089eedafe639cf909831042679a7be0f01527cd9e5065a523e44a8e9135c9274a6af6fe19600000000010000000000000000000000000000000000fc0001a34c01fc0001a34d01fc0001c81900ddba67c250a9c4121d546702cc9d29f65007c855ddba67c250a9c4121d546702cc9d29f65007c8558602cef7812c9171873346962583e161da2a263b30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001123e20847f3690fdd917393ce5fe60a64e3f5900cb167ca31a605683d06e70d0000201123e20847f3690fdd917393ce5fe60a64e3f5900cb167ca31a605683d06e70d202bd1a8ceda027ded8260ba896392d67b5cce6d04f0c9c717e560b5d72335816c004551586144b293cb01564f408f51f778a92730ac00000000003695858ffb4e1ffc0006567a01fc0006c05c01fc000bd9b400309f13210e37d13d130867462ed770f7a6957d8a309f13210e37d13d130867462ed770f7a6957d8a1ec5c66e9789c655ae068d35088b4073345fe0b030154fc5a23ca644b5d085ba1fd39eb6d18e070e14a703de84dcdd54bb37746461f5db2f0c949cddd6e3b225029a0342ad00000000113f86cd2940e9638cf59e9e06e9a73aa132b73c78b8b39c28ae2544ab765979000020113f86cd2940e9638cf59e9e06e9a73aa132b73c78b8b39c28ae2544ab765979202ad2e62e05e11789b21b735f21cf420f5410c0e51b163ac218a0ce6620f5a43400d0047699d8198a6066f90ea2f04011d359289e94000000000012e76fdbfb4e1ffc000113a001fc00012e7d01fc00013fec004daf7ca1ba224384b1a8d0ec83d87513ef08b120caca93fb8cc121ec6183f5cb288779a519cff814b2334b22379811352d9988876a6e586d975e7329309273016bb92b9101798bdbaf656bb14f47120241ff9c76d2650da9e399edb4f7bde8238b260a3bd935609e15e2a7c4790000000011de79269062f95fcf9f5185e33736819af5d1f83ff06589016e7992f9a76e0400002011de79269062f95fcf9f5185e33736819af5d1f83ff06589016e7992f9a76e04203363eea84b7a41211f93a8ea4fe121740ff396ad1a8c91ffe36e350930bbc3b1003623e2c434132d7cc18a2473ef9633c9b814f8cf000000000012ec4499fb4e1ffc0006568001fc000b9be201fc000bd4a30068c9612622050d25168f8ffe4f6b6819f7e4817768c9612622050d25168f8ffe4f6b6819f7e481771ec5c66e9789c655ae068d35088b4073345fe0b03002986699f0f7767bd666ae5087aa0c128b41d2e883c46ddef6e4abe8cb7ea470a2dba2a67e93274818d75839a9e631010000000012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a200012012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a2206793cf0a4aff111f1d61a13002686c066afbfe5da974cc7dec8cb4cef736dd8000542bd8c9d87e1cdd3db777d29c35e9903b17727a4120000000d4186795fb4e1ffc0010903d0000006e52a40d2dc4dea0ae7ff2b299283de0f2798b0a12deb4ca2b5a05b6eb2ab25bb5fee75d3287b3df0d5bcbeeb459af40f97fcb4a98e9d1ed13e904c8308a3dbdeee728fdec9cea3508c19ece8d2e8330b666e25666b1766ed5f44609dc8674dab4163e8574f4adf2e936a209d501c623e2d926af5eb52dcc2b931993d3e52714511801c1161c96de3dae28cd7f20ff8c2aa7b94b866d7601fb8f3001fb05a3138195ab6034f5bb94cb48fd7d46406025e17e49f41df40efa13aa0c40cc945a000020138195ab6034f5bb94cb48fd7d46406025e17e49f41df40efa13aa0c40cc945a205a94cc400caa13fa0ef41df4497ee1256040467dfd48cb94bbf53460ab95811301dd55cf012dea9a2f7ebf0237de0b9221cbdc4026000000000023e6538efb4e1ffc0008e9e701fc0008eb4e01fc0009b06300a8f3150f40bb0cabcfae79e98faa3d9d855d9f27a8f3150f40bb0cabcfae79e98faa3d9d855d9f276da7526423ec9db134526f944a3dc9a050d347ee300d554f8bc61403a96326c47b95797ff0ca91971a73f50b9c95837b912d8f0c191a85792f7ae6106fbff7e51d50818b180000000013b50c43c05e0841efa73ed52a2e5e7fc4790bffed05733243927bca596dd7d700002013b50c43c05e0841efa73ed52a2e5e7fc4790bffed05733243927bca596dd7d720b2a32448a7b0ce9868b350e12c6d0bc2ac0869659c31c8e3b1408ec253b6678e00d2962bb5abd70b77f3f33e3ec87f9684c0a0688b000000000036ca6038fb4e1ffc000bb3b40001fc000bcbaa0088b9b93ab35e81bf4152890bd22abfee38fe60fb88b9b93ab35e81bf4152890bd22abfee38fe60fb1ec5c66e9789c655ae068d35088b4073345fe0b030199cca14db47c035d175e38902dc1e3a25d52bc4ca982e4d6aa380337ab683c941842d01e436f66a746c1da20168da9600000000143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f113000120143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f11320593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c13838ddf0c05bbc0edebee7e368f4dc6306d524af2000000000023a417f5fb4e1ffc000cf99e0000007395853c0be5fb0f0348aff8128979368f52b0ee7395853c0be5fb0f0348aff8128979368f52b0eec69a0bda7daaae481be8def95e5f347a1d00a4b430b928fa4e127214ccb2b5de1660b5e371d2f3c9845077bc3900fc6aabe82ddd2e61530be3765cea15752e30fc761ab7300001b5f25f8f70cf8d05c2d2970bdf186c994431d84e01fb8f3001fb05a314bd7ee89d452d76d524dbfc31b6f2526d7c904a8d7bc1cc70d9e3e0b3d47cce00002014bd7ee89d452d76d524dbfc31b6f2526d7c904a8d7bc1cc70d9e3e0b3d47cce20a1e78087eb631164b217b6efe4fbd23722765c2ddcab903537722d183b12610a00a444ea8d94ff116c8c8363a70aac7c27a224da9e000000000022de350dfb4e1ffc000bb3b40001fc000bcbaa00fad0b3a1008363b74993501effde3aa3760ab6e4fad0b3a1008363b74993501effde3aa3760ab6e41ec5c66e9789c655ae068d35088b4073345fe0b03017288f1886c1f8dcf1d1ca73d4586fc143b1a8abd1f438a3f592b17f35f942de3ca9acc93f18cb3f4ba82b12d6313cc20000000014f2f481ca295a5bdb3e3d7f50ff87f205230609c53989da809420b874a17f3400002014f2f481ca295a5bdb3e3d7f50ff87f205230609c53989da809420b874a17f3420d8c62e2deee0738b5f0f896655ea8acc3f8c0cdb486831d94cf221a13caad545010f3771e69d7faf4ef340696fe5074743a262a6c900000000009f59898ffb4e1ffbc4230001fc0001950c009b5722d68e5dae3988ab71e01497235c79f96196a2b7623bf2c1186d629fd3234b1d058a1ae5b372b2334b22379811352d9988876a6e586d975e7329300871c91beabf5c3b98cdb1009763d03f62550e676d20b54c3fde7e50ba97e54b1cd7bf83909932697fba7627a8e583e50000000015d1b166ff3603d1a583f028e9a0b5334a48db7f3272ea2e4d101306e353f74800002015d1b166ff3603d1a583f028e9a0b5334a48db7f3272ea2e4d101306e353f748208e8e515f7025352e7c608479e413beacf0d95cbb964b47e4a98fd27b6b6b628a5be2e173478997f5d3a3289c84783714de82779cd10000000000369ad3f2fb65a6fc0005e6990001fc0006573c006b78d97d6d777cdadb430c72745d53aa169eed8f6b78d97d6d777cdadb430c72745d53aa169eed8fe2e173478997f5d3a3289c84783714de82779cd13018e4c1013002f690ead979628cecef981034bf9277813035637c376ce9dd04b1b379c4abd45bc5ea969a894fa0d0ebc200000000160120d0aa01ae90e2abb2791a313af326274536f930c95e393959598f29c636000020160120d0aa01ae90e2abb2791a313af326274536f930c95e393959598f29c63620a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e192d7ae4aac5e298584fc2e2eddcf2522ac3b8e3b5000000000036cabeb5fb4e1ffc000ccadd000000ae2c14ab7113b1aea921177e509bc59048556b97ae2c14ab7113b1aea921177e509bc59048556b9764f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d730066d57a6451b7800c1c2a6c6e04fe73ec2e1c95e492bacae760ad2f79ca3c30727ec9bf0daea43c08ff1ad6c2cf07612000000001645a3ebdeff58bb478421fe8e33119d10f22f238c9270a1e80ad46fcaa188a40000201645a3ebdeff58bb478421fe8e33119d10f22f238c9270a1e80ad46fcaa188a4207bb3153777f087f2d3c88debb4372f695aed7e3dfd3efca720e8cf4ef14cfd3e0079e8a0e8b5ad86975702bbd7f192c9cac1104292000000000068f8872cfb4e1ffc000628210001fc00062e1300dec4f1bdf91c23a8ed56738a32f2795855bc9827dec4f1bdf91c23a8ed56738a32f2795855bc98270e5c35f6bd12cc355ab5cf466721bb948e46afb9300a5c47983c44aa99ce5f04b32cfbdff42e7f92b1410558559dcbff3ca8aacc3c2fcaf05db6f021a9f335ba05b9af4c5200000000164730f2cb1a5e6660e77d03c2a4fbf4e9dd23a0798fa7697bcd0aae145ec3b0000020164730f2cb1a5e6660e77d03c2a4fbf4e9dd23a0798fa7697bcd0aae145ec3b0200e1d20e176856da05c1af552bb3d15182d45e15962bbba97702537dfaa8b51b00179f83ea215fcf6ad17a7d147199dca75723dacb600000000005350e2ebfb4e1ffc0006b25b01fc000723fa01fc00074c4b00ed358f1398a3cf37e1b3131e7c492161d6892789d593063ca9a226192be390d6841d9fc28f33818c9602f50d8a498a04e95c35af3c2545ffb074865030874a5fe9d0a2d7ec3ce741fa441e2f9a2f1726fbd2d09a000a6dd4828bd4951a82b0bef934716a40d0ff36e4641f9378000000001659e06c825212c9b11325760a18f6ea06194ec4efd603f03d8704f23d818a6f0000201659e06c825212c9b11325760a18f6ea06194ec4efd603f03d8704f23d818a6f206f8a813df204873df003d6efc44e1906eaf6180a762513b1c91252826ce0591601c274b44875713f1f7107b98c82ec14a3738e36d041300000010000000000000000000000000000000000fb36460001fb364b01140b2fea5ae1aa7e6b8ee68a11d2727663397163595d9f40d00a7ea5cca2502a1c5bc47706688c42c0ee80d8e78d59877e5ca6fa6d071f2bbf3037e6300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017013c34733cdafc4feb7f317587cbb891b1027ded099e2dc2e8e1da05ad0f4200002017013c34733cdafc4feb7f317587cbb891b1027ded099e2dc2e8e1da05ad0f42208e8e515f7025352e7c608479e413beacf0d95cbb964b47e4a98fd27b6b6b628a21492077ea3f2aae501b0dfa814c61c5626c09a614000000000034d41347fb65bafc0005e6990001fc0006576c005caf3605e05011b3abef72e467ab5334e74d68635caf3605e05011b3abef72e467ab5334e74d6863492077ea3f2aae501b0dfa814c61c5626c09a61430836747d419d09200e404aa3500fc5d51f044fc01fd1a9f452324c8c14ab90ccd75887b6bae1599cdd458e738a53587f20000000017454490f2e0d86c39e8d0981b1d1b67354a96915a5866c527ba06fa08b43dcd00002017454490f2e0d86c39e8d0981b1d1b67354a96915a5866c527ba06fa08b43dcd2059e4a4ffb2097f50e8636da1d9fb7b58400563bb19ffe74555b42f7581cc2b74006fb36a0176a614d53ec1402019421234316f9d83000000000036b8f747fb4e1ffc000bb3b40001fc000bcbaa00babd4d5499f8186f8b73cba064eb0cfc4deff4f6babd4d5499f8186f8b73cba064eb0cfc4deff4f61ec5c66e9789c655ae068d35088b4073345fe0b0308fd6de82030e06682e2e65de0fe7efe2edde83f5f96c3446716278d240e0bffb9bf33df3d64d36b9cc6649da7bb0b41b00000000188b4f3700c029d93de43a0e865b3e2e800c3bc67718f8d213dd111a9e401cc2000020188b4f3700c029d93de43a0e865b3e2e800c3bc67718f8d213dd111a9e401cc22068cae611582070c7859ca4ff173baee189eae61bcdd27be131df62a3a630d34901d13ab9ef967f44ff97748303c21e421a7f80974a0000000000761f230dfb4e21fc0003c37c0001fc00044d830039935d16dd5f12eb27272a4190608370e212224fa7755e80caba03e54606c89f955d1d4b9b85d91cdbfeb2a85d70b0a32d9cbc6f4b8f1ba6e375065d30831193814d5cddb0268d276281ff7356b9cbe560bbcb6c9c55f12a53b0dfdb60ed5570c9c4bdd39d8a0728dfb2b0596f000000001910a0aa60c10475397dfc5507a1d765070f96efa15e7a4c6ee559461b23ec8d0000201910a0aa60c10475397dfc5507a1d765070f96efa15e7a4c6ee559461b23ec8d201cee1e4ff907fed96b4079561103d57bda553019cca81d84d0f749c60a5da59c0170f9622bdffd2cf2aa9d2e54ca97ae74ff19b54200000000005350cc76fb4e1ffc000ba06001fc000bbb2d01fc000bbb6b00a2e7118000386185b278ec3d5304db462f23cc55a2e7118000386185b278ec3d5304db462f23cc5590cc3f0be1a150f59168adb0236005438c282f9d3090a2a532b28ceb661521902ada94853f1b90c1a7d13d8ce8a40ebec6c7a62a4e22fe5c1019e278750fc93f6808f410d3000000001a5889046c1a29a03a8a40bbe26da1539d1abf53f9b846857c7fede4d5e3926b0000201a5889046c1a29a03a8a40bbe26da1539d1abf53f9b846857c7fede4d5e3926b20a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e70f6e92e766ee782976b3a25db2143060fd0e69c5d000000000036c8dc69fb4e1ffc000ccadd0001fc0011055b00a5c9f61e9276d9a8471b75beae8d0b91b5b1cbb9a5c9f61e9276d9a8471b75beae8d0b91b5b1cbb964f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d7300406e459bfd155c81f9103a1fe076f1261ee7513275d744c133c5d5dfa956b1449f173bd110bbc03673f376593f32a27000000001b34fcc8306280449bae2eda2361fd372380b9b630b272fc44f55105c58f16110000201b34fcc8306280449bae2eda2361fd372380b9b630b272fc44f55105c58f161120eb748acc6851ad16efe38875924bc04b4c3451ac244e1c979217ecc42b2f90460075fb7f518ebf31fc70855f607f7a092e8bef53cf000000000036cb869dfb4e1ffc000656a80001fc00066e7c00e922c71d669bf4aa1fe543345d67d0be170b91eae922c71d669bf4aa1fe543345d67d0be170b91ea1ec5c66e9789c655ae068d35088b4073345fe0b0301622ef0d7145ce02babddc8762f170f46d5d55c151218ffc12aab3ea9faf90dc97bf158a0fe37a3d8c1fc416bf01bffd000000001b8466759e68ad97c55c8c96a24a060a839baf8a014a7ec897ab6fee410e66e60000201b8466759e68ad97c55c8c96a24a060a839baf8a014a7ec897ab6fee410e66e620e6660e41ee6fab97c87e4a018aaf9b830a064aa2968c5cc597ad689e7566841b0138c25763a87e0036a3f5dab27aca1c85bea508e8412000000023f70440fb4e1ffc00081f780001fc00087abb0046d82dfecb82e98abd5b694ffa54558168fa593c46d82dfecb82e98abd5b694ffa54558168fa593c6ba9df01752f7015bb150fb432f598a91f8b22e3300b0a6390cd90308c8b7adc4374fee6d4c1d0f467d543dec6e306922e7e78d06ddff70e6adf6b2410cdaaf0d7fbab39ba000000001ba9b400a99c8ab19e2681db0e868814aa273e8eaa13615979a14c50bbd53f4c0001201ba9b400a99c8ab19e2681db0e868814aa273e8eaa13615979a14c50bbd53f4c204c3fd5bb504ca179596113aa8e3e27aa1488860edb81269eb18a9ca900b4a91b017c706d1b78fadb609fd92ff5929901a706c55877000000000058162c0bfb08aefc000cf9830001fc000cf99b00f74034f58c080be74bec51165c5ffe60ed1a615f96375e263814e1d54fc3297fe893dfb5a9c1a9eb6443411c39e405d2520567d4f6b041c5c550086230b006ed30975f322c830001d1b3c2e2f14a4ef35445431356f1c5b93c2eedd9c7ea24c4429d27d45f2fd701733ffd65540001f2dbd9b0a1f541a7c44d34a58674d0262f5feca501fb592501fb59261be5730f3876206a58161fa0db37e54389324519b2ffbe53a18910d63e5f74db0000201be5730f3876206a58161fa0db37e54389324519b2ffbe53a18910d63e5f74db2075fc3c877547021a42f8a7f69212d570e4b1c261d7ccbd13a46a0e4cd6661de000d1297438fe58cf5cfbba6dae5cca982c28d8e1460000000000235b74e0fb4e1ffc000bb3b40001fc000bce4300dbf20e7b2d642daebba0567c14cda3d4363ba372dbf20e7b2d642daebba0567c14cda3d4363ba3721ec5c66e9789c655ae068d35088b4073345fe0b0300c03388550cdb5148a63bd3f4ba937b05845748773dfd1adf509ab94d5c525e57f8654b723abadd85d2b650f14a8b9cd000000001bf9d1c02dd94bf4784aa6c1b959942ef6acf0ab1a8579be428b01b5fb87bc8a0000201bf9d1c02dd94bf4784aa6c1b959942ef6acf0ab1a8579be428b01b5fb87bc8a20a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e0b14169d588590a243f1ca0618dd35474b06d08daf000000000032703a72fb4e1ffc000ccadd01fc00107aeb01fc00107b130083564ef2fc85085dc7f2a155a64fb5d14d89dadc83564ef2fc85085dc7f2a155a64fb5d14d89dadc64f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d73014e81203caa5c0cc305b5e0f3ae7a388b974a629358e4e83e50a25b2c2a387e3d114c7c82e2b23c25b65585220e63c99000000001c692349b501682aa983907516959bd6a0148c23ff9b8cbd178e1e07fd9275660000201c692349b501682aa983907516959bd6a0148c23ff9b8cbd178e1e07fd92756620a3ff4c5428133a31449bde462aabfbc9c65ac5044e832ca0900819c8a7feb17d01f32dc6faea0264ec91432ffc25183c63b695ab1f00000000002cf298cbfb4e1ffc000b16820001fc000b17d3000bdc4306178f7c576e5904ed9c0643f2faad4ae3a164232c5ce6f1a1448084d628145eedb09f01472567856cdf62ed7325c44bd7b7557e1acb330a63300923d28fcb1fb8b90bf8281f2f50b6a109f2f5b17a4e1653e193ae58980a03b3538ceb82c6b4e1e986ad40d08c63e330000000001ce233bc4e4b8104def542c9ca2929cc95b42a3bff03ce5c3035dc04cc71bbcb0000201ce233bc4e4b8104def542c9ca2929cc95b42a3bff03ce5c3035dc04cc71bbcb20f8607030e04bafa10d798515b6877c0a599fe907b1737cd0db970c8d144e82f000307a1f9ad73350c1489d17a35ceced0d0405aae8000000000023a51841fb4e1ffc000bb3b40001fc000bce4300d5b08c823b75db3900a75e36c0504619e8a47ecbd5b08c823b75db3900a75e36c0504619e8a47ecb1ec5c66e9789c655ae068d35088b4073345fe0b030880423a2ded94f06b02b66e22219495c386733a27f1ebf1d5aea6017cfe510d6d0e0479d2a5acbf410e4d6e85d7d10f7000000001d0adeaf787ed8f6f73fa936c6313ddfa2dd33ea693a2de22bc346c1b73a4a020000201d0adeaf787ed8f6f73fa936c6313ddfa2dd33ea693a2de22bc346c1b73a4a0220a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e3c6c8d7e6bc5c0d0f84af28da5ef358d40f058ba81000000000022dcaf1dfb4e1ffc000ccadd00000068a589741e0d3d06e5aae5ae008f2a8b11426a8c68a589741e0d3d06e5aae5ae008f2a8b11426a8c64f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d7308b7c76ec03f7ae0dc9be41fb9168906ef0d0d4de74f0ad8c5cf0a30483879b5203ae5d7c6aeee5b92998444bc10f68ec000000001d808b8e69cf109e2b25bb87e40e76593d385bec2ef26e9b0672a3c69418c0f70000201d808b8e69cf109e2b25bb87e40e76593d385bec2ef26e9b0672a3c69418c0f7202fa3b3c49a569e0b5d61aeb0dce73c34d2b267de6c03f81dc4509c1ca6d3f7d300337dde5fe7ce3f75adbda925932e38c456e59e8b000000000022aada88fb4e1ffc000bb09201fc000bb20e01fc000bb2230091755d751fafdbf3c4d1e1dc94c2bc198f7b5bb591755d751fafdbf3c4d1e1dc94c2bc198f7b5bb5a683e40cf2b717576d777fd4a81660ac6c7d939c309687b4c357c8faa53e6733e83b77b94e92d2b528047e2e4cad325810b5e4856b7ffabfdf97c825d224992838d7435d75000000001f1443d9f38273f6437fe37eb34c30033fcd51c7e7f563504c8809906e711de30000201f1443d9f38273f6437fe37eb34c30033fcd51c7e7f563504c8809906e711de3209e3bd9b71a626baac323ec5a6216882496eefb8d70c6a1ef95ee01d57659aa39012ef68619350d67f5e1269aeb7d0459317ee69f3700000000010000000000000000000000000000000000fc0001a89d01fc0001a8a101fc00022899000733464b2d4975e9739512fd74cd6747495adf2f4d532ed2827d7bea5c49ac0e1cf57d6dabe11e06219c4fe7634649826ed14bb206cf90cd20d5bc1130000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001f3ead0b52a6e6e289794c0e84dfe988bd88605fb987a919ea4e3956dc4791240000201f3ead0b52a6e6e289794c0e84dfe988bd88605fb987a919ea4e3956dc4791242046867d5c2d93ac83e7ad8a5079e609902a62f394b4c1858324fa459a652837f60137c49591bb612183440470cfa5065e4090d31e290000000000344820cffb4e1ffc000bdf300001fc000bf28b0048022a40c99c1a58ee5371a2cfc1079df5715aa3e1aea521fd5d9c90c17704c6a7b653c6fdd42ce8264726481a36d7c39125bf90457cd47190718d5f301641b24598bd24e49c4c2c59d027567d89f2e7315e53fabafb508e48a93b48f32525fd9dd9266b0ca4bef5d08b9605af0000000020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c00012020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c20593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c117663ee06b0b159308edf41150954372a730aa6a50000000000235515b3fb4e1ffc000cf99e00000004d65ec5142719f58e31f4510dda3c810a84364204d65ec5142719f58e31f4510dda3c810a843642c69a0bda7daaae481be8def95e5f347a1d00a4b430b6e979f20241cbb73de7451779e8e059d9cb75a74b72ea6862d7ac703dc2ac07d86cec39b6e8923b55fd54dbc6177c3a000135d9eb76397d05b43b5cd8da7ccfa8408bc89ab301fb8f3001fb05a3207d97711f4c60a23f5ba1a79bf4b86adceb51bdfc25ce25172c8a311147bce8000020207d97711f4c60a23f5ba1a79bf4b86adceb51bdfc25ce25172c8a311147bce820cb2fc1a392bb538ebcc5d73250eccafe08c96e6e7e209185f6e73ee8ffd84074001738f719112c8fb6fb5e9d66f9b011c24219177a000000000034286568fb4e1ffc0006568001fc000b9be201fc000bd4aa00caa5590bf043919888c4bc0c739482e84d51030dcaa5590bf043919888c4bc0c739482e84d51030d1ec5c66e9789c655ae068d35088b4073345fe0b0301956c264759bd857f9d78d04cc67e42b39e5296bb15f16d0350d741b026ac4a7fa79985eb63c487d91b7ac250dea3afd000000002344c8196ab9a4becdfb3a287a511278581d784b9afda234be289c85463219ad0000202344c8196ab9a4becdfb3a287a511278581d784b9afda234be289c85463219ad20e79944387083c27fe76eed01599c5c4921f40cff7a45e6b62624b97b748730ed005b224c407e486ad5d944af0e7344fd0dc3a20e05000000000022dc4a30fb4e1ffc0006567a0001fc000bdc0b00a988a44ae537e9365e8199cbfe84c453714bf3aaa988a44ae537e9365e8199cbfe84c453714bf3aa1ec5c66e9789c655ae068d35088b4073345fe0b0300d85038bf7b6e4365042c33610afbd181c0729f2107bb7e3e229daa870007757e1851a077e252405ff35373e780815d7000000002356f75f3f35322a81e5b8a37bf6ec59388408f8faa6468075ee5f4026ee0f930000202356f75f3f35322a81e5b8a37bf6ec59388408f8faa6468075ee5f4026ee0f932015842c095193a92bfc68c7b66dce922a9c3a119721ea0f0131727a1633bb982f01cba75a1c4d696337d08874fd92650aae0b7f8226000000000023ac3458fb4e1ffc0003844b0001fc00048ffb00dfeb04f9a4566f877926da380ff6cd983f693747e37b26efc667299ef749a8ffb5a2a64bc48c5236315fddab967ae28ddfb91ddd515c7b89bfeaf2ee3005d35fb7ea96c707d0bb6a9185f575596285d3578af73d43d2940e6ba7a39a60ad5d3a6f5df16449e4f5ba1cbd8306f60000000023dfd9ad3215287b8e08973b049a55a3024058390e1e9c338c98c967e6de38f900002023dfd9ad3215287b8e08973b049a55a3024058390e1e9c338c98c967e6de38f920b6f6b4620ced1393cbbd57400b11c84142d66c9ab6553cc5dd4b21e6add8c96801a62279c8b16cc1c8e38faadd5c7d146e67e5bf3a000000000022db3f31fb4e1ffc000b9ba201fc000ba67d01fc000bd4a30078ef25845ce006d5f5fc3be9773e2f57282f4bdb78ef25845ce006d5f5fc3be9773e2f57282f4bdb1ec5c66e9789c655ae068d35088b4073345fe0b03014e98c3260409c144f2ef15607ca1677c6eecdf723e3f7c99b25e0f561d4a315d25b702e9153524446b0a2514bb09adb0000000023f239d376d072dfcc083c6e012b1aa149a3ab66cb8bd524c2a00fd534a5d26100002023f239d376d072dfcc083c6e012b1aa149a3ab66cb8bd524c2a00fd534a5d26120a83c3da02e42ee3c9c13e27ec391c97a43f6fbb59ca6dab3086f6f6f2180565601f2b65c96c7febf32ea46461feb1b1c0d00516b6e000000000050f0182cfb4e1ffc0006d4c101fc0007015b01fc000701ab0091cf245e465930b748480cf54da8da800e8b49591516fc10404fc6199c750577dabb9f26800c86525748d29ccddd0db9317ce1f8c3f4b8ac69731c4d3094b3e11094b8781908d100194fa8b47659c2ee17720200f9fcdc2804c557d219e87eb68fb0e6db97822f1f73ab7f846d00000000246b31866af114ef8f6d7146a68bf15004c1dbcc7229accd1ad81078547b4d96000020246b31866af114ef8f6d7146a68bf15004c1dbcc7229accd1ad81078547b4d9620904bca9accaa1c0120066b43889cde3737f885679baecd956cb34caa1523842f012aec349ad1f39b61c6116b419d98d1ebfa980fa2000000000022d934eefb4e1ffc000bb3b40001fc000bce2b0057fc65161b69a4d3fadc9c4e75850d5b4ae0256757fc65161b69a4d3fadc9c4e75850d5b4ae025671ec5c66e9789c655ae068d35088b4073345fe0b03017b350c9c4d8b39af2ce0e3fd8d7cb9539a6da30533f8fa7c2aa1c4f6b976f625c6b68e86d95e79bf9c758076569c35d00000000254739a1dfbf7795267e64686dd07cd61c6f87e665efd52e15910fa29b3da3bd000020254739a1dfbf7795267e64686dd07cd61c6f87e665efd52e15910fa29b3da3bd2068d9641221273796f8fbe1d920832c88a3b5b4b95463206485182f648dd3fa670096345fddfd53f65ef43487849a6f469c9eb64136000000000047c6dc82fb4e1ffc0006f4d10001fc0006f51b00eafc007af0360da4457b92cbb8ad08650f20ea4ceafc007af0360da4457b92cbb8ad08650f20ea4c19c2c7d2ac04ffda699922b0d78957ee839ebffa3090f7f3a97069a5090c885a85aa7e8c970b5d3982718dc4394e2de8ecc2d1c38c8ef51a322e6a5e9660eb794af6c404740000000025b1e2cc3dec589720bafa5769d16437e2e5073d63df9659d05199fe22366b0900002025b1e2cc3dec589720bafa5769d16437e2e5073d63df9659d05199fe22366b0920d73d548e5f6c1b4f19114e39bf27e78530faa14c6fd4f019c589805c624556c4014e63b061493879a21b61e49607d988ce43449eed000000000012ec855ffb4e1ffc000bb3b40001fc000bce43001c544de6c1eaa3cbaa78ebceeb76f1c9d9d799941c544de6c1eaa3cbaa78ebceeb76f1c9d9d799941ec5c66e9789c655ae068d35088b4073345fe0b03083cc6e11edd346dcb19cd422faeb218e37568f66ef70656c93d6d43bbd2eb8715a99af27323d075f6b31d955ccb303e400000000262f95031d76363e3fad8c110694a8894077ca0ae98acffc94200b16cba997b4000020262f95031d76363e3fad8c110694a8894077ca0ae98acffc94200b16cba997b420abf84695101d7649a8be1488b7173bcd83a050c4d4735974b6f08c997f1fffa201feadb5e4467d54029de5820c960b2932ba61b58b000000000003e25369fb4e1ffc000607de0001fc00065754000348d6a81e71ebb94c607c7c79d9500f2d689869f98d462531cb02fdc829890da5d5f248c81f961958b2b6e9982851794782fc7102ceffef076d4c15308a50a9ec0042d293ca23c941142561632df2f182445a96d693b70079a085dc35073092d00761156f88a1f269a2d87e7f000000002695fed97527f712995a207d278a1cb7fea614effd3f6d3cacf58052af020b8c0000202695fed97527f712995a207d278a1cb7fea614effd3f6d3cacf58052af020b8c208e8e515f7025352e7c608479e413beacf0d95cbb964b47e4a98fd27b6b6b628a46ba4f939d4efc43e1a17deec2b9695271bd162d14000000000034d41347fb65a2fc0005e6990001fc0006578400c33d559a563e9c22c95585c0f556727c6c5195f4c33d559a563e9c22c95585c0f556727c6c5195f4ba4f939d4efc43e1a17deec2b9695271bd162d143091c5a9a2513c46543acad374e11f69e63df9583e74e511e619355f2cb7c1b9cd7b4c1ddf3f33c28a8c046658958c3a1000000000271b3eaea9e4fa8717b42dc04a257bf689d56e400683d608ff7cec3a34ad7115000020271b3eaea9e4fa8717b42dc04a257bf689d56e400683d608ff7cec3a34ad711520a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e428d9aaf516d9d692b3476014c6f0790a8c609991b000000000022d21a5dfb4e1ffc000ccadd0001fc0010b6cb00476fca90e883f3fa6116515e120c7e4c1b33d302476fca90e883f3fa6116515e120c7e4c1b33d30264f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d73012730062f122f937b29f69536db3ad36980b88004eadc2ca341425d432723d67e53a4f55786c54017d77c1bd1df6b31000000000274ae6ab38ea0f3b8fe726b3e52d998443ba0d77e85d88c20d179d4fecd0b96e000020274ae6ab38ea0f3b8fe726b3e52d998443ba0d77e85d88c20d179d4fecd0b96e20a096901dffaa36cab6566f3a7028c1cb81ab8906b6804a12132666cfb240301301bceb142ede41aa52eed6c38b326e7df12226e01c000000000086d1e74ffb4e1ffc000335940001fc00052b840074f9875462d0f10d60acafc3f64ca89e86e491977f0dddb29235681f498bb64f7bdcee4bee1f4c98bceb142ede41aa52eed6c38b326e7df12226e01c300db6da5d8ee9fb8925f0818df7553062bf35ec9d62114144bc395980c29fcd06b738beca63faf265d7480106fc6cceea00000000289b8c9733345bd0c9855f933d947192f566a6d6bd5ca694d3ae0b5e9d3882f6000020289b8c9733345bd0c9855f933d947192f566a6d6bd5ca694d3ae0b5e9d3882f620a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e1b2f17f1892888740eff564e5925560fedfee93f7e000000000022d254a3fb4e1ffc000ccadd0000001c6031c212e840f9756b8f08e3801cca20b38a621c6031c212e840f9756b8f08e3801cca20b38a6264f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d7300e2825781a496023c8be61f2bf352ad1094afd6e4f84c4ef331bc727bc149a6dd7e23d78944b8b047c03da44eef1c79600000000298bb1ffac5832d9bad4339c93948f449a2aaeb2d66f685836b6bdf4275b6d6d000020298bb1ffac5832d9bad4339c93948f449a2aaeb2d66f685836b6bdf4275b6d6d206d6d5b27f4bdb63658686fd6b2ae2a9a448f94939c33d4bad93258acffb18b2901dbc9cf11f6b96f87c6435430e66384b80d674c380000000000ae22e976fb4e1ffc000c225401fc000cf06901fc000cf6cb0031471f3f5be089945132a63168b2e4feb2cc5893ce7f101b7f075273c892063b1b8571311737a5767f95c0f808aff27883260bfaf9cfe2b84519a6b230925d20af1a6d0ccd3890f0aead4a05a59be22e005b6d732f855311915b351a9153b2c83d84611b2c9958f806c93f7b5f000000002ab90c655fce7462791fd57049fd3477460cf45aec3483dd8f92ac76cbb5b65f0000202ab90c655fce7462791fd57049fd3477460cf45aec3483dd8f92ac76cbb5b65f20ff005bf96c06ff60140f082130050e2c3231178769c841f5d2e7c8936c53214301491707fcd2969c5f8ece1e0102d6f8425336700100000000009fcb1514fb4e1ffc0001aa940001fc0001ab14009406f3c3f3e20632e58e419a5107a5db669cb4209406f3c3f3e20632e58e419a5107a5db669cb420491707fcd2969c5f8ece1e0102d6f842533670013006b2e598c2a16e7394cff63bb9939e8bec49849f2520f97d8de70ed9336625ea0582889be68007e93663685d03d6996b000000002ab9d8594ed6b96aad7e0d89e739e15f43540da076265f22f1f2be892b9af9ba0000202ab9d8594ed6b96aad7e0d89e739e15f43540da076265f22f1f2be892b9af9ba2031b660b28d594534ac630a8e9739ec2d87f054298223188a66f7ab813007545901653e5576338dd6a629c58b7bed6fada76b62919b00000000003ada3c2afb4e21fc0003b80f0001fc0004053b006672b178caabeecb6cbe108c960367333fd237f778a2c01c623373d2761103791484d3ad1164c06d22ee55a30f4a11a8c3fbd3eb1ec76d9ca8ff4ff73004eda2a8c31489e17463ea27c0c39473afe2c9153641028de360eee8ce213d36a14ef8f8b4f85fb2cd70815a9c1f56db000000002bcdbb54e0eba24d0a83a339436d84c916947205535f755f21cc4843ea3d2cf10000202bcdbb54e0eba24d0a83a339436d84c916947205535f755f21cc4843ea3d2cf120d7c8b2f884a83fecc4227138495333e0db8b7125f2d9a306218176604a30f48600481565d75de04c111a345dd844afde2b9a54220b000000000022dca522fb4e1ffc000bb3b40001fc000bc79c0008b5cf180aa32a061e3ad75bc37908a4ff705ce808b5cf180aa32a061e3ad75bc37908a4ff705ce81ec5c66e9789c655ae068d35088b4073345fe0b0300d450032d437d4a3ce7b62b4fcf70599c467722d2a3ec10844d4cedbe6783d39b7180fa294e7b3f819c4b4c293437770000000002bd7d5200b9a5e22d5c95c2c19923e9cff64ed36a1f736372b87d82b2383926c0000202bd7d5200b9a5e22d5c95c2c19923e9cff64ed36a1f736372b87d82b2383926c20451a8c759ac8fd8f333e230268f26808131fc02a734a1fe98b234ddbae4b1375019263a05cc87500b6bd59287c7665e0c84f210c9f000000000022dc8cccfb4e1ffc000bb3b40001fc000bd21b00eca70167cf9b64e7daa3bbefa9fdafb213f5016beca70167cf9b64e7daa3bbefa9fdafb213f5016b1ec5c66e9789c655ae068d35088b4073345fe0b0301066424f46c8c13274c1aa17df6a3fc1ca4fe80d9dac09525ae40670c5a6ca193854ef663940ddf64740fcaf7b83bac3000000002c8126dfa695f9c0da6183451834b6ada03adc05c54c72594187bbf65d8591f30000202c8126dfa695f9c0da6183451834b6ada03adc05c54c72594187bbf65d8591f32095cfedb09499fd9459f4cb839f6fc086a7ab10762181108913f996689914d050019f9db9aeabf86561085372a2ba98078afc0ef278000000000036bd713efb4e1ffc000bb3b401fc000bbd8501fc000bd21b00b2a4ee6e3d9d40899ab18ae6f737c85278d907f4b2a4ee6e3d9d40899ab18ae6f737c85278d907f41ec5c66e9789c655ae068d35088b4073345fe0b0301095623aca38c0609bf75ce889406d896b2d06763728796d1d9e154392e74e16e41716c1dae79d1e321a47ce2e4eac7a000000002cb309db9b7c22b337a7c24aca6a2d730030bef2f3a7c5f104d6c9ffd9ee64d00000202cb309db9b7c22b337a7c24aca6a2d730030bef2f3a7c5f104d6c9ffd9ee64d020d0cdca3ceae80c1da9521a82711b05c63a82a6821b2c1ba4e9d2a529f645bd61003d1eb245b39df4983715e8579b8053ae088176cc00000000007217368dfb4e1ffc000606a50001fc0006072b005871467000cb7d7144ece56406a6d0f8e97360395871467000cb7d7144ece56406a6d0f8e97360393d1eb245b39df4983715e8579b8053ae088176cc30903a0f90f0ee9ee05c0d567eaae8ca9aab5bf0d5d1e0240494f40e4bf954201e48585c5a2897ed76697b4fb95dd993f5000000002cc0a073e9fadb5cea5cc3303b8f85ed603dc6de043f0ec06edab72d886c57cd0000202cc0a073e9fadb5cea5cc3303b8f85ed603dc6de043f0ec06edab72d886c57cd20f2645684284391532fda7db234d517365631647782fcdfae42d5d7ebca78f3cc013c56bfe3279092a8afe0a282c66f1c68c6a331a100000000005fd8ae98fb4e1ffc0002ddc90001fc0002df8400c5871227ddeef90af4d9e891170c4407a5957ca0c5871227ddeef90af4d9e891170c4407a5957ca03c56bfe3279092a8afe0a282c66f1c68c6a331a1308dd3ff4dfb358ca5c5c58f5c163d73482caf44427b62751b18255a456b8edb175f887db87b3b214753045f631db58475000000002d3394ece5ebfb9e2f369fae0c663b01b978f946dfa06fe938f2c292661c94990000202d3394ece5ebfb9e2f369fae0c663b01b978f946dfa06fe938f2c292661c94992005987511f1162441ccd624fae51f48274da77bd4a6a103de7b767a963e06280e00bbae8d6f3091b51bb8bd2e948907ee11744e6616000000000050f017c7fb4e1ffc0005329d0001fc0005340c008c5f76e0794a0729c41142e619663b77948748ab8c5f76e0794a0729c41142e619663b77948748abc66ab236698c66f559ac918689cadae4c8aff0f6301260b9b40d6a39c14c5f52763ef6e98094a6d41ed35660ba24334c50b60cbf18a524aec8bd4d0203c3257e70e193fd30000000002e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb0001202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb20593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c0101e19b30edacc8bd047a72d6b12b79b3f1b2babd0000000000369521a7fb4e1ffc000cf99e00000063f16c50b9cd1dccd8465e1802749bd00dd49a2d63f16c50b9cd1dccd8465e1802749bd00dd49a2dc69a0bda7daaae481be8def95e5f347a1d00a4b430943a88959611417f9e8ce4e664e1d9c6a839daae14f54ae8e78bc5ef6ec1524d116efca49ecd5c57dce31d90015a51ff00011ffbf1d32541dcb8f5555305295704a9ff9adc2401fb8f3001fb05a32f4bf68bcd9f4fe5171f8111a7f007f76d1298c1124b8a85174e64e057a2522d0000202f4bf68bcd9f4fe5171f8111a7f007f76d1298c1124b8a85174e64e057a2522d202c4f5235e6615104fa3709900b96bfc192e6264d8edfbc24f7af6f1d9b2508e900e5ec4a87e9bd6276f5954a87ddbae45e398bba5c00000000003694d7a1fb4e1ffc0006567a0001fc000bd99b0031e5d66a6457e3181b3dc060f5a278bb61a54aba31e5d66a6457e3181b3dc060f5a278bb61a54aba1ec5c66e9789c655ae068d35088b4073345fe0b030978c2c6ad4f75b983efe0be4ff9d9fd5c70645dfe27b4aadbb33ea857e63ae59f7907a9e65850000d968af60e264370c0000000030110b4643c2d8c7521f27ccc2a6a70579bc859087fb95facbb831b3a3d107c700012030110b4643c2d8c7521f27ccc2a6a70579bc859087fb95facbb831b3a3d107c720fbcd42341652da33e977bab8bbef42d0f053f93e9e2748f3f39881d11e28910c017798d43ef1f85193b1a0e5a7ab7853a39d27f0334060000000a6469a72fb4e1ffc000f01930001fc001046630057656569e143ae0cc0419020708c8ce5f4c776e452bfa12608d37422d52423c3a71f9574ffa8267f535e571f5fb89e31f634da8b91769ea4dd252e19308cf6a03c7a0bd8c38c1fc536a013f93afc8224cbfc79d8b0157c7080117ec9c1c60198c3fb3886ec472aeaf80bd5fffc0001c3f93922e89f4bb3869da0c18d8e30dd91019bb101fb669601fb2710302ba9134d9d734e0a76599c9cddfdd1ea2231ff6c152fd5a95c9ec38aa66d02000020302ba9134d9d734e0a76599c9cddfdd1ea2231ff6c152fd5a95c9ec38aa66d02203114c3b632de2d7ece96a92ea26b83b4ea213a9db1eb4fdfc2dcfa84e7cc500900c437a1e129915fbc02e98bca6d8e8fb8d08001c60000000000a5e33fdffb4e1ffbc40f0001fc000196140036c7c737a21e3e6227791978495ea6516da151c9cea287fadf53be3891e7d421908b9a64a5ef3147b2334b22379811352d9988876a6e586d975e732930083997ad0a7d12c5038242eb54f0aa3952ede09814c57b7392adc4db58f4070dc0b44431c20be0636a21ec238436fafb00000000306c038de5c583febcb09b55f527eaffe177acd9d118e8076f61349a305e902c000020306c038de5c583febcb09b55f527eaffe177acd9d118e8076f61349a305e902c208e8e515f7025352e7c608479e413beacf0d95cbb964b47e4a98fd27b6b6b628a0e1e7fc490e774db8c9100bd196291d79699001e24000000000034d41347fb6598fc0005e69901fc0005f6b801fc0006573c0077d7ce66a12ce0c43ee6b3b9116649dba376cbeb77d7ce66a12ce0c43ee6b3b9116649dba376cbeb1e7fc490e774db8c9100bd196291d79699001e2430052abb8468545b0593010c326d358cec47a3079a36c6f5002b2c36fb45aeaa6ef00746d0e73697fef01704d51d8704940000000030bd48a0fe09f6d72a94df8ca9d58e1c9015dc218685f17e2f711a1c8fd3c3fa00002030bd48a0fe09f6d72a94df8ca9d58e1c9015dc218685f17e2f711a1c8fd3c3fa20ade9aaa50015e14f1e50cb83348552efacd55d5f4198c837d8b6e01af95e510501bc1b78aed1c8dde1141a1880702373d656b7e7420000000000235a9f29fb4e1ffc000bb3b40001fc000bd20300941e9b03a9e4597551f4335ad9b6bd400313e19a941e9b03a9e4597551f4335ad9b6bd400313e19a1ec5c66e9789c655ae068d35088b4073345fe0b0300e2f8770da14ae4c8a45692c8939addbeed7a91b3006e827def586f427cc4deba43db8f89cffc5d2ab9196763671c1cf0000000030db7910ec759ca0b32c3ab934092fe50b1fe9af6fbb76fd5efd7a47eab53b7600002030db7910ec759ca0b32c3ab934092fe50b1fe9af6fbb76fd5efd7a47eab53b7620a4bd1cd4f0ade45f968839d7a0f661d603f7c02d2a1c6f659e6685d67d8d7e3b00358bb3c78aa69792b91f6e14efc4dac13b46d557000000000022d1ecfafb4e1ffc000bb3b40001fc000bc79c00a52289f61d0ba312a086112ba5fee4cf65057ccfa52289f61d0ba312a086112ba5fee4cf65057ccf1ec5c66e9789c655ae068d35088b4073345fe0b0300729c8e764d6566a66b65ab3b4467b5e463984c8841d6a93a869848958a052e1acea53bec6cfb00de6f2e0b8cb0491180000000030eded4041e2c494c3e5ae391331b4ea1dc464d50a34d76178d20fe9904d041d00002030eded4041e2c494c3e5ae391331b4ea1dc464d50a34d76178d20fe9904d041d204809ea7f6bb2e840e7a71c40e435edfb9618c79f822165c721dce537b7ce52c601f44f02a47f3e123e3fdbeddf59307407d1b272870000000000a747dfd4fb07cffc000241e10001fc0002433b008d2aefc27102e8b3f7615e419a61bc394fe83ba4ac1a700d32a6ab3f00aebf68573e26613e62a825d458f5157d91f4832e66eb8630ab3dbff95551d8300d731903ca090050801af45465c96d1248532819959a5a97eacb1ce518dcd5c5a21f20676d7c893f81ba672fcfb0f8050000000030fb0b68444a03b7a3a7f079f1445cab153962fdebaf77d9752cd1c08c816c4800002030fb0b68444a03b7a3a7f079f1445cab153962fdebaf77d9752cd1c08c816c4820a2805906f085aa712b452f8f05002dd3ae71648511dc6a88fe742bdf1990edf1006b827aec87ef146557c8528760f9240e747a8b96000000000022d3f475fb4e1ffc0006567a0001fc000bd99b007ab77c02d06ed94aeb677fbafdeaf0f6c0da49c57ab77c02d06ed94aeb677fbafdeaf0f6c0da49c51ec5c66e9789c655ae068d35088b4073345fe0b0300610fa6d1e213d65b653302ee8ea682b7c454e2117939ca77ee122a5cd8a387cc199ed1bc01d18641a05aa1e7ffe74300000000031a74f4cfe217fd8504e6b210fcdf12243828a67191448b649b648f7397da08d00002031a74f4cfe217fd8504e6b210fcdf12243828a67191448b649b648f7397da08d20520e51c4633d678e5ae07dcdeb878c950195be4f521e76a8e8efb802490bc7540105dbe6edec2480181164c7d62edf45068cc3e5a800000000008b3bf941fb4e1ffc0005e2fe01fc0005ef9701fc0005efbb0005d6c86082462b374e1eedaf7f53bd44e95a1f68c522817f1747a9922db608af9f16503bff07798005dbe6edec2480181164c7d62edf45068cc3e5a83082f48df5b39fac4fe299c0741cdf675eb53aa0b936ea147d4883b650596887142e4fecf91087799de85312aa47c6d60100000000324443f3ffc7b3cc689194e0a0acbbcb943482010e6ebe895e3ccaec58525922000020324443f3ffc7b3cc689194e0a0acbbcb943482010e6ebe895e3ccaec585259222018929b9319a3c5f73c75d7696fb45a41da8842a9a1df4a94b6c7ea5ce5e4696200e405f89a110cceae2689f59d7eee20122e7b23d50000000000235a73befb4e1ffc000bb3b40001fc000bcba300c04ced284f6d465e579d8e64e9eab9c0852c0766c04ced284f6d465e579d8e64e9eab9c0852c07661ec5c66e9789c655ae068d35088b4073345fe0b03007cbeec33e4aacfe4a2b4a29b60a7b702bf3735bf48fbb86a2ca883c949c0d2c84b26cffd564411041ee5218f551ce2b0000000032f66942ac8ad4e5d6552e1c22d990c8663deedee1b0f79783ab4ab395f5652c00002032f66942ac8ad4e5d6552e1c22d990c8663deedee1b0f79783ab4ab395f5652c2034ba66b442a95a29eb695c36e912dc00d958f0a7f2ea178d8f8081115c0af1b6004ee9a0820126e33f0b27f53b37fec69d0322eb86000000000022dda8affb4e1ffc000bb3b40001fc000bcbaa009eebe57e4f2f24ec1aa880e2ea00513ab416e7339eebe57e4f2f24ec1aa880e2ea00513ab416e7331ec5c66e9789c655ae068d35088b4073345fe0b0301368e69be7748d2e13f6e6addd0a775062a856a9333dd25a1ca0662decf7bb98a2f3181fa53598fd387da63b5704250500000000339358bbca4d00397e0b4fa1fce5b7af195a8e8e14e79e75a91dc54ca34fd2c8000020339358bbca4d00397e0b4fa1fce5b7af195a8e8e14e79e75a91dc54ca34fd2c820b8ef3ff343c38e2a71c8be729700db41bfeeb0df9e57b48534227c44f6d53db600038ac68f188a776526681ef676fb5d6404d78b4d000000000022ddef7afb4e1ffc000bb3b40001fc000bcbaa0073f6d493ef502c02f82678f82b2d834cb361254d73f6d493ef502c02f82678f82b2d834cb361254d1ec5c66e9789c655ae068d35088b4073345fe0b03083415bb44cad9fc44854254a6bba65b7b34f1226bc3e844685e7e62cd6f53e7a6dc7b12d1fffbad7fe0c135101408d320000000033c82292c562fca8cd876144b725bfab4be9975cd54a5f7903663c2ee60d49fe00002033c82292c562fca8cd876144b725bfab4be9975cd54a5f7903663c2ee60d49fe20e597f8e67bfb6955354448b6d50e77ede36dadef2c313f79cd42274fa195eea001a7283956624e1d51147b90106872fe169291f4e50000000000235b9986fb4e1ffc000bb3b40001fc000bce2b00607f9501a1545d0aae13127aa475a3f25c6d8458607f9501a1545d0aae13127aa475a3f25c6d84581ec5c66e9789c655ae068d35088b4073345fe0b0308800a5f9efc7684c4fce24f11c103b04634b52d008e0272d89d9105d57e6fd8c4079e6a8331f2cc2b8f36b28c4afe3f90000000033ef407d7aa49e2e929285bdbd1dc6e4b8e2e423e0e0f2b28328ae8a8ffbeaea00002033ef407d7aa49e2e929285bdbd1dc6e4b8e2e423e0e0f2b28328ae8a8ffbeaea2084b5cee14786065b3efe381a9f7e0619548c5fe19e68d20532a00b262f8c72e3013b4bdf5074ad4c48e2669cff6b8b5bc260919178000000000088f471a6fb4e1ffc0007e4d20001fc0008df3b00f019d6736feb8fa148524c0b3fa3af0da39ae5aa4f9406e645e1d2a24f68a29124a5ed91782c9208598120ebfed5f9197261ee352b5029f9cacd5983300032db28dfb209566356ae396255132f8f8e412d6a59dd5cde82ca347f4fb2a4713d8a49dd2dd9b8019bc2dd3a62745a0000000034f19e4ac7e1b2abbded7fe0d19991cde34eb7797d8e81fe01d6e73db209718000002034f19e4ac7e1b2abbded7fe0d19991cde34eb7797d8e81fe01d6e73db209718020cafd1d29a6bfb5294fb789c8226d61a2f4b641964f2d2483fe880ebb5d6a506f0176a4e499430b47be702257744898bb3d95e06799000000000003144612fb2713fc0003ac100001fc0003b5eb001dc640b7e408921b2c99d18ec5bfee69e61d85b61dc640b7e408921b2c99d18ec5bfee69e61d85b64217790c6c0655795f7c3d47e42d94c9dae99d4b300fb7164d86058e2b22c4a6f6917714dfa4a2cb4d54bebbf3c9300ebfe1759b33d15b0b68e32999aae19bf0dd92341e400000000036c99a74a4cfec77b2a7438558a8ec53ee09c11833597c1b601c5b00c93e37d600002036c99a74a4cfec77b2a7438558a8ec53ee09c11833597c1b601c5b00c93e37d62002b0140755817c6d71787ea5004a1342bcf6f1ea8626eee46ab8affd15a5fe6901c9d30aa841c8e37e16f8095f20aaeac9869d26d9000000000023af3e6afb4e1ffc0001e72f01fc0003707201fc0004053b0052b7f1604d249547c79a4056b2969ef98e816aba7509e1003c6e1b4f64a954ba6297e4554f3e7359b508db53f0a3f072b00f579a86e813d6af2856f3308f2caf4cf1e01130aa6bcf27784bb36a2b4daea4ada3be553c9b709afcc752d0f34a0c35e3301e8f6a2fb3ca44656be20000000038f8cc9f9bbfc0ea0b35880a727940037849db6f717f146392a2bc3e971a6f6100002038f8cc9f9bbfc0ea0b35880a727940037849db6f717f146392a2bc3e971a6f6120a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e4790853e3887a8aba03562d217ed6db4fd74aefe82000000000022d21ac3fb4e1ffc000ccadd000000ea1e4a53ffa1572af733c63b530860885f9c8ad8ea1e4a53ffa1572af733c63b530860885f9c8ad864f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d730897fc76b69f1ff4b06535e7a4bc7396fb66b33194effbb72214dbefc2c7cd3220ab6cc39fe4630a513879f9f8dca27e300000000393936246926976b4135b6dca4295f45dcf95c875422b70be451f2d51293c7d4000020393936246926976b4135b6dca4295f45dcf95c875422b70be451f2d51293c7d42096e4d1ef906cdfa4084e2a8dfe662116ad8fdf25b395ec355602edc0d72eb8ea001feec80a8a9f80fbb419cd7e118c67524156f51e00000000005fb3a457fb4e1ffc000532300001fc000533f400e8ca11e6c7d6a9e15b9676b534663298040b88b7e8ca11e6c7d6a9e15b9676b534663298040b88b7c66ab236698c66f559ac918689cadae4c8aff0f630847383710ac1786f020769809abad8f93018338eb855c103f5239d75dc2767770eb45709c895c99c0c86d375ddbe478d000000003971dab9691efac06e4ce7a5483131373e84726458924fe48b7d541791693be10001203971dab9691efac06e4ce7a5483131373e84726458924fe48b7d541791693be120926c6d0e0ce17a51dadcdc5be4f4cce0175d8d7a147e294580e3080d6a22f96d00e5cae595965e89fa9f94152f57b315ca504ee1b300000000005c3fb0cafb4e1ffc0011098b000000b29a8f14049a111260586f489d72cfea1ed8ee5d492df4065de3d5d44692934635d826255f7a60f80e7e48253baecd886fd539601fd5e95efd61534d30b92d4ef819fe283a307e6bcd500d8cd35e9a7b779dbca59bd3bc77b3bb3611c370258aa6dec13d0781e0b53c911bde08000161c274080f47a95be5372ef8c69bb60ab1d4ca8201fb8f3001fb05a339741ad83dd791e1e738f19edae82d6c0322972e6a455981424da3769b3dbd4a00012039741ad83dd791e1e738f19edae82d6c0322972e6a455981424da3769b3dbd4a20593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c0826c998cd53845caec6858f3121e5d3a88df6c7a3000000000023a390e6fb4e1ffc000cf99e000000bd9857229d4c0509c753afc85d264fe2e4f344a3bd9857229d4c0509c753afc85d264fe2e4f344a3c69a0bda7daaae481be8def95e5f347a1d00a4b430b6693296894820bdc3c0ae76f357e544847f10a68f0046f53745370dbe861d57e194ddaf7ff7d5e73cc3f240515c448e0001ec7bf3b9bc72eda38c80bb7cf16e294e763e56b401fb8f3001fb05a33979cfb79c4562e819aca69ffae2ea84b9b8f29bd89bdc68be67b88c6f31bf990001203979cfb79c4562e819aca69ffae2ea84b9b8f29bd89bdc68be67b88c6f31bf992067a0592b5510496cb42f2d784cc3b933a0156b10c8b54e440673bb87c57dbb01011353eea2d4fbc06aedc288e493b70de32b3e977f0000000000adc777f2fb4e1ffc000d5e0f0001fc000d5e4b00d8155dce6238737a6af04e068bd92048e68a7f51212e07f7407be541b585ff0a8225fa1afbcc9ac8dc82946c9cee9ab3e8fef5a5d641a57bdf1523c030a73d8c1e640d29e2257042a39bbbac8d867f69ae252e146884816b98ab0d0526ed4992d9cff22ef04878423f66583382000171b5c04007f6af71d99893478feb52df0f5a770101fb592501fb592639a1339d9bf26de701345beecc5de75a690bc9533741a3dbe90f2fd88b8ed46100002039a1339d9bf26de701345beecc5de75a690bc9533741a3dbe90f2fd88b8ed461209b9054ff7839b940277b8eb8211570b2f16850ef729ee635e24d722fbc4a462301852d4f5bcc34685e3583dbbdc92e9bedd3e985a60000000000c6c74af1fb4e1ffbfb1e01fc000107bb01fc000134f400891cbc8a94fa7fea64ca9994870dca0f75bbd075359c348a574176c210c37a25d4ffd917866fb0a3e54445646929fac8b7d6c71715913af443249784300efda51589f86e30cc2305e7388c01ce0309c19a182cf37bced97c7da72236f660c0a395e765e6e06962ecff5a69d7de0000000039b88e537c795f0b093c951539695fd4819a91a542b247ebd3a0ddd6a4c1c43900012039b88e537c795f0b093c951539695fd4819a91a542b247ebd3a0ddd6a4c1c43920bb600d779c7be93a83b9d7878fb38b0b1b7ff1390b231c5da8136b674cde822f01fd9cd0a5165717d4b3a17afddc669f3fd14efbb5000000000082a2e172fb4e1ffc000ddfee0001fc000e0d6b00f5cd552d14676526ef325757eddcfa285b15ac34bf951db34349385992e0303f21fd7240e44e4b0222319c7fcaf88f86259ffd3fa8430e4665f2e1f53090d98ff5c2f2970197ce80ca8cba9431f7dd7cff5d9fc9c4e99c2ed06e598f273d31dad8d8d05655c8b04599495cee2300018e976c7a2f79745d70e41aab1e61cb5f4db4323c01fb682001fb01bb39ec834a6c7ac5ebf5fd885a271e2149099e87e89a9ea30f573b4b699b9399c600002039ec834a6c7ac5ebf5fd885a271e2149099e87e89a9ea30f573b4b699b9399c6203eee0b9d7239564719e9ece229505909d518b38defcf16aa286871b5d6afae03007e345d48c4d9a24dfed5f23ce04963868ae7bc3e000000000086d10280fb4e1ffbc4260001fc0001962b008b7355042f324a44995bb21f9b68d63e4ae3ca6b959ccc5ac3cb8830eec83a7f15d433ac5452d425b2334b22379811352d9988876a6e586d975e7329300617fffba2681e4712782d97b84cb41b722d56089c3f3b3978b8724cb02baf0f67a57e8d1e2f8227d21700f7b10230c4000000003a3e75555ef79cb77c55684587b65a9ef728efcbb443b46fe2e7ed3e660c4a660000203a3e75555ef79cb77c55684587b65a9ef728efcbb443b46fe2e7ed3e660c4a66202cbbc61af11fd5c13e19c53fe37aafb9ec1793a6682273ac1c639ebdb605d36101f8bf45c29243a614283bcb7e6ba1995124d670ce000000000067507615fb4e1ffc0007ca830001fc0007cac3006dfb5ed0a495b0082f54056634d8bc1431d4f00f0aeea2780fdcce25eb1ff50c0edafd09e0397ec1201d032a4c937947e7d6469d39b2092dfcaa0b723087a55d353f1c76f34d45486140b3242762e03d9f688b7be28be4389f552b7a057e3a014f7f654cf7da7260b5ec1c15e5000000003a541549d161a0e134f54db0afaee615530bb6d84e353b82afc9af76a9a393290000203a541549d161a0e134f54db0afaee615530bb6d84e353b82afc9af76a9a3932920fd9f12dc7a00babfb75867303b9e99bed0d2ad149074350c4659612c0b88cb5b00d488c9d5bc5de3c5b9190fec92c5b37e705ce3f700000000008b3b2314fb4e1ffbc8a50001fc0001197c00abbbe06cd2bdb3615599a7576dacf0cc3cad128728c20f725ddcc44c5d6c728b05b886805ca125afd488c9d5bc5de3c5b9190fec92c5b37e705ce3f7300a97f109f81f15cc0b6af0a57ec93cf9f201789fd28494baf1840594d4bb233cb790f4ba434c49ecb6a1ebba61beec03000000003a80d01eee0c4b79f9de8393f0260fe859677b6bda207a21fc3217a9ae4b5a030000203a80d01eee0c4b79f9de8393f0260fe859677b6bda207a21fc3217a9ae4b5a0320035a4baea91732fc217a20da6b7b6759e80f26f09383def9794b0cee1ed0803a00cb3b7402b0dcee772112cfae17e12cda1eae0dd600000000010000000000000000000000000000000000fc000194d001fc000194d201fc0001a33d00e3f6150f12df79d8bf1fa5513edcc000b93d388ae3f6150f12df79d8bf1fa5513edcc000b93d388a2c0be6e924cf853fa531434308f0c389449ec73930000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003aa33cbad1659ba0bdf6530b5ba543592e2f30c5a35cd89fac77604317cff0f10000203aa33cbad1659ba0bdf6530b5ba543592e2f30c5a35cd89fac77604317cff0f1201927dfd5c8e7396db11536e478f4ccba1a05c7cbde3fcd5c2c98eee94178916d01cfc20de0654c5bb2318915c8f9a3bc3395f84e64000000000074cbc88bfb4e1ffc00035a160001fc00052a63002576863b75bc6a1861ac0a2f0e18ab0d373986b5e5abcfb8f638610b4b5ea0b23d82db8e7560b4003b9fac2da702d7161a178f359f98f0276d9556b1308130957c5939cc5aa59a9d7ebb88a03c8e60175230f87927f9485d452f6c844454148d8efdeb9e3216600b7f6645ecb8000000003ada735b7fb780232ed20e0a96d293385a0793ab7c5c360dd356c98192cc290a0000203ada735b7fb780232ed20e0a96d293385a0793ab7c5c360dd356c98192cc290a20a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e3154cf88c4f4815dbbf2a3912e55b1bd7d84fd8a800000000000235b9d1efb4e1ffc000ccadd0000004c58fc64d6bf36b4cd655f04a3e35ddb1ed7a48b4c58fc64d6bf36b4cd655f04a3e35ddb1ed7a48b64f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d7308c290b31d2e878c2d7235efb0c61f423aa37742a31318e61f8bb0bd6c110a892dc244512fec12a8b0fe7cbb08e12be28000000003b056202a743c16d86aff2f8ef6cf5d402e312f70740b9ae20ae92e47f1de1740000203b056202a743c16d86aff2f8ef6cf5d402e312f70740b9ae20ae92e47f1de17420a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e2945dcbb68ad19e70cbbd741c61b2267e08ba65182000000000022de150efb4e1ffc000ccadd00000042d81ce6e9a394d9a408d1fa828a8bb7bf84d17342d81ce6e9a394d9a408d1fa828a8bb7bf84d17364f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d7300d9ee7b7e66124c4b047e1f93aed5a764ed7384292737ea17f3a7e429ce3f24d602d54b97f72d181b6f093da9b3ad3f5000000003bed128ba5c04b627627cf5d9f1dec0622caef4725d8d9d4c37c65642dce92ff0000203bed128ba5c04b627627cf5d9f1dec0622caef4725d8d9d4c37c65642dce92ff20ff92ce2d64657cc3d4d9d82547efca2206ec1d9f5dcf2776624bc0a58b12ed3b01cf2d268921dbfa2c604c708275f79623d67b0e6c0000000000ae22e973fb4e1ffc000cf13801fc000cf17501fc000cf6e3009c543dbc00467b9451f2e47e7c6f01f7695c0451ce7f101b7f075273c892063b1b8571311737a5767f95c0f808aff27883260bfaf9cfe2b84519a6b2308c9c5c77fe321ff0a115d1ba5bf7462063ef21a82ba796415f4ee538bf9e8a6a49707530c72cbb6b60026c46ff1b9443000000003c7e5634f8fd8af476905ba2e94db5d6b46c41b22445382bf949a71cd16fc18f0000203c7e5634f8fd8af476905ba2e94db5d6b46c41b22445382bf949a71cd16fc18f20a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e15241e1813fbd233ceb15a094365a689154d9b9a0d000000000022ddfcb3fb4e1ffc000ccadd000000055d0c3a48dbbfab9fe7e77aaff5818e4d5a0ef2055d0c3a48dbbfab9fe7e77aaff5818e4d5a0ef264f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d7301130b42d6eb505e811dfb18ff87c4bcacde56b76a7d47a8db88ca26e75f5c2eebdd767d440f375784f9d1f127f57c977000000003c99840d0c2ebb37b76a6a9dce2b876822ef969f7c2dabe67f0e7f071f2b03180000203c99840d0c2ebb37b76a6a9dce2b876822ef969f7c2dabe67f0e7f071f2b031820a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e448fa93403837002c7b2d0de6c44892051489928ac000000000022dd6633fb4e1ffc000ccadd000000c682e285e7a7bd65e9268c1bc695091eb4ce5a8cc682e285e7a7bd65e9268c1bc695091eb4ce5a8c64f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d730121adeaff038746afb470b84fb3a58f1a3bf304cac771d16980845c4902e5da34d366394c8e84a46d8bc0c0a1da23cc6000000003dbb7de94e219e8f7eaea4f3c01cf97d77372e10152734c1959f17302369aa490000203dbb7de94e219e8f7eaea4f3c01cf97d77372e10152734c1959f17302369aa4920b23e38fe428255d0068cc218c2c831e3bfc87c8249f3cba941e126053fd73b8a017aebdd020a3c7d9accde7db5d32c6a06d4c8ee9f000000000034244094fb4e1ffbfb9d01fbfe0d01fc0001195600ecb1486be55e4301c45b87cbad94daa8c5d17fdd6cc4a7bb877a80c11ae06b988d98305773f93b9856bcf3cac49235537d6ce0fb3214d8850a6db77730139b654f0b1c031e1cf2b934c2d895178875cfe7c6a4f6758f02bc66eea7fc292d0040701acbe31f5e14a911cb061a2f000000003ecdbedf3d9a13822f437a1f0c5ea44f290ab90f7c3bb42c1b5fd785b5f9596a0000203ecdbedf3d9a13822f437a1f0c5ea44f290ab90f7c3bb42c1b5fd785b5f9596a2072f157ae4a1ecfc6aceedf008abd5679ec9731abfa05dca49eba50b1c0b6ba860021a6e0e4828963d5f39e3129bbd9e1af873671e700000000006c3dc02ffb4e1ffb1c6501fc0001f46401fc000532f5001bba3b56ededb76c1834f3b3e02c159aba4777a61bba3b56ededb76c1834f3b3e02c159aba4777a6415e1236ed7df54649a880d353acb6f9ccdc622c300634f8b926631cb2b14c81720c6130b3f6f5429da1c9dc9c33918b2474b7ffff239caa9b59c7b1a782565052232d052a000000003f43ff3539e5a4fbcc88c7f031a544fe7e62557b5963cb7e43157ef73abfb13d0001203f43ff3539e5a4fbcc88c7f031a544fe7e62557b5963cb7e43157ef73abfb13d20476ad8662b3be5582b98569b76f66d2eecb59a943e9fb28bcbd23a10d53817bb01127e174ed242c758d4db9b7d5b19c1e0743728960000000000b29d5bbcfb4e1ffc000de50401fc000def0c01fc000e366a008ee38b4c9c407b21612862db1ac4e98a6edacb4b62026629f37f587b1dc70ccbc6732225803db4e3ecc3795b4c3e8c5b840dbfa092df1395237f2f8a30980213c5fa8031aff096b8a3eddeefd0584a0e5c2492f631ef67941e082763250e2615975db1f1bfae631f80d41d839a000100120432e9d299caad204ff1ec0c515babddc28601fb8f3001fb05a33f669abeefbe8527a5ca342037f8f97f5e6c8a65f559936abe546601efdab6030000203f669abeefbe8527a5ca342037f8f97f5e6c8a65f559936abe546601efdab60320106da0d689007410d07536c59586b62f5507aec775cc2a9cb4b73de8b7681cca0091c213cd9929a245bcfc03a9add339a210101ea3000000000022d17c70fb4e1ffc0006567a01fc0006c05c01fc000bdc0b0012e05b745751ccacdbc852c12ab9c3b9feb5b77412e05b745751ccacdbc852c12ab9c3b9feb5b7741ec5c66e9789c655ae068d35088b4073345fe0b0308c6eabbfad80e5acfbaa7a4fc148317f52d80d4249b62b9c3b23ae8592cb7306e798cda7c90dd366ced083618fe2bb8c000000003f960fd8d414906a260cd07db16f743f65306823355b61b5d3ad4bdcf91845490000203f960fd8d414906a260cd07db16f743f65306823355b61b5d3ad4bdcf9184549209c8946bb69fa334913c78c08bcc2ce898861e57a316b6edf4b3f4d6d8de49d33013f7a3f24310795b901908ce57d40dae9d09dc59100000000010000000000000000000000000000000000fc000196f301fc000196f401fc00022899007118238bc3182204c634d9035a968e9b59cd11971db884e38658de13612ec46d636c67f26d3c43ab771e413eefaafeea2aa4c0ecf2fad265164e83f330000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fe25a5d51edc1942b3e68170fd693bf8068968ca6e1be3a1721bfe5ac8416420000203fe25a5d51edc1942b3e68170fd693bf8068968ca6e1be3a1721bfe5ac84164220cedb19ac5ae1a42eff8e7bc39aa68803f6828db1549bf1f17f041816c961f8cf0163df30d171377fbf7611b741436a40d70969a98a000000000086d15a70fb4e1ffc0001aa9401fc0005f08501fc0005f34b00d71dc86bda7e222f78c9e45f22deae9437028650d71dc86bda7e222f78c9e45f22deae94370286501bc18ed01b8e3a9f78a209e7eb7f07edcdacb0ff3091386d3acee0bf9044cce40a07515289589b68fc9b8c8e5d184471ed7982106b1e11587af4c9e983883baec00b67e473000000004008a18371798ba28da7c9a581daf0aa92c4ac0b980c3438936823274f64dfef0000204008a18371798ba28da7c9a581daf0aa92c4ac0b980c3438936823274f64dfef20efdf644f2723689338340c980bacc492aaf0da81a5c9a78da28b797183a10840019bec606b655f5b5bbd68207755e614a79dbf4db30000000000a5e30a44fb4e1ffc000123a90001fc000123e300207d0b14af27f5a735cc27f37c29428f99fdc25c463b7729308cbc30c9c199ccee5a77921bb0ace59bec606b655f5b5bbd68207755e614a79dbf4db330121af4d4c49a65e1439a27ce0f39a2eca5ff751e9998c0fea7a3c2b13731cfa47fc6a56a313a38b448f3792fb60dc11700000000400c7f8990e6f8a3993b7d5900ea0b58e18bf86ba9b147bdefcd0df4cda1887b000020400c7f8990e6f8a3993b7d5900ea0b58e18bf86ba9b147bdefcd0df4cda1887b2017808983e70240144c4c811a1c3404d9d2f1395dc937dd761dc437d80e07928401d45a97fcf480feb7b262a80eda5b78a2a1a0621600000000005911296afb4e1ffb392101fc000124ed01fc00013d4b00724befff5e89d92cbad3cb0cc8281020b0243bd8724befff5e89d92cbad3cb0cc8281020b0243bd8d45a97fcf480feb7b262a80eda5b78a2a1a0621630848bfbe1bf50debe1322e14c9115adb3b96e5b8a3ae96beb7e2161281d9e56c30e43478d6f39835e3533a1c54377258b0000000040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d00012040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d20593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c02024eb44eadf4a67de93988f1400bfd5fd6fdbf830000000000340ae50bfb4e1ffc000cf99e000000f37ebd7e83f4185ccc5fb617a7ac9e09c11ffc12f37ebd7e83f4185ccc5fb617a7ac9e09c11ffc12c69a0bda7daaae481be8def95e5f347a1d00a4b43082f60dad4b7b498379d1c700da56d4927727eab4387a793b861a96df47bdabe5666c270acf04b5b842ab54045bbf102a00013e8b10646ee9d6c28d75c280b357dd3a9ae9f96201fb8f3001fb05a34106bef7acd1243652495260325ec3baf5bba47bb6e5d934c67b96bb24e3af1c0000204106bef7acd1243652495260325ec3baf5bba47bb6e5d934c67b96bb24e3af1c206658709bcdba4349bbf6d9fad0c66006993521ad1b989113855bf751a5ca1ff301f153617d41645e0e25985e35c09f98960f1863dc0000000000c3c91328fb4e1ffc00044ff60001fc0004c9730032b8da1c9e22be858fa29f61e92d6d48eb84e27032b8da1c9e22be858fa29f61e92d6d48eb84e270f153617d41645e0e25985e35c09f98960f1863dc3098e7dca1b8dbcfdc54faff65b94f81f2e3fce6440bb10848d434a96ebe30ccbb33aa586a2d0ddce112e38cb09bbf13c70000000041c4a6b724a0d25cb089ef946b7c1985a2815bc6a4e45f15bbcbd445b6d10b7900002041c4a6b724a0d25cb089ef946b7c1985a2815bc6a4e45f15bbcbd445b6d10b7920a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e172c58166b1f9c8d9f67b86e3812f98d4bfd86404b000000000022dcbbe9fb4e1ffc000ccadd0000008164fcd1a488ebde9344cbd205ce705bbe3121808164fcd1a488ebde9344cbd205ce705bbe31218064f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d73007df25a28955c903cc19f836a4daa0842d203cfc0dc5ae9b57b8246a4787ee4c98ea3f2586203315d61f4e77b6c80dc50000000041e41c6b6e1b1c43e73c7644ea36eb622bee149ab05693ea487e784614e524fc00002041e41c6b6e1b1c43e73c7644ea36eb622bee149ab05693ea487e784614e524fc207a644e33e16840030e5170f7e07877c4f992de0d330c7ba1568a651edc3c4cbe012c72148f57b165ac7a3a23d0a28ee3baa6675b8f000000000095f8331efb4e1ffc00021d3d0001fc00021deb00df7e1106ceb6cbdd287af2c99fad3d0d9181ff127efda5f8279fc8c7490aa37ed57903870a1f4ee1fd5780dec499c5f53a4222c6e0a5e3bd74097a043099567cfb20c6bed5d20638c31e7e512aedda02649e82f2b955ecd3e34f73c2229b350069f6e74a4304acedddd87997fe0000000041fb85bb67981f4e1fe41e0f7d520bf6df2167c9ced5e51fae33343f98d9cc9900002041fb85bb67981f4e1fe41e0f7d520bf6df2167c9ced5e51fae33343f98d9cc9920cc86f090d7505156acdb61b8b997eac5cbc5c77e72fd3c04ccc0a01a77183f210104b4bd6b5d6e830b55249ec9858328a1a1f504090000000000019f8febfb4e1ffc0002f8cd0001fc0002fa840040374e1c147337992d41ef2dfc974f928bd2d5a607ee5dd8d1e99e4bc8e015d94346580d7cfb1c44aeba71ea426d63532121268dec246f833444bb33308e53b8ab39fcc259aa22b93d1ab4e333353e6d56b9bd4d194985a59e0de5060c1225588a256569848ea421725223711b00000000422456a81d1601f5aab4494d935919058905ffe2dff342e8be1345f5e5b46c51000020422456a81d1601f5aab4494d935919058905ffe2dff342e8be1345f5e5b46c5120f9cdc515389213075782c4f03fad8a5010b7aa4165b804fbb1caae54c1c0f15701e1e77f1b5b7d2696a2836aee5e97b0eaaafe9fd000000000009b8aefd9fb4e1ffc000533b001fc00053d0d01fc00053fdc003d88e6f4cd4c285f48dadba815f581acc2e2df7c3d88e6f4cd4c285f48dadba815f581acc2e2df7cda952b3b45775c0af85fbe2e2ab21549d86beb0a3014f9192c3986e589f919f428c43770c3eca5c4ff3722d967d8f0d4b69ec3ec02fd876737fb06880a54566f5639389972000000004289460073f565eebd310b303cbc14fcee17c4df56a3b09e42888ded565599640000204289460073f565eebd310b303cbc14fcee17c4df56a3b09e42888ded5655996420d0407f4f9a7f087c1dd689e30783aa29dc3ed7da4b1b571dd314adac9baaa61e003b79244bcba351a570b19909002352062aa889ab0000000000235a990afb4e1ffc000bb3b40001fc000bce2b00f039342be55b7297da4170afd2df995d185f699bf039342be55b7297da4170afd2df995d185f699b1ec5c66e9789c655ae068d35088b4073345fe0b0309349d9598c25eb5aa9bc9d29c5c82fdbeefc73d1902ab2eee457b9898933a782f7db5676929c1cf3041db9322c06cbdd000000004292028ae9eb69f51d35a8a0f1cdd625f6dfee2a9ebc7bd4d9b7cb99ecc43f9b0000204292028ae9eb69f51d35a8a0f1cdd625f6dfee2a9ebc7bd4d9b7cb99ecc43f9b20a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e6ef29d62543892b99ae4398060c478dccfc4ce432f0000000000235afc03fb4e1ffc000ccadd000000ecd8bcbf77d0dae7f59c750bf68d5d33a45ddfa2ecd8bcbf77d0dae7f59c750bf68d5d33a45ddfa264f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d7308f70ff352844250e267b31c0ddb83dffd4cac43532194bd47cbabf410ca29fa7f1ecec08c8fde8c0d13910e903016d5a00000000429e8599b012fb642220d2308c8747d148f14fd3d92e169e5a5bce329853ef40000020429e8599b012fb642220d2308c8747d148f14fd3d92e169e5a5bce329853ef402003bdcb9deb0c0f2f807aabe0edf471a0bdaa803cf56fe0e855c2e60c119ee86a011574764041f46b7e8b0a3e77991a49c39f2f47f900000000003419c8a3fb4e1ffc000bb3b40001fc000bd23300f9c8a5855606a8895a4e3efaa42d987b2b7aeb0ff9c8a5855606a8895a4e3efaa42d987b2b7aeb0f1ec5c66e9789c655ae068d35088b4073345fe0b030814562b9c96db22a34d86e5c8db1fa30cf322fc3ccf743d5253f37e1cf09fb6347cc57bdbf221f076bf7c818caeffc430000000042a6958a544309799f965d193372baad8f38120a117e3700ad2d62ded1ed440800002042a6958a544309799f965d193372baad8f38120a117e3700ad2d62ded1ed440820c3448a2225a03a273f6a972bedb320c0eda40dfc46a11cdca62edb64212e1f3e005f813b236a6fbe45983588d7851c9344abe32d9a000000000023a67a3dfb4e1ffc000bb3b40001fc000bcba3009b6fde4a7f45246abc4d043aeab7c7d35934580e9b6fde4a7f45246abc4d043aeab7c7d35934580e1ec5c66e9789c655ae068d35088b4073345fe0b03091b5adb32d0031219fb93e5e8b20219b07b8a7860770e7d8935fcaa32ec36d75458180b71fcbd20a808373a16dfe972b0000000042f67134f85223da03fd3a670e68802d959ec1236fc6317b855d7133df4ee59400002042f67134f85223da03fd3a670e68802d959ec1236fc6317b855d7133df4ee59420a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e3054331ff5356c8a834bc40ec241aacfae8bf5c54e00000000003424147bfb4e1ffc000ccadd000000bb34d97e1f0a6406ea00f10eaced5e3ef227a5cabb34d97e1f0a6406ea00f10eaced5e3ef227a5ca64f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d7300bde30ce81e7c6396e334eb1bd788b683535eefe9911286bb42662c46e3712ddb5c7c24d7998118ae089e804e14efee500000000431514b6af73d8a20f06ce90b838acc055d749d77762adfb29a918dbe7611352000020431514b6af73d8a20f06ce90b838acc055d749d77762adfb29a918dbe761135220319b982bf533a97290333d1a2dbdc0e5d516bd1c2add8c0eaa6d248fd26d732d007a4bcc5bcf61fabd62a57eae55f427a8a1fb8800000000000022d8f465fb4e1ffc000bb3b40001fc000bc7cb00e921c4edd1f6b892477f9b5eb39a324aa6e5839ee921c4edd1f6b892477f9b5eb39a324aa6e5839e1ec5c66e9789c655ae068d35088b4073345fe0b030981f8a7f20ae3ff84c15f27a7157dc2e4935e956ed25166035e012ecd7f0885d961564111704303642151aa6fbdf34f000000000436f16038374090405c95464197b0a756aa8ec72137ddbd21161fcc6fc3c61f5000020436f16038374090405c95464197b0a756aa8ec72137ddbd21161fcc6fc3c61f52025ca852a8da0b2ff4aac4af3ae4088c7ae49c0656371511c187f4de7f1f3b524018bbebe630cc30eee2942c1f398fdcd8ec7ccc8cd000000000003d8c6fbfb4e1ffc000b21600001fc000b42ab006eb2e3cb6be0a0244121fcd374a5dd38e4e0ec33e7cbf5568870f2e301ec84dd720ce2d71d2ef6db3a840c9fab8a7618147fb2f3060fd847cf86f08f3007bab9e0cfd301779007735cfcd14445ef09191df5a8ac39aa177abcd56d20e46f7aff4286ca6ff02f4747c0534dae9a000000004393fb7ebb6fa9df7073cfa5bdd241f420520e1a50e6f3b6f9c436d578bb26e20000204393fb7ebb6fa9df7073cfa5bdd241f420520e1a50e6f3b6f9c436d578bb26e220910cf7ec24b21aa8582d11d9a17fc912cb0f9688e4426100fb96a7e08d3a712c0017c0398111d8169fa33a3eebfaeb34ac7b82109c0000000000235b320cfb4e1ffc000bb3b40001fc000bc783002fa548f62b9105adc27c7c69f93e32b395009dfd2fa548f62b9105adc27c7c69f93e32b395009dfd1ec5c66e9789c655ae068d35088b4073345fe0b03006e17d8852c49d0bf9ca9cb2aa16aadc523dcba6af2db6d774b3092f8522595b72564f777a8d60ad8ea79fa1c817068c0000000043e49c1f2735906dc298e133e1d22e8fe4a2a4b23e05e871deb6e99dd6a924cd00002043e49c1f2735906dc298e133e1d22e8fe4a2a4b23e05e871deb6e99dd6a924cd20e0afab253c2a299493acab401cb0ff85bde56b38d310e86627713c849fea165f0066ca67531d6cf56218281080a0a9903032bb0edb00000000003429c6f2fb4e1ffc0006567a0001fc000bd99b00bcb01d935cf0b393aea40d7f0b39f24f27f364f5bcb01d935cf0b393aea40d7f0b39f24f27f364f51ec5c66e9789c655ae068d35088b4073345fe0b0300c33a73d7e9ef598da0b1b9ad04b12f98da67f75d66f1237866fa64f4586a4b156a83e8c79b38139d32f452dee313bf600000000444d4d1e9850cf19adcf3aa6e01e8a198779eecc8d55fe8bc9715726efc58987000020444d4d1e9850cf19adcf3aa6e01e8a198779eecc8d55fe8bc9715726efc58987203cbfe25dc4f982ee3ce537123108745285809ce3d8e5f71c6049b1b328356808015ee12a27a3bdbea28f50b697200e612dbd4a249d0000000000cf9af29dfb4e1ffc0001167d01fc00011b9701fc00011d0b003cc1fe7d3423d6a9a847723ecdee0368320171ad3cc1fe7d3423d6a9a847723ecdee0368320171ad5ee12a27a3bdbea28f50b697200e612dbd4a249d30958adbe9f954ec23983c4be5788e86e0df30fed1d6852136376b49c1a24e0fe1da1178b23dec4ea098b9e355aba8de0b00000000445e313b262961a5244f30e02946445dfcb52420767688db8aaa6cb5f382052c000020445e313b262961a5244f30e02946445dfcb52420767688db8aaa6cb5f382052c20a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e4184248712d2e21cddf89379ad490e99dafabeccc20000000000235971c3fb4e1ffc000ccadd0000000a2d318258cf9455a414d2fbe30c69f5ce8d09290a2d318258cf9455a414d2fbe30c69f5ce8d092964f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d73012fa57a5676925e8dfe3b340df2132f5844ad9f89594b04efa28fb4fb884fe21f411fa49120ed7a60ce9381a54232a1000000000446395517d8dc7a2fe06ffc2dcb5300c248a324b9bd5bd91532acd77eabb5d69000020446395517d8dc7a2fe06ffc2dcb5300c248a324b9bd5bd91532acd77eabb5d6920e51b139b1838d2b9b4bc77080544cd03c11eeb0c5b70f5af44f33fc940de433901a38211dfb24c64aedfd08760984fee730d6e60cf00000000010000000000000000000000000000000000fc0002ddd70001fc00033e4c016af70254b26589b80f06011b3de26f7fbf715b8e6af70254b26589b80f06011b3de26f7fbf715b8ea38211dfb24c64aedfd08760984fee730d6e60cf3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000447962fd8a1e759aea5e00d0272df10c38deab7fd410c916a2b77eee7276b047000020447962fd8a1e759aea5e00d0272df10c38deab7fd410c916a2b77eee7276b047207ebcb8e4c5a9e6837e65e818f89ccd6063c1c5c3604b073ab60015b7ea7f41fe002c491d6e81334e057e3a1fbf1bb18ef2b90fa19d000000000022ddbfaafb4e1ffc000bb3b40001fc000bcba30075c6a48d5a612acd4bd3feebe0f6da422f685de775c6a48d5a612acd4bd3feebe0f6da422f685de71ec5c66e9789c655ae068d35088b4073345fe0b0308d3a62107f6534da1933eae8fae34d5b2c7fce2a39672e9c4473323f90dd9cfb333cc4d39b45cb220460b63c1d11009b0000000045a9800145a0abd2b8f4fe1fed333f712091bc46b4c1a4ed4c21390ec2ddeab600002045a9800145a0abd2b8f4fe1fed333f712091bc46b4c1a4ed4c21390ec2ddeab620410c3c13c2080484354a44116a425a0582bca2873f9ad8e9e914eaa9962baf6e006fa76977109534ddafa6eef7bb017d4c3a882222000000000036da6255fb4e1ffc000bb3b40001fc000bcba300ddf3baa5c5a1d3992213b6780d5bb228d54c2928ddf3baa5c5a1d3992213b6780d5bb228d54c29281ec5c66e9789c655ae068d35088b4073345fe0b030808963d5165e95a9c68094c7ddf16300ce59f127e4555633603efa4e776b026819e534ec54357e25ab467c9859e2a14d000000004636ed7acbacbc76aba60aa7a1011688fe9ad5fd701d0bf8fc42a502ea3e65430000204636ed7acbacbc76aba60aa7a1011688fe9ad5fd701d0bf8fc42a502ea3e654320cebdbed894cf5595b08368bcaafa6112fa743ac8bf50ec4788f5ae60e7783ac0007733a403791a61f42a529fd3281758a248195249000000000086d10594fb4e1ffbc4110001fc00019493006a6434babd99215b4f98316b3f701ecb7cca0aa2a820f49ed49d977621b499c9fc344f28a9b1c0cbb2334b22379811352d9988876a6e586d975e73293083a6548569b0c410d7e1dec3f4f5a18a0790723a991d3b9477a9e062c660959bdbe5b3c1d231195801b9072ae94279660000000046ce2b4b45b41f52b9e634ebc3e8b37c3e1685dcf53092521050884a2dff406d00002046ce2b4b45b41f52b9e634ebc3e8b37c3e1685dcf53092521050884a2dff406d2013f4687763666394944279985ab891c698a9bffc567be7751a80488f98f0cd210189e26bbc182969b51b8d729c0196c0f7b29811d4000000000036caf173fb4e1ffc000bb3b40001fc000bd21b00f07a6a479a2cd5a6e130d51d128a8ca998d1b209f07a6a479a2cd5a6e130d51d128a8ca998d1b2091ec5c66e9789c655ae068d35088b4073345fe0b030870b84b1994be69b0dcfee35aa1e5d1042ab1407b1eb5622eef0fa248e562220695ca423ef6a41abdeff3d802d1ca2440000000046dbd118b9d9b138a5be20446ae3448e8c41acc8c28411848fc85f563090b19600002046dbd118b9d9b138a5be20446ae3448e8c41acc8c28411848fc85f563090b1962094aa08aaeaa7f1581edad08db7bccb4cb24055fe20dd3c783df878e8f12a0042001bc18ed01b8e3a9f78a209e7eb7f07edcdacb0ff0000000000a516e93bfb4e1ffc0002925d01fc0002aaf501fc00052cd300ad0d1c7493405ae2836390ada4ad0227c8278f39e3bbcadcc1f89ed98a2ada3473bde7dc618cf3a763df30d171377fbf7611b741436a40d70969a98a3097adf3867ae5155b18345e44e277ab26b9a497c7d0cf9b53bdc42362dff3642c922d1d10e277ce6bd407f48bfabac68b00000000484c56b2f30e7a223d5a633d19bb54100bf9bc8a1a6ed1e72ba86c9758558d19000020484c56b2f30e7a223d5a633d19bb54100bf9bc8a1a6ed1e72ba86c9758558d19205b016215386c035a42042a93736befccdb87c30cb90adc3b1279da58ac57cc1401112c35b14433e8a28f70889c6d8ca99095bf0a91000000000036b99e7cfb4e1ffc000cf8b101fc000cf93601fc000d049300f6dfd96165379ea02d0e5650085cbc5765d22df2f6dfd96165379ea02d0e5650085cbc5765d22df2c69a0bda7daaae481be8def95e5f347a1d00a4b43093b18f6658a9d0830057a2a0513c2f4bc70eb0c41df4346fc849170fe0b1374716d0d1ea24726fdce68636fe713ef44a00000000485d33cc5a823b6ed0ac345b93438ecbfc44aea7964ca95cfd998dbfaa16ec76000020485d33cc5a823b6ed0ac345b93438ecbfc44aea7964ca95cfd998dbfaa16ec7620a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e4c9d7137cc2ba84ef788209f51340daf53f40a2437000000000023594254fb4e1ffc000ccadd000000192cc27d195d1a06bd813765887587824d036b25192cc27d195d1a06bd813765887587824d036b2564f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d73015f9da603c572257802a689964ca8f4d96f9b94f33ab75968c9cb6c730a28d50b7bb72ac2cfceee6ab0755ead9cb53cd0000000048c29275ad2ba66954b3ed4d58a29c799da0abcfbbd38da9646079e94610c8cc00002048c29275ad2ba66954b3ed4d58a29c799da0abcfbbd38da9646079e94610c8cc20d3ca56e9eb70d7e9a43a93f27446d29c9017bd3225905e50b1d56daaa6c515c10089ffce4da0663d5e5ae1a930ca9f919b8e7500da000000000088f459e2fb4e1ffc0005e0ee0001fc0005e26b004188469fff56b20349d06ab783d8e44b7e698a734188469fff56b20349d06ab783d8e44b7e698a73776e544e9097c2457f74dd5bf1ee545643d2ceb23090dfa669abbc6504966bf8cc2b4971db18a5052b70475fdd5e6f427349635ccd6b9c7869b52ff3133c5661412ea5ec130000000048eb1b545d87e712edb1382d8bee300aa0bae80bfd0c347920f4afcd0ea34b0b00002048eb1b545d87e712edb1382d8bee300aa0bae80bfd0c347920f4afcd0ea34b0b2093e40ad62d5fad58ff996065d66ba1adde1f4c1d47ab9407614c98f8523d95ff00c8b1d47b6f0a98d16aadcfa32910b454024fb63a000000000023a84ebffb4e1ffc0002199b01fc0005007901fc000607bc0098bbc48b046bf66975aaec4bc7a1d9224d75c75e27ab63981bb3d5f5b0375ebd3c709b95174ec67a253cae727106faa4bf76b0b4f8375091889f671530051b1a638ba22cba300ba0836304586ba5572a525622c4dd49e7178214985277eebad66a371253163e35e93d3b44081b00000000493422474d55896888a6eb24804cf3af1d7479956d6706a44ed80aa5cde12af7000020493422474d55896888a6eb24804cf3af1d7479956d6706a44ed80aa5cde12af72054d645b1fba1e7adff0e213c3fb1de352e6f806fc7c5f9d0b716599b66c7261a01c940f123afaf075e70ab25bc4cbf59248e37e7e400000000002358395afb4e1ffc000bb3b40001fc000bd20300d40244c9f7115897ec1afb80fca9e5c7cbffa2e2d40244c9f7115897ec1afb80fca9e5c7cbffa2e21ec5c66e9789c655ae068d35088b4073345fe0b03007e428808a71ba6201f8bb0a3dd71be6de31816eeafb1108b3710e956db7ef5bcf2fb8bc9976a20799077a24fa847d660000000049f9818da1c1948ffbd964d593b7ef590031b794617e62587d984f61f2fbe20e00002049f9818da1c1948ffbd964d593b7ef590031b794617e62587d984f61f2fbe20e20a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e2339ebe0fa295b303b5b8aadfd91a64d75e46740590000000000235bef4bfb4e1ffc000ccadd000000ec97fc04493eb004db432813f88f3ce6e730baf5ec97fc04493eb004db432813f88f3ce6e730baf564f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d7308c1cc0f5e0a5aea680a170ec945074f5b83d83db4d208854204f57c0de220ceb63b0121bd2a7bdb214228338c575ff6f000000004a7d3e011dcbe58192a8bee91d366c6f3720d8247a7dd586b8a50a0159eec9370000204a7d3e011dcbe58192a8bee91d366c6f3720d8247a7dd586b8a50a0159eec9372026dc073174dba917c013e7e0751c19e58fb1e7f86fcca485b2e96d2933096ae400986b9daca0805a7096a6c63e7873b66f6f49c055000000000022d149d0fb4e1ffc0006567a01fc0006c05c01fc000bd4aa00f2ccd30a71c62243bc1b85b0a7346be5b0365febf2ccd30a71c62243bc1b85b0a7346be5b0365feb1ec5c66e9789c655ae068d35088b4073345fe0b0308979c7c3f2f5778e536fa1136af3a024021cd7be5c6dcfc2d51e84091783a5b512b7f6a2c5851be08437be08d17199f1000000004ac3d41c3b2fb88c4e4c33b465ec1150b43522985fe221f18c4b91b5f7b43cdf0000204ac3d41c3b2fb88c4e4c33b465ec1150b43522985fe221f18c4b91b5f7b43cdf207523a0aad3ec9005879e0066cc09b41e57f3b9fd6110f99de7d485ad8f1f192b0143c1ba3eb8658a4a88acfc9842eef008612bb8a242c8000000b93e96c3fb2711fc000152b90001fc000155c4009b977ce8fb19c58e12c2da268990d358df102721208d9e4d63aa7667b7b67bebf81d9e58e2f4d464b88b7859dca0971128eca01438c8a22d7ff13b5f308ebffc014c8b97d9da8841464d3c7cd09b9f679471a068666c217ec13524ad7ccafa50eb18126c99edcb43fb74e290b901b88b7859dca0971128eca01438c8a22d7ff13b5f0000004ba9ca59a188bca15df2ede79db16e72f427d2f8b6f6786d82d4c64319411e230000204ba9ca59a188bca15df2ede79db16e72f427d2f8b6f6786d82d4c64319411e2320a9fee48733f80aec8d5fa07e467748169501c42f39b051f970827b977e4c68c501f74cd1f9e2fa05c4244dd2489fc836825e9f10d800000000000343bb9bfb4e1ffc000b2b630001fc000b2d1b00dc02c3b908e77a84a09427aaaf15c5256f5b458e1f69134183fab7568ebf7eef6c97f80b3ed603aeab2f3158075540dbf499033592d803e7fa3675a2308b7381340a3e266498248137c146a3c82e36c27c196bac05772dd7b22132912bcfdc1263e2761245b6871b47dba982a6000000004bba47ad7330a358cafe2890f1578f874006a68bdc7b786a7c1d440823e683d40001204bba47ad7330a358cafe2890f1578f874006a68bdc7b786a7c1d440823e683d420ca7dbad69767b30fe851c08c80df2cc8398bcc8c33df2d03bcb810485f3d8d31006e6c9189021b6e38326dff6886104054a110990d00000000005fd916b6fb4e1ffc0010871f0001fc0010874300bd8b7dede4dab5e22b84ee0f3dace1c1021add92c9924137fa318dbfca7cabf3a1127fc358acc74d6e6c9189021b6e38326dff6886104054a110990d308ebfddfa72f3140798b6c0d89190164c4dc569ffdd95bd1dd43e7f54f1405c1927b37b499623b4c806ea396bea40a84d0001b98306c317875b12fae8a85c85eb23269168981801fb682301fb01c14d13a8912d3119f1a9eea95d70a546bc449307af3521dd532c0ecb1ee5a494d70000204d13a8912d3119f1a9eea95d70a546bc449307af3521dd532c0ecb1ee5a494d7203df27e67f50cb6875d7b692c594939cf46afb84f80c3a483181a3235532c325a01c329e938e558a6f1a348468050a6a0a48f8468d1000000000036c8c8e4fb4e1ffb66b70001fb69fa00e855484a6e6f72f6f4793b80cafc202a981fe8c1e855484a6e6f72f6f4793b80cafc202a981fe8c14fc445e107964acb8baf2e91cc87acc92ec7fa6c3009ca23af93ce00a95bfefe790ffca791e093a8c0e79675b103b2a4d06f930433b3f6b15c83f4e2c4b5118fe0c27ca13a000000004d159f983d445130fff5ade93b05e01172ee4c56ee3c5b252277615ac10c4c8f0000204d159f983d445130fff5ade93b05e01172ee4c56ee3c5b252277615ac10c4c8f20313e02ee0e20e1cdbca93d89490c8c9caaba06e6558670cacd259f1c8814007b01e0464a5d60141aeb8650b95a88f576c86ad8230200000000003425a9c4fb4e1ffc000bb3b40001fc000bd23300f062a34a0fb6489242d4679a98a4b853087d6903f062a34a0fb6489242d4679a98a4b853087d69031ec5c66e9789c655ae068d35088b4073345fe0b030848d62d66f87f7de6ad828ffbfbd1432dbc983ce86bba885cabf1114835f6de4614d3cf293d6daa92d98e5e1ca36d26e000000004d5087a16a45ee3434db18ba9be18b627794ea9fcc2ade4411ab0745c587c16a0000204d5087a16a45ee3434db18ba9be18b627794ea9fcc2ade4411ab0745c587c16a20486494877c77a3dd5d80aea481a1dd6821d00eb7785d7c5b0646dfe9cc7c01b901a610254a55a28d50033f2df6b34baf904c3132e3000000000041152056fb4e1ffc000c329401fc000cc8b801fc000ce9c300336788df1ce1418edfb0b8321db1611264010a7b336788df1ce1418edfb0b8321db1611264010a7b7ad529c7f0f78a1f5a4ee5c4f8855dad34d7c535308162401aae703d5bb3f53a7b9c5b65b9a94dbd1c207a8da8f1350200a960d1607e89e50b365afb14cf3b700662342a4c000000004d5fe9da329316db465fb3f4925cd5604dd61335c32f0b7d79bdcc98e71880d20000204d5fe9da329316db465fb3f4925cd5604dd61335c32f0b7d79bdcc98e71880d220a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e50a4cbeb2381d842c9d9e0221395627f391d1581a200000000003422fad6fb4e1ffc000ccadd0000004bd7db8a067386d8bda99986fd6661186757bf954bd7db8a067386d8bda99986fd6661186757bf9564f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d73087be789e5b798cf3a40ff5dc22b0384dc690acadd614067c0f7e6a933b8f0c72c67b3f4b3e666e6fc48369a8161b04e6000000004e440fd1740b4ad578af9d5f11667830eaf8f422898c00d891e3f3cd075ea6130000204e440fd1740b4ad578af9d5f11667830eaf8f422898c00d891e3f3cd075ea61320b1e914db9a6663500db9ff75eba0c6717a9fec4abd9abe995897ca5cd84ec20e00beb09ba540e70a97843006e392a012cb8cbdc70900000000005fd916b6fb4e19fc00108b3f0001fc00108b7b000586047cd6cfc021d742ed07f331cc5e41b6b76d21be19b26057cba9acdd22fabf0d3643e8440b65beb09ba540e70a97843006e392a012cb8cbdc7093090e7cc61a596c1cae0c431f22e92ad1ea142558e6e2fdfd8cba033040a4bc56e58f44ccb3380d10ce89246fb6f1c52bb000000004ee1227ac0f4be1fe27ec0d00601287cbcd3182d3b10db952fec225d68f717b90000204ee1227ac0f4be1fe27ec0d00601287cbcd3182d3b10db952fec225d68f717b920037c32c262a9f798855661033c70a485c9efbab9379458ebd2bc3dce1f2cbf48011f6a174996c5075c827596ea0bfc10a97a071dd100000000010000000000000000000000000000000000fc00067ac70001fc00067af3016398e2e031739ca5378d8b64d33340a99d1317260258f7afa5a4ec575f6781fb2d91fd59f8a409d63e28db34964d56b44c53996dd85877e69c9453ef30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004f4cdd55a71a68183cd6ceb8da6e95c9526e259ce0d243e297ecbeaae0f93ef70000204f4cdd55a71a68183cd6ceb8da6e95c9526e259ce0d243e297ecbeaae0f93ef720b711c40f6d1eb02fff2b03c35a759fa63b3eedc2b47e59191b7e1d0353b814cd0072235a751c82d0d01ab336190bdfd4eceebf4a6e0000000000b23e5de2fb4e1ffc00022f9b01fc000266ac01fc00052bcb00a97f2ca1f2953b0ad3dbc58b12fde33f39a4fbeee0cabfbceeb716b5b558739f218f9516c16918d272235a751c82d0d01ab336190bdfd4eceebf4a6e3093a5eb4a6fb84c13bba4d597a6f9d37f565048a384c94d3b81630c6965a023eb3748b6fed0ebc224f051eb23f50d9ff300000000500bde7398a2ef46b93994f34d3607875321076ee3ef975d5477c3d06b0c1659000020500bde7398a2ef46b93994f34d3607875321076ee3ef975d5477c3d06b0c1659200a73fb35537392612450d065440abe6b192373607da402843c78ceddccb3cca201f958e2271fac8498a057a0f4715f46ecae3993bd0000000000a763b737fb4e1ffc00051ba001fc00052fc601fc00053183003a442deb895344b8c98d1f96db46d73aec73149334e4669b580af3248979acd2db51c30d0794c76ef958e2271fac8498a057a0f4715f46ecae3993bd30822967c827427a4ea722459a6a5d007c5a14e1da4b6fd52417914cdac7dfbc9233dd046cda0c2980d1936cfa8b22920000000000507e64b697d351d57308e00312cb269564502e07fb3a05c501952de3972f059a000020507e64b697d351d57308e00312cb269564502e07fb3a05c501952de3972f059a2034fe0ea681d38ede04970088cdd82161c09e03c24f08d62c08bbecfcdc62ec1b00979be1258712fc0292ed17304a2aa2f05ae762e6000000000036cb2ac0fb4e1ffc000bb3b40001fc000bc79c00491b2884357e499e86dad5fc363b951305570ace491b2884357e499e86dad5fc363b951305570ace1ec5c66e9789c655ae068d35088b4073345fe0b03081baf71805fd63ca4357d12c6b77cd04b70846abd99d8dfa9e8b4469c2d167909399b2efcb32ec817e7fe75324151c080000000051172935cfc699e312ec12338e14d12fd54a5fb4065922055980d8206ded70ec00002051172935cfc699e312ec12338e14d12fd54a5fb4065922055980d8206ded70ec20ca564761a2aae2a77d104426a7843a92995d2d94f7e951d792bb78fc22be0d5c00636bf0d4a97d772962f96c66675629bd3e6578ff000000000022d0be82fb4e1ffc0006567a0001fc000bdc2300587cd605573d22f879d8f02b4fc6901ffa1ce1df587cd605573d22f879d8f02b4fc6901ffa1ce1df1ec5c66e9789c655ae068d35088b4073345fe0b03005e41c9c5f3e90a39f01b6a6723d505378fb3a25e19c0b7915303a1e7da89a19ed0a1c5ea765a6ed2efb3710de56f19b0000000051238bb9e2b68fc822e8eb15d415e97ebc86f769a72c15e0a6e25d9ea8d3847500002051238bb9e2b68fc822e8eb15d415e97ebc86f769a72c15e0a6e25d9ea8d384752073663de296744bdf1a11ef3f43d64e249644ea7499e54a8848baed56d716fc3e002b7856de53d4c1823090c98f8ad79862842c09b54120000000b23ecbf9fb4e1ffc0006b1f900000091448a07a2696b4d310761442aa07e3f2021cb731341a33990289395b5659a4cb30cc07ba002b505288e0340106fb37e4cba12e21c2af87e965ebb8b30ace65ce6933fbafc8686ea9e8ba72bc98f3d07905b4ccfb83162db440308e9255f708ce4f2623b27f9fc04fe11cf605700000000518ebe3158701e981095522cab5941883e56240c8ce9ddd79247fc5efa00af3d000020518ebe3158701e981095522cab5941883e56240c8ce9ddd79247fc5efa00af3d20a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e162ad150d5b108c42779d7e62869b5c32c2352498b000000000022dc764ffb4e1ffc000ccadd00000081a5a6e113fbb398b5dd1a3817a4cd66b955b58881a5a6e113fbb398b5dd1a3817a4cd66b955b58864f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d73096594c4eedb5183b0a4e1e96e45bbe8a042904abea4ece4619cc4c3c70073036adb8eb9130a672481eef6a2143b8761c00000000520c7377bf695cde36a0dc0ddd9aea060ce4a4cdce59022e7d74f501e5fa71c0000020520c7377bf695cde36a0dc0ddd9aea060ce4a4cdce59022e7d74f501e5fa71c020a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e62dab139056dee908016c56f7676e18f04666c4937000000000036bf9289fb4e1ffc000ccadd00000033fe2817ece26659df352c7abdf87f8cb7dde58b33fe2817ece26659df352c7abdf87f8cb7dde58b64f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d730842d732a03847819b1e2675ac48b9af4a1c92b310ecacc42c428ff902099cc47d08ecd4616da55d185463855aee99f7900000000521e7d6a4b937cb19dc62371436f1805c2337a772a5e3884097088b23cb39c9a000020521e7d6a4b937cb19dc62371436f1805c2337a772a5e3884097088b23cb39c9a2016bfb58979d90f27253d7a052b620631266a3f35e1e46fc40ff6481f2acebe40000ba3bc9b96c628693877db3bfeebe29b3ac1b1ae000000000023596403fb4e1ffc000bb3b40001fc000bc76b000fe161af74ed12af85556bae73fd1d3af6a01ea40fe161af74ed12af85556bae73fd1d3af6a01ea41ec5c66e9789c655ae068d35088b4073345fe0b0308d51215f8e1c1f68fc8db92517650a76251c8ee8800de92b97c7f4d29c50eda699c82a7f671b597eb52fe08cad760d6400000000528b059c0430be26babd893fce8850ef5f10ba1b166331aa66de0f58f1bd5cb9000020528b059c0430be26babd893fce8850ef5f10ba1b166331aa66de0f58f1bd5cb920778ce40a708f33b1ed5239b14edeae85497eef97146cbbb8ca62b37873abdb07002300d33f550b325773744b9f8843a65151388644000000000022d1a62afb4e1ffc0006567a0001fc000bd983009678d36b05e068a7aefc08edf11353d6db33253d9678d36b05e068a7aefc08edf11353d6db33253d1ec5c66e9789c655ae068d35088b4073345fe0b03080a3e42e4ef0c3f27fcc7b70edb253590af1ae9865bc936210f0b68f8e7c0690b6ba65daec04e9da61da85ec8865244f000000005346dd62f6d0d846ca8b37cad7e4438d1effa1a61a63f8d55ba93069f560949b0000205346dd62f6d0d846ca8b37cad7e4438d1effa1a61a63f8d55ba93069f560949b20ef27728a1bfbf13abcf7420e3118cae96ca0184ff1d0a796b90c51a543202b0001a01a6124dd32d31434325f8b39e3133ca643b8c3000000000034348bbafb4e1ffc00013b0a01fc00014e4301fc0001517300692ac6d2aff4da4de4a815b41b58369de627380f692ac6d2aff4da4de4a815b41b58369de627380f69a9e3015032f43608f55847cfac26a1926ace9b30847178ed08f0f5728dfe39ba9e3a43555b4c5e8100d825d91bf452bb7dad7bce7e8224fb665abc59cfc74d3bd1e040e10000000053572db6934dd429546362bd33dd18aed1a49b96dd9a8bf0ce1936975991b6b200002053572db6934dd429546362bd33dd18aed1a49b96dd9a8bf0ce1936975991b6b220b2b69159973619cef08b9add969ba4d1ae18dd33bd62635429d44d93b62d5753013ee3c4a4a092ba275cdff0c03b912eb1d83c5e8c0000000000ae22e975fb4e1ffc000cf13c0001fc000cf6cb000d432b7c544c11176c8b543613cc395f4b1bbcf8ce7f101b7f075273c892063b1b8571311737a5767f95c0f808aff27883260bfaf9cfe2b84519a6b23007f818e5c2330ac4e7f0ef820f337addf8ab28b07c9d451304d807feda1d764c7074bccbbd941284b0d0276a96cf5e7f0000000053bb55e972ab4f796aae8c7eed34d09adc55241edeead6c7171c2ada2769c68f00002053bb55e972ab4f796aae8c7eed34d09adc55241edeead6c7171c2ada2769c68f208230f90a0fa0e758f70dcee360ab25c46f3c43e674fe277b60ca7764c5f420840076e959b03bac123bf2ced68c6705fe4fd4e280f441700000002269201dfb4e1ffc0008836d0001fc0008844b00df18a921f89745939ee3f00b9dfc07a167f4061fc291f09365d25227523575b9f07683a28c205a30de9aea4685986edd2c37ee8a3245d8886e63fc663008af8fcaaef14df7bc8ddfae8fbcb1f239040be0ac89d43ce0f27ea3f7a00d1685ffc1075614144e70f02df385a996f7000000005557273f5922d9925e2327908ddb128bcf8e055a04d86e23431809bedd0770600000205557273f5922d9925e2327908ddb128bcf8e055a04d86e23431809bedd0770602011980a810803e9264875774c7b736eafc40e3c0c6d86b719f2e54143874d0299011485ab410c60ed103eb5a0bae666add00978a88140a00000005fde193cfb4e1dfc0004a2b30001fc0004a34c00b0e606ec0ec732170fada5204ef8ef5d1dcf73948fd1a9502c58ab103792693e951bf39f10ee46a9cb4b5cb5765cfbfbc3ae17aeb48f8533bd5391ee3008b66151b81bd6a08bad2e68810ea07014012d6d804859219958a7fbc293689aa902bd0cd6db7a4699c9e88a4ae8c2c00000000055cd64d8a3d53fde1faeb46de639a7478b4559aa9040d37b2b19a28a7c029cf100002055cd64d8a3d53fde1faeb46de639a7478b4559aa9040d37b2b19a28a7c029cf12071f2bf95b4d52ba83c2fac722efd30723f3e99ccd83849006df4045760bc919e002e7e345d77cab6d1ec5e81f17b98f1e4d0ebc4984120000000c1758ec8fb4e1ffc000ac3160001fc000ac34300d2f955d617b4c5687619d9030ff1b9bc39a7fb4ad2f955d617b4c5687619d9030ff1b9bc39a7fb4abb42031cbd012787b56d53dff7a46c1d0b66ff77300a1442ae1b122649814bd8354b4daee4a289220eea514988d6cc93ec6302e346bdc77236c91967ff86362d81b18b1c7c00000000568a820b27ca755a2dbd072d68d0a8bb19ff486b472aca350290ca30ac7a934d000020568a820b27ca755a2dbd072d68d0a8bb19ff486b472aca350290ca30ac7a934d204d937aac30ca900235ca2a476b48ff19bba8d0682d07bd2d5a75ca270b828a5601ae69c3808753ea7dd0e2e3d1565ded12d8eadb9e000000000004030201fb4e1ffc0007581001fc0007586401fc000758930094c7496c719925d805ad2f0a75c837fd9abc52c794c7496c719925d805ad2f0a75c837fd9abc52c754de5d26228df57289545787fa448a7c9f7ebe2c30983bd995f3e1280858f37e33edabbd8ca4d90605e26cb6dce824a2c03f83dd498180085db4168f9e6b4df0b46a7f4f54000000005725d47a054dc1b4d34f719c4f9a5a75b52f08b59b0ba5ad788c1e29bbca0ca50000205725d47a054dc1b4d34f719c4f9a5a75b52f08b59b0ba5ad788c1e29bbca0ca5200e2bea11a7d2fa54cfab488d4cb0e7e5c28d8fb1f17b89b3a5346bdec9b53fd900e4f9a674bedaa1272b51355d8efad13d6fe7653f000000000036bb2f47fb4e1ffc000bb3b40001fc000bcb8b00482738ebae2e214d55bbcd03d7d0e81a7130f955482738ebae2e214d55bbcd03d7d0e81a7130f9551ec5c66e9789c655ae068d35088b4073345fe0b0308397590e589e42728f349a499466c06a7dbc797a07787b79145d6e18ef9859e0b07e64a665a3e1c2b54663ee8dca6bd500000000574a8a1c55a14ef27fbc1cbc52545d9e94944984c1201fba3aeacc309a63660b000020574a8a1c55a14ef27fbc1cbc52545d9e94944984c1201fba3aeacc309a63660b205fd493a731389488c69e721fbe31f8996395311728f8393c97648970b1c3f0af0033cfb3f4008a512c56a47174b23d40700065161700000000003422e1c6fb4e1ffc000bb3b40001fc000bce1300175b30c912de7bbb1a71fb1766ca91eaaab6e8b0175b30c912de7bbb1a71fb1766ca91eaaab6e8b01ec5c66e9789c655ae068d35088b4073345fe0b03009637af6c8533b5329eee8457477bf89386af20149a7f4ad3a76dc74876907cae2672324e816d70b9160e27e335f1bc0000000005855f045dc4db4213f0bd153adf6ce3a02e59a06a3887cf01ff552f81e580cc10000205855f045dc4db4213f0bd153adf6ce3a02e59a06a3887cf01ff552f81e580cc120e75569a4dfbbd1fd45e5f54f03642caba755b5ff7d1e2919f71c069cdb9266d90012da5021d6ab01854ecf7510d834d6ae89cead96000000000012edcc99fb4e1ffc000656800001fc000bd4aa005b7fffe5a92fb181e91ab6fa5cbdff30266c86d25b7fffe5a92fb181e91ab6fa5cbdff30266c86d21ec5c66e9789c655ae068d35088b4073345fe0b03018ea4f800b55d185f2abf9b0df7aee48cdca7089178e1b1ed212f2b561eb2f66d638c64e9a3dec12490c04a4deac6faf00000000585674740dac63692bbb0ea4ee899c575f9883e91fb5ba5ebf26b5b2fb66f21b000020585674740dac63692bbb0ea4ee899c575f9883e91fb5ba5ebf26b5b2fb66f21b202bba3595a323203f3baaf14c9e656a2db305b371f974fd2c08d63559dcb356380181949e154a2d3e19abaadccd78998f419f86075e000000000034dc8558fb4e1ffc00012b5f0001fc0001305c00c1eab1a29d98db4b44708a6db97dfeae5fb123c60e03a8899ae0f3a5771fa41ee75752713e920fd85aad5c1b35da17982597334b504c22752cd6319e3093dac0f5d028eeddeaf4257919511991872523675ab24d1d971af3ab1900f27fc617d1d53a846c32abe1ef52a2cb26ee0000000058eac04dafeed9c30b3397c527714c273323fa036a0ccfe5aa71d5c4fdcc270800002058eac04dafeed9c30b3397c527714c273323fa036a0ccfe5aa71d5c4fdcc2708205529d4297a7587a2a915070b9b6f53eacdb4350d118e5af99b6a2abc8b500029005127e6f29037d8849f2a3be369dd9989e383016d00000000000b7a212cfb4e1ffc000607b20001fc0006087b0044c8afafbb5c35b797e7a8876f8932829f99c6c044c8afafbb5c35b797e7a8876f8932829f99c6c05127e6f29037d8849f2a3be369dd9989e383016d30046e3d8efdf54e1cf182c8eb894c4bc1a2845fd3e8e20a383a80435dd131e34e69ee562cc7f31628960e1ad57fdc538a0000000059d45830e45260a043fdd196f966679f1a63f1b6c28f04563738226bd654865800002059d45830e45260a043fdd196f966679f1a63f1b6c28f04563738226bd654865820a042308e7ee24af38a5afdd588c33e007a0ff9168bc6cdbd7ad29836488c64c6006b4ca496710b456df19d9f8f7bbda99d4a9bbfe4000000000036da68c2fb4e1ffc0006567a0001fc000bd99b00717fb4495269642bdd0e16cbc60d15e31a2802aa717fb4495269642bdd0e16cbc60d15e31a2802aa1ec5c66e9789c655ae068d35088b4073345fe0b0308ba4d80404dae1a9a1b3aa7bb7173ba161b87f3212cc4566bc22ff9cb1253376d8f9edfaab3db702a32741b1bd902016000000005a5b3a5da96d5ee8ec30e9cfe76cf0c407ef040836d2dcedd94c4315c9f07b590000205a5b3a5da96d5ee8ec30e9cfe76cf0c407ef040836d2dcedd94c4315c9f07b5920597bf0c915434cd9eddcd2360804ef07c4f06ce7cfe930ece85e6da95d3a5b5a016cc8146b2b970595fbf4e267afcfc3212002584c410000000012de6f46fb4e1ffc0005418b0001fc000543b40010b27fac0d3106227397fb1cb91eabba630c0a31f0c742302a89db49217e328e18811d0ab1904ac5da952b3b45775c0af85fbe2e2ab21549d86beb0a3080f8dfef131ac329d428504e7cb89974f188f07caef0668df1daa4ca8fc5f50f6c5945f020271292dc220ce313c00f16000000005a608427d3cb472597fe47ed7f9c4b430961bff0e7fd3bbe3a4553375cf2e4ab0000205a608427d3cb472597fe47ed7f9c4b430961bff0e7fd3bbe3a4553375cf2e4ab20abe4f25c3753453abe3bfde7f0bf6109434b9c7fed47fe972547cbd32784605a01118b5a615cdde7e435bb8bd1ee15a7f4c490d21e0000000000ae22e977fb4e1ffc000c225301fc000cf06701fc000cf6cb00c1ad3af209f75deaeb9216fc8339fd48d376f9b0ce7f101b7f075273c892063b1b8571311737a5767f95c0f808aff27883260bfaf9cfe2b84519a6b2308a0ede82d78a0a8f4c2332d431c7be496c3aa09349ed3b2db30f7eb7dcc7b6e580a9d71f7d76bdaca1b3670e0cf4cd3c000000005a6d674367f4fad9883595d74d6eb628c59495a3af0732d24db983359cb7127f0000205a6d674367f4fad9883595d74d6eb628c59495a3af0732d24db983359cb7127f20de14b280405beaa7359475326e337d7fe322e550a612c188c8c33f1ec05ffc7a01b1ec17072d731ed30edac35422f49fc43c6117d50000000000b9c313d4fb4e1ffb89660001fb89da00a6c4b0ce143aed43b6665e086fdabc05f6797a2aa6c4b0ce143aed43b6665e086fdabc05f6797a2a486c5d35a36a1cc86cb1c8946be6c3095b79a544308f53fb19c3be85ce00e96d634221f20a06a3a50942998193004264075a70422a3305f57c0c478a70ad69f1112e2f9993000000005b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a230001205b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a2320774441a2d4ff6133747a8bb1b5e4a9a21bb73c4b77cf31e85bda68f898949db0013f978f2c099e310cac9e854b99bc981c8fdcade2000000000023a5327efb4e1ffc000cfb4d000000ebb7d8141ecbdf2abcdc3ebe25420b9425745293ebb7d8141ecbdf2abcdc3ebe25420b9425745293c69a0bda7daaae481be8def95e5f347a1d00a4b430b44cee83a79fa151527e527f3f4f5ba022e73ae8b0d913c4185a45c2a129aef935a585a7a725edcb36ece72a957586880001f460a07a2b0dc932e1d8ff2dee2b984ac415dceb01fb8f3001fb05a35b5e74eaa81cf214241dc38fda186e7782243b77f112bd61c3e4e83f49f27a270000205b5e74eaa81cf214241dc38fda186e7782243b77f112bd61c3e4e83f49f27a27201059a0d6de258ea8455e3b995cfc62aa2773a3bafd6e1fcc00e9c4c5b8bb9a7d01433d10cc55f8c79b2dc5909099ee24ae9d3f56590000000000037c8ecdfb34a1fc000d6e440001fc000d6e9b001c2ce317e6977a829188866e9d4f82b53b82ac0c90d6c5ee0763ec84de95ae93cdabd1155d9d8f4e972364013299903de8c3a8c504669542ce20fd04308119fe1f9f05f7222f62c4b22a05880a89e4d8b3b8fd3011661df80e46da3ccb2222598129e3e67998883ede2bfe1143000000005be5a28138a658a802a1e871d7bb4a5e8a167effe9e665b4a2ecaa559d01734e0000205be5a28138a658a802a1e871d7bb4a5e8a167effe9e665b4a2ecaa559d01734e20439873740ad2b64a21becf94198b3d570250c8230b4a0ece9e0b78a9035c189b0096fee7f21ab31bda8471cec48b23e87b029d42d7000000000022de6689fb4e1ffc0006567a0001fc000bdbf30028a6d0e9738eb5ac91e4e5e5e715f0b16631396728a6d0e9738eb5ac91e4e5e5e715f0b1663139671ec5c66e9789c655ae068d35088b4073345fe0b0300dd55240db07aa6079e3b84af0d86acf307411f6a99d9570eebec93b6e7e5890db40e31efdca4d5d7bcee1f105e80ea4000000005c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef4360001205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef43620593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c0f62555d44fc8d089674bab5d090a48825bea701b700000000002cef2799fb4e1ffc000cf99e0000007ef7c15840f96c603fcd29409a70f77f878d25d87ef7c15840f96c603fcd29409a70f77f878d25d8c69a0bda7daaae481be8def95e5f347a1d00a4b43086d0a2ca6f434eaa47ff6919ecafa4fc3b012b89c62a04835a24c00faf62c3d30d3f8755c33a7abc595e96fb5b79594a0001972a33056d57359de8acfa4fb8b29dc1c14f76b801fb8f3001fb05a35c6d5b4d2567346b2ada40d2dabbc907cf8a53c352593333e7d1fa8a635572080000205c6d5b4d2567346b2ada40d2dabbc907cf8a53c352593333e7d1fa8a63557208205b016215386c035a42042a93736befccdb87c30cb90adc3b1279da58ac57cc14046094547209833dca44803c3a5b039a038be4034c000000000012eddee4fb4e1ffc000cf8b101fc000cf93501fc000cf95300bfa25fb4ed44c385e69d5d8369a0a7b90d68b4f7bfa25fb4ed44c385e69d5d8369a0a7b90d68b4f7c69a0bda7daaae481be8def95e5f347a1d00a4b43096f1efdb9fbe12961b7f113de6a5e57e6f547a3b27b4b8941a5265ddc51de7b6dfa7eb52ef96fef6503b4a729884ef12000000005cd86ed16f87819dca7b6e4e3d24947b1a6328ed8cc4c9aec7af35fa2b1622200000205cd86ed16f87819dca7b6e4e3d24947b1a6328ed8cc4c9aec7af35fa2b16222020fbae7f5db70dfecd69081854b27514ec0b29f4bab86717174e0220bd7bb9584700b9dd1b5f9c18e8260fd7e7f9f1d9503709f9168b000000000044b7a710fb4e1ffbc4230001fc000195cc0025c8d7361af14d912026940701c3d5d440ae6913069efe06c4c2d7ac2a8c61f961f686a13423467cb2334b22379811352d9988876a6e586d975e73293018af4d035eed23d30eb02808af0c133d9879c0fb82c72329ab2ed208ebc1631641ca42bbf462239d151f4e84d8dcde7b000000005d49c93481f99c7e1d85cde715697762973d9c49d6facf50131e11b2c14c78130000205d49c93481f99c7e1d85cde715697762973d9c49d6facf50131e11b2c14c781320a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e1120959bed4177d7abcdbb412bd8b8e1f920bb623a000000000022d93a9efb4e1ffc000ccadd000000079a7d38b11c6a3e040e4e665150768b8a5faec4079a7d38b11c6a3e040e4e665150768b8a5faec464f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d730826cbf63d989916d252cfc2cf827f34314c32c64acc0c252f1c3d42019589650c3ecb098655ba153dbc04211a1a73e88000000005d906997d8b370d37f813ed55c664457fc98acabfbf5e5602952f710b54bd4e50000205d906997d8b370d37f813ed55c664457fc98acabfbf5e5602952f710b54bd4e520a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e3d6ca51bdcb6817cb4f722a45a7646fa5070ee902800000000002357ee76fb4e1ffc000ccadd000000431c84baf52eb97d5546ed1ee44872c30772a30a431c84baf52eb97d5546ed1ee44872c30772a30a64f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d730155b2a1aa71cbb3b5fc81b00242805a6d573826679a2b6a5c49bec714829322efe8af0c1640ba3b59811c70e17b488a5000000005dbd3e1adcef3a9e61ea1c8d0d3bed643ab3a36872ad78905b009cd6dbde6df50000205dbd3e1adcef3a9e61ea1c8d0d3bed643ab3a36872ad78905b009cd6dbde6df5208e8e515f7025352e7c608479e413beacf0d95cbb964b47e4a98fd27b6b6b628a275615f5efe0555e81f7799ff3e1017eed0f5d8160000000000034d41347fb65a7fc0005e6990001fc0006579c00d0a7d804064376431fc57385721270a55fd99154d0a7d804064376431fc57385721270a55fd991545615f5efe0555e81f7799ff3e1017eed0f5d816030119d599048331efb5bd38ea0506ac51765eaddf396114dcf14fbbbab70b7a929c9227f8ec980851ad79f502d2fd1750a000000005dd021fc25cffa8a8fcc138726d3771d7a11ed67826ef92f8cce1deeeb8994cd0000205dd021fc25cffa8a8fcc138726d3771d7a11ed67826ef92f8cce1deeeb8994cd207d3a61ee47e7406247f3c530c94eca04fb61215407084d494fe341e0bd6e6dfb00e64dbdd97978ca06825948e22965eaf261f75e3e0000000000b2077c28fb4e1ffc000732760001fc00073283006d40952f2f57e3d63ad144d4171de75dbad6871c6d40952f2f57e3d63ad144d4171de75dbad6871c3b8fed059edc3b85af8bc75de109566b89aef260300cacf46c91a350240272bcf66d48eafd77c78ab71185ca41769621116c8dae8b29732fb998cb6547f3fb27b556c660ed000000005f8457a7640a8e99840193865a971146d9e25a97d8dfd6f0f1f73b18fd962c440000205f8457a7640a8e99840193865a971146d9e25a97d8dfd6f0f1f73b18fd962c4420e77f5d18d3565f6130ef095290517a91b9591ae927defeafd6875daade6ee39601609b88d96948cb06b59241d773a085b72f416caf3f80000000b951a487fb4e1ffc0007d1f4000000d45e1d0d83cae06f0c68b0dfba62807d59214bc0fbe729266f43adfcdf3ede4f478c7a0ef915cd460d5bcbeeb459af40f97fcb4a98e9d1ed13e904c83097d5f022c3b6c314bde5171ead1616e4c27f0e9a48a9a9dc3a7227a62d42213b93c8a4c32af18bd8ff931b7732782e0901c623e2d926af5eb52dcc2b931993d3e5271451180000006029fadf3355a31c6f841570e76bcdf5636378c65ff1da8f580806602752694b0001206029fadf3355a31c6f841570e76bcdf5636378c65ff1da8f580806602752694b203e14ea3daa62c03d9ed56e8895b5d98188711c49818cd0add43d37fe512c93d1012a5d83dcce0edae361a62d8bc2a308a87e29a49b000000000059a9ab6afb4e1ffc001079fe01fc00107c0e01fc00108203001119c437dbe2c3aeb4a3c7d1e29380738e3372433e443eba6ce82ca15b203d10117c653f26944256cb505749178fb4f731643d9aa56c54e504f9cc6e30a4adf9fa35bc975e52e3f667e48ff3ed7ce71f8ecb85d5ec728596f7fee735c2f857fae1569c8b4c6839ca849cba42d1000197ed64c04be77ef571fd5624c0f7705192630e3a01fb8f3001fb05a36071df1e3bf80ba6cb9795bb2a82ef426cf559b7711e555af45fd8da7fb629b80001206071df1e3bf80ba6cb9795bb2a82ef426cf559b7711e555af45fd8da7fb629b820387368b816ed3599d758185ae60d943afc22201e94e06ffb3dad30a3ddc6756b0005ccc78c0358f7b71d254b28c7287da9b39b81f400000000002d20db70fb4e1ffc000d05b30001fc000d05cb00434dcdb7115427657cf2936248b62a97b9969795ff1266f2c8aa7b1f93a15b8882013af424d7d9e805ccc78c0358f7b71d254b28c7287da9b39b81f430b4e545a909b1916959139eaea845262b0aadec1c5cf555922bb6e6d1804343e6490428a382a0c01832fc70c50438fea6000152cdd176257544a263ecadb986ed72375589a8a401fb682001fb01bb610f8f8dd4cae7aec25116ce7104742254ec559baa67b27ab471ece2a2aa7803000020610f8f8dd4cae7aec25116ce7104742254ec559baa67b27ab471ece2a2aa780320a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e264345f7c30d3267da06c6f685ac42770abc5b0ab8000000000036ba9112fb4e1ffc000ccadd000000bec1b55112fe6dee11593a3ec19e9d7128555218bec1b55112fe6dee11593a3ec19e9d712855521864f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d73090ea47f22be1644834d8756793f2308f2c5b40afd16ebb98d29a3bd37e437990d4d5930ccfa56c1ea0b4e51d05a49f2300000000617d72f6941af02ef5f2ceaa2ac0315ed5db0979c45391398f74b0fadc100ca6000020617d72f6941af02ef5f2ceaa2ac0315ed5db0979c45391398f74b0fadc100ca620a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e69eaa58fb3c117406b24cb6bce3b818f582ea7647e000000000023587acafb4e1ffc000ccadd00000017acdf555cdcf9dec1b41f2b44511123917d299817acdf555cdcf9dec1b41f2b44511123917d299864f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d730067ec5f7cb5511ba2bf10aa09eac4107d76fd53edeb2fd94edef4555171dbe3ed7dc6cfe37b087390af61a6aa269182b0000000061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb00012061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb20593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c15888380d6096d829d6864cf6eec66812266839e0d0000000000340cb05afb4e1ffc000cf99e000000b5b414e1a68e36a25df214ac6eba35782a0437dab5b414e1a68e36a25df214ac6eba35782a0437dac69a0bda7daaae481be8def95e5f347a1d00a4b430a6a63376eb861bda6afa09e28e39ba40cdfb877ee6f9aace10eaccd4caafe8d9243f2f2c0ef982a0766347073cc199bb00017ada3e486409b39c94a0833c8d782f35bc24e96a01fb8f3001fb05a36213059ec1749bcbb42e7b0ee5205b88df03ea2fb1a73d6c4ee10c9d3de9345c0000206213059ec1749bcbb42e7b0ee5205b88df03ea2fb1a73d6c4ee10c9d3de9345c203ad8c08b05fcd0c0dd9cdd85ffceb21c25366f4f32b81f6a0cc009e774987154006d2ceb670b5e0484285fd83d0d13177f608641a5000000000055d1f304fb4e1ffc0010173e0001fc0010175300da8d49b6e91746c548bbd0de25fdb62bbed5b872a43561ee4583153f4b18ea92e8fdcb3a602e84fc482551fcc51ba10000202e7d6a7938cba1cd28ef3013b9b565d5772aeb5080dc5bdc91a319dc33b4a2fca52d3998d6561a043b51bca50eea4dd8e8510239af01fcd6312f050000000063115def57591ee9abad23b796cff8cf63b7c1e9878ab77ce8e354c38803501600002063115def57591ee9abad23b796cff8cf63b7c1e9878ab77ce8e354c38803501620c72e50fdd7acc0be5942e53d2e5a616f7e86c4b4ae675b8099e4f8a1caef049f0018d49a0f47500900fc886294ab346b7c02c7a9d800000000002d4db010fb4e20fc000374ad0001fc00037a330079cd5958432147b2cafde22aad47375e690a9a4d79cd5958432147b2cafde22aad47375e690a9a4d83ee938aaaf0e18dbe7bdf40e639fd2d2dc188d93002ede7bba4f6330aa85b22f2d20167cb529ac1334125ec439f873c0cd7d54e7c07b65bca725799f8292564af4296f0600000000063dc5ee3b0ae326b1d590c1253aceb6b50982721e6d8b20e862433a2a6438c6000002063dc5ee3b0ae326b1d590c1253aceb6b50982721e6d8b20e862433a2a6438c6020a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e6bee55061de10219326c570d2c39cd051ef00d2c5e0000000000235bc5dafb4e1ffc000ccadd000000b190542b5c7522f4db19e48033d17c34afd71845b190542b5c7522f4db19e48033d17c34afd7184564f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d73013f411bb160a34b3d8254e7c537e1300afed010d4a245e376b81d889020854fb999fe9cbb7430ddee0faf2fe5e711ebb0000000065d8d0b30932771009cd7f022fa796da3ef4c1268728843ba71b5ca8c6c4374a00002065d8d0b30932771009cd7f022fa796da3ef4c1268728843ba71b5ca8c6c4374a204a37c4c6a85c1ba73b84288726c1f43eda96a72f027fcd0910773209b3d0d86500bce5e6c41e6658bf2a5738b7fcac02c520e391be000000000023a155eafb4e1ffc000b942c0001fc000b9d53008e9431059fc57f8c0c1a9625506b80589feb7fd6faab53c3c104da464745c096b8c79c91f47b835ef9cdba10be63d3e13607d4f420bb6b8013af2f7d308b98c8e6620c7893f7c26acc50d4e335b74f9cc866019ff0b6af497407fd0ebdb33c2cba0a6f2c4ea9a8aee85f22bf5f000000006691b5981eb27314fdd2c2eedf58a0571da48ee074600449eb825c485a17ea7c0000206691b5981eb27314fdd2c2eedf58a0571da48ee074600449eb825c485a17ea7c20a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e13229a05ff3504b016eafada8216af6f4a4170e2b4000000000036bf1c2cfb4e1ffc000ccadd000000f719327671f37c8f4dca62dba332ba17ba42e7e2f719327671f37c8f4dca62dba332ba17ba42e7e264f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d73000a2e66a810493a91b5ed1a8ef8ac4be41543598f5b4765a6f5d6339078ab88030817dc9c9bdb60c7c7a02d7787d6f2e00000000672830015f3330a96d5aa74d43b6dd2f6896821d8caed7fdad6427c74b7a7e2c000020672830015f3330a96d5aa74d43b6dd2f6896821d8caed7fdad6427c74b7a7e2c208e8e515f7025352e7c608479e413beacf0d95cbb964b47e4a98fd27b6b6b628a4ac20bcbf3e1989bd3da763af41bfd39b45b130e11000000000034d41347fb65f3fc0005e6990001fc0006573c000fb0af93f68351ac5e92ff99c982c664da1697020fb0af93f68351ac5e92ff99c982c664da169702c20bcbf3e1989bd3da763af41bfd39b45b130e1130151436dee05a55afb36dfcc21afcd193ec0852d2f2b27d86f3ce8c05e7e4d4af4e0023d0089b0ef3d41bcdaf4556b1fe0000000067491f0cb0874d179d8ece6f3ff25f721b2eb016ab5768bfabdc5e6ca614aaf900002067491f0cb0874d179d8ece6f3ff25f721b2eb016ab5768bfabdc5e6ca614aaf9200b469b5bc9057f1869e277e9abc139e8a7fa9cbf98f3bf4592a740249834d5a001cf333b39b37c22e1bcbfb2cfb9e98e85c622f08200000000005bbe7d85fb1a0bfb4ab40001fb701200de6d2589b9cd1d134c8aee733d9ecf70a21d3347de6d2589b9cd1d134c8aee733d9ecf70a21d3347a618f8434a31c9d45afc5d99aa253bdf1319f9413091e633b72726091f58e3bd1ede3a21de66abb2456c2f669be8bdcf76f3ab76aa2d75f7d03cf2f7d5761ab15e62e006130000000067636d7c7516e0eba85e2950cfa2c4d14e89b0aeb6d1700cb1c9f1bfdb4bb8ec00002067636d7c7516e0eba85e2950cfa2c4d14e89b0aeb6d1700cb1c9f1bfdb4bb8ec20bf0cdd7af7085c9e845a46ffd4fb3f460b73ab18af5ab9d7c76c1a8f13f63f210029aebc9994e27800397664c85b8d7c3c19ab788000000000003427fc58fb4e1ffc000bb3b40001fc000bc79c00a32c3c54a801798f6c7e4e579dcca4d55b9f6ddfa32c3c54a801798f6c7e4e579dcca4d55b9f6ddf1ec5c66e9789c655ae068d35088b4073345fe0b030071b53468e6124803ed05bb4961177a9e5207744ce04e742c6397e70c3bab2c4161838ce8a7284a043f7d1ab1f18d025000000006802ed5074a42b84a99b5fb6da29d04c2c80e6c9dc437203acd698ade36c6eee0000206802ed5074a42b84a99b5fb6da29d04c2c80e6c9dc437203acd698ade36c6eee20ee6e6ce3ad98d6ac037243dcc9e6802c4cd029dab65f9ba9842ba47450ed026801eaf63db1bbed2ccc65ff8763bf9cabf44b8d6dce000000000022e09864fb4e1ffc00017ebb0001fc0001aa6c00c924a295c5c6c72c2a650224eaf345293a9c18050c5f490d930fd36cd578b0f71c053b488b42c4edf32bb66d6fdcd07b1268d21a3e021c9c95445293308d6bea256f36d8b92071b66fa64f4023737cbd1b5dac7c1c9bf514cae400c332a1091df0ba8cd007d641a92507d9cbbf00000000682b3e58e283081c51f2e8e7a7de5c7312a2e8074affaf389fafcc39c4805404000020682b3e58e283081c51f2e8e7a7de5c7312a2e8074affaf389fafcc39c48054042090e2875a5147dd4d0c167017ddc3050be5a0c8690348ceb20567f5f9b8dc55490144d0e04d397a70492557046f0416c70765363f6c000000000040c13ecefb4e1ffb1bde0001fb37d200f4aa6fd6b27d9649267b4ae48e3be5399c89d63af4aa6fd6b27d9649267b4ae48e3be5399c89d63ace33dbd25c0eca0572668b263e170a70de199dac3005f2269374676476f00068b7cb168d124b7b780a92e8564e18edf45d77497abd9debf186ee98001a0c9a6dfccbab7a0a0000000068512af99ba954cba495e96651a8d730880e21437a873fd9309b54ea9e3b53cc00012068512af99ba954cba495e96651a8d730880e21437a873fd9309b54ea9e3b53cc207459dbe6d9b1930f8d6bf4d0872b2ed6af58baa2f0effe608e6e2ab0c98c148501f30f8dc6c5b956089b30b3dc91867a3b72620b2f0000000000b92f8494fb4e1ffc000faa6501fc000fcdc401fc000fcdec0044b7348492de6612c17d0aff5a3f6fb5f338d57ab2f70938b1cfaba9eab8eee718a48f292e1d5180d86df99cea20e4fadf223310df529ce645f0db2330a28a648ac2b271105426f11a070d3f4854f812c3fd0241860afd511a7ac76e681210505ed41121b141e377a73faaedde0001e33c1f9be807b975c0f5e1c0e3c63175d9e55ea901fb8f3001fb05a368fa216e06d6eded3afecfe2c4b1320a20652972a006f85bc024d8f46dbe8d8800002068fa216e06d6eded3afecfe2c4b1320a20652972a006f85bc024d8f46dbe8d8820f526a08420ddb3e2613d4b76068f9ab4e1fddf144ed69a02e8db33eb66b653d601eda9e9c11e82f102204cff0c4002e701b3f5cd1100000000009f45480cfb4e1ffc000504b10001fc000514d40086e21949f0e591e8803504f5245bef823d701997f07b6cfed0116e02792156cfa9f595b52a3d87c82d08e955f84b217d4dde65a6519ab77800c7954730039715a9bc06634ab10b432e3a9d446d436b4584f65c19aef93c69d07802690df0b51d81da6ff9a8de1542c40edb0b1a00000000697c2c82e72c2adb8909de0659da51fd64cca28f8e3bda7edd8db0d0653d4e2f000020697c2c82e72c2adb8909de0659da51fd64cca28f8e3bda7edd8db0d0653d4e2f20dd94d2653996e56e93e922e2dee824f6bab41274f86b183fc7312eedb229840700840a5c486b762696e25eae2bc9ff85b0d44011f50000000000235c0934fb4e1ffc000bb3b40001fc000bcbaa006aa4bdc44241524d580524e2623576169a0ab5616aa4bdc44241524d580524e2623576169a0ab5611ec5c66e9789c655ae068d35088b4073345fe0b030947b7beffebce3bdee5bba609a5c4491711f9c8c42d25fa02ed7da12f2fd7342762ef913986f1df8cc13c0a4381d1e1d0000000069d69bae567a8184b2b254ca9a5c4b8732daef78788a3b722f931f74df08f9e400002069d69bae567a8184b2b254ca9a5c4b8732daef78788a3b722f931f74df08f9e420b90bf3823ec4c4c6b4e0283d7ddb9ec00f99797471d585a93c0cf29f9bc98fb000cdd609cf68a00b4c13b040736aca0237a41d3006000000000022d78201fb4e1ffc000bb3b40001fc000bcba3001e009a2934acb4c1bf40a84eb29cb251d18e8fb31e009a2934acb4c1bf40a84eb29cb251d18e8fb31ec5c66e9789c655ae068d35088b4073345fe0b03084c5c9186e0d8efb404f4806218c2a5bc711396f445c27b0cdc8d31246ac7cf42d4b38ffe62340570711e446651569cb0000000069f156c10220991da1f4e8d692a582ea686a028d532b037f29684610fdb60d2600002069f156c10220991da1f4e8d692a582ea686a028d532b037f29684610fdb60d26208e8e515f7025352e7c608479e413beacf0d95cbb964b47e4a98fd27b6b6b628a409a9ff9309062608aa8b3124cb264fd29810bfbe4000000000034d41347fb65e6fc0005e6990001fc000657240076a035432f549ce35f39ae28b45f19965340d82a76a035432f549ce35f39ae28b45f19965340d82a9a9ff9309062608aa8b3124cb264fd29810bfbe4308e72ce4ecb7e37c0ba5376c77ec364606b796eccd05d80583a36da42d57421c21d3ccc3b3105ab18f87901e03ce09a000000000069fea9883dea2a9a962965e56322afc4f22484c3289726708fc760110804abc900002069fea9883dea2a9a962965e56322afc4f22484c3289726708fc760110804abc920ae65c812772f699dfef8c267595bcd8989043245ffd5a478953f4ff6bafb6af401a7749b674b1a7a60ef4e659d00e285c83dffdeef000000000022e180e4fb4e1ffc000607e90001fc00062e5b002c191f6fe901a5475f2a87fc3aaa12502057e97cf573287084ca8cd1ca8ab21ff5436945022466c2c9d30aa841c8e37e16f8095f20aaeac9869d26d93018d5da073c85f04213bf2cbc10eaab55f3a2779c0f347e2fb9c869024f30afa57c7054ed6b69f2a03ce928bc9683ecad000000006bb76b085315ed584034979fc0df5d8c09abf056299dfbab264a82f57b7245ae0000206bb76b085315ed584034979fc0df5d8c09abf056299dfbab264a82f57b7245ae20a0fcf7abd47df5bc7389ce1562d3b36d08d13ccfce876241191ffc269a4ba76b00885df61c52dd658243170bcb804fd4437895c8c0000000000023a48665fb4e1ffc000bb3b40001fc000bc79c005fd714f8f797e38f44abc6bf6ee6a17a932b68e65fd714f8f797e38f44abc6bf6ee6a17a932b68e61ec5c66e9789c655ae068d35088b4073345fe0b0308552bfb82f92fc63648ab91ea38925f889da4e349a2fe50e07b06beb1d15668e0e6fcee57dd80ad932459dbe6c8ecbbb000000006c397ecdbcf1a9b5901d871dd908ecac4a132391989bbfe0f75251eddd6fa21a0000206c397ecdbcf1a9b5901d871dd908ecac4a132391989bbfe0f75251eddd6fa21a20741e45b4f21dcb9bc4c1395a714685c225b50ffffe403bc369da656127e31167001a63f648d47bd04707df3fdc4ebe860990625393000000000022de80e0fb4e1ffc000bb3b40001fc000bcba300fbcff1cbe6c28765f774e51a53601d2687c831c4fbcff1cbe6c28765f774e51a53601d2687c831c41ec5c66e9789c655ae068d35088b4073345fe0b0300befed2efcc28f3b82a25c59d2ae163d3940801f2ac4f36afbd372d6c1f6c02a8a5214a29aac39d2059ffe6ac8217925000000006cca50b04c9816b07a8a831ebec34866f1f0fe836047890dce4f1c46f9e8a3c00000206cca50b04c9816b07a8a831ebec34866f1f0fe836047890dce4f1c46f9e8a3c020a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e102031ace81ec2e17de17e57c69f3c3eead8334423000000000036bc4559fb4e1ffc000ccadd00000094d596c0f06812174b31eb104a44cb1c9456307394d596c0f06812174b31eb104a44cb1c9456307364f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d7300ad4f577d067630f6fd15f4d2aefdb9456d648b71cb7253d47511acc81dd5ddb69a03c848322aa11e5242f66afde5a2a000000006ced683bb70cfb82159b08d68a9b6bf2069b328e3bd028a441574fdbb0f9d9a70000206ced683bb70cfb82159b08d68a9b6bf2069b328e3bd028a441574fdbb0f9d9a720a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e5dcef7f4fc2d4474828e84e85ddaafe52f606d7a3f000000000022d7abedfb4e1ffc000ccadd000000ad8cd8652d70a94aed1d6802bcfe9858f7c8a079ad8cd8652d70a94aed1d6802bcfe9858f7c8a07964f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d730118081d1c248d74a0737f36e5bd40aa71b512c6be6f68e3664723849ac47a62fc743c4dc7234694bda1b7701f33d2e81000000006d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e528633209660001206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e5286332096620593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c18a93e60c572add22525a10a5554e6f6a4feca49fe00000000002ce4f2b5fb4e1ffc000cf99e000000f3a83d259634fbfc3e3c4ed50cdcab6598fce20bf3a83d259634fbfc3e3c4ed50cdcab6598fce20bc69a0bda7daaae481be8def95e5f347a1d00a4b430b8a2161c64bfdc7d621df51de569911a219f718bad4d6058dcca9bddf6696d43ddc4c1e3cf91640c93f820e5680efac30001c374f016ea61e76aab79b8bb95a1ba0e6e3eee6f01fb8f3001fb05a36d6eb7a108fef471947d245e9189e47284d9a720f95aab0127adb9bc6459557a0000206d6eb7a108fef471947d245e9189e47284d9a720f95aab0127adb9bc6459557a20a159f4eb744960b4d191a95585db3f17384e36e5f1cf8c7ceae4f13a1dc46505016c8a0d99a474b91b9119b0b6bfc4da988491ec0300000000005fd91a87fb49c8fc0004e25101fc0005345d01fc000536ab00fb38720e8317dce4ccfc1174da29f071077dd371387b6ba2b25346e89278b4fae874858a8c09960f6ebb7dea2d0ff4054af20815296dbcb9e0cfe2ba30955368e9fb5cce100a0ce6df64bcf624355222e19032cff0c80cbc75140173c2eb47863b189d2423b64af6544226bb50000000006da069138e905fcf845d2e92979086e2bf89ba25d50e1c59799cbf4d2f2a9d010000206da069138e905fcf845d2e92979086e2bf89ba25d50e1c59799cbf4d2f2a9d012055f820fe0081c55c139ebd9eb6d053aadb85d441a7e8eae8dfde4f4bddb3f1ac00777742af1e086c95ad279e2173e6e04937d9206f000000000036bf0f03fb4e1ffc000656800001fc000bd4aa006c0659d3417e8b51836885241a09ac204e87c55c6c0659d3417e8b51836885241a09ac204e87c55c1ec5c66e9789c655ae068d35088b4073345fe0b0308ea05dfec6d5186476b3096e34f6777c221cf0bbce352daf402bb182e2d94297521ffe8c3d09e3e430376fc5c147fe64000000006e736990d9bd8b9b1c0164b8634a07c0da1a2bce1543e7620513b5c95fe288490000206e736990d9bd8b9b1c0164b8634a07c0da1a2bce1543e7620513b5c95fe2884920db520fffbbe239dbebf8301c7ce3bc55a891e467cb3dafe3479fc4e97072d84700ca6b25bd815213810f685818fa28dfb0760b07c8000000000036b856cdfb4e1ffc000bb3b40001fc000bcb8b00a0efde49999335db44bcaeac0af934a4759ad34aa0efde49999335db44bcaeac0af934a4759ad34a1ec5c66e9789c655ae068d35088b4073345fe0b0308c74753516550b53c30a89f5d0c5e08cdc0145d1be5e45d8db75597745346ff4aacc04c1de1f31aa42e43e3fba15ec6b000000006e84dcf6f2ddcf4444bec6dc070d9cbc52c3ef6681a14238b2e1390a77a6435e0000206e84dcf6f2ddcf4444bec6dc070d9cbc52c3ef6681a14238b2e1390a77a6435e202208e9b3635f0fcc623f88c9f45256d6557744d5aa12f126adc3d07ed43a2e8d0192ad947d47ae5f960ea418954db0f96dda7572d60000000000175b61d3fb4e1ffc00025be10001fc00025c4400aff050dc4d29cd0413c1890c6d8db9e8372b4cd38d83de554dcaf4e9c01608497bf4b6bc63210142a4687a0e78a9b3a071ad6ce8e33b008ab5cb7dca300064583f3f5dbb756708aa405572d2eaf3349ec2d9048c93f21a2d1e5a0da7ae1675d27d626035ce0754de1898d5cc30000000006ebfbf45a7e6f5e4d25ba315f1e1a44178f6961271b23925a2871d0c5b9e132e0000206ebfbf45a7e6f5e4d25ba315f1e1a44178f6961271b23925a2871d0c5b9e132e20a06518e3c9374e778a185bf5a4d056b1816719feb626112da42d4a065fdf5e90000b22ca74c045f776efd482aca95f692d3551dd6500000000002d3dbaf5fb4e1ffc000c6da10001fc000c6deb0035d5591040d1158f08d837b59f0b57b6912560cd75246a92185e0f116ef70707a58be008da5ce1680b22ca74c045f776efd482aca95f692d3551dd65300f57b0dd5947df31adba9480eda73a2282aeee0bace77680da718af1b91a05f878e433e8455ad56a38918b5aa262be09000000006fbe7935a362d6c08e5d10af09398ac4ebd2edcd1f5d657816c4f0982da6999b0000206fbe7935a362d6c08e5d10af09398ac4ebd2edcd1f5d657816c4f0982da6999b2051352f9cdd2b3bed963c98435f57a9c2c868773e4aa0ac4e3b8d07afd2da0b3a004b1eda1e91bd4d5907b65f8755c4e3e0e12453d70000000000a5e3146ffb4e1ffbc4110001fc00019d0400fa2440f3ed05121bcc2463ed00d1664946b68b120f4dbff3f157e6fbdf65169a1c1a26fedf178dfdb2334b22379811352d9988876a6e586d975e7329300dc936ac5a2e0e0e81a682afbf1d5a4b6c761d265c944b7065cde7c0009b103b6e163441eab78460b0aa6951477123a0000000006fc2e949a1bb5bff22ac494c3434d2db20a61bc91c9f8a3e57048292abd33f780000206fc2e949a1bb5bff22ac494c3434d2db20a61bc91c9f8a3e57048292abd33f7820c73a0b3cce7ca6c5b5370ac2311140cdc30315ddb718f8c46bc2149894da68d80194970c5f6511cf4757972c8c723ca5e097d0999f0000000000c2100205fb07cefc00040bcd01fc000468e101fc00046af300e565047bbe00199e47400db3a356034373647fe7c8a4cfec45b3e5793f8413968d3bd6aa7c6bfffd9a5ff3a72145e4bae41ff7842782f8e851d4275b30032bfab78f78c968f4a1e7fb87d9b3bd75dd2a49e18b7592e4274322660c27f213b898442eb41f5db42291a2172508b600000000712c0edad9b39de087a2422aae59cbee77b63aef06de6db44b2b8287303620ef000020712c0edad9b39de087a2422aae59cbee77b63aef06de6db44b2b8287303620ef2078d4881f8591d4de1be992256cb869064f8a1778c71815e1854c8258f505a3fe01087514e6edcdb460ec2ec30cd6479db40659f0900000000000c9100205fb07cefc00046a5f0001fc0004709400b0c562adbfdb889b2e9cc84e0858209799bbe16857ac5622d91ea4b76a62b0e4d0a47bfc4a1fc03c9d2a53910bb9aaf740ddcea71e896e5fc5aa5239300ec57774146e447ac6cf131a40fb37664ed5f9ff45b59d22cc68f2aa9f4659cef42235b63c3f2c3ed36f8b2344399d2f000000007135069642e1a72807a383fb5a14b9af6758292fee53fe2a7f7ac6f528bf70190001207135069642e1a72807a383fb5a14b9af6758292fee53fe2a7f7ac6f528bf701920593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c1063c03764190123b001e65fd3aa12c030df5bde82000000000036bda427fb4e1ffc000cf99e000000b920a2229f777e360b7da76885a556bb439533bfb920a2229f777e360b7da76885a556bb439533bfc69a0bda7daaae481be8def95e5f347a1d00a4b4309472710b11e34dd5f6fa0d43cdde23ddb33558be1539cc7275cf06ba2d82c6ba0c712e7022752843f411e6702eaa736d0001f9956e70daffa263e8cf29fa6557b7b630a595a801fb8f3001fb05a3714874684cfabe0cca907ff0e61bde28c2fc1a8840c485fa14ba5660bfad5e2c000020714874684cfabe0cca907ff0e61bde28c2fc1a8840c485fa14ba5660bfad5e2c201bbc52c48482f1e6f57e1eab3d8dc53904d5a16f9bbdabee5724578a8bf897560194cbdd7f7e53872cc579e60314867dcdeccea50f0000000000b6327d55fb4e1ffc000218db0001fc0002192400efeb6789243fa23cbf6b5137aa5d4dea847830e33f309e73b02fc83f88a0bf28f87d715a48678ea6e3c8d9b74f3cacd7ab94430574b9816e5047b9033011b8a3cdbf872f868b08b211878ef11a0f6f7a7ebd55533864aa98e53e194faa159ae2d13a7625384a3fd1572f68deb4000000007161d8618826c76aad36d8b59bc4c1fabb1d8299115f8314e74d7854fc3ef6660000207161d8618826c76aad36d8b59bc4c1fabb1d8299115f8314e74d7854fc3ef666202ae863fa61ba16e37e3dad6fc5c07939b8caf322da44272eeea7f645c447234b0049ec22c09c3152674ae7af85ee7e747d08ec387900000000010000000000000000000000000000000000fc0004bea80001fc0004c8e5019676669d0daf4a6ac06239eae91b43b4469cecb49676669d0daf4a6ac06239eae91b43b4469cecb449ec22c09c3152674ae7af85ee7e747d08ec38793000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000717a502e11bfa52d11a10635536205d60934f6f2d0ac64d7fc0f1808a5aaff01000020717a502e11bfa52d11a10635536205d60934f6f2d0ac64d7fc0f1808a5aaff012014d197a4d96ac8c0895b28bfa5ba04c094fdb7a9e073407a499b07b391d3cb980147a99e2ca7487d874d547e887d3f457175ae5897000000000040b032a7fb4e1ffc000d08f40001fc000d091300b7fc053090e0f10f64d962b36ef797ae608f4851b6e879f9bd59a349caa9d490f0bd51988bb1fc341f9162e004553e9fa0d415cfc38431bddd799a6230a90fce30ea814b244dc767b5d29bf227842226705a0bd2e8589e776a4dd113ed3dada52c6a07f55be90173d6431d8f340000000071d1eee72379edada11d464bcee475b37371e4d907db5848c3f50e0bed00a45600002071d1eee72379edada11d464bcee475b37371e4d907db5848c3f50e0bed00a45620e86078d3a9106a2cf3762064b7326edfcf99ac4e1dd76d6e80c9b94bd766737b01c34bf769f46fcc5ba593c2f3a4009c02e6e0cac000000000010000000000000000000000000000000000fc0002d5880001fc0002d5f10159b1ebf04d63af3ef87391a0a4a7b47f5f5e791159b1ebf04d63af3ef87391a0a4a7b47f5f5e7911c34bf769f46fcc5ba593c2f3a4009c02e6e0cac0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000071e6b3fc43cbb7a04eac2799d8f98f76f3b0ac867a8b8c82caf876cd0737ac9800002071e6b3fc43cbb7a04eac2799d8f98f76f3b0ac867a8b8c82caf876cd0737ac98208e8e515f7025352e7c608479e413beacf0d95cbb964b47e4a98fd27b6b6b628a51ce81fb48d349c7ac0e09a8a5d152475b586f4275000000000034d41347fb65f1fc0005e6990001fc0006579c000883903918c1154fb2b589d80caed855a157b1240883903918c1154fb2b589d80caed855a157b124ce81fb48d349c7ac0e09a8a5d152475b586f427530975c482384c7bd4cfd5930fabac11646121d420e31883673dfb6e6e3bfa273da73a2a91b4b69cc108eff9619fdbb4cf4000000007228951470758be7eecda8126c7a23fe8ad019e67f3fdd5507003bf0d2d4159d0000207228951470758be7eecda8126c7a23fe8ad019e67f3fdd5507003bf0d2d4159d209d15d4d2f03b000755dd3f7fe619d08afe237a6c12a8cdeee78b75701495287201e0e440d4c365236c93f5fbe402336cba2c5a506242c80000003feee5bafb270efbeb250001fbec0200ad045f8cfda05187e5dd3f59cdc7f7692816320a5fb5dd519d994f5e5706b4047d65ba1b873d9ffc818d7b316758b285e41c565599c9168da68592913088d719278eef605d9c19037366910b59bc28d437de4a8db4d76fda6d6985dbdf10404fb9bb5cd0e8c22f4a914a6c55660000000072ee70fa75262781a17d1eb69a6c3e97328208be98b59d5530164f31e481d3aa00002072ee70fa75262781a17d1eb69a6c3e97328208be98b59d5530164f31e481d3aa20a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e60d38405d40979e4834a09345b8c7398e0ef14293b0000000000235bd038fb4e1ffc000ccadd000000889e8cd2ab0cc70e36e566648e265c7536a8fcaf889e8cd2ab0cc70e36e566648e265c7536a8fcaf64f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d73091f9052f62561db112ddca7df3d914d546866b130124eccb2ae1e8419563e51f239b2efec3d1b3fd388072610939d6940000000073091b5bc227073da93ca7c25ffee4f9c9e8b3f77b935c99e30e71268704f5ff00002073091b5bc227073da93ca7c25ffee4f9c9e8b3f77b935c99e30e71268704f5ff204cf1e357dc63a5335aa184c8ff929e4db36e83072425065c0655e09f072fea560000899ddc10954edc1ea1398edfd31b0621e5982d00000000008d47264efb4e1ffc000b3c090001fc000b3c630094ced88d9bd5cd2ec75faf451a5e3bb46f5eca6f90614a6e4cf57a7381bd81839ebce238cca8f9f1349317eb79cf1748fda1de3ea69a777d4272c2ee300fa3db9b808db89b49f91f6136cfb966288a56d731c9afd44dc8c4819ae5c286d08dc0572249f41dc919f888d562340100000000731ddb4dace693a27ac91c696685bf3e01440e2f5d57b53e2ed57059f6a33e0d000020731ddb4dace693a27ac91c696685bf3e01440e2f5d57b53e2ed57059f6a33e0d200064d134104e9a09e6e469e442e305ee542d1b5136a7dece41a2b812e3d89a2a00a4ee8867262e7b96728c873c15ae6d983a9e2478000000000036bfed34fb4e1ffc0006567a0001fc000bd98300cf3908c18dbc7d817330d948866a29f69ca15a75cf3908c18dbc7d817330d948866a29f69ca15a751ec5c66e9789c655ae068d35088b4073345fe0b0301213e8a0f73b54c388c26dcf85c158dad87ce9889f45a38bc330d1da4d73a6c02a8d9f6cdf60cdeeadf084c2749fa47d00000000737cba5a656579e1d2becfee2d92f6c7ae3b84a8ecef02c6f53764a6499a8c79000020737cba5a656579e1d2becfee2d92f6c7ae3b84a8ecef02c6f53764a6499a8c7920931fa180adaccb45deeea0a6a7dd618beea65f600ac6fe734e871f97e4476691004b1a70c1e0e8bfe39a5879c943a850f21875508f000000000012ecc7e8fb4e1ffc0006567a0001fc000bd983000eb5e37e0ff88007604e4ebdb28c3beb8120d5fb0eb5e37e0ff88007604e4ebdb28c3beb8120d5fb1ec5c66e9789c655ae068d35088b4073345fe0b03017de44da9886d130629436db995acc9d5f0ef849ff32c4f57b65674f19420dfe8e583dd2c5f37f88edee1ca119f0e8be00000000753f4ae544d5a43787502bda92bf3f635143a0953b31a62c2f61cf8c7df4345c000020753f4ae544d5a43787502bda92bf3f635143a0953b31a62c2f61cf8c7df4345c20141a04d46e28743a8ab8367ab44f05114161e45f3799c2b9f822d8f9895365ac001309f03f9235a96efbe29a9ca62e8fc600208c3c000000000022de04c5fb4e1ffc000bb3b40001fc000bcbaa008186bacf6b22c42e8a63e48c2b2e1ac614bf92db8186bacf6b22c42e8a63e48c2b2e1ac614bf92db1ec5c66e9789c655ae068d35088b4073345fe0b030147039e55cada215fe076a972b046224b43198c9f8d4ddd55db4dc38e4168ec1bcae3cad84f0bb2d9f3db9688561c84000000000754b89dae8db20fc4cee5e3adb07b146d7efe508a66fa0a8e1094675b9daa35e000120754b89dae8db20fc4cee5e3adb07b146d7efe508a66fa0a8e1094675b9daa35e20593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c19ad66f3780f47e83479e1846ecca44d71ba5a902f00000000002ce92c5ffb4e1ffc000cf99e000000e65f1647a5477a20d178b12c509738d7a35ff312e65f1647a5477a20d178b12c509738d7a35ff312c69a0bda7daaae481be8def95e5f347a1d00a4b43099b9f0fbeea3822cdc5b3654dea52103b3d9d5f01db4201955ea3689074d37da4711d8f313d4b5458eef3395aa75bfc7000146d938862af6d9a291e26c0048177db2892a710b01fb8f3001fb05a37551fe264f2ccc4e714195d2ffb79eea7ebd47517a7164c69653569b10f51fc30000207551fe264f2ccc4e714195d2ffb79eea7ebd47517a7164c69653569b10f51fc320c14b73c62e6c0b2df561e37a65ab15e2813a4fbbaa182eae0bb87e3506d4bd9b01b96ce21a90ba65c455609913a18eb7ff20ad55c70000000000a1bd4319fb4e1ffc000376690001fc00038a9c00abf73c421d3d73583ebcd9fdf55fe8b3013a8223abf73c421d3d73583ebcd9fdf55fe8b3013a8223fa34940e957a62dc7177dcf44e74e39828a2a371300becd48c0d44ca6fbff3825f55c35a6f70024f2b8f4f939260d40b5b51c11cdfff85f7d0444a1a9cb8fc45bacd237b310000000075adf981e3a77630507882a9a41d551ee1e5b8ed570e61a855008ca293e615ad00002075adf981e3a77630507882a9a41d551ee1e5b8ed570e61a855008ca293e615ad207a80d77b707fba35384adf0c231ce60d32273de39c9afa9ffc3edf9a2605fa7101828af5d4e701d9c3869a22f2417110f518f364fb0000000000a7636e3bfb4e1ffb9f600001fbeeea0082242bff3c046e018b795b7bc3bb8667628dc02b82242bff3c046e018b795b7bc3bb8667628dc02b69abc168964f63618f587649cb25ddecfb20fcca300fd87b62bf91162008451c1f00a1d7bd65ef581e88c153d105970ab30e451378966b6e4141e68024b3976461605e84020000000075aec7fff319c066890515c7d626166cdd3a28c9bbcd5d949027e5aec46dcbad00002075aec7fff319c066890515c7d626166cdd3a28c9bbcd5d949027e5aec46dcbad20a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e3f7100e7a52bc4a9c2bf5ba1bed4da45153e0f52de0000000000235ad9d0fb4e1ffc000ccadd00000036e3ce4c7f353ef721fc1754406cf534bab728b036e3ce4c7f353ef721fc1754406cf534bab728b064f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d730124aaa5688cb7220be4600211257ae054554583ad9233e8ca0d58abafe317129dcca9e34a1b9bbfa175b88d9fb31b55e0000000075e5c254c195ef04d5bd91294b78211263726c3bc0bf5d4f92690144f65660b600002075e5c254c195ef04d5bd91294b78211263726c3bc0bf5d4f92690144f65660b620052fc2a04f75b150e4ab7c5981bd24532a49805ee42167b6058b832e3b0c2b5300a9b4fc06befaf833456c54d913154f8f115b412b000000000023573001fb4e1ffc000bb3b40001fc000bc7cb00cf3023e2146c3765ae4218f86e605ac503019d63cf3023e2146c3765ae4218f86e605ac503019d631ec5c66e9789c655ae068d35088b4073345fe0b0300100ed63b1fc72b11ffaac5471ec57d9c9a79214f936932e6a59ebef5938be6190ec7de6b98cf6ae92964d2c7a03cb0d0000000075f082ddd488b36e46fcfe4c5284898d3139ea58f9effa9b70fa12b25619890b00002075f082ddd488b36e46fcfe4c5284898d3139ea58f9effa9b70fa12b25619890b20070280de80a8c5f34f7eb94dc35d847530f7ef5a9a6d43d840b2256829e297aa00c4fca50e9f87d5a53b57d8a678b4fc048c7e475000000000010000000000000000000000000000000000fc000ff1b40001fc000ff220013baaeba63dfa6ee2fd67021647213b024f30d9593baaeba63dfa6ee2fd67021647213b024f30d959c4fca50e9f87d5a53b57d8a678b4fc048c7e4750300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000076476a2678d5c1e9ea4951cdd00babd50f6c53f91427ba8dc8fe49f5dc1f5c9700002076476a2678d5c1e9ea4951cdd00babd50f6c53f91427ba8dc8fe49f5dc1f5c9720ebd8732e4738756b96dee3c0e3e60a0027e3b31c3fb0804ef78d46182a84e81c01e03b915271e6dfe5b91126e4bc7b8a981c7459fd000000000034dc3d58fb4e1ffb34f501fb355701fb81fa006dddbc8e0c2bf0803d236fcba6cc32a8123ef43e6dddbc8e0c2bf0803d236fcba6cc32a8123ef43e49d0dcb6162703c2544068536b0b1813c459dff83010142d44041c90621d111283fe46fd8b2450d4b9bebad194290fce09ba080679c748b1ba70e3959623f127af0d2bc9c400000000766c3edf3c134fc0b5ede4fb57b15564819caad310b1929cb5b57251114d64e5000020766c3edf3c134fc0b5ede4fb57b15564819caad310b1929cb5b57251114d64e520b07dc210a205645699a1c7d92d55b55dddedc6fb6c9a7265d1588320a024736501f09070f51717b8bc2800781c21d9b10733d912ec00000000010000000000000000000000000000000000fc0001904201fc0001904301fc00021efd0096b5ec297ab7b977f1f3318291a77ffad070259d8fce46d5cc1aec576dbf5ba0ada049a2c2c64fb3655d3f8b0d7ac259ce9244933bb35544a1341a7d30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be42900001207718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be429020593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c1feea83c4756a349e76b9077636dd04b3306bac60d00000000002ce3894dfb4e1ffc000cf99e000000c0e3581e5165c63790a2b8d2670fb4a1917cd4b8c0e3581e5165c63790a2b8d2670fb4a1917cd4b8c69a0bda7daaae481be8def95e5f347a1d00a4b430b675a1940be872b6a0d4e1696bb39ea38179933a1bae02ae1eaf4b47f625bd939482f8791eb38925af47f73be027a64c00010498ade3c80045c2a7520e921180ae1c39da5c5701fb8f3001fb05a3777dffee76d4ac2b3c9222e6d3ce285527a16281b1d22d511fdfedde4e46ee70000020777dffee76d4ac2b3c9222e6d3ce285527a16281b1d22d511fdfedde4e46ee702079a698f19126f940710af2e89919bf10587c5e9de50451d2f53e76f05ece62a60032b089976a177c7b080b8bdc40d5f387113ed2c8000000000022d73700fb4e1ffc0006567a0001fc000bdc0b000f39e252e534cfd876389ce5770a92ab1d3454ab0f39e252e534cfd876389ce5770a92ab1d3454ab1ec5c66e9789c655ae068d35088b4073345fe0b03089fb9bc6b79eb7b71f8b0dd60c2eb5e0298124b9b10ee29c85415f245c67f4a3d7a8b57573e36110c85fbfedea7129110000000077fcca4a0e43f6e0b96687a87b4272eb8523315c8f2a176d0a2df549a869f3af00002077fcca4a0e43f6e0b96687a87b4272eb8523315c8f2a176d0a2df549a869f3af20460c7a309c739da005bea72bfbf0e74767da84a28f8524f8f5b328518ef147cd0177947714219c0af2be7af73357d3b65ffb6513c800000000008b9fce4cfb4e1ffb5df50001fb97a200f2d2bd8ce0dcf0434c3cf661c2045c6fdd22ba57f2d2bd8ce0dcf0434c3cf661c2045c6fdd22ba5795e13b9a85676df4a1c90dfe0be9725ed714828d30914aa95d1c7d7c39e0a3b213b6497f5c8624d4f476b8043b22c4f30cd05bc037c80d02b42625d743c6a18d0562aeb579000000007838259f0ed6819c5325b663499299319c7e882353c922a11c8ad517a0df99a70000207838259f0ed6819c5325b663499299319c7e882353c922a11c8ad517a0df99a720f3f696aaa2fcab176b1032150d96afaf982b58e24faa35b0c842ede6c9953d6300acb39ddb2ca2a929b3fcf215b699fd2459072ca4000000000022dbd200fb4e1ffc000bb3b40001fc000bce430070a68f83c21da5efaf550eaf261357e8fbbbe4b370a68f83c21da5efaf550eaf261357e8fbbbe4b31ec5c66e9789c655ae068d35088b4073345fe0b030854c69a40b8e3d4209fa88590a9119fb6274d3270618bbb0bee5bd22c801185369babdaf658d5bc6946f55d3e5e14f60000000007893b72d36e71a7b83a1fff61e4fbbe1400b11f12bfb349923397a2df3a9ff4f0000207893b72d36e71a7b83a1fff61e4fbbe1400b11f12bfb349923397a2df3a9ff4f2008ea185caab7f5f289c78dee4563bad2e103b12f662fd23eae770e5a04c48c44016922eb5a8a9b1d41b93076ad1e0a908fc6c5bc01000000000036ecd608fb4e1ffc0003842f0001fc000607bc0069d9f48f92fcc82ac6b04a2b303fb420c500f78643497f4ae216cc6f837b4d82ca8e6cd348b636b1f32bb66d6fdcd07b1268d21a3e021c9c954452933092427cdb8c9694e0c6ba086ed7c00dd9f52ca18e335f65de8a839a378b1e040b279c05e3822e7c2fbd57fa8852d04cf40000000079d1d6276e486ab033dd0984a1da33470b6ef293e19492f459cfba43e703f5f300002079d1d6276e486ab033dd0984a1da33470b6ef293e19492f459cfba43e703f5f320a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e55b4c00cc8352c3dc490b5fd1554666a1c90240a840000000000235d97bcfb4e1ffc000ccadd000000e7378cfcf68e9645d0d0ecbabbeaeb48af9a5ddbe7378cfcf68e9645d0d0ecbabbeaeb48af9a5ddb64f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d73092cafe1870e043973b2f1fded8de3d5a66dac5ade46aa0995157077efee92d852857bc7f03ed69c92723a58f8bd2926e000000007a1ae04de7582262d9dea3f4d72bc24a474c6f71988066b74a41f17be55526520001207a1ae04de7582262d9dea3f4d72bc24a474c6f71988066b74a41f17be555265220593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c1cc1d71953a4a45bd11d458683bbf2ef794d6d6e3d000000000023a612a6fb4e1ffc000cf99e0001fc0010f2fb0063c8d3ed082eb5d476a0940ef9c3fadafc4c5d2c63c8d3ed082eb5d476a0940ef9c3fadafc4c5d2cc69a0bda7daaae481be8def95e5f347a1d00a4b43093943908436a934c08582583b08cbcc50b4478bb79b7718789c25eb0ad2f3e5713ad4c152d4b1fd13cfd12bf896072e600017478cfd163788e3bbe09645776cf59642f28e37901fb8f3001fb05a37abe11022a30fb9e614725880e035fb48a8438d3885a3762cc53b2c3cffa38240000207abe11022a30fb9e614725880e035fb48a8438d3885a3762cc53b2c3cffa3824200c66ca577eb357cbbf6b8e64aabf19a07ac6876fb673547b44f6fe65a0e1adc10143af4ad2582f518ac45af4604ebb893c30a198ee0000000000128891a5fb4e1efc00012b310001fc00012d8b0028895ba824b3989b308b4062cb93c22a842e885ad6f5f660f9cf13ff1ff56a13042be5cdb214c1c114da731fe63359a29148e3f59d4235d5bd261c53308edd5cbdd7b381c92ac7de638440bb1ad417af0e82fece69432f36930a6defd3faa0d53d79bc3347ef684eb1e470abbc000000007ace7f64afc3f78ba5dcabc7f384a1a01ebd4d147f8ef629a968df09885db2770000207ace7f64afc3f78ba5dcabc7f384a1a01ebd4d147f8ef629a968df09885db27720a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e0a122072fe97d1a974045569ff2ed7743096099716000000000036d4597ffb4e1ffc000ccadd000000139d5a4134c30bebba6a178a1c8cf91d8bc47b33139d5a4134c30bebba6a178a1c8cf91d8bc47b3364f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d730826fc7f30c49215b98d5cb47a350f888a306c52fa42c77e765b55288e622f03859273cae7e1cac99e67f7a9a96a6aa2c000000007ad29bc543761bfa9ee6a8be1f32bf5bbbc4f979d036676835b4717f8abb92110000207ad29bc543761bfa9ee6a8be1f32bf5bbbc4f979d036676835b4717f8abb92112039a506efedb5d184475201e06dec512e3216b1e42b1d7c0d6f8b0440e6e6f69601c51cb65f93928d010a18197b6c8631c41edf55cd00000000010000000000000000000000000000000000fc0002d5820001fc0002d5f301224cc410b74ac6206018520cac60988122bb337a224cc410b74ac6206018520cac60988122bb337ac51cb65f93928d010a18197b6c8631c41edf55cd30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007bf37a9b228fa18b95fe74186ebfd2f16a15b970fb0ce68c43fe7dd3ca1924470000207bf37a9b228fa18b95fe74186ebfd2f16a15b970fb0ce68c43fe7dd3ca19244720472419cad37dfe438ce60cfb70b9156af1d2bf6e1874fe958ba18f229b7af37b0133c019d4b8dcd9ba7a78607bf0a8f3c86bba886e000000000009080706fb4e1ffc000763f60001fc0007641b00e6dd610e8d417424f55f90b5c468011307051ecae6dd610e8d417424f55f90b5c468011307051eca02216766b853b1e605f1e7ffb5f50c61278ef9ca30897af9fdc7920426089efaabbae8aacd61ea4306c0a2c89b140c9d3a69a56084dabcea352d2e1ff8e1f3ae127313e989000000007c124a4c83e1947d0474b005dd388928970147153d2d6ac4a5d3ac7a56a88dd90000207c124a4c83e1947d0474b005dd388928970147153d2d6ac4a5d3ac7a56a88dd9208ed933b32509d96770e36575cb341bfadd20d512271caae9816fc65e0c4d50da0081c33ea64d832d50287c2769407fbab4e9487941000000000036f46ccafb4e1ffc000bb3b40001fc000bce2b008e4a45ffd92c0a560ae047a37ae10ae6082acac98e4a45ffd92c0a560ae047a37ae10ae6082acac91ec5c66e9789c655ae068d35088b4073345fe0b0300cf64b243bc58bb385cb911efa5aa0675e9a05d582e9a9aa9bec875931bd11e82c652a7523e37c945be068f3a5af5002000000007cbb7c6b65f9360c3ef908ccf93ef438a449938acf05c743b7b92647ab3ad2640000207cbb7c6b65f9360c3ef908ccf93ef438a449938acf05c743b7b92647ab3ad26420534d653b186b8ab60b401e8572d1f8da42eb274441c955f65c59f0fe3d275158018da8375dd317a277a3f946077e1c970a1d8ccdc8000000000068f85c62fb4e1ffbca950001fbe5d200f46b2001f6dd71cf0fa69aea9f5a71ff61423024f46b2001f6dd71cf0fa69aea9f5a71ff61423024709834244eb07040d585e826f04d8d26b016555130136de56a265eb21c006bd312a0353c7c3eed46f4f63c301c348fb5d5de8f965c9b60ac6a4ae805d0d241e4942821ed9a000000007cc4df7db9cf413c897452820cd2625afffc89711f0a26eefa7cb08f8806a1720000207cc4df7db9cf413c897452820cd2625afffc89711f0a26eefa7cb08f8806a17220f6b63b050d5a90a14e3d59047050495646ec5e1242ba53b62ce81cdafbeef24900e2a84d616dc589856872cf05535d435c81f4cd190000000000235b1690fb4e1ffc000bb3b40001fc000bce2b00cec1c86cf65d548313f4401d83ac2ecd67b89a35cec1c86cf65d548313f4401d83ac2ecd67b89a351ec5c66e9789c655ae068d35088b4073345fe0b03009c21792725c0c58038362caec9e4c73f02fbdbf2244404d91b39b3788360139178a60e16e9094af50c71df853c5d2c1000000007e065c97170d9ca4aff3f9815a989c45a81bd7cb2d691fb32b3282ef6e9ccf8a0000207e065c97170d9ca4aff3f9815a989c45a81bd7cb2d691fb32b3282ef6e9ccf8a200c7bc19d6b2acdb1f6f33f065a8c4e1522af8f036e65cae356be2ddaed7f1b9e004062160cb5c4f52f266ba4c0318d365450c9137100000000003695f949fb4e1ffc000bb3b40001fc000bcbaa00817a4306a27d64e71528a625310b5f347d55d180817a4306a27d64e71528a625310b5f347d55d1801ec5c66e9789c655ae068d35088b4073345fe0b03099b0d7b98000098120aab913482266dde9ce62412767f2771bb4b51036a59f3f93d65ab54b583641dd565e47132abac0000000007e1d6bdfbe135910f32160c96a38469c52e0c8c3af6c489dfbbca6b187e978490000207e1d6bdfbe135910f32160c96a38469c52e0c8c3af6c489dfbbca6b187e97849207c4283aaa1bcca10b1358405b9a9758b2dc48b90cc7847af63fe78f08e96f262016740b901d43493fde55958720fbe004747d1c7cc00000000002d4db010fb4e1ffc000374860001fc0003795b002226272b80f5aa9fce78cc60704f1dbcf81715012226272b80f5aa9fce78cc60704f1dbcf8171501b624b6528c6d0ffdd4993a76a23d06016cdefd73300d5a850d41302b179b9009a4969537c5cbf7f0145c94de4306a4e09115ec00248cb1aa76cf04249e2a5104b5cfa86879000000007e56cc8c37501f3db794a554deb4287ac61c83635a0dec6d0f8e0b54ab14f8cd0001207e56cc8c37501f3db794a554deb4287ac61c83635a0dec6d0f8e0b54ab14f8cd2095f18528a48b7308195ec8201220efaafecfbf4df55cc2c8ab6b518733c22d63010e3edcfe65ca42dccfb1cb826562a46097c6f044412000000022df662bfb4e1ffc001066880001fc00108203006afebaad117b22669d50cf8bffc7863662b1d7e16afebaad117b22669d50cf8bffc7863662b1d7e16c671d1b8ae658d8102e47f0bb3f795482a6e215308156eebd6b52f4146a5b3f9686b9712f48980dfa4e8f17b514ba185a31e8d5fa7568c69aa79d9533fa6efd380c27b0c00001390fef6518c3b4b95551fe1707e0f0c398d5580801fb682001fb01bb7f3eea026e3a3bbc8552525a653de7ad02256e664dc6a0dd5e85b6a4aa5386da0000207f3eea026e3a3bbc8552525a653de7ad02256e664dc6a0dd5e85b6a4aa5386da204dea6406996a98efea88a66bddbe7f9568093185b08c865b1b664ae0e594c7be08b1dce6de276ab51d6d1e36be38a3bb1908438b0d000000000036c96174fb4e1ffc000cf6350001fc000d08b30013b0b76a88de761e2de68dd590fb9b636aa288f613b0b76a88de761e2de68dd590fb9b636aa288f6c69a0bda7daaae481be8def95e5f347a1d00a4b43094916711f20db42a7a62118260a70fedcf09443a263ef1891a0744601315b81b03b68fceff6a505581dedcb794a164cd000000007f771a55bf8d18d1ec8c60e61494546e5b9ea1d0639369aa5d09cb3ec7d531440000207f771a55bf8d18d1ec8c60e61494546e5b9ea1d0639369aa5d09cb3ec7d5314420a56ba768ccfa43f27b401cc24a58c43bc067da2b413ea55538d03d322de2e75c01e5ca81c3110acfa3ac727a1bd05453d6cf06bceb41200000002f4b449afb4e1ffc0001c4110001fc0001c61400ba437071f332909dad28d293eadd2d532700e8a1f0a5dd8f973cec456a2423da87b5f1aa97f282e02f8c9d8ff7ef2ad45047238e6bc187d8c124247f30842b8e5b5cc0841de193f440d5fa3e0b4a34df7fffa798fb8c3df46fa31187162cc3b3ecf929689ae35e04cbac6e069f00000000802811a147502b6982e3b863c43b6cbe305cec9929ef3bef5674122ce17cf1dc000020802811a147502b6982e3b863c43b6cbe305cec9929ef3bef5674122ce17cf1dc208c47b1a602d9a9b72807b5c193807b04179fea1d2bbbe6ba2ea6fe36e6c5896e001a135a0120585004a87405b40ed844252aaf6bab000000000012edd9b2fb4e1ffc000bb3b40001fc000bc7b30000f9c0ee13e710b556c5abb7dba04252cff9525600f9c0ee13e710b556c5abb7dba04252cff952561ec5c66e9789c655ae068d35088b4073345fe0b0300b53e680359dcb0decea5bbbdc65576c6a03efc22d93347f19e635feb55fe0cdff6c0b9685dbc999d889f8eed8833fdb00000000807b6948d2bf213b63f7fb1af6175692b6df4629a6c83d59d933ca0c744a0007000020807b6948d2bf213b63f7fb1af6175692b6df4629a6c83d59d933ca0c744a00072007004a740cca33d9593dc8a62946dfb6925617f61afbf7633b21bfd248697b80007dd6b299910d521be585a9288ca0c7b20c9ca26f00000000002ce28ea0fb4e1ffc000b94c70001fc000b9cf300b5d77242ba975cfd47ebb7c1c6f991a868622f1867d64f06bd6c80af5a0ce510c05488c6b605f5b27dd6b299910d521be585a9288ca0c7b20c9ca26f3091ecae225a25f252b7acb8e79173ab1eebd850c6415019b7ba8d11510a48591c2d4d863ba8b716fe38f248fbe8a1f06a0000000083977cb9a12a31f510641cf6bf09190ebe245b167d9b455cd0437a197933dfcf00002083977cb9a12a31f510641cf6bf09190ebe245b167d9b455cd0437a197933dfcf2073839439e285bc285f129f2439f8f1d6f01092909bd405c318e10b1d68d5af2501eb95c9099b7ea9dcf7d12eab52c964628d99901500000000003695bb4efb4e1ffc000b9bb30001fc000bd21b00c4cb4d2d29e56d01ad22d35a7e9cb0b1bb694ca5c4cb4d2d29e56d01ad22d35a7e9cb0b1bb694ca51ec5c66e9789c655ae068d35088b4073345fe0b03091aa06ab2cf470a4265fbde61c153eabe3bd5efca205dc5de54c42f0041b163cee67b72f3b1da2962a5dee3096cfb580000000008458fbd557903692f8e27b4639421db21b0f90469d310bc9221ef592519cb3250000208458fbd557903692f8e27b4639421db21b0f90469d310bc9221ef592519cb32520a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e66e4dc94aa0f3fc1bca598bcc432424bc69ddf4de6000000000036b87e19fb4e1ffc000ccadd0001fc0010e78b00158c9bc3beedd2fae2f1a25b954f315c4fa44f6e158c9bc3beedd2fae2f1a25b954f315c4fa44f6e64f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d7300935576848f6ab7e27fff34b671953672012352e36f5147181926b8bbc9e8b43b98458704666df25d36f37d41eb7c6940000000084bb939170f4714be54d6217cffa5a3818a1c521115d45141b4df642b1dbc5ac00002084bb939170f4714be54d6217cffa5a3818a1c521115d45141b4df642b1dbc5ac20fc2b411dcc940c02c50ba66566ebc630687c29da1c8c6797c24a101118202d2801b4b492aad7a4e1697be9c6c24f6b4ae07b46190300000000006d61d62bfb4e1ffb8be60001fb8c3200dd52f6e013f0cff9cda0dae34d43317bcb66edfadd52f6e013f0cff9cda0dae34d43317bcb66edfa976b7ff055f5ce7ed9315f6bba901f6064495822300f4002936319c495d9557ac1bd514bc760cb8db72dd99d5d20af93dd5a7570974d75e5761fc494de28127ae02413819c0000000084cb17f8193558315fbb5acb6b285f80c3727489f3f167380189c73751ee99ec00002084cb17f8193558315fbb5acb6b285f80c3727489f3f167380189c73751ee99ec2049c551c2b1b3c0a0e8c90be10c5847f49f7573ba6038dfe56dde66127bada0b3001b35584083c3b6032acef150d939f606bdfcbfeb00000000010000000000000000000000000000000000fc0004bea80001fc0004c8e50197726f02d3aa3114065784a38c5b0c7dd66811d897726f02d3aa3114065784a38c5b0c7dd66811d81b35584083c3b6032acef150d939f606bdfcbfeb300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000084d181ca2e1afd3fb416c71f62c2f5370a1e7f54c3400faadde30563e62f731800002084d181ca2e1afd3fb416c71f62c2f5370a1e7f54c3400faadde30563e62f7318204d00207605a792d8f6a528dadf5169b89982dbe9614f11224f70c4b03d45cb4301f3ce2464a6f42e28bdd570214f656bc226992fc200000000008e5d284ffb4e1ffc0001aa950001fc0001abbc00a4e27301bbacc1c42b5e2268bc2b4400599edcf1a4e27301bbacc1c42b5e2268bc2b4400599edcf1f3ce2464a6f42e28bdd570214f656bc226992fc23005b69b964d581a7659f5fcf2cf4a50a75e9cacccebc4e18d27364225eb3f9886de5472cfffbf9cf029f81b49037e27a20000000085412e8586e7e2015db1d2e9b4dd380e89251ed812e40bf8d5e220ee40bc18a000002085412e8586e7e2015db1d2e9b4dd380e89251ed812e40bf8d5e220ee40bc18a020da0c7a3d5af8a813d69d33357370066a2f5e1f7aa6fd6672090f355b81c3d566014c70d3eeab48b3455b85cfd354c9b4de7c267e3e3c23d70a00a747dfd4fb4e1efc00024da90001fc00025d63000835d0e8b7da48d8880e8d3420b7c8351c7a31d84b682e8847992b8e9a2531cef5a3169ea5b80c58d458f5157d91f4832e66eb8630ab3dbff95551d83080b7defb6341399f9e9b4ed7c2d627fc828d0eff9c168165b75b24e5fc6c3f5bc8a9eeaee2bc655fdaa58c0d2f3b1b940000000085f15a31d3838293a9c1d72a1a0fa21e66110ce20878bd4c1024c4ae1d5be82400012085f15a31d3838293a9c1d72a1a0fa21e66110ce20878bd4c1024c4ae1d5be82420593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c1aba3f43f7376b9025296fa73a30c07ccf5266eed8000000000036c92083fb4e1ffc000cf99e0000000f89b9ac5ac8f31255f692a3eb0283d0ef3be4360f89b9ac5ac8f31255f692a3eb0283d0ef3be436c69a0bda7daaae481be8def95e5f347a1d00a4b430ac3026b3e3023db1db9ec8e3b7678761820a2a6e96e7a5d9a39b1894170f9cea7765d3d131d60fa9d17492ba560fb1f9000168c506d43816d1a8389c860c1d162be44d1e777c01fb8f3001fb05a38627ed5599adf01d97427316b0589c2e97ba6418916a9bde5b2585e1c9c4f6250000208627ed5599adf01d97427316b0589c2e97ba6418916a9bde5b2585e1c9c4f62520aafe6abef33b368787d302dc54f71cd0a619d4f988d3263aecc745238871bd0d01deaeccbae07a6664dc82067b7cfff4ff84c09c1b000000000022d0d181fb4e1ffc000bb3b40001fc000bd203008b582cf224fbd769b14e7bab26bdb4e0c9ca5f038b582cf224fbd769b14e7bab26bdb4e0c9ca5f031ec5c66e9789c655ae068d35088b4073345fe0b0301261d7939ba80738dd1ca4ed73829488159433938e37256803daebcd7042f1963a66a2eb58622a87cc91aee8225a464e00000000869b6700423da629920dc2101ec88e894f450f66aa751879dce0468945e04179000020869b6700423da629920dc2101ec88e894f450f66aa751879dce0468945e04179200c0397f81c000328a2de9d047105f8e01d0ef36fd900ad13691aeec8c536595501352b6ca5a0485762fbe87165aaeed5c05ed4882700000000010000000000000000000000000000000000fc000192350001fc00021efd00e049e560af6d16e85a90ec84285dabca4e44514e011b1a772ead943d16af20c36c7255e18ea51027c0f5b027f3497c6e3151b44b63e43776d34c3b62300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000086b8061fb7fe866b492b84e85aa0548f68ff376c4cbc5893e46ae361a5e5724100002086b8061fb7fe866b492b84e85aa0548f68ff376c4cbc5893e46ae361a5e572412085accdf9c5e5c660057521c0001e313efd673a38d30be926546f897d5b71fdd901e0d22538c2de001eb6fc6c2444c442e944e888e500000000006deb4738fb4e1ffb1c3401fc000132f901fc000378e300c8270f9d208c75006659cedd927f04ccf829242cc8270f9d208c75006659cedd927f04ccf829242c39ec59af37fd69ca39664fea97c3a5d3758f3b17308d1412ff39045ef39c2e19a75cb3ad986afc14c3139ed0a3392b41d471558676029a8137f95b0ba0e7315bf11c497f0f0000000087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d67891800012087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d67891820593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c071594bae6e759f13fbc246c11fbd8d97d68911241000000000023a79195fb4e1ffc000cf99e000000762e689e7bfecbe16bfd0e6138eea642ee0513c5762e689e7bfecbe16bfd0e6138eea642ee0513c5c69a0bda7daaae481be8def95e5f347a1d00a4b430a7afe7674de986aff5e2e0a173be8c29abed8b5d6f878389ea18be0d43c62ad1ba66a59e9e8d8453aa0ed1a69697675800019b9cdbfe3568cc0b37f136b00a634c75653f05e301fb8f3001fb05a3870c6a346d863f0963e4a5f251dcd712b0a8bd8ef6aa8f63c7ccfdf981810705000020870c6a346d863f0963e4a5f251dcd712b0a8bd8ef6aa8f63c7ccfdf98181070520634482f1393532816bd77ece32a84a17a334ac110e47184574d16d8b772261c9007d4af03527d7d34738eefa6bef126718c5e4edc50000000000235667d3fb4e1ffc000bb3b40001fc000bc783006d8404dcefe34e6d52bdb4350026dc8ce574b05e6d8404dcefe34e6d52bdb4350026dc8ce574b05e1ec5c66e9789c655ae068d35088b4073345fe0b03001715f72f5b165d307bac41c2f933aff79265d1b3b7fbcea31e1cf842ff4955b8ec9f510391659eb05282aaf7434b4b500000000874c44b97f12d2ab126377cacdeab45e3fff8c78267c71b1ad051a714d58e6d5000020874c44b97f12d2ab126377cacdeab45e3fff8c78267c71b1ad051a714d58e6d520a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e4da1130bbd7061d88f984d3ec1507026ba9b2493b3000000000023552198fb4e1ffc000ccadd00000001ecf043431973b9cff69b82f15ac7f6a6eb15cd01ecf043431973b9cff69b82f15ac7f6a6eb15cd64f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d73015a577f51dc6fd7fa4621f0a4601e48fd65418a89c2af2afef725fb4f053a8ee5841cd3fdae39ebdf5a202e0c4deca230000000087c23375674218932c768502d4ed00794fa327b0a95f3fd07e3366021284a8ff00002087c23375674218932c768502d4ed00794fa327b0a95f3fd07e3366021284a8ff20e7b95bea480d82316911dec49a09e8ab6a65a40fd4fdd93f11372737636de4cb019dd617c523be40d62d6fe6c8099a2731bb8f64b200000000000353f0dcfb07cefc0001d4d40001fc0001d7830041abf15cda4f87c47836fa95b0e6909449272a4af2b29900381739339a74d57fdbc677a6ef249f1c040683a4f0f1c3abb09335c41cba814d8f1a24a3308074793934715bde7630f4f267a9647955ac45400792369bd3e5f88e2b9d6c809251b79428e3a8ec07bdbb7364e3c2990000000087c5a82f46522a809f60943985bdbbe6ab131f49bc4b35602c0b2ed34dab354d00002087c5a82f46522a809f60943985bdbbe6ab131f49bc4b35602c0b2ed34dab354d20ae0e04e42fd5e99597eeca25834c5eacb8c990957a179f2873cf4b913b97af9d019723404c2622b84de329f7bc2459cc224eec9ba03c23d70a009de62866fb4e1dfc00025ea30001fc0002847c008a8dfe8a388fbef15d0035c320ebefd5ac5ae2463305078857e34417e861260119603fc23c67d221d458f5157d91f4832e66eb8630ab3dbff95551d83084fb8f4119d367a2336982fecdcf326c56b7c09c0911994720ebe2a657d5d95252be1871889b13f81cdd16d49e15a7d30000000087d21608895b8148fdb2c846d5401158720c3721dc07c4fa0981f2bb25ae52d600002087d21608895b8148fdb2c846d5401158720c3721dc07c4fa0981f2bb25ae52d6201e4a5c4121ca8d8f8e51946d9fc42b510937cc7e0a0b9ff1b353aa316ce8a4fc017433ee61219aace0ffab939271e77c28e1290556000000000044b7a536fb2714fb6a490001fb6aa200419483f32fe1e48e4fb5ae37cb31cd39247ed46a419483f32fe1e48e4fb5ae37cb31cd39247ed46a6428ac0c44a1383f70c2fe1f13b588e2dd3b14dc30974b7b4e608007f22ece8fb933fc18d66cf35cc0e5a7977279a092976b501786d4ab9108c7fda681e23978bf54b7709a00000000880ddeceb54dfaa8c4750e03f69d38c06dcb2f8ffa9dafe9b3f7a08d28d45e99000020880ddeceb54dfaa8c4750e03f69d38c06dcb2f8ffa9dafe9b3f7a08d28d45e9920a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e63dbebe4f6a661367d4a83b8f988b5759628d7f66f000000000022dc5551fb4e1ffc000ccadd000000a9cab48330c4f2058fc7d331b9355b91056c68e1a9cab48330c4f2058fc7d331b9355b91056c68e164f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d730111a30e0a5f2f5135dcc5f09498e4ba5de22c7680f396599f7f29b91ac569c3d4336bc157443cf8c06682bfb5abb22710000000088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f00012088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f20593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c03090aa69c8d1a95839e017d1b2b53d3499fa0a9aa000000000034211c2ffb4e1ffc000cf99e0000000799f054652c1cef10d2994fb83d012d559a1faf0799f054652c1cef10d2994fb83d012d559a1fafc69a0bda7daaae481be8def95e5f347a1d00a4b430af9cd8567923fea3f6e6bbf5e1b3a76bf772f6a3c72b41be15c257af50533b32cc3923cebdeda9fce7a6bc9659123d530001711fd9548ae19b2e91c7a9b4067000467ccdd2b501fb8f3001fb05a3886622da5d1f1b025f69e4cd924fc1928ea35d8312b807d8b50d63107fbd9a16000020886622da5d1f1b025f69e4cd924fc1928ea35d8312b807d8b50d63107fbd9a1620afdc274a214d9cffbd84cca49182cdd43ad3abf0aadb1546dc88cfe6c0a754ac0008dcd60f55257d858dca51e0ab3b65e4680cf572000000000022de0637fb4e1ffc0006567a0001fc000bdbf3000fa716254623b29b7651b989fbada389aafe097a0fa716254623b29b7651b989fbada389aafe097a1ec5c66e9789c655ae068d35088b4073345fe0b030162563fec3d0cae18031294dd0f6a4bbcd153bc1c087b18a7438a95650a2225926347ed3f7cb4723972ad97251b6b35d000000008917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f2340001208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f23420593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c21fe8d862d5042691749e866af337e50e599e64fdc0000000000340d8492fb4e1ffc000cf99e00000018d9316618b1f55977af250cc5d8783617084aac18d9316618b1f55977af250cc5d8783617084aacc69a0bda7daaae481be8def95e5f347a1d00a4b43087d25769002af2a4f050127c73fff03a24935e48f34fecaacd69410787d0e6384b345c78e81b1cb397b43dcd635568b600015bdbf34a0dad860c6ec71523ae39373325225cc101fb8f3001fb05a3892048b276a248b44e0e0c498fe0133e19a9a19ff03d2a6201779759a9e597fc000020892048b276a248b44e0e0c498fe0133e19a9a19ff03d2a6201779759a9e597fc205b016215386c035a42042a93736befccdb87c30cb90adc3b1279da58ac57cc14035a6f7ff4fd5aeedd90b2d4a9a746d07039afe6e3000000000022dbcd67fb4e1ffc000cf8b101fc000cf99801fc000d04c300db6568bf9cb89a725c973fffccd4baf12b4bcb82db6568bf9cb89a725c973fffccd4baf12b4bcb82c69a0bda7daaae481be8def95e5f347a1d00a4b430a7676e9a8ef4eaafcf47451801388500aaa1c1994c5df1619eb3b54b83dfab28c7969b262454c0397fe6fc14dc8c62d9000000008ab9b419adde6c292a0376f1b010293252bbb70b7d1ac3e08a843cf7c1d1ec390000208ab9b419adde6c292a0376f1b010293252bbb70b7d1ac3e08a843cf7c1d1ec3920b7ced6bdbb2bd4be7c03c89225aa80a21fa0f189164195d6b38e852a9f615a66000abaa849176e61dab40c075e5a1e80e0f5dc8133000000000022d18d8cfb4e1ffc000bb3b40001fc000bcbaa00a3b6ec8347384c53813aa4eec3f5b4608434ad71a3b6ec8347384c53813aa4eec3f5b4608434ad711ec5c66e9789c655ae068d35088b4073345fe0b0309226928f9d21053e24678f1aea92d7668e8c8b6f75c07519a32a40491428908dd31fcc8c7c630d92eb1255592169b8ab000000008ad0ad3c5d5e607a7978ba3f026240beb079a186a784e2034b41fffe917c46fd0000208ad0ad3c5d5e607a7978ba3f026240beb079a186a784e2034b41fffe917c46fd20a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e458fbc9d5e0fa407cd7238155ef388b400bdb7aeba0000000000235cdb7cfb4e1ffc000ccadd0001fc0010e77400cfbd1e90f25b6978cc09db70685726fd4469de39cfbd1e90f25b6978cc09db70685726fd4469de3964f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d7308ea71272ac9a9c891f0987a75e2200a44fc063bca92892c0a174cff4c0a524935e0b870bd091329836e43ca7d7c87e7f000000008b8d1193afd22e538ce0c9fb50fee155d0f6176ca68e65da684c5dce2d1e08150001208b8d1193afd22e538ce0c9fb50fee155d0f6176ca68e65da684c5dce2d1e081520593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c0b3fe432c394e3e96e8804a8e059b1887afc913012000000000034229032fb4e1ffc000cf99e000000b802f02882ed36279ba95674e7e190e86bd6458db802f02882ed36279ba95674e7e190e86bd6458dc69a0bda7daaae481be8def95e5f347a1d00a4b430a1749fecb407bb0e0ab9d6df65ea068dba5dc03e14dcb36abe5cb2b5c6e424683f715ff09ce290d035dbb31add0c01800001a0a0e17bfe82a484fefe348b7569a6d77d29d2c201fb8f3001fb05a38b971ef085c168cae87c3ef20dcdebb23a9a26eb7d47a4f793aa2353bed4018e0000208b971ef085c168cae87c3ef20dcdebb23a9a26eb7d47a4f793aa2353bed4018e20506cc8538b9cda4631382a1226a65d86a77ee7ca6fdf7d649c06a104c956903b00e91bdc77d4faecb8481e9d54c7e69a74c98d664c000000000023a63971fb4e1ffc000656800001fc000bd4aa000466dd0bf8e08e82a49b9d1e42872510886ab7630466dd0bf8e08e82a49b9d1e42872510886ab7631ec5c66e9789c655ae068d35088b4073345fe0b0300d82df2de7cad8263357f244c3c20824b450e7ad24c6ab0e264a0936b7f737e9402144c5205d4e38507dc90226ab97f6000000008ba8c6867b46bb40408022696bab30719990806d6e5eeebebe8e5377228b3ac70000208ba8c6867b46bb40408022696bab30719990806d6e5eeebebe8e5377228b3ac720dc964f0dba071a3102960a4848d57042e6397a041568e0d8f988d79202fcab780186f37c9afcf2222c2e1846e6aca7cc3075cbbf81000000000022d2f6b9fb4e1ffb7a1501fb868501fc000119c3007dc8a7ab041ff32acaee3dcfcac1e36bbc126cd2b2ea896299dd86bc7c3353a40d354be43ca263727eb0a0af302dd9ff95daf9e98d2f1f2c5d764f74308b5d53516c0c7134efabc77f5f7d19b6e289b5e8befc35ca5d77626a252e659888fdd09a7c9bb286dd9fc4d73025bcd7000000008bcd5c2b4956f890f454d07300fbc2bd5ec291f9f68c5ab4f44af8073a5fbd8b0000208bcd5c2b4956f890f454d07300fbc2bd5ec291f9f68c5ab4f44af8073a5fbd8b20a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e59c3439bb3f8a5f9106af32c1c8cc8d730bbbd8e9e00000000003646f303fb4e1ffc000ccadd0001fc0010e84b00365a8a65e5270895c8e0a3557b1bb425c8efd7da365a8a65e5270895c8e0a3557b1bb425c8efd7da64f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d730183e7c881c6c556701b21eb3f837e2661ad4ae1ad5b9f11faf6cb1246daf99157f3da6491b8dca8517b33b32abce82a3000000008bf18698fd403d18f976fc5f89d79db263fb354a63781a512e2d48faa17190f10000208bf18698fd403d18f976fc5f89d79db263fb354a63781a512e2d48faa17190f12051d89c906e2bddf572717e4806a4be5db96b544b5c9425a069351a0e218c9c2d01e973eded63a3abfb7f48eb28c27469e5da76a01e000000000017f0e8c3fb4e1ffc0001ca240001fc0001ca940039f55c68417e332cb9d56879392d0d34b8858df704dbf4531a1c3aa937a63bb4d5a67f13a335d5c3b1605918c84d18613d2c487619ae380f36282ec8308041404bfd1cd4b71416116af92b7a17f42c47bf3dbc2294369fe1691eccb9ba851183a0e85a4fd728c946a582d006a7000000008c15296dda100476466c2af9f2d212097c0dad634c47894e34e89b0772a7ef6a0000208c15296dda100476466c2af9f2d212097c0dad634c47894e34e89b0772a7ef6a202dd418858077835bf0cee0935325099557a492a8de9117e9477c520eb8349d5c013db931950d15afac53606bc3191ea0ceb8f1a0380000000000340ce25efb4e1ffc000b9bb30001fc000bd24b00bda32a6923c976abd03cf593ee3eca92f44213e0bda32a6923c976abd03cf593ee3eca92f44213e01ec5c66e9789c655ae068d35088b4073345fe0b030858aa595f574ea2a3c76a01d3de5ae733932304d08be169583c75df7879dff27232b0aae832aaa25f318c38794b9f670000000008c754a2bdd2ace903ed98aae9f52f481e7a6949ccf422f4297e0ba9a500ca2740000208c754a2bdd2ace903ed98aae9f52f481e7a6949ccf422f4297e0ba9a500ca27420a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e51a502e87250d362827c252cbf2a4b54bc793b34670000000000340c3659fb4e1ffc000ccadd0000004bbca9fd6c162000d1042f510196c4d069bb05f94bbca9fd6c162000d1042f510196c4d069bb05f964f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d73014eabcb82f2b0b9cda8eaa3cecd39f0058b418cb7a25795f597a811895bfcc23643bb25ae8432a52804dfb53575b649e000000008d4d1bfc7e6667a370e072079dc70b3e3268f71a32a54371487339429aa475360000208d4d1bfc7e6667a370e072079dc70b3e3268f71a32a54371487339429aa4753620431d3dbca48a3392be9c41a68961f2d1cf3d5e5b93151b2b1e47f635e03ba2b6001d70b39a95401ae5dd407a846e9a775a92513f5941700000002d3f6868fb4e1ffb544c0001fb669a00752afd96dceb969687676e32c4cd3116b76a5c84571ac9b0061529d85a340440e6fd38a3ad5633c847b71db162f3f607a3fde13909f0df2e296a72703005e588704a6f6d703617081d8328c006b1173d60aa26cfe44b954f1279a1ba9a042bddc5b3a00cbc8180676d12060d620155ecbd72e31176702506fd6219751a8ae1a6c4310000008de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc40001208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc420593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c1dd08fdbbe79813bc43a306740d2182674141d76de0000000000342b56e7fb4e1ffc000cf99e000000300904176cc6023370b2462964c12c5979b9f411300904176cc6023370b2462964c12c5979b9f411c69a0bda7daaae481be8def95e5f347a1d00a4b4309502bb884b3437d65c0e025e49fb00ff6ea9f55d5bcdc36330b46c8bd18be9126b7a6d7f35f558ef8040f2c2284500a50001337b7fb5d2c531825c3e0123ac3354018085b30201fb8f3001fb05a38e0c95f8f71cd450abe7495077ecb431068da7821ca4e38af735565ec630deeb0000208e0c95f8f71cd450abe7495077ecb431068da7821ca4e38af735565ec630deeb20a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e375f7056751bb5796fd2d228ed85f5c88b053e6443000000000036be8308fb4e1ffc000ccadd000000d28ef7142aa96b23b44a0e7a5294dc2152e5f53fd28ef7142aa96b23b44a0e7a5294dc2152e5f53f64f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d73094a0bd3671bf20ef2a75c2e1723eda50a4d7566ceb0f5e018af7c576e11b1320b4b370e703afd4a7220a7c5688414040000000008e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c00001208e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c020593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c20f53e3ff160dab7ec3cc2a6b0afa6dd8d36e38794000000000034599a30fb4e1ffc000cf99e0000000063eb51fcfd121e6c3eae23b90b26cd1100217b0063eb51fcfd121e6c3eae23b90b26cd1100217bc69a0bda7daaae481be8def95e5f347a1d00a4b4308160877a911d8bb7d1e75e2320e98cc3233c1f6972cb642424bfcec7c182c56d2c0ebb59e45f788f4d5dbfa2ebff3e3a00016d57707c196e06487d326094c964f258f5b77c3501fb8f3001fb05a38e7a3cbb99a9ce89685175ce3b3b5efe33498f22ddb539a2c66190390ff9e37e0000208e7a3cbb99a9ce89685175ce3b3b5efe33498f22ddb539a2c66190390ff9e37e20a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e325baf1be4d6ff7516aa41a0c9947396f5dba016a70000000000235a2a40fb4e1ffc000ccadd00000072ed00fe080bf542275abf350c2922a8a2ff119672ed00fe080bf542275abf350c2922a8a2ff119664f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d730082cbd9118474316f40b800e43f94a121928f256fd340098ff0ad81a902c4326dda4b42737d52739482f2baa80c487cc000000008eca4bcbb3a124ab283afd42dad3bdb2077b3809659788a0f1daffce5b9f001f0001208eca4bcbb3a124ab283afd42dad3bdb2077b3809659788a0f1daffce5b9f001f20593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c0e55b79902ab8dc5c126e61ebd5bdc2ec98d80836600000000003644ebc9fb4e1ffc000cf99e000000983259ad7ed51267fb83a8e41bbaa5ab55c632e1983259ad7ed51267fb83a8e41bbaa5ab55c632e1c69a0bda7daaae481be8def95e5f347a1d00a4b430b942e2e50c5cf9d9fe81119cc5379057c05fe15134f85847356b5d1f6a21f29f4a53f61f03338d056edc15a8c63fbbe80001c075993a8336f93a13bb7bbb7e0e89928be4aafb01fb8f3001fb05a3900618389dd73377e2b33b021d2e8b0e7c51f8f5c1d871af15886e3cd6e6d6ae000020900618389dd73377e2b33b021d2e8b0e7c51f8f5c1d871af15886e3cd6e6d6ae20a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e3a699566abcaa3fe7f3568b95e28dec3bb11537726000000000022dcc2fdfb4e1ffc000ccadd000000e7b23e56a97aec080890987ca187cc902a4efe21e7b23e56a97aec080890987ca187cc902a4efe2164f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d7300dc75e865b89e96560b38fae96f1d0a5438795778e68b705a506046245ca5dbbedb09e2379eea4c9bde0d0fd4fe0508000000000902c18f9e7451f382b6a41e96b766ac3754e792a31e75c8ca0f2da5bda93c708000020902c18f9e7451f382b6a41e96b766ac3754e792a31e75c8ca0f2da5bda93c708203ad39dbb8bfdfb4a46d3f8b1e5b328c4724acac30b82034349a6b831070b8dbe0008cfb189e4df6f2fee5f9c756a0cd23b3c871067000000000053e97783fb4e1ffc000aa0540001fc000ad2eb00747d38fd242d8f1114f47fa24a233831b5305962747d840bce00916fa12947def52684f03a37618b08cfb189e4df6f2fee5f9c756a0cd23b3c87106730198e877839e3a29d8e1e0f0f8db6d9e533902dac30db36ab1330fc4e1e45427b658fac866dd8bb65b0c68b263ebc695f00000000904132db5c8718123233252283268bd908f1585a7a8db92f997c03694914f0d7000020904132db5c8718123233252283268bd908f1585a7a8db92f997c03694914f0d7208e8e515f7025352e7c608479e413beacf0d95cbb964b47e4a98fd27b6b6b628a20484569a0b078f0dcb21a0253aff10ec06b1aaf01000000000034d41347fb65e1fc0005e6990001fc00065754006efa257a906f0adf9b184b0738a187a5b775df686efa257a906f0adf9b184b0738a187a5b775df68484569a0b078f0dcb21a0253aff10ec06b1aaf0130962c65927aa1616e3783ae7cdf8c3d19b4c26b477686a9f146cd9ae40eb7c0e01a1580d5df8c32d1f4c43a52f62ff5e00000000091bbce94c34ebde0d099c0a2cb7635c0c31425ebabcec644f4f1a0854bfa605d00012091bbce94c34ebde0d099c0a2cb7635c0c31425ebabcec644f4f1a0854bfa605d20593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c1eea45a388d248dcd7433c8c8113d5d0966069413500000000003428db29fb4e1ffc000cf99e000000cf83406065cb65ce74100f3c35a0324bfc92dcb0cf83406065cb65ce74100f3c35a0324bfc92dcb0c69a0bda7daaae481be8def95e5f347a1d00a4b43081ad0f9be5a88ae62ff54fe938dfceea71be03bd4c6a7aebf75896e8d495d310acc4146aa4820bc0e5f5b06579dedea5000102aa69f8ef6666e7cad6d9323755a0ef3c1b6bd901fb8f3001fb05a39212f5312730c7881b882b9fb7864dc686fa5a585b7a93253ccf1ce87ee593310000209212f5312730c7881b882b9fb7864dc686fa5a585b7a93253ccf1ce87ee59331203193e57ee81ccf3c25937a5b585afa86c64d86b79f2b881b88c7302731f5129201eaf63db1bbed2ccc65ff8763bf9cabf44b8d6dce00000000006418ef40fb4e1ffc00017eae0001fc0001eef4009f804e8f9cea38d4380e1e4600d4e16bd49ac9d695dc83d7059a8aeca9996d6c5436db3f8c9924fff32bb66d6fdcd07b1268d21a3e021c9c95445293301931bdfa94f15b64ed9d09d210db9998dfa068332fee19d8e1ba4872c0acc3efc723e2fd04a64ef2da473caa4471c69e0000000092b5bbdfcd2d46938c23f5d48ac6dbc2fb041172766455fbd8863cf81e8bc9df00002092b5bbdfcd2d46938c23f5d48ac6dbc2fb041172766455fbd8863cf81e8bc9df20bfbd6a521797bda7e2a5219db241c335870a521037815380e7ac2bca5be84948017bfd226583bc3ca0a3547672f9d264fa04a9d9c200000000006a0c494afb4e1ffc0002fbd50001fc000377ac0007ec0bbe822a5aa140229c9a460489563a7b6a77bb9bd2501e88903aa50a1eb8f36a5eb1fd0a29e250299c1357baa7e34f19a5be2a225eb65f5dd9993007cff9e4c50da82722bf41fa5da01ca4bdb238d8d53fef085a56c34a432f6994c79e5bf754898499ec4dbe91eec0d00a0000000092e1ab09f73e703c196eea46780a14e8eefa5b5e1c0ee31be05718056e020af200002092e1ab09f73e703c196eea46780a14e8eefa5b5e1c0ee31be05718056e020af22020904a313c770af35f380bd22f3f7a1891a7f368e4594de5889adb9beae26911003306e27f0719a83ffd6ebd35183d8dd714991b39000000000012ec7145fb4e1ffc000bb3b40001fc000bc7cb004c6cab39e8742edc7d062b3ec2c51aee9342e8dd4c6cab39e8742edc7d062b3ec2c51aee9342e8dd1ec5c66e9789c655ae068d35088b4073345fe0b03011b5a1fc5f84431ab1546dd7189b7ce61eb9a0615a96e4467819a4af04a633627aca3494cf5636f2376228bbf7e91b470000000094044c070f9ce6bdd05c2b655ad2383c8402a74c10e0a9a3099d759b33cb763000002094044c070f9ce6bdd05c2b655ad2383c8402a74c10e0a9a3099d759b33cb76302081dbccc2d89066db311d0d2ca068436e6d98ffce705abfd0ecf69d70f7206ba401b542c265e3f41425380ee61edfec8a5dea7fda0600000000006c3dbd90fb4e1ffc00023acd0001fc000529a4003c7b27ea1137b6aa8714ebf68d9c54fd7fe23b414915c7d1e335096ed8afa549bd4b52c6491d0df912b3c0f5799b64529486fff598dc276c4897154630996f5888a81b9668c16a12c87134536e3616c929a7b67b37aa06d3eb7d7e405e3d3148ce7a072128c9063e1a8042eccd000000009427f6cbb0807d4783d74927eaf1a70e9c19339ac47ac7be1dd80b0ca4ec28350000209427f6cbb0807d4783d74927eaf1a70e9c19339ac47ac7be1dd80b0ca4ec283520a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e438df2a5d0be49659e711d7ee517481e23107fd25e000000000022d1eee4fb4e1ffc000ccadd000000de39cdda2efe7dde604c1965fa539df01785bccade39cdda2efe7dde604c1965fa539df01785bcca64f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d730959f6f2d48d283390b246a55b19a267f8ada326c8eb67f217839d5d1cc55377d8c1a2962cd5e80b892577454390c36b800000000957acb5bb59e253059da86924b5bbd94c1daf5b0fcd313bdb78e43bdc7cad000000120957acb5bb59e253059da86924b5bbd94c1daf5b0fcd313bdb78e43bdc7cad00020176deee4e53c297f44029a7db294451139901bb49f33a2a0ac8bd1b9e744fee201c406356d37513ea70f93868797061aec981337a700000000002d87b4aafb4e1ffc00102b8501fc0010594501fc0010598300cf0ea50da406da09dd78689abaa7c44aad428e3f37f1afe5852c1aece552ed1be61dc898a8db05f06e0e8a6ca912d408dc8369365e947a41d9d0a9d83098fc5928355798aa9237b107935ba606bd749e16f2922d8c4eb6b6c2cbbb4210f3bad09fe7d199aa3884fae3fce0120d0001a5bf8ff04bf1be7f1d98cb952f1b49f8d162d8a301fb682001fb01bb961e7fe42fe63f21e6e21556d2b4cc8c0423c1e176873efed3a14136dcbcf887000020961e7fe42fe63f21e6e21556d2b4cc8c0423c1e176873efed3a14136dcbcf887206fe932a6b6385b29bcd78378e71a727bcff83226945744019035493b24003e5301892f0612c075706dadccef0848d67a8ff5b8446f4120000000a7637017fb4e1ffc000899e301fc0008a30d01fc0009093b00a656c3104b5aa2a042680aef3494b62eb3ac3e7ea656c3104b5aa2a042680aef3494b62eb3ac3e7e52e70333f9bcad1e0b5c60777fbc3a17bf23e1d830804fadcd7b5dade6f9f577fe663cdf86f1483b71e6fd8e7c5cc4b981c0ee086412b16c796ce8fa3f7b6445fbee8666400152e70333f9bcad1e0b5c60777fbc3a17bf23e1d80000009693e443a6820038ad1160ae01311a85b4573965ca4480317611d5b6e048aa2d0000209693e443a6820038ad1160ae01311a85b4573965ca4480317611d5b6e048aa2d20b7b7b143980f65ade8556b431882dcab54ac9387fef544e8581d709e53d19a000052fc8bcf6fea0c7ac216d544308afa9d8920774900000000003695fc92fb4e1ffc0006567a0001fc000bdc0b005e66b53e3569ba6d1dff160ed56d074dc63f96c35e66b53e3569ba6d1dff160ed56d074dc63f96c31ec5c66e9789c655ae068d35088b4073345fe0b0309058f3873b1b4fcde2ee8c817d04626cad7de91c972988a4288d4548d2585074c11f29e270d094a9ed95f8618ab8ed54000000009712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df540001209712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df5420593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c1277e135a613d9797db4d7a9d2e51bfe8599d3650200000000002352c5c5fb4e1ffc000cf99e00000020c7f1991e06d09b1f067b049fe6d0af0a20f79c20c7f1991e06d09b1f067b049fe6d0af0a20f79cc69a0bda7daaae481be8def95e5f347a1d00a4b430a8dbccb130522909dc710a65728006732c18441757f12a338cf4a6d8cbd5baf1a484537a6a0542f51bb686e6e546f1a00001ed1131823bcea23ac78af8c01e4d24683d6ecf8801fb8f3001fb05a39767a4cafa9d1057b48de795ea834a15664b58a79d75a4f826299ce1ba11842c0000209767a4cafa9d1057b48de795ea834a15664b58a79d75a4f826299ce1ba11842c20cfc9ca7becc69990bce0fdcf42c6d7ab1317281effbb2bef1deb457d226f3c1c012a566509d67f0566a01c5bc8c19b455095a52eb000000000010000000000000000000000000000000000fc000170b801fc0001b6f301fc0002289400f3fab21f5d1e86919c2e57fb4561244688c773aa25df60b3535787ed34aa614aeeea9f99236ea994f0e4fe2e70afb072ea5c2d06f5cf8503068add46300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba09209600012098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba09209620593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c178b5541d75eaaa98f8ad22355a122c55741f339f200000000002ce8c406fb4e1ffc000cf99e000000caf6f1b9916245ce300a63fa2254ada25e0423d6caf6f1b9916245ce300a63fa2254ada25e0423d6c69a0bda7daaae481be8def95e5f347a1d00a4b430b6175b59aba8cc0477d4fff78bd90294f31ebd385c39bc254c7995a5dd3ccb8dc1d8869e247bf63bef8ec79317f479a90001d6ece912cbf02627a4efc3dd37e6833cf367155101fb8f3001fb05a3995d7facdd36d2db5a0e3621ea50678ce494149b4d2dece73d4a7fa2e095ac1c000020995d7facdd36d2db5a0e3621ea50678ce494149b4d2dece73d4a7fa2e095ac1c206a963e1d05f10a5a744a8429a7d5ee8f482c4f6e7c4093a2c60c124f4ae2717001683eda694e5f2b0e9edd6f281eaac015f59790500000000000cff66169fb4e1ffc0002055a01fc0002099e01fc00020beb00f05505af7fce03ad669a45ee34ffcdba84636ca2373eabed3a46c91e10415d8a7e0b36c2867b92f96baeb84347272b9450cfad36524806f5f8135952308c26812d38faf159f811a09c1462e07e40d6b44881114358cb5390b65778ee437018c5879fbf935fd78955899b67633e000000009a37c6dc3e32f3c52d3f3af8b4d46b773e01d3bf27817bf609b60631c620b5900000209a37c6dc3e32f3c52d3f3af8b4d46b773e01d3bf27817bf609b60631c620b59020a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e2b481b3ac3d0ca22240b01de36b235aa1eaf0b05a3000000000022d4a1bafb4e1ffc000ccadd000000fd47aa98b58734af1453cdbbe5ef9396716775f8fd47aa98b58734af1453cdbbe5ef9396716775f864f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d7300aeb5c2757211202b3afd2033ec1b4ef2dfe376ba5c6c07b45e6a7460afa4086423c4a704eb9a781514fbc513e190a62000000009a7f3e66905a2588695023cb6638bac294aa7ba4fc332737062398a173447f4e0000209a7f3e66905a2588695023cb6638bac294aa7ba4fc332737062398a173447f4e206c4add138ec5499b898d5d712924cf027be42e67c94174caebf143030cf15bd401d544504a737db17be4b9bcbe091cb419c8dbe3f000000000000de4d231fb4e1ffc00092bc20001fc000b4a5b0092d2b72ce01caa349e82d0490990e20b88bea135fcec2b5f013e92232ebfdc4f814ac10eb533a25ea5aa7b99f9638528d9186dd57d008654a3abc7a8300517910047a316c354423fedf0402dde38c90fb376dfb680e6b2b430addea140d0b6c795d90ca17f1df658a5d401c9da000000009adf02049b965817cf6fb5b675c17dbc00df7e2fbf68cf3377adfe30e3ed0bca0000209adf02049b965817cf6fb5b675c17dbc00df7e2fbf68cf3377adfe30e3ed0bca205e09a967f881113c81812102e3d365e6573b7269ff1613c7110d058e24ea123601800f683c47564b0cf20428c9abbc735e96c6a49941200000004e2eb95efb4e1ffc0005a5ef0001fc0005a6d500a7889dad2c33e1f6b8b68aa5cbb7392d9e96bdeea7889dad2c33e1f6b8b68aa5cbb7392d9e96bdee27aec5b42d8d74dd11d216bd2628111c4d9fccda300df074095e5498c6f1b76508c3ae700484d8b0d5cd12a990f3dd54e35b47d6fc943af4223d390ddaf8989d883c84b284000000009b135e3d6365e6acc8c0eeb513a3c8cfb68525e6d4719645fdb3fb3340caadc90000209b135e3d6365e6acc8c0eeb513a3c8cfb68525e6d4719645fdb3fb3340caadc920c9cf125e893ba997d1e05decc65ca4ae5c3c658df9b693f1c3b8ca6a14c2157800279480b2aaabcef3c8f4d073724dfffdf6696d13000000000012ec1e46fb4e1ffc000af11f0001fc000af13300d89c5ba79b9553a13f783b50673e15283eff3a3bd89c5ba79b9553a13f783b50673e15283eff3a3b49fd7c9727399a9d1d592b68eb09583bfbbe9ca73088ec95047130c4b310db3b6585c2fbe9453c7f5ff43ee5fe844e74c25766488fae8ad62052ec76a6c2b584029e1b1b04000000009bd4945c016d11b08f5c137900df9fd5472726e002fd7531ffdb4b25bb3c9d330000209bd4945c016d11b08f5c137900df9fd5472726e002fd7531ffdb4b25bb3c9d33208a2bba7feee4b42f3f0d1bf6dec1a3360ea7f61d3352af8bf3a37cfa9a2281ad0077398906f47400c2223db65c6d6b6aff09e0dd2c000000000036c83f2afb4e1ffc000bb3b40001fc000bce8b000a641ffc2886d96fc0d6739f2877e0cb81fe075a0a641ffc2886d96fc0d6739f2877e0cb81fe075a1ec5c66e9789c655ae068d35088b4073345fe0b0301964cfb5518ae0d35f2d02dd5c402351c318b79de1c5ee407811fa950b0ea2ca9f794a8d07ce9cc30fb76fb4e9ca3799000000009cb04f271ba050132c00cc5838fb69e77bc55b5689f9d2d850dc528935f8145c0001209cb04f271ba050132c00cc5838fb69e77bc55b5689f9d2d850dc528935f8145c20593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c1bbb948d5d33120f51f2ca02c77a0b69761b719f07000000000022d63044fb4e1ffc000cf99e000000c54ac69739bf492d4328f1bf0d49581ce0b10d41c54ac69739bf492d4328f1bf0d49581ce0b10d417ea623bdf8c5607f0390c85586d83d473fa6a1c630b6ee48c7a71a9d8e0813e68ca09846245fa155285f24a62b0ce9cb0102b1994ec58af8ba2a01c09363bdcc395d41f3df000162e960a3f6b650feed98a266b3ccdf6e363562cf01fb8f3001fb05a39f1e242390cde84d67d9e2caeb1fc042a6bf0c85c8393026733ef5543fb0bd2e0000209f1e242390cde84d67d9e2caeb1fc042a6bf0c85c8393026733ef5543fb0bd2e20428e2f87d85de3d5b6a5a86ea5863d35b08e9c514460cda44dcb7e199bb769350083f05c3c1667334c68c95ededade304e08b756ca0000000000369550c1fb4e1ffc0006567a0001fc000bdc0b00cbc9ac9fd1bebaf88433e4ffbf3199ba365153bacbc9ac9fd1bebaf88433e4ffbf3199ba365153ba1ec5c66e9789c655ae068d35088b4073345fe0b03005987ec3ce6dac84c1b2cbb4753e5f361fd2217ca4251211d4eb0d82ec729b1ca540da4d8649c74b3a82e8a6e4fdafa8000000009f4f9f83ecbcd5739d7f1479ee14b508f2414d044a717acba0960566c4e6091d0000209f4f9f83ecbcd5739d7f1479ee14b508f2414d044a717acba0960566c4e6091d20ae21919b512cc68554ca16c583688865967f5375d107bbfdcfd79da5cccf772a01bfe3d321e667dfd5d7f5922c1d6bafaea45caf4e00000000002d20d39bfb4e1ffb1be20001fc0001850300a2dbf2c2b6149412562f306841959b9cac234b73a2dbf2c2b6149412562f306841959b9cac234b735cadeb631ebd16a92cbe6cac1be92247e95b51463008e37b3fcba972fe0c2c0ea15f8285c8bfb262ad4d8a6741a530154f1abc4edd367a22abd0cb1934647f033913cca58a000000009fcf7b15b9c7ce71c11b7577e05edd1ea922125b9ee8fed7d0d8ff21d530a33b0000209fcf7b15b9c7ce71c11b7577e05edd1ea922125b9ee8fed7d0d8ff21d530a33b20a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e2f5380d6cae296849f7444e27f8ccba243332d0bd8000000000012edaa20fb4e1ffc000ccadd000000f1b18d69579c40dc8292842f02ff5f511e61609df1b18d69579c40dc8292842f02ff5f511e61609d64f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d7300b04bcb5cf6d2d6df5979234611da42854a5e69374a29e0c85128caedb53d9c818042613d2f30f3ef782ed37bd8ce161000000009fe2f8d43c11c61b5a545f451d5f9ffb89bed5bd91f43988eb97ce9a336922810000209fe2f8d43c11c61b5a545f451d5f9ffb89bed5bd91f43988eb97ce9a33692281200e7a78c30d54bc56f44597f4369f988aa213df3bb910776ba9940e048e37bb9f00e06459f7aafb271dfbfd7ed7dd16fe623589a9ef00000000004e2ea116fb4e1ffc0002dcf40001fc0002dd8c007ec334a85c5cf331176646c2c357732ec06eba397ec334a85c5cf331176646c2c357732ec06eba39e06459f7aafb271dfbfd7ed7dd16fe623589a9ef3080174252e0f66a71b7e53f8b32dea5f97a6b39dfc1479c6e355daa415b1ff7733a4bea6bbe3fdf412fed0fb60e5b71d700000000a052764f93c4edb6c4bad2de10f9328738aef20bbcf3185dee993853a746c097000020a052764f93c4edb6c4bad2de10f9328738aef20bbcf3185dee993853a746c097204dea6406996a98efea88a66bddbe7f9568093185b08c865b1b664ae0e594c7be04692f66e4d117895e7a587976901020ee0bb57dd1000000000036bf4419fb4e1ffc000cf6350001fc000d08cb00cfdabb52d6248b141eb688cdb12f8f07641c3e94cfdabb52d6248b141eb688cdb12f8f07641c3e94c69a0bda7daaae481be8def95e5f347a1d00a4b4300f6c077a09de24df2cc17b64543bb12955632f52bb9525df7686f61c5c86d820ef6d71e9e333ecc869e71418cad80cb000000000a07dffc303cc8c8305380d7d1076d4a0b49bf8ea06352751a1480dd40bf806b0000020a07dffc303cc8c8305380d7d1076d4a0b49bf8ea06352751a1480dd40bf806b0205b016215386c035a42042a93736befccdb87c30cb90adc3b1279da58ac57cc1402276e8dda7b00c16f6cb09751662b1ad26766fff0000000000036bc2e26fb4e1ffc000cf8b101fc000cf93401fc000d08b30083abe51882a96d3c10cbe4a277aec4e0cfbe39cc83abe51882a96d3c10cbe4a277aec4e0cfbe39ccc69a0bda7daaae481be8def95e5f347a1d00a4b430818b1f2d7341dbe7d236945a76a2798da654c792e1311a92736ba4de810af25f1b305ce9acb314eafddca5489f1db88800000000a2313686a6daf92c85bf10c45876b257aaa710b6767d60850c78e33905be433b000020a2313686a6daf92c85bf10c45876b257aaa710b6767d60850c78e33905be433b203b43be0539e3780c85607d76b610a7aa57b27658c410bf852cf9daa6863631a20171d7b555e8a999afba6cb76fd165477520839400000000000068ec34d6fb4e1ffc00065b2b0001fc00065b450050b0f07133bb2fecd59710ae0a4baef7223aceba83c1f4c02bce59c4775cec76c6ca37241429c4e2967023bde3c52aa6bca87686da2c8d5f6cbda76e30915b61f2b726d5409a26a41bb3f350c1e4bbeb5e07e808f9f68361d70ac7fc2fc33178ac9639ae7ef484a427d326f24600000000a3b3e4b3d98c934f056a2e76ec8ff07ef8473b87f559295ece2254b3820e54f0000020a3b3e4b3d98c934f056a2e76ec8ff07ef8473b87f559295ece2254b3820e54f02071ec8af2ff6a68c9fe83db26214dc6cfa49f7e48e20099bb676bc08a26e5691801c81d0059d50a9da36b88ec6e8d69cecf84b567d63dcccccd00d25ad25afb4afffc000446080001fc0004713b002ee6bd87c06f15d21562672548ebb844c5877d5bd641c8b61a2c1d3a3bd4e4c850daccffc59a4ef4c5591200b21667500e76c560dde632b87998d67c3081bc001c31c71b0d4d4f9ecfb205e914fd9cdaab4e7dbaf0b320d40f0bd5b193d1be809ca34eb4979d661f487b21124b00000000a3c1bd9b636f0ddfd72bf99f48c516050085973cd2d30dd637a55bf7178af9f5000020a3c1bd9b636f0ddfd72bf99f48c516050085973cd2d30dd637a55bf7178af9f520a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e5ac5bad801f3318192b2d124eae58e0e24cf32b76a000000000022db991efb4e1ffc000ccadd00000080a52baea6d3b53815a8daab24bb7229c3c6288d80a52baea6d3b53815a8daab24bb7229c3c6288d64f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d73094a637afe3810d73e3402b5d6a398e45222ba846a339f1c3570aa8e3f7f5b9d7acef08ac234cce4f706671498330a59900000000a430cff6d81721057000ace8eec27abbb70d223a6bd565126337ed69493e56d0000020a430cff6d81721057000ace8eec27abbb70d223a6bd565126337ed69493e56d02056475cf5f3827ba09e0307be6d1374b9e5fa9e9cc8dccfc96168be082f335031018f67a58864ad617560e1c9e6b181d0305d3b537800000000008a440d6efb4e1ffc000a7e7701fc000a818a01fc000b4a8b00f89615731050212b9a50c9a6039059397601920484a12f2ef1a65969f60c6d2e2b2974c36cb309d0f629010378393c23e3d0e1382099f8c7f3c2157e308e845bfce2651b80e95f37e231301260449d1d89aad58729398208007ee430fc8137c323857bc75cd9bda7334838181300000000a4d877cee62f82868034fb678436d87afbb13330d2b66a24ae1d357f0de55c68000020a4d877cee62f82868034fb678436d87afbb13330d2b66a24ae1d357f0de55c6820fc211290b15b583a7a8b55990bdab4493a1fe73cfd96c238a205a93b9ca23f080160859bf00fe1859bd038ccb54f7def625334914500000000005350e5d5fb4e1ffb35df0001fb51fa00d0669e929f06ac80c05365d9558ad79cbb78f2c0d0669e929f06ac80c05365d9558ad79cbb78f2c068189a3fea9999f9897f4542a7a0170679a3c3713016415af54406658be9ea44d82b6b502bb90d93e32997484533a8a71a4ed98d12cea3709d84a5835b6ad8ed48d310163300000000a565c913052a586db0d5a000007ff981ff3b59982e662e02ac6d45e37bf8f0e6000020a565c913052a586db0d5a000007ff981ff3b59982e662e02ac6d45e37bf8f0e620589799b1d3a737137c9aca1650ad98fe415cc3c035618c9f0f01b60725c2e156014cbf5b172cbd72849fa68c6fab1041a618599868000000000091efeb10fb4e1ffc000153440001fc0002426400d2a33a64d0e54ed860973f6c22ad36aebba1dc9ed2a33a64d0e54ed860973f6c22ad36aebba1dc9e2588a17ab3f917f19afeb8c32fa7c486ab4105a33001e584b5723fec78495744b68b971fd654f16b016d676ffdbac01b2c64f319675eda577f5eaa5cf5379e95418c61ab1000000000a671f057d9937b97c9d256e4eca70318cf51f7259fed49b9ab441f13cc1b12d0000020a671f057d9937b97c9d256e4eca70318cf51f7259fed49b9ab441f13cc1b12d020a8bbae719937bb8bbad2f4067a16377a022dd411f2a676d49815482084d1d235000ba82bccdd17d425113f03d098dbe9a7285cfa01000000000068f8da17fb4e1ffbc4110001fc000194c300bd605f715f78f4639ee2cb9894f6750526c952da61110603fcbf3d2a30482e4901612318b34602cdb2334b22379811352d9988876a6e586d975e732930898839eeb51c078a7785efeed45b73db7e97138eb950b84302f2f13d6b33e6f8e58eb14e52c4a9c168edf50f35d0a4cc00000000a690051e69de6e36eeba664bff34e017f973d27ce91c1f2247120e8ce586b1f1000020a690051e69de6e36eeba664bff34e017f973d27ce91c1f2247120e8ce586b1f120f1b186e58c0e1247221f1ce97cd273f917e034ff4b66baee366ede691e0590a601aba486210cd648afc5ebb8842b543da323eace1341200000002d4da7f7fb4e1ffb509701fc000b9e8901fc000bdf0b009de28ef58bce6c501541a589eadc9900dbecc7dd4d31414b558eff2b3b489b6128ac6852e0fdb85c5a375814e9caf5b8575a8221be246457e5c5c28d308b165f653a3970a17f432f6c3abb8b681c71a3775f998fff322341d2994767c167c8a43b1b4661b9c01ef637763d4d8100000000a776b3114d2137d1eedb0908aecef3c35ef001166bf3644d8c9f149b3843fde3000020a776b3114d2137d1eedb0908aecef3c35ef001166bf3644d8c9f149b3843fde320a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e3967f8bdf103c99ddc20f32961a22dcc88fe23b014000000000022d3acd4fb4e1ffc000ccadd000000127b867e4c2d040cedaff979c39220c717011dab127b867e4c2d040cedaff979c39220c717011dab64f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d73009f8a06bd95c1be3cfdcd2516fabc0858c611d63c76da3a5beaa007b9d7c895aa63c0b2887bd584a76892db417a6683f00000000aab7b2ed5bc2fa962dca591440e22b47ce41bcd2b79394d53dfac5173a3f97bc000020aab7b2ed5bc2fa962dca591440e22b47ce41bcd2b79394d53dfac5173a3f97bc20a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e53b1be8daa1cafd2685237f3e5652da5d0aee9eaec000000000022dcf318fb4e1ffc000ccadd000000853fd590bbfa10868687b7c648238857248adfb7853fd590bbfa10868687b7c648238857248adfb764f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d730018a6d23ae53d6231f7dd73a058f125340e92f6e97897f017d9d9d4e6671bbd92241170dfcdd5a4ab8ef47ef12ddcad500000000aace03a9c75c17bfb8ed760974e5dd8c94f13234cf03a76123b667caf2b71bbb000020aace03a9c75c17bfb8ed760974e5dd8c94f13234cf03a76123b667caf2b71bbb20b78304bdd6f104cf06b25c94e1de8cd1bc493b801983af667840129fa996dccc007e145aa6ecceb9581d21fe84b2c9f536f31ee0af000000000012ec8031fb4e1ffc0006567a0001fc000bd9b4008b8f48a17ec07a3e313369919447fd44560798a18b8f48a17ec07a3e313369919447fd44560798a11ec5c66e9789c655ae068d35088b4073345fe0b03019f3ddb941f0abfa5195a679846217c55a4a9830e73a97d0b93848928378dedb7a416f875525e6f16b2587abda624d4f00000000ab51b2ba4dca27658e13fea81c0764167c1466aa2d92050c67e4490ce7623da0000020ab51b2ba4dca27658e13fea81c0764167c1466aa2d92050c67e4490ce7623da02042b5315bf35d6f493d885fd156c7a9200cdf5e1aa08b27a035bdcd8058f0fb6401c7aca57d5af87880188266cc82fb2e0306d1af200000000000a763a43cfb4e1ffbc40f0001fc0001949300f769eb159cd4004c2546a757e50efced82fa88d7682f324019f53145cfdee3eb63d2dcdc151a5f6ab2334b22379811352d9988876a6e586d975e7329308072ac9a55d1cf5bf9c4262d49e2ef1ffcd716b8983ffdc62b940fec6cb4179d6275f8b68316f29c6c2ad540db32925800000000ab60639a6f7bb2c6c67fa5a65060fa94d3edc1868e8dd16457945f35caee57a9000020ab60639a6f7bb2c6c67fa5a65060fa94d3edc1868e8dd16457945f35caee57a9206a135dfa33b83c7d1afddef6dcfae0a0ff5e6c7cf6cc8f1d07451e251b0d4d8a00766e47227b7aed504a1ef568f67b059d07b67a53000000000012ed802efb4e1ffc000656800001fc000bd4aa007ad999d1a421e1d109569aeb5969d30283e68ce47ad999d1a421e1d109569aeb5969d30283e68ce41ec5c66e9789c655ae068d35088b4073345fe0b030125e7412707146bae96346cdcf3f7ed773646e5547ba57e318078051893e45b0e88ad1a6ae0fcdd89a93bc009e22075a00000000ac5b22cc7947409cd806908ac78a0a600fc6cac2a9a2eeb4a77d8915933696f1000020ac5b22cc7947409cd806908ac78a0a600fc6cac2a9a2eeb4a77d8915933696f120c7ee263d7818e4d18c578e2be6e4858c9631d303131205f9f3a43a6a4df16eeb0020a0d68a349226cc5ff472d2d6ed5cd288856ed5000000000036c81f99fb4e1ffc000bb3b40001fc000bcbaa00abee7c29b0755392bbe29c42ae94823da8025876abee7c29b0755392bbe29c42ae94823da80258761ec5c66e9789c655ae068d35088b4073345fe0b030081d223cb560a023f279a41df68f22478636932932c5e8ea6fbe56b534d4c09603587bbdd2f68a8d6e4f36838030483000000000accd3915d6756cd44d0334a6f753082cd62e723408f02c52ecd7b74280cd3fbd000020accd3915d6756cd44d0334a6f753082cd62e723408f02c52ecd7b74280cd3fbd202b9cfba78ebe0e26d1318e56bdcc2f26a896a166cb7479088558a550ebc86ab400ba7dcabb1a39ea0e8d19419f6b249eadd48352a200000000010000000000000000000000000000000000fc0004bea80001fc0004c8e50154e91ab69c8979d6f2b5f476f666dd09a07f099c54e91ab69c8979d6f2b5f476f666dd09a07f099cba7dcabb1a39ea0e8d19419f6b249eadd48352a23000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000aceff858918e60e1afb3f7418dfac7b05ebe4f5402687a7b31ad0c1f70c615e1000020aceff858918e60e1afb3f7418dfac7b05ebe4f5402687a7b31ad0c1f70c615e12042fa8da0fee62ef58885385a220ba2b8ba2d7a88eadd23137b03c8a3c9c1a92d0025b9f391c4357fd53d01c5e83916a18ad24868be000000000023a36314fb4e1ffc0006567a0001fc000bd9b4002d499b03a1f4cf6ccf3491629430440c885a399d2d499b03a1f4cf6ccf3491629430440c885a399d1ec5c66e9789c655ae068d35088b4073345fe0b0300fb1e1939b4b6e7da5bc51c8ac931736cf02e21b96c8a57e6db35e62c702745d7a838cfb50a87d1acec4a52f6b8a893100000000ad9ae35caf7548cf3df6343dede0e585702eb5cf80306e76b65db2c603baa0ac000020ad9ae35caf7548cf3df6343dede0e585702eb5cf80306e76b65db2c603baa0ac20de3daf0213196f7d5138276d9a81318e2a6f2ff27781089cafc3d3817d8f211800c45bbf7b65fec374b69de7b5585a301558adacda00000000010000000000000000000000000000000000fc0004bea80001fc0004c8e5018a366a03dfaa43d112376f878b171f8df72896008a366a03dfaa43d112376f878b171f8df7289600c45bbf7b65fec374b69de7b5585a301558adacda3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ae6f0501ba42aa004525f41ffb59ca39f85170e69a241b69cc493118ab745b31000020ae6f0501ba42aa004525f41ffb59ca39f85170e69a241b69cc493118ab745b3120790e6b01db05c42af47508ae009a24e8e0ae633aaaac9afaac23580d0b3e744e002a3b1c1fca3044d3a94b0b264c7ce60e0df75347000000000023a5bb26fb4e1ffc000bb3b40001fc000bc7b3005721268dd22359aae9210eb45596b00ba85de9ca5721268dd22359aae9210eb45596b00ba85de9ca1ec5c66e9789c655ae068d35088b4073345fe0b0308e9a07b8e11d3941637f74c58e60a917e0ae9327bfde9f2b9f1586b52416f4abce50e2c577ff1bdfc0a5d59e094be47b00000000aea2c0ad3c65b374731f81c1c3b9d08ada064798f788cd8346315eab076f6057000020aea2c0ad3c65b374731f81c1c3b9d08ada064798f788cd8346315eab076f6057209bf6470c04b9f1bcbf9c3cb2ff4d5b633101fbb5352f2aded8df1cde62867bea01066c33e3367b1047bdbad8fdcfb3fcd8daa62046000000000074cb570cfb4e1ffc00044c040001fc0004c92c00a17349d2777d28f0cc7d39fda9cace46c23036a0a17349d2777d28f0cc7d39fda9cace46c23036a0066c33e3367b1047bdbad8fdcfb3fcd8daa620463095234e6e7d476318b4811f1daaa7e887fad24b1499b3472a3a7decdd88e8bdd14551b7b67b22ab896adb298600aee96f00000000aedce7a4ed26b9f1975d071c46d6b8792c96e618215b1e3086da5d94543f2ad6000020aedce7a4ed26b9f1975d071c46d6b8792c96e618215b1e3086da5d94543f2ad620a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e0c1b9fe116e4b5263c75a13b5a3b078c30c9a2a6ac000000000012eda5f2fb4e1ffc000ccadd000000996eefc4c3da0c2c59fceec99aac79122c44d632996eefc4c3da0c2c59fceec99aac79122c44d63264f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d730007b1f3f16835ebfba6f505f43c6de757bb22ecf27a89703e90e43aedafea3df353a5bd1915b27e8db397d53f0a23f6000000000aee65248d2955c6954334ada761dd15cb67a58f919e13a41f45d2cb19a35ad26000020aee65248d2955c6954334ada761dd15cb67a58f919e13a41f45d2cb19a35ad262008ac0860ca2a3ddf7ffd7568e37bf192ef8bc83345d12510300fb2cf0150400a015c768ab3ddc84e3d35cb1e9e7daf17a359379a2c000000000036bbef0dfb4e1ffc000bb3b40001fc000bce2b006448d9ce86668d353b6cdef19b1c6523e42f08d46448d9ce86668d353b6cdef19b1c6523e42f08d41ec5c66e9789c655ae068d35088b4073345fe0b03010f6ffb8deec0cbaec7f1284b6cca9c1a46dbb59133c32d58d79490488fce662a9e54d2e9256f394b167ff12b15fb82700000000af33ec874b37177f0ff404564837ad74930b21eca87727b27c2494cf76f580bb000020af33ec874b37177f0ff404564837ad74930b21eca87727b27c2494cf76f580bb20568ac2cbf4c913be67e97440d1666ae9f284a195eaaeb5d6cc088f02c6a40fd8015c6ed0d12929502d6632482c6dc079b38ed1096e000000000034182d1ffb4e1ffc000b9ba201fc000ba67d01fc000bd4aa00c637ae108ab48b62a5c6353f8fdae3578e63e6d3c637ae108ab48b62a5c6353f8fdae3578e63e6d31ec5c66e9789c655ae068d35088b4073345fe0b03018fd8f5cb1579c5a3358126df2a4c0670029ecf97ec95ab2e41e3786bfa9b2c7da308953cb1ea3aebf42910ffbd00f5a00000000af39e406e48c5fac9cd44da1a84541e74f968766bf403718854f8ad2c4f3a1fe000020af39e406e48c5fac9cd44da1a84541e74f968766bf403718854f8ad2c4f3a1fe2035095f3703e5379b03644ff25063c3fc1433144657864d06904b8c4c81235ab8001980cf5e5a4b2e6008ca1f834e297a1a550bb6e7000000000022d111c9fb4e1ffc000bb3b40001fc000bc79c00d3735099e625828d21cd2495e700d8e5fc696bc0d3735099e625828d21cd2495e700d8e5fc696bc01ec5c66e9789c655ae068d35088b4073345fe0b03090680ace6a8f09953a47344b83911d1a1b2c8628d4c712589a9814a04272b70842c9c7cacd1ff5cb19c97e88c67ebec500000000af879b5cbf2bfc94e1a2af602159930146caf7a91e7d9bb08272b82be03137ac000020af879b5cbf2bfc94e1a2af602159930146caf7a91e7d9bb08272b82be03137ac20ac3731e02bb87282b09b7d1ea9f7ca460193592160afa2e194fc2bbf5c9b87af01e31328e1bc246922c2954f8e93562c1e96b9b8ac0000000000ae22e974fb4e1ffc000cf13b0001fc000cf6cb0020c3d21ea834c65e7584f4d3a9270c70297f04d9ce7f101b7f075273c892063b1b8571311737a5767f95c0f808aff27883260bfaf9cfe2b84519a6b230932f6fc90c9dcaacdf9d836a2a7e60d090fe5e55b0b02f5a4f608a4b8235ba5aa7abc4e05f9387d1d942adc57c87f5b700000000b00179bd307619645399361abddcb07287ecd406301fdf405d9a82c8e333aa03000020b00179bd307619645399361abddcb07287ecd406301fdf405d9a82c8e333aa032060c6085ff3174d7f715fe6160822a1ec9a5182e6a6fa7603cdf6759db9726ad90116cb1e8f2ee25a6e24d3bdf0ec74b68635e822410000000000c38d8f31fb4e1ffc00010db90001fc0001854c00307e6b1e1ebb35dc358870ed74feb6563617e40d307e6b1e1ebb35dc358870ed74feb6563617e40dc7bb875d7fd38c672ce10427e7e172735c827f0330878386a8d07cf79e1dc6963d4cdcd7a4af6ef7e350cad3e1373e45fb86fdd9390a77366ccffda6ebe1470c45b0f7591000000000b00c8c773b22a9aa8364340a901a7538459ee38c7a68926e3996be85f6cc0d25000020b00c8c773b22a9aa8364340a901a7538459ee38c7a68926e3996be85f6cc0d252022c561566ca492327efaee43f294f42c95f87499c302dbdeeaf0bfe29ee2d0b00179fef4f73db8737c12eb3b5cbd44882d442c80170000000000ae22e96efb4e1ffc000cf03e01fc000cf12b01fc000cf6cb00d47c40c18e5a783a9277314480c9c0512a8fe825ce7f101b7f075273c892063b1b8571311737a5767f95c0f808aff27883260bfaf9cfe2b84519a6b230926eed90600b93cd05453899e96db8dfa36d2c71c3209e1660738c6b3af11473b5169c8f8dfacd89ad1bc92a481978f700000000b037d52073d1e445bc2fd41e35be1c52426e00152e49ffa55b6fc20f33b28483000020b037d52073d1e445bc2fd41e35be1c52426e00152e49ffa55b6fc20f33b28483208384b2330fc26f5ba5ff492e15006e42521cbe351ed42fbc45e4d17320d537b0014e6de0e472aa530261d5fbd3801d6d777aa7338e00000000010000000000000000000000000000000000fc0001e7020001fc0001e7100052254c6cd12c657c27876bc3c0a7b82aef45305fbf9ef9d3fee586e471698a3f70eaff9dcc96ba84a58bd603afbd1d6198ee831cefe1380b073a24d53009a5e37e3b9e556a7d7fe7cda1b54682351d4d1f6ecd331d98816db0696a5389c4a09bfc57f66f0a27120302ceadb07800000000b0447996025ff084c1fa1e0fc755b32d540143fed28b89791789fde2464f9f2e000020b0447996025ff084c1fa1e0fc755b32d540143fed28b89791789fde2464f9f2e20502fdd2e5de1a8c6ba9b4bfcbd14bb30743353814ee50e33f80c2e063a4ec6ef0045cf243bace96dcc31b4311405a12153630969330000000000235868cffb4e1ffc000bb3b40001fc000bc78300692790b0e670372748d3029fce2bdeb14816c27e692790b0e670372748d3029fce2bdeb14816c27e1ec5c66e9789c655ae068d35088b4073345fe0b03019f2c10770cebad591eefa4fa1e71d2baa7213f7bfea0d7cf6fc9313df3a6095f480b7eedb63ce8aabe16dfb418a9f0000000000b09c47d39537078986e4639420ce87b32039b17d80ff4eb88238c27fcfa1abd3000020b09c47d39537078986e4639420ce87b32039b17d80ff4eb88238c27fcfa1abd32040b9e1633d6a6c0a38ef14d5590c5cba47ea35c13fcdb2b1b86d08f2297a9a0400d8a0974e7667d17dd9a12a9fcfb313a13c918ce7000000000023a97188fb4e1ffc0002198f0001fc0002fd2400c7ddc0f64cab219e4119020d7a9c0ffea17b9ed0dc7ad6d9a56d9e5370352a41c4b9b55601009064253cae727106faa4bf76b0b4f8375091889f6715301848a0024f4a1b85e18552105a7d397714bb9d16a392a29b5d6d18bba91fc880a6b20be09f1400dfe58de3ea87f919ba00000000b0aee43d5964ae06a7ce63c03332d9f1af46386b91738cbbfdf42f67db488c5f000020b0aee43d5964ae06a7ce63c03332d9f1af46386b91738cbbfdf42f67db488c5f2046674ef4c6ad3a94ca837fdda85dcacd4e685f2722cd1b33c26505a95faad46e00976899eaa0087e8b7daf0d688fdaaf2197da58c4000000000022e99becfb4e1ffc000384320001fc000608030014cc95cebcd011e38ee7a83fb6ea445ff8ed0550177f797c6205c1997ff1ffaaf6aac98c13d865ddf32bb66d6fdcd07b1268d21a3e021c9c954452933090ea99287802a44836309be934ed63933b423580626adeb428026acde6bdb283f370ff19bb37f81b0e4775187ad006a300000000b0f7021cd2662eb74b1802ba34fef476d176e815569aadd4931bd4288f5256a8000020b0f7021cd2662eb74b1802ba34fef476d176e815569aadd4931bd4288f5256a8201b6c893a523e3fc81e071e645926300e1a37d71f02e1bbc3aaf75ee1961bb56700a445f904cfb88572a605f98fe2826aacf9bcf268000000000022d91746fb4e1ffc0006567a01fc0006c05c01fc000bdc0b001a238d7bcdd356d52831c991b56beb9a50a986541a238d7bcdd356d52831c991b56beb9a50a986541ec5c66e9789c655ae068d35088b4073345fe0b0309247cd1a65f03a854cf5c9d7ef6c606d5a8789ddcfa7e2f04ec03d6c93b365a01d2f302f1c93aff66f33d55fddc721ed00000000b149c50e97a1411b76b2e26ca20b9a6a317d0afe19df2b78b967f0b94aef1f38000020b149c50e97a1411b76b2e26ca20b9a6a317d0afe19df2b78b967f0b94aef1f3820595c1fb1f5d3ec30b832c9c3cd68e19b4dc85334d0dbf734671e3c38844c8513011fdcb249be6d1f0896ffd3c5965cac5f087864d0412000000034235351fb4e1ffc0001991e01fc0001fa4501fc00038bec002adba90fd804d6d89438ea6729608d5276687fbc2adba90fd804d6d89438ea6729608d5276687fbc44fdc27a48f627d31adb54f482d59e535c226de0308f60f80538f335ba0f9f5452f02d7f5527652671da80c3d1c10e31e040f9b901a53b476a9ce02b507958bc8a65acd7b0018b3277a4f4a3667225def8a4f83000c086719cd9000000b1b3f7b8e4ae179563fc3cf3bf51148644cf9e38256a06d73d31050ebaf486e4000020b1b3f7b8e4ae179563fc3cf3bf51148644cf9e38256a06d73d31050ebaf486e420945e0ef94323e11ae3c6348c22d0106e35d724c00bc81c70956bd98d42a46074009b3193d314bfd2e375084a1d45eb689ccad9c2dc00000000006ca0877ffb4e1ffc0006fcd40001fc00070ca3002986dbc41a156ebc9c49fdf1d1842a76f21044b7c61ae923d66d3e7a9a82b85fe5eb375e966b109103650c94f0e6f7a84dac1089fd0f6dac2aa7b4ea300d7a075032c423dfd82adaba63256db7c7a0ab10eecc99544fd628e76840759ce5fc0f27ad83197f464371a1b353095200000000b1d373e438cf455c8297ff3d8fd1b27a1be7365dc55bdc963d0c02930338a519000020b1d373e438cf455c8297ff3d8fd1b27a1be7365dc55bdc963d0c02930338a519206a67f98d40507765c2142f4d70d3133a428859b1d4eb7f7c702d82781350b7b8016cfeef7175b7dd90412dc38d3cbb55a5da930fd9000000000034281b0efb4e1ffc000bb3b40001fc000bd23300ae5ae49de2bf939a61037d1ab3c9aac1528a8034ae5ae49de2bf939a61037d1ab3c9aac1528a80341ec5c66e9789c655ae068d35088b4073345fe0b030874adb6d0e5b65105e507f97944c24c90c5120d804ee0f36c7079c7c7c2f86aec079d13392b583e0553b699dcfab799400000000b27a788d5106178e1e365336ba2a53d6f0e4a48b76eab2faf3aac12123473740000020b27a788d5106178e1e365336ba2a53d6f0e4a48b76eab2faf3aac1212347374020a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e3b6b2d6b24f4fb4800563a0c581278ba501dd5b46b0000000000235b8659fb4e1ffc000ccadd0000002d0ac80af443e477060c785066014d561253d22d2d0ac80af443e477060c785066014d561253d22d64f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d73000eb80b32b60db5d7b03559f6e9205beac8d047689904bdda0bc50987d5f208d39b78ed90a34af7e1e9d44495ca1eb4200000000b2f62d6812c31f4f46265267da924e38395274e12148d979e4b4759035b26072000020b2f62d6812c31f4f46265267da924e38395274e12148d979e4b4759035b2607220a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e06083c6d6b80dea08171cdbe3134fa90e5dc9711c1000000000022de5512fb4e1ffc000ccadd0001fc0010df0300a3efa844b6dc22d05e802ebd5d1eb02cca122c25a3efa844b6dc22d05e802ebd5d1eb02cca122c2564f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d730075b907b6d6c12aa111da0e102186b9d06f4e065969b60732207f18c2c5d0deb8ecba47cb4c0929647db0e2fae6f08ca00000000b3004b53adce8cdf983830857449bb18787178023971a621d988d360b703e529000020b3004b53adce8cdf983830857449bb18787178023971a621d988d360b703e529204dea6406996a98efea88a66bddbe7f9568093185b08c865b1b664ae0e594c7be010eac161c360c57015ce83107d781b9ed935d3edf000000000008090a0bfb4e1ffc000cf63501fc000cf87a01fc000cf893008a69e5fe65c9a67e214d84a116b441abd5f9aad38a69e5fe65c9a67e214d84a116b441abd5f9aad3c69a0bda7daaae481be8def95e5f347a1d00a4b4308fed7a63ded7f5de0bfee9808589940f1148f47656d017a1fa77642352b5348ee318af4ac3fd63fff3b4e5c55ac1624b00000000b3b5748571b60fe9ad112715d6a51725d6e5a52a9c3af5fd36a1724cf50d862f000120b3b5748571b60fe9ad112715d6a51725d6e5a52a9c3af5fd36a1724cf50d862f20593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c1689fa69f20934cc3ede9dff4589af59c19a14a3f70000000000342b0d5cfb4e1ffc000cf99e000000d57dc73bca0753cbd47bb33f68362ac13e6daeadd57dc73bca0753cbd47bb33f68362ac13e6daeadc69a0bda7daaae481be8def95e5f347a1d00a4b430816ab3f50007333bcb40445130cd0e82139f8c68b592001cd686efc15e303206491fada6cf90af8f24a28b81a9b59ccf000141b308f737ca9e39f67b553158903198a88c516e01fb8f3001fb05a3b42fd6e07095c8b1c88ac52a22cd97d8ebb051ba7adf401896d8aebf04db1080000020b42fd6e07095c8b1c88ac52a22cd97d8ebb051ba7adf401896d8aebf04db108020a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e71fd01a6dcb1e645d921f8e714b2181c90b94e1a24000000000022dc861efb4e1ffc000ccadd000000b4fb462bdbb65e1dc1380a1d4723220a09f3b4ddb4fb462bdbb65e1dc1380a1d4723220a09f3b4dd64f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d730088905cc3f99e76b3a1abf714a55978d9930c2abdc77a21bd809e452e8c47c35d38e318ec3118e1944cf1a4a8df907c100000000b43dadbd485e4d1e1d202ea5180f0ad4e8e7f05e97a7e566a764ed714356bd1f000020b43dadbd485e4d1e1d202ea5180f0ad4e8e7f05e97a7e566a764ed714356bd1f205c71e5f46d35196e33b45c5d59d3fd2dc84381942064cae21744fb717412c1ac010f673549b55f956f58bd209f0cda6e0af0d65b2d00000000002f6fb5cffb4e21fc0003c5f80001fc0003c6840099e9dff4cd5a0abc61b5287a0ba48c0553d6358829dcf16f7a66b832d3b84dbab400a1e9eb7f30ac955410003527bf2b360a7a390b9ff14b9106c6323090c0e9ec9dc5f08b1d4d0211920fe5d96a225c555a4ba7dd7f6cb14e271c925f2fc72316a01282973f9ad9cf1e39e03800000000b4ba4ab73c3757ba9cc6b6fb98020b854228be7de4704ceb7da02e7c6a2ad741000020b4ba4ab73c3757ba9cc6b6fb98020b854228be7de4704ceb7da02e7c6a2ad74120bdfda6f0bbcffdd7aa32a0b762eb6506cd719d88cf5f272d1ced2485a6bcc9ca0149ffc6acbf7ea405fb117bfaea252f885c6b6ba300000000010000000000000000000000000000000000fc0001b1ab01fc0001b1b001fc00021efc0064cf453213924a7f394eb5ff3be693174b8d0d983db6e109e8d2e2f052216a47568b8881f7df245bd8acf473f417dbb62954adab796af04a646847b13000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b4ef45b7d0b716ffa761809326697a6420365e1d137b52d7d275e7f326280ac1000020b4ef45b7d0b716ffa761809326697a6420365e1d137b52d7d275e7f326280ac1201eda6d2f8839ac6331393c4c9e2c97ab17fbd99ee5bf9f02b3ab288d60aeed4101c829eedbb02f90bd3a33dcbd225256ac75e2298c412000000050d1e860fb4e1ffc0007d1da00000064cb3ef38948917a58eca6dcaf03c4d94a3219011546085b56803db4366c2059d4755c8a28796ca30d5bcbeeb459af40f97fcb4a98e9d1ed13e904c8300450dbbbe82df6808151b83a46f8c531cb240eccfe65f8f0b49f3717056da7268c14e45f0dd14fff8daed28fd353c1b401c623e2d926af5eb52dcc2b931993d3e527145118000000b4f9de65ae676b63f84f2865317b8b512a12516c4459f2f59ca2626c71f7dda3000020b4f9de65ae676b63f84f2865317b8b512a12516c4459f2f59ca2626c71f7dda320a3ddf7716c62a29cf5f259446c51122a518b7b3165284ff8636b67ae65def9b401f9a85a965fd3f6ea024aa1af9af585b3993c2882000000000001010101fb4e1ffbed7c0001fbedb2002e57d3d0f052b955f247a5c1d4a41266cf5bd93c6960122148b84c5f044a812c35d5380281a0f02e88a052d5925781c116dff6be4f04739113c0f9a430016a16472319f62f71bb60e38038aa8cb93a301ff6c3727f75f4d770428d71d032fdbd27c5d03dc56ef1d658fefe795400000000b55a74503e30b3f3066ef0d94ddce16cc7f87831a4b782764b588e5575382a88000020b55a74503e30b3f3066ef0d94ddce16cc7f87831a4b782764b588e5575382a88200b18bab21b495a6bd4d872e3fa0f87e5ec27effa90d3c58cca27843d9d96da4f010f4af69185db513ed69f7538a80cdf50cbf6ce2f0000000000235902aefb4e1ffc000bb3b40001fc000bce4300b6bc771fdb7d72115152872d2809ff854a16c4cab6bc771fdb7d72115152872d2809ff854a16c4ca1ec5c66e9789c655ae068d35088b4073345fe0b0309489f888b6bb2b9aea1dc7580c45a7e38d3d3f197ab688c48962ef102588017558d6bc1ad8bec667892b2436e64ba50f00000000b5706630cf1c631b5f95edf39d0fa1fcdaba9d34459b0b392e3f28eb59ae90f6000020b5706630cf1c631b5f95edf39d0fa1fcdaba9d34459b0b392e3f28eb59ae90f620f690ae59eb283f2e390b9b45349dbadafca10f9df3ed955f1b631ccf306670b5016c87be22108a3287243c4bfd060433101cff516f00000000009de6137ffb4e1ffb602001fb626c01fc0001195600d157ab8fe5436f4c7a475be8a35079b3aca6c5fbd157ab8fe5436f4c7a475be8a35079b3aca6c5fb6d4c795644ca86f717628ea27f0af13b0ea70eb730874b17058e37c39f770188dfe8e699959654d723e62e28b2760900e5284f63f6b70e077a6ea9803714bdf62d083b1d9e00000000b5c0d248eac5f19d665159412f357073359d0d643930adee1d071f02e9ad0a1f000020b5c0d248eac5f19d665159412f357073359d0d643930adee1d071f02e9ad0a1f201f0aade9021f071deead3039640d9d357370352f415951669df1c5ea48d2c0b501ab386459f5642306e5993f9f7584fb744de7076300000000010000000000000000000000000000000000fc00025b7301fc00025b7d01fc00026ef0008923f5540c3cde8ff5f57178422303c469510c488923f5540c3cde8ff5f57178422303c469510c484deccc4867afa6d1f8e500e66da4f136e46638b83000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b5d5c145d244a98b81cc9b5fa2f841cb6689e7cab76566fdc66ba16a82db95a5000020b5d5c145d244a98b81cc9b5fa2f841cb6689e7cab76566fdc66ba16a82db95a520dd55abceed2198b21aa5486f47bd0715607d41c79b75aa3e3ce3091b57b46f020159b77252b432ccfd639e3d1286a82a8700f91a4b0000000000336b0426fb4e1ffc000386690001fc00052bfb002e1496064dd3a7a8c0a5cda78f3b4a4073ffa2392e1496064dd3a7a8c0a5cda78f3b4a4073ffa239a6a050bffabcdf986e775567e1ba53dddf578ca1308f4fed7576bd1e31d45225788c1c96836dbc85b3ece3b77fbe4ede0f5f784f138ef6b32884e3345915a758364d1e582300000000b698b5e762f0d11faa437d55b16ca54722ba8ddb0b3eef0256ff80354f0c8d83000020b698b5e762f0d11faa437d55b16ca54722ba8ddb0b3eef0256ff80354f0c8d8320cb53246d5a57694cf7e19868540214769b2d7fad12f824c47130244873204e8c00a80186b44321096c4c5997ee6358e220bfb3d6ce000000000012c3324efb4e1ffc000d62c20001fc000d62fb0023142164ea1319cf4ad34e8fbd273c5502d5dc352e3252f64967541fc0092b78aac3dfbb7fdfa8d2a90c41d69e6e6132b5433b45a661b5f2187458a130a90febb8c2b031ae7ca222debc10f12fa0a71fcef84e2d92f13c1ad192c42e371324bbb66c86e24434754e2864ba14ce00000000b7c7c32bc7f34cb18da6b4b3fa53d8a6125d6f6dec3f7849e728bc8f89eae495000020b7c7c32bc7f34cb18da6b4b3fa53d8a6125d6f6dec3f7849e728bc8f89eae49520e7365918822860b9120091cdf14e16507de20bb5dcdb6784b16352c2b66ba700008f6273f09406792bb9b717499634ecd4446db449000000000036cb0d93fb4e1ffc000bb3b40001fc000bce5b00563f03e344dc17a7849e6320f56c13b0b5c32cb7563f03e344dc17a7849e6320f56c13b0b5c32cb71ec5c66e9789c655ae068d35088b4073345fe0b030011bc68f6561d4a7d5f7c1e6fe4742d8ce2bfec24576e40c8eaec56b3759bdb5be5e6b9234c77475c74be1b0466ad9e400000000b7f0ada8d395f428a1a72db04b76caa042f7020b2f90641fcd1499be6c37fc9e000020b7f0ada8d395f428a1a72db04b76caa042f7020b2f90641fcd1499be6c37fc9e20a3b41298f1b62474eaf528e96815202beebb6eb5751f0b495a7ea49ec6aa04df0029ab2ca57c2c3d3a756db61eefa71cd784a7533f000000000022d536e7fb4e1ffc000bb3b40001fc000bc7e300538584030db46ef33cafa5765401d48e0b9fe6b9538584030db46ef33cafa5765401d48e0b9fe6b91ec5c66e9789c655ae068d35088b4073345fe0b0301802f2a1951734dff2eaf714cb8de115a8df7bbae8da6a1e1bfc9c0f020908cf68cfb2f5efaa4412fea5116db12b569100000000b9e4c7189d01f8da6eb8bb5f4b8f8c2a0a24293d0f6e900aa0371bc32ec6021d000020b9e4c7189d01f8da6eb8bb5f4b8f8c2a0a24293d0f6e900aa0371bc32ec6021d205ab2eb7a853640b8282676a50464bd24596d3094fbe40afa6d2159a6ea64488500db4c10c95bbf83225e49ec3967653007708d8d8b00000000008b3b5692fb4e1ffc0001167b01fc00011b9701fc00011c1b00fc8511ca8de4f660ed57620e4537737e55622bd9fc8511ca8de4f660ed57620e4537737e55622bd9db4c10c95bbf83225e49ec3967653007708d8d8b3098bae0f71cbb77fff1560f45680ada9492ec4c9f779df777754b54bfb3474729c269399bd3cdfc736866364d3fb011d100000000b9eeb35f00d10ebde45a23db94875bed007b94eb03cd0317ff721e24dd5363c8000020b9eeb35f00d10ebde45a23db94875bed007b94eb03cd0317ff721e24dd5363c820f9ada33272169ea08ff6161000b9fee6eb81785cc491b284a2acbb87738a330f0139387c3d869b645b7700d9e16011681c0971cbf63c23d70a009de62866fb4e1cfc000283a70001fc0002ad4400caf26da61833c492453bc2d74c6dce3d91e2c38fda5ea047322750daebfc463a87ec042108d63ce9d458f5157d91f4832e66eb8630ab3dbff95551d8308f420a082c56b30c9bd8492394d83066a8d03628a7c8e3eac27486377e2648bdb3cebcc4fdd16cb4cab1341e480fa43900000000b9fab136129b05d86ccfeee5298f207ab2d76131af41987baccf55fea5efb4c1000020b9fab136129b05d86ccfeee5298f207ab2d76131af41987baccf55fea5efb4c120a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e2542293a57d22c1f9064bb876ef27b3f4a9e5824f5000000000023a21274fb4e1ffc000ccadd000000289d0729f182f703f2df4990b51e2b103515a32b289d0729f182f703f2df4990b51e2b103515a32b64f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d7300fa5377eb256323aace31b45c3e48ea110404b053cb80e8043bd1e44de1705130548e4ab28738816251ea57a7fc1032400000000ba8ce1dc72857b4168e33272571df7fbaf84c316dfe48217addcf6595e254216000120ba8ce1dc72857b4168e33272571df7fbaf84c316dfe48217addcf6595e25421620593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c1488164ceb25e5c05e3192511d2be4a5ac103cc5f70000000000342aca80fb4e1ffc000cf99e000000ca94dd35b74cb251457e475dd7507055eaf1b4e1ca94dd35b74cb251457e475dd7507055eaf1b4e1c69a0bda7daaae481be8def95e5f347a1d00a4b430acec7bbead86221590f132810b8262cf98c91b338927907b86bf48baa54dd1912bfc1f6fccd069052cc8c79eb9e8ed2c000162e0104ce0aafc1f06bde37c73702fe84b307f0501fb8f3001fb05a3bac184b9f1e4eb098d1f8df0b07af6af8919c60c1f60e31ba29c2f39f395ff22000020bac184b9f1e4eb098d1f8df0b07af6af8919c60c1f60e31ba29c2f39f395ff22207186875d6669311c046bc6052538390054e2cebd21b2eaa908af5a273602fe1a00d97799fa72f75b2cab264f40eae80856f27f6f10000000000003dd1d17fb4e1ffc00021c2901fc00021c3c01fc0002712c003da6a63a5f595ab15da44601749453c0ac0b8b7d5519b11029baf89428cad6fd4e70e3bb09f356f1d97799fa72f75b2cab264f40eae80856f27f6f10308bf25d66d63197e3144f6fa17ad92ae38cc11b143027fb91dcf5c20fde6e52bde7f46f2789e6fa84573197d8085389dd00000000bad4dcdc0ec1f274f70f87a3f4509096e7ba517adef56a4121a20f665d5e8e7c000020bad4dcdc0ec1f274f70f87a3f4509096e7ba517adef56a4121a20f665d5e8e7c2076a391457a0942b72645223669feb8e22db6e8ec7d9056eb5149f5689cc3e0c40054a71d0e91f24c449a09b22c0f77e6540261a5500000000000235ae333fb4e1ffc000bb3b40001fc000bc7b300a14dca43f5ef41a8a4340a62787f0901e54e8adfa14dca43f5ef41a8a4340a62787f0901e54e8adf1ec5c66e9789c655ae068d35088b4073345fe0b030848001b4004d5e5eb6782bcf3a3b62c2d14f237af0be67c10d70d84be1a28142bd5edcf4d90de08af31f8381510ff61600000000bb889ccdc43531f927eee1dbf095a5367ea314eb44818be2277476617af7d35a000020bb889ccdc43531f927eee1dbf095a5367ea314eb44818be2277476617af7d35a205ad3f77a61767427e28b8144eb14a37e36a595f0dbe1ee27f93135c4cd9c88bb0176e71a262cca9f6667bd35b19f182ba67b44c9cb000000000059280381fb4e1ffc001094df00000059ba7af9e92023a6b1160a0a45aad2dec70e7cd703815c232820445f311d1192f578077c1cdd3b540d5bcbeeb459af40f97fcb4a98e9d1ed13e904c830b529e500f236ee90a3e7c274dd51ad91310561f10d066560b0f28922634fbf67f50660e317f3f4c06441fa5ca98775d900000000bba99873df74a78b6fd5150907b216eafe16816006225a4912affea3ffb41e00000020bba99873df74a78b6fd5150907b216eafe16816006225a4912affea3ffb41e00207b744d5c91d46c013969caef13e72e56c6ae7bc89588edee53cf4ceb6973a2f50120120c7dfc6f165a4f2c104d6febd11c496069c000000000006b16c782fb4e1ffc000607dc0001fc00062e430047c6566a13ba6a7f8c6a3cb8872664c2f8f4ee27dd3b064ca33829ca65c37e911259da50d3490ef3b508db53f0a3f072b00f579a86e813d6af2856f3301059c4fdcdc32d831534403f7e6587555d74dc1624f6e2bcdba10a099e6c4f8d5f31d4c270231180ded264a009387e6c00000000bbfd0ac1977011267a7032641ef5487fe15a4de798faa485b156fb3b7eb0acb8000120bbfd0ac1977011267a7032641ef5487fe15a4de798faa485b156fb3b7eb0acb820593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c060d8235767cb55972a30d653eb9dd10f51b3c46ec0000000000235231c4fb4e1ffc000cf99e000000f9b93e179a0c22afd92523427341b5e0b2c2a102f9b93e179a0c22afd92523427341b5e0b2c2a102c69a0bda7daaae481be8def95e5f347a1d00a4b43095c89af86eeacfe403684306c98173c2a59198047a778787887d34ad6b0c9b787d689a7c3cd9e9dd5d103cba70f3855f0001dbbebbc52a5bae21b818e0487311041c91b2683b01fb8f3001fb05a3bc77a5a2cec455c79fb92fb683dbd87a2a92b663c9a46d0c50d11889b4aeb121000020bc77a5a2cec455c79fb92fb683dbd87a2a92b663c9a46d0c50d11889b4aeb12120a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e5fd2b74b9987e80fcdd3aebe95721c6c4709724ee6000000000036d55ed8fb4e1ffc000ccadd0000002878a638db0682d49249ff8ca872f16653a84f912878a638db0682d49249ff8ca872f16653a84f9164f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d730174de56654f2bb6417e15ff06361ea0becc00bd72a3eba0f83b60feac860570769fbf28482a706f10906a1e96dae4a8f00000000bc9479593e38ab280b75dc76bb4d10483b1b341c2e792d7dd278c21d202d2b93000020bc9479593e38ab280b75dc76bb4d10483b1b341c2e792d7dd278c21d202d2b9320e9d3abf500bd0cba0f374490d4e0b3adf1dcd865da1ab04e8bef255e4a24ff630041796bb0563ff119ced9d76be68c0d5898bad86e000000000036da55d2fb4e1ffc000bb3b40001fc000bc7b300422b11d7511cab020721d07fa2d011bb1b7ae433422b11d7511cab020721d07fa2d011bb1b7ae4331ec5c66e9789c655ae068d35088b4073345fe0b0308f6e3e0e34f5afcbf9eb7077a3f0e5ddbc2902f5610447b9bbf871fd0065c8f156b514bc5180d579bad722d6112f1a3800000000bdd08cc998cc494d2e008405bd71d5917a64adde6216339d74be4d379c90ff19000020bdd08cc998cc494d2e008405bd71d5917a64adde6216339d74be4d379c90ff1920d5b7bf68c3d573cb8c592b4fca527b753ada034710ae8b5eeec83c426ab00dec01673a5871f70c41403b9fcbdcb7a7e2b734f3cf130000000000951ccbbefb4e1ffc0006592e01fc00065b0801fc00065e350047d2c552db05fdbee9a78f346a8bfbdfbbeaa5a068eb72f005d366e18db38f638716d97bf60d53c7673a5871f70c41403b9fcbdcb7a7e2b734f3cf133003d325fdc665db2900c24c0736b927b7fa7ba7068c9595991e6cfaaa0f8e1269a31f6d1da2b85fd922186a9979872cff00000000be563f5793f34f16e6653efd9060c4042b492cbf676cdc66f9d68836f078b71f000020be563f5793f34f16e6653efd9060c4042b492cbf676cdc66f9d68836f078b71f206a0871d1bd82667b5df31b0c09861a71061f9fb1f0df3c2a8ad0aa11710100410109c927a4a7a41ffdd8cfe3f780f5108a6ffa1c514248000000c3c925fffb4e1ffc00062ecd0001fc00062f6300c5775227677d9c67fb4c13795a2bf9d80ea231c9304c46d5f01a600ba66e3dbbd8bf6dc23e8c5297aabc8c5bbac24daa81a5f2425983dde53230cc203093612d652fabcdc0052e5bde98d276e49ea71d050a323b98c368a06742fd964d21f567e16fbda2c17b00adc470f6f61400000000be89ade2107051d4f50cbf1d99338d42b33fa7efb079e14d906ed9b518768d36000020be89ade2107051d4f50cbf1d99338d42b33fa7efb079e14d906ed9b518768d3620f2cacab8a192994c64ca14bf7a9d1c045a8234e615dcc6764219af3b0705adc000e6996e06f219509dce93957d76e2fde11a5958380000000000341bc6f6fb4e1ffc0006568001fc000a68af01fc000bd4aa004d0684329ab95dd4ee2c0d275ef313bc0e0adaa24d0684329ab95dd4ee2c0d275ef313bc0e0adaa21ec5c66e9789c655ae068d35088b4073345fe0b03016c6904fbceb7584e75ef553b85ca20ec8cbcb1ac49d985b0cb77760107753205415c4d5cffe3be0a10219d0dea98e2200000000be8d0533c692cf23e3d3eeb3957422b5a98acd82aadbf7baef255edb2f491b82000020be8d0533c692cf23e3d3eeb3957422b5a98acd82aadbf7baef255edb2f491b8220821b492fdb5e25efbaf7dbaa82cd8aa9b5227495b3eed3e323cf92c633058dbe01c428ff31ec6308043a7b282eed63d1d8920c2d8300000000010000000000000000000000000000000000fc000293b401fc000293b801fc0002b6e70091b4363730ea1c02de53aaade78508ee41c38f9c91b4363730ea1c02de53aaade78508ee41c38f9cc4097f46f9eb0990bc7e22d3bb29af6eb76d94d03000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c08b723b79a7139fa7097bb85b4d0dc387097cf2ea66ad34992b60e1fdb5df1e000020c08b723b79a7139fa7097bb85b4d0dc387097cf2ea66ad34992b60e1fdb5df1e20c0785da69e10c38185460b8c938566484f113a1bd42feed2e03b8a76567f6b820024ecdc76f0781a35a9a47762313f63c5e21ac0fc000000000022dd41a3fb4e1ffc000bb3b40001fc000bc78300a7afe89589507a716dfcd88009d108734edddeb7a7afe89589507a716dfcd88009d108734edddeb71ec5c66e9789c655ae068d35088b4073345fe0b030169fd77b3f11dd8f82c03ed8b79c1d986fa1445e6f726b0c1b556bb884c83890339733b2521630b8ae57c1428d0ba12c00000000c0aae8ab24aab988cc84385d16af7ffcfd365d0e016f5799759e0525a435a617000020c0aae8ab24aab988cc84385d16af7ffcfd365d0e016f5799759e0525a435a61720a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e355f1d75bff42c098ef3598a9a5fdf2aefd216ef66000000000036be3d46fb4e1ffc000ccadd000000ec74aec7dcccccfaec4c5fe65166a2d5ce0e3268ec74aec7dcccccfaec4c5fe65166a2d5ce0e326864f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d730892a3de6fe305d39d81ecc9dbc7c85bc6eb57434618903f45ac8996aecfa9a7945e2cc48c40c1540172096229780519e00000000c0dc1876eca746f08e401c7873260e277baf0096a0b19e519e6298b649dd23bb000020c0dc1876eca746f08e401c7873260e277baf0096a0b19e519e6298b649dd23bb2025ab3aaf757e9002b95d75ddc9f2ff18ae237e53a8e10a93dc47fc163bc91d120128c20f725ddcc44c5d6c728b05b886805ca125af0000000000b280576ffb4e1ffbc9de0001fc0001196300febd730bedac1010a2943dff1c796cc544609f7cfebd730bedac1010a2943dff1c796cc544609f7c477a52436b944f3e9223ac8404a7717d4176fa533003f959fdcb3eefebe409ee7044748f71ec8cba18a7a73df9d55d118e170d7ec2540d5c08a4cadc4bdeff3f7886265ac100000000c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba8000120c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba820593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c040cb28bcdc1d1a970b6255a04138f84c0ebfa52b6000000000036d5cc55fb4e1ffc000cf99e000000ec040cc1866da3e55c8ae6c0f739cafabe3f5cbaec040cc1866da3e55c8ae6c0f739cafabe3f5cbac69a0bda7daaae481be8def95e5f347a1d00a4b430aa910b9552857a7712d54b468dfcbb7d9e27f26a49e06fb1f0fb00dd0f5a1bf926863c25ad03fd49c56b62065ecd06e70001fdae7cdf38811659ce9481975b326a5d07236bc501fb8f3001fb05a3c1df04cbbc1c77ae3157c4d6b50eac093068c1acccccd1f6206fc6bb892e8bc8000020c1df04cbbc1c77ae3157c4d6b50eac093068c1acccccd1f6206fc6bb892e8bc82015bbe1f1af1bc27cff5a355b82d0c0aaaa5bb19a634fae26671416b39c92630f007a36078fcf52a03235ec5b11dcf012eb7beb356f000000000022da4cb3fb4e1ffc0006568001fc000b9be201fc000bd4aa000eaa20f14a3447fe10315f6891d24da0e44ac1940eaa20f14a3447fe10315f6891d24da0e44ac1941ec5c66e9789c655ae068d35088b4073345fe0b030181387e11f86685b42d5030cf61959e3005d1c328556c83637e4a0acaeb62046847d6260c968ab433c9c6c946d170ef800000000c226d6e2c423eee0bf233ec020c8012b6ccfc1bd5430a02c55613eede35e9107000020c226d6e2c423eee0bf233ec020c8012b6ccfc1bd5430a02c55613eede35e910720bfcb8e882baba43c6975d87daca9b5223c9f8e6ca0ac9e2965c06ead3d89a08200c3063b19c638a44112f5f75c1d066261a497223c000000000022dc8349fb4e1ffc000bb3b40001fc000bce5b0001b9d16bb8176bc52aa900abd93b3613e5e91ca901b9d16bb8176bc52aa900abd93b3613e5e91ca91ec5c66e9789c655ae068d35088b4073345fe0b03017ccfcb2e59e9efd15cd4096192fd937119581523caacb1320afe058b2784b0668e4831bf6e8e79954cd2118d1b0e45700000000c2a54c1ad133acbf3366aba2534ed6c1f01728553a7e877ac2a22c98be085c68000020c2a54c1ad133acbf3366aba2534ed6c1f01728553a7e877ac2a22c98be085c6820bf623c10780b9dcf9e60e181c82b093884f950faeef2c50c9b268342b182b6d301b528aa08346d887417ad542b2dcaba998abb900600000000009de66e56fb4e1ffc00011b610001fc00011d6b0007b48a04d0a73deac14da9df36ca49ffb142339107b48a04d0a73deac14da9df36ca49ffb14233916d4c795644ca86f717628ea27f0af13b0ea70eb73085f01c97f8e6d601ed269d4fd1d33b456c5c940aecc45b084c0f8d9ddac26d6fb7c5cc1eb817a41bca401e5c9c4ff85600000000c321458ad5e9517e64583facbe4ee3d0694ab856377fe216ab2f4bca85cc2f76000020c321458ad5e9517e64583facbe4ee3d0694ab856377fe216ab2f4bca85cc2f7620762fcc85ca4b2fab16e27f3756b84a69d0e34ebeac3f58647e51e9d58a4521c3003e9257ce8103b6a3836bd1e6eb938ea1c04efb480000000000ae22e972fb4e1ffc000cf03e01fc000cf13701fc000cf6cb0044e7c4cde18464d480d28b52fd7d23ffa72d128bce7f101b7f075273c892063b1b8571311737a5767f95c0f808aff27883260bfaf9cfe2b84519a6b23017a49cea05ca2e18f74af110c5ab52c89a43ced4e056a8af7ca8973401494bdaba26d1c56b46b018091d0dd64f24475000000000c36584a1242574644c1a1620703c55200cc0158de276dc388ffa9815ec328c31000020c36584a1242574644c1a1620703c55200cc0158de276dc388ffa9815ec328c3120c6db6a114efbdf794abc8a68954f6005393aa508ff4ba392eb913aca117c8509016dcc6dfbd52edfa0d3cb1b5d503c5c7b00f05d83412000000023a3e220fb4e1ffc000197ca0001fc00019a0300f4c0fe75eec22907d6b043edb0df74ccc7b85a45f4c0fe75eec22907d6b043edb0df74ccc7b85a456dcc6dfbd52edfa0d3cb1b5d503c5c7b00f05d833008b4c1a8b9c1402ea84afe7c47f7e98d657df873b9747a0e4a497120ec62c81f314ad91a6f3384648e7e60f2734554f700000000c367704082306916bf8d0dd2dfabf778c701ca6006a55b56de4e55a0ed9e2f02000020c367704082306916bf8d0dd2dfabf778c701ca6006a55b56de4e55a0ed9e2f0220a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e4b9b98f6b2dadc95391afc16b570bf7e3c706d796c000000000036f54b2ffb4e1ffc000ccadd000000df89a7a4e97a87e090c06cc44cdf6f596632e62cdf89a7a4e97a87e090c06cc44cdf6f596632e62c64f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d73016ca29d03ef4897a22fe467bb58c52448c63bb29534502305e8ff142ac03907fae0851ff2528e4878ef51bfa3d5a1f2200000000c3f559e803f09bb261a5f94a5c020816a4ca04627d1969819c32026d46004816000020c3f559e803f09bb261a5f94a5c020816a4ca04627d1969819c32026d46004816200525bd19daef243898853c4ba419ecdd8e493fa1db91277e6e4de61697438d2900c9a47526781022a84b503301b47c4c277d0d7d700000000000340c2f56fb4e1ffc0006567a01fc0006c05c01fc000bdc2300072732cc8d834a9c3cce0d05deffb324874388ee072732cc8d834a9c3cce0d05deffb324874388ee1ec5c66e9789c655ae068d35088b4073345fe0b0309757e077c72c5dfc02197ea345b361d66f861a16a3d506b5a99493929b7b42d2af420fa73b5c3728b8995d19b5952c0400000000c43b8e35d23d9cb0a088b5153414a204f436683298ad311c9cf2643cb9e482db000020c43b8e35d23d9cb0a088b5153414a204f436683298ad311c9cf2643cb9e482db209795d0f8c2ebc027150b12624db495b54580e283674c062f680b136e6477683801e8588af19dc9a7724451f1ff8a506b30cd18ff8000000000008d47264ffb4e1ffc0009235801fc0009a50701fc000a95e300c42520f12ca094d0c840ec18eaaf497adda92995c42520f12ca094d0c840ec18eaaf497adda9299521fb41623befdb80651c8eb65b8dfa90f1f507993081ace6ff9442d477f7eb80ebdaa666804cd0c1d6cb131838847f75cd83540eace2c501484adf0333b847ddaa6c087a8600000000c4b4329ea9e95851296c2c59d395399e36e2f0a6436d3a03cec8de73f35dd121000020c4b4329ea9e95851296c2c59d395399e36e2f0a6436d3a03cec8de73f35dd12120a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e2d4ec0d7b93616ff664078c9308e0bec4c8284cfec0000000000235c8f07fb4e1ffc000ccadd0001fc0010b8340020b99d09dfcc0f9b69fa97738487f20cc6c5786820b99d09dfcc0f9b69fa97738487f20cc6c5786864f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d7300196970badc74d068ec1226ffd4a656313decef59d792237a32e6ff56cd4e43030c436025831a4a3d0306a616f03381000000000c54b7009fd21294b6bd144e1d8b12492cdb0d2fe3b78007aa29142a84bd2e5d7000020c54b7009fd21294b6bd144e1d8b12492cdb0d2fe3b78007aa29142a84bd2e5d7204dea6406996a98efea88a66bddbe7f9568093185b08c865b1b664ae0e594c7be0238c1a1bec916b5169f94d1600c9062c9e44b62d6000000000036b95180fb4e1ffc000cf6350001fc000d08cb001e8e94abc60514536d80abdcbd1f252523eeb1941e8e94abc60514536d80abdcbd1f252523eeb194c69a0bda7daaae481be8def95e5f347a1d00a4b4300946837d177bd2b042cf1fe665aee99844afcd270601fdc4860231b9cc97909ccc214adbd2406ab38045d4465e3d1d5e00000000c582fbac1ab54ae7b5c89bd0bd92fdcb5e604bde4805e8ca5a61629cba7ef8d6000020c582fbac1ab54ae7b5c89bd0bd92fdcb5e604bde4805e8ca5a61629cba7ef8d6206ab54c4c60a06c2b59c05ce53c8a7939a128e0b8840d37132f13c3b84d203d11010625d7198a11ff1b8b2fdc69bc709657c2a1f7f80000000000035aa743fb4e1ffc0007b74b0001fc0008ac9b00bd63760f50bda0f3d8db2aeff88bc9eaa88596c3ffc45339be50b5953200438ba8c71ebabe9575e9ef0605d9bc9d3b3e7207258797498daded9527f63096153a0fb857c1da0f6bb1ce2e569bebfa14e6e1f532139f9dcb720d481db17999cbcd8eb66a5ab4c0fd20c5f9695fb100000000c6b291a26712b3f789a6f9379d55029d78f895fe3372c701dd5ef0a597be3b69000020c6b291a26712b3f789a6f9379d55029d78f895fe3372c701dd5ef0a597be3b692061f246afa7628f4c86905fc4f9063dba843830d5e5b9f069a6fd7981bb2c34bb01334f24c69a36c9adf8c9c644f9650da7a6655c3800000000002e65f354fb4e1ffc00053c1d01fc0005ad3a01fc0005b1f30033d78a9b138826acab6c464a74f84b9fa5cb23db5d068e0fe2b3fd8bf7983a2d806e797c522b75a9334f24c69a36c9adf8c9c644f9650da7a6655c383083152e6489f210094f5dd558373a1ce9abf36bb8001d4f35b3dea74f7ae74baf859abd22238c682ac94cab82eeb58aab00000000c6eee81fd38e6db24cb5e847794cefca7f3f8f95a066028bb8dfd6f36fb92921000020c6eee81fd38e6db24cb5e847794cefca7f3f8f95a066028bb8dfd6f36fb929212026101299b476b793ac0d19aee60267b583d670c5dae71755decbaab175c8afdd00c9f0eac27fa56e424e669e9205194fc9b173fdbb000000000068f8f27efb4e1ffb5ffe01fbc39901fc000119630038130b3e02c119f53aba29a12de6be40f0c6596f38130b3e02c119f53aba29a12de6be40f0c6596f6d4c795644ca86f717628ea27f0af13b0ea70eb730050f3a743867bf78d2e9a3906d15d8400d8d58255771d12828922386e8685f8aeccb8d9d81153f9c2d7da0436a71fe5500000000c7290309328d48982f4a265566615083ad72ae2e7cca5fdde599371762cd105a000020c7290309328d48982f4a265566615083ad72ae2e7cca5fdde599371762cd105a20c48677c8c69a59d52c2136a85090d3184e46f0c149bb319ffc2bc23d41e39009011a5f40c458858c685001ce69f201d3790b48a88e000000000036f4e7e6fb4e1ffc000bb3b40001fc000bd21b00a0d72e1d1296d2303c68aa6e148064a03e30dea4a0d72e1d1296d2303c68aa6e148064a03e30dea41ec5c66e9789c655ae068d35088b4073345fe0b0300422f6f4b6fb939bad0c5eced0d0085a9cdffe158b7fa0f5a4d83a2e311f080d92346f11764a2a8212196157d83a640b00000000c81c26dda720ccca323cca9a675257c9ea50c4aaf40cb1a4c2e931435f160fb8000020c81c26dda720ccca323cca9a675257c9ea50c4aaf40cb1a4c2e931435f160fb82066f6464e611b519b7abe070b67794d606b844fdfc365560468eca287bb381763014f6a74e089ab620cd7289a8a46a6564092782bb6412000000036bead17fb4e1ffc0004ee4b0001fc00052a3400e614deca3fce7919013e4e440fd3d4721ad3465de614deca3fce7919013e4e440fd3d4721ad3465da91a0b2b6a951742b8766f9a9554c313f29e86d83010d9901c0aa8f9b3e789a1413e731ff07b9b58d4f53925f53a1502f00e6ccf056dc86ffa5595a1ca5c02cbdfb38b1cb800000000c87218fb9d031f4926c22430c69b4edf1f0fb80c331c1a79e3b1b3873407c0ac000020c87218fb9d031f4926c22430c69b4edf1f0fb80c331c1a79e3b1b3873407c0ac20a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e3e709e0d0819c27bba7eb754839e873e9aae580b74000000000036b94585fb4e1ffc000ccadd0000005c0c201c793d6cb7265b6897058b0b1e75fdf5285c0c201c793d6cb7265b6897058b0b1e75fdf52864f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d730842c53c3aa11ae4b985a52ae6a3170bdb58f88ec04c62013f9322bd5fda4417939836b6f41741dd864c348103a1155d300000000c940d40d2849fe70baeffa8e343024d01dc80380f38b2a015798f503cba26d3f000020c940d40d2849fe70baeffa8e343024d01dc80380f38b2a015798f503cba26d3f20ab742c3f5293d67a1834b2506f41b1a36d58b09d713389e35d48beba6c145f620112521c58f53340f2c9569bf9e7d9c04f1b625a390000000000cf9afaaffb4e1ffbcc580001fbe61a008fe94ff326b3d3f9986fe97fb2eefa9a365629198fe94ff326b3d3f9986fe97fb2eefa9a36562919a86ff169d2789750a0bb4a5adecf343dbd10987230069dd3113d6320397e9674ba3595f46dacd562e013e9e80a2e7d1095525f35134d4a8c19f4cd4a19d3886edf6032875500000000c95f78ad5dab4ceaa98ff2d9d60d6d69e741f554b3ff876998dd832b2255a5c1000020c95f78ad5dab4ceaa98ff2d9d60d6d69e741f554b3ff876998dd832b2255a5c120c013351de51a56f7b39f2c10f3840e3fe943a174af4860f8e8665bb78247951501fdb9e309b9b441317475ef6c6bc6c1ea892d6a8c00000000002d2056e7fb4e1ffc0001a3c60001fc0001c433000e06d6f85fbf739967d628e48d87300c4bfa93e565b4b2bd9e302d32234a9bb205db6e51c08767ed1086f7c42d054d120f9ec84739e2211a19866e3d30128e20333b8b51fb8c72c2d5acafa049758b53279bf78f10a1f32995bd05d4f6313b2bd67fbc48379455d89ef869fa6e00000000ca0d0910002aedb97fb303e97b1db11583be62b3db8b6147ffa84b98309fce71000020ca0d0910002aedb97fb303e97b1db11583be62b3db8b6147ffa84b98309fce7120a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e4893f68af96d322ebc11029150d446a551042bcedb000000000036d45b94fb4e1ffc000ccadd000000b7e99fc3ee4cf3d64c4438fc2a61cba12c0e7319b7e99fc3ee4cf3d64c4438fc2a61cba12c0e731964f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d73092823797ad456d53ce1e6bde84e8a19164ff88a73ccd242ec48d9c6a479f2a049e214c7e8ec2243b7ea74ca6144ab2c500000000cc02c1be8ef00540856c769f77bca1afc593d3c40cdaf5ca033e462f1c43fc52000020cc02c1be8ef00540856c769f77bca1afc593d3c40cdaf5ca033e462f1c43fc5220a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e1423146e911e2951e98aadb67f0c40c8a21ed6bf79000000000023a1de4afb4e1ffc000ccadd0001fc0010d993001d92da27f8fd00226f85d9e1c2ae33f2d57b84361d92da27f8fd00226f85d9e1c2ae33f2d57b843664f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d73013146b3252f408f1cffc875b12b61f56c1ae02113b24c0b5aaedcda4a9b509332c8c4587450074f3e0906aaf3ceca75400000000ccc3668156451b3e10ac5c97d60e2c20fadf88c6266e3b2a9afb0e33e658734e000020ccc3668156451b3e10ac5c97d60e2c20fadf88c6266e3b2a9afb0e33e658734e20f9cdc515389213075782c4f03fad8a5010b7aa4165b804fbb1caae54c1c0f15700034ce75a5b9ab22d285c7876ccf1ea1ec4bcfdd300000000009b8ae253fb4e1ffc0005336e01fc00053d0d01fc00053e2c00d144786581a774e12dacc4aa155eb7d6d73869dfd144786581a774e12dacc4aa155eb7d6d73869dfda952b3b45775c0af85fbe2e2ab21549d86beb0a30057b3b0190261b1ded22b9c58550f7bf17a150de6a755a5478988b58e32bb7a53e7e6f9981bdbf416324e75ddd9853b800000000cd2963744e83eb775912b47e751f825f7fc8319db11f7ad4aa8e0f8831d12e09000020cd2963744e83eb775912b47e751f825f7fc8319db11f7ad4aa8e0f8831d12e0920f8659149d6af2d9b210531475f23dc5de3bfa2c35b45b4e54dcc471ab1b7222f0149343c1994d094b8ca7e095671e7aa7ce5cc141300000000002d200ceafb4e1ffc0006f1390001fc0006f1a300f6cdfba67f9b6228a325c80d5723557d8a2006d8f6cdfba67f9b6228a325c80d5723557d8a2006d849343c1994d094b8ca7e095671e7aa7ce5cc14133004ed653b556ea9d8b8391dc59ce49796b15c118e37daa2eb42326f72571b195cf21e814f93338ac9488000dc3d8b4d5500000000cd3fbcf015bb8071f253c07a4c5511e4759db5f655e2d198e4e2042e3986e828000020cd3fbcf015bb8071f253c07a4c5511e4759db5f655e2d198e4e2042e3986e82820dbad65a4c4cdae2325f1cf0f399a16a978c433a81e38987b8d9a5992087607e7019e5d4165c421b666fa97b17b6202fb4a3c34ed4941f00000003ccdda05fb4e1ffc0007663c0001fc0009419300742612cedde82b7e8d1f49ecc96cbd3b3c65372c7fffc5375fa606d4066bfd9f4fd211b3c5d59a955cffda7bd45f324d8b3b96059c999ac2d95044903091da7eb4d0d0f78e4aa5379d45c779105a0d809a04497186d53743876e31874d663f965507339259ce2b99fd3ea4c275015cffda7bd45f324d8b3b96059c999ac2d9504490000000ce09b01abb1fdadc8c04db6f8e9141187b034ae536776134e01156196fd595ed000020ce09b01abb1fdadc8c04db6f8e9141187b034ae536776134e01156196fd595ed20a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e64e01963565d4e45dd2c88567cbf3f1ba813737203000000000022d9bfa4fb4e1ffc000ccadd0001fc0011087300c826f62669213156ccf082dc70087b8e68ff4c58c826f62669213156ccf082dc70087b8e68ff4c5864f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d730068631f31e13e1c29c739619b2cb58adf73724dd8c6227ab1b8f45c08c5d6934338365ed45c795e4117ddf79f1e5037000000000cf774e2a4bcab3c7e7d2d934cd2977b090fc1e414d26dce53e16cf2cc5971ccd000020cf774e2a4bcab3c7e7d2d934cd2977b090fc1e414d26dce53e16cf2cc5971ccd20e91b3aa22e4f2d8326a68f0400a8ab92d2ec4b4af9beb3abebba5ed8127b8cc0005b156c7020f5322d482e14d95a666d0b36d9b8c100000000009f416929fb4e1ffbc4230001fc0001949300beb0ac49dd993a3841c7f91fc63faf17e32ef6edd1c380a3095e1088aae13a699aa83f4dd1bc0fd9b2334b22379811352d9988876a6e586d975e732930002decf89a99afc7bfddbac08c6c25a028e58f0c7863b7fa6811ff84afcefb933b510b78df6551f844eb2221b0c0bb5300000000cfa6f7b58c78f827c15e8f1b6a5a2a3a92140101719006d8226a363e2c0c8e5c000020cfa6f7b58c78f827c15e8f1b6a5a2a3a92140101719006d8226a363e2c0c8e5c201f44f17b876717517c7d133c9128abf51bb6733c87b0ec7ef06ccb96478e8aec01559cd372f02cbd4b52375512d9d55e153a3a873300000000008a442d76fb4e1ffbc39e0001fc000194dc00fd42c918654ccfaef1b1c70efb20d3f4f6b50b65eb294d05b014930dccd16d4878159584189e77c0b2334b22379811352d9988876a6e586d975e7329308ff05fb385c08528b762683c2ab6864ab1ac031146d9be0df597961625c9538e0bb03ae6a759d66e1717e879ebaad41c00000000cfcddb737317b86698faef84734e9e655fcc2899ee449d13ff70b014419b6c4d000020cfcddb737317b86698faef84734e9e655fcc2899ee449d13ff70b014419b6c4d206716b03191d4b9c5e813998018f03105ad3a5a0a7de1a62efc94339fa84afe9601bf58e573242232de98f1bee4b787f64252361cc000000000003415087cfb4e1ffc00021c240001fc0002fdcc00cba37b8b60880605abd3ca81294ca6b6e725a4038b7f823b0acb2fce829b7434a720075572ce6dd69a1a33fb82e27f0405303a4a4183199a5f2fcab830009a876325699d6979757ac10d6b37eb7f6690a40447f6473779eb9130975998d3a9fd6e9ada19559730bc017843ce1200000000d00a073a9de7c2efe78c712aaea77fa1a6c0ed00b55ed2289cf763763eb32a43000020d00a073a9de7c2efe78c712aaea77fa1a6c0ed00b55ed2289cf763763eb32a4320a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e2e5167565f0e750fbe3b6b7baf519c5dca2be263e6000000000036d63baefb4e1ffc000ccadd000000bae896aae3de540d18e5ea8573182860471082f9bae896aae3de540d18e5ea8573182860471082f964f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d73013dac269908111b8b091edbda123d5884f4d47d21225fa319d344b350762a85c6cdbe21804ef9b2cc53a878c72a001d600000000d0b3fda32eacb51f9bf25e533344e144245d629cb1decc05eef2781a658f4ede000020d0b3fda32eacb51f9bf25e533344e144245d629cb1decc05eef2781a658f4ede205d054509583f78aefb625c44e87477878cad43c597a0f169ff8450a1abcc313e004490108b0958d28e47e691abeb21bddee8d08cef000000000022dcaf58fb4e1ffc000bb3b40001fc000bce2b008f4c05bb6a71e94abccfc1c722494ce77ed0a3418f4c05bb6a71e94abccfc1c722494ce77ed0a3411ec5c66e9789c655ae068d35088b4073345fe0b030031eb004643118075e2e22389b29d78e797ca7dc18edf201a2c324658b261803e8d162b172fb00822da1fe4283f8863a00000000d0c37ae5ff62e92d9f065b453c79bdd8b967a7e7e5e3753e94e0f2929065579a000020d0c37ae5ff62e92d9f065b453c79bdd8b967a7e7e5e3753e94e0f2929065579a203432a97c8b76efce888ae94aab39a57465f1e833f89364e8a4d13bf657c24cfa010dcb7083110afca0bb2af934af50512b0bda0d6600000000008c520f8ffb4e1ffc0006b0b601fc0006b32d01fc00071acb000b5424d01a3096f1a61dded02a329caaed8300d16150352212815041fa5dc70a94c7dfd507f4861975f49a2ef947f1f126a241add5de9e0965d20c483010ac5b643b6dfa29989103ad74641e5fa27626492f08b8337a8415b598ebf2bc6676c73621905a71a15d7bf9f92d6efd00000000d1ce9c61c04501fdade45632d83ba14b76b8cd89de369e7ba9594731e21a8c97000020d1ce9c61c04501fdade45632d83ba14b76b8cd89de369e7ba9594731e21a8c9720df179634db5c8c4cfedca1271ed90c3615ef15757d5c7d6fabbd9e18e8752f5201afe98cb66e8326b286b5eb9dd53b0f3043cbcc21000000000044b7c45dfb4e1ffbf08d0001fc0001195600227ac0c292b7d209dc75272563f6e3e40bcd4b66227ac0c292b7d209dc75272563f6e3e40bcd4b666d4c795644ca86f717628ea27f0af13b0ea70eb7300c49037992160cb8d7f6ad7e13d778fbbfb5d10230b456bb3aca1c044e79fb15c3b1fcef7efac59899eccbd190bdc40e00000000d2148afa283037e255d65a3acc82428d6a712215003963a60c6e015aaaa4bff0000020d2148afa283037e255d65a3acc82428d6a712215003963a60c6e015aaaa4bff0207a296529680d98fe988f25841cefd74be42dc27ca52ef6f46421c200f477525301c1e0f105b18897e33ed0d0636a1841c38e3ea826000000000003140e8ffb2712fc00035e2401fc0003cdd701fc0003ce6400bc0daad062fd3cff45c9494fc80bee6a0ad1ef904e818207ce6a7e9752c006ae4328b26c14af2a955e7e959febf6f6f5e42de569815cc416d06032ea308de1a5d67b291f75e87e20eb4b9fa7246dff5bcf4030ae26c321b1845609d50d04b240cc51862b4a7b3dc9be4aff050f00000000d23a37ad5fc04ff18955da1ea1cec8975fa03c525104f9553b3cacd36045b6ea000020d23a37ad5fc04ff18955da1ea1cec8975fa03c525104f9553b3cacd36045b6ea20347d39a27538a8a7819cb8d3aa5e7484b6ceb2ebb18de76970cbadc12837b98700eaf1ecf2a52c4b15b1f29ae0776532a4fab56025000000000036da7f80fb4e1ffc0006568001fc000ba7e201fc000bd4aa00af19744774b258e0ebf2a01006ee507c6a368f27af19744774b258e0ebf2a01006ee507c6a368f271ec5c66e9789c655ae068d35088b4073345fe0b0308b2ae1b6528eb36f1d87d61e763e5d5d26f6eacbfc6b91305eb30d4d4136e7edaf3bcf2fd07f8a91cdef268465f5085400000000d23e1b9f3cb6ed89beb1f11ac96f61c0011655c6cd02c600c6a671cf92c9f070000020d23e1b9f3cb6ed89beb1f11ac96f61c0011655c6cd02c600c6a671cf92c9f07020a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e5bc7da1882838f4aecbe1de16036780bc6dbb5d48c000000000023a7a5e0fb4e1ffc000ccadd0001fc0010a8eb008496f3b53ff1854c310cec50faaed0a3980374dc8496f3b53ff1854c310cec50faaed0a3980374dc64f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d7309291debc5e6c56a9e1a9b77cb980115c36a4d3d584826e62fc4b6ad7834cfc21e7c80226d46e90f4fda7771b4511152600000000d2467a06e67cfe57ce8723f565c296f97abb663380ce87bb8d5e72989e3301d1000020d2467a06e67cfe57ce8723f565c296f97abb663380ce87bb8d5e72989e3301d120da822286edec580e48efe91cf1129ece56530d16667549522d6bcc6d3e3b09910022de1a923e40b1fd9f13fb4f076b69d9ee94e0b3000000000068ee9c6dfb4e1ffbd50c0001fbd68a006bf6187199e0d3b146d1daeb844abed61dde51215d63ccb848f51351e6623f5841dd00e057e4633722de1a923e40b1fd9f13fb4f076b69d9ee94e0b330145a212f37b991a6c050cfaaad7e83f1347486984174e8f446e59fa6c225691ea679f70613d829f536bb1a311d812cb800000000d304e1e869e1a9aee1952f06bfd8dd43f8a4d12231c5d43641a31f89a53eca2c000020d304e1e869e1a9aee1952f06bfd8dd43f8a4d12231c5d43641a31f89a53eca2c2054be51b0a5708936a13e637645dc0c002a2d79282d4f5f2e89aefdfc4c49c8ac0141307e80a8d668b0bf3cc98a52f8d85ec8cf5ae20000000000904c4214fb4e1ffc0001b6a60001fc0003eb43006f39ee8ed58b56b0fdecdbf64cc71b75041ac7716f39ee8ed58b56b0fdecdbf64cc71b75041ac771c0a84112810ea249524c9060518b76dbee8b86cd3009591bf26ea6f179457440d73ebc70c44310ea56dad7539a93be903e28788cac013b646e3ed4198ca74a8325d8a721c200000000d3a0e645c1830de00ca370761d0db7a75a408b9322ca571fe26b7f8cc5a0ecc4000020d3a0e645c1830de00ca370761d0db7a75a408b9322ca571fe26b7f8cc5a0ecc420c4eca0c58c7f6be21f57ca22938b405aa7b70d1d7670a30ce00d83c145e6a0d300b0adcebc8b989c5d9248b195d5b3a3b1a57a855800000000010000000000000000000000000000000000fbaa690001fbaa69001e88661c273d73b44bbf942d3f1cfc145539969d1e88661c273d73b44bbf942d3f1cfc145539969d05b1290b6787444d5ddfdf30f732ee620dadda063005b7d7aee629c25efc5604104a3a9af1e23663464e0505a057e68cf12317834160597fcf80287a94e98f171a8c79a2a900000000d625ce5bfbadaeae3ea778ba16d871e6b61ec07faea80403dd51a9d28df8deea000020d625ce5bfbadaeae3ea778ba16d871e6b61ec07faea80403dd51a9d28df8deea20862bff54719c5747b08e2b5b646efc0e1ae8527b72e6526554e8b1db8655c5b400c315ac9f0d1a78172378ccf1dbe786b01ee7764b000000000055d1f301fb4e1ffc0010173e0001fc0010176b00b80018523ca775bdcf9f5b35b31aec7974cf3b15b80018523ca775bdcf9f5b35b31aec7974cf3b1517c1532d16104848a1cc23893816c93d5559beac3089b278c3322e9e5193d133bd49d958d05383835371944dca113bae75a3c741a61202a7d3f99447f7521708b308028b1200000000d73cc0f5964b94a5c72bf9457ea1681a4dc61940f75e991492b669697a392ffe000020d73cc0f5964b94a5c72bf9457ea1681a4dc61940f75e991492b669697a392ffe20024f7b3d5ef9e0a82cb75799a1589f8bf5d988e1bc342ac533a5aa94f32fb38401a8b2af0c1699023cd662f648d477e7b52bcdffd3000000000036f40a18fb4e1ffc000bb3b40001fc000bd21b00e433c14f7b979d60aa65bdd41a61793a80cb4af9e433c14f7b979d60aa65bdd41a61793a80cb4af91ec5c66e9789c655ae068d35088b4073345fe0b03008591f0c86bab284e3e43d622ebf60c6f2e508d574fce16bec8cf35a04f69fe667a65072dc7e0ebdc78c0a2f82d5d4a000000000d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f89000120d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f8920593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c0d47eb59e9a49b3794acf272f1bfff17f228291daf00000000002cf06266fb4e1ffc000cf99e0000007334f54da07d3b9e177f6e57c64f97bb0f982caf7334f54da07d3b9e177f6e57c64f97bb0f982cafc69a0bda7daaae481be8def95e5f347a1d00a4b43086108e551691da2642f37b68bcfbc5bbe9984ca51aca15ee24b6fa9b8690ed62c6ed722d091e04ef617cfc99341fd35800017034f0d3853c5351fb8e0ffd3c1daf12c51c2d8901fb8f3001fb05a3da0a60d91a09d34a39ba34e4175d2efca738ebb409e3fbb0546d41a24e83a722000020da0a60d91a09d34a39ba34e4175d2efca738ebb409e3fbb0546d41a24e83a72220a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e57bfc4a68510d0df6c7f9b006df5845a8468b5f390000000000036443095fb4e1ffc000ccadd0001fc0010efea009c14a51ad09e0eedf4d49b11a779aebe5755a4e89c14a51ad09e0eedf4d49b11a779aebe5755a4e864f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d7301099dcddc6560d1039b0edb91bd700e5deae0cba43163fa289a80c2bd22335b5b0e7a1fb8f5494c0e6360e73a12fe0a800000000da21ca075f0b1b6c29df0391165030d85a8d5e7474c6358d9edbd3dd270de78e000020da21ca075f0b1b6c29df0391165030d85a8d5e7474c6358d9edbd3dd270de78e20d77e2ba2a4cd96a0cffe43117209beaa0bcca463d583c02ecd118a3e04e5ddfb007caf7956015e9404896b6492227b8517c679a02d000000000036b807b8fb4e1ffc0006567a01fc0006c05c01fc000bdc0b00f5a25e1acba9dae504fb92b2b7f4f8c776b450b8f5a25e1acba9dae504fb92b2b7f4f8c776b450b81ec5c66e9789c655ae068d35088b4073345fe0b0309760a3bdbe28cbc5c64b7426b7b59aa84f6ad6c4fdbe040a9158c359e39feeae4b4168d6231d636eb4024f072b4d465500000000db3158d303d9634fc0a4772452707e4f6154aabedcce40d60e7932137ca52efa000020db3158d303d9634fc0a4772452707e4f6154aabedcce40d60e7932137ca52efa208e8e515f7025352e7c608479e413beacf0d95cbb964b47e4a98fd27b6b6b628a19379812a735584751c27ae8d47205e7048ad8afb7000000000034d41347fb65b0fc0005e6990001fc0006584400f312f66e9433c75b461b481f0576d3acd398c223f312f66e9433c75b461b481f0576d3acd398c223379812a735584751c27ae8d47205e7048ad8afb730989f584df6e5a359bc469a4975baccda2bc6a3fc3e89721c639f5567db7abef79f31ddeb4832b95418d49322419d3eb000000000dbe6cc582f7b5c0eeeab18c03d651274a36a26e5222e9e6ab5dbeef9590c3d40000020dbe6cc582f7b5c0eeeab18c03d651274a36a26e5222e9e6ab5dbeef9590c3d4020a94e29c854f2cf4113be2e8b61faa8bc4749778dffa3edefc112d01de9a677a701bbac279c1e96b87d49a7da69df88948d81d5043c000000000023a39c47fb4e1ffc000b9ba201fc000ba67d01fc000bd4aa0099b35d5698744965f753a627926c0d59b1821c5199b35d5698744965f753a627926c0d59b1821c511ec5c66e9789c655ae068d35088b4073345fe0b030811536feb53c015c2aa7e518611a2f6609fe3362d64b225dd26ec2becf55100402e561aff014fa31ee0ab41e53d437ff00000000dc1a51970c343e17706bf77aa4309149613f7a69650f274b6a9fa1c6dd1c4f87000020dc1a51970c343e17706bf77aa4309149613f7a69650f274b6a9fa1c6dd1c4f87205b016215386c035a42042a93736befccdb87c30cb90adc3b1279da58ac57cc1407eeccb10d4e73ed1650cd3fcb2dd3cf4c2f7347420000000000235adf83fb4e1ffc000cf8b101fc000cf98d01fc000cf9fb00f49a8758b606e7ecf90fda27c30efdd71ab8be9ef49a8758b606e7ecf90fda27c30efdd71ab8be9ec69a0bda7daaae481be8def95e5f347a1d00a4b430846e41a6e970b78fdcf39e3348689944de461e961a0c5dae123c3b7c4d985bbfb0eae2da56b6600dcf82f196df258ee600000000dc2e02ac95ce4ccc9843c38de7bdaf32f2a1d5966c054127a3f4ca4f4bbd5991000020dc2e02ac95ce4ccc9843c38de7bdaf32f2a1d5966c054127a3f4ca4f4bbd599120a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e2239379b568d6e941d8e551204c4a13b38a8313155000000000023576903fb4e1ffc000ccadd00000032eb51df8032392d44594907e5032d23df570b2d32eb51df8032392d44594907e5032d23df570b2d64f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d7300db85a27cd589d225beff9977aa0ac32551d15bd906a899bc1ef33458d7c979118f92bf1de4ddb55144acc2f7cf6d85400000000dcbcf8311e414aaafac3650f3f61326dce386eee3d1a53da86e4c9925af48d9d000020dcbcf8311e414aaafac3650f3f61326dce386eee3d1a53da86e4c9925af48d9d209d8df45a92c9e486da531a3dee6e38ce6d32613f0f65c3faaa4a411e31f8bcdc01c939bc570a54556243cc0386615fd4f77fc3a3950000000000b23e440afb4e1ffb66900001fc0001193400d930d39369c43d62ef0fa29c85a349673712f597d930d39369c43d62ef0fa29c85a349673712f597c939bc570a54556243cc0386615fd4f77fc3a3953089277d2620e48dcf8456cc8815aa18ad3587bbf40cf0d1718696bd126e19791bb600b22f1063d4e5e8efe85fab8f90c800000000ddb33a8e1dc94f0d2c78faf99f2209c5a6304924675ee639b237e00051e5adbd000020ddb33a8e1dc94f0d2c78faf99f2209c5a6304924675ee639b237e00051e5adbd20a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e020173018c4450e8125fd37bc507fb4feeeec09d49000000000022de527ffb4e1ffc000ccadd00000017a7876ff09a4592bf27959546c02232a48d49f117a7876ff09a4592bf27959546c02232a48d49f164f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d730882aed1df01917097a5502ff541a800d268967ab39c8f841ed62c5387eb46459d6f6959166cafec148dcae03830e83a500000000deaaf275e9e384f3e7b190cb4e779d200a8c22dd968e6eaee0bf0a2900ac93b7000020deaaf275e9e384f3e7b190cb4e779d200a8c22dd968e6eaee0bf0a2900ac93b720a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e080dbf942f2afe5fc96072af6ae4599720d1e88c3f000000000022db21e7fb4e1ffc000ccadd00000076c44d67639aaa8fb877f1db08d5e582b570c25d76c44d67639aaa8fb877f1db08d5e582b570c25d64f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d73017f78abcee6d2ed68bf2c82afbf56ef9af67313e2eb655ea5178850907cb3057cae0bb5a1d09f161057bf62f9d4890c600000000df770657631b27b71aa97f295c8c345df6f73617f2cc48f5d414955094a4d2ab000020df770657631b27b71aa97f295c8c345df6f73617f2cc48f5d414955094a4d2ab20eb25924c31ced9ab50bb1efa43f51e7f9e3a883b0668b1aca170731b2c73876f0116464c645e265c1dc215d0da895a91cf33c53f720000000000a123e12efb4e1ffc0006b45c0001fc0006b4cb0069c4cac4ececac7282dac6b8a9198772ce3f72995603402752878f5c76e9f40a3091b748a731beea16464c645e265c1dc215d0da895a91cf33c53f7230865e0561715f28e996d2c63e1ed462c82d403ad9300369529cc8932f02a8ecd6bf5c5b316130997f2c1ad1df700ea2fb00000000dfab7fd7e6f141d1ad7ff9fcaf8dafaf85b05dafc9058b376a33c6f4ee1da607000020dfab7fd7e6f141d1ad7ff9fcaf8dafaf85b05dafc9058b376a33c6f4ee1da6072032048e6d7e2751d4029bfddd77d06ea72c07fffb2d2a67b73ac1cc499fd10cf90210837fd9d5cba10bb91fc24c4faa5c7f591f4289000000000091efeb12fb4e1ffc000153490001fc0002427c004c90d0d2b49179ba1311496241623928b4e9bfc64c90d0d2b49179ba1311496241623928b4e9bfc62588a17ab3f917f19afeb8c32fa7c486ab4105a3300b4282cdfe1cd639e60b6c58b2f210bfe6b57f8f247cc5b55673d188ef458270c7314f7128b286a3326b9ab6109bd2ff00000000e0e5e51a1d6c471289fa4dde52bf5de747e1238a478a7fad107427a485921dea000020e0e5e51a1d6c471289fa4dde52bf5de747e1238a478a7fad107427a485921dea20c476e128117f5b8573cdedca3abdad1e49bc2d1ccbc8d536286a10c14c4bfbe9012aff26638de9d67c2ff76983669a27a5369f1146000000000002030405fb4e1ffc000834c30001fc000834e3003a8be94ab784cc8472ac6739fc763589673af28152b3089828ccd5c5e2929bb45057829bf2cd9900194748ff7e003ab02fd6964087130588b6c71c743019224c48bde28c061c99ca2a641ed1f695546fb6f1d103e93b4d8aa5164f5fdced8073ee239baa885cf377c8c173016500000000e0ef260e49c9f2139825cc98504c536397595e05813cc1de5dff2eb793aeb5ef000020e0ef260e49c9f2139825cc98504c536397595e05813cc1de5dff2eb793aeb5ef20aaa6c559704660301f5d58d95bba0be1df90ac849a60e537a7e1895e3a90d354016582f71a9a070fc634378449053280e8b5a64a0200000000008e5da342fb4e1ffb92e801fb93eb01fb96fa005d3a8bd28dc7d0ea750f976b89991482da5ef8bf5d3a8bd28dc7d0ea750f976b89991482da5ef8bf8e9c7503df018ff14c7f28047d833d1dda31efe5300dda9adbc22cdf89c04e8ee714da7d80dd5620c1d14e30780668d3b782b2f0acac9f00a556be1548733c1ad1abdd96ff00000000e1051e900f3f13c6cf79e1734ae1c65683c627982c5ddeb30f8afaa85116ab4e000020e1051e900f3f13c6cf79e1734ae1c65683c627982c5ddeb30f8afaa85116ab4e204dea6406996a98efea88a66bddbe7f9568093185b08c865b1b664ae0e594c7be06aec4b5523c900755019a250cd5922349690a448c00000000010000000000000000000000000000000000fc000cf6350001fc000cf889002a5b7ea1a484ccab3250dc7656ca99f7bc1cd21c2a5b7ea1a484ccab3250dc7656ca99f7bc1cd21cc69a0bda7daaae481be8def95e5f347a1d00a4b43000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e11bc5514ce9e362112fe4bc2356d68a63dd62b3834e320726709bb707564510000020e11bc5514ce9e362112fe4bc2356d68a63dd62b3834e320726709bb70756451020a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e499644ab02bf96193c58f4421e41886319036b09c60000000000235a35b4fb4e1ffc000ccadd00000002b43db3b33d56022be0be0abcd8a470f3624c8602b43db3b33d56022be0be0abcd8a470f3624c8664f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d73017596d7a72b65531fffd5f610752422d6e286c975f30d026092f7900f8015073bd6f6d1b85dd3981814c093910e7dac600000000e220b3b30879a4e489a99f265f00aeafaab0fbedd0ec3fa194befc03fe93ac30000020e220b3b30879a4e489a99f265f00aeafaab0fbedd0ec3fa194befc03fe93ac302049104fbd6215a0f0642bb38f73f479a8694ab35111093a57d07464b7224857e70060494598e236442ea115c2fd4772c8ef4881c0c00000000000951c7f08fb5207fc0004f3ab0001fc0004f3eb0027ac0bbb97d398cc78587b58ea40d92039f6a27527ac0bbb97d398cc78587b58ea40d92039f6a2754a0ba964dc2701ea622ef904633191f9444a5fce30127147f0cd5bc3ec7c8c5704924e855d46dac21de72e2de112f7dee7c9c3f9c40d4474c0d9ae36a56b800659af62c16d00000000e341b4207f799d7b216593303c5705c97825331805f32cf54188dd05a7e9940a000020e341b4207f799d7b216593303c5705c97825331805f32cf54188dd05a7e9940a20ed0a3741f44d013b11c389c282f6ba4b53abd15f4b8b7d2b08ac06ccb7a923f401844e2264660076d8db9477d915f43ee0c68d228c0000000000369d0891fb4e1ffc000384570001fc00044423000ee3064c60e85c3f9e8175b2a4d748a2fa3138949dbb34ad2ac21a13371e4212a67150bbc0320b2ff28f590dc3a245b02f545deca4b8d37217444def30029d0298b3ab58f541f566ba5ddd40e8e1e711dca26b1757fd1b707baea16ce77aaf8a836232809a5e1d301a36f2045800000000e44e528f46f8338398e514570b715cb77f2e001bed967bf0012f99a81be34d9b000020e44e528f46f8338398e514570b715cb77f2e001bed967bf0012f99a81be34d9b20cbfd47c5be15b98099bde2b2d79a1b71ab29e9f70fe74b9a41d3ad87bd1b33f900a51180fa46b6e0e6763d1ec58803d676fddd4a3f0000000000235590e7fb4e1ffc000bb3b40001fc000bcba300c830435c4611335accf4d70344a9512e4af1cf82c830435c4611335accf4d70344a9512e4af1cf821ec5c66e9789c655ae068d35088b4073345fe0b0300c07de8f27328b0e1dfd46c77a183f153ef4179971b08597e3206b97b7ebd80a6d0fd81ae6d69fd9f1c2425952e6636f00000000e461d74c2d6f83e032068bf1f8bc5e019f220187c74ce90625ffff2fb0622a48000020e461d74c2d6f83e032068bf1f8bc5e019f220187c74ce90625ffff2fb0622a48204d5e955db2aa6907ad086e36d6e596554d9fe90df258edb34c1db83dbe05bded00c82b198d97a2b96efc25645a104f3de3f25ae4dd000000000036c81bcefb4e1ffc000bb3b40001fc000bcbaa0095745dc68d45784cfcba71fd18c5b0b0e2ed4f7e95745dc68d45784cfcba71fd18c5b0b0e2ed4f7e1ec5c66e9789c655ae068d35088b4073345fe0b03092110df65b98e79912f6b80aed1eda6e66c55da2549472aa7a089a003efdd5244b39c208acf902198701f623fac145b300000000e52d2f726c9d7fe66a042564fcde9d4189180b7f9debb60ae3241872338b8e9f000020e52d2f726c9d7fe66a042564fcde9d4189180b7f9debb60ae3241872338b8e9f2091cd1bffaa50fef228069e113b7935af4b78c904a32ed0e7984b1086478373020199f5f489bbf74630e2aa67714aa7596510133be5000000000036cad177fb4e1ffc000bb3b40001fc000bd21b009017184ce5f2e988321891515465de3330af413c9017184ce5f2e988321891515465de3330af413c1ec5c66e9789c655ae068d35088b4073345fe0b03010487fb44636ebee88be5e76841d80b2710c25717d82d4ded913ca5c9c9a5d85f80268687b237632cac812518a2464cb00000000e558c21609f13196f38a0e135c8a56ee4632ea1681a9dedd5d65ae8031b34be1000020e558c21609f13196f38a0e135c8a56ee4632ea1681a9dedd5d65ae8031b34be1208e8e515f7025352e7c608479e413beacf0d95cbb964b47e4a98fd27b6b6b628a07082bf9bc77c34eaaf9c9cf4b1b8cd01f1768bab0000000000034d41347fb6596fc0005e6990001fc0006579c0018fdd71cb9d2d0a4cd75e08191dff37fbdf4465018fdd71cb9d2d0a4cd75e08191dff37fbdf44650082bf9bc77c34eaaf9c9cf4b1b8cd01f1768bab030005d1f334fabccd08847756effff3116eece973c077e3acd1aa936f4e51293fa8753de661dc7a03edde24714eb7acdcd00000000e58b99ba67999559acc105b139ad7c0f75e4b88b64ec8e9e3f91d19b18a02fa5000020e58b99ba67999559acc105b139ad7c0f75e4b88b64ec8e9e3f91d19b18a02fa520b4863351e597af3a020f3a1bdcfcca49c63059d3a2769c3bc5628f2c580d988d006156c9f4174e1544f07c378dc4c20b5fff8877ee000000000022ddabc6fb4e1ffc000bb3b40001fc000bc78300b42b27cc27998975c7ebebbbcc18c98c097b60aab42b27cc27998975c7ebebbbcc18c98c097b60aa1ec5c66e9789c655ae068d35088b4073345fe0b030067ff22ce46ff515d5869ef672ace862c7afe2e81a6820d39098419322ad2858a3305f03601a9a85f76333be38b65c4300000000e6595f88f935fef934a6d51dc0a1fd43e65de1adfacc2c99851a69d80cd26493000020e6595f88f935fef934a6d51dc0a1fd43e65de1adfacc2c99851a69d80cd26493208e8e515f7025352e7c608479e413beacf0d95cbb964b47e4a98fd27b6b6b628a3273c764874df7a0f6d7b1c77ae924dde0e3affe430000000000369ad3f2fb65d8fc0005e6990001fc0006575400ca9f4452a8988619c535d28f0b25aaf2c34b5d13ca9f4452a8988619c535d28f0b25aaf2c34b5d1373c764874df7a0f6d7b1c77ae924dde0e3affe43308f72e69ac2373a62f14b7b1d99fb24eafdc87b74247af42a591aef0989c9a3e152197736dbc266b2535c4b4b53d8ec4a00000000e780a06795b6c316aa84451acf07e0f11f9565e256a59057717fbcf0008ac254000020e780a06795b6c316aa84451acf07e0f11f9565e256a59057717fbcf0008ac25420e06631f4da3659b5efefa7eda26e82d9f30427da7c63c0943aa4e6a5a03079c900d1f5e6e6661ec2fbbd62e961da89d2d9fcf11099000000000022dc5846fb4e1ffc0006567a01fc0006c42101fc000bd4a3007d1c61a5a5d33cf6b75aad99d80d90e6f6585dfb7d1c61a5a5d33cf6b75aad99d80d90e6f6585dfb1ec5c66e9789c655ae068d35088b4073345fe0b03007f707431f05ae863a756854d6a8e6c5c37d071f5dc9e3debd2057c36106eaf8102b3313d1b369f3dfddefbc1394639400000000e9126eafb8f62f5a4e8b4d4f2419f4377a8dd14635fc749f9ca2636ffa93815e000020e9126eafb8f62f5a4e8b4d4f2419f4377a8dd14635fc749f9ca2636ffa93815e20cea979a463cdaf780c42b7a196049c04fb8466bf35b0618814e0759fb702c3cd01e0ce79910a4636b0e6a1d9695cee5aada92ee76e00000000003695cfc1fb4e1ffb699601fb868d01fc0001194c00b2ea896299dd86bc7c3353a40d354be43ca26372b2ea896299dd86bc7c3353a40d354be43ca263727eb0a0af302dd9ff95daf9e98d2f1f2c5d764f74308ad9500ef26ae510e0dd8cf0568b2a89d1234697873db2fcdd11674a73caba91cd416f9ac701f4f7807d8db102bc4a3900000000e995e4b4ba9fb3fc8cbc7c779b8b933367c54166175c3cf507aa92d0667ba7b3000020e995e4b4ba9fb3fc8cbc7c779b8b933367c54166175c3cf507aa92d0667ba7b320a5fa769a80bb95a3901423e38b27a4708f7ea2719b1e4bd01aa4a5b8ec9eadb300d33fa6c54b097be5bdc537d894e2d2f144f9847b0000000000ae22e96ffb4e1ffc000cf03e01fc000cf17501fc000cf6e30007f79cc14feaf70775dfd89cdaabc42f9d5a3416ce7f101b7f075273c892063b1b8571311737a5767f95c0f808aff27883260bfaf9cfe2b84519a6b2300620124f5dbe95b93bbcbab48452ba0cc47beaaf554e63db5deef90c10ca79c1e83c08a43d4316105419bccf6595802300000000eaaf0220c44e4e049b5899f162e7adf2da1e7946a2272489f304fe3df5247349000020eaaf0220c44e4e049b5899f162e7adf2da1e7946a2272489f304fe3df52473492050f57d34e7aceac2e5ac132c091ae69842d484ab382d59ac5459a9c8c3efdd4b01fac33d28f64870ce06e55c632d3ce829c9aa8e4e00000000009fcb2263fb4e1ffb641e0001fb64420016c792ef93229ad52721ad5b08249eac743fb74f16c792ef93229ad52721ad5b08249eac743fb74ffac33d28f64870ce06e55c632d3ce829c9aa8e4e300452f32ac367f352d6ef53f984667db9ad658bf940292eae2440024e5af9445f7a7a618d536c4743c9de4c3e07b6a5f900000000ead18f6dabac93c3fa0df238e992fabbecfd75b28dfbbcbcd0ac4bd4dc89a255000020ead18f6dabac93c3fa0df238e992fabbecfd75b28dfbbcbcd0ac4bd4dc89a25520ae5c3b488065fb736209d417e87458b953d6ac9b7bee596447ac119f68f3a287008ff714a271165a679a084036555ef7ea685a458a000000000022d743e0fb4e1ffc0006567a01fc00068cf701fc000bd99b00c9adf3d64cbd87212f093e52caace7296c89fe68c9adf3d64cbd87212f093e52caace7296c89fe681ec5c66e9789c655ae068d35088b4073345fe0b030023bdd31086c9f2de87f380a0c24fd3e7d699a2a43f87bc8d5a395c0eb3f8e19d82af15542302c129c981f352a3e890900000000ec6e4e052c3b28d77c13ccc5072b5f5c185e1a53a6ffaedbb1de9739c0d31489000020ec6e4e052c3b28d77c13ccc5072b5f5c185e1a53a6ffaedbb1de9739c0d31489206fe7864bc5e0241a306eb3adac70d56ba305b520ed44b6917981be5862ac7c76011172bfbafd8ddfbb947170ff69ebc2bc1a7c16680000000000c380664bfb4e1ffc0004bc490001fc0004be7b00cebc041331aa21d5fdce3e44b4a2a520889d4ba4cebc041331aa21d5fdce3e44b4a2a520889d4ba4382477245731a85b4a1b2ca6af9e904517d07e97301926b68942b544b4e17347c5e0d28ba91453984294c7679965f3a1d3cdcd9f5bf80f2c28a48b503f301bada54479896800000000ed1caa0e3a8c97dffb71fd26d6aa03a4d52347d8da71709220b0b4357e2a7236000020ed1caa0e3a8c97dffb71fd26d6aa03a4d52347d8da71709220b0b4357e2a7236207027e327b827fa7edc0fbd17b85900f2787d210c76a3ea06182088249d157679008e7e021f47d1e9425609af4dd695253fd8a9a0760000000000235a0070fb4e1ffc000bb3b40001fc000bce430039e05a296f11c657770a6161ea00a72b625d1de439e05a296f11c657770a6161ea00a72b625d1de41ec5c66e9789c655ae068d35088b4073345fe0b0300583a5fb61d625bb0640bbd1dbec505e8747dee734bd9dcda0c62fffeb13e24bc8cf3475e1535f8f8700fc48f177569100000000ed8575335b7e0b420b09b4b8c530711b98aa472504d91bbca9745873a106cb0c000020ed8575335b7e0b420b09b4b8c530711b98aa472504d91bbca9745873a106cb0c2092ebd7ca076b40f4012ca7e115e04bc2b1baab1be5289f8c975d580d64848769019aa6ac346d95f15724c602b262b8178333646dcd00000000008b3b51aafb4e1ffc0001aaae0001fc0001aae4009f9695e95af100e56314bd08680812a0f6256e119f9695e95af100e56314bd08680812a0f6256e119aa6ac346d95f15724c602b262b8178333646dcd308dd3b8d006c8ea260bc6158daf0680c5cc7cf4936458024b51ea2036a800ec6563d75135004055d94743b8341b70135800000000edc1fe5456b869747a4f41f92ab8bb8b10c1f43bbbd97957a16698783baa0d2a000020edc1fe5456b869747a4f41f92ab8bb8b10c1f43bbbd97957a16698783baa0d2a20a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e335e9d6b2065deb3d586152f44f0578cb0d51a5e74000000000022dc9b03fb4e1ffc000ccadd0000000e42f45a86824089891f17af573e84512f00d8850e42f45a86824089891f17af573e84512f00d88564f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d73006e81b2ac08c3ba6308868ced5075f366013ee8598961bc84150d8dfe9085fdceafc082fd18d3a7bb1338b74584048fc00000000edfb29497dd86e1bcbe72cce1cca1adbc1d9a991d3384c0a1a83d35808cbf5a4000020edfb29497dd86e1bcbe72cce1cca1adbc1d9a991d3384c0a1a83d35808cbf5a4206deb6528ee95044163f5e417053b8b43f32ebf26fad8d9e47e1222d611f7cd1c00ff84a8ead83fb486d9321ea63b356b287c2c569600000000000b7a212dfb4e1ffc000607a70001fc000608330035d72ae28122e666401fbc5f914da502815aedd335d72ae28122e666401fbc5f914da502815aedd3ff84a8ead83fb486d9321ea63b356b287c2c5696308d052595c653122cccb964230a5404399634e7cc6b3fa9314b54678c28d2f9c4854baa7be02845937bb0de35e43cfbd400000000ee12a4658170bf28f8ae6eacbc48fbe62d009582bafe6714f630484b14474944000020ee12a4658170bf28f8ae6eacbc48fbe62d009582bafe6714f630484b14474944206d945b3976197533a8283ecf24a1f1b86c51eaaaa28b4556e6fac59a0d21875f0108bd9dfcf61ed79b051ac428f69328463aab0001000000000034ce62c4fb4e1ffc000a4a8e0001fc000a4a9b0025a3f54d7d674aa11d94a1a7d4f40d618f8aff3a9a870b5d4ccfe0068e92a6cb4cd35915ef94df9c3a840c9fab8a7618147fb2f3060fd847cf86f08f30121a1cade221b1eadcc0c7a02a03508551dfb97b959ae1511d4cae47b503b39ba0fb37b984e4010164378513edfaf07200000000ee733db5519c987496eb3b871d5fa543ddb19db3e848f2fbb0af01585fc76af5000120ee733db5519c987496eb3b871d5fa543ddb19db3e848f2fbb0af01585fc76af520f56ac75f5801afb0fbf248e8b39db1dd43a55f1d873beb9674989c51b53d73ee0191be18196047ed60fca300e6fdca0b7bea81beac00000000000238d45dfb4e1ffc000de7c001fc000de9f801fc000f13a3000bf9547a7b4d12def0019da71e989821a60d9c915b44dc4b3f0ed26a8243afa46bada49c18da6b2a21eca01872dbfce4bf20886a004f6caaa69c1ff730b695a4757d60c472f67a7807def81ab7a52dec3bc64aa1c4188d02a4768ac3a862b404f0656ed395f1eb6470dca7bca400018355913e3791438c18b5ac50fe03784df789424101fb8f3001fb05a3eeb8cb773673c77f664501bc68b813206e9cd0920a11cb74cc918897804bee24000020eeb8cb773673c77f664501bc68b813206e9cd0920a11cb74cc918897804bee2420ded1303c7551bf04f34b3b61a00d142d46f2329ed8137295b51c89f613f5b62f01df33af9d739271f406b1c31d11a2f570c524e9dd0000000000030d2293fb2711fc0003abff0001fc0003b6940087de47ade017f67b717616f8bd4f5fc3005dbe8587de47ade017f67b717616f8bd4f5fc3005dbe8567918cbbd6928be3a8e76c1a8d89717c2e3d08ce3004cab5bc1d73f5f8299feeecc0bee2d76f27c3b2a56a7e2fc1f927e495ac9b2a0560b7d82fd06fa8fce4af69d0fcb10b00000000efb3f539ad844bf34f9529602480e504885915b42b10102b9be38c4db31eb1b1000020efb3f539ad844bf34f9529602480e504885915b42b10102b9be38c4db31eb1b1200ce06bc2b322337c43a1d3befe252ff366f81600bee06a14c07ac462e17498e00020eba3616392708db9c3a971924380b6080bd17e000000000022db5eb2fb4e1ffc0006568001fc000b9be201fc000bd4aa0086cd7c93e15658bbce6b175c320e67aad70c8cc686cd7c93e15658bbce6b175c320e67aad70c8cc61ec5c66e9789c655ae068d35088b4073345fe0b0300abc2b9eab7faedd46b321ef733583d1edf73112492b5a84f8d61bb83801f1269878d663ba0f037752792ff5226b02b700000000efd6717fe659d2b949955f2c01985d4ff36848c96e425c6bea4780e2ab0ff2d9000020efd6717fe659d2b949955f2c01985d4ff36848c96e425c6bea4780e2ab0ff2d920c8c64c21433a191413a465619ed9255bec0027a8f938e34af2846a3ef764d87101719ad3711be4ac4c4d3e916a78bf59fa8b486d1e000000000022e0950afb4e1ffc000bdcae0001fc000bdccc00e88bf8b114ce7d91ae8968eaba14be60d05491579d39d1cb8cd5844cb453cdb1a62b73e0ea6cde7b43e505b33b6e189d0f3c9f598a1e551fcd953cd6301560ff0ddb3c1e8bad9f2e237b3ad39c37ba804fc09d4ccd928362ee874308b29e827ea60c21b3c04787d771a16e732100000000f0e0387783674bd818ebae2fb6b5c20659cfcd5c68a2f8a1f03b03ae3004724c000020f0e0387783674bd818ebae2fb6b5c20659cfcd5c68a2f8a1f03b03ae3004724c2049106aa9cb4165261f6af3c21680cc16effd3449f9f73ac5e765c2e2380587ee01e02dac43c4d57aa2a821a9b0b25068f5f5edfa3200000000002be54d2efb4e1ffc0009c59901fc000c0e8a01fc000c13aa00e53909416dd7f61cdabae76c20347cabeec8a21ca6986dc7a8d22b1ec6edc799608163d63eb92ff6e02dac43c4d57aa2a821a9b0b25068f5f5edfa323088aef910c408df03f396e0f92411de096d08d4ea727fb3abf45541685d0327ee1e8d5b5a5057c92fa2360d9c0abbd11f00000000f129a2035414a54881224bb0926390bef90b8bfcc63fd2757ae95f07fc9cb381000020f129a2035414a54881224bb0926390bef90b8bfcc63fd2757ae95f07fc9cb381202d618978b20c66d63c97dbcc2f064fccbc03d2403baae27322c43315b1543391017f5372f19a541e9afb85c443c3645ad95a37f15d0000000000a747dfd4fb4e1ffc00023d3b0001fc000242030026cfdbcfd54646d88cd9fe62da04f5e70eba5ce6e21d3baa7509a95b0a9d741549047c2e90ed8aa785512acdbe7b71cba4d29a25df44193d6e950c063084657bff1dbf81b2aa50e385d01549f9c3683994ab0b16d5b7e3ede8efe95992bb621ec221c5003d2f9f26fa190ffb2a00000000f14c9af014af86568a4ae2582c3ffcf6602920ee4155b8a08b1054cbf31536c1000020f14c9af014af86568a4ae2582c3ffcf6602920ee4155b8a08b1054cbf31536c120a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e6df28cf902610e816bd509758353005ba3ee418fa0000000000023593580fb4e1ffc000ccadd0000001cffef89d1917166a4e3d2443411f6cd1032bf291cffef89d1917166a4e3d2443411f6cd1032bf2964f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d7300ea46d70601eb45319ab495e2462f981debc8316df2bb1a679ae3525c7f517e535b69a02052844374c887a9312a4798400000000f2382c75e2009f5ce32df63933aa700a05239dde4f2df94a40ba2234b8e777f2000020f2382c75e2009f5ce32df63933aa700a05239dde4f2df94a40ba2234b8e777f2200c69789a95af40ef45beaa00faff26487428af61cefe1f64b4099f4a90583bbc015d58fd558edd7f6e2ed85b5fa134648f477d32f30000000000342ad593fb4e1ffb783b01fb868c01fc0001196300c3bd25702c4c5cabd642d5498f118ec73134c534c3bd25702c4c5cabd642d5498f118ec73134c5347eb0a0af302dd9ff95daf9e98d2f1f2c5d764f743016d49c42cf506d5687c4035fc8ea37c2bc293761412b8c28a73f674df9d3983581f53a8eeb7f1c7b6382bb0485df381400000000f2b2cda32fe9ab9a29ad463e878bc4061e3fd74bd30508c53a214333f8b58839000020f2b2cda32fe9ab9a29ad463e878bc4061e3fd74bd30508c53a214333f8b58839203988b5f83343213ac50805d34bd73f1e06c48b873e46ad299aabe92fa3cdb2f201e0e440d4c365236c93f5fbe402336cba2c5a506242c800000022d1d386fb4e1ffbed4e0001fbf1ea003e58db4338161895653ffe307a9fd3567d7b3c3bba7c694196934a70e11ed92a56db5766131968cc365b70e557479d57b35b99598327dfbd0bf9291330195b44e1d553d160abfcf70b8ccfaf24480ad34fa7917fb87675f712f0795a23dd0107f5f3e39c07474697e95b15170d00000000f311a4630250c2c2fe0f6121d7214b1e962d2e7385e78cdc3ff694c9cfc0cbe8000020f311a4630250c2c2fe0f6121d7214b1e962d2e7385e78cdc3ff694c9cfc0cbe82090d0e59ebc9e022b3074f6eb4a31650a7d41f7e2d4a97a1956577ab903a5afe801794b99b1cd0a4f69ee1072b041560edd584e1d1a41a00000006a334e46fb4e1efc0003a9ef0001fc0003aaf4006171861fc24ad0c91cf01b5950b00dfd2b0e65e757f73d89afcfbd3c34ff42e19f32af77dfd7a8990fdbf7aed02a6e0d546fa6c8abb8d7e1f65743d03001841a16adc73f0224e6544d0cc57057ee2508c906706307ef8561908bd476594ff1e825798faac54c8f8a66583a3dba00000000f39722e1e9d02ddb49512b16674868a865bae2a912401bb6b006b09a74186beb000020f39722e1e9d02ddb49512b16674868a865bae2a912401bb6b006b09a74186beb2047d6aaf3ee8ba77263837e9720492e7b57d59345881f5443442861f43fbd0f68017583afdc80db725044af4e20f5a892f4a60770fb0000000000030d2293fb2717fc0003ab450001fc0003b66300bc97efd5f5716cff0af50478f0d383052635c7ebbc97efd5f5716cff0af50478f0d383052635c7eb0740696a1602a31eda2d6bbd49303ad3c665a3c63096395d8ca159e5ca66eae7685beb6766a6c0ae50b4569809c4ecca3e101a1f210bc35637473b5afd5e71bfbbc976277d00000000f3eeb1461780dc6c62c5793df607e23f55153945b17ee029b3404dce7450ca84000020f3eeb1461780dc6c62c5793df607e23f55153945b17ee029b3404dce7450ca8420a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e6aee197c209560b451adf796ae802f30ef1375183a000000000022ddc467fb4e1ffc000ccadd0001fc0010dcca003ecf5e66d9c0373f20f86d3fefdce2165c19c7be3ecf5e66d9c0373f20f86d3fefdce2165c19c7be64f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d73090051db915bd86bd938746c14440b11ee3b2801cbc6d6c1c912e8b41ea5eb1d8f852abf220ae91ecdb6da094846c1ba800000000f5e25c2dc6aedeff586b26a5fef15bfeb332963bd32fa02d1e8e1b0b74784c7e000020f5e25c2dc6aedeff586b26a5fef15bfeb332963bd32fa02d1e8e1b0b74784c7e207d6e5caedcfca225cb8da762d52bcd3d73b2b3ce2c7f8fa3f900bf0b6c75460b01c106d71f6a7402065c35fda833c7148623179b56000000000022cb31a3fb4e1ffc000a4aaf0001fc000a4afb0015b1012a3f35f6b6873a144ed87b5711f467030601878fc5b0bde020f35fd7dab0709c0faacba8fe3a840c9fab8a7618147fb2f3060fd847cf86f08f3099cec23c58cf89081e39d8862912ecd50a18b44dbe92af0378ef2a3bbbdf4a6a11a76af5b70db205cfd31323391ee64000000000f5ff9fbf1daf5db3539c7e307d9d50b12bb58a491b2f684c123256fd8193aa22000020f5ff9fbf1daf5db3539c7e307d9d50b12bb58a491b2f684c123256fd8193aa2220693022de7fb65f12cc990c6c3db7b02488cfa0d222ad3ce8ce8970dcd945666e01feac00c4a5ee38b2a8e6857126d5b39c05062c1e00000000010000000000000000000000000000000000fc0001923901fc0001ba5b01fc00021efd00d3f5c934320be62f66647087ee07d9e3b68996165bd941a8832f305921d4f2bdf7946d8ac1b6b379bcfd75be0403b27a8121583a01d004c114f919753000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f60f6c91316fb671bc4887c714f9ff99a836645e69d0a411fd85468602489133000020f60f6c91316fb671bc4887c714f9ff99a836645e69d0a411fd85468602489133200f90ec21220fcd572f8a7361d9b45930be3067834acbb21df32da4f8070d03c701989c8077698d0a9dd2f90be13019eae3a8d13e0600000000002cea7d97fb4e1ffc000b18330001fc000b1a2b00e3ea58a452a6c8d408df64a2f8511642921268034e28cb55a991fc1d6062edd80b6597f7e72d2a922567856cdf62ed7325c44bd7b7557e1acb330a633006af52990c96c3d5aa6d8d29ffc118f43a74c12f3dc860825818e70bbdc9548a6b62d680af91772ba9231378cb6d292500000000f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba7863990381000120f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba786399038120593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c050d1611e03249023d89c1ac086036cbea392768cc0000000000340dfab6fb4e1ffc000cf99e0000006cc3fca46aae1c44ea1bab81d506e9f0a3ae1d056cc3fca46aae1c44ea1bab81d506e9f0a3ae1d05c69a0bda7daaae481be8def95e5f347a1d00a4b4308f2df81ba65db70eaab625c5fe46f0f5e52a45b25c761686db23b4f18e547cb0d161912dd187302eb6f7c4a9a666a3230001fe2d4798df3e9b41a6823bc0b3f020478e87925d01fb8f3001fb05a3f69c63feb0590c9febd1f76164c44123538f67e4c9fd6f8d6393908f80c01d87000020f69c63feb0590c9febd1f76164c44123538f67e4c9fd6f8d6393908f80c01d87204dea6406996a98efea88a66bddbe7f9568093185b08c865b1b664ae0e594c7be07b165b659c3d7c15bba69e00c837d2a599526c6ec00000000003270c21afb4e1ffc000cf8b10001fc000d0b2300f0d1ca8f807aedfa439ff530b2653ae37bb94e6af0d1ca8f807aedfa439ff530b2653ae37bb94e6ac69a0bda7daaae481be8def95e5f347a1d00a4b43016cfe921690a750621948774a88522d4af9e4167a605797abdc8adb414aa254c2e16c43b95e491c1965eb90c528224a600000000f6f8f1b3377129a483e7c027f8ea7df7d2378de902f0788b132ba87c19c29f2f000020f6f8f1b3377129a483e7c027f8ea7df7d2378de902f0788b132ba87c19c29f2f20970ad5ad9687bcd4e164c49064780b2b2a038c942a81f7f939543dc0447996110031331182f4105cd8a4690b82482ec4c09197f5e9000000000022d91cf8fb4e1ffc0006567a01fc00091ca701fc000bdc0b005964edbb7dea08cb0987faa03a37a2295c19f4105964edbb7dea08cb0987faa03a37a2295c19f4101ec5c66e9789c655ae068d35088b4073345fe0b030167d2ac620df46eb74cb2069f69c30965f6c899a134366ab95e41c894293e0d987a3cb78176fe852a309faf101883bb100000000f718902044925ab8ba5089667a4c2a1e45b855eb4388d21c1b14e1d05bc1991f000020f718902044925ab8ba5089667a4c2a1e45b855eb4388d21c1b14e1d05bc1991f20c3aedb72e0902bd6da0a97cf554bdbe6aa6183fb075b4aa3a13fafd81f430e200150046adb767e71c9cd404518f190faa10ca9b9b800000000002e65348afb4e1ffbe5be0001fc00011beb00a7327f6d42206d3642c4633c4b6b10919202cc8ba7327f6d42206d3642c4633c4b6b10919202cc8b6d4c795644ca86f717628ea27f0af13b0ea70eb7300d2be4cbd0faf7a27695a4f11690ba772a32c9df368f0558998681d697e60888b7127314dfa8495096050638d8507c9200000000f735ca801b3ed2a87a0fe2838a38a56d72239fd0c4e3877e80cc280090c6f8e2000020f735ca801b3ed2a87a0fe2838a38a56d72239fd0c4e3877e80cc280090c6f8e220362c9cd667b23f106f2fe366206f8e1d7353c5185de1426e64fabbc2ebe2856d00a1dbf97a74f90b10f8ebb6d919f21cc2cf9e2a13412000000022da8162fb4e1ffc0001980801fc0001c2de01fc0002787b0065802f3ece78b624b0739a8002fe35327ab85b7065802f3ece78b624b0739a8002fe35327ab85b703864c3d41a45675756b2543a0bd787a1a18fb4d9308cf9b3235f77637f144728584ca13d1d3fd47450ad392a510beb2425e0d88f6a3354f0cbdd26d4e6152d38899c025aa3018b3277a4f4a3667225def8a4f83000c086719cd9000000f773def21e01af33f508b4e978631b99405fd1ad3947984d3bbca5b41b221175000020f773def21e01af33f508b4e978631b99405fd1ad3947984d3bbca5b41b2211752071e06128c6220c4671d4582596eaa9528757fc86bfd42a7e6545314a2271c2c501cfdae7bd25128cbaf6e27f37b9bd0e1024d4d3fd000000000023b9cadbfb4e1ffbe35e01fc00015cf101fc000467dc008a108538dca5b073f24fb8db78f06ab6a0aec27e8a108538dca5b073f24fb8db78f06ab6a0aec27e23baa2294dc2c2f7b6e6fa3717074afef3ef2d783004f1a3407bf953809815243d539d316d2b055a57ff6c5412f31d98f0d5ea84f54511fa9f02ddd6d7f8751505c560eaec00000000f7f3a36e13bd406d5b9c9a19b6c67c5051f7a29e6596c1413326b98c00cad909000020f7f3a36e13bd406d5b9c9a19b6c67c5051f7a29e6596c1413326b98c00cad9092009d9ca008cb9263341c196659ea2f751507cc6b6199a9c5b6d40bd136ea3f3f7001d328264ad882a524f8fdec5cadc094fec10834b00000000010000000000000000000000000000000000fc0001979e01fc000197a101fc0001a33d00954c2b52b2f86d89f81b8eb64b0944a1b1033e38954c2b52b2f86d89f81b8eb64b0944a1b1033e385f9227e2d862ef10a8aed1df196e5267accf22023000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f8293d83dfb38fa7a6c34928e9171fe6a112d5a5b1d07592d59f37a23ed0a00c000020f8293d83dfb38fa7a6c34928e9171fe6a112d5a5b1d07592d59f37a23ed0a00c20e0699697fd9e5d90cf616f1f65e6172be9660e8741e431a48b5b280ec9c54aa001a01a6124dd32d31434325f8b39e3133ca643b8c3000000000034348bbafb4e21fc00014c6b0001fc00014cc400894737fba2d8ab6dd337538735ae0a74b18cd19a8e4960713412ea367f0a11c39808c2e77b83048b69a9e3015032f43608f55847cfac26a1926ace9b30803d3e3a2593dfd56111203f3f7c562d1df639d57376d1994aff17260cfbfa576bfed870eedf234bec169e2f8e6c44da00000000f82d3b1184dc6c6f444bea666c1b0da5e0d58a4a29b036e6c21d9e26ec349b44000020f82d3b1184dc6c6f444bea666c1b0da5e0d58a4a29b036e6c21d9e26ec349b442048ba30ad4c27e9c0e3b495b609c15987832ab0f4f22d138dbde025c25e500dcf00d5918187a24fbec74eba87813da01d4977383bf90000000000037ffd56fb4e1bfc000d63490001fc000d640300336fd9a1efbd7983dfc291e482862541dd50af197d354fb6b06f9f41e73aef311024f576db99e6c365af4ce6e6ba9ae427611b7164d92adeddc6c7dd308458274be8fddb6b8685d753bb151ebe32a9021fab91228611a81c3c70b287b607a81388b46aabb16518494f9127776600000000f8ef5516cb8f36418e42dc9e078b26b0c4b1b9ad810019974686fb9a6dc88206000020f8ef5516cb8f36418e42dc9e078b26b0c4b1b9ad810019974686fb9a6dc8820620a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e12220b8c3cf751fb6bcf3b11f12e6406cee717c1ad0000000000235a9dcefb4e1ffc000ccadd000000baee5acad0f663430ff83c4e9b9fcb0122789520baee5acad0f663430ff83c4e9b9fcb012278952064f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d730015ae7a4f88fd79e4659c4b24b32f24d1e92106b867a2c23d1d084cfedd0e2766edd3f0a77f274acd4d1d53fb1ff021800000000f94177aabacd11c12c92b1d5ec28b8ee9f1c07b220ab783cbf8a1a21cf6a5f55000020f94177aabacd11c12c92b1d5ec28b8ee9f1c07b220ab783cbf8a1a21cf6a5f55202048b7ea90f351d942342361942f53cc52eac2b6d2df7aa5cde9ca4f832e699401ad1d4e86ad3a26c56694ad85fc4e14bb01a0244700000000009de6f7dbfb4e1ffbc8190001fc0001195600365a7fa9a52936ee5272729a4011c8a00c0351d3365a7fa9a52936ee5272729a4011c8a00c0351d3ad1d4e86ad3a26c56694ad85fc4e14bb01a02447309993c900fc49b020d4050981a45281cc71274196c57c9405f7ea8d82823b2cb36c04a2aa363111d74e383bdf9fdfe25400000000f9b4e4b1c35b8890d0ef29ee2c8ba7e600ba9acee68b100d24f4c30f190f07b6000020f9b4e4b1c35b8890d0ef29ee2c8ba7e600ba9acee68b100d24f4c30f190f07b620a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e52b046b8be830ef6606eb16136766fb8f5a378f4ce000000000022dcab9cfb4e1ffc000ccadd000000e148cd41cb7a2aa954707c3a5846ea7927d7c835e148cd41cb7a2aa954707c3a5846ea7927d7c83564f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d7308d4afa904198af1607c56fd3a1e8fa546dd2940e603c87fd64905a5eb86334046a7eb8638e36a2dbdb6ca59fa8e6886400000000fa6350305c1ce0de594787f20ff7ddd0c35a4cbdf10c8a9956d833ab6fdcd225000020fa6350305c1ce0de594787f20ff7ddd0c35a4cbdf10c8a9956d833ab6fdcd22520a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e030254e4408d72c5c1ccad797bc8c1bfd869d91c24000000000023a44db1fb4e1ffc000ccadd0001fc0010e71300ea33f7129398e7e2436a712ab55fa95a2c0e4cc6ea33f7129398e7e2436a712ab55fa95a2c0e4cc664f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d73000ea87eef15f38c1a844d77348e687794c601277011c933026cdfdb649524632b055feea3539abc48472cb447d281d6500000000fb1f0a8cd13a1ed6e11d83d906cf3cd42114e36a762e214e04f6f0bfa698dbc2000020fb1f0a8cd13a1ed6e11d83d906cf3cd42114e36a762e214e04f6f0bfa698dbc220a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e1d32db872659af4d0bd7c6f8f7e40f40564c4fcea1000000000022d3c081fb4e1ffc000ccadd000000083a4e9632bcb5c6490a92b3c3b05979bcc866f5083a4e9632bcb5c6490a92b3c3b05979bcc866f564f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d73002ce863d0843ca66b4a64d94c0d84ec15980ea04e4444ac4d4188f38cc0da4d6d2360b8a2046725b682862255af6a48c00000000fbdcb8ebb8b7b0536b8af0bd89b5f973fedb880b51d03434767eaf9ea7443bb6000020fbdcb8ebb8b7b0536b8af0bd89b5f973fedb880b51d03434767eaf9ea7443bb620a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e4a999c0b640e64f1d95e90b4e6b75651cd9581d92c000000000036cae7c3fb4e1ffc000ccadd000000982169553d0e618637a1cc6847b185baa50a2ae4982169553d0e618637a1cc6847b185baa50a2ae464f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d73017f2a4f37de1f78a0d356835de99c7639d8daf824b0d432b2a7c01a921f6a8cd4028272e2962f7d04abf9bfd5a77ab8e00000000fc07e381f05476042949b584f41fabd582e6a54d70657b8ff39fce58af62eb53000020fc07e381f05476042949b584f41fabd582e6a54d70657b8ff39fce58af62eb5320a8e7d1287b0354408fda5a65427a636c7c5854a957b94c5f993d727450ffe34e2a473290be126b36c0ebbc0ea853721bc67ea994a80000000000235b9622fb4e1ffc000ccadd0001fc0011030a0087e9edf19d1998903bf17a10a954872f429ced8287e9edf19d1998903bf17a10a954872f429ced8264f2b2b84f62d68a2cd7f7f5fb2b5aa75ef716d730090f1ca955443740346b5b4b0bfb8251f040074b5a2feb77e54add831bf34aaf1d84207691f6f5aa5e702152a496fadc00000000fc196382366234f4645215261ca7e62f53499345ec1def69289e47c0c388dc6d000120fc196382366234f4645215261ca7e62f53499345ec1def69289e47c0c388dc6d20151b4f6fbc7351efba1dd1c36c733978a184561af7497b25b4a8a3e0afec0e7f016608134feb91cb878b26b977f1d7983a2f14452a4248000000258b0cf7fb4e1ffc000df5420001fc000df56b00c346a8ffbdcc80462cb69a6f524388a5f496fc6ec9a9263ee8c8c606c449959c48978ba70d4a097bfc86e599d56c282377dd9510ee62c55fefa553b1308d0651a04f9c243872f613901a1eeb2fa86f3e9a65168bc39941790783d9189a9a7876cedb0c6d7ff7d49fbc88a7191100011348d8f97063cf6ff602c14bf59b5ff501c8bbf401fb8f3001fb05a3fcc330b0afdf27d07997b93277a3942e28f7cf4fd043b7ee64b6b5c16173c936000020fcc330b0afdf27d07997b93277a3942e28f7cf4fd043b7ee64b6b5c16173c9362036c97361c1b5b664eeb743d04fcff7282e94a37732b99779d027dfafb030c3fc003d2324a9cadcb2ea6579a7348ab70aa933472bfa41000000000381198efb4e1ffc000541190001fc000541d400e73be15c24f67457c2337a8c99ca1e58aa68598d7200be0fcbcb2c10e968ea0b5508bc3424c9c68bda952b3b45775c0af85fbe2e2ab21549d86beb0a3089aaf743d70a26ecd18aae71d8e2ff0bfc98a51511f83c8acda856e3f5d7c61c21ff4e19a56f02ecfb6ee014097945e300000000fcdeb237fae2e669a85a86e8077e608c6939ef0f4f9e49a44e5ed6795572e6a8000020fcdeb237fae2e669a85a86e8077e608c6939ef0f4f9e49a44e5ed6795572e6a820d3a8d64ff151b1ba13683b26008256b24aacec6f9da5c0066ca64c10a73517ce012c3e80b009a279f6b8cd5db9fb3206f14676366000000000002356861dfb4e1ffc000b9bb301fc000ba63001fc000bd21b0047618a2082ca728a4d9397643a7578a735a44d1b47618a2082ca728a4d9397643a7578a735a44d1b1ec5c66e9789c655ae068d35088b4073345fe0b0308341875737a85768a19cfe8c6c220b594bb18131adfd2fb44e386f7b31253aeeb48140170e29db98507489c7b1f792de00000000fd21cf50c8f2f7e475b7092a5f136129b12d30e9ec98b03614ea0788fae2f888000020fd21cf50c8f2f7e475b7092a5f136129b12d30e9ec98b03614ea0788fae2f88820a8e027adb039814f1d9a37963c233d9d768e2fbe810c79c0818a5fe103a2505c00582f33bc9bb2587d4d87dfbb37d44b1d1c201fe7000000000022dfe2e0fb4e1ffc0006567a01fc00068cf701fc000bd9830055f851335398fd598265dcc41dcbefbc307b609955f851335398fd598265dcc41dcbefbc307b60991ec5c66e9789c655ae068d35088b4073345fe0b030046fe8b4fa7dd4fb52ac2a77b4ef7dcd3f4ee6c940789144504c95390d556eab1ed97db4d9de695796fc0bdbf0543cf700000000fdb15344c0b81fa9204adadf4fbb285a8e57c6079071c1e6134ef1a28ff23630000020fdb15344c0b81fa9204adadf4fbb285a8e57c6079071c1e6134ef1a28ff23630205b016215386c035a42042a93736befccdb87c30cb90adc3b1279da58ac57cc1406928d5d3df4acda874f594b59a88a38052478f10d000000000036b87f1cfb4e1ffc000cf8b101fc000cf98701fc000d0493000453c5b78e603d51a58a56e7a3b6a4bcfa5b1bca0453c5b78e603d51a58a56e7a3b6a4bcfa5b1bcac69a0bda7daaae481be8def95e5f347a1d00a4b4308a1a6b956acbb6cc1c4fc3713ae482d84ac9d3e00ec86ffe25a56a717b748564128c97f38e99bfe7292fd4737ce5299c00000000fef106ff6420f9c6638c9676988a8fc655750caafb506c98cb5ff3d4fea99a41000020fef106ff6420f9c6638c9676988a8fc655750caafb506c98cb5ff3d4fea99a41203933d2e77a9b59df4215597e381942291a23aa6765386dbabb04117c1018988001d5faf54e1d7675b61cd63f569ee38bfaee9501b800000000002d30a810fb4e1ffb3e6401fc000b253301fc000b322c00ce2342a602ce6bd150809591377ecf31971558cace2342a602ce6bd150809591377ecf31971558ca05ea03a6c9dfa67e1837b3c14965ba3cb53bce7230842476e8d82327adfb9b617a7ac3f62868946c0c4b6b0e365747cfb8825b8b79ba0eb1fa62e8583ae7102f59bf70c7c700000000ff261d2c1c76907a2ad8aeb6c5611796f03b5cbd88ae92452a4727e13f4f4ac9000120ff261d2c1c76907a2ad8aeb6c5611796f03b5cbd88ae92452a4727e13f4f4ac920593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c0c456ce31778e3778c88a87ac36a1a8bd4aa5bdbe9000000000036bb0ee8fb4e1ffc000cf99e000000b14f661da8227a41acef9f8096df2afd2a192aafb14f661da8227a41acef9f8096df2afd2a192aafc69a0bda7daaae481be8def95e5f347a1d00a4b430967796952922dcc5208a3848ab85a787e4592df2d8ce36a29369b0b3a9576073651075039e1377873aa8c67514ad2726000167e05b1b52c7c896adf20035036fe1d30dcefc9c01fb8f3001fb05a33005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea800012005b687978344fa2433b2aa99d41f643e2d8581a789cdc23084889ceca5244ea820593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c093de7795dfedb896cb65547535ed92f27489d8df3000000000034187ca2fb4e1ffc000cf99e000000ec83a5f23ec17737f590153eb7eed16f7b2f1327ec83a5f23ec17737f590153eb7eed16f7b2f1327c69a0bda7daaae481be8def95e5f347a1d00a4b43080f8efb42f65ed9650078785be5d13e6e90eb9df87a99261d4de34df2b4b79a9c9b8c5e1aec7ac068ebef14636ceac4c00018feb00404d6f765856c95e587b2523a365bc725801fb8f3001fb05a312de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a200012012de3ea6678dadb1db529b7fa98762160625055de2aa34e757c93c136233f4a2206793cf0a4aff111f1d61a13002686c066afbfe5da974cc7dec8cb4cef736dd8000542bd8c9d87e1cdd3db777d29c35e9903b17727a4120000000d4186795fb4e1ffc0010903d0000006e52a40d2dc4dea0ae7ff2b299283de0f2798b0a12deb4ca2b5a05b6eb2ab25bb5fee75d3287b3df0d5bcbeeb459af40f97fcb4a98e9d1ed13e904c8308a3dbdeee728fdec9cea3508c19ece8d2e8330b666e25666b1766ed5f44609dc8674dab4163e8574f4adf2e936a209d501c623e2d926af5eb52dcc2b931993d3e52714511801c1161c96de3dae28cd7f20ff8c2aa7b94b866d7601fb8f3001fb05a3143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f113000120143dcd6a6b7684fde01e88a10e5d65de9a29244c5ecd586d14a342657025f11320593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c13838ddf0c05bbc0edebee7e368f4dc6306d524af2000000000023a417f5fb4e1ffc000cf99e0000007395853c0be5fb0f0348aff8128979368f52b0ee7395853c0be5fb0f0348aff8128979368f52b0eec69a0bda7daaae481be8def95e5f347a1d00a4b430b928fa4e127214ccb2b5de1660b5e371d2f3c9845077bc3900fc6aabe82ddd2e61530be3765cea15752e30fc761ab7300001b5f25f8f70cf8d05c2d2970bdf186c994431d84e01fb8f3001fb05a31ba9b400a99c8ab19e2681db0e868814aa273e8eaa13615979a14c50bbd53f4c0001201ba9b400a99c8ab19e2681db0e868814aa273e8eaa13615979a14c50bbd53f4c204c3fd5bb504ca179596113aa8e3e27aa1488860edb81269eb18a9ca900b4a91b017c706d1b78fadb609fd92ff5929901a706c55877000000000058162c0bfb08aefc000cf9830001fc000cf99b00f74034f58c080be74bec51165c5ffe60ed1a615f96375e263814e1d54fc3297fe893dfb5a9c1a9eb6443411c39e405d2520567d4f6b041c5c550086230b006ed30975f322c830001d1b3c2e2f14a4ef35445431356f1c5b93c2eedd9c7ea24c4429d27d45f2fd701733ffd65540001f2dbd9b0a1f541a7c44d34a58674d0262f5feca501fb592501fb592620107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c00012020107ec50e81880dca18178bb7e53e2d0449c0734106a607253b9af2ffea006c20593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c117663ee06b0b159308edf41150954372a730aa6a50000000000235515b3fb4e1ffc000cf99e00000004d65ec5142719f58e31f4510dda3c810a84364204d65ec5142719f58e31f4510dda3c810a843642c69a0bda7daaae481be8def95e5f347a1d00a4b430b6e979f20241cbb73de7451779e8e059d9cb75a74b72ea6862d7ac703dc2ac07d86cec39b6e8923b55fd54dbc6177c3a000135d9eb76397d05b43b5cd8da7ccfa8408bc89ab301fb8f3001fb05a32e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb0001202e48651a2e9c0cb4f2fb7ab874061aa4af0cd28b59695631e6a35af3950ef6fb20593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c0101e19b30edacc8bd047a72d6b12b79b3f1b2babd0000000000369521a7fb4e1ffc000cf99e00000063f16c50b9cd1dccd8465e1802749bd00dd49a2d63f16c50b9cd1dccd8465e1802749bd00dd49a2dc69a0bda7daaae481be8def95e5f347a1d00a4b430943a88959611417f9e8ce4e664e1d9c6a839daae14f54ae8e78bc5ef6ec1524d116efca49ecd5c57dce31d90015a51ff00011ffbf1d32541dcb8f5555305295704a9ff9adc2401fb8f3001fb05a330110b4643c2d8c7521f27ccc2a6a70579bc859087fb95facbb831b3a3d107c700012030110b4643c2d8c7521f27ccc2a6a70579bc859087fb95facbb831b3a3d107c720fbcd42341652da33e977bab8bbef42d0f053f93e9e2748f3f39881d11e28910c017798d43ef1f85193b1a0e5a7ab7853a39d27f0334060000000a6469a72fb4e1ffc000f01930001fc001046630057656569e143ae0cc0419020708c8ce5f4c776e452bfa12608d37422d52423c3a71f9574ffa8267f535e571f5fb89e31f634da8b91769ea4dd252e19308cf6a03c7a0bd8c38c1fc536a013f93afc8224cbfc79d8b0157c7080117ec9c1c60198c3fb3886ec472aeaf80bd5fffc0001c3f93922e89f4bb3869da0c18d8e30dd91019bb101fb669601fb27103971dab9691efac06e4ce7a5483131373e84726458924fe48b7d541791693be10001203971dab9691efac06e4ce7a5483131373e84726458924fe48b7d541791693be120926c6d0e0ce17a51dadcdc5be4f4cce0175d8d7a147e294580e3080d6a22f96d00e5cae595965e89fa9f94152f57b315ca504ee1b300000000005c3fb0cafb4e1ffc0011098b000000b29a8f14049a111260586f489d72cfea1ed8ee5d492df4065de3d5d44692934635d826255f7a60f80e7e48253baecd886fd539601fd5e95efd61534d30b92d4ef819fe283a307e6bcd500d8cd35e9a7b779dbca59bd3bc77b3bb3611c370258aa6dec13d0781e0b53c911bde08000161c274080f47a95be5372ef8c69bb60ab1d4ca8201fb8f3001fb05a339741ad83dd791e1e738f19edae82d6c0322972e6a455981424da3769b3dbd4a00012039741ad83dd791e1e738f19edae82d6c0322972e6a455981424da3769b3dbd4a20593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c0826c998cd53845caec6858f3121e5d3a88df6c7a3000000000023a390e6fb4e1ffc000cf99e000000bd9857229d4c0509c753afc85d264fe2e4f344a3bd9857229d4c0509c753afc85d264fe2e4f344a3c69a0bda7daaae481be8def95e5f347a1d00a4b430b6693296894820bdc3c0ae76f357e544847f10a68f0046f53745370dbe861d57e194ddaf7ff7d5e73cc3f240515c448e0001ec7bf3b9bc72eda38c80bb7cf16e294e763e56b401fb8f3001fb05a33979cfb79c4562e819aca69ffae2ea84b9b8f29bd89bdc68be67b88c6f31bf990001203979cfb79c4562e819aca69ffae2ea84b9b8f29bd89bdc68be67b88c6f31bf992067a0592b5510496cb42f2d784cc3b933a0156b10c8b54e440673bb87c57dbb01011353eea2d4fbc06aedc288e493b70de32b3e977f0000000000adc777f2fb4e1ffc000d5e0f0001fc000d5e4b00d8155dce6238737a6af04e068bd92048e68a7f51212e07f7407be541b585ff0a8225fa1afbcc9ac8dc82946c9cee9ab3e8fef5a5d641a57bdf1523c030a73d8c1e640d29e2257042a39bbbac8d867f69ae252e146884816b98ab0d0526ed4992d9cff22ef04878423f66583382000171b5c04007f6af71d99893478feb52df0f5a770101fb592501fb592639b88e537c795f0b093c951539695fd4819a91a542b247ebd3a0ddd6a4c1c43900012039b88e537c795f0b093c951539695fd4819a91a542b247ebd3a0ddd6a4c1c43920bb600d779c7be93a83b9d7878fb38b0b1b7ff1390b231c5da8136b674cde822f01fd9cd0a5165717d4b3a17afddc669f3fd14efbb5000000000082a2e172fb4e1ffc000ddfee0001fc000e0d6b00f5cd552d14676526ef325757eddcfa285b15ac34bf951db34349385992e0303f21fd7240e44e4b0222319c7fcaf88f86259ffd3fa8430e4665f2e1f53090d98ff5c2f2970197ce80ca8cba9431f7dd7cff5d9fc9c4e99c2ed06e598f273d31dad8d8d05655c8b04599495cee2300018e976c7a2f79745d70e41aab1e61cb5f4db4323c01fb682001fb01bb3f43ff3539e5a4fbcc88c7f031a544fe7e62557b5963cb7e43157ef73abfb13d0001203f43ff3539e5a4fbcc88c7f031a544fe7e62557b5963cb7e43157ef73abfb13d20476ad8662b3be5582b98569b76f66d2eecb59a943e9fb28bcbd23a10d53817bb01127e174ed242c758d4db9b7d5b19c1e0743728960000000000b29d5bbcfb4e1ffc000de50401fc000def0c01fc000e366a008ee38b4c9c407b21612862db1ac4e98a6edacb4b62026629f37f587b1dc70ccbc6732225803db4e3ecc3795b4c3e8c5b840dbfa092df1395237f2f8a30980213c5fa8031aff096b8a3eddeefd0584a0e5c2492f631ef67941e082763250e2615975db1f1bfae631f80d41d839a000100120432e9d299caad204ff1ec0c515babddc28601fb8f3001fb05a340784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d00012040784f3f9a761c60156f9244a902c0626f8bc8fe003786c70f1fc6be41da467d20593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c02024eb44eadf4a67de93988f1400bfd5fd6fdbf830000000000340ae50bfb4e1ffc000cf99e000000f37ebd7e83f4185ccc5fb617a7ac9e09c11ffc12f37ebd7e83f4185ccc5fb617a7ac9e09c11ffc12c69a0bda7daaae481be8def95e5f347a1d00a4b43082f60dad4b7b498379d1c700da56d4927727eab4387a793b861a96df47bdabe5666c270acf04b5b842ab54045bbf102a00013e8b10646ee9d6c28d75c280b357dd3a9ae9f96201fb8f3001fb05a34bba47ad7330a358cafe2890f1578f874006a68bdc7b786a7c1d440823e683d40001204bba47ad7330a358cafe2890f1578f874006a68bdc7b786a7c1d440823e683d420ca7dbad69767b30fe851c08c80df2cc8398bcc8c33df2d03bcb810485f3d8d31006e6c9189021b6e38326dff6886104054a110990d00000000005fd916b6fb4e1ffc0010871f0001fc0010874300bd8b7dede4dab5e22b84ee0f3dace1c1021add92c9924137fa318dbfca7cabf3a1127fc358acc74d6e6c9189021b6e38326dff6886104054a110990d308ebfddfa72f3140798b6c0d89190164c4dc569ffdd95bd1dd43e7f54f1405c1927b37b499623b4c806ea396bea40a84d0001b98306c317875b12fae8a85c85eb23269168981801fb682301fb01c15b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a230001205b246080ba64350685fe302d3d790f5bb238cb619920d46230c844f079944a2320774441a2d4ff6133747a8bb1b5e4a9a21bb73c4b77cf31e85bda68f898949db0013f978f2c099e310cac9e854b99bc981c8fdcade2000000000023a5327efb4e1ffc000cfb4d000000ebb7d8141ecbdf2abcdc3ebe25420b9425745293ebb7d8141ecbdf2abcdc3ebe25420b9425745293c69a0bda7daaae481be8def95e5f347a1d00a4b430b44cee83a79fa151527e527f3f4f5ba022e73ae8b0d913c4185a45c2a129aef935a585a7a725edcb36ece72a957586880001f460a07a2b0dc932e1d8ff2dee2b984ac415dceb01fb8f3001fb05a35c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef4360001205c6542766615387183715d958a925552472f93335fa1612880423e4bbdaef43620593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c0f62555d44fc8d089674bab5d090a48825bea701b700000000002cef2799fb4e1ffc000cf99e0000007ef7c15840f96c603fcd29409a70f77f878d25d87ef7c15840f96c603fcd29409a70f77f878d25d8c69a0bda7daaae481be8def95e5f347a1d00a4b43086d0a2ca6f434eaa47ff6919ecafa4fc3b012b89c62a04835a24c00faf62c3d30d3f8755c33a7abc595e96fb5b79594a0001972a33056d57359de8acfa4fb8b29dc1c14f76b801fb8f3001fb05a36029fadf3355a31c6f841570e76bcdf5636378c65ff1da8f580806602752694b0001206029fadf3355a31c6f841570e76bcdf5636378c65ff1da8f580806602752694b203e14ea3daa62c03d9ed56e8895b5d98188711c49818cd0add43d37fe512c93d1012a5d83dcce0edae361a62d8bc2a308a87e29a49b000000000059a9ab6afb4e1ffc001079fe01fc00107c0e01fc00108203001119c437dbe2c3aeb4a3c7d1e29380738e3372433e443eba6ce82ca15b203d10117c653f26944256cb505749178fb4f731643d9aa56c54e504f9cc6e30a4adf9fa35bc975e52e3f667e48ff3ed7ce71f8ecb85d5ec728596f7fee735c2f857fae1569c8b4c6839ca849cba42d1000197ed64c04be77ef571fd5624c0f7705192630e3a01fb8f3001fb05a36071df1e3bf80ba6cb9795bb2a82ef426cf559b7711e555af45fd8da7fb629b80001206071df1e3bf80ba6cb9795bb2a82ef426cf559b7711e555af45fd8da7fb629b820387368b816ed3599d758185ae60d943afc22201e94e06ffb3dad30a3ddc6756b0005ccc78c0358f7b71d254b28c7287da9b39b81f400000000002d20db70fb4e1ffc000d05b30001fc000d05cb00434dcdb7115427657cf2936248b62a97b9969795ff1266f2c8aa7b1f93a15b8882013af424d7d9e805ccc78c0358f7b71d254b28c7287da9b39b81f430b4e545a909b1916959139eaea845262b0aadec1c5cf555922bb6e6d1804343e6490428a382a0c01832fc70c50438fea6000152cdd176257544a263ecadb986ed72375589a8a401fb682001fb01bb61d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb00012061d33f478933797be4de88353c7c2d843c21310f6d00f6eff31424a756ee7dfb20593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c15888380d6096d829d6864cf6eec66812266839e0d0000000000340cb05afb4e1ffc000cf99e000000b5b414e1a68e36a25df214ac6eba35782a0437dab5b414e1a68e36a25df214ac6eba35782a0437dac69a0bda7daaae481be8def95e5f347a1d00a4b430a6a63376eb861bda6afa09e28e39ba40cdfb877ee6f9aace10eaccd4caafe8d9243f2f2c0ef982a0766347073cc199bb00017ada3e486409b39c94a0833c8d782f35bc24e96a01fb8f3001fb05a368512af99ba954cba495e96651a8d730880e21437a873fd9309b54ea9e3b53cc00012068512af99ba954cba495e96651a8d730880e21437a873fd9309b54ea9e3b53cc207459dbe6d9b1930f8d6bf4d0872b2ed6af58baa2f0effe608e6e2ab0c98c148501f30f8dc6c5b956089b30b3dc91867a3b72620b2f0000000000b92f8494fb4e1ffc000faa6501fc000fcdc401fc000fcdec0044b7348492de6612c17d0aff5a3f6fb5f338d57ab2f70938b1cfaba9eab8eee718a48f292e1d5180d86df99cea20e4fadf223310df529ce645f0db2330a28a648ac2b271105426f11a070d3f4854f812c3fd0241860afd511a7ac76e681210505ed41121b141e377a73faaedde0001e33c1f9be807b975c0f5e1c0e3c63175d9e55ea901fb8f3001fb05a36d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e528633209660001206d1b185ba036efcd44a77e05a9aaf69a0c4e40976aec00b04773e5286332096620593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c18a93e60c572add22525a10a5554e6f6a4feca49fe00000000002ce4f2b5fb4e1ffc000cf99e000000f3a83d259634fbfc3e3c4ed50cdcab6598fce20bf3a83d259634fbfc3e3c4ed50cdcab6598fce20bc69a0bda7daaae481be8def95e5f347a1d00a4b430b8a2161c64bfdc7d621df51de569911a219f718bad4d6058dcca9bddf6696d43ddc4c1e3cf91640c93f820e5680efac30001c374f016ea61e76aab79b8bb95a1ba0e6e3eee6f01fb8f3001fb05a37135069642e1a72807a383fb5a14b9af6758292fee53fe2a7f7ac6f528bf70190001207135069642e1a72807a383fb5a14b9af6758292fee53fe2a7f7ac6f528bf701920593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c1063c03764190123b001e65fd3aa12c030df5bde82000000000036bda427fb4e1ffc000cf99e000000b920a2229f777e360b7da76885a556bb439533bfb920a2229f777e360b7da76885a556bb439533bfc69a0bda7daaae481be8def95e5f347a1d00a4b4309472710b11e34dd5f6fa0d43cdde23ddb33558be1539cc7275cf06ba2d82c6ba0c712e7022752843f411e6702eaa736d0001f9956e70daffa263e8cf29fa6557b7b630a595a801fb8f3001fb05a3754b89dae8db20fc4cee5e3adb07b146d7efe508a66fa0a8e1094675b9daa35e000120754b89dae8db20fc4cee5e3adb07b146d7efe508a66fa0a8e1094675b9daa35e20593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c19ad66f3780f47e83479e1846ecca44d71ba5a902f00000000002ce92c5ffb4e1ffc000cf99e000000e65f1647a5477a20d178b12c509738d7a35ff312e65f1647a5477a20d178b12c509738d7a35ff312c69a0bda7daaae481be8def95e5f347a1d00a4b43099b9f0fbeea3822cdc5b3654dea52103b3d9d5f01db4201955ea3689074d37da4711d8f313d4b5458eef3395aa75bfc7000146d938862af6d9a291e26c0048177db2892a710b01fb8f3001fb05a37718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be42900001207718edad371e46d20fad30086e4acf4a05c2b660df6ae5f2a684aebdf1be429020593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c1feea83c4756a349e76b9077636dd04b3306bac60d00000000002ce3894dfb4e1ffc000cf99e000000c0e3581e5165c63790a2b8d2670fb4a1917cd4b8c0e3581e5165c63790a2b8d2670fb4a1917cd4b8c69a0bda7daaae481be8def95e5f347a1d00a4b430b675a1940be872b6a0d4e1696bb39ea38179933a1bae02ae1eaf4b47f625bd939482f8791eb38925af47f73be027a64c00010498ade3c80045c2a7520e921180ae1c39da5c5701fb8f3001fb05a37a1ae04de7582262d9dea3f4d72bc24a474c6f71988066b74a41f17be55526520001207a1ae04de7582262d9dea3f4d72bc24a474c6f71988066b74a41f17be555265220593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c1cc1d71953a4a45bd11d458683bbf2ef794d6d6e3d000000000023a612a6fb4e1ffc000cf99e0001fc0010f2fb0063c8d3ed082eb5d476a0940ef9c3fadafc4c5d2c63c8d3ed082eb5d476a0940ef9c3fadafc4c5d2cc69a0bda7daaae481be8def95e5f347a1d00a4b43093943908436a934c08582583b08cbcc50b4478bb79b7718789c25eb0ad2f3e5713ad4c152d4b1fd13cfd12bf896072e600017478cfd163788e3bbe09645776cf59642f28e37901fb8f3001fb05a37e56cc8c37501f3db794a554deb4287ac61c83635a0dec6d0f8e0b54ab14f8cd0001207e56cc8c37501f3db794a554deb4287ac61c83635a0dec6d0f8e0b54ab14f8cd2095f18528a48b7308195ec8201220efaafecfbf4df55cc2c8ab6b518733c22d63010e3edcfe65ca42dccfb1cb826562a46097c6f044412000000022df662bfb4e1ffc001066880001fc00108203006afebaad117b22669d50cf8bffc7863662b1d7e16afebaad117b22669d50cf8bffc7863662b1d7e16c671d1b8ae658d8102e47f0bb3f795482a6e215308156eebd6b52f4146a5b3f9686b9712f48980dfa4e8f17b514ba185a31e8d5fa7568c69aa79d9533fa6efd380c27b0c00001390fef6518c3b4b95551fe1707e0f0c398d5580801fb682001fb01bb85f15a31d3838293a9c1d72a1a0fa21e66110ce20878bd4c1024c4ae1d5be82400012085f15a31d3838293a9c1d72a1a0fa21e66110ce20878bd4c1024c4ae1d5be82420593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c1aba3f43f7376b9025296fa73a30c07ccf5266eed8000000000036c92083fb4e1ffc000cf99e0000000f89b9ac5ac8f31255f692a3eb0283d0ef3be4360f89b9ac5ac8f31255f692a3eb0283d0ef3be436c69a0bda7daaae481be8def95e5f347a1d00a4b430ac3026b3e3023db1db9ec8e3b7678761820a2a6e96e7a5d9a39b1894170f9cea7765d3d131d60fa9d17492ba560fb1f9000168c506d43816d1a8389c860c1d162be44d1e777c01fb8f3001fb05a387075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d67891800012087075234ac47353b42bb97ce46330cb67cd4648c01f0b2393d7e729b0d67891820593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c071594bae6e759f13fbc246c11fbd8d97d68911241000000000023a79195fb4e1ffc000cf99e000000762e689e7bfecbe16bfd0e6138eea642ee0513c5762e689e7bfecbe16bfd0e6138eea642ee0513c5c69a0bda7daaae481be8def95e5f347a1d00a4b430a7afe7674de986aff5e2e0a173be8c29abed8b5d6f878389ea18be0d43c62ad1ba66a59e9e8d8453aa0ed1a69697675800019b9cdbfe3568cc0b37f136b00a634c75653f05e301fb8f3001fb05a388251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f00012088251bd4b124efeb87537deabeec54f6c8f575f4df81f10cf5e8eea073092b6f20593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c03090aa69c8d1a95839e017d1b2b53d3499fa0a9aa000000000034211c2ffb4e1ffc000cf99e0000000799f054652c1cef10d2994fb83d012d559a1faf0799f054652c1cef10d2994fb83d012d559a1fafc69a0bda7daaae481be8def95e5f347a1d00a4b430af9cd8567923fea3f6e6bbf5e1b3a76bf772f6a3c72b41be15c257af50533b32cc3923cebdeda9fce7a6bc9659123d530001711fd9548ae19b2e91c7a9b4067000467ccdd2b501fb8f3001fb05a38917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f2340001208917bb546318f3410d1a7901c7b846a73446311b5164b45a03f0e613f208f23420593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c21fe8d862d5042691749e866af337e50e599e64fdc0000000000340d8492fb4e1ffc000cf99e00000018d9316618b1f55977af250cc5d8783617084aac18d9316618b1f55977af250cc5d8783617084aacc69a0bda7daaae481be8def95e5f347a1d00a4b43087d25769002af2a4f050127c73fff03a24935e48f34fecaacd69410787d0e6384b345c78e81b1cb397b43dcd635568b600015bdbf34a0dad860c6ec71523ae39373325225cc101fb8f3001fb05a38b8d1193afd22e538ce0c9fb50fee155d0f6176ca68e65da684c5dce2d1e08150001208b8d1193afd22e538ce0c9fb50fee155d0f6176ca68e65da684c5dce2d1e081520593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c0b3fe432c394e3e96e8804a8e059b1887afc913012000000000034229032fb4e1ffc000cf99e000000b802f02882ed36279ba95674e7e190e86bd6458db802f02882ed36279ba95674e7e190e86bd6458dc69a0bda7daaae481be8def95e5f347a1d00a4b430a1749fecb407bb0e0ab9d6df65ea068dba5dc03e14dcb36abe5cb2b5c6e424683f715ff09ce290d035dbb31add0c01800001a0a0e17bfe82a484fefe348b7569a6d77d29d2c201fb8f3001fb05a38de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc40001208de8b12952f7058d827bd04cdff1c2175d87bbf89f28b52452a637bc979addc420593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c1dd08fdbbe79813bc43a306740d2182674141d76de0000000000342b56e7fb4e1ffc000cf99e000000300904176cc6023370b2462964c12c5979b9f411300904176cc6023370b2462964c12c5979b9f411c69a0bda7daaae481be8def95e5f347a1d00a4b4309502bb884b3437d65c0e025e49fb00ff6ea9f55d5bcdc36330b46c8bd18be9126b7a6d7f35f558ef8040f2c2284500a50001337b7fb5d2c531825c3e0123ac3354018085b30201fb8f3001fb05a38e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c00001208e11eb784883d3dc9d0d74a74633f067dc61c408dfdee49b8f93bb161f2916c020593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c20f53e3ff160dab7ec3cc2a6b0afa6dd8d36e38794000000000034599a30fb4e1ffc000cf99e0000000063eb51fcfd121e6c3eae23b90b26cd1100217b0063eb51fcfd121e6c3eae23b90b26cd1100217bc69a0bda7daaae481be8def95e5f347a1d00a4b4308160877a911d8bb7d1e75e2320e98cc3233c1f6972cb642424bfcec7c182c56d2c0ebb59e45f788f4d5dbfa2ebff3e3a00016d57707c196e06487d326094c964f258f5b77c3501fb8f3001fb05a38eca4bcbb3a124ab283afd42dad3bdb2077b3809659788a0f1daffce5b9f001f0001208eca4bcbb3a124ab283afd42dad3bdb2077b3809659788a0f1daffce5b9f001f20593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c0e55b79902ab8dc5c126e61ebd5bdc2ec98d80836600000000003644ebc9fb4e1ffc000cf99e000000983259ad7ed51267fb83a8e41bbaa5ab55c632e1983259ad7ed51267fb83a8e41bbaa5ab55c632e1c69a0bda7daaae481be8def95e5f347a1d00a4b430b942e2e50c5cf9d9fe81119cc5379057c05fe15134f85847356b5d1f6a21f29f4a53f61f03338d056edc15a8c63fbbe80001c075993a8336f93a13bb7bbb7e0e89928be4aafb01fb8f3001fb05a391bbce94c34ebde0d099c0a2cb7635c0c31425ebabcec644f4f1a0854bfa605d00012091bbce94c34ebde0d099c0a2cb7635c0c31425ebabcec644f4f1a0854bfa605d20593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c1eea45a388d248dcd7433c8c8113d5d0966069413500000000003428db29fb4e1ffc000cf99e000000cf83406065cb65ce74100f3c35a0324bfc92dcb0cf83406065cb65ce74100f3c35a0324bfc92dcb0c69a0bda7daaae481be8def95e5f347a1d00a4b43081ad0f9be5a88ae62ff54fe938dfceea71be03bd4c6a7aebf75896e8d495d310acc4146aa4820bc0e5f5b06579dedea5000102aa69f8ef6666e7cad6d9323755a0ef3c1b6bd901fb8f3001fb05a3957acb5bb59e253059da86924b5bbd94c1daf5b0fcd313bdb78e43bdc7cad000000120957acb5bb59e253059da86924b5bbd94c1daf5b0fcd313bdb78e43bdc7cad00020176deee4e53c297f44029a7db294451139901bb49f33a2a0ac8bd1b9e744fee201c406356d37513ea70f93868797061aec981337a700000000002d87b4aafb4e1ffc00102b8501fc0010594501fc0010598300cf0ea50da406da09dd78689abaa7c44aad428e3f37f1afe5852c1aece552ed1be61dc898a8db05f06e0e8a6ca912d408dc8369365e947a41d9d0a9d83098fc5928355798aa9237b107935ba606bd749e16f2922d8c4eb6b6c2cbbb4210f3bad09fe7d199aa3884fae3fce0120d0001a5bf8ff04bf1be7f1d98cb952f1b49f8d162d8a301fb682001fb01bb9712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df540001209712e85d660fa2f761f980ef5812c225f33f336f285728803dcd421937d3df5420593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c1277e135a613d9797db4d7a9d2e51bfe8599d3650200000000002352c5c5fb4e1ffc000cf99e00000020c7f1991e06d09b1f067b049fe6d0af0a20f79c20c7f1991e06d09b1f067b049fe6d0af0a20f79cc69a0bda7daaae481be8def95e5f347a1d00a4b430a8dbccb130522909dc710a65728006732c18441757f12a338cf4a6d8cbd5baf1a484537a6a0542f51bb686e6e546f1a00001ed1131823bcea23ac78af8c01e4d24683d6ecf8801fb8f3001fb05a398ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba09209600012098ef58c338a0a68e4f2f1d1ee9eb05fcafbb9177d192dac0f698d3d9ba09209620593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c178b5541d75eaaa98f8ad22355a122c55741f339f200000000002ce8c406fb4e1ffc000cf99e000000caf6f1b9916245ce300a63fa2254ada25e0423d6caf6f1b9916245ce300a63fa2254ada25e0423d6c69a0bda7daaae481be8def95e5f347a1d00a4b430b6175b59aba8cc0477d4fff78bd90294f31ebd385c39bc254c7995a5dd3ccb8dc1d8869e247bf63bef8ec79317f479a90001d6ece912cbf02627a4efc3dd37e6833cf367155101fb8f3001fb05a39cb04f271ba050132c00cc5838fb69e77bc55b5689f9d2d850dc528935f8145c0001209cb04f271ba050132c00cc5838fb69e77bc55b5689f9d2d850dc528935f8145c20593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c1bbb948d5d33120f51f2ca02c77a0b69761b719f07000000000022d63044fb4e1ffc000cf99e000000c54ac69739bf492d4328f1bf0d49581ce0b10d41c54ac69739bf492d4328f1bf0d49581ce0b10d417ea623bdf8c5607f0390c85586d83d473fa6a1c630b6ee48c7a71a9d8e0813e68ca09846245fa155285f24a62b0ce9cb0102b1994ec58af8ba2a01c09363bdcc395d41f3df000162e960a3f6b650feed98a266b3ccdf6e363562cf01fb8f3001fb05a3b3b5748571b60fe9ad112715d6a51725d6e5a52a9c3af5fd36a1724cf50d862f000120b3b5748571b60fe9ad112715d6a51725d6e5a52a9c3af5fd36a1724cf50d862f20593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c1689fa69f20934cc3ede9dff4589af59c19a14a3f70000000000342b0d5cfb4e1ffc000cf99e000000d57dc73bca0753cbd47bb33f68362ac13e6daeadd57dc73bca0753cbd47bb33f68362ac13e6daeadc69a0bda7daaae481be8def95e5f347a1d00a4b430816ab3f50007333bcb40445130cd0e82139f8c68b592001cd686efc15e303206491fada6cf90af8f24a28b81a9b59ccf000141b308f737ca9e39f67b553158903198a88c516e01fb8f3001fb05a3ba8ce1dc72857b4168e33272571df7fbaf84c316dfe48217addcf6595e254216000120ba8ce1dc72857b4168e33272571df7fbaf84c316dfe48217addcf6595e25421620593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c1488164ceb25e5c05e3192511d2be4a5ac103cc5f70000000000342aca80fb4e1ffc000cf99e000000ca94dd35b74cb251457e475dd7507055eaf1b4e1ca94dd35b74cb251457e475dd7507055eaf1b4e1c69a0bda7daaae481be8def95e5f347a1d00a4b430acec7bbead86221590f132810b8262cf98c91b338927907b86bf48baa54dd1912bfc1f6fccd069052cc8c79eb9e8ed2c000162e0104ce0aafc1f06bde37c73702fe84b307f0501fb8f3001fb05a3bbfd0ac1977011267a7032641ef5487fe15a4de798faa485b156fb3b7eb0acb8000120bbfd0ac1977011267a7032641ef5487fe15a4de798faa485b156fb3b7eb0acb820593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c060d8235767cb55972a30d653eb9dd10f51b3c46ec0000000000235231c4fb4e1ffc000cf99e000000f9b93e179a0c22afd92523427341b5e0b2c2a102f9b93e179a0c22afd92523427341b5e0b2c2a102c69a0bda7daaae481be8def95e5f347a1d00a4b43095c89af86eeacfe403684306c98173c2a59198047a778787887d34ad6b0c9b787d689a7c3cd9e9dd5d103cba70f3855f0001dbbebbc52a5bae21b818e0487311041c91b2683b01fb8f3001fb05a3c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba8000120c11c1168dcf9479475cb1355855e30ea75c0cdda8a8f9ea80591568dd1c33ba820593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c040cb28bcdc1d1a970b6255a04138f84c0ebfa52b6000000000036d5cc55fb4e1ffc000cf99e000000ec040cc1866da3e55c8ae6c0f739cafabe3f5cbaec040cc1866da3e55c8ae6c0f739cafabe3f5cbac69a0bda7daaae481be8def95e5f347a1d00a4b430aa910b9552857a7712d54b468dfcbb7d9e27f26a49e06fb1f0fb00dd0f5a1bf926863c25ad03fd49c56b62065ecd06e70001fdae7cdf38811659ce9481975b326a5d07236bc501fb8f3001fb05a3d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f89000120d9b090cfc19caf2e27d512e69c43812a274bdf29c081d0ade4fd272ad56a5f8920593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c0d47eb59e9a49b3794acf272f1bfff17f228291daf00000000002cf06266fb4e1ffc000cf99e0000007334f54da07d3b9e177f6e57c64f97bb0f982caf7334f54da07d3b9e177f6e57c64f97bb0f982cafc69a0bda7daaae481be8def95e5f347a1d00a4b43086108e551691da2642f37b68bcfbc5bbe9984ca51aca15ee24b6fa9b8690ed62c6ed722d091e04ef617cfc99341fd35800017034f0d3853c5351fb8e0ffd3c1daf12c51c2d8901fb8f3001fb05a3ee733db5519c987496eb3b871d5fa543ddb19db3e848f2fbb0af01585fc76af5000120ee733db5519c987496eb3b871d5fa543ddb19db3e848f2fbb0af01585fc76af520f56ac75f5801afb0fbf248e8b39db1dd43a55f1d873beb9674989c51b53d73ee0191be18196047ed60fca300e6fdca0b7bea81beac00000000000238d45dfb4e1ffc000de7c001fc000de9f801fc000f13a3000bf9547a7b4d12def0019da71e989821a60d9c915b44dc4b3f0ed26a8243afa46bada49c18da6b2a21eca01872dbfce4bf20886a004f6caaa69c1ff730b695a4757d60c472f67a7807def81ab7a52dec3bc64aa1c4188d02a4768ac3a862b404f0656ed395f1eb6470dca7bca400018355913e3791438c18b5ac50fe03784df789424101fb8f3001fb05a3f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba7863990381000120f6496d3c0ac1ad94ff5e3aab2edcabc1c8ba3fbfea0ef3026e90ba786399038120593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c050d1611e03249023d89c1ac086036cbea392768cc0000000000340dfab6fb4e1ffc000cf99e0000006cc3fca46aae1c44ea1bab81d506e9f0a3ae1d056cc3fca46aae1c44ea1bab81d506e9f0a3ae1d05c69a0bda7daaae481be8def95e5f347a1d00a4b4308f2df81ba65db70eaab625c5fe46f0f5e52a45b25c761686db23b4f18e547cb0d161912dd187302eb6f7c4a9a666a3230001fe2d4798df3e9b41a6823bc0b3f020478e87925d01fb8f3001fb05a3fc196382366234f4645215261ca7e62f53499345ec1def69289e47c0c388dc6d000120fc196382366234f4645215261ca7e62f53499345ec1def69289e47c0c388dc6d20151b4f6fbc7351efba1dd1c36c733978a184561af7497b25b4a8a3e0afec0e7f016608134feb91cb878b26b977f1d7983a2f14452a4248000000258b0cf7fb4e1ffc000df5420001fc000df56b00c346a8ffbdcc80462cb69a6f524388a5f496fc6ec9a9263ee8c8c606c449959c48978ba70d4a097bfc86e599d56c282377dd9510ee62c55fefa553b1308d0651a04f9c243872f613901a1eeb2fa86f3e9a65168bc39941790783d9189a9a7876cedb0c6d7ff7d49fbc88a7191100011348d8f97063cf6ff602c14bf59b5ff501c8bbf401fb8f3001fb05a3ff261d2c1c76907a2ad8aeb6c5611796f03b5cbd88ae92452a4727e13f4f4ac9000120ff261d2c1c76907a2ad8aeb6c5611796f03b5cbd88ae92452a4727e13f4f4ac920593aaec65459ca9a97bd34b2657c8201ae83952d062715ba3af0d4255e54e86c0c456ce31778e3778c88a87ac36a1a8bd4aa5bdbe9000000000036bb0ee8fb4e1ffc000cf99e000000b14f661da8227a41acef9f8096df2afd2a192aafb14f661da8227a41acef9f8096df2afd2a192aafc69a0bda7daaae481be8def95e5f347a1d00a4b430967796952922dcc5208a3848ab85a787e4592df2d8ce36a29369b0b3a9576073651075039e1377873aa8c67514ad2726000167e05b1b52c7c896adf20035036fe1d30dcefc9c01fb8f3001fb05a301fb037f01fb03e8fb6978fb0190140afb07d0fb3a98fc000493e0fb3c8cfc000493e0fb0dac64fb012cfb1388fb177064fb2710fb2328fb3a98fb2328fb2710fb271032fb01f40a28321e643cfc000186a0fc000186a0fc000186a0fc000186a0fc000186a0fc000186a0fc000186a0fd00000004a817c800fd0000005d21dba000fc00989680" +}); diff --git a/packages/rs-drive-abci/tests/strategy_tests/execution.rs b/packages/rs-drive-abci/tests/strategy_tests/execution.rs index 133b281446..777dc361a2 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/execution.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/execution.rs @@ -829,8 +829,15 @@ pub(crate) fn start_chain_for_strategy( .get::(¤t_validator_quorum_hash) .expect("expected a quorum to be found"); + let platform_state = abci_application.platform.state.load(); + let protocol_version = platform_state + .current_platform_version() + .unwrap() + .protocol_version; + drop(platform_state); + // init chain - let mut init_chain_request = static_init_chain_request(&config); + let mut init_chain_request = static_init_chain_request(&config, protocol_version); init_chain_request.initial_core_height = config.abci.genesis_core_height; init_chain_request.validator_set = Some(ValidatorSetUpdate { @@ -1209,5 +1216,6 @@ pub(crate) fn continue_chain_for_strategy( validator_set_updates, state_transition_results_per_block, instant_lock_quorums, + signer, } } diff --git a/packages/rs-drive-abci/tests/strategy_tests/main.rs b/packages/rs-drive-abci/tests/strategy_tests/main.rs index f42f791ebb..2312241cc6 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/main.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/main.rs @@ -30,6 +30,7 @@ mod strategy; mod upgrade_fork_tests; mod verify_state_transitions; mod voting_tests; +mod withdrawal_tests; pub type BlockHeight = u64; @@ -43,15 +44,13 @@ fn asset_unlock_index(tx: &Transaction) -> u64 { #[cfg(test)] mod tests { use super::*; - use crate::execution::{continue_chain_for_strategy, run_chain_for_strategy, GENESIS_TIME_MS}; + use crate::execution::{continue_chain_for_strategy, run_chain_for_strategy}; use crate::query::QueryStrategy; use crate::strategy::{FailureStrategy, MasternodeListChangesStrategy}; use dashcore_rpc::dashcore::hashes::Hash; use dashcore_rpc::dashcore::BlockHash; - use dashcore_rpc::dashcore_rpc_json::AssetUnlockStatus; - use dashcore_rpc::json::{AssetUnlockStatusResult, QuorumType}; + use dashcore_rpc::json::QuorumType; use dpp::block::extended_block_info::v0::ExtendedBlockInfoV0Getters; - use std::sync::{Arc, Mutex}; use strategy_tests::operations::DocumentAction::{ DocumentActionReplaceRandom, DocumentActionTransferRandom, }; @@ -61,21 +60,15 @@ mod tests { use strategy_tests::{IdentityInsertInfo, StartIdentities}; use crate::strategy::CoreHeightIncrease::RandomCoreHeightIncrease; - use dpp::dashcore::bls_sig_utils::BLSSignature; use dpp::dashcore::ChainLock; - use dpp::dashcore::Txid; use dpp::data_contract::accessors::v0::{DataContractV0Getters, DataContractV0Setters}; use dpp::data_contract::document_type::random_document::{ DocumentFieldFillSize, DocumentFieldFillType, }; use dpp::identity::accessors::IdentityGettersV0; use dpp::identity::identity_public_key::accessors::v0::IdentityPublicKeyGettersV0; - use dpp::system_data_contracts::withdrawals_contract; use dpp::tests::json_document::json_document_to_created_contract; use dpp::util::hash::hash_to_hex_string; - use dpp::version::PlatformVersion; - use drive::config::DEFAULT_QUERY_LIMIT; - use drive::drive::identity::withdrawals::WithdrawalTransactionIndex; use drive_abci::config::{ ChainLockConfig, ExecutionConfig, InstantLockConfig, PlatformTestConfig, ValidatorSetConfig, }; @@ -87,11 +80,14 @@ mod tests { use rand::SeedableRng; use tenderdash_abci::proto::abci::{RequestInfo, ResponseInfo}; + use dpp::dash_to_duffs; use dpp::data_contract::document_type::v0::random_document_type::{ FieldMinMaxBounds, FieldTypeWeights, RandomDocumentTypeParameters, }; use dpp::identity::{Identity, KeyType, Purpose, SecurityLevel}; use dpp::state_transition::StateTransition; + use platform_version::version::v1::PROTOCOL_VERSION_1; + use platform_version::version::PlatformVersion; use simple_signer::signer::SimpleSigner; use strategy_tests::transitions::create_state_transitions_for_identities; use tenderdash_abci::Application; @@ -1163,6 +1159,7 @@ mod tests { let mut platform = TestPlatformBuilder::new() .with_config(config.clone()) + .with_initial_protocol_version(PROTOCOL_VERSION_1) .build_with_mock_rpc(); let outcome = run_chain_for_strategy(&mut platform, 150, strategy, config, 15, &mut None); @@ -1253,6 +1250,16 @@ mod tests { let outcome = run_chain_for_strategy(&mut platform, 1, strategy, config, 15, &mut None); + for tx_results_per_block in outcome.state_transition_results_per_block.values() { + for (state_transition, result) in tx_results_per_block { + assert_eq!( + result.code, 0, + "state transition got code {} : {:?}", + result.code, state_transition + ); + } + } + outcome .abci_app .platform @@ -1879,6 +1886,7 @@ mod tests { let block_count = 120; let mut platform = TestPlatformBuilder::new() .with_config(config.clone()) + .with_initial_protocol_version(PROTOCOL_VERSION_1) .build_with_mock_rpc(); let outcome = @@ -2009,6 +2017,7 @@ mod tests { let block_count = 120; let mut platform = TestPlatformBuilder::new() .with_config(config.clone()) + .with_initial_protocol_version(PROTOCOL_VERSION_1) .build_with_mock_rpc(); let outcome = @@ -2331,6 +2340,7 @@ mod tests { }, start_keys: 5, extra_keys: Default::default(), + start_balance_range: dash_to_duffs!(1)..=dash_to_duffs!(1), }, identity_contract_nonce_gaps: None, @@ -2464,6 +2474,7 @@ mod tests { }, start_keys: 5, extra_keys: Default::default(), + start_balance_range: dash_to_duffs!(1)..=dash_to_duffs!(1), }, identity_contract_nonce_gaps: None, @@ -2587,6 +2598,7 @@ mod tests { let start_identities = create_state_transitions_for_identities( vec![identity1, identity2], + &(dash_to_duffs!(1)..=dash_to_duffs!(1)), &simple_signer, &mut rng, platform_version, @@ -2756,6 +2768,7 @@ mod tests { }, start_keys: 5, extra_keys: Default::default(), + start_balance_range: dash_to_duffs!(1)..=dash_to_duffs!(1), }, identity_contract_nonce_gaps: None, @@ -2921,6 +2934,7 @@ mod tests { }, start_keys: 5, extra_keys: Default::default(), + start_balance_range: dash_to_duffs!(1)..=dash_to_duffs!(1), }, identity_contract_nonce_gaps: None, @@ -2982,7 +2996,7 @@ mod tests { strategy: Strategy { start_contracts: vec![], operations: vec![Operation { - op_type: OperationType::IdentityTopUp, + op_type: OperationType::IdentityTopUp(dash_to_duffs!(1)..=dash_to_duffs!(1)), frequency: Frequency { times_per_block_range: 1..3, chance_per_block: None, @@ -3224,609 +3238,6 @@ mod tests { })); } - #[test] - #[ignore] - fn run_chain_top_up_and_withdraw_from_identities() { - let platform_version = PlatformVersion::latest(); - let strategy = NetworkStrategy { - strategy: Strategy { - start_contracts: vec![], - operations: vec![ - Operation { - op_type: OperationType::IdentityTopUp, - frequency: Frequency { - times_per_block_range: 1..4, - chance_per_block: None, - }, - }, - Operation { - op_type: OperationType::IdentityWithdrawal, - frequency: Frequency { - times_per_block_range: 1..4, - chance_per_block: None, - }, - }, - ], - start_identities: StartIdentities::default(), - identity_inserts: IdentityInsertInfo { - frequency: Frequency { - times_per_block_range: 1..2, - chance_per_block: None, - }, - start_keys: 3, - extra_keys: [( - Purpose::TRANSFER, - [(SecurityLevel::CRITICAL, vec![KeyType::ECDSA_SECP256K1])].into(), - )] - .into(), - }, - identity_contract_nonce_gaps: None, - signer: None, - }, - total_hpmns: 100, - extra_normal_mns: 0, - validator_quorum_count: 24, - chain_lock_quorum_count: 24, - upgrading_info: None, - - proposer_strategy: Default::default(), - rotate_quorums: false, - failure_testing: None, - query_testing: None, - // because we can add an identity and withdraw from it in the same block - // the result would be different from what would be expected - verify_state_transition_results: false, - ..Default::default() - }; - let config = PlatformConfig { - validator_set: ValidatorSetConfig::default_100_67(), - chain_lock: ChainLockConfig::default_100_67(), - instant_lock: InstantLockConfig::default_100_67(), - execution: ExecutionConfig { - verify_sum_trees: true, - - ..Default::default() - }, - block_spacing_ms: 3000, - testing_configs: PlatformTestConfig::default_minimal_verifications(), - ..Default::default() - }; - - let mut platform = TestPlatformBuilder::new() - .with_config(config.clone()) - .build_with_mock_rpc(); - - platform - .core_rpc - .expect_send_raw_transaction() - .returning(move |_| Ok(Txid::all_zeros())); - - struct CoreState { - asset_unlock_statuses: BTreeMap, - chain_lock: ChainLock, - } - - let mut chain_locked_height = 1; - - // Have to go with a complicated shared object for the core state because we need to change - // rpc response along the way but we can't mutate `platform.core_rpc` later - // because platform reference is moved into the AbciApplication. - let shared_core_state = Arc::new(Mutex::new(CoreState { - asset_unlock_statuses: BTreeMap::new(), - chain_lock: ChainLock { - block_height: chain_locked_height, - block_hash: BlockHash::from_byte_array([1; 32]), - signature: BLSSignature::from([2; 96]), - }, - })); - - // Set up Core RPC responses - { - let core_state = shared_core_state.clone(); - - platform - .core_rpc - .expect_get_asset_unlock_statuses() - .returning(move |indices, _| { - Ok(indices - .iter() - .map(|index| { - core_state - .lock() - .unwrap() - .asset_unlock_statuses - .get(index) - .cloned() - .unwrap() - }) - .collect()) - }); - - let core_state = shared_core_state.clone(); - platform - .core_rpc - .expect_get_best_chain_lock() - .returning(move || Ok(core_state.lock().unwrap().chain_lock.clone())); - } - - // Run first two blocks: - // - Block 1: creates identity - // - Block 2: tops up identity and initiates withdrawals - let ( - ChainExecutionOutcome { - abci_app, - proposers, - validator_quorums: quorums, - current_validator_quorum_hash: current_quorum_hash, - current_proposer_versions, - end_time_ms, - identity_nonce_counter, - identity_contract_nonce_counter, - instant_lock_quorums, - .. - }, - last_block_pooled_withdrawals_amount, - ) = { - let outcome = run_chain_for_strategy( - &mut platform, - 2, - strategy.clone(), - config.clone(), - 1, - &mut None, - ); - - // Withdrawal transactions are not populated to block execution context yet - assert_eq!(outcome.withdrawals.len(), 0); - - // Withdrawal documents with pooled status should exist. - let withdrawal_documents_pooled = outcome - .abci_app - .platform - .drive - .fetch_oldest_withdrawal_documents_by_status( - withdrawals_contract::WithdrawalStatus::POOLED.into(), - DEFAULT_QUERY_LIMIT, - None, - platform_version, - ) - .unwrap(); - assert!(!withdrawal_documents_pooled.is_empty()); - let pooled_withdrawals = withdrawal_documents_pooled.len(); - - (outcome, pooled_withdrawals) - }; - - // Run block 3 - // Should broadcast previously pooled withdrawals to core - let ChainExecutionOutcome { - abci_app, - proposers, - validator_quorums: quorums, - current_validator_quorum_hash: current_quorum_hash, - current_proposer_versions, - end_time_ms, - withdrawals: last_block_withdrawals, - identity_nonce_counter, - identity_contract_nonce_counter, - instant_lock_quorums, - .. - } = { - let outcome = continue_chain_for_strategy( - abci_app, - ChainExecutionParameters { - block_start: 3, - core_height_start: 1, - block_count: 1, - proposers, - validator_quorums: quorums, - current_validator_quorum_hash: current_quorum_hash, - current_proposer_versions: Some(current_proposer_versions), - current_identity_nonce_counter: identity_nonce_counter, - current_identity_contract_nonce_counter: identity_contract_nonce_counter, - current_votes: BTreeMap::default(), - start_time_ms: GENESIS_TIME_MS, - current_time_ms: end_time_ms, - instant_lock_quorums, - current_identities: Vec::new(), - }, - strategy.clone(), - config.clone(), - StrategyRandomness::SeedEntropy(2), - ); - - // Withdrawal documents with pooled status should exist. - let withdrawal_documents_broadcasted = outcome - .abci_app - .platform - .drive - .fetch_oldest_withdrawal_documents_by_status( - withdrawals_contract::WithdrawalStatus::BROADCASTED.into(), - DEFAULT_QUERY_LIMIT, - None, - platform_version, - ) - .unwrap(); - - // In this block all previously pooled withdrawals should be broadcasted - assert_eq!( - outcome.withdrawals.len(), - last_block_pooled_withdrawals_amount - ); - assert_eq!( - withdrawal_documents_broadcasted.len(), - last_block_pooled_withdrawals_amount - ); - - outcome - }; - - // Update core state before running next block. - // Asset unlocks broadcasted in the last block should have Unknown status - { - let mut core_state = shared_core_state.lock().unwrap(); - last_block_withdrawals.iter().for_each(|tx| { - let index = asset_unlock_index(tx); - - core_state.asset_unlock_statuses.insert( - index, - AssetUnlockStatusResult { - index, - status: AssetUnlockStatus::Unknown, - }, - ); - }); - } - - // Run block 4 - // Should change pooled status to broadcasted - let last_block_broadcasted_withdrawals_amount = last_block_withdrawals.len(); - let ( - ChainExecutionOutcome { - abci_app, - proposers, - validator_quorums: quorums, - current_validator_quorum_hash: current_quorum_hash, - current_proposer_versions, - end_time_ms, - withdrawals: last_block_withdrawals, - identity_nonce_counter, - identity_contract_nonce_counter, - instant_lock_quorums, - .. - }, - last_block_broadcased_withdrawals_amount, - ) = { - let outcome = continue_chain_for_strategy( - abci_app, - ChainExecutionParameters { - block_start: 4, - core_height_start: 1, - block_count: 1, - proposers, - validator_quorums: quorums, - current_validator_quorum_hash: current_quorum_hash, - current_proposer_versions: Some(current_proposer_versions), - current_identity_nonce_counter: identity_nonce_counter, - current_identity_contract_nonce_counter: identity_contract_nonce_counter, - current_votes: BTreeMap::default(), - start_time_ms: GENESIS_TIME_MS, - current_time_ms: end_time_ms + 1000, - instant_lock_quorums, - current_identities: Vec::new(), - }, - strategy.clone(), - config.clone(), - StrategyRandomness::SeedEntropy(3), - ); - - let withdrawal_documents_pooled = outcome - .abci_app - .platform - .drive - .fetch_oldest_withdrawal_documents_by_status( - withdrawals_contract::WithdrawalStatus::POOLED.into(), - DEFAULT_QUERY_LIMIT, - None, - platform_version, - ) - .unwrap(); - - let withdrawal_documents_broadcasted = outcome - .abci_app - .platform - .drive - .fetch_oldest_withdrawal_documents_by_status( - withdrawals_contract::WithdrawalStatus::BROADCASTED.into(), - DEFAULT_QUERY_LIMIT, - None, - platform_version, - ) - .unwrap(); - - // In this block we should have new withdrawals pooled - assert!(!withdrawal_documents_pooled.is_empty()); - - // And extra withdrawals broadcasted - let withdrawals_broadcasted_expected = - last_block_broadcasted_withdrawals_amount + outcome.withdrawals.len(); - assert_eq!( - withdrawal_documents_broadcasted.len(), - withdrawals_broadcasted_expected - ); - - (outcome, withdrawal_documents_broadcasted.len()) - }; - - // Update core state for newly broadcasted transactions - { - let mut core_state = shared_core_state.lock().unwrap(); - - // First, set all previously broadcasted transactions to Chainlocked - core_state - .asset_unlock_statuses - .iter_mut() - .for_each(|(index, status_result)| { - // Do not settle yet transactions that were broadcasted in the last block - status_result.index = *index; - status_result.status = AssetUnlockStatus::Chainlocked; - }); - - // Then increase chainlocked height, so that withdrawals for chainlocked transactions - // could be completed in the next block - // TODO: do we need this var? - chain_locked_height += 1; - core_state.chain_lock.block_height = chain_locked_height; - - // Then set all newly broadcasted transactions to Unknown - last_block_withdrawals.iter().for_each(|tx| { - let index = asset_unlock_index(tx); - - core_state.asset_unlock_statuses.insert( - index, - AssetUnlockStatusResult { - index, - status: AssetUnlockStatus::Unknown, - }, - ); - }); - - drop(core_state); - } - - // Run block 5 - // Previously broadcasted transactions should be settled after block 5, - // and their corresponding statuses should be changed to COMPLETED - let ( - ChainExecutionOutcome { - abci_app, - proposers, - validator_quorums: quorums, - current_validator_quorum_hash: current_quorum_hash, - current_proposer_versions, - end_time_ms, - withdrawals: last_block_withdrawals, - identity_nonce_counter, - identity_contract_nonce_counter, - instant_lock_quorums, - .. - }, - last_block_withdrawals_completed_amount, - ) = { - let outcome = continue_chain_for_strategy( - abci_app, - ChainExecutionParameters { - block_start: 5, - core_height_start: 1, - block_count: 1, - proposers, - validator_quorums: quorums, - current_validator_quorum_hash: current_quorum_hash, - current_proposer_versions: Some(current_proposer_versions), - current_identity_nonce_counter: identity_nonce_counter, - current_identity_contract_nonce_counter: identity_contract_nonce_counter, - current_votes: BTreeMap::default(), - start_time_ms: GENESIS_TIME_MS, - current_time_ms: end_time_ms + 1000, - instant_lock_quorums, - current_identities: Vec::new(), - }, - strategy.clone(), - config.clone(), - StrategyRandomness::SeedEntropy(4), - ); - - let withdrawal_documents_pooled = outcome - .abci_app - .platform - .drive - .fetch_oldest_withdrawal_documents_by_status( - withdrawals_contract::WithdrawalStatus::POOLED.into(), - DEFAULT_QUERY_LIMIT, - None, - platform_version, - ) - .unwrap(); - - let withdrawal_documents_broadcasted = outcome - .abci_app - .platform - .drive - .fetch_oldest_withdrawal_documents_by_status( - withdrawals_contract::WithdrawalStatus::BROADCASTED.into(), - DEFAULT_QUERY_LIMIT, - None, - platform_version, - ) - .unwrap(); - - let withdrawal_documents_completed = outcome - .abci_app - .platform - .drive - .fetch_oldest_withdrawal_documents_by_status( - withdrawals_contract::WithdrawalStatus::COMPLETE.into(), - DEFAULT_QUERY_LIMIT, - None, - platform_version, - ) - .unwrap(); - - // In this block we should have new withdrawals pooled - assert!(!withdrawal_documents_pooled.is_empty()); - - // And some withdrawals completed - let withdrawals_completed_expected = - // Withdrawals issued on {previous_block - 1} considered completed - last_block_broadcased_withdrawals_amount - last_block_withdrawals.len(); - assert_eq!( - withdrawal_documents_completed.len(), - withdrawals_completed_expected - ); - - // And extra withdrawals broadcasted - let withdrawals_broadcasted_expected = - // Withdrawals issued on previous block + withdrawals from this block are still in broadcasted state - last_block_withdrawals.len() + outcome.withdrawals.len(); - - assert_eq!( - withdrawal_documents_broadcasted.len(), - withdrawals_broadcasted_expected - ); - - (outcome, withdrawal_documents_completed.len()) - }; - - // Update state of the core before proceeding to the next block - { - // Simulate transactions being added to the core mempool - let mut core_state = shared_core_state.lock().unwrap(); - - let number_of_blocks_before_expiration: u32 = 48; - chain_locked_height += number_of_blocks_before_expiration; - - core_state.chain_lock.block_height = chain_locked_height; - - last_block_withdrawals.iter().for_each(|tx| { - let index = asset_unlock_index(tx); - - core_state.asset_unlock_statuses.insert( - index, - AssetUnlockStatusResult { - index, - status: AssetUnlockStatus::Unknown, - }, - ); - }); - } - - // Run block 6. - // Tests withdrawal expiration - let ChainExecutionOutcome { .. } = { - let outcome = continue_chain_for_strategy( - abci_app, - ChainExecutionParameters { - block_start: 6, - core_height_start: 1, - block_count: 1, - proposers, - validator_quorums: quorums, - current_validator_quorum_hash: current_quorum_hash, - current_proposer_versions: Some(current_proposer_versions), - current_identity_nonce_counter: identity_nonce_counter, - current_identity_contract_nonce_counter: identity_contract_nonce_counter, - current_votes: BTreeMap::default(), - start_time_ms: GENESIS_TIME_MS, - current_time_ms: end_time_ms + 1000, - instant_lock_quorums, - current_identities: Vec::new(), - }, - strategy.clone(), - config.clone(), - StrategyRandomness::SeedEntropy(5), - ); - - let withdrawal_documents_pooled = outcome - .abci_app - .platform - .drive - .fetch_oldest_withdrawal_documents_by_status( - withdrawals_contract::WithdrawalStatus::POOLED.into(), - DEFAULT_QUERY_LIMIT, - None, - platform_version, - ) - .unwrap(); - - let withdrawal_documents_broadcasted = outcome - .abci_app - .platform - .drive - .fetch_oldest_withdrawal_documents_by_status( - withdrawals_contract::WithdrawalStatus::BROADCASTED.into(), - DEFAULT_QUERY_LIMIT, - None, - platform_version, - ) - .unwrap(); - - let withdrawal_documents_completed = outcome - .abci_app - .platform - .drive - .fetch_oldest_withdrawal_documents_by_status( - withdrawals_contract::WithdrawalStatus::COMPLETE.into(), - DEFAULT_QUERY_LIMIT, - None, - platform_version, - ) - .unwrap(); - - let withdrawal_documents_expired = outcome - .abci_app - .platform - .drive - .fetch_oldest_withdrawal_documents_by_status( - withdrawals_contract::WithdrawalStatus::EXPIRED.into(), - DEFAULT_QUERY_LIMIT, - None, - platform_version, - ) - .unwrap(); - - // In this block we should have new withdrawals pooled - assert!(!withdrawal_documents_pooled.is_empty()); - - // Amount of completed withdrawals stays the same as in the last block - assert_eq!( - withdrawal_documents_completed.len(), - last_block_withdrawals_completed_amount - ); - - // And some withdrawals got expired - let withdrawals_expired_expected = - // Withdrawals issued on {previous_block - 1}, but not chainlocked yet, considered expired - last_block_broadcased_withdrawals_amount - last_block_withdrawals.len(); - - assert_eq!( - withdrawal_documents_expired.len(), - withdrawals_expired_expected - ); - - // And extra withdrawals broadcasted - let withdrawals_broadcasted_expected = - // Withdrawals issued on previous block + withdrawals from this block are still in broadcasted state - last_block_withdrawals.len() + outcome.withdrawals.len(); - - assert_eq!( - withdrawal_documents_broadcasted.len(), - withdrawals_broadcasted_expected - ); - - outcome - }; - } - #[test] fn run_chain_rotation_is_deterministic_1_block() { let strategy = NetworkStrategy { @@ -3842,6 +3253,7 @@ mod tests { }, start_keys: 5, extra_keys: Default::default(), + start_balance_range: dash_to_duffs!(1)..=dash_to_duffs!(1), }, identity_contract_nonce_gaps: None, @@ -4028,6 +3440,7 @@ mod tests { }, start_keys: 5, extra_keys: Default::default(), + start_balance_range: dash_to_duffs!(1)..=dash_to_duffs!(1), }, identity_contract_nonce_gaps: None, @@ -4190,6 +3603,7 @@ mod tests { }, start_keys: 5, extra_keys: Default::default(), + start_balance_range: dash_to_duffs!(1)..=dash_to_duffs!(1), }, identity_contract_nonce_gaps: None, @@ -4515,6 +3929,7 @@ mod tests { [(SecurityLevel::CRITICAL, vec![KeyType::ECDSA_SECP256K1])].into(), )] .into(), + start_balance_range: dash_to_duffs!(1)..=dash_to_duffs!(1), }, identity_contract_nonce_gaps: None, @@ -4584,6 +3999,7 @@ mod tests { }, start_keys: 5, extra_keys: Default::default(), + start_balance_range: dash_to_duffs!(1)..=dash_to_duffs!(1), }, ..Default::default() diff --git a/packages/rs-drive-abci/tests/strategy_tests/patch_platform_tests.rs b/packages/rs-drive-abci/tests/strategy_tests/patch_platform_tests.rs index 2e5fd9fe26..6a68330cae 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/patch_platform_tests.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/patch_platform_tests.rs @@ -18,6 +18,7 @@ mod tests { use platform_version::version; use platform_version::version::mocks::v2_test::TEST_PROTOCOL_VERSION_2; use platform_version::version::patches::PatchFn; + use platform_version::version::v1::PROTOCOL_VERSION_1; use platform_version::version::PlatformVersion; #[test] @@ -105,6 +106,7 @@ mod tests { let mut platform = TestPlatformBuilder::new() .with_config(config.clone()) + .with_initial_protocol_version(PROTOCOL_VERSION_1) .build_with_mock_rpc(); // Run chain before the first patch diff --git a/packages/rs-drive-abci/tests/strategy_tests/strategy.rs b/packages/rs-drive-abci/tests/strategy_tests/strategy.rs index 13f22b16f8..667b846868 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/strategy.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/strategy.rs @@ -14,7 +14,8 @@ use dpp::state_transition::identity_topup_transition::IdentityTopUpTransition; use strategy_tests::frequency::Frequency; use strategy_tests::operations::FinalizeBlockOperation::IdentityAddKeys; use strategy_tests::operations::{ - DocumentAction, DocumentOp, FinalizeBlockOperation, IdentityUpdateOp, OperationType, + AmountRange, DocumentAction, DocumentOp, FinalizeBlockOperation, IdentityUpdateOp, + OperationType, }; use dpp::document::DocumentV0Getters; @@ -40,9 +41,10 @@ use drive_abci::rpc::core::MockCoreRPCLike; use rand::prelude::{IteratorRandom, SliceRandom, StdRng}; use rand::Rng; use strategy_tests::Strategy; -use strategy_tests::transitions::{create_state_transitions_for_identities, create_state_transitions_for_identities_and_proofs, instant_asset_lock_proof_fixture}; +use strategy_tests::transitions::{create_state_transitions_for_identities, create_state_transitions_for_identities_and_proofs, instant_asset_lock_proof_fixture, instant_asset_lock_proof_fixture_with_dynamic_range}; use std::borrow::Cow; use std::collections::{BTreeMap, HashMap, HashSet}; +use std::ops::RangeInclusive; use std::str::FromStr; use tenderdash_abci::proto::abci::{ExecTxResult, ValidatorSetUpdate}; use dpp::dashcore::hashes::Hash; @@ -1118,7 +1120,7 @@ impl NetworkStrategy { operations.push(document_batch_transition); } } - OperationType::IdentityTopUp if !current_identities.is_empty() => { + OperationType::IdentityTopUp(amount) if !current_identities.is_empty() => { let indices: Vec = (0..current_identities.len()).choose_multiple(rng, count as usize); let random_identities: Vec<&Identity> = indices @@ -1130,6 +1132,7 @@ impl NetworkStrategy { operations.push(self.create_identity_top_up_transition( rng, random_identity, + amount, instant_lock_quorums, &platform.config, platform_version, @@ -1177,7 +1180,7 @@ impl NetworkStrategy { } } } - OperationType::IdentityWithdrawal if !current_identities.is_empty() => { + OperationType::IdentityWithdrawal(amount) if !current_identities.is_empty() => { let indices: Vec = (0..current_identities.len()).choose_multiple(rng, count as usize); for index in indices { @@ -1185,6 +1188,7 @@ impl NetworkStrategy { let state_transition = strategy_tests::transitions::create_identity_withdrawal_transition( random_identity, + amount.clone(), identity_nonce_counter, signer, rng, @@ -1491,6 +1495,7 @@ impl NetworkStrategy { ) -> Vec<(Identity, StateTransition)> { let key_count = self.strategy.identity_inserts.start_keys as KeyID; let extra_keys = &self.strategy.identity_inserts.extra_keys; + let balance_range = &self.strategy.identity_inserts.start_balance_range; let (mut identities, mut keys) = Identity::random_identities_with_private_keys_with_rng::< Vec<_>, @@ -1524,6 +1529,7 @@ impl NetworkStrategy { if self.sign_instant_locks { let identities_with_proofs = create_signed_instant_asset_lock_proofs_for_identities( identities, + balance_range, rng, instant_lock_quorums, platform_config, @@ -1536,7 +1542,13 @@ impl NetworkStrategy { platform_version, ) } else { - create_state_transitions_for_identities(identities, signer, rng, platform_version) + create_state_transitions_for_identities( + identities, + balance_range, + signer, + rng, + platform_version, + ) } } @@ -1545,6 +1557,7 @@ impl NetworkStrategy { &self, rng: &mut StdRng, identity: &Identity, + amount_range: &AmountRange, instant_lock_quorums: &Quorums, platform_config: &PlatformConfig, platform_version: &PlatformVersion, @@ -1554,8 +1567,11 @@ impl NetworkStrategy { .unwrap(); let sk: [u8; 32] = pk.try_into().unwrap(); let secret_key = SecretKey::from_str(hex::encode(sk).as_str()).unwrap(); - let mut asset_lock_proof = - instant_asset_lock_proof_fixture(PrivateKey::new(secret_key, Network::Dash)); + let mut asset_lock_proof = instant_asset_lock_proof_fixture_with_dynamic_range( + PrivateKey::new(secret_key, Network::Dash), + amount_range, + rng, + ); // Sign transaction and update signature in instant lock proof if self.sign_instant_locks { @@ -1636,6 +1652,7 @@ pub struct ChainExecutionOutcome<'a> { /// height to the validator set update at that height pub validator_set_updates: BTreeMap, pub state_transition_results_per_block: BTreeMap>, + pub signer: SimpleSigner, } impl<'a> ChainExecutionOutcome<'a> { @@ -1667,6 +1684,7 @@ pub struct ChainExecutionParameters { fn create_signed_instant_asset_lock_proofs_for_identities( identities: Vec, + balance_range: &RangeInclusive, rng: &mut StdRng, instant_lock_quorums: &Quorums, platform_config: &PlatformConfig, @@ -1691,7 +1709,11 @@ fn create_signed_instant_asset_lock_proofs_for_identities( let secret_key = SecretKey::from_str(hex::encode(pk_fixed).as_str()).unwrap(); let private_key = PrivateKey::new(secret_key, Network::Dash); - let mut asset_lock_proof = instant_asset_lock_proof_fixture(private_key); + let mut asset_lock_proof = instant_asset_lock_proof_fixture_with_dynamic_range( + private_key, + balance_range, + rng, + ); // Sign transaction and update instant lock let AssetLockProof::Instant(InstantAssetLockProof { instant_lock, .. }) = diff --git a/packages/rs-drive-abci/tests/strategy_tests/upgrade_fork_tests.rs b/packages/rs-drive-abci/tests/strategy_tests/upgrade_fork_tests.rs index 928fc0a6a7..554394956b 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/upgrade_fork_tests.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/upgrade_fork_tests.rs @@ -621,7 +621,6 @@ mod tests { epoch_time_length_s, ..Default::default() }, - initial_protocol_version: PROTOCOL_VERSION_1, block_spacing_ms: epoch_time_length_s * 1000, testing_configs: PlatformTestConfig::default_minimal_verifications(), ..Default::default() @@ -629,7 +628,7 @@ mod tests { let mut platform = TestPlatformBuilder::new() .with_config(config.clone()) - .with_initial_protocol_version(INITIAL_PROTOCOL_VERSION) + .with_initial_protocol_version(PROTOCOL_VERSION_1) .build_with_mock_rpc(); let ChainExecutionOutcome { diff --git a/packages/rs-drive-abci/tests/strategy_tests/voting_tests.rs b/packages/rs-drive-abci/tests/strategy_tests/voting_tests.rs index c27e5e16f5..e14f8d7b1b 100644 --- a/packages/rs-drive-abci/tests/strategy_tests/voting_tests.rs +++ b/packages/rs-drive-abci/tests/strategy_tests/voting_tests.rs @@ -24,6 +24,7 @@ mod tests { use dapi_grpc::platform::v0::get_contested_resource_vote_state_response::get_contested_resource_vote_state_response_v0::FinishedVoteInfo; use dapi_grpc::platform::v0::get_contested_resource_vote_state_response::get_contested_resource_vote_state_response_v0::finished_vote_info::FinishedVoteOutcome; use dpp::block::extended_block_info::v0::ExtendedBlockInfoV0Getters; + use dpp::dash_to_duffs; use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters; use dpp::state_transition::StateTransition; use dpp::voting::vote_choices::resource_vote_choice::ResourceVoteChoice; @@ -80,6 +81,7 @@ mod tests { let start_identities = create_state_transitions_for_identities( vec![identity1], + &(dash_to_duffs!(1)..=dash_to_duffs!(1)), &simple_signer, &mut rng, platform_version, @@ -363,6 +365,7 @@ mod tests { let start_identities = create_state_transitions_for_identities( vec![identity1, identity2], + &(dash_to_duffs!(1)..=dash_to_duffs!(1)), &simple_signer, &mut rng, platform_version, @@ -634,6 +637,7 @@ mod tests { let start_identities = create_state_transitions_for_identities( vec![identity1, identity2], + &(dash_to_duffs!(1)..=dash_to_duffs!(1)), &simple_signer, &mut rng, platform_version, @@ -986,6 +990,7 @@ mod tests { let start_identities = create_state_transitions_for_identities( vec![identity1, identity2], + &(dash_to_duffs!(1)..=dash_to_duffs!(1)), &simple_signer, &mut rng, platform_version, @@ -1350,6 +1355,7 @@ mod tests { let start_identities = create_state_transitions_for_identities( vec![identity1, identity2], + &(dash_to_duffs!(1)..=dash_to_duffs!(1)), &simple_signer, &mut rng, platform_version, diff --git a/packages/rs-drive-abci/tests/strategy_tests/withdrawal_tests.rs b/packages/rs-drive-abci/tests/strategy_tests/withdrawal_tests.rs new file mode 100644 index 0000000000..1748498709 --- /dev/null +++ b/packages/rs-drive-abci/tests/strategy_tests/withdrawal_tests.rs @@ -0,0 +1,2699 @@ +mod tests { + use crate::asset_unlock_index; + use crate::execution::{continue_chain_for_strategy, run_chain_for_strategy, GENESIS_TIME_MS}; + use crate::strategy::{ + ChainExecutionOutcome, ChainExecutionParameters, NetworkStrategy, StrategyRandomness, + }; + use dashcore_rpc::dashcore_rpc_json::{AssetUnlockStatus, AssetUnlockStatusResult}; + use dpp::dashcore::bls_sig_utils::BLSSignature; + use dpp::dashcore::hashes::Hash; + use dpp::dashcore::{BlockHash, ChainLock, Txid}; + use dpp::data_contracts::withdrawals_contract; + use dpp::identity::{KeyType, Purpose, SecurityLevel}; + use dpp::withdrawal::WithdrawalTransactionIndex; + use dpp::{dash_to_credits, dash_to_duffs}; + use drive::config::DEFAULT_QUERY_LIMIT; + use drive::drive::balances::TOTAL_SYSTEM_CREDITS_STORAGE_KEY; + use drive::drive::identity::withdrawals::paths::{ + get_withdrawal_root_path, WITHDRAWAL_TRANSACTIONS_SUM_AMOUNT_TREE_KEY, + }; + use drive::drive::system::misc_path; + use drive::util::grove_operations::DirectQueryType; + use drive_abci::config::{ + ChainLockConfig, ExecutionConfig, InstantLockConfig, PlatformConfig, PlatformTestConfig, + ValidatorSetConfig, + }; + use drive_abci::test::helpers::setup::TestPlatformBuilder; + use platform_version::version::mocks::v3_test::TEST_PLATFORM_V3; + use platform_version::version::PlatformVersion; + use std::collections::BTreeMap; + use std::sync::{Arc, Mutex}; + use strategy_tests::frequency::Frequency; + use strategy_tests::operations::{Operation, OperationType}; + use strategy_tests::{IdentityInsertInfo, StartIdentities, Strategy}; + + struct CoreState { + asset_unlock_statuses: BTreeMap, + chain_lock: ChainLock, + } + + #[test] + fn run_chain_withdraw_from_identities() { + // TEST_PLATFORM_V3 is like v4, but without the single quorum can sign withdrawals restriction + let platform_version = PlatformVersion::get(TEST_PLATFORM_V3.protocol_version) + .expect("expected to get platform version"); + let start_strategy = NetworkStrategy { + strategy: Strategy { + start_contracts: vec![], + operations: vec![Operation { + op_type: OperationType::IdentityTopUp(dash_to_duffs!(10)..=dash_to_duffs!(10)), + frequency: Frequency { + times_per_block_range: 1..4, + chance_per_block: None, + }, + }], + start_identities: StartIdentities::default(), + identity_inserts: IdentityInsertInfo { + frequency: Frequency { + times_per_block_range: 1..2, + chance_per_block: None, + }, + start_keys: 3, + extra_keys: [( + Purpose::TRANSFER, + [(SecurityLevel::CRITICAL, vec![KeyType::ECDSA_SECP256K1])].into(), + )] + .into(), + start_balance_range: dash_to_duffs!(1)..=dash_to_duffs!(1), + }, + identity_contract_nonce_gaps: None, + signer: None, + }, + total_hpmns: 100, + extra_normal_mns: 0, + validator_quorum_count: 24, + chain_lock_quorum_count: 24, + upgrading_info: None, + + proposer_strategy: Default::default(), + rotate_quorums: false, + failure_testing: None, + query_testing: None, + verify_state_transition_results: true, + ..Default::default() + }; + + let hour_in_ms = 1000 * 60 * 60; + let config = PlatformConfig { + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), + execution: ExecutionConfig { + verify_sum_trees: true, + + ..Default::default() + }, + block_spacing_ms: hour_in_ms, + testing_configs: PlatformTestConfig::default_minimal_verifications(), + ..Default::default() + }; + + let mut platform = TestPlatformBuilder::new() + .with_config(config.clone()) + .with_initial_protocol_version(TEST_PLATFORM_V3.protocol_version) + .build_with_mock_rpc(); + + platform + .core_rpc + .expect_send_raw_transaction() + .returning(move |_| Ok(Txid::all_zeros())); + + let mut chain_locked_height = 1; + + // Have to go with a complicated shared object for the core state because we need to change + // rpc response along the way but we can't mutate `platform.core_rpc` later + // because platform reference is moved into the AbciApplication. + let shared_core_state = Arc::new(Mutex::new(CoreState { + asset_unlock_statuses: BTreeMap::new(), + chain_lock: ChainLock { + block_height: chain_locked_height, + block_hash: BlockHash::from_byte_array([1; 32]), + signature: BLSSignature::from([2; 96]), + }, + })); + + // Set up Core RPC responses + { + let core_state = shared_core_state.clone(); + + platform + .core_rpc + .expect_get_asset_unlock_statuses() + .returning(move |indices, _| { + Ok(indices + .iter() + .map(|index| { + core_state + .lock() + .unwrap() + .asset_unlock_statuses + .get(index) + .cloned() + .unwrap() + }) + .collect()) + }); + + let core_state = shared_core_state.clone(); + platform + .core_rpc + .expect_get_best_chain_lock() + .returning(move || Ok(core_state.lock().unwrap().chain_lock.clone())); + } + + // Run first two blocks: + // - Block 1: creates identity + // - Block 2: tops up identity + let ChainExecutionOutcome { + abci_app, + proposers, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, + current_proposer_versions, + end_time_ms, + identity_nonce_counter, + identity_contract_nonce_counter, + instant_lock_quorums, + identities, + signer, + .. + } = { + let outcome = run_chain_for_strategy( + &mut platform, + 2, + start_strategy, + config.clone(), + 1, + &mut None, + ); + + for tx_results_per_block in outcome.state_transition_results_per_block.values() { + for (state_transition, result) in tx_results_per_block { + assert_eq!( + result.code, 0, + "state transition got code {} : {:?}", + result.code, state_transition + ); + } + } + + // Withdrawal transactions are not populated to block execution context yet + assert_eq!(outcome.withdrawals.len(), 0); + + // Withdrawal documents with pooled status should exist. + let withdrawal_documents_pooled = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::POOLED.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + assert!(withdrawal_documents_pooled.is_empty()); + + let locked_amount = outcome + .abci_app + .platform + .drive + .grove_get_sum_tree_total_value( + (&get_withdrawal_root_path()).into(), + &WITHDRAWAL_TRANSACTIONS_SUM_AMOUNT_TREE_KEY, + DirectQueryType::StatefulDirectQuery, + None, + &mut vec![], + &platform_version.drive, + ) + .expect("expected to get locked amount"); + + assert_eq!(locked_amount, 0); + + let pooled_withdrawals = withdrawal_documents_pooled.len(); + + assert_eq!(pooled_withdrawals, 0); + + outcome + }; + + let continue_strategy_only_withdrawal = NetworkStrategy { + strategy: Strategy { + start_contracts: vec![], + operations: vec![Operation { + op_type: OperationType::IdentityWithdrawal( + dash_to_credits!(0.1)..=dash_to_credits!(0.1), + ), + frequency: Frequency { + times_per_block_range: 1..2, + chance_per_block: None, + }, + }], + start_identities: StartIdentities::default(), + identity_inserts: IdentityInsertInfo::default(), + identity_contract_nonce_gaps: None, + signer: Some(signer.clone()), + }, + total_hpmns: 100, + extra_normal_mns: 0, + validator_quorum_count: 24, + chain_lock_quorum_count: 24, + upgrading_info: None, + + proposer_strategy: Default::default(), + rotate_quorums: false, + failure_testing: None, + query_testing: None, + verify_state_transition_results: true, + ..Default::default() + }; + + let continue_strategy_no_operations = NetworkStrategy { + strategy: Strategy { + start_contracts: vec![], + operations: vec![], + start_identities: StartIdentities::default(), + identity_inserts: IdentityInsertInfo::default(), + identity_contract_nonce_gaps: None, + signer: Some(signer), + }, + total_hpmns: 100, + extra_normal_mns: 0, + validator_quorum_count: 24, + chain_lock_quorum_count: 24, + upgrading_info: None, + + proposer_strategy: Default::default(), + rotate_quorums: false, + failure_testing: None, + query_testing: None, + verify_state_transition_results: true, + ..Default::default() + }; + + // Run Block 3: initiates a withdrawal + let ( + ChainExecutionOutcome { + abci_app, + proposers, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, + current_proposer_versions, + end_time_ms, + identity_nonce_counter, + identity_contract_nonce_counter, + instant_lock_quorums, + identities, + .. + }, + last_block_pooled_withdrawals_amount, + ) = { + let outcome = continue_chain_for_strategy( + abci_app, + ChainExecutionParameters { + block_start: 3, + core_height_start: 1, + block_count: 1, + proposers, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, + current_proposer_versions: Some(current_proposer_versions), + current_identity_nonce_counter: identity_nonce_counter, + current_identity_contract_nonce_counter: identity_contract_nonce_counter, + current_votes: BTreeMap::default(), + start_time_ms: GENESIS_TIME_MS, + current_time_ms: end_time_ms, + instant_lock_quorums, + current_identities: identities, + }, + continue_strategy_only_withdrawal.clone(), + config.clone(), + StrategyRandomness::SeedEntropy(2), + ); + + for tx_results_per_block in outcome.state_transition_results_per_block.values() { + assert_eq!(tx_results_per_block.len(), 1); + for (state_transition, result) in tx_results_per_block { + assert_eq!( + result.code, 0, + "state transition got code {} : {:?}", + result.code, state_transition + ); + } + } + + // Withdrawal transactions are not populated to block execution context yet + assert_eq!(outcome.withdrawals.len(), 0); + + // Withdrawal documents with pooled status should exist. + let withdrawal_documents_pooled = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::POOLED.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + assert!(!withdrawal_documents_pooled.is_empty()); + + let locked_amount = outcome + .abci_app + .platform + .drive + .grove_get_sum_tree_total_value( + (&get_withdrawal_root_path()).into(), + &WITHDRAWAL_TRANSACTIONS_SUM_AMOUNT_TREE_KEY, + DirectQueryType::StatefulDirectQuery, + None, + &mut vec![], + &platform_version.drive, + ) + .expect("expected to get locked amount"); + + assert_eq!(locked_amount, dash_to_credits!(0.1) as i64); + + let pooled_withdrawals = withdrawal_documents_pooled.len(); + + (outcome, pooled_withdrawals) + }; + + // Run block 4 + // Should broadcast previously pooled withdrawals to core + let ChainExecutionOutcome { + abci_app, + proposers, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, + current_proposer_versions, + end_time_ms, + withdrawals: last_block_withdrawals, + identity_nonce_counter, + identity_contract_nonce_counter, + instant_lock_quorums, + identities, + .. + } = { + let outcome = continue_chain_for_strategy( + abci_app, + ChainExecutionParameters { + block_start: 4, + core_height_start: 1, + block_count: 1, + proposers, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, + current_proposer_versions: Some(current_proposer_versions), + current_identity_nonce_counter: identity_nonce_counter, + current_identity_contract_nonce_counter: identity_contract_nonce_counter, + current_votes: BTreeMap::default(), + start_time_ms: GENESIS_TIME_MS, + current_time_ms: end_time_ms, + instant_lock_quorums, + current_identities: identities, + }, + continue_strategy_no_operations.clone(), + config.clone(), + StrategyRandomness::SeedEntropy(3), + ); + + // Withdrawal documents with pooled status should exist. + let withdrawal_documents_broadcasted = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::BROADCASTED.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + // In this block all previously pooled withdrawals should be broadcasted + assert_eq!( + outcome.withdrawals.len(), + last_block_pooled_withdrawals_amount + ); + assert_eq!( + withdrawal_documents_broadcasted.len(), + last_block_pooled_withdrawals_amount + ); + + let locked_amount = outcome + .abci_app + .platform + .drive + .grove_get_sum_tree_total_value( + (&get_withdrawal_root_path()).into(), + &WITHDRAWAL_TRANSACTIONS_SUM_AMOUNT_TREE_KEY, + DirectQueryType::StatefulDirectQuery, + None, + &mut vec![], + &platform_version.drive, + ) + .expect("expected to get locked amount"); + + assert_eq!(locked_amount, dash_to_credits!(0.1) as i64); + + outcome + }; + + // Update core state before running next block. + // Asset unlocks broadcasted in the last block should have Unknown status + { + let mut core_state = shared_core_state.lock().unwrap(); + last_block_withdrawals.iter().for_each(|tx| { + let index = asset_unlock_index(tx); + + core_state.asset_unlock_statuses.insert( + index, + AssetUnlockStatusResult { + index, + status: AssetUnlockStatus::Unknown, + }, + ); + }); + } + + // Run block 5 + // Should change do nothing, because core doesn't report any change + let ChainExecutionOutcome { + abci_app, + proposers, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, + current_proposer_versions, + end_time_ms, + withdrawals: last_block_withdrawals, + identity_nonce_counter, + identity_contract_nonce_counter, + instant_lock_quorums, + identities, + .. + } = { + let outcome = continue_chain_for_strategy( + abci_app, + ChainExecutionParameters { + block_start: 5, + core_height_start: 1, + block_count: 1, + proposers, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, + current_proposer_versions: Some(current_proposer_versions), + current_identity_nonce_counter: identity_nonce_counter, + current_identity_contract_nonce_counter: identity_contract_nonce_counter, + current_votes: BTreeMap::default(), + start_time_ms: GENESIS_TIME_MS, + current_time_ms: end_time_ms + 1000, + instant_lock_quorums, + current_identities: identities, + }, + continue_strategy_no_operations.clone(), + config.clone(), + StrategyRandomness::SeedEntropy(4), + ); + + let withdrawal_documents_completed = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::COMPLETE.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + // things have not changed + assert!(withdrawal_documents_completed.is_empty()); + + let locked_amount = outcome + .abci_app + .platform + .drive + .grove_get_sum_tree_total_value( + (&get_withdrawal_root_path()).into(), + &WITHDRAWAL_TRANSACTIONS_SUM_AMOUNT_TREE_KEY, + DirectQueryType::StatefulDirectQuery, + None, + &mut vec![], + &platform_version.drive, + ) + .expect("expected to get locked amount"); + + assert_eq!(locked_amount, dash_to_credits!(0.1) as i64); + + outcome + }; + + // Update core state for newly broadcasted transactions + { + let mut core_state = shared_core_state.lock().unwrap(); + + // First, set all previously broadcasted transactions to Chainlocked + core_state + .asset_unlock_statuses + .iter_mut() + .for_each(|(index, status_result)| { + // Do not settle yet transactions that were broadcasted in the last block + status_result.index = *index; + status_result.status = AssetUnlockStatus::Chainlocked; + }); + + // Then increase chainlocked height, so that withdrawals for chainlocked transactions + // could be completed in the next block + // TODO: do we need this var? + chain_locked_height += 1; + core_state.chain_lock.block_height = chain_locked_height; + + // Then set all newly broadcasted transactions to Unknown + last_block_withdrawals.iter().for_each(|tx| { + let index = asset_unlock_index(tx); + + core_state.asset_unlock_statuses.insert( + index, + AssetUnlockStatusResult { + index, + status: AssetUnlockStatus::Unknown, + }, + ); + }); + + drop(core_state); + } + + // Run block 6 + // Previously broadcasted transactions should be settled after block 5, + // and their corresponding statuses should be changed to COMPLETED + let ChainExecutionOutcome { + abci_app, + proposers, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, + current_proposer_versions, + end_time_ms, + identity_nonce_counter, + identity_contract_nonce_counter, + instant_lock_quorums, + identities, + .. + } = { + let outcome = continue_chain_for_strategy( + abci_app, + ChainExecutionParameters { + block_start: 6, + core_height_start: 1, + block_count: 1, + proposers, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, + current_proposer_versions: Some(current_proposer_versions), + current_identity_nonce_counter: identity_nonce_counter, + current_identity_contract_nonce_counter: identity_contract_nonce_counter, + current_votes: BTreeMap::default(), + start_time_ms: GENESIS_TIME_MS, + current_time_ms: end_time_ms + 1000, + instant_lock_quorums, + current_identities: identities, + }, + continue_strategy_no_operations.clone(), + config.clone(), + StrategyRandomness::SeedEntropy(5), + ); + + let withdrawal_documents_pooled = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::POOLED.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + let withdrawal_documents_broadcasted = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::BROADCASTED.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + let withdrawal_documents_completed = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::COMPLETE.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + // In this block we should have new withdrawals pooled + assert!(withdrawal_documents_pooled.is_empty()); + assert!(withdrawal_documents_broadcasted.is_empty()); + + assert_eq!(withdrawal_documents_completed.len(), 1); + + let locked_amount = outcome + .abci_app + .platform + .drive + .grove_get_sum_tree_total_value( + (&get_withdrawal_root_path()).into(), + &WITHDRAWAL_TRANSACTIONS_SUM_AMOUNT_TREE_KEY, + DirectQueryType::StatefulDirectQuery, + None, + &mut vec![], + &platform_version.drive, + ) + .expect("expected to get locked amount"); + + assert_eq!(locked_amount, dash_to_credits!(0.1) as i64); + + outcome + }; + + let outcome = continue_chain_for_strategy( + abci_app, + ChainExecutionParameters { + block_start: 7, + core_height_start: 1, + block_count: 24, + proposers, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, + current_proposer_versions: Some(current_proposer_versions), + current_identity_nonce_counter: identity_nonce_counter, + current_identity_contract_nonce_counter: identity_contract_nonce_counter, + current_votes: BTreeMap::default(), + start_time_ms: GENESIS_TIME_MS, + current_time_ms: end_time_ms + 1000, + instant_lock_quorums, + current_identities: identities, + }, + continue_strategy_no_operations.clone(), + config.clone(), + StrategyRandomness::SeedEntropy(6), + ); + + // We should have unlocked the amounts by now + let locked_amount = outcome + .abci_app + .platform + .drive + .grove_get_sum_tree_total_value( + (&get_withdrawal_root_path()).into(), + &WITHDRAWAL_TRANSACTIONS_SUM_AMOUNT_TREE_KEY, + DirectQueryType::StatefulDirectQuery, + None, + &mut vec![], + &platform_version.drive, + ) + .expect("expected to get locked amount"); + + assert_eq!(locked_amount, 0); + } + + #[test] + fn run_chain_withdrawal_expired() { + // TEST_PLATFORM_V3 is like v4, but without the single quorum can sign withdrawals restriction + let platform_version = PlatformVersion::get(TEST_PLATFORM_V3.protocol_version) + .expect("expected to get platform version"); + let start_strategy = NetworkStrategy { + strategy: Strategy { + start_contracts: vec![], + operations: vec![Operation { + op_type: OperationType::IdentityTopUp(dash_to_duffs!(10)..=dash_to_duffs!(10)), + frequency: Frequency { + times_per_block_range: 1..4, + chance_per_block: None, + }, + }], + start_identities: StartIdentities::default(), + identity_inserts: IdentityInsertInfo { + frequency: Frequency { + times_per_block_range: 1..2, + chance_per_block: None, + }, + start_keys: 3, + extra_keys: [( + Purpose::TRANSFER, + [(SecurityLevel::CRITICAL, vec![KeyType::ECDSA_SECP256K1])].into(), + )] + .into(), + start_balance_range: dash_to_duffs!(1)..=dash_to_duffs!(1), + }, + identity_contract_nonce_gaps: None, + signer: None, + }, + total_hpmns: 100, + extra_normal_mns: 0, + validator_quorum_count: 24, + chain_lock_quorum_count: 24, + upgrading_info: None, + + proposer_strategy: Default::default(), + rotate_quorums: false, + failure_testing: None, + query_testing: None, + verify_state_transition_results: true, + ..Default::default() + }; + + let hour_in_ms = 1000 * 60 * 60; + let config = PlatformConfig { + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), + execution: ExecutionConfig { + verify_sum_trees: true, + + ..Default::default() + }, + block_spacing_ms: hour_in_ms, + testing_configs: PlatformTestConfig::default_minimal_verifications(), + ..Default::default() + }; + + let mut platform = TestPlatformBuilder::new() + .with_config(config.clone()) + .with_initial_protocol_version(TEST_PLATFORM_V3.protocol_version) + .build_with_mock_rpc(); + + platform + .core_rpc + .expect_send_raw_transaction() + .returning(move |_| Ok(Txid::all_zeros())); + + // Have to go with a complicated shared object for the core state because we need to change + // rpc response along the way but we can't mutate `platform.core_rpc` later + // because platform reference is moved into the AbciApplication. + let shared_core_state = Arc::new(Mutex::new(CoreState { + asset_unlock_statuses: BTreeMap::new(), + chain_lock: ChainLock { + block_height: 1, + block_hash: BlockHash::from_byte_array([1; 32]), + signature: BLSSignature::from([2; 96]), + }, + })); + + // Set up Core RPC responses + { + let core_state = shared_core_state.clone(); + + platform + .core_rpc + .expect_get_asset_unlock_statuses() + .returning(move |indices, _| { + Ok(indices + .iter() + .map(|index| { + core_state + .lock() + .unwrap() + .asset_unlock_statuses + .get(index) + .cloned() + .unwrap() + }) + .collect()) + }); + + let core_state = shared_core_state.clone(); + platform + .core_rpc + .expect_get_best_chain_lock() + .returning(move || Ok(core_state.lock().unwrap().chain_lock.clone())); + } + + // Run first two blocks: + // - Block 1: creates identity + // - Block 2: tops up identity + let ChainExecutionOutcome { + abci_app, + proposers, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, + current_proposer_versions, + end_time_ms, + identity_nonce_counter, + identity_contract_nonce_counter, + instant_lock_quorums, + identities, + signer, + .. + } = { + let outcome = run_chain_for_strategy( + &mut platform, + 2, + start_strategy, + config.clone(), + 1, + &mut None, + ); + + for tx_results_per_block in outcome.state_transition_results_per_block.values() { + for (state_transition, result) in tx_results_per_block { + assert_eq!( + result.code, 0, + "state transition got code {} : {:?}", + result.code, state_transition + ); + } + } + + // Withdrawal transactions are not populated to block execution context yet + assert_eq!(outcome.withdrawals.len(), 0); + + // Withdrawal documents with pooled status should exist. + let withdrawal_documents_pooled = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::POOLED.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + assert!(withdrawal_documents_pooled.is_empty()); + + let locked_amount = outcome + .abci_app + .platform + .drive + .grove_get_sum_tree_total_value( + (&get_withdrawal_root_path()).into(), + &WITHDRAWAL_TRANSACTIONS_SUM_AMOUNT_TREE_KEY, + DirectQueryType::StatefulDirectQuery, + None, + &mut vec![], + &platform_version.drive, + ) + .expect("expected to get locked amount"); + + assert_eq!(locked_amount, 0); + + let pooled_withdrawals = withdrawal_documents_pooled.len(); + + assert_eq!(pooled_withdrawals, 0); + + outcome + }; + + let continue_strategy_only_withdrawal = NetworkStrategy { + strategy: Strategy { + start_contracts: vec![], + operations: vec![Operation { + op_type: OperationType::IdentityWithdrawal( + dash_to_credits!(0.1)..=dash_to_credits!(0.1), + ), + frequency: Frequency { + times_per_block_range: 1..2, + chance_per_block: None, + }, + }], + start_identities: StartIdentities::default(), + identity_inserts: IdentityInsertInfo::default(), + identity_contract_nonce_gaps: None, + signer: Some(signer.clone()), + }, + total_hpmns: 100, + extra_normal_mns: 0, + validator_quorum_count: 24, + chain_lock_quorum_count: 24, + upgrading_info: None, + + proposer_strategy: Default::default(), + rotate_quorums: false, + failure_testing: None, + query_testing: None, + verify_state_transition_results: true, + ..Default::default() + }; + + let continue_strategy_no_operations = NetworkStrategy { + strategy: Strategy { + start_contracts: vec![], + operations: vec![], + start_identities: StartIdentities::default(), + identity_inserts: IdentityInsertInfo::default(), + identity_contract_nonce_gaps: None, + signer: Some(signer), + }, + total_hpmns: 100, + extra_normal_mns: 0, + validator_quorum_count: 24, + chain_lock_quorum_count: 24, + upgrading_info: None, + + proposer_strategy: Default::default(), + rotate_quorums: false, + failure_testing: None, + query_testing: None, + verify_state_transition_results: true, + ..Default::default() + }; + + // Run Block 3: initiates a withdrawal + let ( + ChainExecutionOutcome { + abci_app, + proposers, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, + current_proposer_versions, + end_time_ms, + identity_nonce_counter, + identity_contract_nonce_counter, + instant_lock_quorums, + identities, + .. + }, + last_block_pooled_withdrawals_amount, + ) = { + let outcome = continue_chain_for_strategy( + abci_app, + ChainExecutionParameters { + block_start: 3, + core_height_start: 1, + block_count: 1, + proposers, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, + current_proposer_versions: Some(current_proposer_versions), + current_identity_nonce_counter: identity_nonce_counter, + current_identity_contract_nonce_counter: identity_contract_nonce_counter, + current_votes: BTreeMap::default(), + start_time_ms: GENESIS_TIME_MS, + current_time_ms: end_time_ms, + instant_lock_quorums, + current_identities: identities, + }, + continue_strategy_only_withdrawal.clone(), + config.clone(), + StrategyRandomness::SeedEntropy(2), + ); + + for tx_results_per_block in outcome.state_transition_results_per_block.values() { + assert_eq!(tx_results_per_block.len(), 1); + for (state_transition, result) in tx_results_per_block { + assert_eq!( + result.code, 0, + "state transition got code {} : {:?}", + result.code, state_transition + ); + } + } + + // Withdrawal transactions are not populated to block execution context yet + assert_eq!(outcome.withdrawals.len(), 0); + + // Withdrawal documents with pooled status should exist. + let withdrawal_documents_pooled = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::POOLED.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + assert!(!withdrawal_documents_pooled.is_empty()); + + let locked_amount = outcome + .abci_app + .platform + .drive + .grove_get_sum_tree_total_value( + (&get_withdrawal_root_path()).into(), + &WITHDRAWAL_TRANSACTIONS_SUM_AMOUNT_TREE_KEY, + DirectQueryType::StatefulDirectQuery, + None, + &mut vec![], + &platform_version.drive, + ) + .expect("expected to get locked amount"); + + assert_eq!(locked_amount, dash_to_credits!(0.1) as i64); + + let pooled_withdrawals = withdrawal_documents_pooled.len(); + + (outcome, pooled_withdrawals) + }; + + // Run block 4 + // Should broadcast previously pooled withdrawals to core + let ChainExecutionOutcome { + abci_app, + proposers, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, + current_proposer_versions, + end_time_ms, + withdrawals: last_block_withdrawals, + identity_nonce_counter, + identity_contract_nonce_counter, + instant_lock_quorums, + identities, + .. + } = { + let outcome = continue_chain_for_strategy( + abci_app, + ChainExecutionParameters { + block_start: 4, + core_height_start: 1, + block_count: 1, + proposers, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, + current_proposer_versions: Some(current_proposer_versions), + current_identity_nonce_counter: identity_nonce_counter, + current_identity_contract_nonce_counter: identity_contract_nonce_counter, + current_votes: BTreeMap::default(), + start_time_ms: GENESIS_TIME_MS, + current_time_ms: end_time_ms, + instant_lock_quorums, + current_identities: identities, + }, + continue_strategy_no_operations.clone(), + config.clone(), + StrategyRandomness::SeedEntropy(2), + ); + + // Withdrawal documents with pooled status should exist. + let withdrawal_documents_broadcasted = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::BROADCASTED.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + // In this block all previously pooled withdrawals should be broadcasted + assert_eq!( + outcome.withdrawals.len(), + last_block_pooled_withdrawals_amount + ); + assert_eq!( + withdrawal_documents_broadcasted.len(), + last_block_pooled_withdrawals_amount + ); + + outcome + }; + + // Update state of the core before proceeding to the next block + { + // Simulate transactions being added to the core mempool + let mut core_state = shared_core_state.lock().unwrap(); + + core_state.chain_lock.block_height = 50; + + last_block_withdrawals.iter().for_each(|tx| { + let index = asset_unlock_index(tx); + + core_state.asset_unlock_statuses.insert( + index, + AssetUnlockStatusResult { + index, + status: AssetUnlockStatus::Unknown, + }, + ); + }); + } + + // Run block 5 + // Tests withdrawal expiration + let ChainExecutionOutcome { + abci_app, + proposers, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, + current_proposer_versions, + end_time_ms, + identity_nonce_counter, + identity_contract_nonce_counter, + instant_lock_quorums, + identities, + .. + } = { + let outcome = continue_chain_for_strategy( + abci_app, + ChainExecutionParameters { + block_start: 5, + core_height_start: 50, + block_count: 1, + proposers, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, + current_proposer_versions: Some(current_proposer_versions), + current_identity_nonce_counter: identity_nonce_counter, + current_identity_contract_nonce_counter: identity_contract_nonce_counter, + current_votes: BTreeMap::default(), + start_time_ms: GENESIS_TIME_MS, + current_time_ms: end_time_ms + 1000, + instant_lock_quorums, + current_identities: identities, + }, + continue_strategy_no_operations.clone(), + config.clone(), + StrategyRandomness::SeedEntropy(5), + ); + + let withdrawal_documents_pooled = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::POOLED.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + let withdrawal_documents_broadcasted = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::BROADCASTED.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + let withdrawal_documents_completed = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::COMPLETE.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + let withdrawal_documents_expired = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::EXPIRED.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + assert!(withdrawal_documents_pooled.is_empty()); + assert!(withdrawal_documents_completed.is_empty()); + + assert_eq!(withdrawal_documents_expired.len(), 1); + + assert!(withdrawal_documents_broadcasted.is_empty()); + + outcome + }; + + // Run block 6 + // Should broadcast previously expired transaction + let ChainExecutionOutcome { + abci_app, + proposers, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, + current_proposer_versions, + end_time_ms, + identity_nonce_counter, + identity_contract_nonce_counter, + instant_lock_quorums, + identities, + .. + } = { + let outcome = continue_chain_for_strategy( + abci_app, + ChainExecutionParameters { + block_start: 6, + core_height_start: 50, + block_count: 1, + proposers, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, + current_proposer_versions: Some(current_proposer_versions), + current_identity_nonce_counter: identity_nonce_counter, + current_identity_contract_nonce_counter: identity_contract_nonce_counter, + current_votes: BTreeMap::default(), + start_time_ms: GENESIS_TIME_MS, + current_time_ms: end_time_ms, + instant_lock_quorums, + current_identities: identities, + }, + continue_strategy_no_operations.clone(), + config.clone(), + StrategyRandomness::SeedEntropy(2), + ); + + let withdrawal_documents_pooled = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::POOLED.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + let withdrawal_documents_broadcasted = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::BROADCASTED.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + let withdrawal_documents_completed = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::COMPLETE.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + let withdrawal_documents_expired = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::EXPIRED.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + assert!(withdrawal_documents_pooled.is_empty()); + assert!(withdrawal_documents_completed.is_empty()); + + assert_eq!(withdrawal_documents_broadcasted.len(), 1); + + assert!(withdrawal_documents_expired.is_empty()); + + outcome + }; + + // Update core state saying transaction is chainlocked + { + let mut core_state = shared_core_state.lock().unwrap(); + + // First, set all previously broadcasted transactions to Chainlocked + core_state + .asset_unlock_statuses + .iter_mut() + .for_each(|(index, status_result)| { + // Do not settle yet transactions that were broadcasted in the last block + status_result.index = *index; + status_result.status = AssetUnlockStatus::Chainlocked; + }); + + core_state.chain_lock.block_height = 51; + + drop(core_state); + } + + let outcome = continue_chain_for_strategy( + abci_app, + ChainExecutionParameters { + block_start: 7, + core_height_start: 51, + block_count: 1, + proposers, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, + current_proposer_versions: Some(current_proposer_versions), + current_identity_nonce_counter: identity_nonce_counter, + current_identity_contract_nonce_counter: identity_contract_nonce_counter, + current_votes: BTreeMap::default(), + start_time_ms: GENESIS_TIME_MS, + current_time_ms: end_time_ms, + instant_lock_quorums, + current_identities: identities, + }, + continue_strategy_no_operations.clone(), + config.clone(), + StrategyRandomness::SeedEntropy(2), + ); + + let withdrawal_documents_pooled = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::POOLED.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + let withdrawal_documents_broadcasted = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::BROADCASTED.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + let withdrawal_documents_completed = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::COMPLETE.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + let withdrawal_documents_expired = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::EXPIRED.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + assert_eq!(withdrawal_documents_completed.len(), 1); + assert!(withdrawal_documents_pooled.is_empty()); + assert!(withdrawal_documents_broadcasted.is_empty()); + assert!(withdrawal_documents_expired.is_empty()); + } + + #[test] + fn run_chain_withdraw_from_identities_too_many_withdrawals_within_a_day_hitting_limit() { + // TEST_PLATFORM_V3 is like v4, but without the single quorum can sign withdrawals restriction + let platform_version = PlatformVersion::get(TEST_PLATFORM_V3.protocol_version) + .expect("expected to get platform version"); + let start_strategy = NetworkStrategy { + strategy: Strategy { + start_contracts: vec![], + operations: vec![Operation { + op_type: OperationType::IdentityTopUp(dash_to_duffs!(10)..=dash_to_duffs!(10)), + frequency: Frequency { + times_per_block_range: 10..11, + chance_per_block: None, + }, + }], + start_identities: StartIdentities::default(), + identity_inserts: IdentityInsertInfo { + frequency: Frequency { + times_per_block_range: 10..11, + chance_per_block: None, + }, + start_keys: 3, + extra_keys: [( + Purpose::TRANSFER, + [(SecurityLevel::CRITICAL, vec![KeyType::ECDSA_SECP256K1])].into(), + )] + .into(), + start_balance_range: dash_to_duffs!(200)..=dash_to_duffs!(200), + }, + identity_contract_nonce_gaps: None, + signer: None, + }, + total_hpmns: 100, + extra_normal_mns: 0, + validator_quorum_count: 24, + chain_lock_quorum_count: 24, + upgrading_info: None, + + proposer_strategy: Default::default(), + rotate_quorums: false, + failure_testing: None, + query_testing: None, + verify_state_transition_results: true, + ..Default::default() + }; + + let minute_in_ms = 1000 * 60; + let config = PlatformConfig { + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), + execution: ExecutionConfig { + verify_sum_trees: true, + + ..Default::default() + }, + block_spacing_ms: minute_in_ms, + testing_configs: PlatformTestConfig::default_minimal_verifications(), + ..Default::default() + }; + + let mut platform = TestPlatformBuilder::new() + .with_initial_protocol_version(TEST_PLATFORM_V3.protocol_version) + .with_config(config.clone()) + .build_with_mock_rpc(); + + platform + .core_rpc + .expect_send_raw_transaction() + .returning(move |_| Ok(Txid::all_zeros())); + + let chain_locked_height = 1; + + // Have to go with a complicated shared object for the core state because we need to change + // rpc response along the way but we can't mutate `platform.core_rpc` later + // because platform reference is moved into the AbciApplication. + let shared_core_state = Arc::new(Mutex::new(CoreState { + asset_unlock_statuses: BTreeMap::new(), + chain_lock: ChainLock { + block_height: chain_locked_height, + block_hash: BlockHash::from_byte_array([1; 32]), + signature: BLSSignature::from([2; 96]), + }, + })); + + // Set up Core RPC responses + { + let core_state = shared_core_state.clone(); + + platform + .core_rpc + .expect_get_asset_unlock_statuses() + .returning(move |indices, _| { + Ok(indices + .iter() + .map(|index| { + core_state + .lock() + .unwrap() + .asset_unlock_statuses + .get(index) + .cloned() + .unwrap() + }) + .collect()) + }); + + let core_state = shared_core_state.clone(); + platform + .core_rpc + .expect_get_best_chain_lock() + .returning(move || Ok(core_state.lock().unwrap().chain_lock.clone())); + } + + // Run first two blocks: + // - Block 1: creates identity + // - Block 2: tops up identity + let ChainExecutionOutcome { + abci_app, + proposers, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, + current_proposer_versions, + end_time_ms, + identity_nonce_counter, + identity_contract_nonce_counter, + instant_lock_quorums, + identities, + signer, + .. + } = { + let outcome = run_chain_for_strategy( + &mut platform, + 2, + start_strategy, + config.clone(), + 1, + &mut None, + ); + + for tx_results_per_block in outcome.state_transition_results_per_block.values() { + for (state_transition, result) in tx_results_per_block { + assert_eq!( + result.code, 0, + "state transition got code {} : {:?}", + result.code, state_transition + ); + } + } + + // Withdrawal transactions are not populated to block execution context yet + assert_eq!(outcome.withdrawals.len(), 0); + + // Withdrawal documents with pooled status should exist. + let withdrawal_documents_pooled = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::POOLED.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + assert!(withdrawal_documents_pooled.is_empty()); + + let locked_amount = outcome + .abci_app + .platform + .drive + .grove_get_sum_tree_total_value( + (&get_withdrawal_root_path()).into(), + &WITHDRAWAL_TRANSACTIONS_SUM_AMOUNT_TREE_KEY, + DirectQueryType::StatefulDirectQuery, + None, + &mut vec![], + &platform_version.drive, + ) + .expect("expected to get locked amount"); + + assert_eq!(locked_amount, 0); + + let pooled_withdrawals = withdrawal_documents_pooled.len(); + + assert_eq!(pooled_withdrawals, 0); + + let total_credits_balance = outcome + .abci_app + .platform + .drive + .calculate_total_credits_balance(None, &platform_version.drive) + .expect("expected to get total credits balance"); + + assert_eq!( + total_credits_balance.total_identity_balances, + 409997575280380 + ); // Around 4100 Dash. + + assert_eq!( + total_credits_balance.total_in_trees().unwrap(), + 410000000000000 + ); // Around 4100 Dash. + + let total_credits_in_platform = outcome + .abci_app + .platform + .drive + .grove_get_raw_value_u64_from_encoded_var_vec( + (&misc_path()).into(), + TOTAL_SYSTEM_CREDITS_STORAGE_KEY, + DirectQueryType::StatefulDirectQuery, + None, + &mut vec![], + &platform_version.drive, + ) + .expect("expected to get total credits in platform"); + + assert_eq!(total_credits_in_platform, Some(410000000000000)); + + outcome + }; + + let continue_strategy_only_withdrawal = NetworkStrategy { + strategy: Strategy { + start_contracts: vec![], + operations: vec![Operation { + op_type: OperationType::IdentityWithdrawal( + dash_to_credits!(25)..=dash_to_credits!(25), + ), + frequency: Frequency { + times_per_block_range: 4..5, // 25 Dash x 4 Withdrawals = 100 Dash + chance_per_block: None, + }, + }], + start_identities: StartIdentities::default(), + identity_inserts: IdentityInsertInfo::default(), + identity_contract_nonce_gaps: None, + signer: Some(signer.clone()), + }, + total_hpmns: 100, + extra_normal_mns: 0, + validator_quorum_count: 24, + chain_lock_quorum_count: 24, + upgrading_info: None, + + proposer_strategy: Default::default(), + rotate_quorums: false, + failure_testing: None, + query_testing: None, + verify_state_transition_results: true, + ..Default::default() + }; + + let continue_strategy_no_operations = NetworkStrategy { + strategy: Strategy { + start_contracts: vec![], + operations: vec![], + start_identities: StartIdentities::default(), + identity_inserts: IdentityInsertInfo::default(), + identity_contract_nonce_gaps: None, + signer: Some(signer), + }, + total_hpmns: 100, + extra_normal_mns: 0, + validator_quorum_count: 24, + chain_lock_quorum_count: 24, + upgrading_info: None, + + proposer_strategy: Default::default(), + rotate_quorums: false, + failure_testing: None, + query_testing: None, + verify_state_transition_results: true, + ..Default::default() + }; + + // Run Block 3 onwards: initiates withdrawals + let ChainExecutionOutcome { + abci_app, + proposers, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, + current_proposer_versions, + end_time_ms, + identity_nonce_counter, + identity_contract_nonce_counter, + instant_lock_quorums, + identities, + .. + } = { + let outcome = continue_chain_for_strategy( + abci_app, + ChainExecutionParameters { + block_start: 3, + core_height_start: 1, + block_count: 20, + proposers, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, + current_proposer_versions: Some(current_proposer_versions), + current_identity_nonce_counter: identity_nonce_counter, + current_identity_contract_nonce_counter: identity_contract_nonce_counter, + current_votes: BTreeMap::default(), + start_time_ms: GENESIS_TIME_MS, + current_time_ms: end_time_ms, + instant_lock_quorums, + current_identities: identities, + }, + continue_strategy_only_withdrawal.clone(), + config.clone(), + StrategyRandomness::SeedEntropy(2), + ); + + for tx_results_per_block in outcome.state_transition_results_per_block.values() { + assert_eq!(tx_results_per_block.len(), 4); + for (state_transition, result) in tx_results_per_block { + assert_eq!( + result.code, 0, + "state transition got code {} : {:?}", + result.code, state_transition + ); + } + } + + // Withdrawal documents with pooled status should not exist. + let withdrawal_documents_pooled = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::POOLED.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + // None are currently pooled since we have no more room + assert!(withdrawal_documents_pooled.is_empty()); + + // Withdrawal documents with queued status should exist. + let withdrawal_documents_queued = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::QUEUED.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + // We have 66 out of 100 queued + assert_eq!(withdrawal_documents_queued.len(), 66); + + // Withdrawal documents with queued status should exist. + let withdrawal_documents_completed = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::COMPLETE.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + // None have completed because core didn't acknowledge them + assert_eq!(withdrawal_documents_completed.len(), 0); + + // Withdrawal documents with EXPIRED status should not exist yet. + let withdrawal_documents_expired = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::EXPIRED.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + // We have none expired yet + assert_eq!(withdrawal_documents_expired.len(), 0); + + // Withdrawal documents with broadcasted status should exist. + let withdrawal_documents_broadcasted = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::BROADCASTED.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + // We have 14 broadcasted (66 queued + 14 broadcasted = 80 total) + // 14 broadcasted = 14 * 25 Dash = 350 Dash + // This is explained by + // withdrawal block 1 : 4 withdrawals taking us to 4000 Dash and 100 Dash Taken + // limit is 100, 4 broadcasted + // withdrawal block 2 : 4 withdrawals taking us to 3900 Dash and 100 Dash Taken + // limit is 390 - 100 = 290, 4 broadcasted + // withdrawal block 3 : 4 withdrawals taking us to 3800 Dash and 100 Dash Taken + // limit is 380 - 200 = 180, 4 broadcasted + // withdrawal block 4 : 4 withdrawals taking us to 3700 Dash and 100 Dash Taken + // limit is 370 - 300 = 70, 2 broadcasted + assert_eq!(withdrawal_documents_broadcasted.len(), 14); + + let locked_amount = outcome + .abci_app + .platform + .drive + .grove_get_sum_tree_total_value( + (&get_withdrawal_root_path()).into(), + &WITHDRAWAL_TRANSACTIONS_SUM_AMOUNT_TREE_KEY, + DirectQueryType::StatefulDirectQuery, + None, + &mut vec![], + &platform_version.drive, + ) + .expect("expected to get locked amount"); + + assert_eq!(locked_amount, dash_to_credits!(350) as i64); + + outcome + }; + + let hour_in_ms = 1000 * 60 * 60; + + let ChainExecutionOutcome { + abci_app, + proposers, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, + current_proposer_versions, + end_time_ms, + identity_nonce_counter, + identity_contract_nonce_counter, + instant_lock_quorums, + identities, + .. + } = { + let outcome = continue_chain_for_strategy( + abci_app, + ChainExecutionParameters { + block_start: 23, + core_height_start: 1, + block_count: 48, + proposers, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, + current_proposer_versions: Some(current_proposer_versions), + current_identity_nonce_counter: identity_nonce_counter, + current_identity_contract_nonce_counter: identity_contract_nonce_counter, + current_votes: BTreeMap::default(), + start_time_ms: GENESIS_TIME_MS, + current_time_ms: end_time_ms + 1000, + instant_lock_quorums, + current_identities: identities, + }, + continue_strategy_no_operations.clone(), + PlatformConfig { + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), + execution: ExecutionConfig { + verify_sum_trees: true, + + ..Default::default() + }, + block_spacing_ms: hour_in_ms, + testing_configs: PlatformTestConfig::default_minimal_verifications(), + ..Default::default() + }, + StrategyRandomness::SeedEntropy(9), + ); + + // We should have unlocked the amounts by now + let locked_amount = outcome + .abci_app + .platform + .drive + .grove_get_sum_tree_total_value( + (&get_withdrawal_root_path()).into(), + &WITHDRAWAL_TRANSACTIONS_SUM_AMOUNT_TREE_KEY, + DirectQueryType::StatefulDirectQuery, + None, + &mut vec![], + &platform_version.drive, + ) + .expect("expected to get locked amount"); + + // There's about 2000 Dash left in platform, it's normal we are locking 1/10th of it + assert_eq!(locked_amount, 20000000000000); + + // Withdrawal documents with pooled status should not exist. + let withdrawal_documents_pooled = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::POOLED.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + // None are currently pooled since we have no more room + assert!(withdrawal_documents_pooled.is_empty()); + + // Withdrawal documents with queued status should exist. + let withdrawal_documents_queued = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::QUEUED.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + // We have 58 out of 100 queued + assert_eq!(withdrawal_documents_queued.len(), 58); + + // Withdrawal documents with queued status should exist. + let withdrawal_documents_completed = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::COMPLETE.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + // None have completed because core didn't acknowledge them + assert_eq!(withdrawal_documents_completed.len(), 0); + + // Withdrawal documents with EXPIRED status should not exist yet. + let withdrawal_documents_expired = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::EXPIRED.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + // We have none expired yet, because the core height never went up + assert_eq!(withdrawal_documents_expired.len(), 0); + + // Withdrawal documents with broadcasted status should exist. + let withdrawal_documents_broadcasted = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::BROADCASTED.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + assert_eq!(withdrawal_documents_broadcasted.len(), 22); + outcome + }; + + let outcome = continue_chain_for_strategy( + abci_app, + ChainExecutionParameters { + block_start: 71, + core_height_start: 1, + block_count: 250, + proposers, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, + current_proposer_versions: Some(current_proposer_versions), + current_identity_nonce_counter: identity_nonce_counter, + current_identity_contract_nonce_counter: identity_contract_nonce_counter, + current_votes: BTreeMap::default(), + start_time_ms: GENESIS_TIME_MS, + current_time_ms: end_time_ms + 1000, + instant_lock_quorums, + current_identities: identities, + }, + continue_strategy_no_operations.clone(), + PlatformConfig { + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), + execution: ExecutionConfig { + verify_sum_trees: true, + + ..Default::default() + }, + block_spacing_ms: hour_in_ms, + testing_configs: PlatformTestConfig::default_minimal_verifications(), + ..Default::default() + }, + StrategyRandomness::SeedEntropy(9), + ); + + // We should have unlocked the amounts by now + let locked_amount = outcome + .abci_app + .platform + .drive + .grove_get_sum_tree_total_value( + (&get_withdrawal_root_path()).into(), + &WITHDRAWAL_TRANSACTIONS_SUM_AMOUNT_TREE_KEY, + DirectQueryType::StatefulDirectQuery, + None, + &mut vec![], + &platform_version.drive, + ) + .expect("expected to get locked amount"); + + // We have nothing locked left + assert_eq!(locked_amount, 0); + + // Withdrawal documents with pooled status should not exist. + let withdrawal_documents_pooled = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::POOLED.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + // None are currently pooled since we have no more room + assert!(withdrawal_documents_pooled.is_empty()); + + // Withdrawal documents with queued status should exist. + let withdrawal_documents_queued = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::QUEUED.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + // Nothing is left in the queue + assert_eq!(withdrawal_documents_queued.len(), 0); + + // Withdrawal documents with queued status should exist. + let withdrawal_documents_completed = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::COMPLETE.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + // None have completed because core didn't acknowledge them + assert_eq!(withdrawal_documents_completed.len(), 0); + + // Withdrawal documents with EXPIRED status should not exist yet. + let withdrawal_documents_expired = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::EXPIRED.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + // We have none expired yet, because the core height never went up + assert_eq!(withdrawal_documents_expired.len(), 0); + + // Withdrawal documents with broadcasted status should exist. + let withdrawal_documents_broadcasted = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::BROADCASTED.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + assert_eq!(withdrawal_documents_broadcasted.len(), 80); + } + + #[test] + fn run_chain_withdraw_from_identities_many_small_withdrawals() { + // TEST_PLATFORM_V3 is like v4, but without the single quorum can sign withdrawals restriction + let platform_version = PlatformVersion::get(TEST_PLATFORM_V3.protocol_version) + .expect("expected to get platform version"); + let start_strategy = NetworkStrategy { + strategy: Strategy { + start_contracts: vec![], + operations: vec![Operation { + op_type: OperationType::IdentityTopUp(dash_to_duffs!(10)..=dash_to_duffs!(10)), + frequency: Frequency { + times_per_block_range: 10..11, + chance_per_block: None, + }, + }], + start_identities: StartIdentities::default(), + identity_inserts: IdentityInsertInfo { + frequency: Frequency { + times_per_block_range: 10..11, + chance_per_block: None, + }, + start_keys: 3, + extra_keys: [( + Purpose::TRANSFER, + [(SecurityLevel::CRITICAL, vec![KeyType::ECDSA_SECP256K1])].into(), + )] + .into(), + start_balance_range: dash_to_duffs!(200)..=dash_to_duffs!(200), + }, + identity_contract_nonce_gaps: None, + signer: None, + }, + total_hpmns: 100, + extra_normal_mns: 0, + validator_quorum_count: 24, + chain_lock_quorum_count: 24, + upgrading_info: None, + + proposer_strategy: Default::default(), + rotate_quorums: false, + failure_testing: None, + query_testing: None, + verify_state_transition_results: true, + ..Default::default() + }; + + let minute_in_ms = 1000 * 60; + let config = PlatformConfig { + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), + execution: ExecutionConfig { + verify_sum_trees: true, + + ..Default::default() + }, + block_spacing_ms: minute_in_ms, + testing_configs: PlatformTestConfig::default_minimal_verifications(), + ..Default::default() + }; + + let mut platform = TestPlatformBuilder::new() + .with_config(config.clone()) + .with_initial_protocol_version(TEST_PLATFORM_V3.protocol_version) + .build_with_mock_rpc(); + + platform + .core_rpc + .expect_send_raw_transaction() + .returning(move |_| Ok(Txid::all_zeros())); + + let chain_locked_height = 1; + + // Have to go with a complicated shared object for the core state because we need to change + // rpc response along the way but we can't mutate `platform.core_rpc` later + // because platform reference is moved into the AbciApplication. + let shared_core_state = Arc::new(Mutex::new(CoreState { + asset_unlock_statuses: BTreeMap::new(), + chain_lock: ChainLock { + block_height: chain_locked_height, + block_hash: BlockHash::from_byte_array([1; 32]), + signature: BLSSignature::from([2; 96]), + }, + })); + + // Set up Core RPC responses + { + let core_state = shared_core_state.clone(); + + platform + .core_rpc + .expect_get_asset_unlock_statuses() + .returning(move |indices, _| { + Ok(indices + .iter() + .map(|index| { + core_state + .lock() + .unwrap() + .asset_unlock_statuses + .get(index) + .cloned() + .unwrap() + }) + .collect()) + }); + + let core_state = shared_core_state.clone(); + platform + .core_rpc + .expect_get_best_chain_lock() + .returning(move || Ok(core_state.lock().unwrap().chain_lock.clone())); + } + + // Run first two blocks: + // - Block 1: creates identity + // - Block 2: tops up identity + let ChainExecutionOutcome { + abci_app, + proposers, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, + current_proposer_versions, + end_time_ms, + identity_nonce_counter, + identity_contract_nonce_counter, + instant_lock_quorums, + identities, + signer, + .. + } = { + let outcome = run_chain_for_strategy( + &mut platform, + 2, + start_strategy, + config.clone(), + 1, + &mut None, + ); + + for tx_results_per_block in outcome.state_transition_results_per_block.values() { + for (state_transition, result) in tx_results_per_block { + assert_eq!( + result.code, 0, + "state transition got code {} : {:?}", + result.code, state_transition + ); + } + } + + // Withdrawal transactions are not populated to block execution context yet + assert_eq!(outcome.withdrawals.len(), 0); + + // Withdrawal documents with pooled status should exist. + let withdrawal_documents_pooled = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::POOLED.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + assert!(withdrawal_documents_pooled.is_empty()); + + let locked_amount = outcome + .abci_app + .platform + .drive + .grove_get_sum_tree_total_value( + (&get_withdrawal_root_path()).into(), + &WITHDRAWAL_TRANSACTIONS_SUM_AMOUNT_TREE_KEY, + DirectQueryType::StatefulDirectQuery, + None, + &mut vec![], + &platform_version.drive, + ) + .expect("expected to get locked amount"); + + assert_eq!(locked_amount, 0); + + let pooled_withdrawals = withdrawal_documents_pooled.len(); + + assert_eq!(pooled_withdrawals, 0); + + let total_credits_balance = outcome + .abci_app + .platform + .drive + .calculate_total_credits_balance(None, &platform_version.drive) + .expect("expected to get total credits balance"); + + assert_eq!( + total_credits_balance.total_identity_balances, + 409997575280380 + ); // Around 4100 Dash. + + assert_eq!( + total_credits_balance.total_in_trees().unwrap(), + 410000000000000 + ); // Around 4100 Dash. + + let total_credits_in_platform = outcome + .abci_app + .platform + .drive + .grove_get_raw_value_u64_from_encoded_var_vec( + (&misc_path()).into(), + TOTAL_SYSTEM_CREDITS_STORAGE_KEY, + DirectQueryType::StatefulDirectQuery, + None, + &mut vec![], + &platform_version.drive, + ) + .expect("expected to get total credits in platform"); + + assert_eq!(total_credits_in_platform, Some(410000000000000)); + + outcome + }; + + let continue_strategy_only_withdrawal = NetworkStrategy { + strategy: Strategy { + start_contracts: vec![], + operations: vec![Operation { + op_type: OperationType::IdentityWithdrawal( + dash_to_credits!(0.0025)..=dash_to_credits!(0.0025), + ), + frequency: Frequency { + times_per_block_range: 40..41, // 0.0025 Dash x 40 Withdrawals = 0.1 Dash + chance_per_block: None, + }, + }], + start_identities: StartIdentities::default(), + identity_inserts: IdentityInsertInfo::default(), + identity_contract_nonce_gaps: None, + signer: Some(signer.clone()), + }, + total_hpmns: 100, + extra_normal_mns: 0, + validator_quorum_count: 24, + chain_lock_quorum_count: 24, + upgrading_info: None, + + proposer_strategy: Default::default(), + rotate_quorums: false, + failure_testing: None, + query_testing: None, + verify_state_transition_results: true, + ..Default::default() + }; + + let continue_strategy_no_operations = NetworkStrategy { + strategy: Strategy { + start_contracts: vec![], + operations: vec![], + start_identities: StartIdentities::default(), + identity_inserts: IdentityInsertInfo::default(), + identity_contract_nonce_gaps: None, + signer: Some(signer), + }, + total_hpmns: 100, + extra_normal_mns: 0, + validator_quorum_count: 24, + chain_lock_quorum_count: 24, + upgrading_info: None, + + proposer_strategy: Default::default(), + rotate_quorums: false, + failure_testing: None, + query_testing: None, + verify_state_transition_results: true, + ..Default::default() + }; + + // Run Block 3-23 onwards: initiates withdrawals + let ChainExecutionOutcome { + abci_app, + proposers, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, + current_proposer_versions, + end_time_ms, + identity_nonce_counter, + identity_contract_nonce_counter, + instant_lock_quorums, + identities, + .. + } = { + let outcome = continue_chain_for_strategy( + abci_app, + ChainExecutionParameters { + block_start: 3, + core_height_start: 1, + block_count: 20, + proposers, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, + current_proposer_versions: Some(current_proposer_versions), + current_identity_nonce_counter: identity_nonce_counter, + current_identity_contract_nonce_counter: identity_contract_nonce_counter, + current_votes: BTreeMap::default(), + start_time_ms: GENESIS_TIME_MS, + current_time_ms: end_time_ms, + instant_lock_quorums, + current_identities: identities, + }, + continue_strategy_only_withdrawal.clone(), + config.clone(), + StrategyRandomness::SeedEntropy(2), + ); + + for tx_results_per_block in outcome.state_transition_results_per_block.values() { + assert_eq!(tx_results_per_block.len(), 20); + for (state_transition, result) in tx_results_per_block { + assert_eq!( + result.code, 0, + "state transition got code {} : {:?}", + result.code, state_transition + ); + } + } + + // Withdrawal documents with pooled status should not exist. + let withdrawal_documents_pooled = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::POOLED.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + // We should have 4 pooled, which is the limit per block + assert_eq!(withdrawal_documents_pooled.len(), 4); + + // Withdrawal documents with queued status should exist. + let withdrawal_documents_queued = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::QUEUED.into(), + 10000, + None, + platform_version, + ) + .unwrap(); + + // We have 320 queued + assert_eq!(withdrawal_documents_queued.len(), 320); + + // Withdrawal documents with queued status should exist. + let withdrawal_documents_completed = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::COMPLETE.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + // None have completed because core didn't acknowledge them + assert_eq!(withdrawal_documents_completed.len(), 0); + + // Withdrawal documents with EXPIRED status should not exist yet. + let withdrawal_documents_expired = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::EXPIRED.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + // We have none expired yet + assert_eq!(withdrawal_documents_expired.len(), 0); + + // Withdrawal documents with broadcasted status should exist. + let withdrawal_documents_broadcasted = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::BROADCASTED.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + // We have 76 broadcasted (4 pooled + 76 broadcasted = 80 total for 4 per block in 20 blocks) + assert_eq!(withdrawal_documents_broadcasted.len(), 76); + + let locked_amount = outcome + .abci_app + .platform + .drive + .grove_get_sum_tree_total_value( + (&get_withdrawal_root_path()).into(), + &WITHDRAWAL_TRANSACTIONS_SUM_AMOUNT_TREE_KEY, + DirectQueryType::StatefulDirectQuery, + None, + &mut vec![], + &platform_version.drive, + ) + .expect("expected to get locked amount"); + + // 0.2 is 0.0025 amount * 80 withdrawals + assert_eq!(locked_amount, dash_to_credits!(0.2) as i64); + + outcome + }; + + let hour_in_ms = 1000 * 60 * 60; + + let outcome = continue_chain_for_strategy( + abci_app, + ChainExecutionParameters { + block_start: 23, + core_height_start: 1, + block_count: 88, + proposers, + validator_quorums: quorums, + current_validator_quorum_hash: current_quorum_hash, + current_proposer_versions: Some(current_proposer_versions), + current_identity_nonce_counter: identity_nonce_counter, + current_identity_contract_nonce_counter: identity_contract_nonce_counter, + current_votes: BTreeMap::default(), + start_time_ms: GENESIS_TIME_MS, + current_time_ms: end_time_ms + 1000, + instant_lock_quorums, + current_identities: identities, + }, + continue_strategy_no_operations.clone(), + PlatformConfig { + validator_set: ValidatorSetConfig::default_100_67(), + chain_lock: ChainLockConfig::default_100_67(), + instant_lock: InstantLockConfig::default_100_67(), + execution: ExecutionConfig { + verify_sum_trees: true, + + ..Default::default() + }, + block_spacing_ms: hour_in_ms, + testing_configs: PlatformTestConfig::default_minimal_verifications(), + ..Default::default() + }, + StrategyRandomness::SeedEntropy(9), + ); + + // We should have unlocked the amounts by now + let locked_amount = outcome + .abci_app + .platform + .drive + .grove_get_sum_tree_total_value( + (&get_withdrawal_root_path()).into(), + &WITHDRAWAL_TRANSACTIONS_SUM_AMOUNT_TREE_KEY, + DirectQueryType::StatefulDirectQuery, + None, + &mut vec![], + &platform_version.drive, + ) + .expect("expected to get locked amount"); + + assert_eq!(locked_amount, 18000000000); + + // Withdrawal documents with pooled status should not exist. + let withdrawal_documents_pooled = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::POOLED.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + // None are currently pooled since we finished the queue + assert!(withdrawal_documents_pooled.is_empty()); + + // Withdrawal documents with queued status should exist. + let withdrawal_documents_queued = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::QUEUED.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + // Queue has been finished + assert_eq!(withdrawal_documents_queued.len(), 0); + + // Withdrawal documents with queued status should exist. + let withdrawal_documents_completed = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::COMPLETE.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + // None have completed because core didn't acknowledge them + assert_eq!(withdrawal_documents_completed.len(), 0); + + // Withdrawal documents with EXPIRED status should not exist yet. + let withdrawal_documents_expired = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::EXPIRED.into(), + DEFAULT_QUERY_LIMIT, + None, + platform_version, + ) + .unwrap(); + + // We have none expired yet, because the core height never went up + assert_eq!(withdrawal_documents_expired.len(), 0); + + // Withdrawal documents with broadcasted status should exist. + let withdrawal_documents_broadcasted = outcome + .abci_app + .platform + .drive + .fetch_oldest_withdrawal_documents_by_status( + withdrawals_contract::WithdrawalStatus::BROADCASTED.into(), + 1000, + None, + platform_version, + ) + .unwrap(); + + assert_eq!(withdrawal_documents_broadcasted.len(), 400); + } +} diff --git a/packages/rs-drive-proof-verifier/Cargo.toml b/packages/rs-drive-proof-verifier/Cargo.toml index 9c35e7fc82..3eaa9f3bdf 100644 --- a/packages/rs-drive-proof-verifier/Cargo.toml +++ b/packages/rs-drive-proof-verifier/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "drive-proof-verifier" -version = "1.3.1" +version = "1.5.0" edition = "2021" rust-version.workspace = true @@ -15,6 +15,7 @@ mocks = [ "dep:platform-serialization-derive", "dep:platform-serialization", "dpp/document-serde-conversion", + "indexmap/serde", ] [dependencies] @@ -28,11 +29,12 @@ dpp = { path = "../rs-dpp", features = [ "bls-signatures", "document-value-conversion", "extended-document", + "core-types-serialization", ], default-features = false } bincode = { version = "2.0.0-rc.3", features = ["serde"], optional = true } platform-serialization-derive = { path = "../rs-platform-serialization-derive", optional = true } platform-serialization = { path = "../rs-platform-serialization", optional = true } -tenderdash-abci = { git = "https://github.com/dashpay/rs-tenderdash-abci", version = "1.2.0+1.3.0", tag = "v1.2.0+1.3.0", features = [ +tenderdash-abci = { git = "https://github.com/dashpay/rs-tenderdash-abci", version = "1.2.1", tag = "v1.2.1+1.3.0", features = [ "crypto", ], default-features = false } tracing = { version = "0.1.37" } @@ -41,4 +43,5 @@ serde_json = { version = "1.0.103", features = [ "preserve_order", ], optional = true } hex = { version = "0.4.3" } -derive_more = { version = "0.99.11" } +indexmap = { version = "2.6.0" } +derive_more = { version = "1.0", features = ["from"] } diff --git a/packages/rs-drive-proof-verifier/src/error.rs b/packages/rs-drive-proof-verifier/src/error.rs index 02752a4b12..3203eb7317 100644 --- a/packages/rs-drive-proof-verifier/src/error.rs +++ b/packages/rs-drive-proof-verifier/src/error.rs @@ -106,6 +106,10 @@ pub enum ContextProviderError { /// Core Fork Error #[error("activation fork error: {0}")] ActivationForkError(String), + + /// Async error, eg. when tokio runtime fails + #[error("async error: {0}")] + AsyncError(String), } impl From for Error { diff --git a/packages/rs-drive-proof-verifier/src/lib.rs b/packages/rs-drive-proof-verifier/src/lib.rs index 7e28b6691f..dfa6e41443 100644 --- a/packages/rs-drive-proof-verifier/src/lib.rs +++ b/packages/rs-drive-proof-verifier/src/lib.rs @@ -13,7 +13,10 @@ pub use proof::{FromProof, Length}; #[cfg(feature = "mocks")] pub use provider::MockContextProvider; pub use provider::{ContextProvider, DataContractProvider}; +/// From Request pub mod from_request; +/// Implementation of unproved verification +pub mod unproved; // Needed for #[derive(PlatformSerialize, PlatformDeserialize)] #[cfg(feature = "mocks")] diff --git a/packages/rs-drive-proof-verifier/src/proof.rs b/packages/rs-drive-proof-verifier/src/proof.rs index f3a256e301..3685df1779 100644 --- a/packages/rs-drive-proof-verifier/src/proof.rs +++ b/packages/rs-drive-proof-verifier/src/proof.rs @@ -2,13 +2,16 @@ use crate::from_request::TryFromRequest; use crate::provider::DataContractProvider; use crate::verify::verify_tenderdash_proof; use crate::{types, types::*, ContextProvider, Error}; +use dapi_grpc::platform::v0::get_evonodes_proposed_epoch_blocks_by_range_request::get_evonodes_proposed_epoch_blocks_by_range_request_v0::Start; use dapi_grpc::platform::v0::get_identities_contract_keys_request::GetIdentitiesContractKeysRequestV0; use dapi_grpc::platform::v0::get_path_elements_request::GetPathElementsRequestV0; use dapi_grpc::platform::v0::get_protocol_version_upgrade_vote_status_request::{ self, GetProtocolVersionUpgradeVoteStatusRequestV0, }; use dapi_grpc::platform::v0::security_level_map::KeyKindRequestType as GrpcKeyKind; -use dapi_grpc::platform::v0::{get_contested_resource_identity_votes_request, get_data_contract_history_request, get_data_contract_request, get_data_contracts_request, get_epochs_info_request, get_evonodes_proposed_epoch_blocks_by_ids_request, get_evonodes_proposed_epoch_blocks_by_range_request, get_identities_balances_request, get_identities_contract_keys_request, get_identity_balance_and_revision_request, get_identity_balance_request, get_identity_by_public_key_hash_request, get_identity_contract_nonce_request, get_identity_keys_request, get_identity_nonce_request, get_identity_request, get_path_elements_request, get_prefunded_specialized_balance_request, GetContestedResourceVotersForIdentityRequest, GetContestedResourceVotersForIdentityResponse, GetPathElementsRequest, GetPathElementsResponse, GetProtocolVersionUpgradeStateRequest, GetProtocolVersionUpgradeStateResponse, GetProtocolVersionUpgradeVoteStatusRequest, GetProtocolVersionUpgradeVoteStatusResponse, Proof, ResponseMetadata}; +use dapi_grpc::platform::v0::{ + get_contested_resource_identity_votes_request, get_data_contract_history_request, get_data_contract_request, get_data_contracts_request, get_epochs_info_request, get_evonodes_proposed_epoch_blocks_by_ids_request, get_evonodes_proposed_epoch_blocks_by_range_request, get_identities_balances_request, get_identities_contract_keys_request, get_identity_balance_and_revision_request, get_identity_balance_request, get_identity_by_public_key_hash_request, get_identity_contract_nonce_request, get_identity_keys_request, get_identity_nonce_request, get_identity_request, get_path_elements_request, get_prefunded_specialized_balance_request, GetContestedResourceVotersForIdentityRequest, GetContestedResourceVotersForIdentityResponse, GetPathElementsRequest, GetPathElementsResponse, GetProtocolVersionUpgradeStateRequest, GetProtocolVersionUpgradeStateResponse, GetProtocolVersionUpgradeVoteStatusRequest, GetProtocolVersionUpgradeVoteStatusResponse, Proof, ResponseMetadata +}; use dapi_grpc::platform::{ v0::{self as platform, key_request_type, KeyRequestType as GrpcKeyType}, VersionedGrpcResponse, @@ -35,15 +38,15 @@ use drive::drive::identity::key::fetch::{ use drive::drive::Drive; use drive::error::proof::ProofError; use drive::query::contested_resource_votes_given_by_identity_query::ContestedResourceVotesGivenByIdentityQuery; +use drive::query::proposer_block_count_query::ProposerQueryType; use drive::query::vote_poll_contestant_votes_query::ContestedDocumentVotePollVotesDriveQuery; use drive::query::vote_poll_vote_state_query::ContestedDocumentVotePollDriveQuery; use drive::query::vote_polls_by_document_type_query::VotePollsByDocumentTypeQuery; use drive::query::{DriveDocumentQuery, VotePollsByEndDateDriveQuery}; +use indexmap::IndexMap; use std::array::TryFromSliceError; use std::collections::BTreeMap; use std::num::TryFromIntError; -use dapi_grpc::platform::v0::get_evonodes_proposed_epoch_blocks_by_range_request::get_evonodes_proposed_epoch_blocks_by_range_request_v0::Start; -use drive::query::proposer_block_count_query::ProposerQueryType; /// Parse and verify the received proof and retrieve the requested object, if any. /// @@ -78,7 +81,7 @@ pub trait FromProof { /// /// * `Ok(Some(object, metadata))` when the requested object was found in the proof. /// * `Ok(None)` when the requested object was not found in the proof; this can be interpreted as proof of non-existence. - /// For collections, returns Ok(None) if none of the requested objects were found. + /// For collections, returns Ok(None) if none of the requested objects were found. /// * `Err(Error)` when either the provided data is invalid or proof validation failed. fn maybe_from_proof<'a, I: Into, O: Into>( request: I, @@ -108,7 +111,7 @@ pub trait FromProof { /// /// * `Ok(Some((object, metadata)))` when the requested object was found in the proof. /// * `Ok(None)` when the requested object was not found in the proof; this can be interpreted as proof of non-existence. - /// For collections, returns Ok(None) if none of the requested objects were found. + /// For collections, returns Ok(None) if none of the requested objects were found. /// * `Err(Error)` when either the provided data is invalid or proof validation failed. fn maybe_from_proof_with_metadata<'a, I: Into, O: Into>( request: I, @@ -368,33 +371,13 @@ impl FromProof for IdentityPublicKeys { } }; - let key_request = match parse_key_request_type(&request_type)? { - KeyRequestType::SpecificKeys(specific_keys) => { - IdentityKeysRequest::new_specific_keys_query(&identity_id, specific_keys) - } - KeyRequestType::AllKeys => IdentityKeysRequest::new_all_keys_query(&identity_id, None), - KeyRequestType::SearchKey(criteria) => IdentityKeysRequest { - identity_id, - request_type: KeyRequestType::SearchKey(criteria), - limit, - offset, - }, - KeyRequestType::ContractBoundKey(id, purpose, kind) => IdentityKeysRequest { - identity_id, - request_type: KeyRequestType::ContractBoundKey(id, purpose, kind), - limit, - offset, - }, - KeyRequestType::ContractDocumentTypeBoundKey(id, s, purpose, kind) => { - IdentityKeysRequest { - identity_id, - request_type: KeyRequestType::ContractDocumentTypeBoundKey( - id, s, purpose, kind, - ), - limit, - offset, - } - } + let request_type = parse_key_request_type(&request_type)?; + + let key_request = IdentityKeysRequest { + identity_id, + request_type, + limit, + offset, }; tracing::debug!(?identity_id, "checking proof of identity keys"); @@ -849,25 +832,22 @@ impl FromProof for DataContracts { })?; verify_tenderdash_proof(proof, mtd, &root_hash, provider)?; - - let maybe_contracts: Option>> = - if !contracts.is_empty() { - let contracts: DataContracts = contracts - .into_iter() - .try_fold(DataContracts::new(), |mut acc, (k, v)| { - Identifier::from_bytes(&k).map(|id| { - acc.insert(id, v); - acc - }) - }) - .map_err(|e| Error::ResultEncodingError { + let contracts = contracts + .into_iter() + .map(|(k, v)| { + Identifier::from_bytes(&k).map(|id| (id, v)).map_err(|e| { + Error::ResultEncodingError { error: e.to_string(), - })?; + } + }) + }) + .collect::>()?; - Some(contracts) - } else { - None - }; + let maybe_contracts = if contracts.is_empty() { + None + } else { + Some(contracts) + }; Ok((maybe_contracts, mtd.clone(), proof.clone())) } @@ -922,7 +902,11 @@ impl FromProof for DataContractHistory verify_tenderdash_proof(proof, mtd, &root_hash, provider)?; - Ok((maybe_history, mtd.clone(), proof.clone())) + Ok(( + maybe_history.map(IndexMap::from_iter), + mtd.clone(), + proof.clone(), + )) } } @@ -1005,13 +989,13 @@ impl FromProof for ExtendedEpochInfo { provider, )?; - if let Some(mut e) = epochs.0 { + if let Some(e) = epochs.0 { if e.len() != 1 { return Err(Error::RequestError { error: format!("expected 1 epoch, got {}", e.len()), }); } - let epoch = e.pop_first().and_then(|v| v.1); + let epoch = e.into_iter().next().and_then(|v| v.1); Ok((epoch, epochs.1, epochs.2)) } else { Ok((None, epochs.1, epochs.2)) @@ -1074,7 +1058,7 @@ impl FromProof for ExtendedEpochInfos { (info.index, Some(v)) }) - .collect::>>(); + .collect::(); verify_tenderdash_proof(proof, mtd, &root_hash, provider)?; @@ -1221,10 +1205,11 @@ impl FromProof for Elements { let (root_hash, objects) = Drive::verify_elements(&proof.grovedb_proof, path, keys, platform_version)?; + let elements: Elements = Elements::from_iter(objects); verify_tenderdash_proof(proof, mtd, &root_hash, provider)?; - Ok((objects.into_option(), mtd.clone(), proof.clone())) + Ok((elements.into_option(), mtd.clone(), proof.clone())) } } @@ -1396,8 +1381,7 @@ impl FromProof for ContestedResources { verify_tenderdash_proof(proof, mtd, &root_hash, provider)?; - let resources: ContestedResources = - items.into_iter().map(ContestedResource::Value).collect(); + let resources: ContestedResources = items.into_iter().map(ContestedResource).collect(); Ok((resources.into_option(), mtd.clone(), proof.clone())) } @@ -1656,23 +1640,25 @@ impl FromProof for Vote { } }; - let (mut maybe_votes, mtd, proof) = - ResourceVotesByIdentity::maybe_from_proof_with_metadata( - request, - response, - network, - platform_version, - provider, - )?; + let (maybe_votes, mtd, proof) = ResourceVotesByIdentity::maybe_from_proof_with_metadata( + request, + response, + network, + platform_version, + provider, + )?; - let (id, vote) = match maybe_votes.as_mut() { + let (id, vote) = match maybe_votes { Some(v) if v.len() > 1 => { return Err(Error::ResponseDecodeError { error: format!("expected 1 vote, got {}", v.len()), }) } Some(v) if v.is_empty() => return Ok((None, mtd, proof)), - Some(v) => v.pop_first().expect("is_empty() must detect empty map"), + Some(v) => v + .into_iter() + .next() + .expect("is_empty() must detect empty map"), None => return Ok((None, mtd, proof)), }; @@ -1734,7 +1720,6 @@ impl FromProof for TotalCreditsInPla )) } } - impl FromProof for ProposerBlockCounts { type Request = platform::GetEvonodesProposedEpochBlocksByIdsRequest; type Response = platform::GetEvonodesProposedEpochBlocksResponse; @@ -1868,6 +1853,8 @@ fn u32_to_u16_opt(i: u32) -> Result, Error> { pub trait Length { /// Return number of non-None elements in the data structure fn count_some(&self) -> usize; + /// Return number of all elements in the data structure, including None + fn count(&self) -> usize; } impl Length for Option { @@ -1877,24 +1864,52 @@ impl Length for Option { Some(i) => i.count_some(), } } + fn count(&self) -> usize { + match self { + None => 0, + Some(i) => i.count(), + } + } } impl Length for Vec> { fn count_some(&self) -> usize { self.iter().filter(|v| v.is_some()).count() } + + fn count(&self) -> usize { + self.len() + } } impl Length for Vec<(K, Option)> { fn count_some(&self) -> usize { self.iter().filter(|(_, v)| v.is_some()).count() } + + fn count(&self) -> usize { + self.len() + } } impl Length for BTreeMap> { fn count_some(&self) -> usize { self.values().filter(|v| v.is_some()).count() } + + fn count(&self) -> usize { + self.len() + } +} + +impl Length for IndexMap> { + fn count_some(&self) -> usize { + self.values().filter(|v| v.is_some()).count() + } + + fn count(&self) -> usize { + self.len() + } } /// Implement Length trait for a type @@ -1904,16 +1919,24 @@ impl Length for BTreeMap> { /// * `$object`: The type for which to implement Length trait /// * `$len`: A closure that returns the length of the object; if ommitted, defaults to 1 macro_rules! define_length { - ($object:ty,$len:expr) => { + ($object:ty,$some:expr,$counter:expr) => { impl Length for $object { fn count_some(&self) -> usize { #[allow(clippy::redundant_closure_call)] - $len(self) + $some(self) + } + + fn count(&self) -> usize { + #[allow(clippy::redundant_closure_call)] + $counter(self) } } }; + ($object:ty,$some:expr) => { + define_length!($object, $some, $some); + }; ($object:ty) => { - define_length!($object, |_| 1); + define_length!($object, |_| 1, |_| 1); }; } @@ -1923,22 +1946,30 @@ define_length!(Document); define_length!(Identity); define_length!(IdentityBalance); define_length!(IdentityBalanceAndRevision); -define_length!(IdentitiesContractKeys, |x: &IdentitiesContractKeys| x - .values() - .map(|v| v.count_some()) - .sum()); +define_length!( + IdentitiesContractKeys, + |x: &IdentitiesContractKeys| x.values().map(|v| v.count_some()).sum(), + |x: &IdentitiesContractKeys| x.len() +); define_length!(ContestedResources, |x: &ContestedResources| x.0.len()); define_length!(Contenders, |x: &Contenders| x.contenders.len()); define_length!(Voters, |x: &Voters| x.0.len()); define_length!( VotePollsGroupedByTimestamp, - |x: &VotePollsGroupedByTimestamp| x.0.iter().map(|v| v.1.len()).sum() + |x: &VotePollsGroupedByTimestamp| x.0.iter().map(|v| v.1.len()).sum(), + |x: &VotePollsGroupedByTimestamp| x.0.len() ); + +/// Convert a type into an Option trait IntoOption where Self: Sized, { - /// For zero-length data structures, return None, otherwise return Some(self) + /// For zero-length data structures, return None, otherwise return Some(self). + /// + /// In case of a zero-length data structure, the function returns None. + /// Otherwise, it returns Some(self), even it all values are None. This is to ensure that proof of absence + /// preserves the keys that are not present in the data structure. fn into_option(self) -> Option; } @@ -1947,7 +1978,7 @@ impl IntoOption for L { where Self: Sized, { - if self.count_some() == 0 { + if self.count() == 0 { None } else { Some(self) diff --git a/packages/rs-drive-proof-verifier/src/provider.rs b/packages/rs-drive-proof-verifier/src/provider.rs index ecead85994..e7eafd2e45 100644 --- a/packages/rs-drive-proof-verifier/src/provider.rs +++ b/packages/rs-drive-proof-verifier/src/provider.rs @@ -47,7 +47,7 @@ pub trait ContextProvider: Send + Sync { /// # Returns /// /// * `Ok(Option>)`: On success, returns the data contract if it exists, or `None` if it does not. - /// We use Arc to avoid copying the data contract. + /// We use Arc to avoid copying the data contract. /// * `Err(Error)`: On failure, returns an error indicating why the operation failed. fn get_data_contract( &self, diff --git a/packages/rs-drive-proof-verifier/src/types.rs b/packages/rs-drive-proof-verifier/src/types.rs index 1a6fe75d88..40fa528a54 100644 --- a/packages/rs-drive-proof-verifier/src/types.rs +++ b/packages/rs-drive-proof-verifier/src/types.rs @@ -5,6 +5,10 @@ //! In this case, the [FromProof](crate::FromProof) trait is implemented for dedicated object type //! defined in this module. +mod evonode_status; + +use dpp::block::block_info::BlockInfo; +use dpp::core_types::validator_set::ValidatorSet; use dpp::data_contract::document_type::DocumentType; use dpp::fee::Credits; use dpp::platform_value::Value; @@ -13,6 +17,7 @@ use dpp::version::PlatformVersion; pub use dpp::version::ProtocolVersionVoteCount; use dpp::voting::contender_structs::{Contender, ContenderWithSerializedDocument}; use dpp::voting::vote_choices::resource_vote_choice::ResourceVoteChoice; +use dpp::voting::vote_info_storage::contested_document_vote_poll_winner_info::ContestedDocumentVotePollWinnerInfo; use dpp::voting::vote_polls::contested_document_resource_vote_poll::ContestedDocumentResourceVotePoll; use dpp::voting::vote_polls::VotePoll; use dpp::voting::votes::resource_vote::ResourceVote; @@ -24,12 +29,12 @@ use dpp::{ prelude::{DataContract, Identifier, IdentityPublicKey, Revision}, util::deserializer::ProtocolVersion, }; +use drive::grovedb::query_result_type::Path; use drive::grovedb::Element; +// IndexMap is exposed to the public API +pub use indexmap::IndexMap; use std::collections::{BTreeMap, BTreeSet}; -use dpp::block::block_info::BlockInfo; -use dpp::voting::vote_info_storage::contested_document_vote_poll_winner_info::ContestedDocumentVotePollWinnerInfo; -use drive::grovedb::query_result_type::Path; #[cfg(feature = "mocks")] use { bincode::{Decode, Encode}, @@ -38,42 +43,54 @@ use { platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}, }; +pub use evonode_status::*; + /// A data structure that holds a set of objects of a generic type `O`, indexed by a key of type `K`. /// /// This type is typically returned by functions that operate on multiple objects, such as fetching multiple objects /// from a server using [`FetchMany`](dash_sdk::platform::FetchMany) or parsing a proof that contains multiple objects /// using [`FromProof`](crate::FromProof). /// -/// Each key in the `RetrievedObjects` corresponds to an object of generic type `O`. -/// If an object is found for a given key, the value is `Some(object)`. -/// If no object is found for a given key, the value is `None`. +/// Each key `K` in the `RetrievedObjects` corresponds to zero or one object of generic type `O`: +/// * if an object is found for a given key, the value is `Some(object)`, +/// * if no object is found for a given key, the value is `None`; this can be interpreted as a proof of absence. +/// +/// This data structure preserves order of objects insertion. However, actual order of objects depends on the order of +/// objects returned by Dash Drive, which is not always guaranteed to be correct. +/// You can sort the objects by key if you need a specific order; see [`IndexMap::sort_keys`] and similar methods. +/// +/// `RetrievedObjects` is a wrapper around the [`IndexMap`] type. /// /// # Generic Type Parameters /// /// * `K`: The type of the keys in the map. /// * `O`: The type of the objects in the map. -pub type RetrievedObjects = BTreeMap>; +pub type RetrievedObjects = IndexMap>; -/// A data structure that holds a set of objects of a generic type `O`, indexed by a key of type `K`. +/// A data structure that holds a set of values of a generic type `I`, indexed by a key of type `K`. /// /// This type is typically returned by functions that operate on multiple objects, such as fetching multiple objects /// from a server using [`FetchMany`](dash_sdk::platform::FetchMany) or parsing a proof that contains multiple objects /// using [`FromProof`](crate::FromProof). /// -/// Each key in the `RetrievedObjects` corresponds to an object of generic type `O`. -/// If a value is found for a given key, the value is `value`. -/// If no value is found for a given key, the value is `0`. +/// Each key in this data structure corresponds to an existing value of generic type `I`. It differs from +/// [`RetrievedObjects`] in that it does not contain `Option`, but only `I`, so it cannot be interpreted as a +/// proof of absence. +/// +/// This data structure preserves the order of object insertion. However, the actual order of objects depends on the +/// order of objects returned by Dash Drive, which is not always guaranteed to be correct. +/// You can sort the objects by key if you need a specific order; see [`IndexMap::sort_keys`] and similar methods. /// /// # Generic Type Parameters /// /// * `K`: The type of the keys in the map. -/// * `I`: The type of the integer in the map. -pub type RetrievedIntegerValue = BTreeMap; +/// * `I`: The type of the integer values in the map. +pub type RetrievedValues = IndexMap; /// History of a data contract. /// /// Contains a map of data contract revisions to data contracts. -pub type DataContractHistory = BTreeMap; +pub type DataContractHistory = RetrievedValues; /// Multiple data contracts. /// /// Mapping between data contract IDs and data contracts. @@ -219,11 +236,8 @@ pub struct ElementFetchRequestItem(pub Element); pub type IdentityBalanceAndRevision = (u64, Revision); /// Contested resource values. -#[derive(Debug, derive_more::From, Clone, PartialEq)] -pub enum ContestedResource { - /// Generic [Value] - Value(Value), -} +#[derive(Debug, Clone, PartialEq)] +pub struct ContestedResource(pub Value); impl ContestedResource { /// Get the value. @@ -238,14 +252,9 @@ impl ContestedResource { ) } } - -impl TryInto for ContestedResource { - type Error = crate::Error; - - fn try_into(self) -> Result { - match self { - ContestedResource::Value(value) => Ok(value), - } +impl From for Value { + fn from(resource: ContestedResource) -> Self { + resource.0 } } @@ -256,9 +265,7 @@ impl PlatformVersionEncode for ContestedResource { encoder: &mut E, _platform_version: &platform_version::PlatformVersion, ) -> Result<(), bincode::error::EncodeError> { - match self { - ContestedResource::Value(value) => value.encode(encoder), - } + self.0.encode(encoder) } } @@ -268,7 +275,7 @@ impl PlatformVersionedDecode for ContestedResource { decoder: &mut D, _platform_version: &platform_version::PlatformVersion, ) -> Result { - Ok(ContestedResource::Value(Value::decode(decoder)?)) + Ok(ContestedResource(Value::decode(decoder)?)) } } @@ -325,6 +332,74 @@ pub struct ContestedVote(ContestedDocumentResourceVotePoll, ResourceVoteChoice); /// Votes casted by some identity. pub type ResourceVotesByIdentity = RetrievedObjects; +/// Represents the current state of quorums in the platform. +/// +/// This struct holds various information related to the current quorums, +/// including the list of quorum hashes, the current active quorum hash, +/// and details about the validators and their statuses. +/// +/// # Fields +/// +/// - `quorum_hashes`: A list of 32-byte hashes representing the active quorums. +/// - `current_quorum_hash`: A 32-byte hash identifying the currently active quorum. +/// This is the quorum that is currently responsible for platform operations. +/// - `validator_sets`: A collection of [`ValidatorSet`] structs, each representing +/// a set of validators for different quorums. This provides detailed information +/// about the members of each quorum. +/// - `last_block_proposer`: A vector of bytes representing the identity of the last +/// block proposer. This is typically the ProTxHash of the masternode that proposed +/// the most recent platform block. +/// - `last_platform_block_height`: The height of the most recent platform block. +/// This indicates the latest block height at the platform level, which may differ +/// from the core blockchain height. +/// - `last_core_block_height`: The height of the most recent core blockchain block +/// associated with the platform. This is the height of the blockchain where the +/// platform block was anchored. +/// +/// # Derives +/// +/// - `Debug`: Provides a debug representation of the `CurrentQuorumsInfo` struct, useful +/// for logging and debugging purposes. +/// - `Clone`: Allows the `CurrentQuorumsInfo` struct to be cloned, creating a deep copy +/// of its contents. +/// +/// # Conditional Derives +/// +/// When the `mocks` feature is enabled, the following derives and attributes are applied: +/// +/// - `Encode`: Allows the struct to be serialized into a binary format using the `bincode` crate. +/// - `Decode`: Allows the struct to be deserialized from a binary format using the `bincode` crate. +/// - `PlatformSerialize`: Enables serialization of the struct using the platform-specific +/// serialization format. +/// - `PlatformDeserialize`: Enables deserialization of the struct using the platform-specific +/// deserialization format. +/// - `platform_serialize(unversioned)`: Specifies that the struct should be serialized +/// without including a version field in the serialized data. +/// +/// This structure is typically used in scenarios where the state of the current quorums +/// needs to be accessed, for example, when validating or proposing new blocks, or when +/// determining the active set of validators. +#[derive(Debug, Clone)] +#[cfg_attr( + feature = "mocks", + derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), + platform_serialize(unversioned) +)] +pub struct CurrentQuorumsInfo { + /// A list of 32-byte hashes representing the active quorums. + pub quorum_hashes: Vec<[u8; 32]>, + /// A 32-byte hash identifying the currently active quorum. + pub current_quorum_hash: [u8; 32], + /// A collection of [`ValidatorSet`] structs, each representing a set of validators for different quorums. + pub validator_sets: Vec, + /// A vector of bytes representing the identity of the last block proposer. + pub last_block_proposer: [u8; 32], + /// The height of the most recent platform block. + pub last_platform_block_height: u64, + /// The height of the most recent core blockchain block associated with the platform. + pub last_core_block_height: u32, +} + /// Prefunded specialized balance. #[derive(Debug, derive_more::From, Copy, Clone)] #[cfg_attr( @@ -497,7 +572,7 @@ pub type MasternodeProtocolVotes = RetrievedObjects); +pub struct ProposerBlockCounts(pub RetrievedValues); impl FromIterator<(ProTxHash, Option)> for ProposerBlockCounts { fn from_iter)>>( @@ -511,7 +586,7 @@ impl FromIterator<(ProTxHash, Option)> for ProposerBl let identifier = Identifier::from(pro_tx_hash.to_byte_array()); // Adjust this conversion logic as needed (identifier, block_count) }) - .collect::>(); + .collect::>(); ProposerBlockCounts(map) } @@ -529,7 +604,7 @@ impl FromIterator<(ProTxHash, Option)> for ProposerBlock let identifier = Identifier::from(pro_tx_hash.to_byte_array()); // Adjust this conversion logic as needed (identifier, block_count) }) - .collect::>(); + .collect::>(); ProposerBlockCounts(map) } diff --git a/packages/rs-drive-proof-verifier/src/types/evonode_status.rs b/packages/rs-drive-proof-verifier/src/types/evonode_status.rs new file mode 100644 index 0000000000..87831de0f6 --- /dev/null +++ b/packages/rs-drive-proof-verifier/src/types/evonode_status.rs @@ -0,0 +1,382 @@ +//! Status details of EvoNode, like version, current height, etc. + +use crate::Error; +use dapi_grpc::platform::v0::{ + get_status_response::{self}, + GetStatusResponse, +}; + +#[cfg(feature = "mocks")] +use { + bincode::{Decode, Encode}, + dpp::{version as platform_version, ProtocolError}, + platform_serialization_derive::{PlatformDeserialize, PlatformSerialize}, +}; + +#[derive(Debug, Clone, Default)] +#[cfg_attr( + feature = "mocks", + derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), + platform_serialize(unversioned) +)] +/// The status of an EvoNode. +pub struct EvoNodeStatus { + /// Information about protocol and software components versions. + pub version: Version, + /// Information about the node. + pub node: Node, + /// Layer 2 blockchain information + pub chain: Chain, + /// Node networking information. + pub network: Network, + /// Information about state synchronization progress. + pub state_sync: StateSync, + /// Information about current time used by the node. + pub time: Time, +} +#[derive(Debug, Clone, Default)] +#[cfg_attr( + feature = "mocks", + derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), + platform_serialize(unversioned) +)] + +/// Information about protocol and software components versions. +pub struct Version { + /// Information about software components versions. + pub software: Option, + /// Information about protocol version. + pub protocol: Option, +} +#[derive(Debug, Clone, Default)] +#[cfg_attr( + feature = "mocks", + derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), + platform_serialize(unversioned) +)] +/// Information about software components versions. +pub struct Software { + /// DAPI version, semver-compatible string. + pub dapi: String, + /// Drive version, semver-compatible string. + pub drive: Option, + /// Tenderdash version, semver-compatible string. + pub tenderdash: Option, +} +#[derive(Debug, Clone, Default)] +#[cfg_attr( + feature = "mocks", + derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), + platform_serialize(unversioned) +)] +/// Information about protocol-level versions used by the node +pub struct Protocol { + /// Tenderdash protocols version. + pub tenderdash: Option, + /// Drive protocols version. + pub drive: Option, +} +#[derive(Debug, Clone, Default)] +#[cfg_attr( + feature = "mocks", + derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), + platform_serialize(unversioned) +)] +/// Tenderdash protocol versions. +pub struct TenderdashProtocol { + /// Tenderdash P2P protocol version. + pub p2p: u32, + /// Tenderdash block protocol version. + pub block: u32, +} + +#[derive(Debug, Clone, Default)] +#[cfg_attr( + feature = "mocks", + derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), + platform_serialize(unversioned) +)] + +/// Drive protocol versions. +pub struct DriveProtocol { + /// Latest version supported by the node. + pub latest: u32, + /// Current version used by the node. + pub current: u32, +} +#[derive(Debug, Clone, Default)] +#[cfg_attr( + feature = "mocks", + derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), + platform_serialize(unversioned) +)] + +/// Information about current time used by the node. +pub struct Time { + /// Local time of the node. Unix timestamp since epoch. + pub local: u64, + /// Time of the last block. Unix timestamp since epoch. + pub block: Option, + /// Genesis time. Unix timestamp since epoch. + pub genesis: Option, + /// Epoch number + pub epoch: Option, +} + +#[derive(Debug, Clone, Default)] +#[cfg_attr( + feature = "mocks", + derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), + platform_serialize(unversioned) +)] + +/// Evo node identification information. +pub struct Node { + /// Node ID + pub id: Vec, + /// ProTxHash of masternode; None for full nodes + pub pro_tx_hash: Option>, +} +#[derive(Debug, Clone, Default)] +#[cfg_attr( + feature = "mocks", + derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), + platform_serialize(unversioned) +)] + +/// Layer 2 blockchain information +pub struct Chain { + /// Whether the node is catching up with the network. + pub catching_up: bool, + /// Block hash of the latest block on the node. + pub latest_block_hash: Vec, + /// Latest app hash of the node, as visible in the latest block. + pub latest_app_hash: Vec, + /// Block hash of the earliest block available on the node. + pub earliest_block_hash: Vec, + /// Earliest app hash of the node, as visible in the earliest block. + pub earliest_app_hash: Vec, + /// Height of the latest block available on the node. + pub latest_block_height: u64, + /// Height of the earliest block available on the node. + pub earliest_block_height: u64, + /// Maximum block height of the peers connected to the node. + pub max_peer_block_height: u64, + /// Current core chain locked height. + pub core_chain_locked_height: Option, +} +#[derive(Debug, Clone, Default)] +#[cfg_attr( + feature = "mocks", + derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), + platform_serialize(unversioned) +)] +/// Node networking information. +pub struct Network { + /// Identifier of chain the node is member of. + pub chain_id: String, + /// Number of peers in the address book. + pub peers_count: u32, + /// Whether the node is listening for incoming connections. + pub listening: bool, +} + +#[derive(Debug, Clone, Default)] +#[cfg_attr( + feature = "mocks", + derive(Encode, Decode, PlatformSerialize, PlatformDeserialize), + platform_serialize(unversioned) +)] +/// Information about state synchronization progress. +pub struct StateSync { + /// Total time spent on state synchronization. + pub total_synced_time: u64, + /// Estimated remaining time to finish state synchronization. + pub remaining_time: u64, + /// Total number of snapshots available. + pub total_snapshots: u32, + /// Average time spent on processing a chunk of snapshot data. + pub chunk_process_avg_time: u64, + /// Height of the latest snapshot. + pub snapshot_height: u64, + /// Number of chunks in the latest snapshot. + pub snapshot_chunks_count: u64, + /// Number of backfilled blocks. + pub backfilled_blocks: u64, + /// Total number of blocks to backfill. + pub backfill_blocks_total: u64, +} + +impl TryFrom for EvoNodeStatus { + type Error = Error; + + fn try_from(response: GetStatusResponse) -> Result { + Ok(Self { + version: Version::try_from(&response)?, + node: Node::try_from(&response)?, + chain: Chain::try_from(&response)?, + network: Network::try_from(&response)?, + state_sync: StateSync::try_from(&response)?, + time: Time::try_from(&response)?, + }) + } +} + +impl TryFrom<&GetStatusResponse> for Version { + type Error = Error; + + fn try_from(response: &GetStatusResponse) -> Result { + match &response.version { + Some(get_status_response::Version::V0(v0)) => { + let software = v0 + .version + .as_ref() + .and_then(|v| v.software.clone()) + .map(|s| Software { + dapi: s.dapi, + drive: s.drive, + tenderdash: s.tenderdash, + }); + + let protocol = v0 + .version + .as_ref() + .and_then(|v| v.protocol.clone()) + .map(|p| Protocol { + tenderdash: p.tenderdash.map(|t| TenderdashProtocol { + p2p: t.p2p, + block: t.block, + }), + drive: p.drive.map(|d| DriveProtocol { + latest: d.latest, + current: d.current, + }), + }); + + Ok(Self { software, protocol }) + } + _ => Err(Error::EmptyVersion), + } + } +} + +impl TryFrom<&GetStatusResponse> for Node { + type Error = Error; + + fn try_from(response: &GetStatusResponse) -> Result { + match &response.version { + Some(get_status_response::Version::V0(v0)) => { + let node = v0 + .node + .as_ref() + .map(|n| Self { + id: n.id.clone(), + pro_tx_hash: n.pro_tx_hash.clone(), + }) + .unwrap_or_default(); + Ok(node) + } + _ => Err(Error::EmptyVersion), + } + } +} + +impl TryFrom<&GetStatusResponse> for Chain { + type Error = Error; + + fn try_from(response: &GetStatusResponse) -> Result { + match &response.version { + Some(get_status_response::Version::V0(v0)) => { + let chain = v0 + .chain + .as_ref() + .map(|c| Self { + catching_up: c.catching_up, + latest_block_hash: c.latest_block_hash.clone(), + latest_app_hash: c.latest_app_hash.clone(), + earliest_block_hash: c.earliest_block_hash.clone(), + earliest_app_hash: c.earliest_app_hash.clone(), + latest_block_height: c.latest_block_height, + earliest_block_height: c.earliest_block_height, + max_peer_block_height: c.max_peer_block_height, + core_chain_locked_height: c.core_chain_locked_height, + }) + .unwrap_or_default(); + Ok(chain) + } + _ => Err(Error::EmptyVersion), + } + } +} + +impl TryFrom<&GetStatusResponse> for Network { + type Error = Error; + + fn try_from(response: &GetStatusResponse) -> Result { + match &response.version { + Some(get_status_response::Version::V0(v0)) => { + let network = v0 + .network + .as_ref() + .map(|n| Self { + chain_id: n.chain_id.clone(), + peers_count: n.peers_count, + listening: n.listening, + }) + .unwrap_or_default(); + Ok(network) + } + _ => Err(Error::EmptyVersion), + } + } +} + +impl TryFrom<&GetStatusResponse> for StateSync { + type Error = Error; + + fn try_from(response: &GetStatusResponse) -> Result { + match &response.version { + Some(get_status_response::Version::V0(v0)) => { + let state_sync = v0 + .state_sync + .as_ref() + .map(|s| Self { + total_synced_time: s.total_synced_time, + remaining_time: s.remaining_time, + total_snapshots: s.total_snapshots, + chunk_process_avg_time: s.chunk_process_avg_time, + snapshot_height: s.snapshot_height, + snapshot_chunks_count: s.snapshot_chunks_count, + backfilled_blocks: s.backfilled_blocks, + backfill_blocks_total: s.backfill_blocks_total, + }) + .unwrap_or_default(); + Ok(state_sync) + } + _ => Err(Error::EmptyVersion), + } + } +} + +impl TryFrom<&GetStatusResponse> for Time { + type Error = Error; + + fn try_from(response: &GetStatusResponse) -> Result { + match &response.version { + Some(get_status_response::Version::V0(v0)) => { + let time = v0 + .time + .as_ref() + .map(|t| Self { + local: t.local, + block: t.block, + genesis: t.genesis, + epoch: t.epoch, + }) + .unwrap_or_default(); + Ok(time) + } + _ => Err(Error::EmptyVersion), + } + } +} diff --git a/packages/rs-drive-proof-verifier/src/unproved.rs b/packages/rs-drive-proof-verifier/src/unproved.rs new file mode 100644 index 0000000000..cc7c63c83e --- /dev/null +++ b/packages/rs-drive-proof-verifier/src/unproved.rs @@ -0,0 +1,296 @@ +use crate::types::{CurrentQuorumsInfo, EvoNodeStatus}; +use crate::Error; +use dapi_grpc::platform::v0::ResponseMetadata; +use dapi_grpc::platform::v0::{self as platform}; +use dapi_grpc::tonic::async_trait; +use dpp::bls_signatures::PublicKey as BlsPublicKey; +use dpp::core_types::validator::v0::ValidatorV0; +use dpp::core_types::validator_set::v0::ValidatorSetV0; +use dpp::core_types::validator_set::ValidatorSet; +use dpp::dashcore::hashes::Hash; +use dpp::dashcore::{Network, ProTxHash, PubkeyHash, QuorumHash}; +use dpp::version::PlatformVersion; +use std::collections::BTreeMap; + +/// Trait for parsing unproved responses from the Platform. +/// +/// This trait defines methods for extracting data from responses received from the Platform +/// without the need for cryptographic proof validation. It is primarily used for scenarios where +/// the proof data is not available or not required, and only the data itself is needed. +/// +/// ## Associated Types +/// +/// - `Request`: The type of the request sent to the server. This represents the format of the +/// data that the platform expects when making a query. +/// - `Response`: The type of the response received from the server. This represents the format of +/// the data returned by the platform after executing the query. +/// +/// ## Methods +/// +/// - `maybe_from_unproved`: Parses the response to retrieve the requested object, if any. +/// - `maybe_from_unproved_with_metadata`: Parses the response to retrieve the requested object +/// along with response metadata, if any. +/// - `from_unproved`: Retrieves the requested object from the response, returning an error if the +/// object is not found. +/// - `from_unproved_with_metadata`: Retrieves the requested object from the response along with +/// metadata, returning an error if the object is not found. +/// +/// ``` +pub trait FromUnproved { + /// Request type for which this trait is implemented. + type Request; + /// Response type for which this trait is implemented. + type Response; + + /// Parse the received response and retrieve the requested object, if any. + /// + /// # Arguments + /// + /// * `request`: The request sent to the server. + /// * `response`: The response received from the server. + /// * `network`: The network we are using (Mainnet/Testnet/Devnet/Regtest). + /// * `platform_version`: The platform version that should be used. + /// + /// # Returns + /// + /// * `Ok(Some(object))` when the requested object was found in the response. + /// * `Ok(None)` when the requested object was not found. + /// * `Err(Error)` when parsing fails or data is invalid. + fn maybe_from_unproved, O: Into>( + request: I, + response: O, + network: Network, + platform_version: &PlatformVersion, + ) -> Result, Error> + where + Self: Sized, + { + Self::maybe_from_unproved_with_metadata(request, response, network, platform_version) + .map(|maybe_result| maybe_result.0) + } + + /// Parse the received response and retrieve the requested object along with metadata, if any. + /// + /// # Arguments + /// + /// * `request`: The request sent to the server. + /// * `response`: The response received from the server. + /// * `network`: The network we are using (Mainnet/Testnet/Devnet/Regtest). + /// * `platform_version`: The platform version that should be used. + /// + /// # Returns + /// + /// * `Ok((Some(object), metadata))` when the requested object was found. + /// * `Ok((None, metadata))` when the requested object was not found. + /// * `Err(Error)` when parsing fails or data is invalid. + fn maybe_from_unproved_with_metadata, O: Into>( + request: I, + response: O, + network: Network, + platform_version: &PlatformVersion, + ) -> Result<(Option, ResponseMetadata), Error> + where + Self: Sized; + + /// Retrieve the requested object from the response. + /// + /// # Arguments + /// + /// * `request`: The request sent to the server. + /// * `response`: The response received from the server. + /// * `network`: The network we are using. + /// * `platform_version`: The platform version that should be used. + /// + /// # Returns + /// + /// * `Ok(object)` when the requested object was found. + /// * `Err(Error::NotFound)` when the requested object was not found. + /// * `Err(Error)` when parsing fails or data is invalid. + fn from_unproved, O: Into>( + request: I, + response: O, + network: Network, + platform_version: &PlatformVersion, + ) -> Result + where + Self: Sized, + { + Self::maybe_from_unproved(request, response, network, platform_version)? + .ok_or(Error::NotFound) + } + + /// Retrieve the requested object from the response along with metadata. + /// + /// # Arguments + /// + /// * `request`: The request sent to the server. + /// * `response`: The response received from the server. + /// * `network`: The network we are using. + /// * `platform_version`: The platform version that should be used. + /// + /// # Returns + /// + /// * `Ok((object, metadata))` when the requested object was found. + /// * `Err(Error::NotFound)` when the requested object was not found. + /// * `Err(Error)` when parsing fails or data is invalid. + fn from_unproved_with_metadata, O: Into>( + request: I, + response: O, + network: Network, + platform_version: &PlatformVersion, + ) -> Result<(Self, ResponseMetadata), Error> + where + Self: Sized, + { + let (main_item, response_metadata) = + Self::maybe_from_unproved_with_metadata(request, response, network, platform_version)?; + Ok((main_item.ok_or(Error::NotFound)?, response_metadata)) + } +} + +impl FromUnproved for CurrentQuorumsInfo { + type Request = platform::GetCurrentQuorumsInfoRequest; + type Response = platform::GetCurrentQuorumsInfoResponse; + + fn maybe_from_unproved_with_metadata, O: Into>( + _request: I, + response: O, + _network: Network, + _platform_version: &PlatformVersion, + ) -> Result<(Option, ResponseMetadata), Error> + where + Self: Sized, + { + // Convert the response into a GetCurrentQuorumsInfoResponse + let response: platform::GetCurrentQuorumsInfoResponse = response.into(); + + // Extract metadata from the response + let metadata = match &response.version { + Some(platform::get_current_quorums_info_response::Version::V0(ref v0)) => { + v0.metadata.clone() + } + None => None, + } + .ok_or(Error::EmptyResponseMetadata)?; + + // Parse response based on the version field + let info = match response.version.ok_or(Error::EmptyVersion)? { + platform::get_current_quorums_info_response::Version::V0(v0) => { + // Extract quorum hashes + let quorum_hashes = v0 + .quorum_hashes + .into_iter() + .map(|q_hash| { + let mut q_hash_array = [0u8; 32]; + if q_hash.len() != 32 { + return Err(Error::ProtocolError { + error: "Invalid quorum_hash length".to_string(), + }); + } + q_hash_array.copy_from_slice(&q_hash); + Ok(q_hash_array) + }) + .collect::, Error>>()?; + + // Extract current quorum hash + let mut current_quorum_hash = [0u8; 32]; + if v0.current_quorum_hash.len() != 32 { + return Err(Error::ProtocolError { + error: "Invalid current_quorum_hash length".to_string(), + }); + } + current_quorum_hash.copy_from_slice(&v0.current_quorum_hash); + + let mut last_block_proposer = [0u8; 32]; + if v0.last_block_proposer.len() != 32 { + return Err(Error::ProtocolError { + error: "Invalid last_block_proposer length".to_string(), + }); + } + last_block_proposer.copy_from_slice(&v0.last_block_proposer); + + // Extract validator sets + let validator_sets = + v0.validator_sets + .into_iter() + .map(|vs| { + // Parse the ValidatorSetV0 + let mut quorum_hash = [0u8; 32]; + quorum_hash.copy_from_slice(&vs.quorum_hash); + + // Parse ValidatorV0 members + let members = vs + .members + .into_iter() + .map(|member| { + let pro_tx_hash = ProTxHash::from_slice(&member.pro_tx_hash) + .map_err(|_| Error::ProtocolError { + error: "Invalid ProTxHash format".to_string(), + })?; + let validator = ValidatorV0 { + pro_tx_hash, + public_key: None, // Assuming it's not provided here + node_ip: member.node_ip, + node_id: PubkeyHash::from_slice(&[0; 20]).expect("expected to make pub key hash from 20 byte empty array"), // Placeholder, since not provided + core_port: 0, // Placeholder, since not provided + platform_http_port: 0, // Placeholder, since not provided + platform_p2p_port: 0, // Placeholder, since not provided + is_banned: member.is_banned, + }; + Ok((pro_tx_hash, validator)) + }) + .collect::, Error>>()?; + + Ok(ValidatorSet::V0(ValidatorSetV0 { + quorum_hash: QuorumHash::from_slice(quorum_hash.as_slice()) + .map_err(|_| Error::ProtocolError { + error: "Invalid Quorum Hash format".to_string(), + })?, + quorum_index: None, // Assuming it's not provided here + core_height: vs.core_height, + members, + threshold_public_key: BlsPublicKey::from_bytes( + &vs.threshold_public_key, + ) + .map_err(|_| Error::ProtocolError { + error: "Invalid BlsPublicKey format".to_string(), + })?, + })) + }) + .collect::, Error>>()?; + + // Create the CurrentQuorumsInfo struct + Ok::(CurrentQuorumsInfo { + quorum_hashes, + current_quorum_hash, + validator_sets, + last_block_proposer, + last_platform_block_height: metadata.height, + last_core_block_height: metadata.core_chain_locked_height, + }) + } + }?; + + Ok((Some(info), metadata)) + } +} + +#[async_trait] +impl FromUnproved for EvoNodeStatus { + type Request = platform::GetStatusRequest; + type Response = platform::GetStatusResponse; + + fn maybe_from_unproved_with_metadata, O: Into>( + _request: I, + response: O, + _network: Network, + _platform_version: &PlatformVersion, + ) -> Result<(Option, ResponseMetadata), Error> + where + Self: Sized, + { + let status = Self::try_from(response.into())?; + // we use default response metadata, as this request does not return any metadata + Ok((Some(status), Default::default())) + } +} diff --git a/packages/rs-drive/Cargo.toml b/packages/rs-drive/Cargo.toml index 7ad0520a8f..340ca3a9ee 100644 --- a/packages/rs-drive/Cargo.toml +++ b/packages/rs-drive/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "drive" description = "Dash drive built on top of GroveDB" -version = "1.3.1" +version = "1.5.0" authors = [ "Samuel Westrich ", "Ivan Shumkov ", @@ -31,7 +31,7 @@ dpp = { path = "../rs-dpp", features = [ ], default-features = false, optional = true } thiserror = { version = "1.0.63" } tracing = { version = "0.1.37", default-features = false, features = [] } -derive_more = { version = "0.99.17" } +derive_more = { version = "1.0", features = ["from"] } hex = { version = "0.4.3" } # optional dependencies @@ -40,9 +40,10 @@ ciborium = { git = "https://github.com/qrayven/ciborium", branch = "feat-ser-nul arc-swap = { version = "1.7.0", optional = true } serde = { version = "1.0.197", features = ["derive"], optional = true } rand = { version = "0.8.4", features = ["small_rng"], optional = true } -moka = { version = "0.11.1", features = [ +moka = { version = "0.12", features = [ "future", "futures-util", + "sync", ], optional = true } bs58 = { version = "0.5.0", optional = true } base64 = { version = "0.22.1", optional = true } @@ -50,16 +51,16 @@ tempfile = { version = "3", optional = true } enum-map = { version = "2.0.3", optional = true } intmap = { version = "2.0.0", features = ["serde"], optional = true } chrono = { version = "0.4.35", optional = true } -itertools = { version = "0.11.0", optional = true } -grovedb = { version = "2.0.3", optional = true, default-features = false } -grovedb-costs = { version = "2.0.3", optional = true } -grovedb-path = { version = "2.0.3" } -grovedb-storage = { version = "2.0.3", optional = true } -grovedb-version = { version = "2.0.3"} -grovedb-epoch-based-storage-flags = { version = "2.0.3"} +itertools = { version = "0.13", optional = true } +grovedb = { version = "2.1.0", optional = true, default-features = false } +grovedb-costs = { version = "2.1.0", optional = true } +grovedb-path = { version = "2.1.0" } +grovedb-storage = { version = "2.1.0", optional = true } +grovedb-version = { version = "2.1.0" } +grovedb-epoch-based-storage-flags = { version = "2.1.0" } [dev-dependencies] -criterion = "0.3.5" +criterion = "0.5" platform-version = { path = "../rs-platform-version", features = [ "mock-versions", ] } @@ -77,6 +78,7 @@ dpp = { path = "../rs-dpp", features = [ ], default-features = false } once_cell = "1.7" serde_json = { version = "1.0", features = ["preserve_order"] } +assert_matches = "1.5.0" [[bench]] name = "benchmarks" diff --git a/packages/rs-drive/src/drive/balances/mod.rs b/packages/rs-drive/src/drive/balances/mod.rs index 0af170831e..39f15f4298 100644 --- a/packages/rs-drive/src/drive/balances/mod.rs +++ b/packages/rs-drive/src/drive/balances/mod.rs @@ -79,7 +79,7 @@ mod tests { #[test] fn verify_total_credits_structure() { - let drive: Drive = setup_drive_with_initial_state_structure(); + let drive: Drive = setup_drive_with_initial_state_structure(None); let db_transaction = drive.grove.start_transaction(); let platform_version = PlatformVersion::latest(); diff --git a/packages/rs-drive/src/drive/contract/get_fetch/fetch_contract_with_history/mod.rs b/packages/rs-drive/src/drive/contract/get_fetch/fetch_contract_with_history/mod.rs index ee60215b7f..fdcb837850 100644 --- a/packages/rs-drive/src/drive/contract/get_fetch/fetch_contract_with_history/mod.rs +++ b/packages/rs-drive/src/drive/contract/get_fetch/fetch_contract_with_history/mod.rs @@ -256,7 +256,7 @@ mod tests { TestData { data_contract, - drive: setup_drive_with_initial_state_structure(), + drive: setup_drive_with_initial_state_structure(None), } } diff --git a/packages/rs-drive/src/drive/contract/get_fetch/get_contract_with_fetch_info/mod.rs b/packages/rs-drive/src/drive/contract/get_fetch/get_contract_with_fetch_info/mod.rs index e49ee0b1f8..5bee42052d 100644 --- a/packages/rs-drive/src/drive/contract/get_fetch/get_contract_with_fetch_info/mod.rs +++ b/packages/rs-drive/src/drive/contract/get_fetch/get_contract_with_fetch_info/mod.rs @@ -248,7 +248,7 @@ mod tests { #[test] fn should_return_none_if_contract_not_exist() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); let result = drive @@ -261,7 +261,7 @@ mod tests { #[test] fn should_return_fees_for_non_existing_contract_if_epoch_is_passed() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); let result = drive diff --git a/packages/rs-drive/src/drive/contract/mod.rs b/packages/rs-drive/src/drive/contract/mod.rs index 6ccfda8292..c48343d6c4 100644 --- a/packages/rs-drive/src/drive/contract/mod.rs +++ b/packages/rs-drive/src/drive/contract/mod.rs @@ -68,7 +68,7 @@ mod tests { #[deprecated(note = "This function is marked as unused.")] #[allow(deprecated)] fn setup_deep_nested_50_contract() -> (Drive, DataContract) { - let drive: Drive = setup_drive_with_initial_state_structure(); + let drive: Drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); let contract_path = "tests/supporting_files/contract/deepNested/deep-nested50.json"; @@ -93,7 +93,7 @@ mod tests { #[deprecated(note = "This function is marked as unused.")] #[allow(deprecated)] fn setup_deep_nested_10_contract() -> (Drive, DataContract) { - let drive: Drive = setup_drive_with_initial_state_structure(); + let drive: Drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); let contract_path = "tests/supporting_files/contract/deepNested/deep-nested10.json"; @@ -115,7 +115,7 @@ mod tests { } pub(in crate::drive::contract) fn setup_reference_contract() -> (Drive, DataContract) { - let drive: Drive = setup_drive_with_initial_state_structure(); + let drive: Drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); let contract_path = "tests/supporting_files/contract/references/references.json"; @@ -138,7 +138,7 @@ mod tests { } pub(in crate::drive::contract) fn setup_dashpay() -> (Drive, DataContract) { - let drive: Drive = setup_drive_with_initial_state_structure(); + let drive: Drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); // let's construct the grovedb structure for the dashpay data contract @@ -159,7 +159,7 @@ mod tests { pub(in crate::drive::contract) fn setup_dashpay_with_generalized_encryption_contract( ) -> (Drive, DataContract) { - let drive: Drive = setup_drive_with_initial_state_structure(); + let drive: Drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); // let's construct the grovedb structure for the dashpay data contract @@ -419,7 +419,7 @@ mod tests { #[test] fn test_create_reference_contract_without_apply() { - let drive: Drive = setup_drive_with_initial_state_structure(); + let drive: Drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); let contract_path = "tests/supporting_files/contract/references/references.json"; @@ -441,7 +441,7 @@ mod tests { #[test] fn test_create_reference_contract_with_history_without_apply() { - let drive: Drive = setup_drive_with_initial_state_structure(); + let drive: Drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); let contract_path = @@ -464,7 +464,7 @@ mod tests { #[test] fn test_update_reference_contract_without_apply() { - let drive: Drive = setup_drive_with_initial_state_structure(); + let drive: Drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); let contract_path = "tests/supporting_files/contract/references/references.json"; diff --git a/packages/rs-drive/src/drive/credit_pools/epochs/credit_distribution_pools/get_epoch_fee_multiplier/v0/mod.rs b/packages/rs-drive/src/drive/credit_pools/epochs/credit_distribution_pools/get_epoch_fee_multiplier/v0/mod.rs index d89596e693..46984456fa 100644 --- a/packages/rs-drive/src/drive/credit_pools/epochs/credit_distribution_pools/get_epoch_fee_multiplier/v0/mod.rs +++ b/packages/rs-drive/src/drive/credit_pools/epochs/credit_distribution_pools/get_epoch_fee_multiplier/v0/mod.rs @@ -61,7 +61,7 @@ mod tests { #[test] fn test_error_if_epoch_tree_is_not_initiated_v0() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); let transaction = drive.grove.start_transaction(); @@ -77,7 +77,7 @@ mod tests { #[test] fn test_error_if_value_has_invalid_length_v0() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); let transaction = drive.grove.start_transaction(); @@ -106,7 +106,7 @@ mod tests { #[test] fn test_value_is_set_v0() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); let transaction = drive.grove.start_transaction(); diff --git a/packages/rs-drive/src/drive/credit_pools/epochs/credit_distribution_pools/get_epoch_processing_credits_for_distribution/v0/mod.rs b/packages/rs-drive/src/drive/credit_pools/epochs/credit_distribution_pools/get_epoch_processing_credits_for_distribution/v0/mod.rs index ad944b1d36..05782b23b2 100644 --- a/packages/rs-drive/src/drive/credit_pools/epochs/credit_distribution_pools/get_epoch_processing_credits_for_distribution/v0/mod.rs +++ b/packages/rs-drive/src/drive/credit_pools/epochs/credit_distribution_pools/get_epoch_processing_credits_for_distribution/v0/mod.rs @@ -54,7 +54,7 @@ mod tests { #[test] fn test_error_if_value_has_wrong_element_type() { let platform_version = PlatformVersion::latest(); - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); let epoch = Epoch::new(0).unwrap(); diff --git a/packages/rs-drive/src/drive/credit_pools/epochs/credit_distribution_pools/get_epoch_storage_credits_for_distribution/v0/mod.rs b/packages/rs-drive/src/drive/credit_pools/epochs/credit_distribution_pools/get_epoch_storage_credits_for_distribution/v0/mod.rs index f52962d3be..c12720a8b6 100644 --- a/packages/rs-drive/src/drive/credit_pools/epochs/credit_distribution_pools/get_epoch_storage_credits_for_distribution/v0/mod.rs +++ b/packages/rs-drive/src/drive/credit_pools/epochs/credit_distribution_pools/get_epoch_storage_credits_for_distribution/v0/mod.rs @@ -53,7 +53,7 @@ mod tests { #[test] fn test_error_if_epoch_tree_is_not_initiated_v0() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); let platform_version = PlatformVersion::latest(); @@ -75,7 +75,7 @@ mod tests { #[test] fn test_error_if_value_has_invalid_length_v0() { let platform_version = PlatformVersion::latest(); - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); let epoch = Epoch::new(0).unwrap(); diff --git a/packages/rs-drive/src/drive/credit_pools/epochs/credit_distribution_pools/get_epoch_total_credits_for_distribution/v0/mod.rs b/packages/rs-drive/src/drive/credit_pools/epochs/credit_distribution_pools/get_epoch_total_credits_for_distribution/v0/mod.rs index 9e6cf57e43..ea9fce1ef1 100644 --- a/packages/rs-drive/src/drive/credit_pools/epochs/credit_distribution_pools/get_epoch_total_credits_for_distribution/v0/mod.rs +++ b/packages/rs-drive/src/drive/credit_pools/epochs/credit_distribution_pools/get_epoch_total_credits_for_distribution/v0/mod.rs @@ -48,7 +48,7 @@ mod tests { #[test] fn test_get_epoch_total_credits_for_distribution_v0() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); let platform_version = PlatformVersion::latest(); diff --git a/packages/rs-drive/src/drive/credit_pools/epochs/has_epoch_tree_exists.rs b/packages/rs-drive/src/drive/credit_pools/epochs/has_epoch_tree_exists.rs index 7fca44958e..7106d15a79 100644 --- a/packages/rs-drive/src/drive/credit_pools/epochs/has_epoch_tree_exists.rs +++ b/packages/rs-drive/src/drive/credit_pools/epochs/has_epoch_tree_exists.rs @@ -41,7 +41,7 @@ mod tests { #[test] fn test_return_true_if_tree_exists() { let platform_version = PlatformVersion::latest(); - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); let epoch_tree = Epoch::new(GENESIS_EPOCH_INDEX).unwrap(); @@ -59,7 +59,7 @@ mod tests { // default will be 40 epochs per era // 50 eras // = 2000 - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); let epoch_tree = Epoch::new(2000 + 1).unwrap(); diff --git a/packages/rs-drive/src/drive/credit_pools/epochs/operations_factory.rs b/packages/rs-drive/src/drive/credit_pools/epochs/operations_factory.rs index 8274656c2b..81248a8e5a 100644 --- a/packages/rs-drive/src/drive/credit_pools/epochs/operations_factory.rs +++ b/packages/rs-drive/src/drive/credit_pools/epochs/operations_factory.rs @@ -315,7 +315,7 @@ mod tests { #[test] fn test_increment_block_count_to_1_if_proposers_tree_is_not_committed() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); let platform_version = PlatformVersion::first(); @@ -358,7 +358,7 @@ mod tests { #[test] fn test_existing_block_count_is_incremented() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); let platform_version = PlatformVersion::first(); @@ -445,7 +445,7 @@ mod tests { #[test] fn test_values_are_set() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); let platform_version = PlatformVersion::first(); @@ -480,7 +480,7 @@ mod tests { #[test] fn test_values_are_set() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); let platform_version = PlatformVersion::first(); @@ -561,7 +561,7 @@ mod tests { #[test] fn test_values_are_deleted() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); let platform_version = PlatformVersion::first(); @@ -633,7 +633,7 @@ mod tests { #[test] fn test_value_is_set() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); let platform_version = PlatformVersion::first(); @@ -668,7 +668,7 @@ mod tests { #[test] fn test_update_start_time() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); let platform_version = PlatformVersion::first(); @@ -694,7 +694,7 @@ mod tests { #[test] fn test_update_epoch_start_block_height() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); let platform_version = PlatformVersion::first(); @@ -718,7 +718,7 @@ mod tests { #[test] fn test_update_epoch_start_block_core_height() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); let platform_version = PlatformVersion::first(); @@ -745,7 +745,7 @@ mod tests { #[test] fn test_error_if_epoch_tree_is_not_initiated() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); let platform_version = PlatformVersion::first(); @@ -767,7 +767,7 @@ mod tests { #[test] fn test_value_is_set() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); let platform_version = PlatformVersion::first(); @@ -801,7 +801,7 @@ mod tests { #[test] fn test_error_if_epoch_tree_is_not_initiated() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); let platform_version = PlatformVersion::first(); @@ -823,7 +823,7 @@ mod tests { #[test] fn test_value_is_set() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); let platform_version = PlatformVersion::first(); @@ -857,7 +857,7 @@ mod tests { #[test] fn test_values_has_been_deleted() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); let platform_version = PlatformVersion::first(); @@ -905,7 +905,7 @@ mod tests { #[test] fn test_values_are_being_deleted() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); let epoch = Epoch::new(0).unwrap(); diff --git a/packages/rs-drive/src/drive/credit_pools/epochs/proposers/fetch_epoch_proposers/v0/mod.rs b/packages/rs-drive/src/drive/credit_pools/epochs/proposers/fetch_epoch_proposers/v0/mod.rs index e86547c225..992cb31dd9 100644 --- a/packages/rs-drive/src/drive/credit_pools/epochs/proposers/fetch_epoch_proposers/v0/mod.rs +++ b/packages/rs-drive/src/drive/credit_pools/epochs/proposers/fetch_epoch_proposers/v0/mod.rs @@ -135,7 +135,7 @@ mod tests { #[test] fn test_value() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); let transaction = drive.grove.start_transaction(); diff --git a/packages/rs-drive/src/drive/credit_pools/epochs/proposers/get_epochs_proposer_block_count/v0/mod.rs b/packages/rs-drive/src/drive/credit_pools/epochs/proposers/get_epochs_proposer_block_count/v0/mod.rs index 9ebe6efdc3..8475308ffd 100644 --- a/packages/rs-drive/src/drive/credit_pools/epochs/proposers/get_epochs_proposer_block_count/v0/mod.rs +++ b/packages/rs-drive/src/drive/credit_pools/epochs/proposers/get_epochs_proposer_block_count/v0/mod.rs @@ -63,7 +63,7 @@ mod tests { #[test] fn test_error_if_value_has_invalid_length_v0() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); let transaction = drive.grove.start_transaction(); @@ -100,7 +100,7 @@ mod tests { #[test] fn test_error_if_epoch_tree_is_not_initiated_v0() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); let transaction = drive.grove.start_transaction(); diff --git a/packages/rs-drive/src/drive/credit_pools/epochs/proposers/is_epochs_proposers_tree_empty/mod.rs b/packages/rs-drive/src/drive/credit_pools/epochs/proposers/is_epochs_proposers_tree_empty/mod.rs index dad59b749e..a1266856f0 100644 --- a/packages/rs-drive/src/drive/credit_pools/epochs/proposers/is_epochs_proposers_tree_empty/mod.rs +++ b/packages/rs-drive/src/drive/credit_pools/epochs/proposers/is_epochs_proposers_tree_empty/mod.rs @@ -51,7 +51,7 @@ mod tests { #[test] fn test_check_if_empty() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let drive_version = DriveVersion::default(); let transaction = drive.grove.start_transaction(); diff --git a/packages/rs-drive/src/drive/credit_pools/epochs/proposers/prove_epoch_proposers/v0/mod.rs b/packages/rs-drive/src/drive/credit_pools/epochs/proposers/prove_epoch_proposers/v0/mod.rs index 396591cea5..8deba51b9b 100644 --- a/packages/rs-drive/src/drive/credit_pools/epochs/proposers/prove_epoch_proposers/v0/mod.rs +++ b/packages/rs-drive/src/drive/credit_pools/epochs/proposers/prove_epoch_proposers/v0/mod.rs @@ -63,7 +63,7 @@ mod tests { #[test] fn test_value() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); let transaction = drive.grove.start_transaction(); diff --git a/packages/rs-drive/src/drive/credit_pools/epochs/start_block/mod.rs b/packages/rs-drive/src/drive/credit_pools/epochs/start_block/mod.rs index bea94b346e..2788fd9ff2 100644 --- a/packages/rs-drive/src/drive/credit_pools/epochs/start_block/mod.rs +++ b/packages/rs-drive/src/drive/credit_pools/epochs/start_block/mod.rs @@ -43,7 +43,7 @@ mod tests { #[test] fn test_error_if_epoch_tree_is_not_initiated() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); let platform_version = PlatformVersion::latest(); @@ -64,7 +64,7 @@ mod tests { #[test] fn test_error_if_value_is_not_set() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); let platform_version = PlatformVersion::latest(); @@ -79,7 +79,7 @@ mod tests { #[test] fn test_error_if_value_has_invalid_length() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); let platform_version = PlatformVersion::latest(); @@ -110,7 +110,7 @@ mod tests { #[test] fn test_error_if_value_has_invalid_length_core_height() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); let platform_version = PlatformVersion::latest(); @@ -144,7 +144,7 @@ mod tests { #[test] fn test_error_if_element_has_invalid_type() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); let platform_version = PlatformVersion::latest(); @@ -175,7 +175,7 @@ mod tests { #[test] fn test_error_if_element_has_invalid_type_core_height() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); let transaction = drive.grove.start_transaction(); @@ -218,7 +218,7 @@ mod tests { #[test] fn test_next_block_height() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); let platform_version = PlatformVersion::latest(); @@ -258,7 +258,7 @@ mod tests { #[test] fn test_none_if_there_are_no_start_block_heights() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); let platform_version = PlatformVersion::latest(); @@ -277,7 +277,7 @@ mod tests { #[test] fn test_none_if_start_block_height_is_outside_of_specified_epoch_range() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); @@ -309,7 +309,7 @@ mod tests { #[test] fn test_start_block_height_in_two_epoch_in_case_of_gaps() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); diff --git a/packages/rs-drive/src/drive/credit_pools/epochs/start_time/get_epoch_start_time/v0/mod.rs b/packages/rs-drive/src/drive/credit_pools/epochs/start_time/get_epoch_start_time/v0/mod.rs index 65414461dd..390a878b74 100644 --- a/packages/rs-drive/src/drive/credit_pools/epochs/start_time/get_epoch_start_time/v0/mod.rs +++ b/packages/rs-drive/src/drive/credit_pools/epochs/start_time/get_epoch_start_time/v0/mod.rs @@ -56,7 +56,7 @@ mod tests { #[test] fn test_error_if_epoch_tree_is_not_initiated() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); let platform_version = PlatformVersion::latest(); @@ -77,7 +77,7 @@ mod tests { #[test] fn test_error_if_value_is_not_set() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); let platform_version = PlatformVersion::latest(); @@ -92,7 +92,7 @@ mod tests { #[test] fn test_error_if_element_has_invalid_type() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); let platform_version = PlatformVersion::latest(); @@ -122,7 +122,7 @@ mod tests { #[test] fn test_error_if_value_has_invalid_length() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); let platform_version = PlatformVersion::latest(); diff --git a/packages/rs-drive/src/drive/credit_pools/mod.rs b/packages/rs-drive/src/drive/credit_pools/mod.rs index 398980bc91..9696cce681 100644 --- a/packages/rs-drive/src/drive/credit_pools/mod.rs +++ b/packages/rs-drive/src/drive/credit_pools/mod.rs @@ -195,7 +195,7 @@ mod tests { #[test] fn should_do_nothing_if_credits_per_epoch_are_empty() { let platform_version = PlatformVersion::latest(); - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); let credits_per_epoch = SignedCreditsPerEpoch::default(); @@ -216,7 +216,7 @@ mod tests { #[test] fn should_update_epoch_storage_fee_pools() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); const TO_EPOCH_INDEX: EpochIndex = 10; @@ -281,7 +281,7 @@ mod tests { #[test] fn should_subtract_negative_credits_from_future_epochs() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); let platform_version = PlatformVersion::latest(); diff --git a/packages/rs-drive/src/drive/credit_pools/operations.rs b/packages/rs-drive/src/drive/credit_pools/operations.rs index 7dd78802b5..9aad69bf5b 100644 --- a/packages/rs-drive/src/drive/credit_pools/operations.rs +++ b/packages/rs-drive/src/drive/credit_pools/operations.rs @@ -52,7 +52,7 @@ mod tests { #[test] fn test_values_are_set() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); let platform_version = PlatformVersion::latest(); @@ -65,7 +65,7 @@ mod tests { #[test] fn test_epoch_trees_are_created() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); let transaction = drive.grove.start_transaction(); @@ -106,7 +106,7 @@ mod tests { #[test] fn test_update_and_get_value() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); let platform_version = PlatformVersion::latest(); diff --git a/packages/rs-drive/src/drive/credit_pools/pending_epoch_refunds/methods/add_delete_pending_epoch_refunds_except_specified/v0/mod.rs b/packages/rs-drive/src/drive/credit_pools/pending_epoch_refunds/methods/add_delete_pending_epoch_refunds_except_specified/v0/mod.rs index 49cf61635e..21b200ade4 100644 --- a/packages/rs-drive/src/drive/credit_pools/pending_epoch_refunds/methods/add_delete_pending_epoch_refunds_except_specified/v0/mod.rs +++ b/packages/rs-drive/src/drive/credit_pools/pending_epoch_refunds/methods/add_delete_pending_epoch_refunds_except_specified/v0/mod.rs @@ -74,7 +74,7 @@ mod tests { #[test] fn should_add_delete_operations_v0() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); let transaction = drive.grove.start_transaction(); diff --git a/packages/rs-drive/src/drive/credit_pools/pending_epoch_refunds/methods/fetch_and_add_pending_epoch_refunds_to_collection/v0/mod.rs b/packages/rs-drive/src/drive/credit_pools/pending_epoch_refunds/methods/fetch_and_add_pending_epoch_refunds_to_collection/v0/mod.rs index c593f5d49f..737cadc748 100644 --- a/packages/rs-drive/src/drive/credit_pools/pending_epoch_refunds/methods/fetch_and_add_pending_epoch_refunds_to_collection/v0/mod.rs +++ b/packages/rs-drive/src/drive/credit_pools/pending_epoch_refunds/methods/fetch_and_add_pending_epoch_refunds_to_collection/v0/mod.rs @@ -87,7 +87,7 @@ mod tests { #[test] fn should_fetch_and_merge_pending_updates_v0() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); let transaction = drive.grove.start_transaction(); diff --git a/packages/rs-drive/src/drive/credit_pools/storage_fee_distribution_pool/get_storage_fees_from_distribution_pool/v0/mod.rs b/packages/rs-drive/src/drive/credit_pools/storage_fee_distribution_pool/get_storage_fees_from_distribution_pool/v0/mod.rs index 98e8dac0f1..ee90eec06c 100644 --- a/packages/rs-drive/src/drive/credit_pools/storage_fee_distribution_pool/get_storage_fees_from_distribution_pool/v0/mod.rs +++ b/packages/rs-drive/src/drive/credit_pools/storage_fee_distribution_pool/get_storage_fees_from_distribution_pool/v0/mod.rs @@ -68,7 +68,7 @@ mod tests { #[test] fn test_error_if_wrong_value_encoded() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); let platform_version = PlatformVersion::first(); @@ -96,7 +96,7 @@ mod tests { #[test] fn test_error_if_storage_pool_is_not_initiated() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); let platform_version = PlatformVersion::first(); diff --git a/packages/rs-drive/src/drive/credit_pools/unpaid_epoch/get_unpaid_epoch_index/v0/mod.rs b/packages/rs-drive/src/drive/credit_pools/unpaid_epoch/get_unpaid_epoch_index/v0/mod.rs index a9c1e14a2d..bcfdaf59b1 100644 --- a/packages/rs-drive/src/drive/credit_pools/unpaid_epoch/get_unpaid_epoch_index/v0/mod.rs +++ b/packages/rs-drive/src/drive/credit_pools/unpaid_epoch/get_unpaid_epoch_index/v0/mod.rs @@ -71,7 +71,7 @@ mod tests { #[test] fn test_error_if_element_has_invalid_type() { let platform_version = PlatformVersion::latest(); - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); // We need to first delete the item, because you can not replace an item with a tree @@ -111,7 +111,7 @@ mod tests { #[test] fn test_error_if_value_has_invalid_length() { let platform_version = PlatformVersion::latest(); - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); drive diff --git a/packages/rs-drive/src/drive/document/delete/mod.rs b/packages/rs-drive/src/drive/document/delete/mod.rs index 07d7326135..c2da69240b 100644 --- a/packages/rs-drive/src/drive/document/delete/mod.rs +++ b/packages/rs-drive/src/drive/document/delete/mod.rs @@ -76,10 +76,11 @@ mod tests { use dpp::tests::json_document::{json_document_to_contract, json_document_to_document}; use crate::util::test_helpers::setup::setup_drive_with_initial_state_structure; + use dpp::version::fee::FeeVersion; use dpp::version::PlatformVersion; static EPOCH_CHANGE_FEE_VERSION_TEST: Lazy = - Lazy::new(|| BTreeMap::from([(0, PlatformVersion::first().fee_version.clone())])); + Lazy::new(|| BTreeMap::from([(0, FeeVersion::first())])); #[test] fn test_add_and_remove_family_one_document_no_transaction() { @@ -181,7 +182,7 @@ mod tests { #[test] fn test_add_and_remove_family_one_document() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let db_transaction = drive.grove.start_transaction(); @@ -322,7 +323,7 @@ mod tests { #[test] fn test_add_and_remove_family_documents() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let db_transaction = drive.grove.start_transaction(); @@ -506,7 +507,7 @@ mod tests { #[test] fn test_add_and_remove_family_documents_with_empty_fields() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let db_transaction = drive.grove.start_transaction(); @@ -781,7 +782,7 @@ mod tests { #[test] fn test_delete_dashpay_documents() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let db_transaction = drive.grove.start_transaction(); @@ -881,7 +882,7 @@ mod tests { #[test] fn test_delete_dashpay_documents_without_apply() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let db_transaction = drive.grove.start_transaction(); diff --git a/packages/rs-drive/src/drive/document/insert/mod.rs b/packages/rs-drive/src/drive/document/insert/mod.rs index 6b88440bf2..f0eb33b8a7 100644 --- a/packages/rs-drive/src/drive/document/insert/mod.rs +++ b/packages/rs-drive/src/drive/document/insert/mod.rs @@ -60,10 +60,11 @@ mod tests { use dpp::fee::default_costs::{CachedEpochIndexFeeVersions, EpochCosts}; use dpp::fee::fee_result::FeeResult; use dpp::tests::json_document::json_document_to_document; + use dpp::version::fee::FeeVersion; use dpp::version::PlatformVersion; static EPOCH_CHANGE_FEE_VERSION_TEST: Lazy = - Lazy::new(|| BTreeMap::from([(0, PlatformVersion::first().fee_version.clone())])); + Lazy::new(|| BTreeMap::from([(0, FeeVersion::first())])); #[test] fn test_add_dashpay_documents_no_transaction() { @@ -154,7 +155,7 @@ mod tests { #[test] fn test_add_dashpay_documents() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let db_transaction = drive.grove.start_transaction(); @@ -250,7 +251,7 @@ mod tests { #[test] fn test_add_dashpay_contact_request_with_fee() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let db_transaction = drive.grove.start_transaction(); @@ -315,7 +316,7 @@ mod tests { #[test] fn test_add_dashpay_profile_with_fee() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let db_transaction = drive.grove.start_transaction(); @@ -380,7 +381,7 @@ mod tests { #[test] fn test_add_dashpay_profile_average_case_cost_fee() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let db_transaction = drive.grove.start_transaction(); @@ -445,7 +446,7 @@ mod tests { #[test] fn test_unknown_state_cost_dashpay_fee_for_add_documents() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let db_transaction = drive.grove.start_transaction(); @@ -521,7 +522,7 @@ mod tests { #[test] fn test_add_dashpay_fee_for_documents_detail() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let db_transaction = drive.grove.start_transaction(); @@ -614,7 +615,7 @@ mod tests { #[test] fn test_add_dpns_document_with_fee() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let db_transaction = drive.grove.start_transaction(); diff --git a/packages/rs-drive/src/drive/document/mod.rs b/packages/rs-drive/src/drive/document/mod.rs index 08a8a4be48..fb0cd21529 100644 --- a/packages/rs-drive/src/drive/document/mod.rs +++ b/packages/rs-drive/src/drive/document/mod.rs @@ -155,7 +155,7 @@ pub(crate) mod tests { /// Setup Dashpay pub fn setup_dashpay(_prefix: &str, mutable_contact_requests: bool) -> (Drive, DataContract) { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); diff --git a/packages/rs-drive/src/drive/document/update/mod.rs b/packages/rs-drive/src/drive/document/update/mod.rs index 313af57de8..fccb43e3e8 100644 --- a/packages/rs-drive/src/drive/document/update/mod.rs +++ b/packages/rs-drive/src/drive/document/update/mod.rs @@ -65,11 +65,12 @@ mod tests { use dpp::fee::fee_result::FeeResult; use dpp::platform_value; use dpp::tests::json_document::json_document_to_document; + use dpp::version::fee::FeeVersion; use once_cell::sync::Lazy; use platform_version::version::PlatformVersion; static EPOCH_CHANGE_FEE_VERSION_TEST: Lazy = - Lazy::new(|| BTreeMap::from([(0, PlatformVersion::first().fee_version.clone())])); + Lazy::new(|| BTreeMap::from([(0, FeeVersion::first())])); #[test] fn test_create_and_update_document_same_transaction() { @@ -514,7 +515,7 @@ mod tests { #[test] fn test_create_update_and_delete_document() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); @@ -673,7 +674,7 @@ mod tests { #[test] fn test_modify_dashpay_contact_request() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let db_transaction = drive.grove.start_transaction(); @@ -762,7 +763,7 @@ mod tests { #[test] fn test_update_dashpay_profile_with_history() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let db_transaction = drive.grove.start_transaction(); @@ -1815,7 +1816,7 @@ mod tests { #[test] fn test_update_document_without_apply_should_calculate_storage_fees() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); diff --git a/packages/rs-drive/src/drive/identity/balance/prove.rs b/packages/rs-drive/src/drive/identity/balance/prove.rs index 81542d575a..0fcdd61cb5 100644 --- a/packages/rs-drive/src/drive/identity/balance/prove.rs +++ b/packages/rs-drive/src/drive/identity/balance/prove.rs @@ -70,7 +70,7 @@ mod tests { #[test] fn should_prove_a_single_identity_balance() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::first(); @@ -113,7 +113,7 @@ mod tests { #[test] fn should_prove_multiple_identity_balances() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); let identities: BTreeMap<[u8; 32], Identity> = Identity::random_identities(10, 3, Some(14), platform_version) diff --git a/packages/rs-drive/src/drive/identity/balance/update.rs b/packages/rs-drive/src/drive/identity/balance/update.rs index df5644b546..dc7c94e3e7 100644 --- a/packages/rs-drive/src/drive/identity/balance/update.rs +++ b/packages/rs-drive/src/drive/identity/balance/update.rs @@ -22,7 +22,7 @@ mod tests { #[test] fn should_add_to_balance() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); @@ -89,7 +89,7 @@ mod tests { #[test] fn should_fail_if_balance_is_not_persisted() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); @@ -111,7 +111,7 @@ mod tests { #[test] fn should_deduct_from_debt_if_balance_is_nil() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); let identity = create_test_identity(&drive, [0; 32], Some(1), None, platform_version) @@ -194,7 +194,7 @@ mod tests { #[test] fn should_keep_nil_balance_and_reduce_debt_if_added_balance_is_lower() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); let identity = create_test_identity(&drive, [0; 32], Some(1), None, platform_version) .expect("expected an identity"); @@ -273,7 +273,7 @@ mod tests { #[test] fn should_estimate_costs_without_state() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); @@ -337,7 +337,7 @@ mod tests { #[test] fn should_remove_from_balance() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); @@ -405,7 +405,7 @@ mod tests { #[test] fn should_estimated_costs_without_state() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); @@ -481,7 +481,7 @@ mod tests { #[test] fn should_do_nothing_if_there_is_no_balance_change() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); @@ -505,7 +505,7 @@ mod tests { #[test] fn should_add_to_balance() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); @@ -570,7 +570,7 @@ mod tests { #[test] fn should_fail_if_balance_is_not_persisted() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); @@ -590,7 +590,7 @@ mod tests { #[test] fn should_deduct_from_debt_if_balance_is_nil() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); @@ -665,7 +665,7 @@ mod tests { #[test] fn should_keep_nil_balance_and_reduce_debt_if_added_balance_is_lower() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); @@ -734,7 +734,7 @@ mod tests { #[test] fn should_remove_from_balance_less_amount() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); @@ -788,7 +788,7 @@ mod tests { #[test] fn should_remove_from_balance_bigger_amount_and_get_into_debt() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); @@ -861,7 +861,7 @@ mod tests { #[test] fn should_return_error_if_required_amount_bigger_than_balance() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); diff --git a/packages/rs-drive/src/drive/identity/estimation_costs/for_purpose_in_key_reference_tree/v0/mod.rs b/packages/rs-drive/src/drive/identity/estimation_costs/for_purpose_in_key_reference_tree/v0/mod.rs index f7a49a2bd7..68d4852ad3 100644 --- a/packages/rs-drive/src/drive/identity/estimation_costs/for_purpose_in_key_reference_tree/v0/mod.rs +++ b/packages/rs-drive/src/drive/identity/estimation_costs/for_purpose_in_key_reference_tree/v0/mod.rs @@ -45,6 +45,7 @@ impl Drive { Purpose::TRANSFER => ApproximateElements(1), Purpose::SYSTEM => ApproximateElements(1), Purpose::VOTING => ApproximateElements(1), + Purpose::OWNER => ApproximateElements(1), }; let estimated_layer_sizes = match purpose { @@ -58,6 +59,7 @@ impl Drive { Purpose::TRANSFER => AllReference(1, KEY_REFERENCE_SIZE, None), Purpose::SYSTEM => AllReference(1, KEY_REFERENCE_SIZE, None), Purpose::VOTING => AllReference(1, KEY_REFERENCE_SIZE, None), + Purpose::OWNER => AllReference(1, KEY_REFERENCE_SIZE, None), }; // we then need to insert the identity keys layer estimated_costs_only_with_layer_info.insert( diff --git a/packages/rs-drive/src/drive/identity/fetch/full_identity/mod.rs b/packages/rs-drive/src/drive/identity/fetch/full_identity/mod.rs index 95dc07e00d..ebfe8128a9 100644 --- a/packages/rs-drive/src/drive/identity/fetch/full_identity/mod.rs +++ b/packages/rs-drive/src/drive/identity/fetch/full_identity/mod.rs @@ -17,7 +17,7 @@ mod tests { #[test] fn should_get_full_identities() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); let identities: BTreeMap<[u8; 32], Option> = @@ -60,7 +60,7 @@ mod tests { #[test] fn should_return_none_if_identity_is_not_present() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); @@ -80,7 +80,7 @@ mod tests { #[test] fn should_get_a_full_identity() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); let identity = Identity::random_identity(3, Some(14), platform_version) diff --git a/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identities/v0/mod.rs b/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identities/v0/mod.rs index 66e2899199..1bac303eee 100644 --- a/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identities/v0/mod.rs +++ b/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identities/v0/mod.rs @@ -38,7 +38,7 @@ mod tests { #[test] fn should_prove_two_full_identities_query_no_tx() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); let identities: BTreeMap<[u8; 32], Option> = @@ -111,7 +111,7 @@ mod tests { #[test] fn should_prove_ten_full_identities_query_no_tx() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); let identities: BTreeMap<[u8; 32], Option> = diff --git a/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identities_by_unique_public_key_hashes/v0/mod.rs b/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identities_by_unique_public_key_hashes/v0/mod.rs index b7be9365d3..44f7965678 100644 --- a/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identities_by_unique_public_key_hashes/v0/mod.rs +++ b/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identities_by_unique_public_key_hashes/v0/mod.rs @@ -63,7 +63,7 @@ mod tests { #[test] fn should_prove_multiple_identities() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); diff --git a/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identity/v0/mod.rs b/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identity/v0/mod.rs index 4d3676d9b1..1f8cc5580c 100644 --- a/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identity/v0/mod.rs +++ b/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identity/v0/mod.rs @@ -37,7 +37,7 @@ mod tests { #[test] fn should_prove_full_identity_query_no_tx() { let platform_version = PlatformVersion::latest(); - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let identity = Identity::random_identity(5, Some(14), platform_version) .expect("expected a random identity"); diff --git a/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identity_by_unique_public_key_hash/v0/mod.rs b/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identity_by_unique_public_key_hash/v0/mod.rs index 3df63086c2..f474fa5231 100644 --- a/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identity_by_unique_public_key_hash/v0/mod.rs +++ b/packages/rs-drive/src/drive/identity/fetch/prove/prove_full_identity_by_unique_public_key_hash/v0/mod.rs @@ -57,7 +57,7 @@ mod tests { #[test] fn should_prove_a_single_identity() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::first(); diff --git a/packages/rs-drive/src/drive/identity/fetch/prove/prove_identity_id_by_unique_public_key_hash/v0/mod.rs b/packages/rs-drive/src/drive/identity/fetch/prove/prove_identity_id_by_unique_public_key_hash/v0/mod.rs index cd41d83e24..8900c2e2dc 100644 --- a/packages/rs-drive/src/drive/identity/fetch/prove/prove_identity_id_by_unique_public_key_hash/v0/mod.rs +++ b/packages/rs-drive/src/drive/identity/fetch/prove/prove_identity_id_by_unique_public_key_hash/v0/mod.rs @@ -32,7 +32,7 @@ mod tests { #[test] fn should_prove_a_single_identity_id() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); let identity = Identity::random_identity(3, Some(14), platform_version) .expect("expected a random identity"); diff --git a/packages/rs-drive/src/drive/identity/fetch/prove/prove_identity_ids_by_unique_public_key_hashes/v0/mod.rs b/packages/rs-drive/src/drive/identity/fetch/prove/prove_identity_ids_by_unique_public_key_hashes/v0/mod.rs index 28a7cfa35c..1b4636e6b5 100644 --- a/packages/rs-drive/src/drive/identity/fetch/prove/prove_identity_ids_by_unique_public_key_hashes/v0/mod.rs +++ b/packages/rs-drive/src/drive/identity/fetch/prove/prove_identity_ids_by_unique_public_key_hashes/v0/mod.rs @@ -38,7 +38,7 @@ mod tests { #[test] fn should_prove_multiple_identity_ids() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); let identities: BTreeMap<[u8; 32], Identity> = diff --git a/packages/rs-drive/src/drive/identity/insert/add_new_identity/v0/mod.rs b/packages/rs-drive/src/drive/identity/insert/add_new_identity/v0/mod.rs index 6b6dfbf6d0..f756234431 100644 --- a/packages/rs-drive/src/drive/identity/insert/add_new_identity/v0/mod.rs +++ b/packages/rs-drive/src/drive/identity/insert/add_new_identity/v0/mod.rs @@ -320,7 +320,7 @@ mod tests { #[test] fn test_insert_identity_v0() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let db_transaction = drive.grove.start_transaction(); diff --git a/packages/rs-drive/src/drive/identity/key/fetch/fetch_identity_keys/v0/mod.rs b/packages/rs-drive/src/drive/identity/key/fetch/fetch_identity_keys/v0/mod.rs index d9a4edf0fa..877634eec0 100644 --- a/packages/rs-drive/src/drive/identity/key/fetch/fetch_identity_keys/v0/mod.rs +++ b/packages/rs-drive/src/drive/identity/key/fetch/fetch_identity_keys/v0/mod.rs @@ -1,5 +1,6 @@ use crate::drive::identity::key::fetch::KeyRequestType::{ - AllKeys, ContractBoundKey, ContractDocumentTypeBoundKey, SearchKey, SpecificKeys, + AllKeys, ContractBoundKey, ContractDocumentTypeBoundKey, RecentWithdrawalKeys, SearchKey, + SpecificKeys, }; use crate::drive::identity::key::fetch::{ IdentityKeysRequest, IdentityPublicKeyResult, KeyKindRequestType, @@ -79,10 +80,11 @@ impl Drive { T::try_from_path_key_optional(result, platform_version) } ContractBoundKey(_, _, KeyKindRequestType::AllKeysOfKindRequest) - | ContractDocumentTypeBoundKey(_, _, _, KeyKindRequestType::AllKeysOfKindRequest) => { + | ContractDocumentTypeBoundKey(_, _, _, KeyKindRequestType::AllKeysOfKindRequest) + | RecentWithdrawalKeys => { let path_query = key_request.into_path_query(); - let (result, _) = self.grove_get_raw_path_query( + let (result, _) = self.grove_get_path_query( &path_query, transaction, QueryPathKeyElementTrioResultType, diff --git a/packages/rs-drive/src/drive/identity/key/fetch/mod.rs b/packages/rs-drive/src/drive/identity/key/fetch/mod.rs index 4567278c78..75466736bd 100644 --- a/packages/rs-drive/src/drive/identity/key/fetch/mod.rs +++ b/packages/rs-drive/src/drive/identity/key/fetch/mod.rs @@ -22,6 +22,7 @@ use { }; // Conditional imports for the feature "server" +use crate::drive::identity::identity_transfer_keys_path_vec; #[cfg(feature = "server")] use { crate::error::{drive::DriveError, fee::FeeError, identity::IdentityError, Error}, @@ -74,6 +75,8 @@ pub enum KeyRequestType { SpecificKeys(Vec), /// Search for keys on an identity SearchKey(BTreeMap>), + /// Recent withdrawal keys + RecentWithdrawalKeys, /// Search for contract bound keys ContractBoundKey([u8; 32], Purpose, KeyKindRequestType), /// Search for contract bound keys @@ -655,7 +658,9 @@ impl IdentityKeysRequest { .fee_version .processing .fetch_single_identity_key_processing_cost), - SearchKey(_search) => todo!(), + SearchKey(_) => Err(Error::Fee(FeeError::OperationNotAllowed( + "You can not get costs for requesting search key", + ))), ContractBoundKey(_, _, key_kind) | ContractDocumentTypeBoundKey(_, _, _, key_kind) => { match key_kind { CurrentKeyOfKindRequest => { @@ -670,6 +675,11 @@ impl IdentityKeysRequest { ))), } } + KeyRequestType::RecentWithdrawalKeys => Ok(self.limit.unwrap_or(10) as Credits + * platform_version + .fee_version + .processing + .fetch_single_identity_key_processing_cost), } } @@ -681,8 +691,8 @@ impl IdentityKeysRequest { sec_btree_map.insert(security_level, CurrentKeyOfKindRequest); } let mut purpose_btree_map = BTreeMap::new(); - for purpose in 0..=Purpose::last() as u8 { - purpose_btree_map.insert(purpose, sec_btree_map.clone()); + for purpose in Purpose::searchable_purposes() { + purpose_btree_map.insert(purpose as u8, sec_btree_map.clone()); } IdentityKeysRequest { identity_id, @@ -927,6 +937,19 @@ impl IdentityKeysRequest { }, } } + KeyRequestType::RecentWithdrawalKeys => { + let query_keys_path = identity_transfer_keys_path_vec(&identity_id); + let mut query = Query::new_with_direction(false); + query.insert_all(); + PathQuery { + path: query_keys_path, + query: SizedQuery { + query, + limit, + offset, + }, + } + } } } diff --git a/packages/rs-drive/src/drive/identity/mod.rs b/packages/rs-drive/src/drive/identity/mod.rs index 65928b5ecb..1922e74b88 100644 --- a/packages/rs-drive/src/drive/identity/mod.rs +++ b/packages/rs-drive/src/drive/identity/mod.rs @@ -259,7 +259,6 @@ pub(crate) fn identity_query_keys_purpose_tree_path_vec( /// identity query keys security level tree path vec #[cfg(feature = "server")] -/// Identity query keys security level tree path vec pub(crate) fn identity_query_keys_security_level_tree_path_vec( identity_id: &[u8], security_level: SecurityLevel, @@ -288,7 +287,6 @@ pub(crate) fn identity_query_keys_for_direct_searchable_reference_full_tree_path ] } -/// identity query keys full tree path #[cfg(feature = "server")] /// Identity query keys full tree path pub(crate) fn identity_query_keys_for_authentication_full_tree_path<'a>( @@ -304,6 +302,28 @@ pub(crate) fn identity_query_keys_for_authentication_full_tree_path<'a>( ] } +/// Identity query keys for transfer full tree path +#[cfg(feature = "server")] +pub fn identity_transfer_keys_tree_path(identity_id: &[u8]) -> [&[u8]; 5] { + [ + Into::<&[u8; 1]>::into(RootTree::Identities), + identity_id, + Into::<&[u8; 1]>::into(IdentityRootStructure::IdentityTreeKeyReferences), + Into::<&[u8; 1]>::into(Purpose::TRANSFER), + Into::<&[u8; 1]>::into(SecurityLevel::CRITICAL), + ] +} + +/// Identity query keys for transfer full tree path as vec +pub fn identity_transfer_keys_path_vec(identity_id: &[u8]) -> Vec> { + vec![ + vec![RootTree::Identities as u8], + identity_id.to_vec(), + vec![IdentityRootStructure::IdentityTreeKeyReferences as u8], + vec![Purpose::TRANSFER as u8], + ] +} + /// The root structure of identities #[cfg(any(feature = "server", feature = "verify"))] #[repr(u8)] diff --git a/packages/rs-drive/src/drive/identity/update/mod.rs b/packages/rs-drive/src/drive/identity/update/mod.rs index b28d7f3134..c846d8d43d 100644 --- a/packages/rs-drive/src/drive/identity/update/mod.rs +++ b/packages/rs-drive/src/drive/identity/update/mod.rs @@ -21,7 +21,7 @@ mod tests { #[test] fn should_add_one_new_key_to_identity() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::first(); @@ -81,7 +81,7 @@ mod tests { #[test] fn should_add_two_dozen_new_keys_to_identity() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::first(); @@ -141,7 +141,7 @@ mod tests { #[test] fn should_estimated_costs_without_state() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::first(); @@ -200,7 +200,7 @@ mod tests { #[test] fn should_disable_a_few_keys() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::first(); @@ -279,7 +279,7 @@ mod tests { #[test] fn should_estimated_costs_without_state() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::first(); @@ -328,7 +328,7 @@ mod tests { #[test] fn estimated_costs_should_have_same_storage_cost() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::first(); @@ -387,7 +387,7 @@ mod tests { #[test] fn should_update_revision() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::first(); @@ -447,7 +447,7 @@ mod tests { #[test] fn should_estimated_costs_without_state() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::first(); diff --git a/packages/rs-drive/src/drive/identity/withdrawals/calculate_current_withdrawal_limit/mod.rs b/packages/rs-drive/src/drive/identity/withdrawals/calculate_current_withdrawal_limit/mod.rs new file mode 100644 index 0000000000..1d31584f69 --- /dev/null +++ b/packages/rs-drive/src/drive/identity/withdrawals/calculate_current_withdrawal_limit/mod.rs @@ -0,0 +1,69 @@ +use crate::drive::Drive; +use crate::error::drive::DriveError; +use crate::error::Error; +use dpp::fee::Credits; +use grovedb::TransactionArg; +use platform_version::version::PlatformVersion; + +mod v0; + +/// Daily withdrawal limit information +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct WithdrawalLimitInfo { + /// The total maximum withdrawal amount allowed in a 24-hour period. + pub daily_maximum: Credits, + /// The amount already withdrawn in the last 24 hours. + pub withdrawals_amount: Credits, +} + +impl WithdrawalLimitInfo { + /// Calculates the available credits to withdraw + pub fn available(&self) -> Credits { + self.daily_maximum.saturating_sub(self.withdrawals_amount) + } +} + +impl Drive { + /// Calculates the current withdrawal limit based on the total credits available in the platform + /// and the amount already withdrawn in the last 24 hours, using the appropriate version-specific logic. + /// + /// This function selects the version-specific implementation based on the provided `platform_version`. + /// It currently supports only version 0 (`calculate_current_withdrawal_limit_v0`). + /// + /// # Parameters + /// + /// * `transaction`: The transaction context used for querying data. + /// * `platform_version`: The version of the platform being used, which contains configuration details and version-specific methods. + /// + /// # Returns + /// + /// * `Ok(Credits)`: The calculated current withdrawal limit, representing the maximum amount that can still be withdrawn in the current 24-hour window. + /// * `Err(Error)`: Returns an error if the version specified in `platform_version` is not supported or if there is an issue in the version-specific calculation. + /// + /// # Errors + /// + /// * `Error::Drive(DriveError::UnknownVersionMismatch)`: + /// - If the platform version provided does not match any known versions supported by this function. + /// + /// * `Error`: Any error propagated from the version-specific implementation, such as issues in retrieving data or calculating the withdrawal limit. + pub fn calculate_current_withdrawal_limit( + &self, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result { + match platform_version + .drive + .methods + .identity + .withdrawals + .calculate_current_withdrawal_limit + { + 0 => self.calculate_current_withdrawal_limit_v0(transaction, platform_version), + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "calculate_current_withdrawal_limit".to_string(), + known_versions: vec![0], + received: version, + })), + } + } +} diff --git a/packages/rs-drive/src/drive/identity/withdrawals/calculate_current_withdrawal_limit/v0/mod.rs b/packages/rs-drive/src/drive/identity/withdrawals/calculate_current_withdrawal_limit/v0/mod.rs new file mode 100644 index 0000000000..c4f2316d3f --- /dev/null +++ b/packages/rs-drive/src/drive/identity/withdrawals/calculate_current_withdrawal_limit/v0/mod.rs @@ -0,0 +1,89 @@ +use crate::drive::balances::TOTAL_SYSTEM_CREDITS_STORAGE_KEY; +use crate::drive::identity::withdrawals::calculate_current_withdrawal_limit::WithdrawalLimitInfo; +use crate::drive::identity::withdrawals::paths::{ + get_withdrawal_root_path, WITHDRAWAL_TRANSACTIONS_SUM_AMOUNT_TREE_KEY, +}; +use crate::drive::system::misc_path; +use crate::drive::Drive; +use crate::error::drive::DriveError; +use crate::error::Error; +use crate::util::grove_operations::DirectQueryType; +use dpp::withdrawal::daily_withdrawal_limit::daily_withdrawal_limit; +use grovedb::TransactionArg; +use platform_version::version::PlatformVersion; + +impl Drive { + /// Calculates the current withdrawal limit based on the available credits in the platform + /// and the amount already withdrawn in the last 24 hours. + /// + /// This function considers two main components to calculate the current withdrawal limit: + /// 1. The total maximum withdrawal allowed in a 24-hour period (`daily_maximum`). + /// 2. The amount already withdrawn in the last 24 hours (`withdrawal_amount_in_last_day`). + /// + /// The formula used is: `daily_maximum - withdrawal_amount_in_last_day`. + /// If the withdrawal amount in the last 24 hours exceeds the daily maximum, the result will be 0. + /// + /// # Parameters + /// + /// * `transaction`: The transaction context to use for querying data. + /// * `platform_version`: The version of the platform being used, containing relevant configuration details. + /// + /// # Returns + /// + /// * `Ok(Credits)`: The calculated current withdrawal limit, which is the maximum amount that can still be withdrawn in the current 24-hour window. + /// * `Err(Error)`: Returns an error if there was an issue retrieving the total credits, the daily maximum, or the already withdrawn amount. + /// + /// # Errors + /// + /// * `Error::Drive(DriveError::CriticalCorruptedState)`: + /// - If the total credits in the platform cannot be found, indicating a critical state corruption. + /// - If the withdrawal amount in the last 24 hours is negative, which should not happen. + pub(super) fn calculate_current_withdrawal_limit_v0( + &self, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result { + // The current withdrawal limit has two components + // 1. The total maximum that we are allowed to do in 24 hours + // 2. The amount that we have already withdrawn in the last 24 hours + let mut drive_operations = vec![]; + + let path_holding_total_credits = misc_path(); + let total_credits_in_platform = self + .grove_get_raw_value_u64_from_encoded_var_vec( + (&path_holding_total_credits).into(), + TOTAL_SYSTEM_CREDITS_STORAGE_KEY, + DirectQueryType::StatefulDirectQuery, + transaction, + &mut drive_operations, + &platform_version.drive, + )? + .ok_or(Error::Drive(DriveError::CriticalCorruptedState( + "Credits not found in Platform", + )))?; + + // Let's get the amount that we are allowed to get in the last 24 hours. + let daily_maximum = daily_withdrawal_limit(total_credits_in_platform, platform_version)?; + + let withdrawal_amount_in_last_day: u64 = self + .grove_get_sum_tree_total_value( + (&get_withdrawal_root_path()).into(), + &WITHDRAWAL_TRANSACTIONS_SUM_AMOUNT_TREE_KEY, + DirectQueryType::StatefulDirectQuery, + transaction, + &mut drive_operations, + &platform_version.drive, + )? + .try_into() + .map_err(|_| { + Error::Drive(DriveError::CriticalCorruptedState( + "Withdrawal amount in last day is negative", + )) + })?; + + Ok(WithdrawalLimitInfo { + daily_maximum, + withdrawals_amount: withdrawal_amount_in_last_day, + }) + } +} diff --git a/packages/rs-drive/src/drive/identity/withdrawals/document/fetch_oldest_withdrawal_documents_by_status/v0/mod.rs b/packages/rs-drive/src/drive/identity/withdrawals/document/fetch_oldest_withdrawal_documents_by_status/v0/mod.rs index b60e41be44..4e611e39fb 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/document/fetch_oldest_withdrawal_documents_by_status/v0/mod.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/document/fetch_oldest_withdrawal_documents_by_status/v0/mod.rs @@ -113,7 +113,7 @@ mod tests { #[test] fn test_return_list_of_documents() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); diff --git a/packages/rs-drive/src/drive/identity/withdrawals/document/find_withdrawal_documents_by_status_and_transaction_indices/mod.rs b/packages/rs-drive/src/drive/identity/withdrawals/document/find_withdrawal_documents_by_status_and_transaction_indices/mod.rs index a3545ad539..ca67af28bc 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/document/find_withdrawal_documents_by_status_and_transaction_indices/mod.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/document/find_withdrawal_documents_by_status_and_transaction_indices/mod.rs @@ -1,11 +1,11 @@ mod v0; -use crate::drive::identity::withdrawals::WithdrawalTransactionIndex; use crate::drive::Drive; use crate::error::drive::DriveError; use crate::error::Error; use dpp::data_contracts::withdrawals_contract; use dpp::document::Document; +use dpp::withdrawal::WithdrawalTransactionIndex; use grovedb::TransactionArg; use platform_version::version::PlatformVersion; @@ -25,7 +25,7 @@ impl Drive { .identity .withdrawals .document - .find_up_to_100_withdrawal_documents_by_status_and_transaction_indices + .find_withdrawal_documents_by_status_and_transaction_indices { 0 => self.find_withdrawal_documents_by_status_and_transaction_indices_v0( status, @@ -35,8 +35,7 @@ impl Drive { platform_version, ), version => Err(Error::Drive(DriveError::UnknownVersionMismatch { - method: "find_up_to_100_withdrawal_documents_by_status_and_transaction_indices" - .to_string(), + method: "find_withdrawal_documents_by_status_and_transaction_indices".to_string(), known_versions: vec![0], received: version, })), diff --git a/packages/rs-drive/src/drive/identity/withdrawals/document/find_withdrawal_documents_by_status_and_transaction_indices/v0/mod.rs b/packages/rs-drive/src/drive/identity/withdrawals/document/find_withdrawal_documents_by_status_and_transaction_indices/v0/mod.rs index 0d0dda43ed..ea92ef5a67 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/document/find_withdrawal_documents_by_status_and_transaction_indices/v0/mod.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/document/find_withdrawal_documents_by_status_and_transaction_indices/v0/mod.rs @@ -1,5 +1,4 @@ use crate::drive::document::query::QueryDocumentsOutcomeV0Methods; -use crate::drive::identity::withdrawals::WithdrawalTransactionIndex; use crate::drive::Drive; use crate::error::Error; use crate::query::{DriveDocumentQuery, InternalClauses, OrderClause, WhereClause}; @@ -8,6 +7,7 @@ use dpp::data_contracts::withdrawals_contract; use dpp::data_contracts::withdrawals_contract::v1::document_types::withdrawal; use dpp::document::Document; use dpp::platform_value::Value; +use dpp::withdrawal::WithdrawalTransactionIndex; use grovedb::TransactionArg; use indexmap::IndexMap; use platform_version::version::PlatformVersion; @@ -16,6 +16,7 @@ use std::collections::BTreeMap; impl Drive { // TODO(withdrawals): Currently it queries only up to 100 documents. // It works while we don't have pooling + // This should be a pathquery directly instead of a drive query for efficiency pub(super) fn find_withdrawal_documents_by_status_and_transaction_indices_v0( &self, @@ -97,7 +98,6 @@ impl Drive { #[cfg(test)] mod tests { use crate::config::DEFAULT_QUERY_LIMIT; - use crate::drive::identity::withdrawals::WithdrawalTransactionIndex; use crate::util::test_helpers::setup::{ setup_document, setup_drive_with_initial_state_structure, setup_system_data_contract, }; @@ -110,12 +110,13 @@ mod tests { use dpp::tests::fixtures::get_withdrawal_document_fixture; use dpp::version::PlatformVersion; use dpp::withdrawal::Pooling; + use dpp::withdrawal::WithdrawalTransactionIndex; use super::*; #[test] fn test_find_pooled_withdrawal_documents_by_transaction_index() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); diff --git a/packages/rs-drive/src/drive/identity/withdrawals/document/mod.rs b/packages/rs-drive/src/drive/identity/withdrawals/document/mod.rs index 0f3e6aec29..e047ea5a45 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/document/mod.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/document/mod.rs @@ -1,4 +1,4 @@ -/// This module dedicated for a versioned fetch_up_to_100_oldest_withdrawal_documents_by_status +/// This module dedicated for a versioned fetch_oldest_withdrawal_documents_by_status pub mod fetch_oldest_withdrawal_documents_by_status; -/// This module dedicated for a versioned find_up_to_100_withdrawal_documents_by_status_and_transaction_indices +/// This module dedicated for a versioned find_withdrawal_documents_by_status_and_transaction_indices pub mod find_withdrawal_documents_by_status_and_transaction_indices; diff --git a/packages/rs-drive/src/drive/identity/withdrawals/mod.rs b/packages/rs-drive/src/drive/identity/withdrawals/mod.rs index 57f26a5b5e..25296ff37a 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/mod.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/mod.rs @@ -1,12 +1,8 @@ /// Functions related to withdrawal documents pub mod document; +mod calculate_current_withdrawal_limit; /// Functions and constants related to GroveDB paths pub mod paths; /// Functions related to withdrawal transactions pub mod transaction; - -/// Simple type alias for withdrawal transaction with it's index -pub type WithdrawalTransactionIndexAndBytes = (WithdrawalTransactionIndex, Vec); -/// Transaction index type -pub type WithdrawalTransactionIndex = u64; diff --git a/packages/rs-drive/src/drive/identity/withdrawals/paths.rs b/packages/rs-drive/src/drive/identity/withdrawals/paths.rs index 0dfcb3c4c9..3d85be63b3 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/paths.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/paths.rs @@ -1,17 +1,24 @@ -use grovedb::Element; - use crate::drive::{Drive, RootTree}; use crate::util::batch::grovedb_op_batch::GroveDbOpBatchV0Methods; use crate::util::batch::GroveDbOpBatch; +use grovedb::Element; +use platform_version::version::PlatformVersion; /// constant key for transaction counter pub const WITHDRAWAL_TRANSACTIONS_NEXT_INDEX_KEY: [u8; 1] = [0]; /// constant id for subtree containing transactions queue pub const WITHDRAWAL_TRANSACTIONS_QUEUE_KEY: [u8; 1] = [1]; +/// constant id for subtree containing the sum of withdrawals +pub const WITHDRAWAL_TRANSACTIONS_SUM_AMOUNT_TREE_KEY: [u8; 1] = [2]; +/// constant id for subtree containing the untied withdrawal transactions after they were broadcasted +pub const WITHDRAWAL_TRANSACTIONS_BROADCASTED_KEY: [u8; 1] = [3]; impl Drive { /// Add operations for creating initial withdrawal state structure - pub fn add_initial_withdrawal_state_structure_operations(batch: &mut GroveDbOpBatch) { + pub fn add_initial_withdrawal_state_structure_operations( + batch: &mut GroveDbOpBatch, + platform_version: &PlatformVersion, + ) { batch.add_insert( vec![vec![RootTree::WithdrawalTransactions as u8]], WITHDRAWAL_TRANSACTIONS_NEXT_INDEX_KEY.to_vec(), @@ -22,6 +29,17 @@ impl Drive { vec![vec![RootTree::WithdrawalTransactions as u8]], WITHDRAWAL_TRANSACTIONS_QUEUE_KEY.to_vec(), ); + + if platform_version.protocol_version >= 4 { + batch.add_insert_empty_sum_tree( + vec![vec![RootTree::WithdrawalTransactions as u8]], + WITHDRAWAL_TRANSACTIONS_SUM_AMOUNT_TREE_KEY.to_vec(), + ); + batch.add_insert_empty_sum_tree( + vec![vec![RootTree::WithdrawalTransactions as u8]], + WITHDRAWAL_TRANSACTIONS_BROADCASTED_KEY.to_vec(), + ); + } } } @@ -50,3 +68,35 @@ pub fn get_withdrawal_transactions_queue_path() -> [&'static [u8]; 2] { &WITHDRAWAL_TRANSACTIONS_QUEUE_KEY, ] } + +/// Helper function to get the withdrawal transactions sum tree path as Vec +pub fn get_withdrawal_transactions_sum_tree_path_vec() -> Vec> { + vec![ + vec![RootTree::WithdrawalTransactions as u8], + WITHDRAWAL_TRANSACTIONS_SUM_AMOUNT_TREE_KEY.to_vec(), + ] +} + +/// Helper function to get the withdrawal transactions sum tree path as [u8] +pub fn get_withdrawal_transactions_sum_tree_path() -> [&'static [u8]; 2] { + [ + Into::<&[u8; 1]>::into(RootTree::WithdrawalTransactions), + &WITHDRAWAL_TRANSACTIONS_SUM_AMOUNT_TREE_KEY, + ] +} + +/// Helper function to get the withdrawal transactions broadcasted path as Vec +pub fn get_withdrawal_transactions_broadcasted_path_vec() -> Vec> { + vec![ + vec![RootTree::WithdrawalTransactions as u8], + WITHDRAWAL_TRANSACTIONS_BROADCASTED_KEY.to_vec(), + ] +} + +/// Helper function to get the withdrawal transactions broadcasted path as [u8] +pub fn get_withdrawal_transactions_broadcasted_path() -> [&'static [u8]; 2] { + [ + Into::<&[u8; 1]>::into(RootTree::WithdrawalTransactions), + &WITHDRAWAL_TRANSACTIONS_BROADCASTED_KEY, + ] +} diff --git a/packages/rs-drive/src/drive/identity/withdrawals/transaction/index/add_update_next_withdrawal_transaction_index_operation/mod.rs b/packages/rs-drive/src/drive/identity/withdrawals/transaction/index/add_update_next_withdrawal_transaction_index_operation/mod.rs index 5554f8a4f6..59c820433d 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/transaction/index/add_update_next_withdrawal_transaction_index_operation/mod.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/transaction/index/add_update_next_withdrawal_transaction_index_operation/mod.rs @@ -1,10 +1,10 @@ mod v0; -use crate::drive::identity::withdrawals::WithdrawalTransactionIndex; use crate::drive::Drive; use crate::error::drive::DriveError; use crate::error::Error; use crate::util::batch::DriveOperation; +use dpp::withdrawal::WithdrawalTransactionIndex; use platform_version::version::PlatformVersion; impl Drive { diff --git a/packages/rs-drive/src/drive/identity/withdrawals/transaction/index/add_update_next_withdrawal_transaction_index_operation/v0/mod.rs b/packages/rs-drive/src/drive/identity/withdrawals/transaction/index/add_update_next_withdrawal_transaction_index_operation/v0/mod.rs index 4c162fd5ea..fb4b7f39c0 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/transaction/index/add_update_next_withdrawal_transaction_index_operation/v0/mod.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/transaction/index/add_update_next_withdrawal_transaction_index_operation/v0/mod.rs @@ -1,7 +1,7 @@ -use crate::drive::identity::withdrawals::WithdrawalTransactionIndex; use crate::drive::Drive; use crate::util::batch::drive_op_batch::WithdrawalOperationType; use crate::util::batch::DriveOperation; +use dpp::withdrawal::WithdrawalTransactionIndex; impl Drive { pub(super) fn add_update_next_withdrawal_transaction_index_operation_v0( diff --git a/packages/rs-drive/src/drive/identity/withdrawals/transaction/index/fetch_next_withdrawal_transaction_index/mod.rs b/packages/rs-drive/src/drive/identity/withdrawals/transaction/index/fetch_next_withdrawal_transaction_index/mod.rs index c3ae1dae3c..bc8268b257 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/transaction/index/fetch_next_withdrawal_transaction_index/mod.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/transaction/index/fetch_next_withdrawal_transaction_index/mod.rs @@ -1,7 +1,7 @@ -use crate::drive::identity::withdrawals::WithdrawalTransactionIndex; use crate::drive::Drive; use crate::error::drive::DriveError; use crate::error::Error; +use dpp::withdrawal::WithdrawalTransactionIndex; use grovedb::TransactionArg; use platform_version::version::PlatformVersion; diff --git a/packages/rs-drive/src/drive/identity/withdrawals/transaction/index/fetch_next_withdrawal_transaction_index/v0/mod.rs b/packages/rs-drive/src/drive/identity/withdrawals/transaction/index/fetch_next_withdrawal_transaction_index/v0/mod.rs index bdc01546dd..e0ca52ed8b 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/transaction/index/fetch_next_withdrawal_transaction_index/v0/mod.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/transaction/index/fetch_next_withdrawal_transaction_index/v0/mod.rs @@ -1,8 +1,8 @@ use crate::drive::identity::withdrawals::paths::WITHDRAWAL_TRANSACTIONS_NEXT_INDEX_KEY; -use crate::drive::identity::withdrawals::WithdrawalTransactionIndex; use crate::drive::{Drive, RootTree}; use crate::error::drive::DriveError; use crate::error::Error; +use dpp::withdrawal::WithdrawalTransactionIndex; use grovedb::{Element, TransactionArg}; use platform_version::version::PlatformVersion; diff --git a/packages/rs-drive/src/drive/identity/withdrawals/transaction/index/mod.rs b/packages/rs-drive/src/drive/identity/withdrawals/transaction/index/mod.rs index 9928d324da..a2dafcb7cb 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/transaction/index/mod.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/transaction/index/mod.rs @@ -14,7 +14,7 @@ mod tests { #[test] fn test_next_withdrawal_transaction_index() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); @@ -59,7 +59,7 @@ mod tests { #[test] fn test_initial_withdrawal_transaction_index() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); diff --git a/packages/rs-drive/src/drive/identity/withdrawals/transaction/queue/add_enqueue_untied_withdrawal_transaction_operations/mod.rs b/packages/rs-drive/src/drive/identity/withdrawals/transaction/queue/add_enqueue_untied_withdrawal_transaction_operations/mod.rs index d0e8168790..f23c60bba4 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/transaction/queue/add_enqueue_untied_withdrawal_transaction_operations/mod.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/transaction/queue/add_enqueue_untied_withdrawal_transaction_operations/mod.rs @@ -1,8 +1,9 @@ -use crate::drive::identity::withdrawals::WithdrawalTransactionIndexAndBytes; use crate::drive::Drive; use crate::error::drive::DriveError; use crate::error::Error; use crate::util::batch::DriveOperation; +use dpp::fee::Credits; +use dpp::withdrawal::WithdrawalTransactionIndexAndBytes; use platform_version::version::PlatformVersion; mod v0; @@ -12,6 +13,7 @@ impl Drive { pub fn add_enqueue_untied_withdrawal_transaction_operations( &self, withdrawal_transactions: Vec, + total_sum: Credits, drive_operation_types: &mut Vec, platform_version: &PlatformVersion, ) -> Result<(), Error> { @@ -27,6 +29,7 @@ impl Drive { 0 => { self.add_enqueue_untied_withdrawal_transaction_operations_v0( withdrawal_transactions, + total_sum, drive_operation_types, ); diff --git a/packages/rs-drive/src/drive/identity/withdrawals/transaction/queue/add_enqueue_untied_withdrawal_transaction_operations/v0/mod.rs b/packages/rs-drive/src/drive/identity/withdrawals/transaction/queue/add_enqueue_untied_withdrawal_transaction_operations/v0/mod.rs index b14f505218..1df5e12da9 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/transaction/queue/add_enqueue_untied_withdrawal_transaction_operations/v0/mod.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/transaction/queue/add_enqueue_untied_withdrawal_transaction_operations/v0/mod.rs @@ -1,12 +1,16 @@ -use crate::drive::identity::withdrawals::WithdrawalTransactionIndexAndBytes; use crate::drive::Drive; use crate::util::batch::drive_op_batch::WithdrawalOperationType; use crate::util::batch::DriveOperation; +use dpp::fee::Credits; +use dpp::prelude::TimestampMillis; +use dpp::withdrawal::WithdrawalTransactionIndexAndBytes; +const DAY_AND_A_HOUR_IN_MS: TimestampMillis = 90_000_000; //25 hours impl Drive { pub(super) fn add_enqueue_untied_withdrawal_transaction_operations_v0( &self, withdrawal_transactions: Vec, + total_sum: Credits, drive_operation_types: &mut Vec, ) { if !withdrawal_transactions.is_empty() { @@ -15,6 +19,13 @@ impl Drive { withdrawal_transactions, }, )); + drive_operation_types.push(DriveOperation::WithdrawalOperation( + WithdrawalOperationType::ReserveWithdrawalAmount { + amount: total_sum, + // Best to use a constant here and not a versioned item as this most likely will not change + expiration_after: DAY_AND_A_HOUR_IN_MS, + }, + )); } } } diff --git a/packages/rs-drive/src/drive/identity/withdrawals/transaction/queue/dequeue_untied_withdrawal_transactions/mod.rs b/packages/rs-drive/src/drive/identity/withdrawals/transaction/queue/dequeue_untied_withdrawal_transactions/mod.rs index 3fadfcc5c8..cdc4672759 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/transaction/queue/dequeue_untied_withdrawal_transactions/mod.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/transaction/queue/dequeue_untied_withdrawal_transactions/mod.rs @@ -1,15 +1,16 @@ mod v0; -use crate::drive::identity::withdrawals::WithdrawalTransactionIndexAndBytes; use crate::drive::Drive; use crate::error::drive::DriveError; use crate::error::Error; use crate::util::batch::DriveOperation; +use dpp::withdrawal::WithdrawalTransactionIndexAndBytes; use grovedb::TransactionArg; use platform_version::version::PlatformVersion; impl Drive { - /// Get specified amount of withdrawal transactions from the DB + /// Deque specified amount of untiled withdrawal transactions + /// and move them to broadcasted queue pub fn dequeue_untied_withdrawal_transactions( &self, limit: u16, diff --git a/packages/rs-drive/src/drive/identity/withdrawals/transaction/queue/dequeue_untied_withdrawal_transactions/v0/mod.rs b/packages/rs-drive/src/drive/identity/withdrawals/transaction/queue/dequeue_untied_withdrawal_transactions/v0/mod.rs index a89b788b10..5911ed5cda 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/transaction/queue/dequeue_untied_withdrawal_transactions/v0/mod.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/transaction/queue/dequeue_untied_withdrawal_transactions/v0/mod.rs @@ -1,13 +1,11 @@ use crate::drive::identity::withdrawals::paths::get_withdrawal_transactions_queue_path_vec; -use crate::drive::identity::withdrawals::{ - WithdrawalTransactionIndex, WithdrawalTransactionIndexAndBytes, -}; use crate::drive::Drive; use crate::error::drive::DriveError; use crate::error::Error; use crate::query::{Query, QueryItem}; use crate::util::batch::drive_op_batch::WithdrawalOperationType; use crate::util::batch::DriveOperation; +use dpp::withdrawal::{WithdrawalTransactionIndex, WithdrawalTransactionIndexAndBytes}; use grovedb::query_result_type::QueryResultType; use grovedb::{Element, PathQuery, SizedQuery, TransactionArg}; use platform_version::version::PlatformVersion; @@ -22,7 +20,7 @@ impl Drive { drive_operation_types: &mut Vec, platform_version: &PlatformVersion, ) -> Result, Error> { - let mut query = Query::new(); + let mut query = Query::new_with_direction(true); query.insert_item(QueryItem::RangeFull(RangeFull)); @@ -39,7 +37,7 @@ impl Drive { .grove .query_raw( &path_query, - transaction.is_some(), + true, true, true, QueryResultType::QueryKeyElementPairResultType, @@ -71,12 +69,14 @@ impl Drive { }) .collect::, Error>>()?; - if !withdrawal_transactions.is_empty() { - for (index, _) in withdrawal_transactions.iter() { - drive_operation_types.push(DriveOperation::WithdrawalOperation( - WithdrawalOperationType::DeleteWithdrawalTransaction { index: *index }, - )); - } + let indexes: Vec = withdrawal_transactions + .iter() + .map(|(index, _)| *index) + .collect(); + if !indexes.is_empty() { + drive_operation_types.push(DriveOperation::WithdrawalOperation( + WithdrawalOperationType::MoveWithdrawalTransactionsToBroadcasted { indexes }, + )); } Ok(withdrawal_transactions) diff --git a/packages/rs-drive/src/drive/identity/withdrawals/transaction/queue/mod.rs b/packages/rs-drive/src/drive/identity/withdrawals/transaction/queue/mod.rs index 85621a35e4..b7817dd338 100644 --- a/packages/rs-drive/src/drive/identity/withdrawals/transaction/queue/mod.rs +++ b/packages/rs-drive/src/drive/identity/withdrawals/transaction/queue/mod.rs @@ -1,25 +1,28 @@ -/// This module dedicated for a versioned add_enqueue_untied_withdrawal_transaction_operations +/// This module is dedicated for a versioned add_enqueue_untied_withdrawal_transaction_operations pub mod add_enqueue_untied_withdrawal_transaction_operations; -/// This module dedicated for a versioned dequeue_untied_withdrawal_transactions +/// This module is dedicated for a versioned dequeue_untied_withdrawal_transactions pub mod dequeue_untied_withdrawal_transactions; +/// This module is dedicated to removing broadcasted withdrawal transactions after core says they were completed +pub mod remove_broadcasted_withdrawal_transactions_after_completion; + +/// This module is dedicated to moving broadcasted withdrawal transactions back to the main queue +pub mod move_broadcasted_withdrawal_transactions_back_to_queue_operations; + #[cfg(test)] mod tests { - use crate::drive::identity::withdrawals::{ - WithdrawalTransactionIndex, WithdrawalTransactionIndexAndBytes, - }; use crate::util::batch::DriveOperation; use dpp::block::block_info::BlockInfo; use dpp::block::epoch::Epoch; use crate::util::test_helpers::setup::setup_drive_with_initial_state_structure; - use dpp::version::PlatformVersion; + use dpp::withdrawal::{WithdrawalTransactionIndex, WithdrawalTransactionIndexAndBytes}; + use platform_version::version::PlatformVersion; #[test] fn test_enqueue_and_dequeue() { - let drive = setup_drive_with_initial_state_structure(); - let platform_version = PlatformVersion::latest(); + let drive = setup_drive_with_initial_state_structure(None); let transaction = drive.grove.start_transaction(); @@ -39,6 +42,7 @@ mod tests { drive .add_enqueue_untied_withdrawal_transaction_operations( withdrawals, + 100, &mut drive_operations, platform_version, ) diff --git a/packages/rs-drive/src/drive/identity/withdrawals/transaction/queue/move_broadcasted_withdrawal_transactions_back_to_queue_operations/mod.rs b/packages/rs-drive/src/drive/identity/withdrawals/transaction/queue/move_broadcasted_withdrawal_transactions_back_to_queue_operations/mod.rs new file mode 100644 index 0000000000..d7ca0deb45 --- /dev/null +++ b/packages/rs-drive/src/drive/identity/withdrawals/transaction/queue/move_broadcasted_withdrawal_transactions_back_to_queue_operations/mod.rs @@ -0,0 +1,43 @@ +use crate::drive::Drive; +use crate::error::drive::DriveError; +use crate::error::Error; +use crate::util::batch::DriveOperation; +use dpp::withdrawal::WithdrawalTransactionIndex; +use platform_version::version::PlatformVersion; + +mod v0; + +impl Drive { + /// Moves broadcasted withdrawal transactions back to the queue + pub fn move_broadcasted_withdrawal_transactions_back_to_queue_operations( + &self, + indexes: Vec, + drive_operation_types: &mut Vec, + platform_version: &PlatformVersion, + ) -> Result<(), Error> { + match platform_version + .drive + .methods + .identity + .withdrawals + .transaction + .queue + .move_broadcasted_withdrawal_transactions_back_to_queue_operations + { + 0 => { + self.move_broadcasted_withdrawal_transactions_back_to_queue_operations_v0( + indexes, + drive_operation_types, + ); + + Ok(()) + } + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "move_broadcasted_withdrawal_transactions_back_to_queue_operations" + .to_string(), + known_versions: vec![0], + received: version, + })), + } + } +} diff --git a/packages/rs-drive/src/drive/identity/withdrawals/transaction/queue/move_broadcasted_withdrawal_transactions_back_to_queue_operations/v0/mod.rs b/packages/rs-drive/src/drive/identity/withdrawals/transaction/queue/move_broadcasted_withdrawal_transactions_back_to_queue_operations/v0/mod.rs new file mode 100644 index 0000000000..7fc17d4d8a --- /dev/null +++ b/packages/rs-drive/src/drive/identity/withdrawals/transaction/queue/move_broadcasted_withdrawal_transactions_back_to_queue_operations/v0/mod.rs @@ -0,0 +1,25 @@ +use crate::drive::Drive; +use crate::util::batch::drive_op_batch::WithdrawalOperationType; +use crate::util::batch::DriveOperation; +use dpp::withdrawal::WithdrawalTransactionIndex; + +impl Drive { + pub(super) fn move_broadcasted_withdrawal_transactions_back_to_queue_operations_v0( + &self, + indexes: Vec, + drive_operation_types: &mut Vec, + ) { + if !indexes.is_empty() { + tracing::trace!( + "Moving {} broadcasted withdrawal transactions back to the queue for resigning: {:?}", + indexes.len(), + indexes + ); + drive_operation_types.push(DriveOperation::WithdrawalOperation( + WithdrawalOperationType::MoveBroadcastedWithdrawalTransactionsBackToQueueForResigning { + indexes, + }, + )); + } + } +} diff --git a/packages/rs-drive/src/drive/identity/withdrawals/transaction/queue/remove_broadcasted_withdrawal_transactions_after_completion/mod.rs b/packages/rs-drive/src/drive/identity/withdrawals/transaction/queue/remove_broadcasted_withdrawal_transactions_after_completion/mod.rs new file mode 100644 index 0000000000..a3f0c50dbc --- /dev/null +++ b/packages/rs-drive/src/drive/identity/withdrawals/transaction/queue/remove_broadcasted_withdrawal_transactions_after_completion/mod.rs @@ -0,0 +1,40 @@ +mod v0; + +use crate::drive::Drive; +use crate::error::drive::DriveError; +use crate::error::Error; +use crate::util::batch::DriveOperation; +use dpp::withdrawal::WithdrawalTransactionIndex; +use platform_version::version::PlatformVersion; + +impl Drive { + /// Get specified amount of withdrawal transactions from the DB + pub fn remove_broadcasted_withdrawal_transactions_after_completion_operations( + &self, + indexes: Vec, + drive_operation_types: &mut Vec, + platform_version: &PlatformVersion, + ) -> Result<(), Error> { + match platform_version + .drive + .methods + .identity + .withdrawals + .transaction + .queue + .remove_broadcasted_withdrawal_transactions_after_completion_operations + { + 0 => Ok(self + .remove_broadcasted_withdrawal_transactions_after_completion_operations_v0( + indexes, + drive_operation_types, + )), + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "remove_broadcasted_withdrawal_transactions_after_completion_operations" + .to_string(), + known_versions: vec![0], + received: version, + })), + } + } +} diff --git a/packages/rs-drive/src/drive/identity/withdrawals/transaction/queue/remove_broadcasted_withdrawal_transactions_after_completion/v0/mod.rs b/packages/rs-drive/src/drive/identity/withdrawals/transaction/queue/remove_broadcasted_withdrawal_transactions_after_completion/v0/mod.rs new file mode 100644 index 0000000000..70cf03bad1 --- /dev/null +++ b/packages/rs-drive/src/drive/identity/withdrawals/transaction/queue/remove_broadcasted_withdrawal_transactions_after_completion/v0/mod.rs @@ -0,0 +1,15 @@ +use crate::drive::Drive; +use crate::util::batch::drive_op_batch::WithdrawalOperationType; +use crate::util::batch::DriveOperation; +use dpp::withdrawal::WithdrawalTransactionIndex; +impl Drive { + pub(super) fn remove_broadcasted_withdrawal_transactions_after_completion_operations_v0( + &self, + indexes: Vec, + drive_operation_types: &mut Vec, + ) { + drive_operation_types.push(DriveOperation::WithdrawalOperation( + WithdrawalOperationType::DeleteCompletedBroadcastedWithdrawalTransactions { indexes }, + )); + } +} diff --git a/packages/rs-drive/src/drive/initialization/genesis_core_height/mod.rs b/packages/rs-drive/src/drive/initialization/genesis_core_height/mod.rs index 5e8f21d95e..189bbac47a 100644 --- a/packages/rs-drive/src/drive/initialization/genesis_core_height/mod.rs +++ b/packages/rs-drive/src/drive/initialization/genesis_core_height/mod.rs @@ -81,7 +81,7 @@ mod tests { #[test] fn test_initial_state_structure_proper_heights() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let db_transaction = drive.grove.start_transaction(); diff --git a/packages/rs-drive/src/drive/initialization/v0/mod.rs b/packages/rs-drive/src/drive/initialization/v0/mod.rs index e1c4ee377d..ff30075d68 100644 --- a/packages/rs-drive/src/drive/initialization/v0/mod.rs +++ b/packages/rs-drive/src/drive/initialization/v0/mod.rs @@ -170,7 +170,7 @@ impl Drive { )?; // In Withdrawals - Drive::add_initial_withdrawal_state_structure_operations(&mut batch); + Drive::add_initial_withdrawal_state_structure_operations(&mut batch, platform_version); // For Versioning via forks Drive::add_initial_fork_update_structure_operations(&mut batch); @@ -199,7 +199,7 @@ mod tests { #[test] fn test_create_initial_state_structure() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); @@ -228,7 +228,7 @@ mod tests { #[test] fn test_initial_state_structure_proper_heights() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let _db_transaction = drive.grove.start_transaction(); diff --git a/packages/rs-drive/src/drive/system/genesis_time/mod.rs b/packages/rs-drive/src/drive/system/genesis_time/mod.rs index cd888ccd31..9eee51529b 100644 --- a/packages/rs-drive/src/drive/system/genesis_time/mod.rs +++ b/packages/rs-drive/src/drive/system/genesis_time/mod.rs @@ -94,7 +94,7 @@ mod tests { #[test] fn should_return_some_if_genesis_time_is_persisted() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let genesis_time_ms = 100; diff --git a/packages/rs-drive/src/query/mod.rs b/packages/rs-drive/src/query/mod.rs index 456b4fc411..7491454a64 100644 --- a/packages/rs-drive/src/query/mod.rs +++ b/packages/rs-drive/src/query/mod.rs @@ -1275,23 +1275,39 @@ impl<'a> DriveDocumentQuery<'a> { #[cfg(any(feature = "server", feature = "verify"))] /// Returns a `Query` that either starts at or after the given key. fn inner_query_starts_from_key( - start_at_key: Vec, + start_at_key: Option>, left_to_right: bool, included: bool, ) -> Query { // We only need items after the start at document let mut inner_query = Query::new_with_direction(left_to_right); + if left_to_right { - if included { - inner_query.insert_range_from(start_at_key..); + if let Some(start_at_key) = start_at_key { + if included { + inner_query.insert_range_from(start_at_key..); + } else { + inner_query.insert_range_after(start_at_key..); + } } else { - inner_query.insert_range_after(start_at_key..); + inner_query.insert_all(); } } else if included { - inner_query.insert_range_to_inclusive(..=start_at_key); + if let Some(start_at_key) = start_at_key { + inner_query.insert_range_to_inclusive(..=start_at_key); + } else { + inner_query.insert_key(vec![]); + } } else { - inner_query.insert_range_to(..start_at_key); + if let Some(start_at_key) = start_at_key { + inner_query.insert_range_to(..start_at_key); + } else { + //todo: really not sure if this is correct + // Should investigate more + inner_query.insert_key(vec![]); + } } + inner_query } @@ -1434,11 +1450,11 @@ impl<'a> DriveDocumentQuery<'a> { platform_version, ) .ok() - .flatten() - .unwrap_or_default(); + .flatten(); // We should always include if we have left_over - let non_conditional_included = !left_over.is_empty() | *included; + let non_conditional_included = + !left_over.is_empty() | *included | start_at_key.is_none(); let mut non_conditional_query = Self::inner_query_starts_from_key( start_at_key, @@ -1849,6 +1865,7 @@ impl<'a> DriveDocumentQuery<'a> { drive_operations, platform_version, )?; + let query_result = drive.grove_get_path_query_serialized_results( &path_query, transaction, @@ -1976,6 +1993,8 @@ mod tests { use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters; use dpp::prelude::Identifier; + use grovedb::Query; + use indexmap::IndexMap; use rand::prelude::StdRng; use rand::SeedableRng; use serde_json::json; @@ -1995,11 +2014,16 @@ mod tests { use serde_json::Value::Null; use crate::config::DriveConfig; - use crate::util::test_helpers::setup::setup_drive_with_initial_state_structure; + use crate::util::test_helpers::setup::{ + setup_drive_with_initial_state_structure, setup_system_data_contract, + }; use dpp::block::block_info::BlockInfo; use dpp::data_contract::accessors::v0::DataContractV0Getters; + use dpp::data_contracts::SystemDataContract; + use dpp::document::DocumentV0; use dpp::platform_value::string_encoding::Encoding; use dpp::platform_value::Value; + use dpp::system_data_contracts::load_system_data_contract; use dpp::tests::fixtures::{get_data_contract_fixture, get_dpns_data_contract_fixture}; use dpp::tests::json_document::json_document_to_contract; use dpp::util::cbor_serializer; @@ -2037,8 +2061,38 @@ mod tests { (drive, contract) } + fn setup_withdrawal_contract() -> (Drive, DataContract) { + let tmp_dir = TempDir::new().unwrap(); + + let (drive, _) = Drive::open(tmp_dir, None).expect("expected to open Drive successfully"); + + let platform_version = PlatformVersion::latest(); + + drive + .create_initial_state_structure(None, platform_version) + .expect("expected to create root tree successfully"); + + // let's construct the grovedb structure for the dashpay data contract + let contract = load_system_data_contract(SystemDataContract::Withdrawals, platform_version) + .expect("load system contact"); + + let storage_flags = Some(Cow::Owned(StorageFlags::SingleEpoch(0))); + drive + .apply_contract( + &contract, + BlockInfo::default(), + true, + storage_flags, + None, + platform_version, + ) + .expect("expected to apply contract successfully"); + + (drive, contract) + } + fn setup_family_birthday_contract() -> (Drive, DataContract) { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); @@ -2667,4 +2721,99 @@ mod tests { ) .expect_err("starts with can not start with an empty string"); } + + #[test] + fn test_withdrawal_query_with_missing_transaction_index() { + // Setup the withdrawal contract + let (_, contract) = setup_withdrawal_contract(); + let platform_version = PlatformVersion::latest(); + + let document_type_name = "withdrawal"; + let document_type = contract + .document_type_for_name(document_type_name) + .expect("expected to get document type"); + + // Create a DriveDocumentQuery that simulates missing 'transactionIndex' in documents + let drive_document_query = DriveDocumentQuery { + contract: &contract, + document_type, + internal_clauses: InternalClauses { + primary_key_in_clause: None, + primary_key_equal_clause: None, + in_clause: Some(WhereClause { + field: "status".to_string(), + operator: WhereOperator::In, + value: Value::Array(vec![ + Value::U64(0), + Value::U64(1), + Value::U64(2), + Value::U64(3), + Value::U64(4), + ]), + }), + range_clause: None, + equal_clauses: BTreeMap::default(), + }, + offset: None, + limit: Some(3), + order_by: IndexMap::from([ + ( + "status".to_string(), + OrderClause { + field: "status".to_string(), + ascending: true, + }, + ), + ( + "transactionIndex".to_string(), + OrderClause { + field: "transactionIndex".to_string(), + ascending: true, + }, + ), + ]), + start_at: Some([3u8; 32]), + start_at_included: false, + block_time_ms: None, + }; + + // Create a document that we are starting at, which may be missing 'transactionIndex' + let mut properties = BTreeMap::new(); + properties.insert("status".to_string(), Value::U64(0)); + // We intentionally omit 'transactionIndex' to simulate missing field + + let starts_at_document = DocumentV0 { + id: Identifier::from([3u8; 32]), // The same as start_at + owner_id: Identifier::random(), + 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, + } + .into(); + + // Attempt to construct the path query + let result = drive_document_query + .construct_path_query(Some(starts_at_document), platform_version) + .expect("expected to construct a path query"); + + assert_eq!( + result + .clone() + .query + .query + .default_subquery_branch + .subquery + .expect("expected subquery") + .items, + Query::new_range_full().items + ); + } } diff --git a/packages/rs-drive/src/state_transition_action/identity/identity_credit_withdrawal/transformer.rs b/packages/rs-drive/src/state_transition_action/identity/identity_credit_withdrawal/transformer.rs index 6ea2449408..5f619841bb 100644 --- a/packages/rs-drive/src/state_transition_action/identity/identity_credit_withdrawal/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/identity/identity_credit_withdrawal/transformer.rs @@ -1,20 +1,43 @@ +use crate::drive::Drive; +use crate::error::Error; use crate::state_transition_action::identity::identity_credit_withdrawal::v0::IdentityCreditWithdrawalTransitionActionV0; use crate::state_transition_action::identity::identity_credit_withdrawal::IdentityCreditWithdrawalTransitionAction; +use dpp::block::block_info::BlockInfo; use dpp::state_transition::identity_credit_withdrawal_transition::IdentityCreditWithdrawalTransition; +use dpp::validation::ConsensusValidationResult; +use grovedb::TransactionArg; +use platform_version::version::PlatformVersion; impl IdentityCreditWithdrawalTransitionAction { - /// from - pub fn from_identity_credit_withdrawal( + /// try from an identity credit withdrawal + pub fn try_from_identity_credit_withdrawal( + drive: &Drive, + tx: TransactionArg, identity_credit_withdrawal: &IdentityCreditWithdrawalTransition, - creation_time_ms: u64, - ) -> Self { + block_info: &BlockInfo, + platform_version: &PlatformVersion, + ) -> Result, Error> { match identity_credit_withdrawal { IdentityCreditWithdrawalTransition::V0(v0) => { - IdentityCreditWithdrawalTransitionActionV0::from_identity_credit_withdrawal( - v0, - creation_time_ms, + Ok(ConsensusValidationResult::new_with_data( + IdentityCreditWithdrawalTransitionActionV0::from_identity_credit_withdrawal_v0( + v0, + block_info.time_ms, + ) + .into(), + )) + } + IdentityCreditWithdrawalTransition::V1(v1) => { + IdentityCreditWithdrawalTransitionActionV0::try_from_identity_credit_withdrawal_v1( + drive, + tx, + v1, + block_info, + platform_version, ) - .into() + .map(|consensus_validation_result| { + consensus_validation_result.map(|withdrawal| withdrawal.into()) + }) } } } diff --git a/packages/rs-drive/src/state_transition_action/identity/identity_credit_withdrawal/v0/transformer.rs b/packages/rs-drive/src/state_transition_action/identity/identity_credit_withdrawal/v0/transformer.rs index 742476740c..e2c443d9ab 100644 --- a/packages/rs-drive/src/state_transition_action/identity/identity_credit_withdrawal/v0/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/identity/identity_credit_withdrawal/v0/transformer.rs @@ -1,14 +1,33 @@ +use crate::drive::identity::key::fetch::{ + IdentityKeysRequest, KeyIDIdentityPublicKeyPairBTreeMap, KeyRequestType, +}; +use crate::drive::Drive; +use crate::error::Error; use crate::state_transition_action::identity::identity_credit_withdrawal::v0::IdentityCreditWithdrawalTransitionActionV0; +use dpp::block::block_info::BlockInfo; +use dpp::consensus::state::identity::identity_public_key_is_disabled_error::IdentityPublicKeyIsDisabledError; +use dpp::consensus::state::identity::missing_transfer_key_error::MissingTransferKeyError; +use dpp::consensus::state::identity::no_transfer_key_for_core_withdrawal_available_error::NoTransferKeyForCoreWithdrawalAvailableError; +use dpp::consensus::state::state_error::StateError; +use dpp::consensus::ConsensusError; use dpp::data_contracts::withdrawals_contract; use dpp::data_contracts::withdrawals_contract::v1::document_types::withdrawal; use dpp::document::{Document, DocumentV0}; +use dpp::identity::core_script::CoreScript; +use dpp::identity::hash::IdentityPublicKeyHashMethodsV0; +use dpp::identity::identity_public_key::accessors::v0::IdentityPublicKeyGettersV0; +use dpp::identity::{IdentityPublicKey, KeyType}; use dpp::platform_value::platform_value; +use dpp::state_transition::identity_credit_withdrawal_transition::v1::IdentityCreditWithdrawalTransitionV1; use dpp::state_transition::state_transitions::identity::identity_credit_withdrawal_transition::v0::IdentityCreditWithdrawalTransitionV0; +use dpp::validation::ConsensusValidationResult; use dpp::withdrawal::Pooling; +use grovedb::TransactionArg; +use platform_version::version::PlatformVersion; impl IdentityCreditWithdrawalTransitionActionV0 { /// from identity credit withdrawal - pub fn from_identity_credit_withdrawal( + pub fn from_identity_credit_withdrawal_v0( identity_credit_withdrawal: &IdentityCreditWithdrawalTransitionV0, creation_time_ms: u64, ) -> Self { @@ -57,4 +76,129 @@ impl IdentityCreditWithdrawalTransitionActionV0 { user_fee_increase: identity_credit_withdrawal.user_fee_increase, } } + + /// from identity credit withdrawal v1 + pub fn try_from_identity_credit_withdrawal_v1( + drive: &Drive, + tx: TransactionArg, + identity_credit_withdrawal: &IdentityCreditWithdrawalTransitionV1, + block_info: &BlockInfo, + platform_version: &PlatformVersion, + ) -> Result, Error> { + let output_script_bytes = if let Some(output_script) = + &identity_credit_withdrawal.output_script + { + output_script.to_bytes() + } else { + let key_request = IdentityKeysRequest { + identity_id: identity_credit_withdrawal.identity_id.to_buffer(), + request_type: KeyRequestType::RecentWithdrawalKeys, + limit: None, + offset: None, + }; + let key: Option = + drive.fetch_identity_keys(key_request, tx, platform_version)?; + let Some(mut key) = key else { + return Ok(ConsensusValidationResult::new_with_error( + ConsensusError::StateError(StateError::MissingTransferKeyError( + MissingTransferKeyError::new(identity_credit_withdrawal.identity_id), + )), + )); + }; + if key.is_disabled() { + // The first key is disabled, let's look at some more withdrawal keys to find one that isn't disabled + let after_first_key_request = IdentityKeysRequest { + identity_id: identity_credit_withdrawal.identity_id.to_buffer(), + request_type: KeyRequestType::RecentWithdrawalKeys, + limit: Some(5), + offset: Some(1), + }; + let other_keys: KeyIDIdentityPublicKeyPairBTreeMap = + drive.fetch_identity_keys(after_first_key_request, tx, platform_version)?; + + if let Some(found_non_disabled_key) = other_keys + .values() + .rev() + .find(|identity_public_key| !identity_public_key.is_disabled()) + .cloned() + { + key = found_non_disabled_key + } else { + return Ok(ConsensusValidationResult::new_with_error( + ConsensusError::StateError(StateError::IdentityPublicKeyIsDisabledError( + IdentityPublicKeyIsDisabledError::new(key.id()), + )), + )); + } + } + match key.key_type() { + KeyType::ECDSA_HASH160 => { + // We should get the withdrawal address + CoreScript::new_p2pkh(key.public_key_hash()?).to_bytes() + } + KeyType::BIP13_SCRIPT_HASH => { + // We should get the withdrawal address + CoreScript::new_p2sh(key.public_key_hash()?).to_bytes() + } + _ => { + return Ok(ConsensusValidationResult::new_with_error( + ConsensusError::StateError( + StateError::NoTransferKeyForCoreWithdrawalAvailableError( + NoTransferKeyForCoreWithdrawalAvailableError::new( + identity_credit_withdrawal.identity_id, + ), + ), + ), + )); + } + } + }; + + let mut entropy = Vec::new(); + entropy.extend_from_slice(&identity_credit_withdrawal.nonce.to_be_bytes()); + entropy.extend_from_slice(output_script_bytes.as_slice()); + + let document_id = Document::generate_document_id_v0( + &withdrawals_contract::ID, + &identity_credit_withdrawal.identity_id, + withdrawal::NAME, + &entropy, + ); + + let document_data = platform_value!({ + withdrawal::properties::AMOUNT: identity_credit_withdrawal.amount, + withdrawal::properties::CORE_FEE_PER_BYTE: identity_credit_withdrawal.core_fee_per_byte, + // TODO(withdrawals): replace with actual value from state transition once pooling is done + withdrawal::properties::POOLING: Pooling::Never, + withdrawal::properties::OUTPUT_SCRIPT: output_script_bytes, + withdrawal::properties::STATUS: withdrawals_contract::WithdrawalStatus::QUEUED, + }); + + let withdrawal_document = DocumentV0 { + id: document_id, + owner_id: identity_credit_withdrawal.identity_id, + properties: document_data.into_btree_string_map().unwrap(), + revision: Some(1), + created_at: Some(block_info.time_ms), + updated_at: Some(block_info.time_ms), + 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, + } + .into(); + + Ok(ConsensusValidationResult::new_with_data( + IdentityCreditWithdrawalTransitionActionV0 { + identity_id: identity_credit_withdrawal.identity_id, + nonce: identity_credit_withdrawal.nonce, + prepared_withdrawal_document: withdrawal_document, + amount: identity_credit_withdrawal.amount, + user_fee_increase: identity_credit_withdrawal.user_fee_increase, + }, + )) + } } diff --git a/packages/rs-drive/src/state_transition_action/system/bump_identity_nonce_action/transformer.rs b/packages/rs-drive/src/state_transition_action/system/bump_identity_nonce_action/transformer.rs index 674fb61d3b..ae5afef5ff 100644 --- a/packages/rs-drive/src/state_transition_action/system/bump_identity_nonce_action/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/system/bump_identity_nonce_action/transformer.rs @@ -137,22 +137,14 @@ impl BumpIdentityNonceAction { pub fn from_identity_credit_withdrawal_transition( value: IdentityCreditWithdrawalTransition, ) -> Self { - match value { - IdentityCreditWithdrawalTransition::V0(v0) => { - BumpIdentityNonceActionV0::from_identity_credit_withdrawal(v0).into() - } - } + BumpIdentityNonceActionV0::from_identity_credit_withdrawal(value).into() } /// from borrowed identity withdrawal pub fn from_borrowed_identity_credit_withdrawal_transition( value: &IdentityCreditWithdrawalTransition, ) -> Self { - match value { - IdentityCreditWithdrawalTransition::V0(v0) => { - BumpIdentityNonceActionV0::from_borrowed_identity_credit_withdrawal(v0).into() - } - } + BumpIdentityNonceActionV0::from_borrowed_identity_credit_withdrawal(value).into() } /// from identity withdrawal action diff --git a/packages/rs-drive/src/state_transition_action/system/bump_identity_nonce_action/v0/transformer.rs b/packages/rs-drive/src/state_transition_action/system/bump_identity_nonce_action/v0/transformer.rs index 99cb834032..8c5520f7d7 100644 --- a/packages/rs-drive/src/state_transition_action/system/bump_identity_nonce_action/v0/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/system/bump_identity_nonce_action/v0/transformer.rs @@ -6,8 +6,10 @@ use crate::state_transition_action::system::bump_identity_nonce_action::BumpIden use dpp::data_contract::accessors::v0::DataContractV0Getters; use dpp::state_transition::data_contract_create_transition::DataContractCreateTransitionV0; use dpp::state_transition::identity_credit_transfer_transition::v0::IdentityCreditTransferTransitionV0; -use dpp::state_transition::identity_credit_withdrawal_transition::v0::IdentityCreditWithdrawalTransitionV0; +use dpp::state_transition::identity_credit_withdrawal_transition::accessors::IdentityCreditWithdrawalTransitionAccessorsV0; +use dpp::state_transition::identity_credit_withdrawal_transition::IdentityCreditWithdrawalTransition; use dpp::state_transition::identity_update_transition::v0::IdentityUpdateTransitionV0; +use dpp::state_transition::StateTransitionLike; impl BumpIdentityNonceActionV0 { /// from identity update @@ -199,34 +201,22 @@ impl BumpIdentityNonceActionV0 { } /// from identity credit withdrawal - pub fn from_identity_credit_withdrawal(value: IdentityCreditWithdrawalTransitionV0) -> Self { - let IdentityCreditWithdrawalTransitionV0 { - identity_id, - nonce, - user_fee_increase, - .. - } = value; + pub fn from_identity_credit_withdrawal(value: IdentityCreditWithdrawalTransition) -> Self { BumpIdentityNonceActionV0 { - identity_id, - identity_nonce: nonce, - user_fee_increase, + identity_id: value.identity_id(), + identity_nonce: value.nonce(), + user_fee_increase: value.user_fee_increase(), } } /// from borrowed identity credit withdrawal pub fn from_borrowed_identity_credit_withdrawal( - value: &IdentityCreditWithdrawalTransitionV0, + value: &IdentityCreditWithdrawalTransition, ) -> Self { - let IdentityCreditWithdrawalTransitionV0 { - identity_id, - nonce, - user_fee_increase, - .. - } = value; BumpIdentityNonceActionV0 { - identity_id: *identity_id, - identity_nonce: *nonce, - user_fee_increase: *user_fee_increase, + identity_id: value.identity_id(), + identity_nonce: value.nonce(), + user_fee_increase: value.user_fee_increase(), } } diff --git a/packages/rs-drive/src/util/batch/drive_op_batch/mod.rs b/packages/rs-drive/src/util/batch/drive_op_batch/mod.rs index 144bcda787..abdd9f4cc6 100644 --- a/packages/rs-drive/src/util/batch/drive_op_batch/mod.rs +++ b/packages/rs-drive/src/util/batch/drive_op_batch/mod.rs @@ -229,7 +229,7 @@ mod tests { #[test] fn test_add_dashpay_documents() { - let drive: Drive = setup_drive_with_initial_state_structure(); + let drive: Drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); let mut drive_operations = vec![]; @@ -336,7 +336,7 @@ mod tests { #[test] fn test_add_multiple_dashpay_documents_individually_should_succeed() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); @@ -435,7 +435,7 @@ mod tests { #[test] fn test_add_multiple_dashpay_documents() { - let drive: Drive = setup_drive_with_initial_state_structure(); + let drive: Drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); @@ -568,7 +568,7 @@ mod tests { #[test] fn test_add_multiple_family_documents() { - let drive: Drive = setup_drive_with_initial_state_structure(); + let drive: Drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); @@ -679,7 +679,7 @@ mod tests { #[test] fn test_update_multiple_family_documents() { - let drive: Drive = setup_drive_with_initial_state_structure(); + let drive: Drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); @@ -897,7 +897,7 @@ mod tests { #[test] fn test_update_multiple_family_documents_with_index_being_removed_and_added() { - let drive: Drive = setup_drive_with_initial_state_structure(); + let drive: Drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); diff --git a/packages/rs-drive/src/util/batch/drive_op_batch/withdrawals.rs b/packages/rs-drive/src/util/batch/drive_op_batch/withdrawals.rs index 972f6be00e..26bf6617a7 100644 --- a/packages/rs-drive/src/util/batch/drive_op_batch/withdrawals.rs +++ b/packages/rs-drive/src/util/batch/drive_op_batch/withdrawals.rs @@ -1,22 +1,25 @@ use std::collections::HashMap; use crate::drive::identity::withdrawals::paths::{ - get_withdrawal_root_path_vec, get_withdrawal_transactions_queue_path, - get_withdrawal_transactions_queue_path_vec, WITHDRAWAL_TRANSACTIONS_NEXT_INDEX_KEY, + get_withdrawal_root_path_vec, get_withdrawal_transactions_broadcasted_path_vec, + get_withdrawal_transactions_queue_path_vec, get_withdrawal_transactions_sum_tree_path_vec, + WITHDRAWAL_TRANSACTIONS_NEXT_INDEX_KEY, }; -use crate::drive::identity::withdrawals::{ - WithdrawalTransactionIndex, WithdrawalTransactionIndexAndBytes, +use crate::util::grove_operations::{ + BatchDeleteApplyType, BatchInsertApplyType, BatchMoveApplyType, }; -use crate::util::grove_operations::BatchDeleteApplyType; use crate::util::object_size_info::PathKeyElementInfo; use crate::{drive::Drive, error::Error, fees::op::LowLevelDriveOperation}; use dpp::block::block_info::BlockInfo; +use super::DriveLowLevelOperationConverter; +use crate::query::Query; +use dpp::fee::{Credits, SignedCredits}; +use dpp::prelude::TimestampMillis; use dpp::version::PlatformVersion; -use grovedb::Element; +use dpp::withdrawal::{WithdrawalTransactionIndex, WithdrawalTransactionIndexAndBytes}; use grovedb::{batch::KeyInfoPath, EstimatedLayerInformation, TransactionArg}; - -use super::DriveLowLevelOperationConverter; +use grovedb::{Element, PathQuery, SizedQuery}; /// Operations for Withdrawals #[derive(Clone, Debug)] @@ -31,10 +34,27 @@ pub enum WithdrawalOperationType { /// transaction id bytes withdrawal_transactions: Vec, }, - /// Delete withdrawal - DeleteWithdrawalTransaction { - /// withdrawal transaction tuple with id and bytes - index: WithdrawalTransactionIndex, + /// Deletes the withdrawal transactions from the main queue and adds them to the broadcasted queue + MoveWithdrawalTransactionsToBroadcasted { + /// A vector of the indexes to be moved + indexes: Vec, + }, + /// Deletes the withdrawal transactions from the main queue and adds them to the broadcasted queue + MoveBroadcastedWithdrawalTransactionsBackToQueueForResigning { + /// A vector of the indexes to be moved + indexes: Vec, + }, + /// Deletes the withdrawal transactions from the broadcasted queue + DeleteCompletedBroadcastedWithdrawalTransactions { + /// A vector of the indexes to be deleted + indexes: Vec, + }, + /// Reserve an amount in the system for withdrawals, the reservation will expire at the date given + ReserveWithdrawalAmount { + /// amount to reserve + amount: Credits, + /// expiration date + expiration_after: TimestampMillis, }, } @@ -45,7 +65,7 @@ impl DriveLowLevelOperationConverter for WithdrawalOperationType { _estimated_costs_only_with_layer_info: &mut Option< HashMap, >, - _block_info: &BlockInfo, + block_info: &BlockInfo, transaction: TransactionArg, platform_version: &PlatformVersion, ) -> Result, Error> { @@ -76,7 +96,7 @@ impl DriveLowLevelOperationConverter for WithdrawalOperationType { for (index, bytes) in withdrawal_transactions { drive.batch_insert( - PathKeyElementInfo::PathKeyElement::<'_, 1>(( + PathKeyElementInfo::PathKeyElement::<'_, 0>(( path.clone(), index.to_be_bytes().to_vec(), Element::Item(bytes, None), @@ -88,14 +108,140 @@ impl DriveLowLevelOperationConverter for WithdrawalOperationType { Ok(drive_operations) } - WithdrawalOperationType::DeleteWithdrawalTransaction { index } => { + WithdrawalOperationType::ReserveWithdrawalAmount { + amount, + expiration_after, + } => { + let mut drive_operations = vec![]; + + let expiration_date = block_info.time_ms + expiration_after; + + let sum_path = get_withdrawal_transactions_sum_tree_path_vec(); + + drive.batch_insert_sum_item_or_add_to_if_already_exists( + PathKeyElementInfo::PathKeyElement::<'_, 0>(( + sum_path.clone(), + expiration_date.to_be_bytes().to_vec(), + Element::SumItem(amount as SignedCredits, None), + )), + BatchInsertApplyType::StatefulBatchInsert, + transaction, + &mut drive_operations, + &platform_version.drive, + )?; + + Ok(drive_operations) + } + WithdrawalOperationType::MoveWithdrawalTransactionsToBroadcasted { indexes } => { + let mut drive_operations = vec![]; + + if indexes.is_empty() { + return Ok(drive_operations); + } + + let original_path = get_withdrawal_transactions_queue_path_vec(); + let new_path = get_withdrawal_transactions_broadcasted_path_vec(); + + let mut query = Query::new(); + + let len = indexes.len(); + + query.insert_keys( + indexes + .into_iter() + .map(|index| index.to_be_bytes().to_vec()) + .collect(), + ); + + let path_query = PathQuery::new( + original_path, + SizedQuery::new(query, Some(len as u16), None), + ); + + drive.batch_move_items_in_path_query( + &path_query, + new_path, + true, + // we know that we are not deleting a subtree + BatchMoveApplyType::StatefulBatchMove { + is_known_to_be_subtree_with_sum: Some((false, false)), + }, + transaction, + &mut drive_operations, + &platform_version.drive, + )?; + + Ok(drive_operations) + } + WithdrawalOperationType::MoveBroadcastedWithdrawalTransactionsBackToQueueForResigning { indexes } => { + let mut drive_operations = vec![]; + + if indexes.is_empty() { + return Ok(drive_operations); + } + + let original_path = get_withdrawal_transactions_broadcasted_path_vec(); + let new_path = get_withdrawal_transactions_queue_path_vec(); + + let mut query = Query::new(); + + let len = indexes.len(); + + query.insert_keys( + indexes + .into_iter() + .map(|index| index.to_be_bytes().to_vec()) + .collect(), + ); + + let path_query = PathQuery::new( + original_path, + SizedQuery::new(query, Some(len as u16), None), + ); + + drive.batch_move_items_in_path_query( + &path_query, + new_path, + true, + // we know that we are not deleting a subtree + BatchMoveApplyType::StatefulBatchMove { + is_known_to_be_subtree_with_sum: Some((false, false)), + }, + transaction, + &mut drive_operations, + &platform_version.drive, + )?; + + Ok(drive_operations) + } + WithdrawalOperationType::DeleteCompletedBroadcastedWithdrawalTransactions { indexes } => { let mut drive_operations = vec![]; - let path = get_withdrawal_transactions_queue_path(); + if indexes.is_empty() { + return Ok(drive_operations); + } + + let path = get_withdrawal_transactions_broadcasted_path_vec(); + + let mut query = Query::new(); + + let len = indexes.len(); + + query.insert_keys( + indexes + .into_iter() + .map(|index| index.to_be_bytes().to_vec()) + .collect(), + ); + + let path_query = PathQuery::new( + path, + SizedQuery::new(query, Some(len as u16), None), + ); - drive.batch_delete( - (&path).into(), - &index.to_be_bytes(), + drive.batch_delete_items_in_path_query( + &path_query, + true, // we know that we are not deleting a subtree BatchDeleteApplyType::StatefulBatchDelete { is_known_to_be_subtree_with_sum: Some((false, false)), diff --git a/packages/rs-drive/src/util/grove_operations/batch_delete_items_in_path_query/mod.rs b/packages/rs-drive/src/util/grove_operations/batch_delete_items_in_path_query/mod.rs new file mode 100644 index 0000000000..24b03094ef --- /dev/null +++ b/packages/rs-drive/src/util/grove_operations/batch_delete_items_in_path_query/mod.rs @@ -0,0 +1,56 @@ +mod v0; + +use crate::drive::Drive; +use crate::error::drive::DriveError; +use crate::error::Error; +use crate::fees::op::LowLevelDriveOperation; +use crate::util::grove_operations::BatchDeleteApplyType; + +use dpp::version::drive_versions::DriveVersion; + +use grovedb::{PathQuery, TransactionArg}; + +impl Drive { + /// Pushes multiple "delete element" operations for items in a given path based on a `PathQuery` to `drive_operations`. + /// + /// # Parameters + /// * `path_query`: The path query specifying the items to delete within the path. + /// * `error_if_intermediate_path_tree_not_present`: Tells the function to either error or do nothing if an intermediate tree is not present. + /// * `apply_type`: The apply type for the delete operations. + /// * `transaction`: The transaction argument. + /// * `drive_operations`: The vector containing low-level drive operations. + /// * `drive_version`: The drive version to select the correct function version to run. + /// + /// # Returns + /// * `Ok(())` if the operation was successful. + /// * `Err(DriveError::UnknownVersionMismatch)` if the drive version does not match known versions. + pub fn batch_delete_items_in_path_query( + &self, + path_query: &PathQuery, + error_if_intermediate_path_tree_not_present: bool, + apply_type: BatchDeleteApplyType, + transaction: TransactionArg, + drive_operations: &mut Vec, + drive_version: &DriveVersion, + ) -> Result<(), Error> { + match drive_version + .grove_methods + .batch + .batch_delete_items_in_path_query + { + 0 => self.batch_delete_items_in_path_query_v0( + path_query, + error_if_intermediate_path_tree_not_present, + apply_type, + transaction, + drive_operations, + drive_version, + ), + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "batch_delete_items_in_path_query".to_string(), + known_versions: vec![0], + received: version, + })), + } + } +} diff --git a/packages/rs-drive/src/util/grove_operations/batch_delete_items_in_path_query/v0/mod.rs b/packages/rs-drive/src/util/grove_operations/batch_delete_items_in_path_query/v0/mod.rs new file mode 100644 index 0000000000..a530776986 --- /dev/null +++ b/packages/rs-drive/src/util/grove_operations/batch_delete_items_in_path_query/v0/mod.rs @@ -0,0 +1,588 @@ +use crate::drive::Drive; +use crate::error::drive::DriveError; +use crate::error::Error; +use crate::fees::op::LowLevelDriveOperation; +use crate::fees::op::LowLevelDriveOperation::GroveOperation; +use crate::util::grove_operations::{push_drive_operation_result, BatchDeleteApplyType}; +use grovedb::batch::key_info::KeyInfo; +use grovedb::batch::KeyInfoPath; +use grovedb::operations::delete::DeleteOptions; +use grovedb::query_result_type::QueryResultType; +use grovedb::{GroveDb, PathQuery, TransactionArg}; +use grovedb_storage::rocksdb_storage::RocksDbStorage; +use platform_version::version::drive_versions::DriveVersion; + +impl Drive { + /// Version 0 implementation of the "delete multiple elements" operation based on a `PathQuery`. + /// Deletes items in the specified path that match the given query. + /// + /// # Parameters + /// * `path_query`: The path query specifying the items to delete within the path. + /// * `error_if_intermediate_path_tree_not_present`: Tells the function to either error or do nothing if an intermediate tree is not present. + /// * `apply_type`: The apply type for the delete operations. + /// * `transaction`: The transaction argument. + /// * `drive_operations`: The vector containing low-level drive operations. + /// * `drive_version`: The drive version to select the correct function version to run. + /// + /// # Returns + /// * `Ok(())` if the operation was successful. + /// * `Err(DriveError::CorruptedCodeExecution)` if the operation is not supported. + pub(super) fn batch_delete_items_in_path_query_v0( + &self, + path_query: &PathQuery, + error_if_intermediate_path_tree_not_present: bool, + apply_type: BatchDeleteApplyType, + transaction: TransactionArg, + drive_operations: &mut Vec, + drive_version: &DriveVersion, + ) -> Result<(), Error> { + if path_query.query.limit == None { + Error::Drive(DriveError::NotSupported( + "Limits are required for path_query", + )); + } + let query_result = if path_query + .query + .query + .items + .iter() + .all(|query_item| query_item.is_key()) + { + // Fetch the elements that match the path query + let query_result = self.grove_get_raw_path_query_with_optional( + path_query, + error_if_intermediate_path_tree_not_present, + transaction, + drive_operations, + drive_version, + )?; + + query_result + .into_iter() + .filter_map(|(path, key, maybe_element)| { + maybe_element.map(|element| (path, key, element)) + }) + .collect() + } else { + self.grove_get_raw_path_query( + path_query, + transaction, + QueryResultType::QueryPathKeyElementTrioResultType, + drive_operations, + drive_version, + )? + .0 + .to_path_key_elements() + }; + + // Iterate over each element and add a delete operation for it + for (path, key, _) in query_result { + let current_batch_operations = + LowLevelDriveOperation::grovedb_operations_batch(drive_operations); + let options = DeleteOptions { + allow_deleting_non_empty_trees: false, + deleting_non_empty_trees_returns_error: true, + base_root_storage_is_free: true, + validate_tree_at_path_exists: false, + }; + let delete_operation = match apply_type { + BatchDeleteApplyType::StatelessBatchDelete { + is_sum_tree, + estimated_key_size, + estimated_value_size, + } => GroveDb::average_case_delete_operation_for_delete::( + &KeyInfoPath::from_known_owned_path(path.to_vec()), + &KeyInfo::KnownKey(key.to_vec()), + is_sum_tree, + false, + true, + 0, + (estimated_key_size, estimated_value_size), + &drive_version.grove_version, + ) + .map(|r| r.map(Some)), + BatchDeleteApplyType::StatefulBatchDelete { + is_known_to_be_subtree_with_sum, + } => self.grove.delete_operation_for_delete_internal( + (path.as_slice()).into(), + key.as_slice(), + &options, + is_known_to_be_subtree_with_sum, + ¤t_batch_operations.operations, + transaction, + &drive_version.grove_version, + ), + }; + + if let Some(delete_operation) = + push_drive_operation_result(delete_operation, drive_operations)? + { + // Add the delete operation to the batch of drive operations + drive_operations.push(GroveOperation(delete_operation)); + } + } + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use crate::util::grove_operations::QueryType; + use crate::util::test_helpers::setup::setup_drive; + use crate::{ + error::Error, + grovedb::{Element, PathQuery, Query}, + util::grove_operations::BatchDeleteApplyType, + }; + use assert_matches::assert_matches; + use grovedb::SizedQuery; + use grovedb_path::SubtreePath; + use platform_version::version::PlatformVersion; + + #[test] + fn test_batch_delete_items_in_path_query_success() { + // Set up a test drive instance and transaction + let drive = setup_drive(None); + let platform_version = PlatformVersion::latest(); + let transaction = drive.grove.start_transaction(); + + // Insert some elements that will be matched and deleted + let path = vec![b"root".to_vec()]; + let key = b"key".to_vec(); + let element = Element::new_item(b"value".to_vec()); + + drive + .grove_insert_empty_tree( + SubtreePath::empty(), + b"root", + Some(&transaction), + None, + &mut vec![], + &platform_version.drive, + ) + .expect("expected insert root tree"); + + drive + .grove + .insert( + path.as_slice(), + &key, + element.clone(), + None, + Some(&transaction), + &platform_version.drive.grove_version, + ) + .unwrap() + .expect("expected insert"); + + // Create a path query that matches the inserted elements + let mut query = Query::new(); + query.insert_key(key.clone()); + let path_query = PathQuery::new(path.clone(), SizedQuery::new(query, Some(1), None)); + + // Set up the apply type and drive operations vector + let apply_type = BatchDeleteApplyType::StatefulBatchDelete { + is_known_to_be_subtree_with_sum: None, + }; + let mut drive_operations = Vec::new(); + + // Call the function + drive + .batch_delete_items_in_path_query_v0( + &path_query, + true, + apply_type, + Some(&transaction), + &mut drive_operations, + &platform_version.drive, + ) + .expect("expected to batch delete items"); + + drive + .apply_batch_low_level_drive_operations( + None, + Some(&transaction), + drive_operations, + &mut vec![], + &platform_version.drive, + ) + .expect("expected to apply operations"); + + // Commit the transaction + drive + .grove + .commit_transaction(transaction) + .unwrap() + .expect("expected to commit transaction"); + + // Verify the element has been deleted + let get_result = drive.grove_get( + path.as_slice().into(), + &key, + QueryType::StatefulQuery, + None, + &mut vec![], + &platform_version.drive, + ); + assert_matches!( + get_result, + Err(Error::GroveDB(grovedb::Error::PathKeyNotFound(_))) + ); + } + + #[test] + fn test_batch_delete_items_in_path_query_range_query() { + // Set up a test drive instance and transaction + let drive = setup_drive(None); + let platform_version = PlatformVersion::latest(); + let transaction = drive.grove.start_transaction(); + + // Insert the root tree + drive + .grove_insert_empty_tree( + SubtreePath::empty(), + b"root", + Some(&transaction), + None, + &mut vec![], + &platform_version.drive, + ) + .expect("expected to insert root tree"); + + // Insert three elements with keys 1, 2, and 3 + let path = vec![b"root".to_vec()]; + let key1 = b"1".to_vec(); + let key2 = b"2".to_vec(); + let key3 = b"3".to_vec(); + let element = Element::new_item(b"value".to_vec()); + + drive + .grove + .insert( + path.as_slice(), + &key1, + element.clone(), + None, + Some(&transaction), + &platform_version.drive.grove_version, + ) + .unwrap() + .expect("expected insert for key 1"); + + drive + .grove + .insert( + path.as_slice(), + &key2, + element.clone(), + None, + Some(&transaction), + &platform_version.drive.grove_version, + ) + .unwrap() + .expect("expected insert for key 2"); + + drive + .grove + .insert( + path.as_slice(), + &key3, + element.clone(), + None, + Some(&transaction), + &platform_version.drive.grove_version, + ) + .unwrap() + .expect("expected insert for key 3"); + + // Create a range path query that matches keys less than 3 + let mut query = Query::new(); + query.insert_range_to(..b"3".to_vec()); + let path_query = PathQuery::new(path.clone(), SizedQuery::new(query, Some(100), None)); + + // Set up the apply type and drive operations vector + let apply_type = BatchDeleteApplyType::StatefulBatchDelete { + is_known_to_be_subtree_with_sum: None, + }; + let mut drive_operations = Vec::new(); + + // Call the function + drive + .batch_delete_items_in_path_query_v0( + &path_query, + true, + apply_type, + Some(&transaction), + &mut drive_operations, + &platform_version.drive, + ) + .expect("expected to batch delete items"); + + // Apply batch operations + drive + .apply_batch_low_level_drive_operations( + None, + Some(&transaction), + drive_operations, + &mut vec![], + &platform_version.drive, + ) + .expect("expected to apply operations"); + + // Commit the transaction + drive + .grove + .commit_transaction(transaction) + .unwrap() + .expect("expected to commit transaction"); + + // Verify that keys 1 and 2 have been deleted + let get_result_1 = drive.grove_get( + path.as_slice().into(), + &key1, + QueryType::StatefulQuery, + None, + &mut vec![], + &platform_version.drive, + ); + assert_matches!( + get_result_1, + Err(Error::GroveDB(grovedb::Error::PathKeyNotFound(_))) + ); + + let get_result_2 = drive.grove_get( + path.as_slice().into(), + &key2, + QueryType::StatefulQuery, + None, + &mut vec![], + &platform_version.drive, + ); + assert_matches!( + get_result_2, + Err(Error::GroveDB(grovedb::Error::PathKeyNotFound(_))) + ); + + // Verify that key 3 is still there + let get_result_3 = drive.grove_get( + path.as_slice().into(), + &key3, + QueryType::StatefulQuery, + None, + &mut vec![], + &platform_version.drive, + ); + assert_matches!(get_result_3, Ok(Some(Element::Item(..)))); + } + + #[test] + fn test_batch_delete_items_in_path_query_no_elements() { + // Set up a test drive instance and transaction + let drive = setup_drive(None); + let platform_version = PlatformVersion::latest(); + let transaction = drive.grove.start_transaction(); + + // Create the root tree to allow querying it + drive + .grove_insert_empty_tree( + SubtreePath::empty(), + b"root", + Some(&transaction), + None, + &mut vec![], + &platform_version.drive, + ) + .expect("expected to insert root tree"); + + // Create a path query that does not match any elements + let path = vec![b"root".to_vec()]; + let mut query = Query::new(); + query.insert_key(b"non_existent_key".to_vec()); + let path_query = PathQuery::new(path.clone(), SizedQuery::new(query, Some(1), None)); + + // Set up the apply type and drive operations vector + let apply_type = BatchDeleteApplyType::StatefulBatchDelete { + is_known_to_be_subtree_with_sum: None, + }; + let mut drive_operations = Vec::new(); + + // Call the function + drive + .batch_delete_items_in_path_query_v0( + &path_query, + true, + apply_type, + Some(&transaction), + &mut drive_operations, + &platform_version.drive, + ) + .expect("expected batch delete to succeed"); + + // Apply batch operations + drive + .apply_batch_low_level_drive_operations( + None, + Some(&transaction), + drive_operations, + &mut vec![], + &platform_version.drive, + ) + .expect("expected to apply operations"); + + // Commit the transaction + drive + .grove + .commit_transaction(transaction) + .unwrap() + .expect("expected to commit transaction"); + + // Verify that no elements were deleted as no matching elements existed + let get_result = drive.grove_get( + path.as_slice().into(), + b"non_existent_key", + QueryType::StatefulQuery, + None, + &mut vec![], + &platform_version.drive, + ); + assert_matches!( + get_result, + Err(Error::GroveDB(grovedb::Error::PathKeyNotFound(_))) + ); + } + + #[test] + fn test_batch_delete_items_in_path_query_intermediate_path_missing() { + // Set up a test drive instance and transaction + let drive = setup_drive(None); + let platform_version = PlatformVersion::latest(); + let transaction = drive.grove.start_transaction(); + + // Create a path query with a missing intermediate path + let path = vec![b"missing_root".to_vec()]; + let mut query = Query::new(); + query.insert_key(b"key".to_vec()); + let path_query = PathQuery::new(path.clone(), SizedQuery::new(query, Some(1), None)); + + // Set up the apply type and drive operations vector + let apply_type = BatchDeleteApplyType::StatefulBatchDelete { + is_known_to_be_subtree_with_sum: None, + }; + let mut drive_operations = Vec::new(); + + // Call the function with error_if_intermediate_path_tree_not_present set to true + let result = drive.batch_delete_items_in_path_query_v0( + &path_query, + true, + apply_type, + Some(&transaction), + &mut drive_operations, + &platform_version.drive, + ); + + // Assert failure due to missing intermediate path + assert_matches!( + result, + Err(Error::GroveDB(grovedb::Error::PathParentLayerNotFound(_))) + ); + } + + #[test] + fn test_batch_delete_items_in_path_query_stateless_delete() { + // Set up a test drive instance and transaction + let drive = setup_drive(None); + let platform_version = PlatformVersion::latest(); + let transaction = drive.grove.start_transaction(); + + // Insert some elements that will be matched and deleted + let path = vec![b"root".to_vec()]; + let key = b"key".to_vec(); + let element = Element::new_item(b"value".to_vec()); + + // Insert the root tree + drive + .grove_insert_empty_tree( + SubtreePath::empty(), + b"root", + Some(&transaction), + None, + &mut vec![], + &platform_version.drive, + ) + .expect("expected to insert root tree"); + + // Insert an item in the tree + drive + .grove + .insert( + path.as_slice(), + &key, + element.clone(), + None, + Some(&transaction), + &platform_version.drive.grove_version, + ) + .unwrap() + .expect("expected insert"); + + // Create a path query that matches the inserted elements + let mut query = Query::new(); + query.insert_key(key.clone()); + let path_query = PathQuery::new(path.clone(), SizedQuery::new(query, Some(1), None)); + + // Set up the stateless apply type with estimated sizes + let apply_type = BatchDeleteApplyType::StatelessBatchDelete { + is_sum_tree: false, + estimated_key_size: key.len() as u32, + estimated_value_size: element + .serialized_size(&platform_version.drive.grove_version) + .unwrap() as u32, + }; + let mut drive_operations = Vec::new(); + + // Call the function + drive + .batch_delete_items_in_path_query_v0( + &path_query, + true, + apply_type, + Some(&transaction), + &mut drive_operations, + &platform_version.drive, + ) + .expect("expected to batch delete items"); + + // Apply batch operations + drive + .apply_batch_low_level_drive_operations( + None, + Some(&transaction), + drive_operations, + &mut vec![], + &platform_version.drive, + ) + .expect("expected to apply operations"); + + // Commit the transaction + drive + .grove + .commit_transaction(transaction) + .unwrap() + .expect("expected to commit transaction"); + + // Verify the element has been deleted + let get_result = drive.grove_get( + path.as_slice().into(), + &key, + QueryType::StatefulQuery, + None, + &mut vec![], + &platform_version.drive, + ); + assert_matches!( + get_result, + Err(Error::GroveDB(grovedb::Error::PathKeyNotFound(_))) + ); + } +} diff --git a/packages/rs-drive/src/util/grove_operations/batch_insert_if_not_exists/mod.rs b/packages/rs-drive/src/util/grove_operations/batch_insert_if_not_exists/mod.rs index d14f1e2773..c08390ba86 100644 --- a/packages/rs-drive/src/util/grove_operations/batch_insert_if_not_exists/mod.rs +++ b/packages/rs-drive/src/util/grove_operations/batch_insert_if_not_exists/mod.rs @@ -23,7 +23,7 @@ impl Drive { /// * `drive_version`: The drive version to select the correct function version to run. /// /// # Returns - /// * `Ok(bool)` if the operation was successful. Returns true if the path key already exists without references. + /// * `Ok(bool)` if the operation was successful. Returns true if we were able to insert. /// * `Err(DriveError::UnknownVersionMismatch)` if the drive version does not match known versions. /// * `Err(DriveError::CorruptedCodeExecution)` if the operation is not supported. pub fn batch_insert_if_not_exists( diff --git a/packages/rs-drive/src/util/grove_operations/batch_insert_if_not_exists/v0/mod.rs b/packages/rs-drive/src/util/grove_operations/batch_insert_if_not_exists/v0/mod.rs index 8bacd80606..8fc5c16c5b 100644 --- a/packages/rs-drive/src/util/grove_operations/batch_insert_if_not_exists/v0/mod.rs +++ b/packages/rs-drive/src/util/grove_operations/batch_insert_if_not_exists/v0/mod.rs @@ -15,7 +15,7 @@ use grovedb::{GroveDb, TransactionArg}; impl Drive { /// Pushes an "insert element if the path key does not yet exist" operation to `drive_operations`. - /// Returns true if the path key already exists without references. + /// Returns true if we inserted. pub(crate) fn batch_insert_if_not_exists_v0( &self, path_key_element_info: PathKeyElementInfo, diff --git a/packages/rs-drive/src/util/grove_operations/batch_insert_if_not_exists_return_existing_element/mod.rs b/packages/rs-drive/src/util/grove_operations/batch_insert_if_not_exists_return_existing_element/mod.rs new file mode 100644 index 0000000000..df437be5b2 --- /dev/null +++ b/packages/rs-drive/src/util/grove_operations/batch_insert_if_not_exists_return_existing_element/mod.rs @@ -0,0 +1,69 @@ +mod v0; + +use crate::util::grove_operations::BatchInsertApplyType; + +use crate::drive::Drive; +use crate::error::drive::DriveError; +use crate::error::Error; +use crate::fees::op::LowLevelDriveOperation; +use crate::util::object_size_info::PathKeyElementInfo; + +use dpp::version::drive_versions::DriveVersion; +use grovedb::{Element, TransactionArg}; + +impl Drive { + /// Pushes an "insert element if the path key does not yet exist" operation to `drive_operations` + /// and returns the existing element if it already exists. + /// + /// This function attempts to insert a new element into the database at a specified path and key. + /// If an element already exists at the given path and key, it returns the existing element without inserting the new one. + /// If the element does not exist, it inserts the new element and returns `Ok(None)`. + /// + /// The function dynamically selects the appropriate implementation version based on the provided `drive_version`. + /// + /// # Parameters + /// + /// * `path_key_element_info`: Information about the path, key, and element to be inserted. + /// - Supports various configurations including direct references, owned elements, fixed-size keys, and estimated sizes. + /// * `apply_type`: Defines whether the operation is stateless or stateful, influencing how the insertion is handled. + /// * `transaction`: The transaction context in which the operation will be executed. + /// * `drive_operations`: A mutable reference to the list of drive operations where this operation will be appended. + /// * `drive_version`: The version of the drive being used, determining which function version to execute. + /// + /// # Returns + /// + /// * `Ok(Some(Element))`: If an element already exists at the specified path and key, it returns the existing element. + /// * `Ok(None)`: If the element was successfully inserted because it did not exist before. + /// * `Err(Error)`: Returns an error if: + /// - The drive version provided is not supported (`Error::Drive(DriveError::UnknownVersionMismatch)`). + /// - The operation is not supported in the current state due to invalid configurations or unsupported features (`Error::Drive(DriveError::NotSupportedPrivate)`). + /// + /// # Errors + /// + /// * `Error::Drive(DriveError::UnknownVersionMismatch)`: If the provided drive version is not supported by this function. + /// * `Error::Drive(DriveError::NotSupportedPrivate)`: If the function encounters unsupported configurations such as unknown element sizes for batch operations. + /// + pub fn batch_insert_if_not_exists_return_existing_element( + &self, + path_key_element_info: PathKeyElementInfo, + apply_type: BatchInsertApplyType, + transaction: TransactionArg, + drive_operations: &mut Vec, + drive_version: &DriveVersion, + ) -> Result, Error> { + match drive_version.grove_methods.batch.batch_insert_if_not_exists { + 0 => self.batch_insert_if_not_exists_return_existing_element_v0( + path_key_element_info, + apply_type, + transaction, + drive_operations, + drive_version, + ), + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "batch_insert_if_not_exists_return_existing_element".to_string(), + known_versions: vec![0], + received: version, + })), + } + } +} diff --git a/packages/rs-drive/src/util/grove_operations/batch_insert_if_not_exists_return_existing_element/v0/mod.rs b/packages/rs-drive/src/util/grove_operations/batch_insert_if_not_exists_return_existing_element/v0/mod.rs new file mode 100644 index 0000000000..55f411caeb --- /dev/null +++ b/packages/rs-drive/src/util/grove_operations/batch_insert_if_not_exists_return_existing_element/v0/mod.rs @@ -0,0 +1,165 @@ +use crate::util::grove_operations::BatchInsertApplyType; +use crate::util::object_size_info::PathKeyElementInfo::{ + PathFixedSizeKeyRefElement, PathKeyElement, PathKeyElementSize, PathKeyRefElement, + PathKeyUnknownElementSize, +}; + +use crate::drive::Drive; +use crate::error::drive::DriveError; +use crate::error::Error; +use crate::fees::op::LowLevelDriveOperation; +use crate::fees::op::LowLevelDriveOperation::CalculatedCostOperation; +use crate::util::object_size_info::PathKeyElementInfo; +use dpp::version::drive_versions::DriveVersion; +use grovedb::{Element, GroveDb, TransactionArg}; + +impl Drive { + /// Version 0 implementation of the "insert element if the path key does not yet exist" operation. + /// If the element already exists, it returns the existing element. + /// + /// This function checks whether an element exists at a specified path and key. + /// If the element exists, it returns the existing element. If not, it inserts the new element + /// into the database and returns `None`. This operation supports different types of path, key, and element configurations + /// and can be applied in either stateless or stateful contexts. + /// + /// # Parameters + /// + /// * `path_key_element_info`: Information about the path, key, and element to insert. + /// - Supports multiple configurations: direct references, owned elements, fixed size keys, or estimated sizes. + /// * `apply_type`: The application type of the operation, defining whether the operation is stateless or stateful. + /// * `transaction`: The transaction context for the operation, allowing it to be atomic within a batch. + /// * `drive_operations`: A mutable reference to the list of drive operations to which this operation will be appended. + /// * `drive_version`: The version of the drive being used, ensuring compatibility with the function version. + /// + /// # Returns + /// + /// * `Ok(Some(Element))`: If the element already exists at the specified path and key, returning the existing element. + /// * `Ok(None)`: If the element was successfully inserted because it did not exist before. + /// * `Err(Error)`: Returns an error if: + /// - The insertion operation is not supported in the current state. + /// - The operation encounters any unexpected issues related to invalid configurations or unsupported features. + /// + /// # Errors + /// + /// * `Error::Drive(DriveError::NotSupportedPrivate)`: If the function encounters unsupported configurations, such as document sizes for stateful inserts. + /// * `Error::Drive(DriveError::UnknownVersionMismatch)`: If the drive version is not supported for the operation. + /// + /// # PathKeyElementInfo Variants + /// + /// The function supports various `PathKeyElementInfo` variants: + /// * `PathKeyRefElement`: Reference to the path, key, and element. + /// * `PathKeyElement`: Owned path, key, and element. + /// * `PathFixedSizeKeyRefElement`: Reference to the path with a fixed-size key and element. + /// * `PathKeyElementSize`: Path and key with known element size, used for estimation. + /// * `PathKeyUnknownElementSize`: Unsupported in this version and returns an error. + pub(super) fn batch_insert_if_not_exists_return_existing_element_v0( + &self, + path_key_element_info: PathKeyElementInfo, + apply_type: BatchInsertApplyType, + transaction: TransactionArg, + drive_operations: &mut Vec, + drive_version: &DriveVersion, + ) -> Result, Error> { + match path_key_element_info { + PathKeyRefElement((path, key, element)) => { + // Check if the element already exists + let existing_element = self.grove_get_raw_optional( + path.as_slice().into(), + key, + apply_type.to_direct_query_type(), + transaction, + drive_operations, + drive_version, + )?; + if let Some(existing_element) = existing_element { + return Ok(Some(existing_element)); + } + + // Element does not exist, proceed with insertion + drive_operations.push(LowLevelDriveOperation::insert_for_known_path_key_element( + path, + key.to_vec(), + element, + )); + Ok(None) + } + PathKeyElement((path, key, element)) => { + // Check if the element already exists + let existing_element = self.grove_get_raw_optional( + path.as_slice().into(), + key.as_slice(), + apply_type.to_direct_query_type(), + transaction, + drive_operations, + drive_version, + )?; + if let Some(existing_element) = existing_element { + return Ok(Some(existing_element)); + } + + // Element does not exist, proceed with insertion + drive_operations.push(LowLevelDriveOperation::insert_for_known_path_key_element( + path, key, element, + )); + Ok(None) + } + PathFixedSizeKeyRefElement((path, key, element)) => { + // Check if the element already exists + let existing_element = self.grove_get_raw_optional( + path.as_slice().into(), + key, + apply_type.to_direct_query_type(), + transaction, + drive_operations, + drive_version, + )?; + if let Some(existing_element) = existing_element { + return Ok(Some(existing_element)); + } + + // Element does not exist, proceed with insertion + let path_items: Vec> = path.into_iter().map(Vec::from).collect(); + drive_operations.push(LowLevelDriveOperation::insert_for_known_path_key_element( + path_items, + key.to_vec(), + element, + )); + Ok(None) + } + PathKeyElementSize((key_info_path, key_info, element)) => { + match apply_type { + BatchInsertApplyType::StatelessBatchInsert { + in_tree_using_sums, .. + } => { + // Estimate if the element with the given size already exists + drive_operations.push(CalculatedCostOperation( + GroveDb::average_case_for_has_raw( + &key_info_path, + &key_info, + element.serialized_size(&drive_version.grove_version)? as u32, + in_tree_using_sums, + &drive_version.grove_version, + )?, + )); + drive_operations.push( + LowLevelDriveOperation::insert_for_estimated_path_key_element( + key_info_path, + key_info, + element, + ), + ); + Ok(None) + } + BatchInsertApplyType::StatefulBatchInsert => { + Err(Error::Drive(DriveError::NotSupportedPrivate( + "document sizes for stateful insert in batch operations not supported", + ))) + } + } + } + PathKeyUnknownElementSize(_) => Err(Error::Drive(DriveError::NotSupportedPrivate( + "document sizes in batch operations not supported", + ))), + } + } +} diff --git a/packages/rs-drive/src/util/grove_operations/batch_insert_sum_item_or_add_to_if_already_exists/mod.rs b/packages/rs-drive/src/util/grove_operations/batch_insert_sum_item_or_add_to_if_already_exists/mod.rs new file mode 100644 index 0000000000..87331adad0 --- /dev/null +++ b/packages/rs-drive/src/util/grove_operations/batch_insert_sum_item_or_add_to_if_already_exists/mod.rs @@ -0,0 +1,58 @@ +mod v0; + +use crate::util::grove_operations::BatchInsertApplyType; + +use crate::drive::Drive; +use crate::error::drive::DriveError; +use crate::error::Error; +use crate::fees::op::LowLevelDriveOperation; +use crate::util::object_size_info::PathKeyElementInfo; + +use dpp::version::drive_versions::DriveVersion; +use grovedb::TransactionArg; + +impl Drive { + /// Pushes an "insert sum item or add to it if the item already exists" operation to `drive_operations`. + /// This operation either inserts a new sum item at the given path and key or adds the value to the existing sum item. + /// + /// # Parameters + /// * `path_key_element_info`: Information about the path, key, and element. + /// * `apply_type`: The apply type for the operation. + /// * `transaction`: The transaction argument for the operation. + /// * `drive_operations`: The list of drive operations to append to. + /// * `drive_version`: The drive version to select the correct function version to run. + /// + /// # Returns + /// * `Ok(())` if the operation was successful. + /// * `Err(DriveError::UnknownVersionMismatch)` if the drive version does not match known versions. + /// * `Err(DriveError::CorruptedCodeExecution)` (rare) if the operation is not supported. + /// * `Err(DriveError::CorruptedElementType)` (rare) if drive is in a corrupted state and + /// gives back an incorrect element type. + pub fn batch_insert_sum_item_or_add_to_if_already_exists( + &self, + path_key_element_info: PathKeyElementInfo, + apply_type: BatchInsertApplyType, + transaction: TransactionArg, + drive_operations: &mut Vec, + drive_version: &DriveVersion, + ) -> Result<(), Error> { + match drive_version + .grove_methods + .batch + .batch_insert_sum_item_or_add_to_if_already_exists + { + 0 => self.batch_insert_sum_item_or_add_to_if_already_exists_v0( + path_key_element_info, + apply_type, + transaction, + drive_operations, + drive_version, + ), + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "batch_insert_sum_item_or_add_to_if_already_exists".to_string(), + known_versions: vec![0], + received: version, + })), + } + } +} diff --git a/packages/rs-drive/src/util/grove_operations/batch_insert_sum_item_or_add_to_if_already_exists/v0/mod.rs b/packages/rs-drive/src/util/grove_operations/batch_insert_sum_item_or_add_to_if_already_exists/v0/mod.rs new file mode 100644 index 0000000000..8294a6786b --- /dev/null +++ b/packages/rs-drive/src/util/grove_operations/batch_insert_sum_item_or_add_to_if_already_exists/v0/mod.rs @@ -0,0 +1,220 @@ +use crate::util::grove_operations::BatchInsertApplyType; +use crate::util::object_size_info::PathKeyElementInfo::{ + PathFixedSizeKeyRefElement, PathKeyElement, PathKeyElementSize, PathKeyRefElement, + PathKeyUnknownElementSize, +}; + +use crate::drive::Drive; +use crate::error::drive::DriveError; +use crate::error::Error; +use crate::fees::op::LowLevelDriveOperation; +use crate::fees::op::LowLevelDriveOperation::CalculatedCostOperation; +use crate::util::object_size_info::PathKeyElementInfo; +use dpp::version::drive_versions::DriveVersion; +use dpp::ProtocolError; +use grovedb::{Element, GroveDb, TransactionArg}; + +impl Drive { + /// Version 0 implementation of the "insert sum item or add to it if the item already exists" operation. + /// This operation either inserts a new sum item at the given path and key or adds the value to the existing sum item. + /// + /// # Parameters + /// * `path_key_element_info`: Information about the path, key, and element. + /// * `apply_type`: The apply type for the operation. + /// * `transaction`: The transaction argument for the operation. + /// * `drive_operations`: The list of drive operations to append to. + /// * `drive_version`: The drive version to select the correct function version to run. + /// + /// # Returns + /// * `Ok(())` if the operation was successful. + /// * `Err(DriveError::CorruptedCodeExecution)` if the operation is not supported. + pub(crate) fn batch_insert_sum_item_or_add_to_if_already_exists_v0( + &self, + path_key_element_info: PathKeyElementInfo, + apply_type: BatchInsertApplyType, + transaction: TransactionArg, + drive_operations: &mut Vec, + drive_version: &DriveVersion, + ) -> Result<(), Error> { + match path_key_element_info { + PathKeyRefElement((path, key, element)) => { + if let Element::SumItem(new_value, _) = element { + // Check if the sum item already exists + let existing_element = self.grove_get_raw_optional( + path.as_slice().into(), + key, + apply_type.to_direct_query_type(), + transaction, + drive_operations, + drive_version, + )?; + + if let Some(Element::SumItem(existing_value, _)) = existing_element { + // Add to the existing sum item + let updated_value = existing_value + .checked_add(new_value) + .ok_or(ProtocolError::Overflow("overflow when adding to sum item"))?; + drive_operations.push( + LowLevelDriveOperation::insert_for_known_path_key_element( + path, + key.to_vec(), + Element::new_sum_item(updated_value), + ), + ); + } else if existing_element.is_some() { + return Err(Error::Drive(DriveError::CorruptedElementType( + "expected sum item element type", + ))); + } else { + // Insert as a new sum item + drive_operations.push( + LowLevelDriveOperation::insert_for_known_path_key_element( + path, + key.to_vec(), + Element::new_sum_item(new_value), + ), + ); + } + } else { + return Err(Error::Drive(DriveError::CorruptedCodeExecution( + "expected sum item element type", + ))); + } + Ok(()) + } + PathKeyElement((path, key, element)) => { + if let Element::SumItem(new_value, _) = element { + // Check if the sum item already exists + let existing_element = self.grove_get_raw_optional( + path.as_slice().into(), + key.as_slice(), + apply_type.to_direct_query_type(), + transaction, + drive_operations, + drive_version, + )?; + + if let Some(Element::SumItem(existing_value, _)) = existing_element { + // Add to the existing sum item + let updated_value = existing_value + .checked_add(new_value) + .ok_or(ProtocolError::Overflow("overflow when adding to sum item"))?; + drive_operations.push( + LowLevelDriveOperation::insert_for_known_path_key_element( + path, + key, + Element::new_sum_item(updated_value), + ), + ); + } else if existing_element.is_some() { + return Err(Error::Drive(DriveError::CorruptedElementType( + "expected sum item element type", + ))); + } else { + // Insert as a new sum item + drive_operations.push( + LowLevelDriveOperation::insert_for_known_path_key_element( + path, + key, + Element::new_sum_item(new_value), + ), + ); + } + } else { + return Err(Error::Drive(DriveError::CorruptedCodeExecution( + "expected sum item element type", + ))); + } + Ok(()) + } + PathFixedSizeKeyRefElement((path, key, element)) => { + if let Element::SumItem(new_value, _) = element { + // Check if the sum item already exists + let existing_element = self.grove_get_raw_optional( + path.as_slice().into(), + key, + apply_type.to_direct_query_type(), + transaction, + drive_operations, + drive_version, + )?; + + if let Some(Element::SumItem(existing_value, _)) = existing_element { + // Add to the existing sum item + let updated_value = existing_value + .checked_add(new_value) + .ok_or(ProtocolError::Overflow("overflow when adding to sum item"))?; + let path_items: Vec> = path.into_iter().map(Vec::from).collect(); + drive_operations.push( + LowLevelDriveOperation::insert_for_known_path_key_element( + path_items, + key.to_vec(), + Element::new_sum_item(updated_value), + ), + ); + } else if existing_element.is_some() { + return Err(Error::Drive(DriveError::CorruptedElementType( + "expected sum item element type", + ))); + } else { + // Insert as a new sum item + let path_items: Vec> = path.into_iter().map(Vec::from).collect(); + drive_operations.push( + LowLevelDriveOperation::insert_for_known_path_key_element( + path_items, + key.to_vec(), + Element::new_sum_item(new_value), + ), + ); + } + } else { + return Err(Error::Drive(DriveError::CorruptedCodeExecution( + "expected sum item element type", + ))); + } + Ok(()) + } + PathKeyElementSize((key_info_path, key_info, element)) => { + if let Element::SumItem(new_value, _) = element { + match apply_type { + BatchInsertApplyType::StatelessBatchInsert { + in_tree_using_sums, .. + } => { + // Estimate if the sum item with the given size already exists + drive_operations.push(CalculatedCostOperation( + GroveDb::average_case_for_has_raw( + &key_info_path, + &key_info, + element.serialized_size(&drive_version.grove_version)? as u32, + in_tree_using_sums, + &drive_version.grove_version, + )?, + )); + + drive_operations.push( + LowLevelDriveOperation::insert_for_estimated_path_key_element( + key_info_path, + key_info, + Element::new_sum_item(new_value), + ), + ); + Ok(()) + } + BatchInsertApplyType::StatefulBatchInsert => { + Err(Error::Drive(DriveError::NotSupportedPrivate( + "document sizes for stateful insert in batch operations not supported", + ))) + } + } + } else { + Err(Error::Drive(DriveError::CorruptedCodeExecution( + "expected sum item element type", + ))) + } + } + PathKeyUnknownElementSize(_) => Err(Error::Drive(DriveError::NotSupportedPrivate( + "document sizes in batch operations not supported", + ))), + } + } +} diff --git a/packages/rs-drive/src/util/grove_operations/batch_move_items_in_path_query/mod.rs b/packages/rs-drive/src/util/grove_operations/batch_move_items_in_path_query/mod.rs new file mode 100644 index 0000000000..ae886e0f54 --- /dev/null +++ b/packages/rs-drive/src/util/grove_operations/batch_move_items_in_path_query/mod.rs @@ -0,0 +1,58 @@ +mod v0; + +use crate::drive::Drive; +use crate::error::drive::DriveError; +use crate::error::Error; +use crate::fees::op::LowLevelDriveOperation; +use crate::util::grove_operations::BatchMoveApplyType; + +use dpp::version::drive_versions::DriveVersion; + +use grovedb::{PathQuery, TransactionArg}; + +impl Drive { + /// Pushes multiple "delete element" and "insert element operations for items in a given path based on a `PathQuery` to `drive_operations`. + /// + /// # Parameters + /// * `path_query`: The path query specifying the items to delete within the path. + /// * `error_if_intermediate_path_tree_not_present`: Tells the function to either error or do nothing if an intermediate tree is not present. + /// * `apply_type`: The apply type for the move operations. + /// * `transaction`: The transaction argument. + /// * `drive_operations`: The vector containing low-level drive operations. + /// * `drive_version`: The drive version to select the correct function version to run. + /// + /// # Returns + /// * `Ok(())` if the operation was successful. + /// * `Err(DriveError::UnknownVersionMismatch)` if the drive version does not match known versions. + pub fn batch_move_items_in_path_query( + &self, + path_query: &PathQuery, + new_path: Vec>, + error_if_intermediate_path_tree_not_present: bool, + apply_type: BatchMoveApplyType, + transaction: TransactionArg, + drive_operations: &mut Vec, + drive_version: &DriveVersion, + ) -> Result<(), Error> { + match drive_version + .grove_methods + .batch + .batch_move_items_in_path_query + { + 0 => self.batch_move_items_in_path_query_v0( + path_query, + new_path, + error_if_intermediate_path_tree_not_present, + apply_type, + transaction, + drive_operations, + drive_version, + ), + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "batch_move_items_in_path_query".to_string(), + known_versions: vec![0], + received: version, + })), + } + } +} diff --git a/packages/rs-drive/src/util/grove_operations/batch_move_items_in_path_query/v0/mod.rs b/packages/rs-drive/src/util/grove_operations/batch_move_items_in_path_query/v0/mod.rs new file mode 100644 index 0000000000..f8b2b904cc --- /dev/null +++ b/packages/rs-drive/src/util/grove_operations/batch_move_items_in_path_query/v0/mod.rs @@ -0,0 +1,530 @@ +use crate::drive::Drive; +use crate::error::drive::DriveError; +use crate::error::Error; +use crate::fees::op::LowLevelDriveOperation; +use crate::fees::op::LowLevelDriveOperation::GroveOperation; +use crate::util::grove_operations::{push_drive_operation_result, BatchMoveApplyType}; +use grovedb::batch::key_info::KeyInfo; +use grovedb::batch::{KeyInfoPath, QualifiedGroveDbOp}; +use grovedb::operations::delete::DeleteOptions; +use grovedb::query_result_type::QueryResultType; +use grovedb::{GroveDb, PathQuery, TransactionArg}; +use grovedb_storage::rocksdb_storage::RocksDbStorage; +use platform_version::version::drive_versions::DriveVersion; + +impl Drive { + /// Version 0 implementation of the "delete multiple elements" and "insert multiple elements" operation based on a `PathQuery`. + /// Deletes items in the specified path that match the given query. + /// Then inserts those items at the given path. + /// + /// # Parameters + /// * `path_query`: The path query specifying the items to delete within the path. + /// * `error_if_intermediate_path_tree_not_present`: Tells the function to either error or do nothing if an intermediate tree is not present. + /// * `apply_type`: The apply type for the move operations. + /// * `transaction`: The transaction argument. + /// * `drive_operations`: The vector containing low-level drive operations. + /// * `drive_version`: The drive version to select the correct function version to run. + /// + /// # Returns + /// * `Ok(())` if the operation was successful. + /// * `Err(DriveError::CorruptedCodeExecution)` if the operation is not supported. + pub(super) fn batch_move_items_in_path_query_v0( + &self, + path_query: &PathQuery, + new_path: Vec>, + error_if_intermediate_path_tree_not_present: bool, + apply_type: BatchMoveApplyType, + transaction: TransactionArg, + drive_operations: &mut Vec, + drive_version: &DriveVersion, + ) -> Result<(), Error> { + if path_query.query.limit == None { + return Err(Error::Drive(DriveError::NotSupported( + "Limits are required for path_query", + ))); + } + let query_result = if path_query + .query + .query + .items + .iter() + .all(|query_item| query_item.is_key()) + { + // Fetch the elements that match the path query + let query_result = self.grove_get_raw_path_query_with_optional( + path_query, + error_if_intermediate_path_tree_not_present, + transaction, + drive_operations, + drive_version, + )?; + + query_result + .into_iter() + .filter_map(|(path, key, maybe_element)| { + maybe_element.map(|element| (path, key, element)) + }) + .collect() + } else { + self.grove_get_raw_path_query( + path_query, + transaction, + QueryResultType::QueryPathKeyElementTrioResultType, + drive_operations, + drive_version, + )? + .0 + .to_path_key_elements() + }; + + // Iterate over each element and add a delete operation for it + for (path, key, element) in query_result { + let current_batch_operations = + LowLevelDriveOperation::grovedb_operations_batch(drive_operations); + let options = DeleteOptions { + allow_deleting_non_empty_trees: false, + deleting_non_empty_trees_returns_error: true, + base_root_storage_is_free: true, + validate_tree_at_path_exists: false, + }; + let delete_operation = match apply_type { + BatchMoveApplyType::StatelessBatchMove { + is_sum_tree, + estimated_key_size, + estimated_value_size, + .. + } => GroveDb::average_case_delete_operation_for_delete::( + &KeyInfoPath::from_known_owned_path(path.to_vec()), + &KeyInfo::KnownKey(key.to_vec()), + is_sum_tree, + false, + true, + 0, + (estimated_key_size, estimated_value_size), + &drive_version.grove_version, + ) + .map(|r| r.map(Some)), + BatchMoveApplyType::StatefulBatchMove { + is_known_to_be_subtree_with_sum, + } => self.grove.delete_operation_for_delete_internal( + (path.as_slice()).into(), + key.as_slice(), + &options, + is_known_to_be_subtree_with_sum, + ¤t_batch_operations.operations, + transaction, + &drive_version.grove_version, + ), + }; + + if let Some(delete_operation) = + push_drive_operation_result(delete_operation, drive_operations)? + { + // Add the delete operation to the batch of drive operations + drive_operations.push(GroveOperation(delete_operation)); + // Adds the insert operation to the batch of drive operations + drive_operations.push(GroveOperation(QualifiedGroveDbOp::insert_or_replace_op( + new_path.clone(), + key, + element, + ))); + } + } + + Ok(()) + } +} +#[cfg(test)] +mod tests { + use crate::util::grove_operations::QueryType; + use crate::{ + error::Error, util::grove_operations::BatchMoveApplyType, + util::test_helpers::setup::setup_drive, + }; + use assert_matches::assert_matches; + use grovedb::{Element, PathQuery, Query, SizedQuery}; + use grovedb_path::SubtreePath; + use platform_version::version::PlatformVersion; + + #[test] + fn test_batch_move_items_in_path_query_success() { + // Set up a test drive instance and transaction + let drive = setup_drive(None); + let platform_version = PlatformVersion::latest(); + let transaction = drive.grove.start_transaction(); + + // Insert elements that will be moved + let path = vec![b"root".to_vec()]; + let new_path = vec![b"new_root".to_vec()]; + let key1 = b"key1".to_vec(); + let key2 = b"key2".to_vec(); + let element1 = Element::new_item(b"value1".to_vec()); + let element2 = Element::new_item(b"value2".to_vec()); + + // Insert the root tree and new root tree + drive + .grove_insert_empty_tree( + SubtreePath::empty(), + b"root", + Some(&transaction), + None, + &mut vec![], + &platform_version.drive, + ) + .expect("expected to insert root tree"); + + drive + .grove_insert_empty_tree( + SubtreePath::empty(), + b"new_root", + Some(&transaction), + None, + &mut vec![], + &platform_version.drive, + ) + .expect("expected to insert new root tree"); + + drive + .grove + .insert( + path.as_slice(), + &key1, + element1.clone(), + None, + Some(&transaction), + &platform_version.drive.grove_version, + ) + .unwrap() + .expect("expected to insert element1"); + + drive + .grove + .insert( + path.as_slice(), + &key2, + element2.clone(), + None, + Some(&transaction), + &platform_version.drive.grove_version, + ) + .unwrap() + .expect("expected to insert element2"); + + // Create a path query that matches the inserted elements + let mut query = Query::new(); + query.insert_key(key1.clone()); + query.insert_key(key2.clone()); + let path_query = PathQuery::new(path.clone(), SizedQuery::new(query, Some(100), None)); + + // Set up the apply type and drive operations vector + let apply_type = BatchMoveApplyType::StatefulBatchMove { + is_known_to_be_subtree_with_sum: Some((false, false)), + }; + let mut drive_operations = Vec::new(); + + // Call the function + drive + .batch_move_items_in_path_query_v0( + &path_query, + new_path.clone(), + true, + apply_type, + Some(&transaction), + &mut drive_operations, + &platform_version.drive, + ) + .expect("expected to move items"); + + // Apply batch operations + drive + .apply_batch_low_level_drive_operations( + None, + Some(&transaction), + drive_operations, + &mut vec![], + &platform_version.drive, + ) + .expect("expected to apply operations"); + + // Commit the transaction + drive + .grove + .commit_transaction(transaction) + .unwrap() + .expect("expected to commit transaction"); + + // Verify that keys have been moved to the new path + let get_result_1 = drive.grove_get( + new_path.as_slice().into(), + &key1, + QueryType::StatefulQuery, + None, + &mut vec![], + &platform_version.drive, + ); + assert_matches!(get_result_1, Ok(Some(Element::Item(value, _))) if value == b"value1".to_vec()); + + let get_result_2 = drive.grove_get( + new_path.as_slice().into(), + &key2, + QueryType::StatefulQuery, + None, + &mut vec![], + &platform_version.drive, + ); + assert_matches!(get_result_2, Ok(Some(Element::Item(value, _))) if value == b"value2".to_vec()); + + // Verify that keys are no longer in the original path + let get_result_1_old = drive.grove_get( + path.as_slice().into(), + &key1, + QueryType::StatefulQuery, + None, + &mut vec![], + &platform_version.drive, + ); + assert_matches!( + get_result_1_old, + Err(Error::GroveDB(grovedb::Error::PathKeyNotFound(_))) + ); + + let get_result_2_old = drive.grove_get( + path.as_slice().into(), + &key2, + QueryType::StatefulQuery, + None, + &mut vec![], + &platform_version.drive, + ); + assert_matches!( + get_result_2_old, + Err(Error::GroveDB(grovedb::Error::PathKeyNotFound(_))) + ); + } + + #[test] + fn test_batch_move_items_in_path_query_no_elements() { + // Set up a test drive instance and transaction + let drive = setup_drive(None); + let platform_version = PlatformVersion::latest(); + let transaction = drive.grove.start_transaction(); + + // Create the root tree to allow querying it + drive + .grove_insert_empty_tree( + SubtreePath::empty(), + b"root", + Some(&transaction), + None, + &mut vec![], + &platform_version.drive, + ) + .expect("expected to insert root tree"); + + // Create a path query that does not match any elements + let path = vec![b"root".to_vec()]; + let new_path = vec![b"new_root".to_vec()]; + let mut query = Query::new(); + query.insert_key(b"non_existent_key".to_vec()); + let path_query = PathQuery::new(path.clone(), SizedQuery::new(query, Some(1), None)); + + // Set up the apply type and drive operations vector + let apply_type = BatchMoveApplyType::StatefulBatchMove { + is_known_to_be_subtree_with_sum: Some((false, false)), + }; + let mut drive_operations = Vec::new(); + + // Call the function + let result = drive.batch_move_items_in_path_query_v0( + &path_query, + new_path.clone(), + true, + apply_type, + Some(&transaction), + &mut drive_operations, + &platform_version.drive, + ); + + assert!(result.is_ok()); + } + + #[test] + fn test_batch_move_items_in_path_query_range_query() { + // Set up a test drive instance and transaction + let drive = setup_drive(None); + let platform_version = PlatformVersion::latest(); + let transaction = drive.grove.start_transaction(); + + // Insert the root tree + drive + .grove_insert_empty_tree( + SubtreePath::empty(), + b"root", + Some(&transaction), + None, + &mut vec![], + &platform_version.drive, + ) + .expect("expected to insert root tree"); + + // Insert three elements with keys 1, 2, and 3 + let path = vec![b"root".to_vec()]; + let new_path = vec![b"new_root".to_vec()]; + let key1 = b"1".to_vec(); + let key2 = b"2".to_vec(); + let key3 = b"3".to_vec(); + let element = Element::new_item(b"value".to_vec()); + + // Insert the new root tree + drive + .grove_insert_empty_tree( + SubtreePath::empty(), + b"new_root", + Some(&transaction), + None, + &mut vec![], + &platform_version.drive, + ) + .expect("expected to insert new root tree"); + + drive + .grove + .insert( + path.as_slice(), + &key1, + element.clone(), + None, + Some(&transaction), + &platform_version.drive.grove_version, + ) + .unwrap() + .expect("expected insert for key 1"); + + drive + .grove + .insert( + path.as_slice(), + &key2, + element.clone(), + None, + Some(&transaction), + &platform_version.drive.grove_version, + ) + .unwrap() + .expect("expected insert for key 2"); + + drive + .grove + .insert( + path.as_slice(), + &key3, + element.clone(), + None, + Some(&transaction), + &platform_version.drive.grove_version, + ) + .unwrap() + .expect("expected insert for key 3"); + + // Create a range path query that matches keys less than 3 + let mut query = Query::new(); + query.insert_range_to(..b"3".to_vec()); + let path_query = PathQuery::new(path.clone(), SizedQuery::new(query, Some(100), None)); + + // Set up the apply type and drive operations vector + let apply_type = BatchMoveApplyType::StatefulBatchMove { + is_known_to_be_subtree_with_sum: Some((false, false)), + }; + let mut drive_operations = Vec::new(); + + // Call the function + drive + .batch_move_items_in_path_query_v0( + &path_query, + new_path.clone(), + true, + apply_type, + Some(&transaction), + &mut drive_operations, + &platform_version.drive, + ) + .expect("expected to batch move items"); + + // Apply batch operations + drive + .apply_batch_low_level_drive_operations( + None, + Some(&transaction), + drive_operations, + &mut vec![], + &platform_version.drive, + ) + .expect("expected to apply operations"); + + // Commit the transaction + drive + .grove + .commit_transaction(transaction) + .unwrap() + .expect("expected to commit transaction"); + + // Verify that keys 1 and 2 have been moved to the new path + let get_result_1 = drive.grove_get( + new_path.as_slice().into(), + &key1, + QueryType::StatefulQuery, + None, + &mut vec![], + &platform_version.drive, + ); + assert_matches!(get_result_1, Ok(Some(Element::Item(value, _))) if value == b"value".to_vec()); + + let get_result_2 = drive.grove_get( + new_path.as_slice().into(), + &key2, + QueryType::StatefulQuery, + None, + &mut vec![], + &platform_version.drive, + ); + assert_matches!(get_result_2, Ok(Some(Element::Item(value, _))) if value == b"value".to_vec()); + + // Verify that keys 1 and 2 are no longer in the original path + let get_result_1_old = drive.grove_get( + path.as_slice().into(), + &key1, + QueryType::StatefulQuery, + None, + &mut vec![], + &platform_version.drive, + ); + assert_matches!( + get_result_1_old, + Err(Error::GroveDB(grovedb::Error::PathKeyNotFound(_))) + ); + + let get_result_2_old = drive.grove_get( + path.as_slice().into(), + &key2, + QueryType::StatefulQuery, + None, + &mut vec![], + &platform_version.drive, + ); + assert_matches!( + get_result_2_old, + Err(Error::GroveDB(grovedb::Error::PathKeyNotFound(_))) + ); + + // Verify that key 3 is still in the original path + let get_result_3 = drive.grove_get( + path.as_slice().into(), + &key3, + QueryType::StatefulQuery, + None, + &mut vec![], + &platform_version.drive, + ); + assert_matches!(get_result_3, Ok(Some(Element::Item(..)))); + } +} diff --git a/packages/rs-drive/src/util/grove_operations/grove_get_sum_tree_total_value/v0/mod.rs b/packages/rs-drive/src/util/grove_operations/grove_get_sum_tree_total_value/v0/mod.rs index a2a27c7c64..65bd03f3e3 100644 --- a/packages/rs-drive/src/util/grove_operations/grove_get_sum_tree_total_value/v0/mod.rs +++ b/packages/rs-drive/src/util/grove_operations/grove_get_sum_tree_total_value/v0/mod.rs @@ -14,7 +14,7 @@ use platform_version::version::drive_versions::DriveVersion; impl Drive { /// Gets the element at the given path from groveDB. /// Pushes the `OperationCost` of getting the element to `drive_operations`. - pub(crate) fn grove_get_sum_tree_total_value_v0>( + pub(super) fn grove_get_sum_tree_total_value_v0>( &self, path: SubtreePath<'_, B>, key: &[u8], diff --git a/packages/rs-drive/src/util/grove_operations/grove_insert_if_not_exists_return_existing_element/mod.rs b/packages/rs-drive/src/util/grove_operations/grove_insert_if_not_exists_return_existing_element/mod.rs new file mode 100644 index 0000000000..6727b72014 --- /dev/null +++ b/packages/rs-drive/src/util/grove_operations/grove_insert_if_not_exists_return_existing_element/mod.rs @@ -0,0 +1,53 @@ +mod v0; + +use crate::drive::Drive; +use crate::error::drive::DriveError; +use crate::error::Error; +use crate::fees::op::LowLevelDriveOperation; +use dpp::version::drive_versions::DriveVersion; +use grovedb::{Element, TransactionArg}; +use grovedb_path::SubtreePath; + +impl Drive { + /// Inserts an element into groveDB only if the specified path and key do not exist. + /// This operation costs are then stored in `drive_operations`. + /// + /// # Parameters + /// * `path`: The groveDB hierarchical authenticated structure path where the new element is to be inserted. + /// * `key`: The key where the new element should be inserted in the subtree. + /// * `element`: The element to be inserted. + /// * `transaction`: The groveDB transaction associated with this operation. + /// * `drive_operations`: A vector to collect the costs of operations for later computation. In this case, + /// it collects the cost of this insert operation if the path and key did not exist. + /// * `platform_version`: The platform version to select the correct function version to run. + /// + /// # Returns + /// * `Ok(true)` if the insertion was successful. + /// * `Ok(false)` if the path and key already existed. + /// * `Err(DriveError::UnknownVersionMismatch)` if the platform version does not match known versions. + pub fn grove_insert_if_not_exists_return_existing_element>( + &self, + path: SubtreePath<'_, B>, + key: &[u8], + element: Element, + transaction: TransactionArg, + drive_operations: Option<&mut Vec>, + drive_version: &DriveVersion, + ) -> Result, Error> { + match drive_version.grove_methods.basic.grove_insert_if_not_exists { + 0 => self.grove_insert_if_not_exists_return_existing_element_v0( + path, + key, + element, + transaction, + drive_operations, + drive_version, + ), + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "grove_insert_if_not_exists_return_existing_element".to_string(), + known_versions: vec![0], + received: version, + })), + } + } +} diff --git a/packages/rs-drive/src/util/grove_operations/grove_insert_if_not_exists_return_existing_element/v0/mod.rs b/packages/rs-drive/src/util/grove_operations/grove_insert_if_not_exists_return_existing_element/v0/mod.rs new file mode 100644 index 0000000000..69b55ba2d7 --- /dev/null +++ b/packages/rs-drive/src/util/grove_operations/grove_insert_if_not_exists_return_existing_element/v0/mod.rs @@ -0,0 +1,30 @@ +use crate::drive::Drive; +use crate::error::Error; +use crate::fees::op::LowLevelDriveOperation; +use crate::util::grove_operations::push_drive_operation_result_optional; +use grovedb::{Element, TransactionArg}; +use grovedb_path::SubtreePath; +use platform_version::version::drive_versions::DriveVersion; + +impl Drive { + /// Pushes the `OperationCost` of inserting an element in groveDB where the path key does not yet exist + /// to `drive_operations`. + pub(crate) fn grove_insert_if_not_exists_return_existing_element_v0>( + &self, + path: SubtreePath<'_, B>, + key: &[u8], + element: Element, + transaction: TransactionArg, + drive_operations: Option<&mut Vec>, + drive_version: &DriveVersion, + ) -> Result, Error> { + let cost_context = self.grove.insert_if_not_exists_return_existing_element( + path, + key, + element, + transaction, + &drive_version.grove_version, + ); + push_drive_operation_result_optional(cost_context, drive_operations) + } +} diff --git a/packages/rs-drive/src/util/grove_operations/mod.rs b/packages/rs-drive/src/util/grove_operations/mod.rs index a328aa8efb..41736ed442 100644 --- a/packages/rs-drive/src/util/grove_operations/mod.rs +++ b/packages/rs-drive/src/util/grove_operations/mod.rs @@ -108,10 +108,27 @@ pub mod grove_batch_operations_costs; /// Clear a subtree in grovedb pub mod grove_clear; +/// Provides functionality to delete items in a path based on a query. +pub mod batch_delete_items_in_path_query; + +/// Inserts an element if it does not exist and returns the existing element if it does. +pub mod batch_insert_if_not_exists_return_existing_element; + +/// Inserts a sum item or adds to it if it already exists. +pub mod batch_insert_sum_item_or_add_to_if_already_exists; + +/// Retrieves serialized or sum results from a path query in GroveDB. mod grove_get_path_query_serialized_or_sum_results; -/// Proved path query in grovedb with a conditional query + +/// Executes a proved path query in GroveDB with an optional conditional query. pub mod grove_get_proved_path_query_with_conditional; +/// Inserts an element if it does not exist and returns the existing element if it does in GroveDB. +pub mod grove_insert_if_not_exists_return_existing_element; + +/// Moved items that are found in a path query to a new path. +pub mod batch_move_items_in_path_query; + use grovedb_costs::CostContext; use grovedb::EstimatedLayerInformation; @@ -163,7 +180,7 @@ pub enum BatchDeleteApplyType { StatelessBatchDelete { /// Are we deleting in a sum tree is_sum_tree: bool, - /// What is the estimated value size + /// What is the estimated key size estimated_key_size: u32, /// What is the estimated value size estimated_value_size: u32, @@ -175,6 +192,29 @@ pub enum BatchDeleteApplyType { }, } +/// Batch move apply type +#[derive(Debug, Copy, Clone)] +pub enum BatchMoveApplyType { + /// Stateless batch move + StatelessBatchMove { + /// Are we moving from inside a sum tree + in_tree_using_sums: bool, + /// Are we moving a sum tree + is_sum_tree: bool, + /// What is the estimated key size + estimated_key_size: u32, + /// What is the estimated value size + estimated_value_size: u32, + /// The flags length + flags_len: FlagsLen, + }, + /// Stateful batch move + StatefulBatchMove { + /// Are we known to be in a subtree and does this subtree have sums + is_known_to_be_subtree_with_sum: Option<(IsSubTree, IsSumSubTree)>, + }, +} + #[derive(Clone)] /// Batch delete up tree apply type pub enum BatchDeleteUpTreeApplyType { diff --git a/packages/rs-drive/src/util/test_helpers/setup.rs b/packages/rs-drive/src/util/test_helpers/setup.rs index a9e4cb6aad..d80f600def 100644 --- a/packages/rs-drive/src/util/test_helpers/setup.rs +++ b/packages/rs-drive/src/util/test_helpers/setup.rs @@ -46,13 +46,15 @@ pub fn setup_drive(drive_config: Option) -> Drive { #[cfg(feature = "full")] /// Sets up Drive using a temporary directory and the default initial state structure. -pub fn setup_drive_with_initial_state_structure() -> Drive { +pub fn setup_drive_with_initial_state_structure( + specific_platform_version: Option<&PlatformVersion>, +) -> Drive { let drive = setup_drive(Some(DriveConfig { batching_consistency_verification: true, ..Default::default() })); - let platform_version = PlatformVersion::latest(); + let platform_version = specific_platform_version.unwrap_or(PlatformVersion::latest()); drive .create_initial_state_structure(None, platform_version) .expect("should create root tree successfully"); diff --git a/packages/rs-drive/src/verify/document/verify_proof_keep_serialized/v0/mod.rs b/packages/rs-drive/src/verify/document/verify_proof_keep_serialized/v0/mod.rs index dc362c7ead..51c1bad4c4 100644 --- a/packages/rs-drive/src/verify/document/verify_proof_keep_serialized/v0/mod.rs +++ b/packages/rs-drive/src/verify/document/verify_proof_keep_serialized/v0/mod.rs @@ -39,6 +39,7 @@ impl<'a> DriveDocumentQuery<'a> { } else { self.construct_path_query(None, platform_version) }?; + let (root_hash, proved_key_values) = if self.start_at.is_some() { GroveDb::verify_subset_query(proof, &path_query, &platform_version.drive.grove_version)? } else { diff --git a/packages/rs-drive/tests/dashpay.rs b/packages/rs-drive/tests/dashpay.rs index f00008712c..1dbc23e8aa 100644 --- a/packages/rs-drive/tests/dashpay.rs +++ b/packages/rs-drive/tests/dashpay.rs @@ -11,7 +11,7 @@ mod contact_request { #[test] fn test_user_id_query() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); @@ -47,7 +47,7 @@ mod contact_request { #[test] fn test_user_id_by_created_at_query() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); @@ -83,7 +83,7 @@ mod contact_request { #[test] fn test_owner_id_query() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); @@ -119,7 +119,7 @@ mod contact_request { #[test] fn test_owner_id_by_created_at_query() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); @@ -155,7 +155,7 @@ mod contact_request { #[test] fn test_owner_id_and_to_user_id_query() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); diff --git a/packages/rs-drive/tests/masternode_rewards.rs b/packages/rs-drive/tests/masternode_rewards.rs index 56464bbae5..0c7fc4bbc8 100644 --- a/packages/rs-drive/tests/masternode_rewards.rs +++ b/packages/rs-drive/tests/masternode_rewards.rs @@ -11,7 +11,7 @@ mod reward_share { #[test] fn test_owner_id_query() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); @@ -47,7 +47,7 @@ mod reward_share { #[test] fn test_owner_id_and_pay_to_id_query() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); diff --git a/packages/rs-drive/tests/query_tests.rs b/packages/rs-drive/tests/query_tests.rs index 0850fc8d62..23d8491885 100644 --- a/packages/rs-drive/tests/query_tests.rs +++ b/packages/rs-drive/tests/query_tests.rs @@ -75,6 +75,7 @@ use dpp::tests::json_document::json_document_to_contract; use dpp::util::cbor_serializer; use once_cell::sync::Lazy; +use dpp::version::fee::FeeVersion; use dpp::version::PlatformVersion; #[cfg(feature = "server")] @@ -2305,7 +2306,7 @@ fn test_family_person_update() { let platform_version = PlatformVersion::latest(); let epoch_change_fee_version_test: Lazy = - Lazy::new(|| BTreeMap::from([(0, PlatformVersion::first().fee_version.clone())])); + Lazy::new(|| BTreeMap::from([(0, FeeVersion::first())])); let db_transaction = drive.grove.start_transaction(); @@ -2883,7 +2884,7 @@ fn test_family_with_nulls_query() { let platform_version = PlatformVersion::latest(); let epoch_change_fee_version_test: Lazy = - Lazy::new(|| BTreeMap::from([(0, PlatformVersion::first().fee_version.clone())])); + Lazy::new(|| BTreeMap::from([(0, FeeVersion::first())])); let db_transaction = drive.grove.start_transaction(); @@ -4341,6 +4342,8 @@ fn test_dpns_query_start_after_with_null_id() { let domain1_id = Identifier::random_with_rng(&mut rng); + assert!(domain0_id > domain1_id); + let domain1 = Domain { id: domain1_id, owner_id: Identifier::random_with_rng(&mut rng), @@ -4427,7 +4430,7 @@ fn test_dpns_query_start_after_with_null_id() { ["normalizedParentDomainName", "==", "dash"] ], "startAfter": encoded_start_at, - "limit": 2, + "limit": 3, "orderBy": [ ["normalizedLabel", "asc"] ] @@ -4804,7 +4807,7 @@ fn test_dpns_query_start_after_with_null_id_desc() { #[cfg(feature = "server")] #[test] fn test_query_a_b_c_d_e_contract() { - let drive: Drive = setup_drive_with_initial_state_structure(); + let drive: Drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); @@ -4919,7 +4922,7 @@ fn test_query_a_b_c_d_e_contract() { #[cfg(feature = "server")] #[test] fn test_query_documents_by_created_at() { - let drive = setup_drive_with_initial_state_structure(); + let drive = setup_drive_with_initial_state_structure(None); let platform_version = PlatformVersion::latest(); diff --git a/packages/rs-drive/tests/query_tests_history.rs b/packages/rs-drive/tests/query_tests_history.rs index 2d609f0c2b..c14dfeca9e 100644 --- a/packages/rs-drive/tests/query_tests_history.rs +++ b/packages/rs-drive/tests/query_tests_history.rs @@ -53,6 +53,7 @@ use dpp::document::serialization_traits::{ use dpp::document::DocumentV0Getters; use dpp::fee::default_costs::CachedEpochIndexFeeVersions; use dpp::tests::json_document::json_document_to_contract; +use dpp::version::fee::FeeVersion; use dpp::version::PlatformVersion; use drive::util::batch::grovedb_op_batch::GroveDbOpBatchV0Methods; #[cfg(feature = "server")] @@ -166,7 +167,7 @@ pub fn setup( let platform_version = PlatformVersion::latest(); let epoch_change_fee_version_test: Lazy = - Lazy::new(|| BTreeMap::from([(0, PlatformVersion::first().fee_version.clone())])); + Lazy::new(|| BTreeMap::from([(0, FeeVersion::first())])); let drive = setup_drive(Some(drive_config)); @@ -260,7 +261,7 @@ fn test_query_historical() { let platform_version = PlatformVersion::latest(); let epoch_change_fee_version_test: Lazy = - Lazy::new(|| BTreeMap::from([(0, PlatformVersion::first().fee_version.clone())])); + Lazy::new(|| BTreeMap::from([(0, FeeVersion::first())])); let db_transaction = drive.grove.start_transaction(); diff --git a/packages/rs-json-schema-compatibility-validator/Cargo.toml b/packages/rs-json-schema-compatibility-validator/Cargo.toml index 8673490a0b..6e1d43be34 100644 --- a/packages/rs-json-schema-compatibility-validator/Cargo.toml +++ b/packages/rs-json-schema-compatibility-validator/Cargo.toml @@ -1,14 +1,14 @@ [package] name = "json-schema-compatibility-validator" -version = "1.3.1" +version = "1.5.0" edition = "2021" rust-version.workspace = true authors = ["Ivan Shumkov "] [dependencies] -json-patch = "1.2.0" +json-patch = "1.4" serde_json = "1.0.115" -thiserror = "1.0.58" +thiserror = "1.0.64" once_cell = "1.19.0" [dev-dependencies] diff --git a/packages/rs-platform-serialization-derive/Cargo.toml b/packages/rs-platform-serialization-derive/Cargo.toml index 08ea5b240e..27d6cba787 100644 --- a/packages/rs-platform-serialization-derive/Cargo.toml +++ b/packages/rs-platform-serialization-derive/Cargo.toml @@ -2,7 +2,7 @@ name = "platform-serialization-derive" authors = ["Samuel Westrich "] description = "Bincode serialization and deserialization derivations" -version = "1.3.1" +version = "1.5.0" edition = "2021" rust-version.workspace = true license = "MIT" @@ -12,6 +12,6 @@ proc-macro = true [dependencies] proc-macro2 = "1.0.56" -virtue = "0.0.14" -quote = "1.0.26" -syn = "2.0.15" +virtue = "0.0.17" +quote = "1.0.37" +syn = "2.0.75" diff --git a/packages/rs-platform-serialization-derive/src/attribute.rs b/packages/rs-platform-serialization-derive/src/attribute.rs index d908a7c165..3b873607cd 100644 --- a/packages/rs-platform-serialization-derive/src/attribute.rs +++ b/packages/rs-platform-serialization-derive/src/attribute.rs @@ -5,7 +5,6 @@ use virtue::utils::{parse_tagged_attribute, ParsedAttribute}; pub struct ContainerAttributes { pub crate_name: String, pub untagged: bool, - pub unversioned: bool, pub bounds: Option<(String, Literal)>, pub decode_bounds: Option<(String, Literal)>, pub borrow_decode_bounds: Option<(String, Literal)>, @@ -16,7 +15,6 @@ impl Default for ContainerAttributes { fn default() -> Self { Self { crate_name: "::platform_serialization".to_string(), - unversioned: false, untagged: false, bounds: None, decode_bounds: None, @@ -111,7 +109,6 @@ impl FromAttribute for ContainerAttributes { pub struct FieldAttributes { pub with_serde: bool, pub with_platform_version: bool, - pub platform_version_path_bounds: String, } impl FromAttribute for FieldAttributes { diff --git a/packages/rs-platform-serialization/Cargo.toml b/packages/rs-platform-serialization/Cargo.toml index 75bf479610..fc4679a3fb 100644 --- a/packages/rs-platform-serialization/Cargo.toml +++ b/packages/rs-platform-serialization/Cargo.toml @@ -2,7 +2,7 @@ name = "platform-serialization" authors = ["Samuel Westrich "] description = "Bincode based serialization and deserialization" -version = "1.3.1" +version = "1.5.0" edition = "2021" rust-version.workspace = true license = "MIT" diff --git a/packages/rs-platform-value-convertible/Cargo.toml b/packages/rs-platform-value-convertible/Cargo.toml index 7c7c15b537..b3145a3a40 100644 --- a/packages/rs-platform-value-convertible/Cargo.toml +++ b/packages/rs-platform-value-convertible/Cargo.toml @@ -2,7 +2,7 @@ name = "platform-value-convertible" authors = ["Samuel Westrich "] description = "Convertion to and from platform values" -version = "1.3.1" +version = "1.5.0" edition = "2021" rust-version.workspace = true license = "MIT" @@ -11,5 +11,5 @@ license = "MIT" proc-macro = true [dependencies] -quote = "1.0.26" -syn = "2.0.15" +quote = "1.0.37" +syn = "2.0.75" diff --git a/packages/rs-platform-value/Cargo.toml b/packages/rs-platform-value/Cargo.toml index 1150c31be2..d31603fbc7 100644 --- a/packages/rs-platform-value/Cargo.toml +++ b/packages/rs-platform-value/Cargo.toml @@ -2,7 +2,7 @@ name = "platform-value" authors = ["Samuel Westrich "] description = "A simple value module" -version = "1.3.1" +version = "1.5.0" edition = "2021" rust-version.workspace = true license = "MIT" @@ -10,7 +10,7 @@ license = "MIT" [dependencies] bincode = { version = "2.0.0-rc.3", features = ["serde"] } ciborium = { git = "https://github.com/qrayven/ciborium", branch = "feat-ser-null-as-undefined", optional = true } -thiserror = "1.0.58" +thiserror = "1.0.64" bs58 = "0.5.1" base64 = "0.22.1" hex = "0.4.3" diff --git a/packages/rs-platform-value/src/string_encoding.rs b/packages/rs-platform-value/src/string_encoding.rs index c31d172839..bce2c69fbb 100644 --- a/packages/rs-platform-value/src/string_encoding.rs +++ b/packages/rs-platform-value/src/string_encoding.rs @@ -3,13 +3,27 @@ use base64; use base64::prelude::BASE64_STANDARD; use base64::Engine; use bs58; +use std::fmt; +#[derive(Debug, Copy, Clone)] pub enum Encoding { Base58, Base64, Hex, } +pub const ALL_ENCODINGS: [Encoding; 3] = [Encoding::Hex, Encoding::Base58, Encoding::Base64]; + +impl fmt::Display for Encoding { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Encoding::Base58 => write!(f, "Base58"), + Encoding::Base64 => write!(f, "Base64"), + Encoding::Hex => write!(f, "Hex"), + } + } +} + pub fn decode(encoded_value: &str, encoding: Encoding) -> Result, Error> { match encoding { Encoding::Base58 => Ok(bs58::decode(encoded_value) diff --git a/packages/rs-platform-value/src/types/identifier.rs b/packages/rs-platform-value/src/types/identifier.rs index 07bdcbd425..f2f173b7d7 100644 --- a/packages/rs-platform-value/src/types/identifier.rs +++ b/packages/rs-platform-value/src/types/identifier.rs @@ -11,7 +11,7 @@ use serde::{Deserialize, Serialize}; #[cfg(feature = "json")] use serde_json::Value as JsonValue; -use crate::string_encoding::Encoding; +use crate::string_encoding::{Encoding, ALL_ENCODINGS}; use crate::types::encoding_string_to_encoding; use crate::{string_encoding, Error, Value}; @@ -170,6 +170,29 @@ impl Identifier { Identifier::from_bytes(&vec) } + pub fn from_string_try_encodings( + encoded_value: &str, + encodings: &[Encoding], + ) -> Result { + let mut tried = vec![]; + for encoding in encodings { + if let Ok(vec) = string_encoding::decode(encoded_value, *encoding) { + if vec.len() == 32 { + return Identifier::from_bytes(&vec); + } + } + tried.push(encoding.to_string()); + } + Err(Error::StringDecodingError(format!( + "Failed to decode string with encodings [{}]", + tried.join(", ") + ))) + } + + pub fn from_string_unknown_encoding(encoded_value: &str) -> Result { + Identifier::from_string_try_encodings(encoded_value, &ALL_ENCODINGS) + } + pub fn from_string_with_encoding_string( encoded_value: &str, encoding_string: Option<&str>, diff --git a/packages/rs-platform-version/Cargo.toml b/packages/rs-platform-version/Cargo.toml index 0731482b02..fecc94f775 100644 --- a/packages/rs-platform-version/Cargo.toml +++ b/packages/rs-platform-version/Cargo.toml @@ -2,16 +2,16 @@ name = "platform-version" authors = ["Samuel Westrich "] description = "Versioning library for Platform" -version = "1.3.1" +version = "1.5.0" edition = "2021" rust-version.workspace = true license = "MIT" [dependencies] thiserror = { version = "1.0.63" } -bincode = { version = "2.0.0-rc.3"} +bincode = { version = "2.0.0-rc.3" } versioned-feature-core = { git = "https://github.com/dashpay/versioned-feature-core", version = "1.0.0" } -grovedb-version = { version = "2.0.3"} +grovedb-version = { version = "2.1.0" } once_cell = "1.19.0" [features] diff --git a/packages/rs-platform-version/src/version/dpp_versions.rs b/packages/rs-platform-version/src/version/dpp_versions.rs deleted file mode 100644 index e168d8aa95..0000000000 --- a/packages/rs-platform-version/src/version/dpp_versions.rs +++ /dev/null @@ -1,273 +0,0 @@ -use crate::version::{FeatureVersion, FeatureVersionBounds}; - -#[derive(Clone, Debug, Default)] -pub struct DPPVersion { - pub costs: CostVersions, - pub validation: DPPValidationVersions, - // TODO: Should be split by state transition type - pub state_transition_serialization_versions: StateTransitionSerializationVersions, - pub state_transition_conversion_versions: StateTransitionConversionVersions, - pub state_transition_method_versions: StateTransitionMethodVersions, - pub state_transitions: StateTransitionVersions, - pub contract_versions: ContractVersions, - pub document_versions: DocumentVersions, - pub identity_versions: IdentityVersions, - pub voting_versions: VotingVersions, - pub asset_lock_versions: AssetLockVersions, - pub methods: DPPMethodVersions, -} - -#[derive(Clone, Debug, Default)] -pub struct StateTransitionVersions { - pub documents: DocumentTransitionVersions, - pub identities: IdentityTransitionVersions, -} - -#[derive(Clone, Debug, Default)] -pub struct IdentityTransitionVersions { - pub max_public_keys_in_creation: u16, - pub asset_locks: IdentityTransitionAssetLockVersions, -} - -#[derive(Clone, Debug, Default)] -pub struct IdentityTransitionAssetLockVersions { - pub required_asset_lock_duff_balance_for_processing_start_for_identity_create: u64, - pub required_asset_lock_duff_balance_for_processing_start_for_identity_top_up: u64, - pub validate_asset_lock_transaction_structure: FeatureVersion, - pub validate_instant_asset_lock_proof_structure: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DocumentTransitionVersions { - pub documents_batch_transition: DocumentsBatchTransitionVersions, -} - -#[derive(Clone, Debug, Default)] -pub struct DocumentsBatchTransitionVersions { - pub validation: DocumentsBatchTransitionValidationVersions, -} - -#[derive(Clone, Debug, Default)] -pub struct DocumentsBatchTransitionValidationVersions { - pub find_duplicates_by_id: FeatureVersion, - pub validate_base_structure: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct CostVersions { - pub signature_verify: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DPPValidationVersions { - pub json_schema_validator: JsonSchemaValidatorVersions, - pub data_contract: DataContractValidationVersions, - pub document_type: DocumentTypeValidationVersions, - pub voting: VotingValidationVersions, -} - -#[derive(Clone, Debug, Default)] -pub struct DataContractValidationVersions { - pub validate: FeatureVersion, - pub validate_config_update: FeatureVersion, - pub validate_index_definitions: FeatureVersion, - pub validate_index_naming_duplicates: FeatureVersion, - pub validate_not_defined_properties: FeatureVersion, - pub validate_property_definition: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct VotingValidationVersions { - /// How long do we allow other contenders to join a contest after the first contender - pub allow_other_contenders_time_mainnet_ms: u64, - /// How long do we allow other contenders to join a contest after the first contender in a testing environment - pub allow_other_contenders_time_testing_ms: u64, - /// How many votes do we allow from the same masternode? - pub votes_allowed_per_masternode: u16, -} - -#[derive(Clone, Debug, Default)] -pub struct DocumentTypeValidationVersions { - pub validate_update: FeatureVersion, - pub unique_index_limit: u16, - pub contested_index_limit: u16, -} - -#[derive(Clone, Debug, Default)] -pub struct JsonSchemaValidatorVersions { - pub new: FeatureVersion, - pub validate: FeatureVersion, - pub compile: FeatureVersion, - pub compile_and_validate: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct StateTransitionMethodVersions { - pub public_key_in_creation_methods: PublicKeyInCreationMethodVersions, -} - -#[derive(Clone, Debug, Default)] -pub struct PublicKeyInCreationMethodVersions { - pub from_public_key_signed_with_private_key: FeatureVersion, - pub from_public_key_signed_external: FeatureVersion, - pub hash: FeatureVersion, - pub duplicated_key_ids_witness: FeatureVersion, - pub duplicated_keys_witness: FeatureVersion, - pub validate_identity_public_keys_structure: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct StateTransitionConversionVersions { - pub identity_to_identity_create_transition: FeatureVersion, - pub identity_to_identity_top_up_transition: FeatureVersion, - pub identity_to_identity_withdrawal_transition: FeatureVersion, - pub identity_to_identity_create_transition_with_signer: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct StateTransitionSerializationVersions { - pub identity_public_key_in_creation: FeatureVersionBounds, - pub identity_create_state_transition: FeatureVersionBounds, - pub identity_update_state_transition: FeatureVersionBounds, - pub identity_top_up_state_transition: FeatureVersionBounds, - pub identity_credit_withdrawal_state_transition: FeatureVersionBounds, - pub identity_credit_transfer_state_transition: FeatureVersionBounds, - pub masternode_vote_state_transition: FeatureVersionBounds, - pub contract_create_state_transition: FeatureVersionBounds, - pub contract_update_state_transition: FeatureVersionBounds, - pub documents_batch_state_transition: FeatureVersionBounds, - pub document_base_state_transition: FeatureVersionBounds, - pub document_create_state_transition: DocumentFeatureVersionBounds, - pub document_replace_state_transition: DocumentFeatureVersionBounds, - pub document_delete_state_transition: DocumentFeatureVersionBounds, - pub document_transfer_state_transition: DocumentFeatureVersionBounds, - pub document_update_price_state_transition: DocumentFeatureVersionBounds, - pub document_purchase_state_transition: DocumentFeatureVersionBounds, -} - -#[derive(Clone, Debug, Default)] -pub struct DocumentFeatureVersionBounds { - pub bounds: FeatureVersionBounds, -} - -#[derive(Clone, Debug, Default)] -pub struct ContractVersions { - /// The maximum that we can store a data contract in the state. There is a possibility that a client - /// sends a state transition serialized in a specific version and that the system re-serializes it - /// to the current version, and in so doing increases it's size. - pub max_serialized_size: u32, - /// This is how we serialize and deserialize a contract - pub contract_serialization_version: FeatureVersionBounds, - /// This is the structure of the Contract as it is defined for code paths - pub contract_structure_version: FeatureVersion, - pub created_data_contract_structure: FeatureVersion, - pub config: FeatureVersion, - pub methods: DataContractMethodVersions, - pub document_type_versions: DocumentTypeVersions, -} - -#[derive(Clone, Debug, Default)] -pub struct DataContractMethodVersions { - pub validate_document: FeatureVersion, - pub validate_update: FeatureVersion, - pub schema: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DocumentTypeClassMethodVersions { - pub try_from_schema: FeatureVersion, - pub create_document_types_from_document_schemas: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DocumentTypeIndexVersions { - pub index_levels_from_indices: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DocumentTypeVersions { - pub index_versions: DocumentTypeIndexVersions, - pub class_method_versions: DocumentTypeClassMethodVersions, - /// This is for the overall structure of the document type, like DocumentTypeV0 - pub structure_version: FeatureVersion, - pub schema: DocumentTypeSchemaVersions, - pub methods: DocumentTypeMethodVersions, -} - -#[derive(Clone, Debug, Default)] -pub struct DocumentTypeMethodVersions { - pub create_document_from_data: FeatureVersion, - pub create_document_with_prevalidated_properties: FeatureVersion, - pub prefunded_voting_balance_for_document: FeatureVersion, - pub contested_vote_poll_for_document: FeatureVersion, - pub estimated_size: FeatureVersion, - pub index_for_types: FeatureVersion, - pub max_size: FeatureVersion, - pub serialize_value_for_key: FeatureVersion, - pub deserialize_value_for_key: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DocumentTypeSchemaVersions { - pub enrich_with_base_schema: FeatureVersion, - pub find_identifier_and_binary_paths: FeatureVersion, - pub validate_max_depth: FeatureVersion, - pub max_depth: u16, - pub recursive_schema_validator_versions: RecursiveSchemaValidatorVersions, - pub validate_schema_compatibility: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct RecursiveSchemaValidatorVersions { - pub traversal_validator: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct AssetLockVersions { - pub reduced_asset_lock_value: FeatureVersionBounds, -} - -#[derive(Clone, Debug, Default)] -pub struct IdentityVersions { - /// This is the structure of the Identity as it is defined for code paths - pub identity_structure_version: FeatureVersion, - pub identity_key_structure_version: FeatureVersion, - pub identity_key_type_method_versions: IdentityKeyTypeMethodVersions, -} - -#[derive(Clone, Debug, Default)] -pub struct VotingVersions { - pub default_vote_poll_time_duration_mainnet_ms: u64, - pub default_vote_poll_time_duration_test_network_ms: u64, - pub contested_document_vote_poll_stored_info_version: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct IdentityKeyTypeMethodVersions { - pub random_public_key_data: FeatureVersion, - pub random_public_and_private_key_data: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DocumentVersions { - // This is for the overall structure of the document, like DocumentV0 - pub document_structure_version: FeatureVersion, - pub document_serialization_version: FeatureVersionBounds, - pub document_cbor_serialization_version: FeatureVersionBounds, - pub extended_document_structure_version: FeatureVersion, - pub extended_document_serialization_version: FeatureVersionBounds, - pub document_method_versions: DocumentMethodVersions, -} - -#[derive(Clone, Debug, Default)] -pub struct DocumentMethodVersions { - pub is_equal_ignoring_timestamps: FeatureVersion, - pub hash: FeatureVersion, - pub get_raw_for_contract: FeatureVersion, - pub get_raw_for_document_type: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DPPMethodVersions { - pub epoch_core_reward_credits_for_distribution: FeatureVersion, -} diff --git a/packages/rs-platform-version/src/version/dpp_versions/dpp_asset_lock_versions/mod.rs b/packages/rs-platform-version/src/version/dpp_versions/dpp_asset_lock_versions/mod.rs new file mode 100644 index 0000000000..50f27a70ed --- /dev/null +++ b/packages/rs-platform-version/src/version/dpp_versions/dpp_asset_lock_versions/mod.rs @@ -0,0 +1,8 @@ +use versioned_feature_core::FeatureVersionBounds; + +pub mod v1; + +#[derive(Clone, Debug, Default)] +pub struct DPPAssetLockVersions { + pub reduced_asset_lock_value: FeatureVersionBounds, +} diff --git a/packages/rs-platform-version/src/version/dpp_versions/dpp_asset_lock_versions/v1.rs b/packages/rs-platform-version/src/version/dpp_versions/dpp_asset_lock_versions/v1.rs new file mode 100644 index 0000000000..0e494c8662 --- /dev/null +++ b/packages/rs-platform-version/src/version/dpp_versions/dpp_asset_lock_versions/v1.rs @@ -0,0 +1,10 @@ +use crate::version::dpp_versions::dpp_asset_lock_versions::DPPAssetLockVersions; +use versioned_feature_core::FeatureVersionBounds; + +pub const DPP_ASSET_LOCK_VERSIONS_V1: DPPAssetLockVersions = DPPAssetLockVersions { + reduced_asset_lock_value: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, +}; diff --git a/packages/rs-platform-version/src/version/dpp_versions/dpp_contract_versions/mod.rs b/packages/rs-platform-version/src/version/dpp_versions/dpp_contract_versions/mod.rs new file mode 100644 index 0000000000..91fd85cbae --- /dev/null +++ b/packages/rs-platform-version/src/version/dpp_versions/dpp_contract_versions/mod.rs @@ -0,0 +1,74 @@ +use versioned_feature_core::{FeatureVersion, FeatureVersionBounds}; +pub mod v1; + +#[derive(Clone, Debug, Default)] +pub struct DPPContractVersions { + /// The maximum that we can store a data contract in the state. There is a possibility that a client + /// sends a state transition serialized in a specific version and that the system re-serializes it + /// to the current version, and in so doing increases it's size. + pub max_serialized_size: u32, + /// This is how we serialize and deserialize a contract + pub contract_serialization_version: FeatureVersionBounds, + /// This is the structure of the Contract as it is defined for code paths + pub contract_structure_version: FeatureVersion, + pub created_data_contract_structure: FeatureVersion, + pub config: FeatureVersion, + pub methods: DataContractMethodVersions, + pub document_type_versions: DocumentTypeVersions, +} + +#[derive(Clone, Debug, Default)] +pub struct DataContractMethodVersions { + pub validate_document: FeatureVersion, + pub validate_update: FeatureVersion, + pub schema: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DocumentTypeClassMethodVersions { + pub try_from_schema: FeatureVersion, + pub create_document_types_from_document_schemas: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DocumentTypeIndexVersions { + pub index_levels_from_indices: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DocumentTypeVersions { + pub index_versions: DocumentTypeIndexVersions, + pub class_method_versions: DocumentTypeClassMethodVersions, + /// This is for the overall structure of the document type, like DocumentTypeV0 + pub structure_version: FeatureVersion, + pub schema: DocumentTypeSchemaVersions, + pub methods: DocumentTypeMethodVersions, +} + +#[derive(Clone, Debug, Default)] +pub struct DocumentTypeMethodVersions { + pub create_document_from_data: FeatureVersion, + pub create_document_with_prevalidated_properties: FeatureVersion, + pub prefunded_voting_balance_for_document: FeatureVersion, + pub contested_vote_poll_for_document: FeatureVersion, + pub estimated_size: FeatureVersion, + pub index_for_types: FeatureVersion, + pub max_size: FeatureVersion, + pub serialize_value_for_key: FeatureVersion, + pub deserialize_value_for_key: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DocumentTypeSchemaVersions { + pub enrich_with_base_schema: FeatureVersion, + pub find_identifier_and_binary_paths: FeatureVersion, + pub validate_max_depth: FeatureVersion, + pub max_depth: u16, + pub recursive_schema_validator_versions: RecursiveSchemaValidatorVersions, + pub validate_schema_compatibility: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct RecursiveSchemaValidatorVersions { + pub traversal_validator: FeatureVersion, +} diff --git a/packages/rs-platform-version/src/version/dpp_versions/dpp_contract_versions/v1.rs b/packages/rs-platform-version/src/version/dpp_versions/dpp_contract_versions/v1.rs new file mode 100644 index 0000000000..5483e66c95 --- /dev/null +++ b/packages/rs-platform-version/src/version/dpp_versions/dpp_contract_versions/v1.rs @@ -0,0 +1,54 @@ +use crate::version::dpp_versions::dpp_contract_versions::{ + DPPContractVersions, DataContractMethodVersions, DocumentTypeClassMethodVersions, + DocumentTypeIndexVersions, DocumentTypeMethodVersions, DocumentTypeSchemaVersions, + DocumentTypeVersions, RecursiveSchemaValidatorVersions, +}; +use versioned_feature_core::FeatureVersionBounds; + +pub const CONTRACT_VERSIONS_V1: DPPContractVersions = DPPContractVersions { + max_serialized_size: 65000, + contract_serialization_version: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + contract_structure_version: 0, + created_data_contract_structure: 0, + config: 0, + methods: DataContractMethodVersions { + validate_document: 0, + validate_update: 0, + schema: 0, + }, + document_type_versions: DocumentTypeVersions { + index_versions: DocumentTypeIndexVersions { + index_levels_from_indices: 0, + }, + class_method_versions: DocumentTypeClassMethodVersions { + try_from_schema: 0, + create_document_types_from_document_schemas: 0, + }, + structure_version: 0, + schema: DocumentTypeSchemaVersions { + enrich_with_base_schema: 0, + find_identifier_and_binary_paths: 0, + validate_max_depth: 0, + max_depth: 256, + recursive_schema_validator_versions: RecursiveSchemaValidatorVersions { + traversal_validator: 0, + }, + validate_schema_compatibility: 0, + }, + methods: DocumentTypeMethodVersions { + create_document_from_data: 0, + create_document_with_prevalidated_properties: 0, + prefunded_voting_balance_for_document: 0, + contested_vote_poll_for_document: 0, + estimated_size: 0, + index_for_types: 0, + max_size: 0, + serialize_value_for_key: 0, + deserialize_value_for_key: 0, + }, + }, +}; diff --git a/packages/rs-platform-version/src/version/dpp_versions/dpp_costs_versions/mod.rs b/packages/rs-platform-version/src/version/dpp_versions/dpp_costs_versions/mod.rs new file mode 100644 index 0000000000..672e076137 --- /dev/null +++ b/packages/rs-platform-version/src/version/dpp_versions/dpp_costs_versions/mod.rs @@ -0,0 +1,8 @@ +use versioned_feature_core::FeatureVersion; + +pub mod v1; + +#[derive(Clone, Debug, Default)] +pub struct DPPCostsVersions { + pub signature_verify: FeatureVersion, +} diff --git a/packages/rs-platform-version/src/version/dpp_versions/dpp_costs_versions/v1.rs b/packages/rs-platform-version/src/version/dpp_versions/dpp_costs_versions/v1.rs new file mode 100644 index 0000000000..0d8d5622ec --- /dev/null +++ b/packages/rs-platform-version/src/version/dpp_versions/dpp_costs_versions/v1.rs @@ -0,0 +1,5 @@ +use crate::version::dpp_versions::dpp_costs_versions::DPPCostsVersions; + +pub const DPP_COSTS_VERSIONS_V1: DPPCostsVersions = DPPCostsVersions { + signature_verify: 0, +}; diff --git a/packages/rs-platform-version/src/version/dpp_versions/dpp_document_versions/mod.rs b/packages/rs-platform-version/src/version/dpp_versions/dpp_document_versions/mod.rs new file mode 100644 index 0000000000..d5a81808e4 --- /dev/null +++ b/packages/rs-platform-version/src/version/dpp_versions/dpp_document_versions/mod.rs @@ -0,0 +1,23 @@ +use versioned_feature_core::{FeatureVersion, FeatureVersionBounds}; + +pub mod v1; + +#[derive(Clone, Debug, Default)] +pub struct DPPDocumentVersions { + // This is for the overall structure of the document, like DocumentV0 + pub document_structure_version: FeatureVersion, + pub document_serialization_version: FeatureVersionBounds, + pub document_cbor_serialization_version: FeatureVersionBounds, + pub extended_document_structure_version: FeatureVersion, + pub extended_document_serialization_version: FeatureVersionBounds, + pub document_method_versions: DocumentMethodVersions, +} + +#[derive(Clone, Debug, Default)] +pub struct DocumentMethodVersions { + pub is_equal_ignoring_timestamps: FeatureVersion, + pub hash: FeatureVersion, + pub get_raw_for_contract: FeatureVersion, + pub get_raw_for_document_type: FeatureVersion, + pub try_into_asset_unlock_base_transaction_info: FeatureVersion, +} diff --git a/packages/rs-platform-version/src/version/dpp_versions/dpp_document_versions/v1.rs b/packages/rs-platform-version/src/version/dpp_versions/dpp_document_versions/v1.rs new file mode 100644 index 0000000000..8911129ab6 --- /dev/null +++ b/packages/rs-platform-version/src/version/dpp_versions/dpp_document_versions/v1.rs @@ -0,0 +1,31 @@ +use crate::version::dpp_versions::dpp_document_versions::{ + DPPDocumentVersions, DocumentMethodVersions, +}; +use versioned_feature_core::FeatureVersionBounds; + +pub const DOCUMENT_VERSIONS_V1: DPPDocumentVersions = DPPDocumentVersions { + document_structure_version: 0, + document_serialization_version: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + document_cbor_serialization_version: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + extended_document_structure_version: 0, + extended_document_serialization_version: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + document_method_versions: DocumentMethodVersions { + is_equal_ignoring_timestamps: 0, + hash: 0, + get_raw_for_contract: 0, + get_raw_for_document_type: 0, + try_into_asset_unlock_base_transaction_info: 0, + }, +}; diff --git a/packages/rs-platform-version/src/version/dpp_versions/dpp_factory_versions/mod.rs b/packages/rs-platform-version/src/version/dpp_versions/dpp_factory_versions/mod.rs new file mode 100644 index 0000000000..1ce467d139 --- /dev/null +++ b/packages/rs-platform-version/src/version/dpp_versions/dpp_factory_versions/mod.rs @@ -0,0 +1,9 @@ +pub mod v1; + +use versioned_feature_core::FeatureVersion; + +#[derive(Clone, Debug, Default)] +pub struct DPPFactoryVersions { + pub data_contract_factory_structure_version: FeatureVersion, + pub document_factory_structure_version: FeatureVersion, +} diff --git a/packages/rs-platform-version/src/version/dpp_versions/dpp_factory_versions/v1.rs b/packages/rs-platform-version/src/version/dpp_versions/dpp_factory_versions/v1.rs new file mode 100644 index 0000000000..1eb875eab1 --- /dev/null +++ b/packages/rs-platform-version/src/version/dpp_versions/dpp_factory_versions/v1.rs @@ -0,0 +1,6 @@ +use crate::version::dpp_versions::dpp_factory_versions::DPPFactoryVersions; + +pub const DPP_FACTORY_VERSIONS_V1: DPPFactoryVersions = DPPFactoryVersions { + data_contract_factory_structure_version: 0, + document_factory_structure_version: 0, +}; diff --git a/packages/rs-platform-version/src/version/dpp_versions/dpp_identity_versions/mod.rs b/packages/rs-platform-version/src/version/dpp_versions/dpp_identity_versions/mod.rs new file mode 100644 index 0000000000..df9356c003 --- /dev/null +++ b/packages/rs-platform-version/src/version/dpp_versions/dpp_identity_versions/mod.rs @@ -0,0 +1,17 @@ +use versioned_feature_core::FeatureVersion; + +pub mod v1; + +#[derive(Clone, Debug, Default)] +pub struct DPPIdentityVersions { + /// This is the structure of the Identity as it is defined for code paths + pub identity_structure_version: FeatureVersion, + pub identity_key_structure_version: FeatureVersion, + pub identity_key_type_method_versions: IdentityKeyTypeMethodVersions, +} + +#[derive(Clone, Debug, Default)] +pub struct IdentityKeyTypeMethodVersions { + pub random_public_key_data: FeatureVersion, + pub random_public_and_private_key_data: FeatureVersion, +} diff --git a/packages/rs-platform-version/src/version/dpp_versions/dpp_identity_versions/v1.rs b/packages/rs-platform-version/src/version/dpp_versions/dpp_identity_versions/v1.rs new file mode 100644 index 0000000000..6726dbc55d --- /dev/null +++ b/packages/rs-platform-version/src/version/dpp_versions/dpp_identity_versions/v1.rs @@ -0,0 +1,12 @@ +use crate::version::dpp_versions::dpp_identity_versions::{ + DPPIdentityVersions, IdentityKeyTypeMethodVersions, +}; + +pub const IDENTITY_VERSIONS_V1: DPPIdentityVersions = DPPIdentityVersions { + identity_structure_version: 0, + identity_key_structure_version: 0, + identity_key_type_method_versions: IdentityKeyTypeMethodVersions { + random_public_key_data: 0, + random_public_and_private_key_data: 0, + }, +}; diff --git a/packages/rs-platform-version/src/version/dpp_versions/dpp_method_versions/mod.rs b/packages/rs-platform-version/src/version/dpp_versions/dpp_method_versions/mod.rs new file mode 100644 index 0000000000..a39362f90e --- /dev/null +++ b/packages/rs-platform-version/src/version/dpp_versions/dpp_method_versions/mod.rs @@ -0,0 +1,9 @@ +use versioned_feature_core::FeatureVersion; + +pub mod v1; + +#[derive(Clone, Debug, Default)] +pub struct DPPMethodVersions { + pub epoch_core_reward_credits_for_distribution: FeatureVersion, + pub daily_withdrawal_limit: FeatureVersion, +} diff --git a/packages/rs-platform-version/src/version/dpp_versions/dpp_method_versions/v1.rs b/packages/rs-platform-version/src/version/dpp_versions/dpp_method_versions/v1.rs new file mode 100644 index 0000000000..dfc749b7b3 --- /dev/null +++ b/packages/rs-platform-version/src/version/dpp_versions/dpp_method_versions/v1.rs @@ -0,0 +1,5 @@ +use crate::version::dpp_versions::dpp_method_versions::DPPMethodVersions; +pub const DPP_METHOD_VERSIONS_V1: DPPMethodVersions = DPPMethodVersions { + epoch_core_reward_credits_for_distribution: 0, + daily_withdrawal_limit: 0, +}; diff --git a/packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_conversion_versions/mod.rs b/packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_conversion_versions/mod.rs new file mode 100644 index 0000000000..74d2b39661 --- /dev/null +++ b/packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_conversion_versions/mod.rs @@ -0,0 +1,13 @@ +use versioned_feature_core::FeatureVersion; + +pub mod v1; +pub mod v2; + +#[derive(Clone, Debug, Default)] +pub struct DPPStateTransitionConversionVersions { + pub identity_to_identity_create_transition: FeatureVersion, + pub identity_to_identity_top_up_transition: FeatureVersion, + pub identity_to_identity_transfer_transition: FeatureVersion, + pub identity_to_identity_withdrawal_transition: FeatureVersion, + pub identity_to_identity_create_transition_with_signer: FeatureVersion, +} diff --git a/packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_conversion_versions/v1.rs b/packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_conversion_versions/v1.rs new file mode 100644 index 0000000000..a6ce094346 --- /dev/null +++ b/packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_conversion_versions/v1.rs @@ -0,0 +1,10 @@ +use crate::version::dpp_versions::dpp_state_transition_conversion_versions::DPPStateTransitionConversionVersions; + +pub const STATE_TRANSITION_CONVERSION_VERSIONS_V1: DPPStateTransitionConversionVersions = + DPPStateTransitionConversionVersions { + identity_to_identity_create_transition: 0, + identity_to_identity_top_up_transition: 0, + identity_to_identity_transfer_transition: 0, + identity_to_identity_withdrawal_transition: 0, + identity_to_identity_create_transition_with_signer: 0, + }; diff --git a/packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_conversion_versions/v2.rs b/packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_conversion_versions/v2.rs new file mode 100644 index 0000000000..fb38e3ebd7 --- /dev/null +++ b/packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_conversion_versions/v2.rs @@ -0,0 +1,10 @@ +use crate::version::dpp_versions::dpp_state_transition_conversion_versions::DPPStateTransitionConversionVersions; + +pub const STATE_TRANSITION_CONVERSION_VERSIONS_V2: DPPStateTransitionConversionVersions = + DPPStateTransitionConversionVersions { + identity_to_identity_create_transition: 0, + identity_to_identity_top_up_transition: 0, + identity_to_identity_transfer_transition: 0, + identity_to_identity_withdrawal_transition: 1, + identity_to_identity_create_transition_with_signer: 0, + }; diff --git a/packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_method_versions/mod.rs b/packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_method_versions/mod.rs new file mode 100644 index 0000000000..ad2a16e431 --- /dev/null +++ b/packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_method_versions/mod.rs @@ -0,0 +1,18 @@ +use versioned_feature_core::FeatureVersion; + +pub mod v1; + +#[derive(Clone, Debug, Default)] +pub struct DPPStateTransitionMethodVersions { + pub public_key_in_creation_methods: PublicKeyInCreationMethodVersions, +} + +#[derive(Clone, Debug, Default)] +pub struct PublicKeyInCreationMethodVersions { + pub from_public_key_signed_with_private_key: FeatureVersion, + pub from_public_key_signed_external: FeatureVersion, + pub hash: FeatureVersion, + pub duplicated_key_ids_witness: FeatureVersion, + pub duplicated_keys_witness: FeatureVersion, + pub validate_identity_public_keys_structure: FeatureVersion, +} diff --git a/packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_method_versions/v1.rs b/packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_method_versions/v1.rs new file mode 100644 index 0000000000..f8844fa69e --- /dev/null +++ b/packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_method_versions/v1.rs @@ -0,0 +1,15 @@ +use crate::version::dpp_versions::dpp_state_transition_method_versions::{ + DPPStateTransitionMethodVersions, PublicKeyInCreationMethodVersions, +}; + +pub const STATE_TRANSITION_METHOD_VERSIONS_V1: DPPStateTransitionMethodVersions = + DPPStateTransitionMethodVersions { + public_key_in_creation_methods: PublicKeyInCreationMethodVersions { + from_public_key_signed_with_private_key: 0, + from_public_key_signed_external: 0, + hash: 0, + duplicated_key_ids_witness: 0, + duplicated_keys_witness: 0, + validate_identity_public_keys_structure: 0, + }, + }; diff --git a/packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_serialization_versions/mod.rs b/packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_serialization_versions/mod.rs new file mode 100644 index 0000000000..3ad838e5de --- /dev/null +++ b/packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_serialization_versions/mod.rs @@ -0,0 +1,29 @@ +use versioned_feature_core::FeatureVersionBounds; + +pub mod v1; + +#[derive(Clone, Debug, Default)] +pub struct DPPStateTransitionSerializationVersions { + pub identity_public_key_in_creation: FeatureVersionBounds, + pub identity_create_state_transition: FeatureVersionBounds, + pub identity_update_state_transition: FeatureVersionBounds, + pub identity_top_up_state_transition: FeatureVersionBounds, + pub identity_credit_withdrawal_state_transition: FeatureVersionBounds, + pub identity_credit_transfer_state_transition: FeatureVersionBounds, + pub masternode_vote_state_transition: FeatureVersionBounds, + pub contract_create_state_transition: FeatureVersionBounds, + pub contract_update_state_transition: FeatureVersionBounds, + pub documents_batch_state_transition: FeatureVersionBounds, + pub document_base_state_transition: FeatureVersionBounds, + pub document_create_state_transition: DocumentFeatureVersionBounds, + pub document_replace_state_transition: DocumentFeatureVersionBounds, + pub document_delete_state_transition: DocumentFeatureVersionBounds, + pub document_transfer_state_transition: DocumentFeatureVersionBounds, + pub document_update_price_state_transition: DocumentFeatureVersionBounds, + pub document_purchase_state_transition: DocumentFeatureVersionBounds, +} + +#[derive(Clone, Debug, Default)] +pub struct DocumentFeatureVersionBounds { + pub bounds: FeatureVersionBounds, +} diff --git a/packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_serialization_versions/v1.rs b/packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_serialization_versions/v1.rs new file mode 100644 index 0000000000..917b8405f0 --- /dev/null +++ b/packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_serialization_versions/v1.rs @@ -0,0 +1,105 @@ +use crate::version::dpp_versions::dpp_state_transition_serialization_versions::{ + DPPStateTransitionSerializationVersions, DocumentFeatureVersionBounds, +}; +use versioned_feature_core::FeatureVersionBounds; + +pub const STATE_TRANSITION_SERIALIZATION_VERSIONS_V1: DPPStateTransitionSerializationVersions = + DPPStateTransitionSerializationVersions { + identity_public_key_in_creation: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + identity_create_state_transition: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + identity_update_state_transition: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + identity_top_up_state_transition: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + identity_credit_withdrawal_state_transition: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + identity_credit_transfer_state_transition: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + masternode_vote_state_transition: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + contract_create_state_transition: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + contract_update_state_transition: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + documents_batch_state_transition: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + document_base_state_transition: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + document_create_state_transition: DocumentFeatureVersionBounds { + bounds: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + }, + document_replace_state_transition: DocumentFeatureVersionBounds { + bounds: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + }, + document_delete_state_transition: DocumentFeatureVersionBounds { + bounds: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + }, + document_transfer_state_transition: DocumentFeatureVersionBounds { + bounds: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + }, + document_update_price_state_transition: DocumentFeatureVersionBounds { + bounds: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + }, + document_purchase_state_transition: DocumentFeatureVersionBounds { + bounds: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + }, + }; diff --git a/packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_versions/mod.rs b/packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_versions/mod.rs new file mode 100644 index 0000000000..407e6e1c52 --- /dev/null +++ b/packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_versions/mod.rs @@ -0,0 +1,46 @@ +use versioned_feature_core::FeatureVersion; + +pub mod v1; +pub mod v2; + +#[derive(Clone, Debug, Default)] +pub struct DPPStateTransitionVersions { + pub documents: DocumentTransitionVersions, + pub identities: IdentityTransitionVersions, +} + +#[derive(Clone, Debug, Default)] +pub struct IdentityTransitionVersions { + pub max_public_keys_in_creation: u16, + pub asset_locks: IdentityTransitionAssetLockVersions, + pub credit_withdrawal: IdentityCreditWithdrawalTransitionVersions, +} + +#[derive(Clone, Debug, Default)] +pub struct IdentityCreditWithdrawalTransitionVersions { + pub default_constructor: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct IdentityTransitionAssetLockVersions { + pub required_asset_lock_duff_balance_for_processing_start_for_identity_create: u64, + pub required_asset_lock_duff_balance_for_processing_start_for_identity_top_up: u64, + pub validate_asset_lock_transaction_structure: FeatureVersion, + pub validate_instant_asset_lock_proof_structure: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DocumentTransitionVersions { + pub documents_batch_transition: DocumentsBatchTransitionVersions, +} + +#[derive(Clone, Debug, Default)] +pub struct DocumentsBatchTransitionVersions { + pub validation: DocumentsBatchTransitionValidationVersions, +} + +#[derive(Clone, Debug, Default)] +pub struct DocumentsBatchTransitionValidationVersions { + pub find_duplicates_by_id: FeatureVersion, + pub validate_base_structure: FeatureVersion, +} diff --git a/packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_versions/v1.rs b/packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_versions/v1.rs new file mode 100644 index 0000000000..2dac96fd8f --- /dev/null +++ b/packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_versions/v1.rs @@ -0,0 +1,29 @@ +use crate::version::dpp_versions::dpp_state_transition_versions::{ + DPPStateTransitionVersions, DocumentTransitionVersions, + DocumentsBatchTransitionValidationVersions, DocumentsBatchTransitionVersions, + IdentityCreditWithdrawalTransitionVersions, IdentityTransitionAssetLockVersions, + IdentityTransitionVersions, +}; + +pub const STATE_TRANSITION_VERSIONS_V1: DPPStateTransitionVersions = DPPStateTransitionVersions { + documents: DocumentTransitionVersions { + documents_batch_transition: DocumentsBatchTransitionVersions { + validation: DocumentsBatchTransitionValidationVersions { + find_duplicates_by_id: 0, + validate_base_structure: 0, + }, + }, + }, + identities: IdentityTransitionVersions { + max_public_keys_in_creation: 6, + asset_locks: IdentityTransitionAssetLockVersions { + required_asset_lock_duff_balance_for_processing_start_for_identity_create: 200000, + required_asset_lock_duff_balance_for_processing_start_for_identity_top_up: 50000, + validate_asset_lock_transaction_structure: 0, + validate_instant_asset_lock_proof_structure: 0, + }, + credit_withdrawal: IdentityCreditWithdrawalTransitionVersions { + default_constructor: 0, + }, + }, +}; diff --git a/packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_versions/v2.rs b/packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_versions/v2.rs new file mode 100644 index 0000000000..2a5d2d0651 --- /dev/null +++ b/packages/rs-platform-version/src/version/dpp_versions/dpp_state_transition_versions/v2.rs @@ -0,0 +1,29 @@ +use crate::version::dpp_versions::dpp_state_transition_versions::{ + DPPStateTransitionVersions, DocumentTransitionVersions, + DocumentsBatchTransitionValidationVersions, DocumentsBatchTransitionVersions, + IdentityCreditWithdrawalTransitionVersions, IdentityTransitionAssetLockVersions, + IdentityTransitionVersions, +}; + +pub const STATE_TRANSITION_VERSIONS_V2: DPPStateTransitionVersions = DPPStateTransitionVersions { + documents: DocumentTransitionVersions { + documents_batch_transition: DocumentsBatchTransitionVersions { + validation: DocumentsBatchTransitionValidationVersions { + find_duplicates_by_id: 0, + validate_base_structure: 0, + }, + }, + }, + identities: IdentityTransitionVersions { + max_public_keys_in_creation: 6, + asset_locks: IdentityTransitionAssetLockVersions { + required_asset_lock_duff_balance_for_processing_start_for_identity_create: 200000, + required_asset_lock_duff_balance_for_processing_start_for_identity_top_up: 50000, + validate_asset_lock_transaction_structure: 0, + validate_instant_asset_lock_proof_structure: 0, + }, + credit_withdrawal: IdentityCreditWithdrawalTransitionVersions { + default_constructor: 1, + }, + }, +}; diff --git a/packages/rs-platform-version/src/version/dpp_versions/dpp_validation_versions/mod.rs b/packages/rs-platform-version/src/version/dpp_versions/dpp_validation_versions/mod.rs new file mode 100644 index 0000000000..ebaa11678f --- /dev/null +++ b/packages/rs-platform-version/src/version/dpp_versions/dpp_validation_versions/mod.rs @@ -0,0 +1,47 @@ +use versioned_feature_core::FeatureVersion; + +pub mod v1; +pub mod v2; + +#[derive(Clone, Debug, Default)] +pub struct DPPValidationVersions { + pub json_schema_validator: JsonSchemaValidatorVersions, + pub data_contract: DataContractValidationVersions, + pub document_type: DocumentTypeValidationVersions, + pub voting: VotingValidationVersions, +} + +#[derive(Clone, Debug, Default)] +pub struct DataContractValidationVersions { + pub validate: FeatureVersion, + pub validate_config_update: FeatureVersion, + pub validate_index_definitions: FeatureVersion, + pub validate_index_naming_duplicates: FeatureVersion, + pub validate_not_defined_properties: FeatureVersion, + pub validate_property_definition: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct VotingValidationVersions { + /// How long do we allow other contenders to join a contest after the first contender + pub allow_other_contenders_time_mainnet_ms: u64, + /// How long do we allow other contenders to join a contest after the first contender in a testing environment + pub allow_other_contenders_time_testing_ms: u64, + /// How many votes do we allow from the same masternode? + pub votes_allowed_per_masternode: u16, +} + +#[derive(Clone, Debug, Default)] +pub struct DocumentTypeValidationVersions { + pub validate_update: FeatureVersion, + pub unique_index_limit: u16, + pub contested_index_limit: u16, +} + +#[derive(Clone, Debug, Default)] +pub struct JsonSchemaValidatorVersions { + pub new: FeatureVersion, + pub validate: FeatureVersion, + pub compile: FeatureVersion, + pub compile_and_validate: FeatureVersion, +} diff --git a/packages/rs-platform-version/src/version/dpp_versions/dpp_validation_versions/v1.rs b/packages/rs-platform-version/src/version/dpp_versions/dpp_validation_versions/v1.rs new file mode 100644 index 0000000000..e698694e62 --- /dev/null +++ b/packages/rs-platform-version/src/version/dpp_versions/dpp_validation_versions/v1.rs @@ -0,0 +1,31 @@ +use crate::version::dpp_versions::dpp_validation_versions::{ + DPPValidationVersions, DataContractValidationVersions, DocumentTypeValidationVersions, + JsonSchemaValidatorVersions, VotingValidationVersions, +}; + +pub const DPP_VALIDATION_VERSIONS_V1: DPPValidationVersions = DPPValidationVersions { + json_schema_validator: JsonSchemaValidatorVersions { + new: 0, + validate: 0, + compile: 0, + compile_and_validate: 0, + }, + data_contract: DataContractValidationVersions { + validate: 0, + validate_config_update: 0, + validate_index_definitions: 0, + validate_index_naming_duplicates: 0, + validate_not_defined_properties: 0, + validate_property_definition: 0, + }, + document_type: DocumentTypeValidationVersions { + validate_update: 0, + contested_index_limit: 1, + unique_index_limit: 10, + }, + voting: VotingValidationVersions { + allow_other_contenders_time_mainnet_ms: 604_800_000, // 1 week in ms + allow_other_contenders_time_testing_ms: 604_800_000, // 1 week in ms for v1 (changes in v2) + votes_allowed_per_masternode: 5, + }, +}; diff --git a/packages/rs-platform-version/src/version/dpp_versions/dpp_validation_versions/v2.rs b/packages/rs-platform-version/src/version/dpp_versions/dpp_validation_versions/v2.rs new file mode 100644 index 0000000000..7122390711 --- /dev/null +++ b/packages/rs-platform-version/src/version/dpp_versions/dpp_validation_versions/v2.rs @@ -0,0 +1,31 @@ +use crate::version::dpp_versions::dpp_validation_versions::{ + DPPValidationVersions, DataContractValidationVersions, DocumentTypeValidationVersions, + JsonSchemaValidatorVersions, VotingValidationVersions, +}; + +pub const DPP_VALIDATION_VERSIONS_V2: DPPValidationVersions = DPPValidationVersions { + json_schema_validator: JsonSchemaValidatorVersions { + new: 0, + validate: 0, + compile: 0, + compile_and_validate: 0, + }, + data_contract: DataContractValidationVersions { + validate: 0, + validate_config_update: 0, + validate_index_definitions: 0, + validate_index_naming_duplicates: 0, + validate_not_defined_properties: 0, + validate_property_definition: 0, + }, + document_type: DocumentTypeValidationVersions { + validate_update: 0, + contested_index_limit: 1, + unique_index_limit: 10, + }, + voting: VotingValidationVersions { + allow_other_contenders_time_mainnet_ms: 604_800_000, // 1 week in ms + allow_other_contenders_time_testing_ms: 2_700_000, //45 minutes + votes_allowed_per_masternode: 5, + }, +}; diff --git a/packages/rs-platform-version/src/version/dpp_versions/dpp_voting_versions/mod.rs b/packages/rs-platform-version/src/version/dpp_versions/dpp_voting_versions/mod.rs new file mode 100644 index 0000000000..900fab5a43 --- /dev/null +++ b/packages/rs-platform-version/src/version/dpp_versions/dpp_voting_versions/mod.rs @@ -0,0 +1,11 @@ +use versioned_feature_core::FeatureVersion; + +pub mod v1; +pub mod v2; + +#[derive(Clone, Debug, Default)] +pub struct DPPVotingVersions { + pub default_vote_poll_time_duration_mainnet_ms: u64, + pub default_vote_poll_time_duration_test_network_ms: u64, + pub contested_document_vote_poll_stored_info_version: FeatureVersion, +} diff --git a/packages/rs-platform-version/src/version/dpp_versions/dpp_voting_versions/v1.rs b/packages/rs-platform-version/src/version/dpp_versions/dpp_voting_versions/v1.rs new file mode 100644 index 0000000000..944a295d1f --- /dev/null +++ b/packages/rs-platform-version/src/version/dpp_versions/dpp_voting_versions/v1.rs @@ -0,0 +1,7 @@ +use crate::version::dpp_versions::dpp_voting_versions::DPPVotingVersions; + +pub const VOTING_VERSION_V1: DPPVotingVersions = DPPVotingVersions { + default_vote_poll_time_duration_mainnet_ms: 1_209_600_000, //2 weeks + default_vote_poll_time_duration_test_network_ms: 1_209_600_000, //2 weeks + contested_document_vote_poll_stored_info_version: 0, +}; diff --git a/packages/rs-platform-version/src/version/dpp_versions/dpp_voting_versions/v2.rs b/packages/rs-platform-version/src/version/dpp_versions/dpp_voting_versions/v2.rs new file mode 100644 index 0000000000..de072e8783 --- /dev/null +++ b/packages/rs-platform-version/src/version/dpp_versions/dpp_voting_versions/v2.rs @@ -0,0 +1,7 @@ +use crate::version::dpp_versions::dpp_voting_versions::DPPVotingVersions; + +pub const VOTING_VERSION_V2: DPPVotingVersions = DPPVotingVersions { + default_vote_poll_time_duration_mainnet_ms: 1_209_600_000, //2 weeks + default_vote_poll_time_duration_test_network_ms: 5_400_000, //90 minutes + contested_document_vote_poll_stored_info_version: 0, +}; diff --git a/packages/rs-platform-version/src/version/dpp_versions/mod.rs b/packages/rs-platform-version/src/version/dpp_versions/mod.rs new file mode 100644 index 0000000000..e51203512c --- /dev/null +++ b/packages/rs-platform-version/src/version/dpp_versions/mod.rs @@ -0,0 +1,45 @@ +pub mod dpp_asset_lock_versions; +pub mod dpp_contract_versions; +pub mod dpp_costs_versions; +pub mod dpp_document_versions; +pub mod dpp_factory_versions; +pub mod dpp_identity_versions; +pub mod dpp_method_versions; +pub mod dpp_state_transition_conversion_versions; +pub mod dpp_state_transition_method_versions; +pub mod dpp_state_transition_serialization_versions; +pub mod dpp_state_transition_versions; +pub mod dpp_validation_versions; +pub mod dpp_voting_versions; + +use dpp_asset_lock_versions::DPPAssetLockVersions; +use dpp_contract_versions::DPPContractVersions; +use dpp_costs_versions::DPPCostsVersions; +use dpp_document_versions::DPPDocumentVersions; +use dpp_factory_versions::DPPFactoryVersions; +use dpp_identity_versions::DPPIdentityVersions; +use dpp_method_versions::DPPMethodVersions; +use dpp_state_transition_conversion_versions::DPPStateTransitionConversionVersions; +use dpp_state_transition_method_versions::DPPStateTransitionMethodVersions; +use dpp_state_transition_serialization_versions::DPPStateTransitionSerializationVersions; +use dpp_state_transition_versions::DPPStateTransitionVersions; +use dpp_validation_versions::DPPValidationVersions; +use dpp_voting_versions::DPPVotingVersions; + +#[derive(Clone, Debug, Default)] +pub struct DPPVersion { + pub costs: DPPCostsVersions, + pub validation: DPPValidationVersions, + // TODO: Should be split by state transition type + pub state_transition_serialization_versions: DPPStateTransitionSerializationVersions, + pub state_transition_conversion_versions: DPPStateTransitionConversionVersions, + pub state_transition_method_versions: DPPStateTransitionMethodVersions, + pub state_transitions: DPPStateTransitionVersions, + pub contract_versions: DPPContractVersions, + pub document_versions: DPPDocumentVersions, + pub identity_versions: DPPIdentityVersions, + pub voting_versions: DPPVotingVersions, + pub asset_lock_versions: DPPAssetLockVersions, + pub methods: DPPMethodVersions, + pub factory_versions: DPPFactoryVersions, +} diff --git a/packages/rs-platform-version/src/version/drive_abci_versions.rs b/packages/rs-platform-version/src/version/drive_abci_versions.rs deleted file mode 100644 index bf80179c09..0000000000 --- a/packages/rs-platform-version/src/version/drive_abci_versions.rs +++ /dev/null @@ -1,349 +0,0 @@ -use crate::version::{FeatureVersion, FeatureVersionBounds, OptionalFeatureVersion}; - -#[derive(Clone, Debug, Default)] -pub struct DriveAbciVersion { - pub structs: DriveAbciStructureVersions, - pub methods: DriveAbciMethodVersions, - pub validation_and_processing: DriveAbciValidationVersions, - pub query: DriveAbciQueryVersions, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveAbciQueryVersions { - pub max_returned_elements: u16, - pub response_metadata: FeatureVersion, - pub proofs_query: FeatureVersionBounds, - pub document_query: FeatureVersionBounds, - pub prefunded_specialized_balances: DriveAbciQueryPrefundedSpecializedBalancesVersions, - pub identity_based_queries: DriveAbciQueryIdentityVersions, - pub validator_queries: DriveAbciQueryValidatorVersions, - pub data_contract_based_queries: DriveAbciQueryDataContractVersions, - pub voting_based_queries: DriveAbciQueryVotingVersions, - pub system: DriveAbciQuerySystemVersions, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveAbciQueryPrefundedSpecializedBalancesVersions { - pub balance: FeatureVersionBounds, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveAbciQueryIdentityVersions { - pub identity: FeatureVersionBounds, - pub identities_contract_keys: FeatureVersionBounds, - pub keys: FeatureVersionBounds, - pub identity_nonce: FeatureVersionBounds, - pub identity_contract_nonce: FeatureVersionBounds, - pub balance: FeatureVersionBounds, - pub identities_balances: FeatureVersionBounds, - pub balance_and_revision: FeatureVersionBounds, - pub identity_by_public_key_hash: FeatureVersionBounds, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveAbciQueryValidatorVersions { - pub proposed_block_counts_by_evonode_ids: FeatureVersionBounds, - pub proposed_block_counts_by_range: FeatureVersionBounds, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveAbciQueryVotingVersions { - pub vote_polls_by_end_date_query: FeatureVersionBounds, - pub contested_resource_vote_state: FeatureVersionBounds, - pub contested_resource_voters_for_identity: FeatureVersionBounds, - pub contested_resource_identity_vote_status: FeatureVersionBounds, - pub contested_resources: FeatureVersionBounds, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveAbciQueryDataContractVersions { - pub data_contract: FeatureVersionBounds, - pub data_contract_history: FeatureVersionBounds, - pub data_contracts: FeatureVersionBounds, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveAbciQuerySystemVersions { - pub version_upgrade_state: FeatureVersionBounds, - pub version_upgrade_vote_status: FeatureVersionBounds, - pub epoch_infos: FeatureVersionBounds, - pub partial_status: FeatureVersionBounds, - pub path_elements: FeatureVersionBounds, - pub total_credits_in_platform: FeatureVersionBounds, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveAbciStructureVersions { - pub platform_state_structure: FeatureVersion, - pub platform_state_for_saving_structure: FeatureVersion, - pub state_transition_execution_context: FeatureVersion, - pub commit: FeatureVersion, - pub masternode: FeatureVersion, - pub signature_verification_quorum_set: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveAbciMethodVersions { - pub engine: DriveAbciEngineMethodVersions, - pub initialization: DriveAbciInitializationMethodVersions, - pub core_based_updates: DriveAbciCoreBasedUpdatesMethodVersions, - pub protocol_upgrade: DriveAbciProtocolUpgradeMethodVersions, - pub block_fee_processing: DriveAbciBlockFeeProcessingMethodVersions, - pub core_chain_lock: DriveAbciCoreChainLockMethodVersionsAndConstants, - pub core_instant_send_lock: DriveAbciCoreInstantSendLockMethodVersions, - pub fee_pool_inwards_distribution: DriveAbciFeePoolInwardsDistributionMethodVersions, - pub fee_pool_outwards_distribution: DriveAbciFeePoolOutwardsDistributionMethodVersions, - pub withdrawals: DriveAbciIdentityCreditWithdrawalMethodVersions, - pub voting: DriveAbciVotingMethodVersions, - pub state_transition_processing: DriveAbciStateTransitionProcessingMethodVersions, - pub epoch: DriveAbciEpochMethodVersions, - pub block_start: DriveAbciBlockStartMethodVersions, - pub block_end: DriveAbciBlockEndMethodVersions, - pub platform_state_storage: DriveAbciPlatformStateStorageMethodVersions, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveAbciValidationVersions { - pub state_transitions: DriveAbciStateTransitionValidationVersions, - pub process_state_transition: FeatureVersion, - pub state_transition_to_execution_event_for_check_tx: FeatureVersion, - pub penalties: PenaltyAmounts, - pub event_constants: DriveAbciValidationConstants, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveAbciValidationConstants { - pub maximum_vote_polls_to_process: u16, - pub maximum_contenders_to_consider: u16, -} - -/// All of these penalty amounts are in credits -#[derive(Clone, Debug, Default)] -pub struct PenaltyAmounts { - pub identity_id_not_correct: u64, - pub unique_key_already_present: u64, - pub validation_of_added_keys_structure_failure: u64, - pub validation_of_added_keys_proof_of_possession_failure: u64, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveAbciPlatformStateStorageMethodVersions { - pub fetch_platform_state: FeatureVersion, - pub store_platform_state: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveAbciDocumentsStateTransitionValidationVersions { - pub balance_pre_check: FeatureVersion, - pub basic_structure: FeatureVersion, - pub advanced_structure: FeatureVersion, - pub revision: FeatureVersion, - pub state: FeatureVersion, - pub transform_into_action: FeatureVersion, - pub data_triggers: DriveAbciValidationDataTriggerAndBindingVersions, - pub is_allowed: FeatureVersion, - pub document_create_transition_structure_validation: FeatureVersion, - pub document_delete_transition_structure_validation: FeatureVersion, - pub document_replace_transition_structure_validation: FeatureVersion, - pub document_transfer_transition_structure_validation: FeatureVersion, - pub document_purchase_transition_structure_validation: FeatureVersion, - pub document_update_price_transition_structure_validation: FeatureVersion, - pub document_create_transition_state_validation: FeatureVersion, - pub document_delete_transition_state_validation: FeatureVersion, - pub document_replace_transition_state_validation: FeatureVersion, - pub document_transfer_transition_state_validation: FeatureVersion, - pub document_purchase_transition_state_validation: FeatureVersion, - pub document_update_price_transition_state_validation: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveAbciValidationDataTriggerAndBindingVersions { - pub bindings: FeatureVersion, - pub triggers: DriveAbciValidationDataTriggerVersions, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveAbciValidationDataTriggerVersions { - pub create_contact_request_data_trigger: FeatureVersion, - pub create_domain_data_trigger: FeatureVersion, - pub create_identity_data_trigger: FeatureVersion, - pub create_feature_flag_data_trigger: FeatureVersion, - pub create_masternode_reward_shares_data_trigger: FeatureVersion, - pub delete_withdrawal_data_trigger: FeatureVersion, - pub reject_data_trigger: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveAbciStateTransitionValidationVersion { - pub basic_structure: OptionalFeatureVersion, - pub advanced_structure: OptionalFeatureVersion, - pub identity_signatures: OptionalFeatureVersion, - pub advanced_minimum_balance_pre_check: OptionalFeatureVersion, - pub nonce: OptionalFeatureVersion, - pub state: FeatureVersion, - pub transform_into_action: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveAbciStateTransitionValidationVersions { - pub common_validation_methods: DriveAbciStateTransitionCommonValidationVersions, - pub max_asset_lock_usage_attempts: u16, - pub identity_create_state_transition: DriveAbciStateTransitionValidationVersion, - pub identity_update_state_transition: DriveAbciStateTransitionValidationVersion, - pub identity_top_up_state_transition: DriveAbciStateTransitionValidationVersion, - pub identity_credit_withdrawal_state_transition: DriveAbciStateTransitionValidationVersion, - pub identity_credit_transfer_state_transition: DriveAbciStateTransitionValidationVersion, - pub masternode_vote_state_transition: DriveAbciStateTransitionValidationVersion, - pub contract_create_state_transition: DriveAbciStateTransitionValidationVersion, - pub contract_update_state_transition: DriveAbciStateTransitionValidationVersion, - pub documents_batch_state_transition: DriveAbciDocumentsStateTransitionValidationVersions, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveAbciStateTransitionCommonValidationVersions { - pub asset_locks: DriveAbciAssetLockValidationVersions, - pub validate_identity_public_key_contract_bounds: FeatureVersion, - pub validate_identity_public_key_ids_dont_exist_in_state: FeatureVersion, - pub validate_identity_public_key_ids_exist_in_state: FeatureVersion, - pub validate_state_transition_identity_signed: FeatureVersion, - pub validate_unique_identity_public_key_hashes_in_state: FeatureVersion, - pub validate_master_key_uniqueness: FeatureVersion, - pub validate_simple_pre_check_balance: FeatureVersion, -} - -#[derive(Clone, Copy, Debug, Default)] -pub struct DriveAbciAssetLockValidationVersions { - pub fetch_asset_lock_transaction_output_sync: FeatureVersion, - pub verify_asset_lock_is_not_spent_and_has_enough_balance: FeatureVersion, -} - -#[derive(Clone, Copy, Debug, Default)] -pub struct DriveAbciEngineMethodVersions { - pub init_chain: FeatureVersion, - pub check_tx: FeatureVersion, - pub run_block_proposal: FeatureVersion, - pub finalize_block_proposal: FeatureVersion, - pub consensus_params_update: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveAbciCoreBasedUpdatesMethodVersions { - pub update_core_info: FeatureVersion, - pub update_masternode_list: FeatureVersion, - pub update_quorum_info: FeatureVersion, - pub masternode_updates: DriveAbciMasternodeIdentitiesUpdatesMethodVersions, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveAbciMasternodeIdentitiesUpdatesMethodVersions { - pub get_voter_identity_key: FeatureVersion, - pub get_operator_identity_keys: FeatureVersion, - pub get_owner_identity_withdrawal_key: FeatureVersion, - pub get_voter_identifier_from_masternode_list_item: FeatureVersion, - pub get_operator_identifier_from_masternode_list_item: FeatureVersion, - pub create_operator_identity: FeatureVersion, - pub create_owner_identity: FeatureVersion, - pub create_voter_identity: FeatureVersion, - pub disable_identity_keys: FeatureVersion, - pub update_masternode_identities: FeatureVersion, - pub update_operator_identity: FeatureVersion, - pub update_owner_withdrawal_address: FeatureVersion, - pub update_voter_identity: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveAbciInitializationMethodVersions { - pub initial_core_height_and_time: FeatureVersion, - pub create_genesis_state: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveAbciBlockFeeProcessingMethodVersions { - pub add_process_epoch_change_operations: FeatureVersion, - pub process_block_fees: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveAbciCoreInstantSendLockMethodVersions { - pub verify_recent_signature_locally: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveAbciCoreChainLockMethodVersionsAndConstants { - pub choose_quorum: FeatureVersion, - pub verify_chain_lock: FeatureVersion, - pub verify_chain_lock_locally: FeatureVersion, - pub verify_chain_lock_through_core: FeatureVersion, - pub make_sure_core_is_synced_to_chain_lock: FeatureVersion, - pub recent_block_count_amount: u32, //what constitutes a recent block, for v0 it's 2. -} - -#[derive(Clone, Debug, Default)] -pub struct DriveAbciFeePoolInwardsDistributionMethodVersions { - pub add_distribute_block_fees_into_pools_operations: FeatureVersion, - pub add_distribute_storage_fee_to_epochs_operations: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveAbciFeePoolOutwardsDistributionMethodVersions { - pub add_distribute_fees_from_oldest_unpaid_epoch_pool_to_proposers_operations: FeatureVersion, - pub add_epoch_pool_to_proposers_payout_operations: FeatureVersion, - pub find_oldest_epoch_needing_payment: FeatureVersion, - pub fetch_reward_shares_list_for_masternode: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveAbciEpochMethodVersions { - pub gather_epoch_info: FeatureVersion, - pub get_genesis_time: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveAbciBlockStartMethodVersions { - pub clear_drive_block_cache: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveAbciBlockEndMethodVersions { - pub update_state_cache: FeatureVersion, - pub update_drive_cache: FeatureVersion, - pub validator_set_update: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveAbciVotingMethodVersions { - pub keep_record_of_finished_contested_resource_vote_poll: FeatureVersion, - pub clean_up_after_vote_poll_end: FeatureVersion, - pub clean_up_after_contested_resources_vote_poll_end: FeatureVersion, - pub check_for_ended_vote_polls: FeatureVersion, - pub tally_votes_for_contested_document_resource_vote_poll: FeatureVersion, - pub award_document_to_winner: FeatureVersion, - pub delay_vote_poll: FeatureVersion, - pub run_dao_platform_events: FeatureVersion, - pub remove_votes_for_removed_masternodes: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveAbciIdentityCreditWithdrawalMethodVersions { - pub build_untied_withdrawal_transactions_from_documents: FeatureVersion, - pub dequeue_and_build_unsigned_withdrawal_transactions: FeatureVersion, - pub fetch_transactions_block_inclusion_status: FeatureVersion, - pub pool_withdrawals_into_transactions_queue: FeatureVersion, - pub update_broadcasted_withdrawal_statuses: FeatureVersion, - pub append_signatures_and_broadcast_withdrawal_transactions: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveAbciProtocolUpgradeMethodVersions { - pub check_for_desired_protocol_upgrade: FeatureVersion, - pub upgrade_protocol_version_on_epoch_change: FeatureVersion, - pub protocol_version_upgrade_percentage_needed: u64, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveAbciStateTransitionProcessingMethodVersions { - pub execute_event: FeatureVersion, - pub process_raw_state_transitions: FeatureVersion, - pub decode_raw_state_transitions: FeatureVersion, - pub validate_fees_of_event: FeatureVersion, -} diff --git a/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_method_versions/mod.rs b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_method_versions/mod.rs new file mode 100644 index 0000000000..48caab4b3c --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_method_versions/mod.rs @@ -0,0 +1,167 @@ +use versioned_feature_core::{FeatureVersion, OptionalFeatureVersion}; + +pub mod v1; +pub mod v2; +pub mod v3; +pub mod v4; + +#[derive(Clone, Debug, Default)] +pub struct DriveAbciMethodVersions { + pub engine: DriveAbciEngineMethodVersions, + pub initialization: DriveAbciInitializationMethodVersions, + pub core_based_updates: DriveAbciCoreBasedUpdatesMethodVersions, + pub protocol_upgrade: DriveAbciProtocolUpgradeMethodVersions, + pub block_fee_processing: DriveAbciBlockFeeProcessingMethodVersions, + pub core_chain_lock: DriveAbciCoreChainLockMethodVersionsAndConstants, + pub core_instant_send_lock: DriveAbciCoreInstantSendLockMethodVersions, + pub fee_pool_inwards_distribution: DriveAbciFeePoolInwardsDistributionMethodVersions, + pub fee_pool_outwards_distribution: DriveAbciFeePoolOutwardsDistributionMethodVersions, + pub withdrawals: DriveAbciIdentityCreditWithdrawalMethodVersions, + pub voting: DriveAbciVotingMethodVersions, + pub state_transition_processing: DriveAbciStateTransitionProcessingMethodVersions, + pub epoch: DriveAbciEpochMethodVersions, + pub block_start: DriveAbciBlockStartMethodVersions, + pub block_end: DriveAbciBlockEndMethodVersions, + pub platform_state_storage: DriveAbciPlatformStateStorageMethodVersions, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveAbciPlatformStateStorageMethodVersions { + pub fetch_platform_state: FeatureVersion, + pub store_platform_state: FeatureVersion, +} + +#[derive(Clone, Copy, Debug, Default)] +pub struct DriveAbciEngineMethodVersions { + pub init_chain: FeatureVersion, + pub check_tx: FeatureVersion, + pub run_block_proposal: FeatureVersion, + pub finalize_block_proposal: FeatureVersion, + pub consensus_params_update: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveAbciCoreBasedUpdatesMethodVersions { + pub update_core_info: FeatureVersion, + pub update_masternode_list: FeatureVersion, + pub update_quorum_info: FeatureVersion, + pub masternode_updates: DriveAbciMasternodeIdentitiesUpdatesMethodVersions, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveAbciMasternodeIdentitiesUpdatesMethodVersions { + pub get_voter_identity_key: FeatureVersion, + pub get_operator_identity_keys: FeatureVersion, + pub get_owner_identity_withdrawal_key: FeatureVersion, + pub get_owner_identity_owner_key: FeatureVersion, + pub get_voter_identifier_from_masternode_list_item: FeatureVersion, + pub get_operator_identifier_from_masternode_list_item: FeatureVersion, + pub create_operator_identity: FeatureVersion, + pub create_owner_identity: FeatureVersion, + pub create_voter_identity: FeatureVersion, + pub disable_identity_keys: FeatureVersion, + pub update_masternode_identities: FeatureVersion, + pub update_operator_identity: FeatureVersion, + pub update_owner_withdrawal_address: FeatureVersion, + pub update_voter_identity: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveAbciInitializationMethodVersions { + pub initial_core_height_and_time: FeatureVersion, + pub create_genesis_state: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveAbciBlockFeeProcessingMethodVersions { + pub add_process_epoch_change_operations: FeatureVersion, + pub process_block_fees: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveAbciCoreInstantSendLockMethodVersions { + pub verify_recent_signature_locally: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveAbciCoreChainLockMethodVersionsAndConstants { + pub choose_quorum: FeatureVersion, + pub verify_chain_lock: FeatureVersion, + pub verify_chain_lock_locally: FeatureVersion, + pub verify_chain_lock_through_core: FeatureVersion, + pub make_sure_core_is_synced_to_chain_lock: FeatureVersion, + pub recent_block_count_amount: u32, //what constitutes a recent block, for v0 it's 2. +} + +#[derive(Clone, Debug, Default)] +pub struct DriveAbciFeePoolInwardsDistributionMethodVersions { + pub add_distribute_block_fees_into_pools_operations: FeatureVersion, + pub add_distribute_storage_fee_to_epochs_operations: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveAbciFeePoolOutwardsDistributionMethodVersions { + pub add_distribute_fees_from_oldest_unpaid_epoch_pool_to_proposers_operations: FeatureVersion, + pub add_epoch_pool_to_proposers_payout_operations: FeatureVersion, + pub find_oldest_epoch_needing_payment: FeatureVersion, + pub fetch_reward_shares_list_for_masternode: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveAbciEpochMethodVersions { + pub gather_epoch_info: FeatureVersion, + pub get_genesis_time: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveAbciBlockStartMethodVersions { + pub clear_drive_block_cache: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveAbciBlockEndMethodVersions { + pub update_state_cache: FeatureVersion, + pub update_drive_cache: FeatureVersion, + pub validator_set_update: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveAbciVotingMethodVersions { + pub keep_record_of_finished_contested_resource_vote_poll: FeatureVersion, + pub clean_up_after_vote_poll_end: FeatureVersion, + pub clean_up_after_contested_resources_vote_poll_end: FeatureVersion, + pub check_for_ended_vote_polls: FeatureVersion, + pub tally_votes_for_contested_document_resource_vote_poll: FeatureVersion, + pub award_document_to_winner: FeatureVersion, + pub delay_vote_poll: FeatureVersion, + pub run_dao_platform_events: FeatureVersion, + pub remove_votes_for_removed_masternodes: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveAbciIdentityCreditWithdrawalMethodVersions { + pub build_untied_withdrawal_transactions_from_documents: FeatureVersion, + pub dequeue_and_build_unsigned_withdrawal_transactions: FeatureVersion, + pub fetch_transactions_block_inclusion_status: FeatureVersion, + pub pool_withdrawals_into_transactions_queue: FeatureVersion, + pub update_broadcasted_withdrawal_statuses: FeatureVersion, + pub rebroadcast_expired_withdrawal_documents: FeatureVersion, + pub append_signatures_and_broadcast_withdrawal_transactions: FeatureVersion, + pub cleanup_expired_locks_of_withdrawal_amounts: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveAbciProtocolUpgradeMethodVersions { + pub check_for_desired_protocol_upgrade: FeatureVersion, + pub upgrade_protocol_version_on_epoch_change: FeatureVersion, + pub perform_events_on_first_block_of_protocol_change: OptionalFeatureVersion, + pub protocol_version_upgrade_percentage_needed: u64, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveAbciStateTransitionProcessingMethodVersions { + pub execute_event: FeatureVersion, + pub process_raw_state_transitions: FeatureVersion, + pub decode_raw_state_transitions: FeatureVersion, + pub validate_fees_of_event: FeatureVersion, +} diff --git a/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_method_versions/v1.rs b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_method_versions/v1.rs new file mode 100644 index 0000000000..e6e1c63a40 --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_method_versions/v1.rs @@ -0,0 +1,121 @@ +use crate::version::drive_abci_versions::drive_abci_method_versions::{ + DriveAbciBlockEndMethodVersions, DriveAbciBlockFeeProcessingMethodVersions, + DriveAbciBlockStartMethodVersions, DriveAbciCoreBasedUpdatesMethodVersions, + DriveAbciCoreChainLockMethodVersionsAndConstants, DriveAbciCoreInstantSendLockMethodVersions, + DriveAbciEngineMethodVersions, DriveAbciEpochMethodVersions, + DriveAbciFeePoolInwardsDistributionMethodVersions, + DriveAbciFeePoolOutwardsDistributionMethodVersions, + DriveAbciIdentityCreditWithdrawalMethodVersions, DriveAbciInitializationMethodVersions, + DriveAbciMasternodeIdentitiesUpdatesMethodVersions, DriveAbciMethodVersions, + DriveAbciPlatformStateStorageMethodVersions, DriveAbciProtocolUpgradeMethodVersions, + DriveAbciStateTransitionProcessingMethodVersions, DriveAbciVotingMethodVersions, +}; + +pub const DRIVE_ABCI_METHOD_VERSIONS_V1: DriveAbciMethodVersions = DriveAbciMethodVersions { + engine: DriveAbciEngineMethodVersions { + init_chain: 0, + check_tx: 0, + run_block_proposal: 0, + finalize_block_proposal: 0, + consensus_params_update: 0, + }, + initialization: DriveAbciInitializationMethodVersions { + initial_core_height_and_time: 0, + create_genesis_state: 0, + }, + core_based_updates: DriveAbciCoreBasedUpdatesMethodVersions { + update_core_info: 0, + update_masternode_list: 0, + update_quorum_info: 0, + masternode_updates: DriveAbciMasternodeIdentitiesUpdatesMethodVersions { + get_voter_identity_key: 0, + get_operator_identity_keys: 0, + get_owner_identity_withdrawal_key: 0, + get_owner_identity_owner_key: 0, + get_voter_identifier_from_masternode_list_item: 0, + get_operator_identifier_from_masternode_list_item: 0, + create_operator_identity: 0, + create_owner_identity: 0, + create_voter_identity: 0, + disable_identity_keys: 0, + update_masternode_identities: 0, + update_operator_identity: 0, + update_owner_withdrawal_address: 0, + update_voter_identity: 0, + }, + }, + protocol_upgrade: DriveAbciProtocolUpgradeMethodVersions { + check_for_desired_protocol_upgrade: 0, + upgrade_protocol_version_on_epoch_change: 0, + perform_events_on_first_block_of_protocol_change: None, + protocol_version_upgrade_percentage_needed: 75, + }, + block_fee_processing: DriveAbciBlockFeeProcessingMethodVersions { + add_process_epoch_change_operations: 0, + process_block_fees: 0, + }, + core_chain_lock: DriveAbciCoreChainLockMethodVersionsAndConstants { + choose_quorum: 0, + verify_chain_lock: 0, + verify_chain_lock_locally: 0, + verify_chain_lock_through_core: 0, + make_sure_core_is_synced_to_chain_lock: 0, + recent_block_count_amount: 2, + }, + core_instant_send_lock: DriveAbciCoreInstantSendLockMethodVersions { + verify_recent_signature_locally: 0, + }, + fee_pool_inwards_distribution: DriveAbciFeePoolInwardsDistributionMethodVersions { + add_distribute_block_fees_into_pools_operations: 0, + add_distribute_storage_fee_to_epochs_operations: 0, + }, + fee_pool_outwards_distribution: DriveAbciFeePoolOutwardsDistributionMethodVersions { + add_distribute_fees_from_oldest_unpaid_epoch_pool_to_proposers_operations: 0, + add_epoch_pool_to_proposers_payout_operations: 0, + find_oldest_epoch_needing_payment: 0, + fetch_reward_shares_list_for_masternode: 0, + }, + withdrawals: DriveAbciIdentityCreditWithdrawalMethodVersions { + build_untied_withdrawal_transactions_from_documents: 0, + dequeue_and_build_unsigned_withdrawal_transactions: 0, + fetch_transactions_block_inclusion_status: 0, + pool_withdrawals_into_transactions_queue: 0, + update_broadcasted_withdrawal_statuses: 0, + rebroadcast_expired_withdrawal_documents: 0, + append_signatures_and_broadcast_withdrawal_transactions: 0, + cleanup_expired_locks_of_withdrawal_amounts: 0, + }, + voting: DriveAbciVotingMethodVersions { + keep_record_of_finished_contested_resource_vote_poll: 0, + clean_up_after_vote_poll_end: 0, + clean_up_after_contested_resources_vote_poll_end: 0, + check_for_ended_vote_polls: 0, + tally_votes_for_contested_document_resource_vote_poll: 0, + award_document_to_winner: 0, + delay_vote_poll: 0, + run_dao_platform_events: 0, + remove_votes_for_removed_masternodes: 0, + }, + state_transition_processing: DriveAbciStateTransitionProcessingMethodVersions { + execute_event: 0, + process_raw_state_transitions: 0, + decode_raw_state_transitions: 0, + validate_fees_of_event: 0, + }, + epoch: DriveAbciEpochMethodVersions { + gather_epoch_info: 0, + get_genesis_time: 0, + }, + block_start: DriveAbciBlockStartMethodVersions { + clear_drive_block_cache: 0, + }, + block_end: DriveAbciBlockEndMethodVersions { + update_state_cache: 0, + update_drive_cache: 0, + validator_set_update: 0, + }, + platform_state_storage: DriveAbciPlatformStateStorageMethodVersions { + fetch_platform_state: 0, + store_platform_state: 0, + }, +}; diff --git a/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_method_versions/v2.rs b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_method_versions/v2.rs new file mode 100644 index 0000000000..1e355fa6a2 --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_method_versions/v2.rs @@ -0,0 +1,122 @@ +use crate::version::drive_abci_versions::drive_abci_method_versions::{ + DriveAbciBlockEndMethodVersions, DriveAbciBlockFeeProcessingMethodVersions, + DriveAbciBlockStartMethodVersions, DriveAbciCoreBasedUpdatesMethodVersions, + DriveAbciCoreChainLockMethodVersionsAndConstants, DriveAbciCoreInstantSendLockMethodVersions, + DriveAbciEngineMethodVersions, DriveAbciEpochMethodVersions, + DriveAbciFeePoolInwardsDistributionMethodVersions, + DriveAbciFeePoolOutwardsDistributionMethodVersions, + DriveAbciIdentityCreditWithdrawalMethodVersions, DriveAbciInitializationMethodVersions, + DriveAbciMasternodeIdentitiesUpdatesMethodVersions, DriveAbciMethodVersions, + DriveAbciPlatformStateStorageMethodVersions, DriveAbciProtocolUpgradeMethodVersions, + DriveAbciStateTransitionProcessingMethodVersions, DriveAbciVotingMethodVersions, +}; + +pub const DRIVE_ABCI_METHOD_VERSIONS_V2: DriveAbciMethodVersions = DriveAbciMethodVersions { + engine: DriveAbciEngineMethodVersions { + init_chain: 0, + check_tx: 0, + run_block_proposal: 0, + finalize_block_proposal: 0, + // Update app version if changed as well + consensus_params_update: 1, + }, + initialization: DriveAbciInitializationMethodVersions { + initial_core_height_and_time: 0, + create_genesis_state: 0, + }, + core_based_updates: DriveAbciCoreBasedUpdatesMethodVersions { + update_core_info: 0, + update_masternode_list: 0, + update_quorum_info: 0, + masternode_updates: DriveAbciMasternodeIdentitiesUpdatesMethodVersions { + get_voter_identity_key: 0, + get_operator_identity_keys: 0, + get_owner_identity_withdrawal_key: 0, + get_owner_identity_owner_key: 0, + get_voter_identifier_from_masternode_list_item: 0, + get_operator_identifier_from_masternode_list_item: 0, + create_operator_identity: 0, + create_owner_identity: 0, + create_voter_identity: 0, + disable_identity_keys: 0, + update_masternode_identities: 0, + update_operator_identity: 0, + update_owner_withdrawal_address: 0, + update_voter_identity: 0, + }, + }, + protocol_upgrade: DriveAbciProtocolUpgradeMethodVersions { + check_for_desired_protocol_upgrade: 1, + upgrade_protocol_version_on_epoch_change: 0, + perform_events_on_first_block_of_protocol_change: None, + protocol_version_upgrade_percentage_needed: 67, + }, + block_fee_processing: DriveAbciBlockFeeProcessingMethodVersions { + add_process_epoch_change_operations: 0, + process_block_fees: 0, + }, + core_chain_lock: DriveAbciCoreChainLockMethodVersionsAndConstants { + choose_quorum: 0, + verify_chain_lock: 0, + verify_chain_lock_locally: 0, + verify_chain_lock_through_core: 0, + make_sure_core_is_synced_to_chain_lock: 0, + recent_block_count_amount: 2, + }, + core_instant_send_lock: DriveAbciCoreInstantSendLockMethodVersions { + verify_recent_signature_locally: 0, + }, + fee_pool_inwards_distribution: DriveAbciFeePoolInwardsDistributionMethodVersions { + add_distribute_block_fees_into_pools_operations: 0, + add_distribute_storage_fee_to_epochs_operations: 0, + }, + fee_pool_outwards_distribution: DriveAbciFeePoolOutwardsDistributionMethodVersions { + add_distribute_fees_from_oldest_unpaid_epoch_pool_to_proposers_operations: 0, + add_epoch_pool_to_proposers_payout_operations: 0, + find_oldest_epoch_needing_payment: 0, + fetch_reward_shares_list_for_masternode: 0, + }, + withdrawals: DriveAbciIdentityCreditWithdrawalMethodVersions { + build_untied_withdrawal_transactions_from_documents: 0, + dequeue_and_build_unsigned_withdrawal_transactions: 0, + fetch_transactions_block_inclusion_status: 0, + pool_withdrawals_into_transactions_queue: 0, + update_broadcasted_withdrawal_statuses: 0, + rebroadcast_expired_withdrawal_documents: 0, + append_signatures_and_broadcast_withdrawal_transactions: 0, + cleanup_expired_locks_of_withdrawal_amounts: 0, + }, + voting: DriveAbciVotingMethodVersions { + keep_record_of_finished_contested_resource_vote_poll: 0, + clean_up_after_vote_poll_end: 0, + clean_up_after_contested_resources_vote_poll_end: 0, + check_for_ended_vote_polls: 0, + tally_votes_for_contested_document_resource_vote_poll: 0, + award_document_to_winner: 0, + delay_vote_poll: 0, + run_dao_platform_events: 0, + remove_votes_for_removed_masternodes: 0, + }, + state_transition_processing: DriveAbciStateTransitionProcessingMethodVersions { + execute_event: 0, + process_raw_state_transitions: 0, + decode_raw_state_transitions: 0, + validate_fees_of_event: 0, + }, + epoch: DriveAbciEpochMethodVersions { + gather_epoch_info: 0, + get_genesis_time: 0, + }, + block_start: DriveAbciBlockStartMethodVersions { + clear_drive_block_cache: 0, + }, + block_end: DriveAbciBlockEndMethodVersions { + update_state_cache: 0, + update_drive_cache: 0, + validator_set_update: 0, + }, + platform_state_storage: DriveAbciPlatformStateStorageMethodVersions { + fetch_platform_state: 0, + store_platform_state: 0, + }, +}; diff --git a/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_method_versions/v3.rs b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_method_versions/v3.rs new file mode 100644 index 0000000000..2b48e7a034 --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_method_versions/v3.rs @@ -0,0 +1,121 @@ +use crate::version::drive_abci_versions::drive_abci_method_versions::{ + DriveAbciBlockEndMethodVersions, DriveAbciBlockFeeProcessingMethodVersions, + DriveAbciBlockStartMethodVersions, DriveAbciCoreBasedUpdatesMethodVersions, + DriveAbciCoreChainLockMethodVersionsAndConstants, DriveAbciCoreInstantSendLockMethodVersions, + DriveAbciEngineMethodVersions, DriveAbciEpochMethodVersions, + DriveAbciFeePoolInwardsDistributionMethodVersions, + DriveAbciFeePoolOutwardsDistributionMethodVersions, + DriveAbciIdentityCreditWithdrawalMethodVersions, DriveAbciInitializationMethodVersions, + DriveAbciMasternodeIdentitiesUpdatesMethodVersions, DriveAbciMethodVersions, + DriveAbciPlatformStateStorageMethodVersions, DriveAbciProtocolUpgradeMethodVersions, + DriveAbciStateTransitionProcessingMethodVersions, DriveAbciVotingMethodVersions, +}; + +pub const DRIVE_ABCI_METHOD_VERSIONS_V3: DriveAbciMethodVersions = DriveAbciMethodVersions { + engine: DriveAbciEngineMethodVersions { + init_chain: 0, + check_tx: 0, + run_block_proposal: 0, + finalize_block_proposal: 0, + consensus_params_update: 1, + }, + initialization: DriveAbciInitializationMethodVersions { + initial_core_height_and_time: 0, + create_genesis_state: 0, + }, + core_based_updates: DriveAbciCoreBasedUpdatesMethodVersions { + update_core_info: 0, + update_masternode_list: 0, + update_quorum_info: 0, + masternode_updates: DriveAbciMasternodeIdentitiesUpdatesMethodVersions { + get_voter_identity_key: 0, + get_operator_identity_keys: 0, + get_owner_identity_withdrawal_key: 0, + get_owner_identity_owner_key: 0, + get_voter_identifier_from_masternode_list_item: 0, + get_operator_identifier_from_masternode_list_item: 0, + create_operator_identity: 0, + create_owner_identity: 1, + create_voter_identity: 0, + disable_identity_keys: 0, + update_masternode_identities: 0, + update_operator_identity: 0, + update_owner_withdrawal_address: 1, + update_voter_identity: 0, + }, + }, + protocol_upgrade: DriveAbciProtocolUpgradeMethodVersions { + check_for_desired_protocol_upgrade: 1, + upgrade_protocol_version_on_epoch_change: 0, + perform_events_on_first_block_of_protocol_change: Some(0), + protocol_version_upgrade_percentage_needed: 67, + }, + block_fee_processing: DriveAbciBlockFeeProcessingMethodVersions { + add_process_epoch_change_operations: 0, + process_block_fees: 0, + }, + core_chain_lock: DriveAbciCoreChainLockMethodVersionsAndConstants { + choose_quorum: 0, + verify_chain_lock: 0, + verify_chain_lock_locally: 0, + verify_chain_lock_through_core: 0, + make_sure_core_is_synced_to_chain_lock: 0, + recent_block_count_amount: 2, + }, + core_instant_send_lock: DriveAbciCoreInstantSendLockMethodVersions { + verify_recent_signature_locally: 0, + }, + fee_pool_inwards_distribution: DriveAbciFeePoolInwardsDistributionMethodVersions { + add_distribute_block_fees_into_pools_operations: 0, + add_distribute_storage_fee_to_epochs_operations: 0, + }, + fee_pool_outwards_distribution: DriveAbciFeePoolOutwardsDistributionMethodVersions { + add_distribute_fees_from_oldest_unpaid_epoch_pool_to_proposers_operations: 0, + add_epoch_pool_to_proposers_payout_operations: 0, + find_oldest_epoch_needing_payment: 0, + fetch_reward_shares_list_for_masternode: 0, + }, + withdrawals: DriveAbciIdentityCreditWithdrawalMethodVersions { + build_untied_withdrawal_transactions_from_documents: 0, + dequeue_and_build_unsigned_withdrawal_transactions: 0, + fetch_transactions_block_inclusion_status: 0, + pool_withdrawals_into_transactions_queue: 0, + update_broadcasted_withdrawal_statuses: 0, + rebroadcast_expired_withdrawal_documents: 0, + append_signatures_and_broadcast_withdrawal_transactions: 0, + cleanup_expired_locks_of_withdrawal_amounts: 0, + }, + voting: DriveAbciVotingMethodVersions { + keep_record_of_finished_contested_resource_vote_poll: 0, + clean_up_after_vote_poll_end: 0, + clean_up_after_contested_resources_vote_poll_end: 0, + check_for_ended_vote_polls: 0, + tally_votes_for_contested_document_resource_vote_poll: 0, + award_document_to_winner: 0, + delay_vote_poll: 0, + run_dao_platform_events: 0, + remove_votes_for_removed_masternodes: 0, + }, + state_transition_processing: DriveAbciStateTransitionProcessingMethodVersions { + execute_event: 0, + process_raw_state_transitions: 0, + decode_raw_state_transitions: 0, + validate_fees_of_event: 0, + }, + epoch: DriveAbciEpochMethodVersions { + gather_epoch_info: 0, + get_genesis_time: 0, + }, + block_start: DriveAbciBlockStartMethodVersions { + clear_drive_block_cache: 0, + }, + block_end: DriveAbciBlockEndMethodVersions { + update_state_cache: 0, + update_drive_cache: 0, + validator_set_update: 1, + }, + platform_state_storage: DriveAbciPlatformStateStorageMethodVersions { + fetch_platform_state: 0, + store_platform_state: 0, + }, +}; diff --git a/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_method_versions/v4.rs b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_method_versions/v4.rs new file mode 100644 index 0000000000..bedfb591c3 --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_method_versions/v4.rs @@ -0,0 +1,121 @@ +use crate::version::drive_abci_versions::drive_abci_method_versions::{ + DriveAbciBlockEndMethodVersions, DriveAbciBlockFeeProcessingMethodVersions, + DriveAbciBlockStartMethodVersions, DriveAbciCoreBasedUpdatesMethodVersions, + DriveAbciCoreChainLockMethodVersionsAndConstants, DriveAbciCoreInstantSendLockMethodVersions, + DriveAbciEngineMethodVersions, DriveAbciEpochMethodVersions, + DriveAbciFeePoolInwardsDistributionMethodVersions, + DriveAbciFeePoolOutwardsDistributionMethodVersions, + DriveAbciIdentityCreditWithdrawalMethodVersions, DriveAbciInitializationMethodVersions, + DriveAbciMasternodeIdentitiesUpdatesMethodVersions, DriveAbciMethodVersions, + DriveAbciPlatformStateStorageMethodVersions, DriveAbciProtocolUpgradeMethodVersions, + DriveAbciStateTransitionProcessingMethodVersions, DriveAbciVotingMethodVersions, +}; + +pub const DRIVE_ABCI_METHOD_VERSIONS_V4: DriveAbciMethodVersions = DriveAbciMethodVersions { + engine: DriveAbciEngineMethodVersions { + init_chain: 0, + check_tx: 0, + run_block_proposal: 0, + finalize_block_proposal: 0, + consensus_params_update: 1, + }, + initialization: DriveAbciInitializationMethodVersions { + initial_core_height_and_time: 0, + create_genesis_state: 0, + }, + core_based_updates: DriveAbciCoreBasedUpdatesMethodVersions { + update_core_info: 0, + update_masternode_list: 0, + update_quorum_info: 0, + masternode_updates: DriveAbciMasternodeIdentitiesUpdatesMethodVersions { + get_voter_identity_key: 0, + get_operator_identity_keys: 0, + get_owner_identity_withdrawal_key: 0, + get_owner_identity_owner_key: 0, + get_voter_identifier_from_masternode_list_item: 0, + get_operator_identifier_from_masternode_list_item: 0, + create_operator_identity: 0, + create_owner_identity: 1, + create_voter_identity: 0, + disable_identity_keys: 0, + update_masternode_identities: 0, + update_operator_identity: 0, + update_owner_withdrawal_address: 1, + update_voter_identity: 0, + }, + }, + protocol_upgrade: DriveAbciProtocolUpgradeMethodVersions { + check_for_desired_protocol_upgrade: 1, + upgrade_protocol_version_on_epoch_change: 0, + perform_events_on_first_block_of_protocol_change: Some(0), + protocol_version_upgrade_percentage_needed: 67, + }, + block_fee_processing: DriveAbciBlockFeeProcessingMethodVersions { + add_process_epoch_change_operations: 0, + process_block_fees: 0, + }, + core_chain_lock: DriveAbciCoreChainLockMethodVersionsAndConstants { + choose_quorum: 0, + verify_chain_lock: 0, + verify_chain_lock_locally: 0, + verify_chain_lock_through_core: 0, + make_sure_core_is_synced_to_chain_lock: 0, + recent_block_count_amount: 2, + }, + core_instant_send_lock: DriveAbciCoreInstantSendLockMethodVersions { + verify_recent_signature_locally: 0, + }, + fee_pool_inwards_distribution: DriveAbciFeePoolInwardsDistributionMethodVersions { + add_distribute_block_fees_into_pools_operations: 0, + add_distribute_storage_fee_to_epochs_operations: 0, + }, + fee_pool_outwards_distribution: DriveAbciFeePoolOutwardsDistributionMethodVersions { + add_distribute_fees_from_oldest_unpaid_epoch_pool_to_proposers_operations: 0, + add_epoch_pool_to_proposers_payout_operations: 0, + find_oldest_epoch_needing_payment: 0, + fetch_reward_shares_list_for_masternode: 0, + }, + withdrawals: DriveAbciIdentityCreditWithdrawalMethodVersions { + build_untied_withdrawal_transactions_from_documents: 0, + dequeue_and_build_unsigned_withdrawal_transactions: 0, + fetch_transactions_block_inclusion_status: 0, + pool_withdrawals_into_transactions_queue: 0, + update_broadcasted_withdrawal_statuses: 0, + rebroadcast_expired_withdrawal_documents: 0, + append_signatures_and_broadcast_withdrawal_transactions: 0, + cleanup_expired_locks_of_withdrawal_amounts: 0, + }, + voting: DriveAbciVotingMethodVersions { + keep_record_of_finished_contested_resource_vote_poll: 0, + clean_up_after_vote_poll_end: 0, + clean_up_after_contested_resources_vote_poll_end: 0, + check_for_ended_vote_polls: 0, + tally_votes_for_contested_document_resource_vote_poll: 0, + award_document_to_winner: 0, + delay_vote_poll: 0, + run_dao_platform_events: 0, + remove_votes_for_removed_masternodes: 0, + }, + state_transition_processing: DriveAbciStateTransitionProcessingMethodVersions { + execute_event: 0, + process_raw_state_transitions: 0, + decode_raw_state_transitions: 0, + validate_fees_of_event: 0, + }, + epoch: DriveAbciEpochMethodVersions { + gather_epoch_info: 0, + get_genesis_time: 0, + }, + block_start: DriveAbciBlockStartMethodVersions { + clear_drive_block_cache: 0, + }, + block_end: DriveAbciBlockEndMethodVersions { + update_state_cache: 0, + update_drive_cache: 0, + validator_set_update: 2, + }, + platform_state_storage: DriveAbciPlatformStateStorageMethodVersions { + fetch_platform_state: 0, + store_platform_state: 0, + }, +}; diff --git a/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_query_versions/mod.rs b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_query_versions/mod.rs new file mode 100644 index 0000000000..8b010c9c3d --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_query_versions/mod.rs @@ -0,0 +1,68 @@ +pub mod v1; + +use versioned_feature_core::{FeatureVersion, FeatureVersionBounds}; + +#[derive(Clone, Debug, Default)] +pub struct DriveAbciQueryVersions { + pub max_returned_elements: u16, + pub response_metadata: FeatureVersion, + pub proofs_query: FeatureVersionBounds, + pub document_query: FeatureVersionBounds, + pub prefunded_specialized_balances: DriveAbciQueryPrefundedSpecializedBalancesVersions, + pub identity_based_queries: DriveAbciQueryIdentityVersions, + pub validator_queries: DriveAbciQueryValidatorVersions, + pub data_contract_based_queries: DriveAbciQueryDataContractVersions, + pub voting_based_queries: DriveAbciQueryVotingVersions, + pub system: DriveAbciQuerySystemVersions, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveAbciQueryPrefundedSpecializedBalancesVersions { + pub balance: FeatureVersionBounds, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveAbciQueryIdentityVersions { + pub identity: FeatureVersionBounds, + pub identities_contract_keys: FeatureVersionBounds, + pub keys: FeatureVersionBounds, + pub identity_nonce: FeatureVersionBounds, + pub identity_contract_nonce: FeatureVersionBounds, + pub balance: FeatureVersionBounds, + pub identities_balances: FeatureVersionBounds, + pub balance_and_revision: FeatureVersionBounds, + pub identity_by_public_key_hash: FeatureVersionBounds, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveAbciQueryValidatorVersions { + pub proposed_block_counts_by_evonode_ids: FeatureVersionBounds, + pub proposed_block_counts_by_range: FeatureVersionBounds, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveAbciQueryVotingVersions { + pub vote_polls_by_end_date_query: FeatureVersionBounds, + pub contested_resource_vote_state: FeatureVersionBounds, + pub contested_resource_voters_for_identity: FeatureVersionBounds, + pub contested_resource_identity_vote_status: FeatureVersionBounds, + pub contested_resources: FeatureVersionBounds, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveAbciQueryDataContractVersions { + pub data_contract: FeatureVersionBounds, + pub data_contract_history: FeatureVersionBounds, + pub data_contracts: FeatureVersionBounds, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveAbciQuerySystemVersions { + pub version_upgrade_state: FeatureVersionBounds, + pub version_upgrade_vote_status: FeatureVersionBounds, + pub epoch_infos: FeatureVersionBounds, + pub current_quorums_info: FeatureVersionBounds, + pub partial_status: FeatureVersionBounds, + pub path_elements: FeatureVersionBounds, + pub total_credits_in_platform: FeatureVersionBounds, +} diff --git a/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_query_versions/v1.rs b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_query_versions/v1.rs new file mode 100644 index 0000000000..b6af08405c --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_query_versions/v1.rs @@ -0,0 +1,168 @@ +use crate::version::drive_abci_versions::drive_abci_query_versions::{ + DriveAbciQueryDataContractVersions, DriveAbciQueryIdentityVersions, + DriveAbciQueryPrefundedSpecializedBalancesVersions, DriveAbciQuerySystemVersions, + DriveAbciQueryValidatorVersions, DriveAbciQueryVersions, DriveAbciQueryVotingVersions, +}; +use versioned_feature_core::FeatureVersionBounds; + +pub const DRIVE_ABCI_QUERY_VERSIONS_V1: DriveAbciQueryVersions = DriveAbciQueryVersions { + max_returned_elements: 100, + response_metadata: 0, + proofs_query: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + document_query: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + prefunded_specialized_balances: DriveAbciQueryPrefundedSpecializedBalancesVersions { + balance: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + }, + identity_based_queries: DriveAbciQueryIdentityVersions { + identity: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + keys: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + identities_contract_keys: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + identity_nonce: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + identity_contract_nonce: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + balance: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + identities_balances: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + balance_and_revision: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + identity_by_public_key_hash: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + }, + validator_queries: DriveAbciQueryValidatorVersions { + proposed_block_counts_by_evonode_ids: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + proposed_block_counts_by_range: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + }, + data_contract_based_queries: DriveAbciQueryDataContractVersions { + data_contract: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + data_contract_history: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + data_contracts: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + }, + voting_based_queries: DriveAbciQueryVotingVersions { + vote_polls_by_end_date_query: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + contested_resource_vote_state: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + contested_resource_voters_for_identity: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + contested_resource_identity_vote_status: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + contested_resources: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + }, + system: DriveAbciQuerySystemVersions { + version_upgrade_state: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + version_upgrade_vote_status: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + epoch_infos: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + current_quorums_info: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + partial_status: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + path_elements: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + total_credits_in_platform: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + }, +}; diff --git a/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_structure_versions/mod.rs b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_structure_versions/mod.rs new file mode 100644 index 0000000000..d00c9187ae --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_structure_versions/mod.rs @@ -0,0 +1,13 @@ +pub mod v1; + +use versioned_feature_core::FeatureVersion; + +#[derive(Clone, Debug, Default)] +pub struct DriveAbciStructureVersions { + pub platform_state_structure: FeatureVersion, + pub platform_state_for_saving_structure_default: FeatureVersion, + pub state_transition_execution_context: FeatureVersion, + pub commit: FeatureVersion, + pub masternode: FeatureVersion, + pub signature_verification_quorum_set: FeatureVersion, +} diff --git a/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_structure_versions/v1.rs b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_structure_versions/v1.rs new file mode 100644 index 0000000000..b8e6725281 --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_structure_versions/v1.rs @@ -0,0 +1,11 @@ +use crate::version::drive_abci_versions::drive_abci_structure_versions::DriveAbciStructureVersions; + +pub const DRIVE_ABCI_STRUCTURE_VERSIONS_V1: DriveAbciStructureVersions = + DriveAbciStructureVersions { + platform_state_structure: 0, + platform_state_for_saving_structure_default: 0, + state_transition_execution_context: 0, + commit: 0, + masternode: 0, + signature_verification_quorum_set: 0, + }; diff --git a/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_validation_versions/mod.rs b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_validation_versions/mod.rs new file mode 100644 index 0000000000..c2044bb829 --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_validation_versions/mod.rs @@ -0,0 +1,115 @@ +pub mod v1; +pub mod v2; +pub mod v3; + +use versioned_feature_core::{FeatureVersion, OptionalFeatureVersion}; + +#[derive(Clone, Debug, Default)] +pub struct DriveAbciValidationVersions { + pub state_transitions: DriveAbciStateTransitionValidationVersions, + pub process_state_transition: FeatureVersion, + pub state_transition_to_execution_event_for_check_tx: FeatureVersion, + pub penalties: PenaltyAmounts, + pub event_constants: DriveAbciValidationConstants, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveAbciValidationConstants { + pub maximum_vote_polls_to_process: u16, + pub maximum_contenders_to_consider: u16, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveAbciStateTransitionValidationVersion { + pub basic_structure: OptionalFeatureVersion, + pub advanced_structure: OptionalFeatureVersion, + pub identity_signatures: OptionalFeatureVersion, + pub advanced_minimum_balance_pre_check: OptionalFeatureVersion, + pub nonce: OptionalFeatureVersion, + pub state: FeatureVersion, + pub transform_into_action: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveAbciStateTransitionValidationVersions { + pub common_validation_methods: DriveAbciStateTransitionCommonValidationVersions, + pub max_asset_lock_usage_attempts: u16, + pub identity_create_state_transition: DriveAbciStateTransitionValidationVersion, + pub identity_update_state_transition: DriveAbciStateTransitionValidationVersion, + pub identity_top_up_state_transition: DriveAbciStateTransitionValidationVersion, + pub identity_credit_withdrawal_state_transition: DriveAbciStateTransitionValidationVersion, + pub identity_credit_withdrawal_state_transition_purpose_matches_requirements: FeatureVersion, + pub identity_credit_transfer_state_transition: DriveAbciStateTransitionValidationVersion, + pub masternode_vote_state_transition: DriveAbciStateTransitionValidationVersion, + pub contract_create_state_transition: DriveAbciStateTransitionValidationVersion, + pub contract_update_state_transition: DriveAbciStateTransitionValidationVersion, + pub documents_batch_state_transition: DriveAbciDocumentsStateTransitionValidationVersions, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveAbciStateTransitionCommonValidationVersions { + pub asset_locks: DriveAbciAssetLockValidationVersions, + pub validate_identity_public_key_contract_bounds: FeatureVersion, + pub validate_identity_public_key_ids_dont_exist_in_state: FeatureVersion, + pub validate_identity_public_key_ids_exist_in_state: FeatureVersion, + pub validate_state_transition_identity_signed: FeatureVersion, + pub validate_unique_identity_public_key_hashes_in_state: FeatureVersion, + pub validate_master_key_uniqueness: FeatureVersion, + pub validate_simple_pre_check_balance: FeatureVersion, +} + +/// All of these penalty amounts are in credits +#[derive(Clone, Debug, Default)] +pub struct PenaltyAmounts { + pub identity_id_not_correct: u64, + pub unique_key_already_present: u64, + pub validation_of_added_keys_structure_failure: u64, + pub validation_of_added_keys_proof_of_possession_failure: u64, +} + +#[derive(Clone, Copy, Debug, Default)] +pub struct DriveAbciAssetLockValidationVersions { + pub fetch_asset_lock_transaction_output_sync: FeatureVersion, + pub verify_asset_lock_is_not_spent_and_has_enough_balance: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveAbciDocumentsStateTransitionValidationVersions { + pub balance_pre_check: FeatureVersion, + pub basic_structure: FeatureVersion, + pub advanced_structure: FeatureVersion, + pub revision: FeatureVersion, + pub state: FeatureVersion, + pub transform_into_action: FeatureVersion, + pub data_triggers: DriveAbciValidationDataTriggerAndBindingVersions, + pub is_allowed: FeatureVersion, + pub document_create_transition_structure_validation: FeatureVersion, + pub document_delete_transition_structure_validation: FeatureVersion, + pub document_replace_transition_structure_validation: FeatureVersion, + pub document_transfer_transition_structure_validation: FeatureVersion, + pub document_purchase_transition_structure_validation: FeatureVersion, + pub document_update_price_transition_structure_validation: FeatureVersion, + pub document_create_transition_state_validation: FeatureVersion, + pub document_delete_transition_state_validation: FeatureVersion, + pub document_replace_transition_state_validation: FeatureVersion, + pub document_transfer_transition_state_validation: FeatureVersion, + pub document_purchase_transition_state_validation: FeatureVersion, + pub document_update_price_transition_state_validation: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveAbciValidationDataTriggerAndBindingVersions { + pub bindings: FeatureVersion, + pub triggers: DriveAbciValidationDataTriggerVersions, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveAbciValidationDataTriggerVersions { + pub create_contact_request_data_trigger: FeatureVersion, + pub create_domain_data_trigger: FeatureVersion, + pub create_identity_data_trigger: FeatureVersion, + pub create_feature_flag_data_trigger: FeatureVersion, + pub create_masternode_reward_shares_data_trigger: FeatureVersion, + pub delete_withdrawal_data_trigger: FeatureVersion, + pub reject_data_trigger: FeatureVersion, +} diff --git a/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_validation_versions/v1.rs b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_validation_versions/v1.rs new file mode 100644 index 0000000000..a617c54afb --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_validation_versions/v1.rs @@ -0,0 +1,146 @@ +use crate::version::drive_abci_versions::drive_abci_validation_versions::{ + DriveAbciAssetLockValidationVersions, DriveAbciDocumentsStateTransitionValidationVersions, + DriveAbciStateTransitionCommonValidationVersions, DriveAbciStateTransitionValidationVersion, + DriveAbciStateTransitionValidationVersions, DriveAbciValidationConstants, + DriveAbciValidationDataTriggerAndBindingVersions, DriveAbciValidationDataTriggerVersions, + DriveAbciValidationVersions, PenaltyAmounts, +}; + +pub const DRIVE_ABCI_VALIDATION_VERSIONS_V1: DriveAbciValidationVersions = + DriveAbciValidationVersions { + state_transitions: DriveAbciStateTransitionValidationVersions { + common_validation_methods: DriveAbciStateTransitionCommonValidationVersions { + asset_locks: DriveAbciAssetLockValidationVersions { + fetch_asset_lock_transaction_output_sync: 0, + verify_asset_lock_is_not_spent_and_has_enough_balance: 0, + }, + validate_identity_public_key_contract_bounds: 0, + validate_identity_public_key_ids_dont_exist_in_state: 0, + validate_identity_public_key_ids_exist_in_state: 0, + validate_state_transition_identity_signed: 0, + validate_unique_identity_public_key_hashes_in_state: 0, + validate_master_key_uniqueness: 0, + validate_simple_pre_check_balance: 0, + }, + max_asset_lock_usage_attempts: 16, + identity_create_state_transition: DriveAbciStateTransitionValidationVersion { + basic_structure: Some(0), + advanced_structure: Some(0), + identity_signatures: Some(0), + advanced_minimum_balance_pre_check: None, + nonce: None, + state: 0, + transform_into_action: 0, + }, + identity_update_state_transition: DriveAbciStateTransitionValidationVersion { + basic_structure: Some(0), + advanced_structure: Some(0), + identity_signatures: Some(0), + advanced_minimum_balance_pre_check: None, + nonce: Some(0), + state: 0, + transform_into_action: 0, + }, + identity_top_up_state_transition: DriveAbciStateTransitionValidationVersion { + basic_structure: Some(0), + advanced_structure: None, + identity_signatures: None, + advanced_minimum_balance_pre_check: None, + nonce: None, + state: 0, + transform_into_action: 0, + }, + identity_credit_withdrawal_state_transition: + DriveAbciStateTransitionValidationVersion { + basic_structure: Some(0), + advanced_structure: None, + identity_signatures: None, + advanced_minimum_balance_pre_check: Some(0), + nonce: Some(0), + state: 0, + transform_into_action: 0, + }, + identity_credit_withdrawal_state_transition_purpose_matches_requirements: 0, + identity_credit_transfer_state_transition: DriveAbciStateTransitionValidationVersion { + basic_structure: Some(0), + advanced_structure: None, + identity_signatures: None, + advanced_minimum_balance_pre_check: Some(0), + nonce: Some(0), + state: 0, + transform_into_action: 0, + }, + masternode_vote_state_transition: DriveAbciStateTransitionValidationVersion { + basic_structure: None, + advanced_structure: Some(0), + identity_signatures: None, + advanced_minimum_balance_pre_check: Some(0), + nonce: Some(0), + state: 0, + transform_into_action: 0, + }, + contract_create_state_transition: DriveAbciStateTransitionValidationVersion { + basic_structure: Some(0), + advanced_structure: None, + identity_signatures: None, + advanced_minimum_balance_pre_check: None, + nonce: Some(0), + state: 0, + transform_into_action: 0, + }, + contract_update_state_transition: DriveAbciStateTransitionValidationVersion { + basic_structure: None, + advanced_structure: None, + identity_signatures: None, + advanced_minimum_balance_pre_check: None, + nonce: Some(0), + state: 0, + transform_into_action: 0, + }, + documents_batch_state_transition: DriveAbciDocumentsStateTransitionValidationVersions { + balance_pre_check: 0, + basic_structure: 0, + advanced_structure: 0, + state: 0, + revision: 0, + transform_into_action: 0, + data_triggers: DriveAbciValidationDataTriggerAndBindingVersions { + bindings: 0, + triggers: DriveAbciValidationDataTriggerVersions { + create_contact_request_data_trigger: 0, + create_domain_data_trigger: 0, + create_identity_data_trigger: 0, + create_feature_flag_data_trigger: 0, + create_masternode_reward_shares_data_trigger: 0, + delete_withdrawal_data_trigger: 0, + reject_data_trigger: 0, + }, + }, + is_allowed: 0, + document_create_transition_structure_validation: 0, + document_delete_transition_structure_validation: 0, + document_replace_transition_structure_validation: 0, + document_transfer_transition_structure_validation: 0, + document_purchase_transition_structure_validation: 0, + document_update_price_transition_structure_validation: 0, + document_create_transition_state_validation: 0, + document_delete_transition_state_validation: 0, + document_replace_transition_state_validation: 0, + document_transfer_transition_state_validation: 0, + document_purchase_transition_state_validation: 0, + document_update_price_transition_state_validation: 0, + }, + }, + process_state_transition: 0, + state_transition_to_execution_event_for_check_tx: 0, + penalties: PenaltyAmounts { + identity_id_not_correct: 50000000, + unique_key_already_present: 10000000, + validation_of_added_keys_structure_failure: 10000000, + validation_of_added_keys_proof_of_possession_failure: 50000000, + }, + event_constants: DriveAbciValidationConstants { + maximum_vote_polls_to_process: 2, + maximum_contenders_to_consider: 100, + }, + }; diff --git a/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_validation_versions/v2.rs b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_validation_versions/v2.rs new file mode 100644 index 0000000000..577fc0c74b --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_validation_versions/v2.rs @@ -0,0 +1,146 @@ +use crate::version::drive_abci_versions::drive_abci_validation_versions::{ + DriveAbciAssetLockValidationVersions, DriveAbciDocumentsStateTransitionValidationVersions, + DriveAbciStateTransitionCommonValidationVersions, DriveAbciStateTransitionValidationVersion, + DriveAbciStateTransitionValidationVersions, DriveAbciValidationConstants, + DriveAbciValidationDataTriggerAndBindingVersions, DriveAbciValidationDataTriggerVersions, + DriveAbciValidationVersions, PenaltyAmounts, +}; + +pub const DRIVE_ABCI_VALIDATION_VERSIONS_V2: DriveAbciValidationVersions = + DriveAbciValidationVersions { + state_transitions: DriveAbciStateTransitionValidationVersions { + common_validation_methods: DriveAbciStateTransitionCommonValidationVersions { + asset_locks: DriveAbciAssetLockValidationVersions { + fetch_asset_lock_transaction_output_sync: 0, + verify_asset_lock_is_not_spent_and_has_enough_balance: 0, + }, + validate_identity_public_key_contract_bounds: 0, + validate_identity_public_key_ids_dont_exist_in_state: 0, + validate_identity_public_key_ids_exist_in_state: 0, + validate_state_transition_identity_signed: 0, + validate_unique_identity_public_key_hashes_in_state: 0, + validate_master_key_uniqueness: 0, + validate_simple_pre_check_balance: 0, + }, + max_asset_lock_usage_attempts: 16, + identity_create_state_transition: DriveAbciStateTransitionValidationVersion { + basic_structure: Some(0), + advanced_structure: Some(0), + identity_signatures: Some(0), + advanced_minimum_balance_pre_check: None, + nonce: None, + state: 0, + transform_into_action: 0, + }, + identity_update_state_transition: DriveAbciStateTransitionValidationVersion { + basic_structure: Some(0), + advanced_structure: Some(0), + identity_signatures: Some(0), + advanced_minimum_balance_pre_check: None, + nonce: Some(0), + state: 0, + transform_into_action: 0, + }, + identity_top_up_state_transition: DriveAbciStateTransitionValidationVersion { + basic_structure: Some(0), + advanced_structure: None, + identity_signatures: None, + advanced_minimum_balance_pre_check: None, + nonce: None, + state: 0, + transform_into_action: 0, + }, + identity_credit_withdrawal_state_transition: + DriveAbciStateTransitionValidationVersion { + basic_structure: Some(0), + advanced_structure: None, + identity_signatures: None, + advanced_minimum_balance_pre_check: Some(0), + nonce: Some(0), + state: 0, + transform_into_action: 0, + }, + identity_credit_withdrawal_state_transition_purpose_matches_requirements: 0, + identity_credit_transfer_state_transition: DriveAbciStateTransitionValidationVersion { + basic_structure: Some(0), + advanced_structure: None, + identity_signatures: None, + advanced_minimum_balance_pre_check: Some(0), + nonce: Some(0), + state: 0, + transform_into_action: 0, + }, + masternode_vote_state_transition: DriveAbciStateTransitionValidationVersion { + basic_structure: None, + advanced_structure: Some(0), + identity_signatures: None, + advanced_minimum_balance_pre_check: Some(0), + nonce: Some(0), + state: 0, + transform_into_action: 0, + }, + contract_create_state_transition: DriveAbciStateTransitionValidationVersion { + basic_structure: Some(0), + advanced_structure: None, + identity_signatures: None, + advanced_minimum_balance_pre_check: None, + nonce: Some(0), + state: 0, + transform_into_action: 0, + }, + contract_update_state_transition: DriveAbciStateTransitionValidationVersion { + basic_structure: None, + advanced_structure: None, + identity_signatures: None, + advanced_minimum_balance_pre_check: None, + nonce: Some(0), + state: 0, + transform_into_action: 0, + }, + documents_batch_state_transition: DriveAbciDocumentsStateTransitionValidationVersions { + balance_pre_check: 0, + basic_structure: 0, + advanced_structure: 0, + state: 0, + revision: 0, + transform_into_action: 0, + data_triggers: DriveAbciValidationDataTriggerAndBindingVersions { + bindings: 0, + triggers: DriveAbciValidationDataTriggerVersions { + create_contact_request_data_trigger: 0, + create_domain_data_trigger: 0, + create_identity_data_trigger: 0, + create_feature_flag_data_trigger: 0, + create_masternode_reward_shares_data_trigger: 0, + delete_withdrawal_data_trigger: 0, + reject_data_trigger: 0, + }, + }, + is_allowed: 0, + document_create_transition_structure_validation: 0, + document_delete_transition_structure_validation: 0, + document_replace_transition_structure_validation: 0, + document_transfer_transition_structure_validation: 0, + document_purchase_transition_structure_validation: 0, + document_update_price_transition_structure_validation: 0, + document_create_transition_state_validation: 1, + document_delete_transition_state_validation: 0, + document_replace_transition_state_validation: 0, + document_transfer_transition_state_validation: 0, + document_purchase_transition_state_validation: 0, + document_update_price_transition_state_validation: 0, + }, + }, + process_state_transition: 0, + state_transition_to_execution_event_for_check_tx: 0, + penalties: PenaltyAmounts { + identity_id_not_correct: 50000000, + unique_key_already_present: 10000000, + validation_of_added_keys_structure_failure: 10000000, + validation_of_added_keys_proof_of_possession_failure: 50000000, + }, + event_constants: DriveAbciValidationConstants { + maximum_vote_polls_to_process: 2, + maximum_contenders_to_consider: 100, + }, + }; diff --git a/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_validation_versions/v3.rs b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_validation_versions/v3.rs new file mode 100644 index 0000000000..76197377e6 --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_validation_versions/v3.rs @@ -0,0 +1,146 @@ +use crate::version::drive_abci_versions::drive_abci_validation_versions::{ + DriveAbciAssetLockValidationVersions, DriveAbciDocumentsStateTransitionValidationVersions, + DriveAbciStateTransitionCommonValidationVersions, DriveAbciStateTransitionValidationVersion, + DriveAbciStateTransitionValidationVersions, DriveAbciValidationConstants, + DriveAbciValidationDataTriggerAndBindingVersions, DriveAbciValidationDataTriggerVersions, + DriveAbciValidationVersions, PenaltyAmounts, +}; + +pub const DRIVE_ABCI_VALIDATION_VERSIONS_V3: DriveAbciValidationVersions = + DriveAbciValidationVersions { + state_transitions: DriveAbciStateTransitionValidationVersions { + common_validation_methods: DriveAbciStateTransitionCommonValidationVersions { + asset_locks: DriveAbciAssetLockValidationVersions { + fetch_asset_lock_transaction_output_sync: 0, + verify_asset_lock_is_not_spent_and_has_enough_balance: 0, + }, + validate_identity_public_key_contract_bounds: 0, + validate_identity_public_key_ids_dont_exist_in_state: 0, + validate_identity_public_key_ids_exist_in_state: 0, + validate_state_transition_identity_signed: 0, + validate_unique_identity_public_key_hashes_in_state: 0, + validate_master_key_uniqueness: 0, + validate_simple_pre_check_balance: 0, + }, + max_asset_lock_usage_attempts: 16, + identity_create_state_transition: DriveAbciStateTransitionValidationVersion { + basic_structure: Some(0), + advanced_structure: Some(0), + identity_signatures: Some(0), + advanced_minimum_balance_pre_check: None, + nonce: None, + state: 0, + transform_into_action: 0, + }, + identity_update_state_transition: DriveAbciStateTransitionValidationVersion { + basic_structure: Some(0), + advanced_structure: Some(0), + identity_signatures: Some(0), + advanced_minimum_balance_pre_check: None, + nonce: Some(0), + state: 0, + transform_into_action: 0, + }, + identity_top_up_state_transition: DriveAbciStateTransitionValidationVersion { + basic_structure: Some(0), + advanced_structure: None, + identity_signatures: None, + advanced_minimum_balance_pre_check: None, + nonce: None, + state: 0, + transform_into_action: 0, + }, + identity_credit_withdrawal_state_transition: + DriveAbciStateTransitionValidationVersion { + basic_structure: Some(1), + advanced_structure: None, + identity_signatures: None, + advanced_minimum_balance_pre_check: Some(0), + nonce: Some(0), + state: 0, + transform_into_action: 0, + }, + identity_credit_withdrawal_state_transition_purpose_matches_requirements: 0, + identity_credit_transfer_state_transition: DriveAbciStateTransitionValidationVersion { + basic_structure: Some(0), + advanced_structure: None, + identity_signatures: None, + advanced_minimum_balance_pre_check: Some(0), + nonce: Some(0), + state: 0, + transform_into_action: 0, + }, + masternode_vote_state_transition: DriveAbciStateTransitionValidationVersion { + basic_structure: None, + advanced_structure: Some(0), + identity_signatures: None, + advanced_minimum_balance_pre_check: Some(0), + nonce: Some(0), + state: 0, + transform_into_action: 0, + }, + contract_create_state_transition: DriveAbciStateTransitionValidationVersion { + basic_structure: Some(0), + advanced_structure: None, + identity_signatures: None, + advanced_minimum_balance_pre_check: None, + nonce: Some(0), + state: 0, + transform_into_action: 0, + }, + contract_update_state_transition: DriveAbciStateTransitionValidationVersion { + basic_structure: None, + advanced_structure: None, + identity_signatures: None, + advanced_minimum_balance_pre_check: None, + nonce: Some(0), + state: 0, + transform_into_action: 0, + }, + documents_batch_state_transition: DriveAbciDocumentsStateTransitionValidationVersions { + balance_pre_check: 0, + basic_structure: 0, + advanced_structure: 0, + state: 0, + revision: 0, + transform_into_action: 0, + data_triggers: DriveAbciValidationDataTriggerAndBindingVersions { + bindings: 0, + triggers: DriveAbciValidationDataTriggerVersions { + create_contact_request_data_trigger: 0, + create_domain_data_trigger: 0, + create_identity_data_trigger: 0, + create_feature_flag_data_trigger: 0, + create_masternode_reward_shares_data_trigger: 0, + delete_withdrawal_data_trigger: 0, + reject_data_trigger: 0, + }, + }, + is_allowed: 0, + document_create_transition_structure_validation: 0, + document_delete_transition_structure_validation: 0, + document_replace_transition_structure_validation: 0, + document_transfer_transition_structure_validation: 0, + document_purchase_transition_structure_validation: 0, + document_update_price_transition_structure_validation: 0, + document_create_transition_state_validation: 1, + document_delete_transition_state_validation: 0, + document_replace_transition_state_validation: 0, + document_transfer_transition_state_validation: 0, + document_purchase_transition_state_validation: 0, + document_update_price_transition_state_validation: 0, + }, + }, + process_state_transition: 0, + state_transition_to_execution_event_for_check_tx: 0, + penalties: PenaltyAmounts { + identity_id_not_correct: 50000000, + unique_key_already_present: 10000000, + validation_of_added_keys_structure_failure: 10000000, + validation_of_added_keys_proof_of_possession_failure: 50000000, + }, + event_constants: DriveAbciValidationConstants { + maximum_vote_polls_to_process: 2, + maximum_contenders_to_consider: 100, + }, + }; diff --git a/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_withdrawal_constants/mod.rs b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_withdrawal_constants/mod.rs new file mode 100644 index 0000000000..b20f85efde --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_withdrawal_constants/mod.rs @@ -0,0 +1,8 @@ +pub mod v1; +pub mod v2; + +#[derive(Clone, Debug, Default)] +pub struct DriveAbciWithdrawalConstants { + pub core_expiration_blocks: u32, + pub cleanup_expired_locks_of_withdrawal_amounts_limit: u16, +} diff --git a/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_withdrawal_constants/v1.rs b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_withdrawal_constants/v1.rs new file mode 100644 index 0000000000..73bc3f93f9 --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_withdrawal_constants/v1.rs @@ -0,0 +1,7 @@ +use crate::version::drive_abci_versions::drive_abci_withdrawal_constants::DriveAbciWithdrawalConstants; + +pub const DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V1: DriveAbciWithdrawalConstants = + DriveAbciWithdrawalConstants { + core_expiration_blocks: 48, + cleanup_expired_locks_of_withdrawal_amounts_limit: 0, + }; diff --git a/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_withdrawal_constants/v2.rs b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_withdrawal_constants/v2.rs new file mode 100644 index 0000000000..41cdd51f69 --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_withdrawal_constants/v2.rs @@ -0,0 +1,7 @@ +use crate::version::drive_abci_versions::drive_abci_withdrawal_constants::DriveAbciWithdrawalConstants; + +pub const DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V2: DriveAbciWithdrawalConstants = + DriveAbciWithdrawalConstants { + core_expiration_blocks: 48, + cleanup_expired_locks_of_withdrawal_amounts_limit: 64, + }; diff --git a/packages/rs-platform-version/src/version/drive_abci_versions/mod.rs b/packages/rs-platform-version/src/version/drive_abci_versions/mod.rs new file mode 100644 index 0000000000..a6168ce9db --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_abci_versions/mod.rs @@ -0,0 +1,19 @@ +pub mod drive_abci_method_versions; +pub mod drive_abci_query_versions; +pub mod drive_abci_structure_versions; +pub mod drive_abci_validation_versions; +pub mod drive_abci_withdrawal_constants; + +use drive_abci_method_versions::DriveAbciMethodVersions; +use drive_abci_query_versions::DriveAbciQueryVersions; +use drive_abci_structure_versions::DriveAbciStructureVersions; +use drive_abci_validation_versions::DriveAbciValidationVersions; +use drive_abci_withdrawal_constants::DriveAbciWithdrawalConstants; +#[derive(Clone, Debug, Default)] +pub struct DriveAbciVersion { + pub structs: DriveAbciStructureVersions, + pub methods: DriveAbciMethodVersions, + pub validation_and_processing: DriveAbciValidationVersions, + pub withdrawal_constants: DriveAbciWithdrawalConstants, + pub query: DriveAbciQueryVersions, +} diff --git a/packages/rs-platform-version/src/version/drive_versions.rs b/packages/rs-platform-version/src/version/drive_versions.rs deleted file mode 100644 index 5e67347b44..0000000000 --- a/packages/rs-platform-version/src/version/drive_versions.rs +++ /dev/null @@ -1,749 +0,0 @@ -use crate::version::{FeatureVersion, FeatureVersionBounds, OptionalFeatureVersion}; -use grovedb_version::version::GroveVersion; - -#[derive(Clone, Debug, Default)] -pub struct DriveVersion { - pub structure: DriveStructureVersion, - pub methods: DriveMethodVersions, - pub grove_methods: DriveGroveMethodVersions, - pub grove_version: GroveVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveMethodVersions { - pub initialization: DriveInitializationMethodVersions, - pub credit_pools: DriveCreditPoolMethodVersions, - pub protocol_upgrade: DriveProtocolUpgradeVersions, - pub prefunded_specialized_balances: DrivePrefundedSpecializedMethodVersions, - pub balances: DriveBalancesMethodVersions, - pub document: DriveDocumentMethodVersions, - pub vote: DriveVoteMethodVersions, - pub contract: DriveContractMethodVersions, - pub fees: DriveFeesMethodVersions, - pub estimated_costs: DriveEstimatedCostsMethodVersions, - pub asset_lock: DriveAssetLockMethodVersions, - pub verify: DriveVerifyMethodVersions, - pub identity: DriveIdentityMethodVersions, - pub platform_system: DrivePlatformSystemMethodVersions, - pub operations: DriveOperationsMethodVersion, - pub batch_operations: DriveBatchOperationsMethodVersion, - pub fetch: DriveFetchMethodVersions, - pub prove: DriveProveMethodVersions, - pub state_transitions: DriveStateTransitionMethodVersions, - pub platform_state: DrivePlatformStateMethodVersions, -} - -#[derive(Clone, Debug, Default)] -pub struct DrivePlatformStateMethodVersions { - pub fetch_platform_state_bytes: FeatureVersion, - pub store_platform_state_bytes: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveStateTransitionMethodVersions { - pub operations: DriveStateTransitionOperationMethodVersions, - pub convert_to_high_level_operations: - DriveStateTransitionActionConvertToHighLevelOperationsMethodVersions, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveStateTransitionActionConvertToHighLevelOperationsMethodVersions { - pub data_contract_create_transition: FeatureVersion, - pub data_contract_update_transition: FeatureVersion, - pub document_create_transition: FeatureVersion, - pub document_delete_transition: FeatureVersion, - pub document_purchase_transition: FeatureVersion, - pub document_replace_transition: FeatureVersion, - pub document_transfer_transition: FeatureVersion, - pub document_update_price_transition: FeatureVersion, - pub documents_batch_transition: FeatureVersion, - pub identity_create_transition: FeatureVersion, - pub identity_credit_transfer_transition: FeatureVersion, - pub identity_credit_withdrawal_transition: FeatureVersion, - pub identity_top_up_transition: FeatureVersion, - pub identity_update_transition: FeatureVersion, - pub masternode_vote_transition: FeatureVersion, - pub bump_identity_data_contract_nonce: FeatureVersion, - pub bump_identity_nonce: FeatureVersion, - pub partially_use_asset_lock: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveStateTransitionOperationMethodVersions { - pub finalization_tasks: FeatureVersion, - pub contracts: DriveDataContractOperationMethodVersions, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveDataContractOperationMethodVersions { - pub finalization_tasks: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveFetchMethodVersions { - pub fetch_elements: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveProveMethodVersions { - pub prove_elements: FeatureVersion, - pub prove_multiple_state_transition_results: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveVerifyMethodVersions { - pub contract: DriveVerifyContractMethodVersions, - pub document: DriveVerifyDocumentMethodVersions, - pub identity: DriveVerifyIdentityMethodVersions, - pub single_document: DriveVerifySingleDocumentMethodVersions, - pub system: DriveVerifySystemMethodVersions, - pub voting: DriveVerifyVoteMethodVersions, - pub state_transition: DriveVerifyStateTransitionMethodVersions, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveVerifyContractMethodVersions { - pub verify_contract: FeatureVersion, - pub verify_contract_history: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveVerifyDocumentMethodVersions { - pub verify_proof: FeatureVersion, - pub verify_proof_keep_serialized: FeatureVersion, - pub verify_start_at_document_in_proof: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveVerifyIdentityMethodVersions { - pub verify_full_identities_by_public_key_hashes: FeatureVersion, - pub verify_full_identity_by_identity_id: FeatureVersion, - pub verify_full_identity_by_public_key_hash: FeatureVersion, - pub verify_identity_balance_for_identity_id: FeatureVersion, - pub verify_identity_balances_for_identity_ids: FeatureVersion, - pub verify_identity_id_by_public_key_hash: FeatureVersion, - pub verify_identity_ids_by_public_key_hashes: FeatureVersion, - pub verify_identity_keys_by_identity_id: FeatureVersion, - pub verify_identity_nonce: FeatureVersion, - pub verify_identity_contract_nonce: FeatureVersion, - pub verify_identities_contract_keys: FeatureVersion, - pub verify_identity_revision_for_identity_id: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveVerifyVoteMethodVersions { - pub verify_masternode_vote: FeatureVersion, - pub verify_start_at_contender_in_proof: FeatureVersion, - pub verify_vote_poll_votes_proof: FeatureVersion, - pub verify_identity_votes_given_proof: FeatureVersion, - pub verify_vote_poll_vote_state_proof: FeatureVersion, - pub verify_contests_proof: FeatureVersion, - pub verify_vote_polls_by_end_date_proof: FeatureVersion, - pub verify_specialized_balance: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveVerifySystemMethodVersions { - pub verify_epoch_infos: FeatureVersion, - pub verify_epoch_proposers: FeatureVersion, - pub verify_elements: FeatureVersion, - pub verify_total_credits_in_system: FeatureVersion, - pub verify_upgrade_state: FeatureVersion, - pub verify_upgrade_vote_status: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveVerifySingleDocumentMethodVersions { - pub verify_proof: FeatureVersion, - pub verify_proof_keep_serialized: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveVerifyStateTransitionMethodVersions { - pub verify_state_transition_was_executed_with_proof: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveGroveMethodVersions { - pub basic: DriveGroveBasicMethodVersions, - pub batch: DriveGroveBatchMethodVersions, - pub apply: DriveGroveApplyMethodVersions, - pub costs: DriveGroveCostMethodVersions, -} - -#[derive(Clone, Debug, Default)] -pub struct DrivePrefundedSpecializedMethodVersions { - pub fetch_single: FeatureVersion, - pub prove_single: FeatureVersion, - pub add_prefunded_specialized_balance: FeatureVersion, - pub add_prefunded_specialized_balance_operations: FeatureVersion, - pub deduct_from_prefunded_specialized_balance: FeatureVersion, - pub deduct_from_prefunded_specialized_balance_operations: FeatureVersion, - pub estimated_cost_for_prefunded_specialized_balance_update: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveBalancesMethodVersions { - pub add_to_system_credits: FeatureVersion, - pub add_to_system_credits_operations: FeatureVersion, - pub remove_from_system_credits: FeatureVersion, - pub remove_from_system_credits_operations: FeatureVersion, - pub calculate_total_credits_balance: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveAssetLockMethodVersions { - pub add_asset_lock_outpoint: FeatureVersion, - pub add_estimation_costs_for_adding_asset_lock: FeatureVersion, - pub fetch_asset_lock_outpoint_info: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveFeesMethodVersions { - pub calculate_fee: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveContractMethodVersions { - pub prove: DriveContractProveMethodVersions, - pub apply: DriveContractApplyMethodVersions, - pub insert: DriveContractInsertMethodVersions, - pub update: DriveContractUpdateMethodVersions, - pub costs: DriveContractCostsMethodVersions, - pub get: DriveContractGetMethodVersions, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveContractProveMethodVersions { - pub prove_contract: FeatureVersion, - pub prove_contract_history: FeatureVersion, - pub prove_contracts: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveContractApplyMethodVersions { - pub apply_contract: FeatureVersion, - pub apply_contract_with_serialization: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveContractInsertMethodVersions { - pub add_contract_to_storage: FeatureVersion, - pub insert_contract: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveContractUpdateMethodVersions { - pub update_contract: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveContractGetMethodVersions { - pub fetch_contract: FeatureVersion, - pub fetch_contract_with_history: FeatureVersion, - pub get_cached_contract_with_fetch_info: FeatureVersion, - pub get_contract_with_fetch_info: FeatureVersion, - pub get_contracts_with_fetch_info: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveContractQueryMethodVersions { - pub fetch_contract_query: FeatureVersion, - pub fetch_contract_with_history_latest_query: FeatureVersion, - pub fetch_contracts_query: FeatureVersion, - pub fetch_contract_history_query: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveContractCostsMethodVersions { - pub add_estimation_costs_for_contract_insertion: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DrivePlatformSystemMethodVersions { - pub estimation_costs: DriveSystemEstimationCostsMethodVersions, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveOperationsMethodVersion { - pub rollback_transaction: FeatureVersion, - pub drop_cache: FeatureVersion, - pub commit_transaction: FeatureVersion, - pub apply_partial_batch_low_level_drive_operations: FeatureVersion, - pub apply_partial_batch_grovedb_operations: FeatureVersion, - pub apply_batch_low_level_drive_operations: FeatureVersion, - pub apply_batch_grovedb_operations: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveBatchOperationsMethodVersion { - pub convert_drive_operations_to_grove_operations: FeatureVersion, - pub apply_drive_operations: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveSystemEstimationCostsMethodVersions { - pub for_total_system_credits_update: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveVoteMethodVersions { - pub insert: DriveVoteInsertMethodVersions, - pub contested_resource_insert: DriveVoteContestedResourceInsertMethodVersions, - pub cleanup: DriveVoteCleanupMethodVersions, - pub setup: DriveVoteSetupMethodVersions, - pub storage_form: DriveVoteStorageFormMethodVersions, - pub fetch: DriveVoteFetchMethodVersions, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveVoteFetchMethodVersions { - pub fetch_identities_voting_for_contenders: FeatureVersion, - pub fetch_contested_document_vote_poll_stored_info: FeatureVersion, - pub fetch_identity_contested_resource_vote: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveVoteStorageFormMethodVersions { - pub resolve_with_contract: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveVoteSetupMethodVersions { - pub add_initial_vote_tree_main_structure_operations: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveVoteCleanupMethodVersions { - pub remove_specific_vote_references_given_by_identity: FeatureVersion, - pub remove_specific_votes_given_by_identity: FeatureVersion, - pub remove_contested_resource_vote_poll_end_date_query_operations: FeatureVersion, - pub remove_contested_resource_vote_poll_votes_operations: FeatureVersion, - pub remove_contested_resource_vote_poll_documents_operations: FeatureVersion, - pub remove_contested_resource_vote_poll_contenders_operations: FeatureVersion, - pub remove_contested_resource_top_level_index_operations: FeatureVersion, - pub remove_contested_resource_info_operations: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveVoteInsertMethodVersions { - pub register_identity_vote: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveVoteContestedResourceInsertMethodVersions { - pub register_contested_resource_identity_vote: FeatureVersion, - pub insert_stored_info_for_contested_resource_vote_poll: FeatureVersion, - pub register_identity_vote: FeatureVersion, - pub add_vote_poll_end_date_query_operations: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveDocumentMethodVersions { - pub query: DriveDocumentQueryMethodVersions, - pub delete: DriveDocumentDeleteMethodVersions, - pub insert: DriveDocumentInsertMethodVersions, - pub insert_contested: DriveDocumentInsertContestedMethodVersions, - pub update: DriveDocumentUpdateMethodVersions, - pub estimation_costs: DriveDocumentEstimationCostsMethodVersions, - pub index_uniqueness: DriveDocumentIndexUniquenessMethodVersions, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveDocumentQueryMethodVersions { - pub query_documents: FeatureVersion, - pub query_contested_documents: FeatureVersion, - pub query_contested_documents_vote_state: FeatureVersion, - pub query_documents_with_flags: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveDocumentEstimationCostsMethodVersions { - pub add_estimation_costs_for_add_document_to_primary_storage: FeatureVersion, - pub add_estimation_costs_for_add_contested_document_to_primary_storage: FeatureVersion, - pub stateless_delete_of_non_tree_for_costs: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveDocumentInsertMethodVersions { - pub add_document: FeatureVersion, - pub add_document_for_contract: FeatureVersion, - pub add_document_for_contract_apply_and_add_to_operations: FeatureVersion, - pub add_document_for_contract_operations: FeatureVersion, - pub add_document_to_primary_storage: FeatureVersion, - pub add_indices_for_index_level_for_contract_operations: FeatureVersion, - pub add_indices_for_top_index_level_for_contract_operations: FeatureVersion, - pub add_reference_for_index_level_for_contract_operations: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveDocumentInsertContestedMethodVersions { - pub add_contested_document: FeatureVersion, - pub add_contested_document_for_contract: FeatureVersion, - pub add_contested_document_for_contract_apply_and_add_to_operations: FeatureVersion, - pub add_contested_document_for_contract_operations: FeatureVersion, - pub add_contested_document_to_primary_storage: FeatureVersion, - pub add_contested_indices_for_contract_operations: FeatureVersion, - pub add_contested_reference_and_vote_subtree_to_document_operations: FeatureVersion, - pub add_contested_vote_subtree_for_non_identities_operations: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveDocumentUpdateMethodVersions { - pub add_update_multiple_documents_operations: FeatureVersion, - pub update_document_for_contract: FeatureVersion, - pub update_document_for_contract_apply_and_add_to_operations: FeatureVersion, - pub update_document_for_contract_id: FeatureVersion, - pub update_document_for_contract_operations: FeatureVersion, - pub update_document_with_serialization_for_contract: FeatureVersion, - pub update_serialized_document_for_contract: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveDocumentDeleteMethodVersions { - pub add_estimation_costs_for_remove_document_to_primary_storage: FeatureVersion, - pub delete_document_for_contract: FeatureVersion, - pub delete_document_for_contract_id: FeatureVersion, - pub delete_document_for_contract_apply_and_add_to_operations: FeatureVersion, - pub remove_document_from_primary_storage: FeatureVersion, - pub remove_reference_for_index_level_for_contract_operations: FeatureVersion, - pub remove_indices_for_index_level_for_contract_operations: FeatureVersion, - pub remove_indices_for_top_index_level_for_contract_operations: FeatureVersion, - pub delete_document_for_contract_id_with_named_type_operations: FeatureVersion, - pub delete_document_for_contract_with_named_type_operations: FeatureVersion, - pub delete_document_for_contract_operations: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveDocumentIndexUniquenessMethodVersions { - pub validate_document_uniqueness: FeatureVersion, - pub validate_document_create_transition_action_uniqueness: FeatureVersion, - pub validate_document_replace_transition_action_uniqueness: FeatureVersion, - pub validate_document_transfer_transition_action_uniqueness: FeatureVersion, - pub validate_document_purchase_transition_action_uniqueness: FeatureVersion, - pub validate_document_update_price_transition_action_uniqueness: FeatureVersion, - pub validate_uniqueness_of_data: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveGroveBasicMethodVersions { - pub grove_insert: FeatureVersion, - pub grove_insert_empty_tree: FeatureVersion, - pub grove_insert_empty_sum_tree: FeatureVersion, - pub grove_insert_if_not_exists: FeatureVersion, - pub grove_clear: FeatureVersion, - pub grove_delete: FeatureVersion, - pub grove_get_raw: FeatureVersion, - pub grove_get_raw_optional: FeatureVersion, - pub grove_get_raw_value_u64_from_encoded_var_vec: FeatureVersion, - pub grove_get: FeatureVersion, - pub grove_get_path_query_serialized_results: FeatureVersion, - pub grove_get_path_query_serialized_or_sum_results: FeatureVersion, - pub grove_get_path_query: FeatureVersion, - pub grove_get_path_query_with_optional: FeatureVersion, - pub grove_get_raw_path_query_with_optional: FeatureVersion, - pub grove_get_raw_path_query: FeatureVersion, - pub grove_get_proved_path_query: FeatureVersion, - pub grove_get_proved_path_query_with_conditional: FeatureVersion, - pub grove_get_sum_tree_total_value: FeatureVersion, - pub grove_has_raw: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveGroveBatchMethodVersions { - pub batch_insert_empty_tree: FeatureVersion, - pub batch_insert_empty_tree_if_not_exists: FeatureVersion, - pub batch_insert_empty_tree_if_not_exists_check_existing_operations: FeatureVersion, - pub batch_insert: FeatureVersion, - pub batch_insert_if_not_exists: FeatureVersion, - pub batch_insert_if_changed_value: FeatureVersion, - pub batch_replace: FeatureVersion, - pub batch_delete: FeatureVersion, - pub batch_remove_raw: FeatureVersion, - pub batch_delete_up_tree_while_empty: FeatureVersion, - pub batch_refresh_reference: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveGroveApplyMethodVersions { - pub grove_apply_operation: FeatureVersion, - pub grove_apply_batch: FeatureVersion, - pub grove_apply_partial_batch: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveGroveCostMethodVersions { - pub grove_batch_operations_costs: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveInitializationMethodVersions { - pub create_initial_state_structure: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveCreditPoolMethodVersions { - pub epochs: DriveCreditPoolEpochsMethodVersions, - pub pending_epoch_refunds: DriveCreditPoolPendingEpochRefundsMethodVersions, - pub storage_fee_distribution_pool: DriveCreditPoolStorageFeeDistributionPoolMethodVersions, - pub unpaid_epoch: DriveCreditPoolUnpaidEpochMethodVersions, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveCreditPoolEpochsMethodVersions { - pub get_epochs_infos: FeatureVersion, - pub get_epochs_protocol_versions: FeatureVersion, - pub prove_epochs_infos: FeatureVersion, - pub get_epoch_fee_multiplier: FeatureVersion, - pub get_epoch_processing_credits_for_distribution: FeatureVersion, - pub get_epoch_storage_credits_for_distribution: FeatureVersion, - pub get_epoch_total_credits_for_distribution: FeatureVersion, - pub get_storage_credits_for_distribution_for_epochs_in_range: FeatureVersion, - pub get_epoch_start_time: FeatureVersion, - pub get_epoch_start_block_core_height: FeatureVersion, - pub get_epoch_start_block_height: FeatureVersion, - pub get_first_epoch_start_block_info_between_epochs: FeatureVersion, - pub fetch_epoch_proposers: FeatureVersion, - pub prove_epoch_proposers: FeatureVersion, - pub get_epochs_proposer_block_count: FeatureVersion, - pub add_update_pending_epoch_refunds_operations: FeatureVersion, - pub is_epochs_proposers_tree_empty: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveCreditPoolUnpaidEpochMethodVersions { - pub get_unpaid_epoch_index: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveCreditPoolPendingEpochRefundsMethodVersions { - pub add_delete_pending_epoch_refunds_except_specified: FeatureVersion, - pub fetch_and_add_pending_epoch_refunds_to_collection: FeatureVersion, - pub fetch_pending_epoch_refunds: FeatureVersion, - pub add_update_pending_epoch_refunds_operations: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveCreditPoolStorageFeeDistributionPoolMethodVersions { - pub get_storage_fees_from_distribution_pool: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveProtocolUpgradeVersions { - pub clear_version_information: FeatureVersion, - pub fetch_versions_with_counter: FeatureVersion, - pub fetch_proved_versions_with_counter: FeatureVersion, - pub fetch_validator_version_votes: FeatureVersion, - pub fetch_proved_validator_version_votes: FeatureVersion, - pub remove_validators_proposed_app_versions: FeatureVersion, - pub update_validator_proposed_app_version: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveStructureVersion { - pub document_indexes: FeatureVersionBounds, - pub identity_indexes: FeatureVersionBounds, - pub pools: FeatureVersionBounds, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveIdentityMethodVersions { - pub fetch: DriveIdentityFetchMethodVersions, - pub prove: DriveIdentityProveMethodVersions, - pub keys: DriveIdentityKeysMethodVersions, - pub update: DriveIdentityUpdateMethodVersions, - pub insert: DriveIdentityInsertMethodVersions, - pub contract_info: DriveIdentityContractInfoMethodVersions, - pub cost_estimation: DriveIdentityCostEstimationMethodVersions, - pub withdrawals: DriveIdentityWithdrawalMethodVersions, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveIdentityWithdrawalMethodVersions { - pub document: DriveIdentityWithdrawalDocumentMethodVersions, - pub transaction: DriveIdentityWithdrawalTransactionMethodVersions, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveIdentityWithdrawalDocumentMethodVersions { - pub fetch_oldest_withdrawal_documents_by_status: FeatureVersion, - pub find_up_to_100_withdrawal_documents_by_status_and_transaction_indices: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveIdentityWithdrawalTransactionMethodVersions { - pub index: DriveIdentityWithdrawalTransactionIndexMethodVersions, - pub queue: DriveIdentityWithdrawalTransactionQueueMethodVersions, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveIdentityWithdrawalTransactionIndexMethodVersions { - pub fetch_next_withdrawal_transaction_index: FeatureVersion, - pub add_update_next_withdrawal_transaction_index_operation: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveIdentityWithdrawalTransactionQueueMethodVersions { - pub add_enqueue_untied_withdrawal_transaction_operations: FeatureVersion, - pub dequeue_untied_withdrawal_transactions: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveIdentityContractInfoMethodVersions { - pub add_potential_contract_info_for_contract_bounded_key: FeatureVersion, - pub refresh_potential_contract_info_key_references: FeatureVersion, - pub merge_identity_contract_nonce: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveIdentityCostEstimationMethodVersions { - pub for_authentication_keys_security_level_in_key_reference_tree: FeatureVersion, - pub for_balances: FeatureVersion, - pub for_contract_info: FeatureVersion, - pub for_contract_info_group: FeatureVersion, - pub for_contract_info_group_keys: FeatureVersion, - pub for_contract_info_group_key_purpose: FeatureVersion, - pub for_keys_for_identity_id: FeatureVersion, - pub for_negative_credit: FeatureVersion, - pub for_purpose_in_key_reference_tree: FeatureVersion, - pub for_root_key_reference_tree: FeatureVersion, - pub for_update_revision: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveIdentityFetchMethodVersions { - pub public_key_hashes: DriveIdentityFetchPublicKeyHashesMethodVersions, - pub attributes: DriveIdentityFetchAttributesMethodVersions, - pub partial_identity: DriveIdentityFetchPartialIdentityMethodVersions, - pub full_identity: DriveIdentityFetchFullIdentityMethodVersions, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveIdentityFetchPublicKeyHashesMethodVersions { - pub fetch_full_identities_by_unique_public_key_hashes: FeatureVersion, - pub fetch_full_identity_by_unique_public_key_hash: FeatureVersion, - pub fetch_identity_id_by_unique_public_key_hash: FeatureVersion, - pub fetch_identity_ids_by_non_unique_public_key_hash: FeatureVersion, - pub fetch_identity_ids_by_unique_public_key_hashes: FeatureVersion, - pub fetch_serialized_full_identity_by_unique_public_key_hash: FeatureVersion, - pub has_any_of_unique_public_key_hashes: FeatureVersion, - pub has_non_unique_public_key_hash: FeatureVersion, - pub has_non_unique_public_key_hash_already_for_identity: FeatureVersion, - pub has_unique_public_key_hash: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveIdentityFetchAttributesMethodVersions { - pub revision: FeatureVersion, - pub nonce: FeatureVersion, - pub identity_contract_nonce: FeatureVersion, - pub balance: FeatureVersion, - pub balance_include_debt: FeatureVersion, - pub negative_balance: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveIdentityFetchFullIdentityMethodVersions { - pub fetch_full_identity: OptionalFeatureVersion, - pub fetch_full_identities: OptionalFeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveIdentityFetchPartialIdentityMethodVersions { - pub fetch_identity_revision_with_keys: FeatureVersion, - pub fetch_identity_balance_with_keys: FeatureVersion, - pub fetch_identity_balance_with_keys_and_revision: FeatureVersion, - pub fetch_identity_with_balance: FeatureVersion, - pub fetch_identity_keys: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveIdentityProveMethodVersions { - pub full_identity: FeatureVersion, - pub full_identities: FeatureVersion, - pub identity_nonce: FeatureVersion, - pub identity_contract_nonce: FeatureVersion, - pub identities_contract_keys: FeatureVersion, - pub prove_full_identities_by_unique_public_key_hashes: FeatureVersion, - pub prove_full_identity_by_unique_public_key_hash: FeatureVersion, - pub prove_identity_id_by_unique_public_key_hash: FeatureVersion, - pub prove_identity_ids_by_unique_public_key_hashes: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveIdentityKeysMethodVersions { - pub fetch: DriveIdentityKeysFetchMethodVersions, - pub prove: DriveIdentityKeysProveMethodVersions, - pub insert: DriveIdentityKeysInsertMethodVersions, - pub insert_key_hash_identity_reference: DriveIdentityKeyHashesToIdentityInsertMethodVersions, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveIdentityKeysFetchMethodVersions { - pub fetch_all_current_identity_keys: FeatureVersion, - pub fetch_all_identity_keys: FeatureVersion, - pub fetch_identities_all_keys: FeatureVersion, - pub fetch_identity_keys: FeatureVersion, - pub fetch_identities_contract_keys: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveIdentityKeysProveMethodVersions { - pub prove_identities_all_keys: FeatureVersion, - pub prove_identity_keys: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveIdentityKeysInsertMethodVersions { - pub create_key_tree_with_keys: FeatureVersion, - pub create_new_identity_key_query_trees: FeatureVersion, - pub insert_key_searchable_references: FeatureVersion, - pub insert_key_to_storage: FeatureVersion, - pub insert_new_non_unique_key: FeatureVersion, - pub insert_new_unique_key: FeatureVersion, - pub replace_key_in_storage: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveIdentityKeyHashesToIdentityInsertMethodVersions { - pub add_estimation_costs_for_insert_non_unique_public_key_hash_reference: FeatureVersion, - pub add_estimation_costs_for_insert_unique_public_key_hash_reference: FeatureVersion, - pub insert_non_unique_public_key_hash_reference_to_identity: FeatureVersion, - pub insert_reference_to_non_unique_key: FeatureVersion, - pub insert_reference_to_unique_key: FeatureVersion, - pub insert_unique_public_key_hash_reference_to_identity: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveIdentityInsertMethodVersions { - pub add_new_identity: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveIdentityUpdateMethodVersions { - pub update_identity_revision: FeatureVersion, - pub merge_identity_nonce: FeatureVersion, - pub update_identity_negative_credit_operation: FeatureVersion, - pub initialize_identity_revision: FeatureVersion, - pub disable_identity_keys: FeatureVersion, - pub re_enable_identity_keys: FeatureVersion, - pub add_new_non_unique_keys_to_identity: FeatureVersion, - pub add_new_unique_keys_to_identity: FeatureVersion, - pub add_new_keys_to_identity: FeatureVersion, - pub insert_identity_balance: FeatureVersion, - pub initialize_negative_identity_balance: FeatureVersion, - pub add_to_identity_balance: FeatureVersion, - pub add_to_previous_balance: FeatureVersion, - pub apply_balance_change_from_fee_to_identity: FeatureVersion, - pub remove_from_identity_balance: FeatureVersion, - pub refresh_identity_key_reference_operations: FeatureVersion, -} - -#[derive(Clone, Debug, Default)] -pub struct DriveEstimatedCostsMethodVersions { - pub add_estimation_costs_for_levels_up_to_contract: FeatureVersion, - pub add_estimation_costs_for_levels_up_to_contract_document_type_excluded: FeatureVersion, - pub add_estimation_costs_for_contested_document_tree_levels_up_to_contract: FeatureVersion, - pub add_estimation_costs_for_contested_document_tree_levels_up_to_contract_document_type_excluded: - FeatureVersion, -} 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 new file mode 100644 index 0000000000..18cf2d3a4f --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/mod.rs @@ -0,0 +1,59 @@ +use versioned_feature_core::FeatureVersion; + +pub mod v1; + +#[derive(Clone, Debug, Default)] +pub struct DriveContractMethodVersions { + pub prove: DriveContractProveMethodVersions, + pub apply: DriveContractApplyMethodVersions, + pub insert: DriveContractInsertMethodVersions, + pub update: DriveContractUpdateMethodVersions, + pub costs: DriveContractCostsMethodVersions, + pub get: DriveContractGetMethodVersions, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveContractProveMethodVersions { + pub prove_contract: FeatureVersion, + pub prove_contract_history: FeatureVersion, + pub prove_contracts: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveContractApplyMethodVersions { + pub apply_contract: FeatureVersion, + pub apply_contract_with_serialization: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveContractInsertMethodVersions { + pub add_contract_to_storage: FeatureVersion, + pub insert_contract: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveContractUpdateMethodVersions { + pub update_contract: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveContractGetMethodVersions { + pub fetch_contract: FeatureVersion, + pub fetch_contract_with_history: FeatureVersion, + pub get_cached_contract_with_fetch_info: FeatureVersion, + pub get_contract_with_fetch_info: FeatureVersion, + pub get_contracts_with_fetch_info: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveContractQueryMethodVersions { + pub fetch_contract_query: FeatureVersion, + pub fetch_contract_with_history_latest_query: FeatureVersion, + pub fetch_contracts_query: FeatureVersion, + pub fetch_contract_history_query: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveContractCostsMethodVersions { + pub add_estimation_costs_for_contract_insertion: FeatureVersion, +} diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/v1.rs b/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/v1.rs new file mode 100644 index 0000000000..67824dafea --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/v1.rs @@ -0,0 +1,33 @@ +use crate::version::drive_versions::drive_contract_method_versions::{ + DriveContractApplyMethodVersions, DriveContractCostsMethodVersions, + DriveContractGetMethodVersions, DriveContractInsertMethodVersions, DriveContractMethodVersions, + DriveContractProveMethodVersions, DriveContractUpdateMethodVersions, +}; + +pub const DRIVE_CONTRACT_METHOD_VERSIONS_V1: 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: 0, + }, + update: DriveContractUpdateMethodVersions { update_contract: 0 }, + costs: DriveContractCostsMethodVersions { + add_estimation_costs_for_contract_insertion: 0, + }, + get: DriveContractGetMethodVersions { + fetch_contract: 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_credit_pool_method_versions/mod.rs b/packages/rs-platform-version/src/version/drive_versions/drive_credit_pool_method_versions/mod.rs new file mode 100644 index 0000000000..0d116b4104 --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_versions/drive_credit_pool_method_versions/mod.rs @@ -0,0 +1,49 @@ +use versioned_feature_core::FeatureVersion; +pub mod v1; + +#[derive(Clone, Debug, Default)] +pub struct DriveCreditPoolMethodVersions { + pub epochs: DriveCreditPoolEpochsMethodVersions, + pub pending_epoch_refunds: DriveCreditPoolPendingEpochRefundsMethodVersions, + pub storage_fee_distribution_pool: DriveCreditPoolStorageFeeDistributionPoolMethodVersions, + pub unpaid_epoch: DriveCreditPoolUnpaidEpochMethodVersions, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveCreditPoolEpochsMethodVersions { + pub get_epochs_infos: FeatureVersion, + pub get_epochs_protocol_versions: FeatureVersion, + pub prove_epochs_infos: FeatureVersion, + pub get_epoch_fee_multiplier: FeatureVersion, + pub get_epoch_processing_credits_for_distribution: FeatureVersion, + pub get_epoch_storage_credits_for_distribution: FeatureVersion, + pub get_epoch_total_credits_for_distribution: FeatureVersion, + pub get_storage_credits_for_distribution_for_epochs_in_range: FeatureVersion, + pub get_epoch_start_time: FeatureVersion, + pub get_epoch_start_block_core_height: FeatureVersion, + pub get_epoch_start_block_height: FeatureVersion, + pub get_first_epoch_start_block_info_between_epochs: FeatureVersion, + pub fetch_epoch_proposers: FeatureVersion, + pub prove_epoch_proposers: FeatureVersion, + pub get_epochs_proposer_block_count: FeatureVersion, + pub add_update_pending_epoch_refunds_operations: FeatureVersion, + pub is_epochs_proposers_tree_empty: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveCreditPoolUnpaidEpochMethodVersions { + pub get_unpaid_epoch_index: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveCreditPoolPendingEpochRefundsMethodVersions { + pub add_delete_pending_epoch_refunds_except_specified: FeatureVersion, + pub fetch_and_add_pending_epoch_refunds_to_collection: FeatureVersion, + pub fetch_pending_epoch_refunds: FeatureVersion, + pub add_update_pending_epoch_refunds_operations: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveCreditPoolStorageFeeDistributionPoolMethodVersions { + pub get_storage_fees_from_distribution_pool: FeatureVersion, +} diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_credit_pool_method_versions/v1.rs b/packages/rs-platform-version/src/version/drive_versions/drive_credit_pool_method_versions/v1.rs new file mode 100644 index 0000000000..4311729886 --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_versions/drive_credit_pool_method_versions/v1.rs @@ -0,0 +1,41 @@ +use crate::version::drive_versions::drive_credit_pool_method_versions::{ + DriveCreditPoolEpochsMethodVersions, DriveCreditPoolMethodVersions, + DriveCreditPoolPendingEpochRefundsMethodVersions, + DriveCreditPoolStorageFeeDistributionPoolMethodVersions, + DriveCreditPoolUnpaidEpochMethodVersions, +}; + +pub const CREDIT_POOL_METHOD_VERSIONS_V1: DriveCreditPoolMethodVersions = + DriveCreditPoolMethodVersions { + epochs: DriveCreditPoolEpochsMethodVersions { + get_epochs_infos: 0, + get_epochs_protocol_versions: 0, + prove_epochs_infos: 0, + get_epoch_fee_multiplier: 0, + get_epoch_processing_credits_for_distribution: 0, + get_epoch_storage_credits_for_distribution: 0, + get_epoch_total_credits_for_distribution: 0, + get_storage_credits_for_distribution_for_epochs_in_range: 0, + get_epoch_start_time: 0, + get_epoch_start_block_core_height: 0, + get_epoch_start_block_height: 0, + get_first_epoch_start_block_info_between_epochs: 0, + fetch_epoch_proposers: 0, + prove_epoch_proposers: 0, + get_epochs_proposer_block_count: 0, + add_update_pending_epoch_refunds_operations: 0, + is_epochs_proposers_tree_empty: 0, + }, + pending_epoch_refunds: DriveCreditPoolPendingEpochRefundsMethodVersions { + add_delete_pending_epoch_refunds_except_specified: 0, + fetch_and_add_pending_epoch_refunds_to_collection: 0, + fetch_pending_epoch_refunds: 0, + add_update_pending_epoch_refunds_operations: 0, + }, + storage_fee_distribution_pool: DriveCreditPoolStorageFeeDistributionPoolMethodVersions { + get_storage_fees_from_distribution_pool: 0, + }, + unpaid_epoch: DriveCreditPoolUnpaidEpochMethodVersions { + get_unpaid_epoch_index: 0, + }, + }; diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_document_method_versions/mod.rs b/packages/rs-platform-version/src/version/drive_versions/drive_document_method_versions/mod.rs new file mode 100644 index 0000000000..12eebc7386 --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_versions/drive_document_method_versions/mod.rs @@ -0,0 +1,90 @@ +use versioned_feature_core::FeatureVersion; + +pub mod v1; + +#[derive(Clone, Debug, Default)] +pub struct DriveDocumentMethodVersions { + pub query: DriveDocumentQueryMethodVersions, + pub delete: DriveDocumentDeleteMethodVersions, + pub insert: DriveDocumentInsertMethodVersions, + pub insert_contested: DriveDocumentInsertContestedMethodVersions, + pub update: DriveDocumentUpdateMethodVersions, + pub estimation_costs: DriveDocumentEstimationCostsMethodVersions, + pub index_uniqueness: DriveDocumentIndexUniquenessMethodVersions, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveDocumentQueryMethodVersions { + pub query_documents: FeatureVersion, + pub query_contested_documents: FeatureVersion, + pub query_contested_documents_vote_state: FeatureVersion, + pub query_documents_with_flags: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveDocumentEstimationCostsMethodVersions { + pub add_estimation_costs_for_add_document_to_primary_storage: FeatureVersion, + pub add_estimation_costs_for_add_contested_document_to_primary_storage: FeatureVersion, + pub stateless_delete_of_non_tree_for_costs: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveDocumentInsertMethodVersions { + pub add_document: FeatureVersion, + pub add_document_for_contract: FeatureVersion, + pub add_document_for_contract_apply_and_add_to_operations: FeatureVersion, + pub add_document_for_contract_operations: FeatureVersion, + pub add_document_to_primary_storage: FeatureVersion, + pub add_indices_for_index_level_for_contract_operations: FeatureVersion, + pub add_indices_for_top_index_level_for_contract_operations: FeatureVersion, + pub add_reference_for_index_level_for_contract_operations: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveDocumentInsertContestedMethodVersions { + pub add_contested_document: FeatureVersion, + pub add_contested_document_for_contract: FeatureVersion, + pub add_contested_document_for_contract_apply_and_add_to_operations: FeatureVersion, + pub add_contested_document_for_contract_operations: FeatureVersion, + pub add_contested_document_to_primary_storage: FeatureVersion, + pub add_contested_indices_for_contract_operations: FeatureVersion, + pub add_contested_reference_and_vote_subtree_to_document_operations: FeatureVersion, + pub add_contested_vote_subtree_for_non_identities_operations: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveDocumentUpdateMethodVersions { + pub add_update_multiple_documents_operations: FeatureVersion, + pub update_document_for_contract: FeatureVersion, + pub update_document_for_contract_apply_and_add_to_operations: FeatureVersion, + pub update_document_for_contract_id: FeatureVersion, + pub update_document_for_contract_operations: FeatureVersion, + pub update_document_with_serialization_for_contract: FeatureVersion, + pub update_serialized_document_for_contract: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveDocumentDeleteMethodVersions { + pub add_estimation_costs_for_remove_document_to_primary_storage: FeatureVersion, + pub delete_document_for_contract: FeatureVersion, + pub delete_document_for_contract_id: FeatureVersion, + pub delete_document_for_contract_apply_and_add_to_operations: FeatureVersion, + pub remove_document_from_primary_storage: FeatureVersion, + pub remove_reference_for_index_level_for_contract_operations: FeatureVersion, + pub remove_indices_for_index_level_for_contract_operations: FeatureVersion, + pub remove_indices_for_top_index_level_for_contract_operations: FeatureVersion, + pub delete_document_for_contract_id_with_named_type_operations: FeatureVersion, + pub delete_document_for_contract_with_named_type_operations: FeatureVersion, + pub delete_document_for_contract_operations: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveDocumentIndexUniquenessMethodVersions { + pub validate_document_uniqueness: FeatureVersion, + pub validate_document_create_transition_action_uniqueness: FeatureVersion, + pub validate_document_replace_transition_action_uniqueness: FeatureVersion, + pub validate_document_transfer_transition_action_uniqueness: FeatureVersion, + pub validate_document_purchase_transition_action_uniqueness: FeatureVersion, + pub validate_document_update_price_transition_action_uniqueness: FeatureVersion, + pub validate_uniqueness_of_data: FeatureVersion, +} diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_document_method_versions/v1.rs b/packages/rs-platform-version/src/version/drive_versions/drive_document_method_versions/v1.rs new file mode 100644 index 0000000000..05479b23e9 --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_versions/drive_document_method_versions/v1.rs @@ -0,0 +1,72 @@ +use crate::version::drive_versions::drive_document_method_versions::{ + DriveDocumentDeleteMethodVersions, DriveDocumentEstimationCostsMethodVersions, + DriveDocumentIndexUniquenessMethodVersions, DriveDocumentInsertContestedMethodVersions, + DriveDocumentInsertMethodVersions, DriveDocumentMethodVersions, + DriveDocumentQueryMethodVersions, DriveDocumentUpdateMethodVersions, +}; + +pub const DRIVE_DOCUMENT_METHOD_VERSIONS_V1: DriveDocumentMethodVersions = + DriveDocumentMethodVersions { + query: DriveDocumentQueryMethodVersions { + query_documents: 0, + query_contested_documents: 0, + query_contested_documents_vote_state: 0, + query_documents_with_flags: 0, + }, + delete: DriveDocumentDeleteMethodVersions { + add_estimation_costs_for_remove_document_to_primary_storage: 0, + delete_document_for_contract: 0, + delete_document_for_contract_id: 0, + delete_document_for_contract_apply_and_add_to_operations: 0, + remove_document_from_primary_storage: 0, + remove_reference_for_index_level_for_contract_operations: 0, + remove_indices_for_index_level_for_contract_operations: 0, + remove_indices_for_top_index_level_for_contract_operations: 0, + delete_document_for_contract_id_with_named_type_operations: 0, + delete_document_for_contract_with_named_type_operations: 0, + delete_document_for_contract_operations: 0, + }, + insert: DriveDocumentInsertMethodVersions { + add_document: 0, + add_document_for_contract: 0, + add_document_for_contract_apply_and_add_to_operations: 0, + add_document_for_contract_operations: 0, + add_document_to_primary_storage: 0, + add_indices_for_index_level_for_contract_operations: 0, + add_indices_for_top_index_level_for_contract_operations: 0, + add_reference_for_index_level_for_contract_operations: 0, + }, + insert_contested: DriveDocumentInsertContestedMethodVersions { + add_contested_document: 0, + add_contested_document_for_contract: 0, + add_contested_document_for_contract_apply_and_add_to_operations: 0, + add_contested_document_for_contract_operations: 0, + add_contested_document_to_primary_storage: 0, + add_contested_indices_for_contract_operations: 0, + add_contested_reference_and_vote_subtree_to_document_operations: 0, + add_contested_vote_subtree_for_non_identities_operations: 0, + }, + update: DriveDocumentUpdateMethodVersions { + add_update_multiple_documents_operations: 0, + update_document_for_contract: 0, + update_document_for_contract_apply_and_add_to_operations: 0, + update_document_for_contract_id: 0, + update_document_for_contract_operations: 0, + update_document_with_serialization_for_contract: 0, + update_serialized_document_for_contract: 0, + }, + estimation_costs: DriveDocumentEstimationCostsMethodVersions { + add_estimation_costs_for_add_document_to_primary_storage: 0, + add_estimation_costs_for_add_contested_document_to_primary_storage: 0, + stateless_delete_of_non_tree_for_costs: 0, + }, + index_uniqueness: DriveDocumentIndexUniquenessMethodVersions { + validate_document_uniqueness: 0, + validate_document_create_transition_action_uniqueness: 0, + validate_document_replace_transition_action_uniqueness: 0, + validate_document_transfer_transition_action_uniqueness: 0, + validate_document_purchase_transition_action_uniqueness: 0, + validate_document_update_price_transition_action_uniqueness: 0, + validate_uniqueness_of_data: 0, + }, + }; diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_grove_method_versions/mod.rs b/packages/rs-platform-version/src/version/drive_versions/drive_grove_method_versions/mod.rs new file mode 100644 index 0000000000..c61b52f250 --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_versions/drive_grove_method_versions/mod.rs @@ -0,0 +1,66 @@ +use versioned_feature_core::FeatureVersion; + +pub mod v1; + +#[derive(Clone, Debug, Default)] +pub struct DriveGroveMethodVersions { + pub basic: DriveGroveBasicMethodVersions, + pub batch: DriveGroveBatchMethodVersions, + pub apply: DriveGroveApplyMethodVersions, + pub costs: DriveGroveCostMethodVersions, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveGroveBasicMethodVersions { + pub grove_insert: FeatureVersion, + pub grove_insert_empty_tree: FeatureVersion, + pub grove_insert_empty_sum_tree: FeatureVersion, + pub grove_insert_if_not_exists: FeatureVersion, + pub grove_insert_if_not_exists_return_existing_element: FeatureVersion, + pub grove_clear: FeatureVersion, + pub grove_delete: FeatureVersion, + pub grove_get_raw: FeatureVersion, + pub grove_get_raw_optional: FeatureVersion, + pub grove_get_raw_value_u64_from_encoded_var_vec: FeatureVersion, + pub grove_get: FeatureVersion, + pub grove_get_path_query_serialized_results: FeatureVersion, + pub grove_get_path_query_serialized_or_sum_results: FeatureVersion, + pub grove_get_path_query: FeatureVersion, + pub grove_get_path_query_with_optional: FeatureVersion, + pub grove_get_raw_path_query_with_optional: FeatureVersion, + pub grove_get_raw_path_query: FeatureVersion, + pub grove_get_proved_path_query: FeatureVersion, + pub grove_get_proved_path_query_with_conditional: FeatureVersion, + pub grove_get_sum_tree_total_value: FeatureVersion, + pub grove_has_raw: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveGroveBatchMethodVersions { + pub batch_insert_empty_tree: FeatureVersion, + pub batch_insert_empty_tree_if_not_exists: FeatureVersion, + pub batch_insert_empty_tree_if_not_exists_check_existing_operations: FeatureVersion, + pub batch_insert_sum_item_or_add_to_if_already_exists: FeatureVersion, + pub batch_insert: FeatureVersion, + pub batch_insert_if_not_exists: FeatureVersion, + pub batch_insert_if_changed_value: FeatureVersion, + pub batch_replace: FeatureVersion, + pub batch_delete: FeatureVersion, + pub batch_delete_items_in_path_query: FeatureVersion, + pub batch_move_items_in_path_query: FeatureVersion, + pub batch_remove_raw: FeatureVersion, + pub batch_delete_up_tree_while_empty: FeatureVersion, + pub batch_refresh_reference: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveGroveApplyMethodVersions { + pub grove_apply_operation: FeatureVersion, + pub grove_apply_batch: FeatureVersion, + pub grove_apply_partial_batch: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveGroveCostMethodVersions { + pub grove_batch_operations_costs: FeatureVersion, +} diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_grove_method_versions/v1.rs b/packages/rs-platform-version/src/version/drive_versions/drive_grove_method_versions/v1.rs new file mode 100644 index 0000000000..6dc9b44503 --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_versions/drive_grove_method_versions/v1.rs @@ -0,0 +1,54 @@ +use crate::version::drive_versions::drive_grove_method_versions::{ + DriveGroveApplyMethodVersions, DriveGroveBasicMethodVersions, DriveGroveBatchMethodVersions, + DriveGroveCostMethodVersions, DriveGroveMethodVersions, +}; + +pub const DRIVE_GROVE_METHOD_VERSIONS_V1: DriveGroveMethodVersions = DriveGroveMethodVersions { + basic: DriveGroveBasicMethodVersions { + grove_insert: 0, + grove_insert_empty_tree: 0, + grove_insert_empty_sum_tree: 0, + grove_insert_if_not_exists: 0, + grove_insert_if_not_exists_return_existing_element: 0, + grove_clear: 0, + grove_delete: 0, + grove_get_raw: 0, + grove_get_raw_optional: 0, + grove_get_raw_value_u64_from_encoded_var_vec: 0, + grove_get: 0, + grove_get_path_query_serialized_results: 0, + grove_get_path_query_serialized_or_sum_results: 0, + grove_get_path_query: 0, + grove_get_path_query_with_optional: 0, + grove_get_raw_path_query_with_optional: 0, + grove_get_raw_path_query: 0, + grove_get_proved_path_query: 0, + grove_get_proved_path_query_with_conditional: 0, + grove_get_sum_tree_total_value: 0, + grove_has_raw: 0, + }, + batch: DriveGroveBatchMethodVersions { + batch_insert_empty_tree: 0, + batch_insert_empty_tree_if_not_exists: 0, + batch_insert_empty_tree_if_not_exists_check_existing_operations: 0, + batch_insert_sum_item_or_add_to_if_already_exists: 0, + batch_insert: 0, + batch_insert_if_not_exists: 0, + batch_insert_if_changed_value: 0, + batch_replace: 0, + batch_delete: 0, + batch_delete_items_in_path_query: 0, + batch_move_items_in_path_query: 0, + batch_remove_raw: 0, + batch_delete_up_tree_while_empty: 0, + batch_refresh_reference: 0, + }, + apply: DriveGroveApplyMethodVersions { + grove_apply_operation: 0, + grove_apply_batch: 0, + grove_apply_partial_batch: 0, + }, + costs: DriveGroveCostMethodVersions { + grove_batch_operations_costs: 0, + }, +}; diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_identity_method_versions/mod.rs b/packages/rs-platform-version/src/version/drive_versions/drive_identity_method_versions/mod.rs new file mode 100644 index 0000000000..c44788e4c3 --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_versions/drive_identity_method_versions/mod.rs @@ -0,0 +1,199 @@ +use versioned_feature_core::{FeatureVersion, OptionalFeatureVersion}; + +pub mod v1; + +#[derive(Clone, Debug, Default)] +pub struct DriveIdentityMethodVersions { + pub fetch: DriveIdentityFetchMethodVersions, + pub prove: DriveIdentityProveMethodVersions, + pub keys: DriveIdentityKeysMethodVersions, + pub update: DriveIdentityUpdateMethodVersions, + pub insert: DriveIdentityInsertMethodVersions, + pub contract_info: DriveIdentityContractInfoMethodVersions, + pub cost_estimation: DriveIdentityCostEstimationMethodVersions, + pub withdrawals: DriveIdentityWithdrawalMethodVersions, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveIdentityWithdrawalMethodVersions { + pub document: DriveIdentityWithdrawalDocumentMethodVersions, + pub transaction: DriveIdentityWithdrawalTransactionMethodVersions, + pub calculate_current_withdrawal_limit: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveIdentityWithdrawalDocumentMethodVersions { + pub fetch_oldest_withdrawal_documents_by_status: FeatureVersion, + pub find_withdrawal_documents_by_status_and_transaction_indices: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveIdentityWithdrawalTransactionMethodVersions { + pub index: DriveIdentityWithdrawalTransactionIndexMethodVersions, + pub queue: DriveIdentityWithdrawalTransactionQueueMethodVersions, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveIdentityWithdrawalTransactionIndexMethodVersions { + pub fetch_next_withdrawal_transaction_index: FeatureVersion, + pub add_update_next_withdrawal_transaction_index_operation: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveIdentityWithdrawalTransactionQueueMethodVersions { + pub add_enqueue_untied_withdrawal_transaction_operations: FeatureVersion, + pub dequeue_untied_withdrawal_transactions: FeatureVersion, + pub remove_broadcasted_withdrawal_transactions_after_completion_operations: FeatureVersion, + pub move_broadcasted_withdrawal_transactions_back_to_queue_operations: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveIdentityContractInfoMethodVersions { + pub add_potential_contract_info_for_contract_bounded_key: FeatureVersion, + pub refresh_potential_contract_info_key_references: FeatureVersion, + pub merge_identity_contract_nonce: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveIdentityCostEstimationMethodVersions { + pub for_authentication_keys_security_level_in_key_reference_tree: FeatureVersion, + pub for_balances: FeatureVersion, + pub for_contract_info: FeatureVersion, + pub for_contract_info_group: FeatureVersion, + pub for_contract_info_group_keys: FeatureVersion, + pub for_contract_info_group_key_purpose: FeatureVersion, + pub for_keys_for_identity_id: FeatureVersion, + pub for_negative_credit: FeatureVersion, + pub for_purpose_in_key_reference_tree: FeatureVersion, + pub for_root_key_reference_tree: FeatureVersion, + pub for_update_revision: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveIdentityFetchMethodVersions { + pub public_key_hashes: DriveIdentityFetchPublicKeyHashesMethodVersions, + pub attributes: DriveIdentityFetchAttributesMethodVersions, + pub partial_identity: DriveIdentityFetchPartialIdentityMethodVersions, + pub full_identity: DriveIdentityFetchFullIdentityMethodVersions, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveIdentityFetchPublicKeyHashesMethodVersions { + pub fetch_full_identities_by_unique_public_key_hashes: FeatureVersion, + pub fetch_full_identity_by_unique_public_key_hash: FeatureVersion, + pub fetch_identity_id_by_unique_public_key_hash: FeatureVersion, + pub fetch_identity_ids_by_non_unique_public_key_hash: FeatureVersion, + pub fetch_identity_ids_by_unique_public_key_hashes: FeatureVersion, + pub fetch_serialized_full_identity_by_unique_public_key_hash: FeatureVersion, + pub has_any_of_unique_public_key_hashes: FeatureVersion, + pub has_non_unique_public_key_hash: FeatureVersion, + pub has_non_unique_public_key_hash_already_for_identity: FeatureVersion, + pub has_unique_public_key_hash: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveIdentityFetchAttributesMethodVersions { + pub revision: FeatureVersion, + pub nonce: FeatureVersion, + pub identity_contract_nonce: FeatureVersion, + pub balance: FeatureVersion, + pub balance_include_debt: FeatureVersion, + pub negative_balance: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveIdentityFetchFullIdentityMethodVersions { + pub fetch_full_identity: OptionalFeatureVersion, + pub fetch_full_identities: OptionalFeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveIdentityFetchPartialIdentityMethodVersions { + pub fetch_identity_revision_with_keys: FeatureVersion, + pub fetch_identity_balance_with_keys: FeatureVersion, + pub fetch_identity_balance_with_keys_and_revision: FeatureVersion, + pub fetch_identity_with_balance: FeatureVersion, + pub fetch_identity_keys: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveIdentityProveMethodVersions { + pub full_identity: FeatureVersion, + pub full_identities: FeatureVersion, + pub identity_nonce: FeatureVersion, + pub identity_contract_nonce: FeatureVersion, + pub identities_contract_keys: FeatureVersion, + pub prove_full_identities_by_unique_public_key_hashes: FeatureVersion, + pub prove_full_identity_by_unique_public_key_hash: FeatureVersion, + pub prove_identity_id_by_unique_public_key_hash: FeatureVersion, + pub prove_identity_ids_by_unique_public_key_hashes: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveIdentityKeysMethodVersions { + pub fetch: DriveIdentityKeysFetchMethodVersions, + pub prove: DriveIdentityKeysProveMethodVersions, + pub insert: DriveIdentityKeysInsertMethodVersions, + pub insert_key_hash_identity_reference: DriveIdentityKeyHashesToIdentityInsertMethodVersions, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveIdentityKeysFetchMethodVersions { + pub fetch_all_current_identity_keys: FeatureVersion, + pub fetch_all_identity_keys: FeatureVersion, + pub fetch_identities_all_keys: FeatureVersion, + pub fetch_identity_keys: FeatureVersion, + pub fetch_identities_contract_keys: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveIdentityKeysProveMethodVersions { + pub prove_identities_all_keys: FeatureVersion, + pub prove_identity_keys: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveIdentityKeysInsertMethodVersions { + pub create_key_tree_with_keys: FeatureVersion, + pub create_new_identity_key_query_trees: FeatureVersion, + pub insert_key_searchable_references: FeatureVersion, + pub insert_key_to_storage: FeatureVersion, + pub insert_new_non_unique_key: FeatureVersion, + pub insert_new_unique_key: FeatureVersion, + pub replace_key_in_storage: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveIdentityKeyHashesToIdentityInsertMethodVersions { + pub add_estimation_costs_for_insert_non_unique_public_key_hash_reference: FeatureVersion, + pub add_estimation_costs_for_insert_unique_public_key_hash_reference: FeatureVersion, + pub insert_non_unique_public_key_hash_reference_to_identity: FeatureVersion, + pub insert_reference_to_non_unique_key: FeatureVersion, + pub insert_reference_to_unique_key: FeatureVersion, + pub insert_unique_public_key_hash_reference_to_identity: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveIdentityInsertMethodVersions { + pub add_new_identity: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveIdentityUpdateMethodVersions { + pub update_identity_revision: FeatureVersion, + pub merge_identity_nonce: FeatureVersion, + pub update_identity_negative_credit_operation: FeatureVersion, + pub initialize_identity_revision: FeatureVersion, + pub disable_identity_keys: FeatureVersion, + pub re_enable_identity_keys: FeatureVersion, + pub add_new_non_unique_keys_to_identity: FeatureVersion, + pub add_new_unique_keys_to_identity: FeatureVersion, + pub add_new_keys_to_identity: FeatureVersion, + pub insert_identity_balance: FeatureVersion, + pub initialize_negative_identity_balance: FeatureVersion, + pub add_to_identity_balance: FeatureVersion, + pub add_to_previous_balance: FeatureVersion, + pub apply_balance_change_from_fee_to_identity: FeatureVersion, + pub remove_from_identity_balance: FeatureVersion, + pub refresh_identity_key_reference_operations: FeatureVersion, +} diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_identity_method_versions/v1.rs b/packages/rs-platform-version/src/version/drive_versions/drive_identity_method_versions/v1.rs new file mode 100644 index 0000000000..098f38ab7c --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_versions/drive_identity_method_versions/v1.rs @@ -0,0 +1,151 @@ +use crate::version::drive_versions::drive_identity_method_versions::{ + DriveIdentityContractInfoMethodVersions, DriveIdentityCostEstimationMethodVersions, + DriveIdentityFetchAttributesMethodVersions, DriveIdentityFetchFullIdentityMethodVersions, + DriveIdentityFetchMethodVersions, DriveIdentityFetchPartialIdentityMethodVersions, + DriveIdentityFetchPublicKeyHashesMethodVersions, DriveIdentityInsertMethodVersions, + DriveIdentityKeyHashesToIdentityInsertMethodVersions, DriveIdentityKeysFetchMethodVersions, + DriveIdentityKeysInsertMethodVersions, DriveIdentityKeysMethodVersions, + DriveIdentityKeysProveMethodVersions, DriveIdentityMethodVersions, + DriveIdentityProveMethodVersions, DriveIdentityUpdateMethodVersions, + DriveIdentityWithdrawalDocumentMethodVersions, DriveIdentityWithdrawalMethodVersions, + DriveIdentityWithdrawalTransactionIndexMethodVersions, + DriveIdentityWithdrawalTransactionMethodVersions, + DriveIdentityWithdrawalTransactionQueueMethodVersions, +}; + +pub const DRIVE_IDENTITY_METHOD_VERSIONS_V1: DriveIdentityMethodVersions = + DriveIdentityMethodVersions { + fetch: DriveIdentityFetchMethodVersions { + public_key_hashes: DriveIdentityFetchPublicKeyHashesMethodVersions { + fetch_full_identities_by_unique_public_key_hashes: 0, + fetch_full_identity_by_unique_public_key_hash: 0, + fetch_identity_id_by_unique_public_key_hash: 0, + fetch_identity_ids_by_non_unique_public_key_hash: 0, + fetch_identity_ids_by_unique_public_key_hashes: 0, + fetch_serialized_full_identity_by_unique_public_key_hash: 0, + has_any_of_unique_public_key_hashes: 0, + has_non_unique_public_key_hash: 0, + has_non_unique_public_key_hash_already_for_identity: 0, + has_unique_public_key_hash: 0, + }, + attributes: DriveIdentityFetchAttributesMethodVersions { + revision: 0, + nonce: 0, + identity_contract_nonce: 0, + balance: 0, + balance_include_debt: 0, + negative_balance: 0, + }, + partial_identity: DriveIdentityFetchPartialIdentityMethodVersions { + fetch_identity_revision_with_keys: 0, + fetch_identity_balance_with_keys: 0, + fetch_identity_balance_with_keys_and_revision: 0, + fetch_identity_with_balance: 0, + fetch_identity_keys: 0, + }, + full_identity: DriveIdentityFetchFullIdentityMethodVersions { + fetch_full_identity: Some(0), + fetch_full_identities: Some(0), + }, + }, + prove: DriveIdentityProveMethodVersions { + full_identity: 0, + full_identities: 0, + identity_nonce: 0, + identity_contract_nonce: 0, + identities_contract_keys: 0, + prove_full_identities_by_unique_public_key_hashes: 0, + prove_full_identity_by_unique_public_key_hash: 0, + prove_identity_id_by_unique_public_key_hash: 0, + prove_identity_ids_by_unique_public_key_hashes: 0, + }, + keys: DriveIdentityKeysMethodVersions { + fetch: DriveIdentityKeysFetchMethodVersions { + fetch_all_current_identity_keys: 0, + fetch_all_identity_keys: 0, + fetch_identities_all_keys: 0, + fetch_identity_keys: 0, + fetch_identities_contract_keys: 0, + }, + prove: DriveIdentityKeysProveMethodVersions { + prove_identities_all_keys: 0, + prove_identity_keys: 0, + }, + insert: DriveIdentityKeysInsertMethodVersions { + create_key_tree_with_keys: 0, + create_new_identity_key_query_trees: 0, + insert_key_searchable_references: 0, + insert_key_to_storage: 0, + insert_new_non_unique_key: 0, + insert_new_unique_key: 0, + replace_key_in_storage: 0, + }, + insert_key_hash_identity_reference: + DriveIdentityKeyHashesToIdentityInsertMethodVersions { + add_estimation_costs_for_insert_non_unique_public_key_hash_reference: 0, + add_estimation_costs_for_insert_unique_public_key_hash_reference: 0, + insert_non_unique_public_key_hash_reference_to_identity: 0, + insert_reference_to_non_unique_key: 0, + insert_reference_to_unique_key: 0, + insert_unique_public_key_hash_reference_to_identity: 0, + }, + }, + update: DriveIdentityUpdateMethodVersions { + update_identity_revision: 0, + merge_identity_nonce: 0, + update_identity_negative_credit_operation: 0, + initialize_identity_revision: 0, + disable_identity_keys: 0, + re_enable_identity_keys: 0, + add_new_non_unique_keys_to_identity: 0, + add_new_unique_keys_to_identity: 0, + add_new_keys_to_identity: 0, + insert_identity_balance: 0, + initialize_negative_identity_balance: 0, + add_to_identity_balance: 0, + add_to_previous_balance: 0, + apply_balance_change_from_fee_to_identity: 0, + remove_from_identity_balance: 0, + refresh_identity_key_reference_operations: 0, + }, + insert: DriveIdentityInsertMethodVersions { + add_new_identity: 0, + }, + contract_info: DriveIdentityContractInfoMethodVersions { + add_potential_contract_info_for_contract_bounded_key: 0, + refresh_potential_contract_info_key_references: 0, + merge_identity_contract_nonce: 0, + }, + cost_estimation: DriveIdentityCostEstimationMethodVersions { + for_authentication_keys_security_level_in_key_reference_tree: 0, + for_balances: 0, + for_contract_info: 0, + for_contract_info_group: 0, + for_contract_info_group_keys: 0, + for_contract_info_group_key_purpose: 0, + for_keys_for_identity_id: 0, + for_negative_credit: 0, + for_purpose_in_key_reference_tree: 0, + for_root_key_reference_tree: 0, + for_update_revision: 0, + }, + withdrawals: DriveIdentityWithdrawalMethodVersions { + document: DriveIdentityWithdrawalDocumentMethodVersions { + fetch_oldest_withdrawal_documents_by_status: 0, + find_withdrawal_documents_by_status_and_transaction_indices: 0, + }, + transaction: DriveIdentityWithdrawalTransactionMethodVersions { + index: DriveIdentityWithdrawalTransactionIndexMethodVersions { + fetch_next_withdrawal_transaction_index: 0, + add_update_next_withdrawal_transaction_index_operation: 0, + }, + queue: DriveIdentityWithdrawalTransactionQueueMethodVersions { + add_enqueue_untied_withdrawal_transaction_operations: 0, + dequeue_untied_withdrawal_transactions: 0, + remove_broadcasted_withdrawal_transactions_after_completion_operations: 0, + move_broadcasted_withdrawal_transactions_back_to_queue_operations: 0, + }, + }, + calculate_current_withdrawal_limit: 0, + }, + }; diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_state_transition_method_versions/mod.rs b/packages/rs-platform-version/src/version/drive_versions/drive_state_transition_method_versions/mod.rs new file mode 100644 index 0000000000..c482548908 --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_versions/drive_state_transition_method_versions/mod.rs @@ -0,0 +1,39 @@ +pub mod v1; + +use crate::version::drive_versions::DriveDataContractOperationMethodVersions; +use versioned_feature_core::FeatureVersion; + +#[derive(Clone, Debug, Default)] +pub struct DriveStateTransitionMethodVersions { + pub operations: DriveStateTransitionOperationMethodVersions, + pub convert_to_high_level_operations: + DriveStateTransitionActionConvertToHighLevelOperationsMethodVersions, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveStateTransitionActionConvertToHighLevelOperationsMethodVersions { + pub data_contract_create_transition: FeatureVersion, + pub data_contract_update_transition: FeatureVersion, + pub document_create_transition: FeatureVersion, + pub document_delete_transition: FeatureVersion, + pub document_purchase_transition: FeatureVersion, + pub document_replace_transition: FeatureVersion, + pub document_transfer_transition: FeatureVersion, + pub document_update_price_transition: FeatureVersion, + pub documents_batch_transition: FeatureVersion, + pub identity_create_transition: FeatureVersion, + pub identity_credit_transfer_transition: FeatureVersion, + pub identity_credit_withdrawal_transition: FeatureVersion, + pub identity_top_up_transition: FeatureVersion, + pub identity_update_transition: FeatureVersion, + pub masternode_vote_transition: FeatureVersion, + pub bump_identity_data_contract_nonce: FeatureVersion, + pub bump_identity_nonce: FeatureVersion, + pub partially_use_asset_lock: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveStateTransitionOperationMethodVersions { + pub finalization_tasks: FeatureVersion, + pub contracts: DriveDataContractOperationMethodVersions, +} diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_state_transition_method_versions/v1.rs b/packages/rs-platform-version/src/version/drive_versions/drive_state_transition_method_versions/v1.rs new file mode 100644 index 0000000000..45e732c99c --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_versions/drive_state_transition_method_versions/v1.rs @@ -0,0 +1,36 @@ +use crate::version::drive_versions::drive_state_transition_method_versions::{ + DriveStateTransitionActionConvertToHighLevelOperationsMethodVersions, + DriveStateTransitionMethodVersions, DriveStateTransitionOperationMethodVersions, +}; +use crate::version::drive_versions::DriveDataContractOperationMethodVersions; + +pub const DRIVE_STATE_TRANSITION_METHOD_VERSIONS_V1: DriveStateTransitionMethodVersions = + DriveStateTransitionMethodVersions { + operations: DriveStateTransitionOperationMethodVersions { + finalization_tasks: 0, + contracts: DriveDataContractOperationMethodVersions { + finalization_tasks: 0, + }, + }, + convert_to_high_level_operations: + DriveStateTransitionActionConvertToHighLevelOperationsMethodVersions { + data_contract_create_transition: 0, + data_contract_update_transition: 0, + document_create_transition: 0, + document_delete_transition: 0, + document_purchase_transition: 0, + document_replace_transition: 0, + document_transfer_transition: 0, + document_update_price_transition: 0, + documents_batch_transition: 0, + identity_create_transition: 0, + identity_credit_transfer_transition: 0, + identity_credit_withdrawal_transition: 0, + identity_top_up_transition: 0, + identity_update_transition: 0, + masternode_vote_transition: 0, + bump_identity_data_contract_nonce: 0, + bump_identity_nonce: 0, + partially_use_asset_lock: 0, + }, + }; diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_structure_version/mod.rs b/packages/rs-platform-version/src/version/drive_versions/drive_structure_version/mod.rs new file mode 100644 index 0000000000..474942c469 --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_versions/drive_structure_version/mod.rs @@ -0,0 +1,10 @@ +use versioned_feature_core::FeatureVersionBounds; + +pub mod v1; + +#[derive(Clone, Debug, Default)] +pub struct DriveStructureVersion { + pub document_indexes: FeatureVersionBounds, + pub identity_indexes: FeatureVersionBounds, + pub pools: FeatureVersionBounds, +} diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_structure_version/v1.rs b/packages/rs-platform-version/src/version/drive_versions/drive_structure_version/v1.rs new file mode 100644 index 0000000000..be8dc19b27 --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_versions/drive_structure_version/v1.rs @@ -0,0 +1,20 @@ +use crate::version::drive_versions::drive_structure_version::DriveStructureVersion; +use versioned_feature_core::FeatureVersionBounds; + +pub const DRIVE_STRUCTURE_V1: DriveStructureVersion = DriveStructureVersion { + document_indexes: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + identity_indexes: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 0, + }, + pools: FeatureVersionBounds { + min_version: 0, + max_version: 0, + default_current_version: 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 new file mode 100644 index 0000000000..39d4255136 --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_versions/drive_verify_method_versions/mod.rs @@ -0,0 +1,76 @@ +use versioned_feature_core::FeatureVersion; + +pub mod v1; + +#[derive(Clone, Debug, Default)] +pub struct DriveVerifyMethodVersions { + pub contract: DriveVerifyContractMethodVersions, + pub document: DriveVerifyDocumentMethodVersions, + pub identity: DriveVerifyIdentityMethodVersions, + pub single_document: DriveVerifySingleDocumentMethodVersions, + pub system: DriveVerifySystemMethodVersions, + pub voting: DriveVerifyVoteMethodVersions, + pub state_transition: DriveVerifyStateTransitionMethodVersions, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveVerifyContractMethodVersions { + pub verify_contract: FeatureVersion, + pub verify_contract_history: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveVerifyDocumentMethodVersions { + pub verify_proof: FeatureVersion, + pub verify_proof_keep_serialized: FeatureVersion, + pub verify_start_at_document_in_proof: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveVerifyIdentityMethodVersions { + pub verify_full_identities_by_public_key_hashes: FeatureVersion, + pub verify_full_identity_by_identity_id: FeatureVersion, + pub verify_full_identity_by_public_key_hash: FeatureVersion, + pub verify_identity_balance_for_identity_id: FeatureVersion, + pub verify_identity_balances_for_identity_ids: FeatureVersion, + pub verify_identity_id_by_public_key_hash: FeatureVersion, + pub verify_identity_ids_by_public_key_hashes: FeatureVersion, + pub verify_identity_keys_by_identity_id: FeatureVersion, + pub verify_identity_nonce: FeatureVersion, + pub verify_identity_contract_nonce: FeatureVersion, + pub verify_identities_contract_keys: FeatureVersion, + pub verify_identity_revision_for_identity_id: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveVerifyVoteMethodVersions { + pub verify_masternode_vote: FeatureVersion, + pub verify_start_at_contender_in_proof: FeatureVersion, + pub verify_vote_poll_votes_proof: FeatureVersion, + pub verify_identity_votes_given_proof: FeatureVersion, + pub verify_vote_poll_vote_state_proof: FeatureVersion, + pub verify_contests_proof: FeatureVersion, + pub verify_vote_polls_by_end_date_proof: FeatureVersion, + pub verify_specialized_balance: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveVerifySystemMethodVersions { + pub verify_epoch_infos: FeatureVersion, + pub verify_epoch_proposers: FeatureVersion, + pub verify_elements: FeatureVersion, + pub verify_total_credits_in_system: FeatureVersion, + pub verify_upgrade_state: FeatureVersion, + pub verify_upgrade_vote_status: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveVerifySingleDocumentMethodVersions { + pub verify_proof: FeatureVersion, + pub verify_proof_keep_serialized: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveVerifyStateTransitionMethodVersions { + pub verify_state_transition_was_executed_with_proof: 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 new file mode 100644 index 0000000000..4c40371f83 --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_versions/drive_verify_method_versions/v1.rs @@ -0,0 +1,57 @@ +use crate::version::drive_versions::drive_verify_method_versions::{ + DriveVerifyContractMethodVersions, DriveVerifyDocumentMethodVersions, + DriveVerifyIdentityMethodVersions, DriveVerifyMethodVersions, + DriveVerifySingleDocumentMethodVersions, DriveVerifyStateTransitionMethodVersions, + DriveVerifySystemMethodVersions, DriveVerifyVoteMethodVersions, +}; + +pub const DRIVE_VERIFY_METHOD_VERSIONS_V1: DriveVerifyMethodVersions = DriveVerifyMethodVersions { + contract: DriveVerifyContractMethodVersions { + verify_contract: 0, + verify_contract_history: 0, + }, + document: DriveVerifyDocumentMethodVersions { + verify_proof: 0, + verify_proof_keep_serialized: 0, + verify_start_at_document_in_proof: 0, + }, + identity: DriveVerifyIdentityMethodVersions { + verify_full_identities_by_public_key_hashes: 0, + verify_full_identity_by_identity_id: 0, + verify_full_identity_by_public_key_hash: 0, + verify_identity_balance_for_identity_id: 0, + verify_identity_balances_for_identity_ids: 0, + verify_identity_id_by_public_key_hash: 0, + verify_identity_ids_by_public_key_hashes: 0, + verify_identity_keys_by_identity_id: 0, + verify_identity_nonce: 0, + verify_identity_contract_nonce: 0, + verify_identities_contract_keys: 0, + verify_identity_revision_for_identity_id: 0, + }, + single_document: DriveVerifySingleDocumentMethodVersions { + verify_proof: 0, + verify_proof_keep_serialized: 0, + }, + system: DriveVerifySystemMethodVersions { + verify_epoch_infos: 0, + verify_epoch_proposers: 0, + verify_elements: 0, + verify_total_credits_in_system: 0, + verify_upgrade_state: 0, + verify_upgrade_vote_status: 0, + }, + voting: DriveVerifyVoteMethodVersions { + verify_masternode_vote: 0, + verify_start_at_contender_in_proof: 0, + verify_vote_poll_votes_proof: 0, + verify_identity_votes_given_proof: 0, + verify_vote_poll_vote_state_proof: 0, + verify_contests_proof: 0, + verify_vote_polls_by_end_date_proof: 0, + verify_specialized_balance: 0, + }, + state_transition: DriveVerifyStateTransitionMethodVersions { + verify_state_transition_was_executed_with_proof: 0, + }, +}; diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_vote_method_versions/mod.rs b/packages/rs-platform-version/src/version/drive_versions/drive_vote_method_versions/mod.rs new file mode 100644 index 0000000000..825b062905 --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_versions/drive_vote_method_versions/mod.rs @@ -0,0 +1,56 @@ +use versioned_feature_core::FeatureVersion; + +pub mod v1; +pub mod v2; + +#[derive(Clone, Debug, Default)] +pub struct DriveVoteMethodVersions { + pub insert: DriveVoteInsertMethodVersions, + pub contested_resource_insert: DriveVoteContestedResourceInsertMethodVersions, + pub cleanup: DriveVoteCleanupMethodVersions, + pub setup: DriveVoteSetupMethodVersions, + pub storage_form: DriveVoteStorageFormMethodVersions, + pub fetch: DriveVoteFetchMethodVersions, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveVoteFetchMethodVersions { + pub fetch_identities_voting_for_contenders: FeatureVersion, + pub fetch_contested_document_vote_poll_stored_info: FeatureVersion, + pub fetch_identity_contested_resource_vote: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveVoteStorageFormMethodVersions { + pub resolve_with_contract: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveVoteSetupMethodVersions { + pub add_initial_vote_tree_main_structure_operations: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveVoteCleanupMethodVersions { + pub remove_specific_vote_references_given_by_identity: FeatureVersion, + pub remove_specific_votes_given_by_identity: FeatureVersion, + pub remove_contested_resource_vote_poll_end_date_query_operations: FeatureVersion, + pub remove_contested_resource_vote_poll_votes_operations: FeatureVersion, + pub remove_contested_resource_vote_poll_documents_operations: FeatureVersion, + pub remove_contested_resource_vote_poll_contenders_operations: FeatureVersion, + pub remove_contested_resource_top_level_index_operations: FeatureVersion, + pub remove_contested_resource_info_operations: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveVoteInsertMethodVersions { + pub register_identity_vote: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveVoteContestedResourceInsertMethodVersions { + pub register_contested_resource_identity_vote: FeatureVersion, + pub insert_stored_info_for_contested_resource_vote_poll: FeatureVersion, + pub register_identity_vote: FeatureVersion, + pub add_vote_poll_end_date_query_operations: FeatureVersion, +} diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_vote_method_versions/v1.rs b/packages/rs-platform-version/src/version/drive_versions/drive_vote_method_versions/v1.rs new file mode 100644 index 0000000000..1e7a59dd95 --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_versions/drive_vote_method_versions/v1.rs @@ -0,0 +1,38 @@ +use crate::version::drive_versions::drive_vote_method_versions::{ + DriveVoteCleanupMethodVersions, DriveVoteContestedResourceInsertMethodVersions, + DriveVoteFetchMethodVersions, DriveVoteInsertMethodVersions, DriveVoteMethodVersions, + DriveVoteSetupMethodVersions, DriveVoteStorageFormMethodVersions, +}; + +pub const DRIVE_VOTE_METHOD_VERSIONS_V1: DriveVoteMethodVersions = DriveVoteMethodVersions { + insert: DriveVoteInsertMethodVersions { + register_identity_vote: 0, + }, + contested_resource_insert: DriveVoteContestedResourceInsertMethodVersions { + register_contested_resource_identity_vote: 0, + insert_stored_info_for_contested_resource_vote_poll: 0, + register_identity_vote: 0, + add_vote_poll_end_date_query_operations: 0, + }, + cleanup: DriveVoteCleanupMethodVersions { + remove_specific_vote_references_given_by_identity: 0, + remove_specific_votes_given_by_identity: 0, + remove_contested_resource_vote_poll_end_date_query_operations: 0, + remove_contested_resource_vote_poll_votes_operations: 0, + remove_contested_resource_vote_poll_documents_operations: 0, + remove_contested_resource_vote_poll_contenders_operations: 0, + remove_contested_resource_top_level_index_operations: 0, + remove_contested_resource_info_operations: 0, + }, + setup: DriveVoteSetupMethodVersions { + add_initial_vote_tree_main_structure_operations: 0, + }, + storage_form: DriveVoteStorageFormMethodVersions { + resolve_with_contract: 0, + }, + fetch: DriveVoteFetchMethodVersions { + fetch_identities_voting_for_contenders: 0, + fetch_contested_document_vote_poll_stored_info: 0, + fetch_identity_contested_resource_vote: 0, + }, +}; diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_vote_method_versions/v2.rs b/packages/rs-platform-version/src/version/drive_versions/drive_vote_method_versions/v2.rs new file mode 100644 index 0000000000..ef99612f58 --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_versions/drive_vote_method_versions/v2.rs @@ -0,0 +1,38 @@ +use crate::version::drive_versions::drive_vote_method_versions::{ + DriveVoteCleanupMethodVersions, DriveVoteContestedResourceInsertMethodVersions, + DriveVoteFetchMethodVersions, DriveVoteInsertMethodVersions, DriveVoteMethodVersions, + DriveVoteSetupMethodVersions, DriveVoteStorageFormMethodVersions, +}; + +pub const DRIVE_VOTE_METHOD_VERSIONS_V2: DriveVoteMethodVersions = DriveVoteMethodVersions { + insert: DriveVoteInsertMethodVersions { + register_identity_vote: 0, + }, + contested_resource_insert: DriveVoteContestedResourceInsertMethodVersions { + register_contested_resource_identity_vote: 0, + insert_stored_info_for_contested_resource_vote_poll: 0, + register_identity_vote: 0, + add_vote_poll_end_date_query_operations: 0, + }, + cleanup: DriveVoteCleanupMethodVersions { + remove_specific_vote_references_given_by_identity: 0, + remove_specific_votes_given_by_identity: 0, + remove_contested_resource_vote_poll_end_date_query_operations: 1, + remove_contested_resource_vote_poll_votes_operations: 0, + remove_contested_resource_vote_poll_documents_operations: 1, + remove_contested_resource_vote_poll_contenders_operations: 1, + remove_contested_resource_top_level_index_operations: 0, + remove_contested_resource_info_operations: 0, + }, + setup: DriveVoteSetupMethodVersions { + add_initial_vote_tree_main_structure_operations: 0, + }, + storage_form: DriveVoteStorageFormMethodVersions { + resolve_with_contract: 0, + }, + fetch: DriveVoteFetchMethodVersions { + fetch_identities_voting_for_contenders: 0, + fetch_contested_document_vote_poll_stored_info: 0, + fetch_identity_contested_resource_vote: 0, + }, +}; diff --git a/packages/rs-platform-version/src/version/drive_versions/mod.rs b/packages/rs-platform-version/src/version/drive_versions/mod.rs new file mode 100644 index 0000000000..b8c3fae487 --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_versions/mod.rs @@ -0,0 +1,161 @@ +use crate::version::FeatureVersion; +use drive_contract_method_versions::DriveContractMethodVersions; +use drive_credit_pool_method_versions::DriveCreditPoolMethodVersions; +use drive_document_method_versions::DriveDocumentMethodVersions; +use drive_grove_method_versions::DriveGroveMethodVersions; +use drive_identity_method_versions::DriveIdentityMethodVersions; +use drive_state_transition_method_versions::DriveStateTransitionMethodVersions; +use drive_structure_version::DriveStructureVersion; +use drive_verify_method_versions::DriveVerifyMethodVersions; +use drive_vote_method_versions::DriveVoteMethodVersions; +use grovedb_version::version::GroveVersion; + +pub mod drive_contract_method_versions; +pub mod drive_credit_pool_method_versions; +pub mod drive_document_method_versions; +pub mod drive_grove_method_versions; +pub mod drive_identity_method_versions; +pub mod drive_state_transition_method_versions; +pub mod drive_structure_version; +pub mod drive_verify_method_versions; +pub mod drive_vote_method_versions; +pub mod v1; +pub mod v2; + +#[derive(Clone, Debug, Default)] +pub struct DriveVersion { + pub structure: DriveStructureVersion, + pub methods: DriveMethodVersions, + pub grove_methods: DriveGroveMethodVersions, + pub grove_version: GroveVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveMethodVersions { + pub initialization: DriveInitializationMethodVersions, + pub credit_pools: DriveCreditPoolMethodVersions, + pub protocol_upgrade: DriveProtocolUpgradeVersions, + pub prefunded_specialized_balances: DrivePrefundedSpecializedMethodVersions, + pub balances: DriveBalancesMethodVersions, + pub document: DriveDocumentMethodVersions, + pub vote: DriveVoteMethodVersions, + pub contract: DriveContractMethodVersions, + pub fees: DriveFeesMethodVersions, + pub estimated_costs: DriveEstimatedCostsMethodVersions, + pub asset_lock: DriveAssetLockMethodVersions, + pub verify: DriveVerifyMethodVersions, + pub identity: DriveIdentityMethodVersions, + pub platform_system: DrivePlatformSystemMethodVersions, + pub operations: DriveOperationsMethodVersion, + pub batch_operations: DriveBatchOperationsMethodVersion, + pub fetch: DriveFetchMethodVersions, + pub prove: DriveProveMethodVersions, + pub state_transitions: DriveStateTransitionMethodVersions, + pub platform_state: DrivePlatformStateMethodVersions, +} + +#[derive(Clone, Debug, Default)] +pub struct DrivePlatformStateMethodVersions { + pub fetch_platform_state_bytes: FeatureVersion, + pub store_platform_state_bytes: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveDataContractOperationMethodVersions { + pub finalization_tasks: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveFetchMethodVersions { + pub fetch_elements: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveProveMethodVersions { + pub prove_elements: FeatureVersion, + pub prove_multiple_state_transition_results: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DrivePrefundedSpecializedMethodVersions { + pub fetch_single: FeatureVersion, + pub prove_single: FeatureVersion, + pub add_prefunded_specialized_balance: FeatureVersion, + pub add_prefunded_specialized_balance_operations: FeatureVersion, + pub deduct_from_prefunded_specialized_balance: FeatureVersion, + pub deduct_from_prefunded_specialized_balance_operations: FeatureVersion, + pub estimated_cost_for_prefunded_specialized_balance_update: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveBalancesMethodVersions { + pub add_to_system_credits: FeatureVersion, + pub add_to_system_credits_operations: FeatureVersion, + pub remove_from_system_credits: FeatureVersion, + pub remove_from_system_credits_operations: FeatureVersion, + pub calculate_total_credits_balance: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveAssetLockMethodVersions { + pub add_asset_lock_outpoint: FeatureVersion, + pub add_estimation_costs_for_adding_asset_lock: FeatureVersion, + pub fetch_asset_lock_outpoint_info: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveFeesMethodVersions { + pub calculate_fee: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DrivePlatformSystemMethodVersions { + pub estimation_costs: DriveSystemEstimationCostsMethodVersions, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveOperationsMethodVersion { + pub rollback_transaction: FeatureVersion, + pub drop_cache: FeatureVersion, + pub commit_transaction: FeatureVersion, + pub apply_partial_batch_low_level_drive_operations: FeatureVersion, + pub apply_partial_batch_grovedb_operations: FeatureVersion, + pub apply_batch_low_level_drive_operations: FeatureVersion, + pub apply_batch_grovedb_operations: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveBatchOperationsMethodVersion { + pub convert_drive_operations_to_grove_operations: FeatureVersion, + pub apply_drive_operations: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveSystemEstimationCostsMethodVersions { + pub for_total_system_credits_update: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveInitializationMethodVersions { + pub create_initial_state_structure: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveProtocolUpgradeVersions { + pub clear_version_information: FeatureVersion, + pub fetch_versions_with_counter: FeatureVersion, + pub fetch_proved_versions_with_counter: FeatureVersion, + pub fetch_validator_version_votes: FeatureVersion, + pub fetch_proved_validator_version_votes: FeatureVersion, + pub remove_validators_proposed_app_versions: FeatureVersion, + pub update_validator_proposed_app_version: FeatureVersion, +} + +#[derive(Clone, Debug, Default)] +pub struct DriveEstimatedCostsMethodVersions { + pub add_estimation_costs_for_levels_up_to_contract: FeatureVersion, + pub add_estimation_costs_for_levels_up_to_contract_document_type_excluded: FeatureVersion, + pub add_estimation_costs_for_contested_document_tree_levels_up_to_contract: FeatureVersion, + pub add_estimation_costs_for_contested_document_tree_levels_up_to_contract_document_type_excluded: + FeatureVersion, +} diff --git a/packages/rs-platform-version/src/version/drive_versions/v1.rs b/packages/rs-platform-version/src/version/drive_versions/v1.rs new file mode 100644 index 0000000000..bbe1a12746 --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_versions/v1.rs @@ -0,0 +1,100 @@ +use crate::version::drive_versions::drive_contract_method_versions::v1::DRIVE_CONTRACT_METHOD_VERSIONS_V1; +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::v1::DRIVE_DOCUMENT_METHOD_VERSIONS_V1; +use crate::version::drive_versions::drive_grove_method_versions::v1::DRIVE_GROVE_METHOD_VERSIONS_V1; +use crate::version::drive_versions::drive_identity_method_versions::v1::DRIVE_IDENTITY_METHOD_VERSIONS_V1; +use crate::version::drive_versions::drive_state_transition_method_versions::v1::DRIVE_STATE_TRANSITION_METHOD_VERSIONS_V1; +use crate::version::drive_versions::drive_structure_version::v1::DRIVE_STRUCTURE_V1; +use crate::version::drive_versions::drive_verify_method_versions::v1::DRIVE_VERIFY_METHOD_VERSIONS_V1; +use crate::version::drive_versions::drive_vote_method_versions::v1::DRIVE_VOTE_METHOD_VERSIONS_V1; +use crate::version::drive_versions::{ + DriveAssetLockMethodVersions, DriveBalancesMethodVersions, DriveBatchOperationsMethodVersion, + DriveEstimatedCostsMethodVersions, DriveFeesMethodVersions, DriveFetchMethodVersions, + DriveInitializationMethodVersions, DriveMethodVersions, DriveOperationsMethodVersion, + DrivePlatformStateMethodVersions, DrivePlatformSystemMethodVersions, + DrivePrefundedSpecializedMethodVersions, DriveProtocolUpgradeVersions, + DriveProveMethodVersions, DriveSystemEstimationCostsMethodVersions, DriveVersion, +}; +use grovedb_version::version::v1::GROVE_V1; + +pub const DRIVE_VERSION_V1: DriveVersion = DriveVersion { + structure: DRIVE_STRUCTURE_V1, + methods: DriveMethodVersions { + initialization: DriveInitializationMethodVersions { + create_initial_state_structure: 0, + }, + credit_pools: CREDIT_POOL_METHOD_VERSIONS_V1, + protocol_upgrade: DriveProtocolUpgradeVersions { + clear_version_information: 0, + fetch_versions_with_counter: 0, + fetch_proved_versions_with_counter: 0, + fetch_validator_version_votes: 0, + fetch_proved_validator_version_votes: 0, + remove_validators_proposed_app_versions: 0, + update_validator_proposed_app_version: 0, + }, + prove: DriveProveMethodVersions { + prove_elements: 0, + prove_multiple_state_transition_results: 0, + }, + balances: DriveBalancesMethodVersions { + add_to_system_credits: 0, + add_to_system_credits_operations: 0, + remove_from_system_credits: 0, + remove_from_system_credits_operations: 0, + calculate_total_credits_balance: 0, + }, + document: DRIVE_DOCUMENT_METHOD_VERSIONS_V1, + vote: DRIVE_VOTE_METHOD_VERSIONS_V1, + contract: DRIVE_CONTRACT_METHOD_VERSIONS_V1, + fees: DriveFeesMethodVersions { calculate_fee: 0 }, + estimated_costs: DriveEstimatedCostsMethodVersions { + add_estimation_costs_for_levels_up_to_contract: 0, + add_estimation_costs_for_levels_up_to_contract_document_type_excluded: 0, + add_estimation_costs_for_contested_document_tree_levels_up_to_contract: 0, + add_estimation_costs_for_contested_document_tree_levels_up_to_contract_document_type_excluded: 0, + }, + asset_lock: DriveAssetLockMethodVersions { + add_asset_lock_outpoint: 0, + add_estimation_costs_for_adding_asset_lock: 0, + fetch_asset_lock_outpoint_info: 0, + }, + verify: DRIVE_VERIFY_METHOD_VERSIONS_V1, + identity: DRIVE_IDENTITY_METHOD_VERSIONS_V1, + platform_system: DrivePlatformSystemMethodVersions { + estimation_costs: DriveSystemEstimationCostsMethodVersions { + for_total_system_credits_update: 0, + }, + }, + operations: DriveOperationsMethodVersion { + rollback_transaction: 0, + drop_cache: 0, + commit_transaction: 0, + apply_partial_batch_low_level_drive_operations: 0, + apply_partial_batch_grovedb_operations: 0, + apply_batch_low_level_drive_operations: 0, + apply_batch_grovedb_operations: 0, + }, + state_transitions: DRIVE_STATE_TRANSITION_METHOD_VERSIONS_V1, + batch_operations: DriveBatchOperationsMethodVersion { + convert_drive_operations_to_grove_operations: 0, + apply_drive_operations: 0, + }, + platform_state: DrivePlatformStateMethodVersions { + fetch_platform_state_bytes: 0, + store_platform_state_bytes: 0, + }, + fetch: DriveFetchMethodVersions { fetch_elements: 0 }, + prefunded_specialized_balances: DrivePrefundedSpecializedMethodVersions { + fetch_single: 0, + prove_single: 0, + add_prefunded_specialized_balance: 0, + add_prefunded_specialized_balance_operations: 0, + deduct_from_prefunded_specialized_balance: 0, + deduct_from_prefunded_specialized_balance_operations: 0, + estimated_cost_for_prefunded_specialized_balance_update: 0, + }, + }, + grove_methods: DRIVE_GROVE_METHOD_VERSIONS_V1, + grove_version: GROVE_V1, +}; diff --git a/packages/rs-platform-version/src/version/drive_versions/v2.rs b/packages/rs-platform-version/src/version/drive_versions/v2.rs new file mode 100644 index 0000000000..5747bc732b --- /dev/null +++ b/packages/rs-platform-version/src/version/drive_versions/v2.rs @@ -0,0 +1,100 @@ +use crate::version::drive_versions::drive_contract_method_versions::v1::DRIVE_CONTRACT_METHOD_VERSIONS_V1; +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::v1::DRIVE_DOCUMENT_METHOD_VERSIONS_V1; +use crate::version::drive_versions::drive_grove_method_versions::v1::DRIVE_GROVE_METHOD_VERSIONS_V1; +use crate::version::drive_versions::drive_identity_method_versions::v1::DRIVE_IDENTITY_METHOD_VERSIONS_V1; +use crate::version::drive_versions::drive_state_transition_method_versions::v1::DRIVE_STATE_TRANSITION_METHOD_VERSIONS_V1; +use crate::version::drive_versions::drive_structure_version::v1::DRIVE_STRUCTURE_V1; +use crate::version::drive_versions::drive_verify_method_versions::v1::DRIVE_VERIFY_METHOD_VERSIONS_V1; +use crate::version::drive_versions::drive_vote_method_versions::v2::DRIVE_VOTE_METHOD_VERSIONS_V2; +use crate::version::drive_versions::{ + DriveAssetLockMethodVersions, DriveBalancesMethodVersions, DriveBatchOperationsMethodVersion, + DriveEstimatedCostsMethodVersions, DriveFeesMethodVersions, DriveFetchMethodVersions, + DriveInitializationMethodVersions, DriveMethodVersions, DriveOperationsMethodVersion, + DrivePlatformStateMethodVersions, DrivePlatformSystemMethodVersions, + DrivePrefundedSpecializedMethodVersions, DriveProtocolUpgradeVersions, + DriveProveMethodVersions, DriveSystemEstimationCostsMethodVersions, DriveVersion, +}; +use grovedb_version::version::v1::GROVE_V1; + +pub const DRIVE_VERSION_V2: DriveVersion = DriveVersion { + structure: DRIVE_STRUCTURE_V1, + methods: DriveMethodVersions { + initialization: DriveInitializationMethodVersions { + create_initial_state_structure: 0, + }, + credit_pools: CREDIT_POOL_METHOD_VERSIONS_V1, + protocol_upgrade: DriveProtocolUpgradeVersions { + clear_version_information: 0, + fetch_versions_with_counter: 0, + fetch_proved_versions_with_counter: 0, + fetch_validator_version_votes: 0, + fetch_proved_validator_version_votes: 0, + remove_validators_proposed_app_versions: 0, + update_validator_proposed_app_version: 0, + }, + prove: DriveProveMethodVersions { + prove_elements: 0, + prove_multiple_state_transition_results: 0, + }, + balances: DriveBalancesMethodVersions { + add_to_system_credits: 0, + add_to_system_credits_operations: 0, + remove_from_system_credits: 0, + remove_from_system_credits_operations: 0, + calculate_total_credits_balance: 0, + }, + document: DRIVE_DOCUMENT_METHOD_VERSIONS_V1, + vote: DRIVE_VOTE_METHOD_VERSIONS_V2, + contract: DRIVE_CONTRACT_METHOD_VERSIONS_V1, + fees: DriveFeesMethodVersions { calculate_fee: 0 }, + estimated_costs: DriveEstimatedCostsMethodVersions { + add_estimation_costs_for_levels_up_to_contract: 0, + add_estimation_costs_for_levels_up_to_contract_document_type_excluded: 0, + add_estimation_costs_for_contested_document_tree_levels_up_to_contract: 0, + add_estimation_costs_for_contested_document_tree_levels_up_to_contract_document_type_excluded: 0, + }, + asset_lock: DriveAssetLockMethodVersions { + add_asset_lock_outpoint: 0, + add_estimation_costs_for_adding_asset_lock: 0, + fetch_asset_lock_outpoint_info: 0, + }, + verify: DRIVE_VERIFY_METHOD_VERSIONS_V1, + identity: DRIVE_IDENTITY_METHOD_VERSIONS_V1, + platform_system: DrivePlatformSystemMethodVersions { + estimation_costs: DriveSystemEstimationCostsMethodVersions { + for_total_system_credits_update: 0, + }, + }, + operations: DriveOperationsMethodVersion { + rollback_transaction: 0, + drop_cache: 0, + commit_transaction: 0, + apply_partial_batch_low_level_drive_operations: 0, + apply_partial_batch_grovedb_operations: 0, + apply_batch_low_level_drive_operations: 0, + apply_batch_grovedb_operations: 0, + }, + state_transitions: DRIVE_STATE_TRANSITION_METHOD_VERSIONS_V1, + batch_operations: DriveBatchOperationsMethodVersion { + convert_drive_operations_to_grove_operations: 0, + apply_drive_operations: 0, + }, + platform_state: DrivePlatformStateMethodVersions { + fetch_platform_state_bytes: 0, + store_platform_state_bytes: 0, + }, + fetch: DriveFetchMethodVersions { fetch_elements: 0 }, + prefunded_specialized_balances: DrivePrefundedSpecializedMethodVersions { + fetch_single: 0, + prove_single: 0, + add_prefunded_specialized_balance: 0, + add_prefunded_specialized_balance_operations: 0, + deduct_from_prefunded_specialized_balance: 0, + deduct_from_prefunded_specialized_balance_operations: 0, + estimated_cost_for_prefunded_specialized_balance_update: 0, + }, + }, + grove_methods: DRIVE_GROVE_METHOD_VERSIONS_V1, + grove_version: GROVE_V1, +}; diff --git a/packages/rs-platform-version/src/version/fee/mod.rs b/packages/rs-platform-version/src/version/fee/mod.rs index c868a3028d..735e1b5146 100644 --- a/packages/rs-platform-version/src/version/fee/mod.rs +++ b/packages/rs-platform-version/src/version/fee/mod.rs @@ -1,9 +1,13 @@ +use crate::error::PlatformVersionError; use crate::version::fee::data_contract::FeeDataContractValidationVersion; use crate::version::fee::hashing::FeeHashingVersion; -use crate::version::fee::processing::FeeProcessingVersion; +use crate::version::fee::processing::{ + FeeProcessingVersion, FeeProcessingVersionFieldsBeforeVersion1Point4, +}; use crate::version::fee::signature::FeeSignatureVersion; use crate::version::fee::state_transition_min_fees::StateTransitionMinFees; use crate::version::fee::storage::FeeStorageVersion; +use crate::version::fee::v1::FEE_VERSION1; use crate::version::fee::vote_resolution_fund_fees::VoteResolutionFundFees; use bincode::{Decode, Encode}; @@ -16,8 +20,13 @@ pub mod storage; pub mod v1; pub mod vote_resolution_fund_fees; +pub type FeeVersionNumber = u32; + +pub const FEE_VERSIONS: &[FeeVersion] = &[FEE_VERSION1]; + #[derive(Clone, Debug, Encode, Decode, Default, PartialEq, Eq)] pub struct FeeVersion { + pub fee_version_number: FeeVersionNumber, // Permille means devise by 1000 pub uses_version_fee_multiplier_permille: Option, pub storage: FeeStorageVersion, @@ -29,135 +38,70 @@ pub struct FeeVersion { pub vote_resolution_fund_fees: VoteResolutionFundFees, } -#[cfg(test)] -mod tests { - use super::FeeVersion; - use crate::version::fee::data_contract::FeeDataContractValidationVersion; - use crate::version::fee::hashing::FeeHashingVersion; - use crate::version::fee::processing::FeeProcessingVersion; - use crate::version::fee::signature::FeeSignatureVersion; - use crate::version::fee::state_transition_min_fees::StateTransitionMinFees; - use crate::version::fee::storage::FeeStorageVersion; - use crate::version::fee::vote_resolution_fund_fees::VoteResolutionFundFees; +impl FeeVersion { + pub fn as_static(&self) -> &'static FeeVersion { + FeeVersion::get(self.fee_version_number).expect("expected fee version to exist") + } + pub fn get<'a>(version: FeeVersionNumber) -> Result<&'a Self, PlatformVersionError> { + if version > 0 { + FEE_VERSIONS.get(version as usize - 1).ok_or_else(|| { + PlatformVersionError::UnknownVersionError(format!("no fee version {version}")) + }) + } else { + Err(PlatformVersionError::UnknownVersionError(format!( + "no fee version {version}" + ))) + } + } + + pub fn get_optional<'a>(version: FeeVersionNumber) -> Option<&'a Self> { + if version > 0 { + FEE_VERSIONS.get(version as usize - 1) + } else { + None + } + } + + pub fn first<'a>() -> &'a Self { + FEE_VERSIONS + .first() + .expect("expected to have a fee version") + } - #[test] - // If this test failed, then a new field was added in FeeVersion. And the corresponding eq needs to be updated as well - fn test_fee_version_equality() { - let version1 = FeeVersion { - uses_version_fee_multiplier_permille: None, - storage: FeeStorageVersion { - storage_disk_usage_credit_per_byte: 1, - storage_processing_credit_per_byte: 2, - storage_load_credit_per_byte: 3, - non_storage_load_credit_per_byte: 4, - storage_seek_cost: 5, - }, - signature: FeeSignatureVersion { - verify_signature_ecdsa_secp256k1: 1, - verify_signature_bls12_381: 2, - verify_signature_ecdsa_hash160: 3, - verify_signature_bip13_script_hash: 4, - verify_signature_eddsa25519_hash160: 5, - }, - hashing: FeeHashingVersion { - single_sha256_base: 1, - blake3_base: 2, - sha256_ripe_md160_base: 3, - sha256_per_block: 4, - blake3_per_block: 5, - }, - processing: FeeProcessingVersion { - fetch_identity_balance_processing_cost: 1, - fetch_identity_revision_processing_cost: 2, - fetch_identity_balance_and_revision_processing_cost: 3, - fetch_identity_cost_per_look_up_key_by_id: 4, - fetch_single_identity_key_processing_cost: 5, - validate_key_structure: 6, - fetch_prefunded_specialized_balance_processing_cost: 7, - }, - data_contract: FeeDataContractValidationVersion { - document_type_base_fee: 1, - document_type_size_fee: 2, - document_type_per_property_fee: 3, - document_type_base_non_unique_index_fee: 4, - document_type_non_unique_index_per_property_fee: 5, - document_type_base_unique_index_fee: 6, - document_type_unique_index_per_property_fee: 7, - }, - state_transition_min_fees: StateTransitionMinFees { - credit_transfer: 1, - credit_withdrawal: 2, - identity_update: 3, - document_batch_sub_transition: 4, - contract_create: 5, - contract_update: 6, - masternode_vote: 7, - }, - vote_resolution_fund_fees: VoteResolutionFundFees { - contested_document_vote_resolution_fund_required_amount: 1, - contested_document_vote_resolution_unlock_fund_required_amount: 2, - contested_document_single_vote_cost: 3, - }, - }; + pub fn latest<'a>() -> &'a Self { + FEE_VERSIONS.last().expect("expected to have a fee version") + } +} - let version2 = FeeVersion { - uses_version_fee_multiplier_permille: None, - storage: FeeStorageVersion { - storage_disk_usage_credit_per_byte: 1, - storage_processing_credit_per_byte: 2, - storage_load_credit_per_byte: 3, - non_storage_load_credit_per_byte: 4, - storage_seek_cost: 5, - }, - signature: FeeSignatureVersion { - verify_signature_ecdsa_secp256k1: 1, - verify_signature_bls12_381: 2, - verify_signature_ecdsa_hash160: 3, - verify_signature_bip13_script_hash: 4, - verify_signature_eddsa25519_hash160: 5, - }, - hashing: FeeHashingVersion { - single_sha256_base: 1, - blake3_base: 2, - sha256_ripe_md160_base: 3, - sha256_per_block: 4, - blake3_per_block: 5, - }, - processing: FeeProcessingVersion { - fetch_identity_balance_processing_cost: 1, - fetch_identity_revision_processing_cost: 2, - fetch_identity_balance_and_revision_processing_cost: 3, - fetch_identity_cost_per_look_up_key_by_id: 4, - fetch_single_identity_key_processing_cost: 5, - validate_key_structure: 6, - fetch_prefunded_specialized_balance_processing_cost: 7, - }, - data_contract: FeeDataContractValidationVersion { - document_type_base_fee: 1, - document_type_size_fee: 2, - document_type_per_property_fee: 3, - document_type_base_non_unique_index_fee: 4, - document_type_non_unique_index_per_property_fee: 5, - document_type_base_unique_index_fee: 6, - document_type_unique_index_per_property_fee: 7, - }, - state_transition_min_fees: StateTransitionMinFees { - credit_transfer: 1, - credit_withdrawal: 2, - identity_update: 3, - document_batch_sub_transition: 4, - contract_create: 5, - contract_update: 6, - masternode_vote: 7, - }, - vote_resolution_fund_fees: VoteResolutionFundFees { - contested_document_vote_resolution_fund_required_amount: 1, - contested_document_vote_resolution_unlock_fund_required_amount: 2, - contested_document_single_vote_cost: 3, - }, - }; +// This is type only meant for deserialization because of an issue +// The issue was that the platform state was stored with FeeVersions in it before version 1.4 +// When we would add new fields we would be unable to deserialize +// This FeeProcessingVersionFieldsBeforeVersion4 is how things were before version 1.4 was released +#[derive(Clone, Debug, Encode, Decode, Default, PartialEq, Eq)] +pub struct FeeVersionFieldsBeforeVersion4 { + // Permille means devise by 1000 + pub uses_version_fee_multiplier_permille: Option, + pub storage: FeeStorageVersion, + pub signature: FeeSignatureVersion, + pub hashing: FeeHashingVersion, + pub processing: FeeProcessingVersionFieldsBeforeVersion1Point4, + pub data_contract: FeeDataContractValidationVersion, + pub state_transition_min_fees: StateTransitionMinFees, + pub vote_resolution_fund_fees: VoteResolutionFundFees, +} - // This assertion will check if all fields are considered in the equality comparison - assert_eq!(version1, version2, "FeeVersion equality test failed. If a field was added or removed, update the Eq implementation."); +impl From for FeeVersion { + fn from(value: FeeVersionFieldsBeforeVersion4) -> Self { + FeeVersion { + fee_version_number: 1, + uses_version_fee_multiplier_permille: value.uses_version_fee_multiplier_permille, + storage: value.storage, + signature: value.signature, + hashing: value.hashing, + processing: FeeProcessingVersion::from(value.processing), + data_contract: value.data_contract, + state_transition_min_fees: value.state_transition_min_fees, + vote_resolution_fund_fees: value.vote_resolution_fund_fees, + } } } diff --git a/packages/rs-platform-version/src/version/fee/processing/mod.rs b/packages/rs-platform-version/src/version/fee/processing/mod.rs index 0427cd0916..a4f33696c0 100644 --- a/packages/rs-platform-version/src/version/fee/processing/mod.rs +++ b/packages/rs-platform-version/src/version/fee/processing/mod.rs @@ -1,3 +1,4 @@ +use crate::version::fee::v1::FEE_VERSION1; use bincode::{Decode, Encode}; pub mod v1; @@ -11,36 +12,41 @@ pub struct FeeProcessingVersion { pub fetch_prefunded_specialized_balance_processing_cost: u64, pub fetch_single_identity_key_processing_cost: u64, pub validate_key_structure: u64, + pub perform_network_threshold_signing: u64, } -#[cfg(test)] -mod tests { - use super::FeeProcessingVersion; - - #[test] - // If this test failed, then a new field was added in FeeProcessingVersion. And the corresponding eq needs to be updated as well - fn test_fee_processing_version_equality() { - let version1 = FeeProcessingVersion { - fetch_identity_balance_processing_cost: 1, - fetch_identity_revision_processing_cost: 2, - fetch_identity_balance_and_revision_processing_cost: 3, - fetch_identity_cost_per_look_up_key_by_id: 4, - fetch_single_identity_key_processing_cost: 5, - validate_key_structure: 6, - fetch_prefunded_specialized_balance_processing_cost: 7, - }; - - let version2 = FeeProcessingVersion { - fetch_identity_balance_processing_cost: 1, - fetch_identity_revision_processing_cost: 2, - fetch_identity_balance_and_revision_processing_cost: 3, - fetch_identity_cost_per_look_up_key_by_id: 4, - fetch_single_identity_key_processing_cost: 5, - validate_key_structure: 6, - fetch_prefunded_specialized_balance_processing_cost: 7, - }; +// This is type only meant for deserialization because of an issue +// The issue was that the platform state was stored with FeeVersions in it before version 1.4 +// When we would add new fields we would be unable to deserialize +// This FeeProcessingVersionFieldsBeforeVersion4 is how things were before version 1.4 was released +#[derive(Clone, Debug, Encode, Decode, Default, PartialEq, Eq)] +pub struct FeeProcessingVersionFieldsBeforeVersion1Point4 { + pub fetch_identity_balance_processing_cost: u64, + pub fetch_identity_revision_processing_cost: u64, + pub fetch_identity_balance_and_revision_processing_cost: u64, + pub fetch_identity_cost_per_look_up_key_by_id: u64, + pub fetch_prefunded_specialized_balance_processing_cost: u64, + pub fetch_single_identity_key_processing_cost: u64, + pub validate_key_structure: u64, +} - // This assertion will check if all fields are considered in the equality comparison - assert_eq!(version1, version2, "FeeProcessingVersion equality test failed. If a field was added or removed, update the Eq implementation."); +impl From for FeeProcessingVersion { + fn from(old: FeeProcessingVersionFieldsBeforeVersion1Point4) -> Self { + FeeProcessingVersion { + fetch_identity_balance_processing_cost: old.fetch_identity_balance_processing_cost, + fetch_identity_revision_processing_cost: old.fetch_identity_revision_processing_cost, + fetch_identity_balance_and_revision_processing_cost: old + .fetch_identity_balance_and_revision_processing_cost, + fetch_identity_cost_per_look_up_key_by_id: old + .fetch_identity_cost_per_look_up_key_by_id, + fetch_prefunded_specialized_balance_processing_cost: old + .fetch_prefunded_specialized_balance_processing_cost, + fetch_single_identity_key_processing_cost: old + .fetch_single_identity_key_processing_cost, + validate_key_structure: old.validate_key_structure, + perform_network_threshold_signing: FEE_VERSION1 + .processing + .perform_network_threshold_signing, + } } } diff --git a/packages/rs-platform-version/src/version/fee/processing/v1.rs b/packages/rs-platform-version/src/version/fee/processing/v1.rs index dbedd153d9..b6ba5ca998 100644 --- a/packages/rs-platform-version/src/version/fee/processing/v1.rs +++ b/packages/rs-platform-version/src/version/fee/processing/v1.rs @@ -7,5 +7,6 @@ pub const FEE_PROCESSING_VERSION1: FeeProcessingVersion = FeeProcessingVersion { fetch_identity_cost_per_look_up_key_by_id: 9000, fetch_prefunded_specialized_balance_processing_cost: 10000, fetch_single_identity_key_processing_cost: 10000, + perform_network_threshold_signing: 100000000, // 1mDash (2.5 cents at 25$/Dash) validate_key_structure: 50, }; diff --git a/packages/rs-platform-version/src/version/fee/state_transition_min_fees/v1.rs b/packages/rs-platform-version/src/version/fee/state_transition_min_fees/v1.rs index 5f759e50fc..5fbfdbbfe6 100644 --- a/packages/rs-platform-version/src/version/fee/state_transition_min_fees/v1.rs +++ b/packages/rs-platform-version/src/version/fee/state_transition_min_fees/v1.rs @@ -2,7 +2,7 @@ use crate::version::fee::state_transition_min_fees::StateTransitionMinFees; pub const STATE_TRANSITION_MIN_FEES_VERSION1: StateTransitionMinFees = StateTransitionMinFees { credit_transfer: 100000, - credit_withdrawal: 100000, + credit_withdrawal: 400000000, //credit withdrawals are more expensive that the rest identity_update: 100000, document_batch_sub_transition: 100000, contract_create: 100000, diff --git a/packages/rs-platform-version/src/version/fee/v1.rs b/packages/rs-platform-version/src/version/fee/v1.rs index dc5a976e11..fe43f0464c 100644 --- a/packages/rs-platform-version/src/version/fee/v1.rs +++ b/packages/rs-platform-version/src/version/fee/v1.rs @@ -8,6 +8,7 @@ use crate::version::fee::vote_resolution_fund_fees::v1::VOTE_RESOLUTION_FUND_FEE use crate::version::fee::FeeVersion; pub const FEE_VERSION1: FeeVersion = FeeVersion { + fee_version_number: 1, uses_version_fee_multiplier_permille: Some(1000), //No action storage: FEE_STORAGE_VERSION1, signature: FEE_SIGNATURE_VERSION1, diff --git a/packages/rs-platform-version/src/version/mocks/v2_test.rs b/packages/rs-platform-version/src/version/mocks/v2_test.rs index a23140000b..931ef19b97 100644 --- a/packages/rs-platform-version/src/version/mocks/v2_test.rs +++ b/packages/rs-platform-version/src/version/mocks/v2_test.rs @@ -1,153 +1,63 @@ use crate::version::consensus_versions::ConsensusVersions; -use crate::version::contracts::SystemDataContractVersions; -use crate::version::dpp_versions::{ - AssetLockVersions, ContractVersions, CostVersions, DPPMethodVersions, DPPValidationVersions, - DPPVersion, DataContractMethodVersions, DataContractValidationVersions, - DocumentFeatureVersionBounds, DocumentMethodVersions, DocumentTransitionVersions, - DocumentTypeClassMethodVersions, DocumentTypeIndexVersions, DocumentTypeMethodVersions, - DocumentTypeSchemaVersions, DocumentTypeValidationVersions, DocumentTypeVersions, - DocumentVersions, DocumentsBatchTransitionValidationVersions, DocumentsBatchTransitionVersions, - IdentityKeyTypeMethodVersions, IdentityTransitionAssetLockVersions, IdentityTransitionVersions, - IdentityVersions, JsonSchemaValidatorVersions, PublicKeyInCreationMethodVersions, - RecursiveSchemaValidatorVersions, StateTransitionConversionVersions, - StateTransitionMethodVersions, StateTransitionSerializationVersions, StateTransitionVersions, - VotingValidationVersions, VotingVersions, -}; -use crate::version::drive_abci_versions::{ - DriveAbciAssetLockValidationVersions, DriveAbciBlockEndMethodVersions, - DriveAbciBlockFeeProcessingMethodVersions, DriveAbciBlockStartMethodVersions, - DriveAbciCoreBasedUpdatesMethodVersions, DriveAbciCoreChainLockMethodVersionsAndConstants, - DriveAbciCoreInstantSendLockMethodVersions, - DriveAbciDocumentsStateTransitionValidationVersions, DriveAbciEngineMethodVersions, - DriveAbciEpochMethodVersions, DriveAbciFeePoolInwardsDistributionMethodVersions, - DriveAbciFeePoolOutwardsDistributionMethodVersions, - DriveAbciIdentityCreditWithdrawalMethodVersions, DriveAbciInitializationMethodVersions, - DriveAbciMasternodeIdentitiesUpdatesMethodVersions, DriveAbciMethodVersions, - DriveAbciPlatformStateStorageMethodVersions, DriveAbciProtocolUpgradeMethodVersions, +use crate::version::dpp_versions::dpp_asset_lock_versions::v1::DPP_ASSET_LOCK_VERSIONS_V1; +use crate::version::dpp_versions::dpp_contract_versions::v1::CONTRACT_VERSIONS_V1; +use crate::version::dpp_versions::dpp_costs_versions::v1::DPP_COSTS_VERSIONS_V1; +use crate::version::dpp_versions::dpp_document_versions::v1::DOCUMENT_VERSIONS_V1; +use crate::version::dpp_versions::dpp_factory_versions::v1::DPP_FACTORY_VERSIONS_V1; +use crate::version::dpp_versions::dpp_identity_versions::v1::IDENTITY_VERSIONS_V1; +use crate::version::dpp_versions::dpp_method_versions::v1::DPP_METHOD_VERSIONS_V1; +use crate::version::dpp_versions::dpp_state_transition_conversion_versions::v1::STATE_TRANSITION_CONVERSION_VERSIONS_V1; +use crate::version::dpp_versions::dpp_state_transition_method_versions::v1::STATE_TRANSITION_METHOD_VERSIONS_V1; +use crate::version::dpp_versions::dpp_state_transition_serialization_versions::v1::STATE_TRANSITION_SERIALIZATION_VERSIONS_V1; +use crate::version::dpp_versions::dpp_state_transition_versions::v1::STATE_TRANSITION_VERSIONS_V1; +use crate::version::dpp_versions::dpp_validation_versions::v2::DPP_VALIDATION_VERSIONS_V2; +use crate::version::dpp_versions::dpp_voting_versions::v2::VOTING_VERSION_V2; +use crate::version::dpp_versions::DPPVersion; +use crate::version::drive_abci_versions::drive_abci_method_versions::v1::DRIVE_ABCI_METHOD_VERSIONS_V1; +use crate::version::drive_abci_versions::drive_abci_query_versions::{ DriveAbciQueryDataContractVersions, DriveAbciQueryIdentityVersions, DriveAbciQueryPrefundedSpecializedBalancesVersions, DriveAbciQuerySystemVersions, DriveAbciQueryValidatorVersions, DriveAbciQueryVersions, DriveAbciQueryVotingVersions, - DriveAbciStateTransitionCommonValidationVersions, - DriveAbciStateTransitionProcessingMethodVersions, DriveAbciStateTransitionValidationVersion, - DriveAbciStateTransitionValidationVersions, DriveAbciStructureVersions, - DriveAbciValidationConstants, DriveAbciValidationDataTriggerAndBindingVersions, - DriveAbciValidationDataTriggerVersions, DriveAbciValidationVersions, DriveAbciVersion, - DriveAbciVotingMethodVersions, PenaltyAmounts, }; +use crate::version::drive_abci_versions::drive_abci_structure_versions::v1::DRIVE_ABCI_STRUCTURE_VERSIONS_V1; +use crate::version::drive_abci_versions::drive_abci_validation_versions::v1::DRIVE_ABCI_VALIDATION_VERSIONS_V1; +use crate::version::drive_abci_versions::drive_abci_withdrawal_constants::v1::DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V1; +use crate::version::drive_abci_versions::DriveAbciVersion; +use crate::version::drive_versions::drive_contract_method_versions::v1::DRIVE_CONTRACT_METHOD_VERSIONS_V1; +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::v1::DRIVE_DOCUMENT_METHOD_VERSIONS_V1; +use crate::version::drive_versions::drive_grove_method_versions::v1::DRIVE_GROVE_METHOD_VERSIONS_V1; +use crate::version::drive_versions::drive_identity_method_versions::v1::DRIVE_IDENTITY_METHOD_VERSIONS_V1; +use crate::version::drive_versions::drive_state_transition_method_versions::v1::DRIVE_STATE_TRANSITION_METHOD_VERSIONS_V1; +use crate::version::drive_versions::drive_structure_version::v1::DRIVE_STRUCTURE_V1; +use crate::version::drive_versions::drive_verify_method_versions::v1::DRIVE_VERIFY_METHOD_VERSIONS_V1; +use crate::version::drive_versions::drive_vote_method_versions::v1::DRIVE_VOTE_METHOD_VERSIONS_V1; use crate::version::drive_versions::{ DriveAssetLockMethodVersions, DriveBalancesMethodVersions, DriveBatchOperationsMethodVersion, - DriveContractApplyMethodVersions, DriveContractCostsMethodVersions, - DriveContractGetMethodVersions, DriveContractInsertMethodVersions, DriveContractMethodVersions, - DriveContractProveMethodVersions, DriveContractUpdateMethodVersions, - DriveCreditPoolEpochsMethodVersions, DriveCreditPoolMethodVersions, - DriveCreditPoolPendingEpochRefundsMethodVersions, - DriveCreditPoolStorageFeeDistributionPoolMethodVersions, - DriveCreditPoolUnpaidEpochMethodVersions, DriveDataContractOperationMethodVersions, - DriveDocumentDeleteMethodVersions, DriveDocumentEstimationCostsMethodVersions, - DriveDocumentIndexUniquenessMethodVersions, DriveDocumentInsertContestedMethodVersions, - DriveDocumentInsertMethodVersions, DriveDocumentMethodVersions, - DriveDocumentQueryMethodVersions, DriveDocumentUpdateMethodVersions, DriveEstimatedCostsMethodVersions, DriveFeesMethodVersions, DriveFetchMethodVersions, - DriveGroveApplyMethodVersions, DriveGroveBasicMethodVersions, DriveGroveBatchMethodVersions, - DriveGroveCostMethodVersions, DriveGroveMethodVersions, - DriveIdentityContractInfoMethodVersions, DriveIdentityCostEstimationMethodVersions, - DriveIdentityFetchAttributesMethodVersions, DriveIdentityFetchFullIdentityMethodVersions, - DriveIdentityFetchMethodVersions, DriveIdentityFetchPartialIdentityMethodVersions, - DriveIdentityFetchPublicKeyHashesMethodVersions, DriveIdentityInsertMethodVersions, - DriveIdentityKeyHashesToIdentityInsertMethodVersions, DriveIdentityKeysFetchMethodVersions, - DriveIdentityKeysInsertMethodVersions, DriveIdentityKeysMethodVersions, - DriveIdentityKeysProveMethodVersions, DriveIdentityMethodVersions, - DriveIdentityProveMethodVersions, DriveIdentityUpdateMethodVersions, - DriveIdentityWithdrawalDocumentMethodVersions, DriveIdentityWithdrawalMethodVersions, - DriveIdentityWithdrawalTransactionIndexMethodVersions, - DriveIdentityWithdrawalTransactionMethodVersions, - DriveIdentityWithdrawalTransactionQueueMethodVersions, DriveInitializationMethodVersions, - DriveMethodVersions, DriveOperationsMethodVersion, DrivePlatformStateMethodVersions, - DrivePlatformSystemMethodVersions, DrivePrefundedSpecializedMethodVersions, - DriveProtocolUpgradeVersions, DriveProveMethodVersions, - DriveStateTransitionActionConvertToHighLevelOperationsMethodVersions, - DriveStateTransitionMethodVersions, DriveStateTransitionOperationMethodVersions, - DriveStructureVersion, DriveSystemEstimationCostsMethodVersions, - DriveVerifyContractMethodVersions, DriveVerifyDocumentMethodVersions, - DriveVerifyIdentityMethodVersions, DriveVerifyMethodVersions, - DriveVerifySingleDocumentMethodVersions, DriveVerifyStateTransitionMethodVersions, - DriveVerifySystemMethodVersions, DriveVerifyVoteMethodVersions, DriveVersion, - DriveVoteCleanupMethodVersions, DriveVoteContestedResourceInsertMethodVersions, - DriveVoteFetchMethodVersions, DriveVoteInsertMethodVersions, DriveVoteMethodVersions, - DriveVoteSetupMethodVersions, DriveVoteStorageFormMethodVersions, + DriveInitializationMethodVersions, DriveMethodVersions, DriveOperationsMethodVersion, + DrivePlatformStateMethodVersions, DrivePlatformSystemMethodVersions, + DrivePrefundedSpecializedMethodVersions, DriveProtocolUpgradeVersions, + DriveProveMethodVersions, DriveSystemEstimationCostsMethodVersions, DriveVersion, }; use crate::version::fee::v1::FEE_VERSION1; -use crate::version::limits::SystemLimits; use crate::version::mocks::TEST_PROTOCOL_VERSION_SHIFT_BYTES; use crate::version::protocol_version::{FeatureVersionBounds, PlatformVersion}; -use crate::version::PlatformArchitectureVersion; +use crate::version::system_data_contract_versions::v1::SYSTEM_DATA_CONTRACT_VERSIONS_V1; +use crate::version::system_limits::SystemLimits; use grovedb_version::version::v1::GROVE_V1; pub const TEST_PROTOCOL_VERSION_2: u32 = (1 << TEST_PROTOCOL_VERSION_SHIFT_BYTES) + 2; pub const TEST_PLATFORM_V2: PlatformVersion = PlatformVersion { protocol_version: TEST_PROTOCOL_VERSION_2, - proofs: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, drive: DriveVersion { - structure: DriveStructureVersion { - document_indexes: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_indexes: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - pools: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, + structure: DRIVE_STRUCTURE_V1, methods: DriveMethodVersions { initialization: DriveInitializationMethodVersions { create_initial_state_structure: 0, }, - credit_pools: DriveCreditPoolMethodVersions { - epochs: DriveCreditPoolEpochsMethodVersions { - get_epochs_infos: 0, - get_epochs_protocol_versions: 0, - prove_epochs_infos: 0, - get_epoch_fee_multiplier: 0, - get_epoch_processing_credits_for_distribution: 0, - get_epoch_storage_credits_for_distribution: 0, - get_epoch_total_credits_for_distribution: 0, - get_storage_credits_for_distribution_for_epochs_in_range: 0, - get_epoch_start_time: 0, - get_epoch_start_block_core_height: 0, - get_epoch_start_block_height: 0, - get_first_epoch_start_block_info_between_epochs: 0, - fetch_epoch_proposers: 0, - prove_epoch_proposers: 0, - get_epochs_proposer_block_count: 0, - add_update_pending_epoch_refunds_operations: 0, - is_epochs_proposers_tree_empty: 0, - }, - pending_epoch_refunds: DriveCreditPoolPendingEpochRefundsMethodVersions { - add_delete_pending_epoch_refunds_except_specified: 0, - fetch_and_add_pending_epoch_refunds_to_collection: 0, - fetch_pending_epoch_refunds: 0, - add_update_pending_epoch_refunds_operations: 0, - }, - storage_fee_distribution_pool: - DriveCreditPoolStorageFeeDistributionPoolMethodVersions { - get_storage_fees_from_distribution_pool: 0, - }, - unpaid_epoch: DriveCreditPoolUnpaidEpochMethodVersions { - get_unpaid_epoch_index: 0, - }, - }, + credit_pools: CREDIT_POOL_METHOD_VERSIONS_V1, protocol_upgrade: DriveProtocolUpgradeVersions { clear_version_information: 0, fetch_versions_with_counter: 0, @@ -168,123 +78,9 @@ pub const TEST_PLATFORM_V2: PlatformVersion = PlatformVersion { remove_from_system_credits_operations: 0, calculate_total_credits_balance: 0, }, - document: DriveDocumentMethodVersions { - query: DriveDocumentQueryMethodVersions { query_documents: 0, query_contested_documents: 0, query_contested_documents_vote_state: 0, query_documents_with_flags: 0 }, - delete: DriveDocumentDeleteMethodVersions { - add_estimation_costs_for_remove_document_to_primary_storage: 0, - delete_document_for_contract: 0, - delete_document_for_contract_id: 0, - delete_document_for_contract_apply_and_add_to_operations: 0, - remove_document_from_primary_storage: 0, - remove_reference_for_index_level_for_contract_operations: 0, - remove_indices_for_index_level_for_contract_operations: 0, - remove_indices_for_top_index_level_for_contract_operations: 0, - delete_document_for_contract_id_with_named_type_operations: 0, - delete_document_for_contract_with_named_type_operations: 0, - delete_document_for_contract_operations: 0, - }, - insert: DriveDocumentInsertMethodVersions { - add_document: 0, - add_document_for_contract: 0, - add_document_for_contract_apply_and_add_to_operations: 0, - add_document_for_contract_operations: 0, - add_document_to_primary_storage: 0, - add_indices_for_index_level_for_contract_operations: 0, - add_indices_for_top_index_level_for_contract_operations: 0, - add_reference_for_index_level_for_contract_operations: 0, - }, - insert_contested: DriveDocumentInsertContestedMethodVersions { - add_contested_document: 0, - add_contested_document_for_contract: 0, - add_contested_document_for_contract_apply_and_add_to_operations: 0, - add_contested_document_for_contract_operations: 0, - add_contested_document_to_primary_storage: 0, - add_contested_indices_for_contract_operations: 0, - add_contested_reference_and_vote_subtree_to_document_operations: 0, - add_contested_vote_subtree_for_non_identities_operations: 0, - }, - update: DriveDocumentUpdateMethodVersions { - add_update_multiple_documents_operations: 0, - update_document_for_contract: 0, - update_document_for_contract_apply_and_add_to_operations: 0, - update_document_for_contract_id: 0, - update_document_for_contract_operations: 0, - update_document_with_serialization_for_contract: 0, - update_serialized_document_for_contract: 0, - }, - estimation_costs: DriveDocumentEstimationCostsMethodVersions { - add_estimation_costs_for_add_document_to_primary_storage: 0, - add_estimation_costs_for_add_contested_document_to_primary_storage: 0, - stateless_delete_of_non_tree_for_costs: 0, - }, - index_uniqueness: DriveDocumentIndexUniquenessMethodVersions { - validate_document_uniqueness: 0, - validate_document_create_transition_action_uniqueness: 0, - validate_document_replace_transition_action_uniqueness: 0, - validate_document_transfer_transition_action_uniqueness: 0, - validate_document_purchase_transition_action_uniqueness: 0, - validate_document_update_price_transition_action_uniqueness: 0, - validate_uniqueness_of_data: 0, - }, - }, - vote: DriveVoteMethodVersions { - insert: DriveVoteInsertMethodVersions { - register_identity_vote: 0, - }, - contested_resource_insert: DriveVoteContestedResourceInsertMethodVersions { - register_contested_resource_identity_vote: 0, - insert_stored_info_for_contested_resource_vote_poll: 0, - register_identity_vote: 0, - add_vote_poll_end_date_query_operations: 0, - }, - cleanup: DriveVoteCleanupMethodVersions { - remove_specific_vote_references_given_by_identity: 0, - remove_specific_votes_given_by_identity: 0, - remove_contested_resource_vote_poll_end_date_query_operations: 0, - remove_contested_resource_vote_poll_votes_operations: 0, - remove_contested_resource_vote_poll_documents_operations: 0, - remove_contested_resource_vote_poll_contenders_operations: 0, - remove_contested_resource_top_level_index_operations: 0, - remove_contested_resource_info_operations: 0, - }, - setup: DriveVoteSetupMethodVersions { - add_initial_vote_tree_main_structure_operations: 0, - }, - storage_form: DriveVoteStorageFormMethodVersions { - resolve_with_contract: 0, - }, - fetch: DriveVoteFetchMethodVersions { - fetch_identities_voting_for_contenders: 0, - fetch_contested_document_vote_poll_stored_info: 0, - fetch_identity_contested_resource_vote: 0, - }, - }, - contract: 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: 0, - }, - update: DriveContractUpdateMethodVersions { update_contract: 0 }, - costs: DriveContractCostsMethodVersions { - add_estimation_costs_for_contract_insertion: 0, - }, - get: DriveContractGetMethodVersions { - fetch_contract: 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, - }, - }, + document: DRIVE_DOCUMENT_METHOD_VERSIONS_V1, + vote: DRIVE_VOTE_METHOD_VERSIONS_V1, + contract: DRIVE_CONTRACT_METHOD_VERSIONS_V1, fees: DriveFeesMethodVersions { calculate_fee: 0 }, estimated_costs: DriveEstimatedCostsMethodVersions { add_estimation_costs_for_levels_up_to_contract: 0, @@ -297,188 +93,8 @@ pub const TEST_PLATFORM_V2: PlatformVersion = PlatformVersion { add_estimation_costs_for_adding_asset_lock: 0, fetch_asset_lock_outpoint_info: 0, }, - verify: DriveVerifyMethodVersions { - contract: DriveVerifyContractMethodVersions { - verify_contract: 0, - verify_contract_history: 0, - }, - document: DriveVerifyDocumentMethodVersions { - verify_proof: 0, - verify_proof_keep_serialized: 0, - verify_start_at_document_in_proof: 0, - }, - identity: DriveVerifyIdentityMethodVersions { - verify_full_identities_by_public_key_hashes: 0, - verify_full_identity_by_identity_id: 0, - verify_full_identity_by_public_key_hash: 0, - verify_identity_balance_for_identity_id: 0, - verify_identity_balances_for_identity_ids: 0, - verify_identity_id_by_public_key_hash: 0, - verify_identity_ids_by_public_key_hashes: 0, - verify_identity_keys_by_identity_id: 0, - verify_identity_nonce: 0, - verify_identity_contract_nonce: 0, - verify_identities_contract_keys: 0, - verify_identity_revision_for_identity_id: 0, - }, - single_document: DriveVerifySingleDocumentMethodVersions { - verify_proof: 0, - verify_proof_keep_serialized: 0, - }, - system: DriveVerifySystemMethodVersions { - verify_epoch_infos: 0, - verify_epoch_proposers: 0, - verify_elements: 0, - verify_total_credits_in_system: 0, - verify_upgrade_state: 0, - verify_upgrade_vote_status: 0, - }, - voting: DriveVerifyVoteMethodVersions { - verify_masternode_vote: 0, - verify_start_at_contender_in_proof: 0, - verify_vote_poll_votes_proof: 0, - verify_identity_votes_given_proof: 0, - verify_vote_poll_vote_state_proof: 0, - verify_contests_proof: 0, - verify_vote_polls_by_end_date_proof: 0, - verify_specialized_balance: 0, - }, - state_transition: DriveVerifyStateTransitionMethodVersions { - verify_state_transition_was_executed_with_proof: 0, - }, - }, - identity: DriveIdentityMethodVersions { - fetch: DriveIdentityFetchMethodVersions { - public_key_hashes: DriveIdentityFetchPublicKeyHashesMethodVersions { - fetch_full_identities_by_unique_public_key_hashes: 0, - fetch_full_identity_by_unique_public_key_hash: 0, - fetch_identity_id_by_unique_public_key_hash: 0, - fetch_identity_ids_by_non_unique_public_key_hash: 0, - fetch_identity_ids_by_unique_public_key_hashes: 0, - fetch_serialized_full_identity_by_unique_public_key_hash: 0, - has_any_of_unique_public_key_hashes: 0, - has_non_unique_public_key_hash: 0, - has_non_unique_public_key_hash_already_for_identity: 0, - has_unique_public_key_hash: 0, - }, - attributes: DriveIdentityFetchAttributesMethodVersions { - revision: 0, - nonce: 0, - identity_contract_nonce: 0, - balance: 0, - balance_include_debt: 0, - negative_balance: 0, - }, - partial_identity: DriveIdentityFetchPartialIdentityMethodVersions { - fetch_identity_revision_with_keys: 0, - fetch_identity_balance_with_keys: 0, - fetch_identity_balance_with_keys_and_revision: 0, - fetch_identity_with_balance: 0, - fetch_identity_keys: 0, - }, - full_identity: DriveIdentityFetchFullIdentityMethodVersions { - fetch_full_identity: Some(0), - fetch_full_identities: Some(0), - }, - }, - prove: DriveIdentityProveMethodVersions { - full_identity: 0, - full_identities: 0, - identity_nonce: 0, - identity_contract_nonce: 0, - identities_contract_keys: 0, - prove_full_identities_by_unique_public_key_hashes: 0, - prove_full_identity_by_unique_public_key_hash: 0, - prove_identity_id_by_unique_public_key_hash: 0, - prove_identity_ids_by_unique_public_key_hashes: 0, - }, - keys: DriveIdentityKeysMethodVersions { - fetch: DriveIdentityKeysFetchMethodVersions { - fetch_all_current_identity_keys: 0, - fetch_all_identity_keys: 0, - fetch_identities_all_keys: 0, - fetch_identity_keys: 0, - fetch_identities_contract_keys: 0, - }, - prove: DriveIdentityKeysProveMethodVersions { - prove_identities_all_keys: 0, - prove_identity_keys: 0, - }, - insert: DriveIdentityKeysInsertMethodVersions { - create_key_tree_with_keys: 0, - create_new_identity_key_query_trees: 0, - insert_key_searchable_references: 0, - insert_key_to_storage: 0, - insert_new_non_unique_key: 0, - insert_new_unique_key: 0, - replace_key_in_storage: 0, - }, - insert_key_hash_identity_reference: - DriveIdentityKeyHashesToIdentityInsertMethodVersions { - add_estimation_costs_for_insert_non_unique_public_key_hash_reference: 0, - add_estimation_costs_for_insert_unique_public_key_hash_reference: 0, - insert_non_unique_public_key_hash_reference_to_identity: 0, - insert_reference_to_non_unique_key: 0, - insert_reference_to_unique_key: 0, - insert_unique_public_key_hash_reference_to_identity: 0, - }, - }, - update: DriveIdentityUpdateMethodVersions { - update_identity_revision: 0, - merge_identity_nonce: 0, - update_identity_negative_credit_operation: 0, - initialize_identity_revision: 0, - disable_identity_keys: 0, - re_enable_identity_keys: 0, - add_new_non_unique_keys_to_identity: 0, - add_new_unique_keys_to_identity: 0, - add_new_keys_to_identity: 0, - insert_identity_balance: 0, - initialize_negative_identity_balance: 0, - add_to_identity_balance: 0, - add_to_previous_balance: 0, - apply_balance_change_from_fee_to_identity: 0, - remove_from_identity_balance: 0, - refresh_identity_key_reference_operations: 0, - }, - insert: DriveIdentityInsertMethodVersions { - add_new_identity: 0, - }, - contract_info: DriveIdentityContractInfoMethodVersions { - add_potential_contract_info_for_contract_bounded_key: 0, - refresh_potential_contract_info_key_references: 0, - merge_identity_contract_nonce: 0, - }, - cost_estimation: DriveIdentityCostEstimationMethodVersions { - for_authentication_keys_security_level_in_key_reference_tree: 0, - for_balances: 0, - for_contract_info: 0, - for_contract_info_group: 0, - for_contract_info_group_keys: 0, - for_contract_info_group_key_purpose: 0, - for_keys_for_identity_id: 0, - for_negative_credit: 0, - for_purpose_in_key_reference_tree: 0, - for_root_key_reference_tree: 0, - for_update_revision: 0, - }, - withdrawals: DriveIdentityWithdrawalMethodVersions { - document: DriveIdentityWithdrawalDocumentMethodVersions { - fetch_oldest_withdrawal_documents_by_status: 0, - find_up_to_100_withdrawal_documents_by_status_and_transaction_indices: 0, - }, - transaction: DriveIdentityWithdrawalTransactionMethodVersions { - index: DriveIdentityWithdrawalTransactionIndexMethodVersions { - fetch_next_withdrawal_transaction_index: 0, - add_update_next_withdrawal_transaction_index_operation: 0, - }, - queue: DriveIdentityWithdrawalTransactionQueueMethodVersions { - add_enqueue_untied_withdrawal_transaction_operations: 0, - dequeue_untied_withdrawal_transactions: 0, - }, - }, - }, - }, + verify: DRIVE_VERIFY_METHOD_VERSIONS_V1, + identity: DRIVE_IDENTITY_METHOD_VERSIONS_V1, platform_system: DrivePlatformSystemMethodVersions { estimation_costs: DriveSystemEstimationCostsMethodVersions { for_total_system_credits_update: 0, @@ -497,35 +113,7 @@ pub const TEST_PLATFORM_V2: PlatformVersion = PlatformVersion { convert_drive_operations_to_grove_operations: 0, apply_drive_operations: 0, }, - state_transitions: DriveStateTransitionMethodVersions { - operations: DriveStateTransitionOperationMethodVersions { - finalization_tasks: 0, - contracts: DriveDataContractOperationMethodVersions { - finalization_tasks: 0, - }, - }, - convert_to_high_level_operations: - DriveStateTransitionActionConvertToHighLevelOperationsMethodVersions { - data_contract_create_transition: 0, - data_contract_update_transition: 0, - document_create_transition: 0, - document_delete_transition: 0, - document_purchase_transition: 0, - document_replace_transition: 0, - document_transfer_transition: 0, - document_update_price_transition: 0, - documents_batch_transition: 0, - identity_create_transition: 0, - identity_credit_transfer_transition: 0, - identity_credit_withdrawal_transition: 0, - identity_top_up_transition: 0, - identity_update_transition: 0, - masternode_vote_transition: 0, - bump_identity_data_contract_nonce: 0, - bump_identity_nonce: 0, - partially_use_asset_lock: 0, - }, - }, + state_transitions: DRIVE_STATE_TRANSITION_METHOD_VERSIONS_V1, platform_state: DrivePlatformStateMethodVersions { fetch_platform_state_bytes: 0, store_platform_state_bytes: 0, @@ -541,308 +129,14 @@ pub const TEST_PLATFORM_V2: PlatformVersion = PlatformVersion { estimated_cost_for_prefunded_specialized_balance_update: 0, }, }, - grove_methods: DriveGroveMethodVersions { - basic: DriveGroveBasicMethodVersions { - grove_insert: 0, - grove_insert_empty_tree: 0, - grove_insert_empty_sum_tree: 0, - grove_insert_if_not_exists: 0, - grove_clear: 0, - grove_delete: 0, - grove_get_raw: 0, - grove_get_raw_optional: 0, - grove_get_raw_value_u64_from_encoded_var_vec: 0, - grove_get: 0, - grove_get_path_query_serialized_results: 0, - grove_get_path_query_serialized_or_sum_results: 0, - grove_get_path_query: 0, - grove_get_path_query_with_optional: 0, - grove_get_raw_path_query_with_optional: 0, - grove_get_raw_path_query: 0, - grove_get_proved_path_query: 0, - grove_get_proved_path_query_with_conditional: 0, - grove_get_sum_tree_total_value: 0, - grove_has_raw: 0, - }, - batch: DriveGroveBatchMethodVersions { - batch_insert_empty_tree: 0, - batch_insert_empty_tree_if_not_exists: 0, - batch_insert_empty_tree_if_not_exists_check_existing_operations: 0, - batch_insert: 0, - batch_insert_if_not_exists: 0, - batch_insert_if_changed_value: 0, - batch_replace: 0, - batch_delete: 0, - batch_remove_raw: 0, - batch_delete_up_tree_while_empty: 0, - batch_refresh_reference: 0, - }, - apply: DriveGroveApplyMethodVersions { - grove_apply_operation: 0, - grove_apply_batch: 0, - grove_apply_partial_batch: 0, - }, - costs: DriveGroveCostMethodVersions { - grove_batch_operations_costs: 0, - }, - }, + grove_methods: DRIVE_GROVE_METHOD_VERSIONS_V1, grove_version: GROVE_V1, }, - platform_architecture: PlatformArchitectureVersion { - data_contract_factory_structure_version: 0, - document_factory_structure_version: 0, - }, drive_abci: DriveAbciVersion { - structs: DriveAbciStructureVersions { - platform_state_structure: 0, - platform_state_for_saving_structure: 0, - state_transition_execution_context: 0, - commit: 0, - masternode: 0, - signature_verification_quorum_set: 0, - }, - methods: DriveAbciMethodVersions { - engine: DriveAbciEngineMethodVersions { - init_chain: 0, - check_tx: 0, - run_block_proposal: 0, - finalize_block_proposal: 0, - consensus_params_update: 0, - }, - initialization: DriveAbciInitializationMethodVersions { - initial_core_height_and_time: 0, - create_genesis_state: 0, - }, - core_based_updates: DriveAbciCoreBasedUpdatesMethodVersions { - update_core_info: 0, - update_masternode_list: 0, - update_quorum_info: 0, - masternode_updates: DriveAbciMasternodeIdentitiesUpdatesMethodVersions { - get_voter_identity_key: 0, - get_operator_identity_keys: 0, - get_owner_identity_withdrawal_key: 0, - get_voter_identifier_from_masternode_list_item: 0, - get_operator_identifier_from_masternode_list_item: 0, - create_operator_identity: 0, - create_owner_identity: 0, - create_voter_identity: 0, - disable_identity_keys: 0, - update_masternode_identities: 0, - update_operator_identity: 0, - update_owner_withdrawal_address: 0, - update_voter_identity: 0, - }, - }, - protocol_upgrade: DriveAbciProtocolUpgradeMethodVersions { - check_for_desired_protocol_upgrade: 0, - upgrade_protocol_version_on_epoch_change: 0, - protocol_version_upgrade_percentage_needed: 75, - }, - block_fee_processing: DriveAbciBlockFeeProcessingMethodVersions { - add_process_epoch_change_operations: 0, - process_block_fees: 0, - }, - core_chain_lock: DriveAbciCoreChainLockMethodVersionsAndConstants { - choose_quorum: 0, - verify_chain_lock: 0, - verify_chain_lock_locally: 0, - verify_chain_lock_through_core: 0, - make_sure_core_is_synced_to_chain_lock: 0, - recent_block_count_amount: 2, - }, - core_instant_send_lock: DriveAbciCoreInstantSendLockMethodVersions { - verify_recent_signature_locally: 0, - }, - fee_pool_inwards_distribution: DriveAbciFeePoolInwardsDistributionMethodVersions { - add_distribute_block_fees_into_pools_operations: 0, - add_distribute_storage_fee_to_epochs_operations: 0, - }, - fee_pool_outwards_distribution: DriveAbciFeePoolOutwardsDistributionMethodVersions { - add_distribute_fees_from_oldest_unpaid_epoch_pool_to_proposers_operations: 0, - add_epoch_pool_to_proposers_payout_operations: 0, - find_oldest_epoch_needing_payment: 0, - fetch_reward_shares_list_for_masternode: 0, - }, - withdrawals: DriveAbciIdentityCreditWithdrawalMethodVersions { - build_untied_withdrawal_transactions_from_documents: 0, - dequeue_and_build_unsigned_withdrawal_transactions: 0, - fetch_transactions_block_inclusion_status: 0, - pool_withdrawals_into_transactions_queue: 0, - update_broadcasted_withdrawal_statuses: 0, - append_signatures_and_broadcast_withdrawal_transactions: 0, - }, - voting: DriveAbciVotingMethodVersions { - keep_record_of_finished_contested_resource_vote_poll: 0, - clean_up_after_vote_poll_end: 0, - clean_up_after_contested_resources_vote_poll_end: 0, - check_for_ended_vote_polls: 0, - tally_votes_for_contested_document_resource_vote_poll: 0, - award_document_to_winner: 0, - delay_vote_poll: 0, - run_dao_platform_events: 0, - remove_votes_for_removed_masternodes: 0, - }, - state_transition_processing: DriveAbciStateTransitionProcessingMethodVersions { - execute_event: 0, - process_raw_state_transitions: 0, - decode_raw_state_transitions: 0, - validate_fees_of_event: 0, - }, - epoch: DriveAbciEpochMethodVersions { - gather_epoch_info: 0, - get_genesis_time: 0, - }, - block_start: DriveAbciBlockStartMethodVersions { - clear_drive_block_cache: 0, - }, - block_end: DriveAbciBlockEndMethodVersions { - update_state_cache: 0, - update_drive_cache: 0, - validator_set_update: 0, - }, - platform_state_storage: DriveAbciPlatformStateStorageMethodVersions { - fetch_platform_state: 0, - store_platform_state: 0, - }, - }, - validation_and_processing: DriveAbciValidationVersions { - state_transitions: DriveAbciStateTransitionValidationVersions { - common_validation_methods: DriveAbciStateTransitionCommonValidationVersions { - asset_locks: DriveAbciAssetLockValidationVersions { - fetch_asset_lock_transaction_output_sync: 0, - verify_asset_lock_is_not_spent_and_has_enough_balance: 0, - }, - validate_identity_public_key_contract_bounds: 0, - validate_identity_public_key_ids_dont_exist_in_state: 0, - validate_identity_public_key_ids_exist_in_state: 0, - validate_state_transition_identity_signed: 0, - validate_unique_identity_public_key_hashes_in_state: 0, - validate_master_key_uniqueness: 0, - validate_simple_pre_check_balance: 0, - }, - max_asset_lock_usage_attempts: 16, - identity_create_state_transition: DriveAbciStateTransitionValidationVersion { - basic_structure: Some(0), - advanced_structure: Some(0), - identity_signatures: Some(0), - advanced_minimum_balance_pre_check: None, - nonce: None, - state: 0, - transform_into_action: 0, - }, - identity_update_state_transition: DriveAbciStateTransitionValidationVersion { - basic_structure: Some(0), - advanced_structure: Some(0), - identity_signatures: Some(0), - advanced_minimum_balance_pre_check: None, - nonce: Some(0), - state: 0, - transform_into_action: 0, - }, - identity_top_up_state_transition: DriveAbciStateTransitionValidationVersion { - basic_structure: Some(0), - advanced_structure: None, - identity_signatures: None, - advanced_minimum_balance_pre_check: None, - nonce: None, - state: 0, - transform_into_action: 0, - }, - identity_credit_withdrawal_state_transition: - DriveAbciStateTransitionValidationVersion { - basic_structure: Some(0), - advanced_structure: None, - identity_signatures: None, - advanced_minimum_balance_pre_check: Some(0), - nonce: Some(0), - state: 0, - transform_into_action: 0, - }, - identity_credit_transfer_state_transition: - DriveAbciStateTransitionValidationVersion { - basic_structure: Some(0), - advanced_structure: None, - identity_signatures: None, - advanced_minimum_balance_pre_check: Some(0), - nonce: Some(0), - state: 0, - transform_into_action: 0, - }, - masternode_vote_state_transition: DriveAbciStateTransitionValidationVersion { - basic_structure: None, - advanced_structure: Some(0), - identity_signatures: None, - advanced_minimum_balance_pre_check: Some(0), - nonce: Some(0), - state: 0, - transform_into_action: 0, - }, - contract_create_state_transition: DriveAbciStateTransitionValidationVersion { - basic_structure: Some(0), - advanced_structure: None, - identity_signatures: None, - advanced_minimum_balance_pre_check: None, - nonce: Some(0), - state: 0, - transform_into_action: 0, - }, - contract_update_state_transition: DriveAbciStateTransitionValidationVersion { - basic_structure: None, - advanced_structure: None, - identity_signatures: None, - advanced_minimum_balance_pre_check: None, - nonce: Some(0), - state: 0, - transform_into_action: 0, - }, - documents_batch_state_transition: - DriveAbciDocumentsStateTransitionValidationVersions { - balance_pre_check: 0, - basic_structure: 0, - advanced_structure: 0, - state: 0, - revision: 0, - transform_into_action: 0, - data_triggers: DriveAbciValidationDataTriggerAndBindingVersions { - bindings: 0, - triggers: DriveAbciValidationDataTriggerVersions { - create_contact_request_data_trigger: 0, - create_domain_data_trigger: 0, - create_identity_data_trigger: 0, - create_feature_flag_data_trigger: 0, - create_masternode_reward_shares_data_trigger: 0, - delete_withdrawal_data_trigger: 0, - reject_data_trigger: 0, - }, - }, - is_allowed: 0, - document_create_transition_structure_validation: 0, - document_delete_transition_structure_validation: 0, - document_replace_transition_structure_validation: 0, - document_transfer_transition_structure_validation: 0, - document_purchase_transition_structure_validation: 0, - document_update_price_transition_structure_validation: 0, - document_create_transition_state_validation: 0, - document_delete_transition_state_validation: 0, - document_replace_transition_state_validation: 0, - document_transfer_transition_state_validation: 0, - document_purchase_transition_state_validation: 0, - document_update_price_transition_state_validation: 0, - }, - }, - process_state_transition: 0, - state_transition_to_execution_event_for_check_tx: 0, - penalties: PenaltyAmounts { - identity_id_not_correct: 50000000, - unique_key_already_present: 10000000, - validation_of_added_keys_structure_failure: 10000000, - validation_of_added_keys_proof_of_possession_failure: 50000000, - }, - event_constants: DriveAbciValidationConstants { - maximum_vote_polls_to_process: 2, - maximum_contenders_to_consider: 100, - }, - }, + structs: DRIVE_ABCI_STRUCTURE_VERSIONS_V1, + methods: DRIVE_ABCI_METHOD_VERSIONS_V1, + validation_and_processing: DRIVE_ABCI_VALIDATION_VERSIONS_V1, + withdrawal_constants: DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V1, query: DriveAbciQueryVersions { max_returned_elements: 100, response_metadata: 0, @@ -982,297 +276,54 @@ pub const TEST_PLATFORM_V2: PlatformVersion = PlatformVersion { max_version: 0, default_current_version: 0, }, - partial_status: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - path_elements: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - total_credits_in_platform: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - }, - }, - dpp: DPPVersion { - costs: CostVersions { - signature_verify: 0, - }, - validation: DPPValidationVersions { - json_schema_validator: JsonSchemaValidatorVersions { - new: 0, - validate: 0, - compile: 0, - compile_and_validate: 0, - }, - data_contract: DataContractValidationVersions { - validate: 0, - validate_config_update: 0, - validate_index_definitions: 0, - validate_index_naming_duplicates: 0, - validate_not_defined_properties: 0, - validate_property_definition: 0, - }, - document_type: DocumentTypeValidationVersions { - validate_update: 0, - contested_index_limit: 1, - unique_index_limit: 10, - }, - voting: VotingValidationVersions { - allow_other_contenders_time_mainnet_ms: 604_800_000, // 1 week in ms - allow_other_contenders_time_testing_ms: 2_700_000, //45 minutes - votes_allowed_per_masternode: 5, - }, - }, - state_transition_serialization_versions: StateTransitionSerializationVersions { - identity_public_key_in_creation: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_create_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_update_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_top_up_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_credit_withdrawal_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_credit_transfer_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - masternode_vote_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - contract_create_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - contract_update_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - documents_batch_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - document_base_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - document_create_state_transition: DocumentFeatureVersionBounds { - bounds: FeatureVersionBounds { + current_quorums_info: FeatureVersionBounds { min_version: 0, max_version: 0, default_current_version: 0, }, - }, - document_replace_state_transition: DocumentFeatureVersionBounds { - bounds: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - document_delete_state_transition: DocumentFeatureVersionBounds { - bounds: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - document_transfer_state_transition: DocumentFeatureVersionBounds { - bounds: FeatureVersionBounds { + partial_status: FeatureVersionBounds { min_version: 0, max_version: 0, default_current_version: 0, }, - }, - document_update_price_state_transition: DocumentFeatureVersionBounds { - bounds: FeatureVersionBounds { + path_elements: FeatureVersionBounds { min_version: 0, max_version: 0, default_current_version: 0, }, - }, - document_purchase_state_transition: DocumentFeatureVersionBounds { - bounds: FeatureVersionBounds { + total_credits_in_platform: FeatureVersionBounds { min_version: 0, max_version: 0, default_current_version: 0, }, }, }, - state_transition_conversion_versions: StateTransitionConversionVersions { - identity_to_identity_create_transition: 0, - identity_to_identity_top_up_transition: 0, - identity_to_identity_withdrawal_transition: 0, - identity_to_identity_create_transition_with_signer: 0, - }, - state_transition_method_versions: StateTransitionMethodVersions { - public_key_in_creation_methods: PublicKeyInCreationMethodVersions { - from_public_key_signed_with_private_key: 0, - from_public_key_signed_external: 0, - hash: 0, - duplicated_key_ids_witness: 0, - duplicated_keys_witness: 0, - validate_identity_public_keys_structure: 0, - }, - }, - state_transitions: StateTransitionVersions { - documents: DocumentTransitionVersions { - documents_batch_transition: DocumentsBatchTransitionVersions { - validation: DocumentsBatchTransitionValidationVersions { - find_duplicates_by_id: 0, - validate_base_structure: 0, - }, - }, - }, - identities: IdentityTransitionVersions { - max_public_keys_in_creation: 6, - asset_locks: IdentityTransitionAssetLockVersions { - required_asset_lock_duff_balance_for_processing_start_for_identity_create: - 200000, - required_asset_lock_duff_balance_for_processing_start_for_identity_top_up: - 50000, - validate_asset_lock_transaction_structure: 0, - validate_instant_asset_lock_proof_structure: 0, - }, - }, - }, - contract_versions: ContractVersions { - max_serialized_size: 65000, - contract_serialization_version: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - contract_structure_version: 0, - created_data_contract_structure: 0, - config: 0, - methods: DataContractMethodVersions { - validate_document: 0, - validate_update: 0, - schema: 0, - }, - document_type_versions: DocumentTypeVersions { - index_versions: DocumentTypeIndexVersions { - index_levels_from_indices: 0, - }, - class_method_versions: DocumentTypeClassMethodVersions { - try_from_schema: 0, - create_document_types_from_document_schemas: 0, - }, - structure_version: 0, - schema: DocumentTypeSchemaVersions { - enrich_with_base_schema: 0, - find_identifier_and_binary_paths: 0, - validate_max_depth: 0, - max_depth: 256, - recursive_schema_validator_versions: RecursiveSchemaValidatorVersions { - traversal_validator: 0, - }, - validate_schema_compatibility: 0, - }, - methods: DocumentTypeMethodVersions { - create_document_from_data: 0, - create_document_with_prevalidated_properties: 0, - prefunded_voting_balance_for_document: 0, - contested_vote_poll_for_document: 0, - estimated_size: 0, - index_for_types: 0, - max_size: 0, - serialize_value_for_key: 0, - deserialize_value_for_key: 0, - }, - }, - }, - document_versions: DocumentVersions { - document_structure_version: 0, - document_serialization_version: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - document_cbor_serialization_version: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - extended_document_structure_version: 0, - extended_document_serialization_version: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - document_method_versions: DocumentMethodVersions { - is_equal_ignoring_timestamps: 0, - hash: 0, - get_raw_for_contract: 0, - get_raw_for_document_type: 0, - }, - }, - identity_versions: IdentityVersions { - identity_structure_version: 0, - identity_key_structure_version: 0, - identity_key_type_method_versions: IdentityKeyTypeMethodVersions { - random_public_key_data: 0, - random_public_and_private_key_data: 0, - }, - }, - voting_versions: VotingVersions { - default_vote_poll_time_duration_mainnet_ms: 1_209_600_000, //2 weeks - default_vote_poll_time_duration_test_network_ms: 5_400_000, //90 minutes - contested_document_vote_poll_stored_info_version: 0, - }, - asset_lock_versions: AssetLockVersions { - reduced_asset_lock_value: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - methods: DPPMethodVersions { epoch_core_reward_credits_for_distribution: 0 }, }, - system_data_contracts: SystemDataContractVersions { - withdrawals: 1, - dpns: 1, - dashpay: 1, - masternode_reward_shares: 1, - feature_flags: 1, + dpp: DPPVersion { + costs: DPP_COSTS_VERSIONS_V1, + validation: DPP_VALIDATION_VERSIONS_V2, + state_transition_serialization_versions: STATE_TRANSITION_SERIALIZATION_VERSIONS_V1, + state_transition_conversion_versions: STATE_TRANSITION_CONVERSION_VERSIONS_V1, + state_transition_method_versions: STATE_TRANSITION_METHOD_VERSIONS_V1, + state_transitions: STATE_TRANSITION_VERSIONS_V1, + contract_versions: CONTRACT_VERSIONS_V1, + document_versions: DOCUMENT_VERSIONS_V1, + identity_versions: IDENTITY_VERSIONS_V1, + voting_versions: VOTING_VERSION_V2, + asset_lock_versions: DPP_ASSET_LOCK_VERSIONS_V1, + methods: DPP_METHOD_VERSIONS_V1, + factory_versions: DPP_FACTORY_VERSIONS_V1, }, + system_data_contracts: SYSTEM_DATA_CONTRACT_VERSIONS_V1, fee_version: FEE_VERSION1, system_limits: SystemLimits { estimated_contract_max_serialized_size: 16384, max_field_value_size: 5000, - max_state_transition_size: 20000, + max_state_transition_size: 20000, // Is different in this test version, not sure if this was a mistake max_transitions_in_documents_batch: 1, + withdrawal_transactions_per_block_limit: 4, + retry_signing_expired_withdrawal_documents_per_block_limit: 1, + max_withdrawal_amount: 50_000_000_000_000, }, consensus: ConsensusVersions { tenderdash_consensus_version: 0, diff --git a/packages/rs-platform-version/src/version/mocks/v3_test.rs b/packages/rs-platform-version/src/version/mocks/v3_test.rs index 919a6add8c..4c54dfbfef 100644 --- a/packages/rs-platform-version/src/version/mocks/v3_test.rs +++ b/packages/rs-platform-version/src/version/mocks/v3_test.rs @@ -1,613 +1,56 @@ use crate::version::consensus_versions::ConsensusVersions; -use crate::version::contracts::SystemDataContractVersions; -use crate::version::dpp_versions::{ - AssetLockVersions, ContractVersions, CostVersions, DPPMethodVersions, DPPValidationVersions, - DPPVersion, DataContractMethodVersions, DataContractValidationVersions, - DocumentFeatureVersionBounds, DocumentMethodVersions, DocumentTransitionVersions, - DocumentTypeClassMethodVersions, DocumentTypeIndexVersions, DocumentTypeMethodVersions, - DocumentTypeSchemaVersions, DocumentTypeValidationVersions, DocumentTypeVersions, - DocumentVersions, DocumentsBatchTransitionValidationVersions, DocumentsBatchTransitionVersions, - IdentityKeyTypeMethodVersions, IdentityTransitionAssetLockVersions, IdentityTransitionVersions, - IdentityVersions, JsonSchemaValidatorVersions, PublicKeyInCreationMethodVersions, - RecursiveSchemaValidatorVersions, StateTransitionConversionVersions, - StateTransitionMethodVersions, StateTransitionSerializationVersions, StateTransitionVersions, - VotingValidationVersions, VotingVersions, -}; -use crate::version::drive_abci_versions::{ - DriveAbciAssetLockValidationVersions, DriveAbciBlockEndMethodVersions, - DriveAbciBlockFeeProcessingMethodVersions, DriveAbciBlockStartMethodVersions, - DriveAbciCoreBasedUpdatesMethodVersions, DriveAbciCoreChainLockMethodVersionsAndConstants, - DriveAbciCoreInstantSendLockMethodVersions, - DriveAbciDocumentsStateTransitionValidationVersions, DriveAbciEngineMethodVersions, - DriveAbciEpochMethodVersions, DriveAbciFeePoolInwardsDistributionMethodVersions, +use crate::version::dpp_versions::dpp_asset_lock_versions::v1::DPP_ASSET_LOCK_VERSIONS_V1; +use crate::version::dpp_versions::dpp_contract_versions::v1::CONTRACT_VERSIONS_V1; +use crate::version::dpp_versions::dpp_costs_versions::v1::DPP_COSTS_VERSIONS_V1; +use crate::version::dpp_versions::dpp_document_versions::v1::DOCUMENT_VERSIONS_V1; +use crate::version::dpp_versions::dpp_factory_versions::v1::DPP_FACTORY_VERSIONS_V1; +use crate::version::dpp_versions::dpp_identity_versions::v1::IDENTITY_VERSIONS_V1; +use crate::version::dpp_versions::dpp_method_versions::v1::DPP_METHOD_VERSIONS_V1; +use crate::version::dpp_versions::dpp_state_transition_conversion_versions::v2::STATE_TRANSITION_CONVERSION_VERSIONS_V2; +use crate::version::dpp_versions::dpp_state_transition_method_versions::v1::STATE_TRANSITION_METHOD_VERSIONS_V1; +use crate::version::dpp_versions::dpp_state_transition_serialization_versions::v1::STATE_TRANSITION_SERIALIZATION_VERSIONS_V1; +use crate::version::dpp_versions::dpp_state_transition_versions::v1::STATE_TRANSITION_VERSIONS_V1; +use crate::version::dpp_versions::dpp_validation_versions::v2::DPP_VALIDATION_VERSIONS_V2; +use crate::version::dpp_versions::dpp_voting_versions::v2::VOTING_VERSION_V2; +use crate::version::dpp_versions::DPPVersion; +use crate::version::drive_abci_versions::drive_abci_method_versions::{ + DriveAbciBlockEndMethodVersions, DriveAbciBlockFeeProcessingMethodVersions, + DriveAbciBlockStartMethodVersions, DriveAbciCoreBasedUpdatesMethodVersions, + DriveAbciCoreChainLockMethodVersionsAndConstants, DriveAbciCoreInstantSendLockMethodVersions, + DriveAbciEngineMethodVersions, DriveAbciEpochMethodVersions, + DriveAbciFeePoolInwardsDistributionMethodVersions, DriveAbciFeePoolOutwardsDistributionMethodVersions, DriveAbciIdentityCreditWithdrawalMethodVersions, DriveAbciInitializationMethodVersions, DriveAbciMasternodeIdentitiesUpdatesMethodVersions, DriveAbciMethodVersions, DriveAbciPlatformStateStorageMethodVersions, DriveAbciProtocolUpgradeMethodVersions, - DriveAbciQueryDataContractVersions, DriveAbciQueryIdentityVersions, - DriveAbciQueryPrefundedSpecializedBalancesVersions, DriveAbciQuerySystemVersions, - DriveAbciQueryValidatorVersions, DriveAbciQueryVersions, DriveAbciQueryVotingVersions, - DriveAbciStateTransitionCommonValidationVersions, - DriveAbciStateTransitionProcessingMethodVersions, DriveAbciStateTransitionValidationVersion, - DriveAbciStateTransitionValidationVersions, DriveAbciStructureVersions, - DriveAbciValidationConstants, DriveAbciValidationDataTriggerAndBindingVersions, - DriveAbciValidationDataTriggerVersions, DriveAbciValidationVersions, DriveAbciVersion, - DriveAbciVotingMethodVersions, PenaltyAmounts, -}; -use crate::version::drive_versions::{ - DriveAssetLockMethodVersions, DriveBalancesMethodVersions, DriveBatchOperationsMethodVersion, - DriveContractApplyMethodVersions, DriveContractCostsMethodVersions, - DriveContractGetMethodVersions, DriveContractInsertMethodVersions, DriveContractMethodVersions, - DriveContractProveMethodVersions, DriveContractUpdateMethodVersions, - DriveCreditPoolEpochsMethodVersions, DriveCreditPoolMethodVersions, - DriveCreditPoolPendingEpochRefundsMethodVersions, - DriveCreditPoolStorageFeeDistributionPoolMethodVersions, - DriveCreditPoolUnpaidEpochMethodVersions, DriveDataContractOperationMethodVersions, - DriveDocumentDeleteMethodVersions, DriveDocumentEstimationCostsMethodVersions, - DriveDocumentIndexUniquenessMethodVersions, DriveDocumentInsertContestedMethodVersions, - DriveDocumentInsertMethodVersions, DriveDocumentMethodVersions, - DriveDocumentQueryMethodVersions, DriveDocumentUpdateMethodVersions, - DriveEstimatedCostsMethodVersions, DriveFeesMethodVersions, DriveFetchMethodVersions, - DriveGroveApplyMethodVersions, DriveGroveBasicMethodVersions, DriveGroveBatchMethodVersions, - DriveGroveCostMethodVersions, DriveGroveMethodVersions, - DriveIdentityContractInfoMethodVersions, DriveIdentityCostEstimationMethodVersions, - DriveIdentityFetchAttributesMethodVersions, DriveIdentityFetchFullIdentityMethodVersions, - DriveIdentityFetchMethodVersions, DriveIdentityFetchPartialIdentityMethodVersions, - DriveIdentityFetchPublicKeyHashesMethodVersions, DriveIdentityInsertMethodVersions, - DriveIdentityKeyHashesToIdentityInsertMethodVersions, DriveIdentityKeysFetchMethodVersions, - DriveIdentityKeysInsertMethodVersions, DriveIdentityKeysMethodVersions, - DriveIdentityKeysProveMethodVersions, DriveIdentityMethodVersions, - DriveIdentityProveMethodVersions, DriveIdentityUpdateMethodVersions, - DriveIdentityWithdrawalDocumentMethodVersions, DriveIdentityWithdrawalMethodVersions, - DriveIdentityWithdrawalTransactionIndexMethodVersions, - DriveIdentityWithdrawalTransactionMethodVersions, - DriveIdentityWithdrawalTransactionQueueMethodVersions, DriveInitializationMethodVersions, - DriveMethodVersions, DriveOperationsMethodVersion, DrivePlatformStateMethodVersions, - DrivePlatformSystemMethodVersions, DrivePrefundedSpecializedMethodVersions, - DriveProtocolUpgradeVersions, DriveProveMethodVersions, - DriveStateTransitionActionConvertToHighLevelOperationsMethodVersions, - DriveStateTransitionMethodVersions, DriveStateTransitionOperationMethodVersions, - DriveStructureVersion, DriveSystemEstimationCostsMethodVersions, - DriveVerifyContractMethodVersions, DriveVerifyDocumentMethodVersions, - DriveVerifyIdentityMethodVersions, DriveVerifyMethodVersions, - DriveVerifySingleDocumentMethodVersions, DriveVerifyStateTransitionMethodVersions, - DriveVerifySystemMethodVersions, DriveVerifyVoteMethodVersions, DriveVersion, - DriveVoteCleanupMethodVersions, DriveVoteContestedResourceInsertMethodVersions, - DriveVoteFetchMethodVersions, DriveVoteInsertMethodVersions, DriveVoteMethodVersions, - DriveVoteSetupMethodVersions, DriveVoteStorageFormMethodVersions, + DriveAbciStateTransitionProcessingMethodVersions, DriveAbciVotingMethodVersions, }; +use crate::version::drive_abci_versions::drive_abci_query_versions::v1::DRIVE_ABCI_QUERY_VERSIONS_V1; +use crate::version::drive_abci_versions::drive_abci_structure_versions::v1::DRIVE_ABCI_STRUCTURE_VERSIONS_V1; +use crate::version::drive_abci_versions::drive_abci_validation_versions::v3::DRIVE_ABCI_VALIDATION_VERSIONS_V3; +use crate::version::drive_abci_versions::drive_abci_withdrawal_constants::v2::DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V2; +use crate::version::drive_abci_versions::DriveAbciVersion; +use crate::version::drive_versions::v2::DRIVE_VERSION_V2; use crate::version::fee::v1::FEE_VERSION1; -use crate::version::limits::SystemLimits; use crate::version::mocks::TEST_PROTOCOL_VERSION_SHIFT_BYTES; -use crate::version::protocol_version::{FeatureVersionBounds, PlatformVersion}; -use crate::version::PlatformArchitectureVersion; -use grovedb_version::version::v1::GROVE_V1; +use crate::version::protocol_version::PlatformVersion; +use crate::version::system_data_contract_versions::v1::SYSTEM_DATA_CONTRACT_VERSIONS_V1; +use crate::version::system_limits::v1::SYSTEM_LIMITS_V1; pub const TEST_PROTOCOL_VERSION_3: u32 = (1 << TEST_PROTOCOL_VERSION_SHIFT_BYTES) + 3; pub const TEST_PLATFORM_V3: PlatformVersion = PlatformVersion { protocol_version: TEST_PROTOCOL_VERSION_3, - proofs: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - drive: DriveVersion { - structure: DriveStructureVersion { - document_indexes: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_indexes: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - pools: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - methods: DriveMethodVersions { - initialization: DriveInitializationMethodVersions { - create_initial_state_structure: 0, - }, - credit_pools: DriveCreditPoolMethodVersions { - epochs: DriveCreditPoolEpochsMethodVersions { - get_epochs_infos: 0, - get_epochs_protocol_versions: 0, - prove_epochs_infos: 0, - get_epoch_fee_multiplier: 0, - get_epoch_processing_credits_for_distribution: 0, - get_epoch_storage_credits_for_distribution: 0, - get_epoch_total_credits_for_distribution: 0, - get_storage_credits_for_distribution_for_epochs_in_range: 0, - get_epoch_start_time: 0, - get_epoch_start_block_core_height: 0, - get_epoch_start_block_height: 0, - get_first_epoch_start_block_info_between_epochs: 0, - fetch_epoch_proposers: 0, - prove_epoch_proposers: 0, - get_epochs_proposer_block_count: 0, - add_update_pending_epoch_refunds_operations: 0, - is_epochs_proposers_tree_empty: 0, - }, - pending_epoch_refunds: DriveCreditPoolPendingEpochRefundsMethodVersions { - add_delete_pending_epoch_refunds_except_specified: 0, - fetch_and_add_pending_epoch_refunds_to_collection: 0, - fetch_pending_epoch_refunds: 0, - add_update_pending_epoch_refunds_operations: 0, - }, - storage_fee_distribution_pool: - DriveCreditPoolStorageFeeDistributionPoolMethodVersions { - get_storage_fees_from_distribution_pool: 0, - }, - unpaid_epoch: DriveCreditPoolUnpaidEpochMethodVersions { - get_unpaid_epoch_index: 0, - }, - }, - protocol_upgrade: DriveProtocolUpgradeVersions { - clear_version_information: 0, - fetch_versions_with_counter: 0, - fetch_proved_versions_with_counter: 0, - fetch_validator_version_votes: 0, - fetch_proved_validator_version_votes: 0, - remove_validators_proposed_app_versions: 0, - update_validator_proposed_app_version: 0, - }, - prove: DriveProveMethodVersions { - prove_elements: 0, - prove_multiple_state_transition_results: 0, - }, - balances: DriveBalancesMethodVersions { - add_to_system_credits: 0, - add_to_system_credits_operations: 0, - remove_from_system_credits: 0, - remove_from_system_credits_operations: 0, - calculate_total_credits_balance: 0, - }, - state_transitions: DriveStateTransitionMethodVersions { - operations: DriveStateTransitionOperationMethodVersions { - finalization_tasks: 0, - contracts: DriveDataContractOperationMethodVersions { - finalization_tasks: 0, - }, - }, - convert_to_high_level_operations: - DriveStateTransitionActionConvertToHighLevelOperationsMethodVersions { - data_contract_create_transition: 0, - data_contract_update_transition: 0, - document_create_transition: 0, - document_delete_transition: 0, - document_purchase_transition: 0, - document_replace_transition: 0, - document_transfer_transition: 0, - document_update_price_transition: 0, - documents_batch_transition: 0, - identity_create_transition: 0, - identity_credit_transfer_transition: 0, - identity_credit_withdrawal_transition: 0, - identity_top_up_transition: 0, - identity_update_transition: 0, - masternode_vote_transition: 0, - bump_identity_data_contract_nonce: 0, - bump_identity_nonce: 0, - partially_use_asset_lock: 0, - }, - }, - document: DriveDocumentMethodVersions { - query: DriveDocumentQueryMethodVersions { query_documents: 0, query_contested_documents: 0, query_contested_documents_vote_state: 0, query_documents_with_flags: 0 }, - delete: DriveDocumentDeleteMethodVersions { - add_estimation_costs_for_remove_document_to_primary_storage: 0, - delete_document_for_contract: 0, - delete_document_for_contract_id: 0, - delete_document_for_contract_apply_and_add_to_operations: 0, - remove_document_from_primary_storage: 0, - remove_reference_for_index_level_for_contract_operations: 0, - remove_indices_for_index_level_for_contract_operations: 0, - remove_indices_for_top_index_level_for_contract_operations: 0, - delete_document_for_contract_id_with_named_type_operations: 0, - delete_document_for_contract_with_named_type_operations: 0, - delete_document_for_contract_operations: 0, - }, - insert: DriveDocumentInsertMethodVersions { - add_document: 0, - add_document_for_contract: 0, - add_document_for_contract_apply_and_add_to_operations: 0, - add_document_for_contract_operations: 0, - add_document_to_primary_storage: 0, - add_indices_for_index_level_for_contract_operations: 0, - add_indices_for_top_index_level_for_contract_operations: 0, - add_reference_for_index_level_for_contract_operations: 0, - }, - insert_contested: DriveDocumentInsertContestedMethodVersions { - add_contested_document: 0, - add_contested_document_for_contract: 0, - add_contested_document_for_contract_apply_and_add_to_operations: 0, - add_contested_document_for_contract_operations: 0, - add_contested_document_to_primary_storage: 0, - add_contested_indices_for_contract_operations: 0, - add_contested_reference_and_vote_subtree_to_document_operations: 0, - add_contested_vote_subtree_for_non_identities_operations: 0, - }, - update: DriveDocumentUpdateMethodVersions { - add_update_multiple_documents_operations: 0, - update_document_for_contract: 0, - update_document_for_contract_apply_and_add_to_operations: 0, - update_document_for_contract_id: 0, - update_document_for_contract_operations: 0, - update_document_with_serialization_for_contract: 0, - update_serialized_document_for_contract: 0, - }, - estimation_costs: DriveDocumentEstimationCostsMethodVersions { - add_estimation_costs_for_add_document_to_primary_storage: 0, - add_estimation_costs_for_add_contested_document_to_primary_storage: 0, - stateless_delete_of_non_tree_for_costs: 0, - }, - index_uniqueness: DriveDocumentIndexUniquenessMethodVersions { - validate_document_uniqueness: 0, - validate_document_create_transition_action_uniqueness: 0, - validate_document_replace_transition_action_uniqueness: 0, - validate_document_transfer_transition_action_uniqueness: 0, - validate_document_purchase_transition_action_uniqueness: 0, - validate_document_update_price_transition_action_uniqueness: 0, - validate_uniqueness_of_data: 0, - }, - }, - vote: DriveVoteMethodVersions { - insert: DriveVoteInsertMethodVersions { - register_identity_vote: 0, - }, - contested_resource_insert: DriveVoteContestedResourceInsertMethodVersions { - register_contested_resource_identity_vote: 0, - insert_stored_info_for_contested_resource_vote_poll: 0, - register_identity_vote: 0, - add_vote_poll_end_date_query_operations: 0, - }, - cleanup: DriveVoteCleanupMethodVersions { - remove_specific_vote_references_given_by_identity: 0, - remove_specific_votes_given_by_identity: 0, - remove_contested_resource_vote_poll_end_date_query_operations: 0, - remove_contested_resource_vote_poll_votes_operations: 0, - remove_contested_resource_vote_poll_documents_operations: 0, - remove_contested_resource_vote_poll_contenders_operations: 0, - remove_contested_resource_top_level_index_operations: 0, - remove_contested_resource_info_operations: 0, - }, - setup: DriveVoteSetupMethodVersions { - add_initial_vote_tree_main_structure_operations: 0, - }, - storage_form: DriveVoteStorageFormMethodVersions { - resolve_with_contract: 0, - }, - fetch: DriveVoteFetchMethodVersions { - fetch_identities_voting_for_contenders: 0, - fetch_contested_document_vote_poll_stored_info: 0, - fetch_identity_contested_resource_vote: 0, - }, - }, - contract: 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: 0, - }, - update: DriveContractUpdateMethodVersions { update_contract: 0 }, - costs: DriveContractCostsMethodVersions { - add_estimation_costs_for_contract_insertion: 0, - }, - get: DriveContractGetMethodVersions { - fetch_contract: 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, - }, - }, - fees: DriveFeesMethodVersions { calculate_fee: 0 }, - estimated_costs: DriveEstimatedCostsMethodVersions { - add_estimation_costs_for_levels_up_to_contract: 0, - add_estimation_costs_for_levels_up_to_contract_document_type_excluded: 0, - add_estimation_costs_for_contested_document_tree_levels_up_to_contract: 0, - add_estimation_costs_for_contested_document_tree_levels_up_to_contract_document_type_excluded: 0, - }, - asset_lock: DriveAssetLockMethodVersions { - add_asset_lock_outpoint: 0, - add_estimation_costs_for_adding_asset_lock: 0, - fetch_asset_lock_outpoint_info: 0, - }, - verify: DriveVerifyMethodVersions { - contract: DriveVerifyContractMethodVersions { - verify_contract: 0, - verify_contract_history: 0, - }, - document: DriveVerifyDocumentMethodVersions { - verify_proof: 0, - verify_proof_keep_serialized: 0, - verify_start_at_document_in_proof: 0, - }, - identity: DriveVerifyIdentityMethodVersions { - verify_full_identities_by_public_key_hashes: 0, - verify_full_identity_by_identity_id: 0, - verify_full_identity_by_public_key_hash: 0, - verify_identity_balance_for_identity_id: 0, - verify_identity_balances_for_identity_ids: 0, - verify_identity_id_by_public_key_hash: 0, - verify_identity_ids_by_public_key_hashes: 0, - verify_identity_keys_by_identity_id: 0, - verify_identity_nonce: 0, - verify_identity_contract_nonce: 0, - verify_identities_contract_keys: 0, - verify_identity_revision_for_identity_id: 0, - }, - single_document: DriveVerifySingleDocumentMethodVersions { - verify_proof: 0, - verify_proof_keep_serialized: 0, - }, - system: DriveVerifySystemMethodVersions { - verify_epoch_infos: 0, - verify_epoch_proposers: 0, - verify_elements: 0, - verify_total_credits_in_system: 0, - verify_upgrade_state: 0, - verify_upgrade_vote_status: 0, - }, - voting: DriveVerifyVoteMethodVersions { - verify_masternode_vote: 0, - verify_start_at_contender_in_proof: 0, - verify_vote_poll_votes_proof: 0, - verify_identity_votes_given_proof: 0, - verify_vote_poll_vote_state_proof: 0, - verify_contests_proof: 0, - verify_vote_polls_by_end_date_proof: 0, - verify_specialized_balance: 0, - }, - state_transition: DriveVerifyStateTransitionMethodVersions { - verify_state_transition_was_executed_with_proof: 0, - }, - }, - identity: DriveIdentityMethodVersions { - fetch: DriveIdentityFetchMethodVersions { - public_key_hashes: DriveIdentityFetchPublicKeyHashesMethodVersions { - fetch_full_identities_by_unique_public_key_hashes: 0, - fetch_full_identity_by_unique_public_key_hash: 0, - fetch_identity_id_by_unique_public_key_hash: 0, - fetch_identity_ids_by_non_unique_public_key_hash: 0, - fetch_identity_ids_by_unique_public_key_hashes: 0, - fetch_serialized_full_identity_by_unique_public_key_hash: 0, - has_any_of_unique_public_key_hashes: 0, - has_non_unique_public_key_hash: 0, - has_non_unique_public_key_hash_already_for_identity: 0, - has_unique_public_key_hash: 0, - }, - attributes: DriveIdentityFetchAttributesMethodVersions { - revision: 0, - nonce: 0, - identity_contract_nonce: 0, - balance: 0, - balance_include_debt: 0, - negative_balance: 0, - }, - partial_identity: DriveIdentityFetchPartialIdentityMethodVersions { - fetch_identity_revision_with_keys: 0, - fetch_identity_balance_with_keys: 0, - fetch_identity_balance_with_keys_and_revision: 0, - fetch_identity_with_balance: 0, - fetch_identity_keys: 0, - }, - full_identity: DriveIdentityFetchFullIdentityMethodVersions { - fetch_full_identity: Some(0), - fetch_full_identities: Some(0), - }, - }, - prove: DriveIdentityProveMethodVersions { - full_identity: 0, - full_identities: 0, - identity_nonce: 0, - identity_contract_nonce: 0, - identities_contract_keys: 0, - prove_full_identities_by_unique_public_key_hashes: 0, - prove_full_identity_by_unique_public_key_hash: 0, - prove_identity_id_by_unique_public_key_hash: 0, - prove_identity_ids_by_unique_public_key_hashes: 0, - }, - keys: DriveIdentityKeysMethodVersions { - fetch: DriveIdentityKeysFetchMethodVersions { - fetch_all_current_identity_keys: 0, - fetch_all_identity_keys: 0, - fetch_identities_all_keys: 0, - fetch_identity_keys: 0, - fetch_identities_contract_keys: 0, - }, - prove: DriveIdentityKeysProveMethodVersions { - prove_identities_all_keys: 0, - prove_identity_keys: 0, - }, - insert: DriveIdentityKeysInsertMethodVersions { - create_key_tree_with_keys: 0, - create_new_identity_key_query_trees: 0, - insert_key_searchable_references: 0, - insert_key_to_storage: 0, - insert_new_non_unique_key: 0, - insert_new_unique_key: 0, - replace_key_in_storage: 0, - }, - insert_key_hash_identity_reference: - DriveIdentityKeyHashesToIdentityInsertMethodVersions { - add_estimation_costs_for_insert_non_unique_public_key_hash_reference: 0, - add_estimation_costs_for_insert_unique_public_key_hash_reference: 0, - insert_non_unique_public_key_hash_reference_to_identity: 0, - insert_reference_to_non_unique_key: 0, - insert_reference_to_unique_key: 0, - insert_unique_public_key_hash_reference_to_identity: 0, - }, - }, - update: DriveIdentityUpdateMethodVersions { - update_identity_revision: 0, - merge_identity_nonce: 0, - update_identity_negative_credit_operation: 0, - initialize_identity_revision: 0, - disable_identity_keys: 0, - re_enable_identity_keys: 0, - add_new_non_unique_keys_to_identity: 0, - add_new_unique_keys_to_identity: 0, - add_new_keys_to_identity: 0, - insert_identity_balance: 0, - initialize_negative_identity_balance: 0, - add_to_identity_balance: 0, - add_to_previous_balance: 0, - apply_balance_change_from_fee_to_identity: 0, - remove_from_identity_balance: 0, - refresh_identity_key_reference_operations: 0, - }, - insert: DriveIdentityInsertMethodVersions { - add_new_identity: 0, - }, - contract_info: DriveIdentityContractInfoMethodVersions { - add_potential_contract_info_for_contract_bounded_key: 0, - refresh_potential_contract_info_key_references: 0, - merge_identity_contract_nonce: 0, - }, - cost_estimation: DriveIdentityCostEstimationMethodVersions { - for_authentication_keys_security_level_in_key_reference_tree: 0, - for_balances: 0, - for_contract_info: 0, - for_contract_info_group: 0, - for_contract_info_group_keys: 0, - for_contract_info_group_key_purpose: 0, - for_keys_for_identity_id: 0, - for_negative_credit: 0, - for_purpose_in_key_reference_tree: 0, - for_root_key_reference_tree: 0, - for_update_revision: 0, - }, - withdrawals: DriveIdentityWithdrawalMethodVersions { - document: DriveIdentityWithdrawalDocumentMethodVersions { - fetch_oldest_withdrawal_documents_by_status: 0, - find_up_to_100_withdrawal_documents_by_status_and_transaction_indices: 0, - }, - transaction: DriveIdentityWithdrawalTransactionMethodVersions { - index: DriveIdentityWithdrawalTransactionIndexMethodVersions { - fetch_next_withdrawal_transaction_index: 0, - add_update_next_withdrawal_transaction_index_operation: 0, - }, - queue: DriveIdentityWithdrawalTransactionQueueMethodVersions { - add_enqueue_untied_withdrawal_transaction_operations: 0, - dequeue_untied_withdrawal_transactions: 0, - }, - }, - }, - }, - platform_system: DrivePlatformSystemMethodVersions { - estimation_costs: DriveSystemEstimationCostsMethodVersions { - for_total_system_credits_update: 0, - }, - }, - operations: DriveOperationsMethodVersion { - rollback_transaction: 0, - drop_cache: 0, - commit_transaction: 0, - apply_partial_batch_low_level_drive_operations: 0, - apply_partial_batch_grovedb_operations: 0, - apply_batch_low_level_drive_operations: 0, - apply_batch_grovedb_operations: 0, - }, - batch_operations: DriveBatchOperationsMethodVersion { - convert_drive_operations_to_grove_operations: 0, - apply_drive_operations: 0, - }, - platform_state: DrivePlatformStateMethodVersions { - fetch_platform_state_bytes: 0, - store_platform_state_bytes: 0, - }, - fetch: DriveFetchMethodVersions { fetch_elements: 0 }, - prefunded_specialized_balances: DrivePrefundedSpecializedMethodVersions { - fetch_single: 0, - prove_single: 0, - add_prefunded_specialized_balance: 0, - add_prefunded_specialized_balance_operations: 0, - deduct_from_prefunded_specialized_balance: 0, - deduct_from_prefunded_specialized_balance_operations: 0, - estimated_cost_for_prefunded_specialized_balance_update: 0, - }, - }, - grove_methods: DriveGroveMethodVersions { - basic: DriveGroveBasicMethodVersions { - grove_insert: 0, - grove_insert_empty_tree: 0, - grove_insert_empty_sum_tree: 0, - grove_insert_if_not_exists: 0, - grove_clear: 0, - grove_delete: 0, - grove_get_raw: 0, - grove_get_raw_optional: 0, - grove_get_raw_value_u64_from_encoded_var_vec: 0, - grove_get: 0, - grove_get_path_query_serialized_results: 0, - grove_get_path_query_serialized_or_sum_results: 0, - grove_get_path_query: 0, - grove_get_path_query_with_optional: 0, - grove_get_raw_path_query_with_optional: 0, - grove_get_raw_path_query: 0, - grove_get_proved_path_query: 0, - grove_get_proved_path_query_with_conditional: 0, - grove_get_sum_tree_total_value: 0, - grove_has_raw: 0, - }, - batch: DriveGroveBatchMethodVersions { - batch_insert_empty_tree: 0, - batch_insert_empty_tree_if_not_exists: 0, - batch_insert_empty_tree_if_not_exists_check_existing_operations: 0, - batch_insert: 0, - batch_insert_if_not_exists: 0, - batch_insert_if_changed_value: 0, - batch_replace: 0, - batch_delete: 0, - batch_remove_raw: 0, - batch_delete_up_tree_while_empty: 0, - batch_refresh_reference: 0, - }, - apply: DriveGroveApplyMethodVersions { - grove_apply_operation: 0, - grove_apply_batch: 0, - grove_apply_partial_batch: 0, - }, - costs: DriveGroveCostMethodVersions { - grove_batch_operations_costs: 0, - }, - }, - grove_version: GROVE_V1, - }, - platform_architecture: PlatformArchitectureVersion { - data_contract_factory_structure_version: 0, - document_factory_structure_version: 0, - }, + drive: DRIVE_VERSION_V2, drive_abci: DriveAbciVersion { - structs: DriveAbciStructureVersions { - platform_state_structure: 0, - platform_state_for_saving_structure: 0, - state_transition_execution_context: 0, - commit: 0, - masternode: 0, - signature_verification_quorum_set: 0, - }, + structs: DRIVE_ABCI_STRUCTURE_VERSIONS_V1, methods: DriveAbciMethodVersions { engine: DriveAbciEngineMethodVersions { init_chain: 0, check_tx: 0, run_block_proposal: 0, finalize_block_proposal: 0, - consensus_params_update: 0, + consensus_params_update: 1, }, initialization: DriveAbciInitializationMethodVersions { initial_core_height_and_time: 0, @@ -621,6 +64,7 @@ pub const TEST_PLATFORM_V3: PlatformVersion = PlatformVersion { get_voter_identity_key: 0, get_operator_identity_keys: 0, get_owner_identity_withdrawal_key: 0, + get_owner_identity_owner_key: 0, get_voter_identifier_from_masternode_list_item: 0, get_operator_identifier_from_masternode_list_item: 0, create_operator_identity: 0, @@ -634,9 +78,10 @@ pub const TEST_PLATFORM_V3: PlatformVersion = PlatformVersion { }, }, protocol_upgrade: DriveAbciProtocolUpgradeMethodVersions { - check_for_desired_protocol_upgrade: 0, + check_for_desired_protocol_upgrade: 1, upgrade_protocol_version_on_epoch_change: 0, - protocol_version_upgrade_percentage_needed: 75, + perform_events_on_first_block_of_protocol_change: None, + protocol_version_upgrade_percentage_needed: 67, }, block_fee_processing: DriveAbciBlockFeeProcessingMethodVersions { add_process_epoch_change_operations: 0, @@ -667,9 +112,11 @@ pub const TEST_PLATFORM_V3: PlatformVersion = PlatformVersion { build_untied_withdrawal_transactions_from_documents: 0, dequeue_and_build_unsigned_withdrawal_transactions: 0, fetch_transactions_block_inclusion_status: 0, - pool_withdrawals_into_transactions_queue: 0, + pool_withdrawals_into_transactions_queue: 1, update_broadcasted_withdrawal_statuses: 0, + rebroadcast_expired_withdrawal_documents: 1, append_signatures_and_broadcast_withdrawal_transactions: 0, + cleanup_expired_locks_of_withdrawal_amounts: 0, }, voting: DriveAbciVotingMethodVersions { keep_record_of_finished_contested_resource_vote_poll: 0, @@ -705,578 +152,29 @@ pub const TEST_PLATFORM_V3: PlatformVersion = PlatformVersion { store_platform_state: 0, }, }, - validation_and_processing: DriveAbciValidationVersions { - state_transitions: DriveAbciStateTransitionValidationVersions { - common_validation_methods: DriveAbciStateTransitionCommonValidationVersions { - asset_locks: DriveAbciAssetLockValidationVersions { - fetch_asset_lock_transaction_output_sync: 0, - verify_asset_lock_is_not_spent_and_has_enough_balance: 0, - }, - validate_identity_public_key_contract_bounds: 0, - validate_identity_public_key_ids_dont_exist_in_state: 0, - validate_identity_public_key_ids_exist_in_state: 0, - validate_state_transition_identity_signed: 0, - validate_unique_identity_public_key_hashes_in_state: 0, - validate_master_key_uniqueness: 0, - validate_simple_pre_check_balance: 0, - }, - max_asset_lock_usage_attempts: 16, - identity_create_state_transition: DriveAbciStateTransitionValidationVersion { - basic_structure: Some(0), - advanced_structure: Some(0), - identity_signatures: Some(0), - advanced_minimum_balance_pre_check: None, - nonce: None, - state: 0, - transform_into_action: 0, - }, - identity_update_state_transition: DriveAbciStateTransitionValidationVersion { - basic_structure: Some(0), - advanced_structure: Some(0), - identity_signatures: Some(0), - advanced_minimum_balance_pre_check: None, - nonce: Some(0), - state: 0, - transform_into_action: 0, - }, - identity_top_up_state_transition: DriveAbciStateTransitionValidationVersion { - basic_structure: Some(0), - advanced_structure: None, - identity_signatures: None, - advanced_minimum_balance_pre_check: None, - nonce: None, - state: 0, - transform_into_action: 0, - }, - identity_credit_withdrawal_state_transition: - DriveAbciStateTransitionValidationVersion { - basic_structure: Some(0), - advanced_structure: None, - identity_signatures: None, - advanced_minimum_balance_pre_check: Some(0), - nonce: Some(0), - state: 0, - transform_into_action: 0, - }, - identity_credit_transfer_state_transition: - DriveAbciStateTransitionValidationVersion { - basic_structure: Some(0), - advanced_structure: None, - identity_signatures: None, - advanced_minimum_balance_pre_check: Some(0), - nonce: Some(0), - state: 0, - transform_into_action: 0, - }, - masternode_vote_state_transition: DriveAbciStateTransitionValidationVersion { - basic_structure: None, - advanced_structure: Some(0), - identity_signatures: None, - advanced_minimum_balance_pre_check: Some(0), - nonce: Some(0), - state: 0, - transform_into_action: 0, - }, - contract_create_state_transition: DriveAbciStateTransitionValidationVersion { - basic_structure: Some(0), - advanced_structure: None, - identity_signatures: None, - advanced_minimum_balance_pre_check: None, - nonce: Some(0), - state: 0, - transform_into_action: 0, - }, - contract_update_state_transition: DriveAbciStateTransitionValidationVersion { - basic_structure: None, - advanced_structure: None, - identity_signatures: None, - advanced_minimum_balance_pre_check: None, - nonce: Some(0), - state: 0, - transform_into_action: 0, - }, - documents_batch_state_transition: - DriveAbciDocumentsStateTransitionValidationVersions { - balance_pre_check: 0, - basic_structure: 0, - advanced_structure: 0, - state: 0, - revision: 0, - transform_into_action: 0, - data_triggers: DriveAbciValidationDataTriggerAndBindingVersions { - bindings: 0, - triggers: DriveAbciValidationDataTriggerVersions { - create_contact_request_data_trigger: 0, - create_domain_data_trigger: 0, - create_identity_data_trigger: 0, - create_feature_flag_data_trigger: 0, - create_masternode_reward_shares_data_trigger: 0, - delete_withdrawal_data_trigger: 0, - reject_data_trigger: 0, - }, - }, - is_allowed: 0, - document_create_transition_structure_validation: 0, - document_delete_transition_structure_validation: 0, - document_replace_transition_structure_validation: 0, - document_transfer_transition_structure_validation: 0, - document_purchase_transition_structure_validation: 0, - document_update_price_transition_structure_validation: 0, - document_create_transition_state_validation: 0, - document_delete_transition_state_validation: 0, - document_replace_transition_state_validation: 0, - document_transfer_transition_state_validation: 0, - document_purchase_transition_state_validation: 0, - document_update_price_transition_state_validation: 0, - }, - }, - process_state_transition: 0, - state_transition_to_execution_event_for_check_tx: 0, - penalties: PenaltyAmounts { - identity_id_not_correct: 50000000, - unique_key_already_present: 10000000, - validation_of_added_keys_structure_failure: 10000000, - validation_of_added_keys_proof_of_possession_failure: 50000000, - }, - event_constants: DriveAbciValidationConstants { - maximum_vote_polls_to_process: 2, - maximum_contenders_to_consider: 100, - }, - }, - query: DriveAbciQueryVersions { - max_returned_elements: 100, - response_metadata: 0, - proofs_query: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - document_query: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - prefunded_specialized_balances: DriveAbciQueryPrefundedSpecializedBalancesVersions { - balance: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - identity_based_queries: DriveAbciQueryIdentityVersions { - identity: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - keys: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_nonce: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_contract_nonce: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - balance: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identities_balances: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - balance_and_revision: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_by_public_key_hash: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identities_contract_keys: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - validator_queries: DriveAbciQueryValidatorVersions { - proposed_block_counts_by_evonode_ids: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - proposed_block_counts_by_range: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - data_contract_based_queries: DriveAbciQueryDataContractVersions { - data_contract: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - data_contract_history: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - data_contracts: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - voting_based_queries: DriveAbciQueryVotingVersions { - vote_polls_by_end_date_query: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - contested_resource_vote_state: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - contested_resource_voters_for_identity: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - contested_resource_identity_vote_status: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - contested_resources: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - system: DriveAbciQuerySystemVersions { - version_upgrade_state: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - version_upgrade_vote_status: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - epoch_infos: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - partial_status: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - path_elements: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - total_credits_in_platform: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - }, + validation_and_processing: DRIVE_ABCI_VALIDATION_VERSIONS_V3, + withdrawal_constants: DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V2, + query: DRIVE_ABCI_QUERY_VERSIONS_V1, }, dpp: DPPVersion { - costs: CostVersions { - signature_verify: 0, - }, - validation: DPPValidationVersions { - json_schema_validator: JsonSchemaValidatorVersions { - new: 0, - validate: 0, - compile: 0, - compile_and_validate: 0, - }, - data_contract: DataContractValidationVersions { - validate: 0, - validate_config_update: 0, - validate_index_definitions: 0, - validate_index_naming_duplicates: 0, - validate_not_defined_properties: 0, - validate_property_definition: 0, - }, - document_type: DocumentTypeValidationVersions { - validate_update: 0, - contested_index_limit: 1, - unique_index_limit: 10, - }, - voting: VotingValidationVersions { - allow_other_contenders_time_mainnet_ms: 604_800_000, // 1 week in ms - allow_other_contenders_time_testing_ms: 2_700_000, //45 minutes - votes_allowed_per_masternode: 5, - }, - }, - state_transition_serialization_versions: StateTransitionSerializationVersions { - identity_public_key_in_creation: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_create_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_update_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_top_up_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_credit_withdrawal_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_credit_transfer_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - masternode_vote_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - contract_create_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - contract_update_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - documents_batch_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - document_base_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - document_create_state_transition: DocumentFeatureVersionBounds { - bounds: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - document_replace_state_transition: DocumentFeatureVersionBounds { - bounds: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - document_delete_state_transition: DocumentFeatureVersionBounds { - bounds: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - document_transfer_state_transition: DocumentFeatureVersionBounds { - bounds: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - document_update_price_state_transition: DocumentFeatureVersionBounds { - bounds: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - document_purchase_state_transition: DocumentFeatureVersionBounds { - bounds: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - }, - state_transition_conversion_versions: StateTransitionConversionVersions { - identity_to_identity_create_transition: 0, - identity_to_identity_top_up_transition: 0, - identity_to_identity_withdrawal_transition: 0, - identity_to_identity_create_transition_with_signer: 0, - }, - state_transition_method_versions: StateTransitionMethodVersions { - public_key_in_creation_methods: PublicKeyInCreationMethodVersions { - from_public_key_signed_with_private_key: 0, - from_public_key_signed_external: 0, - hash: 0, - duplicated_key_ids_witness: 0, - duplicated_keys_witness: 0, - validate_identity_public_keys_structure: 0, - }, - }, - state_transitions: StateTransitionVersions { - documents: DocumentTransitionVersions { - documents_batch_transition: DocumentsBatchTransitionVersions { - validation: DocumentsBatchTransitionValidationVersions { - find_duplicates_by_id: 0, - validate_base_structure: 0, - }, - }, - }, - identities: IdentityTransitionVersions { - max_public_keys_in_creation: 6, - asset_locks: IdentityTransitionAssetLockVersions { - required_asset_lock_duff_balance_for_processing_start_for_identity_create: - 200000, - required_asset_lock_duff_balance_for_processing_start_for_identity_top_up: - 50000, - validate_asset_lock_transaction_structure: 0, - validate_instant_asset_lock_proof_structure: 0, - }, - }, - }, - contract_versions: ContractVersions { - max_serialized_size: 65000, - contract_serialization_version: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - contract_structure_version: 0, - created_data_contract_structure: 0, - config: 0, - methods: DataContractMethodVersions { - validate_document: 0, - validate_update: 0, - schema: 0, - }, - document_type_versions: DocumentTypeVersions { - index_versions: DocumentTypeIndexVersions { - index_levels_from_indices: 0, - }, - class_method_versions: DocumentTypeClassMethodVersions { - try_from_schema: 0, - create_document_types_from_document_schemas: 0, - }, - structure_version: 0, - schema: DocumentTypeSchemaVersions { - enrich_with_base_schema: 0, - find_identifier_and_binary_paths: 0, - validate_max_depth: 0, - max_depth: 256, - recursive_schema_validator_versions: RecursiveSchemaValidatorVersions { - traversal_validator: 0, - }, - validate_schema_compatibility: 0, - }, - methods: DocumentTypeMethodVersions { - create_document_from_data: 0, - create_document_with_prevalidated_properties: 0, - prefunded_voting_balance_for_document: 0, - contested_vote_poll_for_document: 0, - estimated_size: 0, - index_for_types: 0, - max_size: 0, - serialize_value_for_key: 0, - deserialize_value_for_key: 0, - }, - }, - }, - document_versions: DocumentVersions { - document_structure_version: 0, - document_serialization_version: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - document_cbor_serialization_version: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - extended_document_structure_version: 0, - extended_document_serialization_version: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - document_method_versions: DocumentMethodVersions { - is_equal_ignoring_timestamps: 0, - hash: 0, - get_raw_for_contract: 0, - get_raw_for_document_type: 0, - }, - }, - identity_versions: IdentityVersions { - identity_structure_version: 0, - identity_key_structure_version: 0, - identity_key_type_method_versions: IdentityKeyTypeMethodVersions { - random_public_key_data: 0, - random_public_and_private_key_data: 0, - }, - }, - voting_versions: VotingVersions { - default_vote_poll_time_duration_mainnet_ms: 1_209_600_000, //2 weeks - default_vote_poll_time_duration_test_network_ms: 5_400_000, //90 minutes - contested_document_vote_poll_stored_info_version: 0, - }, - asset_lock_versions: AssetLockVersions { - reduced_asset_lock_value: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - methods: DPPMethodVersions { - epoch_core_reward_credits_for_distribution: 0, - }, - }, - system_data_contracts: SystemDataContractVersions { - withdrawals: 1, - dpns: 1, - dashpay: 1, - masternode_reward_shares: 1, - feature_flags: 1, + costs: DPP_COSTS_VERSIONS_V1, + validation: DPP_VALIDATION_VERSIONS_V2, + state_transition_serialization_versions: STATE_TRANSITION_SERIALIZATION_VERSIONS_V1, + state_transition_conversion_versions: STATE_TRANSITION_CONVERSION_VERSIONS_V2, + state_transition_method_versions: STATE_TRANSITION_METHOD_VERSIONS_V1, + state_transitions: STATE_TRANSITION_VERSIONS_V1, + contract_versions: CONTRACT_VERSIONS_V1, + document_versions: DOCUMENT_VERSIONS_V1, + identity_versions: IDENTITY_VERSIONS_V1, + voting_versions: VOTING_VERSION_V2, + asset_lock_versions: DPP_ASSET_LOCK_VERSIONS_V1, + methods: DPP_METHOD_VERSIONS_V1, + factory_versions: DPP_FACTORY_VERSIONS_V1, }, + system_data_contracts: SYSTEM_DATA_CONTRACT_VERSIONS_V1, fee_version: FEE_VERSION1, - system_limits: SystemLimits { - estimated_contract_max_serialized_size: 16384, - max_field_value_size: 5000, - max_state_transition_size: 20000, - max_transitions_in_documents_batch: 1, - }, + system_limits: SYSTEM_LIMITS_V1, consensus: ConsensusVersions { - tenderdash_consensus_version: 0, + tenderdash_consensus_version: 1, }, }; diff --git a/packages/rs-platform-version/src/version/mod.rs b/packages/rs-platform-version/src/version/mod.rs index d7346a7097..5c9f2d2942 100644 --- a/packages/rs-platform-version/src/version/mod.rs +++ b/packages/rs-platform-version/src/version/mod.rs @@ -1,22 +1,24 @@ mod protocol_version; -use crate::version::v3::PROTOCOL_VERSION_3; +use crate::version::v5::PROTOCOL_VERSION_5; pub use protocol_version::*; mod consensus_versions; -pub mod contracts; pub mod dpp_versions; pub mod drive_abci_versions; pub mod drive_versions; pub mod fee; -mod limits; #[cfg(feature = "mock-versions")] pub mod mocks; pub mod patches; +pub mod system_data_contract_versions; +mod system_limits; pub mod v1; pub mod v2; pub mod v3; +pub mod v4; +pub mod v5; pub type ProtocolVersion = u32; -pub const LATEST_VERSION: ProtocolVersion = PROTOCOL_VERSION_3; +pub const LATEST_VERSION: ProtocolVersion = PROTOCOL_VERSION_5; pub const INITIAL_PROTOCOL_VERSION: ProtocolVersion = 1; diff --git a/packages/rs-platform-version/src/version/protocol_version.rs b/packages/rs-platform-version/src/version/protocol_version.rs index 607a267844..67f1b96754 100644 --- a/packages/rs-platform-version/src/version/protocol_version.rs +++ b/packages/rs-platform-version/src/version/protocol_version.rs @@ -1,5 +1,4 @@ use crate::error::PlatformVersionError; -use crate::version::contracts::SystemDataContractVersions; use crate::version::dpp_versions::DPPVersion; use crate::version::drive_abci_versions::DriveAbciVersion; use crate::version::drive_versions::DriveVersion; @@ -10,38 +9,39 @@ use crate::version::mocks::v2_test::TEST_PLATFORM_V2; use crate::version::mocks::v3_test::TEST_PLATFORM_V3; #[cfg(feature = "mock-versions")] use crate::version::mocks::TEST_PROTOCOL_VERSION_SHIFT_BYTES; +use crate::version::system_data_contract_versions::SystemDataContractVersions; use crate::version::v1::PLATFORM_V1; #[cfg(feature = "mock-versions")] use std::sync::OnceLock; use crate::version::consensus_versions::ConsensusVersions; -use crate::version::limits::SystemLimits; +use crate::version::system_limits::SystemLimits; use crate::version::v2::PLATFORM_V2; use crate::version::v3::PLATFORM_V3; +use crate::version::v4::PLATFORM_V4; +use crate::version::v5::PLATFORM_V5; use crate::version::ProtocolVersion; pub use versioned_feature_core::*; -#[derive(Clone, Debug, Default)] -pub struct PlatformArchitectureVersion { - pub data_contract_factory_structure_version: FeatureVersion, - pub document_factory_structure_version: FeatureVersion, -} - #[derive(Clone, Debug)] pub struct PlatformVersion { pub protocol_version: ProtocolVersion, - pub proofs: FeatureVersionBounds, pub dpp: DPPVersion, pub drive: DriveVersion, pub drive_abci: DriveAbciVersion, pub consensus: ConsensusVersions, pub fee_version: FeeVersion, - pub platform_architecture: PlatformArchitectureVersion, pub system_data_contracts: SystemDataContractVersions, pub system_limits: SystemLimits, } -pub const PLATFORM_VERSIONS: &[PlatformVersion] = &[PLATFORM_V1, PLATFORM_V2, PLATFORM_V3]; +pub const PLATFORM_VERSIONS: &[PlatformVersion] = &[ + PLATFORM_V1, + PLATFORM_V2, + PLATFORM_V3, + PLATFORM_V4, + PLATFORM_V5, +]; #[cfg(feature = "mock-versions")] // We use OnceLock to be able to modify the version mocks @@ -49,9 +49,8 @@ pub static PLATFORM_TEST_VERSIONS: OnceLock> = OnceLock::ne #[cfg(feature = "mock-versions")] const DEFAULT_PLATFORM_TEST_VERSIONS: &[PlatformVersion] = &[TEST_PLATFORM_V2, TEST_PLATFORM_V3]; -pub const LATEST_PLATFORM_VERSION: &PlatformVersion = &PLATFORM_V3; +pub const LATEST_PLATFORM_VERSION: &PlatformVersion = &PLATFORM_V5; -/// For V3 release we want to do an emergency version upgrade pub const DESIRED_PLATFORM_VERSION: &PlatformVersion = LATEST_PLATFORM_VERSION; impl PlatformVersion { @@ -151,6 +150,10 @@ impl PlatformVersion { .expect("expected to have a platform version") } + pub fn desired<'a>() -> &'a Self { + DESIRED_PLATFORM_VERSION + } + #[cfg(feature = "mock-versions")] /// Set mock versions for testing pub fn replace_test_versions(versions: Vec) { diff --git a/packages/rs-platform-version/src/version/contracts.rs b/packages/rs-platform-version/src/version/system_data_contract_versions/mod.rs similarity index 95% rename from packages/rs-platform-version/src/version/contracts.rs rename to packages/rs-platform-version/src/version/system_data_contract_versions/mod.rs index 84c0d874b1..53af3b5ce0 100644 --- a/packages/rs-platform-version/src/version/contracts.rs +++ b/packages/rs-platform-version/src/version/system_data_contract_versions/mod.rs @@ -1,3 +1,5 @@ +pub mod v1; + use crate::version::FeatureVersion; #[derive(Clone, Debug, Default)] diff --git a/packages/rs-platform-version/src/version/system_data_contract_versions/v1.rs b/packages/rs-platform-version/src/version/system_data_contract_versions/v1.rs new file mode 100644 index 0000000000..205d6fda2a --- /dev/null +++ b/packages/rs-platform-version/src/version/system_data_contract_versions/v1.rs @@ -0,0 +1,10 @@ +use crate::version::system_data_contract_versions::SystemDataContractVersions; + +pub const SYSTEM_DATA_CONTRACT_VERSIONS_V1: SystemDataContractVersions = + SystemDataContractVersions { + withdrawals: 1, + dpns: 1, + dashpay: 1, + masternode_reward_shares: 1, + feature_flags: 1, + }; diff --git a/packages/rs-platform-version/src/version/limits.rs b/packages/rs-platform-version/src/version/system_limits/mod.rs similarity index 57% rename from packages/rs-platform-version/src/version/limits.rs rename to packages/rs-platform-version/src/version/system_limits/mod.rs index 7035d6ae7c..0dd2c5b922 100644 --- a/packages/rs-platform-version/src/version/limits.rs +++ b/packages/rs-platform-version/src/version/system_limits/mod.rs @@ -1,7 +1,12 @@ +pub mod v1; + #[derive(Clone, Debug, Default)] pub struct SystemLimits { pub estimated_contract_max_serialized_size: u16, pub max_field_value_size: u32, pub max_state_transition_size: u64, pub max_transitions_in_documents_batch: u16, + pub withdrawal_transactions_per_block_limit: u16, + pub retry_signing_expired_withdrawal_documents_per_block_limit: u16, + pub max_withdrawal_amount: u64, } diff --git a/packages/rs-platform-version/src/version/system_limits/v1.rs b/packages/rs-platform-version/src/version/system_limits/v1.rs new file mode 100644 index 0000000000..6dacce0b35 --- /dev/null +++ b/packages/rs-platform-version/src/version/system_limits/v1.rs @@ -0,0 +1,11 @@ +use crate::version::system_limits::SystemLimits; + +pub const SYSTEM_LIMITS_V1: SystemLimits = SystemLimits { + estimated_contract_max_serialized_size: 16384, + max_field_value_size: 5120, //5 KiB + max_state_transition_size: 20480, //20 KiB + max_transitions_in_documents_batch: 1, + withdrawal_transactions_per_block_limit: 4, + retry_signing_expired_withdrawal_documents_per_block_limit: 1, + max_withdrawal_amount: 50_000_000_000_000, //500 Dash +}; diff --git a/packages/rs-platform-version/src/version/v1.rs b/packages/rs-platform-version/src/version/v1.rs index 325336c52f..f7803b32c5 100644 --- a/packages/rs-platform-version/src/version/v1.rs +++ b/packages/rs-platform-version/src/version/v1.rs @@ -1,1280 +1,61 @@ use crate::version::consensus_versions::ConsensusVersions; -use crate::version::contracts::SystemDataContractVersions; -use crate::version::dpp_versions::{ - AssetLockVersions, ContractVersions, CostVersions, DPPMethodVersions, DPPValidationVersions, - DPPVersion, DataContractMethodVersions, DataContractValidationVersions, - DocumentFeatureVersionBounds, DocumentMethodVersions, DocumentTransitionVersions, - DocumentTypeClassMethodVersions, DocumentTypeIndexVersions, DocumentTypeMethodVersions, - DocumentTypeSchemaVersions, DocumentTypeValidationVersions, DocumentTypeVersions, - DocumentVersions, DocumentsBatchTransitionValidationVersions, DocumentsBatchTransitionVersions, - IdentityKeyTypeMethodVersions, IdentityTransitionAssetLockVersions, IdentityTransitionVersions, - IdentityVersions, JsonSchemaValidatorVersions, PublicKeyInCreationMethodVersions, - RecursiveSchemaValidatorVersions, StateTransitionConversionVersions, - StateTransitionMethodVersions, StateTransitionSerializationVersions, StateTransitionVersions, - VotingValidationVersions, VotingVersions, -}; -use crate::version::drive_abci_versions::{ - DriveAbciAssetLockValidationVersions, DriveAbciBlockEndMethodVersions, - DriveAbciBlockFeeProcessingMethodVersions, DriveAbciBlockStartMethodVersions, - DriveAbciCoreBasedUpdatesMethodVersions, DriveAbciCoreChainLockMethodVersionsAndConstants, - DriveAbciCoreInstantSendLockMethodVersions, - DriveAbciDocumentsStateTransitionValidationVersions, DriveAbciEngineMethodVersions, - DriveAbciEpochMethodVersions, DriveAbciFeePoolInwardsDistributionMethodVersions, - DriveAbciFeePoolOutwardsDistributionMethodVersions, - DriveAbciIdentityCreditWithdrawalMethodVersions, DriveAbciInitializationMethodVersions, - DriveAbciMasternodeIdentitiesUpdatesMethodVersions, DriveAbciMethodVersions, - DriveAbciPlatformStateStorageMethodVersions, DriveAbciProtocolUpgradeMethodVersions, - DriveAbciQueryDataContractVersions, DriveAbciQueryIdentityVersions, - DriveAbciQueryPrefundedSpecializedBalancesVersions, DriveAbciQuerySystemVersions, - DriveAbciQueryValidatorVersions, DriveAbciQueryVersions, DriveAbciQueryVotingVersions, - DriveAbciStateTransitionCommonValidationVersions, - DriveAbciStateTransitionProcessingMethodVersions, DriveAbciStateTransitionValidationVersion, - DriveAbciStateTransitionValidationVersions, DriveAbciStructureVersions, - DriveAbciValidationConstants, DriveAbciValidationDataTriggerAndBindingVersions, - DriveAbciValidationDataTriggerVersions, DriveAbciValidationVersions, DriveAbciVersion, - DriveAbciVotingMethodVersions, PenaltyAmounts, -}; -use crate::version::drive_versions::{ - DriveAssetLockMethodVersions, DriveBalancesMethodVersions, DriveBatchOperationsMethodVersion, - DriveContractApplyMethodVersions, DriveContractCostsMethodVersions, - DriveContractGetMethodVersions, DriveContractInsertMethodVersions, DriveContractMethodVersions, - DriveContractProveMethodVersions, DriveContractUpdateMethodVersions, - DriveCreditPoolEpochsMethodVersions, DriveCreditPoolMethodVersions, - DriveCreditPoolPendingEpochRefundsMethodVersions, - DriveCreditPoolStorageFeeDistributionPoolMethodVersions, - DriveCreditPoolUnpaidEpochMethodVersions, DriveDataContractOperationMethodVersions, - DriveDocumentDeleteMethodVersions, DriveDocumentEstimationCostsMethodVersions, - DriveDocumentIndexUniquenessMethodVersions, DriveDocumentInsertContestedMethodVersions, - DriveDocumentInsertMethodVersions, DriveDocumentMethodVersions, - DriveDocumentQueryMethodVersions, DriveDocumentUpdateMethodVersions, - DriveEstimatedCostsMethodVersions, DriveFeesMethodVersions, DriveFetchMethodVersions, - DriveGroveApplyMethodVersions, DriveGroveBasicMethodVersions, DriveGroveBatchMethodVersions, - DriveGroveCostMethodVersions, DriveGroveMethodVersions, - DriveIdentityContractInfoMethodVersions, DriveIdentityCostEstimationMethodVersions, - DriveIdentityFetchAttributesMethodVersions, DriveIdentityFetchFullIdentityMethodVersions, - DriveIdentityFetchMethodVersions, DriveIdentityFetchPartialIdentityMethodVersions, - DriveIdentityFetchPublicKeyHashesMethodVersions, DriveIdentityInsertMethodVersions, - DriveIdentityKeyHashesToIdentityInsertMethodVersions, DriveIdentityKeysFetchMethodVersions, - DriveIdentityKeysInsertMethodVersions, DriveIdentityKeysMethodVersions, - DriveIdentityKeysProveMethodVersions, DriveIdentityMethodVersions, - DriveIdentityProveMethodVersions, DriveIdentityUpdateMethodVersions, - DriveIdentityWithdrawalDocumentMethodVersions, DriveIdentityWithdrawalMethodVersions, - DriveIdentityWithdrawalTransactionIndexMethodVersions, - DriveIdentityWithdrawalTransactionMethodVersions, - DriveIdentityWithdrawalTransactionQueueMethodVersions, DriveInitializationMethodVersions, - DriveMethodVersions, DriveOperationsMethodVersion, DrivePlatformStateMethodVersions, - DrivePlatformSystemMethodVersions, DrivePrefundedSpecializedMethodVersions, - DriveProtocolUpgradeVersions, DriveProveMethodVersions, - DriveStateTransitionActionConvertToHighLevelOperationsMethodVersions, - DriveStateTransitionMethodVersions, DriveStateTransitionOperationMethodVersions, - DriveStructureVersion, DriveSystemEstimationCostsMethodVersions, - DriveVerifyContractMethodVersions, DriveVerifyDocumentMethodVersions, - DriveVerifyIdentityMethodVersions, DriveVerifyMethodVersions, - DriveVerifySingleDocumentMethodVersions, DriveVerifyStateTransitionMethodVersions, - DriveVerifySystemMethodVersions, DriveVerifyVoteMethodVersions, DriveVersion, - DriveVoteCleanupMethodVersions, DriveVoteContestedResourceInsertMethodVersions, - DriveVoteFetchMethodVersions, DriveVoteInsertMethodVersions, DriveVoteMethodVersions, - DriveVoteSetupMethodVersions, DriveVoteStorageFormMethodVersions, -}; +use crate::version::dpp_versions::dpp_asset_lock_versions::v1::DPP_ASSET_LOCK_VERSIONS_V1; +use crate::version::dpp_versions::dpp_contract_versions::v1::CONTRACT_VERSIONS_V1; +use crate::version::dpp_versions::dpp_costs_versions::v1::DPP_COSTS_VERSIONS_V1; +use crate::version::dpp_versions::dpp_document_versions::v1::DOCUMENT_VERSIONS_V1; +use crate::version::dpp_versions::dpp_factory_versions::v1::DPP_FACTORY_VERSIONS_V1; +use crate::version::dpp_versions::dpp_identity_versions::v1::IDENTITY_VERSIONS_V1; +use crate::version::dpp_versions::dpp_method_versions::v1::DPP_METHOD_VERSIONS_V1; +use crate::version::dpp_versions::dpp_state_transition_conversion_versions::v1::STATE_TRANSITION_CONVERSION_VERSIONS_V1; +use crate::version::dpp_versions::dpp_state_transition_method_versions::v1::STATE_TRANSITION_METHOD_VERSIONS_V1; +use crate::version::dpp_versions::dpp_state_transition_serialization_versions::v1::STATE_TRANSITION_SERIALIZATION_VERSIONS_V1; +use crate::version::dpp_versions::dpp_state_transition_versions::v1::STATE_TRANSITION_VERSIONS_V1; +use crate::version::dpp_versions::dpp_validation_versions::v1::DPP_VALIDATION_VERSIONS_V1; +use crate::version::dpp_versions::dpp_voting_versions::v1::VOTING_VERSION_V1; +use crate::version::dpp_versions::DPPVersion; +use crate::version::drive_abci_versions::drive_abci_method_versions::v1::DRIVE_ABCI_METHOD_VERSIONS_V1; +use crate::version::drive_abci_versions::drive_abci_query_versions::v1::DRIVE_ABCI_QUERY_VERSIONS_V1; +use crate::version::drive_abci_versions::drive_abci_structure_versions::v1::DRIVE_ABCI_STRUCTURE_VERSIONS_V1; +use crate::version::drive_abci_versions::drive_abci_validation_versions::v1::DRIVE_ABCI_VALIDATION_VERSIONS_V1; +use crate::version::drive_abci_versions::drive_abci_withdrawal_constants::v1::DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V1; +use crate::version::drive_abci_versions::DriveAbciVersion; +use crate::version::drive_versions::v1::DRIVE_VERSION_V1; use crate::version::fee::v1::FEE_VERSION1; -use crate::version::limits::SystemLimits; -use crate::version::protocol_version::{FeatureVersionBounds, PlatformVersion}; -use crate::version::{PlatformArchitectureVersion, ProtocolVersion}; -use grovedb_version::version::v1::GROVE_V1; +use crate::version::protocol_version::PlatformVersion; +use crate::version::system_data_contract_versions::v1::SYSTEM_DATA_CONTRACT_VERSIONS_V1; +use crate::version::system_limits::v1::SYSTEM_LIMITS_V1; +use crate::version::ProtocolVersion; pub const PROTOCOL_VERSION_1: ProtocolVersion = 1; pub const PLATFORM_V1: PlatformVersion = PlatformVersion { protocol_version: 1, - proofs: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - drive: DriveVersion { - structure: DriveStructureVersion { - document_indexes: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_indexes: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - pools: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - methods: DriveMethodVersions { - initialization: DriveInitializationMethodVersions { - create_initial_state_structure: 0, - }, - credit_pools: DriveCreditPoolMethodVersions { - epochs: DriveCreditPoolEpochsMethodVersions { - get_epochs_infos: 0, - get_epochs_protocol_versions: 0, - prove_epochs_infos: 0, - get_epoch_fee_multiplier: 0, - get_epoch_processing_credits_for_distribution: 0, - get_epoch_storage_credits_for_distribution: 0, - get_epoch_total_credits_for_distribution: 0, - get_storage_credits_for_distribution_for_epochs_in_range: 0, - get_epoch_start_time: 0, - get_epoch_start_block_core_height: 0, - get_epoch_start_block_height: 0, - get_first_epoch_start_block_info_between_epochs: 0, - fetch_epoch_proposers: 0, - prove_epoch_proposers: 0, - get_epochs_proposer_block_count: 0, - add_update_pending_epoch_refunds_operations: 0, - is_epochs_proposers_tree_empty: 0, - }, - pending_epoch_refunds: DriveCreditPoolPendingEpochRefundsMethodVersions { - add_delete_pending_epoch_refunds_except_specified: 0, - fetch_and_add_pending_epoch_refunds_to_collection: 0, - fetch_pending_epoch_refunds: 0, - add_update_pending_epoch_refunds_operations: 0, - }, - storage_fee_distribution_pool: - DriveCreditPoolStorageFeeDistributionPoolMethodVersions { - get_storage_fees_from_distribution_pool: 0, - }, - unpaid_epoch: DriveCreditPoolUnpaidEpochMethodVersions { - get_unpaid_epoch_index: 0, - }, - }, - protocol_upgrade: DriveProtocolUpgradeVersions { - clear_version_information: 0, - fetch_versions_with_counter: 0, - fetch_proved_versions_with_counter: 0, - fetch_validator_version_votes: 0, - fetch_proved_validator_version_votes: 0, - remove_validators_proposed_app_versions: 0, - update_validator_proposed_app_version: 0, - }, - prove: DriveProveMethodVersions { - prove_elements: 0, - prove_multiple_state_transition_results: 0, - }, - balances: DriveBalancesMethodVersions { - add_to_system_credits: 0, - add_to_system_credits_operations: 0, - remove_from_system_credits: 0, - remove_from_system_credits_operations: 0, - calculate_total_credits_balance: 0, - }, - document: DriveDocumentMethodVersions { - query: DriveDocumentQueryMethodVersions { query_documents: 0, query_contested_documents: 0, query_contested_documents_vote_state: 0, query_documents_with_flags: 0 }, - delete: DriveDocumentDeleteMethodVersions { - add_estimation_costs_for_remove_document_to_primary_storage: 0, - delete_document_for_contract: 0, - delete_document_for_contract_id: 0, - delete_document_for_contract_apply_and_add_to_operations: 0, - remove_document_from_primary_storage: 0, - remove_reference_for_index_level_for_contract_operations: 0, - remove_indices_for_index_level_for_contract_operations: 0, - remove_indices_for_top_index_level_for_contract_operations: 0, - delete_document_for_contract_id_with_named_type_operations: 0, - delete_document_for_contract_with_named_type_operations: 0, - delete_document_for_contract_operations: 0, - }, - insert: DriveDocumentInsertMethodVersions { - add_document: 0, - add_document_for_contract: 0, - add_document_for_contract_apply_and_add_to_operations: 0, - add_document_for_contract_operations: 0, - add_document_to_primary_storage: 0, - add_indices_for_index_level_for_contract_operations: 0, - add_indices_for_top_index_level_for_contract_operations: 0, - add_reference_for_index_level_for_contract_operations: 0, - }, - insert_contested: DriveDocumentInsertContestedMethodVersions { - add_contested_document: 0, - add_contested_document_for_contract: 0, - add_contested_document_for_contract_apply_and_add_to_operations: 0, - add_contested_document_for_contract_operations: 0, - add_contested_document_to_primary_storage: 0, - add_contested_indices_for_contract_operations: 0, - add_contested_reference_and_vote_subtree_to_document_operations: 0, - add_contested_vote_subtree_for_non_identities_operations: 0, - }, - update: DriveDocumentUpdateMethodVersions { - add_update_multiple_documents_operations: 0, - update_document_for_contract: 0, - update_document_for_contract_apply_and_add_to_operations: 0, - update_document_for_contract_id: 0, - update_document_for_contract_operations: 0, - update_document_with_serialization_for_contract: 0, - update_serialized_document_for_contract: 0, - }, - estimation_costs: DriveDocumentEstimationCostsMethodVersions { - add_estimation_costs_for_add_document_to_primary_storage: 0, - add_estimation_costs_for_add_contested_document_to_primary_storage: 0, - stateless_delete_of_non_tree_for_costs: 0, - }, - index_uniqueness: DriveDocumentIndexUniquenessMethodVersions { - validate_document_uniqueness: 0, - validate_document_create_transition_action_uniqueness: 0, - validate_document_replace_transition_action_uniqueness: 0, - validate_document_transfer_transition_action_uniqueness: 0, - validate_document_purchase_transition_action_uniqueness: 0, - validate_document_update_price_transition_action_uniqueness: 0, - validate_uniqueness_of_data: 0, - }, - }, - vote: DriveVoteMethodVersions { - insert: DriveVoteInsertMethodVersions { - register_identity_vote: 0, - }, - contested_resource_insert: DriveVoteContestedResourceInsertMethodVersions { - register_contested_resource_identity_vote: 0, - insert_stored_info_for_contested_resource_vote_poll: 0, - register_identity_vote: 0, - add_vote_poll_end_date_query_operations: 0, - }, - cleanup: DriveVoteCleanupMethodVersions { - remove_specific_vote_references_given_by_identity: 0, - remove_specific_votes_given_by_identity: 0, - remove_contested_resource_vote_poll_end_date_query_operations: 0, - remove_contested_resource_vote_poll_votes_operations: 0, - remove_contested_resource_vote_poll_documents_operations: 0, - remove_contested_resource_vote_poll_contenders_operations: 0, - remove_contested_resource_top_level_index_operations: 0, - remove_contested_resource_info_operations: 0, - }, - setup: DriveVoteSetupMethodVersions { - add_initial_vote_tree_main_structure_operations: 0, - }, - storage_form: DriveVoteStorageFormMethodVersions { - resolve_with_contract: 0, - }, - fetch: DriveVoteFetchMethodVersions { - fetch_identities_voting_for_contenders: 0, - fetch_contested_document_vote_poll_stored_info: 0, - fetch_identity_contested_resource_vote: 0, - }, - }, - contract: 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: 0, - }, - update: DriveContractUpdateMethodVersions { update_contract: 0 }, - costs: DriveContractCostsMethodVersions { - add_estimation_costs_for_contract_insertion: 0, - }, - get: DriveContractGetMethodVersions { - fetch_contract: 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, - }, - }, - fees: DriveFeesMethodVersions { calculate_fee: 0 }, - estimated_costs: DriveEstimatedCostsMethodVersions { - add_estimation_costs_for_levels_up_to_contract: 0, - add_estimation_costs_for_levels_up_to_contract_document_type_excluded: 0, - add_estimation_costs_for_contested_document_tree_levels_up_to_contract: 0, - add_estimation_costs_for_contested_document_tree_levels_up_to_contract_document_type_excluded: 0, - }, - asset_lock: DriveAssetLockMethodVersions { - add_asset_lock_outpoint: 0, - add_estimation_costs_for_adding_asset_lock: 0, - fetch_asset_lock_outpoint_info: 0, - }, - verify: DriveVerifyMethodVersions { - contract: DriveVerifyContractMethodVersions { - verify_contract: 0, - verify_contract_history: 0, - }, - document: DriveVerifyDocumentMethodVersions { - verify_proof: 0, - verify_proof_keep_serialized: 0, - verify_start_at_document_in_proof: 0, - }, - identity: DriveVerifyIdentityMethodVersions { - verify_full_identities_by_public_key_hashes: 0, - verify_full_identity_by_identity_id: 0, - verify_full_identity_by_public_key_hash: 0, - verify_identity_balance_for_identity_id: 0, - verify_identity_balances_for_identity_ids: 0, - verify_identity_id_by_public_key_hash: 0, - verify_identity_ids_by_public_key_hashes: 0, - verify_identity_keys_by_identity_id: 0, - verify_identity_nonce: 0, - verify_identity_contract_nonce: 0, - verify_identities_contract_keys: 0, - verify_identity_revision_for_identity_id: 0, - }, - single_document: DriveVerifySingleDocumentMethodVersions { - verify_proof: 0, - verify_proof_keep_serialized: 0, - }, - system: DriveVerifySystemMethodVersions { - verify_epoch_infos: 0, - verify_epoch_proposers: 0, - verify_elements: 0, - verify_total_credits_in_system: 0, - verify_upgrade_state: 0, - verify_upgrade_vote_status: 0, - }, - voting: DriveVerifyVoteMethodVersions { - verify_masternode_vote: 0, - verify_start_at_contender_in_proof: 0, - verify_vote_poll_votes_proof: 0, - verify_identity_votes_given_proof: 0, - verify_vote_poll_vote_state_proof: 0, - verify_contests_proof: 0, - verify_vote_polls_by_end_date_proof: 0, - verify_specialized_balance: 0, - }, - state_transition: DriveVerifyStateTransitionMethodVersions { - verify_state_transition_was_executed_with_proof: 0, - }, - }, - identity: DriveIdentityMethodVersions { - fetch: DriveIdentityFetchMethodVersions { - public_key_hashes: DriveIdentityFetchPublicKeyHashesMethodVersions { - fetch_full_identities_by_unique_public_key_hashes: 0, - fetch_full_identity_by_unique_public_key_hash: 0, - fetch_identity_id_by_unique_public_key_hash: 0, - fetch_identity_ids_by_non_unique_public_key_hash: 0, - fetch_identity_ids_by_unique_public_key_hashes: 0, - fetch_serialized_full_identity_by_unique_public_key_hash: 0, - has_any_of_unique_public_key_hashes: 0, - has_non_unique_public_key_hash: 0, - has_non_unique_public_key_hash_already_for_identity: 0, - has_unique_public_key_hash: 0, - }, - attributes: DriveIdentityFetchAttributesMethodVersions { - revision: 0, - nonce: 0, - identity_contract_nonce: 0, - balance: 0, - balance_include_debt: 0, - negative_balance: 0, - }, - partial_identity: DriveIdentityFetchPartialIdentityMethodVersions { - fetch_identity_revision_with_keys: 0, - fetch_identity_balance_with_keys: 0, - fetch_identity_balance_with_keys_and_revision: 0, - fetch_identity_with_balance: 0, - fetch_identity_keys: 0, - }, - full_identity: DriveIdentityFetchFullIdentityMethodVersions { - fetch_full_identity: Some(0), - fetch_full_identities: Some(0), - }, - }, - prove: DriveIdentityProveMethodVersions { - full_identity: 0, - full_identities: 0, - identity_nonce: 0, - identity_contract_nonce: 0, - identities_contract_keys: 0, - prove_full_identities_by_unique_public_key_hashes: 0, - prove_full_identity_by_unique_public_key_hash: 0, - prove_identity_id_by_unique_public_key_hash: 0, - prove_identity_ids_by_unique_public_key_hashes: 0, - }, - keys: DriveIdentityKeysMethodVersions { - fetch: DriveIdentityKeysFetchMethodVersions { - fetch_all_current_identity_keys: 0, - fetch_all_identity_keys: 0, - fetch_identities_all_keys: 0, - fetch_identity_keys: 0, - fetch_identities_contract_keys: 0, - }, - prove: DriveIdentityKeysProveMethodVersions { - prove_identities_all_keys: 0, - prove_identity_keys: 0, - }, - insert: DriveIdentityKeysInsertMethodVersions { - create_key_tree_with_keys: 0, - create_new_identity_key_query_trees: 0, - insert_key_searchable_references: 0, - insert_key_to_storage: 0, - insert_new_non_unique_key: 0, - insert_new_unique_key: 0, - replace_key_in_storage: 0, - }, - insert_key_hash_identity_reference: - DriveIdentityKeyHashesToIdentityInsertMethodVersions { - add_estimation_costs_for_insert_non_unique_public_key_hash_reference: 0, - add_estimation_costs_for_insert_unique_public_key_hash_reference: 0, - insert_non_unique_public_key_hash_reference_to_identity: 0, - insert_reference_to_non_unique_key: 0, - insert_reference_to_unique_key: 0, - insert_unique_public_key_hash_reference_to_identity: 0, - }, - }, - update: DriveIdentityUpdateMethodVersions { - update_identity_revision: 0, - merge_identity_nonce: 0, - update_identity_negative_credit_operation: 0, - initialize_identity_revision: 0, - disable_identity_keys: 0, - re_enable_identity_keys: 0, - add_new_non_unique_keys_to_identity: 0, - add_new_unique_keys_to_identity: 0, - add_new_keys_to_identity: 0, - insert_identity_balance: 0, - initialize_negative_identity_balance: 0, - add_to_identity_balance: 0, - add_to_previous_balance: 0, - apply_balance_change_from_fee_to_identity: 0, - remove_from_identity_balance: 0, - refresh_identity_key_reference_operations: 0, - }, - insert: DriveIdentityInsertMethodVersions { - add_new_identity: 0, - }, - contract_info: DriveIdentityContractInfoMethodVersions { - add_potential_contract_info_for_contract_bounded_key: 0, - refresh_potential_contract_info_key_references: 0, - merge_identity_contract_nonce: 0, - }, - cost_estimation: DriveIdentityCostEstimationMethodVersions { - for_authentication_keys_security_level_in_key_reference_tree: 0, - for_balances: 0, - for_contract_info: 0, - for_contract_info_group: 0, - for_contract_info_group_keys: 0, - for_contract_info_group_key_purpose: 0, - for_keys_for_identity_id: 0, - for_negative_credit: 0, - for_purpose_in_key_reference_tree: 0, - for_root_key_reference_tree: 0, - for_update_revision: 0, - }, - withdrawals: DriveIdentityWithdrawalMethodVersions { - document: DriveIdentityWithdrawalDocumentMethodVersions { - fetch_oldest_withdrawal_documents_by_status: 0, - find_up_to_100_withdrawal_documents_by_status_and_transaction_indices: 0, - }, - transaction: DriveIdentityWithdrawalTransactionMethodVersions { - index: DriveIdentityWithdrawalTransactionIndexMethodVersions { - fetch_next_withdrawal_transaction_index: 0, - add_update_next_withdrawal_transaction_index_operation: 0, - }, - queue: DriveIdentityWithdrawalTransactionQueueMethodVersions { - add_enqueue_untied_withdrawal_transaction_operations: 0, - dequeue_untied_withdrawal_transactions: 0, - }, - }, - }, - }, - platform_system: DrivePlatformSystemMethodVersions { - estimation_costs: DriveSystemEstimationCostsMethodVersions { - for_total_system_credits_update: 0, - }, - }, - operations: DriveOperationsMethodVersion { - rollback_transaction: 0, - drop_cache: 0, - commit_transaction: 0, - apply_partial_batch_low_level_drive_operations: 0, - apply_partial_batch_grovedb_operations: 0, - apply_batch_low_level_drive_operations: 0, - apply_batch_grovedb_operations: 0, - }, - state_transitions: DriveStateTransitionMethodVersions { - operations: DriveStateTransitionOperationMethodVersions { - finalization_tasks: 0, - contracts: DriveDataContractOperationMethodVersions { - finalization_tasks: 0, - }, - }, - convert_to_high_level_operations: - DriveStateTransitionActionConvertToHighLevelOperationsMethodVersions { - data_contract_create_transition: 0, - data_contract_update_transition: 0, - document_create_transition: 0, - document_delete_transition: 0, - document_purchase_transition: 0, - document_replace_transition: 0, - document_transfer_transition: 0, - document_update_price_transition: 0, - documents_batch_transition: 0, - identity_create_transition: 0, - identity_credit_transfer_transition: 0, - identity_credit_withdrawal_transition: 0, - identity_top_up_transition: 0, - identity_update_transition: 0, - masternode_vote_transition: 0, - bump_identity_data_contract_nonce: 0, - bump_identity_nonce: 0, - partially_use_asset_lock: 0, - }, - }, - batch_operations: DriveBatchOperationsMethodVersion { - convert_drive_operations_to_grove_operations: 0, - apply_drive_operations: 0, - }, - platform_state: DrivePlatformStateMethodVersions { - fetch_platform_state_bytes: 0, - store_platform_state_bytes: 0, - }, - fetch: DriveFetchMethodVersions { fetch_elements: 0 }, - prefunded_specialized_balances: DrivePrefundedSpecializedMethodVersions { - fetch_single: 0, - prove_single: 0, - add_prefunded_specialized_balance: 0, - add_prefunded_specialized_balance_operations: 0, - deduct_from_prefunded_specialized_balance: 0, - deduct_from_prefunded_specialized_balance_operations: 0, - estimated_cost_for_prefunded_specialized_balance_update: 0, - }, - }, - grove_methods: DriveGroveMethodVersions { - basic: DriveGroveBasicMethodVersions { - grove_insert: 0, - grove_insert_empty_tree: 0, - grove_insert_empty_sum_tree: 0, - grove_insert_if_not_exists: 0, - grove_clear: 0, - grove_delete: 0, - grove_get_raw: 0, - grove_get_raw_optional: 0, - grove_get_raw_value_u64_from_encoded_var_vec: 0, - grove_get: 0, - grove_get_path_query_serialized_results: 0, - grove_get_path_query_serialized_or_sum_results: 0, - grove_get_path_query: 0, - grove_get_path_query_with_optional: 0, - grove_get_raw_path_query_with_optional: 0, - grove_get_raw_path_query: 0, - grove_get_proved_path_query: 0, - grove_get_proved_path_query_with_conditional: 0, - grove_get_sum_tree_total_value: 0, - grove_has_raw: 0, - }, - batch: DriveGroveBatchMethodVersions { - batch_insert_empty_tree: 0, - batch_insert_empty_tree_if_not_exists: 0, - batch_insert_empty_tree_if_not_exists_check_existing_operations: 0, - batch_insert: 0, - batch_insert_if_not_exists: 0, - batch_insert_if_changed_value: 0, - batch_replace: 0, - batch_delete: 0, - batch_remove_raw: 0, - batch_delete_up_tree_while_empty: 0, - batch_refresh_reference: 0, - }, - apply: DriveGroveApplyMethodVersions { - grove_apply_operation: 0, - grove_apply_batch: 0, - grove_apply_partial_batch: 0, - }, - costs: DriveGroveCostMethodVersions { - grove_batch_operations_costs: 0, - }, - }, - grove_version: GROVE_V1, - }, - platform_architecture: PlatformArchitectureVersion { - data_contract_factory_structure_version: 0, - document_factory_structure_version: 0, - }, + drive: DRIVE_VERSION_V1, drive_abci: DriveAbciVersion { - structs: DriveAbciStructureVersions { - platform_state_structure: 0, - platform_state_for_saving_structure: 0, - state_transition_execution_context: 0, - commit: 0, - masternode: 0, - signature_verification_quorum_set: 0, - }, - methods: DriveAbciMethodVersions { - engine: DriveAbciEngineMethodVersions { - init_chain: 0, - check_tx: 0, - run_block_proposal: 0, - finalize_block_proposal: 0, - consensus_params_update: 0, - }, - initialization: DriveAbciInitializationMethodVersions { - initial_core_height_and_time: 0, - create_genesis_state: 0, - }, - core_based_updates: DriveAbciCoreBasedUpdatesMethodVersions { - update_core_info: 0, - update_masternode_list: 0, - update_quorum_info: 0, - masternode_updates: DriveAbciMasternodeIdentitiesUpdatesMethodVersions { - get_voter_identity_key: 0, - get_operator_identity_keys: 0, - get_owner_identity_withdrawal_key: 0, - get_voter_identifier_from_masternode_list_item: 0, - get_operator_identifier_from_masternode_list_item: 0, - create_operator_identity: 0, - create_owner_identity: 0, - create_voter_identity: 0, - disable_identity_keys: 0, - update_masternode_identities: 0, - update_operator_identity: 0, - update_owner_withdrawal_address: 0, - update_voter_identity: 0, - }, - }, - protocol_upgrade: DriveAbciProtocolUpgradeMethodVersions { - check_for_desired_protocol_upgrade: 0, - upgrade_protocol_version_on_epoch_change: 0, - protocol_version_upgrade_percentage_needed: 75, - }, - block_fee_processing: DriveAbciBlockFeeProcessingMethodVersions { - add_process_epoch_change_operations: 0, - process_block_fees: 0, - }, - core_chain_lock: DriveAbciCoreChainLockMethodVersionsAndConstants { - choose_quorum: 0, - verify_chain_lock: 0, - verify_chain_lock_locally: 0, - verify_chain_lock_through_core: 0, - make_sure_core_is_synced_to_chain_lock: 0, - recent_block_count_amount: 2, - }, - core_instant_send_lock: DriveAbciCoreInstantSendLockMethodVersions { - verify_recent_signature_locally: 0, - }, - fee_pool_inwards_distribution: DriveAbciFeePoolInwardsDistributionMethodVersions { - add_distribute_block_fees_into_pools_operations: 0, - add_distribute_storage_fee_to_epochs_operations: 0, - }, - fee_pool_outwards_distribution: DriveAbciFeePoolOutwardsDistributionMethodVersions { - add_distribute_fees_from_oldest_unpaid_epoch_pool_to_proposers_operations: 0, - add_epoch_pool_to_proposers_payout_operations: 0, - find_oldest_epoch_needing_payment: 0, - fetch_reward_shares_list_for_masternode: 0, - }, - withdrawals: DriveAbciIdentityCreditWithdrawalMethodVersions { - build_untied_withdrawal_transactions_from_documents: 0, - dequeue_and_build_unsigned_withdrawal_transactions: 0, - fetch_transactions_block_inclusion_status: 0, - pool_withdrawals_into_transactions_queue: 0, - update_broadcasted_withdrawal_statuses: 0, - append_signatures_and_broadcast_withdrawal_transactions: 0, - }, - voting: DriveAbciVotingMethodVersions { - keep_record_of_finished_contested_resource_vote_poll: 0, - clean_up_after_vote_poll_end: 0, - clean_up_after_contested_resources_vote_poll_end: 0, - check_for_ended_vote_polls: 0, - tally_votes_for_contested_document_resource_vote_poll: 0, - award_document_to_winner: 0, - delay_vote_poll: 0, - run_dao_platform_events: 0, - remove_votes_for_removed_masternodes: 0, - }, - state_transition_processing: DriveAbciStateTransitionProcessingMethodVersions { - execute_event: 0, - process_raw_state_transitions: 0, - decode_raw_state_transitions: 0, - validate_fees_of_event: 0, - }, - epoch: DriveAbciEpochMethodVersions { - gather_epoch_info: 0, - get_genesis_time: 0, - }, - block_start: DriveAbciBlockStartMethodVersions { - clear_drive_block_cache: 0, - }, - block_end: DriveAbciBlockEndMethodVersions { - update_state_cache: 0, - update_drive_cache: 0, - validator_set_update: 0, - }, - platform_state_storage: DriveAbciPlatformStateStorageMethodVersions { - fetch_platform_state: 0, - store_platform_state: 0, - }, - }, - validation_and_processing: DriveAbciValidationVersions { - state_transitions: DriveAbciStateTransitionValidationVersions { - common_validation_methods: DriveAbciStateTransitionCommonValidationVersions { - asset_locks: DriveAbciAssetLockValidationVersions { - fetch_asset_lock_transaction_output_sync: 0, - verify_asset_lock_is_not_spent_and_has_enough_balance: 0, - }, - validate_identity_public_key_contract_bounds: 0, - validate_identity_public_key_ids_dont_exist_in_state: 0, - validate_identity_public_key_ids_exist_in_state: 0, - validate_state_transition_identity_signed: 0, - validate_unique_identity_public_key_hashes_in_state: 0, - validate_master_key_uniqueness: 0, - validate_simple_pre_check_balance: 0, - }, - max_asset_lock_usage_attempts: 16, - identity_create_state_transition: DriveAbciStateTransitionValidationVersion { - basic_structure: Some(0), - advanced_structure: Some(0), - identity_signatures: Some(0), - advanced_minimum_balance_pre_check: None, - nonce: None, - state: 0, - transform_into_action: 0, - }, - identity_update_state_transition: DriveAbciStateTransitionValidationVersion { - basic_structure: Some(0), - advanced_structure: Some(0), - identity_signatures: Some(0), - advanced_minimum_balance_pre_check: None, - nonce: Some(0), - state: 0, - transform_into_action: 0, - }, - identity_top_up_state_transition: DriveAbciStateTransitionValidationVersion { - basic_structure: Some(0), - advanced_structure: None, - identity_signatures: None, - advanced_minimum_balance_pre_check: None, - nonce: None, - state: 0, - transform_into_action: 0, - }, - identity_credit_withdrawal_state_transition: - DriveAbciStateTransitionValidationVersion { - basic_structure: Some(0), - advanced_structure: None, - identity_signatures: None, - advanced_minimum_balance_pre_check: Some(0), - nonce: Some(0), - state: 0, - transform_into_action: 0, - }, - identity_credit_transfer_state_transition: - DriveAbciStateTransitionValidationVersion { - basic_structure: Some(0), - advanced_structure: None, - identity_signatures: None, - advanced_minimum_balance_pre_check: Some(0), - nonce: Some(0), - state: 0, - transform_into_action: 0, - }, - masternode_vote_state_transition: DriveAbciStateTransitionValidationVersion { - basic_structure: None, - advanced_structure: Some(0), - identity_signatures: None, - advanced_minimum_balance_pre_check: Some(0), - nonce: Some(0), - state: 0, - transform_into_action: 0, - }, - contract_create_state_transition: DriveAbciStateTransitionValidationVersion { - basic_structure: Some(0), - advanced_structure: None, - identity_signatures: None, - advanced_minimum_balance_pre_check: None, - nonce: Some(0), - state: 0, - transform_into_action: 0, - }, - contract_update_state_transition: DriveAbciStateTransitionValidationVersion { - basic_structure: None, - advanced_structure: None, - identity_signatures: None, - advanced_minimum_balance_pre_check: None, - nonce: Some(0), - state: 0, - transform_into_action: 0, - }, - documents_batch_state_transition: - DriveAbciDocumentsStateTransitionValidationVersions { - balance_pre_check: 0, - basic_structure: 0, - advanced_structure: 0, - state: 0, - revision: 0, - transform_into_action: 0, - data_triggers: DriveAbciValidationDataTriggerAndBindingVersions { - bindings: 0, - triggers: DriveAbciValidationDataTriggerVersions { - create_contact_request_data_trigger: 0, - create_domain_data_trigger: 0, - create_identity_data_trigger: 0, - create_feature_flag_data_trigger: 0, - create_masternode_reward_shares_data_trigger: 0, - delete_withdrawal_data_trigger: 0, - reject_data_trigger: 0, - }, - }, - is_allowed: 0, - document_create_transition_structure_validation: 0, - document_delete_transition_structure_validation: 0, - document_replace_transition_structure_validation: 0, - document_transfer_transition_structure_validation: 0, - document_purchase_transition_structure_validation: 0, - document_update_price_transition_structure_validation: 0, - document_create_transition_state_validation: 0, - document_delete_transition_state_validation: 0, - document_replace_transition_state_validation: 0, - document_transfer_transition_state_validation: 0, - document_purchase_transition_state_validation: 0, - document_update_price_transition_state_validation: 0, - }, - }, - process_state_transition: 0, - state_transition_to_execution_event_for_check_tx: 0, - penalties: PenaltyAmounts { - identity_id_not_correct: 50000000, - unique_key_already_present: 10000000, - validation_of_added_keys_structure_failure: 10000000, - validation_of_added_keys_proof_of_possession_failure: 50000000, - }, - event_constants: DriveAbciValidationConstants { - maximum_vote_polls_to_process: 2, - maximum_contenders_to_consider: 100, - }, - }, - query: DriveAbciQueryVersions { - max_returned_elements: 100, - response_metadata: 0, - proofs_query: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - document_query: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - prefunded_specialized_balances: DriveAbciQueryPrefundedSpecializedBalancesVersions { - balance: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - identity_based_queries: DriveAbciQueryIdentityVersions { - identity: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - keys: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identities_contract_keys: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_nonce: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_contract_nonce: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - balance: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identities_balances: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - balance_and_revision: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_by_public_key_hash: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - validator_queries: DriveAbciQueryValidatorVersions { - proposed_block_counts_by_evonode_ids: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - proposed_block_counts_by_range: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - data_contract_based_queries: DriveAbciQueryDataContractVersions { - data_contract: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - data_contract_history: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - data_contracts: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - voting_based_queries: DriveAbciQueryVotingVersions { - vote_polls_by_end_date_query: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - contested_resource_vote_state: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - contested_resource_voters_for_identity: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - contested_resource_identity_vote_status: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - contested_resources: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - system: DriveAbciQuerySystemVersions { - version_upgrade_state: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - version_upgrade_vote_status: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - epoch_infos: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - partial_status: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - path_elements: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - total_credits_in_platform: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - }, + structs: DRIVE_ABCI_STRUCTURE_VERSIONS_V1, + methods: DRIVE_ABCI_METHOD_VERSIONS_V1, + validation_and_processing: DRIVE_ABCI_VALIDATION_VERSIONS_V1, + withdrawal_constants: DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V1, + query: DRIVE_ABCI_QUERY_VERSIONS_V1, }, dpp: DPPVersion { - costs: CostVersions { - signature_verify: 0, - }, - validation: DPPValidationVersions { - json_schema_validator: JsonSchemaValidatorVersions { - new: 0, - validate: 0, - compile: 0, - compile_and_validate: 0, - }, - data_contract: DataContractValidationVersions { - validate: 0, - validate_config_update: 0, - validate_index_definitions: 0, - validate_index_naming_duplicates: 0, - validate_not_defined_properties: 0, - validate_property_definition: 0, - }, - document_type: DocumentTypeValidationVersions { - validate_update: 0, - contested_index_limit: 1, - unique_index_limit: 10, - }, - voting: VotingValidationVersions { - allow_other_contenders_time_mainnet_ms: 604_800_000, // 1 week in ms - allow_other_contenders_time_testing_ms: 604_800_000, // 1 week in ms for v1 (changes in v2) - votes_allowed_per_masternode: 5, - }, - }, - state_transition_serialization_versions: StateTransitionSerializationVersions { - identity_public_key_in_creation: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_create_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_update_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_top_up_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_credit_withdrawal_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_credit_transfer_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - masternode_vote_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - contract_create_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - contract_update_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - documents_batch_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - document_base_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - document_create_state_transition: DocumentFeatureVersionBounds { - bounds: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - document_replace_state_transition: DocumentFeatureVersionBounds { - bounds: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - document_delete_state_transition: DocumentFeatureVersionBounds { - bounds: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - document_transfer_state_transition: DocumentFeatureVersionBounds { - bounds: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - document_update_price_state_transition: DocumentFeatureVersionBounds { - bounds: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - document_purchase_state_transition: DocumentFeatureVersionBounds { - bounds: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - }, - state_transition_conversion_versions: StateTransitionConversionVersions { - identity_to_identity_create_transition: 0, - identity_to_identity_top_up_transition: 0, - identity_to_identity_withdrawal_transition: 0, - identity_to_identity_create_transition_with_signer: 0, - }, - state_transition_method_versions: StateTransitionMethodVersions { - public_key_in_creation_methods: PublicKeyInCreationMethodVersions { - from_public_key_signed_with_private_key: 0, - from_public_key_signed_external: 0, - hash: 0, - duplicated_key_ids_witness: 0, - duplicated_keys_witness: 0, - validate_identity_public_keys_structure: 0, - }, - }, - state_transitions: StateTransitionVersions { - documents: DocumentTransitionVersions { - documents_batch_transition: DocumentsBatchTransitionVersions { - validation: DocumentsBatchTransitionValidationVersions { - find_duplicates_by_id: 0, - validate_base_structure: 0, - }, - }, - }, - identities: IdentityTransitionVersions { - max_public_keys_in_creation: 6, - asset_locks: IdentityTransitionAssetLockVersions { - required_asset_lock_duff_balance_for_processing_start_for_identity_create: - 200000, - required_asset_lock_duff_balance_for_processing_start_for_identity_top_up: - 50000, - validate_asset_lock_transaction_structure: 0, - validate_instant_asset_lock_proof_structure: 0, - }, - }, - }, - contract_versions: ContractVersions { - max_serialized_size: 65000, - contract_serialization_version: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - contract_structure_version: 0, - created_data_contract_structure: 0, - config: 0, - methods: DataContractMethodVersions { - validate_document: 0, - validate_update: 0, - schema: 0, - }, - document_type_versions: DocumentTypeVersions { - index_versions: DocumentTypeIndexVersions { - index_levels_from_indices: 0, - }, - class_method_versions: DocumentTypeClassMethodVersions { - try_from_schema: 0, - create_document_types_from_document_schemas: 0, - }, - structure_version: 0, - schema: DocumentTypeSchemaVersions { - enrich_with_base_schema: 0, - find_identifier_and_binary_paths: 0, - validate_max_depth: 0, - max_depth: 256, - recursive_schema_validator_versions: RecursiveSchemaValidatorVersions { - traversal_validator: 0, - }, - validate_schema_compatibility: 0, - }, - methods: DocumentTypeMethodVersions { - create_document_from_data: 0, - create_document_with_prevalidated_properties: 0, - prefunded_voting_balance_for_document: 0, - contested_vote_poll_for_document: 0, - estimated_size: 0, - index_for_types: 0, - max_size: 0, - serialize_value_for_key: 0, - deserialize_value_for_key: 0, - }, - }, - }, - document_versions: DocumentVersions { - document_structure_version: 0, - document_serialization_version: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - document_cbor_serialization_version: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - extended_document_structure_version: 0, - extended_document_serialization_version: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - document_method_versions: DocumentMethodVersions { - is_equal_ignoring_timestamps: 0, - hash: 0, - get_raw_for_contract: 0, - get_raw_for_document_type: 0, - }, - }, - identity_versions: IdentityVersions { - identity_structure_version: 0, - identity_key_structure_version: 0, - identity_key_type_method_versions: IdentityKeyTypeMethodVersions { - random_public_key_data: 0, - random_public_and_private_key_data: 0, - }, - }, - voting_versions: VotingVersions { - default_vote_poll_time_duration_mainnet_ms: 1_209_600_000, //2 weeks - default_vote_poll_time_duration_test_network_ms: 1_209_600_000, //2 weeks - contested_document_vote_poll_stored_info_version: 0, - }, - asset_lock_versions: AssetLockVersions { - reduced_asset_lock_value: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - methods: DPPMethodVersions { - epoch_core_reward_credits_for_distribution: 0, - }, - }, - system_data_contracts: SystemDataContractVersions { - withdrawals: 1, - dpns: 1, - dashpay: 1, - masternode_reward_shares: 1, - feature_flags: 1, - }, + costs: DPP_COSTS_VERSIONS_V1, + validation: DPP_VALIDATION_VERSIONS_V1, + state_transition_serialization_versions: STATE_TRANSITION_SERIALIZATION_VERSIONS_V1, + state_transition_conversion_versions: STATE_TRANSITION_CONVERSION_VERSIONS_V1, + state_transition_method_versions: STATE_TRANSITION_METHOD_VERSIONS_V1, + state_transitions: STATE_TRANSITION_VERSIONS_V1, + contract_versions: CONTRACT_VERSIONS_V1, + document_versions: DOCUMENT_VERSIONS_V1, + identity_versions: IDENTITY_VERSIONS_V1, + voting_versions: VOTING_VERSION_V1, + asset_lock_versions: DPP_ASSET_LOCK_VERSIONS_V1, + methods: DPP_METHOD_VERSIONS_V1, + factory_versions: DPP_FACTORY_VERSIONS_V1, + }, + system_data_contracts: SYSTEM_DATA_CONTRACT_VERSIONS_V1, fee_version: FEE_VERSION1, - system_limits: SystemLimits { - estimated_contract_max_serialized_size: 16384, - max_field_value_size: 5120, //5 KiB - max_state_transition_size: 20480, //20 KiB - max_transitions_in_documents_batch: 1, - }, + system_limits: SYSTEM_LIMITS_V1, consensus: ConsensusVersions { tenderdash_consensus_version: 0, }, diff --git a/packages/rs-platform-version/src/version/v2.rs b/packages/rs-platform-version/src/version/v2.rs index 5ed8d2d3e3..6e1ed40094 100644 --- a/packages/rs-platform-version/src/version/v2.rs +++ b/packages/rs-platform-version/src/version/v2.rs @@ -1,1280 +1,61 @@ use crate::version::consensus_versions::ConsensusVersions; -use crate::version::contracts::SystemDataContractVersions; -use crate::version::dpp_versions::{ - AssetLockVersions, ContractVersions, CostVersions, DPPMethodVersions, DPPValidationVersions, - DPPVersion, DataContractMethodVersions, DataContractValidationVersions, - DocumentFeatureVersionBounds, DocumentMethodVersions, DocumentTransitionVersions, - DocumentTypeClassMethodVersions, DocumentTypeIndexVersions, DocumentTypeMethodVersions, - DocumentTypeSchemaVersions, DocumentTypeValidationVersions, DocumentTypeVersions, - DocumentVersions, DocumentsBatchTransitionValidationVersions, DocumentsBatchTransitionVersions, - IdentityKeyTypeMethodVersions, IdentityTransitionAssetLockVersions, IdentityTransitionVersions, - IdentityVersions, JsonSchemaValidatorVersions, PublicKeyInCreationMethodVersions, - RecursiveSchemaValidatorVersions, StateTransitionConversionVersions, - StateTransitionMethodVersions, StateTransitionSerializationVersions, StateTransitionVersions, - VotingValidationVersions, VotingVersions, -}; -use crate::version::drive_abci_versions::{ - DriveAbciAssetLockValidationVersions, DriveAbciBlockEndMethodVersions, - DriveAbciBlockFeeProcessingMethodVersions, DriveAbciBlockStartMethodVersions, - DriveAbciCoreBasedUpdatesMethodVersions, DriveAbciCoreChainLockMethodVersionsAndConstants, - DriveAbciCoreInstantSendLockMethodVersions, - DriveAbciDocumentsStateTransitionValidationVersions, DriveAbciEngineMethodVersions, - DriveAbciEpochMethodVersions, DriveAbciFeePoolInwardsDistributionMethodVersions, - DriveAbciFeePoolOutwardsDistributionMethodVersions, - DriveAbciIdentityCreditWithdrawalMethodVersions, DriveAbciInitializationMethodVersions, - DriveAbciMasternodeIdentitiesUpdatesMethodVersions, DriveAbciMethodVersions, - DriveAbciPlatformStateStorageMethodVersions, DriveAbciProtocolUpgradeMethodVersions, - DriveAbciQueryDataContractVersions, DriveAbciQueryIdentityVersions, - DriveAbciQueryPrefundedSpecializedBalancesVersions, DriveAbciQuerySystemVersions, - DriveAbciQueryValidatorVersions, DriveAbciQueryVersions, DriveAbciQueryVotingVersions, - DriveAbciStateTransitionCommonValidationVersions, - DriveAbciStateTransitionProcessingMethodVersions, DriveAbciStateTransitionValidationVersion, - DriveAbciStateTransitionValidationVersions, DriveAbciStructureVersions, - DriveAbciValidationConstants, DriveAbciValidationDataTriggerAndBindingVersions, - DriveAbciValidationDataTriggerVersions, DriveAbciValidationVersions, DriveAbciVersion, - DriveAbciVotingMethodVersions, PenaltyAmounts, -}; -use crate::version::drive_versions::{ - DriveAssetLockMethodVersions, DriveBalancesMethodVersions, DriveBatchOperationsMethodVersion, - DriveContractApplyMethodVersions, DriveContractCostsMethodVersions, - DriveContractGetMethodVersions, DriveContractInsertMethodVersions, DriveContractMethodVersions, - DriveContractProveMethodVersions, DriveContractUpdateMethodVersions, - DriveCreditPoolEpochsMethodVersions, DriveCreditPoolMethodVersions, - DriveCreditPoolPendingEpochRefundsMethodVersions, - DriveCreditPoolStorageFeeDistributionPoolMethodVersions, - DriveCreditPoolUnpaidEpochMethodVersions, DriveDataContractOperationMethodVersions, - DriveDocumentDeleteMethodVersions, DriveDocumentEstimationCostsMethodVersions, - DriveDocumentIndexUniquenessMethodVersions, DriveDocumentInsertContestedMethodVersions, - DriveDocumentInsertMethodVersions, DriveDocumentMethodVersions, - DriveDocumentQueryMethodVersions, DriveDocumentUpdateMethodVersions, - DriveEstimatedCostsMethodVersions, DriveFeesMethodVersions, DriveFetchMethodVersions, - DriveGroveApplyMethodVersions, DriveGroveBasicMethodVersions, DriveGroveBatchMethodVersions, - DriveGroveCostMethodVersions, DriveGroveMethodVersions, - DriveIdentityContractInfoMethodVersions, DriveIdentityCostEstimationMethodVersions, - DriveIdentityFetchAttributesMethodVersions, DriveIdentityFetchFullIdentityMethodVersions, - DriveIdentityFetchMethodVersions, DriveIdentityFetchPartialIdentityMethodVersions, - DriveIdentityFetchPublicKeyHashesMethodVersions, DriveIdentityInsertMethodVersions, - DriveIdentityKeyHashesToIdentityInsertMethodVersions, DriveIdentityKeysFetchMethodVersions, - DriveIdentityKeysInsertMethodVersions, DriveIdentityKeysMethodVersions, - DriveIdentityKeysProveMethodVersions, DriveIdentityMethodVersions, - DriveIdentityProveMethodVersions, DriveIdentityUpdateMethodVersions, - DriveIdentityWithdrawalDocumentMethodVersions, DriveIdentityWithdrawalMethodVersions, - DriveIdentityWithdrawalTransactionIndexMethodVersions, - DriveIdentityWithdrawalTransactionMethodVersions, - DriveIdentityWithdrawalTransactionQueueMethodVersions, DriveInitializationMethodVersions, - DriveMethodVersions, DriveOperationsMethodVersion, DrivePlatformStateMethodVersions, - DrivePlatformSystemMethodVersions, DrivePrefundedSpecializedMethodVersions, - DriveProtocolUpgradeVersions, DriveProveMethodVersions, - DriveStateTransitionActionConvertToHighLevelOperationsMethodVersions, - DriveStateTransitionMethodVersions, DriveStateTransitionOperationMethodVersions, - DriveStructureVersion, DriveSystemEstimationCostsMethodVersions, - DriveVerifyContractMethodVersions, DriveVerifyDocumentMethodVersions, - DriveVerifyIdentityMethodVersions, DriveVerifyMethodVersions, - DriveVerifySingleDocumentMethodVersions, DriveVerifyStateTransitionMethodVersions, - DriveVerifySystemMethodVersions, DriveVerifyVoteMethodVersions, DriveVersion, - DriveVoteCleanupMethodVersions, DriveVoteContestedResourceInsertMethodVersions, - DriveVoteFetchMethodVersions, DriveVoteInsertMethodVersions, DriveVoteMethodVersions, - DriveVoteSetupMethodVersions, DriveVoteStorageFormMethodVersions, -}; +use crate::version::dpp_versions::dpp_asset_lock_versions::v1::DPP_ASSET_LOCK_VERSIONS_V1; +use crate::version::dpp_versions::dpp_contract_versions::v1::CONTRACT_VERSIONS_V1; +use crate::version::dpp_versions::dpp_costs_versions::v1::DPP_COSTS_VERSIONS_V1; +use crate::version::dpp_versions::dpp_document_versions::v1::DOCUMENT_VERSIONS_V1; +use crate::version::dpp_versions::dpp_factory_versions::v1::DPP_FACTORY_VERSIONS_V1; +use crate::version::dpp_versions::dpp_identity_versions::v1::IDENTITY_VERSIONS_V1; +use crate::version::dpp_versions::dpp_method_versions::v1::DPP_METHOD_VERSIONS_V1; +use crate::version::dpp_versions::dpp_state_transition_conversion_versions::v1::STATE_TRANSITION_CONVERSION_VERSIONS_V1; +use crate::version::dpp_versions::dpp_state_transition_method_versions::v1::STATE_TRANSITION_METHOD_VERSIONS_V1; +use crate::version::dpp_versions::dpp_state_transition_serialization_versions::v1::STATE_TRANSITION_SERIALIZATION_VERSIONS_V1; +use crate::version::dpp_versions::dpp_state_transition_versions::v1::STATE_TRANSITION_VERSIONS_V1; +use crate::version::dpp_versions::dpp_validation_versions::v2::DPP_VALIDATION_VERSIONS_V2; +use crate::version::dpp_versions::dpp_voting_versions::v1::VOTING_VERSION_V1; +use crate::version::dpp_versions::DPPVersion; +use crate::version::drive_abci_versions::drive_abci_method_versions::v1::DRIVE_ABCI_METHOD_VERSIONS_V1; +use crate::version::drive_abci_versions::drive_abci_query_versions::v1::DRIVE_ABCI_QUERY_VERSIONS_V1; +use crate::version::drive_abci_versions::drive_abci_structure_versions::v1::DRIVE_ABCI_STRUCTURE_VERSIONS_V1; +use crate::version::drive_abci_versions::drive_abci_validation_versions::v2::DRIVE_ABCI_VALIDATION_VERSIONS_V2; +use crate::version::drive_abci_versions::drive_abci_withdrawal_constants::v1::DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V1; +use crate::version::drive_abci_versions::DriveAbciVersion; +use crate::version::drive_versions::v2::DRIVE_VERSION_V2; use crate::version::fee::v1::FEE_VERSION1; -use crate::version::limits::SystemLimits; -use crate::version::protocol_version::{FeatureVersionBounds, PlatformVersion}; -use crate::version::{PlatformArchitectureVersion, ProtocolVersion}; -use grovedb_version::version::v1::GROVE_V1; +use crate::version::protocol_version::PlatformVersion; +use crate::version::system_data_contract_versions::v1::SYSTEM_DATA_CONTRACT_VERSIONS_V1; +use crate::version::system_limits::v1::SYSTEM_LIMITS_V1; +use crate::version::ProtocolVersion; pub const PROTOCOL_VERSION_2: ProtocolVersion = 2; pub const PLATFORM_V2: PlatformVersion = PlatformVersion { protocol_version: 2, - proofs: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - drive: DriveVersion { - structure: DriveStructureVersion { - document_indexes: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_indexes: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - pools: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - methods: DriveMethodVersions { - initialization: DriveInitializationMethodVersions { - create_initial_state_structure: 0, - }, - credit_pools: DriveCreditPoolMethodVersions { - epochs: DriveCreditPoolEpochsMethodVersions { - get_epochs_infos: 0, - get_epochs_protocol_versions: 0, - prove_epochs_infos: 0, - get_epoch_fee_multiplier: 0, - get_epoch_processing_credits_for_distribution: 0, - get_epoch_storage_credits_for_distribution: 0, - get_epoch_total_credits_for_distribution: 0, - get_storage_credits_for_distribution_for_epochs_in_range: 0, - get_epoch_start_time: 0, - get_epoch_start_block_core_height: 0, - get_epoch_start_block_height: 0, - get_first_epoch_start_block_info_between_epochs: 0, - fetch_epoch_proposers: 0, - prove_epoch_proposers: 0, - get_epochs_proposer_block_count: 0, - add_update_pending_epoch_refunds_operations: 0, - is_epochs_proposers_tree_empty: 0, - }, - pending_epoch_refunds: DriveCreditPoolPendingEpochRefundsMethodVersions { - add_delete_pending_epoch_refunds_except_specified: 0, - fetch_and_add_pending_epoch_refunds_to_collection: 0, - fetch_pending_epoch_refunds: 0, - add_update_pending_epoch_refunds_operations: 0, - }, - storage_fee_distribution_pool: - DriveCreditPoolStorageFeeDistributionPoolMethodVersions { - get_storage_fees_from_distribution_pool: 0, - }, - unpaid_epoch: DriveCreditPoolUnpaidEpochMethodVersions { - get_unpaid_epoch_index: 0, - }, - }, - protocol_upgrade: DriveProtocolUpgradeVersions { - clear_version_information: 0, - fetch_versions_with_counter: 0, - fetch_proved_versions_with_counter: 0, - fetch_validator_version_votes: 0, - fetch_proved_validator_version_votes: 0, - remove_validators_proposed_app_versions: 0, - update_validator_proposed_app_version: 0, - }, - prove: DriveProveMethodVersions { - prove_elements: 0, - prove_multiple_state_transition_results: 0, - }, - balances: DriveBalancesMethodVersions { - add_to_system_credits: 0, - add_to_system_credits_operations: 0, - remove_from_system_credits: 0, - remove_from_system_credits_operations: 0, - calculate_total_credits_balance: 0, - }, - document: DriveDocumentMethodVersions { - query: DriveDocumentQueryMethodVersions { query_documents: 0, query_contested_documents: 0, query_contested_documents_vote_state: 0, query_documents_with_flags: 0 }, - delete: DriveDocumentDeleteMethodVersions { - add_estimation_costs_for_remove_document_to_primary_storage: 0, - delete_document_for_contract: 0, - delete_document_for_contract_id: 0, - delete_document_for_contract_apply_and_add_to_operations: 0, - remove_document_from_primary_storage: 0, - remove_reference_for_index_level_for_contract_operations: 0, - remove_indices_for_index_level_for_contract_operations: 0, - remove_indices_for_top_index_level_for_contract_operations: 0, - delete_document_for_contract_id_with_named_type_operations: 0, - delete_document_for_contract_with_named_type_operations: 0, - delete_document_for_contract_operations: 0, - }, - insert: DriveDocumentInsertMethodVersions { - add_document: 0, - add_document_for_contract: 0, - add_document_for_contract_apply_and_add_to_operations: 0, - add_document_for_contract_operations: 0, - add_document_to_primary_storage: 0, - add_indices_for_index_level_for_contract_operations: 0, - add_indices_for_top_index_level_for_contract_operations: 0, - add_reference_for_index_level_for_contract_operations: 0, - }, - insert_contested: DriveDocumentInsertContestedMethodVersions { - add_contested_document: 0, - add_contested_document_for_contract: 0, - add_contested_document_for_contract_apply_and_add_to_operations: 0, - add_contested_document_for_contract_operations: 0, - add_contested_document_to_primary_storage: 0, - add_contested_indices_for_contract_operations: 0, - add_contested_reference_and_vote_subtree_to_document_operations: 0, - add_contested_vote_subtree_for_non_identities_operations: 0, - }, - update: DriveDocumentUpdateMethodVersions { - add_update_multiple_documents_operations: 0, - update_document_for_contract: 0, - update_document_for_contract_apply_and_add_to_operations: 0, - update_document_for_contract_id: 0, - update_document_for_contract_operations: 0, - update_document_with_serialization_for_contract: 0, - update_serialized_document_for_contract: 0, - }, - estimation_costs: DriveDocumentEstimationCostsMethodVersions { - add_estimation_costs_for_add_document_to_primary_storage: 0, - add_estimation_costs_for_add_contested_document_to_primary_storage: 0, - stateless_delete_of_non_tree_for_costs: 0, - }, - index_uniqueness: DriveDocumentIndexUniquenessMethodVersions { - validate_document_uniqueness: 0, - validate_document_create_transition_action_uniqueness: 0, - validate_document_replace_transition_action_uniqueness: 0, - validate_document_transfer_transition_action_uniqueness: 0, - validate_document_purchase_transition_action_uniqueness: 0, - validate_document_update_price_transition_action_uniqueness: 0, - validate_uniqueness_of_data: 0, - }, - }, - vote: DriveVoteMethodVersions { - insert: DriveVoteInsertMethodVersions { - register_identity_vote: 0, - }, - contested_resource_insert: DriveVoteContestedResourceInsertMethodVersions { - register_contested_resource_identity_vote: 0, - insert_stored_info_for_contested_resource_vote_poll: 0, - register_identity_vote: 0, - add_vote_poll_end_date_query_operations: 0, - }, - cleanup: DriveVoteCleanupMethodVersions { - remove_specific_vote_references_given_by_identity: 0, - remove_specific_votes_given_by_identity: 0, - remove_contested_resource_vote_poll_end_date_query_operations: 1, - remove_contested_resource_vote_poll_votes_operations: 0, - remove_contested_resource_vote_poll_documents_operations: 1, - remove_contested_resource_vote_poll_contenders_operations: 1, - remove_contested_resource_top_level_index_operations: 0, - remove_contested_resource_info_operations: 0, - }, - setup: DriveVoteSetupMethodVersions { - add_initial_vote_tree_main_structure_operations: 0, - }, - storage_form: DriveVoteStorageFormMethodVersions { - resolve_with_contract: 0, - }, - fetch: DriveVoteFetchMethodVersions { - fetch_identities_voting_for_contenders: 0, - fetch_contested_document_vote_poll_stored_info: 0, - fetch_identity_contested_resource_vote: 0, - }, - }, - contract: 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: 0, - }, - update: DriveContractUpdateMethodVersions { update_contract: 0 }, - costs: DriveContractCostsMethodVersions { - add_estimation_costs_for_contract_insertion: 0, - }, - get: DriveContractGetMethodVersions { - fetch_contract: 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, - }, - }, - fees: DriveFeesMethodVersions { calculate_fee: 0 }, - estimated_costs: DriveEstimatedCostsMethodVersions { - add_estimation_costs_for_levels_up_to_contract: 0, - add_estimation_costs_for_levels_up_to_contract_document_type_excluded: 0, - add_estimation_costs_for_contested_document_tree_levels_up_to_contract: 0, - add_estimation_costs_for_contested_document_tree_levels_up_to_contract_document_type_excluded: 0, - }, - asset_lock: DriveAssetLockMethodVersions { - add_asset_lock_outpoint: 0, - add_estimation_costs_for_adding_asset_lock: 0, - fetch_asset_lock_outpoint_info: 0, - }, - verify: DriveVerifyMethodVersions { - contract: DriveVerifyContractMethodVersions { - verify_contract: 0, - verify_contract_history: 0, - }, - document: DriveVerifyDocumentMethodVersions { - verify_proof: 0, - verify_proof_keep_serialized: 0, - verify_start_at_document_in_proof: 0, - }, - identity: DriveVerifyIdentityMethodVersions { - verify_full_identities_by_public_key_hashes: 0, - verify_full_identity_by_identity_id: 0, - verify_full_identity_by_public_key_hash: 0, - verify_identity_balance_for_identity_id: 0, - verify_identity_balances_for_identity_ids: 0, - verify_identity_id_by_public_key_hash: 0, - verify_identity_ids_by_public_key_hashes: 0, - verify_identity_keys_by_identity_id: 0, - verify_identity_nonce: 0, - verify_identity_contract_nonce: 0, - verify_identities_contract_keys: 0, - verify_identity_revision_for_identity_id: 0, - }, - single_document: DriveVerifySingleDocumentMethodVersions { - verify_proof: 0, - verify_proof_keep_serialized: 0, - }, - system: DriveVerifySystemMethodVersions { - verify_epoch_infos: 0, - verify_epoch_proposers: 0, - verify_elements: 0, - verify_total_credits_in_system: 0, - verify_upgrade_state: 0, - verify_upgrade_vote_status: 0, - }, - voting: DriveVerifyVoteMethodVersions { - verify_masternode_vote: 0, - verify_start_at_contender_in_proof: 0, - verify_vote_poll_votes_proof: 0, - verify_identity_votes_given_proof: 0, - verify_vote_poll_vote_state_proof: 0, - verify_contests_proof: 0, - verify_vote_polls_by_end_date_proof: 0, - verify_specialized_balance: 0, - }, - state_transition: DriveVerifyStateTransitionMethodVersions { - verify_state_transition_was_executed_with_proof: 0, - }, - }, - identity: DriveIdentityMethodVersions { - fetch: DriveIdentityFetchMethodVersions { - public_key_hashes: DriveIdentityFetchPublicKeyHashesMethodVersions { - fetch_full_identities_by_unique_public_key_hashes: 0, - fetch_full_identity_by_unique_public_key_hash: 0, - fetch_identity_id_by_unique_public_key_hash: 0, - fetch_identity_ids_by_non_unique_public_key_hash: 0, - fetch_identity_ids_by_unique_public_key_hashes: 0, - fetch_serialized_full_identity_by_unique_public_key_hash: 0, - has_any_of_unique_public_key_hashes: 0, - has_non_unique_public_key_hash: 0, - has_non_unique_public_key_hash_already_for_identity: 0, - has_unique_public_key_hash: 0, - }, - attributes: DriveIdentityFetchAttributesMethodVersions { - revision: 0, - nonce: 0, - identity_contract_nonce: 0, - balance: 0, - balance_include_debt: 0, - negative_balance: 0, - }, - partial_identity: DriveIdentityFetchPartialIdentityMethodVersions { - fetch_identity_revision_with_keys: 0, - fetch_identity_balance_with_keys: 0, - fetch_identity_balance_with_keys_and_revision: 0, - fetch_identity_with_balance: 0, - fetch_identity_keys: 0, - }, - full_identity: DriveIdentityFetchFullIdentityMethodVersions { - fetch_full_identity: Some(0), - fetch_full_identities: Some(0), - }, - }, - prove: DriveIdentityProveMethodVersions { - full_identity: 0, - full_identities: 0, - identity_nonce: 0, - identity_contract_nonce: 0, - identities_contract_keys: 0, - prove_full_identities_by_unique_public_key_hashes: 0, - prove_full_identity_by_unique_public_key_hash: 0, - prove_identity_id_by_unique_public_key_hash: 0, - prove_identity_ids_by_unique_public_key_hashes: 0, - }, - keys: DriveIdentityKeysMethodVersions { - fetch: DriveIdentityKeysFetchMethodVersions { - fetch_all_current_identity_keys: 0, - fetch_all_identity_keys: 0, - fetch_identities_all_keys: 0, - fetch_identity_keys: 0, - fetch_identities_contract_keys: 0, - }, - prove: DriveIdentityKeysProveMethodVersions { - prove_identities_all_keys: 0, - prove_identity_keys: 0, - }, - insert: DriveIdentityKeysInsertMethodVersions { - create_key_tree_with_keys: 0, - create_new_identity_key_query_trees: 0, - insert_key_searchable_references: 0, - insert_key_to_storage: 0, - insert_new_non_unique_key: 0, - insert_new_unique_key: 0, - replace_key_in_storage: 0, - }, - insert_key_hash_identity_reference: - DriveIdentityKeyHashesToIdentityInsertMethodVersions { - add_estimation_costs_for_insert_non_unique_public_key_hash_reference: 0, - add_estimation_costs_for_insert_unique_public_key_hash_reference: 0, - insert_non_unique_public_key_hash_reference_to_identity: 0, - insert_reference_to_non_unique_key: 0, - insert_reference_to_unique_key: 0, - insert_unique_public_key_hash_reference_to_identity: 0, - }, - }, - update: DriveIdentityUpdateMethodVersions { - update_identity_revision: 0, - merge_identity_nonce: 0, - update_identity_negative_credit_operation: 0, - initialize_identity_revision: 0, - disable_identity_keys: 0, - re_enable_identity_keys: 0, - add_new_non_unique_keys_to_identity: 0, - add_new_unique_keys_to_identity: 0, - add_new_keys_to_identity: 0, - insert_identity_balance: 0, - initialize_negative_identity_balance: 0, - add_to_identity_balance: 0, - add_to_previous_balance: 0, - apply_balance_change_from_fee_to_identity: 0, - remove_from_identity_balance: 0, - refresh_identity_key_reference_operations: 0, - }, - insert: DriveIdentityInsertMethodVersions { - add_new_identity: 0, - }, - contract_info: DriveIdentityContractInfoMethodVersions { - add_potential_contract_info_for_contract_bounded_key: 0, - refresh_potential_contract_info_key_references: 0, - merge_identity_contract_nonce: 0, - }, - cost_estimation: DriveIdentityCostEstimationMethodVersions { - for_authentication_keys_security_level_in_key_reference_tree: 0, - for_balances: 0, - for_contract_info: 0, - for_contract_info_group: 0, - for_contract_info_group_keys: 0, - for_contract_info_group_key_purpose: 0, - for_keys_for_identity_id: 0, - for_negative_credit: 0, - for_purpose_in_key_reference_tree: 0, - for_root_key_reference_tree: 0, - for_update_revision: 0, - }, - withdrawals: DriveIdentityWithdrawalMethodVersions { - document: DriveIdentityWithdrawalDocumentMethodVersions { - fetch_oldest_withdrawal_documents_by_status: 0, - find_up_to_100_withdrawal_documents_by_status_and_transaction_indices: 0, - }, - transaction: DriveIdentityWithdrawalTransactionMethodVersions { - index: DriveIdentityWithdrawalTransactionIndexMethodVersions { - fetch_next_withdrawal_transaction_index: 0, - add_update_next_withdrawal_transaction_index_operation: 0, - }, - queue: DriveIdentityWithdrawalTransactionQueueMethodVersions { - add_enqueue_untied_withdrawal_transaction_operations: 0, - dequeue_untied_withdrawal_transactions: 0, - }, - }, - }, - }, - platform_system: DrivePlatformSystemMethodVersions { - estimation_costs: DriveSystemEstimationCostsMethodVersions { - for_total_system_credits_update: 0, - }, - }, - operations: DriveOperationsMethodVersion { - rollback_transaction: 0, - drop_cache: 0, - commit_transaction: 0, - apply_partial_batch_low_level_drive_operations: 0, - apply_partial_batch_grovedb_operations: 0, - apply_batch_low_level_drive_operations: 0, - apply_batch_grovedb_operations: 0, - }, - state_transitions: DriveStateTransitionMethodVersions { - operations: DriveStateTransitionOperationMethodVersions { - finalization_tasks: 0, - contracts: DriveDataContractOperationMethodVersions { - finalization_tasks: 0, - }, - }, - convert_to_high_level_operations: - DriveStateTransitionActionConvertToHighLevelOperationsMethodVersions { - data_contract_create_transition: 0, - data_contract_update_transition: 0, - document_create_transition: 0, - document_delete_transition: 0, - document_purchase_transition: 0, - document_replace_transition: 0, - document_transfer_transition: 0, - document_update_price_transition: 0, - documents_batch_transition: 0, - identity_create_transition: 0, - identity_credit_transfer_transition: 0, - identity_credit_withdrawal_transition: 0, - identity_top_up_transition: 0, - identity_update_transition: 0, - masternode_vote_transition: 0, - bump_identity_data_contract_nonce: 0, - bump_identity_nonce: 0, - partially_use_asset_lock: 0, - }, - }, - batch_operations: DriveBatchOperationsMethodVersion { - convert_drive_operations_to_grove_operations: 0, - apply_drive_operations: 0, - }, - platform_state: DrivePlatformStateMethodVersions { - fetch_platform_state_bytes: 0, - store_platform_state_bytes: 0, - }, - fetch: DriveFetchMethodVersions { fetch_elements: 0 }, - prefunded_specialized_balances: DrivePrefundedSpecializedMethodVersions { - fetch_single: 0, - prove_single: 0, - add_prefunded_specialized_balance: 0, - add_prefunded_specialized_balance_operations: 0, - deduct_from_prefunded_specialized_balance: 0, - deduct_from_prefunded_specialized_balance_operations: 0, - estimated_cost_for_prefunded_specialized_balance_update: 0, - }, - }, - grove_methods: DriveGroveMethodVersions { - basic: DriveGroveBasicMethodVersions { - grove_insert: 0, - grove_insert_empty_tree: 0, - grove_insert_empty_sum_tree: 0, - grove_insert_if_not_exists: 0, - grove_clear: 0, - grove_delete: 0, - grove_get_raw: 0, - grove_get_raw_optional: 0, - grove_get_raw_value_u64_from_encoded_var_vec: 0, - grove_get: 0, - grove_get_path_query_serialized_results: 0, - grove_get_path_query_serialized_or_sum_results: 0, - grove_get_path_query: 0, - grove_get_path_query_with_optional: 0, - grove_get_raw_path_query_with_optional: 0, - grove_get_raw_path_query: 0, - grove_get_proved_path_query: 0, - grove_get_proved_path_query_with_conditional: 0, - grove_get_sum_tree_total_value: 0, - grove_has_raw: 0, - }, - batch: DriveGroveBatchMethodVersions { - batch_insert_empty_tree: 0, - batch_insert_empty_tree_if_not_exists: 0, - batch_insert_empty_tree_if_not_exists_check_existing_operations: 0, - batch_insert: 0, - batch_insert_if_not_exists: 0, - batch_insert_if_changed_value: 0, - batch_replace: 0, - batch_delete: 0, - batch_remove_raw: 0, - batch_delete_up_tree_while_empty: 0, - batch_refresh_reference: 0, - }, - apply: DriveGroveApplyMethodVersions { - grove_apply_operation: 0, - grove_apply_batch: 0, - grove_apply_partial_batch: 0, - }, - costs: DriveGroveCostMethodVersions { - grove_batch_operations_costs: 0, - }, - }, - grove_version: GROVE_V1, - }, - platform_architecture: PlatformArchitectureVersion { - data_contract_factory_structure_version: 0, - document_factory_structure_version: 0, - }, + drive: DRIVE_VERSION_V2, drive_abci: DriveAbciVersion { - structs: DriveAbciStructureVersions { - platform_state_structure: 0, - platform_state_for_saving_structure: 0, - state_transition_execution_context: 0, - commit: 0, - masternode: 0, - signature_verification_quorum_set: 0, - }, - methods: DriveAbciMethodVersions { - engine: DriveAbciEngineMethodVersions { - init_chain: 0, - check_tx: 0, - run_block_proposal: 0, - finalize_block_proposal: 0, - consensus_params_update: 0, - }, - initialization: DriveAbciInitializationMethodVersions { - initial_core_height_and_time: 0, - create_genesis_state: 0, - }, - core_based_updates: DriveAbciCoreBasedUpdatesMethodVersions { - update_core_info: 0, - update_masternode_list: 0, - update_quorum_info: 0, - masternode_updates: DriveAbciMasternodeIdentitiesUpdatesMethodVersions { - get_voter_identity_key: 0, - get_operator_identity_keys: 0, - get_owner_identity_withdrawal_key: 0, - get_voter_identifier_from_masternode_list_item: 0, - get_operator_identifier_from_masternode_list_item: 0, - create_operator_identity: 0, - create_owner_identity: 0, - create_voter_identity: 0, - disable_identity_keys: 0, - update_masternode_identities: 0, - update_operator_identity: 0, - update_owner_withdrawal_address: 0, - update_voter_identity: 0, - }, - }, - protocol_upgrade: DriveAbciProtocolUpgradeMethodVersions { - check_for_desired_protocol_upgrade: 0, - upgrade_protocol_version_on_epoch_change: 0, - protocol_version_upgrade_percentage_needed: 75, - }, - block_fee_processing: DriveAbciBlockFeeProcessingMethodVersions { - add_process_epoch_change_operations: 0, - process_block_fees: 0, - }, - core_chain_lock: DriveAbciCoreChainLockMethodVersionsAndConstants { - choose_quorum: 0, - verify_chain_lock: 0, - verify_chain_lock_locally: 0, - verify_chain_lock_through_core: 0, - make_sure_core_is_synced_to_chain_lock: 0, - recent_block_count_amount: 2, - }, - core_instant_send_lock: DriveAbciCoreInstantSendLockMethodVersions { - verify_recent_signature_locally: 0, - }, - fee_pool_inwards_distribution: DriveAbciFeePoolInwardsDistributionMethodVersions { - add_distribute_block_fees_into_pools_operations: 0, - add_distribute_storage_fee_to_epochs_operations: 0, - }, - fee_pool_outwards_distribution: DriveAbciFeePoolOutwardsDistributionMethodVersions { - add_distribute_fees_from_oldest_unpaid_epoch_pool_to_proposers_operations: 0, - add_epoch_pool_to_proposers_payout_operations: 0, - find_oldest_epoch_needing_payment: 0, - fetch_reward_shares_list_for_masternode: 0, - }, - withdrawals: DriveAbciIdentityCreditWithdrawalMethodVersions { - build_untied_withdrawal_transactions_from_documents: 0, - dequeue_and_build_unsigned_withdrawal_transactions: 0, - fetch_transactions_block_inclusion_status: 0, - pool_withdrawals_into_transactions_queue: 0, - update_broadcasted_withdrawal_statuses: 0, - append_signatures_and_broadcast_withdrawal_transactions: 0, - }, - voting: DriveAbciVotingMethodVersions { - keep_record_of_finished_contested_resource_vote_poll: 0, - clean_up_after_vote_poll_end: 0, - clean_up_after_contested_resources_vote_poll_end: 0, - check_for_ended_vote_polls: 0, - tally_votes_for_contested_document_resource_vote_poll: 0, - award_document_to_winner: 0, - delay_vote_poll: 0, - run_dao_platform_events: 0, - remove_votes_for_removed_masternodes: 0, - }, - state_transition_processing: DriveAbciStateTransitionProcessingMethodVersions { - execute_event: 0, - process_raw_state_transitions: 0, - decode_raw_state_transitions: 0, - validate_fees_of_event: 0, - }, - epoch: DriveAbciEpochMethodVersions { - gather_epoch_info: 0, - get_genesis_time: 0, - }, - block_start: DriveAbciBlockStartMethodVersions { - clear_drive_block_cache: 0, - }, - block_end: DriveAbciBlockEndMethodVersions { - update_state_cache: 0, - update_drive_cache: 0, - validator_set_update: 0, - }, - platform_state_storage: DriveAbciPlatformStateStorageMethodVersions { - fetch_platform_state: 0, - store_platform_state: 0, - }, - }, - validation_and_processing: DriveAbciValidationVersions { - state_transitions: DriveAbciStateTransitionValidationVersions { - common_validation_methods: DriveAbciStateTransitionCommonValidationVersions { - asset_locks: DriveAbciAssetLockValidationVersions { - fetch_asset_lock_transaction_output_sync: 0, - verify_asset_lock_is_not_spent_and_has_enough_balance: 0, - }, - validate_identity_public_key_contract_bounds: 0, - validate_identity_public_key_ids_dont_exist_in_state: 0, - validate_identity_public_key_ids_exist_in_state: 0, - validate_state_transition_identity_signed: 0, - validate_unique_identity_public_key_hashes_in_state: 0, - validate_master_key_uniqueness: 0, - validate_simple_pre_check_balance: 0, - }, - max_asset_lock_usage_attempts: 16, - identity_create_state_transition: DriveAbciStateTransitionValidationVersion { - basic_structure: Some(0), - advanced_structure: Some(0), - identity_signatures: Some(0), - advanced_minimum_balance_pre_check: None, - nonce: None, - state: 0, - transform_into_action: 0, - }, - identity_update_state_transition: DriveAbciStateTransitionValidationVersion { - basic_structure: Some(0), - advanced_structure: Some(0), - identity_signatures: Some(0), - advanced_minimum_balance_pre_check: None, - nonce: Some(0), - state: 0, - transform_into_action: 0, - }, - identity_top_up_state_transition: DriveAbciStateTransitionValidationVersion { - basic_structure: Some(0), - advanced_structure: None, - identity_signatures: None, - advanced_minimum_balance_pre_check: None, - nonce: None, - state: 0, - transform_into_action: 0, - }, - identity_credit_withdrawal_state_transition: - DriveAbciStateTransitionValidationVersion { - basic_structure: Some(0), - advanced_structure: None, - identity_signatures: None, - advanced_minimum_balance_pre_check: Some(0), - nonce: Some(0), - state: 0, - transform_into_action: 0, - }, - identity_credit_transfer_state_transition: - DriveAbciStateTransitionValidationVersion { - basic_structure: Some(0), - advanced_structure: None, - identity_signatures: None, - advanced_minimum_balance_pre_check: Some(0), - nonce: Some(0), - state: 0, - transform_into_action: 0, - }, - masternode_vote_state_transition: DriveAbciStateTransitionValidationVersion { - basic_structure: None, - advanced_structure: Some(0), - identity_signatures: None, - advanced_minimum_balance_pre_check: Some(0), - nonce: Some(0), - state: 0, - transform_into_action: 0, - }, - contract_create_state_transition: DriveAbciStateTransitionValidationVersion { - basic_structure: Some(0), - advanced_structure: None, - identity_signatures: None, - advanced_minimum_balance_pre_check: None, - nonce: Some(0), - state: 0, - transform_into_action: 0, - }, - contract_update_state_transition: DriveAbciStateTransitionValidationVersion { - basic_structure: None, - advanced_structure: None, - identity_signatures: None, - advanced_minimum_balance_pre_check: None, - nonce: Some(0), - state: 0, - transform_into_action: 0, - }, - documents_batch_state_transition: - DriveAbciDocumentsStateTransitionValidationVersions { - balance_pre_check: 0, - basic_structure: 0, - advanced_structure: 0, - state: 0, - revision: 0, - transform_into_action: 0, - data_triggers: DriveAbciValidationDataTriggerAndBindingVersions { - bindings: 0, - triggers: DriveAbciValidationDataTriggerVersions { - create_contact_request_data_trigger: 0, - create_domain_data_trigger: 0, - create_identity_data_trigger: 0, - create_feature_flag_data_trigger: 0, - create_masternode_reward_shares_data_trigger: 0, - delete_withdrawal_data_trigger: 0, - reject_data_trigger: 0, - }, - }, - is_allowed: 0, - document_create_transition_structure_validation: 0, - document_delete_transition_structure_validation: 0, - document_replace_transition_structure_validation: 0, - document_transfer_transition_structure_validation: 0, - document_purchase_transition_structure_validation: 0, - document_update_price_transition_structure_validation: 0, - document_create_transition_state_validation: 1, - document_delete_transition_state_validation: 0, - document_replace_transition_state_validation: 0, - document_transfer_transition_state_validation: 0, - document_purchase_transition_state_validation: 0, - document_update_price_transition_state_validation: 0, - }, - }, - process_state_transition: 0, - state_transition_to_execution_event_for_check_tx: 0, - penalties: PenaltyAmounts { - identity_id_not_correct: 50000000, - unique_key_already_present: 10000000, - validation_of_added_keys_structure_failure: 10000000, - validation_of_added_keys_proof_of_possession_failure: 50000000, - }, - event_constants: DriveAbciValidationConstants { - maximum_vote_polls_to_process: 2, - maximum_contenders_to_consider: 100, - }, - }, - query: DriveAbciQueryVersions { - max_returned_elements: 100, - response_metadata: 0, - proofs_query: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - document_query: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - prefunded_specialized_balances: DriveAbciQueryPrefundedSpecializedBalancesVersions { - balance: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - identity_based_queries: DriveAbciQueryIdentityVersions { - identity: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - keys: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identities_contract_keys: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_nonce: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_contract_nonce: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - balance: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identities_balances: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - balance_and_revision: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_by_public_key_hash: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - validator_queries: DriveAbciQueryValidatorVersions { - proposed_block_counts_by_evonode_ids: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - proposed_block_counts_by_range: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - data_contract_based_queries: DriveAbciQueryDataContractVersions { - data_contract: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - data_contract_history: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - data_contracts: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - voting_based_queries: DriveAbciQueryVotingVersions { - vote_polls_by_end_date_query: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - contested_resource_vote_state: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - contested_resource_voters_for_identity: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - contested_resource_identity_vote_status: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - contested_resources: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - system: DriveAbciQuerySystemVersions { - version_upgrade_state: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - version_upgrade_vote_status: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - epoch_infos: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - partial_status: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - path_elements: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - total_credits_in_platform: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - }, + structs: DRIVE_ABCI_STRUCTURE_VERSIONS_V1, + methods: DRIVE_ABCI_METHOD_VERSIONS_V1, + validation_and_processing: DRIVE_ABCI_VALIDATION_VERSIONS_V2, + withdrawal_constants: DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V1, + query: DRIVE_ABCI_QUERY_VERSIONS_V1, }, dpp: DPPVersion { - costs: CostVersions { - signature_verify: 0, - }, - validation: DPPValidationVersions { - json_schema_validator: JsonSchemaValidatorVersions { - new: 0, - validate: 0, - compile: 0, - compile_and_validate: 0, - }, - data_contract: DataContractValidationVersions { - validate: 0, - validate_config_update: 0, - validate_index_definitions: 0, - validate_index_naming_duplicates: 0, - validate_not_defined_properties: 0, - validate_property_definition: 0, - }, - document_type: DocumentTypeValidationVersions { - validate_update: 0, - contested_index_limit: 1, - unique_index_limit: 10, - }, - voting: VotingValidationVersions { - allow_other_contenders_time_mainnet_ms: 604_800_000, // 1 week in ms - allow_other_contenders_time_testing_ms: 2_700_000, //45 minutes - votes_allowed_per_masternode: 5, - }, - }, - state_transition_serialization_versions: StateTransitionSerializationVersions { - identity_public_key_in_creation: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_create_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_update_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_top_up_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_credit_withdrawal_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_credit_transfer_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - masternode_vote_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - contract_create_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - contract_update_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - documents_batch_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - document_base_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - document_create_state_transition: DocumentFeatureVersionBounds { - bounds: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - document_replace_state_transition: DocumentFeatureVersionBounds { - bounds: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - document_delete_state_transition: DocumentFeatureVersionBounds { - bounds: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - document_transfer_state_transition: DocumentFeatureVersionBounds { - bounds: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - document_update_price_state_transition: DocumentFeatureVersionBounds { - bounds: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - document_purchase_state_transition: DocumentFeatureVersionBounds { - bounds: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - }, - state_transition_conversion_versions: StateTransitionConversionVersions { - identity_to_identity_create_transition: 0, - identity_to_identity_top_up_transition: 0, - identity_to_identity_withdrawal_transition: 0, - identity_to_identity_create_transition_with_signer: 0, - }, - state_transition_method_versions: StateTransitionMethodVersions { - public_key_in_creation_methods: PublicKeyInCreationMethodVersions { - from_public_key_signed_with_private_key: 0, - from_public_key_signed_external: 0, - hash: 0, - duplicated_key_ids_witness: 0, - duplicated_keys_witness: 0, - validate_identity_public_keys_structure: 0, - }, - }, - state_transitions: StateTransitionVersions { - documents: DocumentTransitionVersions { - documents_batch_transition: DocumentsBatchTransitionVersions { - validation: DocumentsBatchTransitionValidationVersions { - find_duplicates_by_id: 0, - validate_base_structure: 0, - }, - }, - }, - identities: IdentityTransitionVersions { - max_public_keys_in_creation: 6, - asset_locks: IdentityTransitionAssetLockVersions { - required_asset_lock_duff_balance_for_processing_start_for_identity_create: - 200000, - required_asset_lock_duff_balance_for_processing_start_for_identity_top_up: - 50000, - validate_asset_lock_transaction_structure: 0, - validate_instant_asset_lock_proof_structure: 0, - }, - }, - }, - contract_versions: ContractVersions { - max_serialized_size: 65000, - contract_serialization_version: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - contract_structure_version: 0, - created_data_contract_structure: 0, - config: 0, - methods: DataContractMethodVersions { - validate_document: 0, - validate_update: 0, - schema: 0, - }, - document_type_versions: DocumentTypeVersions { - index_versions: DocumentTypeIndexVersions { - index_levels_from_indices: 0, - }, - class_method_versions: DocumentTypeClassMethodVersions { - try_from_schema: 0, - create_document_types_from_document_schemas: 0, - }, - structure_version: 0, - schema: DocumentTypeSchemaVersions { - enrich_with_base_schema: 0, - find_identifier_and_binary_paths: 0, - validate_max_depth: 0, - max_depth: 256, - recursive_schema_validator_versions: RecursiveSchemaValidatorVersions { - traversal_validator: 0, - }, - validate_schema_compatibility: 0, - }, - methods: DocumentTypeMethodVersions { - create_document_from_data: 0, - create_document_with_prevalidated_properties: 0, - prefunded_voting_balance_for_document: 0, - contested_vote_poll_for_document: 0, - estimated_size: 0, - index_for_types: 0, - max_size: 0, - serialize_value_for_key: 0, - deserialize_value_for_key: 0, - }, - }, - }, - document_versions: DocumentVersions { - document_structure_version: 0, - document_serialization_version: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - document_cbor_serialization_version: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - extended_document_structure_version: 0, - extended_document_serialization_version: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - document_method_versions: DocumentMethodVersions { - is_equal_ignoring_timestamps: 0, - hash: 0, - get_raw_for_contract: 0, - get_raw_for_document_type: 0, - }, - }, - identity_versions: IdentityVersions { - identity_structure_version: 0, - identity_key_structure_version: 0, - identity_key_type_method_versions: IdentityKeyTypeMethodVersions { - random_public_key_data: 0, - random_public_and_private_key_data: 0, - }, - }, - voting_versions: VotingVersions { - default_vote_poll_time_duration_mainnet_ms: 1_209_600_000, //2 weeks - default_vote_poll_time_duration_test_network_ms: 1_209_600_000, //2 weeks - contested_document_vote_poll_stored_info_version: 0, - }, - asset_lock_versions: AssetLockVersions { - reduced_asset_lock_value: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - methods: DPPMethodVersions { - epoch_core_reward_credits_for_distribution: 0, - }, - }, - system_data_contracts: SystemDataContractVersions { - withdrawals: 1, - dpns: 1, - dashpay: 1, - masternode_reward_shares: 1, - feature_flags: 1, - }, + costs: DPP_COSTS_VERSIONS_V1, + validation: DPP_VALIDATION_VERSIONS_V2, + state_transition_serialization_versions: STATE_TRANSITION_SERIALIZATION_VERSIONS_V1, + state_transition_conversion_versions: STATE_TRANSITION_CONVERSION_VERSIONS_V1, + state_transition_method_versions: STATE_TRANSITION_METHOD_VERSIONS_V1, + state_transitions: STATE_TRANSITION_VERSIONS_V1, + contract_versions: CONTRACT_VERSIONS_V1, + document_versions: DOCUMENT_VERSIONS_V1, + identity_versions: IDENTITY_VERSIONS_V1, + voting_versions: VOTING_VERSION_V1, + asset_lock_versions: DPP_ASSET_LOCK_VERSIONS_V1, + methods: DPP_METHOD_VERSIONS_V1, + factory_versions: DPP_FACTORY_VERSIONS_V1, + }, + system_data_contracts: SYSTEM_DATA_CONTRACT_VERSIONS_V1, fee_version: FEE_VERSION1, - system_limits: SystemLimits { - estimated_contract_max_serialized_size: 16384, - max_field_value_size: 5120, //5 KiB - max_state_transition_size: 20480, //20 KiB - max_transitions_in_documents_batch: 1, - }, + system_limits: SYSTEM_LIMITS_V1, consensus: ConsensusVersions { tenderdash_consensus_version: 0, }, diff --git a/packages/rs-platform-version/src/version/v3.rs b/packages/rs-platform-version/src/version/v3.rs index cb608a3b3c..f3856bc1e6 100644 --- a/packages/rs-platform-version/src/version/v3.rs +++ b/packages/rs-platform-version/src/version/v3.rs @@ -1,86 +1,30 @@ use crate::version::consensus_versions::ConsensusVersions; -use crate::version::contracts::SystemDataContractVersions; -use crate::version::dpp_versions::{ - AssetLockVersions, ContractVersions, CostVersions, DPPMethodVersions, DPPValidationVersions, - DPPVersion, DataContractMethodVersions, DataContractValidationVersions, - DocumentFeatureVersionBounds, DocumentMethodVersions, DocumentTransitionVersions, - DocumentTypeClassMethodVersions, DocumentTypeIndexVersions, DocumentTypeMethodVersions, - DocumentTypeSchemaVersions, DocumentTypeValidationVersions, DocumentTypeVersions, - DocumentVersions, DocumentsBatchTransitionValidationVersions, DocumentsBatchTransitionVersions, - IdentityKeyTypeMethodVersions, IdentityTransitionAssetLockVersions, IdentityTransitionVersions, - IdentityVersions, JsonSchemaValidatorVersions, PublicKeyInCreationMethodVersions, - RecursiveSchemaValidatorVersions, StateTransitionConversionVersions, - StateTransitionMethodVersions, StateTransitionSerializationVersions, StateTransitionVersions, - VotingValidationVersions, VotingVersions, -}; -use crate::version::drive_abci_versions::{ - DriveAbciAssetLockValidationVersions, DriveAbciBlockEndMethodVersions, - DriveAbciBlockFeeProcessingMethodVersions, DriveAbciBlockStartMethodVersions, - DriveAbciCoreBasedUpdatesMethodVersions, DriveAbciCoreChainLockMethodVersionsAndConstants, - DriveAbciCoreInstantSendLockMethodVersions, - DriveAbciDocumentsStateTransitionValidationVersions, DriveAbciEngineMethodVersions, - DriveAbciEpochMethodVersions, DriveAbciFeePoolInwardsDistributionMethodVersions, - DriveAbciFeePoolOutwardsDistributionMethodVersions, - DriveAbciIdentityCreditWithdrawalMethodVersions, DriveAbciInitializationMethodVersions, - DriveAbciMasternodeIdentitiesUpdatesMethodVersions, DriveAbciMethodVersions, - DriveAbciPlatformStateStorageMethodVersions, DriveAbciProtocolUpgradeMethodVersions, - DriveAbciQueryDataContractVersions, DriveAbciQueryIdentityVersions, - DriveAbciQueryPrefundedSpecializedBalancesVersions, DriveAbciQuerySystemVersions, - DriveAbciQueryValidatorVersions, DriveAbciQueryVersions, DriveAbciQueryVotingVersions, - DriveAbciStateTransitionCommonValidationVersions, - DriveAbciStateTransitionProcessingMethodVersions, DriveAbciStateTransitionValidationVersion, - DriveAbciStateTransitionValidationVersions, DriveAbciStructureVersions, - DriveAbciValidationConstants, DriveAbciValidationDataTriggerAndBindingVersions, - DriveAbciValidationDataTriggerVersions, DriveAbciValidationVersions, DriveAbciVersion, - DriveAbciVotingMethodVersions, PenaltyAmounts, -}; -use crate::version::drive_versions::{ - DriveAssetLockMethodVersions, DriveBalancesMethodVersions, DriveBatchOperationsMethodVersion, - DriveContractApplyMethodVersions, DriveContractCostsMethodVersions, - DriveContractGetMethodVersions, DriveContractInsertMethodVersions, DriveContractMethodVersions, - DriveContractProveMethodVersions, DriveContractUpdateMethodVersions, - DriveCreditPoolEpochsMethodVersions, DriveCreditPoolMethodVersions, - DriveCreditPoolPendingEpochRefundsMethodVersions, - DriveCreditPoolStorageFeeDistributionPoolMethodVersions, - DriveCreditPoolUnpaidEpochMethodVersions, DriveDataContractOperationMethodVersions, - DriveDocumentDeleteMethodVersions, DriveDocumentEstimationCostsMethodVersions, - DriveDocumentIndexUniquenessMethodVersions, DriveDocumentInsertContestedMethodVersions, - DriveDocumentInsertMethodVersions, DriveDocumentMethodVersions, - DriveDocumentQueryMethodVersions, DriveDocumentUpdateMethodVersions, - DriveEstimatedCostsMethodVersions, DriveFeesMethodVersions, DriveFetchMethodVersions, - DriveGroveApplyMethodVersions, DriveGroveBasicMethodVersions, DriveGroveBatchMethodVersions, - DriveGroveCostMethodVersions, DriveGroveMethodVersions, - DriveIdentityContractInfoMethodVersions, DriveIdentityCostEstimationMethodVersions, - DriveIdentityFetchAttributesMethodVersions, DriveIdentityFetchFullIdentityMethodVersions, - DriveIdentityFetchMethodVersions, DriveIdentityFetchPartialIdentityMethodVersions, - DriveIdentityFetchPublicKeyHashesMethodVersions, DriveIdentityInsertMethodVersions, - DriveIdentityKeyHashesToIdentityInsertMethodVersions, DriveIdentityKeysFetchMethodVersions, - DriveIdentityKeysInsertMethodVersions, DriveIdentityKeysMethodVersions, - DriveIdentityKeysProveMethodVersions, DriveIdentityMethodVersions, - DriveIdentityProveMethodVersions, DriveIdentityUpdateMethodVersions, - DriveIdentityWithdrawalDocumentMethodVersions, DriveIdentityWithdrawalMethodVersions, - DriveIdentityWithdrawalTransactionIndexMethodVersions, - DriveIdentityWithdrawalTransactionMethodVersions, - DriveIdentityWithdrawalTransactionQueueMethodVersions, DriveInitializationMethodVersions, - DriveMethodVersions, DriveOperationsMethodVersion, DrivePlatformStateMethodVersions, - DrivePlatformSystemMethodVersions, DrivePrefundedSpecializedMethodVersions, - DriveProtocolUpgradeVersions, DriveProveMethodVersions, - DriveStateTransitionActionConvertToHighLevelOperationsMethodVersions, - DriveStateTransitionMethodVersions, DriveStateTransitionOperationMethodVersions, - DriveStructureVersion, DriveSystemEstimationCostsMethodVersions, - DriveVerifyContractMethodVersions, DriveVerifyDocumentMethodVersions, - DriveVerifyIdentityMethodVersions, DriveVerifyMethodVersions, - DriveVerifySingleDocumentMethodVersions, DriveVerifyStateTransitionMethodVersions, - DriveVerifySystemMethodVersions, DriveVerifyVoteMethodVersions, DriveVersion, - DriveVoteCleanupMethodVersions, DriveVoteContestedResourceInsertMethodVersions, - DriveVoteFetchMethodVersions, DriveVoteInsertMethodVersions, DriveVoteMethodVersions, - DriveVoteSetupMethodVersions, DriveVoteStorageFormMethodVersions, -}; +use crate::version::dpp_versions::dpp_asset_lock_versions::v1::DPP_ASSET_LOCK_VERSIONS_V1; +use crate::version::dpp_versions::dpp_contract_versions::v1::CONTRACT_VERSIONS_V1; +use crate::version::dpp_versions::dpp_costs_versions::v1::DPP_COSTS_VERSIONS_V1; +use crate::version::dpp_versions::dpp_document_versions::v1::DOCUMENT_VERSIONS_V1; +use crate::version::dpp_versions::dpp_factory_versions::v1::DPP_FACTORY_VERSIONS_V1; +use crate::version::dpp_versions::dpp_identity_versions::v1::IDENTITY_VERSIONS_V1; +use crate::version::dpp_versions::dpp_method_versions::v1::DPP_METHOD_VERSIONS_V1; +use crate::version::dpp_versions::dpp_state_transition_conversion_versions::v2::STATE_TRANSITION_CONVERSION_VERSIONS_V2; +use crate::version::dpp_versions::dpp_state_transition_method_versions::v1::STATE_TRANSITION_METHOD_VERSIONS_V1; +use crate::version::dpp_versions::dpp_state_transition_serialization_versions::v1::STATE_TRANSITION_SERIALIZATION_VERSIONS_V1; +use crate::version::dpp_versions::dpp_state_transition_versions::v2::STATE_TRANSITION_VERSIONS_V2; +use crate::version::dpp_versions::dpp_validation_versions::v2::DPP_VALIDATION_VERSIONS_V2; +use crate::version::dpp_versions::dpp_voting_versions::v2::VOTING_VERSION_V2; +use crate::version::dpp_versions::DPPVersion; +use crate::version::drive_abci_versions::drive_abci_method_versions::v2::DRIVE_ABCI_METHOD_VERSIONS_V2; +use crate::version::drive_abci_versions::drive_abci_query_versions::v1::DRIVE_ABCI_QUERY_VERSIONS_V1; +use crate::version::drive_abci_versions::drive_abci_structure_versions::v1::DRIVE_ABCI_STRUCTURE_VERSIONS_V1; +use crate::version::drive_abci_versions::drive_abci_validation_versions::v2::DRIVE_ABCI_VALIDATION_VERSIONS_V2; +use crate::version::drive_abci_versions::drive_abci_withdrawal_constants::v1::DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V1; +use crate::version::drive_abci_versions::DriveAbciVersion; +use crate::version::drive_versions::v2::DRIVE_VERSION_V2; use crate::version::fee::v1::FEE_VERSION1; -use crate::version::limits::SystemLimits; -use crate::version::protocol_version::{FeatureVersionBounds, PlatformVersion}; -use crate::version::{PlatformArchitectureVersion, ProtocolVersion}; -use grovedb_version::version::v1::GROVE_V1; +use crate::version::protocol_version::PlatformVersion; +use crate::version::system_data_contract_versions::v1::SYSTEM_DATA_CONTRACT_VERSIONS_V1; +use crate::version::system_limits::v1::SYSTEM_LIMITS_V1; +use crate::version::ProtocolVersion; pub const PROTOCOL_VERSION_3: ProtocolVersion = 3; @@ -93,1195 +37,32 @@ pub const PROTOCOL_VERSION_3: ProtocolVersion = 3; pub const PLATFORM_V3: PlatformVersion = PlatformVersion { protocol_version: 3, - proofs: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - drive: DriveVersion { - structure: DriveStructureVersion { - document_indexes: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_indexes: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - pools: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - methods: DriveMethodVersions { - initialization: DriveInitializationMethodVersions { - create_initial_state_structure: 0, - }, - credit_pools: DriveCreditPoolMethodVersions { - epochs: DriveCreditPoolEpochsMethodVersions { - get_epochs_infos: 0, - get_epochs_protocol_versions: 0, - prove_epochs_infos: 0, - get_epoch_fee_multiplier: 0, - get_epoch_processing_credits_for_distribution: 0, - get_epoch_storage_credits_for_distribution: 0, - get_epoch_total_credits_for_distribution: 0, - get_storage_credits_for_distribution_for_epochs_in_range: 0, - get_epoch_start_time: 0, - get_epoch_start_block_core_height: 0, - get_epoch_start_block_height: 0, - get_first_epoch_start_block_info_between_epochs: 0, - fetch_epoch_proposers: 0, - prove_epoch_proposers: 0, - get_epochs_proposer_block_count: 0, - add_update_pending_epoch_refunds_operations: 0, - is_epochs_proposers_tree_empty: 0, - }, - pending_epoch_refunds: DriveCreditPoolPendingEpochRefundsMethodVersions { - add_delete_pending_epoch_refunds_except_specified: 0, - fetch_and_add_pending_epoch_refunds_to_collection: 0, - fetch_pending_epoch_refunds: 0, - add_update_pending_epoch_refunds_operations: 0, - }, - storage_fee_distribution_pool: - DriveCreditPoolStorageFeeDistributionPoolMethodVersions { - get_storage_fees_from_distribution_pool: 0, - }, - unpaid_epoch: DriveCreditPoolUnpaidEpochMethodVersions { - get_unpaid_epoch_index: 0, - }, - }, - protocol_upgrade: DriveProtocolUpgradeVersions { - clear_version_information: 0, - fetch_versions_with_counter: 0, - fetch_proved_versions_with_counter: 0, - fetch_validator_version_votes: 0, - fetch_proved_validator_version_votes: 0, - remove_validators_proposed_app_versions: 0, - update_validator_proposed_app_version: 0, - }, - prove: DriveProveMethodVersions { - prove_elements: 0, - prove_multiple_state_transition_results: 0, - }, - balances: DriveBalancesMethodVersions { - add_to_system_credits: 0, - add_to_system_credits_operations: 0, - remove_from_system_credits: 0, - remove_from_system_credits_operations: 0, - calculate_total_credits_balance: 0, - }, - document: DriveDocumentMethodVersions { - query: DriveDocumentQueryMethodVersions { query_documents: 0, query_contested_documents: 0, query_contested_documents_vote_state: 0, query_documents_with_flags: 0 }, - delete: DriveDocumentDeleteMethodVersions { - add_estimation_costs_for_remove_document_to_primary_storage: 0, - delete_document_for_contract: 0, - delete_document_for_contract_id: 0, - delete_document_for_contract_apply_and_add_to_operations: 0, - remove_document_from_primary_storage: 0, - remove_reference_for_index_level_for_contract_operations: 0, - remove_indices_for_index_level_for_contract_operations: 0, - remove_indices_for_top_index_level_for_contract_operations: 0, - delete_document_for_contract_id_with_named_type_operations: 0, - delete_document_for_contract_with_named_type_operations: 0, - delete_document_for_contract_operations: 0, - }, - insert: DriveDocumentInsertMethodVersions { - add_document: 0, - add_document_for_contract: 0, - add_document_for_contract_apply_and_add_to_operations: 0, - add_document_for_contract_operations: 0, - add_document_to_primary_storage: 0, - add_indices_for_index_level_for_contract_operations: 0, - add_indices_for_top_index_level_for_contract_operations: 0, - add_reference_for_index_level_for_contract_operations: 0, - }, - insert_contested: DriveDocumentInsertContestedMethodVersions { - add_contested_document: 0, - add_contested_document_for_contract: 0, - add_contested_document_for_contract_apply_and_add_to_operations: 0, - add_contested_document_for_contract_operations: 0, - add_contested_document_to_primary_storage: 0, - add_contested_indices_for_contract_operations: 0, - add_contested_reference_and_vote_subtree_to_document_operations: 0, - add_contested_vote_subtree_for_non_identities_operations: 0, - }, - update: DriveDocumentUpdateMethodVersions { - add_update_multiple_documents_operations: 0, - update_document_for_contract: 0, - update_document_for_contract_apply_and_add_to_operations: 0, - update_document_for_contract_id: 0, - update_document_for_contract_operations: 0, - update_document_with_serialization_for_contract: 0, - update_serialized_document_for_contract: 0, - }, - estimation_costs: DriveDocumentEstimationCostsMethodVersions { - add_estimation_costs_for_add_document_to_primary_storage: 0, - add_estimation_costs_for_add_contested_document_to_primary_storage: 0, - stateless_delete_of_non_tree_for_costs: 0, - }, - index_uniqueness: DriveDocumentIndexUniquenessMethodVersions { - validate_document_uniqueness: 0, - validate_document_create_transition_action_uniqueness: 0, - validate_document_replace_transition_action_uniqueness: 0, - validate_document_transfer_transition_action_uniqueness: 0, - validate_document_purchase_transition_action_uniqueness: 0, - validate_document_update_price_transition_action_uniqueness: 0, - validate_uniqueness_of_data: 0, - }, - }, - vote: DriveVoteMethodVersions { - insert: DriveVoteInsertMethodVersions { - register_identity_vote: 0, - }, - contested_resource_insert: DriveVoteContestedResourceInsertMethodVersions { - register_contested_resource_identity_vote: 0, - insert_stored_info_for_contested_resource_vote_poll: 0, - register_identity_vote: 0, - add_vote_poll_end_date_query_operations: 0, - }, - cleanup: DriveVoteCleanupMethodVersions { - remove_specific_vote_references_given_by_identity: 0, - remove_specific_votes_given_by_identity: 0, - remove_contested_resource_vote_poll_end_date_query_operations: 1, - remove_contested_resource_vote_poll_votes_operations: 0, - remove_contested_resource_vote_poll_documents_operations: 1, - remove_contested_resource_vote_poll_contenders_operations: 1, - remove_contested_resource_top_level_index_operations: 0, - remove_contested_resource_info_operations: 0, - }, - setup: DriveVoteSetupMethodVersions { - add_initial_vote_tree_main_structure_operations: 0, - }, - storage_form: DriveVoteStorageFormMethodVersions { - resolve_with_contract: 0, - }, - fetch: DriveVoteFetchMethodVersions { - fetch_identities_voting_for_contenders: 0, - fetch_contested_document_vote_poll_stored_info: 0, - fetch_identity_contested_resource_vote: 0, - }, - }, - contract: 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: 0, - }, - update: DriveContractUpdateMethodVersions { update_contract: 0 }, - costs: DriveContractCostsMethodVersions { - add_estimation_costs_for_contract_insertion: 0, - }, - get: DriveContractGetMethodVersions { - fetch_contract: 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, - }, - }, - fees: DriveFeesMethodVersions { calculate_fee: 0 }, - estimated_costs: DriveEstimatedCostsMethodVersions { - add_estimation_costs_for_levels_up_to_contract: 0, - add_estimation_costs_for_levels_up_to_contract_document_type_excluded: 0, - add_estimation_costs_for_contested_document_tree_levels_up_to_contract: 0, - add_estimation_costs_for_contested_document_tree_levels_up_to_contract_document_type_excluded: 0, - }, - asset_lock: DriveAssetLockMethodVersions { - add_asset_lock_outpoint: 0, - add_estimation_costs_for_adding_asset_lock: 0, - fetch_asset_lock_outpoint_info: 0, - }, - verify: DriveVerifyMethodVersions { - contract: DriveVerifyContractMethodVersions { - verify_contract: 0, - verify_contract_history: 0, - }, - document: DriveVerifyDocumentMethodVersions { - verify_proof: 0, - verify_proof_keep_serialized: 0, - verify_start_at_document_in_proof: 0, - }, - identity: DriveVerifyIdentityMethodVersions { - verify_full_identities_by_public_key_hashes: 0, - verify_full_identity_by_identity_id: 0, - verify_full_identity_by_public_key_hash: 0, - verify_identity_balance_for_identity_id: 0, - verify_identity_balances_for_identity_ids: 0, - verify_identity_id_by_public_key_hash: 0, - verify_identity_ids_by_public_key_hashes: 0, - verify_identity_keys_by_identity_id: 0, - verify_identity_nonce: 0, - verify_identity_contract_nonce: 0, - verify_identities_contract_keys: 0, - verify_identity_revision_for_identity_id: 0, - }, - single_document: DriveVerifySingleDocumentMethodVersions { - verify_proof: 0, - verify_proof_keep_serialized: 0, - }, - system: DriveVerifySystemMethodVersions { - verify_epoch_infos: 0, - verify_epoch_proposers: 0, - verify_elements: 0, - verify_total_credits_in_system: 0, - verify_upgrade_state: 0, - verify_upgrade_vote_status: 0, - }, - voting: DriveVerifyVoteMethodVersions { - verify_masternode_vote: 0, - verify_start_at_contender_in_proof: 0, - verify_vote_poll_votes_proof: 0, - verify_identity_votes_given_proof: 0, - verify_vote_poll_vote_state_proof: 0, - verify_contests_proof: 0, - verify_vote_polls_by_end_date_proof: 0, - verify_specialized_balance: 0, - }, - state_transition: DriveVerifyStateTransitionMethodVersions { - verify_state_transition_was_executed_with_proof: 0, - }, - }, - identity: DriveIdentityMethodVersions { - fetch: DriveIdentityFetchMethodVersions { - public_key_hashes: DriveIdentityFetchPublicKeyHashesMethodVersions { - fetch_full_identities_by_unique_public_key_hashes: 0, - fetch_full_identity_by_unique_public_key_hash: 0, - fetch_identity_id_by_unique_public_key_hash: 0, - fetch_identity_ids_by_non_unique_public_key_hash: 0, - fetch_identity_ids_by_unique_public_key_hashes: 0, - fetch_serialized_full_identity_by_unique_public_key_hash: 0, - has_any_of_unique_public_key_hashes: 0, - has_non_unique_public_key_hash: 0, - has_non_unique_public_key_hash_already_for_identity: 0, - has_unique_public_key_hash: 0, - }, - attributes: DriveIdentityFetchAttributesMethodVersions { - revision: 0, - nonce: 0, - identity_contract_nonce: 0, - balance: 0, - balance_include_debt: 0, - negative_balance: 0, - }, - partial_identity: DriveIdentityFetchPartialIdentityMethodVersions { - fetch_identity_revision_with_keys: 0, - fetch_identity_balance_with_keys: 0, - fetch_identity_balance_with_keys_and_revision: 0, - fetch_identity_with_balance: 0, - fetch_identity_keys: 0, - }, - full_identity: DriveIdentityFetchFullIdentityMethodVersions { - fetch_full_identity: Some(0), - fetch_full_identities: Some(0), - }, - }, - prove: DriveIdentityProveMethodVersions { - full_identity: 0, - full_identities: 0, - identity_nonce: 0, - identity_contract_nonce: 0, - identities_contract_keys: 0, - prove_full_identities_by_unique_public_key_hashes: 0, - prove_full_identity_by_unique_public_key_hash: 0, - prove_identity_id_by_unique_public_key_hash: 0, - prove_identity_ids_by_unique_public_key_hashes: 0, - }, - keys: DriveIdentityKeysMethodVersions { - fetch: DriveIdentityKeysFetchMethodVersions { - fetch_all_current_identity_keys: 0, - fetch_all_identity_keys: 0, - fetch_identities_all_keys: 0, - fetch_identity_keys: 0, - fetch_identities_contract_keys: 0, - }, - prove: DriveIdentityKeysProveMethodVersions { - prove_identities_all_keys: 0, - prove_identity_keys: 0, - }, - insert: DriveIdentityKeysInsertMethodVersions { - create_key_tree_with_keys: 0, - create_new_identity_key_query_trees: 0, - insert_key_searchable_references: 0, - insert_key_to_storage: 0, - insert_new_non_unique_key: 0, - insert_new_unique_key: 0, - replace_key_in_storage: 0, - }, - insert_key_hash_identity_reference: - DriveIdentityKeyHashesToIdentityInsertMethodVersions { - add_estimation_costs_for_insert_non_unique_public_key_hash_reference: 0, - add_estimation_costs_for_insert_unique_public_key_hash_reference: 0, - insert_non_unique_public_key_hash_reference_to_identity: 0, - insert_reference_to_non_unique_key: 0, - insert_reference_to_unique_key: 0, - insert_unique_public_key_hash_reference_to_identity: 0, - }, - }, - update: DriveIdentityUpdateMethodVersions { - update_identity_revision: 0, - merge_identity_nonce: 0, - update_identity_negative_credit_operation: 0, - initialize_identity_revision: 0, - disable_identity_keys: 0, - re_enable_identity_keys: 0, - add_new_non_unique_keys_to_identity: 0, - add_new_unique_keys_to_identity: 0, - add_new_keys_to_identity: 0, - insert_identity_balance: 0, - initialize_negative_identity_balance: 0, - add_to_identity_balance: 0, - add_to_previous_balance: 0, - apply_balance_change_from_fee_to_identity: 0, - remove_from_identity_balance: 0, - refresh_identity_key_reference_operations: 0, - }, - insert: DriveIdentityInsertMethodVersions { - add_new_identity: 0, - }, - contract_info: DriveIdentityContractInfoMethodVersions { - add_potential_contract_info_for_contract_bounded_key: 0, - refresh_potential_contract_info_key_references: 0, - merge_identity_contract_nonce: 0, - }, - cost_estimation: DriveIdentityCostEstimationMethodVersions { - for_authentication_keys_security_level_in_key_reference_tree: 0, - for_balances: 0, - for_contract_info: 0, - for_contract_info_group: 0, - for_contract_info_group_keys: 0, - for_contract_info_group_key_purpose: 0, - for_keys_for_identity_id: 0, - for_negative_credit: 0, - for_purpose_in_key_reference_tree: 0, - for_root_key_reference_tree: 0, - for_update_revision: 0, - }, - withdrawals: DriveIdentityWithdrawalMethodVersions { - document: DriveIdentityWithdrawalDocumentMethodVersions { - fetch_oldest_withdrawal_documents_by_status: 0, - find_up_to_100_withdrawal_documents_by_status_and_transaction_indices: 0, - }, - transaction: DriveIdentityWithdrawalTransactionMethodVersions { - index: DriveIdentityWithdrawalTransactionIndexMethodVersions { - fetch_next_withdrawal_transaction_index: 0, - add_update_next_withdrawal_transaction_index_operation: 0, - }, - queue: DriveIdentityWithdrawalTransactionQueueMethodVersions { - add_enqueue_untied_withdrawal_transaction_operations: 0, - dequeue_untied_withdrawal_transactions: 0, - }, - }, - }, - }, - platform_system: DrivePlatformSystemMethodVersions { - estimation_costs: DriveSystemEstimationCostsMethodVersions { - for_total_system_credits_update: 0, - }, - }, - operations: DriveOperationsMethodVersion { - rollback_transaction: 0, - drop_cache: 0, - commit_transaction: 0, - apply_partial_batch_low_level_drive_operations: 0, - apply_partial_batch_grovedb_operations: 0, - apply_batch_low_level_drive_operations: 0, - apply_batch_grovedb_operations: 0, - }, - state_transitions: DriveStateTransitionMethodVersions { - operations: DriveStateTransitionOperationMethodVersions { - finalization_tasks: 0, - contracts: DriveDataContractOperationMethodVersions { - finalization_tasks: 0, - }, - }, - convert_to_high_level_operations: - DriveStateTransitionActionConvertToHighLevelOperationsMethodVersions { - data_contract_create_transition: 0, - data_contract_update_transition: 0, - document_create_transition: 0, - document_delete_transition: 0, - document_purchase_transition: 0, - document_replace_transition: 0, - document_transfer_transition: 0, - document_update_price_transition: 0, - documents_batch_transition: 0, - identity_create_transition: 0, - identity_credit_transfer_transition: 0, - identity_credit_withdrawal_transition: 0, - identity_top_up_transition: 0, - identity_update_transition: 0, - masternode_vote_transition: 0, - bump_identity_data_contract_nonce: 0, - bump_identity_nonce: 0, - partially_use_asset_lock: 0, - }, - }, - batch_operations: DriveBatchOperationsMethodVersion { - convert_drive_operations_to_grove_operations: 0, - apply_drive_operations: 0, - }, - platform_state: DrivePlatformStateMethodVersions { - fetch_platform_state_bytes: 0, - store_platform_state_bytes: 0, - }, - fetch: DriveFetchMethodVersions { fetch_elements: 0 }, - prefunded_specialized_balances: DrivePrefundedSpecializedMethodVersions { - fetch_single: 0, - prove_single: 0, - add_prefunded_specialized_balance: 0, - add_prefunded_specialized_balance_operations: 0, - deduct_from_prefunded_specialized_balance: 0, - deduct_from_prefunded_specialized_balance_operations: 0, - estimated_cost_for_prefunded_specialized_balance_update: 0, - }, - }, - grove_methods: DriveGroveMethodVersions { - basic: DriveGroveBasicMethodVersions { - grove_insert: 0, - grove_insert_empty_tree: 0, - grove_insert_empty_sum_tree: 0, - grove_insert_if_not_exists: 0, - grove_clear: 0, - grove_delete: 0, - grove_get_raw: 0, - grove_get_raw_optional: 0, - grove_get_raw_value_u64_from_encoded_var_vec: 0, - grove_get: 0, - grove_get_path_query_serialized_results: 0, - grove_get_path_query_serialized_or_sum_results: 0, - grove_get_path_query: 0, - grove_get_path_query_with_optional: 0, - grove_get_raw_path_query_with_optional: 0, - grove_get_raw_path_query: 0, - grove_get_proved_path_query: 0, - grove_get_proved_path_query_with_conditional: 0, - grove_get_sum_tree_total_value: 0, - grove_has_raw: 0, - }, - batch: DriveGroveBatchMethodVersions { - batch_insert_empty_tree: 0, - batch_insert_empty_tree_if_not_exists: 0, - batch_insert_empty_tree_if_not_exists_check_existing_operations: 0, - batch_insert: 0, - batch_insert_if_not_exists: 0, - batch_insert_if_changed_value: 0, - batch_replace: 0, - batch_delete: 0, - batch_remove_raw: 0, - batch_delete_up_tree_while_empty: 0, - batch_refresh_reference: 0, - }, - apply: DriveGroveApplyMethodVersions { - grove_apply_operation: 0, - grove_apply_batch: 0, - grove_apply_partial_batch: 0, - }, - costs: DriveGroveCostMethodVersions { - grove_batch_operations_costs: 0, - }, - }, - grove_version: GROVE_V1, - }, - platform_architecture: PlatformArchitectureVersion { - data_contract_factory_structure_version: 0, - document_factory_structure_version: 0, - }, + drive: DRIVE_VERSION_V2, drive_abci: DriveAbciVersion { - structs: DriveAbciStructureVersions { - platform_state_structure: 0, - platform_state_for_saving_structure: 0, - state_transition_execution_context: 0, - commit: 0, - masternode: 0, - signature_verification_quorum_set: 0, - }, - methods: DriveAbciMethodVersions { - engine: DriveAbciEngineMethodVersions { - init_chain: 0, - check_tx: 0, - run_block_proposal: 0, - finalize_block_proposal: 0, - consensus_params_update: 0, - }, - initialization: DriveAbciInitializationMethodVersions { - initial_core_height_and_time: 0, - create_genesis_state: 0, - }, - core_based_updates: DriveAbciCoreBasedUpdatesMethodVersions { - update_core_info: 0, - update_masternode_list: 0, - update_quorum_info: 0, - masternode_updates: DriveAbciMasternodeIdentitiesUpdatesMethodVersions { - get_voter_identity_key: 0, - get_operator_identity_keys: 0, - get_owner_identity_withdrawal_key: 0, - get_voter_identifier_from_masternode_list_item: 0, - get_operator_identifier_from_masternode_list_item: 0, - create_operator_identity: 0, - create_owner_identity: 0, - create_voter_identity: 0, - disable_identity_keys: 0, - update_masternode_identities: 0, - update_operator_identity: 0, - update_owner_withdrawal_address: 0, - update_voter_identity: 0, - }, - }, - protocol_upgrade: DriveAbciProtocolUpgradeMethodVersions { - check_for_desired_protocol_upgrade: 1, - upgrade_protocol_version_on_epoch_change: 0, - protocol_version_upgrade_percentage_needed: 67, - }, - block_fee_processing: DriveAbciBlockFeeProcessingMethodVersions { - add_process_epoch_change_operations: 0, - process_block_fees: 0, - }, - core_chain_lock: DriveAbciCoreChainLockMethodVersionsAndConstants { - choose_quorum: 0, - verify_chain_lock: 0, - verify_chain_lock_locally: 0, - verify_chain_lock_through_core: 0, - make_sure_core_is_synced_to_chain_lock: 0, - recent_block_count_amount: 2, - }, - core_instant_send_lock: DriveAbciCoreInstantSendLockMethodVersions { - verify_recent_signature_locally: 0, - }, - fee_pool_inwards_distribution: DriveAbciFeePoolInwardsDistributionMethodVersions { - add_distribute_block_fees_into_pools_operations: 0, - add_distribute_storage_fee_to_epochs_operations: 0, - }, - fee_pool_outwards_distribution: DriveAbciFeePoolOutwardsDistributionMethodVersions { - add_distribute_fees_from_oldest_unpaid_epoch_pool_to_proposers_operations: 0, - add_epoch_pool_to_proposers_payout_operations: 0, - find_oldest_epoch_needing_payment: 0, - fetch_reward_shares_list_for_masternode: 0, - }, - withdrawals: DriveAbciIdentityCreditWithdrawalMethodVersions { - build_untied_withdrawal_transactions_from_documents: 0, - dequeue_and_build_unsigned_withdrawal_transactions: 0, - fetch_transactions_block_inclusion_status: 0, - pool_withdrawals_into_transactions_queue: 0, - update_broadcasted_withdrawal_statuses: 0, - append_signatures_and_broadcast_withdrawal_transactions: 0, - }, - voting: DriveAbciVotingMethodVersions { - keep_record_of_finished_contested_resource_vote_poll: 0, - clean_up_after_vote_poll_end: 0, - clean_up_after_contested_resources_vote_poll_end: 0, - check_for_ended_vote_polls: 0, - tally_votes_for_contested_document_resource_vote_poll: 0, - award_document_to_winner: 0, - delay_vote_poll: 0, - run_dao_platform_events: 0, - remove_votes_for_removed_masternodes: 0, - }, - state_transition_processing: DriveAbciStateTransitionProcessingMethodVersions { - execute_event: 0, - process_raw_state_transitions: 0, - decode_raw_state_transitions: 0, - validate_fees_of_event: 0, - }, - epoch: DriveAbciEpochMethodVersions { - gather_epoch_info: 0, - get_genesis_time: 0, - }, - block_start: DriveAbciBlockStartMethodVersions { - clear_drive_block_cache: 0, - }, - block_end: DriveAbciBlockEndMethodVersions { - update_state_cache: 0, - update_drive_cache: 0, - validator_set_update: 0, - }, - platform_state_storage: DriveAbciPlatformStateStorageMethodVersions { - fetch_platform_state: 0, - store_platform_state: 0, - }, - }, - validation_and_processing: DriveAbciValidationVersions { - state_transitions: DriveAbciStateTransitionValidationVersions { - common_validation_methods: DriveAbciStateTransitionCommonValidationVersions { - asset_locks: DriveAbciAssetLockValidationVersions { - fetch_asset_lock_transaction_output_sync: 0, - verify_asset_lock_is_not_spent_and_has_enough_balance: 0, - }, - validate_identity_public_key_contract_bounds: 0, - validate_identity_public_key_ids_dont_exist_in_state: 0, - validate_identity_public_key_ids_exist_in_state: 0, - validate_state_transition_identity_signed: 0, - validate_unique_identity_public_key_hashes_in_state: 0, - validate_master_key_uniqueness: 0, - validate_simple_pre_check_balance: 0, - }, - max_asset_lock_usage_attempts: 16, - identity_create_state_transition: DriveAbciStateTransitionValidationVersion { - basic_structure: Some(0), - advanced_structure: Some(0), - identity_signatures: Some(0), - advanced_minimum_balance_pre_check: None, - nonce: None, - state: 0, - transform_into_action: 0, - }, - identity_update_state_transition: DriveAbciStateTransitionValidationVersion { - basic_structure: Some(0), - advanced_structure: Some(0), - identity_signatures: Some(0), - advanced_minimum_balance_pre_check: None, - nonce: Some(0), - state: 0, - transform_into_action: 0, - }, - identity_top_up_state_transition: DriveAbciStateTransitionValidationVersion { - basic_structure: Some(0), - advanced_structure: None, - identity_signatures: None, - advanced_minimum_balance_pre_check: None, - nonce: None, - state: 0, - transform_into_action: 0, - }, - identity_credit_withdrawal_state_transition: - DriveAbciStateTransitionValidationVersion { - basic_structure: Some(0), - advanced_structure: None, - identity_signatures: None, - advanced_minimum_balance_pre_check: Some(0), - nonce: Some(0), - state: 0, - transform_into_action: 0, - }, - identity_credit_transfer_state_transition: - DriveAbciStateTransitionValidationVersion { - basic_structure: Some(0), - advanced_structure: None, - identity_signatures: None, - advanced_minimum_balance_pre_check: Some(0), - nonce: Some(0), - state: 0, - transform_into_action: 0, - }, - masternode_vote_state_transition: DriveAbciStateTransitionValidationVersion { - basic_structure: None, - advanced_structure: Some(0), - identity_signatures: None, - advanced_minimum_balance_pre_check: Some(0), - nonce: Some(0), - state: 0, - transform_into_action: 0, - }, - contract_create_state_transition: DriveAbciStateTransitionValidationVersion { - basic_structure: Some(0), - advanced_structure: None, - identity_signatures: None, - advanced_minimum_balance_pre_check: None, - nonce: Some(0), - state: 0, - transform_into_action: 0, - }, - contract_update_state_transition: DriveAbciStateTransitionValidationVersion { - basic_structure: None, - advanced_structure: None, - identity_signatures: None, - advanced_minimum_balance_pre_check: None, - nonce: Some(0), - state: 0, - transform_into_action: 0, - }, - documents_batch_state_transition: - DriveAbciDocumentsStateTransitionValidationVersions { - balance_pre_check: 0, - basic_structure: 0, - advanced_structure: 0, - state: 0, - revision: 0, - transform_into_action: 0, - data_triggers: DriveAbciValidationDataTriggerAndBindingVersions { - bindings: 0, - triggers: DriveAbciValidationDataTriggerVersions { - create_contact_request_data_trigger: 0, - create_domain_data_trigger: 0, - create_identity_data_trigger: 0, - create_feature_flag_data_trigger: 0, - create_masternode_reward_shares_data_trigger: 0, - delete_withdrawal_data_trigger: 0, - reject_data_trigger: 0, - }, - }, - is_allowed: 0, - document_create_transition_structure_validation: 0, - document_delete_transition_structure_validation: 0, - document_replace_transition_structure_validation: 0, - document_transfer_transition_structure_validation: 0, - document_purchase_transition_structure_validation: 0, - document_update_price_transition_structure_validation: 0, - document_create_transition_state_validation: 1, - document_delete_transition_state_validation: 0, - document_replace_transition_state_validation: 0, - document_transfer_transition_state_validation: 0, - document_purchase_transition_state_validation: 0, - document_update_price_transition_state_validation: 0, - }, - }, - process_state_transition: 0, - state_transition_to_execution_event_for_check_tx: 0, - penalties: PenaltyAmounts { - identity_id_not_correct: 50000000, - unique_key_already_present: 10000000, - validation_of_added_keys_structure_failure: 10000000, - validation_of_added_keys_proof_of_possession_failure: 50000000, - }, - event_constants: DriveAbciValidationConstants { - maximum_vote_polls_to_process: 2, - maximum_contenders_to_consider: 100, - }, - }, - query: DriveAbciQueryVersions { - max_returned_elements: 100, - response_metadata: 0, - proofs_query: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - document_query: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - prefunded_specialized_balances: DriveAbciQueryPrefundedSpecializedBalancesVersions { - balance: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - identity_based_queries: DriveAbciQueryIdentityVersions { - identity: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - keys: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identities_contract_keys: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_nonce: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_contract_nonce: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - balance: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identities_balances: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - balance_and_revision: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_by_public_key_hash: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - validator_queries: DriveAbciQueryValidatorVersions { - proposed_block_counts_by_evonode_ids: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - proposed_block_counts_by_range: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - data_contract_based_queries: DriveAbciQueryDataContractVersions { - data_contract: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - data_contract_history: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - data_contracts: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - voting_based_queries: DriveAbciQueryVotingVersions { - vote_polls_by_end_date_query: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - contested_resource_vote_state: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - contested_resource_voters_for_identity: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - contested_resource_identity_vote_status: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - contested_resources: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - system: DriveAbciQuerySystemVersions { - version_upgrade_state: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - version_upgrade_vote_status: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - epoch_infos: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - partial_status: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - path_elements: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - total_credits_in_platform: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - }, + structs: DRIVE_ABCI_STRUCTURE_VERSIONS_V1, + methods: DRIVE_ABCI_METHOD_VERSIONS_V2, + validation_and_processing: DRIVE_ABCI_VALIDATION_VERSIONS_V2, + withdrawal_constants: DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V1, + query: DRIVE_ABCI_QUERY_VERSIONS_V1, }, dpp: DPPVersion { - costs: CostVersions { - signature_verify: 0, - }, - validation: DPPValidationVersions { - json_schema_validator: JsonSchemaValidatorVersions { - new: 0, - validate: 0, - compile: 0, - compile_and_validate: 0, - }, - data_contract: DataContractValidationVersions { - validate: 0, - validate_config_update: 0, - validate_index_definitions: 0, - validate_index_naming_duplicates: 0, - validate_not_defined_properties: 0, - validate_property_definition: 0, - }, - document_type: DocumentTypeValidationVersions { - validate_update: 0, - contested_index_limit: 1, - unique_index_limit: 10, - }, - voting: VotingValidationVersions { - allow_other_contenders_time_mainnet_ms: 604_800_000, // 1 week in ms - allow_other_contenders_time_testing_ms: 2_700_000, //45 minutes - votes_allowed_per_masternode: 5, - }, - }, - state_transition_serialization_versions: StateTransitionSerializationVersions { - identity_public_key_in_creation: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_create_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_update_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_top_up_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_credit_withdrawal_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - identity_credit_transfer_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - masternode_vote_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - contract_create_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - contract_update_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - documents_batch_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - document_base_state_transition: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - document_create_state_transition: DocumentFeatureVersionBounds { - bounds: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - document_replace_state_transition: DocumentFeatureVersionBounds { - bounds: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - document_delete_state_transition: DocumentFeatureVersionBounds { - bounds: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - document_transfer_state_transition: DocumentFeatureVersionBounds { - bounds: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - document_update_price_state_transition: DocumentFeatureVersionBounds { - bounds: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - document_purchase_state_transition: DocumentFeatureVersionBounds { - bounds: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - }, - state_transition_conversion_versions: StateTransitionConversionVersions { - identity_to_identity_create_transition: 0, - identity_to_identity_top_up_transition: 0, - identity_to_identity_withdrawal_transition: 0, - identity_to_identity_create_transition_with_signer: 0, - }, - state_transition_method_versions: StateTransitionMethodVersions { - public_key_in_creation_methods: PublicKeyInCreationMethodVersions { - from_public_key_signed_with_private_key: 0, - from_public_key_signed_external: 0, - hash: 0, - duplicated_key_ids_witness: 0, - duplicated_keys_witness: 0, - validate_identity_public_keys_structure: 0, - }, - }, - state_transitions: StateTransitionVersions { - documents: DocumentTransitionVersions { - documents_batch_transition: DocumentsBatchTransitionVersions { - validation: DocumentsBatchTransitionValidationVersions { - find_duplicates_by_id: 0, - validate_base_structure: 0, - }, - }, - }, - identities: IdentityTransitionVersions { - max_public_keys_in_creation: 6, - asset_locks: IdentityTransitionAssetLockVersions { - required_asset_lock_duff_balance_for_processing_start_for_identity_create: - 200000, - required_asset_lock_duff_balance_for_processing_start_for_identity_top_up: - 50000, - validate_asset_lock_transaction_structure: 0, - validate_instant_asset_lock_proof_structure: 0, - }, - }, - }, - contract_versions: ContractVersions { - max_serialized_size: 65000, - contract_serialization_version: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - contract_structure_version: 0, - created_data_contract_structure: 0, - config: 0, - methods: DataContractMethodVersions { - validate_document: 0, - validate_update: 0, - schema: 0, - }, - document_type_versions: DocumentTypeVersions { - index_versions: DocumentTypeIndexVersions { - index_levels_from_indices: 0, - }, - class_method_versions: DocumentTypeClassMethodVersions { - try_from_schema: 0, - create_document_types_from_document_schemas: 0, - }, - structure_version: 0, - schema: DocumentTypeSchemaVersions { - enrich_with_base_schema: 0, - find_identifier_and_binary_paths: 0, - validate_max_depth: 0, - max_depth: 256, - recursive_schema_validator_versions: RecursiveSchemaValidatorVersions { - traversal_validator: 0, - }, - validate_schema_compatibility: 0, - }, - methods: DocumentTypeMethodVersions { - create_document_from_data: 0, - create_document_with_prevalidated_properties: 0, - prefunded_voting_balance_for_document: 0, - contested_vote_poll_for_document: 0, - estimated_size: 0, - index_for_types: 0, - max_size: 0, - serialize_value_for_key: 0, - deserialize_value_for_key: 0, - }, - }, - }, - document_versions: DocumentVersions { - document_structure_version: 0, - document_serialization_version: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - document_cbor_serialization_version: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - extended_document_structure_version: 0, - extended_document_serialization_version: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - document_method_versions: DocumentMethodVersions { - is_equal_ignoring_timestamps: 0, - hash: 0, - get_raw_for_contract: 0, - get_raw_for_document_type: 0, - }, - }, - identity_versions: IdentityVersions { - identity_structure_version: 0, - identity_key_structure_version: 0, - identity_key_type_method_versions: IdentityKeyTypeMethodVersions { - random_public_key_data: 0, - random_public_and_private_key_data: 0, - }, - }, - voting_versions: VotingVersions { - default_vote_poll_time_duration_mainnet_ms: 1_209_600_000, //2 weeks - default_vote_poll_time_duration_test_network_ms: 5_400_000, //90 minutes - contested_document_vote_poll_stored_info_version: 0, - }, - asset_lock_versions: AssetLockVersions { - reduced_asset_lock_value: FeatureVersionBounds { - min_version: 0, - max_version: 0, - default_current_version: 0, - }, - }, - methods: DPPMethodVersions { - epoch_core_reward_credits_for_distribution: 0, - }, - }, - system_data_contracts: SystemDataContractVersions { - withdrawals: 1, - dpns: 1, - dashpay: 1, - masternode_reward_shares: 1, - feature_flags: 1, + costs: DPP_COSTS_VERSIONS_V1, + validation: DPP_VALIDATION_VERSIONS_V2, + state_transition_serialization_versions: STATE_TRANSITION_SERIALIZATION_VERSIONS_V1, + state_transition_conversion_versions: STATE_TRANSITION_CONVERSION_VERSIONS_V2, + state_transition_method_versions: STATE_TRANSITION_METHOD_VERSIONS_V1, + state_transitions: STATE_TRANSITION_VERSIONS_V2, + contract_versions: CONTRACT_VERSIONS_V1, + document_versions: DOCUMENT_VERSIONS_V1, + identity_versions: IDENTITY_VERSIONS_V1, + voting_versions: VOTING_VERSION_V2, + asset_lock_versions: DPP_ASSET_LOCK_VERSIONS_V1, + methods: DPP_METHOD_VERSIONS_V1, + factory_versions: DPP_FACTORY_VERSIONS_V1, }, + system_data_contracts: SYSTEM_DATA_CONTRACT_VERSIONS_V1, fee_version: FEE_VERSION1, - system_limits: SystemLimits { - estimated_contract_max_serialized_size: 16384, - max_field_value_size: 5120, //5 KiB - max_state_transition_size: 20480, //20 KiB - max_transitions_in_documents_batch: 1, - }, + system_limits: SYSTEM_LIMITS_V1, consensus: ConsensusVersions { tenderdash_consensus_version: 1, }, diff --git a/packages/rs-platform-version/src/version/v4.rs b/packages/rs-platform-version/src/version/v4.rs new file mode 100644 index 0000000000..d0b5894374 --- /dev/null +++ b/packages/rs-platform-version/src/version/v4.rs @@ -0,0 +1,64 @@ +use crate::version::consensus_versions::ConsensusVersions; +use crate::version::dpp_versions::dpp_asset_lock_versions::v1::DPP_ASSET_LOCK_VERSIONS_V1; +use crate::version::dpp_versions::dpp_contract_versions::v1::CONTRACT_VERSIONS_V1; +use crate::version::dpp_versions::dpp_costs_versions::v1::DPP_COSTS_VERSIONS_V1; +use crate::version::dpp_versions::dpp_document_versions::v1::DOCUMENT_VERSIONS_V1; +use crate::version::dpp_versions::dpp_factory_versions::v1::DPP_FACTORY_VERSIONS_V1; +use crate::version::dpp_versions::dpp_identity_versions::v1::IDENTITY_VERSIONS_V1; +use crate::version::dpp_versions::dpp_method_versions::v1::DPP_METHOD_VERSIONS_V1; +use crate::version::dpp_versions::dpp_state_transition_conversion_versions::v2::STATE_TRANSITION_CONVERSION_VERSIONS_V2; +use crate::version::dpp_versions::dpp_state_transition_method_versions::v1::STATE_TRANSITION_METHOD_VERSIONS_V1; +use crate::version::dpp_versions::dpp_state_transition_serialization_versions::v1::STATE_TRANSITION_SERIALIZATION_VERSIONS_V1; +use crate::version::dpp_versions::dpp_state_transition_versions::v2::STATE_TRANSITION_VERSIONS_V2; +use crate::version::dpp_versions::dpp_validation_versions::v2::DPP_VALIDATION_VERSIONS_V2; +use crate::version::dpp_versions::dpp_voting_versions::v2::VOTING_VERSION_V2; +use crate::version::dpp_versions::DPPVersion; +use crate::version::drive_abci_versions::drive_abci_method_versions::v3::DRIVE_ABCI_METHOD_VERSIONS_V3; +use crate::version::drive_abci_versions::drive_abci_query_versions::v1::DRIVE_ABCI_QUERY_VERSIONS_V1; +use crate::version::drive_abci_versions::drive_abci_structure_versions::v1::DRIVE_ABCI_STRUCTURE_VERSIONS_V1; +use crate::version::drive_abci_versions::drive_abci_validation_versions::v3::DRIVE_ABCI_VALIDATION_VERSIONS_V3; +use crate::version::drive_abci_versions::drive_abci_withdrawal_constants::v2::DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V2; +use crate::version::drive_abci_versions::DriveAbciVersion; +use crate::version::drive_versions::v2::DRIVE_VERSION_V2; +use crate::version::fee::v1::FEE_VERSION1; +use crate::version::protocol_version::PlatformVersion; +use crate::version::system_data_contract_versions::v1::SYSTEM_DATA_CONTRACT_VERSIONS_V1; +use crate::version::system_limits::v1::SYSTEM_LIMITS_V1; +use crate::version::ProtocolVersion; + +pub const PROTOCOL_VERSION_4: ProtocolVersion = 4; + +/// This version introduces withdrawals. + +pub const PLATFORM_V4: PlatformVersion = PlatformVersion { + protocol_version: PROTOCOL_VERSION_4, + drive: DRIVE_VERSION_V2, + drive_abci: DriveAbciVersion { + structs: DRIVE_ABCI_STRUCTURE_VERSIONS_V1, + methods: DRIVE_ABCI_METHOD_VERSIONS_V3, + validation_and_processing: DRIVE_ABCI_VALIDATION_VERSIONS_V3, + withdrawal_constants: DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V2, + query: DRIVE_ABCI_QUERY_VERSIONS_V1, + }, + dpp: DPPVersion { + costs: DPP_COSTS_VERSIONS_V1, + validation: DPP_VALIDATION_VERSIONS_V2, + state_transition_serialization_versions: STATE_TRANSITION_SERIALIZATION_VERSIONS_V1, + state_transition_conversion_versions: STATE_TRANSITION_CONVERSION_VERSIONS_V2, + state_transition_method_versions: STATE_TRANSITION_METHOD_VERSIONS_V1, + state_transitions: STATE_TRANSITION_VERSIONS_V2, + contract_versions: CONTRACT_VERSIONS_V1, + document_versions: DOCUMENT_VERSIONS_V1, + identity_versions: IDENTITY_VERSIONS_V1, + voting_versions: VOTING_VERSION_V2, + asset_lock_versions: DPP_ASSET_LOCK_VERSIONS_V1, + methods: DPP_METHOD_VERSIONS_V1, + factory_versions: DPP_FACTORY_VERSIONS_V1, + }, + system_data_contracts: SYSTEM_DATA_CONTRACT_VERSIONS_V1, + fee_version: FEE_VERSION1, + system_limits: SYSTEM_LIMITS_V1, + consensus: ConsensusVersions { + tenderdash_consensus_version: 1, + }, +}; diff --git a/packages/rs-platform-version/src/version/v5.rs b/packages/rs-platform-version/src/version/v5.rs new file mode 100644 index 0000000000..988531b3d0 --- /dev/null +++ b/packages/rs-platform-version/src/version/v5.rs @@ -0,0 +1,64 @@ +use crate::version::consensus_versions::ConsensusVersions; +use crate::version::dpp_versions::dpp_asset_lock_versions::v1::DPP_ASSET_LOCK_VERSIONS_V1; +use crate::version::dpp_versions::dpp_contract_versions::v1::CONTRACT_VERSIONS_V1; +use crate::version::dpp_versions::dpp_costs_versions::v1::DPP_COSTS_VERSIONS_V1; +use crate::version::dpp_versions::dpp_document_versions::v1::DOCUMENT_VERSIONS_V1; +use crate::version::dpp_versions::dpp_factory_versions::v1::DPP_FACTORY_VERSIONS_V1; +use crate::version::dpp_versions::dpp_identity_versions::v1::IDENTITY_VERSIONS_V1; +use crate::version::dpp_versions::dpp_method_versions::v1::DPP_METHOD_VERSIONS_V1; +use crate::version::dpp_versions::dpp_state_transition_conversion_versions::v2::STATE_TRANSITION_CONVERSION_VERSIONS_V2; +use crate::version::dpp_versions::dpp_state_transition_method_versions::v1::STATE_TRANSITION_METHOD_VERSIONS_V1; +use crate::version::dpp_versions::dpp_state_transition_serialization_versions::v1::STATE_TRANSITION_SERIALIZATION_VERSIONS_V1; +use crate::version::dpp_versions::dpp_state_transition_versions::v2::STATE_TRANSITION_VERSIONS_V2; +use crate::version::dpp_versions::dpp_validation_versions::v2::DPP_VALIDATION_VERSIONS_V2; +use crate::version::dpp_versions::dpp_voting_versions::v2::VOTING_VERSION_V2; +use crate::version::dpp_versions::DPPVersion; +use crate::version::drive_abci_versions::drive_abci_method_versions::v4::DRIVE_ABCI_METHOD_VERSIONS_V4; +use crate::version::drive_abci_versions::drive_abci_query_versions::v1::DRIVE_ABCI_QUERY_VERSIONS_V1; +use crate::version::drive_abci_versions::drive_abci_structure_versions::v1::DRIVE_ABCI_STRUCTURE_VERSIONS_V1; +use crate::version::drive_abci_versions::drive_abci_validation_versions::v3::DRIVE_ABCI_VALIDATION_VERSIONS_V3; +use crate::version::drive_abci_versions::drive_abci_withdrawal_constants::v2::DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V2; +use crate::version::drive_abci_versions::DriveAbciVersion; +use crate::version::drive_versions::v2::DRIVE_VERSION_V2; +use crate::version::fee::v1::FEE_VERSION1; +use crate::version::protocol_version::PlatformVersion; +use crate::version::system_data_contract_versions::v1::SYSTEM_DATA_CONTRACT_VERSIONS_V1; +use crate::version::system_limits::v1::SYSTEM_LIMITS_V1; +use crate::version::ProtocolVersion; + +pub const PROTOCOL_VERSION_5: ProtocolVersion = 5; + +/// This version added a fix to withdrawals so we would rotate to first quorum always. + +pub const PLATFORM_V5: PlatformVersion = PlatformVersion { + protocol_version: PROTOCOL_VERSION_5, + drive: DRIVE_VERSION_V2, + drive_abci: DriveAbciVersion { + structs: DRIVE_ABCI_STRUCTURE_VERSIONS_V1, + methods: DRIVE_ABCI_METHOD_VERSIONS_V4, // changed to v4 + validation_and_processing: DRIVE_ABCI_VALIDATION_VERSIONS_V3, + withdrawal_constants: DRIVE_ABCI_WITHDRAWAL_CONSTANTS_V2, + query: DRIVE_ABCI_QUERY_VERSIONS_V1, + }, + dpp: DPPVersion { + costs: DPP_COSTS_VERSIONS_V1, + validation: DPP_VALIDATION_VERSIONS_V2, + state_transition_serialization_versions: STATE_TRANSITION_SERIALIZATION_VERSIONS_V1, + state_transition_conversion_versions: STATE_TRANSITION_CONVERSION_VERSIONS_V2, + state_transition_method_versions: STATE_TRANSITION_METHOD_VERSIONS_V1, + state_transitions: STATE_TRANSITION_VERSIONS_V2, + contract_versions: CONTRACT_VERSIONS_V1, + document_versions: DOCUMENT_VERSIONS_V1, + identity_versions: IDENTITY_VERSIONS_V1, + voting_versions: VOTING_VERSION_V2, + asset_lock_versions: DPP_ASSET_LOCK_VERSIONS_V1, + methods: DPP_METHOD_VERSIONS_V1, + factory_versions: DPP_FACTORY_VERSIONS_V1, + }, + system_data_contracts: SYSTEM_DATA_CONTRACT_VERSIONS_V1, + fee_version: FEE_VERSION1, + system_limits: SYSTEM_LIMITS_V1, + consensus: ConsensusVersions { + tenderdash_consensus_version: 1, + }, +}; diff --git a/packages/rs-platform-versioning/Cargo.toml b/packages/rs-platform-versioning/Cargo.toml index e7bcf02d77..4a0f8f5a6d 100644 --- a/packages/rs-platform-versioning/Cargo.toml +++ b/packages/rs-platform-versioning/Cargo.toml @@ -2,7 +2,7 @@ name = "platform-versioning" authors = ["Samuel Westrich "] description = "Version derivation" -version = "1.3.1" +version = "1.5.0" edition = "2021" rust-version.workspace = true license = "MIT" @@ -12,5 +12,5 @@ proc-macro = true [dependencies] proc-macro2 = "1.0.56" -quote = "1.0.26" -syn = "2.0.15" +quote = "1.0.37" +syn = "2.0.75" diff --git a/packages/rs-sdk/Cargo.toml b/packages/rs-sdk/Cargo.toml index 9b3d901a8d..ed45b0d813 100644 --- a/packages/rs-sdk/Cargo.toml +++ b/packages/rs-sdk/Cargo.toml @@ -1,10 +1,13 @@ [package] name = "dash-sdk" -version = "1.3.1" +version = "1.5.0" edition = "2021" [dependencies] + arc-swap = { version = "1.7.1" } +backon = { version = "1.2", features = ["tokio-sleep"] } +chrono = { version = "0.4.38" } dpp = { path = "../rs-dpp", default-features = false, features = [ "dash-sdk-features", ] } @@ -15,30 +18,30 @@ drive = { path = "../rs-drive", default-features = false, features = [ ] } drive-proof-verifier = { path = "../rs-drive-proof-verifier" } dapi-grpc-macros = { path = "../rs-dapi-grpc-macros" } -thiserror = "1.0.58" -tokio = { version = "1.36.0", features = ["macros"] } -tokio-util = { version = "0.7.10" } -async-trait = { version = "0.1.79" } -http = { version = "0.2.12" } +http = { version = "1.1" } +thiserror = "1.0.64" +tokio = { version = "1.40", features = ["macros", "rt-multi-thread"] } +tokio-util = { version = "0.7.12" } +async-trait = { version = "0.1.83" } ciborium = { git = "https://github.com/qrayven/ciborium", branch = "feat-ser-null-as-undefined" } serde = { version = "1.0.197", default-features = false, features = [ "rc", ], optional = true } serde_json = { version = "1.0", features = ["preserve_order"], optional = true } tracing = { version = "0.1.40" } -hex = { version = "0.4.3"} +hex = { version = "0.4.3" } dotenvy = { version = "0.15.7", optional = true } envy = { version = "0.4.2", optional = true } futures = { version = "0.3.30" } -derive_more = { version = "0.99.17" } +derive_more = { version = "1.0", features = ["from"] } # dashcore-rpc is only needed for core rpc; TODO remove once we have correct core rpc impl -dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore-rpc", tag = "v0.15.4" } +dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore-rpc", tag = "v0.15.8" } lru = { version = "0.12.3", optional = true } bip37-bloom-filter = { git = "https://github.com/dashpay/rs-bip37-bloom-filter", branch = "develop" } -pollster = { version = "0.3.0" } +zeroize = { version = "1.8", features = ["derive"] } [dev-dependencies] -tokio = { version = "1.36.0", features = ["macros", "rt-multi-thread"] } +tokio = { version = "1.40", features = ["macros", "rt-multi-thread"] } rs-dapi-client = { path = "../rs-dapi-client", features = ["mocks"] } base64 = { version = "0.22.1" } tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } @@ -51,7 +54,6 @@ data-contracts = { path = "../data-contracts" } tokio-test = { version = "0.4.4" } clap = { version = "4.5.4", features = ["derive"] } sanitize-filename = { version = "0.5.0" } -chrono = { version = "0.4.38" } test-case = { version = "3.3.1" } [features] @@ -69,6 +71,7 @@ mocks = [ "dep:dotenvy", "dep:envy", "dep:lru", + "zeroize/serde", ] # Run integration tests using test vectors from `tests/vectors/` instead of connecting to live Dash Platform. diff --git a/packages/rs-sdk/README.md b/packages/rs-sdk/README.md index 4d543c5857..c14b9bbd59 100644 --- a/packages/rs-sdk/README.md +++ b/packages/rs-sdk/README.md @@ -97,9 +97,9 @@ Run the offline test using the following command: cargo test -p dash-platform-sdk ``` -## Implementing Fetch and FetchAny on new objects +## Implementing Fetch and FetchMany on new objects -How to implement `Fetch` and `FetchAny` trait on new object types (`Object`). +How to implement `Fetch` and `FetchMany` trait on new object types (`Object`). It's basically copy-paste and tweaking of existing implementation for another object type. @@ -114,7 +114,7 @@ Definitions: Checklist: 1. [ ] Ensure protobuf messages are defined in `packages/dapi-grpc/protos/platform/v0/platform.proto` and generated - correctly in `packages/dapi-grpc/src/platform/proto/org.dash.platform.dapi.v0.rs`. + correctly in `packages/dapi-grpc/src/platform/client/org.dash.platform.dapi.v0.rs`. 2. [ ] In `packages/dapi-grpc/build.rs`, add `Request` to `VERSIONED_REQUESTS` and response `Response` to `VERSIONED_RESPONSES`. This should add derive of `VersionedGrpcMessage` (and some more) in `org.dash.platform.dapi.v0.rs`. 3. [ ] Link request and response type to dapi-client by adding appropriate invocation of `impl_transport_request_grpc!` macro @@ -123,7 +123,7 @@ in `packages/rs-dapi-client/src/transport/grpc.rs`. used internally. If you intend to implement `FetchMany`, you should define type returned by `fetch_many()` using `RetrievedObjects` - that will store collection of returned objects, indexd by some key. + that will store collection of returned objects, indexed by some key. 5. [ ] Implement `FromProof` trait for the `Object` (or type defined in `types.rs`) in `packages/rs-drive-proof-verifier/src/proof.rs`. 6. [ ] Implement `Query` trait for the `Request` in `packages/rs-sdk/src/platform/query.rs`. 7. [ ] Implement `Fetch` trait for the `Object` (or type defined in `types.rs`), with inner type Request = `Request`, diff --git a/packages/rs-sdk/examples/read_contract.rs b/packages/rs-sdk/examples/read_contract.rs index ca37f1cfa7..7ac2cc333d 100644 --- a/packages/rs-sdk/examples/read_contract.rs +++ b/packages/rs-sdk/examples/read_contract.rs @@ -4,6 +4,7 @@ use clap::Parser; use dash_sdk::{mock::provider::GrpcContextProvider, platform::Fetch, Sdk, SdkBuilder}; use dpp::prelude::{DataContract, Identifier}; use rs_dapi_client::AddressList; +use zeroize::Zeroizing; #[derive(clap::Parser, Debug)] #[command(version)] @@ -22,7 +23,7 @@ pub struct Config { // Dash Core RPC password #[arg(short = 'p', long)] - pub core_password: String, + pub core_password: Zeroizing, /// Dash Platform DAPI port #[arg(short = 'd', long)] @@ -86,7 +87,7 @@ fn setup_sdk(config: &Config) -> Sdk { .expect("parse uri"); // Now, we create the Sdk with the wallet and context provider. - let mut sdk = SdkBuilder::new(AddressList::from_iter([uri])) + let sdk = SdkBuilder::new(AddressList::from_iter([uri])) .build() .expect("cannot build sdk"); diff --git a/packages/rs-sdk/src/core_client.rs b/packages/rs-sdk/src/core/dash_core_client.rs similarity index 89% rename from packages/rs-sdk/src/core_client.rs rename to packages/rs-sdk/src/core/dash_core_client.rs index e68bb6166d..d59af4207c 100644 --- a/packages/rs-sdk/src/core_client.rs +++ b/packages/rs-sdk/src/core/dash_core_client.rs @@ -14,20 +14,33 @@ use dpp::dashcore::ProTxHash; use dpp::prelude::CoreBlockHeight; use drive_proof_verifier::error::ContextProviderError; use std::{fmt::Debug, sync::Mutex}; +use zeroize::Zeroizing; /// Core RPC client that can be used to retrieve quorum keys from core. /// -/// Implements [`ContextProvider`] trait. -/// /// TODO: This is a temporary implementation, effective until we integrate SPV. -pub struct CoreClient { +pub struct LowLevelDashCoreClient { core: Mutex, server_address: String, core_user: String, + core_password: Zeroizing, core_port: u16, } -impl Debug for CoreClient { +impl Clone for LowLevelDashCoreClient { + // As Client does not implement Clone, we just create a new instance of CoreClient here. + fn clone(&self) -> Self { + LowLevelDashCoreClient::new( + &self.server_address, + self.core_port, + &self.core_user, + &self.core_password, + ) + .expect("Failed to clone CoreClient when cloning, this should not happen") + } +} + +impl Debug for LowLevelDashCoreClient { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("CoreClient") .field("server_address", &self.server_address) @@ -37,7 +50,7 @@ impl Debug for CoreClient { } } -impl CoreClient { +impl LowLevelDashCoreClient { /// Create new Dash Core client. /// /// # Arguments @@ -63,13 +76,14 @@ impl CoreClient { core: Mutex::new(core), server_address: server_address.to_string(), core_user: core_user.to_string(), + core_password: core_password.to_string().into(), core_port, }) } } // Wallet functions -impl CoreClient { +impl LowLevelDashCoreClient { /// List unspent transactions /// /// ## Arguments diff --git a/packages/rs-sdk/src/core/mod.rs b/packages/rs-sdk/src/core/mod.rs index ed7d4726cf..f642f3b26f 100644 --- a/packages/rs-sdk/src/core/mod.rs +++ b/packages/rs-sdk/src/core/mod.rs @@ -1,4 +1,8 @@ //! Dash Core SDK implementation. //! //! TODO: This is work in progress. +#[cfg(feature = "mocks")] +mod dash_core_client; mod transaction; +#[cfg(feature = "mocks")] +pub use dash_core_client::LowLevelDashCoreClient; diff --git a/packages/rs-sdk/src/core/transaction.rs b/packages/rs-sdk/src/core/transaction.rs index 39dd85e562..a71a6f664c 100644 --- a/packages/rs-sdk/src/core/transaction.rs +++ b/packages/rs-sdk/src/core/transaction.rs @@ -12,7 +12,7 @@ use dpp::identity::state_transition::asset_lock_proof::chain::ChainAssetLockProo use dpp::identity::state_transition::asset_lock_proof::InstantAssetLockProof; use dpp::prelude::AssetLockProof; -use rs_dapi_client::{DapiRequestExecutor, RequestSettings}; +use rs_dapi_client::{DapiRequestExecutor, IntoInner, RequestSettings}; use std::time::Duration; use tokio::time::{sleep, timeout}; @@ -56,6 +56,7 @@ impl Sdk { }; self.execute(core_transactions_stream, RequestSettings::default()) .await + .into_inner() .map_err(|e| Error::DapiClientError(e.to_string())) } @@ -180,7 +181,8 @@ impl Sdk { }, RequestSettings::default(), ) - .await?; + .await // TODO: We need better way to handle execution errors + .into_inner()?; core_chain_locked_height = height; diff --git a/packages/rs-sdk/src/error.rs b/packages/rs-sdk/src/error.rs index ce8b3f309a..2d0ba29a2b 100644 --- a/packages/rs-sdk/src/error.rs +++ b/packages/rs-sdk/src/error.rs @@ -1,15 +1,16 @@ //! Definitions of errors -use std::fmt::Debug; -use std::time::Duration; - -use dapi_grpc::mock::Mockable; +use dpp::consensus::ConsensusError; +use dpp::serialization::PlatformDeserializable; use dpp::version::PlatformVersionError; use dpp::ProtocolError; -use rs_dapi_client::DapiClientError; - pub use drive_proof_verifier::error::ContextProviderError; +use rs_dapi_client::transport::TransportError; +use rs_dapi_client::{CanRetry, DapiClientError, ExecutionError}; +use std::fmt::Debug; +use std::time::Duration; /// Error type for the SDK +// TODO: Propagate server address and retry information so that the user can retrieve it #[derive(Debug, thiserror::Error)] pub enum Error { /// SDK is not configured properly @@ -67,10 +68,30 @@ pub enum Error { /// Operation cancelled - cancel token was triggered, timeout, etc. #[error("Operation cancelled: {0}")] Cancelled(String), + + /// Remote node is stale; try another server + #[error(transparent)] + StaleNode(#[from] StaleNodeError), } -impl From> for Error { - fn from(value: DapiClientError) -> Self { +// TODO: Decompose DapiClientError to more specific errors like connection, node error instead of DAPI client error +impl From for Error { + fn from(value: DapiClientError) -> Self { + if let DapiClientError::Transport(TransportError::Grpc(status)) = &value { + if let Some(consensus_error_value) = status + .metadata() + .get_bin("dash-serialized-consensus-error-bin") + { + return ConsensusError::deserialize_from_bytes( + consensus_error_value.as_encoded_bytes(), + ) + .map(|consensus_error| { + Self::Protocol(ProtocolError::ConsensusError(Box::new(consensus_error))) + }) + .unwrap_or_else(Self::Protocol); + } + } + Self::DapiClientError(format!("{:?}", value)) } } @@ -80,3 +101,46 @@ impl From for Error { Self::Protocol(value.into()) } } + +impl From> for Error +where + ExecutionError: ToString, +{ + fn from(value: ExecutionError) -> Self { + // TODO: Improve error handling + Self::DapiClientError(value.to_string()) + } +} + +impl CanRetry for Error { + fn can_retry(&self) -> bool { + matches!(self, Error::StaleNode(..) | Error::TimeoutReached(_, _)) + } +} + +/// Server returned stale metadata +#[derive(Debug, thiserror::Error)] +pub enum StaleNodeError { + /// Server returned metadata with outdated height + #[error("received height is outdated: expected {expected_height}, received {received_height}, tolerance {tolerance_blocks}; try another server")] + Height { + /// Expected height - last block height seen by the Sdk + expected_height: u64, + /// Block height received from the server + received_height: u64, + /// Tolerance - how many blocks can be behind the expected height + tolerance_blocks: u64, + }, + /// Server returned metadata with time outside of the tolerance + #[error( + "received invalid time: expected {expected_timestamp_ms}ms, received {received_timestamp_ms} ms, tolerance {tolerance_ms} ms; try another server" + )] + Time { + /// Expected time in milliseconds - is local time when the message was received + expected_timestamp_ms: u64, + /// Time received from the server in the message, in milliseconds + received_timestamp_ms: u64, + /// Tolerance in milliseconds + tolerance_ms: u64, + }, +} diff --git a/packages/rs-sdk/src/lib.rs b/packages/rs-sdk/src/lib.rs index 14b65a58c2..1f928ab6db 100644 --- a/packages/rs-sdk/src/lib.rs +++ b/packages/rs-sdk/src/lib.rs @@ -32,8 +32,8 @@ //! //! 1. [`Identifier`](crate::platform::Identifier) - fetches an object by its identifier //! 2. [`DocumentQuery`](crate::platform::DocumentQuery) - fetches documents based on search conditions; see -//! [query syntax documentation](https://docs.dash.org/projects/platform/en/stable/docs/reference/query-syntax.html) -//! for more details. +//! [query syntax documentation](https://docs.dash.org/projects/platform/en/stable/docs/reference/query-syntax.html) +//! for more details. //! 3. [`DriveQuery`](crate::platform::DriveDocumentQuery) - can be used to build more complex queries //! //! ## Testability @@ -62,8 +62,6 @@ #![allow(rustdoc::private_intra_doc_links)] pub mod core; -#[cfg(feature = "mocks")] -mod core_client; pub mod error; mod internal_cache; pub mod mock; @@ -73,8 +71,12 @@ pub mod sdk; pub use error::Error; pub use sdk::{RequestSettings, Sdk, SdkBuilder}; +pub use dashcore_rpc; pub use dpp; +pub use drive; +pub use drive_proof_verifier::types as query_types; pub use rs_dapi_client as dapi_client; +pub mod sync; /// Version of the SDK pub const VERSION: &str = env!("CARGO_PKG_VERSION"); diff --git a/packages/rs-sdk/src/mock.rs b/packages/rs-sdk/src/mock.rs index b3f1b69c63..7ad4dc7ccd 100644 --- a/packages/rs-sdk/src/mock.rs +++ b/packages/rs-sdk/src/mock.rs @@ -32,7 +32,6 @@ pub mod sdk; // Otherwise dapi_grpc_macros::Mockable fails. // TODO: move Mockable to some crate that can be shared between dapi-grpc, rs-dapi-client, and dash-sdk pub use dapi_grpc::mock::Mockable; - // MockResponse is needed even if mocks feature is disabled - it just does nothing. #[cfg(not(feature = "mocks"))] pub use noop::MockResponse; diff --git a/packages/rs-sdk/src/mock/provider.rs b/packages/rs-sdk/src/mock/provider.rs index 8c0297bf47..879c4137eb 100644 --- a/packages/rs-sdk/src/mock/provider.rs +++ b/packages/rs-sdk/src/mock/provider.rs @@ -1,13 +1,13 @@ //! Example ContextProvider that uses the Core gRPC API to fetch data from Platform. -use crate::core_client::CoreClient; +use crate::core::LowLevelDashCoreClient; use crate::platform::Fetch; +use crate::sync::block_on; use crate::{Error, Sdk}; use arc_swap::ArcSwapAny; use dpp::prelude::{CoreBlockHeight, DataContract, Identifier}; use drive_proof_verifier::error::ContextProviderError; use drive_proof_verifier::ContextProvider; -use pollster::FutureExt; use std::hash::Hash; use std::num::NonZeroUsize; use std::sync::Arc; @@ -17,7 +17,7 @@ use std::sync::Arc; /// Example [ContextProvider] used by the Sdk for testing purposes. pub struct GrpcContextProvider { /// Core client - core: CoreClient, + core: LowLevelDashCoreClient, /// [Sdk] to use when fetching data from Platform /// /// Note that if the `sdk` is `None`, the context provider will not be able to fetch data itself and will rely on @@ -62,7 +62,8 @@ impl GrpcContextProvider { data_contracts_cache_size: NonZeroUsize, quorum_public_keys_cache_size: NonZeroUsize, ) -> Result { - let core_client = CoreClient::new(core_ip, core_port, core_user, core_password)?; + let core_client = + LowLevelDashCoreClient::new(core_ip, core_port, core_user, core_password)?; Ok(Self { core: core_client, sdk: ArcSwapAny::new(Arc::new(sdk)), @@ -197,9 +198,9 @@ impl ContextProvider for GrpcContextProvider { let sdk_cloned = sdk.clone(); - let data_contract: Option = DataContract::fetch(&sdk_cloned, contract_id) - .block_on() - .map_err(|e| ContextProviderError::DataContractFailure(e.to_string()))?; + let data_contract: Option = + block_on(async move { DataContract::fetch(&sdk_cloned, contract_id).await })? + .map_err(|e| ContextProviderError::DataContractFailure(e.to_string()))?; if let Some(ref dc) = data_contract { self.data_contracts_cache.put(*data_contract_id, dc.clone()); diff --git a/packages/rs-sdk/src/mock/requests.rs b/packages/rs-sdk/src/mock/requests.rs index 879fe88bb4..582c3628a0 100644 --- a/packages/rs-sdk/src/mock/requests.rs +++ b/packages/rs-sdk/src/mock/requests.rs @@ -1,8 +1,9 @@ use super::MockDashPlatformSdk; +use dpp::bincode::config::standard; use dpp::{ bincode, block::extended_epoch_info::ExtendedEpochInfo, - dashcore::{hashes::Hash, ProTxHash}, + dashcore::{hashes::Hash as CoreHash, ProTxHash}, document::{serialization_traits::DocumentCborMethodsV0, Document}, identifier::Identifier, identity::IdentityPublicKey, @@ -14,12 +15,14 @@ use dpp::{ }, voting::votes::{resource_vote::ResourceVote, Vote}, }; +use drive::grovedb::Element; use drive_proof_verifier::types::{ - Contenders, ContestedResources, ElementFetchRequestItem, IdentityBalanceAndRevision, - MasternodeProtocolVote, PrefundedSpecializedBalance, ProposerBlockCounts, - RetrievedIntegerValue, TotalCreditsInPlatform, VotePollsGroupedByTimestamp, Voters, + Contenders, ContestedResources, CurrentQuorumsInfo, ElementFetchRequestItem, EvoNodeStatus, + IdentityBalanceAndRevision, IndexMap, MasternodeProtocolVote, PrefundedSpecializedBalance, + ProposerBlockCounts, RetrievedValues, TotalCreditsInPlatform, VotePollsGroupedByTimestamp, + Voters, }; -use std::collections::BTreeMap; +use std::{collections::BTreeMap, hash::Hash}; static BINCODE_CONFIG: bincode::config::Configuration = bincode::config::standard(); @@ -112,6 +115,29 @@ impl MockResponse for BTreeMap { } } +impl MockResponse for IndexMap { + fn mock_deserialize(sdk: &MockDashPlatformSdk, buf: &[u8]) -> Self + where + Self: Sized, + { + let (data, _): (IndexMap, Vec>, _) = + bincode::serde::decode_from_slice(buf, BINCODE_CONFIG).expect("decode IndexMap"); + + data.into_iter() + .map(|(k, v)| (K::mock_deserialize(sdk, &k), V::mock_deserialize(sdk, &v))) + .collect() + } + + fn mock_serialize(&self, sdk: &MockDashPlatformSdk) -> Vec { + let data: IndexMap, Vec> = self + .iter() + .map(|(k, v)| (k.mock_serialize(sdk), v.mock_serialize(sdk))) + .collect(); + + bincode::serde::encode_to_vec(data, BINCODE_CONFIG).expect("encode IndexMap") + } +} + /// Serialize and deserialize the object for mocking using bincode. /// /// Use this macro when the object implements platform serialization. @@ -164,6 +190,29 @@ impl MockResponse for Document { } } +impl MockResponse for Element { + fn mock_serialize(&self, _sdk: &MockDashPlatformSdk) -> Vec { + // Create a bincode configuration + let config = standard(); + + // Serialize using the specified configuration + bincode::encode_to_vec(self, config).expect("Failed to serialize Element") + } + + fn mock_deserialize(_sdk: &MockDashPlatformSdk, buf: &[u8]) -> Self + where + Self: Sized, + { + // Create a bincode configuration + let config = standard(); + + // Deserialize using the specified configuration + bincode::decode_from_slice(buf, config) + .expect("Failed to deserialize Element") + .0 + } +} + impl MockResponse for drive_proof_verifier::types::IdentityNonceFetcher { fn mock_serialize(&self, _sdk: &MockDashPlatformSdk) -> Vec { (self.0).to_be_bytes().to_vec() @@ -206,7 +255,7 @@ impl MockResponse for ProTxHash { { let data = platform_versioned_decode_from_slice(buf, BINCODE_CONFIG, sdk.version()) .expect("decode ProTxHash"); - ProTxHash::from_raw_hash(Hash::from_byte_array(data)) + ProTxHash::from_raw_hash(CoreHash::from_byte_array(data)) } } @@ -219,7 +268,7 @@ impl MockResponse for ProposerBlockCounts { where Self: Sized, { - let data = RetrievedIntegerValue::::mock_deserialize(sdk, buf); + let data = RetrievedValues::::mock_deserialize(sdk, buf); ProposerBlockCounts(data) } } @@ -243,3 +292,5 @@ impl_mock_response!(VotePollsGroupedByTimestamp); impl_mock_response!(PrefundedSpecializedBalance); impl_mock_response!(TotalCreditsInPlatform); impl_mock_response!(ElementFetchRequestItem); +impl_mock_response!(EvoNodeStatus); +impl_mock_response!(CurrentQuorumsInfo); diff --git a/packages/rs-sdk/src/mock/sdk.rs b/packages/rs-sdk/src/mock/sdk.rs index 0f37c7dd36..c2a180bcda 100644 --- a/packages/rs-sdk/src/mock/sdk.rs +++ b/packages/rs-sdk/src/mock/sdk.rs @@ -1,8 +1,13 @@ //! Mocking mechanisms for Dash Platform SDK. //! //! See [MockDashPlatformSdk] for more details. +use super::MockResponse; use crate::{ - platform::{types::identity::IdentityRequest, DocumentQuery, Fetch, FetchMany, Query}, + platform::{ + types::{evonode::EvoNode, identity::IdentityRequest}, + DocumentQuery, Fetch, FetchMany, Query, + }, + sync::block_on, Error, Sdk, }; use arc_swap::ArcSwapOption; @@ -18,12 +23,10 @@ use rs_dapi_client::mock::MockError; use rs_dapi_client::{ mock::{Key, MockDapiClient}, transport::TransportRequest, - DapiClient, DumpData, + DapiClient, DumpData, ExecutionResponse, }; use std::{collections::BTreeMap, path::PathBuf, sync::Arc}; -use tokio::sync::Mutex; - -use super::MockResponse; +use tokio::sync::{Mutex, OwnedMutexGuard}; /// Mechanisms to mock Dash Platform SDK. /// @@ -79,6 +82,17 @@ impl MockDashPlatformSdk { self.platform_version } + /// Load all expectations from files in a directory asynchronously. + /// + /// See [MockDashPlatformSdk::load_expectations_sync()] for more details. + #[deprecated(since = "1.4.0", note = "use load_expectations_sync")] + pub async fn load_expectations + Send + 'static>( + &mut self, + dir: P, + ) -> Result<&mut Self, Error> { + self.load_expectations_sync(dir) + } + /// Load all expectations from files in a directory. /// /// @@ -86,7 +100,7 @@ impl MockDashPlatformSdk { /// This function can be used to load expectations after the Sdk is created, or use alternative location. /// Expectation files must be prefixed with [DapiClient::DUMP_FILE_PREFIX] and /// have `.json` extension. - pub async fn load_expectations>( + pub fn load_expectations_sync>( &mut self, dir: P, ) -> Result<&mut Self, Error> { @@ -111,99 +125,83 @@ impl MockDashPlatformSdk { .map(|f| f.path()) .collect(); + let mut dapi = block_on(self.dapi.clone().lock_owned())?; + for filename in &files { let basename = filename.file_name().unwrap().to_str().unwrap(); let request_type = basename.split('_').nth(1).unwrap_or_default(); match request_type { - "DocumentQuery" => self.load_expectation::(filename).await?, + "DocumentQuery" => load_expectation::(&mut dapi, filename)?, "GetEpochsInfoRequest" => { - self.load_expectation::(filename) - .await? + load_expectation::(&mut dapi, filename)? } "GetDataContractRequest" => { - self.load_expectation::(filename) - .await? + load_expectation::(&mut dapi, filename)? } "GetDataContractsRequest" => { - self.load_expectation::(filename) - .await? + load_expectation::(&mut dapi, filename)? } "GetDataContractHistoryRequest" => { - self.load_expectation::(filename) - .await? + load_expectation::(&mut dapi, filename)? } - "IdentityRequest" => self.load_expectation::(filename).await?, + "IdentityRequest" => load_expectation::(&mut dapi, filename)?, "GetIdentityRequest" => { - self.load_expectation::(filename) - .await? + load_expectation::(&mut dapi, filename)? } "GetIdentityBalanceRequest" => { - self.load_expectation::(filename) - .await? + load_expectation::(&mut dapi, filename)? } "GetIdentityContractNonceRequest" => { - self.load_expectation::(filename) - .await? - } - "GetIdentityBalanceAndRevisionRequest" => { - self.load_expectation::(filename) - .await? + load_expectation::(&mut dapi, filename)? } + "GetIdentityBalanceAndRevisionRequest" => load_expectation::< + proto::GetIdentityBalanceAndRevisionRequest, + >(&mut dapi, filename)?, "GetIdentityKeysRequest" => { - self.load_expectation::(filename) - .await? - } - "GetProtocolVersionUpgradeStateRequest" => { - self.load_expectation::(filename) - .await? + load_expectation::(&mut dapi, filename)? } + "GetProtocolVersionUpgradeStateRequest" => load_expectation::< + proto::GetProtocolVersionUpgradeStateRequest, + >(&mut dapi, filename)?, "GetProtocolVersionUpgradeVoteStatusRequest" => { - self.load_expectation::( - filename, - ) - .await? + load_expectation::( + &mut dapi, filename, + )? } "GetContestedResourcesRequest" => { - self.load_expectation::(filename) - .await? - } - "GetContestedResourceVoteStateRequest" => { - self.load_expectation::(filename) - .await? + load_expectation::(&mut dapi, filename)? } + "GetContestedResourceVoteStateRequest" => load_expectation::< + proto::GetContestedResourceVoteStateRequest, + >(&mut dapi, filename)?, "GetContestedResourceVotersForIdentityRequest" => { - self.load_expectation::( - filename, - ) - .await? + load_expectation::( + &mut dapi, filename, + )? } "GetContestedResourceIdentityVotesRequest" => { - self.load_expectation::( - filename, - ) - .await? + load_expectation::( + &mut dapi, filename, + )? } "GetVotePollsByEndDateRequest" => { - self.load_expectation::(filename) - .await? - } - "GetPrefundedSpecializedBalanceRequest" => { - self.load_expectation::(filename) - .await? + load_expectation::(&mut dapi, filename)? } + "GetPrefundedSpecializedBalanceRequest" => load_expectation::< + proto::GetPrefundedSpecializedBalanceRequest, + >(&mut dapi, filename)?, "GetPathElementsRequest" => { - self.load_expectation::(filename) - .await? - } - "GetTotalCreditsInPlatformRequest" => { - self.load_expectation::(filename) - .await? + load_expectation::(&mut dapi, filename)? } + "GetTotalCreditsInPlatformRequest" => load_expectation::< + proto::GetTotalCreditsInPlatformRequest, + >(&mut dapi, filename)?, + "EvoNode" => load_expectation::(&mut dapi, filename)?, _ => { return Err(Error::Config(format!( - "unknown request type {} in {}", + "unknown request type {} in {}, missing match arm in load_expectations?", request_type, filename.display() ))) @@ -214,21 +212,6 @@ impl MockDashPlatformSdk { Ok(self) } - async fn load_expectation(&mut self, path: &PathBuf) -> Result<(), Error> { - let data = DumpData::::load(path) - .map_err(|e| { - Error::Config(format!( - "cannot load mock expectations from {}: {}", - path.display(), - e - )) - })? - .deserialize(); - - self.dapi.lock().await.expect(&data.0, &data.1)?; - Ok(()) - } - /// Expect a [Fetch] request and return provided object. /// /// This method is used to define mock expectations for [Fetch] requests. @@ -300,7 +283,7 @@ impl MockDashPlatformSdk { /// ## Generic Parameters /// /// - `O`: Type of the object that will be returned in response to the query. - /// Must implement [FetchMany]. `Vec` must implement [MockResponse]. + /// Must implement [FetchMany]. `Vec` must implement [MockResponse]. /// - `Q`: Type of the query that will be sent to Platform. Must implement [Query] and [Mockable]. /// /// ## Arguments @@ -326,20 +309,23 @@ impl MockDashPlatformSdk { K: Ord, O: FetchMany, Q: Query<>::Request>, - R: FromIterator<(K, Option)> + MockResponse + Send + Default, + R, >( &mut self, query: Q, objects: Option, ) -> Result<&mut Self, Error> where - R: MockResponse, - <>::Request as TransportRequest>::Response: Default, - R: FromProof< + R: FromIterator<(K, Option)> + + MockResponse + + FromProof< >::Request, Request = >::Request, Response = <>::Request as TransportRequest>::Response, - > + Sync, + > + Sync + + Send + + Default, + <>::Request as TransportRequest>::Response: Default, { let grpc_request = query.query(self.prove()).expect("query must be correct"); self.expect(grpc_request, objects).await?; @@ -376,7 +362,14 @@ impl MockDashPlatformSdk { // This expectation will work for execute let mut dapi_guard = self.dapi.lock().await; // We don't really care about the response, as it will be mocked by from_proof, so we provide default() - dapi_guard.expect(&grpc_request, &Ok(Default::default()))?; + dapi_guard.expect( + &grpc_request, + &Ok(ExecutionResponse { + inner: Default::default(), + retries: 0, + address: "http://127.0.0.1".parse().expect("failed to parse address"), + }), + )?; Ok(()) } @@ -427,3 +420,25 @@ impl MockDashPlatformSdk { } } } + +/// Load expectation from file and save it to `dapi_guard` mock Dapi client. +/// +/// This function is used to load expectations from files in a directory. +/// It is implemented without reference to the `MockDashPlatformSdk` object +/// to make it easier to use in async context. +fn load_expectation( + dapi_guard: &mut OwnedMutexGuard, + path: &PathBuf, +) -> Result<(), Error> { + let data = DumpData::::load(path) + .map_err(|e| { + Error::Config(format!( + "cannot load mock expectations from {}: {}", + path.display(), + e + )) + })? + .deserialize(); + dapi_guard.expect(&data.0, &data.1)?; + Ok(()) +} diff --git a/packages/rs-sdk/src/platform.rs b/packages/rs-sdk/src/platform.rs index 4766201620..a4c0fb83f4 100644 --- a/packages/rs-sdk/src/platform.rs +++ b/packages/rs-sdk/src/platform.rs @@ -11,6 +11,7 @@ mod document_query; mod fetch; pub mod fetch_current_no_parameters; mod fetch_many; +mod fetch_unproved; mod identities_contract_keys_query; mod query; pub mod transition; @@ -31,5 +32,6 @@ pub use { document_query::DocumentQuery, fetch::Fetch, fetch_many::FetchMany, + fetch_unproved::FetchUnproved, query::{LimitQuery, Query, QueryStartInfo, DEFAULT_EPOCH_QUERY_LIMIT}, }; diff --git a/packages/rs-sdk/src/platform/block_info_from_metadata.rs b/packages/rs-sdk/src/platform/block_info_from_metadata.rs index 713e1e176d..5e96e13655 100644 --- a/packages/rs-sdk/src/platform/block_info_from_metadata.rs +++ b/packages/rs-sdk/src/platform/block_info_from_metadata.rs @@ -12,8 +12,8 @@ use drive::error::proof::ProofError; /// /// # Parameters /// - `response_metadata`: A reference to `ResponseMetadata` obtained from a platform response. -/// This metadata includes various block-related information such as time in milliseconds, -/// height, core chain locked height, and epoch. +/// This metadata includes various block-related information such as time in milliseconds, +/// height, core chain locked height, and epoch. /// /// # Returns /// If successful, returns `Ok(BlockInfo)` where `BlockInfo` contains: diff --git a/packages/rs-sdk/src/platform/delegate.rs b/packages/rs-sdk/src/platform/delegate.rs index 9b77b751e6..63f250e59e 100644 --- a/packages/rs-sdk/src/platform/delegate.rs +++ b/packages/rs-sdk/src/platform/delegate.rs @@ -43,11 +43,11 @@ macro_rules! delegate_transport_request_variant { self, client: &'c mut Self::Client, settings: &$crate::platform::dapi::transport::AppliedRequestSettings, - ) -> $crate::platform::dapi::transport::BoxFuture<'c, Result::Error>> { + ) -> $crate::platform::dapi::transport::BoxFuture<'c, Result> { use futures::FutureExt; use $request::*; - let settings =settings.clone(); + let settings = settings.clone(); // We need to build new async box because we have to map response to the $response type match self {$( diff --git a/packages/rs-sdk/src/platform/document_query.rs b/packages/rs-sdk/src/platform/document_query.rs index 9c61f94376..1da50d73f8 100644 --- a/packages/rs-sdk/src/platform/document_query.rs +++ b/packages/rs-sdk/src/platform/document_query.rs @@ -19,12 +19,12 @@ use dpp::{ document::Document, platform_value::{platform_value, Value}, prelude::{DataContract, Identifier}, - ProtocolError, + InvalidVectorSizeError, ProtocolError, }; use drive::query::{DriveDocumentQuery, InternalClauses, OrderClause, WhereClause, WhereOperator}; use drive_proof_verifier::{types::Documents, ContextProvider, FromProof}; use rs_dapi_client::transport::{ - AppliedRequestSettings, BoxFuture, TransportClient, TransportRequest, + AppliedRequestSettings, BoxFuture, TransportError, TransportRequest, }; use super::fetch::Fetch; @@ -37,7 +37,7 @@ use super::fetch::Fetch; /// required to correctly verify proofs returned by the Dash Platform. /// /// Conversions are implemented between this type, [GetDocumentsRequest] and [DriveDocumentQuery] using [TryFrom] trait. -#[derive(Debug, Clone, dapi_grpc_macros::Mockable)] +#[derive(Debug, Clone, PartialEq, dapi_grpc_macros::Mockable)] #[cfg_attr(feature = "mocks", derive(serde::Serialize, serde::Deserialize))] pub struct DocumentQuery { /// Data contract ID @@ -148,7 +148,7 @@ impl TransportRequest for DocumentQuery { self, client: &'c mut Self::Client, settings: &AppliedRequestSettings, - ) -> BoxFuture<'c, Result::Error>> { + ) -> BoxFuture<'c, Result> { let request: GetDocumentsRequest = self .try_into() .expect("DocumentQuery should always be valid"); @@ -326,6 +326,26 @@ impl<'a> TryFrom<&'a DocumentQuery> for DriveDocumentQuery<'a> { } else { None }; + + let (start_at, start_at_included) = match request.start.as_ref() { + None => (None, false), + Some(Start::StartAt(at)) => ( + Some(at.clone().try_into().map_err(|_| { + ProtocolError::InvalidVectorSizeError(InvalidVectorSizeError::new(32, at.len())) + })?), + true, + ), + Some(Start::StartAfter(after)) => ( + Some(after.clone().try_into().map_err(|_| { + ProtocolError::InvalidVectorSizeError(InvalidVectorSizeError::new( + 32, + after.len(), + )) + })?), + true, + ), + }; + let query = Self { contract: &request.data_contract, document_type, @@ -338,8 +358,8 @@ impl<'a> TryFrom<&'a DocumentQuery> for DriveDocumentQuery<'a> { .into_iter() .map(|v| (v.field.clone(), v)) .collect(), - start_at: None, - start_at_included: false, + start_at, + start_at_included, block_time_ms: None, }; diff --git a/packages/rs-sdk/src/platform/fetch.rs b/packages/rs-sdk/src/platform/fetch.rs index 109140bdb7..80564fbdf2 100644 --- a/packages/rs-sdk/src/platform/fetch.rs +++ b/packages/rs-sdk/src/platform/fetch.rs @@ -9,6 +9,7 @@ //! traits. The associated [Fetch::Request]` type needs to implement [TransportRequest]. use crate::mock::MockResponse; +use crate::sync::retry; use crate::{error::Error, platform::query::Query, Sdk}; use dapi_grpc::platform::v0::{self as platform_proto, Proof, ResponseMetadata}; use dpp::voting::votes::Vote; @@ -18,6 +19,7 @@ use dpp::{ }; use drive_proof_verifier::FromProof; use rs_dapi_client::{transport::TransportRequest, DapiRequest, RequestSettings}; +use rs_dapi_client::{ExecutionError, ExecutionResponse, InnerInto, IntoInner}; use std::fmt::Debug; use super::types::identity::IdentityRequest; @@ -119,23 +121,9 @@ where query: Q, settings: Option, ) -> Result<(Option, ResponseMetadata), Error> { - let request = query.query(sdk.prove())?; - - let response = request - .clone() - .execute(sdk, settings.unwrap_or_default()) - .await?; - - let object_type = std::any::type_name::().to_string(); - tracing::trace!(request = ?request, response = ?response, object_type, "fetched object from platform"); - - let (object, response_metadata): (Option, ResponseMetadata) = - sdk.parse_proof_with_metadata(request, response).await?; - - match object { - Some(item) => Ok((item.into(), response_metadata)), - None => Ok((None, response_metadata)), - } + Self::fetch_with_metadata_and_proof(sdk, query, settings) + .await + .map(|(object, metadata, _)| (object, metadata)) } /// Fetch single object from Platform with metadata and underlying proof. @@ -167,24 +155,47 @@ where query: Q, settings: Option, ) -> Result<(Option, ResponseMetadata, Proof), Error> { - let request = query.query(sdk.prove())?; + let request: &::Request = &query.query(sdk.prove())?; + + let fut = |settings: RequestSettings| async move { + let ExecutionResponse { + address, + retries, + inner: response, + } = request + .clone() + .execute(sdk, settings) + .await + .map_err(|execution_error| execution_error.inner_into())?; + + let object_type = std::any::type_name::().to_string(); + tracing::trace!(request = ?request, response = ?response, ?address, retries, object_type, "fetched object from platform"); - let response = request - .clone() - .execute(sdk, settings.unwrap_or_default()) - .await?; + let (object, response_metadata, proof): (Option, ResponseMetadata, Proof) = sdk + .parse_proof_with_metadata_and_proof(request.clone(), response) + .await + .map_err(|e| ExecutionError { + inner: e, + address: Some(address.clone()), + retries, + })?; - let object_type = std::any::type_name::().to_string(); - tracing::trace!(request = ?request, response = ?response, object_type, "fetched object from platform"); + match object { + Some(item) => Ok((item.into(), response_metadata, proof)), + None => Ok((None, response_metadata, proof)), + } + .map(|x| ExecutionResponse { + inner: x, + address, + retries, + }) + }; - let (object, response_metadata, proof): (Option, ResponseMetadata, Proof) = sdk - .parse_proof_with_metadata_and_proof(request, response) - .await?; + let settings = sdk + .dapi_client_settings + .override_by(settings.unwrap_or_default()); - match object { - Some(item) => Ok((item.into(), response_metadata, proof)), - None => Ok((None, response_metadata, proof)), - } + retry(settings, fut).await.into_inner() } /// Fetch single object from Platform. diff --git a/packages/rs-sdk/src/platform/fetch_many.rs b/packages/rs-sdk/src/platform/fetch_many.rs index feba82fd65..4653835557 100644 --- a/packages/rs-sdk/src/platform/fetch_many.rs +++ b/packages/rs-sdk/src/platform/fetch_many.rs @@ -4,19 +4,21 @@ //! //! ## Traits //! - `[FetchMany]`: An async trait that fetches multiple items of a specific type from Platform. + use super::LimitQuery; use crate::{ error::Error, mock::MockResponse, platform::{document_query::DocumentQuery, query::Query}, + sync::retry, Sdk, }; use dapi_grpc::platform::v0::{ GetContestedResourceIdentityVotesRequest, GetContestedResourceVoteStateRequest, GetContestedResourceVotersForIdentityRequest, GetContestedResourcesRequest, - GetDataContractsRequest, GetDocumentsResponse, GetEpochsInfoRequest, - GetEvonodesProposedEpochBlocksByIdsRequest, GetEvonodesProposedEpochBlocksByRangeRequest, - GetIdentitiesBalancesRequest, GetIdentityKeysRequest, GetProtocolVersionUpgradeStateRequest, + GetDataContractsRequest, GetEpochsInfoRequest, GetEvonodesProposedEpochBlocksByIdsRequest, + GetEvonodesProposedEpochBlocksByRangeRequest, GetIdentitiesBalancesRequest, + GetIdentityKeysRequest, GetPathElementsRequest, GetProtocolVersionUpgradeStateRequest, GetProtocolVersionUpgradeVoteStatusRequest, GetVotePollsByEndDateRequest, }; use dashcore_rpc::dashcore::ProTxHash; @@ -30,15 +32,19 @@ use dpp::{ block::extended_epoch_info::ExtendedEpochInfo, voting::votes::resource_vote::ResourceVote, }; use dpp::{document::Document, voting::contender_structs::ContenderWithSerializedDocument}; +use drive::grovedb::query_result_type::Key; +use drive::grovedb::Element; use drive_proof_verifier::types::{ - Contenders, ContestedResource, ContestedResources, DataContracts, ExtendedEpochInfos, + Contenders, ContestedResource, ContestedResources, DataContracts, Elements, ExtendedEpochInfos, IdentityBalances, IdentityPublicKeys, MasternodeProtocolVote, MasternodeProtocolVotes, ProposerBlockCountById, ProposerBlockCountByRange, ProposerBlockCounts, ProtocolVersionUpgrades, ResourceVotesByIdentity, VotePollsGroupedByTimestamp, Voter, Voters, }; use drive_proof_verifier::{types::Documents, FromProof}; -use rs_dapi_client::{transport::TransportRequest, DapiRequest, RequestSettings}; -use std::collections::BTreeMap; +use rs_dapi_client::{ + transport::TransportRequest, DapiRequest, ExecutionError, ExecutionResponse, InnerInto, + IntoInner, RequestSettings, +}; /// Fetch multiple objects from Platform. /// @@ -139,22 +145,41 @@ where sdk: &Sdk, query: Q, ) -> Result { - let request = query.query(sdk.prove())?; + let request = &query.query(sdk.prove())?; + let closure = |settings: RequestSettings| async move { + let ExecutionResponse { + address, + retries, + inner: response, + } = request + .clone() + .execute(sdk, settings) + .await + .map_err(|e| e.inner_into())?; - let response = request - .clone() - .execute(sdk, RequestSettings::default()) - .await?; + let object_type = std::any::type_name::().to_string(); + tracing::trace!(request = ?request, response = ?response, ?address, retries, object_type, "fetched object from platform"); - let object_type = std::any::type_name::().to_string(); - tracing::trace!(request = ?request, response = ?response, object_type, "fetched object from platform"); + sdk.parse_proof::<>::Request, O>(request.clone(), response) + .await + .map(|o| ExecutionResponse { + inner: o, + retries, + address: address.clone(), + }) + .map_err(|e| ExecutionError { + inner: e, + retries, + address: Some(address), + }) + }; - let object: O = sdk - .parse_proof::<>::Request, O>(request, response) - .await? - .unwrap_or_default(); + let settings = sdk.dapi_client_settings; - Ok(object) + retry(settings, closure) + .await + .into_inner() + .map(|o| o.unwrap_or_default()) } /// Fetch multiple objects from Platform by their identifiers. @@ -183,7 +208,7 @@ where /// Fetch multiple objects from Platform with limit. /// - /// Fetches up to `limit` objects matching the `query`. + /// Fetches up to `limit` objects matching the `query`. /// See [FetchMany] and [FetchMany::fetch_many()] for more detailed documentation. /// /// ## Parameters @@ -227,21 +252,38 @@ impl FetchMany for Document { sdk: &Sdk, query: Q, ) -> Result { - let document_query: DocumentQuery = query.query(sdk.prove())?; + let document_query: &DocumentQuery = &query.query(sdk.prove())?; - let request = document_query.clone(); - let response: GetDocumentsResponse = - request.execute(sdk, RequestSettings::default()).await?; + retry(sdk.dapi_client_settings, |settings| async move { + let request = document_query.clone(); - tracing::trace!(request=?document_query, response=?response, "fetch multiple documents"); + let ExecutionResponse { + address, + retries, + inner: response, + } = request.execute(sdk, settings).await.map_err(|e| e.inner_into())?; - // let object: Option> = sdk - let documents: BTreeMap> = sdk - .parse_proof::(document_query, response) - .await? - .unwrap_or_default(); + tracing::trace!(request=?document_query, response=?response, ?address, retries, "fetch multiple documents"); - Ok(documents) + // let object: Option> = sdk + let documents = sdk + .parse_proof::(document_query.clone(), response) + .await + .map_err(|e| ExecutionError { + inner: e, + retries, + address: Some(address.clone()), + })? + .unwrap_or_default(); + + Ok(ExecutionResponse { + inner: documents, + retries, + address, + }) + }) + .await + .into_inner() } } @@ -415,3 +457,13 @@ impl FetchMany for VotePoll { impl FetchMany for drive_proof_verifier::types::IdentityBalance { type Request = GetIdentitiesBalancesRequest; } + +// +/// Fetch multiple elements. +/// +/// ## Supported query types +/// +/// * [KeysInPath] +impl FetchMany for Element { + type Request = GetPathElementsRequest; +} diff --git a/packages/rs-sdk/src/platform/fetch_unproved.rs b/packages/rs-sdk/src/platform/fetch_unproved.rs new file mode 100644 index 0000000000..ac3a682f81 --- /dev/null +++ b/packages/rs-sdk/src/platform/fetch_unproved.rs @@ -0,0 +1,145 @@ +use super::{types::evonode::EvoNode, Query}; +use crate::mock::MockResponse; +use crate::Sdk; +use crate::{error::Error, sync::retry}; +use dapi_grpc::platform::v0::{ + self as platform_proto, GetStatusRequest, GetStatusResponse, ResponseMetadata, +}; +use dpp::{dashcore::Network, version::PlatformVersion}; +use drive_proof_verifier::types::EvoNodeStatus; +use drive_proof_verifier::unproved::FromUnproved; +use rs_dapi_client::{transport::TransportRequest, DapiRequest, RequestSettings}; +use rs_dapi_client::{ExecutionError, ExecutionResponse, InnerInto, IntoInner}; +use std::fmt::Debug; + +#[async_trait::async_trait] +pub trait FetchUnproved +where + Self: Sized + Debug + MockResponse, +{ + /// Type of request used to fetch data from Platform. + type Request: TransportRequest; + + /// Fetch unproved data from the Platform. + /// + /// ## Parameters + /// - `sdk`: An instance of [Sdk]. + /// - `query`: Query used to fetch data from the Platform. + /// + /// ## Returns + /// Returns: + /// * `Ok(Some(Self))` when object is found. + /// * `Ok(None)` when object is not found. + /// * [`Err(Error)`](Error) when an error occurs. + async fn fetch_unproved::Request>>( + sdk: &Sdk, + query: Q, + ) -> Result, Error> + where + Self: FromUnproved< + ::Request, + Request = ::Request, + Response = <::Request as TransportRequest>::Response, + >, + { + let (obj, _mtd) = + Self::fetch_unproved_with_settings(sdk, query, RequestSettings::default()).await?; + Ok(obj) + } + + /// Fetch unproved data from the Platform with custom settings. + /// + /// ## Parameters + /// - `sdk`: An instance of [Sdk]. + /// - `query`: Query used to fetch data from the Platform. + /// - `settings`: Request settings for the connection to Platform. + /// + /// ## Returns + /// Returns: + /// * `Ok(Some(Self))` when object is found. + /// * `Ok(None)` when object is not found. + /// * [`Err(Error)`](Error) when an error occurs. + async fn fetch_unproved_with_settings::Request>>( + sdk: &Sdk, + query: Q, + settings: RequestSettings, + ) -> Result<(Option, ResponseMetadata), Error> + where + Self: FromUnproved< + ::Request, + Request = ::Request, + Response = <::Request as TransportRequest>::Response, + >, + { + // Default implementation + let request: &::Request = &query.query(false)?; + let closure = move |local_settings: RequestSettings| async move { + // Execute the request using the Sdk instance + let ExecutionResponse { + inner: response, + address, + retries, + } = request + .clone() + .execute(sdk, local_settings) + .await + .map_err(|e| e.inner_into())?; + + // Parse the response into the appropriate type along with metadata + let (object, metadata): (Option, platform_proto::ResponseMetadata) = + Self::maybe_from_unproved_with_metadata( + request.clone(), + response, + sdk.network, + sdk.version(), + ) + .map_err(|e| ExecutionError { + inner: e.into(), + address: Some(address.clone()), + retries, + })?; + + Ok(ExecutionResponse { + inner: (object, metadata), + address, + retries, + }) + }; + + let settings = sdk.dapi_client_settings.override_by(settings); + retry(settings, closure).await.into_inner() + } +} + +impl FetchUnproved for drive_proof_verifier::types::CurrentQuorumsInfo { + type Request = platform_proto::GetCurrentQuorumsInfoRequest; +} + +impl FetchUnproved for EvoNodeStatus { + type Request = EvoNode; +} + +// We need to delegate FromUnproved for the impl FetchUnproved for EvonodeStatus. +#[async_trait::async_trait] +impl FromUnproved for EvoNodeStatus { + type Request = EvoNode; + type Response = GetStatusResponse; + + fn maybe_from_unproved_with_metadata, O: Into>( + request: I, + response: O, + network: Network, + platform_version: &PlatformVersion, + ) -> Result<(Option, ResponseMetadata), drive_proof_verifier::Error> + where + Self: Sized, + { + // delegate to the FromUnproved + >::maybe_from_unproved_with_metadata( + request.into(), + response, + network, + platform_version, + ) + } +} diff --git a/packages/rs-sdk/src/platform/identities_contract_keys_query.rs b/packages/rs-sdk/src/platform/identities_contract_keys_query.rs index 15570d23a7..e761cecce9 100644 --- a/packages/rs-sdk/src/platform/identities_contract_keys_query.rs +++ b/packages/rs-sdk/src/platform/identities_contract_keys_query.rs @@ -3,7 +3,7 @@ use dapi_grpc::platform::v0::get_identities_contract_keys_request::Version::V0; use dapi_grpc::platform::v0::GetIdentitiesContractKeysRequest; use dpp::identity::Purpose; use rs_dapi_client::transport::{ - AppliedRequestSettings, BoxFuture, TransportClient, TransportRequest, + AppliedRequestSettings, BoxFuture, TransportError, TransportRequest, }; use crate::platform::Identifier; @@ -81,7 +81,7 @@ impl TransportRequest for IdentitiesContractKeysQuery { self, client: &'c mut Self::Client, settings: &AppliedRequestSettings, - ) -> BoxFuture<'c, Result::Error>> { + ) -> BoxFuture<'c, Result> { let request: GetIdentitiesContractKeysRequest = self .try_into() .expect("IdentitiesContractKeysQuery should always be valid"); diff --git a/packages/rs-sdk/src/platform/query.rs b/packages/rs-sdk/src/platform/query.rs index e55f0e3e6a..a145d89058 100644 --- a/packages/rs-sdk/src/platform/query.rs +++ b/packages/rs-sdk/src/platform/query.rs @@ -2,26 +2,30 @@ //! //! [Query] trait is used to specify individual objects as well as search criteria for fetching multiple objects from Platform. use super::types::epoch::EpochQuery; +use super::types::evonode::EvoNode; use crate::{error::Error, platform::document_query::DocumentQuery}; use dapi_grpc::mock::Mockable; use dapi_grpc::platform::v0::get_contested_resource_identity_votes_request::GetContestedResourceIdentityVotesRequestV0; use dapi_grpc::platform::v0::get_contested_resource_voters_for_identity_request::GetContestedResourceVotersForIdentityRequestV0; use dapi_grpc::platform::v0::get_contested_resources_request::GetContestedResourcesRequestV0; +use dapi_grpc::platform::v0::get_current_quorums_info_request::GetCurrentQuorumsInfoRequestV0; use dapi_grpc::platform::v0::get_evonodes_proposed_epoch_blocks_by_range_request::GetEvonodesProposedEpochBlocksByRangeRequestV0; use dapi_grpc::platform::v0::get_path_elements_request::GetPathElementsRequestV0; +use dapi_grpc::platform::v0::get_status_request::GetStatusRequestV0; use dapi_grpc::platform::v0::get_total_credits_in_platform_request::GetTotalCreditsInPlatformRequestV0; use dapi_grpc::platform::v0::{ - self as proto, get_identity_keys_request, get_identity_keys_request::GetIdentityKeysRequestV0, - get_path_elements_request, get_total_credits_in_platform_request, AllKeys, - GetContestedResourceVoteStateRequest, GetContestedResourceVotersForIdentityRequest, - GetContestedResourcesRequest, GetEpochsInfoRequest, + self as proto, get_current_quorums_info_request, get_identity_keys_request, + get_identity_keys_request::GetIdentityKeysRequestV0, get_path_elements_request, + get_total_credits_in_platform_request, AllKeys, GetContestedResourceVoteStateRequest, + GetContestedResourceVotersForIdentityRequest, GetContestedResourcesRequest, + GetCurrentQuorumsInfoRequest, GetEpochsInfoRequest, GetEvonodesProposedEpochBlocksByRangeRequest, GetIdentityKeysRequest, GetPathElementsRequest, GetProtocolVersionUpgradeStateRequest, GetProtocolVersionUpgradeVoteStatusRequest, GetTotalCreditsInPlatformRequest, KeyRequestType, }; use dapi_grpc::platform::v0::{ - GetContestedResourceIdentityVotesRequest, GetPrefundedSpecializedBalanceRequest, - GetVotePollsByEndDateRequest, + get_status_request, GetContestedResourceIdentityVotesRequest, + GetPrefundedSpecializedBalanceRequest, GetStatusRequest, GetVotePollsByEndDateRequest, }; use dashcore_rpc::dashcore::{hashes::Hash, ProTxHash}; use dpp::version::PlatformVersionError; @@ -98,7 +102,7 @@ where { fn query(self, prove: bool) -> Result { if !prove { - unimplemented!("queries without proofs are not supported yet"); + tracing::warn!(request= ?self, "sending query without proof, ensure data is trusted"); } Ok(self) } @@ -619,6 +623,24 @@ impl Query for NoParamQuery { } } +impl Query for NoParamQuery { + fn query(self, prove: bool) -> Result { + if prove { + unimplemented!( + "query with proof are not supported yet for GetCurrentQuorumsInfoRequest" + ); + } + + let request: GetCurrentQuorumsInfoRequest = GetCurrentQuorumsInfoRequest { + version: Some(get_current_quorums_info_request::Version::V0( + GetCurrentQuorumsInfoRequestV0 {}, + )), + }; + + Ok(request) + } +} + impl Query for LimitQuery> { fn query(self, prove: bool) -> Result { if !prove { @@ -645,3 +667,15 @@ impl Query for LimitQuery for EvoNode { + fn query(self, _prove: bool) -> Result { + // ignore proof + + let request: GetStatusRequest = GetStatusRequest { + version: Some(get_status_request::Version::V0(GetStatusRequestV0 {})), + }; + + Ok(request) + } +} diff --git a/packages/rs-sdk/src/platform/transition.rs b/packages/rs-sdk/src/platform/transition.rs index 490bc40090..6bd51a3b2e 100644 --- a/packages/rs-sdk/src/platform/transition.rs +++ b/packages/rs-sdk/src/platform/transition.rs @@ -9,6 +9,7 @@ pub mod put_document; pub mod put_identity; pub mod put_settings; pub mod top_up_identity; +pub mod transfer; pub mod transfer_document; mod txid; pub mod update_price_of_document; diff --git a/packages/rs-sdk/src/platform/transition/broadcast.rs b/packages/rs-sdk/src/platform/transition/broadcast.rs index 5c050ce8cf..7e4c6488c1 100644 --- a/packages/rs-sdk/src/platform/transition/broadcast.rs +++ b/packages/rs-sdk/src/platform/transition/broadcast.rs @@ -7,7 +7,7 @@ use dpp::state_transition::StateTransition; use drive::drive::Drive; use drive_proof_verifier::error::ContextProviderError; use drive_proof_verifier::DataContractProvider; -use rs_dapi_client::{DapiRequest, RequestSettings}; +use rs_dapi_client::{DapiRequest, IntoInner, RequestSettings}; #[async_trait::async_trait] pub trait BroadcastStateTransition { @@ -24,7 +24,10 @@ impl BroadcastStateTransition for StateTransition { async fn broadcast(&self, sdk: &Sdk) -> Result<(), Error> { let request = self.broadcast_request_for_state_transition()?; - request.execute(sdk, RequestSettings::default()).await?; + request + .execute(sdk, RequestSettings::default()) + .await // TODO: We need better way to handle execution errors + .into_inner()?; // response is empty for a broadcast, result comes from the stream wait for state transition result @@ -37,15 +40,19 @@ impl BroadcastStateTransition for StateTransition { _time_out_ms: Option, ) -> Result { let request = self.broadcast_request_for_state_transition()?; - + // TODO: Implement retry logic request .clone() .execute(sdk, RequestSettings::default()) - .await?; + .await + .into_inner()?; let request = self.wait_for_state_transition_result_request()?; - let response = request.execute(sdk, RequestSettings::default()).await?; + let response = request + .execute(sdk, RequestSettings::default()) + .await + .into_inner()?; let block_info = block_info_from_metadata(response.metadata()?)?; let proof = response.proof_owned()?; diff --git a/packages/rs-sdk/src/platform/transition/purchase_document.rs b/packages/rs-sdk/src/platform/transition/purchase_document.rs index aa58b63b32..1ede5c247e 100644 --- a/packages/rs-sdk/src/platform/transition/purchase_document.rs +++ b/packages/rs-sdk/src/platform/transition/purchase_document.rs @@ -19,7 +19,7 @@ use dpp::state_transition::documents_batch_transition::DocumentsBatchTransition; use dpp::state_transition::proof_result::StateTransitionProofResult; use dpp::state_transition::StateTransition; use drive::drive::Drive; -use rs_dapi_client::{DapiRequest, RequestSettings}; +use rs_dapi_client::{DapiRequest, IntoInner, RequestSettings}; #[async_trait::async_trait] /// A trait for purchasing a document on Platform @@ -101,7 +101,8 @@ impl PurchaseDocument for Document { request .clone() .execute(sdk, settings.request_settings) - .await?; + .await // TODO: We need better way to handle execution errors + .into_inner()?; // response is empty for a broadcast, result comes from the stream wait for state transition result @@ -115,8 +116,11 @@ impl PurchaseDocument for Document { data_contract: Arc, ) -> Result { let request = state_transition.wait_for_state_transition_result_request()?; - - let response = request.execute(sdk, RequestSettings::default()).await?; + // TODO: Implement retry logic + let response = request + .execute(sdk, RequestSettings::default()) + .await + .into_inner()?; let block_info = block_info_from_metadata(response.metadata()?)?; diff --git a/packages/rs-sdk/src/platform/transition/put_contract.rs b/packages/rs-sdk/src/platform/transition/put_contract.rs index fb7e55b5bc..a8f07b0b31 100644 --- a/packages/rs-sdk/src/platform/transition/put_contract.rs +++ b/packages/rs-sdk/src/platform/transition/put_contract.rs @@ -18,7 +18,7 @@ use dpp::state_transition::StateTransition; use drive::drive::Drive; use drive_proof_verifier::error::ContextProviderError; use drive_proof_verifier::DataContractProvider; -use rs_dapi_client::{DapiRequest, RequestSettings}; +use rs_dapi_client::{DapiRequest, IntoInner, RequestSettings}; #[async_trait::async_trait] /// A trait for putting a contract to platform @@ -86,7 +86,8 @@ impl PutContract for DataContract { request .clone() .execute(sdk, settings.unwrap_or_default().request_settings) - .await?; + .await // TODO: We need better way to handle execution errors + .into_inner()?; // response is empty for a broadcast, result comes from the stream wait for state transition result @@ -100,7 +101,10 @@ impl PutContract for DataContract { ) -> Result { let request = state_transition.wait_for_state_transition_result_request()?; - let response = request.execute(sdk, RequestSettings::default()).await?; + let response = request + .execute(sdk, RequestSettings::default()) + .await + .into_inner()?; let block_info = block_info_from_metadata(response.metadata()?)?; diff --git a/packages/rs-sdk/src/platform/transition/put_document.rs b/packages/rs-sdk/src/platform/transition/put_document.rs index 7c9fecac3a..806e640d93 100644 --- a/packages/rs-sdk/src/platform/transition/put_document.rs +++ b/packages/rs-sdk/src/platform/transition/put_document.rs @@ -17,7 +17,7 @@ use dpp::state_transition::documents_batch_transition::DocumentsBatchTransition; use dpp::state_transition::proof_result::StateTransitionProofResult; use dpp::state_transition::StateTransition; use drive::drive::Drive; -use rs_dapi_client::{DapiRequest, RequestSettings}; +use rs_dapi_client::{DapiRequest, IntoInner, RequestSettings}; #[async_trait::async_trait] /// A trait for putting a document to platform @@ -95,7 +95,8 @@ impl PutDocument for Document { request .clone() .execute(sdk, settings.request_settings) - .await?; + .await // TODO: We need better way to handle execution errors + .into_inner()?; // response is empty for a broadcast, result comes from the stream wait for state transition result @@ -109,8 +110,11 @@ impl PutDocument for Document { data_contract: Arc, ) -> Result { let request = state_transition.wait_for_state_transition_result_request()?; - - let response = request.execute(sdk, RequestSettings::default()).await?; + // TODO: Implement retry logic + let response = request + .execute(sdk, RequestSettings::default()) + .await + .into_inner()?; let block_info = block_info_from_metadata(response.metadata()?)?; diff --git a/packages/rs-sdk/src/platform/transition/put_identity.rs b/packages/rs-sdk/src/platform/transition/put_identity.rs index 59422aa6b2..30276a06a0 100644 --- a/packages/rs-sdk/src/platform/transition/put_identity.rs +++ b/packages/rs-sdk/src/platform/transition/put_identity.rs @@ -14,7 +14,8 @@ use drive_proof_verifier::DataContractProvider; use crate::platform::block_info_from_metadata::block_info_from_metadata; use dpp::state_transition::proof_result::StateTransitionProofResult; use drive::drive::Drive; -use rs_dapi_client::{DapiClientError, DapiRequest, RequestSettings}; +use rs_dapi_client::transport::TransportError; +use rs_dapi_client::{DapiClientError, DapiRequest, IntoInner, RequestSettings}; #[async_trait::async_trait] /// A trait for putting an identity to platform @@ -56,7 +57,8 @@ impl PutIdentity for Identity { request .clone() .execute(sdk, RequestSettings::default()) - .await?; + .await // TODO: We need better way to handle execution errors + .into_inner()?; // response is empty for a broadcast, result comes from the stream wait for state transition result @@ -81,12 +83,15 @@ impl PutIdentity for Identity { let response_result = request .clone() .execute(sdk, RequestSettings::default()) - .await; + .await + .into_inner(); match response_result { Ok(_) => {} //todo make this more reliable - Err(DapiClientError::Transport(te, _)) if te.code() == Code::AlreadyExists => { + Err(DapiClientError::Transport(TransportError::Grpc(te))) + if te.code() == Code::AlreadyExists => + { tracing::debug!( ?identity_id, "attempt to create identity that already exists" @@ -100,8 +105,12 @@ impl PutIdentity for Identity { } let request = state_transition.wait_for_state_transition_result_request()?; + // TODO: Implement retry logic - let response = request.execute(sdk, RequestSettings::default()).await?; + let response = request + .execute(sdk, RequestSettings::default()) + .await + .into_inner()?; let block_info = block_info_from_metadata(response.metadata()?)?; let proof = response.proof_owned()?; diff --git a/packages/rs-sdk/src/platform/transition/top_up_identity.rs b/packages/rs-sdk/src/platform/transition/top_up_identity.rs index 48145234f4..c43d8a9f19 100644 --- a/packages/rs-sdk/src/platform/transition/top_up_identity.rs +++ b/packages/rs-sdk/src/platform/transition/top_up_identity.rs @@ -11,7 +11,7 @@ use dpp::state_transition::proof_result::StateTransitionProofResult; use drive::drive::Drive; use drive_proof_verifier::error::ContextProviderError; use drive_proof_verifier::DataContractProvider; -use rs_dapi_client::{DapiRequest, RequestSettings}; +use rs_dapi_client::{DapiRequest, IntoInner, RequestSettings}; #[async_trait::async_trait] pub trait TopUpIdentity { @@ -47,11 +47,15 @@ impl TopUpIdentity for Identity { request .clone() .execute(sdk, RequestSettings::default()) - .await?; + .await // TODO: We need better way to handle execution errors + .into_inner()?; let request = state_transition.wait_for_state_transition_result_request()?; - - let response = request.execute(sdk, RequestSettings::default()).await?; + // TODO: Implement retry logic in wait for state transition result + let response = request + .execute(sdk, RequestSettings::default()) + .await + .into_inner()?; let block_info = block_info_from_metadata(response.metadata()?)?; diff --git a/packages/rs-sdk/src/platform/transition/transfer.rs b/packages/rs-sdk/src/platform/transition/transfer.rs new file mode 100644 index 0000000000..bf330a1024 --- /dev/null +++ b/packages/rs-sdk/src/platform/transition/transfer.rs @@ -0,0 +1,67 @@ +use dpp::identifier::Identifier; +use dpp::identity::accessors::IdentityGettersV0; + +use crate::platform::transition::broadcast::BroadcastStateTransition; +use crate::platform::transition::put_settings::PutSettings; +use crate::{Error, Sdk}; +use dpp::identity::signer::Signer; +use dpp::identity::{Identity, IdentityPublicKey}; +use dpp::state_transition::identity_credit_transfer_transition::methods::IdentityCreditTransferTransitionMethodsV0; +use dpp::state_transition::identity_credit_transfer_transition::IdentityCreditTransferTransition; +use dpp::state_transition::proof_result::StateTransitionProofResult; + +#[async_trait::async_trait] +pub trait TransferToIdentity { + /// Function to transfer credits from an identity to another identity. Returns the final + /// identity balance. + /// + /// If signing_transfer_key_to_use is not set, we will try to use one in the signer that is + /// available for the transfer. + async fn transfer_credits( + &self, + sdk: &Sdk, + to_identity_id: Identifier, + amount: u64, + signing_transfer_key_to_use: Option<&IdentityPublicKey>, + signer: S, + settings: Option, + ) -> Result; +} + +#[async_trait::async_trait] +impl TransferToIdentity for Identity { + async fn transfer_credits( + &self, + sdk: &Sdk, + to_identity_id: Identifier, + amount: u64, + signing_transfer_key_to_use: Option<&IdentityPublicKey>, + signer: S, + settings: Option, + ) -> Result { + let new_identity_nonce = sdk.get_identity_nonce(self.id(), true, settings).await?; + let user_fee_increase = settings.and_then(|settings| settings.user_fee_increase); + let state_transition = IdentityCreditTransferTransition::try_from_identity( + self, + to_identity_id, + amount, + user_fee_increase.unwrap_or_default(), + signer, + signing_transfer_key_to_use, + new_identity_nonce, + sdk.version(), + None, + )?; + + let result = state_transition.broadcast_and_wait(sdk, None).await?; + + match result { + StateTransitionProofResult::VerifiedPartialIdentity(identity) => { + identity.balance.ok_or(Error::DapiClientError( + "expected an identity balance after transfer".to_string(), + )) + } + _ => Err(Error::DapiClientError("proved a non identity".to_string())), + } + } +} diff --git a/packages/rs-sdk/src/platform/transition/transfer_document.rs b/packages/rs-sdk/src/platform/transition/transfer_document.rs index 140a6e3166..a64c76cb95 100644 --- a/packages/rs-sdk/src/platform/transition/transfer_document.rs +++ b/packages/rs-sdk/src/platform/transition/transfer_document.rs @@ -18,7 +18,7 @@ use dpp::state_transition::documents_batch_transition::DocumentsBatchTransition; use dpp::state_transition::proof_result::StateTransitionProofResult; use dpp::state_transition::StateTransition; use drive::drive::Drive; -use rs_dapi_client::{DapiRequest, RequestSettings}; +use rs_dapi_client::{DapiRequest, IntoInner, RequestSettings}; #[async_trait::async_trait] /// A trait for transferring a document on Platform @@ -96,7 +96,8 @@ impl TransferDocument for Document { request .clone() .execute(sdk, settings.request_settings) - .await?; + .await // TODO: We need better way to handle execution errors + .into_inner()?; // response is empty for a broadcast, result comes from the stream wait for state transition result @@ -111,7 +112,10 @@ impl TransferDocument for Document { ) -> Result { let request = state_transition.wait_for_state_transition_result_request()?; - let response = request.execute(sdk, RequestSettings::default()).await?; + let response = request + .execute(sdk, RequestSettings::default()) + .await + .into_inner()?; let block_info = block_info_from_metadata(response.metadata()?)?; diff --git a/packages/rs-sdk/src/platform/transition/update_price_of_document.rs b/packages/rs-sdk/src/platform/transition/update_price_of_document.rs index 93da9aaf2b..0f331cde5d 100644 --- a/packages/rs-sdk/src/platform/transition/update_price_of_document.rs +++ b/packages/rs-sdk/src/platform/transition/update_price_of_document.rs @@ -18,7 +18,7 @@ use dpp::state_transition::documents_batch_transition::DocumentsBatchTransition; use dpp::state_transition::proof_result::StateTransitionProofResult; use dpp::state_transition::StateTransition; use drive::drive::Drive; -use rs_dapi_client::{DapiRequest, RequestSettings}; +use rs_dapi_client::{DapiRequest, IntoInner, RequestSettings}; #[async_trait::async_trait] /// A trait for updating the price of a document on Platform @@ -97,7 +97,8 @@ impl UpdatePriceOfDocument for Document { request .clone() .execute(sdk, settings.request_settings) - .await?; + .await // TODO: We need better way to handle execution errors + .into_inner()?; // response is empty for a broadcast, result comes from the stream wait for state transition result @@ -111,8 +112,11 @@ impl UpdatePriceOfDocument for Document { data_contract: Arc, ) -> Result { let request = state_transition.wait_for_state_transition_result_request()?; - - let response = request.execute(sdk, RequestSettings::default()).await?; + // TODO: Implement retry logic + let response = request + .execute(sdk, RequestSettings::default()) + .await + .into_inner()?; let block_info = block_info_from_metadata(response.metadata()?)?; diff --git a/packages/rs-sdk/src/platform/transition/vote.rs b/packages/rs-sdk/src/platform/transition/vote.rs index 56864a760c..5666b8b42d 100644 --- a/packages/rs-sdk/src/platform/transition/vote.rs +++ b/packages/rs-sdk/src/platform/transition/vote.rs @@ -17,7 +17,7 @@ use dpp::voting::votes::resource_vote::accessors::v0::ResourceVoteGettersV0; use dpp::voting::votes::Vote; use drive::drive::Drive; use drive_proof_verifier::{error::ContextProviderError, DataContractProvider}; -use rs_dapi_client::DapiRequest; +use rs_dapi_client::{DapiRequest, IntoInner}; #[async_trait::async_trait] /// A trait for putting a vote on platform @@ -71,7 +71,10 @@ impl PutVote for Vote { )?; let request = masternode_vote_transition.broadcast_request_for_state_transition()?; - request.execute(sdk, settings.request_settings).await?; + request + .execute(sdk, settings.request_settings) + .await // TODO: We need better way to handle execution errors + .into_inner()?; Ok(()) } @@ -105,8 +108,11 @@ impl PutVote for Vote { None, )?; let request = masternode_vote_transition.broadcast_request_for_state_transition()?; - - let response_result = request.execute(sdk, settings.request_settings).await; + // TODO: Implement retry logic + let response_result = request + .execute(sdk, settings.request_settings) + .await + .into_inner(); match response_result { Ok(_) => {} @@ -125,7 +131,10 @@ impl PutVote for Vote { } let request = masternode_vote_transition.wait_for_state_transition_result_request()?; - let response = request.execute(sdk, settings.request_settings).await?; + let response = request + .execute(sdk, settings.request_settings) + .await + .into_inner()?; let block_info = block_info_from_metadata(response.metadata()?)?; let proof = response.proof_owned()?; diff --git a/packages/rs-sdk/src/platform/transition/withdraw_from_identity.rs b/packages/rs-sdk/src/platform/transition/withdraw_from_identity.rs index 1dbff8c3ea..1d72c86e07 100644 --- a/packages/rs-sdk/src/platform/transition/withdraw_from_identity.rs +++ b/packages/rs-sdk/src/platform/transition/withdraw_from_identity.rs @@ -1,36 +1,32 @@ -use dapi_grpc::platform::VersionedGrpcResponse; use dpp::dashcore::Address; use dpp::identity::accessors::IdentityGettersV0; use dpp::identity::core_script::CoreScript; use dpp::identity::signer::Signer; -use dpp::identity::Identity; -use dpp::prelude::UserFeeIncrease; +use dpp::identity::{Identity, IdentityPublicKey}; -use dpp::state_transition::identity_credit_withdrawal_transition::IdentityCreditWithdrawalTransition; -use drive_proof_verifier::error::ContextProviderError; -use drive_proof_verifier::DataContractProvider; - -use crate::platform::block_info_from_metadata::block_info_from_metadata; -use crate::platform::transition::broadcast_request::BroadcastRequestForStateTransition; +use crate::platform::transition::broadcast::BroadcastStateTransition; use crate::platform::transition::put_settings::PutSettings; use crate::{Error, Sdk}; -use dpp::state_transition::identity_credit_withdrawal_transition::methods::IdentityCreditWithdrawalTransitionMethodsV0; +use dpp::state_transition::identity_credit_withdrawal_transition::methods::{ + IdentityCreditWithdrawalTransitionMethodsV0, PreferredKeyPurposeForSigningWithdrawal, +}; +use dpp::state_transition::identity_credit_withdrawal_transition::IdentityCreditWithdrawalTransition; use dpp::state_transition::proof_result::StateTransitionProofResult; use dpp::withdrawal::Pooling; -use drive::drive::Drive; -use rs_dapi_client::{DapiRequest, RequestSettings}; #[async_trait::async_trait] pub trait WithdrawFromIdentity { /// Function to withdraw credits from an identity. Returns the final identity balance. + /// If signing_withdrawal_key_to_use is not set, we will try to use one in the signer that is + /// available for withdrawal async fn withdraw( &self, sdk: &Sdk, - address: Address, + address: Option
, amount: u64, core_fee_per_byte: Option, - user_fee_increase: Option, + signing_withdrawal_key_to_use: Option<&IdentityPublicKey>, signer: S, settings: Option, ) -> Result; @@ -41,60 +37,37 @@ impl WithdrawFromIdentity for Identity { async fn withdraw( &self, sdk: &Sdk, - address: Address, + address: Option
, amount: u64, core_fee_per_byte: Option, - user_fee_increase: Option, + signing_withdrawal_key_to_use: Option<&IdentityPublicKey>, signer: S, settings: Option, ) -> Result { let new_identity_nonce = sdk.get_identity_nonce(self.id(), true, settings).await?; + let script = address.map(|address| CoreScript::new(address.script_pubkey())); + let user_fee_increase = settings.and_then(|settings| settings.user_fee_increase); let state_transition = IdentityCreditWithdrawalTransition::try_from_identity( self, - None, - CoreScript::new(address.script_pubkey()), + script, amount, Pooling::Never, core_fee_per_byte.unwrap_or(1), user_fee_increase.unwrap_or_default(), signer, + signing_withdrawal_key_to_use, + PreferredKeyPurposeForSigningWithdrawal::TransferPreferred, new_identity_nonce, sdk.version(), None, )?; - let request = state_transition.broadcast_request_for_state_transition()?; - - request - .clone() - .execute(sdk, settings.unwrap_or_default().request_settings) - .await?; - - let request = state_transition.wait_for_state_transition_result_request()?; - - let response = request.execute(sdk, RequestSettings::default()).await?; - - let block_info = block_info_from_metadata(response.metadata()?)?; - - let proof = response.proof_owned()?; - let context_provider = - sdk.context_provider() - .ok_or(Error::from(ContextProviderError::Config( - "Context provider not initialized".to_string(), - )))?; - - let (_, result) = Drive::verify_state_transition_was_executed_with_proof( - &state_transition, - &block_info, - proof.grovedb_proof.as_slice(), - &context_provider.as_contract_lookup_fn(), - sdk.version(), - )?; + let result = state_transition.broadcast_and_wait(sdk, None).await?; match result { StateTransitionProofResult::VerifiedPartialIdentity(identity) => { identity.balance.ok_or(Error::DapiClientError( - "expected an identity balance".to_string(), + "expected an identity balance after withdrawal".to_string(), )) } _ => Err(Error::DapiClientError("proved a non identity".to_string())), diff --git a/packages/rs-sdk/src/platform/types.rs b/packages/rs-sdk/src/platform/types.rs index 97a12c40b5..e4fbab2d47 100644 --- a/packages/rs-sdk/src/platform/types.rs +++ b/packages/rs-sdk/src/platform/types.rs @@ -1,5 +1,6 @@ //! Type-specific implementation for various dpp object types to make queries more convenient and intuitive. pub mod epoch; +pub mod evonode; pub mod identity; pub mod proposed_blocks; mod total_credits_in_platform; diff --git a/packages/rs-sdk/src/platform/types/evonode.rs b/packages/rs-sdk/src/platform/types/evonode.rs new file mode 100644 index 0000000000..70bbabee61 --- /dev/null +++ b/packages/rs-sdk/src/platform/types/evonode.rs @@ -0,0 +1,118 @@ +//! Evo Node represents a network node (server). + +use dapi_grpc::mock::Mockable; +use dapi_grpc::platform::v0::get_status_request::GetStatusRequestV0; +use dapi_grpc::platform::v0::{self as proto, get_status_request, GetStatusRequest}; +use dapi_grpc::tonic::IntoRequest; +pub use drive_proof_verifier::types::EvoNodeStatus; +use futures::future::BoxFuture; +use futures::{FutureExt, TryFutureExt}; +use rs_dapi_client::transport::{ + AppliedRequestSettings, PlatformGrpcClient, TransportClient, TransportError, TransportRequest, +}; +use rs_dapi_client::{Address, ConnectionPool, RequestSettings}; +#[cfg(feature = "mocks")] +use serde::{Deserialize, Serialize}; +use std::fmt::Debug; + +/// EvoNode allows querying the status of a single node using DAPI. +/// +/// ## Example +/// +/// ```rust,no_run +/// use dash_sdk::{platform::types::evonode::EvoNode,platform::FetchUnproved, Sdk}; +/// use drive_proof_verifier::types::EvoNodeStatus; +/// use futures::executor::block_on; +/// +/// let sdk = Sdk::new_mock(); +/// let uri: http::Uri = "http://127.0.0.1:1".parse().unwrap(); +/// let node = EvoNode::new(uri.into()); +/// let status = block_on(EvoNodeStatus::fetch_unproved(&sdk, node)).unwrap(); +/// ``` + +#[derive(Debug, Clone)] +#[cfg_attr(feature = "mocks", derive(Serialize, Deserialize))] +pub struct EvoNode(Address); + +impl EvoNode { + /// Creates a new `EvoNode` with the given address. + pub fn new(address: Address) -> Self { + Self(address) + } +} + +impl Mockable for EvoNode { + #[cfg(feature = "mocks")] + fn mock_deserialize(data: &[u8]) -> Option { + serde_json::de::from_slice(data).ok() + } + + #[cfg(feature = "mocks")] + fn mock_serialize(&self) -> Option> { + serde_json::ser::to_vec(self).ok() + } +} +impl TransportRequest for EvoNode { + type Client = PlatformGrpcClient; + type Response = proto::GetStatusResponse; + + const SETTINGS_OVERRIDES: rs_dapi_client::RequestSettings = RequestSettings::default(); + + fn method_name(&self) -> &'static str { + "get_status" + } + + fn execute_transport<'c>( + self, + _client: &'c mut Self::Client, + settings: &AppliedRequestSettings, + ) -> BoxFuture<'c, Result> { + let uri = self.0.uri(); + // As this is single node connection case, we create a new connection pool with space for a single connection + // and we drop it after use. + // + // We also create a new client to use with this request, so that the user does not need to + // reconfigure SDK to use a single node. + let pool = ConnectionPool::new(1); + // We create a new client with the given URI and settings + let client_result = Self::Client::with_uri_and_settings(uri.clone(), settings, &pool); + + // Handle the result manually to create a proper error response + let mut client = match client_result { + Ok(client) => client, + Err(e) => { + return async { Err(e) }.boxed(); + } + }; + let mut grpc_request = GetStatusRequest { + version: Some(get_status_request::Version::V0(GetStatusRequestV0 {})), + } + .into_request(); + + // we need to establish connection only with provided node, so we override client + + if !settings.timeout.is_zero() { + grpc_request.set_timeout(settings.timeout); + } + + async move { + let response = client + .get_status(grpc_request) + .map_err(TransportError::Grpc) + .map_ok(|response| response.into_inner()) + .await; + + drop(client); + drop(pool); + response + } + .boxed() + } +} + +impl From for GetStatusRequest { + fn from(_node: EvoNode) -> Self { + // we don't need to send any data to the node, and address is handled in impl TrasportRequest + GetStatusRequestV0 {}.into() + } +} diff --git a/packages/rs-sdk/src/platform/types/identity.rs b/packages/rs-sdk/src/platform/types/identity.rs index 632e3bd5e4..4b7b7754d0 100644 --- a/packages/rs-sdk/src/platform/types/identity.rs +++ b/packages/rs-sdk/src/platform/types/identity.rs @@ -22,6 +22,7 @@ use dapi_grpc::platform::v0::{ GetIdentityRequest, ResponseMetadata, }; use dpp::prelude::Identity; +use rs_dapi_client::transport::TransportError; // Create enum [IdentityRequest] and [IdentityResponse] that will wrap all possible // request/response types for [Identity] object. diff --git a/packages/rs-sdk/src/sdk.rs b/packages/rs-sdk/src/sdk.rs index fb8bd7fed8..3fd570e206 100644 --- a/packages/rs-sdk/src/sdk.rs +++ b/packages/rs-sdk/src/sdk.rs @@ -1,12 +1,13 @@ //! [Sdk] entrypoint to Dash Platform. -use crate::error::Error; +use crate::error::{Error, StaleNodeError}; use crate::internal_cache::InternalSdkCache; use crate::mock::MockResponse; #[cfg(feature = "mocks")] use crate::mock::{provider::GrpcContextProvider, MockDashPlatformSdk}; use crate::platform::transition::put_settings::PutSettings; use crate::platform::{Fetch, Identifier}; +use arc_swap::{ArcSwapAny, ArcSwapOption}; use dapi_grpc::mock::Mockable; use dapi_grpc::platform::v0::{Proof, ResponseMetadata}; use dpp::bincode; @@ -26,8 +27,7 @@ use rs_dapi_client::mock::MockDapiClient; pub use rs_dapi_client::AddressList; pub use rs_dapi_client::RequestSettings; use rs_dapi_client::{ - transport::{TransportClient, TransportRequest}, - DapiClient, DapiClientError, DapiRequestExecutor, + transport::TransportRequest, DapiClient, DapiClientError, DapiRequestExecutor, ExecutionResult, }; use std::collections::btree_map::Entry; use std::fmt::Debug; @@ -35,11 +35,13 @@ use std::fmt::Debug; use std::num::NonZeroUsize; #[cfg(feature = "mocks")] use std::path::{Path, PathBuf}; -use std::sync::Arc; +use std::sync::atomic::Ordering; +use std::sync::{atomic, Arc}; use std::time::{SystemTime, UNIX_EPOCH}; #[cfg(feature = "mocks")] use tokio::sync::{Mutex, MutexGuard}; use tokio_util::sync::{CancellationToken, WaitForCancellationFuture}; +use zeroize::Zeroizing; /// How many data contracts fit in the cache. pub const DEFAULT_CONTRACT_CACHE_SIZE: usize = 100; @@ -79,9 +81,8 @@ pub type LastQueryTimestamp = u64; /// ## Examples /// /// See tests/ for examples of using the SDK. -#[derive(Clone)] pub struct Sdk { - /// The network that the sdk is configured for (Dash (mainnet), Testnet, Devnet, Regtest) + /// The network that the sdk is configured for (Dash (mainnet), Testnet, Devnet, Regtest) pub network: Network, inner: SdkInstance, /// Use proofs when retrieving data from Platform. @@ -97,14 +98,50 @@ pub struct Sdk { /// ## Panics /// /// Note that setting this to None can panic. - context_provider: Option>>, + context_provider: ArcSwapOption>, + + /// Last seen height; used to determine if the remote node is stale. + /// + /// This is clone-able and can be shared between threads. + metadata_last_seen_height: Arc, + + /// How many blocks difference is allowed between the last height and the current height received in metadata. + /// + /// See [SdkBuilder::with_height_tolerance] for more information. + metadata_height_tolerance: Option, + + /// How many milliseconds difference is allowed between the time received in response and current local time. + /// + /// See [SdkBuilder::with_time_tolerance] for more information. + metadata_time_tolerance_ms: Option, /// Cancellation token; once cancelled, all pending requests should be aborted. pub(crate) cancel_token: CancellationToken, + /// Global settings of dapi client + pub(crate) dapi_client_settings: RequestSettings, + #[cfg(feature = "mocks")] dump_dir: Option, } +impl Clone for Sdk { + fn clone(&self) -> Self { + Self { + network: self.network, + inner: self.inner.clone(), + proofs: self.proofs, + internal_cache: Arc::clone(&self.internal_cache), + context_provider: ArcSwapOption::new(self.context_provider.load_full()), + cancel_token: self.cancel_token.clone(), + metadata_last_seen_height: Arc::clone(&self.metadata_last_seen_height), + metadata_height_tolerance: self.metadata_height_tolerance, + metadata_time_tolerance_ms: self.metadata_time_tolerance_ms, + dapi_client_settings: self.dapi_client_settings, + #[cfg(feature = "mocks")] + dump_dir: self.dump_dir.clone(), + } + } +} impl Debug for Sdk { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -177,7 +214,7 @@ impl Sdk { &self, request: O::Request, response: O::Response, - ) -> Result, drive_proof_verifier::Error> + ) -> Result, Error> where O::Request: Mockable, { @@ -198,32 +235,32 @@ impl Sdk { &self, request: O::Request, response: O::Response, - ) -> Result<(Option, ResponseMetadata), drive_proof_verifier::Error> + ) -> Result<(Option, ResponseMetadata), Error> where O::Request: Mockable, { - let provider = self - .context_provider - .as_ref() - .ok_or(drive_proof_verifier::Error::ContextProviderNotSet)?; + let (object, metadata, _proof) = self + .parse_proof_with_metadata_and_proof(request, response) + .await?; - match self.inner { - SdkInstance::Dapi { .. } => O::maybe_from_proof_with_metadata( - request, - response, - self.network, - self.version(), - &provider, - ) - .map(|(a, b, _)| (a, b)), - #[cfg(feature = "mocks")] - SdkInstance::Mock { ref mock, .. } => { - let guard = mock.lock().await; - guard - .parse_proof_with_metadata(request, response) - .map(|(a, b, _)| (a, b)) - } - } + Ok((object, metadata)) + } + + /// Verify response metadata against the current state of the SDK. + fn verify_response_metadata(&self, metadata: &ResponseMetadata) -> Result<(), Error> { + if let Some(height_tolerance) = self.metadata_height_tolerance { + verify_metadata_height( + metadata, + height_tolerance, + Arc::clone(&(self.metadata_last_seen_height)), + )?; + }; + if let Some(time_tolerance) = self.metadata_time_tolerance_ms { + let now = chrono::Utc::now().timestamp_millis() as u64; + verify_metadata_time(metadata, now, time_tolerance)?; + }; + + Ok(()) } /// Retrieve object `O` from proof contained in `request` (of type `R`) and `response`. @@ -238,16 +275,15 @@ impl Sdk { &self, request: O::Request, response: O::Response, - ) -> Result<(Option, ResponseMetadata, Proof), drive_proof_verifier::Error> + ) -> Result<(Option, ResponseMetadata, Proof), Error> where O::Request: Mockable, { let provider = self - .context_provider - .as_ref() + .context_provider() .ok_or(drive_proof_verifier::Error::ContextProviderNotSet)?; - match self.inner { + let (object, metadata, proof) = match self.inner { SdkInstance::Dapi { .. } => O::maybe_from_proof_with_metadata( request, response, @@ -260,10 +296,18 @@ impl Sdk { let guard = mock.lock().await; guard.parse_proof_with_metadata(request, response) } - } + }?; + + self.verify_response_metadata(&metadata)?; + Ok((object, metadata, proof)) } + + /// Return [ContextProvider] used by the SDK. pub fn context_provider(&self) -> Option { - self.context_provider.as_ref().map(Arc::clone) + let provider_guard = self.context_provider.load(); + let provider = provider_guard.as_ref().map(Arc::clone); + + provider } /// Returns a mutable reference to the `MockDashPlatformSdk` instance. @@ -377,6 +421,7 @@ impl Sdk { } } + // TODO: Move to a separate struct /// Updates or fetches the nonce for a given identity and contract pair from a cache, /// querying Platform if the cached value is stale or absent. Optionally /// increments the nonce before storing it, based on the provided settings. @@ -493,9 +538,9 @@ impl Sdk { /// [ContextProvider] is used to access state information, like data contracts and quorum public keys. /// /// Note that this will overwrite any previous context provider. - pub fn set_context_provider(&mut self, context_provider: C) { + pub fn set_context_provider(&self, context_provider: C) { self.context_provider - .replace(Arc::new(Box::new(context_provider))); + .swap(Some(Arc::new(Box::new(context_provider)))); } /// Returns a future that resolves when the Sdk is cancelled (eg. shutdown was requested). @@ -507,6 +552,122 @@ impl Sdk { pub fn shutdown(&self) { self.cancel_token.cancel(); } + + /// Return the [DapiClient] address list + pub fn address_list(&self) -> Result { + match &self.inner { + SdkInstance::Dapi { dapi, version: _ } => { + let address_list_arc = dapi.address_list(); + let address_list_lock = address_list_arc + .read() + .map_err(|e| format!("Failed to read address list: {e}"))?; + Ok(address_list_lock.clone()) + } + #[cfg(feature = "mocks")] + SdkInstance::Mock { .. } => { + unimplemented!("mock Sdk does not have address list") + } + } + } +} + +/// If received metadata time differs from local time by more than `tolerance`, the remote node is considered stale. +/// +/// ## Parameters +/// +/// - `metadata`: Metadata of the received response +/// - `now_ms`: Current local time in milliseconds +/// - `tolerance_ms`: Tolerance in milliseconds +fn verify_metadata_time( + metadata: &ResponseMetadata, + now_ms: u64, + tolerance_ms: u64, +) -> Result<(), Error> { + let metadata_time = metadata.time_ms; + + // metadata_time - tolerance_ms <= now_ms <= metadata_time + tolerance_ms + if now_ms.abs_diff(metadata_time) > tolerance_ms { + tracing::warn!( + expected_time = now_ms, + received_time = metadata_time, + tolerance_ms, + "received response with stale time; you should retry with another server" + ); + return Err(StaleNodeError::Time { + expected_timestamp_ms: now_ms, + received_timestamp_ms: metadata_time, + tolerance_ms, + } + .into()); + } + + tracing::trace!( + expected_time = now_ms, + received_time = metadata_time, + tolerance_ms, + "received response with valid time" + ); + Ok(()) +} + +/// If current metadata height is behind previously seen height by more than `tolerance`, the remote node +/// is considered stale. +fn verify_metadata_height( + metadata: &ResponseMetadata, + tolerance: u64, + last_seen_height: Arc, +) -> Result<(), Error> { + let mut expected_height = last_seen_height.load(Ordering::Relaxed); + let received_height = metadata.height; + + // Same height, no need to update. + if received_height == expected_height { + tracing::trace!( + expected_height, + received_height, + tolerance, + "received message has the same height as previously seen" + ); + return Ok(()); + } + + // If expected_height <= tolerance, then Sdk just started, so we just assume what we got is correct. + if expected_height > tolerance && received_height < expected_height - tolerance { + tracing::warn!( + expected_height, + received_height, + tolerance, + "received message with stale height; you should retry with another server" + ); + return Err(StaleNodeError::Height { + expected_height, + received_height, + tolerance_blocks: tolerance, + } + .into()); + } + + // New height is ahead of the last seen height, so we update the last seen height. + tracing::trace!( + expected_height = expected_height, + received_height = received_height, + tolerance, + "received message with new height" + ); + while let Err(stored_height) = last_seen_height.compare_exchange( + expected_height, + received_height, + Ordering::SeqCst, + Ordering::Relaxed, + ) { + // The value was changed to a higher value by another thread, so we need to retry. + if stored_height >= metadata.height { + break; + } + expected_height = stored_height; + } + + Ok(()) } #[async_trait::async_trait] @@ -515,7 +676,7 @@ impl DapiRequestExecutor for Sdk { &self, request: R, settings: RequestSettings, - ) -> Result::Error>> { + ) -> ExecutionResult { match self.inner { SdkInstance::Dapi { ref dapi, .. } => dapi.execute(request, settings).await, #[cfg(feature = "mocks")] @@ -551,7 +712,7 @@ pub struct SdkBuilder { core_ip: String, core_port: u16, core_user: String, - core_password: String, + core_password: Zeroizing, /// If true, request and verify proofs of the responses. proofs: bool, @@ -570,6 +731,17 @@ pub struct SdkBuilder { /// Context provider used by the SDK. context_provider: Option>, + /// How many blocks difference is allowed between the last seen metadata height and the height received in response + /// metadata. + /// + /// See [SdkBuilder::with_height_tolerance] for more information. + metadata_height_tolerance: Option, + + /// How many milliseconds difference is allowed between the time received in response metadata and current local time. + /// + /// See [SdkBuilder::with_time_tolerance] for more information. + metadata_time_tolerance_ms: Option, + /// directory where dump files will be stored #[cfg(feature = "mocks")] dump_dir: Option, @@ -587,10 +759,12 @@ impl Default for SdkBuilder { network: Network::Dash, core_ip: "".to_string(), core_port: 0, - core_password: "".to_string(), + core_password: "".to_string().into(), core_user: "".to_string(), proofs: true, + metadata_height_tolerance: Some(1), + metadata_time_tolerance_ms: None, #[cfg(feature = "mocks")] data_contract_cache_size: NonZeroUsize::new(DEFAULT_CONTRACT_CACHE_SIZE) @@ -710,11 +884,46 @@ impl SdkBuilder { self.core_ip = ip.to_string(); self.core_port = port; self.core_user = user.to_string(); - self.core_password = password.to_string(); + self.core_password = Zeroizing::from(password.to_string()); self } + /// Change number of blocks difference allowed between the last height and the height received in current response. + /// + /// If height received in response metadata is behind previously seen height by more than this value, the node + /// is considered stale, and the request will fail. + /// + /// If None, the height is not checked. + /// + /// Note that this feature doesn't guarantee that you are getting latest data, but it significantly decreases + /// probability of getting old data. + /// + /// This is set to `1` by default. + pub fn with_height_tolerance(mut self, tolerance: Option) -> Self { + self.metadata_height_tolerance = tolerance; + self + } + + /// How many milliseconds difference is allowed between the time received in response and current local time. + /// If the received time differs from local time by more than this value, the remote node is stale. + /// + /// If None, the time is not checked. + /// + /// This is set to `None` by default. + /// + /// Note that enabling this check can cause issues if the local time is not synchronized with the network time, + /// when the network is stalled or time between blocks increases significantly. + /// + /// Selecting a safe value for this parameter depends on maximum time between blocks mined on the network. + /// For example, if the network is configured to mine a block every maximum 3 minutes, setting this value + /// to a bit more than 6 minutes (to account for misbehaving proposers, network delays and local time + /// synchronization issues) should be safe. + pub fn with_time_tolerance(mut self, tolerance_ms: Option) -> Self { + self.metadata_time_tolerance_ms = tolerance_ms; + self + } + /// Configure directory where dumps of all requests and responses will be saved. /// Useful for debugging. /// @@ -753,21 +962,25 @@ impl SdkBuilder { #[allow(unused_mut)] // needs to be mutable for #[cfg(feature = "mocks")] let mut sdk= Sdk{ network: self.network, + dapi_client_settings: self.settings, inner:SdkInstance::Dapi { dapi, version:self.version }, proofs:self.proofs, - context_provider: self.context_provider.map(Arc::new), + context_provider: ArcSwapOption::new( self.context_provider.map(Arc::new)), cancel_token: self.cancel_token, + internal_cache: Default::default(), + // Note: in future, we need to securely initialize initial height during Sdk bootstrap or first request. + metadata_last_seen_height: Arc::new(atomic::AtomicU64::new(0)), + metadata_height_tolerance: self.metadata_height_tolerance, + metadata_time_tolerance_ms: self.metadata_time_tolerance_ms, #[cfg(feature = "mocks")] dump_dir: self.dump_dir, - internal_cache: Default::default(), }; // if context provider is not set correctly (is None), it means we need to fallback to core wallet - if sdk.context_provider.is_none() { + if sdk.context_provider.load().is_none() { #[cfg(feature = "mocks")] if !self.core_ip.is_empty() { - tracing::warn!("ContextProvider not set; mocking with Dash Core. \ - Please provide your own ContextProvider with SdkBuilder::with_context_provider()."); - + tracing::warn!( + "ContextProvider not set, falling back to a mock one; use SdkBuilder::with_context_provider() to set it up"); let mut context_provider = GrpcContextProvider::new(None, &self.core_ip, self.core_port, &self.core_user, &self.core_password, self.data_contract_cache_size, self.quorum_public_keys_cache_size)?; @@ -778,15 +991,19 @@ impl SdkBuilder { // We have cyclical dependency Sdk <-> GrpcContextProvider, so we just do some // workaround using additional Arc. let context_provider= Arc::new(context_provider); - sdk.context_provider.replace(Arc::new(Box::new(context_provider.clone()))); + sdk.context_provider.swap(Some(Arc::new(Box::new(context_provider.clone())))); context_provider.set_sdk(Some(sdk.clone())); } else{ - tracing::warn!( - "Configure ContextProvider with Sdk::with_context_provider(); otherwise Sdk will fail"); + return Err(Error::Config(concat!( + "context provider is not set, configure it with SdkBuilder::with_context_provider() ", + "or configure Core access with SdkBuilder::with_core() to use mock context provider") + .to_string())); } #[cfg(not(feature = "mocks"))] - tracing::warn!( - "Configure ContextProvider with Sdk::with_context_provider(); otherwise Sdk will fail"); + return Err(Error::Config(concat!( + "context provider is not set, configure it with SdkBuilder::with_context_provider() ", + "or enable `mocks` feature to use mock context provider") + .to_string())); }; sdk @@ -808,22 +1025,25 @@ impl SdkBuilder { let mock_sdk = Arc::new(Mutex::new(mock_sdk)); let sdk= Sdk { network: self.network, + dapi_client_settings: self.settings, inner:SdkInstance::Mock { mock:mock_sdk.clone(), dapi, version:self.version, - }, dump_dir: self.dump_dir.clone(), proofs:self.proofs, internal_cache: Default::default(), - context_provider:Some(Arc::new(context_provider)), + context_provider:ArcSwapAny::new( Some(Arc::new(context_provider))), cancel_token: self.cancel_token, + metadata_last_seen_height: Arc::new(atomic::AtomicU64::new(0)), + metadata_height_tolerance: self.metadata_height_tolerance, + metadata_time_tolerance_ms: self.metadata_time_tolerance_ms, }; let mut guard = mock_sdk.try_lock().expect("mock sdk is in use by another thread and connot be reconfigured"); guard.set_sdk(sdk.clone()); if let Some(ref dump_dir) = self.dump_dir { - pollster::block_on( guard.load_expectations(dump_dir))?; + guard.load_expectations_sync(dump_dir)?; }; sdk @@ -864,3 +1084,141 @@ pub fn prettify_proof(proof: &Proof) -> String { proof.quorum_type, ) } + +#[cfg(test)] +mod test { + use std::sync::Arc; + + use dapi_grpc::platform::v0::ResponseMetadata; + use test_case::test_matrix; + + use crate::SdkBuilder; + + #[test_matrix(97..102, 100, 2, false; "valid height")] + #[test_case(103, 100, 2, true; "invalid height")] + fn test_verify_metadata_height( + expected_height: u64, + received_height: u64, + tolerance: u64, + expect_err: bool, + ) { + let metadata = ResponseMetadata { + height: received_height, + ..Default::default() + }; + + let last_seen_height = + std::sync::Arc::new(std::sync::atomic::AtomicU64::new(expected_height)); + + let result = + super::verify_metadata_height(&metadata, tolerance, Arc::clone(&last_seen_height)); + + assert_eq!(result.is_err(), expect_err); + if result.is_ok() { + assert_eq!( + last_seen_height.load(std::sync::atomic::Ordering::Relaxed), + received_height, + "previous height should be updated" + ); + } + } + + #[test] + fn cloned_sdk_verify_metadata_height() { + let sdk1 = SdkBuilder::new_mock() + .build() + .expect("mock Sdk should be created"); + + // First message verified, height 1. + let metadata = ResponseMetadata { + height: 1, + ..Default::default() + }; + + sdk1.verify_response_metadata(&metadata) + .expect("metadata should be valid"); + + assert_eq!( + sdk1.metadata_last_seen_height + .load(std::sync::atomic::Ordering::Relaxed), + metadata.height, + "initial height" + ); + + // now, we clone sdk and do two requests. + let sdk2 = sdk1.clone(); + let sdk3 = sdk1.clone(); + + // Second message verified, height 2. + let metadata = ResponseMetadata { + height: 2, + ..Default::default() + }; + sdk2.verify_response_metadata(&metadata) + .expect("metadata should be valid"); + + assert_eq!( + sdk1.metadata_last_seen_height + .load(std::sync::atomic::Ordering::Relaxed), + metadata.height, + "first sdk should see height from second sdk" + ); + assert_eq!( + sdk3.metadata_last_seen_height + .load(std::sync::atomic::Ordering::Relaxed), + metadata.height, + "third sdk should see height from second sdk" + ); + + // Third message verified, height 3. + let metadata = ResponseMetadata { + height: 3, + ..Default::default() + }; + sdk3.verify_response_metadata(&metadata) + .expect("metadata should be valid"); + + assert_eq!( + sdk1.metadata_last_seen_height + .load(std::sync::atomic::Ordering::Relaxed), + metadata.height, + "first sdk should see height from third sdk" + ); + + assert_eq!( + sdk2.metadata_last_seen_height + .load(std::sync::atomic::Ordering::Relaxed), + metadata.height, + "second sdk should see height from third sdk" + ); + + // Now, using sdk1 for height 1 again should fail, as we are already at 3, with default tolerance 1. + let metadata = ResponseMetadata { + height: 1, + ..Default::default() + }; + + sdk1.verify_response_metadata(&metadata) + .expect_err("metadata should be invalid"); + } + + #[test_matrix([90,91,100,109,110], 100, 10, false; "valid time")] + #[test_matrix([0,89,111], 100, 10, true; "invalid time")] + #[test_matrix([0,100], [0,100], 100, false; "zero time")] + #[test_matrix([99,101], 100, 0, true; "zero tolerance")] + fn test_verify_metadata_time( + received_time: u64, + now_time: u64, + tolerance: u64, + expect_err: bool, + ) { + let metadata = ResponseMetadata { + time_ms: received_time, + ..Default::default() + }; + + let result = super::verify_metadata_time(&metadata, now_time, tolerance); + + assert_eq!(result.is_err(), expect_err); + } +} diff --git a/packages/rs-sdk/src/sync.rs b/packages/rs-sdk/src/sync.rs new file mode 100644 index 0000000000..38a878e174 --- /dev/null +++ b/packages/rs-sdk/src/sync.rs @@ -0,0 +1,376 @@ +//! Handle async calls from sync code. +//! +//! This is a workaround for an issue in tokio, where you cannot call `block_on` from sync call that is called +//! inside a tokio runtime. This module spawns async futures in active tokio runtime, and retrieves the result +//! using a channel. + +use arc_swap::ArcSwap; +use drive_proof_verifier::error::ContextProviderError; +use rs_dapi_client::{CanRetry, ExecutionResult, RequestSettings}; +use std::{ + fmt::Debug, + future::Future, + sync::{mpsc::SendError, Arc}, +}; +use tokio::{runtime::TryCurrentError, sync::Mutex}; +#[derive(Debug, thiserror::Error)] +pub enum AsyncError { + /// Not running inside tokio runtime + #[error("not running inside tokio runtime: {0}")] + NotInTokioRuntime(#[from] TryCurrentError), + + /// Cannot receive response from async function + #[error("cannot receive response from async function: {0}")] + RecvError(#[from] std::sync::mpsc::RecvError), + + /// Cannot send response from async function + #[error("cannot send response from async function: {0}")] + SendError(String), + + #[error("asynchronous call from synchronous context failed: {0}")] + #[allow(unused)] + Generic(String), +} + +impl From> for AsyncError { + fn from(error: SendError) -> Self { + Self::SendError(error.to_string()) + } +} + +impl From for ContextProviderError { + fn from(error: AsyncError) -> Self { + ContextProviderError::AsyncError(error.to_string()) + } +} + +impl From for crate::Error { + fn from(error: AsyncError) -> Self { + Self::ContextProviderError(error.into()) + } +} + +/// Blocks on the provided future and returns the result. +/// +/// This function is used to call async functions from sync code. +/// Requires the current thread to be running in a tokio runtime. +/// +/// Due to limitations of tokio runtime, we cannot use `tokio::runtime::Runtime::block_on` if we are already inside a tokio runtime. +/// This function is a workaround for that limitation. +pub fn block_on(fut: F) -> Result +where + F: Future + Send + 'static, + F::Output: Send, +{ + tracing::trace!("block_on: running async function from sync code"); + let rt = tokio::runtime::Handle::try_current()?; + let (tx, rx) = std::sync::mpsc::channel(); + tracing::trace!("block_on: Spawning worker"); + let hdl = rt.spawn(worker(fut, tx)); + tracing::trace!("block_on: Worker spawned"); + let resp = tokio::task::block_in_place(|| rx.recv())?; + + tracing::trace!("Response received"); + if !hdl.is_finished() { + tracing::debug!("async-sync worker future is not finished, aborting; this should not happen, but it's fine"); + hdl.abort(); // cleanup the worker future + } + + Ok(resp) +} + +/// Worker function that runs the provided future and sends the result back to the caller using oneshot channel. +async fn worker( + fut: F, + // response: oneshot::Sender, + response: std::sync::mpsc::Sender, +) -> Result<(), AsyncError> { + tracing::trace!("Worker start"); + let result = fut.await; + tracing::trace!("Worker async function completed, sending response"); + response.send(result)?; + tracing::trace!("Worker response sent"); + + Ok(()) +} + +/// Retry the provided closure. +/// +/// This function is used to retry async code. It takes into account number of retries already executed by lower +/// layers and stops retrying once the maximum number of retries is reached. +/// +/// The `settings` should contain maximum number of retries that should be executed. In case of failure, total number of +/// requests sent is expected to be at least `settings.retries + 1` (initial request + `retries` configured in settings). +/// The actual number of requests sent can be higher, as the lower layers can retry the request multiple times. +/// +/// `future_factory_fn` should be a `FnMut()` closure that returns a future that should be retried. +/// It takes [`RequestSettings`] as an argument and returns [`ExecutionResult`]. +/// Retry mechanism can change [`RequestSettings`] between invocations of the `future_factory_fn` closure +/// to limit the number of retries for lower layers. +/// +/// ## Parameters +/// +/// - `settings` - global settings with any request-specific settings overrides applied. +/// - `future_factory_fn` - closure that returns a future that should be retried. It should take [`RequestSettings`] as +/// an argument and return [`ExecutionResult`]. +/// +/// ## Returns +/// +/// Returns future that resolves to [`ExecutionResult`]. +/// +/// ## Example +/// +/// ```rust +/// # use dash_sdk::RequestSettings; +/// # use dash_sdk::error::{Error,StaleNodeError}; +/// # use rs_dapi_client::{ExecutionResult, ExecutionError}; +/// async fn retry_test_function(settings: RequestSettings) -> ExecutionResult<(), dash_sdk::Error> { +/// // do something +/// Err(ExecutionError { +/// inner: Error::StaleNode(StaleNodeError::Height{ +/// expected_height: 10, +/// received_height: 3, +/// tolerance_blocks: 1, +/// }), +/// retries: 0, +/// address: None, +/// }) +/// } +/// #[tokio::main] +/// async fn main() { +/// let global_settings = RequestSettings::default(); +/// dash_sdk::sync::retry(global_settings, retry_test_function).await.expect_err("should fail"); +/// } +/// ``` +/// +/// ## Troubleshooting +/// +/// Compiler error: `no method named retry found for closure`: +/// - ensure returned value is [`ExecutionResult`]., +/// - consider adding `.await` at the end of the closure. +/// +/// +/// ## See also +/// +/// - [`::backon`] crate that is used by this function. +pub async fn retry( + settings: RequestSettings, + future_factory_fn: FutureFactoryFn, +) -> ExecutionResult +where + Fut: Future>, + FutureFactoryFn: FnMut(RequestSettings) -> Fut, + E: CanRetry + Debug, +{ + let max_retries = settings.retries.unwrap_or_default(); + + let backoff_strategy = backon::ConstantBuilder::default() + .with_delay(std::time::Duration::from_millis(10)) // we use different server, so no real delay needed, just to avoid spamming + .with_max_times(max_retries); + + let mut retries: usize = 0; + + // Settings must be modified inside `when()` closure, so we need to use `ArcSwap` to allow mutable access to settings. + let settings = ArcSwap::new(Arc::new(settings)); + + // Closure below needs to be FnMut, so we need mutable future_factory_fn. In order to achieve that, + // we use Arc>> pattern, to NOT move `future_factory_fn` directly into closure (as this breaks FnMut), + // while still allowing mutable access to it. + let inner_fn = Arc::new(Mutex::new(future_factory_fn)); + + let closure_settings = &settings; + // backon also support [backon::RetryableWithContext], but it doesn't pass the context to `when()` call. + // As we need to modify the settings inside `when()`, context doesn't solve our problem and we have to implement + // our own "context-like" logic using the closure below and `ArcSwap` for settings. + let closure = move || { + let inner_fn = inner_fn.clone(); + async move { + let settings = closure_settings.load_full().clone(); + let mut func = inner_fn.lock().await; + (*func)(*settings).await + } + }; + + let result= ::backon::Retryable::retry(closure,backoff_strategy) + .when(|e| { + if e.can_retry() { + // requests sent for current execution attempt; + let requests_sent = e.retries + 1; + + // requests sent in all preceeding attempts; user expects `settings.retries +1` + retries += requests_sent; + let all_requests_sent = retries; + + if all_requests_sent <=max_retries { // we account for for initial request + tracing::warn!(retry = all_requests_sent, max_retries, error=?e, "retrying request"); + let new_settings = RequestSettings { + retries: Some(max_retries - all_requests_sent), // limit num of retries for lower layer + ..**settings.load() + }; + settings.store(Arc::new(new_settings)); + true + } else { + tracing::error!(retry = all_requests_sent, max_retries, error=?e, "no more retries left, giving up"); + false + } + } else { + false + } + }) + .notify(|error, duration| { + tracing::warn!(?duration, ?error, "request failed, retrying"); + }) + .await; + + result.map_err(|mut e| { + e.retries = retries; + e + }) +} + +#[cfg(test)] +mod test { + use super::*; + use http::Uri; + use rs_dapi_client::ExecutionError; + use std::{ + future::Future, + sync::atomic::{AtomicUsize, Ordering}, + }; + use tokio::{ + runtime::Builder, + sync::mpsc::{self, Receiver}, + }; + + /// Test for block_on with async code that calls sync code, which then calls async code again. + /// + /// Given: An async function that calls a sync function, which then calls another async function. + /// When: The async function is executed using block_on. + /// Then: Other threads can still do some work + #[test] + fn test_block_on_nested_async_sync() { + let rt = Builder::new_multi_thread() + .worker_threads(1) // we should be good with 1 worker thread + .max_blocking_threads(1) // we should be good with 1 blocking thread + .enable_all() + .build() + .expect("Failed to create Tokio runtime"); + // we repeat this test a few times, to make sure it's stable + for _repeat in 0..5 { + // Create a Tokio runtime; we use the current thread runtime for this test. + + const MSGS: usize = 10; + let (tx, rx) = mpsc::channel::(1); + + // Spawn new worker that will just count. + let worker = async move { + for count in 0..MSGS { + tx.send(count).await.unwrap(); + } + }; + let worker_join = rt.spawn(worker); + // Define the number of levels of execution + let levels = 4; + + // Define the innermost async function + async fn innermost_async_function( + mut rx: Receiver, + ) -> Result { + for i in 0..MSGS { + let count = rx.recv().await.unwrap(); + assert_eq!(count, i); + } + + Ok(String::from("Success")) + } + + // Define the nested sync function + fn nested_sync_function(fut: F) -> Result + where + F: Future> + Send + 'static, + F::Output: Send, + { + block_on(fut)?.map_err(|e| ContextProviderError::Generic(e.to_string())) + } + + // Define the outer async function + async fn outer_async_function( + levels: usize, + rx: Receiver, + ) -> Result { + let mut result = innermost_async_function(rx).await; + for _ in 0..levels { + result = nested_sync_function(async { result }); + } + result + } + + // Run the outer async function using block_on + let result = rt.block_on(outer_async_function(levels, rx)); + + rt.block_on(worker_join).unwrap(); + // Assert the result + assert_eq!(result.unwrap(), "Success"); + } + } + + #[derive(Debug)] + enum MockError { + Generic, + } + impl CanRetry for MockError { + fn can_retry(&self) -> bool { + true + } + } + + async fn retry_test_function( + settings: RequestSettings, + counter: Arc, + ) -> ExecutionResult<(), MockError> { + // num or retries increases with each call + let retries = counter.load(Ordering::Relaxed); + let retries = if settings.retries.unwrap_or_default() < retries { + settings.retries.unwrap_or_default() + } else { + retries + }; + + // we sent 1 initial request plus `retries` retries + counter.fetch_add(1 + retries, Ordering::Relaxed); + + Err(ExecutionError { + inner: MockError::Generic, + retries, + address: Some(Uri::from_static("http://localhost").into()), + }) + } + + #[test_case::test_matrix([1,2,3,5,7,8,10,11,23,49, usize::MAX])] + #[tokio::test] + async fn test_retry(expected_requests: usize) { + for _ in 0..1 { + let counter = Arc::new(AtomicUsize::new(0)); + + // we retry 5 times, and expect 5 retries + 1 initial request + let mut global_settings = RequestSettings::default(); + global_settings.retries = Some(expected_requests - 1); + + let closure = |s| { + let counter = counter.clone(); + retry_test_function(s, counter) + }; + + retry(global_settings, closure) + .await + .expect_err("should fail"); + + assert_eq!( + counter.load(Ordering::Relaxed), + expected_requests, + "test failed for expected {} requests", + expected_requests + ); + } + } +} diff --git a/packages/rs-sdk/tests/fetch/broadcast.rs b/packages/rs-sdk/tests/fetch/broadcast.rs index 56e26f457e..1dc45ab701 100644 --- a/packages/rs-sdk/tests/fetch/broadcast.rs +++ b/packages/rs-sdk/tests/fetch/broadcast.rs @@ -33,7 +33,7 @@ mod online { // we add few millis to duration to give chance to the server to time out before we kill request let response = tokio::time::timeout( - TIMEOUT + Duration::from_millis(100), + TIMEOUT + Duration::from_secs(1), request.execute(&sdk, settings), ) .await diff --git a/packages/rs-sdk/tests/fetch/config.rs b/packages/rs-sdk/tests/fetch/config.rs index 445904795d..c2f8edbc4e 100644 --- a/packages/rs-sdk/tests/fetch/config.rs +++ b/packages/rs-sdk/tests/fetch/config.rs @@ -11,6 +11,7 @@ use dpp::{ use rs_dapi_client::AddressList; use serde::Deserialize; use std::{path::PathBuf, str::FromStr}; +use zeroize::Zeroizing; /// Existing document ID /// @@ -43,7 +44,7 @@ pub struct Config { pub core_user: String, /// Password for Dash Core RPC interface #[serde(default)] - pub core_password: String, + pub core_password: Zeroizing, /// When true, use SSL for the Dash Platform node grpc interface #[serde(default)] pub platform_ssl: bool, @@ -71,6 +72,7 @@ pub struct Config { /// ID of document of the type [`existing_document_type_name`](Config::existing_document_type_name) /// in [`existing_data_contract_id`](Config::existing_data_contract_id). #[serde(default = "Config::default_document_id")] + #[allow(unused)] pub existing_document_id: Identifier, // Hex-encoded ProTxHash of the existing HP masternode #[serde(default = "Config::default_protxhash")] @@ -141,14 +143,14 @@ impl Config { /// ## Feature flags /// /// * `offline-testing` is not set - connect to Platform and generate - /// new test vectors during execution + /// new test vectors during execution /// * `offline-testing` is set - use mock implementation and - /// load existing test vectors from disk + /// load existing test vectors from disk /// /// ## Arguments /// /// * namespace - namespace to use when storing mock expectations; this is used to separate - /// expectations from different tests. + /// expectations from different tests. /// /// When empty string is provided, expectations are stored in the root of the dump directory. pub async fn setup_api(&self, namespace: &str) -> dash_sdk::Sdk { @@ -223,8 +225,8 @@ impl Config { // Next time we need to do it again and update this value :(. This is terrible. // We should automate creation of identity for SDK tests when we have time. Identifier::from_string( - "a1534e47f60be71e823a9dbc9ceb6d3ea9f1ebde7a3773f03e49ef31c7d9c044", - Encoding::Hex, + "G5z3hwiLUnRDGrLEgcqM9sX8wWEuNGHQqvioERgdZ2Tq", + Encoding::Base58, ) .unwrap() } @@ -250,7 +252,7 @@ impl Config { /// /// See documentation of [contested_resource_identity_votes_ok](super::contested_resource_identity_votes::contested_resource_identity_votes_ok). fn default_protxhash() -> String { - String::from("d10bf435af7c75f5b07b09486af1212469d69fdc787589548e315776bc1052a1") + String::from("069dcb6e829988af0edb245f30d3b1297a47081854a78c3cdea9fddb8fbd07eb") } /// Return ProTxHash of an existing evo node, or None if not set diff --git a/packages/rs-sdk/tests/fetch/contested_resource.rs b/packages/rs-sdk/tests/fetch/contested_resource.rs index 4f899c2126..643396d495 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource.rs @@ -19,7 +19,6 @@ use drive::query::{ vote_polls_by_document_type_query::VotePollsByDocumentTypeQuery, }; use drive_proof_verifier::types::ContestedResource; -use std::panic::catch_unwind; /// Test that we can fetch contested resources /// @@ -105,7 +104,7 @@ async fn contested_resources_start_at_value() { for inclusive in [true, false] { // when I set start_at_value to some value, for (i, start) in all.0.iter().enumerate() { - let ContestedResource::Value(start_value) = start.clone(); + let ContestedResource(start_value) = start.clone(); let query = VotePollsByDocumentTypeQuery { start_at_value: Some((start_value, inclusive)), @@ -217,7 +216,7 @@ async fn contested_resources_limit_PLAN_656() { ); } - let ContestedResource::Value(last) = + let ContestedResource(last) = rss.0.into_iter().last().expect("last contested resource"); start_at_value = Some((last, false)); @@ -231,14 +230,14 @@ async fn contested_resources_limit_PLAN_656() { /// ## Preconditions /// /// None -#[test_case::test_case(|_q| {}, Ok("ContestedResources([Value(Text(".into()); "unmodified base query is Ok")] +#[test_case::test_case(|_q| {}, Ok("ContestedResources([ContestedResource(Text(".into()); "unmodified base query is Ok")] #[test_case::test_case(|q| q.start_index_values = vec![Value::Text("".to_string())], Ok("".into()); "index value empty string is Ok")] #[test_case::test_case(|q| q.document_type_name = "some random non-existing name".to_string(), Err(r#"code: InvalidArgument, message: "document type some random non-existing name not found"#); "non existing document type returns InvalidArgument")] #[test_case::test_case(|q| q.index_name = "nx index".to_string(), Err(r#"code: InvalidArgument, message: "index with name nx index is not the contested index"#); "non existing index returns InvalidArgument")] #[test_case::test_case(|q| q.index_name = "dashIdentityId".to_string(), Err(r#"code: InvalidArgument, message: "index with name dashIdentityId is not the contested index"#); "existing non-contested index returns InvalidArgument")] // Disabled due to bug PLAN-653 // #[test_case::test_case(|q| q.start_at_value = Some((Value::Array(vec![]), true)), Err(r#"code: InvalidArgument"#); "start_at_value wrong index type returns InvalidArgument PLAN-653")] -#[test_case::test_case(|q| q.start_index_values = vec![], Ok(r#"ContestedResources([Value(Text("dash"))])"#.into()); "start_index_values empty vec returns top-level keys")] +#[test_case::test_case(|q| q.start_index_values = vec![], Ok(r#"ContestedResources([ContestedResource(Text("dash"))])"#.into()); "start_index_values empty vec returns top-level keys")] #[test_case::test_case(|q| q.start_index_values = vec![Value::Text("".to_string())], Ok(r#"ContestedResources([])"#.into()); "start_index_values empty string returns zero results")] #[test_case::test_case(|q| { q.start_index_values = vec![ @@ -249,7 +248,7 @@ async fn contested_resources_limit_PLAN_656() { #[test_case::test_case(|q| { q.start_index_values = vec![]; q.end_index_values = vec![Value::Text(TEST_DPNS_NAME.to_string())]; -}, Ok(r#"ContestedResources([Value(Text("dash"))])"#.into()); "end_index_values one value with empty start_index_values returns 'dash'")] +}, Ok(r#"ContestedResources([ContestedResource(Text("dash"))])"#.into()); "end_index_values one value with empty start_index_values returns 'dash'")] #[test_case::test_case(|q| { q.start_index_values = vec![]; q.end_index_values = vec![Value::Text(TEST_DPNS_NAME.to_string()), Value::Text("non existing".to_string())]; @@ -278,7 +277,7 @@ async fn contested_resources_limit_PLAN_656() { }, Ok("ContestedResources([])".into()); "Non-existing end_index_values returns error")] #[test_case::test_case(|q| q.end_index_values = vec![Value::Array(vec![0.into(), 1.into()])], Err("incorrect index values error: too many end index values were provided"); "wrong type of end_index_values should return InvalidArgument")] #[test_case::test_case(|q| q.limit = Some(0), Err(r#"code: InvalidArgument"#); "limit 0 returns InvalidArgument")] -#[test_case::test_case(|q| q.limit = Some(std::u16::MAX), Err(r#"code: InvalidArgument"#); "limit std::u16::MAX returns InvalidArgument")] +#[test_case::test_case(|q| q.limit = Some(u16::MAX), Err(r#"code: InvalidArgument"#); "limit u16::MAX returns InvalidArgument")] // Disabled due to bug PLAN-656 // #[test_case::test_case(|q| { // q.start_index_values = vec![Value::Text("dash".to_string())]; @@ -304,33 +303,35 @@ async fn contested_resources_fields( tracing::debug!(?expect, "Running test case"); // handle panics to not stop other test cases from running - let unwinded = catch_unwind(|| { - { - pollster::block_on(async { - let mut query = base_query(&cfg); - query_mut_fn(&mut query); - - let (test_case_id, sdk) = - setup_sdk_for_test_case(cfg, query.clone(), "contested_resources_fields").await; - tracing::debug!(test_case_id, ?query, "Executing query"); - - ContestedResource::fetch_many(&sdk, query).await - }) - } - }); - let result = match unwinded { + let join_handle = tokio::task::spawn(async move { + let mut query = base_query(&cfg); + query_mut_fn(&mut query); + + let (test_case_id, sdk) = + setup_sdk_for_test_case(cfg, query.clone(), "contested_resources_fields").await; + tracing::debug!(test_case_id, ?query, "Executing query"); + + ContestedResource::fetch_many(&sdk, query).await + }) + .await; + let result = match join_handle { Ok(r) => r, Err(e) => { - let msg = if let Some(s) = e.downcast_ref::<&str>() { - s.to_string() - } else if let Some(s) = e.downcast_ref::() { - s.to_string() - } else { - format!("unknown panic type: {:?}", std::any::type_name_of_val(&e)) - }; + if e.is_panic() { + let e = e.into_panic(); + let msg = if let Some(s) = e.downcast_ref::<&str>() { + s.to_string() + } else if let Some(s) = e.downcast_ref::() { + s.to_string() + } else { + format!("unknown panic type: {:?}", std::any::type_name_of_val(&e)) + }; - tracing::error!("PANIC: {}", msg); - Err(Error::Generic(msg)) + tracing::error!("PANIC: {}", msg); + Err(Error::Generic(msg)) + } else { + Err(Error::Generic(format!("JoinError: {:?}", e))) + } } }; diff --git a/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs b/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs index 69b66e0e48..6c0bd2f7c4 100644 --- a/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs +++ b/packages/rs-sdk/tests/fetch/contested_resource_vote_state.rs @@ -107,9 +107,10 @@ async fn contested_resource_vote_states_nx_contract() { if let dash_sdk::error::Error::DapiClientError(e) = result { assert!( e.contains( - "Transport(Status { code: InvalidArgument, message: \"contract not found error" + "Transport(Grpc(Status { code: InvalidArgument, message: \"contract not found error" ), - "we should get contract not found error" + "we should get contract not found error, got: {:?}", + e, ); } else { panic!("expected 'contract not found' transport error"); @@ -267,7 +268,7 @@ async fn contested_resource_vote_states_with_limit_PLAN_674() { assert_eq!( contenders.contenders.len(), limit as usize, - "number of contenders for {:?} should must be at least {}", + "number of contenders for {:?} should must be {}", label, limit ); @@ -276,7 +277,7 @@ async fn contested_resource_vote_states_with_limit_PLAN_674() { type MutFn = fn(&mut ContestedDocumentVotePollDriveQuery); #[test_case(|q| q.limit = Some(0), Err("limit 0 out of bounds of [1, 100]"); "limit 0")] -#[test_case(|q| q.limit = Some(std::u16::MAX), Err("limit 65535 out of bounds of [1, 100]"); "limit std::u16::MAX")] +#[test_case(|q| q.limit = Some(u16::MAX), Err("limit 65535 out of bounds of [1, 100]"); "limit u16::MAX")] #[test_case(|q| q.start_at = Some(([0x11; 32], true)), Ok("Contenders { winner: None, contenders: {Identifier("); "start_at does not exist should return next contenders")] #[test_case(|q| q.start_at = Some(([0xff; 32], true)), Ok("Contenders { winner: None, contenders: {}, abstain_vote_tally: None, lock_vote_tally: None }"); "start_at 0xff;32 should return zero contenders")] #[test_case(|q| q.vote_poll.document_type_name = "nx doctype".to_string(), Err(r#"code: InvalidArgument, message: "document type nx doctype not found"#); "non existing document type returns InvalidArgument")] diff --git a/packages/rs-sdk/tests/fetch/data_contract.rs b/packages/rs-sdk/tests/fetch/data_contract.rs index b59acbb97a..41ef33138e 100644 --- a/packages/rs-sdk/tests/fetch/data_contract.rs +++ b/packages/rs-sdk/tests/fetch/data_contract.rs @@ -135,7 +135,7 @@ async fn test_data_contracts_2_nx() { async fn test_data_contract_history_read() { let cfg = Config::new(); let id = Identifier::from_string( - "20d16030541c0494e84064e2e72b5ec620546305849a2f9d5893a5e65072364d", + "eacc9ceb6c11ee1ae82afb5590d78d686f43bc0f0e0cd65de1e23c150e41f97f", Encoding::Hex, ) .unwrap(); @@ -145,6 +145,11 @@ async fn test_data_contract_history_read() { let result = DataContractHistory::fetch(&sdk, LimitQuery::from((id, 10))).await; assert!(matches!(result, Ok(Some(_))), "result: {:?}", result); - let (_, contract) = result.unwrap().unwrap().pop_first().unwrap(); + let (_, contract) = result + .expect("request should succeed") + .expect("data contract should exist") + .into_iter() + .next() + .expect("data contract"); assert_eq!(contract.id(), id); } diff --git a/packages/rs-sdk/tests/fetch/document.rs b/packages/rs-sdk/tests/fetch/document.rs index 8263250d0b..088cf73136 100644 --- a/packages/rs-sdk/tests/fetch/document.rs +++ b/packages/rs-sdk/tests/fetch/document.rs @@ -34,7 +34,8 @@ async fn document_read() { let first_doc = Document::fetch_many(&sdk, all_docs_query) .await .expect("fetch many documents") - .pop_first() + .into_iter() + .next() .expect("first item must exist") .1 .expect("document must exist"); diff --git a/packages/rs-sdk/tests/fetch/epoch.rs b/packages/rs-sdk/tests/fetch/epoch.rs index 8080e3b344..7a2d4c3bed 100644 --- a/packages/rs-sdk/tests/fetch/epoch.rs +++ b/packages/rs-sdk/tests/fetch/epoch.rs @@ -1,10 +1,6 @@ -use std::collections::BTreeMap; - use super::{common::setup_logs, config::Config}; -use dapi_grpc::platform::{ - v0::{get_identity_request::GetIdentityRequestV0, GetIdentityRequest}, - VersionedGrpcResponse, -}; +use dapi_grpc::platform::v0::{get_identity_request::GetIdentityRequestV0, GetIdentityRequest}; +use dapi_grpc::platform::VersionedGrpcResponse; use dash_sdk::{ platform::{ fetch_current_no_parameters::FetchCurrent, Fetch, FetchMany, LimitQuery, @@ -15,7 +11,8 @@ use dash_sdk::{ use dpp::block::epoch::EpochIndex; use dpp::block::extended_epoch_info::v0::ExtendedEpochInfoV0Getters; use dpp::block::extended_epoch_info::ExtendedEpochInfo; -use rs_dapi_client::{DapiRequestExecutor, RequestSettings}; +use drive_proof_verifier::types::ExtendedEpochInfos; +use rs_dapi_client::{DapiRequestExecutor, IntoInner, RequestSettings}; /// Get current epoch index from DAPI response metadata async fn get_current_epoch(sdk: &Sdk, cfg: &Config) -> EpochIndex { @@ -29,13 +26,14 @@ async fn get_current_epoch(sdk: &Sdk, cfg: &Config) -> EpochIndex { let response = sdk .execute(identity_request, RequestSettings::default()) .await + .into_inner() .expect("get identity"); response.metadata().expect("metadata").epoch as EpochIndex } /// Check some assertions on returned epochs list fn assert_epochs( - epochs: BTreeMap>, + epochs: ExtendedEpochInfos, starting_epoch: EpochIndex, current_epoch: EpochIndex, limit: u16, @@ -89,10 +87,9 @@ async fn test_epoch_list() { let current_epoch = get_current_epoch(&sdk, &cfg).await; // When we fetch epochs from the server, starting with `starting_epoch` - let epochs: BTreeMap> = - ExtendedEpochInfo::fetch_many(&sdk, starting_epoch) - .await - .expect("list epochs"); + let epochs: ExtendedEpochInfos = ExtendedEpochInfo::fetch_many(&sdk, starting_epoch) + .await + .expect("list epochs"); assert_epochs( epochs, diff --git a/packages/rs-sdk/tests/fetch/evonode.rs b/packages/rs-sdk/tests/fetch/evonode.rs new file mode 100644 index 0000000000..0d35d5be9f --- /dev/null +++ b/packages/rs-sdk/tests/fetch/evonode.rs @@ -0,0 +1,71 @@ +//! Test evo node status and other node-related functionality. + +use super::{common::setup_logs, config::Config}; +use dash_sdk::platform::{types::evonode::EvoNode, FetchUnproved}; +use dpp::dashcore::{hashes::Hash, ProTxHash}; +use drive_proof_verifier::types::EvoNodeStatus; +use http::Uri; +use std::time::Duration; +/// Given some existing evonode URIs, WHEN we connect to them, THEN we get status. +use tokio::time::timeout; + +#[tokio::test(flavor = "multi_thread", worker_threads = 1)] +async fn test_evonode_status() { + setup_logs(); + + let cfg = Config::new(); + let sdk = cfg.setup_api("test_evonode_status").await; + + let addresses = cfg.address_list(); + + for address in addresses { + let node = EvoNode::new(address.clone()); + match timeout( + Duration::from_secs(3), + EvoNodeStatus::fetch_unproved(&sdk, node), + ) + .await + { + Ok(Ok(Some(status))) => { + tracing::debug!(?status, ?address, "evonode status"); + // Add assertions here to verify the status contents + assert!( + status.chain.latest_block_height > 0, + "latest block height must be positive" + ); + assert!( + status.node.pro_tx_hash.unwrap_or_default().len() == ProTxHash::LEN, + "latest block hash must be non-empty" + ); + // Add more specific assertions based on expected status properties + } + Ok(Ok(None)) => { + tracing::warn!(?address, "No status found for evonode"); + panic!("No status found for evonode"); + } + Ok(Err(e)) => { + tracing::error!(?address, error = ?e, "Error fetching evonode status"); + } + Err(_) => { + tracing::error!(?address, "Timeout while fetching evonode status"); + } + } + } +} + +/// Given invalid evonode URI, when we request status, we get error. +#[tokio::test(flavor = "multi_thread", worker_threads = 1)] +async fn test_evonode_status_refused() { + setup_logs(); + + let cfg = Config::new(); + let sdk = cfg.setup_api("test_evonode_status_refused").await; + + let uri: Uri = "http://127.0.0.1:1".parse().unwrap(); + + let node = EvoNode::new(uri.clone().into()); + let result = EvoNodeStatus::fetch_unproved(&sdk, node).await; + tracing::debug!(?result, ?uri, "evonode status"); + + assert!(result.is_err()); +} diff --git a/packages/rs-sdk/tests/fetch/mock_fetch.rs b/packages/rs-sdk/tests/fetch/mock_fetch.rs index a5d4916077..1b96614ecd 100644 --- a/packages/rs-sdk/tests/fetch/mock_fetch.rs +++ b/packages/rs-sdk/tests/fetch/mock_fetch.rs @@ -1,5 +1,4 @@ -//! -//! +//! Tests of mocked Fetch trait implementations. use super::common::{mock_data_contract, mock_document_type}; use dash_sdk::{ diff --git a/packages/rs-sdk/tests/fetch/mock_fetch_many.rs b/packages/rs-sdk/tests/fetch/mock_fetch_many.rs index fdf3811d8d..36bce78543 100644 --- a/packages/rs-sdk/tests/fetch/mock_fetch_many.rs +++ b/packages/rs-sdk/tests/fetch/mock_fetch_many.rs @@ -1,5 +1,3 @@ -use std::collections::BTreeMap; - use super::common::{mock_data_contract, mock_document_type}; use dash_sdk::{ platform::{DocumentQuery, FetchMany}, @@ -14,6 +12,7 @@ use dpp::{ }, document::{Document, DocumentV0Getters}, }; +use drive_proof_verifier::types::Documents; /// Given some data contract, document type and 1 document of this type, when I request multiple documents, I get that /// document. @@ -26,13 +25,13 @@ async fn test_mock_document_fetch_many() { let expected_doc = document_type .random_document(None, sdk.version()) .expect("document should be created"); - let expected = BTreeMap::from([(expected_doc.id(), Some(expected_doc.clone()))]); + let expected = Documents::from([(expected_doc.id(), Some(expected_doc.clone()))]); // document that should not be returned, as it will be defined as a duplicate let not_expected_doc = document_type .random_document(None, sdk.version()) .expect("document 2 should be created"); - let not_expected = BTreeMap::from([(not_expected_doc.id(), Some(not_expected_doc))]); + let not_expected = Documents::from([(not_expected_doc.id(), Some(not_expected_doc))]); let document_type_name = document_type.name(); diff --git a/packages/rs-sdk/tests/fetch/mod.rs b/packages/rs-sdk/tests/fetch/mod.rs index 76e6c84c69..363e35f069 100644 --- a/packages/rs-sdk/tests/fetch/mod.rs +++ b/packages/rs-sdk/tests/fetch/mod.rs @@ -17,6 +17,7 @@ mod contested_resource_voters; mod data_contract; mod document; mod epoch; +mod evonode; mod identity; mod identity_contract_nonce; mod mock_fetch; diff --git a/packages/rs-sdk/tests/vectors/check_mn_voting_prerequisities/msg_GetContestedResourceVoteStateRequest_aaaa80ce4fdfc75252132a85e6c12bea6a47c9f7bf30133713b6b5cfec3a4d57.json b/packages/rs-sdk/tests/vectors/check_mn_voting_prerequisities/msg_GetContestedResourceVoteStateRequest_aaaa80ce4fdfc75252132a85e6c12bea6a47c9f7bf30133713b6b5cfec3a4d57.json index 300e476a45..7ec5d38676 100644 Binary files a/packages/rs-sdk/tests/vectors/check_mn_voting_prerequisities/msg_GetContestedResourceVoteStateRequest_aaaa80ce4fdfc75252132a85e6c12bea6a47c9f7bf30133713b6b5cfec3a4d57.json and b/packages/rs-sdk/tests/vectors/check_mn_voting_prerequisities/msg_GetContestedResourceVoteStateRequest_aaaa80ce4fdfc75252132a85e6c12bea6a47c9f7bf30133713b6b5cfec3a4d57.json differ diff --git a/packages/rs-sdk/tests/vectors/check_mn_voting_prerequisities/msg_GetContestedResourcesRequest_8f71462d5f438e1b12fedf94ad5799af81392b7b0cbb7e86412da37ab13aef4b.json b/packages/rs-sdk/tests/vectors/check_mn_voting_prerequisities/msg_GetContestedResourcesRequest_8f71462d5f438e1b12fedf94ad5799af81392b7b0cbb7e86412da37ab13aef4b.json index d9c45a55bb..484cfca543 100644 Binary files a/packages/rs-sdk/tests/vectors/check_mn_voting_prerequisities/msg_GetContestedResourcesRequest_8f71462d5f438e1b12fedf94ad5799af81392b7b0cbb7e86412da37ab13aef4b.json and b/packages/rs-sdk/tests/vectors/check_mn_voting_prerequisities/msg_GetContestedResourcesRequest_8f71462d5f438e1b12fedf94ad5799af81392b7b0cbb7e86412da37ab13aef4b.json differ diff --git a/packages/rs-sdk/tests/vectors/check_mn_voting_prerequisities/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json b/packages/rs-sdk/tests/vectors/check_mn_voting_prerequisities/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json index 808b4f0118..e64b73d8a7 100644 Binary files a/packages/rs-sdk/tests/vectors/check_mn_voting_prerequisities/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json and b/packages/rs-sdk/tests/vectors/check_mn_voting_prerequisities/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json differ diff --git a/packages/rs-sdk/tests/vectors/check_mn_voting_prerequisities/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/check_mn_voting_prerequisities/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/check_mn_voting_prerequisities/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/check_mn_voting_prerequisities/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/check_mn_voting_prerequisities/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/check_mn_voting_prerequisities/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_resource_identity_votes_not_found/msg_GetContestedResourceIdentityVotesRequest_e000a8dfb1f42155770acb028f56557d0524384797bb450e22f41f66743d5d11.json b/packages/rs-sdk/tests/vectors/contested_resource_identity_votes_not_found/msg_GetContestedResourceIdentityVotesRequest_e000a8dfb1f42155770acb028f56557d0524384797bb450e22f41f66743d5d11.json index d1a33e908a..40ddedbff5 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resource_identity_votes_not_found/msg_GetContestedResourceIdentityVotesRequest_e000a8dfb1f42155770acb028f56557d0524384797bb450e22f41f66743d5d11.json and b/packages/rs-sdk/tests/vectors/contested_resource_identity_votes_not_found/msg_GetContestedResourceIdentityVotesRequest_e000a8dfb1f42155770acb028f56557d0524384797bb450e22f41f66743d5d11.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resource_identity_votes_not_found/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/contested_resource_identity_votes_not_found/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/contested_resource_identity_votes_not_found/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_resource_identity_votes_not_found/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/contested_resource_identity_votes_not_found/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/contested_resource_identity_votes_not_found/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_resource_identity_votes_ok/msg_GetContestedResourceIdentityVotesRequest_3eae9b60bf6fb0140e51ef4cc1c1b4eb361d64607a75a117ebf3096fafb32a41.json b/packages/rs-sdk/tests/vectors/contested_resource_identity_votes_ok/msg_GetContestedResourceIdentityVotesRequest_3eae9b60bf6fb0140e51ef4cc1c1b4eb361d64607a75a117ebf3096fafb32a41.json deleted file mode 100644 index a230d7abfe..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resource_identity_votes_ok/msg_GetContestedResourceIdentityVotesRequest_3eae9b60bf6fb0140e51ef4cc1c1b4eb361d64607a75a117ebf3096fafb32a41.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resource_identity_votes_ok/msg_GetContestedResourceIdentityVotesRequest_8f3fcd0f5c5546dc3acb53577269a380d88e7caeeb4cc3ab0cf2bb04e2f096af.json b/packages/rs-sdk/tests/vectors/contested_resource_identity_votes_ok/msg_GetContestedResourceIdentityVotesRequest_8f3fcd0f5c5546dc3acb53577269a380d88e7caeeb4cc3ab0cf2bb04e2f096af.json new file mode 100644 index 0000000000..83f2083ba9 Binary files /dev/null and b/packages/rs-sdk/tests/vectors/contested_resource_identity_votes_ok/msg_GetContestedResourceIdentityVotesRequest_8f3fcd0f5c5546dc3acb53577269a380d88e7caeeb4cc3ab0cf2bb04e2f096af.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resource_identity_votes_ok/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json b/packages/rs-sdk/tests/vectors/contested_resource_identity_votes_ok/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json index 808b4f0118..e64b73d8a7 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resource_identity_votes_ok/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json and b/packages/rs-sdk/tests/vectors/contested_resource_identity_votes_ok/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resource_identity_votes_ok/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/contested_resource_identity_votes_ok/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/contested_resource_identity_votes_ok/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_resource_identity_votes_ok/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/contested_resource_identity_votes_ok/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/contested_resource_identity_votes_ok/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_resource_vote_states_not_found/msg_GetContestedResourceVoteStateRequest_8789d5d98ad7f00573a87fd0860dbd43fab2e54a98aa44bc88c049e1cf72f5fb.json b/packages/rs-sdk/tests/vectors/contested_resource_vote_states_not_found/msg_GetContestedResourceVoteStateRequest_8789d5d98ad7f00573a87fd0860dbd43fab2e54a98aa44bc88c049e1cf72f5fb.json index 9f6fdc1a41..fe272aba2c 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resource_vote_states_not_found/msg_GetContestedResourceVoteStateRequest_8789d5d98ad7f00573a87fd0860dbd43fab2e54a98aa44bc88c049e1cf72f5fb.json and b/packages/rs-sdk/tests/vectors/contested_resource_vote_states_not_found/msg_GetContestedResourceVoteStateRequest_8789d5d98ad7f00573a87fd0860dbd43fab2e54a98aa44bc88c049e1cf72f5fb.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resource_vote_states_not_found/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json b/packages/rs-sdk/tests/vectors/contested_resource_vote_states_not_found/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json index 808b4f0118..e64b73d8a7 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resource_vote_states_not_found/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json and b/packages/rs-sdk/tests/vectors/contested_resource_vote_states_not_found/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resource_vote_states_not_found/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/contested_resource_vote_states_not_found/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/contested_resource_vote_states_not_found/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_resource_vote_states_not_found/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/contested_resource_vote_states_not_found/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/contested_resource_vote_states_not_found/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_resource_vote_states_nx_contract/msg_GetContestedResourceVoteStateRequest_f700de7bfd247d4f0193fabc530ac956499cf0081eb632e6d84ef4f9c32d8690.json b/packages/rs-sdk/tests/vectors/contested_resource_vote_states_nx_contract/msg_GetContestedResourceVoteStateRequest_f700de7bfd247d4f0193fabc530ac956499cf0081eb632e6d84ef4f9c32d8690.json index e9e6c9759d..6d4f3e9c52 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resource_vote_states_nx_contract/msg_GetContestedResourceVoteStateRequest_f700de7bfd247d4f0193fabc530ac956499cf0081eb632e6d84ef4f9c32d8690.json and b/packages/rs-sdk/tests/vectors/contested_resource_vote_states_nx_contract/msg_GetContestedResourceVoteStateRequest_f700de7bfd247d4f0193fabc530ac956499cf0081eb632e6d84ef4f9c32d8690.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resource_vote_states_ok/msg_GetContestedResourceVoteStateRequest_aaaa80ce4fdfc75252132a85e6c12bea6a47c9f7bf30133713b6b5cfec3a4d57.json b/packages/rs-sdk/tests/vectors/contested_resource_vote_states_ok/msg_GetContestedResourceVoteStateRequest_aaaa80ce4fdfc75252132a85e6c12bea6a47c9f7bf30133713b6b5cfec3a4d57.json index 300e476a45..7ec5d38676 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resource_vote_states_ok/msg_GetContestedResourceVoteStateRequest_aaaa80ce4fdfc75252132a85e6c12bea6a47c9f7bf30133713b6b5cfec3a4d57.json and b/packages/rs-sdk/tests/vectors/contested_resource_vote_states_ok/msg_GetContestedResourceVoteStateRequest_aaaa80ce4fdfc75252132a85e6c12bea6a47c9f7bf30133713b6b5cfec3a4d57.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resource_vote_states_ok/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json b/packages/rs-sdk/tests/vectors/contested_resource_vote_states_ok/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json index 808b4f0118..e64b73d8a7 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resource_vote_states_ok/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json and b/packages/rs-sdk/tests/vectors/contested_resource_vote_states_ok/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resource_vote_states_ok/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/contested_resource_vote_states_ok/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/contested_resource_vote_states_ok/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_resource_vote_states_ok/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/contested_resource_vote_states_ok/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/contested_resource_vote_states_ok/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_resource_vote_states_with_limit/msg_GetContestedResourceVoteStateRequest_7a62b33ce71dec56fbbcb0302eac0041cdc16404006d1b30577292c6ce106cdb.json b/packages/rs-sdk/tests/vectors/contested_resource_vote_states_with_limit/msg_GetContestedResourceVoteStateRequest_7a62b33ce71dec56fbbcb0302eac0041cdc16404006d1b30577292c6ce106cdb.json index e88e9376ff..0034a48f94 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resource_vote_states_with_limit/msg_GetContestedResourceVoteStateRequest_7a62b33ce71dec56fbbcb0302eac0041cdc16404006d1b30577292c6ce106cdb.json and b/packages/rs-sdk/tests/vectors/contested_resource_vote_states_with_limit/msg_GetContestedResourceVoteStateRequest_7a62b33ce71dec56fbbcb0302eac0041cdc16404006d1b30577292c6ce106cdb.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resource_vote_states_with_limit/msg_GetContestedResourceVoteStateRequest_aaaa80ce4fdfc75252132a85e6c12bea6a47c9f7bf30133713b6b5cfec3a4d57.json b/packages/rs-sdk/tests/vectors/contested_resource_vote_states_with_limit/msg_GetContestedResourceVoteStateRequest_aaaa80ce4fdfc75252132a85e6c12bea6a47c9f7bf30133713b6b5cfec3a4d57.json index 300e476a45..7ec5d38676 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resource_vote_states_with_limit/msg_GetContestedResourceVoteStateRequest_aaaa80ce4fdfc75252132a85e6c12bea6a47c9f7bf30133713b6b5cfec3a4d57.json and b/packages/rs-sdk/tests/vectors/contested_resource_vote_states_with_limit/msg_GetContestedResourceVoteStateRequest_aaaa80ce4fdfc75252132a85e6c12bea6a47c9f7bf30133713b6b5cfec3a4d57.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resource_vote_states_with_limit/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json b/packages/rs-sdk/tests/vectors/contested_resource_vote_states_with_limit/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json index 808b4f0118..e64b73d8a7 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resource_vote_states_with_limit/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json and b/packages/rs-sdk/tests/vectors/contested_resource_vote_states_with_limit/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resource_vote_states_with_limit/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/contested_resource_vote_states_with_limit/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/contested_resource_vote_states_with_limit/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_resource_vote_states_with_limit/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/contested_resource_vote_states_with_limit/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/contested_resource_vote_states_with_limit/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_resource_voters_for_existing_contestant/msg_GetContestedResourceVoteStateRequest_aaaa80ce4fdfc75252132a85e6c12bea6a47c9f7bf30133713b6b5cfec3a4d57.json b/packages/rs-sdk/tests/vectors/contested_resource_voters_for_existing_contestant/msg_GetContestedResourceVoteStateRequest_aaaa80ce4fdfc75252132a85e6c12bea6a47c9f7bf30133713b6b5cfec3a4d57.json index 300e476a45..7ec5d38676 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resource_voters_for_existing_contestant/msg_GetContestedResourceVoteStateRequest_aaaa80ce4fdfc75252132a85e6c12bea6a47c9f7bf30133713b6b5cfec3a4d57.json and b/packages/rs-sdk/tests/vectors/contested_resource_voters_for_existing_contestant/msg_GetContestedResourceVoteStateRequest_aaaa80ce4fdfc75252132a85e6c12bea6a47c9f7bf30133713b6b5cfec3a4d57.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resource_voters_for_existing_contestant/msg_GetContestedResourceVotersForIdentityRequest_10110ee14ae9da0bda6aaa8191c57c0a880092ca161c0d1ad05fb5658e88fd2e.json b/packages/rs-sdk/tests/vectors/contested_resource_voters_for_existing_contestant/msg_GetContestedResourceVotersForIdentityRequest_10110ee14ae9da0bda6aaa8191c57c0a880092ca161c0d1ad05fb5658e88fd2e.json new file mode 100644 index 0000000000..dcbf6985c6 Binary files /dev/null and b/packages/rs-sdk/tests/vectors/contested_resource_voters_for_existing_contestant/msg_GetContestedResourceVotersForIdentityRequest_10110ee14ae9da0bda6aaa8191c57c0a880092ca161c0d1ad05fb5658e88fd2e.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resource_voters_for_existing_contestant/msg_GetContestedResourceVotersForIdentityRequest_4698eed49c628d65b930a48286b7b889b486f0341ced46beee35a8693507d319.json b/packages/rs-sdk/tests/vectors/contested_resource_voters_for_existing_contestant/msg_GetContestedResourceVotersForIdentityRequest_4698eed49c628d65b930a48286b7b889b486f0341ced46beee35a8693507d319.json deleted file mode 100644 index 85c6d7ca37..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resource_voters_for_existing_contestant/msg_GetContestedResourceVotersForIdentityRequest_4698eed49c628d65b930a48286b7b889b486f0341ced46beee35a8693507d319.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resource_voters_for_existing_contestant/msg_GetContestedResourceVotersForIdentityRequest_606cb2d93ca22b6a73e58bca36002e4d9a981806b2efa77c35b08bcffe360bc5.json b/packages/rs-sdk/tests/vectors/contested_resource_voters_for_existing_contestant/msg_GetContestedResourceVotersForIdentityRequest_606cb2d93ca22b6a73e58bca36002e4d9a981806b2efa77c35b08bcffe360bc5.json deleted file mode 100644 index b5cd7667fd..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resource_voters_for_existing_contestant/msg_GetContestedResourceVotersForIdentityRequest_606cb2d93ca22b6a73e58bca36002e4d9a981806b2efa77c35b08bcffe360bc5.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resource_voters_for_existing_contestant/msg_GetContestedResourceVotersForIdentityRequest_6c371f39cd63a4a0dfb9a9fa47de218ef824e28209f3b797076903b13efe884b.json b/packages/rs-sdk/tests/vectors/contested_resource_voters_for_existing_contestant/msg_GetContestedResourceVotersForIdentityRequest_6c371f39cd63a4a0dfb9a9fa47de218ef824e28209f3b797076903b13efe884b.json new file mode 100644 index 0000000000..9ba9e26fac Binary files /dev/null and b/packages/rs-sdk/tests/vectors/contested_resource_voters_for_existing_contestant/msg_GetContestedResourceVotersForIdentityRequest_6c371f39cd63a4a0dfb9a9fa47de218ef824e28209f3b797076903b13efe884b.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resource_voters_for_existing_contestant/msg_GetContestedResourceVotersForIdentityRequest_901f0f04456fd2d03a1d16a56baeb2baad30765e2616aea8a61637690cc28b91.json b/packages/rs-sdk/tests/vectors/contested_resource_voters_for_existing_contestant/msg_GetContestedResourceVotersForIdentityRequest_901f0f04456fd2d03a1d16a56baeb2baad30765e2616aea8a61637690cc28b91.json deleted file mode 100644 index 58a98222fb..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resource_voters_for_existing_contestant/msg_GetContestedResourceVotersForIdentityRequest_901f0f04456fd2d03a1d16a56baeb2baad30765e2616aea8a61637690cc28b91.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resource_voters_for_existing_contestant/msg_GetContestedResourceVotersForIdentityRequest_e42a431aedd97fe3f9057f50e68b2eb86d71a154bb1d8373a11a1564258a40ab.json b/packages/rs-sdk/tests/vectors/contested_resource_voters_for_existing_contestant/msg_GetContestedResourceVotersForIdentityRequest_e42a431aedd97fe3f9057f50e68b2eb86d71a154bb1d8373a11a1564258a40ab.json new file mode 100644 index 0000000000..0c4fc9f1bd Binary files /dev/null and b/packages/rs-sdk/tests/vectors/contested_resource_voters_for_existing_contestant/msg_GetContestedResourceVotersForIdentityRequest_e42a431aedd97fe3f9057f50e68b2eb86d71a154bb1d8373a11a1564258a40ab.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resource_voters_for_existing_contestant/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json b/packages/rs-sdk/tests/vectors/contested_resource_voters_for_existing_contestant/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json index 808b4f0118..e64b73d8a7 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resource_voters_for_existing_contestant/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json and b/packages/rs-sdk/tests/vectors/contested_resource_voters_for_existing_contestant/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resource_voters_for_existing_contestant/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/contested_resource_voters_for_existing_contestant/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/contested_resource_voters_for_existing_contestant/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_resource_voters_for_existing_contestant/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/contested_resource_voters_for_existing_contestant/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/contested_resource_voters_for_existing_contestant/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_0760ac4854fc8db803bbcbab8709f390bd31511a05e29cd3f170b48ca6b87584/msg_GetContestedResourcesRequest_25a3f1603510228a22726e0b4c35bce08c84a0cf72b34f6a408982f7babce2c2.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_0760ac4854fc8db803bbcbab8709f390bd31511a05e29cd3f170b48ca6b87584/msg_GetContestedResourcesRequest_25a3f1603510228a22726e0b4c35bce08c84a0cf72b34f6a408982f7babce2c2.json index bbfdee7b8e..f95cd41ab5 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_fields_0760ac4854fc8db803bbcbab8709f390bd31511a05e29cd3f170b48ca6b87584/msg_GetContestedResourcesRequest_25a3f1603510228a22726e0b4c35bce08c84a0cf72b34f6a408982f7babce2c2.json and b/packages/rs-sdk/tests/vectors/contested_resources_fields_0760ac4854fc8db803bbcbab8709f390bd31511a05e29cd3f170b48ca6b87584/msg_GetContestedResourcesRequest_25a3f1603510228a22726e0b4c35bce08c84a0cf72b34f6a408982f7babce2c2.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_0760ac4854fc8db803bbcbab8709f390bd31511a05e29cd3f170b48ca6b87584/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_0760ac4854fc8db803bbcbab8709f390bd31511a05e29cd3f170b48ca6b87584/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json index 808b4f0118..e64b73d8a7 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_fields_0760ac4854fc8db803bbcbab8709f390bd31511a05e29cd3f170b48ca6b87584/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json and b/packages/rs-sdk/tests/vectors/contested_resources_fields_0760ac4854fc8db803bbcbab8709f390bd31511a05e29cd3f170b48ca6b87584/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_0760ac4854fc8db803bbcbab8709f390bd31511a05e29cd3f170b48ca6b87584/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_0760ac4854fc8db803bbcbab8709f390bd31511a05e29cd3f170b48ca6b87584/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/contested_resources_fields_0760ac4854fc8db803bbcbab8709f390bd31511a05e29cd3f170b48ca6b87584/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_0760ac4854fc8db803bbcbab8709f390bd31511a05e29cd3f170b48ca6b87584/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_0760ac4854fc8db803bbcbab8709f390bd31511a05e29cd3f170b48ca6b87584/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/contested_resources_fields_0760ac4854fc8db803bbcbab8709f390bd31511a05e29cd3f170b48ca6b87584/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_26378250faa97706848b4fee6ed2f2cb0ab194082b611404c4c28b595d5cecdf/msg_GetContestedResourcesRequest_77c7328647f3785936dfb2c48dbcf0ed3b40564b35e3ce17ee02d5b15e9bede1.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_26378250faa97706848b4fee6ed2f2cb0ab194082b611404c4c28b595d5cecdf/msg_GetContestedResourcesRequest_77c7328647f3785936dfb2c48dbcf0ed3b40564b35e3ce17ee02d5b15e9bede1.json index 12c65611a9..5b702bb92b 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_fields_26378250faa97706848b4fee6ed2f2cb0ab194082b611404c4c28b595d5cecdf/msg_GetContestedResourcesRequest_77c7328647f3785936dfb2c48dbcf0ed3b40564b35e3ce17ee02d5b15e9bede1.json and b/packages/rs-sdk/tests/vectors/contested_resources_fields_26378250faa97706848b4fee6ed2f2cb0ab194082b611404c4c28b595d5cecdf/msg_GetContestedResourcesRequest_77c7328647f3785936dfb2c48dbcf0ed3b40564b35e3ce17ee02d5b15e9bede1.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_2dd27fc692c7bf9389f3b48c73a4d2538a4eb72d54c01cc4620b16b06eb31f4c/data_contract-e668c659af66aee1e72c186dde7b5b7e0a1d712a09c40d5721f622bf53c53155.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_2dd27fc692c7bf9389f3b48c73a4d2538a4eb72d54c01cc4620b16b06eb31f4c/data_contract-e668c659af66aee1e72c186dde7b5b7e0a1d712a09c40d5721f622bf53c53155.json deleted file mode 100644 index e67826094c..0000000000 --- a/packages/rs-sdk/tests/vectors/contested_resources_fields_2dd27fc692c7bf9389f3b48c73a4d2538a4eb72d54c01cc4620b16b06eb31f4c/data_contract-e668c659af66aee1e72c186dde7b5b7e0a1d712a09c40d5721f622bf53c53155.json +++ /dev/null @@ -1 +0,0 @@ -{"$format_version":"0","id":"GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec","config":{"$format_version":"0","canBeDeleted":false,"readonly":false,"keepsHistory":false,"documentsKeepHistoryContractDefault":false,"documentsMutableContractDefault":true,"documentsCanBeDeletedContractDefault":true,"requiresIdentityEncryptionBoundedKey":null,"requiresIdentityDecryptionBoundedKey":null},"version":1,"ownerId":"4EfA9Jrvv3nnCFdSf7fad59851iiTRZ6Wcu6YVJ4iSeF","schemaDefs":null,"documentSchemas":{"domain":{"type":"object","documentsMutable":false,"canBeDeleted":false,"indices":[{"name":"parentNameAndLabel","properties":[{"normalizedParentDomainName":"asc"},{"normalizedLabel":"asc"}],"unique":true,"contested":{"fieldMatches":[{"field":"normalizedLabel","regexPattern":"^[a-zA-Z01]{3,19}$"}],"resolution":0,"description":"If the normalized label part of this index is less than 20 characters (all alphabet a-z and 0 and 1) then this index is non unique while contest resolution takes place."}},{"name":"dashIdentityId","properties":[{"records.dashUniqueIdentityId":"asc"}],"unique":true},{"name":"dashAlias","properties":[{"records.dashAliasIdentityId":"asc"}]}],"properties":{"label":{"type":"string","pattern":"^[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]$","minLength":3,"maxLength":63,"position":0,"description":"Domain label. e.g. 'Bob'."},"normalizedLabel":{"type":"string","pattern":"^[a-hj-km-np-z0-9][a-hj-km-np-z0-9-]{0,61}[a-hj-km-np-z0-9]$","maxLength":63,"position":1,"description":"Domain label converted to lowercase for case-insensitive uniqueness validation. \"o\", \"i\" and \"l\" replaced with \"0\" and \"1\" to mitigate homograph attack. e.g. 'b0b'","$comment":"Must be equal to the label in lowercase. \"o\", \"i\" and \"l\" must be replaced with \"0\" and \"1\"."},"parentDomainName":{"type":"string","pattern":"^$|^[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]$","minLength":0,"maxLength":63,"position":2,"description":"A full parent domain name. e.g. 'dash'."},"normalizedParentDomainName":{"type":"string","pattern":"^$|^[a-hj-km-np-z0-9][a-hj-km-np-z0-9-\\.]{0,61}[a-hj-km-np-z0-9]$","minLength":0,"maxLength":63,"position":3,"description":"A parent domain name in lowercase for case-insensitive uniqueness validation. \"o\", \"i\" and \"l\" replaced with \"0\" and \"1\" to mitigate homograph attack. e.g. 'dash'","$comment":"Must either be equal to an existing domain or empty to create a top level domain. \"o\", \"i\" and \"l\" must be replaced with \"0\" and \"1\". Only the data contract owner can create top level domains."},"preorderSalt":{"type":"array","byteArray":true,"minItems":32,"maxItems":32,"position":4,"description":"Salt used in the preorder document"},"records":{"type":"object","properties":{"dashUniqueIdentityId":{"type":"array","byteArray":true,"minItems":32,"maxItems":32,"position":0,"contentMediaType":"application/x.dash.dpp.identifier","description":"Identity ID to be used to create the primary name the Identity","$comment":"Must be equal to the document owner"},"dashAliasIdentityId":{"type":"array","byteArray":true,"minItems":32,"maxItems":32,"position":1,"contentMediaType":"application/x.dash.dpp.identifier","description":"Identity ID to be used to create alias names for the Identity","$comment":"Must be equal to the document owner"}},"minProperties":1,"maxProperties":1,"position":5,"additionalProperties":false,"$comment":"Constraint with max and min properties ensure that only one identity record is used - either a `dashUniqueIdentityId` or a `dashAliasIdentityId`"},"subdomainRules":{"type":"object","properties":{"allowSubdomains":{"type":"boolean","description":"This option defines who can create subdomains: true - anyone; false - only the domain owner","$comment":"Only the domain owner is allowed to create subdomains for non top-level domains","position":0}},"position":6,"description":"Subdomain rules allow domain owners to define rules for subdomains","additionalProperties":false,"required":["allowSubdomains"]}},"required":["label","normalizedLabel","normalizedParentDomainName","preorderSalt","records","subdomainRules"],"additionalProperties":false,"$comment":"In order to register a domain you need to create a preorder. The preorder step is needed to prevent man-in-the-middle attacks. normalizedLabel + '.' + normalizedParentDomain must not be longer than 253 chars length as defined by RFC 1035. Domain documents are immutable: modification and deletion are restricted"},"preorder":{"type":"object","documentsMutable":false,"canBeDeleted":true,"indices":[{"name":"saltedHash","properties":[{"saltedDomainHash":"asc"}],"unique":true}],"properties":{"saltedDomainHash":{"type":"array","byteArray":true,"minItems":32,"maxItems":32,"position":0,"description":"Double sha-256 of the concatenation of a 32 byte random salt and a normalized domain name"}},"required":["saltedDomainHash"],"additionalProperties":false,"$comment":"Preorder documents are immutable: modification and deletion are restricted"}}} \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_2dd27fc692c7bf9389f3b48c73a4d2538a4eb72d54c01cc4620b16b06eb31f4c/msg_GetContestedResourcesRequest_e49260f4b2b31f8b6dafa5d51dd06732ed93fe23ffa9b35f6c92d6ef34732aff.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_2dd27fc692c7bf9389f3b48c73a4d2538a4eb72d54c01cc4620b16b06eb31f4c/msg_GetContestedResourcesRequest_e49260f4b2b31f8b6dafa5d51dd06732ed93fe23ffa9b35f6c92d6ef34732aff.json deleted file mode 100644 index 829ff69141..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_fields_2dd27fc692c7bf9389f3b48c73a4d2538a4eb72d54c01cc4620b16b06eb31f4c/msg_GetContestedResourcesRequest_e49260f4b2b31f8b6dafa5d51dd06732ed93fe23ffa9b35f6c92d6ef34732aff.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_2dd27fc692c7bf9389f3b48c73a4d2538a4eb72d54c01cc4620b16b06eb31f4c/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_2dd27fc692c7bf9389f3b48c73a4d2538a4eb72d54c01cc4620b16b06eb31f4c/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json deleted file mode 100644 index 22611d5e7e..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_fields_2dd27fc692c7bf9389f3b48c73a4d2538a4eb72d54c01cc4620b16b06eb31f4c/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_2dd27fc692c7bf9389f3b48c73a4d2538a4eb72d54c01cc4620b16b06eb31f4c/quorum_pubkey-106-24de77bd1f67e0c3e20a399b6a3e6bfae60312e2f833b302a62be93e181e7a0e.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_2dd27fc692c7bf9389f3b48c73a4d2538a4eb72d54c01cc4620b16b06eb31f4c/quorum_pubkey-106-24de77bd1f67e0c3e20a399b6a3e6bfae60312e2f833b302a62be93e181e7a0e.json deleted file mode 100644 index 37a791a5b2..0000000000 --- a/packages/rs-sdk/tests/vectors/contested_resources_fields_2dd27fc692c7bf9389f3b48c73a4d2538a4eb72d54c01cc4620b16b06eb31f4c/quorum_pubkey-106-24de77bd1f67e0c3e20a399b6a3e6bfae60312e2f833b302a62be93e181e7a0e.json +++ /dev/null @@ -1 +0,0 @@ -a245c69b35145a4a4e1ed00b63fc64b6563d4def0cf87be3fe12e49ea6dc6821b2456cd849db635df51f7d466cf7ac6e \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_31d560b1c7927c2052e6d6efe7a00d204f33b4194f3fba7ed0ec5f2387097dac/msg_GetContestedResourcesRequest_219b7c56aec6474f1bb2eb673898fbd24420cbf27187df52fbb489e70b1c898d.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_31d560b1c7927c2052e6d6efe7a00d204f33b4194f3fba7ed0ec5f2387097dac/msg_GetContestedResourcesRequest_219b7c56aec6474f1bb2eb673898fbd24420cbf27187df52fbb489e70b1c898d.json index e49ea35e19..1cdf75c58b 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_fields_31d560b1c7927c2052e6d6efe7a00d204f33b4194f3fba7ed0ec5f2387097dac/msg_GetContestedResourcesRequest_219b7c56aec6474f1bb2eb673898fbd24420cbf27187df52fbb489e70b1c898d.json and b/packages/rs-sdk/tests/vectors/contested_resources_fields_31d560b1c7927c2052e6d6efe7a00d204f33b4194f3fba7ed0ec5f2387097dac/msg_GetContestedResourcesRequest_219b7c56aec6474f1bb2eb673898fbd24420cbf27187df52fbb489e70b1c898d.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_3cd5aaa5bb117bd7a79c8f91545dbe469d5140b9e3c994bfcb80e3697cd9381e/msg_GetContestedResourcesRequest_be10704137c79a7c54b4c392a640353cf7adee1c4b04dc8689afc26031b9b010.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_3cd5aaa5bb117bd7a79c8f91545dbe469d5140b9e3c994bfcb80e3697cd9381e/msg_GetContestedResourcesRequest_be10704137c79a7c54b4c392a640353cf7adee1c4b04dc8689afc26031b9b010.json index a3f07928c1..059cbc807b 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_fields_3cd5aaa5bb117bd7a79c8f91545dbe469d5140b9e3c994bfcb80e3697cd9381e/msg_GetContestedResourcesRequest_be10704137c79a7c54b4c392a640353cf7adee1c4b04dc8689afc26031b9b010.json and b/packages/rs-sdk/tests/vectors/contested_resources_fields_3cd5aaa5bb117bd7a79c8f91545dbe469d5140b9e3c994bfcb80e3697cd9381e/msg_GetContestedResourcesRequest_be10704137c79a7c54b4c392a640353cf7adee1c4b04dc8689afc26031b9b010.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_465afbed74842189a7651d5ea128874bbcfcb0dc0e4c32ab8ea2d3c8a4d32a03/msg_GetContestedResourcesRequest_6ec2c2e0abfde5adf1d65d2b06ba7401f9ed4ef7493ce9faa08a50e6b4d2c34d.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_465afbed74842189a7651d5ea128874bbcfcb0dc0e4c32ab8ea2d3c8a4d32a03/msg_GetContestedResourcesRequest_6ec2c2e0abfde5adf1d65d2b06ba7401f9ed4ef7493ce9faa08a50e6b4d2c34d.json index ecc26853a4..24e24adc17 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_fields_465afbed74842189a7651d5ea128874bbcfcb0dc0e4c32ab8ea2d3c8a4d32a03/msg_GetContestedResourcesRequest_6ec2c2e0abfde5adf1d65d2b06ba7401f9ed4ef7493ce9faa08a50e6b4d2c34d.json and b/packages/rs-sdk/tests/vectors/contested_resources_fields_465afbed74842189a7651d5ea128874bbcfcb0dc0e4c32ab8ea2d3c8a4d32a03/msg_GetContestedResourcesRequest_6ec2c2e0abfde5adf1d65d2b06ba7401f9ed4ef7493ce9faa08a50e6b4d2c34d.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_473cf8e4a270ced75e199e5a3e907b4df4cd66b64365d1ac77c45bcaed443a03/msg_GetContestedResourcesRequest_80ba1d11caa6442b39ab0f05e7fd84b9984fd04a4ca40a146aea81c3ea5c39ef.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_473cf8e4a270ced75e199e5a3e907b4df4cd66b64365d1ac77c45bcaed443a03/msg_GetContestedResourcesRequest_80ba1d11caa6442b39ab0f05e7fd84b9984fd04a4ca40a146aea81c3ea5c39ef.json index f4c8ab177b..75cb49e824 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_fields_473cf8e4a270ced75e199e5a3e907b4df4cd66b64365d1ac77c45bcaed443a03/msg_GetContestedResourcesRequest_80ba1d11caa6442b39ab0f05e7fd84b9984fd04a4ca40a146aea81c3ea5c39ef.json and b/packages/rs-sdk/tests/vectors/contested_resources_fields_473cf8e4a270ced75e199e5a3e907b4df4cd66b64365d1ac77c45bcaed443a03/msg_GetContestedResourcesRequest_80ba1d11caa6442b39ab0f05e7fd84b9984fd04a4ca40a146aea81c3ea5c39ef.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_473cf8e4a270ced75e199e5a3e907b4df4cd66b64365d1ac77c45bcaed443a03/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_473cf8e4a270ced75e199e5a3e907b4df4cd66b64365d1ac77c45bcaed443a03/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json index 808b4f0118..e64b73d8a7 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_fields_473cf8e4a270ced75e199e5a3e907b4df4cd66b64365d1ac77c45bcaed443a03/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json and b/packages/rs-sdk/tests/vectors/contested_resources_fields_473cf8e4a270ced75e199e5a3e907b4df4cd66b64365d1ac77c45bcaed443a03/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_473cf8e4a270ced75e199e5a3e907b4df4cd66b64365d1ac77c45bcaed443a03/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_473cf8e4a270ced75e199e5a3e907b4df4cd66b64365d1ac77c45bcaed443a03/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/contested_resources_fields_473cf8e4a270ced75e199e5a3e907b4df4cd66b64365d1ac77c45bcaed443a03/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_473cf8e4a270ced75e199e5a3e907b4df4cd66b64365d1ac77c45bcaed443a03/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_473cf8e4a270ced75e199e5a3e907b4df4cd66b64365d1ac77c45bcaed443a03/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/contested_resources_fields_473cf8e4a270ced75e199e5a3e907b4df4cd66b64365d1ac77c45bcaed443a03/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_8ae090a1b1351d43a2df073800c78374b4bab6d7f26b2f163436712312233554/msg_GetContestedResourcesRequest_ad9ea5e65a5302d37eee711c9465a0fc6bf7035276b9ae4be55fb15774eb54e7.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_8ae090a1b1351d43a2df073800c78374b4bab6d7f26b2f163436712312233554/msg_GetContestedResourcesRequest_ad9ea5e65a5302d37eee711c9465a0fc6bf7035276b9ae4be55fb15774eb54e7.json index 92986258ba..f7be916288 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_fields_8ae090a1b1351d43a2df073800c78374b4bab6d7f26b2f163436712312233554/msg_GetContestedResourcesRequest_ad9ea5e65a5302d37eee711c9465a0fc6bf7035276b9ae4be55fb15774eb54e7.json and b/packages/rs-sdk/tests/vectors/contested_resources_fields_8ae090a1b1351d43a2df073800c78374b4bab6d7f26b2f163436712312233554/msg_GetContestedResourcesRequest_ad9ea5e65a5302d37eee711c9465a0fc6bf7035276b9ae4be55fb15774eb54e7.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_93d82dd3f64ebcd26d544e5e5d2933bfca11e0f2d904628d007ad04a12e66ea1/msg_GetContestedResourcesRequest_45785d2d1a5309b4b29ccfa650f30e457c9e0f5d50a3b8f0f86e1da3420877d7.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_93d82dd3f64ebcd26d544e5e5d2933bfca11e0f2d904628d007ad04a12e66ea1/msg_GetContestedResourcesRequest_45785d2d1a5309b4b29ccfa650f30e457c9e0f5d50a3b8f0f86e1da3420877d7.json index 729ec47123..31b3993614 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_fields_93d82dd3f64ebcd26d544e5e5d2933bfca11e0f2d904628d007ad04a12e66ea1/msg_GetContestedResourcesRequest_45785d2d1a5309b4b29ccfa650f30e457c9e0f5d50a3b8f0f86e1da3420877d7.json and b/packages/rs-sdk/tests/vectors/contested_resources_fields_93d82dd3f64ebcd26d544e5e5d2933bfca11e0f2d904628d007ad04a12e66ea1/msg_GetContestedResourcesRequest_45785d2d1a5309b4b29ccfa650f30e457c9e0f5d50a3b8f0f86e1da3420877d7.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_948b5a301af5fc73db7fed418a4fe90f64952b4ddd6b03a7f21d029dc110af50/msg_GetContestedResourcesRequest_5396ff2dd55051d854e18e406fbbfa6b1eff43954af904bce8f123fed7515132.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_948b5a301af5fc73db7fed418a4fe90f64952b4ddd6b03a7f21d029dc110af50/msg_GetContestedResourcesRequest_5396ff2dd55051d854e18e406fbbfa6b1eff43954af904bce8f123fed7515132.json index 827e98aa3b..cd92b9b9ab 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_fields_948b5a301af5fc73db7fed418a4fe90f64952b4ddd6b03a7f21d029dc110af50/msg_GetContestedResourcesRequest_5396ff2dd55051d854e18e406fbbfa6b1eff43954af904bce8f123fed7515132.json and b/packages/rs-sdk/tests/vectors/contested_resources_fields_948b5a301af5fc73db7fed418a4fe90f64952b4ddd6b03a7f21d029dc110af50/msg_GetContestedResourcesRequest_5396ff2dd55051d854e18e406fbbfa6b1eff43954af904bce8f123fed7515132.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_948b5a301af5fc73db7fed418a4fe90f64952b4ddd6b03a7f21d029dc110af50/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_948b5a301af5fc73db7fed418a4fe90f64952b4ddd6b03a7f21d029dc110af50/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json index 808b4f0118..e64b73d8a7 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_fields_948b5a301af5fc73db7fed418a4fe90f64952b4ddd6b03a7f21d029dc110af50/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json and b/packages/rs-sdk/tests/vectors/contested_resources_fields_948b5a301af5fc73db7fed418a4fe90f64952b4ddd6b03a7f21d029dc110af50/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_948b5a301af5fc73db7fed418a4fe90f64952b4ddd6b03a7f21d029dc110af50/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_948b5a301af5fc73db7fed418a4fe90f64952b4ddd6b03a7f21d029dc110af50/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/contested_resources_fields_948b5a301af5fc73db7fed418a4fe90f64952b4ddd6b03a7f21d029dc110af50/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_948b5a301af5fc73db7fed418a4fe90f64952b4ddd6b03a7f21d029dc110af50/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_948b5a301af5fc73db7fed418a4fe90f64952b4ddd6b03a7f21d029dc110af50/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/contested_resources_fields_948b5a301af5fc73db7fed418a4fe90f64952b4ddd6b03a7f21d029dc110af50/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_9f57b982b3e3b0286093d8b48ab27b87b22f67a172579913f2fec7a6b5ea31b7/msg_GetContestedResourcesRequest_f06ea270a508a9d9c386b8da170f67620695a23f63dc7376bd4a509e93335ce9.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_9f57b982b3e3b0286093d8b48ab27b87b22f67a172579913f2fec7a6b5ea31b7/msg_GetContestedResourcesRequest_f06ea270a508a9d9c386b8da170f67620695a23f63dc7376bd4a509e93335ce9.json index df53609095..a0e087bdda 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_fields_9f57b982b3e3b0286093d8b48ab27b87b22f67a172579913f2fec7a6b5ea31b7/msg_GetContestedResourcesRequest_f06ea270a508a9d9c386b8da170f67620695a23f63dc7376bd4a509e93335ce9.json and b/packages/rs-sdk/tests/vectors/contested_resources_fields_9f57b982b3e3b0286093d8b48ab27b87b22f67a172579913f2fec7a6b5ea31b7/msg_GetContestedResourcesRequest_f06ea270a508a9d9c386b8da170f67620695a23f63dc7376bd4a509e93335ce9.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_9f57b982b3e3b0286093d8b48ab27b87b22f67a172579913f2fec7a6b5ea31b7/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_9f57b982b3e3b0286093d8b48ab27b87b22f67a172579913f2fec7a6b5ea31b7/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json index 808b4f0118..e64b73d8a7 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_fields_9f57b982b3e3b0286093d8b48ab27b87b22f67a172579913f2fec7a6b5ea31b7/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json and b/packages/rs-sdk/tests/vectors/contested_resources_fields_9f57b982b3e3b0286093d8b48ab27b87b22f67a172579913f2fec7a6b5ea31b7/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_9f57b982b3e3b0286093d8b48ab27b87b22f67a172579913f2fec7a6b5ea31b7/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_9f57b982b3e3b0286093d8b48ab27b87b22f67a172579913f2fec7a6b5ea31b7/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/contested_resources_fields_9f57b982b3e3b0286093d8b48ab27b87b22f67a172579913f2fec7a6b5ea31b7/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_9f57b982b3e3b0286093d8b48ab27b87b22f67a172579913f2fec7a6b5ea31b7/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_9f57b982b3e3b0286093d8b48ab27b87b22f67a172579913f2fec7a6b5ea31b7/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/contested_resources_fields_9f57b982b3e3b0286093d8b48ab27b87b22f67a172579913f2fec7a6b5ea31b7/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_afc96196b7f1e6f82927d852558ac6e2327f8c74d931d667fbe120136ceb5437/msg_GetContestedResourcesRequest_533d36b545633f42c839ba9038ec301f2326c1e59739fe07fb863facb5f2b5a8.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_afc96196b7f1e6f82927d852558ac6e2327f8c74d931d667fbe120136ceb5437/msg_GetContestedResourcesRequest_533d36b545633f42c839ba9038ec301f2326c1e59739fe07fb863facb5f2b5a8.json index 3273894e34..893e829a3c 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_fields_afc96196b7f1e6f82927d852558ac6e2327f8c74d931d667fbe120136ceb5437/msg_GetContestedResourcesRequest_533d36b545633f42c839ba9038ec301f2326c1e59739fe07fb863facb5f2b5a8.json and b/packages/rs-sdk/tests/vectors/contested_resources_fields_afc96196b7f1e6f82927d852558ac6e2327f8c74d931d667fbe120136ceb5437/msg_GetContestedResourcesRequest_533d36b545633f42c839ba9038ec301f2326c1e59739fe07fb863facb5f2b5a8.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_b7df460e812b958de6e703d8ea325df9aab3448d0409ece3f0baf1d26629e44f/msg_GetContestedResourcesRequest_c8608f7aed7bbe4ced03c9c23f1ce28a227def58e23c39e0384e0cc02fe6360b.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_b7df460e812b958de6e703d8ea325df9aab3448d0409ece3f0baf1d26629e44f/msg_GetContestedResourcesRequest_c8608f7aed7bbe4ced03c9c23f1ce28a227def58e23c39e0384e0cc02fe6360b.json index b689eb3042..46ce3e849c 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_fields_b7df460e812b958de6e703d8ea325df9aab3448d0409ece3f0baf1d26629e44f/msg_GetContestedResourcesRequest_c8608f7aed7bbe4ced03c9c23f1ce28a227def58e23c39e0384e0cc02fe6360b.json and b/packages/rs-sdk/tests/vectors/contested_resources_fields_b7df460e812b958de6e703d8ea325df9aab3448d0409ece3f0baf1d26629e44f/msg_GetContestedResourcesRequest_c8608f7aed7bbe4ced03c9c23f1ce28a227def58e23c39e0384e0cc02fe6360b.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_b7df460e812b958de6e703d8ea325df9aab3448d0409ece3f0baf1d26629e44f/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_b7df460e812b958de6e703d8ea325df9aab3448d0409ece3f0baf1d26629e44f/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json index 808b4f0118..e64b73d8a7 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_fields_b7df460e812b958de6e703d8ea325df9aab3448d0409ece3f0baf1d26629e44f/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json and b/packages/rs-sdk/tests/vectors/contested_resources_fields_b7df460e812b958de6e703d8ea325df9aab3448d0409ece3f0baf1d26629e44f/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_b7df460e812b958de6e703d8ea325df9aab3448d0409ece3f0baf1d26629e44f/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_b7df460e812b958de6e703d8ea325df9aab3448d0409ece3f0baf1d26629e44f/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/contested_resources_fields_b7df460e812b958de6e703d8ea325df9aab3448d0409ece3f0baf1d26629e44f/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_b7df460e812b958de6e703d8ea325df9aab3448d0409ece3f0baf1d26629e44f/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_b7df460e812b958de6e703d8ea325df9aab3448d0409ece3f0baf1d26629e44f/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/contested_resources_fields_b7df460e812b958de6e703d8ea325df9aab3448d0409ece3f0baf1d26629e44f/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_c1b9b8bbe62a89fc36d21db697688ddf4d34adb509daae02524ac41b312105a4/msg_GetContestedResourcesRequest_f063860c9156f1eb609f8f0cccf51b74928ffdfac56bc589d217525ce101d35b.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_c1b9b8bbe62a89fc36d21db697688ddf4d34adb509daae02524ac41b312105a4/msg_GetContestedResourcesRequest_f063860c9156f1eb609f8f0cccf51b74928ffdfac56bc589d217525ce101d35b.json index f4584c3156..2b45b862ed 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_fields_c1b9b8bbe62a89fc36d21db697688ddf4d34adb509daae02524ac41b312105a4/msg_GetContestedResourcesRequest_f063860c9156f1eb609f8f0cccf51b74928ffdfac56bc589d217525ce101d35b.json and b/packages/rs-sdk/tests/vectors/contested_resources_fields_c1b9b8bbe62a89fc36d21db697688ddf4d34adb509daae02524ac41b312105a4/msg_GetContestedResourcesRequest_f063860c9156f1eb609f8f0cccf51b74928ffdfac56bc589d217525ce101d35b.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_ca7552f3c1737e70f4781f101ec9bf73f52ab260cbde3cddcbb38665da1db8f9/msg_GetContestedResourcesRequest_1935cb975797e6d5dc29cca6923b9c94b8d468da725cc241df1601e630036b97.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_ca7552f3c1737e70f4781f101ec9bf73f52ab260cbde3cddcbb38665da1db8f9/msg_GetContestedResourcesRequest_1935cb975797e6d5dc29cca6923b9c94b8d468da725cc241df1601e630036b97.json index 4e53c65fa7..2f7f95e70f 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_fields_ca7552f3c1737e70f4781f101ec9bf73f52ab260cbde3cddcbb38665da1db8f9/msg_GetContestedResourcesRequest_1935cb975797e6d5dc29cca6923b9c94b8d468da725cc241df1601e630036b97.json and b/packages/rs-sdk/tests/vectors/contested_resources_fields_ca7552f3c1737e70f4781f101ec9bf73f52ab260cbde3cddcbb38665da1db8f9/msg_GetContestedResourcesRequest_1935cb975797e6d5dc29cca6923b9c94b8d468da725cc241df1601e630036b97.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_ccb199c48ee58a8bb98742b964cba7bda3b4469b740201d2628f15f926f39347/msg_GetContestedResourcesRequest_7dd3b1061a019dac5fa1f385b8bd5387b9cca48a3062a4db8bf0341a839f2bae.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_ccb199c48ee58a8bb98742b964cba7bda3b4469b740201d2628f15f926f39347/msg_GetContestedResourcesRequest_7dd3b1061a019dac5fa1f385b8bd5387b9cca48a3062a4db8bf0341a839f2bae.json index 4f9cc1a381..44352f58b7 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_fields_ccb199c48ee58a8bb98742b964cba7bda3b4469b740201d2628f15f926f39347/msg_GetContestedResourcesRequest_7dd3b1061a019dac5fa1f385b8bd5387b9cca48a3062a4db8bf0341a839f2bae.json and b/packages/rs-sdk/tests/vectors/contested_resources_fields_ccb199c48ee58a8bb98742b964cba7bda3b4469b740201d2628f15f926f39347/msg_GetContestedResourcesRequest_7dd3b1061a019dac5fa1f385b8bd5387b9cca48a3062a4db8bf0341a839f2bae.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_ccb199c48ee58a8bb98742b964cba7bda3b4469b740201d2628f15f926f39347/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_ccb199c48ee58a8bb98742b964cba7bda3b4469b740201d2628f15f926f39347/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json index 808b4f0118..e64b73d8a7 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_fields_ccb199c48ee58a8bb98742b964cba7bda3b4469b740201d2628f15f926f39347/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json and b/packages/rs-sdk/tests/vectors/contested_resources_fields_ccb199c48ee58a8bb98742b964cba7bda3b4469b740201d2628f15f926f39347/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_ccb199c48ee58a8bb98742b964cba7bda3b4469b740201d2628f15f926f39347/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_ccb199c48ee58a8bb98742b964cba7bda3b4469b740201d2628f15f926f39347/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/contested_resources_fields_ccb199c48ee58a8bb98742b964cba7bda3b4469b740201d2628f15f926f39347/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_ccb199c48ee58a8bb98742b964cba7bda3b4469b740201d2628f15f926f39347/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_ccb199c48ee58a8bb98742b964cba7bda3b4469b740201d2628f15f926f39347/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/contested_resources_fields_ccb199c48ee58a8bb98742b964cba7bda3b4469b740201d2628f15f926f39347/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_d838e1005b493d45e2b6b39712f4aa144f22b4daa1470657c0ab97ffd4f04455/msg_GetContestedResourcesRequest_6c409367beedcc384cfd90f36b1b38482a11c7731ba150ddc1812e3310013c7a.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_d838e1005b493d45e2b6b39712f4aa144f22b4daa1470657c0ab97ffd4f04455/msg_GetContestedResourcesRequest_6c409367beedcc384cfd90f36b1b38482a11c7731ba150ddc1812e3310013c7a.json deleted file mode 100644 index 69bf65c5ae..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_fields_d838e1005b493d45e2b6b39712f4aa144f22b4daa1470657c0ab97ffd4f04455/msg_GetContestedResourcesRequest_6c409367beedcc384cfd90f36b1b38482a11c7731ba150ddc1812e3310013c7a.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_f7abf9d04f5e79fc1bbc2cc010a229ec4b04185dc80580e7e8dd783b45c4eac6/msg_GetContestedResourcesRequest_676e45023cbf73697f012bc5ac51a7310d759b9fe67594f3899f1e0485c383f1.json b/packages/rs-sdk/tests/vectors/contested_resources_fields_f7abf9d04f5e79fc1bbc2cc010a229ec4b04185dc80580e7e8dd783b45c4eac6/msg_GetContestedResourcesRequest_676e45023cbf73697f012bc5ac51a7310d759b9fe67594f3899f1e0485c383f1.json index 08bfc6a975..c4ade09b1a 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_fields_f7abf9d04f5e79fc1bbc2cc010a229ec4b04185dc80580e7e8dd783b45c4eac6/msg_GetContestedResourcesRequest_676e45023cbf73697f012bc5ac51a7310d759b9fe67594f3899f1e0485c383f1.json and b/packages/rs-sdk/tests/vectors/contested_resources_fields_f7abf9d04f5e79fc1bbc2cc010a229ec4b04185dc80580e7e8dd783b45c4eac6/msg_GetContestedResourcesRequest_676e45023cbf73697f012bc5ac51a7310d759b9fe67594f3899f1e0485c383f1.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_13743b3cba702fc90e3618172a46e3dbf9ca8dadcb275c2c28a6dee9e033e292.json b/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_13743b3cba702fc90e3618172a46e3dbf9ca8dadcb275c2c28a6dee9e033e292.json new file mode 100644 index 0000000000..fb031eb0b8 Binary files /dev/null and b/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_13743b3cba702fc90e3618172a46e3dbf9ca8dadcb275c2c28a6dee9e033e292.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_1501210861eb1ce786ba78ba0d7b68db1c1d188ebf01dca2745102e51d0016e4.json b/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_1501210861eb1ce786ba78ba0d7b68db1c1d188ebf01dca2745102e51d0016e4.json deleted file mode 100644 index 4e733b1944..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_1501210861eb1ce786ba78ba0d7b68db1c1d188ebf01dca2745102e51d0016e4.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_1dbad85f242dfc488bf6a736c3c55774151848b669401ef44deadc605b0d278f.json b/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_1dbad85f242dfc488bf6a736c3c55774151848b669401ef44deadc605b0d278f.json new file mode 100644 index 0000000000..60d16671ca Binary files /dev/null and b/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_1dbad85f242dfc488bf6a736c3c55774151848b669401ef44deadc605b0d278f.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_37c394b62a91dfe665432198561649a7d9108f9b96fc074e1da61f0fa19d3b5b.json b/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_37c394b62a91dfe665432198561649a7d9108f9b96fc074e1da61f0fa19d3b5b.json index 923641d5df..6cf6526e77 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_37c394b62a91dfe665432198561649a7d9108f9b96fc074e1da61f0fa19d3b5b.json and b/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_37c394b62a91dfe665432198561649a7d9108f9b96fc074e1da61f0fa19d3b5b.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_3b4ade5c7a2d0d346627a4ee2424f404a90172ba46f3ce4973a5f789c7f89cfa.json b/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_3b4ade5c7a2d0d346627a4ee2424f404a90172ba46f3ce4973a5f789c7f89cfa.json deleted file mode 100644 index 07e4176f45..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_3b4ade5c7a2d0d346627a4ee2424f404a90172ba46f3ce4973a5f789c7f89cfa.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_40ef2688b5170b8889257682591fb6f1f5b483c9e0840abcafe5bcc30b9f0bdd.json b/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_40ef2688b5170b8889257682591fb6f1f5b483c9e0840abcafe5bcc30b9f0bdd.json deleted file mode 100644 index f670b0fb1e..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_40ef2688b5170b8889257682591fb6f1f5b483c9e0840abcafe5bcc30b9f0bdd.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_41eaedc5b2d0e43291fbc6f3d9bf78e918d684b0f66257a9c7d33e2b62bfcfe8.json b/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_41eaedc5b2d0e43291fbc6f3d9bf78e918d684b0f66257a9c7d33e2b62bfcfe8.json deleted file mode 100644 index c759b89111..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_41eaedc5b2d0e43291fbc6f3d9bf78e918d684b0f66257a9c7d33e2b62bfcfe8.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_51c71e845c3f579ad3ced0e35efed11f384144320c099f54b2530f0be42f8664.json b/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_51c71e845c3f579ad3ced0e35efed11f384144320c099f54b2530f0be42f8664.json index 1278507ddd..001e737c21 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_51c71e845c3f579ad3ced0e35efed11f384144320c099f54b2530f0be42f8664.json and b/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_51c71e845c3f579ad3ced0e35efed11f384144320c099f54b2530f0be42f8664.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_7785e71a6245fd4ec421fef4c411f4a723908b4ee33c4612727d101cf58f3394.json b/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_7785e71a6245fd4ec421fef4c411f4a723908b4ee33c4612727d101cf58f3394.json index f626b72903..5e90fa6a3a 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_7785e71a6245fd4ec421fef4c411f4a723908b4ee33c4612727d101cf58f3394.json and b/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_7785e71a6245fd4ec421fef4c411f4a723908b4ee33c4612727d101cf58f3394.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_81cdd94e16c4b296934dfa5bae8d724c98cd0e3653d01d091232c8053d0c6ecb.json b/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_81cdd94e16c4b296934dfa5bae8d724c98cd0e3653d01d091232c8053d0c6ecb.json new file mode 100644 index 0000000000..bce0226539 Binary files /dev/null and b/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_81cdd94e16c4b296934dfa5bae8d724c98cd0e3653d01d091232c8053d0c6ecb.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_8f4daadf3e41747492cd381cbbd1cf33dd52735f597de4b4c804effd2600d135.json b/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_8f4daadf3e41747492cd381cbbd1cf33dd52735f597de4b4c804effd2600d135.json index 84e1f32ded..065e6df12c 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_8f4daadf3e41747492cd381cbbd1cf33dd52735f597de4b4c804effd2600d135.json and b/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_8f4daadf3e41747492cd381cbbd1cf33dd52735f597de4b4c804effd2600d135.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_db80e293e51ffd1cd840ffc18853abc50fc58895d65ce023d46e2c6ded39d257.json b/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_db80e293e51ffd1cd840ffc18853abc50fc58895d65ce023d46e2c6ded39d257.json new file mode 100644 index 0000000000..9c32b4369b Binary files /dev/null and b/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_db80e293e51ffd1cd840ffc18853abc50fc58895d65ce023d46e2c6ded39d257.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_f4686bfe637dbe76a6de26e085c3fb36ec9234525729613a7a0a3138baff6d6a.json b/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_f4686bfe637dbe76a6de26e085c3fb36ec9234525729613a7a0a3138baff6d6a.json deleted file mode 100644 index 81e24ba8f7..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_f4686bfe637dbe76a6de26e085c3fb36ec9234525729613a7a0a3138baff6d6a.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_ff56aa1c3d107ee8f232f889ce6d623ba6f340f6953cc1b450631f9e38394fa6.json b/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_ff56aa1c3d107ee8f232f889ce6d623ba6f340f6953cc1b450631f9e38394fa6.json deleted file mode 100644 index 0993f06871..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetContestedResourcesRequest_ff56aa1c3d107ee8f232f889ce6d623ba6f340f6953cc1b450631f9e38394fa6.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json b/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json index 808b4f0118..e64b73d8a7 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json and b/packages/rs-sdk/tests/vectors/contested_resources_limit/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_limit/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/contested_resources_limit/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/contested_resources_limit/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_resources_limit/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/contested_resources_limit/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/contested_resources_limit/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_00b7bac855f345476da659743b50939881e64c648abe4ad1313f570e98350d1f.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_00b7bac855f345476da659743b50939881e64c648abe4ad1313f570e98350d1f.json deleted file mode 100644 index c445831dad..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_00b7bac855f345476da659743b50939881e64c648abe4ad1313f570e98350d1f.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_015a1d2bbc282c8e87eae9748ffa72db1958762a26a6d156f618978402b1fe4d.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_015a1d2bbc282c8e87eae9748ffa72db1958762a26a6d156f618978402b1fe4d.json new file mode 100644 index 0000000000..da4168c6a6 Binary files /dev/null and b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_015a1d2bbc282c8e87eae9748ffa72db1958762a26a6d156f618978402b1fe4d.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_061d1caf0f2b50525a3e3506457850dfa046ebabf22c41f663ba73e3d730cf95.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_061d1caf0f2b50525a3e3506457850dfa046ebabf22c41f663ba73e3d730cf95.json deleted file mode 100644 index fc29731e9c..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_061d1caf0f2b50525a3e3506457850dfa046ebabf22c41f663ba73e3d730cf95.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_09540b24c4d98960527f45bc20e828d50a4fa7b3230d23ddfac563877efd61e2.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_09540b24c4d98960527f45bc20e828d50a4fa7b3230d23ddfac563877efd61e2.json index a5a70d0893..6cbf5c1a05 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_09540b24c4d98960527f45bc20e828d50a4fa7b3230d23ddfac563877efd61e2.json and b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_09540b24c4d98960527f45bc20e828d50a4fa7b3230d23ddfac563877efd61e2.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_12a83820f10ece0b180bee7d58c1d4e66aec36ada2efbb1072f2196b5b856222.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_12a83820f10ece0b180bee7d58c1d4e66aec36ada2efbb1072f2196b5b856222.json index 9ebddbd993..a729e70831 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_12a83820f10ece0b180bee7d58c1d4e66aec36ada2efbb1072f2196b5b856222.json and b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_12a83820f10ece0b180bee7d58c1d4e66aec36ada2efbb1072f2196b5b856222.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_15d5b23b6b2036272bc068779fecda5177deb7014745c4e797a386e792e55fe7.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_15d5b23b6b2036272bc068779fecda5177deb7014745c4e797a386e792e55fe7.json deleted file mode 100644 index eda9be4b2a..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_15d5b23b6b2036272bc068779fecda5177deb7014745c4e797a386e792e55fe7.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_17549c499ab1bade46e96fe67bc637ba87f58b1be40e677b000fec75c2af2319.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_17549c499ab1bade46e96fe67bc637ba87f58b1be40e677b000fec75c2af2319.json new file mode 100644 index 0000000000..4cc85ee8af Binary files /dev/null and b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_17549c499ab1bade46e96fe67bc637ba87f58b1be40e677b000fec75c2af2319.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_1b0ced62edb21c226e57f54549af899d86a39c5259bdade02cd2e90c72b20388.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_1b0ced62edb21c226e57f54549af899d86a39c5259bdade02cd2e90c72b20388.json deleted file mode 100644 index f071276122..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_1b0ced62edb21c226e57f54549af899d86a39c5259bdade02cd2e90c72b20388.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_1ef94b2835536781d5c37af2990f1400abf368ef25742ac1e4ec0350cc98334d.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_1ef94b2835536781d5c37af2990f1400abf368ef25742ac1e4ec0350cc98334d.json new file mode 100644 index 0000000000..13af120819 Binary files /dev/null and b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_1ef94b2835536781d5c37af2990f1400abf368ef25742ac1e4ec0350cc98334d.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_1f269e8f7c30fc23f85f4aa8c46214b0f6f6b7280b0ea686c2e0070f330add82.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_1f269e8f7c30fc23f85f4aa8c46214b0f6f6b7280b0ea686c2e0070f330add82.json deleted file mode 100644 index 7c91cd21e1..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_1f269e8f7c30fc23f85f4aa8c46214b0f6f6b7280b0ea686c2e0070f330add82.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_1f4401f226caa8a5d77354422e8e82bd614dd12d29f8041839df02c578fb7ed2.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_1f4401f226caa8a5d77354422e8e82bd614dd12d29f8041839df02c578fb7ed2.json deleted file mode 100644 index 89b1c78f64..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_1f4401f226caa8a5d77354422e8e82bd614dd12d29f8041839df02c578fb7ed2.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_1f5b3258963ef7c64984f0d15bbbadb27060d67cd8420c1101237534133c72e4.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_1f5b3258963ef7c64984f0d15bbbadb27060d67cd8420c1101237534133c72e4.json deleted file mode 100644 index 2599be886c..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_1f5b3258963ef7c64984f0d15bbbadb27060d67cd8420c1101237534133c72e4.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_247a25c20366e893f60cc0d9321dd268f3555081d2a3a5e112886b1c78b4009f.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_247a25c20366e893f60cc0d9321dd268f3555081d2a3a5e112886b1c78b4009f.json index d118b25e8a..f36f9ebdb0 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_247a25c20366e893f60cc0d9321dd268f3555081d2a3a5e112886b1c78b4009f.json and b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_247a25c20366e893f60cc0d9321dd268f3555081d2a3a5e112886b1c78b4009f.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_26832b1a90d093f54c3a5eae4903549f6e73f467779e83ef5729423f6ae43ac5.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_26832b1a90d093f54c3a5eae4903549f6e73f467779e83ef5729423f6ae43ac5.json new file mode 100644 index 0000000000..bda5419540 Binary files /dev/null and b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_26832b1a90d093f54c3a5eae4903549f6e73f467779e83ef5729423f6ae43ac5.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_2aeaf8f528e207ff093c003b46e3c4cd53b525ef27be36077437e8b9b8ffadd8.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_2aeaf8f528e207ff093c003b46e3c4cd53b525ef27be36077437e8b9b8ffadd8.json index e6948dc860..c735857dd4 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_2aeaf8f528e207ff093c003b46e3c4cd53b525ef27be36077437e8b9b8ffadd8.json and b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_2aeaf8f528e207ff093c003b46e3c4cd53b525ef27be36077437e8b9b8ffadd8.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_2b0bd7604b1c5ccc1f01ff0da46a4b98bc0a965fb8b29d1b552d5a29ae192ab9.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_2b0bd7604b1c5ccc1f01ff0da46a4b98bc0a965fb8b29d1b552d5a29ae192ab9.json deleted file mode 100644 index 3c5d236a43..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_2b0bd7604b1c5ccc1f01ff0da46a4b98bc0a965fb8b29d1b552d5a29ae192ab9.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_307328f0782bfb7cdc1e11c92af84e6f2c2b37a1da002e0a485ad7bc30b764bb.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_307328f0782bfb7cdc1e11c92af84e6f2c2b37a1da002e0a485ad7bc30b764bb.json deleted file mode 100644 index dbbd1e333e..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_307328f0782bfb7cdc1e11c92af84e6f2c2b37a1da002e0a485ad7bc30b764bb.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_4135759e5ad1ee131eb82fb9c0b66c773b6b6433a3502423706160e543a24f13.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_4135759e5ad1ee131eb82fb9c0b66c773b6b6433a3502423706160e543a24f13.json new file mode 100644 index 0000000000..d3f3f84488 Binary files /dev/null and b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_4135759e5ad1ee131eb82fb9c0b66c773b6b6433a3502423706160e543a24f13.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_4153546f1e76e6a6c20fb42644192ff55e2434e36b13595910f1c02c9473b680.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_4153546f1e76e6a6c20fb42644192ff55e2434e36b13595910f1c02c9473b680.json deleted file mode 100644 index b700bfc7fe..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_4153546f1e76e6a6c20fb42644192ff55e2434e36b13595910f1c02c9473b680.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_43103f757a1b16752bdf92997fe1d98cc81197999226ba2a06e1002b94fa99ba.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_43103f757a1b16752bdf92997fe1d98cc81197999226ba2a06e1002b94fa99ba.json deleted file mode 100644 index cbd3d73ca3..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_43103f757a1b16752bdf92997fe1d98cc81197999226ba2a06e1002b94fa99ba.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_49593e41313ee6da1685f4a59d9e8d08982802ad41ae314ebdd902533315d200.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_49593e41313ee6da1685f4a59d9e8d08982802ad41ae314ebdd902533315d200.json deleted file mode 100644 index 396a405b2a..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_49593e41313ee6da1685f4a59d9e8d08982802ad41ae314ebdd902533315d200.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_4bc3a31c696a234e5ef24e6a1d5f8d622dd35b75e8090c88ddc45fd4e669d448.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_4bc3a31c696a234e5ef24e6a1d5f8d622dd35b75e8090c88ddc45fd4e669d448.json deleted file mode 100644 index f90eb17e1a..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_4bc3a31c696a234e5ef24e6a1d5f8d622dd35b75e8090c88ddc45fd4e669d448.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_53acfa6801e8faf3968fcb37b1977aa3058a5e96a54279f3cd7b134ef5efcbb1.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_53acfa6801e8faf3968fcb37b1977aa3058a5e96a54279f3cd7b134ef5efcbb1.json index 3c675f72e9..0015c38c2a 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_53acfa6801e8faf3968fcb37b1977aa3058a5e96a54279f3cd7b134ef5efcbb1.json and b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_53acfa6801e8faf3968fcb37b1977aa3058a5e96a54279f3cd7b134ef5efcbb1.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_5685b7b4cb0467fc8d4021fb120b76feb7a8b605c1da4a28fc1fd42e93420169.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_5685b7b4cb0467fc8d4021fb120b76feb7a8b605c1da4a28fc1fd42e93420169.json deleted file mode 100644 index dedeb51050..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_5685b7b4cb0467fc8d4021fb120b76feb7a8b605c1da4a28fc1fd42e93420169.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_5878e49ba83fdab3110c674b3ffa4d5675d8b383091c3b9bff1366f82a3aa07b.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_5878e49ba83fdab3110c674b3ffa4d5675d8b383091c3b9bff1366f82a3aa07b.json new file mode 100644 index 0000000000..2b55bd20ab Binary files /dev/null and b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_5878e49ba83fdab3110c674b3ffa4d5675d8b383091c3b9bff1366f82a3aa07b.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_5dd4150344158e77182615c11c9a65ca8a14db4b0950279b5edbf16c6ef5572c.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_5dd4150344158e77182615c11c9a65ca8a14db4b0950279b5edbf16c6ef5572c.json deleted file mode 100644 index 7726ce6936..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_5dd4150344158e77182615c11c9a65ca8a14db4b0950279b5edbf16c6ef5572c.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_5ebeb7c01fffe047c9a91d9b3086ab5e43d4fb9c927bcab551e0c65be65c95c1.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_5ebeb7c01fffe047c9a91d9b3086ab5e43d4fb9c927bcab551e0c65be65c95c1.json new file mode 100644 index 0000000000..6e39af906e Binary files /dev/null and b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_5ebeb7c01fffe047c9a91d9b3086ab5e43d4fb9c927bcab551e0c65be65c95c1.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_61164ed4c833bb713ba73b843a1ac9fe0fc7e82040ccd47c874cd988de5a8574.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_61164ed4c833bb713ba73b843a1ac9fe0fc7e82040ccd47c874cd988de5a8574.json deleted file mode 100644 index 0d8699da07..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_61164ed4c833bb713ba73b843a1ac9fe0fc7e82040ccd47c874cd988de5a8574.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_6867758e065031acc5e4b6bf5ef3b70df05ee0895f634d3fdffa5e9c7fdee578.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_6867758e065031acc5e4b6bf5ef3b70df05ee0895f634d3fdffa5e9c7fdee578.json deleted file mode 100644 index a018630dd1..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_6867758e065031acc5e4b6bf5ef3b70df05ee0895f634d3fdffa5e9c7fdee578.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_6c085c067c576e2a1457a8e78370f9bf0a059ad2788d4630751cfb714a5a9762.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_6c085c067c576e2a1457a8e78370f9bf0a059ad2788d4630751cfb714a5a9762.json new file mode 100644 index 0000000000..6d4e77dc22 Binary files /dev/null and b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_6c085c067c576e2a1457a8e78370f9bf0a059ad2788d4630751cfb714a5a9762.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_74477b940a401b9daa770791ce4ffaf2f0b3d1a7ca2598153024a58bdea3b343.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_74477b940a401b9daa770791ce4ffaf2f0b3d1a7ca2598153024a58bdea3b343.json deleted file mode 100644 index bdfacb5013..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_74477b940a401b9daa770791ce4ffaf2f0b3d1a7ca2598153024a58bdea3b343.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_774f59e620022defe8cede5a337b235f0c1d8085680124a1ddf9d72502e1835b.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_774f59e620022defe8cede5a337b235f0c1d8085680124a1ddf9d72502e1835b.json new file mode 100644 index 0000000000..4843ae6773 Binary files /dev/null and b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_774f59e620022defe8cede5a337b235f0c1d8085680124a1ddf9d72502e1835b.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_7e6aba0e36304760488e6c79655130dcb43dda8bfe725b4edb4b10dd8cdd687c.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_7e6aba0e36304760488e6c79655130dcb43dda8bfe725b4edb4b10dd8cdd687c.json deleted file mode 100644 index 6812e095d8..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_7e6aba0e36304760488e6c79655130dcb43dda8bfe725b4edb4b10dd8cdd687c.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_84129be05fe87a6227fd33f6a281e6062b594012b0f6d26dbb54c090b43170cc.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_84129be05fe87a6227fd33f6a281e6062b594012b0f6d26dbb54c090b43170cc.json deleted file mode 100644 index c0b0ba5a83..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_84129be05fe87a6227fd33f6a281e6062b594012b0f6d26dbb54c090b43170cc.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_8c2e50a4e3c6b6bcce52453520e5d377ddbe6cbdccdff3bb18a89ec8aee7fcec.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_8c2e50a4e3c6b6bcce52453520e5d377ddbe6cbdccdff3bb18a89ec8aee7fcec.json index b7f3e9d898..111b925791 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_8c2e50a4e3c6b6bcce52453520e5d377ddbe6cbdccdff3bb18a89ec8aee7fcec.json and b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_8c2e50a4e3c6b6bcce52453520e5d377ddbe6cbdccdff3bb18a89ec8aee7fcec.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_8f0699751716034f3fa7c28223c048daa8fc887b7fd9431b5b3ebc18bf6c7d42.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_8f0699751716034f3fa7c28223c048daa8fc887b7fd9431b5b3ebc18bf6c7d42.json new file mode 100644 index 0000000000..28655c36b4 Binary files /dev/null and b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_8f0699751716034f3fa7c28223c048daa8fc887b7fd9431b5b3ebc18bf6c7d42.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_91ed87367df512745f96a66d3309cf6980b6b126a73dd990b05887c3ec391b0a.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_91ed87367df512745f96a66d3309cf6980b6b126a73dd990b05887c3ec391b0a.json new file mode 100644 index 0000000000..853bcea5bc Binary files /dev/null and b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_91ed87367df512745f96a66d3309cf6980b6b126a73dd990b05887c3ec391b0a.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_926a2ab53948280066d8d01e7126cf4557623b124ff6f1e0131ae69643535b3d.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_926a2ab53948280066d8d01e7126cf4557623b124ff6f1e0131ae69643535b3d.json deleted file mode 100644 index 19e2c3381e..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_926a2ab53948280066d8d01e7126cf4557623b124ff6f1e0131ae69643535b3d.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_98569ec1918d08eb3547ba4c967535066f7babdbf0697172b281e941ef3a648a.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_98569ec1918d08eb3547ba4c967535066f7babdbf0697172b281e941ef3a648a.json deleted file mode 100644 index 33f16b8e2b..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_98569ec1918d08eb3547ba4c967535066f7babdbf0697172b281e941ef3a648a.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_9a9ab8f7de794f5cbd193c0a79bb64d9a30d277e5438a64f924837c460481679.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_9a9ab8f7de794f5cbd193c0a79bb64d9a30d277e5438a64f924837c460481679.json deleted file mode 100644 index 60b1f041bf..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_9a9ab8f7de794f5cbd193c0a79bb64d9a30d277e5438a64f924837c460481679.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_9bbca1d0964fff817f0ae605922a2614e9ae55d61ff889a99923b50dacf52c35.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_9bbca1d0964fff817f0ae605922a2614e9ae55d61ff889a99923b50dacf52c35.json deleted file mode 100644 index 2af0811b02..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_9bbca1d0964fff817f0ae605922a2614e9ae55d61ff889a99923b50dacf52c35.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_a4cecc3159e93091689acd02e9b10aa19eaf0c52fbcfada86b8600e9c659753a.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_a4cecc3159e93091689acd02e9b10aa19eaf0c52fbcfada86b8600e9c659753a.json new file mode 100644 index 0000000000..520388ac9b Binary files /dev/null and b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_a4cecc3159e93091689acd02e9b10aa19eaf0c52fbcfada86b8600e9c659753a.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_adad8ba03f57791b0c73db74cfbc98186f8f457f14160313b070d535fbe9aac9.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_adad8ba03f57791b0c73db74cfbc98186f8f457f14160313b070d535fbe9aac9.json deleted file mode 100644 index 809e65d83f..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_adad8ba03f57791b0c73db74cfbc98186f8f457f14160313b070d535fbe9aac9.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_b799ae8be5055118672da926306fcc750470faf458435db3d7e52a8557e0d52c.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_b799ae8be5055118672da926306fcc750470faf458435db3d7e52a8557e0d52c.json deleted file mode 100644 index d4fe9e5e75..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_b799ae8be5055118672da926306fcc750470faf458435db3d7e52a8557e0d52c.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_bd96b3514f2c3f1d32c725db2754e1905758178dce3e8085da8dbd0cce4053b7.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_bd96b3514f2c3f1d32c725db2754e1905758178dce3e8085da8dbd0cce4053b7.json new file mode 100644 index 0000000000..8d3dc391de Binary files /dev/null and b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_bd96b3514f2c3f1d32c725db2754e1905758178dce3e8085da8dbd0cce4053b7.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_c99e89c75ebdb8c051fa31ddc93b2d43564f484a6e44b32dc721c425cf3a7b8d.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_c99e89c75ebdb8c051fa31ddc93b2d43564f484a6e44b32dc721c425cf3a7b8d.json new file mode 100644 index 0000000000..2115034cdb Binary files /dev/null and b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_c99e89c75ebdb8c051fa31ddc93b2d43564f484a6e44b32dc721c425cf3a7b8d.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_c9d26c216a8382dee66a3be97b6a822571b9076725566d64e35d36a9cbe991eb.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_c9d26c216a8382dee66a3be97b6a822571b9076725566d64e35d36a9cbe991eb.json deleted file mode 100644 index 5c3f4242d5..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_c9d26c216a8382dee66a3be97b6a822571b9076725566d64e35d36a9cbe991eb.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_cbf94dc9a7e25b00b3a6d10a6efa3a5accdb36127a2e88a02f40578b6bebc0bc.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_cbf94dc9a7e25b00b3a6d10a6efa3a5accdb36127a2e88a02f40578b6bebc0bc.json deleted file mode 100644 index ecc6f4e290..0000000000 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_cbf94dc9a7e25b00b3a6d10a6efa3a5accdb36127a2e88a02f40578b6bebc0bc.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_f3cacf6ef5a1f01d07c3cb41c1b46b1a606a8ccb267440005793b49521c7849b.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_f3cacf6ef5a1f01d07c3cb41c1b46b1a606a8ccb267440005793b49521c7849b.json new file mode 100644 index 0000000000..95b52536f6 Binary files /dev/null and b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_f3cacf6ef5a1f01d07c3cb41c1b46b1a606a8ccb267440005793b49521c7849b.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_fe0d0995c36b430a2a76d1215f53b54536f53a4438de3ef85f387b058c226005.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_fe0d0995c36b430a2a76d1215f53b54536f53a4438de3ef85f387b058c226005.json new file mode 100644 index 0000000000..f0da7dc39e Binary files /dev/null and b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetContestedResourcesRequest_fe0d0995c36b430a2a76d1215f53b54536f53a4438de3ef85f387b058c226005.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json index 808b4f0118..e64b73d8a7 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json and b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/contested_resources_start_at_value/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__1dcc38056f4539944947f843fc5f119ce3058e09a215dcdfdd563c9aca6fc4d3/msg_GetContestedResourceVoteStateRequest_cf751de542a527e565d916c33542a952aa4f09be27ca526b34c4a2d6f7ec3f76.json b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__1dcc38056f4539944947f843fc5f119ce3058e09a215dcdfdd563c9aca6fc4d3/msg_GetContestedResourceVoteStateRequest_cf751de542a527e565d916c33542a952aa4f09be27ca526b34c4a2d6f7ec3f76.json index cc97903beb..2525a12580 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__1dcc38056f4539944947f843fc5f119ce3058e09a215dcdfdd563c9aca6fc4d3/msg_GetContestedResourceVoteStateRequest_cf751de542a527e565d916c33542a952aa4f09be27ca526b34c4a2d6f7ec3f76.json and b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__1dcc38056f4539944947f843fc5f119ce3058e09a215dcdfdd563c9aca6fc4d3/msg_GetContestedResourceVoteStateRequest_cf751de542a527e565d916c33542a952aa4f09be27ca526b34c4a2d6f7ec3f76.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__1df65b498b006bfa52a1c425f30183fdd50ed811f9cd65d2384e688409dfe252/msg_GetContestedResourceVoteStateRequest_b893574a2cd12595446c7084d714266c27c9b0d3c1c6b9dc022c7cf69fde2174.json b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__1df65b498b006bfa52a1c425f30183fdd50ed811f9cd65d2384e688409dfe252/msg_GetContestedResourceVoteStateRequest_b893574a2cd12595446c7084d714266c27c9b0d3c1c6b9dc022c7cf69fde2174.json index da2de8910b..d9005b6c65 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__1df65b498b006bfa52a1c425f30183fdd50ed811f9cd65d2384e688409dfe252/msg_GetContestedResourceVoteStateRequest_b893574a2cd12595446c7084d714266c27c9b0d3c1c6b9dc022c7cf69fde2174.json and b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__1df65b498b006bfa52a1c425f30183fdd50ed811f9cd65d2384e688409dfe252/msg_GetContestedResourceVoteStateRequest_b893574a2cd12595446c7084d714266c27c9b0d3c1c6b9dc022c7cf69fde2174.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__27af3929f22f30de9fa0b90a34194699c0d55b6accfc72374026d2d9bc0f9e01/msg_GetContestedResourceVoteStateRequest_c5783e3abe0971640509ed3b5e20092d1597a92997ac79de0ef89f4cde74aefc.json b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__27af3929f22f30de9fa0b90a34194699c0d55b6accfc72374026d2d9bc0f9e01/msg_GetContestedResourceVoteStateRequest_c5783e3abe0971640509ed3b5e20092d1597a92997ac79de0ef89f4cde74aefc.json index 8d738521a5..565e52a2d5 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__27af3929f22f30de9fa0b90a34194699c0d55b6accfc72374026d2d9bc0f9e01/msg_GetContestedResourceVoteStateRequest_c5783e3abe0971640509ed3b5e20092d1597a92997ac79de0ef89f4cde74aefc.json and b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__27af3929f22f30de9fa0b90a34194699c0d55b6accfc72374026d2d9bc0f9e01/msg_GetContestedResourceVoteStateRequest_c5783e3abe0971640509ed3b5e20092d1597a92997ac79de0ef89f4cde74aefc.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__2c32c08bee77a2d062db8d1cdb999a841b21043ccc5e7fc5ff1507f9703754a9/msg_GetContestedResourceVoteStateRequest_71f48f72373e5db9721e095e8cdc12823a7175b930f49aebb8d9844065da5b44.json b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__2c32c08bee77a2d062db8d1cdb999a841b21043ccc5e7fc5ff1507f9703754a9/msg_GetContestedResourceVoteStateRequest_71f48f72373e5db9721e095e8cdc12823a7175b930f49aebb8d9844065da5b44.json index 55e33840e7..8604262500 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__2c32c08bee77a2d062db8d1cdb999a841b21043ccc5e7fc5ff1507f9703754a9/msg_GetContestedResourceVoteStateRequest_71f48f72373e5db9721e095e8cdc12823a7175b930f49aebb8d9844065da5b44.json and b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__2c32c08bee77a2d062db8d1cdb999a841b21043ccc5e7fc5ff1507f9703754a9/msg_GetContestedResourceVoteStateRequest_71f48f72373e5db9721e095e8cdc12823a7175b930f49aebb8d9844065da5b44.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__2c32c08bee77a2d062db8d1cdb999a841b21043ccc5e7fc5ff1507f9703754a9/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__2c32c08bee77a2d062db8d1cdb999a841b21043ccc5e7fc5ff1507f9703754a9/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json index 808b4f0118..e64b73d8a7 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__2c32c08bee77a2d062db8d1cdb999a841b21043ccc5e7fc5ff1507f9703754a9/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json and b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__2c32c08bee77a2d062db8d1cdb999a841b21043ccc5e7fc5ff1507f9703754a9/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__2c32c08bee77a2d062db8d1cdb999a841b21043ccc5e7fc5ff1507f9703754a9/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__2c32c08bee77a2d062db8d1cdb999a841b21043ccc5e7fc5ff1507f9703754a9/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__2c32c08bee77a2d062db8d1cdb999a841b21043ccc5e7fc5ff1507f9703754a9/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__2c32c08bee77a2d062db8d1cdb999a841b21043ccc5e7fc5ff1507f9703754a9/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__2c32c08bee77a2d062db8d1cdb999a841b21043ccc5e7fc5ff1507f9703754a9/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__2c32c08bee77a2d062db8d1cdb999a841b21043ccc5e7fc5ff1507f9703754a9/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__4d228b5af660c840e140560916dee664696a82c2b75fda103a6490a0a0119fea/msg_GetContestedResourceVoteStateRequest_bd857f0f40a11ccbc620754f0b276da7bcf8bb6352f7f5f26cb8af584712e16a.json b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__4d228b5af660c840e140560916dee664696a82c2b75fda103a6490a0a0119fea/msg_GetContestedResourceVoteStateRequest_bd857f0f40a11ccbc620754f0b276da7bcf8bb6352f7f5f26cb8af584712e16a.json index 2f16ce90b6..6c485aedbc 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__4d228b5af660c840e140560916dee664696a82c2b75fda103a6490a0a0119fea/msg_GetContestedResourceVoteStateRequest_bd857f0f40a11ccbc620754f0b276da7bcf8bb6352f7f5f26cb8af584712e16a.json and b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__4d228b5af660c840e140560916dee664696a82c2b75fda103a6490a0a0119fea/msg_GetContestedResourceVoteStateRequest_bd857f0f40a11ccbc620754f0b276da7bcf8bb6352f7f5f26cb8af584712e16a.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__67dc63814e035b20ff705840e19ebb329026b51129b8dd9cd029d26a0a77408b/msg_GetContestedResourceVoteStateRequest_f7848301c15560f971e007963a349e64e07602f543bda42d5a5d223f0e6102a9.json b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__67dc63814e035b20ff705840e19ebb329026b51129b8dd9cd029d26a0a77408b/msg_GetContestedResourceVoteStateRequest_f7848301c15560f971e007963a349e64e07602f543bda42d5a5d223f0e6102a9.json index 1dde44a113..1bdf34fd44 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__67dc63814e035b20ff705840e19ebb329026b51129b8dd9cd029d26a0a77408b/msg_GetContestedResourceVoteStateRequest_f7848301c15560f971e007963a349e64e07602f543bda42d5a5d223f0e6102a9.json and b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__67dc63814e035b20ff705840e19ebb329026b51129b8dd9cd029d26a0a77408b/msg_GetContestedResourceVoteStateRequest_f7848301c15560f971e007963a349e64e07602f543bda42d5a5d223f0e6102a9.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__67dc63814e035b20ff705840e19ebb329026b51129b8dd9cd029d26a0a77408b/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__67dc63814e035b20ff705840e19ebb329026b51129b8dd9cd029d26a0a77408b/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json index 808b4f0118..e64b73d8a7 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__67dc63814e035b20ff705840e19ebb329026b51129b8dd9cd029d26a0a77408b/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json and b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__67dc63814e035b20ff705840e19ebb329026b51129b8dd9cd029d26a0a77408b/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__67dc63814e035b20ff705840e19ebb329026b51129b8dd9cd029d26a0a77408b/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__67dc63814e035b20ff705840e19ebb329026b51129b8dd9cd029d26a0a77408b/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__67dc63814e035b20ff705840e19ebb329026b51129b8dd9cd029d26a0a77408b/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__67dc63814e035b20ff705840e19ebb329026b51129b8dd9cd029d26a0a77408b/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__67dc63814e035b20ff705840e19ebb329026b51129b8dd9cd029d26a0a77408b/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__67dc63814e035b20ff705840e19ebb329026b51129b8dd9cd029d26a0a77408b/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__863d867345b51a45ba4ec8326f42701a86224b53737b607521f5711340b8ecea/msg_GetContestedResourceVoteStateRequest_b9a737558f8e65f57294ca0f43cb3f1bccd65e01bb860f7648ce860ce03df202.json b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__863d867345b51a45ba4ec8326f42701a86224b53737b607521f5711340b8ecea/msg_GetContestedResourceVoteStateRequest_b9a737558f8e65f57294ca0f43cb3f1bccd65e01bb860f7648ce860ce03df202.json index dd707956b4..29d0ad3833 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__863d867345b51a45ba4ec8326f42701a86224b53737b607521f5711340b8ecea/msg_GetContestedResourceVoteStateRequest_b9a737558f8e65f57294ca0f43cb3f1bccd65e01bb860f7648ce860ce03df202.json and b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__863d867345b51a45ba4ec8326f42701a86224b53737b607521f5711340b8ecea/msg_GetContestedResourceVoteStateRequest_b9a737558f8e65f57294ca0f43cb3f1bccd65e01bb860f7648ce860ce03df202.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__8693b7b63d4af227f34a1c743e52147d48e775e679e50375df37f30bc707ef95/msg_GetContestedResourceVoteStateRequest_c6f0fff8a974cf324b6c2a285e0ae85cdc0620cb84d732a686322ae9dd8c5240.json b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__8693b7b63d4af227f34a1c743e52147d48e775e679e50375df37f30bc707ef95/msg_GetContestedResourceVoteStateRequest_c6f0fff8a974cf324b6c2a285e0ae85cdc0620cb84d732a686322ae9dd8c5240.json index 81c0610d4f..f55749003b 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__8693b7b63d4af227f34a1c743e52147d48e775e679e50375df37f30bc707ef95/msg_GetContestedResourceVoteStateRequest_c6f0fff8a974cf324b6c2a285e0ae85cdc0620cb84d732a686322ae9dd8c5240.json and b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__8693b7b63d4af227f34a1c743e52147d48e775e679e50375df37f30bc707ef95/msg_GetContestedResourceVoteStateRequest_c6f0fff8a974cf324b6c2a285e0ae85cdc0620cb84d732a686322ae9dd8c5240.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__90ed25475456fdfd4f2fd676ed5b5f2e9c390cae806202a046fc93153eea6e00/msg_GetContestedResourceVoteStateRequest_6192aa18cf199acc9ca27cbe0377de9b6df87c4df053f3032a3fac93ca2985c2.json b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__90ed25475456fdfd4f2fd676ed5b5f2e9c390cae806202a046fc93153eea6e00/msg_GetContestedResourceVoteStateRequest_6192aa18cf199acc9ca27cbe0377de9b6df87c4df053f3032a3fac93ca2985c2.json index 8e7ba32ccd..64f9e4f953 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__90ed25475456fdfd4f2fd676ed5b5f2e9c390cae806202a046fc93153eea6e00/msg_GetContestedResourceVoteStateRequest_6192aa18cf199acc9ca27cbe0377de9b6df87c4df053f3032a3fac93ca2985c2.json and b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__90ed25475456fdfd4f2fd676ed5b5f2e9c390cae806202a046fc93153eea6e00/msg_GetContestedResourceVoteStateRequest_6192aa18cf199acc9ca27cbe0377de9b6df87c4df053f3032a3fac93ca2985c2.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__a39a5f7014a616de3d7002bb4f18772c5b5d3526cb2b3c33566bd64512882669/msg_GetContestedResourceVoteStateRequest_aaaa80ce4fdfc75252132a85e6c12bea6a47c9f7bf30133713b6b5cfec3a4d57.json b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__a39a5f7014a616de3d7002bb4f18772c5b5d3526cb2b3c33566bd64512882669/msg_GetContestedResourceVoteStateRequest_aaaa80ce4fdfc75252132a85e6c12bea6a47c9f7bf30133713b6b5cfec3a4d57.json index 300e476a45..7ec5d38676 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__a39a5f7014a616de3d7002bb4f18772c5b5d3526cb2b3c33566bd64512882669/msg_GetContestedResourceVoteStateRequest_aaaa80ce4fdfc75252132a85e6c12bea6a47c9f7bf30133713b6b5cfec3a4d57.json and b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__a39a5f7014a616de3d7002bb4f18772c5b5d3526cb2b3c33566bd64512882669/msg_GetContestedResourceVoteStateRequest_aaaa80ce4fdfc75252132a85e6c12bea6a47c9f7bf30133713b6b5cfec3a4d57.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__a39a5f7014a616de3d7002bb4f18772c5b5d3526cb2b3c33566bd64512882669/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__a39a5f7014a616de3d7002bb4f18772c5b5d3526cb2b3c33566bd64512882669/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json index 808b4f0118..e64b73d8a7 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__a39a5f7014a616de3d7002bb4f18772c5b5d3526cb2b3c33566bd64512882669/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json and b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__a39a5f7014a616de3d7002bb4f18772c5b5d3526cb2b3c33566bd64512882669/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__a39a5f7014a616de3d7002bb4f18772c5b5d3526cb2b3c33566bd64512882669/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__a39a5f7014a616de3d7002bb4f18772c5b5d3526cb2b3c33566bd64512882669/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__a39a5f7014a616de3d7002bb4f18772c5b5d3526cb2b3c33566bd64512882669/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__a39a5f7014a616de3d7002bb4f18772c5b5d3526cb2b3c33566bd64512882669/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__a39a5f7014a616de3d7002bb4f18772c5b5d3526cb2b3c33566bd64512882669/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__a39a5f7014a616de3d7002bb4f18772c5b5d3526cb2b3c33566bd64512882669/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__aabb30e955771841251280c0e6a98257882c3b2ee0b73b4aca838fb78918256b/msg_GetContestedResourceVoteStateRequest_9a43882825cbf3a83a2f623d03ae412662a6acb2d928d56de7a6a67dbf70f80a.json b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__aabb30e955771841251280c0e6a98257882c3b2ee0b73b4aca838fb78918256b/msg_GetContestedResourceVoteStateRequest_9a43882825cbf3a83a2f623d03ae412662a6acb2d928d56de7a6a67dbf70f80a.json index 9437bd3132..adcf11ac7e 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__aabb30e955771841251280c0e6a98257882c3b2ee0b73b4aca838fb78918256b/msg_GetContestedResourceVoteStateRequest_9a43882825cbf3a83a2f623d03ae412662a6acb2d928d56de7a6a67dbf70f80a.json and b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__aabb30e955771841251280c0e6a98257882c3b2ee0b73b4aca838fb78918256b/msg_GetContestedResourceVoteStateRequest_9a43882825cbf3a83a2f623d03ae412662a6acb2d928d56de7a6a67dbf70f80a.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__c71b4f8d63f8a1357936129a226f99e349e7b21b166609cf59062e27ed68a1ee/msg_GetContestedResourceVoteStateRequest_23a531bedb32082b8e3bb799790dbc80a6caf537196a9513dae8967f325ab485.json b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__c71b4f8d63f8a1357936129a226f99e349e7b21b166609cf59062e27ed68a1ee/msg_GetContestedResourceVoteStateRequest_23a531bedb32082b8e3bb799790dbc80a6caf537196a9513dae8967f325ab485.json index 81cdce36dd..b1aa27d675 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__c71b4f8d63f8a1357936129a226f99e349e7b21b166609cf59062e27ed68a1ee/msg_GetContestedResourceVoteStateRequest_23a531bedb32082b8e3bb799790dbc80a6caf537196a9513dae8967f325ab485.json and b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__c71b4f8d63f8a1357936129a226f99e349e7b21b166609cf59062e27ed68a1ee/msg_GetContestedResourceVoteStateRequest_23a531bedb32082b8e3bb799790dbc80a6caf537196a9513dae8967f325ab485.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__c71b4f8d63f8a1357936129a226f99e349e7b21b166609cf59062e27ed68a1ee/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__c71b4f8d63f8a1357936129a226f99e349e7b21b166609cf59062e27ed68a1ee/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json index 808b4f0118..e64b73d8a7 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__c71b4f8d63f8a1357936129a226f99e349e7b21b166609cf59062e27ed68a1ee/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json and b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__c71b4f8d63f8a1357936129a226f99e349e7b21b166609cf59062e27ed68a1ee/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__c71b4f8d63f8a1357936129a226f99e349e7b21b166609cf59062e27ed68a1ee/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__c71b4f8d63f8a1357936129a226f99e349e7b21b166609cf59062e27ed68a1ee/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__c71b4f8d63f8a1357936129a226f99e349e7b21b166609cf59062e27ed68a1ee/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__c71b4f8d63f8a1357936129a226f99e349e7b21b166609cf59062e27ed68a1ee/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__c71b4f8d63f8a1357936129a226f99e349e7b21b166609cf59062e27ed68a1ee/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__c71b4f8d63f8a1357936129a226f99e349e7b21b166609cf59062e27ed68a1ee/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__cf2a2febe0a535f130d2eaaaba3f002c094511cae2fd57dfaa6e5ee607cd72b6/msg_GetContestedResourceVoteStateRequest_b620c564a9caf806d2a4053efc7a8707f36bc1837a661ca9a4a3aae3ab30da7a.json b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__cf2a2febe0a535f130d2eaaaba3f002c094511cae2fd57dfaa6e5ee607cd72b6/msg_GetContestedResourceVoteStateRequest_b620c564a9caf806d2a4053efc7a8707f36bc1837a661ca9a4a3aae3ab30da7a.json index f3c4ba759c..29e7295217 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__cf2a2febe0a535f130d2eaaaba3f002c094511cae2fd57dfaa6e5ee607cd72b6/msg_GetContestedResourceVoteStateRequest_b620c564a9caf806d2a4053efc7a8707f36bc1837a661ca9a4a3aae3ab30da7a.json and b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__cf2a2febe0a535f130d2eaaaba3f002c094511cae2fd57dfaa6e5ee607cd72b6/msg_GetContestedResourceVoteStateRequest_b620c564a9caf806d2a4053efc7a8707f36bc1837a661ca9a4a3aae3ab30da7a.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__cfe3ebd0f17745be80e4348304fe468f3eb8c2d17e23d310582b0b34f2d5bba7/msg_GetContestedResourceVoteStateRequest_bf272e62224361f1e7cf91b7f45285016c5d0ac679c299447df687e866154090.json b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__cfe3ebd0f17745be80e4348304fe468f3eb8c2d17e23d310582b0b34f2d5bba7/msg_GetContestedResourceVoteStateRequest_bf272e62224361f1e7cf91b7f45285016c5d0ac679c299447df687e866154090.json index e876ff6dd3..524100d89d 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__cfe3ebd0f17745be80e4348304fe468f3eb8c2d17e23d310582b0b34f2d5bba7/msg_GetContestedResourceVoteStateRequest_bf272e62224361f1e7cf91b7f45285016c5d0ac679c299447df687e866154090.json and b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__cfe3ebd0f17745be80e4348304fe468f3eb8c2d17e23d310582b0b34f2d5bba7/msg_GetContestedResourceVoteStateRequest_bf272e62224361f1e7cf91b7f45285016c5d0ac679c299447df687e866154090.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__cfe3ebd0f17745be80e4348304fe468f3eb8c2d17e23d310582b0b34f2d5bba7/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__cfe3ebd0f17745be80e4348304fe468f3eb8c2d17e23d310582b0b34f2d5bba7/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json index 808b4f0118..e64b73d8a7 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__cfe3ebd0f17745be80e4348304fe468f3eb8c2d17e23d310582b0b34f2d5bba7/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json and b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__cfe3ebd0f17745be80e4348304fe468f3eb8c2d17e23d310582b0b34f2d5bba7/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__cfe3ebd0f17745be80e4348304fe468f3eb8c2d17e23d310582b0b34f2d5bba7/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__cfe3ebd0f17745be80e4348304fe468f3eb8c2d17e23d310582b0b34f2d5bba7/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__cfe3ebd0f17745be80e4348304fe468f3eb8c2d17e23d310582b0b34f2d5bba7/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__cfe3ebd0f17745be80e4348304fe468f3eb8c2d17e23d310582b0b34f2d5bba7/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__cfe3ebd0f17745be80e4348304fe468f3eb8c2d17e23d310582b0b34f2d5bba7/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__cfe3ebd0f17745be80e4348304fe468f3eb8c2d17e23d310582b0b34f2d5bba7/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__d7532a56162a82dafbbe07d40821db2e8768e2e6a880e7a66018fcd90fa35c71/msg_GetContestedResourceVoteStateRequest_3fede5825779667ef492c2ca1744ae6d7593e5a08c8e0c9971ad1afc8c3e1702.json b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__d7532a56162a82dafbbe07d40821db2e8768e2e6a880e7a66018fcd90fa35c71/msg_GetContestedResourceVoteStateRequest_3fede5825779667ef492c2ca1744ae6d7593e5a08c8e0c9971ad1afc8c3e1702.json index dd1f75831e..c794b9ff5a 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__d7532a56162a82dafbbe07d40821db2e8768e2e6a880e7a66018fcd90fa35c71/msg_GetContestedResourceVoteStateRequest_3fede5825779667ef492c2ca1744ae6d7593e5a08c8e0c9971ad1afc8c3e1702.json and b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__d7532a56162a82dafbbe07d40821db2e8768e2e6a880e7a66018fcd90fa35c71/msg_GetContestedResourceVoteStateRequest_3fede5825779667ef492c2ca1744ae6d7593e5a08c8e0c9971ad1afc8c3e1702.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__fbed6654145b9fba061d182cac5a3879bc9bacb92dc9ae64ed2a07ca2ec0392f/msg_GetContestedResourceVoteStateRequest_e1399ef22320c9690b1c8e548975839e9ea0c40cd94caac5746b19857d52533a.json b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__fbed6654145b9fba061d182cac5a3879bc9bacb92dc9ae64ed2a07ca2ec0392f/msg_GetContestedResourceVoteStateRequest_e1399ef22320c9690b1c8e548975839e9ea0c40cd94caac5746b19857d52533a.json index 1877ca2ee6..8dd21af351 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__fbed6654145b9fba061d182cac5a3879bc9bacb92dc9ae64ed2a07ca2ec0392f/msg_GetContestedResourceVoteStateRequest_e1399ef22320c9690b1c8e548975839e9ea0c40cd94caac5746b19857d52533a.json and b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__fbed6654145b9fba061d182cac5a3879bc9bacb92dc9ae64ed2a07ca2ec0392f/msg_GetContestedResourceVoteStateRequest_e1399ef22320c9690b1c8e548975839e9ea0c40cd94caac5746b19857d52533a.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__fbed6654145b9fba061d182cac5a3879bc9bacb92dc9ae64ed2a07ca2ec0392f/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__fbed6654145b9fba061d182cac5a3879bc9bacb92dc9ae64ed2a07ca2ec0392f/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json index 808b4f0118..e64b73d8a7 100644 Binary files a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__fbed6654145b9fba061d182cac5a3879bc9bacb92dc9ae64ed2a07ca2ec0392f/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json and b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__fbed6654145b9fba061d182cac5a3879bc9bacb92dc9ae64ed2a07ca2ec0392f/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__fbed6654145b9fba061d182cac5a3879bc9bacb92dc9ae64ed2a07ca2ec0392f/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__fbed6654145b9fba061d182cac5a3879bc9bacb92dc9ae64ed2a07ca2ec0392f/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__fbed6654145b9fba061d182cac5a3879bc9bacb92dc9ae64ed2a07ca2ec0392f/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__fbed6654145b9fba061d182cac5a3879bc9bacb92dc9ae64ed2a07ca2ec0392f/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__fbed6654145b9fba061d182cac5a3879bc9bacb92dc9ae64ed2a07ca2ec0392f/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/contested_rss_vote_state_fields__fbed6654145b9fba061d182cac5a3879bc9bacb92dc9ae64ed2a07ca2ec0392f/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/document_list_bug_value_text_decode_base58/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json b/packages/rs-sdk/tests/vectors/document_list_bug_value_text_decode_base58/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json index 808b4f0118..e64b73d8a7 100644 Binary files a/packages/rs-sdk/tests/vectors/document_list_bug_value_text_decode_base58/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json and b/packages/rs-sdk/tests/vectors/document_list_bug_value_text_decode_base58/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json differ diff --git a/packages/rs-sdk/tests/vectors/document_list_bug_value_text_decode_base58/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/document_list_bug_value_text_decode_base58/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/document_list_bug_value_text_decode_base58/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/document_list_bug_value_text_decode_base58/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/document_list_bug_value_text_decode_base58/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/document_list_bug_value_text_decode_base58/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/document_list_document_query/msg_DocumentQuery_86beaec40825e436c6a9467bd1af6d2d9dcd58c35b6aa9e85398a105dfdeb9c6.json b/packages/rs-sdk/tests/vectors/document_list_document_query/msg_DocumentQuery_86beaec40825e436c6a9467bd1af6d2d9dcd58c35b6aa9e85398a105dfdeb9c6.json index a17354f7d7..9b918fc102 100644 Binary files a/packages/rs-sdk/tests/vectors/document_list_document_query/msg_DocumentQuery_86beaec40825e436c6a9467bd1af6d2d9dcd58c35b6aa9e85398a105dfdeb9c6.json and b/packages/rs-sdk/tests/vectors/document_list_document_query/msg_DocumentQuery_86beaec40825e436c6a9467bd1af6d2d9dcd58c35b6aa9e85398a105dfdeb9c6.json differ diff --git a/packages/rs-sdk/tests/vectors/document_list_document_query/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json b/packages/rs-sdk/tests/vectors/document_list_document_query/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json index 808b4f0118..e64b73d8a7 100644 Binary files a/packages/rs-sdk/tests/vectors/document_list_document_query/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json and b/packages/rs-sdk/tests/vectors/document_list_document_query/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json differ diff --git a/packages/rs-sdk/tests/vectors/document_list_document_query/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/document_list_document_query/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/document_list_document_query/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/document_list_document_query/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/document_list_document_query/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/document_list_document_query/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/document_list_drive_query/msg_DocumentQuery_e731a9066a60d9cee4097f419bbe0f17fb3367987f71c5caf9c045ced8633299.json b/packages/rs-sdk/tests/vectors/document_list_drive_query/msg_DocumentQuery_e731a9066a60d9cee4097f419bbe0f17fb3367987f71c5caf9c045ced8633299.json index 1bdafe4e9b..d07952dd0f 100644 Binary files a/packages/rs-sdk/tests/vectors/document_list_drive_query/msg_DocumentQuery_e731a9066a60d9cee4097f419bbe0f17fb3367987f71c5caf9c045ced8633299.json and b/packages/rs-sdk/tests/vectors/document_list_drive_query/msg_DocumentQuery_e731a9066a60d9cee4097f419bbe0f17fb3367987f71c5caf9c045ced8633299.json differ diff --git a/packages/rs-sdk/tests/vectors/document_list_drive_query/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json b/packages/rs-sdk/tests/vectors/document_list_drive_query/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json index 808b4f0118..e64b73d8a7 100644 Binary files a/packages/rs-sdk/tests/vectors/document_list_drive_query/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json and b/packages/rs-sdk/tests/vectors/document_list_drive_query/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json differ diff --git a/packages/rs-sdk/tests/vectors/document_list_drive_query/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/document_list_drive_query/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/document_list_drive_query/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/document_list_drive_query/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/document_list_drive_query/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/document_list_drive_query/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/document_read/msg_DocumentQuery_23b0993681588ca0c66e960ae019dd012ae92b1038a32d1cbb419087d75cc70a.json b/packages/rs-sdk/tests/vectors/document_read/msg_DocumentQuery_23b0993681588ca0c66e960ae019dd012ae92b1038a32d1cbb419087d75cc70a.json deleted file mode 100644 index 243ee061f6..0000000000 Binary files a/packages/rs-sdk/tests/vectors/document_read/msg_DocumentQuery_23b0993681588ca0c66e960ae019dd012ae92b1038a32d1cbb419087d75cc70a.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/document_read/msg_DocumentQuery_54e14af5c2e8a36e3c337f1e7f9288fcadcf4f0c2959c0a632bbd06e28bc3d95.json b/packages/rs-sdk/tests/vectors/document_read/msg_DocumentQuery_54e14af5c2e8a36e3c337f1e7f9288fcadcf4f0c2959c0a632bbd06e28bc3d95.json new file mode 100644 index 0000000000..6978981ec0 Binary files /dev/null and b/packages/rs-sdk/tests/vectors/document_read/msg_DocumentQuery_54e14af5c2e8a36e3c337f1e7f9288fcadcf4f0c2959c0a632bbd06e28bc3d95.json differ diff --git a/packages/rs-sdk/tests/vectors/document_read/msg_DocumentQuery_86beaec40825e436c6a9467bd1af6d2d9dcd58c35b6aa9e85398a105dfdeb9c6.json b/packages/rs-sdk/tests/vectors/document_read/msg_DocumentQuery_86beaec40825e436c6a9467bd1af6d2d9dcd58c35b6aa9e85398a105dfdeb9c6.json index a17354f7d7..9b918fc102 100644 Binary files a/packages/rs-sdk/tests/vectors/document_read/msg_DocumentQuery_86beaec40825e436c6a9467bd1af6d2d9dcd58c35b6aa9e85398a105dfdeb9c6.json and b/packages/rs-sdk/tests/vectors/document_read/msg_DocumentQuery_86beaec40825e436c6a9467bd1af6d2d9dcd58c35b6aa9e85398a105dfdeb9c6.json differ diff --git a/packages/rs-sdk/tests/vectors/document_read/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json b/packages/rs-sdk/tests/vectors/document_read/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json index 808b4f0118..e64b73d8a7 100644 Binary files a/packages/rs-sdk/tests/vectors/document_read/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json and b/packages/rs-sdk/tests/vectors/document_read/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json differ diff --git a/packages/rs-sdk/tests/vectors/document_read/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/document_read/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/document_read/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/document_read/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/document_read/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/document_read/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/document_read_no_contract/msg_GetDataContractRequest_e4cf74168e03a40bd159451456b501c1ba166a2dd8f6efb31b0289dc011da983.json b/packages/rs-sdk/tests/vectors/document_read_no_contract/msg_GetDataContractRequest_e4cf74168e03a40bd159451456b501c1ba166a2dd8f6efb31b0289dc011da983.json index b52ddadb11..06d6b9f4eb 100644 Binary files a/packages/rs-sdk/tests/vectors/document_read_no_contract/msg_GetDataContractRequest_e4cf74168e03a40bd159451456b501c1ba166a2dd8f6efb31b0289dc011da983.json and b/packages/rs-sdk/tests/vectors/document_read_no_contract/msg_GetDataContractRequest_e4cf74168e03a40bd159451456b501c1ba166a2dd8f6efb31b0289dc011da983.json differ diff --git a/packages/rs-sdk/tests/vectors/document_read_no_contract/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/document_read_no_contract/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/document_read_no_contract/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/document_read_no_contract/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/document_read_no_contract/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/document_read_no_contract/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/document_read_no_document/msg_DocumentQuery_20d68bd71dd4309389f14aed5d610bbf4178e9af8e87ee326576ac2b384d726d.json b/packages/rs-sdk/tests/vectors/document_read_no_document/msg_DocumentQuery_20d68bd71dd4309389f14aed5d610bbf4178e9af8e87ee326576ac2b384d726d.json index 1633caffc3..0a87c8d256 100644 Binary files a/packages/rs-sdk/tests/vectors/document_read_no_document/msg_DocumentQuery_20d68bd71dd4309389f14aed5d610bbf4178e9af8e87ee326576ac2b384d726d.json and b/packages/rs-sdk/tests/vectors/document_read_no_document/msg_DocumentQuery_20d68bd71dd4309389f14aed5d610bbf4178e9af8e87ee326576ac2b384d726d.json differ diff --git a/packages/rs-sdk/tests/vectors/document_read_no_document/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json b/packages/rs-sdk/tests/vectors/document_read_no_document/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json index 808b4f0118..e64b73d8a7 100644 Binary files a/packages/rs-sdk/tests/vectors/document_read_no_document/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json and b/packages/rs-sdk/tests/vectors/document_read_no_document/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json differ diff --git a/packages/rs-sdk/tests/vectors/document_read_no_document/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/document_read_no_document/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/document_read_no_document/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/document_read_no_document/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/document_read_no_document/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/document_read_no_document/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_contested_resource_voters_for_identity_not_found/msg_GetContestedResourceVotersForIdentityRequest_365e8cc19afcc569d90d85a2a371ad49d3ae7bc38d217d85b1570274493c4d7e.json b/packages/rs-sdk/tests/vectors/test_contested_resource_voters_for_identity_not_found/msg_GetContestedResourceVotersForIdentityRequest_365e8cc19afcc569d90d85a2a371ad49d3ae7bc38d217d85b1570274493c4d7e.json index 7a88bd92e0..3d8f0402e5 100644 Binary files a/packages/rs-sdk/tests/vectors/test_contested_resource_voters_for_identity_not_found/msg_GetContestedResourceVotersForIdentityRequest_365e8cc19afcc569d90d85a2a371ad49d3ae7bc38d217d85b1570274493c4d7e.json and b/packages/rs-sdk/tests/vectors/test_contested_resource_voters_for_identity_not_found/msg_GetContestedResourceVotersForIdentityRequest_365e8cc19afcc569d90d85a2a371ad49d3ae7bc38d217d85b1570274493c4d7e.json differ diff --git a/packages/rs-sdk/tests/vectors/test_contested_resource_voters_for_identity_not_found/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json b/packages/rs-sdk/tests/vectors/test_contested_resource_voters_for_identity_not_found/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json index 808b4f0118..e64b73d8a7 100644 Binary files a/packages/rs-sdk/tests/vectors/test_contested_resource_voters_for_identity_not_found/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json and b/packages/rs-sdk/tests/vectors/test_contested_resource_voters_for_identity_not_found/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json differ diff --git a/packages/rs-sdk/tests/vectors/test_contested_resource_voters_for_identity_not_found/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/test_contested_resource_voters_for_identity_not_found/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/test_contested_resource_voters_for_identity_not_found/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_contested_resource_voters_for_identity_not_found/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/test_contested_resource_voters_for_identity_not_found/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/test_contested_resource_voters_for_identity_not_found/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_contested_resources_ok/msg_GetContestedResourcesRequest_c8608f7aed7bbe4ced03c9c23f1ce28a227def58e23c39e0384e0cc02fe6360b.json b/packages/rs-sdk/tests/vectors/test_contested_resources_ok/msg_GetContestedResourcesRequest_c8608f7aed7bbe4ced03c9c23f1ce28a227def58e23c39e0384e0cc02fe6360b.json index b689eb3042..46ce3e849c 100644 Binary files a/packages/rs-sdk/tests/vectors/test_contested_resources_ok/msg_GetContestedResourcesRequest_c8608f7aed7bbe4ced03c9c23f1ce28a227def58e23c39e0384e0cc02fe6360b.json and b/packages/rs-sdk/tests/vectors/test_contested_resources_ok/msg_GetContestedResourcesRequest_c8608f7aed7bbe4ced03c9c23f1ce28a227def58e23c39e0384e0cc02fe6360b.json differ diff --git a/packages/rs-sdk/tests/vectors/test_contested_resources_ok/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json b/packages/rs-sdk/tests/vectors/test_contested_resources_ok/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json index 808b4f0118..e64b73d8a7 100644 Binary files a/packages/rs-sdk/tests/vectors/test_contested_resources_ok/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json and b/packages/rs-sdk/tests/vectors/test_contested_resources_ok/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json differ diff --git a/packages/rs-sdk/tests/vectors/test_contested_resources_ok/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/test_contested_resources_ok/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/test_contested_resources_ok/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_contested_resources_ok/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/test_contested_resources_ok/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/test_contested_resources_ok/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_data_contract_history_read/msg_GetDataContractHistoryRequest_05485e622b540237cadaa7fda2a96e8a6cdbd49b7bb7a3ac9cb6ab3035676772.json b/packages/rs-sdk/tests/vectors/test_data_contract_history_read/msg_GetDataContractHistoryRequest_05485e622b540237cadaa7fda2a96e8a6cdbd49b7bb7a3ac9cb6ab3035676772.json new file mode 100644 index 0000000000..ef8726a337 Binary files /dev/null and b/packages/rs-sdk/tests/vectors/test_data_contract_history_read/msg_GetDataContractHistoryRequest_05485e622b540237cadaa7fda2a96e8a6cdbd49b7bb7a3ac9cb6ab3035676772.json differ diff --git a/packages/rs-sdk/tests/vectors/test_data_contract_history_read/msg_GetDataContractHistoryRequest_2bd2bfc3193745cf05fb33fd3e56d1c377e5a79c8bbfad2b8607feeb2743c37c.json b/packages/rs-sdk/tests/vectors/test_data_contract_history_read/msg_GetDataContractHistoryRequest_2bd2bfc3193745cf05fb33fd3e56d1c377e5a79c8bbfad2b8607feeb2743c37c.json deleted file mode 100644 index a3e9089723..0000000000 Binary files a/packages/rs-sdk/tests/vectors/test_data_contract_history_read/msg_GetDataContractHistoryRequest_2bd2bfc3193745cf05fb33fd3e56d1c377e5a79c8bbfad2b8607feeb2743c37c.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/test_data_contract_history_read/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/test_data_contract_history_read/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/test_data_contract_history_read/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_data_contract_history_read/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/test_data_contract_history_read/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/test_data_contract_history_read/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_data_contract_read/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json b/packages/rs-sdk/tests/vectors/test_data_contract_read/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json index 808b4f0118..e64b73d8a7 100644 Binary files a/packages/rs-sdk/tests/vectors/test_data_contract_read/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json and b/packages/rs-sdk/tests/vectors/test_data_contract_read/msg_GetDataContractRequest_e87a2e6acef76975c30eb7272da71733fb6ad13495beb7ca1b6a6c4ceb30e0f7.json differ diff --git a/packages/rs-sdk/tests/vectors/test_data_contract_read/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/test_data_contract_read/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/test_data_contract_read/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_data_contract_read/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/test_data_contract_read/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/test_data_contract_read/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_data_contract_read_not_found/msg_GetDataContractRequest_1d1e53ab5e04d9ec5dce4ff9ac048c03122daf7ab2e77108f4bf44af1ad15eae.json b/packages/rs-sdk/tests/vectors/test_data_contract_read_not_found/msg_GetDataContractRequest_1d1e53ab5e04d9ec5dce4ff9ac048c03122daf7ab2e77108f4bf44af1ad15eae.json index 5bd4cd1d78..655bf9694f 100644 Binary files a/packages/rs-sdk/tests/vectors/test_data_contract_read_not_found/msg_GetDataContractRequest_1d1e53ab5e04d9ec5dce4ff9ac048c03122daf7ab2e77108f4bf44af1ad15eae.json and b/packages/rs-sdk/tests/vectors/test_data_contract_read_not_found/msg_GetDataContractRequest_1d1e53ab5e04d9ec5dce4ff9ac048c03122daf7ab2e77108f4bf44af1ad15eae.json differ diff --git a/packages/rs-sdk/tests/vectors/test_data_contract_read_not_found/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/test_data_contract_read_not_found/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/test_data_contract_read_not_found/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_data_contract_read_not_found/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/test_data_contract_read_not_found/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/test_data_contract_read_not_found/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_data_contracts_1_ok_1_nx/msg_GetDataContractsRequest_f229a0e58a5c4fb050f57c087bf067bd9ccc29eca3092a5664a5a9ba3bb7e967.json b/packages/rs-sdk/tests/vectors/test_data_contracts_1_ok_1_nx/msg_GetDataContractsRequest_f229a0e58a5c4fb050f57c087bf067bd9ccc29eca3092a5664a5a9ba3bb7e967.json index d25fa5b1a5..82950e1e00 100644 Binary files a/packages/rs-sdk/tests/vectors/test_data_contracts_1_ok_1_nx/msg_GetDataContractsRequest_f229a0e58a5c4fb050f57c087bf067bd9ccc29eca3092a5664a5a9ba3bb7e967.json and b/packages/rs-sdk/tests/vectors/test_data_contracts_1_ok_1_nx/msg_GetDataContractsRequest_f229a0e58a5c4fb050f57c087bf067bd9ccc29eca3092a5664a5a9ba3bb7e967.json differ diff --git a/packages/rs-sdk/tests/vectors/test_data_contracts_1_ok_1_nx/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/test_data_contracts_1_ok_1_nx/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/test_data_contracts_1_ok_1_nx/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_data_contracts_1_ok_1_nx/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/test_data_contracts_1_ok_1_nx/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/test_data_contracts_1_ok_1_nx/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_data_contracts_2_nx/msg_GetDataContractsRequest_93bdf343bce1bafb96fd873236cabbc4ac6ad7e80f0e55fe98bbcfbebf6c0878.json b/packages/rs-sdk/tests/vectors/test_data_contracts_2_nx/msg_GetDataContractsRequest_93bdf343bce1bafb96fd873236cabbc4ac6ad7e80f0e55fe98bbcfbebf6c0878.json index 66d946dbd8..cc41d9f1a1 100644 Binary files a/packages/rs-sdk/tests/vectors/test_data_contracts_2_nx/msg_GetDataContractsRequest_93bdf343bce1bafb96fd873236cabbc4ac6ad7e80f0e55fe98bbcfbebf6c0878.json and b/packages/rs-sdk/tests/vectors/test_data_contracts_2_nx/msg_GetDataContractsRequest_93bdf343bce1bafb96fd873236cabbc4ac6ad7e80f0e55fe98bbcfbebf6c0878.json differ diff --git a/packages/rs-sdk/tests/vectors/test_data_contracts_2_nx/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/test_data_contracts_2_nx/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/test_data_contracts_2_nx/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_data_contracts_2_nx/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/test_data_contracts_2_nx/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/test_data_contracts_2_nx/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_epoch_fetch/msg_GetEpochsInfoRequest_00f51345e161bde17d0b008310d7acebec137640ed9cf550876fa1ec438bbcd0.json b/packages/rs-sdk/tests/vectors/test_epoch_fetch/msg_GetEpochsInfoRequest_00f51345e161bde17d0b008310d7acebec137640ed9cf550876fa1ec438bbcd0.json deleted file mode 100644 index bb2962a8d1..0000000000 Binary files a/packages/rs-sdk/tests/vectors/test_epoch_fetch/msg_GetEpochsInfoRequest_00f51345e161bde17d0b008310d7acebec137640ed9cf550876fa1ec438bbcd0.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/test_epoch_fetch/msg_GetEpochsInfoRequest_6a828350e795a088dbc835260a1add01a7428085ffdcf1e11cccf19c48c5f7a1.json b/packages/rs-sdk/tests/vectors/test_epoch_fetch/msg_GetEpochsInfoRequest_6a828350e795a088dbc835260a1add01a7428085ffdcf1e11cccf19c48c5f7a1.json new file mode 100644 index 0000000000..069b9853e0 Binary files /dev/null and b/packages/rs-sdk/tests/vectors/test_epoch_fetch/msg_GetEpochsInfoRequest_6a828350e795a088dbc835260a1add01a7428085ffdcf1e11cccf19c48c5f7a1.json differ diff --git a/packages/rs-sdk/tests/vectors/test_epoch_fetch/msg_GetIdentityRequest_10ade8322ef670cd19d1a472a5477667b9a9edd07833d77c1af884ca8a9849ca.json b/packages/rs-sdk/tests/vectors/test_epoch_fetch/msg_GetIdentityRequest_10ade8322ef670cd19d1a472a5477667b9a9edd07833d77c1af884ca8a9849ca.json new file mode 100644 index 0000000000..c3b77e7974 Binary files /dev/null and b/packages/rs-sdk/tests/vectors/test_epoch_fetch/msg_GetIdentityRequest_10ade8322ef670cd19d1a472a5477667b9a9edd07833d77c1af884ca8a9849ca.json differ diff --git a/packages/rs-sdk/tests/vectors/test_epoch_fetch/msg_GetIdentityRequest_24b7371202615ecd290e0fe7496676f04dc30c79eec5a5df1ab5b8d8671ac38e.json b/packages/rs-sdk/tests/vectors/test_epoch_fetch/msg_GetIdentityRequest_24b7371202615ecd290e0fe7496676f04dc30c79eec5a5df1ab5b8d8671ac38e.json deleted file mode 100644 index 5ba6485778..0000000000 Binary files a/packages/rs-sdk/tests/vectors/test_epoch_fetch/msg_GetIdentityRequest_24b7371202615ecd290e0fe7496676f04dc30c79eec5a5df1ab5b8d8671ac38e.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/test_epoch_fetch/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/test_epoch_fetch/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/test_epoch_fetch/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_epoch_fetch/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/test_epoch_fetch/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/test_epoch_fetch/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_epoch_fetch_current/msg_GetEpochsInfoRequest_1b87e649557ccb609adb9e2904c67089535588985622579e77969e0ffd68afc7.json b/packages/rs-sdk/tests/vectors/test_epoch_fetch_current/msg_GetEpochsInfoRequest_1b87e649557ccb609adb9e2904c67089535588985622579e77969e0ffd68afc7.json index 9a75187088..de6e2c5282 100644 Binary files a/packages/rs-sdk/tests/vectors/test_epoch_fetch_current/msg_GetEpochsInfoRequest_1b87e649557ccb609adb9e2904c67089535588985622579e77969e0ffd68afc7.json and b/packages/rs-sdk/tests/vectors/test_epoch_fetch_current/msg_GetEpochsInfoRequest_1b87e649557ccb609adb9e2904c67089535588985622579e77969e0ffd68afc7.json differ diff --git a/packages/rs-sdk/tests/vectors/test_epoch_fetch_current/msg_GetIdentityRequest_10ade8322ef670cd19d1a472a5477667b9a9edd07833d77c1af884ca8a9849ca.json b/packages/rs-sdk/tests/vectors/test_epoch_fetch_current/msg_GetIdentityRequest_10ade8322ef670cd19d1a472a5477667b9a9edd07833d77c1af884ca8a9849ca.json new file mode 100644 index 0000000000..c3b77e7974 Binary files /dev/null and b/packages/rs-sdk/tests/vectors/test_epoch_fetch_current/msg_GetIdentityRequest_10ade8322ef670cd19d1a472a5477667b9a9edd07833d77c1af884ca8a9849ca.json differ diff --git a/packages/rs-sdk/tests/vectors/test_epoch_fetch_current/msg_GetIdentityRequest_24b7371202615ecd290e0fe7496676f04dc30c79eec5a5df1ab5b8d8671ac38e.json b/packages/rs-sdk/tests/vectors/test_epoch_fetch_current/msg_GetIdentityRequest_24b7371202615ecd290e0fe7496676f04dc30c79eec5a5df1ab5b8d8671ac38e.json deleted file mode 100644 index 5ba6485778..0000000000 Binary files a/packages/rs-sdk/tests/vectors/test_epoch_fetch_current/msg_GetIdentityRequest_24b7371202615ecd290e0fe7496676f04dc30c79eec5a5df1ab5b8d8671ac38e.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/test_epoch_fetch_current/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/test_epoch_fetch_current/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/test_epoch_fetch_current/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_epoch_fetch_current/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/test_epoch_fetch_current/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/test_epoch_fetch_current/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_epoch_fetch_future/msg_GetEpochsInfoRequest_cdea72fd4e08834ef8a3e6a0730fbcae54b0dd1b499fbc91c2c29685e132a339.json b/packages/rs-sdk/tests/vectors/test_epoch_fetch_future/msg_GetEpochsInfoRequest_cdea72fd4e08834ef8a3e6a0730fbcae54b0dd1b499fbc91c2c29685e132a339.json deleted file mode 100644 index 7e140b09a5..0000000000 Binary files a/packages/rs-sdk/tests/vectors/test_epoch_fetch_future/msg_GetEpochsInfoRequest_cdea72fd4e08834ef8a3e6a0730fbcae54b0dd1b499fbc91c2c29685e132a339.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/test_epoch_fetch_future/msg_GetEpochsInfoRequest_f93cf4e7bd56819a2b255d14c3b0208d6c0094fc5f5e03f668d261ae4931e0c9.json b/packages/rs-sdk/tests/vectors/test_epoch_fetch_future/msg_GetEpochsInfoRequest_f93cf4e7bd56819a2b255d14c3b0208d6c0094fc5f5e03f668d261ae4931e0c9.json new file mode 100644 index 0000000000..d48cd3dc6f Binary files /dev/null and b/packages/rs-sdk/tests/vectors/test_epoch_fetch_future/msg_GetEpochsInfoRequest_f93cf4e7bd56819a2b255d14c3b0208d6c0094fc5f5e03f668d261ae4931e0c9.json differ diff --git a/packages/rs-sdk/tests/vectors/test_epoch_fetch_future/msg_GetIdentityRequest_10ade8322ef670cd19d1a472a5477667b9a9edd07833d77c1af884ca8a9849ca.json b/packages/rs-sdk/tests/vectors/test_epoch_fetch_future/msg_GetIdentityRequest_10ade8322ef670cd19d1a472a5477667b9a9edd07833d77c1af884ca8a9849ca.json new file mode 100644 index 0000000000..c3b77e7974 Binary files /dev/null and b/packages/rs-sdk/tests/vectors/test_epoch_fetch_future/msg_GetIdentityRequest_10ade8322ef670cd19d1a472a5477667b9a9edd07833d77c1af884ca8a9849ca.json differ diff --git a/packages/rs-sdk/tests/vectors/test_epoch_fetch_future/msg_GetIdentityRequest_24b7371202615ecd290e0fe7496676f04dc30c79eec5a5df1ab5b8d8671ac38e.json b/packages/rs-sdk/tests/vectors/test_epoch_fetch_future/msg_GetIdentityRequest_24b7371202615ecd290e0fe7496676f04dc30c79eec5a5df1ab5b8d8671ac38e.json deleted file mode 100644 index 5ba6485778..0000000000 Binary files a/packages/rs-sdk/tests/vectors/test_epoch_fetch_future/msg_GetIdentityRequest_24b7371202615ecd290e0fe7496676f04dc30c79eec5a5df1ab5b8d8671ac38e.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/test_epoch_fetch_future/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/test_epoch_fetch_future/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/test_epoch_fetch_future/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_epoch_fetch_future/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/test_epoch_fetch_future/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/test_epoch_fetch_future/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_epoch_list/msg_GetEpochsInfoRequest_734f6594c67fe6a9ab170191031d592c8fe7361bed628d9a36747664c9789bf1.json b/packages/rs-sdk/tests/vectors/test_epoch_list/msg_GetEpochsInfoRequest_734f6594c67fe6a9ab170191031d592c8fe7361bed628d9a36747664c9789bf1.json index 476c2a5fd6..2567948bb1 100644 Binary files a/packages/rs-sdk/tests/vectors/test_epoch_list/msg_GetEpochsInfoRequest_734f6594c67fe6a9ab170191031d592c8fe7361bed628d9a36747664c9789bf1.json and b/packages/rs-sdk/tests/vectors/test_epoch_list/msg_GetEpochsInfoRequest_734f6594c67fe6a9ab170191031d592c8fe7361bed628d9a36747664c9789bf1.json differ diff --git a/packages/rs-sdk/tests/vectors/test_epoch_list/msg_GetIdentityRequest_10ade8322ef670cd19d1a472a5477667b9a9edd07833d77c1af884ca8a9849ca.json b/packages/rs-sdk/tests/vectors/test_epoch_list/msg_GetIdentityRequest_10ade8322ef670cd19d1a472a5477667b9a9edd07833d77c1af884ca8a9849ca.json new file mode 100644 index 0000000000..c3b77e7974 Binary files /dev/null and b/packages/rs-sdk/tests/vectors/test_epoch_list/msg_GetIdentityRequest_10ade8322ef670cd19d1a472a5477667b9a9edd07833d77c1af884ca8a9849ca.json differ diff --git a/packages/rs-sdk/tests/vectors/test_epoch_list/msg_GetIdentityRequest_24b7371202615ecd290e0fe7496676f04dc30c79eec5a5df1ab5b8d8671ac38e.json b/packages/rs-sdk/tests/vectors/test_epoch_list/msg_GetIdentityRequest_24b7371202615ecd290e0fe7496676f04dc30c79eec5a5df1ab5b8d8671ac38e.json deleted file mode 100644 index 5ba6485778..0000000000 Binary files a/packages/rs-sdk/tests/vectors/test_epoch_list/msg_GetIdentityRequest_24b7371202615ecd290e0fe7496676f04dc30c79eec5a5df1ab5b8d8671ac38e.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/test_epoch_list/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/test_epoch_list/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/test_epoch_list/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_epoch_list/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/test_epoch_list/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/test_epoch_list/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_epoch_list_limit/msg_GetEpochsInfoRequest_ae2b6b4e09e8e68e73f2df9af38b0b93d9d2e841a5e3d60755f8e7be3b93315b.json b/packages/rs-sdk/tests/vectors/test_epoch_list_limit/msg_GetEpochsInfoRequest_ae2b6b4e09e8e68e73f2df9af38b0b93d9d2e841a5e3d60755f8e7be3b93315b.json index f61518a9d4..13568b0d05 100644 Binary files a/packages/rs-sdk/tests/vectors/test_epoch_list_limit/msg_GetEpochsInfoRequest_ae2b6b4e09e8e68e73f2df9af38b0b93d9d2e841a5e3d60755f8e7be3b93315b.json and b/packages/rs-sdk/tests/vectors/test_epoch_list_limit/msg_GetEpochsInfoRequest_ae2b6b4e09e8e68e73f2df9af38b0b93d9d2e841a5e3d60755f8e7be3b93315b.json differ diff --git a/packages/rs-sdk/tests/vectors/test_epoch_list_limit/msg_GetIdentityRequest_10ade8322ef670cd19d1a472a5477667b9a9edd07833d77c1af884ca8a9849ca.json b/packages/rs-sdk/tests/vectors/test_epoch_list_limit/msg_GetIdentityRequest_10ade8322ef670cd19d1a472a5477667b9a9edd07833d77c1af884ca8a9849ca.json new file mode 100644 index 0000000000..c3b77e7974 Binary files /dev/null and b/packages/rs-sdk/tests/vectors/test_epoch_list_limit/msg_GetIdentityRequest_10ade8322ef670cd19d1a472a5477667b9a9edd07833d77c1af884ca8a9849ca.json differ diff --git a/packages/rs-sdk/tests/vectors/test_epoch_list_limit/msg_GetIdentityRequest_24b7371202615ecd290e0fe7496676f04dc30c79eec5a5df1ab5b8d8671ac38e.json b/packages/rs-sdk/tests/vectors/test_epoch_list_limit/msg_GetIdentityRequest_24b7371202615ecd290e0fe7496676f04dc30c79eec5a5df1ab5b8d8671ac38e.json deleted file mode 100644 index 5ba6485778..0000000000 Binary files a/packages/rs-sdk/tests/vectors/test_epoch_list_limit/msg_GetIdentityRequest_24b7371202615ecd290e0fe7496676f04dc30c79eec5a5df1ab5b8d8671ac38e.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/test_epoch_list_limit/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/test_epoch_list_limit/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/test_epoch_list_limit/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_epoch_list_limit/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/test_epoch_list_limit/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/test_epoch_list_limit/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_2dd27fc692c7bf9389f3b48c73a4d2538a4eb72d54c01cc4620b16b06eb31f4c/.gitkeep b/packages/rs-sdk/tests/vectors/test_evonode_status/.gitkeep similarity index 100% rename from packages/rs-sdk/tests/vectors/contested_resources_fields_2dd27fc692c7bf9389f3b48c73a4d2538a4eb72d54c01cc4620b16b06eb31f4c/.gitkeep rename to packages/rs-sdk/tests/vectors/test_evonode_status/.gitkeep diff --git a/packages/rs-sdk/tests/vectors/test_evonode_status/msg_EvoNode_fbdf15806b1160a9fb482d5663371cdde55f94897dcf9d905573b01fe445fbc9.json b/packages/rs-sdk/tests/vectors/test_evonode_status/msg_EvoNode_fbdf15806b1160a9fb482d5663371cdde55f94897dcf9d905573b01fe445fbc9.json new file mode 100644 index 0000000000..e51843cf30 Binary files /dev/null and b/packages/rs-sdk/tests/vectors/test_evonode_status/msg_EvoNode_fbdf15806b1160a9fb482d5663371cdde55f94897dcf9d905573b01fe445fbc9.json differ diff --git a/packages/rs-sdk/tests/vectors/contested_resources_fields_d838e1005b493d45e2b6b39712f4aa144f22b4daa1470657c0ab97ffd4f04455/.gitkeep b/packages/rs-sdk/tests/vectors/test_evonode_status_refused/.gitkeep similarity index 100% rename from packages/rs-sdk/tests/vectors/contested_resources_fields_d838e1005b493d45e2b6b39712f4aa144f22b4daa1470657c0ab97ffd4f04455/.gitkeep rename to packages/rs-sdk/tests/vectors/test_evonode_status_refused/.gitkeep diff --git a/packages/rs-sdk/tests/vectors/test_evonode_status_refused/msg_EvoNode_6db392ff1869b56ecc7de9ace5864123671ed14d3f0c537aa8e878d24e529de5.json b/packages/rs-sdk/tests/vectors/test_evonode_status_refused/msg_EvoNode_6db392ff1869b56ecc7de9ace5864123671ed14d3f0c537aa8e878d24e529de5.json new file mode 100644 index 0000000000..c80da24adb Binary files /dev/null and b/packages/rs-sdk/tests/vectors/test_evonode_status_refused/msg_EvoNode_6db392ff1869b56ecc7de9ace5864123671ed14d3f0c537aa8e878d24e529de5.json differ diff --git a/packages/rs-sdk/tests/vectors/test_identity_balance_read/msg_GetIdentityBalanceRequest_10ade8322ef670cd19d1a472a5477667b9a9edd07833d77c1af884ca8a9849ca.json b/packages/rs-sdk/tests/vectors/test_identity_balance_read/msg_GetIdentityBalanceRequest_10ade8322ef670cd19d1a472a5477667b9a9edd07833d77c1af884ca8a9849ca.json new file mode 100644 index 0000000000..8c3a7fa4d5 Binary files /dev/null and b/packages/rs-sdk/tests/vectors/test_identity_balance_read/msg_GetIdentityBalanceRequest_10ade8322ef670cd19d1a472a5477667b9a9edd07833d77c1af884ca8a9849ca.json differ diff --git a/packages/rs-sdk/tests/vectors/test_identity_balance_read/msg_GetIdentityBalanceRequest_24b7371202615ecd290e0fe7496676f04dc30c79eec5a5df1ab5b8d8671ac38e.json b/packages/rs-sdk/tests/vectors/test_identity_balance_read/msg_GetIdentityBalanceRequest_24b7371202615ecd290e0fe7496676f04dc30c79eec5a5df1ab5b8d8671ac38e.json deleted file mode 100644 index d8dff0972b..0000000000 Binary files a/packages/rs-sdk/tests/vectors/test_identity_balance_read/msg_GetIdentityBalanceRequest_24b7371202615ecd290e0fe7496676f04dc30c79eec5a5df1ab5b8d8671ac38e.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/test_identity_balance_read/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/test_identity_balance_read/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/test_identity_balance_read/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_identity_balance_read/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/test_identity_balance_read/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/test_identity_balance_read/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_identity_balance_revision_read/msg_GetIdentityBalanceAndRevisionRequest_10ade8322ef670cd19d1a472a5477667b9a9edd07833d77c1af884ca8a9849ca.json b/packages/rs-sdk/tests/vectors/test_identity_balance_revision_read/msg_GetIdentityBalanceAndRevisionRequest_10ade8322ef670cd19d1a472a5477667b9a9edd07833d77c1af884ca8a9849ca.json new file mode 100644 index 0000000000..550c9f33c1 Binary files /dev/null and b/packages/rs-sdk/tests/vectors/test_identity_balance_revision_read/msg_GetIdentityBalanceAndRevisionRequest_10ade8322ef670cd19d1a472a5477667b9a9edd07833d77c1af884ca8a9849ca.json differ diff --git a/packages/rs-sdk/tests/vectors/test_identity_balance_revision_read/msg_GetIdentityBalanceAndRevisionRequest_24b7371202615ecd290e0fe7496676f04dc30c79eec5a5df1ab5b8d8671ac38e.json b/packages/rs-sdk/tests/vectors/test_identity_balance_revision_read/msg_GetIdentityBalanceAndRevisionRequest_24b7371202615ecd290e0fe7496676f04dc30c79eec5a5df1ab5b8d8671ac38e.json deleted file mode 100644 index 3a8d1cbcc0..0000000000 Binary files a/packages/rs-sdk/tests/vectors/test_identity_balance_revision_read/msg_GetIdentityBalanceAndRevisionRequest_24b7371202615ecd290e0fe7496676f04dc30c79eec5a5df1ab5b8d8671ac38e.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/test_identity_balance_revision_read/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/test_identity_balance_revision_read/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/test_identity_balance_revision_read/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_identity_balance_revision_read/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/test_identity_balance_revision_read/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/test_identity_balance_revision_read/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_identity_contract_no_nonce_read/msg_GetIdentityContractNonceRequest_72462a05bc5903192201b038d5605a8592f3f01c08c7d529932075643c32dbc3.json b/packages/rs-sdk/tests/vectors/test_identity_contract_no_nonce_read/msg_GetIdentityContractNonceRequest_72462a05bc5903192201b038d5605a8592f3f01c08c7d529932075643c32dbc3.json new file mode 100644 index 0000000000..882ce2404b Binary files /dev/null and b/packages/rs-sdk/tests/vectors/test_identity_contract_no_nonce_read/msg_GetIdentityContractNonceRequest_72462a05bc5903192201b038d5605a8592f3f01c08c7d529932075643c32dbc3.json differ diff --git a/packages/rs-sdk/tests/vectors/test_identity_contract_no_nonce_read/msg_GetIdentityContractNonceRequest_815e2b4de88fb56ce7ec833ffe8901b95a32865deb2645934954725fbd1cca03.json b/packages/rs-sdk/tests/vectors/test_identity_contract_no_nonce_read/msg_GetIdentityContractNonceRequest_815e2b4de88fb56ce7ec833ffe8901b95a32865deb2645934954725fbd1cca03.json deleted file mode 100644 index 57897bf779..0000000000 Binary files a/packages/rs-sdk/tests/vectors/test_identity_contract_no_nonce_read/msg_GetIdentityContractNonceRequest_815e2b4de88fb56ce7ec833ffe8901b95a32865deb2645934954725fbd1cca03.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/test_identity_contract_no_nonce_read/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/test_identity_contract_no_nonce_read/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/test_identity_contract_no_nonce_read/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_identity_contract_no_nonce_read/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/test_identity_contract_no_nonce_read/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/test_identity_contract_no_nonce_read/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_identity_public_keys_all_read/msg_GetIdentityKeysRequest_bb682ae3f9e50aac47abec860399a3893c42d439056187c53b775ddc1bf1888d.json b/packages/rs-sdk/tests/vectors/test_identity_public_keys_all_read/msg_GetIdentityKeysRequest_bb682ae3f9e50aac47abec860399a3893c42d439056187c53b775ddc1bf1888d.json new file mode 100644 index 0000000000..06e8873998 Binary files /dev/null and b/packages/rs-sdk/tests/vectors/test_identity_public_keys_all_read/msg_GetIdentityKeysRequest_bb682ae3f9e50aac47abec860399a3893c42d439056187c53b775ddc1bf1888d.json differ diff --git a/packages/rs-sdk/tests/vectors/test_identity_public_keys_all_read/msg_GetIdentityKeysRequest_c9aa65558b4f8ba10bd7509498105dac7fab00a65264648889a477f081e30ced.json b/packages/rs-sdk/tests/vectors/test_identity_public_keys_all_read/msg_GetIdentityKeysRequest_c9aa65558b4f8ba10bd7509498105dac7fab00a65264648889a477f081e30ced.json deleted file mode 100644 index 6cdcab983d..0000000000 Binary files a/packages/rs-sdk/tests/vectors/test_identity_public_keys_all_read/msg_GetIdentityKeysRequest_c9aa65558b4f8ba10bd7509498105dac7fab00a65264648889a477f081e30ced.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/test_identity_public_keys_all_read/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/test_identity_public_keys_all_read/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/test_identity_public_keys_all_read/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_identity_public_keys_all_read/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/test_identity_public_keys_all_read/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/test_identity_public_keys_all_read/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_identity_read/msg_IdentityRequest_d44a1cbdbdc341bf6b93e30b722720adf6dca7b1503f65c559f3b70b7c58293f.json b/packages/rs-sdk/tests/vectors/test_identity_read/msg_IdentityRequest_d44a1cbdbdc341bf6b93e30b722720adf6dca7b1503f65c559f3b70b7c58293f.json new file mode 100644 index 0000000000..5180bb5f34 Binary files /dev/null and b/packages/rs-sdk/tests/vectors/test_identity_read/msg_IdentityRequest_d44a1cbdbdc341bf6b93e30b722720adf6dca7b1503f65c559f3b70b7c58293f.json differ diff --git a/packages/rs-sdk/tests/vectors/test_identity_read/msg_IdentityRequest_da9cbb7a9f245221fe2a5d7fe5dd40a692960262df24a300d226046c57048de7.json b/packages/rs-sdk/tests/vectors/test_identity_read/msg_IdentityRequest_da9cbb7a9f245221fe2a5d7fe5dd40a692960262df24a300d226046c57048de7.json deleted file mode 100644 index 973d06ba4c..0000000000 Binary files a/packages/rs-sdk/tests/vectors/test_identity_read/msg_IdentityRequest_da9cbb7a9f245221fe2a5d7fe5dd40a692960262df24a300d226046c57048de7.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/test_identity_read/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/test_identity_read/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/test_identity_read/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_identity_read/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/test_identity_read/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/test_identity_read/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_identity_read_by_key/msg_IdentityRequest_3dbae0092e7945775a61bd84d655a4a303a60215ac4143afd63720bbb6d8c496.json b/packages/rs-sdk/tests/vectors/test_identity_read_by_key/msg_IdentityRequest_3dbae0092e7945775a61bd84d655a4a303a60215ac4143afd63720bbb6d8c496.json new file mode 100644 index 0000000000..a74e059200 Binary files /dev/null and b/packages/rs-sdk/tests/vectors/test_identity_read_by_key/msg_IdentityRequest_3dbae0092e7945775a61bd84d655a4a303a60215ac4143afd63720bbb6d8c496.json differ diff --git a/packages/rs-sdk/tests/vectors/test_identity_read_by_key/msg_IdentityRequest_d44a1cbdbdc341bf6b93e30b722720adf6dca7b1503f65c559f3b70b7c58293f.json b/packages/rs-sdk/tests/vectors/test_identity_read_by_key/msg_IdentityRequest_d44a1cbdbdc341bf6b93e30b722720adf6dca7b1503f65c559f3b70b7c58293f.json new file mode 100644 index 0000000000..5180bb5f34 Binary files /dev/null and b/packages/rs-sdk/tests/vectors/test_identity_read_by_key/msg_IdentityRequest_d44a1cbdbdc341bf6b93e30b722720adf6dca7b1503f65c559f3b70b7c58293f.json differ diff --git a/packages/rs-sdk/tests/vectors/test_identity_read_by_key/msg_IdentityRequest_da9cbb7a9f245221fe2a5d7fe5dd40a692960262df24a300d226046c57048de7.json b/packages/rs-sdk/tests/vectors/test_identity_read_by_key/msg_IdentityRequest_da9cbb7a9f245221fe2a5d7fe5dd40a692960262df24a300d226046c57048de7.json deleted file mode 100644 index 973d06ba4c..0000000000 Binary files a/packages/rs-sdk/tests/vectors/test_identity_read_by_key/msg_IdentityRequest_da9cbb7a9f245221fe2a5d7fe5dd40a692960262df24a300d226046c57048de7.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/test_identity_read_by_key/msg_IdentityRequest_ec8288b622e659eee0ea5c67d54eaa7b41821696e9131d8bec0e3b4c9cbb6ed4.json b/packages/rs-sdk/tests/vectors/test_identity_read_by_key/msg_IdentityRequest_ec8288b622e659eee0ea5c67d54eaa7b41821696e9131d8bec0e3b4c9cbb6ed4.json deleted file mode 100644 index abe3c317df..0000000000 Binary files a/packages/rs-sdk/tests/vectors/test_identity_read_by_key/msg_IdentityRequest_ec8288b622e659eee0ea5c67d54eaa7b41821696e9131d8bec0e3b4c9cbb6ed4.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/test_identity_read_by_key/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/test_identity_read_by_key/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/test_identity_read_by_key/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_identity_read_by_key/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/test_identity_read_by_key/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/test_identity_read_by_key/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_prefunded_specialized_balance_not_found/msg_GetPrefundedSpecializedBalanceRequest_1d1e53ab5e04d9ec5dce4ff9ac048c03122daf7ab2e77108f4bf44af1ad15eae.json b/packages/rs-sdk/tests/vectors/test_prefunded_specialized_balance_not_found/msg_GetPrefundedSpecializedBalanceRequest_1d1e53ab5e04d9ec5dce4ff9ac048c03122daf7ab2e77108f4bf44af1ad15eae.json index e0f0b7f4df..eb28f8260f 100644 Binary files a/packages/rs-sdk/tests/vectors/test_prefunded_specialized_balance_not_found/msg_GetPrefundedSpecializedBalanceRequest_1d1e53ab5e04d9ec5dce4ff9ac048c03122daf7ab2e77108f4bf44af1ad15eae.json and b/packages/rs-sdk/tests/vectors/test_prefunded_specialized_balance_not_found/msg_GetPrefundedSpecializedBalanceRequest_1d1e53ab5e04d9ec5dce4ff9ac048c03122daf7ab2e77108f4bf44af1ad15eae.json differ diff --git a/packages/rs-sdk/tests/vectors/test_prefunded_specialized_balance_not_found/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/test_prefunded_specialized_balance_not_found/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/test_prefunded_specialized_balance_not_found/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_prefunded_specialized_balance_not_found/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/test_prefunded_specialized_balance_not_found/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/test_prefunded_specialized_balance_not_found/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_prefunded_specialized_balance_ok/msg_GetPrefundedSpecializedBalanceRequest_025257146b516a8c29cad26800714ad6a0b47b50c5fd84a4e094fbf06ff040b1.json b/packages/rs-sdk/tests/vectors/test_prefunded_specialized_balance_ok/msg_GetPrefundedSpecializedBalanceRequest_025257146b516a8c29cad26800714ad6a0b47b50c5fd84a4e094fbf06ff040b1.json new file mode 100644 index 0000000000..06e4faba10 Binary files /dev/null and b/packages/rs-sdk/tests/vectors/test_prefunded_specialized_balance_ok/msg_GetPrefundedSpecializedBalanceRequest_025257146b516a8c29cad26800714ad6a0b47b50c5fd84a4e094fbf06ff040b1.json differ diff --git a/packages/rs-sdk/tests/vectors/test_prefunded_specialized_balance_ok/msg_GetPrefundedSpecializedBalanceRequest_0a917fd6c7841682776fa2800a49fbd646666cf92a70e4954bdeab26f75f3049.json b/packages/rs-sdk/tests/vectors/test_prefunded_specialized_balance_ok/msg_GetPrefundedSpecializedBalanceRequest_0a917fd6c7841682776fa2800a49fbd646666cf92a70e4954bdeab26f75f3049.json deleted file mode 100644 index 48fd17ef44..0000000000 Binary files a/packages/rs-sdk/tests/vectors/test_prefunded_specialized_balance_ok/msg_GetPrefundedSpecializedBalanceRequest_0a917fd6c7841682776fa2800a49fbd646666cf92a70e4954bdeab26f75f3049.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/test_prefunded_specialized_balance_ok/msg_GetVotePollsByEndDateRequest_90f99444544de47f7e78de44bcaca1b6ba4883a92f4533995dbfdbc5875d8bef.json b/packages/rs-sdk/tests/vectors/test_prefunded_specialized_balance_ok/msg_GetVotePollsByEndDateRequest_90f99444544de47f7e78de44bcaca1b6ba4883a92f4533995dbfdbc5875d8bef.json index a6610834d7..cce948bda8 100644 Binary files a/packages/rs-sdk/tests/vectors/test_prefunded_specialized_balance_ok/msg_GetVotePollsByEndDateRequest_90f99444544de47f7e78de44bcaca1b6ba4883a92f4533995dbfdbc5875d8bef.json and b/packages/rs-sdk/tests/vectors/test_prefunded_specialized_balance_ok/msg_GetVotePollsByEndDateRequest_90f99444544de47f7e78de44bcaca1b6ba4883a92f4533995dbfdbc5875d8bef.json differ diff --git a/packages/rs-sdk/tests/vectors/test_prefunded_specialized_balance_ok/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/test_prefunded_specialized_balance_ok/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/test_prefunded_specialized_balance_ok/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_prefunded_specialized_balance_ok/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/test_prefunded_specialized_balance_ok/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/test_prefunded_specialized_balance_ok/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_protocol_version_vote_count/msg_GetProtocolVersionUpgradeStateRequest_bb149e1933b9dc561bbfacfb6d09550f0ea4a6af6f68037e7d50ff4e4de74509.json b/packages/rs-sdk/tests/vectors/test_protocol_version_vote_count/msg_GetProtocolVersionUpgradeStateRequest_bb149e1933b9dc561bbfacfb6d09550f0ea4a6af6f68037e7d50ff4e4de74509.json index ab25ca978d..80e2902e5a 100644 Binary files a/packages/rs-sdk/tests/vectors/test_protocol_version_vote_count/msg_GetProtocolVersionUpgradeStateRequest_bb149e1933b9dc561bbfacfb6d09550f0ea4a6af6f68037e7d50ff4e4de74509.json and b/packages/rs-sdk/tests/vectors/test_protocol_version_vote_count/msg_GetProtocolVersionUpgradeStateRequest_bb149e1933b9dc561bbfacfb6d09550f0ea4a6af6f68037e7d50ff4e4de74509.json differ diff --git a/packages/rs-sdk/tests/vectors/test_protocol_version_vote_count/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/test_protocol_version_vote_count/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/test_protocol_version_vote_count/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_protocol_version_vote_count/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/test_protocol_version_vote_count/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/test_protocol_version_vote_count/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_protocol_version_votes_limit_2/msg_GetProtocolVersionUpgradeVoteStatusRequest_ec9dca65a964669b3bc8195d5ff106e5eda740be44679cc960ea35f2134af628.json b/packages/rs-sdk/tests/vectors/test_protocol_version_votes_limit_2/msg_GetProtocolVersionUpgradeVoteStatusRequest_ec9dca65a964669b3bc8195d5ff106e5eda740be44679cc960ea35f2134af628.json index 5d2c789179..60a871c5ca 100644 Binary files a/packages/rs-sdk/tests/vectors/test_protocol_version_votes_limit_2/msg_GetProtocolVersionUpgradeVoteStatusRequest_ec9dca65a964669b3bc8195d5ff106e5eda740be44679cc960ea35f2134af628.json and b/packages/rs-sdk/tests/vectors/test_protocol_version_votes_limit_2/msg_GetProtocolVersionUpgradeVoteStatusRequest_ec9dca65a964669b3bc8195d5ff106e5eda740be44679cc960ea35f2134af628.json differ diff --git a/packages/rs-sdk/tests/vectors/test_protocol_version_votes_limit_2/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/test_protocol_version_votes_limit_2/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/test_protocol_version_votes_limit_2/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_protocol_version_votes_limit_2/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/test_protocol_version_votes_limit_2/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/test_protocol_version_votes_limit_2/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_protocol_version_votes_none/msg_GetProtocolVersionUpgradeVoteStatusRequest_983670ac95678b1166deab32209bf1acc3394d29ac72f662d38e81344496631e.json b/packages/rs-sdk/tests/vectors/test_protocol_version_votes_none/msg_GetProtocolVersionUpgradeVoteStatusRequest_983670ac95678b1166deab32209bf1acc3394d29ac72f662d38e81344496631e.json index f65662394e..c4bf9c14e5 100644 Binary files a/packages/rs-sdk/tests/vectors/test_protocol_version_votes_none/msg_GetProtocolVersionUpgradeVoteStatusRequest_983670ac95678b1166deab32209bf1acc3394d29ac72f662d38e81344496631e.json and b/packages/rs-sdk/tests/vectors/test_protocol_version_votes_none/msg_GetProtocolVersionUpgradeVoteStatusRequest_983670ac95678b1166deab32209bf1acc3394d29ac72f662d38e81344496631e.json differ diff --git a/packages/rs-sdk/tests/vectors/test_protocol_version_votes_none/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/test_protocol_version_votes_none/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/test_protocol_version_votes_none/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_protocol_version_votes_none/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/test_protocol_version_votes_none/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/test_protocol_version_votes_none/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_protocol_version_votes_nx/msg_GetProtocolVersionUpgradeVoteStatusRequest_8534be7e0b4dd648520dc3a67209b1a05862cb8d40c088b193b59ca3564210bc.json b/packages/rs-sdk/tests/vectors/test_protocol_version_votes_nx/msg_GetProtocolVersionUpgradeVoteStatusRequest_8534be7e0b4dd648520dc3a67209b1a05862cb8d40c088b193b59ca3564210bc.json index 3b399bc398..0ff2528fc3 100644 Binary files a/packages/rs-sdk/tests/vectors/test_protocol_version_votes_nx/msg_GetProtocolVersionUpgradeVoteStatusRequest_8534be7e0b4dd648520dc3a67209b1a05862cb8d40c088b193b59ca3564210bc.json and b/packages/rs-sdk/tests/vectors/test_protocol_version_votes_nx/msg_GetProtocolVersionUpgradeVoteStatusRequest_8534be7e0b4dd648520dc3a67209b1a05862cb8d40c088b193b59ca3564210bc.json differ diff --git a/packages/rs-sdk/tests/vectors/test_protocol_version_votes_nx/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/test_protocol_version_votes_nx/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/test_protocol_version_votes_nx/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_protocol_version_votes_nx/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/test_protocol_version_votes_nx/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/test_protocol_version_votes_nx/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_protocol_version_votes_zeros/msg_GetProtocolVersionUpgradeVoteStatusRequest_92a45a0fe4f69d355022d2f2f7622dfc69cc7b123be24b7ad993281979b2a3a2.json b/packages/rs-sdk/tests/vectors/test_protocol_version_votes_zeros/msg_GetProtocolVersionUpgradeVoteStatusRequest_92a45a0fe4f69d355022d2f2f7622dfc69cc7b123be24b7ad993281979b2a3a2.json index b1065b770a..f46dd956d7 100644 Binary files a/packages/rs-sdk/tests/vectors/test_protocol_version_votes_zeros/msg_GetProtocolVersionUpgradeVoteStatusRequest_92a45a0fe4f69d355022d2f2f7622dfc69cc7b123be24b7ad993281979b2a3a2.json and b/packages/rs-sdk/tests/vectors/test_protocol_version_votes_zeros/msg_GetProtocolVersionUpgradeVoteStatusRequest_92a45a0fe4f69d355022d2f2f7622dfc69cc7b123be24b7ad993281979b2a3a2.json differ diff --git a/packages/rs-sdk/tests/vectors/test_protocol_version_votes_zeros/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/test_protocol_version_votes_zeros/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/test_protocol_version_votes_zeros/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/test_protocol_version_votes_zeros/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/test_protocol_version_votes_zeros/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/test_protocol_version_votes_zeros/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_0329cf0b8851d09d91160eb04ba78d45ac35df7c4a541f2fd79c4e53af000a92.json b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_0329cf0b8851d09d91160eb04ba78d45ac35df7c4a541f2fd79c4e53af000a92.json deleted file mode 100644 index b06a885243..0000000000 Binary files a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_0329cf0b8851d09d91160eb04ba78d45ac35df7c4a541f2fd79c4e53af000a92.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_0cb9ee36247bc1ceaf62016370f4ef834e6bbb89d21b2f08163de5106d9db335.json b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_0cb9ee36247bc1ceaf62016370f4ef834e6bbb89d21b2f08163de5106d9db335.json new file mode 100644 index 0000000000..0372ec584a Binary files /dev/null and b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_0cb9ee36247bc1ceaf62016370f4ef834e6bbb89d21b2f08163de5106d9db335.json differ diff --git a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_0dde395b4b415889954d709f63d4df85a544ca7ab40bb4fc7a1bd8e8ade47e62.json b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_0dde395b4b415889954d709f63d4df85a544ca7ab40bb4fc7a1bd8e8ade47e62.json new file mode 100644 index 0000000000..540dedcfe4 Binary files /dev/null and b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_0dde395b4b415889954d709f63d4df85a544ca7ab40bb4fc7a1bd8e8ade47e62.json differ diff --git a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_0e309af16c3957b15807f1741084729771183f61b1ba73796ee966df7ce206e8.json b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_0e309af16c3957b15807f1741084729771183f61b1ba73796ee966df7ce206e8.json deleted file mode 100644 index ec7ffa5bea..0000000000 Binary files a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_0e309af16c3957b15807f1741084729771183f61b1ba73796ee966df7ce206e8.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_142e6c253c01773656823e7299ccac0d096683e15280eced19ef5ad75e670062.json b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_142e6c253c01773656823e7299ccac0d096683e15280eced19ef5ad75e670062.json deleted file mode 100644 index 59530fd57d..0000000000 Binary files a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_142e6c253c01773656823e7299ccac0d096683e15280eced19ef5ad75e670062.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_2e98e756bbec29c5a8bb6db95209822a2c4f59abefee6ac70309345adad1c202.json b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_2e98e756bbec29c5a8bb6db95209822a2c4f59abefee6ac70309345adad1c202.json deleted file mode 100644 index 2efaa4da15..0000000000 Binary files a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_2e98e756bbec29c5a8bb6db95209822a2c4f59abefee6ac70309345adad1c202.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_4cb42e1877d46573cade78a050501448ade8c60e56c8d4b739ff8d6808694f33.json b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_4cb42e1877d46573cade78a050501448ade8c60e56c8d4b739ff8d6808694f33.json deleted file mode 100644 index 475f92631e..0000000000 Binary files a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_4cb42e1877d46573cade78a050501448ade8c60e56c8d4b739ff8d6808694f33.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_5712787e7fb90c195d81acfdc0659525067352d9440afaca1db61fb1f51e83ae.json b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_5712787e7fb90c195d81acfdc0659525067352d9440afaca1db61fb1f51e83ae.json new file mode 100644 index 0000000000..f669830c8a Binary files /dev/null and b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_5712787e7fb90c195d81acfdc0659525067352d9440afaca1db61fb1f51e83ae.json differ diff --git a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_5a13e820a6f3aa36accabe630aac61d0223027f3bca7edc99237362654f2bfb0.json b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_5a13e820a6f3aa36accabe630aac61d0223027f3bca7edc99237362654f2bfb0.json new file mode 100644 index 0000000000..2730aa198a Binary files /dev/null and b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_5a13e820a6f3aa36accabe630aac61d0223027f3bca7edc99237362654f2bfb0.json differ diff --git a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_61f016345ec587c57ec95cd35ca21e65356ecde06e41dad1c5f4221f2021ff65.json b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_61f016345ec587c57ec95cd35ca21e65356ecde06e41dad1c5f4221f2021ff65.json deleted file mode 100644 index 319bc61225..0000000000 Binary files a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_61f016345ec587c57ec95cd35ca21e65356ecde06e41dad1c5f4221f2021ff65.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_62753b0c8caf599658c8a6becb2a0c949e21b06d4ba0ba04902ed9dd3cf9c180.json b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_62753b0c8caf599658c8a6becb2a0c949e21b06d4ba0ba04902ed9dd3cf9c180.json deleted file mode 100644 index 4ec9e25724..0000000000 Binary files a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_62753b0c8caf599658c8a6becb2a0c949e21b06d4ba0ba04902ed9dd3cf9c180.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_6324f0ce91119010ab60300a78dc362866cbab6d8388743fdcf5d797910561df.json b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_6324f0ce91119010ab60300a78dc362866cbab6d8388743fdcf5d797910561df.json index aa5a28ec90..2ec9c6f452 100644 Binary files a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_6324f0ce91119010ab60300a78dc362866cbab6d8388743fdcf5d797910561df.json and b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_6324f0ce91119010ab60300a78dc362866cbab6d8388743fdcf5d797910561df.json differ diff --git a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_86adcaba8608771c706d272e516e36aa98b6acdcb910a746650383c174e884e8.json b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_86adcaba8608771c706d272e516e36aa98b6acdcb910a746650383c174e884e8.json new file mode 100644 index 0000000000..72871a31a0 Binary files /dev/null and b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_86adcaba8608771c706d272e516e36aa98b6acdcb910a746650383c174e884e8.json differ diff --git a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_8af1fe2b83fc914ad833914a6f47686a168bd79e8751279ec53efb41381dd431.json b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_8af1fe2b83fc914ad833914a6f47686a168bd79e8751279ec53efb41381dd431.json index fbb1cfb284..a9482783b7 100644 Binary files a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_8af1fe2b83fc914ad833914a6f47686a168bd79e8751279ec53efb41381dd431.json and b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_8af1fe2b83fc914ad833914a6f47686a168bd79e8751279ec53efb41381dd431.json differ diff --git a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_8dd8d6620ba68bceb5a65a1c2b80daadb7e1a4cc0c58c52450dd44d5ca462e4a.json b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_8dd8d6620ba68bceb5a65a1c2b80daadb7e1a4cc0c58c52450dd44d5ca462e4a.json new file mode 100644 index 0000000000..ce27975420 Binary files /dev/null and b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_8dd8d6620ba68bceb5a65a1c2b80daadb7e1a4cc0c58c52450dd44d5ca462e4a.json differ diff --git a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_9085af05cad5f81e4684b91c4b6edc3a3ee50e58b0617b9da04faad767a7414e.json b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_9085af05cad5f81e4684b91c4b6edc3a3ee50e58b0617b9da04faad767a7414e.json deleted file mode 100644 index 027fe03684..0000000000 Binary files a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_9085af05cad5f81e4684b91c4b6edc3a3ee50e58b0617b9da04faad767a7414e.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_a2a3107907325a7d7da45018edd1415b05c514461090693b709359fd10719e64.json b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_a2a3107907325a7d7da45018edd1415b05c514461090693b709359fd10719e64.json deleted file mode 100644 index 13f9832696..0000000000 Binary files a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_a2a3107907325a7d7da45018edd1415b05c514461090693b709359fd10719e64.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_c2737f6ccc2ac5cc79e28d4b29fb414d7808274b04acfe789740e18ecf0991c7.json b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_c2737f6ccc2ac5cc79e28d4b29fb414d7808274b04acfe789740e18ecf0991c7.json deleted file mode 100644 index 6635850ad0..0000000000 Binary files a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_c2737f6ccc2ac5cc79e28d4b29fb414d7808274b04acfe789740e18ecf0991c7.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_edb3ea19c943e4ccd318d2742a9ecfc2f026b8a6be6443de638da69f0b4c87b0.json b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_edb3ea19c943e4ccd318d2742a9ecfc2f026b8a6be6443de638da69f0b4c87b0.json deleted file mode 100644 index d3dc6481ce..0000000000 Binary files a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_edb3ea19c943e4ccd318d2742a9ecfc2f026b8a6be6443de638da69f0b4c87b0.json and /dev/null differ diff --git a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_f1f82e9e31d7112f92816896406df8382ca43f73cf9e63aa985c1add075d0264.json b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_f1f82e9e31d7112f92816896406df8382ca43f73cf9e63aa985c1add075d0264.json new file mode 100644 index 0000000000..586068b1ce Binary files /dev/null and b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/msg_GetVotePollsByEndDateRequest_f1f82e9e31d7112f92816896406df8382ca43f73cf9e63aa985c1add075d0264.json differ diff --git a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_limit/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_ok/msg_GetVotePollsByEndDateRequest_90f99444544de47f7e78de44bcaca1b6ba4883a92f4533995dbfdbc5875d8bef.json b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_ok/msg_GetVotePollsByEndDateRequest_90f99444544de47f7e78de44bcaca1b6ba4883a92f4533995dbfdbc5875d8bef.json index a6610834d7..cce948bda8 100644 Binary files a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_ok/msg_GetVotePollsByEndDateRequest_90f99444544de47f7e78de44bcaca1b6ba4883a92f4533995dbfdbc5875d8bef.json and b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_ok/msg_GetVotePollsByEndDateRequest_90f99444544de47f7e78de44bcaca1b6ba4883a92f4533995dbfdbc5875d8bef.json differ diff --git a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_ok/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_ok/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_ok/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_ok/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_ok/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_ok/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_order/msg_GetVotePollsByEndDateRequest_4959b488e99ae1bd41af47fdecce942470ee2b9dff806909798d12c40bc6cf8b.json b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_order/msg_GetVotePollsByEndDateRequest_4959b488e99ae1bd41af47fdecce942470ee2b9dff806909798d12c40bc6cf8b.json index ebae4be65b..2827b35ca3 100644 Binary files a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_order/msg_GetVotePollsByEndDateRequest_4959b488e99ae1bd41af47fdecce942470ee2b9dff806909798d12c40bc6cf8b.json and b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_order/msg_GetVotePollsByEndDateRequest_4959b488e99ae1bd41af47fdecce942470ee2b9dff806909798d12c40bc6cf8b.json differ diff --git a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_order/msg_GetVotePollsByEndDateRequest_90f99444544de47f7e78de44bcaca1b6ba4883a92f4533995dbfdbc5875d8bef.json b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_order/msg_GetVotePollsByEndDateRequest_90f99444544de47f7e78de44bcaca1b6ba4883a92f4533995dbfdbc5875d8bef.json index a6610834d7..cce948bda8 100644 Binary files a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_order/msg_GetVotePollsByEndDateRequest_90f99444544de47f7e78de44bcaca1b6ba4883a92f4533995dbfdbc5875d8bef.json and b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_order/msg_GetVotePollsByEndDateRequest_90f99444544de47f7e78de44bcaca1b6ba4883a92f4533995dbfdbc5875d8bef.json differ diff --git a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_order/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_order/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json new file mode 100644 index 0000000000..f40d52a617 --- /dev/null +++ b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_order/quorum_pubkey-106-029045172fbebcf97290db8879490a48ac0d1d60e249d031b5ad79e3e46e3fca.json @@ -0,0 +1 @@ +90e4366ffd8062dfcd46717d137c9c6c8c312c2622f508c6f3e713f256b7786c3ed8382b2f5fa9710fe592b668a4313a \ No newline at end of file diff --git a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_order/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json b/packages/rs-sdk/tests/vectors/vote_polls_by_ts_order/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json deleted file mode 100644 index 9d31d601d5..0000000000 --- a/packages/rs-sdk/tests/vectors/vote_polls_by_ts_order/quorum_pubkey-106-74bc78bfed100cb1c7da3b1aeeaff1e5767efb0daf93c69cc8294ee246526a09.json +++ /dev/null @@ -1 +0,0 @@ -8fdaad8ac39e23c5b9e773184f5f54523f4bc7b1ed68a66b43c011ecfe8c6f3c38b5e8bae650b2b4434f4ff9f15e7417 \ No newline at end of file diff --git a/packages/simple-signer/Cargo.toml b/packages/simple-signer/Cargo.toml index 6245e5607b..080f921ba7 100644 --- a/packages/simple-signer/Cargo.toml +++ b/packages/simple-signer/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "simple-signer" -version = "1.3.1" +version = "1.5.0" edition = "2021" rust-version.workspace = true @@ -8,6 +8,6 @@ rust-version.workspace = true [dependencies] bincode = { version = "2.0.0-rc.3", features = ["serde"] } -dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore-rpc", tag = "v0.15.4" } +dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore-rpc", tag = "v0.15.8" } dpp = { path = "../rs-dpp", features = ["abci"] } base64 = { version = "0.22.1" } diff --git a/packages/simple-signer/src/signer.rs b/packages/simple-signer/src/signer.rs index f8f8f92f3b..448e1a5c9c 100644 --- a/packages/simple-signer/src/signer.rs +++ b/packages/simple-signer/src/signer.rs @@ -106,4 +106,11 @@ impl Signer for SimpleSigner { )), } } + + fn can_sign_with(&self, identity_public_key: &IdentityPublicKey) -> bool { + self.private_keys + .get(identity_public_key) + .or_else(|| self.private_keys_in_creation.get(identity_public_key)) + .is_some() + } } diff --git a/packages/strategy-tests/Cargo.toml b/packages/strategy-tests/Cargo.toml index 5253de8554..e3666a076e 100644 --- a/packages/strategy-tests/Cargo.toml +++ b/packages/strategy-tests/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "strategy-tests" -version = "1.3.1" +version = "1.5.0" authors = [ "Samuel Westrich ", "Ivan Shumkov ", diff --git a/packages/strategy-tests/src/lib.rs b/packages/strategy-tests/src/lib.rs index 126538a64a..61395d99f2 100644 --- a/packages/strategy-tests/src/lib.rs +++ b/packages/strategy-tests/src/lib.rs @@ -45,13 +45,15 @@ use rand::prelude::StdRng; use rand::seq::{IteratorRandom, SliceRandom}; use rand::Rng; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; +use std::ops::RangeInclusive; use bincode::{Decode, Encode}; use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters; use dpp::identifier::Identifier; use dpp::data_contract::document_type::DocumentType; +use dpp::fee::Credits; use dpp::identity::accessors::IdentityGettersV0; use dpp::platform_value::{BinaryData, Bytes32, Value}; -use dpp::ProtocolError; +use dpp::{dash_to_duffs, ProtocolError}; use dpp::ProtocolError::{PlatformDeserializationError, PlatformSerializationError}; use dpp::state_transition::documents_batch_transition::document_base_transition::v0::DocumentBaseTransitionV0; use dpp::state_transition::documents_batch_transition::document_create_transition::{DocumentCreateTransition, DocumentCreateTransitionV0}; @@ -153,6 +155,7 @@ pub struct IdentityInsertInfo { pub frequency: Frequency, pub start_keys: u8, pub extra_keys: KeyMaps, + pub start_balance_range: RangeInclusive, } impl Default for IdentityInsertInfo { @@ -161,6 +164,7 @@ impl Default for IdentityInsertInfo { frequency: Default::default(), start_keys: 5, extra_keys: Default::default(), + start_balance_range: dash_to_duffs!(1)..=dash_to_duffs!(1), } } } @@ -1167,7 +1171,10 @@ impl Strategy { } // Generate state transition for identity top-up operation - OperationType::IdentityTopUp if !current_identities.is_empty() => { + OperationType::IdentityTopUp(_amount_range) + if !current_identities.is_empty() => + { + // todo: use amount ranges // Use a cyclic iterator over the identities to ensure we can create 'count' transitions let cyclic_identities = current_identities.iter().cycle(); @@ -1261,13 +1268,16 @@ impl Strategy { } // Generate state transition for identity withdrawal operation - OperationType::IdentityWithdrawal if !current_identities.is_empty() => { + OperationType::IdentityWithdrawal(amount_range) + if !current_identities.is_empty() => + { for i in 0..count { let index = (i as usize) % current_identities.len(); let random_identity = &mut current_identities[index]; let state_transition = crate::transitions::create_identity_withdrawal_transition( random_identity, + amount_range.clone(), identity_nonce_counter, signer, rng, @@ -1853,6 +1863,7 @@ mod tests { use crate::operations::{DocumentAction, DocumentOp, Operation, OperationType}; use crate::transitions::create_state_transitions_for_identities; use crate::{StartIdentities, Strategy}; + use dpp::dash_to_duffs; use dpp::data_contract::accessors::v0::DataContractV0Getters; use dpp::data_contract::document_type::random_document::{ DocumentFieldFillSize, DocumentFieldFillType, @@ -1902,6 +1913,7 @@ mod tests { let start_identities = create_state_transitions_for_identities( vec![identity1, identity2], + &(dash_to_duffs!(1)..=dash_to_duffs!(1)), &mut simple_signer, &mut rng, platform_version, diff --git a/packages/strategy-tests/src/operations.rs b/packages/strategy-tests/src/operations.rs index c3e52414cd..675e996843 100644 --- a/packages/strategy-tests/src/operations.rs +++ b/packages/strategy-tests/src/operations.rs @@ -9,6 +9,7 @@ use dpp::data_contract::document_type::v0::random_document_type::RandomDocumentT use dpp::data_contract::document_type::DocumentType; use dpp::data_contract::serialized_version::DataContractInSerializationFormat; use dpp::data_contract::{DataContract as Contract, DataContract}; +use dpp::fee::Credits; use dpp::identifier::Identifier; use dpp::identity::IdentityPublicKey; use dpp::platform_value::Value; @@ -26,7 +27,7 @@ use platform_version::{TryFromPlatformVersioned, TryIntoPlatformVersioned}; use rand::distributions::{Distribution, WeightedIndex}; use rand::prelude::StdRng; use std::collections::BTreeMap; -use std::ops::Range; +use std::ops::{Range, RangeInclusive}; #[derive(Clone, Debug, PartialEq, Encode, Decode)] pub enum DocumentAction { @@ -494,12 +495,14 @@ impl VoteAction { } } +pub type AmountRange = RangeInclusive; + #[derive(Clone, Debug, PartialEq)] pub enum OperationType { Document(DocumentOp), - IdentityTopUp, + IdentityTopUp(AmountRange), IdentityUpdate(IdentityUpdateOp), - IdentityWithdrawal, + IdentityWithdrawal(AmountRange), ContractCreate(RandomDocumentTypeParameters, DocumentTypeCount), ContractUpdate(DataContractUpdateOp), IdentityTransfer, @@ -509,9 +512,9 @@ pub enum OperationType { #[derive(Clone, Debug, Encode, Decode)] enum OperationTypeInSerializationFormat { Document(Vec), - IdentityTopUp, + IdentityTopUp(AmountRange), IdentityUpdate(IdentityUpdateOp), - IdentityWithdrawal, + IdentityWithdrawal(AmountRange), ContractCreate(RandomDocumentTypeParameters, DocumentTypeCount), ContractUpdate(Vec), IdentityTransfer, @@ -540,12 +543,14 @@ impl PlatformSerializableWithPlatformVersion for OperationType { .serialize_consume_to_bytes_with_platform_version(platform_version)?; OperationTypeInSerializationFormat::Document(document_op_in_serialization_format) } - OperationType::IdentityTopUp => OperationTypeInSerializationFormat::IdentityTopUp, + OperationType::IdentityTopUp(amount_range) => { + OperationTypeInSerializationFormat::IdentityTopUp(amount_range) + } OperationType::IdentityUpdate(identity_update_op) => { OperationTypeInSerializationFormat::IdentityUpdate(identity_update_op) } - OperationType::IdentityWithdrawal => { - OperationTypeInSerializationFormat::IdentityWithdrawal + OperationType::IdentityWithdrawal(amount_range) => { + OperationTypeInSerializationFormat::IdentityWithdrawal(amount_range) } OperationType::ContractCreate(p, c) => { OperationTypeInSerializationFormat::ContractCreate(p, c) @@ -601,12 +606,14 @@ impl PlatformDeserializableWithPotentialValidationFromVersionedStructure for Ope )?; OperationType::Document(document_op) } - OperationTypeInSerializationFormat::IdentityTopUp => OperationType::IdentityTopUp, + OperationTypeInSerializationFormat::IdentityTopUp(amount_range) => { + OperationType::IdentityTopUp(amount_range) + } OperationTypeInSerializationFormat::IdentityUpdate(identity_update_op) => { OperationType::IdentityUpdate(identity_update_op) } - OperationTypeInSerializationFormat::IdentityWithdrawal => { - OperationType::IdentityWithdrawal + OperationTypeInSerializationFormat::IdentityWithdrawal(amount_range) => { + OperationType::IdentityWithdrawal(amount_range) } OperationTypeInSerializationFormat::ContractCreate(p, c) => { OperationType::ContractCreate(p, c) diff --git a/packages/strategy-tests/src/transitions.rs b/packages/strategy-tests/src/transitions.rs index 5a456afa3a..85d03eb333 100644 --- a/packages/strategy-tests/src/transitions.rs +++ b/packages/strategy-tests/src/transitions.rs @@ -22,10 +22,6 @@ use dpp::state_transition::identity_create_transition::IdentityCreateTransition; use dpp::state_transition::identity_credit_transfer_transition::v0::IdentityCreditTransferTransitionV0; use dpp::ProtocolError; -use dpp::state_transition::identity_credit_withdrawal_transition::v0::{ - IdentityCreditWithdrawalTransitionV0, MIN_CORE_FEE_PER_BYTE, -}; - use dpp::native_bls::NativeBlsModule; use dpp::state_transition::identity_topup_transition::methods::IdentityTopUpTransitionMethodsV0; use dpp::state_transition::identity_topup_transition::IdentityTopUpTransition; @@ -37,9 +33,13 @@ use dpp::withdrawal::Pooling; use rand::prelude::{IteratorRandom, StdRng}; use simple_signer::signer::SimpleSigner; +use crate::operations::AmountRange; use crate::KeyMaps; use dpp::dashcore::transaction::special_transaction::asset_lock::AssetLockPayload; use dpp::dashcore::transaction::special_transaction::TransactionPayload; +use dpp::state_transition::identity_credit_withdrawal_transition::v1::IdentityCreditWithdrawalTransitionV1; +use dpp::state_transition::identity_credit_withdrawal_transition::MIN_CORE_FEE_PER_BYTE; +use rand::Rng; use std::collections::{BTreeMap, HashSet}; use std::str::FromStr; @@ -77,6 +77,24 @@ pub fn instant_asset_lock_proof_fixture(one_time_private_key: PrivateKey) -> Ass AssetLockProof::Instant(is_lock_proof) } +pub fn instant_asset_lock_proof_fixture_with_dynamic_range( + one_time_private_key: PrivateKey, + amount_range: &AmountRange, + rng: &mut StdRng, +) -> AssetLockProof { + let transaction = instant_asset_lock_proof_transaction_fixture_with_dynamic_amount( + one_time_private_key, + amount_range, + rng, + ); + + let instant_lock = instant_asset_lock_is_lock_fixture(transaction.txid()); + + let is_lock_proof = InstantAssetLockProof::new(instant_lock, transaction, 0); + + AssetLockProof::Instant(is_lock_proof) +} + /// Constructs a fixture of a `Transaction` representing an instant asset lock proof. /// /// The `Transaction` structure is a basic unit of data in a blockchain, recording the transfer of assets between parties. @@ -161,6 +179,73 @@ pub fn instant_asset_lock_proof_transaction_fixture( } } +pub fn instant_asset_lock_proof_transaction_fixture_with_dynamic_amount( + one_time_private_key: PrivateKey, + amount_range: &AmountRange, + rng: &mut StdRng, +) -> Transaction { + let secp = Secp256k1::new(); + + let private_key_hex = "cSBnVM4xvxarwGQuAfQFwqDg9k5tErHUHzgWsEfD4zdwUasvqRVY"; + let private_key = PrivateKey::from_str(private_key_hex).unwrap(); + let public_key = private_key.public_key(&secp); + let public_key_hash = public_key.pubkey_hash(); + //let from_address = Address::p2pkh(&public_key, Network::Testnet); + let one_time_public_key = one_time_private_key.public_key(&secp); + + // We are going to fund 1 Dash and + // assume that input has 100005000 + // 5000 will be returned back + + let input_txid = + Txid::from_str("a477af6b2667c29670467e4e0728b685ee07b240235771862318e29ddbe58458").unwrap(); + + let input_outpoint = OutPoint::new(input_txid, 0); + + let input = TxIn { + previous_output: input_outpoint, + script_sig: ScriptBuf::new_p2pkh(&public_key_hash), + sequence: 0, + witness: Default::default(), + }; + + let one_time_key_hash = one_time_public_key.pubkey_hash(); + + let value_amount = if amount_range.start() == amount_range.end() { + *amount_range.start() //avoid using rng if possible + } else { + rng.gen_range(amount_range.clone()) + }; + + let funding_output = TxOut { + value: value_amount, + script_pubkey: ScriptBuf::new_p2pkh(&one_time_key_hash), + }; + + let burn_output = TxOut { + value: value_amount, + script_pubkey: ScriptBuf::new_op_return(&[]), + }; + + let change_output = TxOut { + value: 5000, + script_pubkey: ScriptBuf::new_p2pkh(&public_key_hash), + }; + + let payload = TransactionPayload::AssetLockPayloadType(AssetLockPayload { + version: 0, + credit_outputs: vec![funding_output], + }); + + Transaction { + version: 0, + lock_time: 0, + input: vec![input], + output: vec![burn_output, change_output], + special_transaction_payload: Some(payload), + } +} + /// Constructs a fixture of `InstantLock` representing an instant asset lock. /// /// The `InstantLock` structure is often used in blockchain systems to represent a condition where funds (or assets) are locked instantly, making them non-spendable until a specified condition is met or the lock duration expires. @@ -448,26 +533,32 @@ pub fn create_identity_update_transition_disable_keys( Some(state_transition) } -/// Creates a state transition for an identity's credit withdrawal. +/// Creates a state transition for an identity's credit withdrawal, with a potential +/// output address based on the identity's capabilities. /// -/// This function generates a state transition representing the withdrawal of credits from an identity. -/// The withdrawal amount is set to 0.001 Dash. The function first bumps the revision -/// of the identity and then constructs the withdrawal transition. Subsequently, it's signed using the -/// identity's authentication key for validity and authenticity. +/// This function generates a state transition representing the withdrawal of credits from +/// an identity. It first checks if the identity has a suitable withdrawal address. If so, +/// there is a 50% chance that the withdrawal will be sent to the identity's transfer key. +/// Otherwise, it will create a withdrawal transition with a random output address. /// /// # Parameters /// - `identity`: A mutable reference to the identity making the withdrawal. +/// - `identity_nonce_counter`: A mutable reference to a BTreeMap that tracks the nonce for +/// each identity, ensuring unique transaction identifiers. /// - `signer`: A mutable reference to the signer used to create the cryptographic signature for /// the state transition. -/// - `rng`: A mutable reference to a random number generator, used for generating the random Pay-To-Script-Hash (P2SH). +/// - `rng`: A mutable reference to a random number generator, used for generating the random +/// Pay-To-Script-Hash (P2SH) when creating a withdrawal with an output address. /// /// # Returns -/// - `StateTransition`: The constructed and signed state transition representing the identity's credit withdrawal. +/// - `StateTransition`: The constructed state transition representing the identity's credit +/// withdrawal. /// /// # Examples /// ```ignore /// let withdrawal_transition = create_identity_withdrawal_transition( /// &mut identity, +/// &mut identity_nonce_counter, /// &mut signer, /// &mut rng, /// ); @@ -475,22 +566,176 @@ pub fn create_identity_update_transition_disable_keys( /// /// # Panics /// This function may panic under the following conditions: +/// - If the identity does not have a suitable withdrawal address or key for signing. +pub fn create_identity_withdrawal_transition( + identity: &mut Identity, + amount_range: AmountRange, + identity_nonce_counter: &mut BTreeMap, + signer: &mut SimpleSigner, + rng: &mut StdRng, +) -> StateTransition { + let has_withdrawal_address = identity + .get_first_public_key_matching( + Purpose::TRANSFER, + HashSet::from([SecurityLevel::CRITICAL]), + HashSet::from([KeyType::ECDSA_HASH160, KeyType::BIP13_SCRIPT_HASH]), + false, + ) + .is_some(); + if has_withdrawal_address && rng.gen_bool(0.5) { + // We can send it to the withdrawal address + create_identity_withdrawal_transition_sent_to_identity_transfer_key( + identity, + amount_range, + identity_nonce_counter, + signer, + rng, + ) + } else { + create_identity_withdrawal_transition_with_output_address( + identity, + amount_range, + identity_nonce_counter, + signer, + rng, + ) + } +} + +/// Creates a state transition for an identity's credit withdrawal directed to its +/// transfer key. +/// +/// This function generates a state transition representing the withdrawal of credits from +/// an identity. The withdrawal amount is set to 0.001 Dash. It increments the identity's +/// nonce and constructs the withdrawal transition. The transition is then signed using the +/// identity's authentication key for validity and authenticity. +/// +/// # Parameters +/// - `identity`: A mutable reference to the identity making the withdrawal. +/// - `identity_nonce_counter`: A mutable reference to a BTreeMap that tracks the nonce for +/// each identity, ensuring unique transaction identifiers. +/// - `signer`: A mutable reference to the signer used to create the cryptographic signature for +/// the state transition. +/// +/// # Returns +/// - `StateTransition`: The constructed and signed state transition representing the identity's +/// credit withdrawal directed to its transfer key. +/// +/// # Examples +/// ```ignore +/// let withdrawal_transition = create_identity_withdrawal_transition_sent_to_identity_transfer_key( +/// &mut identity, +/// &mut identity_nonce_counter, +/// &mut signer, +/// ); +/// ``` +/// +/// # Panics +/// This function may panic under the following conditions: /// - If the identity does not have a suitable authentication key for signing. /// - If there's an error during the signing process. -pub fn create_identity_withdrawal_transition( +pub fn create_identity_withdrawal_transition_sent_to_identity_transfer_key( + identity: &mut Identity, + amount_range: AmountRange, + identity_nonce_counter: &mut BTreeMap, + signer: &mut SimpleSigner, + rng: &mut StdRng, +) -> StateTransition { + let nonce = identity_nonce_counter.entry(identity.id()).or_default(); + *nonce += 1; + let mut withdrawal: StateTransition = IdentityCreditWithdrawalTransitionV1 { + identity_id: identity.id(), + amount: rng.gen_range(amount_range), + core_fee_per_byte: MIN_CORE_FEE_PER_BYTE, + pooling: Pooling::Never, + output_script: None, + nonce: *nonce, + user_fee_increase: 0, + signature_public_key_id: 0, + signature: Default::default(), + } + .into(); + + let identity_public_key = identity + .get_first_public_key_matching( + Purpose::AUTHENTICATION, + HashSet::from([SecurityLevel::MASTER]), + HashSet::from([ + KeyType::ECDSA_SECP256K1, + KeyType::BLS12_381, + KeyType::ECDSA_HASH160, + KeyType::BIP13_SCRIPT_HASH, + KeyType::EDDSA_25519_HASH160, + ]), + false, + ) + .expect("expected to get a signing key"); + + withdrawal + .sign_external( + identity_public_key, + signer, + None::, + ) + .expect("expected to sign withdrawal"); + + withdrawal +} + +/// Creates a state transition for an identity's credit withdrawal directed to a specified +/// output address. +/// +/// This function generates a state transition representing the withdrawal of credits from +/// an identity. The withdrawal amount is set to 0.001 Dash. It increments the identity's +/// nonce and constructs the withdrawal transition, which includes a random P2SH output address. +/// The transition is then signed using the identity's transfer key for validity and authenticity. +/// +/// # Parameters +/// - `identity`: A mutable reference to the identity making the withdrawal. +/// - `identity_nonce_counter`: A mutable reference to a BTreeMap that tracks the nonce for +/// each identity, ensuring unique transaction identifiers. +/// - `signer`: A mutable reference to the signer used to create the cryptographic signature for +/// the state transition. +/// - `rng`: A mutable reference to a random number generator, used for generating the random +/// Pay-To-Script-Hash (P2SH). +/// +/// # Returns +/// - `StateTransition`: The constructed and signed state transition representing the identity's +/// credit withdrawal directed to the specified output address. +/// +/// # Examples +/// ```ignore +/// let withdrawal_transition = create_identity_withdrawal_transition_with_output_address( +/// &mut identity, +/// &mut identity_nonce_counter, +/// &mut signer, +/// &mut rng, +/// ); +/// ``` +/// +/// # Panics +/// This function may panic under the following conditions: +/// - If the identity does not have a suitable transfer key for signing. +/// - If there's an error during the signing process. +pub fn create_identity_withdrawal_transition_with_output_address( identity: &mut Identity, + amount_range: AmountRange, identity_nonce_counter: &mut BTreeMap, signer: &mut SimpleSigner, rng: &mut StdRng, ) -> StateTransition { let nonce = identity_nonce_counter.entry(identity.id()).or_default(); *nonce += 1; - let mut withdrawal: StateTransition = IdentityCreditWithdrawalTransitionV0 { + let mut withdrawal: StateTransition = IdentityCreditWithdrawalTransitionV1 { identity_id: identity.id(), - amount: 1000000, // 1 duff + amount: rng.gen_range(amount_range), core_fee_per_byte: MIN_CORE_FEE_PER_BYTE, pooling: Pooling::Never, - output_script: CoreScript::random_p2sh(rng), + output_script: if rng.gen_bool(0.5) { + Some(CoreScript::random_p2pkh(rng)) + } else { + Some(CoreScript::random_p2sh(rng)) + }, nonce: *nonce, user_fee_increase: 0, signature_public_key_id: 0, @@ -775,6 +1020,7 @@ pub fn create_identities_state_transitions( /// - Conversion and encoding errors related to the cryptographic data. pub fn create_state_transitions_for_identities( identities: Vec, + amount_range: &AmountRange, signer: &SimpleSigner, rng: &mut StdRng, platform_version: &PlatformVersion, @@ -787,8 +1033,11 @@ pub fn create_state_transitions_for_identities( .unwrap(); let sk: [u8; 32] = pk.try_into().unwrap(); let secret_key = SecretKey::from_str(hex::encode(sk).as_str()).unwrap(); - let asset_lock_proof = - instant_asset_lock_proof_fixture(PrivateKey::new(secret_key, Network::Dash)); + let asset_lock_proof = instant_asset_lock_proof_fixture_with_dynamic_range( + PrivateKey::new(secret_key, Network::Dash), + amount_range, + rng, + ); let identity_create_transition = IdentityCreateTransition::try_from_identity_with_signer( &identity.clone(), diff --git a/packages/wallet-lib/package.json b/packages/wallet-lib/package.json index c5fc009158..73bc0575e7 100644 --- a/packages/wallet-lib/package.json +++ b/packages/wallet-lib/package.json @@ -1,6 +1,6 @@ { "name": "@dashevo/wallet-lib", - "version": "8.3.1", + "version": "8.5.0", "description": "Light wallet library for Dash", "main": "src/index.js", "unpkg": "dist/wallet-lib.min.js", @@ -46,7 +46,7 @@ "homepage": "https://github.com/dashevo/wallet-lib#readme", "dependencies": { "@dashevo/dapi-client": "workspace:*", - "@dashevo/dashcore-lib": "~0.21.3", + "@dashevo/dashcore-lib": "~0.22.0", "@dashevo/grpc-common": "workspace:*", "@dashevo/wasm-dpp": "workspace:*", "@yarnpkg/pnpify": "^4.0.0-rc.42", diff --git a/packages/wasm-dpp/Cargo.toml b/packages/wasm-dpp/Cargo.toml index e6a1b6aeed..d4c7a4eebb 100644 --- a/packages/wasm-dpp/Cargo.toml +++ b/packages/wasm-dpp/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wasm-dpp" -version = "1.3.1" +version = "1.5.0" edition = "2021" rust-version.workspace = true authors = ["Anton Suprunchuk "] @@ -41,10 +41,10 @@ dpp = { path = "../rs-dpp", default-features = false, features = [ "document-value-conversion", "document-json-conversion", ] } -itertools = { version = "0.10.5" } +itertools = { version = "0.13" } log = { version = "0.4.6" } wasm-logger = { version = "0.2.0" } -num_enum = "0.5.7" +num_enum = "0.7" hex = { version = "0.4" } paste = "1.0.14" anyhow = { version = "1.0.75" } diff --git a/packages/wasm-dpp/lib/test/fixtures/getIdentityCreditWithdrawalTransitionFixture.js b/packages/wasm-dpp/lib/test/fixtures/getIdentityCreditWithdrawalTransitionFixture.js index 892acc55c1..2bc8478f3b 100644 --- a/packages/wasm-dpp/lib/test/fixtures/getIdentityCreditWithdrawalTransitionFixture.js +++ b/packages/wasm-dpp/lib/test/fixtures/getIdentityCreditWithdrawalTransitionFixture.js @@ -6,7 +6,7 @@ module.exports = function getIdentityCreditWithdrawalTransitionFixture() { const privateKey = new PrivateKey('cSBnVM4xvxarwGQuAfQFwqDg9k5tErHUHzgWsEfD4zdwUasvqRVY'); const address = privateKey.toAddress(); - const stateTransition = new IdentityCreditWithdrawalTransition(1); + const stateTransition = new IdentityCreditWithdrawalTransition(3); stateTransition.setIdentityId(generateRandomIdentifier()); // eslint-disable-next-line stateTransition.setAmount(BigInt(1000)); diff --git a/packages/wasm-dpp/package.json b/packages/wasm-dpp/package.json index a77be229d8..95b70a9681 100644 --- a/packages/wasm-dpp/package.json +++ b/packages/wasm-dpp/package.json @@ -1,6 +1,6 @@ { "name": "@dashevo/wasm-dpp", - "version": "1.3.1", + "version": "1.5.0", "description": "The JavaScript implementation of the Dash Platform Protocol", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -43,7 +43,7 @@ "@babel/cli": "^7.23.0", "@babel/core": "^7.23.3", "@babel/preset-env": "^7.23.3", - "@dashevo/dashcore-lib": "~0.21.3", + "@dashevo/dashcore-lib": "~0.22.0", "@dashevo/dpns-contract": "workspace:*", "@types/bs58": "^4.0.1", "@types/node": "^14.6.0", diff --git a/packages/wasm-dpp/src/document/state_transition/document_batch_transition/mod.rs b/packages/wasm-dpp/src/document/state_transition/document_batch_transition/mod.rs index 8904162c21..d0ebb9ae56 100644 --- a/packages/wasm-dpp/src/document/state_transition/document_batch_transition/mod.rs +++ b/packages/wasm-dpp/src/document/state_transition/document_batch_transition/mod.rs @@ -1,4 +1,4 @@ -use dpp::identity::KeyID; +use dpp::identity::{KeyID, Purpose}; use dpp::{ prelude::Identifier, @@ -346,12 +346,22 @@ impl DocumentsBatchTransitionWasm { } #[wasm_bindgen(js_name=getKeySecurityLevelRequirement)] - pub fn get_security_level_requirement(&self) -> js_sys::Array { + pub fn get_security_level_requirement(&self, purpose: u8) -> Result { + // Convert the integer to a Purpose enum + let purpose_enum = match Purpose::try_from(purpose) { + Ok(purpose) => purpose, + Err(_) => { + return Err(JsValue::from_str( + "Invalid purpose value, expected a number between 0 and 5.", + )) + } + }; + let array = js_sys::Array::new(); - for security_level in self.0.security_level_requirement() { + for security_level in self.0.security_level_requirement(purpose_enum) { array.push(&JsValue::from(security_level as u32)); } - array + Ok(array) } // AbstractStateTransition methods diff --git a/packages/wasm-dpp/src/errors/consensus/basic/invalid_signature_public_key_purpose_error.rs b/packages/wasm-dpp/src/errors/consensus/basic/invalid_signature_public_key_purpose_error.rs index 835d9559a8..f81b0a4e87 100644 --- a/packages/wasm-dpp/src/errors/consensus/basic/invalid_signature_public_key_purpose_error.rs +++ b/packages/wasm-dpp/src/errors/consensus/basic/invalid_signature_public_key_purpose_error.rs @@ -23,8 +23,12 @@ impl InvalidSignaturePublicKeyPurposeErrorWasm { } #[wasm_bindgen(js_name=getKeyPurposeRequirement)] - pub fn get_allowed_key_purpose(&self) -> u8 { - self.inner.allowed_key_purpose() as u8 + pub fn get_allowed_key_purposes(&self) -> js_sys::Array { + let array = js_sys::Array::new(); + for purpose in self.inner.allowed_key_purposes() { + array.push(&JsValue::from(*purpose as u8)); + } + array } #[wasm_bindgen(js_name=getCode)] diff --git a/packages/wasm-dpp/src/errors/consensus/basic/wrong_public_key_purpose_error.rs b/packages/wasm-dpp/src/errors/consensus/basic/wrong_public_key_purpose_error.rs index ff07e99701..4f9e9205af 100644 --- a/packages/wasm-dpp/src/errors/consensus/basic/wrong_public_key_purpose_error.rs +++ b/packages/wasm-dpp/src/errors/consensus/basic/wrong_public_key_purpose_error.rs @@ -23,8 +23,12 @@ impl WrongPublicKeyPurposeErrorWasm { } #[wasm_bindgen(js_name=getKeyPurposeRequirement)] - pub fn get_key_purpose_requirement(&self) -> u8 { - self.inner.key_purpose_requirement() as u8 + pub fn get_allowed_key_purposes(&self) -> js_sys::Array { + let array = js_sys::Array::new(); + for purpose in self.inner.allowed_key_purposes() { + array.push(&JsValue::from(*purpose as u8)); + } + array } #[wasm_bindgen(js_name=getCode)] diff --git a/packages/wasm-dpp/src/errors/consensus/consensus_error.rs b/packages/wasm-dpp/src/errors/consensus/consensus_error.rs index 0d4019fc7c..627b65a267 100644 --- a/packages/wasm-dpp/src/errors/consensus/consensus_error.rs +++ b/packages/wasm-dpp/src/errors/consensus/consensus_error.rs @@ -63,17 +63,20 @@ use dpp::consensus::state::data_trigger::DataTriggerError::{ use wasm_bindgen::{JsError, JsValue}; use dpp::consensus::basic::data_contract::{ContestedUniqueIndexOnMutableDocumentTypeError, ContestedUniqueIndexWithUniqueIndexError, InvalidDocumentTypeRequiredSecurityLevelError, UnknownDocumentCreationRestrictionModeError, UnknownSecurityLevelError, UnknownStorageKeyRequirementsError, UnknownTradeModeError, UnknownTransferableTypeError}; use dpp::consensus::basic::document::{ContestedDocumentsTemporarilyNotAllowedError, DocumentCreationNotAllowedError, DocumentFieldMaxSizeExceededError, MaxDocumentsTransitionsExceededError, MissingPositionsInDocumentTypePropertiesError}; -use dpp::consensus::basic::identity::{DataContractBoundsNotPresentError, DisablingKeyIdAlsoBeingAddedInSameTransitionError, InvalidIdentityCreditWithdrawalTransitionAmountError, InvalidIdentityUpdateTransitionDisableKeysError, InvalidIdentityUpdateTransitionEmptyError, TooManyMasterPublicKeyError}; +use dpp::consensus::basic::identity::{DataContractBoundsNotPresentError, DisablingKeyIdAlsoBeingAddedInSameTransitionError, InvalidIdentityCreditWithdrawalTransitionAmountError, InvalidIdentityUpdateTransitionDisableKeysError, InvalidIdentityUpdateTransitionEmptyError, TooManyMasterPublicKeyError, WithdrawalOutputScriptNotAllowedWhenSigningWithOwnerKeyError}; use dpp::consensus::basic::overflow_error::OverflowError; use dpp::consensus::state::data_contract::document_type_update_error::DocumentTypeUpdateError; use dpp::consensus::state::document::document_contest_currently_locked_error::DocumentContestCurrentlyLockedError; use dpp::consensus::state::document::document_contest_document_with_same_id_already_present_error::DocumentContestDocumentWithSameIdAlreadyPresentError; use dpp::consensus::state::document::document_contest_identity_already_contestant::DocumentContestIdentityAlreadyContestantError; use dpp::consensus::state::document::document_contest_not_joinable_error::DocumentContestNotJoinableError; +use dpp::consensus::state::document::document_contest_not_paid_for_error::DocumentContestNotPaidForError; use dpp::consensus::state::document::document_incorrect_purchase_price_error::DocumentIncorrectPurchasePriceError; use dpp::consensus::state::document::document_not_for_sale_error::DocumentNotForSaleError; use dpp::consensus::state::identity::identity_public_key_already_exists_for_unique_contract_bounds_error::IdentityPublicKeyAlreadyExistsForUniqueContractBoundsError; use dpp::consensus::state::identity::master_public_key_update_error::MasterPublicKeyUpdateError; +use dpp::consensus::state::identity::missing_transfer_key_error::MissingTransferKeyError; +use dpp::consensus::state::identity::no_transfer_key_for_core_withdrawal_available_error::NoTransferKeyForCoreWithdrawalAvailableError; use dpp::consensus::state::prefunded_specialized_balances::prefunded_specialized_balance_insufficient_error::PrefundedSpecializedBalanceInsufficientError; use dpp::consensus::state::prefunded_specialized_balances::prefunded_specialized_balance_not_found_error::PrefundedSpecializedBalanceNotFoundError; use dpp::consensus::state::voting::masternode_incorrect_voter_identity_id_error::MasternodeIncorrectVoterIdentityIdError; @@ -296,6 +299,15 @@ pub fn from_state_error(state_error: &StateError) -> JsValue { StateError::DocumentContestDocumentWithSameIdAlreadyPresentError(e) => { generic_consensus_error!(DocumentContestDocumentWithSameIdAlreadyPresentError, e).into() } + StateError::MissingTransferKeyError(e) => { + generic_consensus_error!(MissingTransferKeyError, e).into() + } + StateError::NoTransferKeyForCoreWithdrawalAvailableError(e) => { + generic_consensus_error!(NoTransferKeyForCoreWithdrawalAvailableError, e).into() + } + StateError::DocumentContestNotPaidForError(e) => { + generic_consensus_error!(DocumentContestNotPaidForError, e).into() + } } } @@ -552,6 +564,13 @@ fn from_basic_error(basic_error: &BasicError) -> JsValue { BasicError::ContestedDocumentsTemporarilyNotAllowedError(e) => { generic_consensus_error!(ContestedDocumentsTemporarilyNotAllowedError, e).into() } + BasicError::WithdrawalOutputScriptNotAllowedWhenSigningWithOwnerKeyError(e) => { + generic_consensus_error!( + WithdrawalOutputScriptNotAllowedWhenSigningWithOwnerKeyError, + e + ) + .into() + } } } diff --git a/packages/wasm-dpp/src/identity/identity_facade.rs b/packages/wasm-dpp/src/identity/identity_facade.rs index d14892d4f9..bd4db7d491 100644 --- a/packages/wasm-dpp/src/identity/identity_facade.rs +++ b/packages/wasm-dpp/src/identity/identity_facade.rs @@ -206,7 +206,7 @@ impl IdentityFacadeWasm { amount: u64, core_fee_per_byte: u32, pooling: u8, - output_script: Vec, + output_script: Option>, identity_nonce: u64, ) -> Result { let pooling = match pooling { @@ -222,7 +222,7 @@ impl IdentityFacadeWasm { amount, core_fee_per_byte, pooling, - CoreScript::from_bytes(output_script), + output_script.map(CoreScript::from_bytes), identity_nonce as IdentityNonce, ) .map(Into::into) diff --git a/packages/wasm-dpp/src/identity/identity_factory.rs b/packages/wasm-dpp/src/identity/identity_factory.rs index b4fcf35d55..799598b456 100644 --- a/packages/wasm-dpp/src/identity/identity_factory.rs +++ b/packages/wasm-dpp/src/identity/identity_factory.rs @@ -210,7 +210,7 @@ impl IdentityFactoryWasm { amount: u64, core_fee_per_byte: u32, pooling: u8, - output_script: Vec, + output_script: Option>, identity_nonce: u64, ) -> Result { let pooling = match pooling { @@ -226,7 +226,7 @@ impl IdentityFactoryWasm { amount, core_fee_per_byte, pooling, - CoreScript::from_bytes(output_script), + output_script.map(CoreScript::from_bytes), identity_nonce as IdentityNonce, ) .map(Into::into) diff --git a/packages/wasm-dpp/src/identity/identity_public_key/purpose.rs b/packages/wasm-dpp/src/identity/identity_public_key/purpose.rs index 5e598ffa52..33503d6179 100644 --- a/packages/wasm-dpp/src/identity/identity_public_key/purpose.rs +++ b/packages/wasm-dpp/src/identity/identity_public_key/purpose.rs @@ -15,6 +15,8 @@ pub enum PurposeWasm { SYSTEM = 4, /// this key cannot be used for signing documents VOTING = 5, + /// this key is only for masternode owners + OWNER = 6, } impl From for PurposeWasm { @@ -26,6 +28,7 @@ impl From for PurposeWasm { Purpose::TRANSFER => PurposeWasm::TRANSFER, Purpose::SYSTEM => PurposeWasm::SYSTEM, Purpose::VOTING => PurposeWasm::VOTING, + Purpose::OWNER => PurposeWasm::OWNER, } } } diff --git a/packages/wasm-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/to_object.rs b/packages/wasm-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/to_object.rs index b0dc0002c8..d805f7f018 100644 --- a/packages/wasm-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/to_object.rs +++ b/packages/wasm-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/to_object.rs @@ -23,7 +23,7 @@ pub struct ToObject { pub amount: u64, pub core_fee_per_byte: u32, pub pooling: Pooling, - pub output_script: CoreScript, + pub output_script: Option, pub nonce: IdentityNonce, pub signature: Option>, pub signature_public_key_id: Option, diff --git a/packages/wasm-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/transition.rs b/packages/wasm-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/transition.rs index 9d75149519..3de33cb834 100644 --- a/packages/wasm-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/transition.rs +++ b/packages/wasm-dpp/src/identity/state_transition/identity_credit_withdrawal_transition/transition.rs @@ -114,14 +114,16 @@ impl IdentityCreditWithdrawalTransitionWasm { } #[wasm_bindgen(js_name=getOutputScript)] - pub fn get_output_script(&self) -> Buffer { - Buffer::from_bytes(self.0.output_script().as_bytes()) + pub fn get_output_script(&self) -> Option { + self.0 + .output_script() + .map(|core_script| Buffer::from_bytes(core_script.as_bytes())) } #[wasm_bindgen(js_name=setOutputScript)] - pub fn set_output_script(&mut self, output_script: Vec) { + pub fn set_output_script(&mut self, output_script: Option>) { self.0 - .set_output_script(CoreScript::from_bytes(output_script)); + .set_output_script(output_script.map(CoreScript::from_bytes)); } #[wasm_bindgen(js_name=getNonce)] @@ -153,6 +155,7 @@ impl IdentityCreditWithdrawalTransitionWasm { let version = match self.0 { IdentityCreditWithdrawalTransition::V0(_) => "0", + IdentityCreditWithdrawalTransition::V1(_) => "1", }; js_sys::Reflect::set(&js_object, &"$version".to_owned().into(), &version.into())?; @@ -205,12 +208,15 @@ impl IdentityCreditWithdrawalTransitionWasm { &JsValue::from_f64((object.pooling as u8) as f64), )?; - let output_script = Buffer::from_bytes(object.output_script.as_bytes()); - js_sys::Reflect::set( - &js_object, - &"outputScript".to_owned().into(), - &output_script.into(), - )?; + if let Some(output_script) = object.output_script { + let output_script = Buffer::from_bytes(output_script.as_bytes()); + + js_sys::Reflect::set( + &js_object, + &"outputScript".to_owned().into(), + &output_script.into(), + )?; + } js_sys::Reflect::set( &js_object, @@ -243,6 +249,7 @@ impl IdentityCreditWithdrawalTransitionWasm { let version = match self.0 { IdentityCreditWithdrawalTransition::V0(_) => "0", + IdentityCreditWithdrawalTransition::V1(_) => "1", }; js_sys::Reflect::set(&js_object, &"$version".to_owned().into(), &version.into())?; @@ -297,16 +304,16 @@ impl IdentityCreditWithdrawalTransitionWasm { &JsValue::from_f64((object.pooling as u8) as f64), )?; - let output_script = platform_value::string_encoding::encode( - object.output_script.as_bytes(), - Encoding::Base64, - ); + if let Some(output_script) = object.output_script { + let output_script = + platform_value::string_encoding::encode(output_script.as_bytes(), Encoding::Base64); - js_sys::Reflect::set( - &js_object, - &"outputScript".to_owned().into(), - &output_script.into(), - )?; + js_sys::Reflect::set( + &js_object, + &"outputScript".to_owned().into(), + &output_script.into(), + )?; + } js_sys::Reflect::set( &js_object, diff --git a/packages/wasm-dpp/test/integration/identity/IdentityFacade.spec.js b/packages/wasm-dpp/test/integration/identity/IdentityFacade.spec.js index 90778aa72e..2ed05d3bcb 100644 --- a/packages/wasm-dpp/test/integration/identity/IdentityFacade.spec.js +++ b/packages/wasm-dpp/test/integration/identity/IdentityFacade.spec.js @@ -24,7 +24,7 @@ describe('IdentityFacade', () => { beforeEach(async () => { dpp = new DashPlatformProtocol( { generate: () => crypto.randomBytes(32) }, - 1, + 3, ); const chainAssetLockProofJS = getChainAssetLockProofFixture(); diff --git a/packages/wasm-dpp/test/unit/identity/IdentityFactory.spec.js b/packages/wasm-dpp/test/unit/identity/IdentityFactory.spec.js index 25c23be0c9..1cd8fc8469 100644 --- a/packages/wasm-dpp/test/unit/identity/IdentityFactory.spec.js +++ b/packages/wasm-dpp/test/unit/identity/IdentityFactory.spec.js @@ -26,7 +26,7 @@ describe('IdentityFactory', () => { // const identityValidator = new IdentityValidator(blsAdapter); - factory = new IdentityFactory(1); + factory = new IdentityFactory(3); identity = await getIdentityFixture(instantAssetLockProof.createIdentifier()); identity.setBalance(0); diff --git a/packages/wasm-dpp/test/unit/identity/stateTransition/IdentityCreditWithdrawalTransition/IdentityCreditWithdrawalTransition.spec.js b/packages/wasm-dpp/test/unit/identity/stateTransition/IdentityCreditWithdrawalTransition/IdentityCreditWithdrawalTransition.spec.js index b80c611116..503ecf4bef 100644 --- a/packages/wasm-dpp/test/unit/identity/stateTransition/IdentityCreditWithdrawalTransition/IdentityCreditWithdrawalTransition.spec.js +++ b/packages/wasm-dpp/test/unit/identity/stateTransition/IdentityCreditWithdrawalTransition/IdentityCreditWithdrawalTransition.spec.js @@ -75,7 +75,7 @@ describe('IdentityCreditWithdrawalTransition', () => { rawStateTransition = stateTransition.toObject(); expect(rawStateTransition).to.deep.equal({ - $version: '0', + $version: '1', type: StateTransitionTypes.IdentityCreditWithdrawal, identityId: stateTransition.getIdentityId().toBuffer(), amount: stateTransition.getAmount(), @@ -92,7 +92,7 @@ describe('IdentityCreditWithdrawalTransition', () => { rawStateTransition = stateTransition.toObject({ skipSignature: true }); expect(rawStateTransition).to.deep.equal({ - $version: '0', + $version: '1', type: StateTransitionTypes.IdentityCreditWithdrawal, identityId: stateTransition.getIdentityId().toBuffer(), amount: stateTransition.getAmount(), @@ -109,7 +109,7 @@ describe('IdentityCreditWithdrawalTransition', () => { const jsonStateTransition = stateTransition.toJSON(); expect(jsonStateTransition).to.deep.equal({ - $version: '0', + $version: '1', type: StateTransitionTypes.IdentityCreditWithdrawal, identityId: stateTransition.getIdentityId().toString(), amount: stateTransition.getAmount().toString(), diff --git a/packages/withdrawals-contract/Cargo.toml b/packages/withdrawals-contract/Cargo.toml index 4840ebe0df..eaef26229c 100644 --- a/packages/withdrawals-contract/Cargo.toml +++ b/packages/withdrawals-contract/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "withdrawals-contract" description = "Witdrawals data contract schema and tools" -version = "1.3.1" +version = "1.5.0" edition = "2021" rust-version.workspace = true license = "MIT" [dependencies] -thiserror = "1.0.58" +thiserror = "1.0.64" platform-version = { path = "../rs-platform-version" } platform-value = { path = "../rs-platform-value" } num_enum = "0.5.7" diff --git a/packages/withdrawals-contract/package.json b/packages/withdrawals-contract/package.json index 59db8a606e..e6031b8ab6 100644 --- a/packages/withdrawals-contract/package.json +++ b/packages/withdrawals-contract/package.json @@ -1,6 +1,6 @@ { "name": "@dashevo/withdrawals-contract", - "version": "1.3.1", + "version": "1.5.0", "description": "Data Contract to manipulate and track withdrawals", "scripts": { "build": "", diff --git a/packages/withdrawals-contract/src/lib.rs b/packages/withdrawals-contract/src/lib.rs index 0eece0b61b..47e735b938 100644 --- a/packages/withdrawals-contract/src/lib.rs +++ b/packages/withdrawals-contract/src/lib.rs @@ -4,6 +4,7 @@ use platform_value::{Identifier, IdentifierBytes32}; use platform_version::version::PlatformVersion; use serde_json::Value; use serde_repr::{Deserialize_repr, Serialize_repr}; +use std::fmt; mod error; pub mod v1; @@ -32,13 +33,31 @@ pub const OWNER_ID: Identifier = Identifier(IdentifierBytes32(OWNER_ID_BYTES)); IntoPrimitive, )] pub enum WithdrawalStatus { + /// The documents are in the state and waiting to be processed. QUEUED = 0, + /// Pooled happens when we are waiting for signing. POOLED = 1, + /// We have broadcasted the transaction to core. BROADCASTED = 2, + /// The transaction is now complete. COMPLETE = 3, + /// We broadcasted the transaction but core never saw it or rejected it. EXPIRED = 4, } +impl fmt::Display for WithdrawalStatus { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let status_str = match self { + WithdrawalStatus::QUEUED => "Queued", + WithdrawalStatus::POOLED => "Pooled", + WithdrawalStatus::BROADCASTED => "Broadcasted", + WithdrawalStatus::COMPLETE => "Complete", + WithdrawalStatus::EXPIRED => "Expired", + }; + write!(f, "{}", status_str) + } +} + pub fn load_definitions(platform_version: &PlatformVersion) -> Result, Error> { match platform_version.system_data_contracts.withdrawals { 1 => Ok(None), diff --git a/yarn.lock b/yarn.lock index f5f5c44e2c..08923aac7f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1436,7 +1436,7 @@ __metadata: version: 0.0.0-use.local resolution: "@dashevo/bench-suite@workspace:packages/bench-suite" dependencies: - "@dashevo/dashcore-lib": "npm:~0.21.3" + "@dashevo/dashcore-lib": "npm:~0.22.0" "@dashevo/dpns-contract": "workspace:*" "@dashevo/wallet-lib": "workspace:*" "@dashevo/wasm-dpp": "workspace:*" @@ -1469,7 +1469,7 @@ __metadata: "@babel/core": "npm:^7.23.3" "@dashevo/dapi-grpc": "workspace:*" "@dashevo/dash-spv": "workspace:*" - "@dashevo/dashcore-lib": "npm:~0.21.3" + "@dashevo/dashcore-lib": "npm:~0.22.0" "@dashevo/grpc-common": "workspace:*" "@dashevo/wasm-dpp": "workspace:*" assert-browserify: "npm:^2.0.0" @@ -1551,7 +1551,7 @@ __metadata: "@dashevo/bls": "npm:~1.2.9" "@dashevo/dapi-client": "workspace:*" "@dashevo/dapi-grpc": "workspace:*" - "@dashevo/dashcore-lib": "npm:~0.21.3" + "@dashevo/dashcore-lib": "npm:~0.22.0" "@dashevo/dashd-rpc": "npm:^19.0.0" "@dashevo/dp-services-ctl": "github:dashevo/js-dp-services-ctl#v0.19-dev" "@dashevo/grpc-common": "workspace:*" @@ -1600,7 +1600,7 @@ __metadata: dependencies: "@dashevo/dark-gravity-wave": "npm:^1.1.1" "@dashevo/dash-util": "npm:^2.0.3" - "@dashevo/dashcore-lib": "npm:~0.21.3" + "@dashevo/dashcore-lib": "npm:~0.22.0" chai: "npm:^4.3.10" eslint: "npm:^8.53.0" eslint-config-airbnb-base: "npm:^15.0.0" @@ -1624,9 +1624,9 @@ __metadata: languageName: node linkType: hard -"@dashevo/dashcore-lib@npm:~0.21.3": - version: 0.21.3 - resolution: "@dashevo/dashcore-lib@npm:0.21.3" +"@dashevo/dashcore-lib@npm:~0.22.0": + version: 0.22.0 + resolution: "@dashevo/dashcore-lib@npm:0.22.0" dependencies: "@dashevo/bls": "npm:~1.2.9" "@dashevo/x11-hash-js": "npm:^1.0.2" @@ -1640,7 +1640,7 @@ __metadata: ripemd160: "npm:^2.0.2" tsd: "npm:^0.28.1" unorm: "npm:^1.6.0" - checksum: 28e2731ac66c34a7b5e160d270b810456dce3a3e1b5227649845aca510f38f441574d154ed8f0a79b26724124f311a87c8f57d53bfb5fd816223e571484fcc2a + checksum: ac9e268f6ec75f32b2c791f5494ec4a99d67c17ad8f8089d5673b1fd9925ac3f47f4981349f82c30e327aa77ee3c2b935dcad154d215f98c72636800030a0994 languageName: node linkType: hard @@ -1780,7 +1780,7 @@ __metadata: resolution: "@dashevo/platform-test-suite@workspace:packages/platform-test-suite" dependencies: "@dashevo/dapi-client": "workspace:*" - "@dashevo/dashcore-lib": "npm:~0.21.3" + "@dashevo/dashcore-lib": "npm:~0.22.0" "@dashevo/dpns-contract": "workspace:*" "@dashevo/feature-flags-contract": "workspace:*" "@dashevo/grpc-common": "workspace:*" @@ -1884,7 +1884,7 @@ __metadata: dependencies: "@dashevo/dapi-client": "workspace:*" "@dashevo/dash-spv": "workspace:*" - "@dashevo/dashcore-lib": "npm:~0.21.3" + "@dashevo/dashcore-lib": "npm:~0.22.0" "@dashevo/grpc-common": "workspace:*" "@dashevo/wasm-dpp": "workspace:*" "@yarnpkg/pnpify": "npm:^4.0.0-rc.42" @@ -1944,7 +1944,7 @@ __metadata: "@babel/core": "npm:^7.23.3" "@babel/preset-env": "npm:^7.23.3" "@dashevo/bls": "npm:~1.2.9" - "@dashevo/dashcore-lib": "npm:~0.21.3" + "@dashevo/dashcore-lib": "npm:~0.22.0" "@dashevo/dpns-contract": "workspace:*" "@types/bs58": "npm:^4.0.1" "@types/node": "npm:^14.6.0" @@ -6161,10 +6161,10 @@ __metadata: languageName: node linkType: hard -"cookie@npm:~0.4.1": - version: 0.4.1 - resolution: "cookie@npm:0.4.1" - checksum: 0f2defd60ac93645ee31e82d11da695080435eb4fe5bed9b14d2fc4e0621a66f4c5c60f3eb05761df08a9d6279366e8646edfd1654f359d0b5afc25304fc4ddc +"cookie@npm:^0.7.0": + version: 0.7.1 + resolution: "cookie@npm:0.7.1" + checksum: aec6a6aa0781761bf55d60447d6be08861d381136a0fe94aa084fddd4f0300faa2b064df490c6798adfa1ebaef9e0af9b08a189c823e0811b8b313b3d9a03380 languageName: node linkType: hard @@ -6344,7 +6344,7 @@ __metadata: "@dashevo/bls": "npm:~1.2.9" "@dashevo/dapi-client": "workspace:*" "@dashevo/dapi-grpc": "workspace:*" - "@dashevo/dashcore-lib": "npm:~0.21.3" + "@dashevo/dashcore-lib": "npm:~0.22.0" "@dashevo/dashpay-contract": "workspace:*" "@dashevo/dpns-contract": "workspace:*" "@dashevo/grpc-common": "workspace:*" @@ -6421,7 +6421,7 @@ __metadata: "@babel/eslint-parser": "npm:^7.23.3" "@dashevo/bls": "npm:~1.2.9" "@dashevo/dapi-client": "workspace:*" - "@dashevo/dashcore-lib": "npm:~0.21.3" + "@dashevo/dashcore-lib": "npm:~0.22.0" "@dashevo/dashd-rpc": "npm:^19.0.0" "@dashevo/docker-compose": "npm:^0.24.4" "@dashevo/wallet-lib": "workspace:*"