Skip to content
Merged
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: 2 additions & 1 deletion .github/workflows/tests-rs-nightly-long-running.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ jobs:
strategy:
fail-fast: false
matrix:
package: [dash-sdk, rs-dapi-client, rs-dapi, dapi-grpc, dpp, drive-abci]
package:
[dash-sdk, rs-dapi-client, rs-dapi, dapi-grpc, dpp, drive-abci, drive-proof-verifier]
steps:
- name: Check out repo
uses: actions/checkout@v4
Expand Down
24 changes: 24 additions & 0 deletions .github/workflows/tests-rs-workspace.yml
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,30 @@ jobs:
cargo install cargo-machete 2>/dev/null || true
cargo machete

# The transport-free cut is 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
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
done
for banned in hyper rustls tower mio; do
for wasm_package in dash-sdk wasm-sdk; do
if cargo tree -p "$wasm_package" --target wasm32-unknown-unknown -e normal -i "$banned" 2>/dev/null | grep -q .; then
echo "::error::$banned leaked into $wasm_package's wasm32 dependency tree"
exit 1
fi
done
done
Comment on lines +205 to +218

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: Make dependency leak guards fail when cargo tree fails

Each inverse cargo tree query suppresses stderr and treats an empty grep result as proof that the dependency is absent. That also treats cargo tree errors as success. For example, an inverse query becomes ambiguous when multiple versions of a package such as rustls are present, so a future transport leak can pass this guard precisely when the graph contains multiple versions. Generate the complete dependency tree as a separate command, allowing Cargo failures to stop the step, and then search its package lines.

Suggested change
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
done
for banned in hyper rustls tower mio; do
for wasm_package in dash-sdk wasm-sdk; do
if cargo tree -p "$wasm_package" --target wasm32-unknown-unknown -e normal -i "$banned" 2>/dev/null | grep -q .; then
echo "::error::$banned leaked into $wasm_package's wasm32 dependency tree"
exit 1
fi
done
done
verifier_tree="$(mktemp)"
cargo tree --locked -p drive-proof-verifier -e normal --prefix none > "$verifier_tree"
for banned in hyper rustls tower; do
if grep -Eq "^${banned} v[0-9]" "$verifier_tree"; then
echo "::error::$banned leaked into drive-proof-verifier's dependency tree"
exit 1
fi
done
rm "$verifier_tree"
for wasm_package in dash-sdk wasm-sdk; do
wasm_tree="$(mktemp)"
cargo tree --locked -p "$wasm_package" --target wasm32-unknown-unknown -e normal --prefix none > "$wasm_tree"
for banned in hyper rustls tower mio; do
if grep -Eq "^${banned} v[0-9]" "$wasm_tree"; then
echo "::error::$banned leaked into $wasm_package's wasm32 dependency tree"
exit 1
fi
done
rm "$wasm_tree"
done

source: ['codex']


- name: Detect immutable structure changes
if: github.event_name == 'pull_request'
run: |
Expand Down
27 changes: 19 additions & 8 deletions packages/dapi-grpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,30 @@ tenderdash-proto = []
# Client support.
client = ["platform"]

# Networked tonic client: `connect()` on generated clients, TLS roots.
# Deliberately NOT in the default set: 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. Without this feature
# the crate provides message types and transport-generic client stubs only.
# Tonic's codegen graph still includes tokio-stream and a minimal Tokio
# slice, but its hyper/rustls transport stack is not enabled. Native
# networked consumers enable this explicitly (rs-dapi-client does so through
# its non-wasm dependency); the wasm codegen path never emits `connect()`.
transport = [
"tonic/channel",
"tonic/transport",
"tonic/tls-native-roots",
"tonic/tls-webpki-roots",
"tonic/tls-ring",
]

# Build tonic server code. Includes all client features and adds server-specific dependencies.
server = [
"platform",
"tenderdash-proto/server",
"client",
"drive",
"transport",
"tonic/router",
]

Expand All @@ -55,14 +73,7 @@ tonic = { version = "0.14.2", features = ["codegen"], default-features = false }
getrandom = { version = "0.2", features = ["js"] }

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
tonic = { version = "0.14.2", features = [
"codegen",
"channel",
"transport",
"tls-native-roots",
"tls-webpki-roots",
"tls-ring",
], default-features = false }
tonic = { version = "0.14.2", features = ["codegen"], default-features = false }

[build-dependencies]
tonic-prost-build = { version = "0.14.2" }
Expand Down
13 changes: 11 additions & 2 deletions packages/dapi-grpc/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ fn generate_code(typ: ImplType, output_base: &Path) {

println!("cargo:rerun-if-changed=./protos");
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_SERDE");
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_TRANSPORT");
println!("cargo:rerun-if-env-changed=CARGO_CFG_TARGET_ARCH");
println!("cargo:rerun-if-env-changed=DAPI_GRPC_OUT_DIR");
}
Expand Down Expand Up @@ -416,15 +417,23 @@ enum ImplType {
impl ImplType {
// Configure the builder based on the implementation type.
pub fn configure(&self, builder: Builder) -> Builder {
// The `transport` cargo feature controls whether generated clients get
// the `connect()` convenience impls over tonic's own channel. Without
// it, clients are still generated but stay generic over the caller's
// transport. Never enabled for wasm32, where tonic transport does not
// build. Note: cfg!(target_arch) in a build script reflects the HOST,
// so the target must be read from CARGO_CFG_TARGET_ARCH.
let transport = std::env::var("CARGO_FEATURE_TRANSPORT").is_ok()
&& std::env::var("CARGO_CFG_TARGET_ARCH").map(|arch| arch != "wasm32") == Ok(true);
match self {
Self::Server => builder
.build_client(true)
.build_server(true)
.build_transport(true),
.build_transport(transport),
Self::Client => builder
.build_client(true)
.build_server(false)
.build_transport(true),
.build_transport(transport),
Self::Wasm => builder
.build_client(true)
.build_server(false)
Expand Down
5 changes: 5 additions & 0 deletions packages/rs-dapi-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ backon = { version = "1.3", default-features = false, features = [
"tokio-sleep",
] }
tokio = { version = "1.40", features = ["time"] }
# The native transport (tonic channel + TLS) comes from dapi-grpc's transport
# feature; wasm builds use tonic-web-wasm-client instead and must not pull it.
dapi-grpc = { path = "../dapi-grpc", features = [
"transport",
], default-features = false }

[target.'cfg(target_arch = "wasm32")'.dependencies]
gloo-timers = { version = "0.3.0", features = ["futures"] }
Expand Down
Loading