Skip to content

Vanadium goes async#248

Merged
bigspider merged 8 commits intomasterfrom
async
Feb 26, 2026
Merged

Vanadium goes async#248
bigspider merged 8 commits intomasterfrom
async

Conversation

@bigspider
Copy link
Collaborator

@bigspider bigspider commented Feb 25, 2026

This adds an executor for futures/async functions in the app-sdk, and migrates the UX framework and the existing V-Apps to use an async approach by default.

The big win of this approach is that it becomes rather easy to create 'worker tasks' that perform useful computations while the device is idle. Thanks to the Rust's futures, the executor, and some syntactic sugar, this comes at very little added complexity when writing V-Apps.

Some use cases that might be useful in order to improve tha V-Apps UX and (perceived) performance:

  • Preload code in hot paths when busy waiting for commands
  • Perform precomputation related to transaction signing (or pre-signing checks) while the user is verifying the transaction details.

This allows to spawn background tasks, and will allow to use the
idle time when the device is showing some UX flow to perform work.
For the moment, app.rs remains synchronous, therefore this is only
a breaking change for apps using lower-level ux functionality (the
'vnd-test' and, to a small extent, the 'vnd-sadik') app.

Making app.rs also work asynchronously will be done in the
following commits.
@bigspider bigspider force-pushed the async branch 2 times, most recently from 8d60b12 to e752e60 Compare February 25, 2026 23:19
@bigspider bigspider requested a review from Copilot February 25, 2026 23:20
@bigspider bigspider marked this pull request as ready for review February 25, 2026 23:21
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a cooperative async/futures execution model to the Vanadium app SDK and migrates the SDK UX + multiple V-Apps to use async handlers by default, enabling background “worker tasks” that run while users are in UX flows.

Changes:

  • Added a single-threaded cooperative executor (block_on, spawn, yield_now) to app-sdk.
  • Switched the App framework handler signature and UX APIs to async, and migrated existing apps/handlers accordingly.
  • Added a #[sdk::handler] attribute macro to ergonomically adapt async fn handlers to the AppBuilder handler type; added a new apps/async example app + client.

Reviewed changes

Copilot reviewed 33 out of 33 changed files in this pull request and generated 12 comments.

Show a summary per file
File Description
macros/src/lib.rs Registers the new handler proc-macro alongside existing derives.
macros/src/handler.rs Implements the #[handler] attribute macro transforming async fn into a boxed-future handler.
macros/Cargo.toml Enables syn’s full feature for parsing function items.
apps/test/app/src/handlers/show_ux_screen.rs Updates UX calls to async by wrapping with executor::block_on in a sync test harness.
apps/template/generate/app/src/main.rs Migrates template-generated V-App to async UI flow and async handler via #[sdk::handler].
apps/template/generate/app/Cargo.toml.liquid Points generated apps at a git dependency configuration for the async SDK branch.
apps/template/app/src/main.rs Migrates the in-repo template app to async UI flow and async handler via #[sdk::handler].
apps/template/app/Cargo.toml Points the template at a git dependency configuration for the async SDK branch.
apps/sadik/app/src/main.rs Converts process_message to async handler and adapts event loop usage.
apps/rps/app/src/main.rs Converts app UX and message handling to async + updates tests to block_on.
apps/bitcoin/app/src/main.rs Converts the main request dispatcher and handler to async.
apps/bitcoin/app/src/handlers/sign_psbt.rs Migrates signing UX/warnings to async and updates tests to block_on.
apps/bitcoin/app/src/handlers/register_account.rs Migrates registration UX flow to async and updates tests to block_on.
apps/bitcoin/app/src/handlers/get_extended_pubkey.rs Migrates xpub display UX flow to async and updates tests to block_on.
apps/bitcoin/app/src/handlers/get_address.rs Migrates address display UX flow to async and updates tests to block_on.
apps/async/vapp.code-workspace Adds a workspace file for the new async example app/client.
apps/async/client/src/main.rs Adds a Tokio-based CLI to drive the async demo V-App.
apps/async/client/src/lib.rs Creates a dual-mode (std client / no_std shared types) crate layout.
apps/async/client/src/common.rs Defines shared Command enum for app/client messaging.
apps/async/client/src/client.rs Implements a transport-backed client API for the demo app.
apps/async/client/Cargo.toml Adds the new client crate with feature flags and optional deps.
apps/async/client/.cargo/config.toml Forces single-threaded tests for the client crate.
apps/async/app/src/main.rs Adds a new demo V-App showcasing sync vs async work with background tasks.
apps/async/app/justfile Adds build/run recipes for the demo app.
apps/async/app/Cargo.toml Adds the demo app crate configuration and vapp metadata.
apps/async/app/.vscode/settings.json Adds rust-analyzer settings for the demo app.
apps/async/app/.cargo/config.toml Adds RISC-V target flags + single-threaded tests for the demo app.
apps/async/README.md Documents building/running the async demo app + client.
app-sdk/src/ux.rs Converts UX primitives (events, waits, review flows, confirm flows, info) to async.
app-sdk/src/lib.rs Exposes the executor module and re-exports #[handler] + task-related types.
app-sdk/src/executor.rs Introduces a cooperative single-threaded async executor with tests.
app-sdk/src/app.rs Updates handler type to async, integrates executor driving, adds background task APIs (spawn_task, TaskHandle).
app-sdk/Cargo.toml Adds dependency on vanadium_macros for #[sdk::handler] re-export.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

A new procedural #[handler] macro added to the SDK allows to hide
almost all the additional complexity migrating from the old to the
new approach, which mostly amounts to adding 'async' wherever
appropriate.
It is wasteful to continue processing a task that is dropped.
This allows aborting the computation on the first occasion, if the
task is no longer useful.
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 38 out of 38 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Validate arguments and return value
- Make sure there are no attribute arguments
- Preserve where-clause (if present), instead of dropping silently
@bigspider bigspider merged commit 80961bb into master Feb 26, 2026
61 of 64 checks passed
@bigspider bigspider deleted the async branch February 26, 2026 10:35
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.

2 participants