bitbox02_rust: move workflow::confirm::UserAbort to hal::ui
What changed, and why it matters
This commit is a simple internal code reorganization. It moves a small user-cancelled error type (UserAbort) from one Rust module to another so the hardware abstraction layer (HAL) can eventually become its own separate crate. No security behavior changes; only import paths and type references are updated.
No security action required; review as normal refactoring if desired.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch relocates workflow::confirm::UserAbort to hal::ui::UserAbort and updates all call sites, trait definitions, and From conversions accordingly. The type remains a zero-sized struct with identical semantics. This is preparatory refactoring for extracting the HAL into a bitbox-hal crate.
Changed components
src/rust/bitbox02-rust/src/hal/bitbox02/ui.rssrc/rust/bitbox02-rust/src/hal/testing/ui.rssrc/rust/bitbox02-rust/src/hal/ui.rssrc/rust/bitbox02-rust/src/hww/api/bitcoin/policies.rssrc/rust/bitbox02-rust/src/hww/api/error.rssrc/rust/bitbox02-rust/src/workflow/confirm.rssrc/rust/bitbox02-rust/src/workflow/mnemonic.rssrc/rust/bitbox02-rust/src/workflow/pairing.rssrc/rust/bitbox02-rust/src/workflow/password.rssrc/rust/bitbox02-rust/src/workflow/transaction.rssrc/rust/bitbox02-rust/src/workflow/u2f_c_api.rssrc/rust/bitbox02-rust/src/workflow/unlock.rssrc/rust/bitbox02-rust/src/workflow/verify_message.rsInspect captured patch +26 / −24
diff --git a/src/rust/bitbox02-rust/src/hal/bitbox02/ui.rs b/src/rust/bitbox02-rust/src/hal/bitbox02/ui.rs
index 55466e3..bea6293 100644
--- a/src/rust/bitbox02-rust/src/hal/bitbox02/ui.rs
+++ b/src/rust/bitbox02-rust/src/hal/bitbox02/ui.rs
@@ -3,16 +3,17 @@
use alloc::string::String;
use crate::hal::Ui;
+use crate::hal::ui::UserAbort;
use crate::workflow::{cancel, confirm, sdcard, transaction, trinary_input_string};
pub struct BitBox02Ui;
impl Ui for BitBox02Ui {
#[inline(always)]
- async fn confirm(&mut self, params: &confirm::Params<'_>) -> Result<(), confirm::UserAbort> {
+ async fn confirm(&mut self, params: &confirm::Params<'_>) -> Result<(), UserAbort> {
match bitbox02::ui::confirm(params).await {
bitbox02::ui::ConfirmResponse::Approved => Ok(()),
- bitbox02::ui::ConfirmResponse::Cancelled => Err(confirm::UserAbort),
+ bitbox02::ui::ConfirmResponse::Cancelled => Err(UserAbort),
}
}
diff --git a/src/rust/bitbox02-rust/src/hal/testing/ui.rs b/src/rust/bitbox02-rust/src/hal/testing/ui.rs
index e49d57c..3310ff9 100644
--- a/src/rust/bitbox02-rust/src/hal/testing/ui.rs
+++ b/src/rust/bitbox02-rust/src/hal/testing/ui.rs
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: Apache-2.0
use crate::hal::Ui;
+use crate::hal::ui::UserAbort;
use crate::workflow::{cancel, confirm, sdcard, transaction, trinary_input_string};
use alloc::boxed::Box;
@@ -47,7 +48,7 @@ pub struct TestingUi<'a> {
}
impl Ui for TestingUi<'_> {
- async fn confirm(&mut self, params: &confirm::Params<'_>) -> Result<(), confirm::UserAbort> {
+ async fn confirm(&mut self, params: &confirm::Params<'_>) -> Result<(), UserAbort> {
self.screens.push(Screen::Confirm {
title: params.title.into(),
body: params.body.into(),
@@ -58,7 +59,7 @@ impl Ui for TestingUi<'_> {
.as_ref()
.is_some_and(|&n| self.screens.len() - 1 == n)
{
- return Err(confirm::UserAbort);
+ return Err(UserAbort);
}
Ok(())
}
diff --git a/src/rust/bitbox02-rust/src/hal/ui.rs b/src/rust/bitbox02-rust/src/hal/ui.rs
index 007944e..0b3b923 100644
--- a/src/rust/bitbox02-rust/src/hal/ui.rs
+++ b/src/rust/bitbox02-rust/src/hal/ui.rs
@@ -4,10 +4,12 @@ use crate::workflow::{cancel, confirm, mnemonic, sdcard, transaction, trinary_in
use alloc::string::String;
+pub struct UserAbort;
+
#[allow(async_fn_in_trait)]
pub trait Ui {
- /// Returns `Ok(())` if the user accepts, `Err(confirm::UserAbort)` if the user rejects.
- async fn confirm(&mut self, params: &confirm::Params<'_>) -> Result<(), confirm::UserAbort>;
+ /// Returns `Ok(())` if the user accepts, `Err(UserAbort)` if the user rejects.
+ async fn confirm(&mut self, params: &confirm::Params<'_>) -> Result<(), UserAbort>;
async fn verify_recipient(
&mut self,
diff --git a/src/rust/bitbox02-rust/src/hww/api/bitcoin/policies.rs b/src/rust/bitbox02-rust/src/hww/api/bitcoin/policies.rs
index bbef698..57fbbfe 100644
--- a/src/rust/bitbox02-rust/src/hww/api/bitcoin/policies.rs
+++ b/src/rust/bitbox02-rust/src/hww/api/bitcoin/policies.rs
@@ -404,7 +404,7 @@ impl ParsedPolicy<'_> {
.await?;
if matches!(mode, Mode::Basic) {
- if let Err(confirm::UserAbort) = hal
+ if let Err(crate::hal::ui::UserAbort) = hal
.ui()
.confirm(&confirm::Params {
body: "Show policy\ndetails?",
diff --git a/src/rust/bitbox02-rust/src/hww/api/error.rs b/src/rust/bitbox02-rust/src/hww/api/error.rs
index 4beecba..195cead 100644
--- a/src/rust/bitbox02-rust/src/hww/api/error.rs
+++ b/src/rust/bitbox02-rust/src/hww/api/error.rs
@@ -62,8 +62,8 @@ impl core::convert::From<crate::workflow::password::EnterTwiceError> for Error {
}
}
-impl core::convert::From<crate::workflow::confirm::UserAbort> for Error {
- fn from(_error: crate::workflow::confirm::UserAbort) -> Self {
+impl core::convert::From<crate::hal::ui::UserAbort> for Error {
+ fn from(_error: crate::hal::ui::UserAbort) -> Self {
Error::UserAbort
}
}
diff --git a/src/rust/bitbox02-rust/src/workflow/confirm.rs b/src/rust/bitbox02-rust/src/workflow/confirm.rs
index 46d0081..89ecf90 100644
--- a/src/rust/bitbox02-rust/src/workflow/confirm.rs
+++ b/src/rust/bitbox02-rust/src/workflow/confirm.rs
@@ -1,5 +1,3 @@
// SPDX-License-Identifier: Apache-2.0
pub use bitbox02::ui::{ConfirmParams as Params, Font};
-
-pub struct UserAbort;
diff --git a/src/rust/bitbox02-rust/src/workflow/mnemonic.rs b/src/rust/bitbox02-rust/src/workflow/mnemonic.rs
index bc27e5a..be3abbc 100644
--- a/src/rust/bitbox02-rust/src/workflow/mnemonic.rs
+++ b/src/rust/bitbox02-rust/src/workflow/mnemonic.rs
@@ -362,7 +362,7 @@ pub async fn get(
..Default::default()
};
- if let Err(confirm::UserAbort) = hal_ui.confirm(¶ms).await {
+ if let Err(crate::hal::ui::UserAbort) = hal_ui.confirm(¶ms).await {
// Cancel cancelled.
continue;
}
diff --git a/src/rust/bitbox02-rust/src/workflow/pairing.rs b/src/rust/bitbox02-rust/src/workflow/pairing.rs
index 1300217..0fa0362 100644
--- a/src/rust/bitbox02-rust/src/workflow/pairing.rs
+++ b/src/rust/bitbox02-rust/src/workflow/pairing.rs
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: Apache-2.0
use crate::hal::Ui;
+pub use crate::hal::ui::UserAbort;
use crate::workflow::confirm;
-pub use confirm::UserAbort;
use alloc::string::String;
diff --git a/src/rust/bitbox02-rust/src/workflow/password.rs b/src/rust/bitbox02-rust/src/workflow/password.rs
index ebf8a82..f18de04 100644
--- a/src/rust/bitbox02-rust/src/workflow/password.rs
+++ b/src/rust/bitbox02-rust/src/workflow/password.rs
@@ -9,7 +9,7 @@ pub use trinary_input_string::{CanCancel, Error};
use alloc::string::String;
-async fn prompt_cancel(hal: &mut impl crate::hal::Hal) -> Result<(), confirm::UserAbort> {
+async fn prompt_cancel(hal: &mut impl crate::hal::Hal) -> Result<(), crate::hal::ui::UserAbort> {
hal.ui()
.confirm(&confirm::Params {
body: "Do you really\nwant to cancel?",
@@ -74,7 +74,7 @@ pub async fn enter(
Ok(pw) => return Ok(pw),
Err(Error::Cancelled) => match prompt_cancel(hal).await {
Ok(()) => return Err(EnterError::Cancelled),
- Err(confirm::UserAbort) => {}
+ Err(crate::hal::ui::UserAbort) => {}
},
}
}
@@ -133,9 +133,9 @@ pub async fn enter_twice(
.await
{
Ok(()) => break,
- Err(confirm::UserAbort) => match prompt_cancel(hal).await {
+ Err(crate::hal::ui::UserAbort) => match prompt_cancel(hal).await {
Ok(()) => return Err(EnterTwiceError::EnterError(EnterError::Cancelled)),
- Err(confirm::UserAbort) => {}
+ Err(crate::hal::ui::UserAbort) => {}
},
}
}
diff --git a/src/rust/bitbox02-rust/src/workflow/transaction.rs b/src/rust/bitbox02-rust/src/workflow/transaction.rs
index 9ee3127..2c40c39 100644
--- a/src/rust/bitbox02-rust/src/workflow/transaction.rs
+++ b/src/rust/bitbox02-rust/src/workflow/transaction.rs
@@ -37,7 +37,7 @@ pub async fn verify_total_fee_maybe_warn(
.await
{
Ok(()) => (),
- Err(super::confirm::UserAbort) => return Err(UserAbort),
+ Err(crate::hal::ui::UserAbort) => return Err(UserAbort),
}
}
Ok(())
diff --git a/src/rust/bitbox02-rust/src/workflow/u2f_c_api.rs b/src/rust/bitbox02-rust/src/workflow/u2f_c_api.rs
index 834dc66..95f5777 100644
--- a/src/rust/bitbox02-rust/src/workflow/u2f_c_api.rs
+++ b/src/rust/bitbox02-rust/src/workflow/u2f_c_api.rs
@@ -27,7 +27,7 @@ impl<O> ConstInit for TaskState<O> {
static NEXT_TASK_TOKEN: AtomicU32 = AtomicU32::new(0);
static UNLOCK_STATE: GroundedCell<TaskState<Result<(), ()>>> = GroundedCell::const_init();
-static CONFIRM_STATE: GroundedCell<TaskState<Result<(), confirm::UserAbort>>> =
+static CONFIRM_STATE: GroundedCell<TaskState<Result<(), crate::hal::ui::UserAbort>>> =
GroundedCell::const_init();
static BITBOX02_HAL: GroundedCell<crate::hal::BitBox02Hal> = GroundedCell::const_init();
@@ -53,7 +53,7 @@ unsafe fn complete_unlock(token: u32, result: Result<(), ()>) {
/// Must not be called concurrently or reentrantly with other operations that mutate confirm
/// workflow state in this module.
/// Callers must guarantee single-threaded access to this workflow.
-unsafe fn complete_confirm(token: u32, result: Result<(), confirm::UserAbort>) {
+unsafe fn complete_confirm(token: u32, result: Result<(), crate::hal::ui::UserAbort>) {
unsafe {
if let TaskState::Running(current_token) = CONFIRM_STATE.get().as_ref().unwrap()
&& *current_token == token
diff --git a/src/rust/bitbox02-rust/src/workflow/unlock.rs b/src/rust/bitbox02-rust/src/workflow/unlock.rs
index 6711f9b..523ae38 100644
--- a/src/rust/bitbox02-rust/src/workflow/unlock.rs
+++ b/src/rust/bitbox02-rust/src/workflow/unlock.rs
@@ -13,7 +13,7 @@ use alloc::vec::Vec;
async fn confirm_mnemonic_passphrase(
hal: &mut impl crate::hal::Hal,
passphrase: &str,
-) -> Result<(), confirm::UserAbort> {
+) -> Result<(), crate::hal::ui::UserAbort> {
// Accept empty passphrase without confirmation.
if passphrase.is_empty() {
return Ok(());
@@ -60,7 +60,7 @@ impl core::convert::From<password::EnterError> for UnlockError {
async fn maybe_confirm_remaining_unlock_attempts(
hal: &mut impl crate::hal::Hal,
can_cancel: password::CanCancel,
-) -> Result<(), confirm::UserAbort> {
+) -> Result<(), crate::hal::ui::UserAbort> {
let remaining = crate::keystore::get_remaining_unlock_attempts(hal);
if remaining >= crate::keystore::MAX_UNLOCK_ATTEMPTS {
return Ok(());
diff --git a/src/rust/bitbox02-rust/src/workflow/verify_message.rs b/src/rust/bitbox02-rust/src/workflow/verify_message.rs
index 7b3ba89..02b446f 100644
--- a/src/rust/bitbox02-rust/src/workflow/verify_message.rs
+++ b/src/rust/bitbox02-rust/src/workflow/verify_message.rs
@@ -12,8 +12,8 @@ pub enum Error {
UserAbort,
}
-impl core::convert::From<confirm::UserAbort> for Error {
- fn from(_error: confirm::UserAbort) -> Self {
+impl core::convert::From<crate::hal::ui::UserAbort> for Error {
+ fn from(_error: crate::hal::ui::UserAbort) -> Self {
Error::UserAbort
}
}
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.