bitbox02_rust/hal: add ui trinary choice
What changed, and why it matters
This commit is a routine internal code cleanup. It introduces a new Rust enum called TrinaryChoice inside a hardware abstraction layer (HAL) so that higher-level code no longer directly depends on a lower-level bitbox02 UI type. The actual on-device behavior is unchanged; only the names used in the source code are different. There is no security bug being fixed here.
No security action needed. Review as normal code-quality refactor.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The change refactors the UI HAL by adding hal::ui::TrinaryChoice with variants Left/Middle/Right and a conversion function from bitbox02::ui::TrinaryChoice. Consumers in bip85.rs and workflow/mnemonic.rs now pattern-match on the HAL enum instead of the underlying bitbox02 enum. A unit test verifies the conversion is exhaustive. This is an abstraction-layer improvement, not a functional or security patch.
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/bip85.rssrc/rust/bitbox02-rust/src/workflow/mnemonic.rsInspect captured patch +52 / −15
diff --git a/src/rust/bitbox02-rust/src/hal/bitbox02/ui.rs b/src/rust/bitbox02-rust/src/hal/bitbox02/ui.rs
index 39f84a4..2fc9d8d 100644
--- a/src/rust/bitbox02-rust/src/hal/bitbox02/ui.rs
+++ b/src/rust/bitbox02-rust/src/hal/bitbox02/ui.rs
@@ -3,7 +3,7 @@
use alloc::string::String;
use crate::hal::Ui;
-use crate::hal::ui::{ConfirmParams, EnterStringParams, Font, UserAbort};
+use crate::hal::ui::{ConfirmParams, EnterStringParams, Font, TrinaryChoice, UserAbort};
use crate::workflow::trinary_input_string;
pub struct BitBox02Ui;
@@ -47,6 +47,14 @@ fn to_bitbox02_trinary_input_string_params<'a>(
}
}
+fn to_hal_trinary_choice(choice: bitbox02::ui::TrinaryChoice) -> TrinaryChoice {
+ match choice {
+ bitbox02::ui::TrinaryChoice::TRINARY_CHOICE_LEFT => TrinaryChoice::Left,
+ bitbox02::ui::TrinaryChoice::TRINARY_CHOICE_MIDDLE => TrinaryChoice::Middle,
+ bitbox02::ui::TrinaryChoice::TRINARY_CHOICE_RIGHT => TrinaryChoice::Right,
+ }
+}
+
impl Ui for BitBox02Ui {
#[inline(always)]
async fn confirm(&mut self, params: &ConfirmParams<'_>) -> Result<(), UserAbort> {
@@ -132,8 +140,10 @@ impl Ui for BitBox02Ui {
label_left: Option<&str>,
label_middle: Option<&str>,
label_right: Option<&str>,
- ) -> bitbox02::ui::TrinaryChoice {
- bitbox02::ui::trinary_choice(message, label_left, label_middle, label_right).await
+ ) -> TrinaryChoice {
+ to_hal_trinary_choice(
+ bitbox02::ui::trinary_choice(message, label_left, label_middle, label_right).await,
+ )
}
async fn show_mnemonic(&mut self, words: &[&str]) -> Result<(), UserAbort> {
@@ -261,4 +271,25 @@ mod tests {
assert!(!output_with_wordlist.cancel_is_backbutton);
assert!(!output_with_wordlist.default_to_digits);
}
+
+ #[test]
+ fn test_to_hal_trinary_choice() {
+ let cases = [
+ (
+ bitbox02::ui::TrinaryChoice::TRINARY_CHOICE_LEFT,
+ TrinaryChoice::Left,
+ ),
+ (
+ bitbox02::ui::TrinaryChoice::TRINARY_CHOICE_MIDDLE,
+ TrinaryChoice::Middle,
+ ),
+ (
+ bitbox02::ui::TrinaryChoice::TRINARY_CHOICE_RIGHT,
+ TrinaryChoice::Right,
+ ),
+ ];
+ for (input, expected) in cases {
+ assert!(to_hal_trinary_choice(input) == expected);
+ }
+ }
}
diff --git a/src/rust/bitbox02-rust/src/hal/testing/ui.rs b/src/rust/bitbox02-rust/src/hal/testing/ui.rs
index 57d36bc..bfa116a 100644
--- a/src/rust/bitbox02-rust/src/hal/testing/ui.rs
+++ b/src/rust/bitbox02-rust/src/hal/testing/ui.rs
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: Apache-2.0
use crate::hal::Ui;
-use crate::hal::ui::{ConfirmParams, EnterStringParams, UserAbort};
+use crate::hal::ui::{ConfirmParams, EnterStringParams, TrinaryChoice, UserAbort};
use crate::workflow::trinary_input_string;
use alloc::boxed::Box;
@@ -134,7 +134,7 @@ impl Ui for TestingUi<'_> {
_label_left: Option<&str>,
_label_middle: Option<&str>,
_label_right: Option<&str>,
- ) -> bitbox02::ui::TrinaryChoice {
+ ) -> TrinaryChoice {
todo!("not used in unit tests yet");
}
diff --git a/src/rust/bitbox02-rust/src/hal/ui.rs b/src/rust/bitbox02-rust/src/hal/ui.rs
index dc078f4..87d32d3 100644
--- a/src/rust/bitbox02-rust/src/hal/ui.rs
+++ b/src/rust/bitbox02-rust/src/hal/ui.rs
@@ -49,6 +49,13 @@ pub struct EnterStringParams<'a> {
pub default_to_digits: bool,
}
+#[derive(Copy, Clone, Eq, PartialEq)]
+pub enum TrinaryChoice {
+ Left,
+ Middle,
+ Right,
+}
+
#[allow(async_fn_in_trait)]
pub trait Ui {
/// Returns `Ok(())` if the user accepts, `Err(UserAbort)` if the user rejects.
@@ -86,7 +93,7 @@ pub trait Ui {
label_left: Option<&str>,
label_middle: Option<&str>,
label_right: Option<&str>,
- ) -> bitbox02::ui::TrinaryChoice;
+ ) -> TrinaryChoice;
/// Display the BIP39 mnemonic to the user.
async fn show_mnemonic(&mut self, words: &[&str]) -> Result<(), UserAbort>;
diff --git a/src/rust/bitbox02-rust/src/hww/api/bip85.rs b/src/rust/bitbox02-rust/src/hww/api/bip85.rs
index c79de90..2819a5f 100644
--- a/src/rust/bitbox02-rust/src/hww/api/bip85.rs
+++ b/src/rust/bitbox02-rust/src/hww/api/bip85.rs
@@ -31,8 +31,8 @@ pub async fn process(
/// Derives and displays a BIP-39 seed according to BIP-85:
/// https://github.com/bitcoin/bips/blob/master/bip-0085.mediawiki#bip39.
async fn process_bip39(hal: &mut impl crate::hal::Hal) -> Result<(), Error> {
+ use crate::hal::ui::TrinaryChoice;
use crate::workflow::trinary_input_string;
- use bitbox02::ui::TrinaryChoice;
hal.ui()
.confirm(&ConfirmParams {
@@ -58,9 +58,9 @@ async fn process_bip39(hal: &mut impl crate::hal::Hal) -> Result<(), Error> {
.trinary_choice("How many words?", Some("12"), None, Some("24"))
.await
{
- TrinaryChoice::TRINARY_CHOICE_LEFT => 12,
- TrinaryChoice::TRINARY_CHOICE_MIDDLE => unreachable!(),
- TrinaryChoice::TRINARY_CHOICE_RIGHT => 24,
+ TrinaryChoice::Left => 12,
+ TrinaryChoice::Middle => unreachable!(),
+ TrinaryChoice::Right => 24,
};
hal.ui().status(&format!("{} words", num_words), true).await;
diff --git a/src/rust/bitbox02-rust/src/workflow/mnemonic.rs b/src/rust/bitbox02-rust/src/workflow/mnemonic.rs
index d54afec..1add239 100644
--- a/src/rust/bitbox02-rust/src/workflow/mnemonic.rs
+++ b/src/rust/bitbox02-rust/src/workflow/mnemonic.rs
@@ -1,12 +1,11 @@
// SPDX-License-Identifier: Apache-2.0
use super::trinary_input_string;
-use crate::hal::ui::{ConfirmParams, UserAbort};
+use crate::hal::ui::{ConfirmParams, TrinaryChoice, UserAbort};
use alloc::string::String;
use alloc::vec::Vec;
-use bitbox02::ui::TrinaryChoice;
use sha2::{Digest, Sha256};
const NUM_RANDOM_WORDS: u8 = 5;
@@ -270,9 +269,9 @@ pub async fn get(
.trinary_choice("How many words?", Some("12"), None, Some("24"))
.await
{
- TrinaryChoice::TRINARY_CHOICE_LEFT => 12,
- TrinaryChoice::TRINARY_CHOICE_MIDDLE => unreachable!(),
- TrinaryChoice::TRINARY_CHOICE_RIGHT => 24,
+ TrinaryChoice::Left => 12,
+ TrinaryChoice::Middle => unreachable!(),
+ TrinaryChoice::Right => 24,
};
hal_ui
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.