Skip to content

Add mobile host scaffolding#215

Open
pgherveou wants to merge 404 commits into
mainfrom
worktree-issue-96-mobile-followup
Open

Add mobile host scaffolding#215
pgherveou wants to merge 404 commits into
mainfrom
worktree-issue-96-mobile-followup

Conversation

@pgherveou

Copy link
Copy Markdown
Collaborator

Summary

  • add Android and iOS host package scaffolding for the Rust core
  • add UniFFI/native bridge and localhost WebSocket bridge surfaces
  • add Gradle, SwiftPM, JitPack, and host package CI wiring

Verification

  • cargo check -p uniffi-bindgen-cli
  • cargo check -p truapi-server --features ws-bridge
  • cargo test -p truapi-server --features ws-bridge

pgherveou added 30 commits June 10, 2026 11:02
Worker faults run the same teardown as dispose (terminate, dispose
subscriptions, close chain connections), init gets a configurable
timeout with error handling before ready, repeated worker init is
rejected, provider close is terminal, and per-frame wire decoding and
logging only run when debug logging is enabled. Subscription dispatch
is table-driven from one declarative entry list shared by both bundles,
unknown names are logged instead of falling through to the preimage
callback, and the wire-tag reverse lookup lives in @parity/truapi as
describeWireId. The sessionUiChanged optional callback forwards typed
session info from the core.
UI-decision callbacks (permissions, confirmations, pairing, navigation,
preimage submission) run on the blocking pool, so a host may block in
them until the user decides without stalling other traffic or
deadlocking when the decision UI issues TrUAPI calls. presentPairing on
iOS receives a cancel handle so bridges need no back-reference to the
core, the Kotlin RuntimeConfig compares its key material by content,
and the wrapper docs describe the threading contract.
The codegen job generates TS before building the npm workspace, then
guards drift with git diff on the committed generated Rust and the
wire-table parity test under TRUAPI_REQUIRE_GENERATED_TS=1. The JS test
job builds the wasm bundle like wasm-bundle-check, the Android job
installs Rust, generates UniFFI bindings, and pins Gradle 8.7, make
uniffi creates the gitignored Swift include dir on fresh clones, and
the license allowlist covers the smoldot and uniffi dependency trees.
npm ci runs the truapi-host-wasm prepare even with --ignore-scripts
(workspace link quirk), so downstream jobs need its generated
host-callbacks TS in the codegen-output artifact. The license allowlist
also covers Apache-2.0 WITH LLVM-exception from the wasmtime tree.
smoldot and smoldot-light carry GPL-3.0-or-later WITH
Classpath-exception-2.0; the exception permits linking into
independently-licensed works, so the allowance is scoped to those two
crates and plain GPL stays rejected everywhere else.
pgherveou added 25 commits July 8, 2026 15:21
Publish the host runtime as @parity/truapi-host and move the dotli diagnosis harness into the playground repo.
…t-core-port

# Conflicts:
#	rust/crates/truapi-codegen/tests/golden/host-callbacks-adapter.ts
#	rust/crates/truapi-codegen/tests/golden/host-callbacks.ts
#	rust/crates/truapi-codegen/tests/golden/worker-callbacks.ts
#	rust/crates/truapi-codegen/tests/golden_rust_emit.rs
#	rust/crates/truapi-server/src/lib.rs
Move the entire Bulletin TransactionStorage.store submission into
truapi-server. The core builds the extrinsic offline (subxt 0.50.2), signs
it with the wallet-delegated allowance key, dry-runs it, broadcasts, and
watches for inclusion over the existing chainHead runtime — replacing the
host signer-callback seam so the allowance secret never crosses the
host/FFI boundary.

Core:
- host_logic/extrinsic.rs: offline SubstrateConfig assembler with a
  config-pinned genesis hash, an sr25519 Signer, and metadata / transaction
  validity / events / header decoders.
- host_logic/bulletin.rs: store{data} construction signed with the allowance
  key, with audited pallet/call-index pinning plus a canonical-bytes guard so
  provider metadata cannot redirect the signature, and a memcpy call-data
  encoder that avoids scale-encode's per-byte cost.
- runtime/bulletin_rpc.rs: serialized submit flow (ephemeral with_runtime
  follow, metadata, nonce, validate_transaction dry-run, broadcast, single
  event-loop inclusion watch gated on nonce advance, System.Events dispatch
  check), typed error taxonomy, and broadcast stop on every exit.
- runtime.rs: Preimage::submit gates on bulletin availability before any
  prompt and refreshes the allowance (Increase policy) with one retry on an
  allowance rejection; lookup_subscribe verifies blake2_256(value)==key and
  serves an in-core content-addressed cache.
- BulletinAllowanceKey is zeroized on drop; PreimageHost keeps only
  lookup_preimage; both host configs gain an optional Bulletin genesis hash.

Codegen/TS: regenerate goldens (product wire unchanged) and drop the signer
bridge from the handwritten host worker. CI compiles the crate for
wasm32-unknown-unknown; .gitignore ignores the renamed wasm bundle path.

Bumps the hosts/dotli gitlink to the matching submodule commit.
Adversarial review of the watch loop found two defects:

- A crafted or buggy chain provider could send a self-referential or cyclic
  `NewBlock` parent link. The nonce-advance ancestor walk had no visited-set
  guard and no `.await`, so such a link spun forever, freezing the worker and
  permanently holding the submit lock across all products. The walk is
  extracted into `ancestors_to_check`, which guards against self-parent and
  cyclic links with a visited set, and is unit-tested.
