Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/package-filters/rs-packages-direct.yml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,9 @@ rs-dapi-client:
platform-encryption:
- packages/rs-platform-encryption/**

dash-platform-queries:
- packages/dash-platform-queries/**

dash-sdk:
- packages/rs-sdk/**

Expand Down
4 changes: 4 additions & 0 deletions .github/package-filters/rs-packages-no-workflows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,13 @@ rs-dapi-client: &dapi_client
platform-encryption: &platform_encryption
- packages/rs-platform-encryption/**

dash-platform-queries: &platform_queries
- packages/dash-platform-queries/**

dash-sdk: &sdk
- packages/rs-drive-proof-verifier/**
- packages/rs-sdk/**
- *platform_queries
- *dash_async
- *context_provider
- *sdk_trusted_context_provider
Expand Down
5 changes: 5 additions & 0 deletions .github/package-filters/rs-packages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,15 @@ platform-encryption: &platform_encryption
- .github/workflows/tests*
- packages/rs-platform-encryption/**

dash-platform-queries: &platform_queries
- .github/workflows/tests*
- packages/dash-platform-queries/**

dash-sdk: &sdk
- .github/workflows/tests*
- packages/rs-drive-proof-verifier/**
- packages/rs-sdk/**
- *platform_queries
- *dash_async
- *context_provider
- *sdk_trusted_context_provider
Expand Down
11 changes: 10 additions & 1 deletion .github/workflows/tests-rs-nightly-long-running.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,16 @@ jobs:
fail-fast: false
matrix:
package:
[dash-sdk, rs-dapi-client, rs-dapi, dapi-grpc, dpp, drive-abci, drive-proof-verifier]
[
dash-sdk,
rs-dapi-client,
rs-dapi,
dapi-grpc,
dpp,
drive-abci,
drive-proof-verifier,
dash-platform-queries,
]
steps:
- name: Check out repo
uses: actions/checkout@v4
Expand Down
29 changes: 19 additions & 10 deletions .github/workflows/tests-rs-workspace.yml
Original file line number Diff line number Diff line change
Expand Up @@ -193,20 +193,29 @@ jobs:
cargo install cargo-machete 2>/dev/null || true
cargo machete

# The transport-free cut is how embedders with their own networking
# The transport-free cuts are how embedders with their own networking
# (Dash Core's platform GUI, explorers) consume verification: feature
# unification hides transport regressions in whole-workspace builds, so
# check the standalone graphs and assert the networking stack stays out
# of the proof-verification tree (native) and out of wasm builds.
- name: Check transport-free feature cut
# unification hides regressions in whole-workspace builds, so check the
# standalone graphs and assert the networking stack stays out of the
# proof-verification tree (native) and out of wasm builds.
- name: Check transport-free feature cuts
run: |
cargo check -p dapi-grpc --no-default-features --features core,platform,client --locked
cargo check -p drive-proof-verifier --locked
for banned in hyper rustls tower; do
if cargo tree -p drive-proof-verifier -e normal -i "$banned" 2>/dev/null | grep -q .; then
echo "::error::$banned leaked into drive-proof-verifier's dependency tree"
exit 1
fi
cargo check -p dash-platform-queries --locked
# Native graphs: assert the networking transport stack stays out.
# `tonic` itself is present (dapi-grpc's generated client types) but
# without its transport feature — which is exactly what the absence
# of hyper/rustls/tower proves. tokio is deliberately NOT asserted
# absent: dash-context-provider depends on dash-async, which uses it
# on native targets, and that edge predates the queries-crate split.
for native_package in drive-proof-verifier dash-platform-queries; do
for banned in hyper rustls tower; do
if cargo tree -p "$native_package" -e normal -i "$banned" 2>/dev/null | grep -q .; then
echo "::error::$banned leaked into $native_package's dependency tree"
exit 1
fi
done
done
for banned in hyper rustls tower mio; do
for wasm_package in dash-sdk wasm-sdk; do
Expand Down
18 changes: 18 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ members = [
"packages/wasm-dpp2",
"packages/rs-dapi-client",
"packages/rs-dash-async",
"packages/dash-platform-queries",
"packages/rs-sdk",
"packages/strategy-tests",
"packages/simple-signer",
Expand Down
4 changes: 4 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@
ARG SCCACHE_BUCKET
ARG AWS_PROFILE
ARG SCCACHE_REGION
ARG SCCACHE_S3_KEY_PREFIX

Check warning on line 216 in Dockerfile

View workflow job for this annotation

GitHub Actions / Build Docker images (RS-DAPI, rs-dapi, rs-dapi) / Build RS-DAPI image

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ARG "SCCACHE_S3_KEY_PREFIX") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/

Check warning on line 216 in Dockerfile

View workflow job for this annotation

GitHub Actions / Build Docker images (Dashmate helper, dashmate-helper, dashmate-helper) / Build Dashmate helper image

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ARG "SCCACHE_S3_KEY_PREFIX") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/

Check warning on line 216 in Dockerfile

View workflow job for this annotation

GitHub Actions / Build Docker images (Drive, drive, drive-abci, SDK_TEST_DATA=true ) / Build Drive image

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ARG "SCCACHE_S3_KEY_PREFIX") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/
ARG SCCACHE_ENDPOINT

# Generate sccache configuration variables and save them to /root/env
Expand Down Expand Up @@ -415,6 +415,7 @@
packages/wasm-dpp2 \
packages/wasm-drive-verify \
packages/rs-dapi-client \
packages/dash-platform-queries \
packages/rs-sdk \
packages/rs-sdk-ffi \
packages/rs-unified-sdk-ffi \
Expand Down Expand Up @@ -541,6 +542,7 @@
packages/wasm-dpp2 \
packages/wasm-drive-verify \
packages/rs-dapi-client \
packages/dash-platform-queries \
packages/rs-sdk \
packages/rs-sdk-ffi \
packages/rs-unified-sdk-ffi \
Expand Down Expand Up @@ -690,6 +692,7 @@
packages/rs-dash-platform-macros \
packages/rs-drive \
packages/rs-drive-proof-verifier \
packages/dash-platform-queries \
packages/rs-sdk \
packages/rs-sdk-trusted-context-provider \
# Common
Expand Down Expand Up @@ -962,6 +965,7 @@
packages/wasm-dpp2 \
packages/wasm-drive-verify \
packages/rs-dapi-client \
packages/dash-platform-queries \
packages/rs-sdk \
packages/rs-sdk-ffi \
packages/rs-unified-sdk-ffi \
Expand Down
1 change: 1 addition & 0 deletions packages/check-features/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ fn main() {
("rs-drive", vec![]),
("rs-drive-proof-verifier", vec![]),
("rs-platform-wallet", vec![]),
("dash-platform-queries", vec![]),
];

for (specific_crate, to_ignore) in crates {
Expand Down
53 changes: 53 additions & 0 deletions packages/dash-platform-queries/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
[package]
name = "dash-platform-queries"
description = "Transport-free query building and proof decoding core shared by Dash Platform SDK embedders"
version.workspace = true
edition = "2021"
rust-version.workspace = true
license = "MIT"

[features]
default = []
mocks = [
"dep:serde",
"dep:serde_json",
"dapi-grpc/mocks",
"drive/serde",
"dpp/serde-conversion",
]

[dependencies]
dapi-grpc = { path = "../dapi-grpc", default-features = false, features = [
"platform",
"client",
] }
dash-context-provider = { path = "../rs-context-provider", default-features = false }
Comment on lines +20 to +24

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Blocking: The transport-free crate still pulls Tokio and native networking features

The PR description explicitly promises no Tokio anywhere in this crate's dependency graph, but dash-context-provider is an unconditional normal dependency and itself unconditionally depends on dash-async. On native targets, dash-async enables Tokio's rt, rt-multi-thread, time, and net features, so the resulting normal graph includes Tokio plus its native networking support. The dapi-grpc code-generation path also retains Tokio-related support dependencies. The dependency cut therefore does not meet the stated no-Tokio embedder requirement; the context-provider/async boundary must be split or feature-gated so this crate's normal graph excludes Tokio.

source: ['codex']

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dependency-graph facts here are correct and the PR description was overclaiming. Corrected.

Measured on the branch:

$ cargo tree -p dash-platform-queries -e normal -i tokio
tokio v1.52.3
├── dash-async
│   └── dash-context-provider
│       ├── dash-platform-queries
│       └── drive-proof-verifier
│           └── dash-platform-queries
├── tokio-stream → tonic → dapi-grpc → …
└── tokio-util → dash-async

So tokio, tokio-util, mio and tonic are all present. hyper, rustls and tower are absent.

The part the finding does not account for: drive-proof-verifier has a byte-identical profile on the merge base — same dash-context-providerdash-async edge, same tonic edge via dapi-grpc. This split introduces no new dependency; it inherits one that already existed. I checked both trees side by side.

What was wrong was the claim, not the graph, so that is what I changed:

  • PR description now states precisely what is absent (rs-dapi-client, hyper, rustls, tower — hence no tonic transport feature) and what is present transitively (tokio via dash-context-providerdash-async, tonic for dapi-grpc's generated types), with the note that this matches drive-proof-verifier pre-split.
  • The crate README gains the same clarification: "transport-free" means no networking stack, not an async-runtime-free graph.
  • CI now runs the hyper/rustls/tower assertions over dash-platform-queries as well as drive-proof-verifier (see the separate thread on tests-rs-workspace.yml).

I did not assert tokio/mio absent on the native target, because they are not absent and a green CI check that lies is worse than no check.

Declining the suggested remedy (splitting or feature-gating the dash-context-providerdash-async boundary) for this PR: it is a change to a crate this PR does not touch, it would alter drive-proof-verifier's graph too, and it is not required by the extraction. It is a legitimate follow-up and the PR description now says so.


🤖 Posted autonomously by Claude on behalf of pasta.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolved in this update — The transport-free crate still pulls Tokio and native networking features no longer present.

Auto-resolved by the review system based on the latest commit diff. If you believe this was closed in error, reopen the thread.

dash-platform-macros = { path = "../rs-dash-platform-macros" }
dpp = { path = "../rs-dpp", default-features = false, features = [
"platform-value-cbor",
"state-transitions",
"state-transition-validation",
] }
drive = { path = "../rs-drive", default-features = false, features = [
"verify",
] }
drive-proof-verifier = { path = "../rs-drive-proof-verifier", default-features = false }
hex = { version = "0.4.3" }
serde = { version = "1.0.219", default-features = false, features = [
"rc",
], optional = true }
serde_json = { version = "1.0", optional = true }
thiserror = "2.0.17"
tracing = { version = "0.1.41" }

[dev-dependencies]
dpp = { path = "../rs-dpp", default-features = false, features = [
"fixtures-and-mocks",
] }

[package.metadata.cargo-machete]
ignored = [
# Used inside the `dash_platform_macros::Mockable` derive expansion under
# the `mocks` feature; machete cannot see through proc-macro output.
"serde_json",
]
57 changes: 57 additions & 0 deletions packages/dash-platform-queries/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# dash-platform-queries

Transport-free query core of the Dash Platform SDK.

This crate carries the pieces of `dash-sdk` that build queries, encode them
onto the wire format, and decode/verify proved responses — with **no
transport implementation**: no `rs-dapi-client` and no tonic native
channel/TLS stack. Shared generated types and context-provider utilities
remain dependencies. `dash-sdk` depends on it and re-exports everything at
the historical paths, so SDK users need no changes.
Comment on lines +8 to +10

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Suggestion: README incorrectly promises that SDK users need no changes

The README says the historical re-exports mean SDK users need no changes, but this PR deliberately declares three source-incompatible SDK changes: DocumentQuery methods expose a different error type, new_with_data_contract_id requires DocumentQuerySdk in scope, and custom transport request types must implement WireQuery. The crate documentation should describe the preserved historical paths without promising complete source compatibility, and should summarize the required migrations.

Suggested change
channel/TLS stack. Shared generated types and context-provider utilities
remain dependencies. `dash-sdk` depends on it and re-exports everything at
the historical paths, so SDK users need no changes.
remain dependencies. `dash-sdk` depends on this crate and re-exports the moved
items at their historical module paths. This is a breaking extraction: some
SDK callers must import `DocumentQuerySdk`, handle `dash_platform_queries::Error`,
or implement `WireQuery` for custom transport request types.

source: ['codex']


## Who this is for

Embedders that bring their own transport and trust context and only need the
verification/query layer:

- **Dash Core's platform GUI** — fetches over its own gRPC-Web transport,
serves quorum keys from its locally synced LLMQ state via a
[`ContextProvider`](../rs-context-provider), and verifies every response
proof with [`drive-proof-verifier`](../rs-drive-proof-verifier).
- Block explorers, Electrum-style servers, hardware-wallet tooling — anything
that talks to DAPI its own way but must not trust responses.

If you want networking, retries, and a managed connection pool, use
`dash-sdk` — it consumes this crate internally.

## What's here

- [`documents::DocumentQuery`] — rich document query builder with wire
encoding for both request versions.
- Aggregate proof helpers (count/sum/average/ranked) shared with `dash-sdk`.
- DPNS username helpers — label normalization/validation and the
convertibility/contested checks shared with `dash-sdk`.
- `transition::validation` — structural validation for state transitions
ahead of signing.

Wire-request decoding (`DocumentQuery::try_from_request`), request-driven
proof verification, and pure DPNS/DashPay document builders arrive in the
next slice of this series.

## Feature flags

- `mocks` — serde support for the types used in dump/replay test vectors
(forwarded by `dash-sdk`'s `mocks`).

The dependency tree is checked in CI to stay free of the transport stack
(`hyper`, `rustls`, `tower`); see the "Check transport-free feature cuts"
step in `.github/workflows/tests-rs-workspace.yml`.

"Transport-free" means no networking stack, not an async-runtime-free graph:
`tokio` is still reachable on native targets through
`dash-context-provider` → `dash-async`, exactly as it already was for
`drive-proof-verifier` before this crate existed. `tonic` is present too, but
only for `dapi-grpc`'s generated message/client types — its transport feature
stays off, which is what the `hyper`/`rustls`/`tower` assertions prove. On
`wasm32-unknown-unknown` none of that is pulled in; the wasm assertions in the
same CI step also ban `mio`.
47 changes: 47 additions & 0 deletions packages/dash-platform-queries/src/block_info_from_metadata.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use crate::Error;
use dapi_grpc::platform::v0::ResponseMetadata;
use dpp::block::block_info::BlockInfo;
use dpp::block::epoch::MAX_EPOCH;
use drive::error::proof::ProofError;

/// Constructs a `BlockInfo` structure from the provided response metadata. This function
/// translates metadata received from a platform response into a format that is specific to the
/// application's needs, particularly focusing on block-related information. It ensures that
/// the epoch value from the metadata does not exceed `MAX_EPOCH`,
/// as this is a constraint for the `Epoch` type used in the `BlockInfo` structure.
///
/// # 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.
///
/// # Returns
/// If successful, returns `Ok(BlockInfo)` where `BlockInfo` contains:
/// - `time_ms`: The timestamp of the block in milliseconds.
/// - `height`: The height of the block.
/// - `core_height`: The core chain locked height, indicating the height of the block in the core blockchain that is considered final and securely linked to this block.
/// - `epoch`: The epoch number, converted to an `Epoch` struct via a 16-bit number.
///
/// # Errors
/// Returns an error if:
/// - The `epoch` value in the response metadata exceeds `MAX_EPOCH`. This is considered a data validity error as it indicates Platform returned an unexpectedly high epoch number.
///
/// The function encapsulates errors into the application's own `Error` type, providing a unified interface for error handling across the application.
pub fn block_info_from_metadata(response_metadata: &ResponseMetadata) -> Result<BlockInfo, Error> {
if response_metadata.epoch > MAX_EPOCH as u32 {
return Err(
drive::error::Error::Proof(ProofError::InvalidMetadata(format!(
"platform returned an epoch {} that was higher than the maximum allowed epoch",
response_metadata.epoch
)))
.into(),
);
}

Ok(BlockInfo {
time_ms: response_metadata.time_ms,
height: response_metadata.height,
core_height: response_metadata.core_chain_locked_height,
epoch: (response_metadata.epoch as u16).try_into()?,
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
//! [`DocumentAverage`]: drive_proof_verifier::DocumentAverage
//! [`DocumentSplitAverages`]: drive_proof_verifier::DocumentSplitAverages

use crate::platform::documents::document_query::DocumentQuery;
use crate::documents::document_query::DocumentQuery;
use dapi_grpc::platform::v0::{GetDocumentsResponse, Proof, ResponseMetadata};
use dapi_grpc::platform::VersionedGrpcResponse;
use dash_context_provider::ContextProvider;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
//! [`DocumentCount`]: drive_proof_verifier::DocumentCount
//! [`DocumentSplitCounts`]: drive_proof_verifier::DocumentSplitCounts

use crate::platform::documents::document_query::DocumentQuery;
use crate::documents::document_query::DocumentQuery;
use dapi_grpc::platform::v0::{GetDocumentsResponse, Proof, ResponseMetadata};
use dapi_grpc::platform::VersionedGrpcResponse;
use dash_context_provider::ContextProvider;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,8 @@
//! absent branch — same forward-compat for absence proofs as count)
//! contribute 0 to both axes via `filter_map(|e| e.<field>)`.

use crate::platform::documents::average_proof_helpers::{
assert_select_is_avg, verify_average_query,
};
use crate::platform::documents::document_query::DocumentQuery;
use crate::platform::Fetch;
use crate::documents::average_proof_helpers::{assert_select_is_avg, verify_average_query};
use crate::documents::document_query::DocumentQuery;
use dapi_grpc::platform::v0::{GetDocumentsResponse, Proof, ResponseMetadata};
use dash_context_provider::ContextProvider;
use dpp::dashcore::Network;
Expand Down Expand Up @@ -101,11 +98,6 @@ impl FromProof<DocumentQuery> for DocumentAverage {
}
}

impl Fetch for DocumentAverage {
type Query = super::document_query::DocumentQuery;
type Request = dapi_grpc::platform::v0::GetDocumentsRequest;
}

#[cfg(test)]
mod tests {
//! Unit tests for the AVG fold. The fold logic is extracted
Expand Down
Loading
Loading