feat(sdk): add transport-free CXX bindings for C++ embedders - #4620
feat(sdk): add transport-free CXX bindings for C++ embedders#4620PastaPastaPasta wants to merge 1 commit into
Conversation
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueThanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
42419d2 to
6bd8e28
Compare
packages/rs-platform-cxx (crate dash-platform-cxx) is the C++ embedding surface Dash Core's platform GUI consumes: proof verification over (request bytes, response bytes), DPP identity/document decoding, and state-transition construction with signing delegated to a C++ digest callback so private keys never cross the FFI. It is a thin cxx bridge over the workspace's own crates rather than a reimplementation: verification is drive-proof-verifier's FromProof impls (including the new request-driven FromProof<GetDocumentsRequest>), document assembly is dash-platform-queries' shared DPNS/DashPay builders, and signing implements dpp's Signer trait over the callback, exactly as rs-sdk-ffi does for Swift. Trust boundary, since every input byte comes from an untrusted node and GroveDB replay necessarily runs before the quorum signature check: every extern Rust entry point runs under catch_unwind (cxx turns Result::Err into rust::Error but a panic reaching its shim aborts the embedding process); request/response bytes are capped before prost decoding; set_context records the network's Platform LLMQ type and any proof naming another quorum type is refused before a key lookup, so keys the embedder pushes for other purposes can never sign Platform state; a response claiming an unknown protocol version is refused instead of verified under a guessed one; the signer refuses non-ECDSA key types it cannot produce signatures for; transitions are structure-validated (as dash-sdk does before broadcast) and built under the network's protocol version from set_context rather than this build's latest. Packaging follows the workspace's FFI crates: build.rs stages the generated bridge header, the cxx runtime header and the hand-written signer.h under target/<profile>/include/, so consumers vendor from the workspace root and install that tree plus the static archive. There is no nested manifest or second lockfile. Tests replay drive-proof-verifier's proof-vector corpus directly (the crate's own copies were byte-identical) and cover tampered signature/quorum/block-id/grovedb bytes, every signed metadata field, non-Platform quorum type, unknown protocol version, request/proof identity mismatch, wrong-shape proof, oversized and garbage input; tests/cxx_smoke.cc links and runs against the staged interface from C++ in CI.
4a8b441 to
b9451fd
Compare
|
Disposition (not closing yet): superseded by #4633, the same crate rebuilt as a bridge over 🤖 Posted autonomously by Claude on behalf of pasta. |
Issue being fixed or feature implemented
Third and last PR of the transport-free-embedder series; stacked on #4619 (review the last commit,
feat(sdk): add transport-free CXX bindings for C++ embedders). Supersedes #4416. Draft until #4619 merges.Dash Core's platform GUI (dashpay/dash#7512, #7623 onward) currently carries a private Rust/CXX bridge and pins individual Platform crates. This crate gives Platform ownership of that embedding surface: proof verification, DPP decoding and state-transition construction for an application that owns its own DAPI transport, quorum-key sync and private keys.
The earlier #4416 was withdrawn after review found (a) a malicious
getDocumentsresponse could abort the embedding process before the quorum signature was checked (fixed upstream in #4618), (b)cxxturns a Rust panic into a deterministic process abort and nothing caught them, (c) a second lockfile understandalone/that had already drifted from the workspace pin so the documented--lockedbuild failed, and (d) ~600 lines of test vectors duplicating the proof-verifier corpus.What was done?
packages/rs-platform-cxx(dash-platform-cxx), a thincxxbridge over the workspace's own crates: verification isdrive-proof-verifier'sFromProofimpls including #4619'sFromProof<GetDocumentsRequest>; document assembly isdash-platform-queries' builders; signing is dpp'sSignertrait implemented over a C++ digest callback (WalletSigner) so private keys never cross the FFI; quorum keys and system contracts come from aContextProviderthe embedder feeds from its synced LLMQ state.Trust boundary (every byte is untrusted DAPI output, and grovedb replay necessarily precedes the signature check):
extern "Rust"entry point runs undercatch_unwindand reports a panic asrust::Error;build.rsrefusespanic = "abort"builds, where that guard would be compiled out;verify::MAX_MESSAGE_BYTESbefore decoding; asset-lock transaction/islock bytes at 2 MiB;set_context(network, platform_quorum_type, protocol_version, activation_height)records the network's Platform LLMQ type; a proof naming any other quorum type is refused before its key is looked up, so keys the embedder pushes for other purposes can never sign Platform state.update_quorum_keysreplaces the whole set;set_context, notPlatformVersion::latest();ensure_valid_state_transition_structuredash-sdkruns before broadcast.Packaging follows the workspace's FFI crates: an ordinary member with no nested lockfile (embedders
cargo vendorfrom the root andcargo build -p dash-platform-cxx),build.rsstagesinclude/dash/platform/{ffi.h,signer.h}andinclude/rust/cxx.hundertarget/<profile>/the wayrs-sdk-ffistages its cbindgen header,cxx = "1.0"unpinned.cxxrather than cbindgen because the surface is dominated by nested byte vectors and fallible calls; the README states that trade-off.How Has This Been Tested?
../rs-drive-proof-verifier/tests/vectors: identity nonce, contract nonce, contested active/finished/absent) plus negatives for tampered signature, unknown quorum hash, non-Platform quorum type, tampered block-id hash, tampered grovedb proof, each signed metadata field individually, unknown protocol version, request/proof identity mismatch, wrong-shape proof, oversized and garbage input; byte-exact state-transition builds against the rs-dpp-generated vectors plus non-ECDSA key, wrong signature size, invalid DPNS label refused before signing, signer refusal; decoders incl. oversized input.scripts/cxx-smoke.sh(in CI) compilestests/cxx_smoke.ccagainst the staged headers and archive and runs it: context setup, garbage input throwsrust::Errorrather than aborting, and all fivest_build_*builders driven through the real bridge with a decliningWalletSigner.cargo clippy --all-targets --all-features -- -D warningsandcargo machete: clean. The transport-free CI cut assertshyper/rustls/towerstay out of the crate's tree.Breaking Changes
None for the workspace (new crate). For the Dash Core consumer of the withdrawn #4416:
set_contextgained two parameters andupdate_quorum_keyslost its per-call type;standalone/andinstall.share gone (install from the stagedinclude/andlibdash_platform_cxx.a).Checklist:
For repository code-owners and collaborators only