What changed, and why it matters
This is a routine internal cleanup in the BitBox02 firmware's user-interface code. It removes an artificial lifetime marker (a 'PhantomData' placeholder) from the Rust 'Component' type because the underlying callbacks that once required it have already been removed. There is no change to security logic, user-facing behavior, or how the device handles secrets.
No security action required. Treat as normal code-quality refactor.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit refactors the Rust UI wrapper around the C component_t. It changes Component<’a> to Component and removes the PhantomData<&’a ()> field and all associated lifetime parameters. The commit message states this is possible because ‘all callbacks are gone, so not needed anymore.’ The change is purely a type-system simplification; the Drop guard, screen_stack_push logic, and FFI calls remain unchanged.
Changed components
src/rust/bitbox02/src/ui/ui.rssrc/rust/bitbox02/src/ui/ui_stub.rssrc/rust/bitbox02/src/ui/ui_stub_c_unit_tests.rssrc/rust/bitbox02-rust/src/hww/api/bitcoin/signtx.rsInspect captured patch +24 / −61
diff --git a/src/rust/bitbox02-rust/src/hww/api/bitcoin/signtx.rs b/src/rust/bitbox02-rust/src/hww/api/bitcoin/signtx.rs
index c4c3c6c..f27ad39 100644
--- a/src/rust/bitbox02-rust/src/hww/api/bitcoin/signtx.rs
+++ b/src/rust/bitbox02-rust/src/hww/api/bitcoin/signtx.rs
@@ -305,7 +305,7 @@ async fn handle_prevtx(
input_index: u32,
input: &pb::BtcSignInputRequest,
num_inputs: u32,
- progress_component: &mut bitbox02::ui::Component<'_>,
+ progress_component: &mut bitbox02::ui::Component,
next_response: &mut NextResponse,
) -> Result<(), Error> {
let prevtx_init = get_prevtx_init(input_index, next_response).await?;
diff --git a/src/rust/bitbox02/src/ui/ui.rs b/src/rust/bitbox02/src/ui/ui.rs
index 7f3d622..d6990c7 100644
--- a/src/rust/bitbox02/src/ui/ui.rs
+++ b/src/rust/bitbox02/src/ui/ui.rs
@@ -15,17 +15,13 @@ use alloc::vec::Vec;
use core::cell::RefCell;
use core::task::{Poll, Waker};
-use core::marker::PhantomData;
-
/// Wraps the C component_t to be used in Rust.
-pub struct Component<'a> {
+pub struct Component {
component: *mut bitbox02_sys::component_t,
is_pushed: bool,
- // This is used to have the result callbacks outlive the component.
- _p: PhantomData<&'a ()>,
}
-impl Component<'_> {
+impl Component {
pub fn screen_stack_push(&mut self) {
if self.is_pushed {
panic!("component pushed twice");
@@ -37,7 +33,7 @@ impl Component<'_> {
}
}
-impl Drop for Component<'_> {
+impl Drop for Component {
fn drop(&mut self) {
if !self.is_pushed {
panic!("component not pushed");
@@ -144,7 +140,6 @@ pub async fn trinary_input_string(
let mut component = Component {
component,
is_pushed: false,
- _p: PhantomData,
};
component.screen_stack_push();
@@ -227,7 +222,6 @@ pub async fn confirm(params: &ConfirmParams<'_>) -> ConfirmResponse {
let mut component = Component {
component,
is_pushed: false,
- _p: PhantomData,
};
component.screen_stack_push();
@@ -254,7 +248,7 @@ pub fn screen_process() {
}
}
-pub fn status_create<'a>(text: &str, status_success: bool) -> Component<'a> {
+pub fn status_create(text: &str, status_success: bool) -> Component {
let component = unsafe {
bitbox02_sys::status_create(
util::strings::str_to_cstr_vec(text).unwrap().as_ptr(), // copied in C
@@ -264,7 +258,6 @@ pub fn status_create<'a>(text: &str, status_success: bool) -> Component<'a> {
Component {
component,
is_pushed: false,
- _p: PhantomData,
}
}
@@ -308,7 +301,6 @@ pub async fn sdcard() -> SdcardResponse {
let mut component = Component {
component,
is_pushed: false,
- _p: PhantomData,
};
component.screen_stack_push();
@@ -429,7 +421,6 @@ pub async fn menu(params: MenuParams<'_>) -> MenuResponse {
let mut component = Component {
component,
is_pushed: false,
- _p: PhantomData,
};
component.screen_stack_push();
@@ -531,7 +522,6 @@ pub async fn trinary_choice(
let mut component = Component {
component,
is_pushed: false,
- _p: PhantomData,
};
component.screen_stack_push();
@@ -593,7 +583,6 @@ pub async fn confirm_transaction_address(amount: &str, address: &str) -> Confirm
let mut component = Component {
component,
is_pushed: false,
- _p: PhantomData,
};
component.screen_stack_push();
@@ -656,7 +645,6 @@ pub async fn confirm_transaction_fee(amount: &str, fee: &str, longtouch: bool) -
let mut component = Component {
component,
is_pushed: false,
- _p: PhantomData,
};
component.screen_stack_push();
@@ -683,7 +671,7 @@ pub fn screen_stack_pop_all() {
}
}
-pub fn progress_create<'a>(title: &str) -> Component<'a> {
+pub fn progress_create(title: &str) -> Component {
let component = unsafe {
bitbox02_sys::progress_create(
util::strings::str_to_cstr_vec(title).unwrap().as_ptr(), // copied in C
@@ -693,7 +681,6 @@ pub fn progress_create<'a>(title: &str) -> Component<'a> {
Component {
component,
is_pushed: false,
- _p: PhantomData,
}
}
@@ -701,11 +688,10 @@ pub fn progress_set(component: &mut Component, progress: f32) {
unsafe { bitbox02_sys::progress_set(component.component, progress) }
}
-pub fn empty_create<'a>() -> Component<'a> {
+pub fn empty_create() -> Component {
Component {
component: unsafe { bitbox02_sys::empty_create() },
is_pushed: false,
- _p: PhantomData,
}
}
@@ -744,7 +730,6 @@ pub async fn unlock_animation() {
let mut component = Component {
component,
is_pushed: false,
- _p: PhantomData,
};
component.screen_stack_push();
@@ -796,7 +781,6 @@ pub async fn choose_orientation() -> bool {
let mut component = Component {
component,
is_pushed: false,
- _p: PhantomData,
};
component.screen_stack_push();
diff --git a/src/rust/bitbox02/src/ui/ui_stub.rs b/src/rust/bitbox02/src/ui/ui_stub.rs
index a88e405..eb4e84b 100644
--- a/src/rust/bitbox02/src/ui/ui_stub.rs
+++ b/src/rust/bitbox02/src/ui/ui_stub.rs
@@ -11,18 +11,15 @@ pub use super::types::{
TrinaryInputStringParams,
};
-use core::marker::PhantomData;
-
extern crate alloc;
use alloc::string::String;
-pub struct Component<'a> {
+pub struct Component {
is_pushed: bool,
- _p: PhantomData<&'a ()>,
}
-impl Component<'_> {
+impl Component {
pub fn screen_stack_push(&mut self) {
if self.is_pushed {
panic!("component pushed twice");
@@ -31,7 +28,7 @@ impl Component<'_> {
}
}
-impl Drop for Component<'_> {
+impl Drop for Component {
fn drop(&mut self) {
if !self.is_pushed {
panic!("component not pushed");
@@ -53,7 +50,7 @@ pub async fn confirm(_params: &ConfirmParams<'_>) -> ConfirmResponse {
pub fn screen_process() {}
-pub fn status_create<'a>(_text: &str, _status_success: bool) -> Component<'a> {
+pub fn status_create(_text: &str, _status_success: bool) -> Component {
panic!("not used");
}
@@ -88,20 +85,14 @@ pub async fn confirm_transaction_fee(
pub fn screen_stack_pop_all() {}
-pub fn progress_create<'a>(_title: &str) -> Component<'a> {
- Component {
- is_pushed: false,
- _p: PhantomData,
- }
+pub fn progress_create(_title: &str) -> Component {
+ Component { is_pushed: false }
}
pub fn progress_set(_component: &mut Component, _progress: f32) {}
-pub fn empty_create<'a>() -> Component<'a> {
- Component {
- is_pushed: false,
- _p: PhantomData,
- }
+pub fn empty_create() -> Component {
+ Component { is_pushed: false }
}
pub async fn unlock_animation() {}
diff --git a/src/rust/bitbox02/src/ui/ui_stub_c_unit_tests.rs b/src/rust/bitbox02/src/ui/ui_stub_c_unit_tests.rs
index 6ae6d14..3603df7 100644
--- a/src/rust/bitbox02/src/ui/ui_stub_c_unit_tests.rs
+++ b/src/rust/bitbox02/src/ui/ui_stub_c_unit_tests.rs
@@ -8,18 +8,15 @@ pub use super::types::{
TrinaryInputStringParams,
};
-use core::marker::PhantomData;
-
extern crate alloc;
use alloc::string::String;
-pub struct Component<'a> {
+pub struct Component {
is_pushed: bool,
- _p: PhantomData<&'a ()>,
}
-impl<'a> Component<'a> {
+impl Component {
pub fn screen_stack_push(&mut self) {
if self.is_pushed {
panic!("component pushed twice");
@@ -28,7 +25,7 @@ impl<'a> Component<'a> {
}
}
-impl<'a> Drop for Component<'a> {
+impl Drop for Component {
fn drop(&mut self) {
if !self.is_pushed {
panic!("component not pushed");
@@ -60,15 +57,12 @@ pub async fn confirm(params: &ConfirmParams<'_>) -> ConfirmResponse {
pub fn screen_process() {}
-pub fn status_create<'a>(text: &str, _status_success: bool) -> Component<'a> {
+pub fn status_create(text: &str, _status_success: bool) -> Component {
crate::print_stdout(&format!(
"STATUS SCREEN START\nTITLE: {}\nSTATUS SCREEN END\n",
text,
));
- Component {
- is_pushed: false,
- _p: PhantomData,
- }
+ Component { is_pushed: false }
}
pub async fn sdcard() -> SdcardResponse {
@@ -110,20 +104,14 @@ pub async fn confirm_transaction_fee(
pub fn screen_stack_pop_all() {}
-pub fn progress_create<'a>(_title: &str) -> Component<'a> {
- Component {
- is_pushed: false,
- _p: PhantomData,
- }
+pub fn progress_create(_title: &str) -> Component {
+ Component { is_pushed: false }
}
pub fn progress_set(_component: &mut Component, _progress: f32) {}
-pub fn empty_create<'a>() -> Component<'a> {
- Component {
- is_pushed: false,
- _p: PhantomData,
- }
+pub fn empty_create() -> Component {
+ Component { is_pushed: false }
}
pub async fn unlock_animation() {}
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.