Skip to content

feat(dig-runtime): wallet-only start + native read-crypto FFI#4

Merged
MichaelTaylor3d merged 1 commit into
mainfrom
feat/dig-runtime-wallet-only-and-read-crypto-ffi
Jul 5, 2026
Merged

feat(dig-runtime): wallet-only start + native read-crypto FFI#4
MichaelTaylor3d merged 1 commit into
mainfrom
feat/dig-runtime-wallet-only-and-read-crypto-ffi

Conversation

@MichaelTaylor3d

Copy link
Copy Markdown
Contributor

TLDR

Adds two additive C-ABI surfaces to the dig-runtime cdylib so the DIG Browser can (a) start the runtime wallet-only — no in-process node engine — and (b) verify+decrypt .dig content by calling the digstore Rust read-crypto DIRECTLY via FFI, NOT wasm (wasm is webpages-only — @MT-Dev's ruling on super #44). Implements super-repo #47 and the Rust side of #44 item 2. All existing exports unchanged.

What changed (crates/dig-runtime/src/lib.rs)

  • dig_runtime_start_wallet() — wallet-only start (#47). Brings up the wallet host + tokio runtime with NO node engine (no P2P / cache / dig_rpc dispatch). The existing full dig_runtime_start() is unchanged; the FIRST dig_runtime_start* call fixes the mode (OnceLock). In wallet-only mode dig_rpc returns a well-formed JSON-RPC error (code -32000, "node engine not available: dig-runtime started wallet-only") rather than spinning up a node.
  • dig_read_verify_decrypt() / dig_bytes_free() — native read-crypto FFI (#44 item 2). Exports the digstore-core .dig verify+decrypt as C-ABI — the SAME Rust the webpage dig-client-wasm wraps (ONE impl, two bindings). Verifies the served ciphertext's Merkle inclusion against the chain-anchored root, THEN AES-256-GCM-SIV decrypts, fail-closed (DIG_READ_OK/BAD_INPUT/VERIFY_FAILED/DECRYPT_FAILED/INTERNAL). Needs no runtime and no node engine — pure crypto over bytes the caller already fetched from an external node (§5.3). Byte-parity with the wasm's decryptResource (same canonical_resource_urn + derive_decryption_key + inclusion-proof core).

digstore-core is pinned to the same rev (bcb84a6…) dig-node-core/dig-wallet use, so cargo unifies to one crypto impl.

FFI contract (for the dig-browser C++ loader)

// wallet-only start (browser calls this at startup instead of dig_runtime_start)
void dig_runtime_start_wallet(void);

// read-crypto: verify Merkle inclusion vs the chain-anchored root, then decrypt. fail-closed.
int32_t dig_read_verify_decrypt(
    const char* store_id_hex,      // 64-hex (required)
    const char* resource_key,      // resource path; "" => index.html (required)
    const uint8_t* ciphertext, size_t ciphertext_len,  // plain concat of chunk ciphertexts
    const char* proof_b64,         // base64 X-Dig-Inclusion-Proof (required)
    const char* trusted_root_hex,  // 64-hex chain-anchored root (required)
    const char* salt_hex,          // 64-hex private-store salt, or NULL/"" for public
    const uint32_t* chunk_lens, size_t chunk_lens_len, // per-chunk ct byte lens; NULL/0 => single
    uint8_t** out_ptr, size_t* out_len);               // heap plaintext; free w/ dig_bytes_free
void dig_bytes_free(uint8_t* ptr, size_t len);
// status: 0 OK, 1 BAD_INPUT, 2 VERIFY_FAILED, 3 DECRYPT_FAILED, 4 INTERNAL

Tests (TDD) — 14 pass

  • #47 split: build_runtime(false) constructs no node engine (tokio still live); build_runtime(true) does; dig_rpc with no engine returns a JSON-RPC error, never a panic.
  • #44 read-crypto: public single-chunk round-trip; empty key ⇒ index.html; private-salt round-trip (+ wrong salt ⇒ DECRYPT_FAILED); multi-chunk; tampered ciphertext ⇒ VERIFY_FAILED; decoy/wrong-root ⇒ VERIFY_FAILED; bad hex ⇒ BAD_INPUT; null out-params ⇒ BAD_INPUT.
  • Existing full-runtime FFI round-trips (dig_rpc, dig_wallet_rpc envelope, null-pointer safety) unchanged.

Verification (this session)

  • cargo test -p dig-runtime14 passed, 0 failed.
  • cargo clippy -p dig-runtime --all-targets -- -D warningsclean (fixed a cast_slice_from_raw_parts lint in dig_bytes_free).
  • cargo fmt --all -- --checkclean.

Blast radius

dig-runtime is a leaf cdylib — nothing in the workspace depends on it (it is the browser's DLL). All changes are additive: new exports + an internal with_node split of the runtime constructor; existing dig_rpc/dig_wallet_rpc/dig_free semantics preserved. Consumer is the dig-browser C++ loader (super #44 Part B), migrated separately.

Docs

  • SPEC.md §15 reworked (two start modes + the three FFI surfaces), new §15.1 (read-crypto FFI: signatures, inputs, status codes, buffer ownership), §1.3 corrected (browser starts wallet-only), conformance-index row 15 updated.
  • SYSTEM.md (superproject) note: line ~123 ("exactly ONE read-crypto implementation (the shared wasm)") should be updated by the orchestrator to "one Rust impl, two bindings (native FFI for the browser, wasm for webpages)" — out of this repo's scope.

Version

dig-runtime 0.1.0 → 0.2.0 (minor — additive feat, no breaking change to existing exports).

Refs super-repo #44, #47.

Add two additive C-ABI surfaces to the dig-runtime cdylib so the DIG
Browser can drop its in-process node (super #44) and verify+decrypt .dig
content by calling the digstore Rust read-crypto DIRECTLY, not through
wasm (wasm is webpages-only — @MT-Dev ruling on #44).

- dig_runtime_start_wallet(): wallet-only start — brings up the wallet
  host + tokio runtime with NO node engine (no P2P / cache / dig_rpc
  dispatch). The existing full dig_runtime_start() is unchanged; the
  first dig_runtime_start* call fixes the mode (OnceLock). In wallet-only
  mode dig_rpc returns a well-formed JSON-RPC "node engine not available"
  error rather than spinning up a node. (super #47)
- dig_read_verify_decrypt() / dig_bytes_free(): the digstore-core .dig
  verify+decrypt exported as C-ABI — the SAME Rust the webpage
  dig-client-wasm wraps (ONE impl, two bindings: native FFI for the
  browser, wasm for webpages). Verifies the served ciphertext's Merkle
  inclusion against the chain-anchored root, then AES-256-GCM-SIV
  decrypts, fail-closed (DIG_READ_* status codes). Needs no runtime and
  no node engine — pure crypto over bytes fetched from an external node.

digstore-core is pinned to the same rev dig-node-core/dig-wallet use so
cargo unifies to one crypto impl. SPEC.md §15/§15.1 + the conformance
index updated. Version 0.1.0 -> 0.2.0 (additive; minor).
@MichaelTaylor3d MichaelTaylor3d merged commit ded2609 into main Jul 5, 2026
9 checks passed
@MichaelTaylor3d MichaelTaylor3d deleted the feat/dig-runtime-wallet-only-and-read-crypto-ffi branch July 5, 2026 01:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant