Refactor multisig_get/set_by_hash into HAL
What changed, and why it matters
This commit is a code cleanup that moves multisig account storage operations behind a hardware-abstraction layer so tests can use a fake memory instead of real device memory. It does not appear to fix or introduce a security vulnerability. A few test files were updated to use the new fake memory, and one small bug was fixed where a test created a fresh fake device after registering an account, which would have made the test fail to find the registered account.
No security action required. Treat as normal maintenance/refactoring. Reviewers may optionally verify that the TestingMemory duplicate-name and full-table behavior accurately mirrors the C implementation so tests remain representative.
Security signals we found
Refactoring only: no change to production memory access semantics
Hash type narrowed from Vec<u8> to [u8; 32], reducing risk of length confusion
Test-only bug fixed: registration and subsequent API call now share the same TestingHal instance
No new input validation or parsing logic in production code paths
Evidence from the diff
The change refactors multisig_get_by_hash and multisig_set_by_hash into the Memory trait in the Rust HAL. The production implementation delegates to the existing C memory functions. A new TestingMemory implementation mirrors the real semantics (duplicate-name rejection, rename-in-place, 25-entry limit). Call sites in bitcoin address generation, registration, and signing now pass the HAL through. The hash return type is tightened from Vec<u8> to [u8; 32]. Several tests were converted from bitbox02::memory::multisig_set_by_hash and mock_memory() to TestingHal. Notably, some tests previously registered a multisig/policy with mock_memory() and then called the API with a brand-new TestingHal::new(), which would not share the registration; those now use the same mock_hal instance for both registration and the API call.
Changed components
src/rust/bitbox02-rust/src/hal.rssrc/rust/bitbox02-rust/src/hww/api/bitcoin.rssrc/rust/bitbox02-rust/src/hww/api/bitcoin/multisig.rssrc/rust/bitbox02-rust/src/hww/api/bitcoin/policies.rssrc/rust/bitbox02-rust/src/hww/api/bitcoin/registration.rssrc/rust/bitbox02-rust/src/hww/api/bitcoin/signtx.rsInspect captured patch +212 / −99
diff --git a/src/rust/bitbox02-rust/src/hal.rs b/src/rust/bitbox02-rust/src/hal.rs
index adc9b9b..694fe3d 100644
--- a/src/rust/bitbox02-rust/src/hal.rs
+++ b/src/rust/bitbox02-rust/src/hal.rs
@@ -85,6 +85,12 @@ pub trait Memory {
root_pubkey_identifier_out: &mut [u8; 32],
) -> Result<(), ()>;
fn get_attestation_bootloader_hash(&mut self) -> [u8; 32];
+ fn multisig_set_by_hash(
+ &mut self,
+ hash: &[u8; 32],
+ name: &str,
+ ) -> Result<(), bitbox02::memory::MemoryError>;
+ fn multisig_get_by_hash(&self, hash: &[u8; 32]) -> Option<String>;
}
/// Hardware abstraction layer for BitBox devices.
@@ -295,6 +301,18 @@ impl Memory for BitBox02Memory {
fn get_attestation_bootloader_hash(&mut self) -> [u8; 32] {
bitbox02::memory::get_attestation_bootloader_hash()
}
+
+ fn multisig_set_by_hash(
+ &mut self,
+ hash: &[u8; 32],
+ name: &str,
+ ) -> Result<(), bitbox02::memory::MemoryError> {
+ bitbox02::memory::multisig_set_by_hash(hash, name)
+ }
+
+ fn multisig_get_by_hash(&self, hash: &[u8; 32]) -> Option<String> {
+ bitbox02::memory::multisig_get_by_hash(hash)
+ }
}
pub struct BitBox02Hal {
@@ -463,6 +481,7 @@ pub mod testing {
attestation_certificate: Option<[u8; 64]>,
attestation_root_pubkey_identifier: Option<[u8; 32]>,
attestation_bootloader_hash: [u8; 32],
+ multisig_entries: Vec<([u8; 32], String)>,
}
impl TestingSecureChip {
@@ -612,6 +631,8 @@ pub mod testing {
}
}
+ // Same as MEMORY_MULTISIG_NUM_ENTRIES in memory.h.
+ const MULTISIG_LIMIT: usize = 25;
impl TestingMemory {
pub fn new() -> Self {
Self {
@@ -629,6 +650,7 @@ pub mod testing {
attestation_certificate: None,
attestation_root_pubkey_identifier: None,
attestation_bootloader_hash: [0; 32],
+ multisig_entries: Vec::new(),
}
}
@@ -742,6 +764,7 @@ pub mod testing {
self.seed_birthdate = 0;
self.encrypted_seed_and_hmac = None;
self.device_name = None;
+ self.multisig_entries = Vec::new();
Ok(())
}
@@ -789,6 +812,53 @@ pub mod testing {
fn get_attestation_bootloader_hash(&mut self) -> [u8; 32] {
self.attestation_bootloader_hash
}
+
+ fn multisig_set_by_hash(
+ &mut self,
+ hash: &[u8; 32],
+ name: &str,
+ ) -> Result<(), bitbox02::memory::MemoryError> {
+ // Validate input
+ if name.is_empty() {
+ return Err(bitbox02::memory::MemoryError::MEMORY_ERR_INVALID_INPUT);
+ }
+ // Check for duplicate name with different hash
+ for (existing_hash, existing_name) in &self.multisig_entries {
+ if existing_name == name {
+ if existing_hash != hash {
+ // Mirror bitbox02::memory multisig_set_by_hash semantics (duplicate-name / full-table),
+ // even if these branches are not currently exercised in bitbox02-rust tests.
+ return Err(bitbox02::memory::MemoryError::MEMORY_ERR_DUPLICATE_NAME);
+ }
+ // same name, same hash (already stored)
+ return Ok(());
+ }
+ }
+ // Try to find existing entry with same hash
+ if let Some((_, existing_name)) = self
+ .multisig_entries
+ .iter_mut()
+ .find(|(existing_hash, _)| existing_hash == hash)
+ {
+ // rename: same hash, new name
+ *existing_name = String::from(name);
+ return Ok(());
+ }
+ if self.multisig_entries.len() >= MULTISIG_LIMIT {
+ // See comment above about mirroring bitbox02::memory semantics.
+ return Err(bitbox02::memory::MemoryError::MEMORY_ERR_FULL);
+ }
+ // Insert new entry
+ self.multisig_entries.push((*hash, String::from(name)));
+ Ok(())
+ }
+
+ fn multisig_get_by_hash(&self, hash: &[u8; 32]) -> Option<String> {
+ self.multisig_entries
+ .iter()
+ .find(|(existing_hash, _)| existing_hash == hash)
+ .map(|(_, name)| name.clone())
+ }
}
pub struct TestingHal<'a> {
diff --git a/src/rust/bitbox02-rust/src/hww/api/bitcoin.rs b/src/rust/bitbox02-rust/src/hww/api/bitcoin.rs
index 3786752..9f4e40e 100644
--- a/src/rust/bitbox02-rust/src/hww/api/bitcoin.rs
+++ b/src/rust/bitbox02-rust/src/hww/api/bitcoin.rs
@@ -196,7 +196,7 @@ pub async fn address_multisig(
.or(Err(Error::InvalidInput))?;
let account_keypath = &keypath[..keypath.len() - 2];
multisig::validate(hal, multisig, account_keypath)?;
- let name = match multisig::get_name(coin, multisig, account_keypath)? {
+ let name = match multisig::get_name(hal, coin, multisig, account_keypath)? {
Some(name) => name,
None => return Err(Error::InvalidInput),
};
@@ -239,7 +239,7 @@ async fn address_policy(
let parsed = policies::parse(hal, policy, coin)?;
- let name = parsed.name(coin_params)?.ok_or(Error::InvalidInput)?;
+ let name = parsed.name(hal, coin_params)?.ok_or(Error::InvalidInput)?;
let title = "Receive to";
@@ -300,7 +300,7 @@ pub async fn process_api(
) -> Result<pb::btc_response::Response, Error> {
match request {
Request::IsScriptConfigRegistered(request) => {
- registration::process_is_script_config_registered(request)
+ registration::process_is_script_config_registered(hal, request)
}
Request::RegisterScriptConfig(request) => {
registration::process_register_script_config(hal, request).await
@@ -322,7 +322,7 @@ mod tests {
use super::*;
use crate::bip32::parse_xpub;
- use crate::hal::testing::TestingHal;
+ use crate::hal::{Memory, testing::TestingHal};
use crate::keystore::testing::{TEST_MNEMONIC, mock_unlocked, mock_unlocked_using_mnemonic};
use crate::workflow::testing::Screen;
use alloc::boxed::Box;
@@ -997,17 +997,16 @@ mod tests {
our_xpub_index: test.our_xpub_index,
script_type: test.script_type as _,
};
- bitbox02::memory::multisig_set_by_hash(
- &multisig::get_hash(
- test.coin,
- &multisig,
- multisig::SortXpubs::Yes,
- &test.keypath[..test.keypath.len() - 2],
- )
- .unwrap(),
- name,
+ let mut mock_hal = TestingHal::new();
+ let account_keypath = &test.keypath[..test.keypath.len() - 2];
+ let hash = multisig::get_hash(
+ test.coin,
+ &multisig,
+ multisig::SortXpubs::Yes,
+ account_keypath,
)
.unwrap();
+ mock_hal.memory.multisig_set_by_hash(&hash, name).unwrap();
let req = pb::BtcPubRequest {
coin: test.coin as _,
keypath: test.keypath.to_vec(),
@@ -1016,8 +1015,6 @@ mod tests {
config: Some(Config::Multisig(multisig)),
})),
};
-
- let mut mock_hal = TestingHal::new();
assert_eq!(
block_on(process_pub(&mut mock_hal, &req)),
Ok(Response::Pub(pb::PubResponse {
@@ -1170,14 +1167,10 @@ mod tests {
};
// Register policy.
- mock_memory();
let name = "some name";
- bitbox02::memory::multisig_set_by_hash(
- &policies::get_hash(test.coin, &policy).unwrap(),
- name,
- )
- .unwrap();
-
+ let mut mock_hal = TestingHal::new();
+ let hash = policies::get_hash(test.coin, &policy).unwrap();
+ mock_hal.memory.multisig_set_by_hash(&hash, name).unwrap();
let req = pb::BtcPubRequest {
coin: test.coin as _,
keypath: test.keypath.to_vec(),
@@ -1187,7 +1180,7 @@ mod tests {
})),
};
assert_eq!(
- block_on(process_pub(&mut TestingHal::new(), &req)),
+ block_on(process_pub(&mut mock_hal, &req)),
Ok(Response::Pub(pb::PubResponse {
r#pub: test.expected_address.into(),
})),
diff --git a/src/rust/bitbox02-rust/src/hww/api/bitcoin/multisig.rs b/src/rust/bitbox02-rust/src/hww/api/bitcoin/multisig.rs
index 62bf74a..b1c943d 100644
--- a/src/rust/bitbox02-rust/src/hww/api/bitcoin/multisig.rs
+++ b/src/rust/bitbox02-rust/src/hww/api/bitcoin/multisig.rs
@@ -10,7 +10,7 @@ use pb::btc_script_config::{Multisig, multisig::ScriptType};
use crate::bip32;
-use crate::hal::Ui;
+use crate::hal::{Memory, Ui};
use crate::workflow::confirm;
use alloc::string::String;
@@ -35,7 +35,7 @@ pub fn get_hash(
multisig: &Multisig,
sort_xpubs: SortXpubs,
keypath: &[u32],
-) -> Result<Vec<u8>, ()> {
+) -> Result<[u8; 32], ()> {
let mut hasher = Sha256::new();
{
// 1. coin
@@ -90,7 +90,7 @@ pub fn get_hash(
hasher.update(el.to_le_bytes());
}
}
- Ok(hasher.finalize().as_slice().into())
+ Ok(hasher.finalize().into())
}
/// Get the name of a registered multisig account. The individual params are not validated, they
@@ -99,20 +99,20 @@ pub fn get_hash(
/// The keypath is the account-level keypath.
///
/// Returns the name of the registered multisig account if it exists or None otherwise.
-pub fn get_name(coin: BtcCoin, multisig: &Multisig, keypath: &[u32]) -> Result<Option<String>, ()> {
+pub fn get_name(
+ hal: &mut impl crate::hal::Hal,
+ coin: BtcCoin,
+ multisig: &Multisig,
+ keypath: &[u32],
+) -> Result<Option<String>, ()> {
// First try using sorted xpubs (the default registration since v9.3.0).
- if let Some(name) =
- bitbox02::memory::multisig_get_by_hash(&get_hash(coin, multisig, SortXpubs::Yes, keypath)?)
- {
+ let hash_sorted = get_hash(coin, multisig, SortXpubs::Yes, keypath)?;
+ if let Some(name) = hal.memory().multisig_get_by_hash(&hash_sorted) {
return Ok(Some(name));
}
// If that did not exist, try with unsorted xpubs for backwards compatibility.
- Ok(bitbox02::memory::multisig_get_by_hash(&get_hash(
- coin,
- multisig,
- SortXpubs::No,
- keypath,
- )?))
+ let hash_unsorted = get_hash(coin, multisig, SortXpubs::No, keypath)?;
+ Ok(hal.memory().multisig_get_by_hash(&hash_unsorted))
}
/// Confirms a multisig setup with the user during send/receive.
@@ -319,6 +319,7 @@ pub fn pkscript(
#[cfg(test)]
mod tests {
use super::*;
+ use hex_lit::hex;
use crate::keystore::testing::mock_unlocked_using_mnemonic;
use bip32::parse_xpub;
@@ -365,23 +366,19 @@ mod tests {
assert_eq!(
get_hash(BtcCoin::Btc, &multisig, SortXpubs::No, keypath).unwrap(),
- hex::decode("b0267fbb26ba0e74bad825c987949f58ba22aa75f63b539986dd937607bb4dc3")
- .unwrap(),
+ hex!("b0267fbb26ba0e74bad825c987949f58ba22aa75f63b539986dd937607bb4dc3"),
);
assert_eq!(
get_hash(BtcCoin::Tbtc, &multisig, SortXpubs::No, keypath).unwrap(),
- hex::decode("3800cb87a1e346eb4a61e25c4775e663f613090aa2bf3fddb057462d174b56ef")
- .unwrap(),
+ hex!("3800cb87a1e346eb4a61e25c4775e663f613090aa2bf3fddb057462d174b56ef"),
);
assert_eq!(
get_hash(BtcCoin::Ltc, &multisig, SortXpubs::No, keypath).unwrap(),
- hex::decode("6cf181d3e131eafefd4258084e5e48366a32d59be80a0afb13345589294ccf2d")
- .unwrap(),
+ hex!("6cf181d3e131eafefd4258084e5e48366a32d59be80a0afb13345589294ccf2d"),
);
assert_eq!(
get_hash(BtcCoin::Tltc, &multisig, SortXpubs::No, keypath).unwrap(),
- hex::decode("0e5ee1d18a74d22cf7e3255a3529b9a453e9b080005ca0bd886f6decf9e4b845")
- .unwrap(),
+ hex!("0e5ee1d18a74d22cf7e3255a3529b9a453e9b080005ca0bd886f6decf9e4b845"),
);
let multisig_p2wsh_p2sh = Multisig {
@@ -395,8 +392,7 @@ mod tests {
};
assert_eq!(
get_hash(BtcCoin::Btc, &multisig_p2wsh_p2sh, SortXpubs::No, keypath).unwrap(),
- hex::decode("24513114c36f5c1f82d7b30c1431fad248d062dfa133d0f52ca85708b5a3fc2c")
- .unwrap(),
+ hex!("24513114c36f5c1f82d7b30c1431fad248d062dfa133d0f52ca85708b5a3fc2c"),
);
// Test that the hash is correct, and the same for all xpubs permutations if xpubs sort is
@@ -560,8 +556,7 @@ mod tests {
};
assert_eq!(
get_hash(BtcCoin::Btc, &multisig, SortXpubs::Yes, keypath).unwrap(),
- hex::decode("e09011232d85b49a9fd5b83d6bef42ff60a50b69b56218333cb61d93c1567fbe")
- .unwrap(),
+ hex!("e09011232d85b49a9fd5b83d6bef42ff60a50b69b56218333cb61d93c1567fbe"),
);
}
}
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 af99333..621fbfe 100644
--- a/src/rust/bitbox02-rust/src/hww/api/bitcoin/policies.rs
+++ b/src/rust/bitbox02-rust/src/hww/api/bitcoin/policies.rs
@@ -17,7 +17,7 @@ use util::bip32::HARDENED;
use miniscript::TranslatePk;
use crate::bip32;
-use crate::hal::Ui;
+use crate::hal::{Memory, Ui};
use crate::workflow::confirm;
use crate::xpubcache::Bip32XpubCache;
@@ -268,8 +268,12 @@ impl ParsedPolicy<'_> {
/// Get the name of a registered policy account.
///
/// Returns the name of the registered policy account if it exists or None otherwise.
- pub fn name(&self, params: &Params) -> Result<Option<String>, ()> {
- get_name(params.coin, self.policy)
+ pub fn name(
+ &self,
+ hal: &mut impl crate::hal::Hal,
+ params: &Params,
+ ) -> Result<Option<String>, ()> {
+ get_name(hal, params.coin, self.policy)
}
/// Iterates over the placeholder keys in this descriptor. For tr() descriptors, this covers the
@@ -716,7 +720,7 @@ pub enum Mode {
}
/// Creates a hash of this policy config, useful for registration and identification.
-pub fn get_hash(coin: BtcCoin, policy: &Policy) -> Result<Vec<u8>, ()> {
+pub fn get_hash(coin: BtcCoin, policy: &Policy) -> Result<[u8; 32], ()> {
let mut hasher = Sha256::new();
{
// 1. Type of registration: policy.
@@ -748,17 +752,20 @@ pub fn get_hash(coin: BtcCoin, policy: &Policy) -> Result<Vec<u8>, ()> {
hasher.update(&bip32::Xpub::from(key.xpub.as_ref().unwrap()).serialize(None)?);
}
}
- Ok(hasher.finalize().as_slice().into())
+ Ok(hasher.finalize().into())
}
/// Get the name of a registered policy account. The policy is not validated, it must be
/// pre-validated!
///
/// Returns the name of the registered policy account if it exists or None otherwise.
-pub fn get_name(coin: BtcCoin, policy: &Policy) -> Result<Option<String>, ()> {
- Ok(bitbox02::memory::multisig_get_by_hash(&get_hash(
- coin, policy,
- )?))
+pub fn get_name(
+ hal: &mut impl crate::hal::Hal,
+ coin: BtcCoin,
+ policy: &Policy,
+) -> Result<Option<String>, ()> {
+ let hash = get_hash(coin, policy)?;
+ Ok(hal.memory().multisig_get_by_hash(&hash))
}
#[cfg(test)]
diff --git a/src/rust/bitbox02-rust/src/hww/api/bitcoin/registration.rs b/src/rust/bitbox02-rust/src/hww/api/bitcoin/registration.rs
index 7958adb..7433cc6 100644
--- a/src/rust/bitbox02-rust/src/hww/api/bitcoin/registration.rs
+++ b/src/rust/bitbox02-rust/src/hww/api/bitcoin/registration.rs
@@ -13,10 +13,11 @@ use pb::btc_script_config::Config;
use super::multisig::SortXpubs;
-use crate::hal::Ui;
+use crate::hal::{Memory, Ui};
use crate::workflow::{confirm, trinary_input_string};
pub fn process_is_script_config_registered(
+ hal: &mut impl crate::hal::Hal,
request: &pb::BtcIsScriptConfigRegisteredRequest,
) -> Result<Response, Error> {
match request.registration.as_ref() {
@@ -31,7 +32,8 @@ pub fn process_is_script_config_registered(
let coin = BtcCoin::try_from(*coin)?;
Ok(Response::IsScriptConfigRegistered(
pb::BtcIsScriptConfigRegisteredResponse {
- is_registered: super::multisig::get_name(coin, multisig, keypath)?.is_some(),
+ is_registered: super::multisig::get_name(hal, coin, multisig, keypath)?
+ .is_some(),
},
))
}
@@ -46,7 +48,7 @@ pub fn process_is_script_config_registered(
let coin = BtcCoin::try_from(*coin)?;
Ok(Response::IsScriptConfigRegistered(
pb::BtcIsScriptConfigRegisteredResponse {
- is_registered: super::policies::get_name(coin, policy)?.is_some(),
+ is_registered: super::policies::get_name(hal, coin, policy)?.is_some(),
},
))
}
@@ -124,7 +126,7 @@ pub async fn process_register_script_config(
)
.await?;
let hash = super::multisig::get_hash(coin, multisig, SortXpubs::Yes, keypath)?;
- match bitbox02::memory::multisig_set_by_hash(&hash, &name) {
+ match hal.memory().multisig_set_by_hash(&hash, &name) {
Ok(()) => {
hal.ui().status("Multisig account\nregistered", true).await;
Ok(Response::Success(pb::BtcSuccess {}))
@@ -157,7 +159,7 @@ pub async fn process_register_script_config(
)
.await?;
let hash = super::policies::get_hash(coin, policy)?;
- match bitbox02::memory::multisig_set_by_hash(&hash, &name) {
+ match hal.memory().multisig_set_by_hash(&hash, &name) {
Ok(()) => {
hal.ui().status("Policy\nregistered", true).await;
Ok(Response::Success(pb::BtcSuccess {}))
@@ -182,12 +184,15 @@ mod tests {
use bitbox02::testing::mock_memory;
use util::bip32::HARDENED;
+ use crate::hal::testing::TestingHal;
+
use pb::btc_script_config::{Multisig, multisig::ScriptType};
#[test]
fn test_process_is_script_config_registered() {
fn test(sort_xpubs: SortXpubs) {
mock_memory();
+ let mut mock_hal = TestingHal::new();
let keypath = &[48 + HARDENED, 0 + HARDENED, 10 + HARDENED, 2 + HARDENED];
// The xpubs in this test are deliberately not ordered correctly to test that ordering
@@ -201,20 +206,22 @@ mod tests {
our_xpub_index: 0,
script_type: ScriptType::P2wsh as _,
};
+
let hash =
- &super::super::multisig::get_hash(BtcCoin::Btc, &multisig, sort_xpubs, keypath)
+ super::super::multisig::get_hash(BtcCoin::Btc, &multisig, sort_xpubs, keypath)
.unwrap();
+
let request = pb::BtcIsScriptConfigRegisteredRequest {
registration: Some(pb::BtcScriptConfigRegistration {
coin: BtcCoin::Btc as _,
script_config: Some(pb::BtcScriptConfig {
- config: Some(Config::Multisig(multisig)),
+ config: Some(Config::Multisig(multisig)), // `multisig` moved here, no more use after
}),
keypath: keypath.to_vec(),
}),
};
assert_eq!(
- process_is_script_config_registered(&request),
+ process_is_script_config_registered(&mut mock_hal, &request),
Ok(Response::IsScriptConfigRegistered(
pb::BtcIsScriptConfigRegisteredResponse {
is_registered: false,
@@ -222,9 +229,13 @@ mod tests {
))
);
- bitbox02::memory::multisig_set_by_hash(hash, "some name").unwrap();
+ mock_hal
+ .memory
+ .multisig_set_by_hash(&hash, "some name")
+ .unwrap();
+
assert_eq!(
- process_is_script_config_registered(&request),
+ process_is_script_config_registered(&mut mock_hal, &request),
Ok(Response::IsScriptConfigRegistered(
pb::BtcIsScriptConfigRegisteredResponse {
is_registered: true,
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 7e4d628..37283a3 100644
--- a/src/rust/bitbox02-rust/src/hww/api/bitcoin/signtx.rs
+++ b/src/rust/bitbox02-rust/src/hww/api/bitcoin/signtx.rs
@@ -383,7 +383,7 @@ fn validate_script_config<'a>(
keypath,
} => {
super::multisig::validate(hal, multisig, keypath)?;
- let name = super::multisig::get_name(coin_params.coin, multisig, keypath)?
+ let name = super::multisig::get_name(hal, coin_params.coin, multisig, keypath)?
.ok_or(Error::InvalidInput)?;
Ok(ValidatedScriptConfigWithKeypath {
keypath,
@@ -399,7 +399,7 @@ fn validate_script_config<'a>(
} => {
let parsed_policy = super::policies::parse(hal, policy, coin_params.coin)?;
let name = parsed_policy
- .name(coin_params)?
+ .name(hal, coin_params)?
.ok_or(Error::InvalidInput)?;
Ok(ValidatedScriptConfigWithKeypath {
keypath,
@@ -1288,7 +1288,7 @@ pub async fn process(
mod tests {
use super::*;
use crate::bip32::parse_xpub;
- use crate::hal::testing::TestingHal;
+ use crate::hal::{Memory, testing::TestingHal};
use crate::keystore::testing::{mock_unlocked, mock_unlocked_using_mnemonic};
use crate::workflow::testing::Screen;
use alloc::boxed::Box;
@@ -1831,6 +1831,9 @@ mod tests {
script_type: pb::btc_script_config::multisig::ScriptType::P2wsh
as _,
};
+
+ let mut mock_hal = TestingHal::new();
+
// Register multisig.
let hash = super::super::multisig::get_hash(
params.coin,
@@ -1839,12 +1842,12 @@ mod tests {
keypath,
)
.unwrap();
- bitbox02::memory::multisig_set_by_hash(&hash, "test name").unwrap();
+ mock_hal
+ .memory
+ .multisig_set_by_hash(&hash, "test name")
+ .unwrap();
- assert!(
- super::super::multisig::validate(&mut TestingHal::new(), &multisig, keypath)
- .is_ok()
- );
+ assert!(super::super::multisig::validate(&mut mock_hal, &multisig, keypath).is_ok());
let mut init_req_invalid = init_req_valid.clone();
init_req_invalid.script_configs = vec![
@@ -2892,7 +2895,10 @@ mod tests {
// Hash of the multisig configuration as computed by `btc_common_multisig_hash_sorted()`.
let multisig_hash =
hex!("89751d19e4e26fbeee2fd2c4f56ab7ae5be6dc46482e81241f4accfbc0a1584e");
- bitbox02::memory::multisig_set_by_hash(&multisig_hash, "test multisig account name")
+ let mut mock_hal = TestingHal::new();
+ mock_hal
+ .memory
+ .multisig_set_by_hash(&multisig_hash, "test multisig account name")
.unwrap();
let init_request = {
@@ -2935,8 +2941,6 @@ mod tests {
}
};
- let mut mock_hal = TestingHal::new();
-
let result = block_on(process(&mut mock_hal, &init_request));
match result {
Ok(Response::BtcSignNext(next)) => {
@@ -3064,7 +3068,10 @@ mod tests {
// Hash of the multisig configuration as computed by `btc_common_multisig_hash_sorted()`.
let multisig_hash =
hex!("a0a982a6f5ba9286ee45cd140fd763d43443d685a89bc60772553cc5418fccc4");
- bitbox02::memory::multisig_set_by_hash(&multisig_hash, "test multisig account name")
+ let mut mock_hal = TestingHal::new();
+ mock_hal
+ .memory
+ .multisig_set_by_hash(&multisig_hash, "test multisig account name")
.unwrap();
let init_request = {
@@ -3106,7 +3113,7 @@ mod tests {
contains_silent_payment_outputs: false,
}
};
- let result = block_on(process(&mut TestingHal::new(), &init_request));
+ let result = block_on(process(&mut mock_hal, &init_request));
match result {
Ok(Response::BtcSignNext(next)) => {
assert!(next.has_signature);
@@ -3136,7 +3143,10 @@ mod tests {
// Hash of the multisig configuration as computed by `btc_common_multisig_hash_sorted()`.
let multisig_hash =
hex!("9dfc0652e2a305c8b9949620f98ee14650302e385f23941bc607cc35fd7a7781");
- bitbox02::memory::multisig_set_by_hash(&multisig_hash, "test multisig account name")
+ let mut mock_hal = TestingHal::new();
+ mock_hal
+ .memory
+ .multisig_set_by_hash(&multisig_hash, "test multisig account name")
.unwrap();
let init_request = {
@@ -3189,7 +3199,7 @@ mod tests {
contains_silent_payment_outputs: false,
}
};
- let result = block_on(process(&mut TestingHal::new(), &init_request));
+ let result = block_on(process(&mut mock_hal, &init_request));
match result {
Ok(Response::BtcSignNext(next)) => {
assert!(next.has_signature);
@@ -3247,8 +3257,11 @@ mod tests {
};
// Register policy.
- let policy_hash = super::super::policies::get_hash(pb::BtcCoin::Tbtc, &policy).unwrap();
- bitbox02::memory::multisig_set_by_hash(&policy_hash, "test policy account name").unwrap();
+ let hash = super::super::policies::get_hash(pb::BtcCoin::Tbtc, &policy).unwrap();
+ mock_hal
+ .memory
+ .multisig_set_by_hash(&hash, "test policy account name")
+ .unwrap();
let result = block_on(process(
&mut mock_hal,
@@ -3369,11 +3382,16 @@ mod tests {
};
// Register policy.
- let policy_hash = super::super::policies::get_hash(pb::BtcCoin::Tbtc, &policy).unwrap();
- bitbox02::memory::multisig_set_by_hash(&policy_hash, "test policy account name").unwrap();
+ let mut mock_hal = TestingHal::new();
+ let hash_vec = super::super::policies::get_hash(pb::BtcCoin::Tbtc, &policy).unwrap();
+ let hash32: [u8; 32] = hash_vec.as_slice().try_into().unwrap();
+ mock_hal
+ .memory
+ .multisig_set_by_hash(&hash32, "test policy account name")
+ .unwrap();
let result = block_on(process(
- &mut TestingHal::new(),
+ &mut mock_hal,
&transaction
.borrow()
.init_request_policy(policy, keypath_account),
@@ -3433,10 +3451,14 @@ mod tests {
};
// Register policy.
- let policy_hash = super::super::policies::get_hash(pb::BtcCoin::Tbtc, &policy).unwrap();
- bitbox02::memory::multisig_set_by_hash(&policy_hash, "test policy account name").unwrap();
-
let mut mock_hal = TestingHal::new();
+ let hash_vec = super::super::policies::get_hash(pb::BtcCoin::Tbtc, &policy).unwrap();
+ let hash32: [u8; 32] = hash_vec.as_slice().try_into().unwrap();
+ mock_hal
+ .memory
+ .multisig_set_by_hash(&hash32, "test policy account name")
+ .unwrap();
+
assert!(
block_on(process(
&mut mock_hal,
@@ -3547,11 +3569,16 @@ mod tests {
};
// Register policy.
- let policy_hash = super::super::policies::get_hash(pb::BtcCoin::Tbtc, &policy).unwrap();
- bitbox02::memory::multisig_set_by_hash(&policy_hash, "test policy account name").unwrap();
+ let mut mock_hal = TestingHal::new();
+ let hash_vec = super::super::policies::get_hash(pb::BtcCoin::Tbtc, &policy).unwrap();
+ let hash32: [u8; 32] = hash_vec.as_slice().try_into().unwrap();
+ mock_hal
+ .memory
+ .multisig_set_by_hash(&hash32, "test policy account name")
+ .unwrap();
let result = block_on(process(
- &mut TestingHal::new(),
+ &mut mock_hal,
&transaction
.borrow()
.init_request_policy(policy, keypath_account),
@@ -3604,12 +3631,17 @@ mod tests {
};
// Register policy.
- let policy_hash = super::super::policies::get_hash(pb::BtcCoin::Tbtc, &policy).unwrap();
- bitbox02::memory::multisig_set_by_hash(&policy_hash, "test policy account name").unwrap();
+ let mut mock_hal = TestingHal::new();
+ let hash_vec = super::super::policies::get_hash(pb::BtcCoin::Tbtc, &policy).unwrap();
+ let hash32: [u8; 32] = hash_vec.as_slice().try_into().unwrap();
+ mock_hal
+ .memory
+ .multisig_set_by_hash(&hash32, "test policy account name")
+ .unwrap();
assert_eq!(
block_on(process(
- &mut TestingHal::new(),
+ &mut mock_hal,
&transaction
.borrow()
.init_request_policy(policy, wrong_keypath_account)
@@ -3653,12 +3685,17 @@ mod tests {
};
// Register policy.
- let policy_hash = super::super::policies::get_hash(pb::BtcCoin::Tbtc, &policy).unwrap();
- bitbox02::memory::multisig_set_by_hash(&policy_hash, "test policy account name").unwrap();
+ let mut mock_hal = TestingHal::new();
+ let hash_vec = super::super::policies::get_hash(pb::BtcCoin::Tbtc, &policy).unwrap();
+ let hash32: [u8; 32] = hash_vec.as_slice().try_into().unwrap();
+ mock_hal
+ .memory
+ .multisig_set_by_hash(&hash32, "test policy account name")
+ .unwrap();
assert_eq!(
block_on(process(
- &mut TestingHal::new(),
+ &mut mock_hal,
&transaction
.borrow()
.init_request_policy(policy, keypath_account)
Why this scored 18/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.