use ms_codec::codex32::{Codex32String, Fe};
fn hex(data: &[u8]) -> String {
let mut ret = String::new();
for byte in data {
ret.push_str(&format!("{byte:02x}"));
}
ret
}
#[test]
fn bip_vector_2_interpolate() {
let share_ac = [
Codex32String::from_string("MS12NAMEA320ZYXWVUTSRQPNMLKJHGFEDCAXRPP870HKKQRM".into())
.unwrap(),
Codex32String::from_string("MS12NAMECACDEFGHJKLMNPQRSTUVWXYZ023FTR2GDZMPY6PN".into())
.unwrap(),
];
let share_d = Codex32String::interpolate_at(&share_ac, Fe::D).unwrap();
assert_eq!(
share_d.to_string(),
"MS12NAMEDLL4F8JLH4E5VDVULDLFXU2JHDNLSM97XVENRXEG"
);
let seed = Codex32String::interpolate_at(&share_ac, Fe::S).unwrap();
assert_eq!(
seed.to_string(),
"MS12NAMES6XQGUZTTXKEQNJSJZV4JV3NZ5K3KWGSPHUH6EVW"
);
assert_eq!(
hex(&seed.parts().data()),
"d1808e096b35b209ca12132b264662a5"
);
}
#[test]
fn bip_vector_3_interpolate() {
let share_sac = [
Codex32String::from_string("ms13cashsllhdmn9m42vcsamx24zrxgs3qqjzqud4m0d6nln".into())
.unwrap(),
Codex32String::from_string("ms13casha320zyxwvutsrqpnmlkjhgfedca2a8d0zehn8a0t".into())
.unwrap(),
Codex32String::from_string("ms13cashcacdefghjklmnpqrstuvwxyz023949xq35my48dr".into())
.unwrap(),
];
let share_def = [
Codex32String::interpolate_at(&share_sac, Fe::D).unwrap(),
Codex32String::interpolate_at(&share_sac, Fe::E).unwrap(),
Codex32String::interpolate_at(&share_sac, Fe::F).unwrap(),
];
assert_eq!(
share_def[0].to_string(),
"ms13cashd0wsedstcdcts64cd7wvy4m90lm28w4ffupqs7rm"
);
assert_eq!(
share_def[1].to_string(),
"ms13casheekgpemxzshcrmqhaydlp6yhms3ws7320xyxsar9"
);
assert_eq!(
share_def[2].to_string(),
"ms13cashf8jh6sdrkpyrsp5ut94pj8ktehhw2hfvyrj48704"
);
}
#[test]
fn bip_vector_4_from_seed() {
#[rustfmt::skip]
let seed_b = [
0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88,
0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00,
0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88,
0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00,
];
let seed = Codex32String::from_seed("ms", 0, "leet", Fe::S, &seed_b).unwrap();
assert_eq!(
seed.to_string(),
"ms10leetsllhdmn9m42vcsamx24zrxgs3qrl7ahwvhw4fnzrhve25gvezzyqqtum9pgv99ycma"
);
assert_eq!(seed.parts().data(), seed_b);
}
#[test]
fn bip_vector_5_long_decode() {
let long_seed = Codex32String::from_string(
"MS100C8VSM32ZXFGUHPCHTLUPZRY9X8GF2TVDW0S3JN54KHCE6MUA7LQPZYGSFJD6AN074RXVCEMLH8WU3TK925ACDEFGHJKLMNPQRSTUVWXY06FHPV80UNDVARHRAK".into()
).unwrap();
assert_eq!(
hex(&long_seed.parts().data()),
"dc5423251cb87175ff8110c8531d0952d8d73e1194e95b5f19d6f9df7c01111104c9baecdfea8cccc677fb9ddc8aec5553b86e528bcadfdcc201c17c638c47e9"
);
}
#[test]
fn from_seed_golden_all_entropy_lengths() {
fn pattern(len: usize) -> Vec<u8> {
(0..len)
.map(|i| (i as u8).wrapping_mul(7).wrapping_add(3))
.collect()
}
let cases: &[(usize, &str)] = &[
(16, "ms10testsqv9pzxqlyckngw6zf9g9whn9dstenv96hhvvflp"),
(20, "ms10testsqv9pzxqlyckngw6zf9g9whn9d3eh4qvg4a6a9f2fsr3r2"),
(
24,
"ms10testsqv9pzxqlyckngw6zf9g9whn9d3eh4qvg37tfmfqvazhe5382e4vw",
),
(
28,
"ms10testsqv9pzxqlyckngw6zf9g9whn9d3eh4qvg37tfmf9tk2uuqru75puvle6emd",
),
(
32,
"ms10testsqv9pzxqlyckngw6zf9g9whn9d3eh4qvg37tfmf9tk2uup37w6hwqgtmddfdndzx5f",
),
];
for &(len, expected) in cases {
let data = pattern(len);
let s = Codex32String::from_seed("ms", 0, "test", Fe::S, &data).unwrap();
assert_eq!(
s.to_string(),
expected,
"from_seed parity drift at entropy length {len}"
);
assert_eq!(
s.parts().data(),
data,
"data round-trip drift at length {len}"
);
}
}