- Blocks that failed the nonce gate were marked checked but never unpinned,
  leaking chainHead pins over the watch's lifetime and risking a false
  BroadcastUnverified once the server's pin limit was hit. They are now
  unpinned like body-negative blocks.

Also log a warning when a host lookup value is downgraded to a miss for
failing the blake2_256(value)==key integrity check.
…bler

The signing-host role now builds and signs transactions locally instead of
returning Unavailable, reusing host_logic/extrinsic.rs.

Because ProductAccountTxPayload carries each extension's `extra` and
`additional_signed` already SCALE-encoded in canonical order, assembly is a
pure offline concatenation — no metadata, no RPC:

- extrinsic.rs gains build_signed_extrinsic_v4 + v4_signer_payload and an
  Sr25519Signer::from_keypair constructor. Body = Compact(len) ++ 0x84 ++
  MultiAddress::Id(signer) ++ MultiSignature::Sr25519(sig) ++ Σextra ++
  call_data; signer payload = call_data ++ Σextra ++ Σadditional_signed,
  blake2_256 only when >256 bytes. Layout is byte-identical to subxt /
  frame-decode.
- signing_host::create_transaction handles Product and LegacyAccount (with a
  fail-closed slot-zero key-match check); the product-facing entrypoint's
  caller-scoping, chain-submit permission, and user-confirmation gates already
  precede it.
- Extrinsic V5 (tx_ext_version != 0) returns the new AuthorityError::NotSupported
  -> HostCreateTransactionError::NotSupported: V5 general carries the signature
  inside a VerifySignature extension, which cannot come from pre-encoded parts.

Tested: v4 layout + signature verification, the >256 hashing boundary, extension
order preservation, and Product/LegacyAccount success plus v5/mismatch/no-session
rejections.
Resolve the headless-host conflicts, add statement-store allowance allocation for SSO, and refresh the headless diagnosis path.
Decode ring revisions correctly for Bulletin allowance claims.

Add CLI-managed signer accounts, network presets, and script-capable host modes.

Regenerate headless signing and pairing diagnosis reports with zero failures.
…ile-followup

# Conflicts:
#	.changeset/rename-provider-to-wireprovider.md
#	.changeset/truapi-sandbox-bootstrap.md
#	.github/workflows/ci.yml
#	.github/workflows/release.yml
#	.gitignore
#	CLAUDE.md
#	Cargo.lock
#	Makefile
#	README.md
#	deny.toml
#	docs/RELEASE_PROCESS.md
#	hosts/dotli
#	js/packages/truapi-host/package.json
#	js/packages/truapi-host/scripts/build-wasm.mjs
#	js/packages/truapi-host/src/adapter-support.ts
#	js/packages/truapi-host/src/host-callbacks-adapter.test.ts
#	js/packages/truapi-host/src/runtime.ts
#	js/packages/truapi-host/src/test-support.ts
#	js/packages/truapi-host/src/web/create-iframe-host.test.ts
#	js/packages/truapi-host/src/web/create-iframe-host.ts
#	js/packages/truapi-host/src/web/create-worker-host-runtime.ts
#	js/packages/truapi-host/src/web/worker-provider.test.ts
#	js/packages/truapi-host/src/worker-protocol.ts
#	js/packages/truapi-host/src/worker-runtime.ts
#	js/packages/truapi/src/sandbox.ts
#	package-lock.json
#	playground/src/lib/auto-test.ts
#	playground/tests/e2e/dotli-diagnosis.ts
#	playground/tests/e2e/dotli/helpers/signer-bot.ts
#	rust/crates/truapi-codegen/src/rust/wasm_bridge.rs
#	rust/crates/truapi-codegen/src/ts/host_callbacks.rs
#	rust/crates/truapi-codegen/tests/golden/host-callbacks-adapter.ts
#	rust/crates/truapi-codegen/tests/golden/host-callbacks.ts
#	rust/crates/truapi-codegen/tests/golden/wasm_bridge.rs
#	rust/crates/truapi-codegen/tests/golden/worker-callbacks.ts
#	rust/crates/truapi-codegen/tests/golden_rust_emit.rs
#	rust/crates/truapi-platform/src/lib.rs
#	rust/crates/truapi-server/Cargo.toml
#	rust/crates/truapi-server/src/chain_runtime.rs
#	rust/crates/truapi-server/src/host_core.rs
#	rust/crates/truapi-server/src/host_logic.rs
#	rust/crates/truapi-server/src/host_logic/bulletin.rs
#	rust/crates/truapi-server/src/host_logic/product_account.rs
#	rust/crates/truapi-server/src/lib.rs
#	rust/crates/truapi-server/src/runtime.rs
#	rust/crates/truapi-server/src/runtime/bulletin_rpc.rs
#	rust/crates/truapi-server/src/runtime/pairing_host.rs
#	rust/crates/truapi-server/src/runtime/signing_host.rs
#	rust/crates/truapi-server/src/runtime/statement_store.rs
#	rust/crates/truapi-server/src/wasm.rs
@pgherveou
pgherveou changed the base branch from worktree-issue-96-rust-core-port to main July 17, 2026 13:29
@pgherveou
pgherveou requested a review from a team July 17, 2026 13:29
@TarikGul
TarikGul force-pushed the worktree-issue-96-mobile-followup branch from 8d5b55d to 45bb321 Compare July 17, 2026 18:10
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