feat(sdk): transport-free verification and query core for embedders - #4335
Draft
PastaPastaPasta wants to merge 7 commits into
Draft
feat(sdk): transport-free verification and query core for embedders#4335PastaPastaPasta wants to merge 7 commits into
PastaPastaPasta wants to merge 7 commits into
Conversation
Contributor
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
This was referenced Aug 8, 2026
dapi-grpc unconditionally built tonic with its native transport stack
(channel + TLS roots) on non-wasm targets, so any consumer of the message
types or proof-verification layers (drive-proof-verifier) dragged
hyper/rustls and the tokio networking stack into its dependency tree even
when it never opens a connection. The wasm target already proves the crate
works with codegen-only tonic.
Add an opt-in 'transport' cargo feature carrying tonic's
channel/transport/tls features, mirroring the client/server feature split
tenderdash-proto already has. It is deliberately NOT a default feature:
cargo features are not target-scoped, so a default-on transport would force
tonic's transport stack onto wasm32 consumers riding defaults, where it
does not build. build.rs drives tonic-build's build_transport from
CARGO_FEATURE_TRANSPORT (never on wasm32). Native networked consumers
enable it explicitly: rs-dapi-client (target-scoped to non-wasm), dash-sdk
(default feature, so SDK users are unchanged), and drive-abci via server
(which now implies transport). wasm-sdk and other wasm consumers need no
changes.
drive-proof-verifier needs no changes and its standalone tree drops from
407 to 339 crates: hyper, h2, rustls, ring, tower and the rest of the
transport stack disappear; what remains of tonic's codegen core is a
sync-only tokio slice via tokio-stream.
Types-only consumption is simply the default; embedders with their own
transport depend on:
dapi-grpc = { default-features = false, features = ["platform", "client"] }
(default-features = false remains advisable for wasm and keeps the feature
set explicit.)
…ueries Split rs-sdk per the maintainer guidance to refactor rather than duplicate: the query-building, wire-encoding, and proof-decoding core that a transport-free embedder needs now lives in a new packages/dash-platform-queries crate, and rs-sdk depends on it and re-exports every moved item at its old path, so no rs-sdk consumer changes imports. Moved out of rs-sdk: DocumentQuery and its wire encoders (document_query.rs), the count/sum/average/ranked proof helpers and their FromProof aggregate views (DocumentCount, DocumentSum, DocumentAverage, DocumentSplitCounts, DocumentSplitSums, DocumentSplitAverages, DocumentRankedEntries), DocumentHistoryQuery, block_info_from_metadata, QuerySettings, FinalizedEpochQuery, ensure_valid_state_transition_structure, and the DPNS username helpers (convert_to_homograph_safe_chars, is_valid_username, is_contested_username). Sdk-bound pieces stay behind: the contract-fetching DocumentQuery constructor (now the DocumentQuerySdk extension trait), the Query<GetDocumentsRequest> encoder impl, the Fetch bindings for the aggregate views, and the Query impls for FinalizedEpochQuery. QuerySettings loses its request_settings field: it was documented dead weight (not consulted by any encoder) and was the only rs-dapi-client tie in the moved struct. Sdk::query_settings and the few test construction sites were updated accordingly. The new crate has its own small thiserror enum (Config/Drive/Protocol); rs-sdk converts it via From, so existing ? call sites keep compiling. wasm-sdk gains the matching From impl for WasmSdkError, routed through SdkError so the mapping is unchanged. Coherence fallout: with DocumentQuery now foreign to rs-sdk, the blanket 'impl Query<T> for T where T: TransportRequest' would conflict with the explicit identity impl for DocumentQuery. The blanket is now additionally bounded by a local, explicitly-implemented WireQuery marker covering every wire request proto (list mirrors rs-dapi-client's TransportRequest impls); rustc can then prove the impl sets disjoint. The new crate's dependency tree is transport-free: no rs-dapi-client, hyper, rustls, or tonic transport.
…d client code The proto-to-domain decoding for document queries existed only server-side (rs-drive-abci's v1 conversions), so a client verifying a documents proof had to reconstruct the query shape by hand and could silently drift from what the server actually proves. Move the decode logic into dash-platform-queries::documents::proto_conversions with a neutral error type; drive-abci's conversions module becomes a thin mapping onto its QueryError surface with identical error message strings. On top of the shared decoder, DocumentQuery::try_from_request(request, contract) reconstructs the rich query from the wire request (both request versions), and verify_documents_response(...) / verify_documents_response_with_provider_contract(...) give embedders a request-driven verification entry point that delegates to the existing FromProof machinery, resolving the contract explicitly or via ContextProvider::get_data_contract. Round-trip tests cover encode-decode equality for representative queries in both wire versions plus malformed-clause rejection; drive-abci's document_query unit tests pass unchanged (76 cases).
Move the document *content* assembly of rs-sdk's networked DPNS and DashPay flows into transport-free functions in dash-platform-queries, so offline/embedder consumers and rs-sdk share one implementation: - build_dpns_preorder_and_domain_documents assembles the preorder and domain documents exactly as register_dpns_name did: both ids from the same entropy via generate_document_id_v0, saltedDomainHash = sha256d(salt || normalized_label + ".dash"), and the full domain property map (parentDomainName/normalizedParentDomainName, label, normalizedLabel, preorderSalt, records.identity, subdomainRules.allowSubdomains=false). It additionally rejects labels failing is_valid_username up front - previously only enforced by rs-sdk-ffi and platform consensus - so register_dpns_name now fails locally on an invalid label instead of after a network round-trip. - build_contact_request_document assembles the DIP-15 contactRequest id and property map from already-derived crypto material (encrypted xpub/label bytes, key indices, entropy). ECDH, encryption, the 69-byte compact-xpub check, key purpose checks, and recipient fetching stay in rs-sdk; the ciphertext size validations (96-byte xpub, 48-80-byte label, 38-102-byte autoAcceptProof) moved into the builder, with validate_auto_accept_proof also called early in create_contact_request to keep the pre-fetch fail-fast. - ensure_entropy_matches_document_id and prepare_document_for_transition moved from put_document.rs into dash_platform_queries::transition::put_document; rs-sdk re-exports and keeps calling them. Entropy/salt generation and all networking remain in rs-sdk. Builder validation errors surface through the new dash_platform_queries::Error::InvalidInput variant, which rs-sdk maps back to Error::Generic with the exact pre-move messages. New unit tests in dash-platform-queries pin a DPNS known vector (document ids and property maps for fixed label/entropy/salt), mirror the entropy-derives-id relation for contact requests, and cover the negative validation paths.
Feature unification hides transport-stack regressions in whole-workspace builds, so add a PR-time step checking the standalone graphs (types-only dapi-grpc, drive-proof-verifier, dash-platform-queries) and failing if hyper, rustls, or tower leaks into drive-proof-verifier's tree. Add both verification crates to the nightly per-feature check matrix and to the check-features tool's crate list.
dapi-grpc gets a crate-level feature table (including the new transport feature and the types-only build recipe), dash-platform-queries gets a README describing who the crate is for and what lives in it, and rs-sdk's README points transport-free embedders at the split crate.
…er seams Review follow-ups on the transport-free series: - The DPNS document builder validated labels with is_valid_username, whose consecutive-hyphen rejection is stricter than the DPNS contract's schema pattern - consensus accepts names like ab--cd. Split the check: new is_consensus_valid_label matches the contract pattern exactly and gates the builder (so dash-sdk's register_dpns_name no longer refuses consensus-valid labels), while is_valid_username keeps the stricter policy for its existing FFI/wasm gates and now documents the difference. - verify_documents_response rejects aggregate projections (COUNT/SUM/AVG) up front with a pointer to the aggregate proof helpers, instead of surfacing an opaque low-level proof error; try_from_request documents that it mirrors the server's wire-shape decode, not validate_and_route business rules. - The CI transport-leak guard also asserts wasm-sdk's wasm32 tree stays free of the native transport stack. - The proof-vector corpus gains a README with an explicit coverage matrix: the four documents-family cases pin query shape and clean decode failure but stop before the BLS check (placeholder payloads in the fixture state); identity, contested, and quorum-sig families run the full pipeline. This corrects the corpus commit's broader claim.
PastaPastaPasta
force-pushed
the
feat/transport-free-embedder-core
branch
from
August 10, 2026 16:34
db332fe to
e8e1961
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Issue being fixed or feature implemented
Embedders that bring their own transport and trust context cannot currently consume Platform's query and proof-verification layer without depending on the networked SDK or reconstructing Drive query shapes themselves.
Dash Core is the concrete consumer: it already owns endpoint selection, transport, locally synchronized LLMQ keys, and wallet key custody. It needs Platform's canonical request construction, response decoding, and proof verification without adopting
rs-dapi-clientor tonic's native channel/TLS stack.What was done?
This branch is rebased onto current
v4.2-dev, which includes the proof-vector corpus from #4345. It contains corrected #4344 as its prerequisite followed by six focused commits:feat(sdk): add transport feature to dapi-grpc for types-only consumers #4344: opt-in native transport for
dapi-grpctransport;rs-dapi-clientand server builds opt in at their target-specific boundaries;dash-sdkandwasm-sdkwasm32 graphs remain transport-free.Extract
dash-platform-queriesdash-sdkconsumes it and preserves historical re-export paths.Share document request decoding
drive-abciand clients;DocumentQuery::try_from_request;verify_documents_responseentry points for embedders.Extract pure DPNS and DashPay builders
Cover transport-free cuts in CI
dapi-grpc,drive-proof-verifier, anddash-platform-queriesgraphs;Document the embedder path
rs-dapi-clientor tonic native channel/TLS stack;Harden validation seams
Once #4344 lands, this branch can be rebased to drop that prerequisite commit without changing the remaining series.
How Has This Been Tested?
Local validation on the final rebased revision
e8e1961fe54fcdcb8eae55b7c2d84bcdf44004a8:cargo fmt --check --allcargo machetedash-platform-queries: 36 unit tests + 9 wire-roundtrip integration testsdrive-proof-verifier --features mocks: 261 unit tests + all 19 test(sdk): add proof-vector regression corpus for drive-proof-verifier #4345 fixture testsdapi-grpc,rs-dapi-client,dash-sdk, verifier, and query-core checksThe exact published revision was then pinned from a clean Dash Core #67 checkout:
dash-platform-ffitests passed (6 decoder, 14 proof, 11 signing/transition)dashrustbuilt successfully with theplatformfeatureBreaking Changes
Existing
dash-sdkpaths remain re-exported.Two narrow Rust source changes remain:
QuerySettings.request_settingsfield is removed;DocumentQuery::new_with_data_contract_idis provided by theDocumentQuerySdkextension trait and requires that trait in scope.External native consumers depending directly on
dapi-grpcand calling generatedconnect()methods must explicitly enablefeatures = ["transport"]. Native SDK/server consumers retain transport through their normal dependencies, and wasm consumers can use the default feature set safely.Checklist: