Skip to content

Commit cf4260d

Browse files
committed
Merge branch 'rust-btc-unit-test'
2 parents ce49531 + 3dba896 commit cf4260d

File tree

4 files changed

+195
-33
lines changed

4 files changed

+195
-33
lines changed

src/rust/bitbox02-rust/src/hww/api/bitcoin.rs

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,3 +201,189 @@ pub async fn process_api(request: &Request) -> Option<Result<pb::btc_response::R
201201
_ => None,
202202
}
203203
}
204+
205+
#[cfg(test)]
206+
mod tests {
207+
use super::*;
208+
209+
use crate::bb02_async::block_on;
210+
use alloc::boxed::Box;
211+
use alloc::vec::Vec;
212+
use bitbox02::testing::{mock, mock_unlocked, Data, MUTEX};
213+
use util::bip32::HARDENED;
214+
215+
#[test]
216+
pub fn test_address_simple() {
217+
let _guard = MUTEX.lock().unwrap();
218+
219+
struct Test<'a> {
220+
coin: BtcCoin,
221+
keypath: &'a [u32],
222+
simple_type: SimpleType,
223+
expected_address: &'a str,
224+
expected_display_title: &'a str,
225+
}
226+
227+
for test in vec![
228+
// BTC P2WPKH-P2SH
229+
Test {
230+
coin: BtcCoin::Btc,
231+
keypath: &[49 + HARDENED, 0 + HARDENED, 0 + HARDENED, 0, 0],
232+
simple_type: SimpleType::P2wpkhP2sh,
233+
expected_address: "3BaL6XecvLAidPToUDhXo1zxD99ZUrErpd",
234+
expected_display_title: "Bitcoin",
235+
},
236+
Test {
237+
coin: BtcCoin::Btc,
238+
keypath: &[49 + HARDENED, 0 + HARDENED, 0 + HARDENED, 0, 1],
239+
simple_type: SimpleType::P2wpkhP2sh,
240+
expected_address: "3QRfCGEJVzvR1HN13kxB7xkuUtdEvG2orZ",
241+
expected_display_title: "Bitcoin",
242+
},
243+
Test {
244+
coin: BtcCoin::Btc,
245+
keypath: &[49 + HARDENED, 0 + HARDENED, 1 + HARDENED, 1, 100],
246+
simple_type: SimpleType::P2wpkhP2sh,
247+
expected_address: "39r7CFVo1wpb3mxQfkG6yYyxMAfqAmZMhA",
248+
expected_display_title: "Bitcoin",
249+
},
250+
// BTC P2WPKH
251+
Test {
252+
coin: BtcCoin::Btc,
253+
keypath: &[84 + HARDENED, 0 + HARDENED, 0 + HARDENED, 0, 0],
254+
simple_type: SimpleType::P2wpkh,
255+
expected_address: "bc1qk5f9em9qc8yfpks8ngfg3h8h02n2e3yeqdyhpt",
256+
expected_display_title: "Bitcoin",
257+
},
258+
Test {
259+
coin: BtcCoin::Btc,
260+
keypath: &[84 + HARDENED, 0 + HARDENED, 0 + HARDENED, 0, 1],
261+
simple_type: SimpleType::P2wpkh,
262+
expected_address: "bc1qtn7feuj7juxkzf48zfxtngrcyqyns9f4ska7hg",
263+
expected_display_title: "Bitcoin",
264+
},
265+
Test {
266+
coin: BtcCoin::Btc,
267+
keypath: &[84 + HARDENED, 0 + HARDENED, 1 + HARDENED, 1, 100],
268+
simple_type: SimpleType::P2wpkh,
269+
expected_address: "bc1qarhxx6daqetewkjwz9p6y78a28ygxm2vndhdas",
270+
expected_display_title: "Bitcoin",
271+
},
272+
// TBTC P2WPKH-P2SH
273+
Test {
274+
coin: BtcCoin::Tbtc,
275+
keypath: &[49 + HARDENED, 1 + HARDENED, 0 + HARDENED, 0, 0],
276+
simple_type: SimpleType::P2wpkhP2sh,
277+
expected_address: "2N5Tjwx5Htk7gLbv7nWqXUgpg5K2Uf4TacQ",
278+
expected_display_title: "BTC Testnet",
279+
},
280+
// TBTC P2WPKH
281+
Test {
282+
coin: BtcCoin::Tbtc,
283+
keypath: &[84 + HARDENED, 1 + HARDENED, 0 + HARDENED, 0, 0],
284+
simple_type: SimpleType::P2wpkh,
285+
expected_address: "tb1qnlyrq9pshg0v0lsuudjgga4nvmjxhcvketqwdg",
286+
expected_display_title: "BTC Testnet",
287+
},
288+
// LTC P2WPKH-P2SH
289+
Test {
290+
coin: BtcCoin::Ltc,
291+
keypath: &[49 + HARDENED, 2 + HARDENED, 0 + HARDENED, 0, 0],
292+
simple_type: SimpleType::P2wpkhP2sh,
293+
expected_address: "MMmYgSH7fbTPnfdi1vTejMJyY7rKY4j9qv",
294+
expected_display_title: "Litecoin",
295+
},
296+
Test {
297+
coin: BtcCoin::Ltc,
298+
keypath: &[49 + HARDENED, 2 + HARDENED, 0 + HARDENED, 0, 1],
299+
simple_type: SimpleType::P2wpkhP2sh,
300+
expected_address: "M7wA8gBLL4SBiwQ1muQeKcG6naYqWcaUHg",
301+
expected_display_title: "Litecoin",
302+
},
303+
Test {
304+
coin: BtcCoin::Ltc,
305+
keypath: &[49 + HARDENED, 2 + HARDENED, 1 + HARDENED, 1, 100],
306+
simple_type: SimpleType::P2wpkhP2sh,
307+
expected_address: "MPBnihMP2JYjPtBnLxGydqvaALBsc5ALTG",
308+
expected_display_title: "Litecoin",
309+
},
310+
// LTC P2WPKH
311+
Test {
312+
coin: BtcCoin::Ltc,
313+
keypath: &[84 + HARDENED, 2 + HARDENED, 0 + HARDENED, 0, 0],
314+
simple_type: SimpleType::P2wpkh,
315+
expected_address: "ltc1q7598y6mzud5fka043vs4vkx7zktvppxffsf7e3",
316+
expected_display_title: "Litecoin",
317+
},
318+
Test {
319+
coin: BtcCoin::Ltc,
320+
keypath: &[84 + HARDENED, 2 + HARDENED, 0 + HARDENED, 0, 1],
321+
simple_type: SimpleType::P2wpkh,
322+
expected_address: "ltc1qtgjfu2ltg4slmksv27awmh6h2pccvsth4mw2w9",
323+
expected_display_title: "Litecoin",
324+
},
325+
Test {
326+
coin: BtcCoin::Ltc,
327+
keypath: &[84 + HARDENED, 2 + HARDENED, 1 + HARDENED, 1, 100],
328+
simple_type: SimpleType::P2wpkh,
329+
expected_address: "ltc1qwsz89auhpezjfllq9y9qegpfgdwpw5vesppsz0",
330+
expected_display_title: "Litecoin",
331+
},
332+
// TLTC P2WPKH-P2SH
333+
Test {
334+
coin: BtcCoin::Tltc,
335+
keypath: &[49 + HARDENED, 1 + HARDENED, 0 + HARDENED, 0, 0],
336+
simple_type: SimpleType::P2wpkhP2sh,
337+
expected_address: "2N5Tjwx5Htk7gLbv7nWqXUgpg5K2Uf4TacQ",
338+
expected_display_title: "LTC Testnet",
339+
},
340+
// TLTC P2WPKH
341+
Test {
342+
coin: BtcCoin::Tltc,
343+
keypath: &[84 + HARDENED, 1 + HARDENED, 0 + HARDENED, 0, 0],
344+
simple_type: SimpleType::P2wpkh,
345+
expected_address: "tltc1qnlyrq9pshg0v0lsuudjgga4nvmjxhcvkqrzsap",
346+
expected_display_title: "LTC Testnet",
347+
},
348+
] {
349+
let mut req = pb::BtcPubRequest {
350+
coin: test.coin as _,
351+
keypath: test.keypath.to_vec(),
352+
display: false,
353+
output: Some(Output::ScriptConfig(BtcScriptConfig {
354+
config: Some(Config::SimpleType(test.simple_type as _)),
355+
})),
356+
};
357+
358+
// Without display.
359+
mock_unlocked();
360+
assert_eq!(
361+
block_on(process_pub(&req)),
362+
Some(Ok(Response::Pub(pb::PubResponse {
363+
r#pub: test.expected_address.into(),
364+
}))),
365+
);
366+
367+
// With display.
368+
req.display = true;
369+
let expected_display_title = test.expected_display_title.clone();
370+
let expected_address = test.expected_address.clone();
371+
mock(Data {
372+
ui_confirm_create: Some(Box::new(move |params| {
373+
assert_eq!(params.title, expected_display_title);
374+
assert_eq!(params.body, expected_address);
375+
assert!(params.scrollable);
376+
true
377+
})),
378+
..Default::default()
379+
});
380+
mock_unlocked();
381+
assert_eq!(
382+
block_on(process_pub(&req)),
383+
Some(Ok(Response::Pub(pb::PubResponse {
384+
r#pub: test.expected_address.into()
385+
}))),
386+
);
387+
}
388+
}
389+
}

src/rust/bitbox02-rust/src/hww/api/bitcoin/signmsg.rs

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -135,9 +135,9 @@ mod tests {
135135
use std::boxed::Box;
136136
use util::bip32::HARDENED;
137137

138-
const ADDRESS: &str = "<address>";
139138
const KEYPATH: &[u32] = &[84 + HARDENED, 0 + HARDENED, 0 + HARDENED, 0, 0];
140139
const MESSAGE: &[u8] = b"message";
140+
const EXPECTED_ADDRESS: &str = "bc1qk5f9em9qc8yfpks8ngfg3h8h02n2e3yeqdyhpt";
141141
const EXPECTED_SIGNATURE: &[u8] = b"\x0f\x1d\x54\x2a\x9e\x2f\x37\x4e\xfe\xd4\x57\x8c\xaa\x84\x72\xd1\xc3\x12\x68\xfb\x89\x2d\x39\xa6\x15\x44\x59\x18\x5b\x2d\x35\x4d\x3b\x2b\xff\xf0\xe1\x61\x5c\x77\x25\x73\x4f\x43\x13\x4a\xb4\x51\x6b\x7e\x7c\xb3\x9d\x2d\xba\xaa\x5f\x4e\x8b\x8a\xff\x9f\x97\xd0\x00";
142142

143143
#[test]
@@ -159,10 +159,6 @@ mod tests {
159159
static mut CONFIRM_COUNTER: u32 = 0;
160160

161161
mock(Data {
162-
btc_address_simple: Some(Box::new(|coin, _, _| {
163-
assert_eq!(coin, BtcCoin::Btc as _);
164-
Ok(ADDRESS.into())
165-
})),
166162
ui_confirm_create: Some(Box::new(|params| {
167163
match unsafe {
168164
CONFIRM_COUNTER += 1;
@@ -175,7 +171,7 @@ mod tests {
175171
}
176172
2 => {
177173
assert_eq!(params.title, "Address");
178-
assert_eq!(params.body, ADDRESS);
174+
assert_eq!(params.body, EXPECTED_ADDRESS);
179175
true
180176
}
181177
3 => {
@@ -217,7 +213,6 @@ mod tests {
217213

218214
// Basic info dialog aborted.
219215
mock(Data {
220-
btc_address_simple: Some(Box::new(|_, _, _| Ok(ADDRESS.into()))),
221216
ui_confirm_create: Some(Box::new(|params| {
222217
match unsafe {
223218
CONFIRM_COUNTER += 1;
@@ -233,14 +228,14 @@ mod tests {
233228
})),
234229
..Default::default()
235230
});
231+
mock_unlocked();
236232
assert_eq!(block_on(process(&request)), Err(Error::UserAbort));
237233

238234
// Address verification aborted.
239235
unsafe {
240236
CONFIRM_COUNTER = 0;
241237
}
242238
mock(Data {
243-
btc_address_simple: Some(Box::new(|_, _, _| Ok(ADDRESS.into()))),
244239
ui_confirm_create: Some(Box::new(|params| {
245240
match unsafe {
246241
CONFIRM_COUNTER += 1;
@@ -249,22 +244,22 @@ mod tests {
249244
1 => true,
250245
2 => {
251246
assert_eq!(params.title, "Address");
252-
assert_eq!(params.body, ADDRESS);
247+
assert_eq!(params.body, EXPECTED_ADDRESS);
253248
false
254249
}
255250
_ => panic!("too many user confirmations"),
256251
}
257252
})),
258253
..Default::default()
259254
});
255+
mock_unlocked();
260256
assert_eq!(block_on(process(&request)), Err(Error::UserAbort));
261257

262258
// Message verification aborted.
263259
unsafe {
264260
CONFIRM_COUNTER = 0;
265261
}
266262
mock(Data {
267-
btc_address_simple: Some(Box::new(|_, _, _| Ok(ADDRESS.into()))),
268263
ui_confirm_create: Some(Box::new(|params| {
269264
match unsafe {
270265
CONFIRM_COUNTER += 1;
@@ -281,6 +276,7 @@ mod tests {
281276
})),
282277
..Default::default()
283278
});
279+
mock_unlocked();
284280
assert_eq!(block_on(process(&request)), Err(Error::UserAbort));
285281
}
286282

@@ -354,19 +350,19 @@ mod tests {
354350
Err(Error::InvalidInput)
355351
);
356352

357-
// Address could not be generated
353+
// Invalid keypath
358354
mock(Data {
359-
btc_address_simple: Some(Box::new(|_, _, _| Err(()))),
360355
..Default::default()
361356
});
357+
mock_unlocked();
362358
assert_eq!(
363359
block_on(process(&pb::BtcSignMessageRequest {
364360
coin: BtcCoin::Btc as _,
365361
script_config: Some(pb::BtcScriptConfigWithKeypath {
366362
script_config: Some(pb::BtcScriptConfig {
367363
config: Some(Config::SimpleType(SimpleType::P2wpkh as _))
368364
}),
369-
keypath: KEYPATH.to_vec(),
365+
keypath: [0].to_vec(),
370366
}),
371367
msg: MESSAGE.to_vec(),
372368
host_nonce_commitment: None,

src/rust/bitbox02/src/app_btc.rs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ use alloc::string::String;
1717

1818
pub use bitbox02_sys::{BTCCoin, BTCScriptConfig_SimpleType};
1919

20-
#[cfg(not(feature = "testing"))]
2120
pub fn address_simple(
2221
coin: BTCCoin,
2322
script_type: BTCScriptConfig_SimpleType,
@@ -40,13 +39,3 @@ pub fn address_simple(
4039
false => Err(()),
4140
}
4241
}
43-
44-
#[cfg(feature = "testing")]
45-
pub fn address_simple(
46-
coin: BTCCoin,
47-
script_type: BTCScriptConfig_SimpleType,
48-
keypath: &[u32],
49-
) -> Result<String, ()> {
50-
let data = crate::testing::DATA.0.borrow();
51-
data.btc_address_simple.as_ref().unwrap()(coin, script_type, keypath)
52-
}

src/rust/bitbox02/src/testing.rs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,6 @@ pub struct Data {
3838
pub backup_create: Option<Box<dyn Fn(u32, u32) -> Result<(), super::backup::Error>>>,
3939
pub keystore_encode_xpub_at_keypath:
4040
Option<Box<dyn Fn(&[u32], super::keystore::xpub_type_t) -> Result<String, ()>>>,
41-
pub btc_address_simple: Option<
42-
Box<
43-
dyn Fn(
44-
bitbox02_sys::BTCCoin,
45-
bitbox02_sys::BTCScriptConfig_SimpleType,
46-
&[u32],
47-
) -> Result<String, ()>,
48-
>,
49-
>,
5041
pub ui_transaction_address_create: Option<Box<dyn Fn(&str, &str) -> bool>>,
5142
pub ui_transaction_fee_create: Option<Box<dyn Fn(&str, &str) -> bool>>,
5243
}

0 commit comments

Comments
 (0)