Skip to content

Commit d855a77

Browse files
feat(sdk): add CXX bindings over dash-sdk for C++ embedders
A C++ application that wants Dash Platform with its own trust context and signing keys had no supported path: rs-sdk-ffi is a C ABI shaped for mobile wallets that fetch quorum keys from a trusted HTTP service and hold private keys in-process. Dash Core's platform GUI needs the opposite: quorum keys from its locally synced LLMQ store, endpoints from its deterministic masternode list, signatures from its wallet, and no key or trust ever leaving the node. packages/rs-platform-cxx is a thin cxx bridge over dash-sdk. The embedder pushes endpoints, Platform quorum keys, its best ChainLock height and a digest-signing callback; the SDK owns query construction, transport (TLS to the evonodes), retries with address banning, proof verification and protocol-version tracking. Queries go through the SDK's Fetch/FetchMany so the rich query it built is what it verifies against; no wire request is ever reconstructed from bytes. On top of the SDK's signed-time window and monotonic Platform height, the client refuses a verified response whose Tenderdash chain id is not the network's or whose signed core-chain-locked height trails the embedder's ChainLock by more than 288 blocks. Every bridge entry point runs under catch_unwind, so a panic anywhere in the SDK surfaces as rust::Error rather than aborting the embedding process; the crate refuses to build under panic=abort. Document assembly is dash-platform-queries' pure DPNS/DashPay builders; signing is dpp's Signer over the callback, with dash-sdk's structure validation before serialization. Broadcast rejections carry DAPI's consensus error decoded through the SDK's error conversion. Tests replay drive-proof-verifier's proof-vector corpus through dash-sdk's mock transport (only the socket is mocked; the SDK runs the GroveDB replay and the BLS quorum check against the key pushed through the client) and cover unknown quorum key, wrong quorum type, tampered signature, foreign chain id, the ChainLock staleness floor, the height watermark surviving an SDK rebuild, cancellation and input bounds; builders are pinned byte for byte against rs-dpp-generated vectors; tests/cxx_smoke.cc links and runs from C++ in CI. Validated against live testnet from a release-built C++ driver: identity, nonce, DPNS resolve (registered and proven absent), names-of-identity, prefix search, profile, contact requests, contested vote state and a rejected broadcast all verify in 0.3 to 2 s; bit-flipped quorum keys fail at the BLS check.
1 parent 0631c07 commit d855a77

27 files changed

Lines changed: 5021 additions & 12 deletions

