Skip to content

Commit cab0fe5

Browse files
committed
Merge remote-tracking branch 'benma/unit-test-xpub'
2 parents 1f76df6 + 02bf45e commit cab0fe5

File tree

5 files changed

+197
-37
lines changed

5 files changed

+197
-37
lines changed

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

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,197 @@ mod tests {
212212
use bitbox02::testing::{mock, mock_unlocked, Data, MUTEX};
213213
use util::bip32::HARDENED;
214214

215+
#[test]
216+
pub fn test_xpub() {
217+
let _guard = MUTEX.lock().unwrap();
218+
struct Test<'a> {
219+
coin: BtcCoin,
220+
keypath: &'a [u32],
221+
xpub_type: XPubType,
222+
expected_xpub: &'a str,
223+
expected_display_title: &'a str,
224+
}
225+
226+
for test in vec![
227+
// BTC P2WPKH-P2SH
228+
Test {
229+
coin: BtcCoin::Btc,
230+
keypath: &[49 + HARDENED, 0 + HARDENED, 0 + HARDENED],
231+
xpub_type: XPubType::Xpub,
232+
expected_xpub: "xpub6Bj8T8R98MTKGDcMpJnoKeHR54EF1JJohA2HLs2WeNiaZ9UdNVvAbYpPnVd3Mcymabx7fYDKx4ubku1DTPRoDzpziD4qK3vxN9FEiF25Hgx",
233+
expected_display_title: "Bitcoin\naccount #1",
234+
},
235+
Test {
236+
coin: BtcCoin::Btc,
237+
keypath: &[49 + HARDENED, 0 + HARDENED, 0 + HARDENED],
238+
xpub_type: XPubType::Ypub,
239+
expected_xpub: "ypub6WZPko64H2zo7WoUefaRXjNvF2NgwvJJcGYW8FvQ2P6TcFHrdA5jDcUXohadMXdgzF4vR1otQjG9eBcnB5qp2EWbaYmFtxkSdsJt6svswWd",
240+
expected_display_title: "Bitcoin\naccount #1",
241+
},
242+
Test {
243+
coin: BtcCoin::Btc,
244+
keypath: &[49 + HARDENED, 0 + HARDENED, 0 + HARDENED],
245+
xpub_type: XPubType::Zpub,
246+
expected_xpub: "zpub6qPf4TkyRiYGxozbV2N3jpURQzX8tYHoXP4iuepHQPULfM75spFHqg8fpuYDMSHcPtBjAVQSsPchXUELtnFppUCCStTgUsZvubNXVPGWjcc",
247+
expected_display_title: "Bitcoin\naccount #1",
248+
},
249+
Test {
250+
coin: BtcCoin::Btc,
251+
keypath: &[84 + HARDENED, 0 + HARDENED, 1 + HARDENED],
252+
xpub_type: XPubType::Xpub,
253+
expected_xpub: "xpub6Bh4PT7iTyf6EHrFhc2ZaRYQxiLexYJQ7DtnNSNipD19JRV5jUW4gVHV9ouWvRY6DbbfyQhjP9E7LQ9QuR1SkPMnMi8NP3o2WtnWZim6Dqd",
254+
expected_display_title: "Bitcoin\naccount #2",
255+
},
256+
// BTC P2WPKH
257+
Test {
258+
coin: BtcCoin::Btc,
259+
keypath: &[84 + HARDENED, 0 + HARDENED, 1 + HARDENED],
260+
xpub_type: XPubType::Zpub,
261+
expected_xpub: "zpub6qMaznTYmLk3vtEVNKbozbjRJedYqnHPwSwDwEAVaDkuQd7YEnqBvcbmCDpgvEqw2sqHUMtrJTwD6yNYLoqULriz6PXDYsS14LuoLr3KxUC",
262+
expected_display_title: "Bitcoin\naccount #2",
263+
},
264+
// TBTC P2WPKH-P2SH
265+
Test {
266+
coin: BtcCoin::Tbtc,
267+
keypath: &[49 + HARDENED, 1 + HARDENED, 0 + HARDENED],
268+
xpub_type: XPubType::Xpub,
269+
expected_xpub: "xpub6BmN7k2vQY7D5jQpmKErAMNRqgtDMz9ePjR83SRAR6GAiWr63z7QLBPvsEQ2ghgT8hm1BoeApuS3paSmGmax2u3ggETCfWJvCEu6jCZDneX",
270+
expected_display_title: "BTC Testnet\naccount #1",
271+
},
272+
Test {
273+
coin: BtcCoin::Tbtc,
274+
keypath: &[49 + HARDENED, 1 + HARDENED, 0 + HARDENED],
275+
xpub_type: XPubType::Tpub,
276+
expected_xpub: "tpubDC8zdyrc7p4fMXbgDWDwNGhoAoysMNehwN1RPzUJm124ToWo8CxVUd4m7GUpDCdgvcHuoPA3N1G6WkwNfdSBvLVyjqCWM2y9nCVWVGLFiLh",
277+
expected_display_title: "BTC Testnet\naccount #1",
278+
},
279+
// TBTC P2WPKH
280+
Test {
281+
coin: BtcCoin::Tbtc,
282+
keypath: &[84 + HARDENED, 1 + HARDENED, 0 + HARDENED],
283+
xpub_type: XPubType::Xpub,
284+
expected_xpub: "xpub6Bs9jH3KF6w5ibrAdLAvY4759RnU74dnmUZ42m5FMqoFQoW9xL6co535xiGzaZMXrYn3nqk94ruLVfArx7sxvUvoXeF3FvXLX9T2dgTLGgc",
285+
expected_display_title: "BTC Testnet\naccount #1",
286+
},
287+
Test {
288+
coin: BtcCoin::Tbtc,
289+
keypath: &[84 + HARDENED, 1 + HARDENED, 0 + HARDENED],
290+
xpub_type: XPubType::Tpub,
291+
expected_xpub: "tpubDCEnFWrzxNtXzQ325XA1jySSUYt86T8rK79MPK8PhkZ9A6As2YwhwWhvCkMn74JmeTJxQRG1bxjPBqfULyjCovP6bEzLwTBa773SPehtXCt",
292+
expected_display_title: "BTC Testnet\naccount #1",
293+
},
294+
// LTC P2WPKH-P2SH
295+
Test {
296+
coin: BtcCoin::Ltc,
297+
keypath: &[49 + HARDENED, 2 + HARDENED, 0 + HARDENED],
298+
xpub_type: XPubType::Xpub,
299+
expected_xpub: "xpub6CC3f5yryzDqxUWHSFz69BcjP1yB7dX3d4MNoyCrc77Z3iAmDdfSmsTR2wCH4WnAhPcmRyAn4tnQsxBD9E1A3DiZ4PA81FUGCYXkJ5hUmEu",
300+
expected_display_title: "Litecoin\naccount #1",
301+
},
302+
// LTC P2WPKH
303+
Test {
304+
coin: BtcCoin::Ltc,
305+
keypath: &[84 + HARDENED, 2 + HARDENED, 0 + HARDENED],
306+
xpub_type: XPubType::Xpub,
307+
expected_xpub: "xpub6CJNSECzxso6VQF15vTqSMUCLDfYytpKgbCEtuMTs6Sbjd3CGUoXynTvQYWDBThN337scHJnjqnQrL31ttZFa9CicdB3pRodqWxyEQwnrqm",
308+
expected_display_title: "Litecoin\naccount #1",
309+
},
310+
] {
311+
mock_unlocked();
312+
313+
// Without display.
314+
let mut req = pb::BtcPubRequest {
315+
coin: test.coin as _,
316+
keypath: test.keypath.to_vec(),
317+
display: false,
318+
output: Some(Output::XpubType(test.xpub_type as _)),
319+
};
320+
321+
assert_eq!(
322+
block_on(process_pub(&req)),
323+
Some(Ok(Response::Pub(pb::PubResponse {
324+
r#pub: test.expected_xpub.into(),
325+
}))),
326+
);
327+
328+
// With display.
329+
req.display = true;
330+
let expected_display_title = test.expected_display_title.clone();
331+
let expected_xpub = test.expected_xpub.clone();
332+
mock(Data {
333+
ui_confirm_create: Some(Box::new(move |params| {
334+
assert_eq!(params.title, expected_display_title);
335+
assert_eq!(params.body, expected_xpub);
336+
assert!(params.scrollable);
337+
true
338+
})),
339+
..Default::default()
340+
});
341+
mock_unlocked();
342+
assert_eq!(
343+
block_on(process_pub(&req)),
344+
Some(Ok(Response::Pub(pb::PubResponse {
345+
r#pub: test.expected_xpub.into(),
346+
}))),
347+
);
348+
}
349+
350+
// --- Negative tests
351+
mock_unlocked();
352+
// -- Invalid keypath for BTC
353+
assert!(block_on(process_pub(&pb::BtcPubRequest {
354+
coin: BtcCoin::Btc as _,
355+
keypath: [49 + HARDENED, 0 + HARDENED, 100 + HARDENED].to_vec(),
356+
display: false,
357+
output: Some(Output::XpubType(XPubType::Xpub as _)),
358+
}))
359+
.unwrap()
360+
.is_err());
361+
// -- Invalid keypath for BTC
362+
assert!(block_on(process_pub(&pb::BtcPubRequest {
363+
coin: BtcCoin::Btc as _,
364+
keypath: [49 + HARDENED, 2 + HARDENED, 0 + HARDENED].to_vec(),
365+
display: false,
366+
output: Some(Output::XpubType(XPubType::Xpub as _)),
367+
}))
368+
.unwrap()
369+
.is_err());
370+
// -- Invalid keypath for TBTC
371+
assert!(block_on(process_pub(&pb::BtcPubRequest {
372+
coin: BtcCoin::Tbtc as _,
373+
keypath: [49 + HARDENED, 0 + HARDENED, 0 + HARDENED].to_vec(),
374+
display: false,
375+
output: Some(Output::XpubType(XPubType::Xpub as _)),
376+
}))
377+
.unwrap()
378+
.is_err());
379+
// -- Invalid keypath for LTC
380+
assert!(block_on(process_pub(&pb::BtcPubRequest {
381+
coin: BtcCoin::Ltc as _,
382+
keypath: [49 + HARDENED, 0 + HARDENED, 0 + HARDENED].to_vec(),
383+
display: false,
384+
output: Some(Output::XpubType(XPubType::Xpub as _)),
385+
}))
386+
.unwrap()
387+
.is_err());
388+
389+
let req = pb::BtcPubRequest {
390+
coin: BtcCoin::Btc as _,
391+
keypath: [49 + HARDENED, 0 + HARDENED, 0 + HARDENED].to_vec(),
392+
display: false,
393+
output: Some(Output::XpubType(XPubType::Xpub as _)),
394+
};
395+
396+
// -- Wrong coin: MIN-1
397+
let mut req_invalid = req.clone();
398+
req_invalid.coin = BtcCoin::Btc as i32 - 1;
399+
assert!(block_on(process_pub(&req_invalid)).unwrap().is_err());
400+
// -- Wrong coin: MAX + 1
401+
let mut req_invalid = req.clone();
402+
req_invalid.coin = BtcCoin::Tltc as i32 + 1;
403+
assert!(block_on(process_pub(&req_invalid)).unwrap().is_err());
404+
}
405+
215406
#[test]
216407
pub fn test_address_simple() {
217408
let _guard = MUTEX.lock().unwrap();

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

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -52,28 +52,16 @@ mod tests {
5252
use super::*;
5353

5454
use crate::bb02_async::block_on;
55-
use bitbox02::testing::{mock, Data, MUTEX};
55+
use bitbox02::testing::{mock_unlocked, MUTEX};
5656
use std::boxed::Box;
5757

5858
#[test]
5959
pub fn test_process() {
6060
let _guard = MUTEX.lock().unwrap();
6161

62+
mock_unlocked();
63+
6264
// All good.
63-
mock(Data {
64-
keystore_encode_xpub_at_keypath: Some(Box::new(|keypath, xpub_type| {
65-
assert_eq!(
66-
keypath,
67-
[
68-
ELECTRUM_WALLET_ENCRYPTION_KEYPATH_LEVEL_ONE,
69-
ELECTRUM_WALLET_ENCRYPTION_KEYPATH_LEVEL_TWO,
70-
]
71-
);
72-
assert_eq!(xpub_type, keystore::xpub_type_t::XPUB);
73-
Ok("<xpub>".into())
74-
})),
75-
..Default::default()
76-
});
7765
assert_eq!(
7866
block_on(process(&pb::ElectrumEncryptionKeyRequest {
7967
keypath: vec![
@@ -83,13 +71,12 @@ mod tests {
8371
})),
8472
Ok(Response::ElectrumEncryptionKey(
8573
pb::ElectrumEncryptionKeyResponse {
86-
key: "<xpub>".into()
74+
key: "xpub6AWqZzUWTTxAzVFXAavh7oX2apTkQAnjX9FU5pUMMjHiFzHLGLVWx9tAVvocV8c2WeoL7sUj2gZmdp3rDWaqmugZdSCYQVHCxCsVajQP7Cx".into()
8775
},
8876
))
8977
);
9078

9179
// Invalid keypath.
92-
mock(Default::default());
9380
assert_eq!(
9481
block_on(process(&pb::ElectrumEncryptionKeyRequest {
9582
keypath: vec![ELECTRUM_WALLET_ENCRYPTION_KEYPATH_LEVEL_ONE, 0]
@@ -98,7 +85,6 @@ mod tests {
9885
);
9986

10087
// Invalid keypath (wrong length).
101-
mock(Default::default());
10288
assert_eq!(
10389
block_on(process(&pb::ElectrumEncryptionKeyRequest {
10490
keypath: vec![

src/rust/bitbox02-rust/src/hww/api/ethereum/pubrequest.rs

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ mod tests {
114114
pub fn test_process_xpub() {
115115
let _guard = MUTEX.lock().unwrap();
116116

117-
const EXPECTED_XPUB: &str = "xpub";
117+
const EXPECTED_XPUB: &str = "xpub6FNKHYBc1HTwuwZcj4dz7xiG1kN7Hs3v7efYmgtzu1Gv6wJXxaCnFdQDRodbQpJKwdeVBf1RRNHARa6FsUMTCuRe2gKR7xCkSDdnppUp9oW";
118118
let request = pb::EthPubRequest {
119119
output_type: OutputType::Xpub as _,
120120
keypath: [44 + HARDENED, 60 + HARDENED, 0 + HARDENED, 0].to_vec(),
@@ -124,13 +124,7 @@ mod tests {
124124
};
125125

126126
// All good.
127-
mock(Data {
128-
keystore_encode_xpub_at_keypath: Some(Box::new(|_, xpub_type| {
129-
assert_eq!(xpub_type, keystore::xpub_type_t::XPUB);
130-
Ok(EXPECTED_XPUB.into())
131-
})),
132-
..Default::default()
133-
});
127+
mock_unlocked();
134128
assert_eq!(
135129
block_on(process(&request)),
136130
Ok(Response::Pub(pb::PubResponse {
@@ -162,7 +156,6 @@ mod tests {
162156

163157
// xpub fetching/encoding failed.
164158
mock(Data {
165-
keystore_encode_xpub_at_keypath: Some(Box::new(|_, _| Err(()))),
166159
..Default::default()
167160
});
168161
assert_eq!(block_on(process(&request)), Err(Error::InvalidInput));

src/rust/bitbox02/src/keystore.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,6 @@ pub fn secp256k1_pubkey_uncompressed(
185185
}
186186
}
187187

188-
#[cfg(not(feature = "testing"))]
189188
pub fn encode_xpub_at_keypath(keypath: &[u32], xpub_type: xpub_type_t) -> Result<String, ()> {
190189
let mut xpub = [0u8; bitbox02_sys::XPUB_ENCODED_LEN as _];
191190
match unsafe {
@@ -204,12 +203,6 @@ pub fn encode_xpub_at_keypath(keypath: &[u32], xpub_type: xpub_type_t) -> Result
204203
}
205204
}
206205

207-
#[cfg(feature = "testing")]
208-
pub fn encode_xpub_at_keypath(keypath: &[u32], xpub_type: xpub_type_t) -> Result<String, ()> {
209-
let data = crate::testing::DATA.0.borrow();
210-
data.keystore_encode_xpub_at_keypath.as_ref().unwrap()(keypath, xpub_type)
211-
}
212-
213206
pub struct SignResult {
214207
pub signature: [u8; 64],
215208
pub recid: u8,

src/rust/bitbox02/src/testing.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
1717
extern crate alloc;
1818
extern crate std;
19-
use alloc::string::String;
2019
use core::cell::RefCell;
2120
use std::boxed::Box;
2221

@@ -36,8 +35,6 @@ pub struct Data {
3635
pub memory_is_initialized: Option<bool>,
3736
pub memory_set_initialized_result: Option<Result<(), ()>>,
3837
pub backup_create: Option<Box<dyn Fn(u32, u32) -> Result<(), super::backup::Error>>>,
39-
pub keystore_encode_xpub_at_keypath:
40-
Option<Box<dyn Fn(&[u32], super::keystore::xpub_type_t) -> Result<String, ()>>>,
4138
pub ui_transaction_address_create: Option<Box<dyn Fn(&str, &str) -> bool>>,
4239
pub ui_transaction_fee_create: Option<Box<dyn Fn(&str, &str) -> bool>>,
4340
}

0 commit comments

Comments
 (0)