‎.github/package-filters/rs-packages-direct.yml‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,9 @@ dash-platform-queries:
121121
dash-sdk:
122122
- packages/rs-sdk/**
123123

124+
dash-platform-cxx:
125+
- packages/rs-platform-cxx/**
126+
124127
rs-sdk-ffi:
125128
- packages/rs-sdk-ffi/**
126129

‎.github/package-filters/rs-packages-no-workflows.yml‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,17 @@ platform-encryption: &platform_encryption
130130
dash-platform-queries: &platform_queries
131131
- packages/dash-platform-queries/**
132132

133+
dash-platform-cxx:
134+
- packages/rs-platform-cxx/**
135+
- *platform_queries
136+
- *context_provider
137+
- *dpp
138+
- *drive
139+
- *dapi_grpc
140+
- packages/rs-drive-proof-verifier/**
141+
- packages/rs-sdk/**
142+
- packages/rs-dapi-client/**
143+
133144
dash-sdk: &sdk
134145
- packages/rs-drive-proof-verifier/**
135146
- packages/rs-sdk/**

‎.github/package-filters/rs-packages.yml‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,18 @@ dash-platform-queries: &platform_queries
155155
- .github/workflows/tests*
156156
- packages/dash-platform-queries/**
157157

158+
dash-platform-cxx:
159+
- .github/workflows/tests*
160+
- packages/rs-platform-cxx/**
161+
- *platform_queries
162+
- *context_provider
163+
- *dpp
164+
- *drive
165+
- *dapi_grpc
166+
- packages/rs-drive-proof-verifier/**
167+
- packages/rs-sdk/**
168+
- packages/rs-dapi-client/**
169+
158170
dash-sdk: &sdk
159171
- .github/workflows/tests*
160172
- packages/rs-drive-proof-verifier/**

‎.github/workflows/tests-rs-workspace.yml‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,13 @@ jobs:
226226
done
227227
done
228228
229+
# The C++ embedding surface must link and run from the staged headers
230+
# and archive alone; the Rust tests cannot see a broken header layout.
231+
# (dash-platform-cxx wraps the full dash-sdk, networking included, so it
232+
# is deliberately absent from the transport-free cuts above.)
233+
- name: Link the Platform CXX embedder from C++
234+
run: packages/rs-platform-cxx/scripts/cxx-smoke.sh
235+
229236
- name: Detect immutable structure changes
230237
if: github.event_name == 'pull_request'
231238
run: |
@@ -342,6 +349,7 @@ jobs:
342349
--package rs-sdk-ffi \
343350
--package platform-wallet-ffi \
344351
--package rs-dapi-client \
352+
--package dash-platform-cxx \
345353
--package platform-serialization \
346354
--package dapi-grpc \
347355
--package json-schema-compatibility-validator \

‎Cargo.lock‎

Lines changed: 140 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Cargo.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ members = [
3838
"packages/document-history-contract",
3939
"packages/keyword-search-contract",
4040
"packages/rs-sdk-ffi",
41+
"packages/rs-platform-cxx",
4142
"packages/wasm-drive-verify",
4243
"packages/dash-platform-balance-checker",
4344
"packages/rs-dapi",

‎packages/dash-platform-queries/README.md‎

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,15 @@ downstream code may need to:
2727
Embedders that bring their own transport and trust context and only need the
2828
verification/query layer:
2929

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

33+
Dash Core's platform GUI consumes the full `dash-sdk` instead, through
34+
[`dash-platform-cxx`](../rs-platform-cxx): it serves quorum keys from its
35+
locally synced LLMQ state via a [`ContextProvider`](../rs-context-provider)
36+
and signatures from its wallet, and lets the SDK own transport, retries and
37+
proof verification.
38+
3739
If you want networking, retries, and a managed connection pool, use
3840
`dash-sdk` — it consumes this crate internally.
3941

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
[package]
2+
name = "dash-platform-cxx"
3+
version.workspace = true
4+
authors = ["Dash Core Group <dev@dash.org>"]
5+
edition = "2021"
6+
rust-version.workspace = true
7+
license = "MIT"
8+
description = "CXX bindings over dash-sdk for C++ embedders that supply their own trust context and signing keys"
9+
10+
[lib]
11+
name = "dash_platform_cxx"
12+
crate-type = ["staticlib", "rlib"]
13+
14+
[features]
15+
default = []
16+
# dash-sdk's mock transport, for tests that replay canned proved responses
17+
# through the same client code an embedder runs. Never enabled by embedders.
18+
mocks = ["dash-sdk/mocks"]
19+
20+
[dependencies]
21+
cxx = "1.0"
22+
dash-sdk = { path = "../rs-sdk", default-features = false, features = [
23+
"dpns-contract",
24+
"dashpay-contract",
25+
] }
26+
dash-context-provider = { path = "../rs-context-provider", default-features = false }
27+
dash-platform-queries = { path = "../dash-platform-queries", default-features = false }
28+
dpp = { path = "../rs-dpp", default-features = false, features = [
29+
"state-transitions",
30+
"state-transition-signing",
31+
"state-transition-validation",
32+
"identity-serialization",
33+
"identity-hashing",
34+
"bls-signatures",
35+
"dpns-contract",
36+
"dashpay-contract",
37+
] }
38+
drive = { path = "../rs-drive", default-features = false, features = ["verify"] }
39+
platform-version = { path = "../rs-platform-version" }
40+
tokio = { version = "1.40", features = ["rt-multi-thread", "net", "time"] }
41+
hex = "0.4"
42+
futures = "0.3"
43+
async-trait = "0.1"
44+
45+
[build-dependencies]
46+
cxx-build = "1.0"
47+
48+
[dev-dependencies]
49+
dash-platform-cxx = { path = ".", features = ["mocks"] }
50+
serde_json = "1"
51+
serde = { version = "1", features = ["derive"] }

0 commit comments

Comments
 (0)