1use aes::Aes256;
6use blake2b_simd::Params as Blake2bParams;
7use byteorder::{ByteOrder, LittleEndian, ReadBytesExt, WriteBytesExt};
8use fpe::ff1::{BinaryNumeralString, FF1};
9use std::convert::TryInto;
10use std::ops::AddAssign;
11use subtle::{Choice, ConditionallySelectable};
12
13use crate::{
14 constants::{PROOF_GENERATION_KEY_GENERATOR, SPENDING_KEY_GENERATOR},
15 sapling::{Diversifier, PaymentAddress, ViewingKey},
16};
17use std::io::{self, Read, Write};
18
19use crate::{
20 keys::{prf_expand, prf_expand_vec, OutgoingViewingKey},
21 sapling::keys::{ExpandedSpendingKey, FullViewingKey},
22};
23
24pub const ZIP32_SAPLING_MASTER_PERSONALIZATION: &[u8; 16] = b"ZcashIP32Sapling";
25pub const ZIP32_SAPLING_FVFP_PERSONALIZATION: &[u8; 16] = b"ZcashSaplingFVFP";
26pub const ZIP32_SAPLING_INT_PERSONALIZATION: &[u8; 16] = b"Zcash_SaplingInt";
27
28#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
30pub struct AccountId(u32);
31
32impl From<u32> for AccountId {
33 fn from(id: u32) -> Self {
34 Self(id)
35 }
36}
37
38impl From<AccountId> for u32 {
39 fn from(id: AccountId) -> Self {
40 id.0
41 }
42}
43
44impl ConditionallySelectable for AccountId {
45 fn conditional_select(a0: &Self, a1: &Self, c: Choice) -> Self {
46 AccountId(u32::conditional_select(&a0.0, &a1.0, c))
47 }
48}
49
50fn derive_child_ovk(parent: &OutgoingViewingKey, i_l: &[u8]) -> OutgoingViewingKey {
53 let mut ovk = [0u8; 32];
54 ovk.copy_from_slice(&prf_expand_vec(i_l, &[&[0x15], &parent.0]).as_bytes()[..32]);
55 OutgoingViewingKey(ovk)
56}
57
58struct FvkFingerprint([u8; 32]);
62
63impl From<&FullViewingKey> for FvkFingerprint {
64 fn from(fvk: &FullViewingKey) -> Self {
65 let mut h = Blake2bParams::new()
66 .hash_length(32)
67 .personal(ZIP32_SAPLING_FVFP_PERSONALIZATION)
68 .to_state();
69 h.update(&fvk.to_bytes());
70 let mut fvfp = [0u8; 32];
71 fvfp.copy_from_slice(h.finalize().as_bytes());
72 FvkFingerprint(fvfp)
73 }
74}
75
76#[derive(Clone, Copy, Debug, PartialEq)]
78struct FvkTag([u8; 4]);
79
80impl FvkFingerprint {
81 fn tag(&self) -> FvkTag {
82 let mut tag = [0u8; 4];
83 tag.copy_from_slice(&self.0[..4]);
84 FvkTag(tag)
85 }
86}
87
88impl FvkTag {
89 fn master() -> Self {
90 FvkTag([0u8; 4])
91 }
92}
93
94#[derive(Clone, Copy, Debug, PartialEq)]
96pub enum ChildIndex {
97 NonHardened(u32),
98 Hardened(u32), }
100
101impl ChildIndex {
102 pub fn from_index(i: u32) -> Self {
103 match i {
104 n if n >= (1 << 31) => ChildIndex::Hardened(n - (1 << 31)),
105 n => ChildIndex::NonHardened(n),
106 }
107 }
108
109 fn master() -> Self {
110 ChildIndex::from_index(0)
111 }
112
113 fn value(&self) -> u32 {
114 match *self {
115 ChildIndex::Hardened(i) => i + (1 << 31),
116 ChildIndex::NonHardened(i) => i,
117 }
118 }
119}
120
121#[derive(Clone, Copy, Debug, PartialEq)]
123pub struct ChainCode([u8; 32]);
124
125#[derive(Clone, Copy, Debug, PartialEq)]
126pub struct DiversifierIndex(pub [u8; 11]);
127
128impl Default for DiversifierIndex {
129 fn default() -> Self {
130 DiversifierIndex::new()
131 }
132}
133
134impl DiversifierIndex {
135 pub fn new() -> Self {
136 DiversifierIndex([0; 11])
137 }
138
139 pub fn increment(&mut self) -> Result<(), ()> {
140 for k in 0..11 {
141 self.0[k] = self.0[k].wrapping_add(1);
142 if self.0[k] != 0 {
143 return Ok(());
145 }
146 }
147 Err(())
149 }
150}
151
152#[derive(Clone, Copy, Debug, PartialEq)]
154pub struct DiversifierKey(pub [u8; 32]);
155
156impl DiversifierKey {
157 pub fn master(sk_m: &[u8]) -> Self {
158 let mut dk_m = [0u8; 32];
159 dk_m.copy_from_slice(&prf_expand(sk_m, &[0x10]).as_bytes()[..32]);
160 DiversifierKey(dk_m)
161 }
162
163 fn derive_child(&self, i_l: &[u8]) -> Self {
164 let mut dk = [0u8; 32];
165 dk.copy_from_slice(&prf_expand_vec(i_l, &[&[0x16], &self.0]).as_bytes()[..32]);
166 DiversifierKey(dk)
167 }
168
169 fn try_diversifier_internal(ff: &FF1<Aes256>, j: DiversifierIndex) -> Option<Diversifier> {
170 let enc = ff
172 .encrypt(&[], &BinaryNumeralString::from_bytes_le(&j.0[..]))
173 .unwrap();
174 let mut d_j = [0; 11];
175 d_j.copy_from_slice(&enc.to_bytes_le());
176 let diversifier = Diversifier(d_j);
177
178 diversifier.g_d().map(|_| diversifier)
180 }
181
182 pub fn diversifier(&self, j: DiversifierIndex) -> Option<Diversifier> {
185 let ff = FF1::<Aes256>::new(&self.0, 2).unwrap();
186 Self::try_diversifier_internal(&ff, j)
187 }
188
189 pub fn diversifier_index(&self, d: &Diversifier) -> DiversifierIndex {
195 let ff = FF1::<Aes256>::new(&self.0, 2).unwrap();
196 let dec = ff
197 .decrypt(&[], &BinaryNumeralString::from_bytes_le(&d.0[..]))
198 .unwrap();
199 let mut j = DiversifierIndex::new();
200 j.0.copy_from_slice(&dec.to_bytes_le());
201 j
202 }
203
204 pub fn find_diversifier(
209 &self,
210 mut j: DiversifierIndex,
211 ) -> Option<(DiversifierIndex, Diversifier)> {
212 let ff = FF1::<Aes256>::new(&self.0, 2).unwrap();
213 loop {
214 match Self::try_diversifier_internal(&ff, j) {
215 Some(d_j) => return Some((j, d_j)),
216 None => {
217 if j.increment().is_err() {
218 return None;
219 }
220 }
221 }
222 }
223 }
224}
225
226pub fn sapling_address(
230 fvk: &FullViewingKey,
231 dk: &DiversifierKey,
232 j: DiversifierIndex,
233) -> Option<PaymentAddress> {
234 dk.diversifier(j)
235 .and_then(|d_j| fvk.vk.to_payment_address(d_j))
236}
237
238pub fn sapling_find_address(
243 fvk: &FullViewingKey,
244 dk: &DiversifierKey,
245 j: DiversifierIndex,
246) -> Option<(DiversifierIndex, PaymentAddress)> {
247 let (j, d_j) = dk.find_diversifier(j)?;
248 fvk.vk.to_payment_address(d_j).map(|addr| (j, addr))
249}
250
251pub fn sapling_default_address(
254 fvk: &FullViewingKey,
255 dk: &DiversifierKey,
256) -> (DiversifierIndex, PaymentAddress) {
257 sapling_find_address(fvk, dk, DiversifierIndex::new()).unwrap()
260}
261
262pub fn sapling_derive_internal_fvk(
268 fvk: &FullViewingKey,
269 dk: &DiversifierKey,
270) -> (FullViewingKey, DiversifierKey) {
271 let i = {
272 let mut h = Blake2bParams::new()
273 .hash_length(32)
274 .personal(crate::zip32::ZIP32_SAPLING_INT_PERSONALIZATION)
275 .to_state();
276 h.update(&fvk.to_bytes());
277 h.update(&dk.0);
278 h.finalize()
279 };
280 let i_nsk = ironfish_jubjub::Fr::from_bytes_wide(prf_expand(i.as_bytes(), &[0x17]).as_array());
281 let r = prf_expand(i.as_bytes(), &[0x18]);
282 let r = r.as_bytes();
283 let nk_internal = *PROOF_GENERATION_KEY_GENERATOR * i_nsk + fvk.vk.nk;
285 let dk_internal = DiversifierKey(r[..32].try_into().unwrap());
286 let ovk_internal = OutgoingViewingKey(r[32..].try_into().unwrap());
287
288 (
289 FullViewingKey {
290 vk: ViewingKey {
291 ak: fvk.vk.ak,
292 nk: nk_internal,
293 },
294 ovk: ovk_internal,
295 },
296 dk_internal,
297 )
298}
299
300#[derive(Clone)]
302pub struct ExtendedSpendingKey {
303 depth: u8,
304 parent_fvk_tag: FvkTag,
305 child_index: ChildIndex,
306 chain_code: ChainCode,
307 pub expsk: ExpandedSpendingKey,
308 dk: DiversifierKey,
309}
310
311#[derive(Clone)]
313pub struct ExtendedFullViewingKey {
314 depth: u8,
315 parent_fvk_tag: FvkTag,
316 child_index: ChildIndex,
317 chain_code: ChainCode,
318 pub fvk: FullViewingKey,
319 pub(crate) dk: DiversifierKey,
320}
321
322impl std::cmp::PartialEq for ExtendedSpendingKey {
323 fn eq(&self, rhs: &ExtendedSpendingKey) -> bool {
324 self.depth == rhs.depth
325 && self.parent_fvk_tag == rhs.parent_fvk_tag
326 && self.child_index == rhs.child_index
327 && self.chain_code == rhs.chain_code
328 && self.expsk.ask == rhs.expsk.ask
329 && self.expsk.nsk == rhs.expsk.nsk
330 && self.expsk.ovk == rhs.expsk.ovk
331 && self.dk == rhs.dk
332 }
333}
334
335impl std::fmt::Debug for ExtendedSpendingKey {
336 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
337 write!(
338 f,
339 "ExtendedSpendingKey(d = {}, tag_p = {:?}, i = {:?})",
340 self.depth, self.parent_fvk_tag, self.child_index
341 )
342 }
343}
344
345impl std::cmp::PartialEq for ExtendedFullViewingKey {
346 fn eq(&self, rhs: &ExtendedFullViewingKey) -> bool {
347 self.depth == rhs.depth
348 && self.parent_fvk_tag == rhs.parent_fvk_tag
349 && self.child_index == rhs.child_index
350 && self.chain_code == rhs.chain_code
351 && self.fvk.vk.ak == rhs.fvk.vk.ak
352 && self.fvk.vk.nk == rhs.fvk.vk.nk
353 && self.fvk.ovk == rhs.fvk.ovk
354 && self.dk == rhs.dk
355 }
356}
357
358impl std::fmt::Debug for ExtendedFullViewingKey {
359 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
360 write!(
361 f,
362 "ExtendedFullViewingKey(d = {}, tag_p = {:?}, i = {:?})",
363 self.depth, self.parent_fvk_tag, self.child_index
364 )
365 }
366}
367
368impl ExtendedSpendingKey {
369 pub fn master(seed: &[u8]) -> Self {
370 let i = Blake2bParams::new()
371 .hash_length(64)
372 .personal(ZIP32_SAPLING_MASTER_PERSONALIZATION)
373 .hash(seed);
374
375 let sk_m = &i.as_bytes()[..32];
376 let mut c_m = [0u8; 32];
377 c_m.copy_from_slice(&i.as_bytes()[32..]);
378
379 ExtendedSpendingKey {
380 depth: 0,
381 parent_fvk_tag: FvkTag::master(),
382 child_index: ChildIndex::master(),
383 chain_code: ChainCode(c_m),
384 expsk: ExpandedSpendingKey::from_spending_key(sk_m),
385 dk: DiversifierKey::master(sk_m),
386 }
387 }
388
389 pub fn read<R: Read>(mut reader: R) -> io::Result<Self> {
390 let depth = reader.read_u8()?;
391 let mut tag = [0; 4];
392 reader.read_exact(&mut tag)?;
393 let i = reader.read_u32::<LittleEndian>()?;
394 let mut c = [0; 32];
395 reader.read_exact(&mut c)?;
396 let expsk = ExpandedSpendingKey::read(&mut reader)?;
397 let mut dk = [0; 32];
398 reader.read_exact(&mut dk)?;
399
400 Ok(ExtendedSpendingKey {
401 depth,
402 parent_fvk_tag: FvkTag(tag),
403 child_index: ChildIndex::from_index(i),
404 chain_code: ChainCode(c),
405 expsk,
406 dk: DiversifierKey(dk),
407 })
408 }
409
410 pub fn write<W: Write>(&self, mut writer: W) -> io::Result<()> {
411 writer.write_u8(self.depth)?;
412 writer.write_all(&self.parent_fvk_tag.0)?;
413 writer.write_u32::<LittleEndian>(self.child_index.value())?;
414 writer.write_all(&self.chain_code.0)?;
415 writer.write_all(&self.expsk.to_bytes())?;
416 writer.write_all(&self.dk.0)?;
417
418 Ok(())
419 }
420
421 pub fn from_path(master: &ExtendedSpendingKey, path: &[ChildIndex]) -> Self {
423 let mut xsk = master.clone();
424 for &i in path.iter() {
425 xsk = xsk.derive_child(i);
426 }
427 xsk
428 }
429
430 #[must_use]
431 pub fn derive_child(&self, i: ChildIndex) -> Self {
432 let fvk = FullViewingKey::from_expanded_spending_key(&self.expsk);
433 let tmp = match i {
434 ChildIndex::Hardened(i) => {
435 let mut le_i = [0; 4];
436 LittleEndian::write_u32(&mut le_i, i + (1 << 31));
437 prf_expand_vec(
438 &self.chain_code.0,
439 &[&[0x11], &self.expsk.to_bytes(), &self.dk.0, &le_i],
440 )
441 }
442 ChildIndex::NonHardened(i) => {
443 let mut le_i = [0; 4];
444 LittleEndian::write_u32(&mut le_i, i);
445 prf_expand_vec(
446 &self.chain_code.0,
447 &[&[0x12], &fvk.to_bytes(), &self.dk.0, &le_i],
448 )
449 }
450 };
451 let i_l = &tmp.as_bytes()[..32];
452 let mut c_i = [0u8; 32];
453 c_i.copy_from_slice(&tmp.as_bytes()[32..]);
454
455 ExtendedSpendingKey {
456 depth: self.depth + 1,
457 parent_fvk_tag: FvkFingerprint::from(&fvk).tag(),
458 child_index: i,
459 chain_code: ChainCode(c_i),
460 expsk: {
461 let mut ask = ironfish_jubjub::Fr::from_bytes_wide(prf_expand(i_l, &[0x13]).as_array());
462 let mut nsk = ironfish_jubjub::Fr::from_bytes_wide(prf_expand(i_l, &[0x14]).as_array());
463 ask.add_assign(&self.expsk.ask);
464 nsk.add_assign(&self.expsk.nsk);
465 let ovk = derive_child_ovk(&self.expsk.ovk, i_l);
466 ExpandedSpendingKey { ask, nsk, ovk }
467 },
468 dk: self.dk.derive_child(i_l),
469 }
470 }
471
472 pub fn default_address(&self) -> (DiversifierIndex, PaymentAddress) {
475 ExtendedFullViewingKey::from(self).default_address()
476 }
477
478 #[must_use]
482 pub fn derive_internal(&self) -> Self {
483 let i = {
484 let fvk = FullViewingKey::from_expanded_spending_key(&self.expsk);
485 let mut h = Blake2bParams::new()
486 .hash_length(32)
487 .personal(crate::zip32::ZIP32_SAPLING_INT_PERSONALIZATION)
488 .to_state();
489 h.update(&fvk.to_bytes());
490 h.update(&self.dk.0);
491 h.finalize()
492 };
493 let i_nsk = ironfish_jubjub::Fr::from_bytes_wide(prf_expand(i.as_bytes(), &[0x17]).as_array());
494 let r = prf_expand(i.as_bytes(), &[0x18]);
495 let r = r.as_bytes();
496 let nsk_internal = i_nsk + self.expsk.nsk;
497 let dk_internal = DiversifierKey(r[..32].try_into().unwrap());
498 let ovk_internal = OutgoingViewingKey(r[32..].try_into().unwrap());
499
500 ExtendedSpendingKey {
501 depth: self.depth,
502 parent_fvk_tag: self.parent_fvk_tag,
503 child_index: self.child_index,
504 chain_code: self.chain_code,
505 expsk: ExpandedSpendingKey {
506 ask: self.expsk.ask,
507 nsk: nsk_internal,
508 ovk: ovk_internal,
509 },
510 dk: dk_internal,
511 }
512 }
513}
514
515impl<'a> From<&'a ExtendedSpendingKey> for ExtendedFullViewingKey {
516 fn from(xsk: &ExtendedSpendingKey) -> Self {
517 ExtendedFullViewingKey {
518 depth: xsk.depth,
519 parent_fvk_tag: xsk.parent_fvk_tag,
520 child_index: xsk.child_index,
521 chain_code: xsk.chain_code,
522 fvk: FullViewingKey::from_expanded_spending_key(&xsk.expsk),
523 dk: xsk.dk,
524 }
525 }
526}
527
528impl ExtendedFullViewingKey {
529 pub fn read<R: Read>(mut reader: R) -> io::Result<Self> {
530 let depth = reader.read_u8()?;
531 let mut tag = [0; 4];
532 reader.read_exact(&mut tag)?;
533 let i = reader.read_u32::<LittleEndian>()?;
534 let mut c = [0; 32];
535 reader.read_exact(&mut c)?;
536 let fvk = FullViewingKey::read(&mut reader)?;
537 let mut dk = [0; 32];
538 reader.read_exact(&mut dk)?;
539
540 Ok(ExtendedFullViewingKey {
541 depth,
542 parent_fvk_tag: FvkTag(tag),
543 child_index: ChildIndex::from_index(i),
544 chain_code: ChainCode(c),
545 fvk,
546 dk: DiversifierKey(dk),
547 })
548 }
549
550 pub fn write<W: Write>(&self, mut writer: W) -> io::Result<()> {
551 writer.write_u8(self.depth)?;
552 writer.write_all(&self.parent_fvk_tag.0)?;
553 writer.write_u32::<LittleEndian>(self.child_index.value())?;
554 writer.write_all(&self.chain_code.0)?;
555 writer.write_all(&self.fvk.to_bytes())?;
556 writer.write_all(&self.dk.0)?;
557
558 Ok(())
559 }
560
561 pub fn derive_child(&self, i: ChildIndex) -> Result<Self, ()> {
562 let tmp = match i {
563 ChildIndex::Hardened(_) => return Err(()),
564 ChildIndex::NonHardened(i) => {
565 let mut le_i = [0; 4];
566 LittleEndian::write_u32(&mut le_i, i);
567 prf_expand_vec(
568 &self.chain_code.0,
569 &[&[0x12], &self.fvk.to_bytes(), &self.dk.0, &le_i],
570 )
571 }
572 };
573 let i_l = &tmp.as_bytes()[..32];
574 let mut c_i = [0u8; 32];
575 c_i.copy_from_slice(&tmp.as_bytes()[32..]);
576
577 Ok(ExtendedFullViewingKey {
578 depth: self.depth + 1,
579 parent_fvk_tag: FvkFingerprint::from(&self.fvk).tag(),
580 child_index: i,
581 chain_code: ChainCode(c_i),
582 fvk: {
583 let i_ask = ironfish_jubjub::Fr::from_bytes_wide(prf_expand(i_l, &[0x13]).as_array());
584 let i_nsk = ironfish_jubjub::Fr::from_bytes_wide(prf_expand(i_l, &[0x14]).as_array());
585 let ak = (*SPENDING_KEY_GENERATOR * i_ask) + self.fvk.vk.ak;
586 let nk = (*PROOF_GENERATION_KEY_GENERATOR * i_nsk) + self.fvk.vk.nk;
587
588 FullViewingKey {
589 vk: ViewingKey { ak, nk },
590 ovk: derive_child_ovk(&self.fvk.ovk, i_l),
591 }
592 },
593 dk: self.dk.derive_child(i_l),
594 })
595 }
596
597 pub fn address(&self, j: DiversifierIndex) -> Option<PaymentAddress> {
601 sapling_address(&self.fvk, &self.dk, j)
602 }
603
604 pub fn find_address(&self, j: DiversifierIndex) -> Option<(DiversifierIndex, PaymentAddress)> {
609 sapling_find_address(&self.fvk, &self.dk, j)
610 }
611
612 pub fn default_address(&self) -> (DiversifierIndex, PaymentAddress) {
615 sapling_default_address(&self.fvk, &self.dk)
616 }
617
618 #[must_use]
625 pub fn derive_internal(&self) -> Self {
626 let (fvk_internal, dk_internal) = sapling_derive_internal_fvk(&self.fvk, &self.dk);
627
628 ExtendedFullViewingKey {
629 depth: self.depth,
630 parent_fvk_tag: self.parent_fvk_tag,
631 child_index: self.child_index,
632 chain_code: self.chain_code,
633 fvk: fvk_internal,
634 dk: dk_internal,
635 }
636 }
637}
638
639#[cfg(test)]
640mod tests {
641 use super::*;
642
643 use ff::PrimeField;
644 use group::GroupEncoding;
645
646 #[test]
647 fn derive_nonhardened_child() {
648 let seed = [0; 32];
649 let xsk_m = ExtendedSpendingKey::master(&seed);
650 let xfvk_m = ExtendedFullViewingKey::from(&xsk_m);
651
652 let i_5 = ChildIndex::NonHardened(5);
653 let xsk_5 = xsk_m.derive_child(i_5);
654 let xfvk_5 = xfvk_m.derive_child(i_5);
655
656 assert!(xfvk_5.is_ok());
657 assert_eq!(ExtendedFullViewingKey::from(&xsk_5), xfvk_5.unwrap());
658 }
659
660 #[test]
661 fn derive_hardened_child() {
662 let seed = [0; 32];
663 let xsk_m = ExtendedSpendingKey::master(&seed);
664 let xfvk_m = ExtendedFullViewingKey::from(&xsk_m);
665
666 let i_5h = ChildIndex::Hardened(5);
667 let xsk_5h = xsk_m.derive_child(i_5h);
668 let xfvk_5h = xfvk_m.derive_child(i_5h);
669
670 assert!(xfvk_5h.is_err());
672 let xfvk_5h = ExtendedFullViewingKey::from(&xsk_5h);
673
674 let i_7 = ChildIndex::NonHardened(7);
675 let xsk_5h_7 = xsk_5h.derive_child(i_7);
676 let xfvk_5h_7 = xfvk_5h.derive_child(i_7);
677
678 assert!(xfvk_5h_7.is_ok());
680 assert_eq!(ExtendedFullViewingKey::from(&xsk_5h_7), xfvk_5h_7.unwrap());
681 }
682
683 #[test]
684 fn path() {
685 let seed = [0; 32];
686 let xsk_m = ExtendedSpendingKey::master(&seed);
687
688 let xsk_5h = xsk_m.derive_child(ChildIndex::Hardened(5));
689 assert_eq!(
690 ExtendedSpendingKey::from_path(&xsk_m, &[ChildIndex::Hardened(5)]),
691 xsk_5h
692 );
693
694 let xsk_5h_7 = xsk_5h.derive_child(ChildIndex::NonHardened(7));
695 assert_eq!(
696 ExtendedSpendingKey::from_path(
697 &xsk_m,
698 &[ChildIndex::Hardened(5), ChildIndex::NonHardened(7)]
699 ),
700 xsk_5h_7
701 );
702 }
703
704 #[test]
705 fn diversifier() {
706 let dk = DiversifierKey([0; 32]);
707 let j_0 = DiversifierIndex::new();
708 let j_1 = DiversifierIndex([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
709 let j_2 = DiversifierIndex([2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
710 let j_3 = DiversifierIndex([3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
711 let d_0 = [220, 231, 126, 188, 236, 10, 38, 175, 214, 153, 140];
713 let d_3 = [60, 253, 170, 8, 171, 147, 220, 31, 3, 144, 34];
714
715 let d_j = dk.diversifier(j_0).unwrap();
717 assert_eq!(d_j.0, d_0);
718 assert_eq!(dk.diversifier_index(&Diversifier(d_0)), j_0);
719
720 assert_eq!(dk.diversifier(j_1), None);
722
723 assert_eq!(dk.diversifier(j_2), None);
725
726 let d_j = dk.diversifier(j_3).unwrap();
728 assert_eq!(d_j.0, d_3);
729 assert_eq!(dk.diversifier_index(&Diversifier(d_3)), j_3);
730 }
731
732 #[test]
733 fn find_diversifier() {
734 let dk = DiversifierKey([0; 32]);
735 let j_0 = DiversifierIndex::new();
736 let j_1 = DiversifierIndex([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
737 let j_2 = DiversifierIndex([2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
738 let j_3 = DiversifierIndex([3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
739 let d_0 = [220, 231, 126, 188, 236, 10, 38, 175, 214, 153, 140];
741 let d_3 = [60, 253, 170, 8, 171, 147, 220, 31, 3, 144, 34];
742
743 let (j, d_j) = dk.find_diversifier(j_0).unwrap();
745 assert_eq!(j, j_0);
746 assert_eq!(d_j.0, d_0);
747
748 let (j, d_j) = dk.find_diversifier(j_1).unwrap();
750 assert_eq!(j, j_3);
751 assert_eq!(d_j.0, d_3);
752
753 let (j, d_j) = dk.find_diversifier(j_2).unwrap();
755 assert_eq!(j, j_3);
756 assert_eq!(d_j.0, d_3);
757
758 let (j, d_j) = dk.find_diversifier(j_3).unwrap();
760 assert_eq!(j, j_3);
761 assert_eq!(d_j.0, d_3);
762 }
763
764 #[test]
765 fn address() {
766 let seed = [0; 32];
767 let xsk_m = ExtendedSpendingKey::master(&seed);
768 let xfvk_m = ExtendedFullViewingKey::from(&xsk_m);
769 let j_0 = DiversifierIndex::new();
770 let addr_m = xfvk_m.address(j_0).unwrap();
771 assert_eq!(
772 addr_m.diversifier().0,
773 [59, 246, 250, 31, 131, 191, 69, 99, 200, 167, 19]
775 );
776
777 let j_1 = DiversifierIndex([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
778 assert_eq!(xfvk_m.address(j_1), None);
779 }
780
781 #[test]
782 fn default_address() {
783 let seed = [0; 32];
784 let xsk_m = ExtendedSpendingKey::master(&seed);
785 let (j_m, addr_m) = xsk_m.default_address();
786 assert_eq!(j_m.0, [0; 11]);
787 assert_eq!(
788 addr_m.diversifier().0,
789 [59, 246, 250, 31, 131, 191, 69, 99, 200, 167, 19]
791 );
792 }
793
794 #[test]
795 fn read_write() {
796 let seed = [0; 32];
797 let xsk = ExtendedSpendingKey::master(&seed);
798 let fvk = ExtendedFullViewingKey::from(&xsk);
799
800 let mut ser = vec![];
801 xsk.write(&mut ser).unwrap();
802 let xsk2 = ExtendedSpendingKey::read(&ser[..]).unwrap();
803 assert_eq!(xsk2, xsk);
804
805 let mut ser = vec![];
806 fvk.write(&mut ser).unwrap();
807 let fvk2 = ExtendedFullViewingKey::read(&ser[..]).unwrap();
808 assert_eq!(fvk2, fvk);
809 }
810
811 #[test]
812 fn test_vectors() {
813 struct TestVector {
814 ask: Option<[u8; 32]>,
815 nsk: Option<[u8; 32]>,
816 ovk: [u8; 32],
817 dk: [u8; 32],
818 c: [u8; 32],
819 ak: [u8; 32],
820 nk: [u8; 32],
821 ivk: [u8; 32],
822 xsk: Option<[u8; 169]>,
823 xfvk: [u8; 169],
824 fp: [u8; 32],
825 d0: Option<[u8; 11]>,
826 d1: Option<[u8; 11]>,
827 d2: Option<[u8; 11]>,
828 dmax: Option<[u8; 11]>,
829 internal_nsk: Option<[u8; 32]>,
830 internal_ovk: [u8; 32],
831 internal_dk: [u8; 32],
832 internal_nk: [u8; 32],
833 internal_ivk: [u8; 32],
834 internal_xsk: Option<[u8; 169]>,
835 internal_xfvk: [u8; 169],
836 internal_fp: [u8; 32],
837 }
838
839 let test_vectors = vec![
841 TestVector {
842 ask: Some([
843 0xb6, 0xc0, 0x0c, 0x93, 0xd3, 0x60, 0x32, 0xb9, 0xa2, 0x68, 0xe9, 0x9e, 0x86,
844 0xa8, 0x60, 0x77, 0x65, 0x60, 0xbf, 0x0e, 0x83, 0xc1, 0xa1, 0x0b, 0x51, 0xf6,
845 0x07, 0xc9, 0x54, 0x74, 0x25, 0x06,
846 ]),
847 nsk: Some([
848 0x82, 0x04, 0xed, 0xe8, 0x3b, 0x2f, 0x1f, 0xbd, 0x84, 0xf9, 0xb4, 0x5d, 0x7f,
849 0x99, 0x6e, 0x2e, 0xbd, 0x0a, 0x03, 0x0a, 0xd2, 0x43, 0xb4, 0x8e, 0xd3, 0x9f,
850 0x74, 0x8a, 0x88, 0x21, 0xea, 0x06,
851 ]),
852 ovk: [
853 0x39, 0x58, 0x84, 0x89, 0x03, 0x23, 0xb9, 0xd4, 0x93, 0x3c, 0x02, 0x1d, 0xb8,
854 0x9b, 0xcf, 0x76, 0x7d, 0xf2, 0x19, 0x77, 0xb2, 0xff, 0x06, 0x83, 0x84, 0x83,
855 0x21, 0xa4, 0xdf, 0x4a, 0xfb, 0x21,
856 ],
857 dk: [
858 0x77, 0xc1, 0x7c, 0xb7, 0x5b, 0x77, 0x96, 0xaf, 0xb3, 0x9f, 0x0f, 0x3e, 0x91,
859 0xc9, 0x24, 0x60, 0x7d, 0xa5, 0x6f, 0xa9, 0xa2, 0x0e, 0x28, 0x35, 0x09, 0xbc,
860 0x8a, 0x3e, 0xf9, 0x96, 0xa1, 0x72,
861 ],
862 c: [
863 0xd0, 0x94, 0x7c, 0x4b, 0x03, 0xbf, 0x72, 0xa3, 0x7a, 0xb4, 0x4f, 0x72, 0x27,
864 0x6d, 0x1c, 0xf3, 0xfd, 0xcd, 0x7e, 0xbf, 0x3e, 0x73, 0x34, 0x8b, 0x7e, 0x55,
865 0x0d, 0x75, 0x20, 0x18, 0x66, 0x8e,
866 ],
867 ak: [
868 0x93, 0x44, 0x2e, 0x5f, 0xef, 0xfb, 0xff, 0x16, 0xe7, 0x21, 0x72, 0x02, 0xdc,
869 0x73, 0x06, 0x72, 0x9f, 0xff, 0xfe, 0x85, 0xaf, 0x56, 0x83, 0xbc, 0xe2, 0x64,
870 0x2e, 0x3e, 0xeb, 0x5d, 0x38, 0x71,
871 ],
872 nk: [
873 0xdc, 0xe8, 0xe7, 0xed, 0xec, 0xe0, 0x4b, 0x89, 0x50, 0x41, 0x7f, 0x85, 0xba,
874 0x57, 0x69, 0x1b, 0x78, 0x3c, 0x45, 0xb1, 0xa2, 0x74, 0x22, 0xdb, 0x16, 0x93,
875 0xdc, 0xeb, 0x67, 0xb1, 0x01, 0x06,
876 ],
877 ivk: [
878 0x48, 0x47, 0xa1, 0x30, 0xe7, 0x99, 0xd3, 0xdb, 0xea, 0x36, 0xa1, 0xc1, 0x64,
879 0x67, 0xd6, 0x21, 0xfb, 0x2d, 0x80, 0xe3, 0x0b, 0x3b, 0x1d, 0x1a, 0x42, 0x68,
880 0x93, 0x41, 0x5d, 0xad, 0x66, 0x01,
881 ],
882 xsk: Some([
883 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x94, 0x7c, 0x4b,
884 0x03, 0xbf, 0x72, 0xa3, 0x7a, 0xb4, 0x4f, 0x72, 0x27, 0x6d, 0x1c, 0xf3, 0xfd,
885 0xcd, 0x7e, 0xbf, 0x3e, 0x73, 0x34, 0x8b, 0x7e, 0x55, 0x0d, 0x75, 0x20, 0x18,
886 0x66, 0x8e, 0xb6, 0xc0, 0x0c, 0x93, 0xd3, 0x60, 0x32, 0xb9, 0xa2, 0x68, 0xe9,
887 0x9e, 0x86, 0xa8, 0x60, 0x77, 0x65, 0x60, 0xbf, 0x0e, 0x83, 0xc1, 0xa1, 0x0b,
888 0x51, 0xf6, 0x07, 0xc9, 0x54, 0x74, 0x25, 0x06, 0x82, 0x04, 0xed, 0xe8, 0x3b,
889 0x2f, 0x1f, 0xbd, 0x84, 0xf9, 0xb4, 0x5d, 0x7f, 0x99, 0x6e, 0x2e, 0xbd, 0x0a,
890 0x03, 0x0a, 0xd2, 0x43, 0xb4, 0x8e, 0xd3, 0x9f, 0x74, 0x8a, 0x88, 0x21, 0xea,
891 0x06, 0x39, 0x58, 0x84, 0x89, 0x03, 0x23, 0xb9, 0xd4, 0x93, 0x3c, 0x02, 0x1d,
892 0xb8, 0x9b, 0xcf, 0x76, 0x7d, 0xf2, 0x19, 0x77, 0xb2, 0xff, 0x06, 0x83, 0x84,
893 0x83, 0x21, 0xa4, 0xdf, 0x4a, 0xfb, 0x21, 0x77, 0xc1, 0x7c, 0xb7, 0x5b, 0x77,
894 0x96, 0xaf, 0xb3, 0x9f, 0x0f, 0x3e, 0x91, 0xc9, 0x24, 0x60, 0x7d, 0xa5, 0x6f,
895 0xa9, 0xa2, 0x0e, 0x28, 0x35, 0x09, 0xbc, 0x8a, 0x3e, 0xf9, 0x96, 0xa1, 0x72,
896 ]),
897 xfvk: [
898 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x94, 0x7c, 0x4b,
899 0x03, 0xbf, 0x72, 0xa3, 0x7a, 0xb4, 0x4f, 0x72, 0x27, 0x6d, 0x1c, 0xf3, 0xfd,
900 0xcd, 0x7e, 0xbf, 0x3e, 0x73, 0x34, 0x8b, 0x7e, 0x55, 0x0d, 0x75, 0x20, 0x18,
901 0x66, 0x8e, 0x93, 0x44, 0x2e, 0x5f, 0xef, 0xfb, 0xff, 0x16, 0xe7, 0x21, 0x72,
902 0x02, 0xdc, 0x73, 0x06, 0x72, 0x9f, 0xff, 0xfe, 0x85, 0xaf, 0x56, 0x83, 0xbc,
903 0xe2, 0x64, 0x2e, 0x3e, 0xeb, 0x5d, 0x38, 0x71, 0xdc, 0xe8, 0xe7, 0xed, 0xec,
904 0xe0, 0x4b, 0x89, 0x50, 0x41, 0x7f, 0x85, 0xba, 0x57, 0x69, 0x1b, 0x78, 0x3c,
905 0x45, 0xb1, 0xa2, 0x74, 0x22, 0xdb, 0x16, 0x93, 0xdc, 0xeb, 0x67, 0xb1, 0x01,
906 0x06, 0x39, 0x58, 0x84, 0x89, 0x03, 0x23, 0xb9, 0xd4, 0x93, 0x3c, 0x02, 0x1d,
907 0xb8, 0x9b, 0xcf, 0x76, 0x7d, 0xf2, 0x19, 0x77, 0xb2, 0xff, 0x06, 0x83, 0x84,
908 0x83, 0x21, 0xa4, 0xdf, 0x4a, 0xfb, 0x21, 0x77, 0xc1, 0x7c, 0xb7, 0x5b, 0x77,
909 0x96, 0xaf, 0xb3, 0x9f, 0x0f, 0x3e, 0x91, 0xc9, 0x24, 0x60, 0x7d, 0xa5, 0x6f,
910 0xa9, 0xa2, 0x0e, 0x28, 0x35, 0x09, 0xbc, 0x8a, 0x3e, 0xf9, 0x96, 0xa1, 0x72,
911 ],
912 fp: [
913 0x14, 0xc2, 0x71, 0x3a, 0xdc, 0xe9, 0x3a, 0x83, 0x0e, 0xa8, 0x3a, 0x05, 0x19,
914 0x08, 0xb7, 0x44, 0x77, 0x83, 0xf5, 0xd1, 0x06, 0xc0, 0x98, 0x5e, 0x02, 0x55,
915 0x0e, 0x42, 0x6f, 0x27, 0x59, 0x7c,
916 ],
917 d0: Some([
918 0xd8, 0x62, 0x1b, 0x98, 0x1c, 0xf3, 0x00, 0xe9, 0xd4, 0xcc, 0x89,
919 ]),
920 d1: Some([
921 0x48, 0xea, 0x17, 0xa1, 0x99, 0xc8, 0x4b, 0xd1, 0xba, 0xa5, 0xd4,
922 ]),
923 d2: None,
924 dmax: None,
925 internal_nsk: Some([
926 0x51, 0x12, 0x33, 0x63, 0x6b, 0x95, 0xfd, 0x0a, 0xfb, 0x6b, 0xf8, 0x19, 0x3a,
927 0x7d, 0x8f, 0x49, 0xef, 0xd7, 0x36, 0xa9, 0x88, 0x77, 0x5c, 0x54, 0xf9, 0x56,
928 0x68, 0x76, 0x46, 0xea, 0xab, 0x07,
929 ]),
930 internal_ovk: [
931 0x9d, 0xc4, 0x77, 0xfe, 0x1e, 0x7d, 0x28, 0x29, 0x13, 0xf6, 0x51, 0x65, 0x4d,
932 0x39, 0x85, 0xf0, 0x9d, 0x53, 0xc2, 0xd3, 0xb5, 0x76, 0x3d, 0x7a, 0x72, 0x3b,
933 0xcb, 0xd6, 0xee, 0x05, 0x3d, 0x5a,
934 ],
935 internal_dk: [
936 0x40, 0xdd, 0xc5, 0x6e, 0x69, 0x75, 0x13, 0x8c, 0x08, 0x39, 0xe5, 0x80, 0xb5,
937 0x4d, 0x6d, 0x99, 0x9d, 0xc6, 0x16, 0x84, 0x3c, 0xfe, 0x04, 0x1e, 0x8f, 0x38,
938 0x8b, 0x12, 0x4e, 0xf7, 0xb5, 0xed,
939 ],
940 internal_nk: [
941 0xa3, 0x83, 0x1a, 0x5c, 0x69, 0x33, 0xf8, 0xec, 0x6a, 0xa5, 0xce, 0x31, 0x6c,
942 0x50, 0x8b, 0x79, 0x91, 0xcd, 0x94, 0xd3, 0xbd, 0xb7, 0x00, 0xa1, 0xc4, 0x27,
943 0xa6, 0xae, 0x15, 0xe7, 0x2f, 0xb5,
944 ],
945 internal_ivk: [
946 0x79, 0x05, 0x77, 0x32, 0x1c, 0x51, 0x18, 0x04, 0x63, 0x6e, 0xe6, 0xba, 0xa4,
947 0xee, 0xa7, 0x79, 0xb4, 0xa4, 0x6a, 0x5a, 0x12, 0xf8, 0x5d, 0x36, 0x50, 0x74,
948 0xa0, 0x9d, 0x05, 0x4f, 0x34, 0x01,
949 ],
950 internal_xsk: Some([
951 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x94, 0x7c, 0x4b,
952 0x03, 0xbf, 0x72, 0xa3, 0x7a, 0xb4, 0x4f, 0x72, 0x27, 0x6d, 0x1c, 0xf3, 0xfd,
953 0xcd, 0x7e, 0xbf, 0x3e, 0x73, 0x34, 0x8b, 0x7e, 0x55, 0x0d, 0x75, 0x20, 0x18,
954 0x66, 0x8e, 0xb6, 0xc0, 0x0c, 0x93, 0xd3, 0x60, 0x32, 0xb9, 0xa2, 0x68, 0xe9,
955 0x9e, 0x86, 0xa8, 0x60, 0x77, 0x65, 0x60, 0xbf, 0x0e, 0x83, 0xc1, 0xa1, 0x0b,
956 0x51, 0xf6, 0x07, 0xc9, 0x54, 0x74, 0x25, 0x06, 0x51, 0x12, 0x33, 0x63, 0x6b,
957 0x95, 0xfd, 0x0a, 0xfb, 0x6b, 0xf8, 0x19, 0x3a, 0x7d, 0x8f, 0x49, 0xef, 0xd7,
958 0x36, 0xa9, 0x88, 0x77, 0x5c, 0x54, 0xf9, 0x56, 0x68, 0x76, 0x46, 0xea, 0xab,
959 0x07, 0x9d, 0xc4, 0x77, 0xfe, 0x1e, 0x7d, 0x28, 0x29, 0x13, 0xf6, 0x51, 0x65,
960 0x4d, 0x39, 0x85, 0xf0, 0x9d, 0x53, 0xc2, 0xd3, 0xb5, 0x76, 0x3d, 0x7a, 0x72,
961 0x3b, 0xcb, 0xd6, 0xee, 0x05, 0x3d, 0x5a, 0x40, 0xdd, 0xc5, 0x6e, 0x69, 0x75,
962 0x13, 0x8c, 0x08, 0x39, 0xe5, 0x80, 0xb5, 0x4d, 0x6d, 0x99, 0x9d, 0xc6, 0x16,
963 0x84, 0x3c, 0xfe, 0x04, 0x1e, 0x8f, 0x38, 0x8b, 0x12, 0x4e, 0xf7, 0xb5, 0xed,
964 ]),
965 internal_xfvk: [
966 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x94, 0x7c, 0x4b,
967 0x03, 0xbf, 0x72, 0xa3, 0x7a, 0xb4, 0x4f, 0x72, 0x27, 0x6d, 0x1c, 0xf3, 0xfd,
968 0xcd, 0x7e, 0xbf, 0x3e, 0x73, 0x34, 0x8b, 0x7e, 0x55, 0x0d, 0x75, 0x20, 0x18,
969 0x66, 0x8e, 0x93, 0x44, 0x2e, 0x5f, 0xef, 0xfb, 0xff, 0x16, 0xe7, 0x21, 0x72,
970 0x02, 0xdc, 0x73, 0x06, 0x72, 0x9f, 0xff, 0xfe, 0x85, 0xaf, 0x56, 0x83, 0xbc,
971 0xe2, 0x64, 0x2e, 0x3e, 0xeb, 0x5d, 0x38, 0x71, 0xa3, 0x83, 0x1a, 0x5c, 0x69,
972 0x33, 0xf8, 0xec, 0x6a, 0xa5, 0xce, 0x31, 0x6c, 0x50, 0x8b, 0x79, 0x91, 0xcd,
973 0x94, 0xd3, 0xbd, 0xb7, 0x00, 0xa1, 0xc4, 0x27, 0xa6, 0xae, 0x15, 0xe7, 0x2f,
974 0xb5, 0x9d, 0xc4, 0x77, 0xfe, 0x1e, 0x7d, 0x28, 0x29, 0x13, 0xf6, 0x51, 0x65,
975 0x4d, 0x39, 0x85, 0xf0, 0x9d, 0x53, 0xc2, 0xd3, 0xb5, 0x76, 0x3d, 0x7a, 0x72,
976 0x3b, 0xcb, 0xd6, 0xee, 0x05, 0x3d, 0x5a, 0x40, 0xdd, 0xc5, 0x6e, 0x69, 0x75,
977 0x13, 0x8c, 0x08, 0x39, 0xe5, 0x80, 0xb5, 0x4d, 0x6d, 0x99, 0x9d, 0xc6, 0x16,
978 0x84, 0x3c, 0xfe, 0x04, 0x1e, 0x8f, 0x38, 0x8b, 0x12, 0x4e, 0xf7, 0xb5, 0xed,
979 ],
980 internal_fp: [
981 0x82, 0x64, 0xed, 0xec, 0x63, 0xb1, 0x55, 0x00, 0x1d, 0x84, 0x96, 0x68, 0x5c,
982 0xc7, 0xc2, 0x1e, 0xa9, 0x57, 0xc6, 0xf5, 0x91, 0x09, 0x0a, 0x1c, 0x20, 0xe5,
983 0x2a, 0x41, 0x89, 0xb8, 0xbb, 0x96,
984 ],
985 },
986 TestVector {
987 ask: Some([
988 0x28, 0x2b, 0xc1, 0x97, 0xa5, 0x16, 0x28, 0x7c, 0x8e, 0xa8, 0xf6, 0x8c, 0x42,
989 0x4a, 0xba, 0xd3, 0x02, 0xb4, 0x5c, 0xdf, 0x95, 0x40, 0x79, 0x61, 0xd7, 0xb8,
990 0xb4, 0x55, 0x26, 0x7a, 0x35, 0x0c,
991 ]),
992 nsk: Some([
993 0xe7, 0xa3, 0x29, 0x88, 0xfd, 0xca, 0x1e, 0xfc, 0xd6, 0xd1, 0xc4, 0xc5, 0x62,
994 0xe6, 0x29, 0xc2, 0xe9, 0x6b, 0x2c, 0x3f, 0x7e, 0xda, 0x04, 0xac, 0x4e, 0xfd,
995 0x18, 0x10, 0xff, 0x6b, 0xba, 0x01,
996 ]),
997 ovk: [
998 0x5f, 0x13, 0x81, 0xfc, 0x88, 0x86, 0xda, 0x6a, 0x02, 0xdf, 0xfe, 0xef, 0xcf,
999 0x50, 0x3c, 0x40, 0xfa, 0x8f, 0x5a, 0x36, 0xf7, 0xa7, 0x14, 0x2f, 0xd8, 0x1b,
1000 0x55, 0x18, 0xc5, 0xa4, 0x74, 0x74,
1001 ],
1002 dk: [
1003 0xe0, 0x4d, 0xe8, 0x32, 0xa2, 0xd7, 0x91, 0xec, 0x12, 0x9a, 0xb9, 0x00, 0x2b,
1004 0x91, 0xc9, 0xe9, 0xcd, 0xee, 0xd7, 0x92, 0x41, 0xa7, 0xc4, 0x96, 0x0e, 0x51,
1005 0x78, 0xd8, 0x70, 0xc1, 0xb4, 0xdc,
1006 ],
1007 c: [
1008 0x01, 0x47, 0x11, 0x0c, 0x69, 0x1a, 0x03, 0xb9, 0xd9, 0xf0, 0xba, 0x90, 0x05,
1009 0xc5, 0xe7, 0x90, 0xa5, 0x95, 0xb7, 0xf0, 0x4e, 0x33, 0x29, 0xd2, 0xfa, 0x43,
1010 0x8a, 0x67, 0x05, 0xda, 0xbc, 0xe6,
1011 ],
1012 ak: [
1013 0xdc, 0x14, 0xb5, 0x14, 0xd3, 0xa9, 0x25, 0x94, 0xc2, 0x19, 0x25, 0xaf, 0x2f,
1014 0x77, 0x65, 0xa5, 0x47, 0xb3, 0x0e, 0x73, 0xfa, 0x7b, 0x70, 0x0e, 0xa1, 0xbf,
1015 0xf2, 0xe5, 0xef, 0xaa, 0xa8, 0x8b,
1016 ],
1017 nk: [
1018 0x61, 0x52, 0xeb, 0x7f, 0xdb, 0x25, 0x27, 0x79, 0xdd, 0xcb, 0x95, 0xd2, 0x17,
1019 0xea, 0x4b, 0x6f, 0xd3, 0x40, 0x36, 0xe9, 0xad, 0xad, 0xb3, 0xb5, 0xc9, 0xcb,
1020 0xec, 0xeb, 0x41, 0xba, 0x45, 0x2a,
1021 ],
1022 ivk: [
1023 0x15, 0x5a, 0x8e, 0xe2, 0x05, 0xd3, 0x87, 0x2d, 0x12, 0xf8, 0xa3, 0xe6, 0x39,
1024 0x91, 0x46, 0x33, 0xc2, 0x3c, 0xde, 0x1f, 0x30, 0xed, 0x50, 0x51, 0xe5, 0x21,
1025 0x30, 0xb1, 0xd0, 0x10, 0x4c, 0x06,
1026 ],
1027 xsk: Some([
1028 0x01, 0x14, 0xc2, 0x71, 0x3a, 0x01, 0x00, 0x00, 0x00, 0x01, 0x47, 0x11, 0x0c,
1029 0x69, 0x1a, 0x03, 0xb9, 0xd9, 0xf0, 0xba, 0x90, 0x05, 0xc5, 0xe7, 0x90, 0xa5,
1030 0x95, 0xb7, 0xf0, 0x4e, 0x33, 0x29, 0xd2, 0xfa, 0x43, 0x8a, 0x67, 0x05, 0xda,
1031 0xbc, 0xe6, 0x28, 0x2b, 0xc1, 0x97, 0xa5, 0x16, 0x28, 0x7c, 0x8e, 0xa8, 0xf6,
1032 0x8c, 0x42, 0x4a, 0xba, 0xd3, 0x02, 0xb4, 0x5c, 0xdf, 0x95, 0x40, 0x79, 0x61,
1033 0xd7, 0xb8, 0xb4, 0x55, 0x26, 0x7a, 0x35, 0x0c, 0xe7, 0xa3, 0x29, 0x88, 0xfd,
1034 0xca, 0x1e, 0xfc, 0xd6, 0xd1, 0xc4, 0xc5, 0x62, 0xe6, 0x29, 0xc2, 0xe9, 0x6b,
1035 0x2c, 0x3f, 0x7e, 0xda, 0x04, 0xac, 0x4e, 0xfd, 0x18, 0x10, 0xff, 0x6b, 0xba,
1036 0x01, 0x5f, 0x13, 0x81, 0xfc, 0x88, 0x86, 0xda, 0x6a, 0x02, 0xdf, 0xfe, 0xef,
1037 0xcf, 0x50, 0x3c, 0x40, 0xfa, 0x8f, 0x5a, 0x36, 0xf7, 0xa7, 0x14, 0x2f, 0xd8,
1038 0x1b, 0x55, 0x18, 0xc5, 0xa4, 0x74, 0x74, 0xe0, 0x4d, 0xe8, 0x32, 0xa2, 0xd7,
1039 0x91, 0xec, 0x12, 0x9a, 0xb9, 0x00, 0x2b, 0x91, 0xc9, 0xe9, 0xcd, 0xee, 0xd7,
1040 0x92, 0x41, 0xa7, 0xc4, 0x96, 0x0e, 0x51, 0x78, 0xd8, 0x70, 0xc1, 0xb4, 0xdc,
1041 ]),
1042 xfvk: [
1043 0x01, 0x14, 0xc2, 0x71, 0x3a, 0x01, 0x00, 0x00, 0x00, 0x01, 0x47, 0x11, 0x0c,
1044 0x69, 0x1a, 0x03, 0xb9, 0xd9, 0xf0, 0xba, 0x90, 0x05, 0xc5, 0xe7, 0x90, 0xa5,
1045 0x95, 0xb7, 0xf0, 0x4e, 0x33, 0x29, 0xd2, 0xfa, 0x43, 0x8a, 0x67, 0x05, 0xda,
1046 0xbc, 0xe6, 0xdc, 0x14, 0xb5, 0x14, 0xd3, 0xa9, 0x25, 0x94, 0xc2, 0x19, 0x25,
1047 0xaf, 0x2f, 0x77, 0x65, 0xa5, 0x47, 0xb3, 0x0e, 0x73, 0xfa, 0x7b, 0x70, 0x0e,
1048 0xa1, 0xbf, 0xf2, 0xe5, 0xef, 0xaa, 0xa8, 0x8b, 0x61, 0x52, 0xeb, 0x7f, 0xdb,
1049 0x25, 0x27, 0x79, 0xdd, 0xcb, 0x95, 0xd2, 0x17, 0xea, 0x4b, 0x6f, 0xd3, 0x40,
1050 0x36, 0xe9, 0xad, 0xad, 0xb3, 0xb5, 0xc9, 0xcb, 0xec, 0xeb, 0x41, 0xba, 0x45,
1051 0x2a, 0x5f, 0x13, 0x81, 0xfc, 0x88, 0x86, 0xda, 0x6a, 0x02, 0xdf, 0xfe, 0xef,
1052 0xcf, 0x50, 0x3c, 0x40, 0xfa, 0x8f, 0x5a, 0x36, 0xf7, 0xa7, 0x14, 0x2f, 0xd8,
1053 0x1b, 0x55, 0x18, 0xc5, 0xa4, 0x74, 0x74, 0xe0, 0x4d, 0xe8, 0x32, 0xa2, 0xd7,
1054 0x91, 0xec, 0x12, 0x9a, 0xb9, 0x00, 0x2b, 0x91, 0xc9, 0xe9, 0xcd, 0xee, 0xd7,
1055 0x92, 0x41, 0xa7, 0xc4, 0x96, 0x0e, 0x51, 0x78, 0xd8, 0x70, 0xc1, 0xb4, 0xdc,
1056 ],
1057 fp: [
1058 0xdb, 0x99, 0x9e, 0x07, 0x1d, 0xcb, 0x58, 0xdd, 0x93, 0x02, 0x9a, 0xe6, 0x97,
1059 0x05, 0x3e, 0x90, 0xed, 0xb3, 0x59, 0xd1, 0xa1, 0xb7, 0xa1, 0x25, 0x16, 0x7e,
1060 0xfb, 0xe9, 0x28, 0x06, 0x84, 0x23,
1061 ],
1062 d0: Some([
1063 0x8b, 0x41, 0x38, 0x32, 0x0d, 0xfa, 0xfd, 0x7b, 0x39, 0x97, 0x81,
1064 ]),
1065 d1: None,
1066 d2: Some([
1067 0x57, 0x49, 0xa1, 0x33, 0x52, 0xbc, 0x22, 0x3e, 0x30, 0x80, 0x78,
1068 ]),
1069 dmax: Some([
1070 0x63, 0x89, 0x57, 0x4c, 0xde, 0x0f, 0xbb, 0xc6, 0x36, 0x81, 0x31,
1071 ]),
1072 internal_nsk: Some([
1073 0x74, 0x92, 0x9f, 0x79, 0x0c, 0x11, 0xdc, 0xab, 0x3a, 0x2f, 0x93, 0x12, 0x35,
1074 0xcd, 0xb2, 0x67, 0xf5, 0xa3, 0x1b, 0x9f, 0x13, 0x9f, 0x2c, 0x9f, 0xd8, 0x16,
1075 0xb0, 0x44, 0x4f, 0xb8, 0x05, 0x05,
1076 ]),
1077 internal_ovk: [
1078 0x0c, 0xd4, 0xd7, 0xc5, 0xcc, 0x7f, 0x53, 0x4b, 0x96, 0xd2, 0x41, 0x82, 0xa3,
1079 0x14, 0x65, 0xb4, 0x78, 0x11, 0x05, 0x48, 0x9c, 0xd1, 0x0d, 0x50, 0x0c, 0xf5,
1080 0x29, 0x5a, 0x6f, 0xd8, 0x18, 0xcc,
1081 ],
1082 internal_dk: [
1083 0xd2, 0x78, 0xb7, 0x2c, 0x62, 0x1d, 0x19, 0xcb, 0x00, 0xf9, 0x70, 0x07, 0x9c,
1084 0x89, 0x22, 0x76, 0x1c, 0xdd, 0x3a, 0xe7, 0xf2, 0x7b, 0x18, 0x47, 0xc5, 0x53,
1085 0x60, 0xdb, 0xeb, 0xf6, 0x54, 0x92,
1086 ],
1087 internal_nk: [
1088 0x2b, 0x5c, 0x78, 0xa2, 0xfb, 0xa5, 0x01, 0x9c, 0x15, 0xa7, 0x51, 0x50, 0x2b,
1089 0xa9, 0x91, 0x6f, 0xae, 0xda, 0xe1, 0xfc, 0x14, 0xdc, 0x81, 0xb0, 0xb8, 0x35,
1090 0xf2, 0xbf, 0x95, 0xc0, 0x68, 0xe8,
1091 ],
1092 internal_ivk: [
1093 0xdf, 0x44, 0x54, 0xa6, 0x76, 0xd1, 0xde, 0x32, 0xe2, 0x0a, 0xe6, 0x28, 0x7a,
1094 0x92, 0xfa, 0xfe, 0xfb, 0xbb, 0x3e, 0x54, 0xb5, 0x88, 0xc8, 0xda, 0x28, 0x07,
1095 0xec, 0x43, 0x68, 0x2c, 0x85, 0x00,
1096 ],
1097 internal_xsk: Some([
1098 0x01, 0x14, 0xc2, 0x71, 0x3a, 0x01, 0x00, 0x00, 0x00, 0x01, 0x47, 0x11, 0x0c,
1099 0x69, 0x1a, 0x03, 0xb9, 0xd9, 0xf0, 0xba, 0x90, 0x05, 0xc5, 0xe7, 0x90, 0xa5,
1100 0x95, 0xb7, 0xf0, 0x4e, 0x33, 0x29, 0xd2, 0xfa, 0x43, 0x8a, 0x67, 0x05, 0xda,
1101 0xbc, 0xe6, 0x28, 0x2b, 0xc1, 0x97, 0xa5, 0x16, 0x28, 0x7c, 0x8e, 0xa8, 0xf6,
1102 0x8c, 0x42, 0x4a, 0xba, 0xd3, 0x02, 0xb4, 0x5c, 0xdf, 0x95, 0x40, 0x79, 0x61,
1103 0xd7, 0xb8, 0xb4, 0x55, 0x26, 0x7a, 0x35, 0x0c, 0x74, 0x92, 0x9f, 0x79, 0x0c,
1104 0x11, 0xdc, 0xab, 0x3a, 0x2f, 0x93, 0x12, 0x35, 0xcd, 0xb2, 0x67, 0xf5, 0xa3,
1105 0x1b, 0x9f, 0x13, 0x9f, 0x2c, 0x9f, 0xd8, 0x16, 0xb0, 0x44, 0x4f, 0xb8, 0x05,
1106 0x05, 0x0c, 0xd4, 0xd7, 0xc5, 0xcc, 0x7f, 0x53, 0x4b, 0x96, 0xd2, 0x41, 0x82,
1107 0xa3, 0x14, 0x65, 0xb4, 0x78, 0x11, 0x05, 0x48, 0x9c, 0xd1, 0x0d, 0x50, 0x0c,
1108 0xf5, 0x29, 0x5a, 0x6f, 0xd8, 0x18, 0xcc, 0xd2, 0x78, 0xb7, 0x2c, 0x62, 0x1d,
1109 0x19, 0xcb, 0x00, 0xf9, 0x70, 0x07, 0x9c, 0x89, 0x22, 0x76, 0x1c, 0xdd, 0x3a,
1110 0xe7, 0xf2, 0x7b, 0x18, 0x47, 0xc5, 0x53, 0x60, 0xdb, 0xeb, 0xf6, 0x54, 0x92,
1111 ]),
1112 internal_xfvk: [
1113 0x01, 0x14, 0xc2, 0x71, 0x3a, 0x01, 0x00, 0x00, 0x00, 0x01, 0x47, 0x11, 0x0c,
1114 0x69, 0x1a, 0x03, 0xb9, 0xd9, 0xf0, 0xba, 0x90, 0x05, 0xc5, 0xe7, 0x90, 0xa5,
1115 0x95, 0xb7, 0xf0, 0x4e, 0x33, 0x29, 0xd2, 0xfa, 0x43, 0x8a, 0x67, 0x05, 0xda,
1116 0xbc, 0xe6, 0xdc, 0x14, 0xb5, 0x14, 0xd3, 0xa9, 0x25, 0x94, 0xc2, 0x19, 0x25,
1117 0xaf, 0x2f, 0x77, 0x65, 0xa5, 0x47, 0xb3, 0x0e, 0x73, 0xfa, 0x7b, 0x70, 0x0e,
1118 0xa1, 0xbf, 0xf2, 0xe5, 0xef, 0xaa, 0xa8, 0x8b, 0x2b, 0x5c, 0x78, 0xa2, 0xfb,
1119 0xa5, 0x01, 0x9c, 0x15, 0xa7, 0x51, 0x50, 0x2b, 0xa9, 0x91, 0x6f, 0xae, 0xda,
1120 0xe1, 0xfc, 0x14, 0xdc, 0x81, 0xb0, 0xb8, 0x35, 0xf2, 0xbf, 0x95, 0xc0, 0x68,
1121 0xe8, 0x0c, 0xd4, 0xd7, 0xc5, 0xcc, 0x7f, 0x53, 0x4b, 0x96, 0xd2, 0x41, 0x82,
1122 0xa3, 0x14, 0x65, 0xb4, 0x78, 0x11, 0x05, 0x48, 0x9c, 0xd1, 0x0d, 0x50, 0x0c,
1123 0xf5, 0x29, 0x5a, 0x6f, 0xd8, 0x18, 0xcc, 0xd2, 0x78, 0xb7, 0x2c, 0x62, 0x1d,
1124 0x19, 0xcb, 0x00, 0xf9, 0x70, 0x07, 0x9c, 0x89, 0x22, 0x76, 0x1c, 0xdd, 0x3a,
1125 0xe7, 0xf2, 0x7b, 0x18, 0x47, 0xc5, 0x53, 0x60, 0xdb, 0xeb, 0xf6, 0x54, 0x92,
1126 ],
1127 internal_fp: [
1128 0x0d, 0xe5, 0x83, 0xca, 0x50, 0x2b, 0x1c, 0x4b, 0x87, 0xca, 0xc8, 0xc9, 0x78,
1129 0x6c, 0x61, 0x9b, 0x79, 0xe1, 0x69, 0xb4, 0x15, 0x61, 0xf2, 0x44, 0xee, 0xec,
1130 0x86, 0x86, 0xb8, 0xdb, 0xc4, 0xe1,
1131 ],
1132 },
1133 TestVector {
1134 ask: Some([
1135 0x8b, 0xe8, 0x11, 0x3c, 0xee, 0x34, 0x13, 0xa7, 0x1f, 0x82, 0xc4, 0x1f, 0xc8,
1136 0xda, 0x51, 0x7b, 0xe1, 0x34, 0x04, 0x98, 0x32, 0xe6, 0x82, 0x5c, 0x92, 0xda,
1137 0x6b, 0x84, 0xfe, 0xe4, 0xc6, 0x0d,
1138 ]),
1139 nsk: Some([
1140 0x37, 0x78, 0x05, 0x9d, 0xc5, 0x69, 0xe7, 0xd0, 0xd3, 0x23, 0x91, 0x57, 0x3f,
1141 0x95, 0x1b, 0xbd, 0xe9, 0x2f, 0xc6, 0xb9, 0xcf, 0x61, 0x47, 0x73, 0x66, 0x1c,
1142 0x5c, 0x27, 0x3a, 0xa6, 0x99, 0x0c,
1143 ]),
1144 ovk: [
1145 0xcf, 0x81, 0x18, 0x2e, 0x96, 0x22, 0x3c, 0x02, 0x8c, 0xe3, 0xd6, 0xeb, 0x47,
1146 0x94, 0xd3, 0x11, 0x3b, 0x95, 0x06, 0x9d, 0x14, 0xc5, 0x75, 0x88, 0xe1, 0x93,
1147 0xb6, 0x5e, 0xfc, 0x28, 0x13, 0xbc,
1148 ],
1149 dk: [
1150 0xa3, 0xed, 0xa1, 0x9f, 0x9e, 0xff, 0x46, 0xca, 0x12, 0xdf, 0xa1, 0xbf, 0x10,
1151 0x37, 0x1b, 0x48, 0xd1, 0xb4, 0xa4, 0x0c, 0x4d, 0x05, 0xa0, 0xd8, 0xdc, 0xe0,
1152 0xe7, 0xdc, 0x62, 0xb0, 0x7b, 0x37,
1153 ],
1154 c: [
1155 0x97, 0xce, 0x15, 0xf4, 0xed, 0x1b, 0x97, 0x39, 0xb0, 0x26, 0x2a, 0x46, 0x3b,
1156 0xcb, 0x3d, 0xc9, 0xb3, 0xbd, 0x23, 0x23, 0xa9, 0xba, 0xa4, 0x41, 0xca, 0x42,
1157 0x77, 0x73, 0x83, 0xa8, 0xd4, 0x35,
1158 ],
1159 ak: [
1160 0xa6, 0xc5, 0x92, 0x5a, 0x0f, 0x85, 0xfa, 0x4f, 0x1e, 0x40, 0x5e, 0x3a, 0x49,
1161 0x70, 0xd0, 0xc4, 0xa4, 0xb4, 0x81, 0x44, 0x38, 0xf4, 0xe9, 0xd4, 0x52, 0x0e,
1162 0x20, 0xf7, 0xfd, 0xcf, 0x38, 0x41,
1163 ],
1164 nk: [
1165 0x30, 0x4e, 0x30, 0x59, 0x16, 0x21, 0x6b, 0xeb, 0x7b, 0x65, 0x4d, 0x8a, 0xae,
1166 0x50, 0xec, 0xd1, 0x88, 0xfc, 0xb3, 0x84, 0xbc, 0x36, 0xc0, 0x0c, 0x66, 0x4f,
1167 0x30, 0x77, 0x25, 0xe2, 0xee, 0x11,
1168 ],
1169 ivk: [
1170 0xa2, 0xa1, 0x3c, 0x1e, 0x38, 0xb4, 0x59, 0x84, 0x44, 0x58, 0x03, 0xe4, 0x30,
1171 0xa6, 0x83, 0xc9, 0x0b, 0xb2, 0xe1, 0x4d, 0x4c, 0x86, 0x92, 0xff, 0x25, 0x3a,
1172 0x64, 0x84, 0xdd, 0x9b, 0xb5, 0x04,
1173 ],
1174 xsk: Some([
1175 0x02, 0xdb, 0x99, 0x9e, 0x07, 0x02, 0x00, 0x00, 0x80, 0x97, 0xce, 0x15, 0xf4,
1176 0xed, 0x1b, 0x97, 0x39, 0xb0, 0x26, 0x2a, 0x46, 0x3b, 0xcb, 0x3d, 0xc9, 0xb3,
1177 0xbd, 0x23, 0x23, 0xa9, 0xba, 0xa4, 0x41, 0xca, 0x42, 0x77, 0x73, 0x83, 0xa8,
1178 0xd4, 0x35, 0x8b, 0xe8, 0x11, 0x3c, 0xee, 0x34, 0x13, 0xa7, 0x1f, 0x82, 0xc4,
1179 0x1f, 0xc8, 0xda, 0x51, 0x7b, 0xe1, 0x34, 0x04, 0x98, 0x32, 0xe6, 0x82, 0x5c,
1180 0x92, 0xda, 0x6b, 0x84, 0xfe, 0xe4, 0xc6, 0x0d, 0x37, 0x78, 0x05, 0x9d, 0xc5,
1181 0x69, 0xe7, 0xd0, 0xd3, 0x23, 0x91, 0x57, 0x3f, 0x95, 0x1b, 0xbd, 0xe9, 0x2f,
1182 0xc6, 0xb9, 0xcf, 0x61, 0x47, 0x73, 0x66, 0x1c, 0x5c, 0x27, 0x3a, 0xa6, 0x99,
1183 0x0c, 0xcf, 0x81, 0x18, 0x2e, 0x96, 0x22, 0x3c, 0x02, 0x8c, 0xe3, 0xd6, 0xeb,
1184 0x47, 0x94, 0xd3, 0x11, 0x3b, 0x95, 0x06, 0x9d, 0x14, 0xc5, 0x75, 0x88, 0xe1,
1185 0x93, 0xb6, 0x5e, 0xfc, 0x28, 0x13, 0xbc, 0xa3, 0xed, 0xa1, 0x9f, 0x9e, 0xff,
1186 0x46, 0xca, 0x12, 0xdf, 0xa1, 0xbf, 0x10, 0x37, 0x1b, 0x48, 0xd1, 0xb4, 0xa4,
1187 0x0c, 0x4d, 0x05, 0xa0, 0xd8, 0xdc, 0xe0, 0xe7, 0xdc, 0x62, 0xb0, 0x7b, 0x37,
1188 ]),
1189 xfvk: [
1190 0x02, 0xdb, 0x99, 0x9e, 0x07, 0x02, 0x00, 0x00, 0x80, 0x97, 0xce, 0x15, 0xf4,
1191 0xed, 0x1b, 0x97, 0x39, 0xb0, 0x26, 0x2a, 0x46, 0x3b, 0xcb, 0x3d, 0xc9, 0xb3,
1192 0xbd, 0x23, 0x23, 0xa9, 0xba, 0xa4, 0x41, 0xca, 0x42, 0x77, 0x73, 0x83, 0xa8,
1193 0xd4, 0x35, 0xa6, 0xc5, 0x92, 0x5a, 0x0f, 0x85, 0xfa, 0x4f, 0x1e, 0x40, 0x5e,
1194 0x3a, 0x49, 0x70, 0xd0, 0xc4, 0xa4, 0xb4, 0x81, 0x44, 0x38, 0xf4, 0xe9, 0xd4,
1195 0x52, 0x0e, 0x20, 0xf7, 0xfd, 0xcf, 0x38, 0x41, 0x30, 0x4e, 0x30, 0x59, 0x16,
1196 0x21, 0x6b, 0xeb, 0x7b, 0x65, 0x4d, 0x8a, 0xae, 0x50, 0xec, 0xd1, 0x88, 0xfc,
1197 0xb3, 0x84, 0xbc, 0x36, 0xc0, 0x0c, 0x66, 0x4f, 0x30, 0x77, 0x25, 0xe2, 0xee,
1198 0x11, 0xcf, 0x81, 0x18, 0x2e, 0x96, 0x22, 0x3c, 0x02, 0x8c, 0xe3, 0xd6, 0xeb,
1199 0x47, 0x94, 0xd3, 0x11, 0x3b, 0x95, 0x06, 0x9d, 0x14, 0xc5, 0x75, 0x88, 0xe1,
1200 0x93, 0xb6, 0x5e, 0xfc, 0x28, 0x13, 0xbc, 0xa3, 0xed, 0xa1, 0x9f, 0x9e, 0xff,
1201 0x46, 0xca, 0x12, 0xdf, 0xa1, 0xbf, 0x10, 0x37, 0x1b, 0x48, 0xd1, 0xb4, 0xa4,
1202 0x0c, 0x4d, 0x05, 0xa0, 0xd8, 0xdc, 0xe0, 0xe7, 0xdc, 0x62, 0xb0, 0x7b, 0x37,
1203 ],
1204 fp: [
1205 0x48, 0xc1, 0x83, 0x75, 0x7b, 0x5d, 0xa6, 0x61, 0x2a, 0x81, 0xb3, 0x0e, 0x40,
1206 0xb4, 0xac, 0xaa, 0x2d, 0x9e, 0x73, 0x95, 0x12, 0xe1, 0xd2, 0xd0, 0x01, 0x0e,
1207 0x92, 0xa7, 0xf7, 0xf2, 0xfc, 0xdf,
1208 ],
1209 d0: Some([
1210 0xe8, 0xd0, 0x37, 0x93, 0xcd, 0xd2, 0xba, 0xcc, 0x9c, 0x70, 0x41,
1211 ]),
1212 d1: Some([
1213 0x02, 0x0a, 0x7a, 0x6b, 0x0b, 0xf8, 0x4d, 0x3e, 0x89, 0x9f, 0x68,
1214 ]),
1215 d2: None,
1216 dmax: None,
1217 internal_nsk: Some([
1218 0x34, 0x78, 0x65, 0xac, 0xf4, 0x7e, 0x50, 0x45, 0x38, 0xf5, 0xef, 0x8b, 0x04,
1219 0x70, 0x20, 0x80, 0xe6, 0x09, 0x1c, 0xda, 0x57, 0x97, 0xcd, 0x7d, 0x23, 0x5a,
1220 0x54, 0x6e, 0xb1, 0x0f, 0x55, 0x08,
1221 ]),
1222 internal_ovk: [
1223 0xdd, 0xba, 0xc2, 0xa4, 0x93, 0xf5, 0x3c, 0x3b, 0x09, 0x33, 0xd9, 0x13, 0xde,
1224 0xf8, 0x88, 0x48, 0x65, 0x4c, 0x08, 0x7c, 0x12, 0x60, 0x9d, 0xf0, 0x1b, 0xaf,
1225 0x94, 0x05, 0xce, 0x78, 0x04, 0xfd,
1226 ],
1227 internal_dk: [
1228 0x60, 0x2c, 0xd3, 0x17, 0xb7, 0xce, 0xa1, 0x1e, 0x8c, 0xc7, 0xae, 0x2e, 0xa4,
1229 0x05, 0xb4, 0x0d, 0x46, 0xb1, 0x59, 0x2a, 0x30, 0xf0, 0xcb, 0x6e, 0x8c, 0x4f,
1230 0x17, 0xd7, 0xf7, 0xc4, 0x7f, 0xeb,
1231 ],
1232 internal_nk: [
1233 0xf9, 0x12, 0x87, 0xc0, 0x6e, 0x30, 0xb6, 0x5e, 0xa1, 0xbd, 0xb7, 0x16, 0xb2,
1234 0x31, 0xde, 0x67, 0x78, 0xa5, 0xd8, 0x0e, 0xe5, 0xcd, 0x9c, 0x06, 0x0d, 0x1a,
1235 0xba, 0xca, 0xe0, 0xaa, 0xe2, 0x3b,
1236 ],
1237 internal_ivk: [
1238 0x1d, 0x59, 0xea, 0x20, 0x17, 0x88, 0x18, 0x64, 0xd2, 0x4e, 0xad, 0xb5, 0xcf,
1239 0x34, 0x68, 0xa4, 0x1a, 0x1b, 0x2a, 0xaa, 0x0d, 0x1b, 0x3a, 0x72, 0xc6, 0xda,
1240 0x9c, 0xe6, 0x50, 0x2a, 0x0a, 0x05,
1241 ],
1242 internal_xsk: Some([
1243 0x02, 0xdb, 0x99, 0x9e, 0x07, 0x02, 0x00, 0x00, 0x80, 0x97, 0xce, 0x15, 0xf4,
1244 0xed, 0x1b, 0x97, 0x39, 0xb0, 0x26, 0x2a, 0x46, 0x3b, 0xcb, 0x3d, 0xc9, 0xb3,
1245 0xbd, 0x23, 0x23, 0xa9, 0xba, 0xa4, 0x41, 0xca, 0x42, 0x77, 0x73, 0x83, 0xa8,
1246 0xd4, 0x35, 0x8b, 0xe8, 0x11, 0x3c, 0xee, 0x34, 0x13, 0xa7, 0x1f, 0x82, 0xc4,
1247 0x1f, 0xc8, 0xda, 0x51, 0x7b, 0xe1, 0x34, 0x04, 0x98, 0x32, 0xe6, 0x82, 0x5c,
1248 0x92, 0xda, 0x6b, 0x84, 0xfe, 0xe4, 0xc6, 0x0d, 0x34, 0x78, 0x65, 0xac, 0xf4,
1249 0x7e, 0x50, 0x45, 0x38, 0xf5, 0xef, 0x8b, 0x04, 0x70, 0x20, 0x80, 0xe6, 0x09,
1250 0x1c, 0xda, 0x57, 0x97, 0xcd, 0x7d, 0x23, 0x5a, 0x54, 0x6e, 0xb1, 0x0f, 0x55,
1251 0x08, 0xdd, 0xba, 0xc2, 0xa4, 0x93, 0xf5, 0x3c, 0x3b, 0x09, 0x33, 0xd9, 0x13,
1252 0xde, 0xf8, 0x88, 0x48, 0x65, 0x4c, 0x08, 0x7c, 0x12, 0x60, 0x9d, 0xf0, 0x1b,
1253 0xaf, 0x94, 0x05, 0xce, 0x78, 0x04, 0xfd, 0x60, 0x2c, 0xd3, 0x17, 0xb7, 0xce,
1254 0xa1, 0x1e, 0x8c, 0xc7, 0xae, 0x2e, 0xa4, 0x05, 0xb4, 0x0d, 0x46, 0xb1, 0x59,
1255 0x2a, 0x30, 0xf0, 0xcb, 0x6e, 0x8c, 0x4f, 0x17, 0xd7, 0xf7, 0xc4, 0x7f, 0xeb,
1256 ]),
1257 internal_xfvk: [
1258 0x02, 0xdb, 0x99, 0x9e, 0x07, 0x02, 0x00, 0x00, 0x80, 0x97, 0xce, 0x15, 0xf4,
1259 0xed, 0x1b, 0x97, 0x39, 0xb0, 0x26, 0x2a, 0x46, 0x3b, 0xcb, 0x3d, 0xc9, 0xb3,
1260 0xbd, 0x23, 0x23, 0xa9, 0xba, 0xa4, 0x41, 0xca, 0x42, 0x77, 0x73, 0x83, 0xa8,
1261 0xd4, 0x35, 0xa6, 0xc5, 0x92, 0x5a, 0x0f, 0x85, 0xfa, 0x4f, 0x1e, 0x40, 0x5e,
1262 0x3a, 0x49, 0x70, 0xd0, 0xc4, 0xa4, 0xb4, 0x81, 0x44, 0x38, 0xf4, 0xe9, 0xd4,
1263 0x52, 0x0e, 0x20, 0xf7, 0xfd, 0xcf, 0x38, 0x41, 0xf9, 0x12, 0x87, 0xc0, 0x6e,
1264 0x30, 0xb6, 0x5e, 0xa1, 0xbd, 0xb7, 0x16, 0xb2, 0x31, 0xde, 0x67, 0x78, 0xa5,
1265 0xd8, 0x0e, 0xe5, 0xcd, 0x9c, 0x06, 0x0d, 0x1a, 0xba, 0xca, 0xe0, 0xaa, 0xe2,
1266 0x3b, 0xdd, 0xba, 0xc2, 0xa4, 0x93, 0xf5, 0x3c, 0x3b, 0x09, 0x33, 0xd9, 0x13,
1267 0xde, 0xf8, 0x88, 0x48, 0x65, 0x4c, 0x08, 0x7c, 0x12, 0x60, 0x9d, 0xf0, 0x1b,
1268 0xaf, 0x94, 0x05, 0xce, 0x78, 0x04, 0xfd, 0x60, 0x2c, 0xd3, 0x17, 0xb7, 0xce,
1269 0xa1, 0x1e, 0x8c, 0xc7, 0xae, 0x2e, 0xa4, 0x05, 0xb4, 0x0d, 0x46, 0xb1, 0x59,
1270 0x2a, 0x30, 0xf0, 0xcb, 0x6e, 0x8c, 0x4f, 0x17, 0xd7, 0xf7, 0xc4, 0x7f, 0xeb,
1271 ],
1272 internal_fp: [
1273 0x30, 0xfe, 0x0d, 0x61, 0x0f, 0x94, 0x7b, 0x2c, 0x26, 0x0e, 0x7b, 0x29, 0xe7,
1274 0x9e, 0x5c, 0x2e, 0x7d, 0x3e, 0x14, 0xab, 0xf9, 0x79, 0xf6, 0x40, 0x6d, 0x07,
1275 0xba, 0xf8, 0xfa, 0xdd, 0xf4, 0x95,
1276 ],
1277 },
1278 TestVector {
1279 ask: None,
1280 nsk: None,
1281 ovk: [
1282 0xcf, 0x81, 0x18, 0x2e, 0x96, 0x22, 0x3c, 0x02, 0x8c, 0xe3, 0xd6, 0xeb, 0x47,
1283 0x94, 0xd3, 0x11, 0x3b, 0x95, 0x06, 0x9d, 0x14, 0xc5, 0x75, 0x88, 0xe1, 0x93,
1284 0xb6, 0x5e, 0xfc, 0x28, 0x13, 0xbc,
1285 ],
1286 dk: [
1287 0xa3, 0xed, 0xa1, 0x9f, 0x9e, 0xff, 0x46, 0xca, 0x12, 0xdf, 0xa1, 0xbf, 0x10,
1288 0x37, 0x1b, 0x48, 0xd1, 0xb4, 0xa4, 0x0c, 0x4d, 0x05, 0xa0, 0xd8, 0xdc, 0xe0,
1289 0xe7, 0xdc, 0x62, 0xb0, 0x7b, 0x37,
1290 ],
1291 c: [
1292 0x97, 0xce, 0x15, 0xf4, 0xed, 0x1b, 0x97, 0x39, 0xb0, 0x26, 0x2a, 0x46, 0x3b,
1293 0xcb, 0x3d, 0xc9, 0xb3, 0xbd, 0x23, 0x23, 0xa9, 0xba, 0xa4, 0x41, 0xca, 0x42,
1294 0x77, 0x73, 0x83, 0xa8, 0xd4, 0x35,
1295 ],
1296 ak: [
1297 0xa6, 0xc5, 0x92, 0x5a, 0x0f, 0x85, 0xfa, 0x4f, 0x1e, 0x40, 0x5e, 0x3a, 0x49,
1298 0x70, 0xd0, 0xc4, 0xa4, 0xb4, 0x81, 0x44, 0x38, 0xf4, 0xe9, 0xd4, 0x52, 0x0e,
1299 0x20, 0xf7, 0xfd, 0xcf, 0x38, 0x41,
1300 ],
1301 nk: [
1302 0x30, 0x4e, 0x30, 0x59, 0x16, 0x21, 0x6b, 0xeb, 0x7b, 0x65, 0x4d, 0x8a, 0xae,
1303 0x50, 0xec, 0xd1, 0x88, 0xfc, 0xb3, 0x84, 0xbc, 0x36, 0xc0, 0x0c, 0x66, 0x4f,
1304 0x30, 0x77, 0x25, 0xe2, 0xee, 0x11,
1305 ],
1306 ivk: [
1307 0xa2, 0xa1, 0x3c, 0x1e, 0x38, 0xb4, 0x59, 0x84, 0x44, 0x58, 0x03, 0xe4, 0x30,
1308 0xa6, 0x83, 0xc9, 0x0b, 0xb2, 0xe1, 0x4d, 0x4c, 0x86, 0x92, 0xff, 0x25, 0x3a,
1309 0x64, 0x84, 0xdd, 0x9b, 0xb5, 0x04,
1310 ],
1311 xsk: None,
1312 xfvk: [
1313 0x02, 0xdb, 0x99, 0x9e, 0x07, 0x02, 0x00, 0x00, 0x80, 0x97, 0xce, 0x15, 0xf4,
1314 0xed, 0x1b, 0x97, 0x39, 0xb0, 0x26, 0x2a, 0x46, 0x3b, 0xcb, 0x3d, 0xc9, 0xb3,
1315 0xbd, 0x23, 0x23, 0xa9, 0xba, 0xa4, 0x41, 0xca, 0x42, 0x77, 0x73, 0x83, 0xa8,
1316 0xd4, 0x35, 0xa6, 0xc5, 0x92, 0x5a, 0x0f, 0x85, 0xfa, 0x4f, 0x1e, 0x40, 0x5e,
1317 0x3a, 0x49, 0x70, 0xd0, 0xc4, 0xa4, 0xb4, 0x81, 0x44, 0x38, 0xf4, 0xe9, 0xd4,
1318 0x52, 0x0e, 0x20, 0xf7, 0xfd, 0xcf, 0x38, 0x41, 0x30, 0x4e, 0x30, 0x59, 0x16,
1319 0x21, 0x6b, 0xeb, 0x7b, 0x65, 0x4d, 0x8a, 0xae, 0x50, 0xec, 0xd1, 0x88, 0xfc,
1320 0xb3, 0x84, 0xbc, 0x36, 0xc0, 0x0c, 0x66, 0x4f, 0x30, 0x77, 0x25, 0xe2, 0xee,
1321 0x11, 0xcf, 0x81, 0x18, 0x2e, 0x96, 0x22, 0x3c, 0x02, 0x8c, 0xe3, 0xd6, 0xeb,
1322 0x47, 0x94, 0xd3, 0x11, 0x3b, 0x95, 0x06, 0x9d, 0x14, 0xc5, 0x75, 0x88, 0xe1,
1323 0x93, 0xb6, 0x5e, 0xfc, 0x28, 0x13, 0xbc, 0xa3, 0xed, 0xa1, 0x9f, 0x9e, 0xff,
1324 0x46, 0xca, 0x12, 0xdf, 0xa1, 0xbf, 0x10, 0x37, 0x1b, 0x48, 0xd1, 0xb4, 0xa4,
1325 0x0c, 0x4d, 0x05, 0xa0, 0xd8, 0xdc, 0xe0, 0xe7, 0xdc, 0x62, 0xb0, 0x7b, 0x37,
1326 ],
1327 fp: [
1328 0x48, 0xc1, 0x83, 0x75, 0x7b, 0x5d, 0xa6, 0x61, 0x2a, 0x81, 0xb3, 0x0e, 0x40,
1329 0xb4, 0xac, 0xaa, 0x2d, 0x9e, 0x73, 0x95, 0x12, 0xe1, 0xd2, 0xd0, 0x01, 0x0e,
1330 0x92, 0xa7, 0xf7, 0xf2, 0xfc, 0xdf,
1331 ],
1332 d0: Some([
1333 0xe8, 0xd0, 0x37, 0x93, 0xcd, 0xd2, 0xba, 0xcc, 0x9c, 0x70, 0x41,
1334 ]),
1335 d1: Some([
1336 0x02, 0x0a, 0x7a, 0x6b, 0x0b, 0xf8, 0x4d, 0x3e, 0x89, 0x9f, 0x68,
1337 ]),
1338 d2: None,
1339 dmax: None,
1340 internal_nsk: None,
1341 internal_ovk: [
1342 0xdd, 0xba, 0xc2, 0xa4, 0x93, 0xf5, 0x3c, 0x3b, 0x09, 0x33, 0xd9, 0x13, 0xde,
1343 0xf8, 0x88, 0x48, 0x65, 0x4c, 0x08, 0x7c, 0x12, 0x60, 0x9d, 0xf0, 0x1b, 0xaf,
1344 0x94, 0x05, 0xce, 0x78, 0x04, 0xfd,
1345 ],
1346 internal_dk: [
1347 0x60, 0x2c, 0xd3, 0x17, 0xb7, 0xce, 0xa1, 0x1e, 0x8c, 0xc7, 0xae, 0x2e, 0xa4,
1348 0x05, 0xb4, 0x0d, 0x46, 0xb1, 0x59, 0x2a, 0x30, 0xf0, 0xcb, 0x6e, 0x8c, 0x4f,
1349 0x17, 0xd7, 0xf7, 0xc4, 0x7f, 0xeb,
1350 ],
1351 internal_nk: [
1352 0xf9, 0x12, 0x87, 0xc0, 0x6e, 0x30, 0xb6, 0x5e, 0xa1, 0xbd, 0xb7, 0x16, 0xb2,
1353 0x31, 0xde, 0x67, 0x78, 0xa5, 0xd8, 0x0e, 0xe5, 0xcd, 0x9c, 0x06, 0x0d, 0x1a,
1354 0xba, 0xca, 0xe0, 0xaa, 0xe2, 0x3b,
1355 ],
1356 internal_ivk: [
1357 0x1d, 0x59, 0xea, 0x20, 0x17, 0x88, 0x18, 0x64, 0xd2, 0x4e, 0xad, 0xb5, 0xcf,
1358 0x34, 0x68, 0xa4, 0x1a, 0x1b, 0x2a, 0xaa, 0x0d, 0x1b, 0x3a, 0x72, 0xc6, 0xda,
1359 0x9c, 0xe6, 0x50, 0x2a, 0x0a, 0x05,
1360 ],
1361 internal_xsk: None,
1362 internal_xfvk: [
1363 0x02, 0xdb, 0x99, 0x9e, 0x07, 0x02, 0x00, 0x00, 0x80, 0x97, 0xce, 0x15, 0xf4,
1364 0xed, 0x1b, 0x97, 0x39, 0xb0, 0x26, 0x2a, 0x46, 0x3b, 0xcb, 0x3d, 0xc9, 0xb3,
1365 0xbd, 0x23, 0x23, 0xa9, 0xba, 0xa4, 0x41, 0xca, 0x42, 0x77, 0x73, 0x83, 0xa8,
1366 0xd4, 0x35, 0xa6, 0xc5, 0x92, 0x5a, 0x0f, 0x85, 0xfa, 0x4f, 0x1e, 0x40, 0x5e,
1367 0x3a, 0x49, 0x70, 0xd0, 0xc4, 0xa4, 0xb4, 0x81, 0x44, 0x38, 0xf4, 0xe9, 0xd4,
1368 0x52, 0x0e, 0x20, 0xf7, 0xfd, 0xcf, 0x38, 0x41, 0xf9, 0x12, 0x87, 0xc0, 0x6e,
1369 0x30, 0xb6, 0x5e, 0xa1, 0xbd, 0xb7, 0x16, 0xb2, 0x31, 0xde, 0x67, 0x78, 0xa5,
1370 0xd8, 0x0e, 0xe5, 0xcd, 0x9c, 0x06, 0x0d, 0x1a, 0xba, 0xca, 0xe0, 0xaa, 0xe2,
1371 0x3b, 0xdd, 0xba, 0xc2, 0xa4, 0x93, 0xf5, 0x3c, 0x3b, 0x09, 0x33, 0xd9, 0x13,
1372 0xde, 0xf8, 0x88, 0x48, 0x65, 0x4c, 0x08, 0x7c, 0x12, 0x60, 0x9d, 0xf0, 0x1b,
1373 0xaf, 0x94, 0x05, 0xce, 0x78, 0x04, 0xfd, 0x60, 0x2c, 0xd3, 0x17, 0xb7, 0xce,
1374 0xa1, 0x1e, 0x8c, 0xc7, 0xae, 0x2e, 0xa4, 0x05, 0xb4, 0x0d, 0x46, 0xb1, 0x59,
1375 0x2a, 0x30, 0xf0, 0xcb, 0x6e, 0x8c, 0x4f, 0x17, 0xd7, 0xf7, 0xc4, 0x7f, 0xeb,
1376 ],
1377 internal_fp: [
1378 0x30, 0xfe, 0x0d, 0x61, 0x0f, 0x94, 0x7b, 0x2c, 0x26, 0x0e, 0x7b, 0x29, 0xe7,
1379 0x9e, 0x5c, 0x2e, 0x7d, 0x3e, 0x14, 0xab, 0xf9, 0x79, 0xf6, 0x40, 0x6d, 0x07,
1380 0xba, 0xf8, 0xfa, 0xdd, 0xf4, 0x95,
1381 ],
1382 },
1383 TestVector {
1384 ask: None,
1385 nsk: None,
1386 ovk: [
1387 0x69, 0xb9, 0xe0, 0xfa, 0x1c, 0x4b, 0x3d, 0xeb, 0x91, 0xd5, 0x3b, 0xee, 0xe8,
1388 0x71, 0x15, 0x61, 0x21, 0x47, 0x4b, 0x8b, 0x62, 0xef, 0x24, 0x13, 0x44, 0x78,
1389 0xdc, 0x34, 0x99, 0x69, 0x1a, 0xf6,
1390 ],
1391 dk: [
1392 0xbe, 0xcb, 0x50, 0xc3, 0x63, 0xbb, 0x2e, 0xd9, 0xda, 0x5c, 0x30, 0x43, 0xce,
1393 0xb0, 0xf1, 0xa0, 0x52, 0x7b, 0xf8, 0x36, 0xb2, 0x9a, 0x35, 0xf7, 0xc0, 0xc9,
1394 0xf2, 0x61, 0x12, 0x3b, 0xe5, 0x6e,
1395 ],
1396 c: [
1397 0x8d, 0x93, 0x7b, 0xcf, 0x81, 0xba, 0x43, 0x0d, 0x5b, 0x49, 0xaf, 0xc0, 0xa4,
1398 0x03, 0x36, 0x7b, 0x1f, 0xd9, 0x98, 0x79, 0xec, 0xba, 0x41, 0xbe, 0x05, 0x1c,
1399 0x5a, 0x4a, 0xa7, 0xd6, 0xe7, 0xe8,
1400 ],
1401 ak: [
1402 0xb1, 0x85, 0xc5, 0x7b, 0x50, 0x9c, 0x25, 0x36, 0xc4, 0xf2, 0xd3, 0x26, 0xd7,
1403 0x66, 0xc8, 0xfa, 0xb2, 0x54, 0x47, 0xde, 0x53, 0x75, 0xa9, 0x32, 0x8d, 0x64,
1404 0x9d, 0xda, 0xbd, 0x97, 0xa6, 0xa3,
1405 ],
1406 nk: [
1407 0xdb, 0x88, 0x04, 0x9e, 0x02, 0xd2, 0x07, 0x56, 0x8a, 0xfc, 0x42, 0xe0, 0x7d,
1408 0xb2, 0xab, 0xed, 0x50, 0x0b, 0x27, 0x01, 0xc0, 0x1b, 0xbf, 0xf3, 0x63, 0x99,
1409 0x76, 0x4b, 0x81, 0xc0, 0x66, 0x4f,
1410 ],
1411 ivk: [
1412 0xb0, 0xa5, 0xf3, 0x37, 0x23, 0x2f, 0x2c, 0x3d, 0xac, 0x70, 0xc2, 0xa4, 0x10,
1413 0xfa, 0x56, 0x1f, 0xc4, 0x5d, 0x8c, 0xc5, 0x9c, 0xda, 0x24, 0x6d, 0x31, 0xc8,
1414 0xb1, 0x71, 0x5a, 0x57, 0xd9, 0x00,
1415 ],
1416 xsk: None,
1417 xfvk: [
1418 0x03, 0x48, 0xc1, 0x83, 0x75, 0x03, 0x00, 0x00, 0x00, 0x8d, 0x93, 0x7b, 0xcf,
1419 0x81, 0xba, 0x43, 0x0d, 0x5b, 0x49, 0xaf, 0xc0, 0xa4, 0x03, 0x36, 0x7b, 0x1f,
1420 0xd9, 0x98, 0x79, 0xec, 0xba, 0x41, 0xbe, 0x05, 0x1c, 0x5a, 0x4a, 0xa7, 0xd6,
1421 0xe7, 0xe8, 0xb1, 0x85, 0xc5, 0x7b, 0x50, 0x9c, 0x25, 0x36, 0xc4, 0xf2, 0xd3,
1422 0x26, 0xd7, 0x66, 0xc8, 0xfa, 0xb2, 0x54, 0x47, 0xde, 0x53, 0x75, 0xa9, 0x32,
1423 0x8d, 0x64, 0x9d, 0xda, 0xbd, 0x97, 0xa6, 0xa3, 0xdb, 0x88, 0x04, 0x9e, 0x02,
1424 0xd2, 0x07, 0x56, 0x8a, 0xfc, 0x42, 0xe0, 0x7d, 0xb2, 0xab, 0xed, 0x50, 0x0b,
1425 0x27, 0x01, 0xc0, 0x1b, 0xbf, 0xf3, 0x63, 0x99, 0x76, 0x4b, 0x81, 0xc0, 0x66,
1426 0x4f, 0x69, 0xb9, 0xe0, 0xfa, 0x1c, 0x4b, 0x3d, 0xeb, 0x91, 0xd5, 0x3b, 0xee,
1427 0xe8, 0x71, 0x15, 0x61, 0x21, 0x47, 0x4b, 0x8b, 0x62, 0xef, 0x24, 0x13, 0x44,
1428 0x78, 0xdc, 0x34, 0x99, 0x69, 0x1a, 0xf6, 0xbe, 0xcb, 0x50, 0xc3, 0x63, 0xbb,
1429 0x2e, 0xd9, 0xda, 0x5c, 0x30, 0x43, 0xce, 0xb0, 0xf1, 0xa0, 0x52, 0x7b, 0xf8,
1430 0x36, 0xb2, 0x9a, 0x35, 0xf7, 0xc0, 0xc9, 0xf2, 0x61, 0x12, 0x3b, 0xe5, 0x6e,
1431 ],
1432 fp: [
1433 0x2e, 0x08, 0x15, 0x6d, 0xf8, 0xdf, 0xa2, 0x5b, 0x50, 0x55, 0xfc, 0x06, 0x3c,
1434 0x67, 0x15, 0x35, 0xa6, 0xa6, 0x5a, 0x60, 0x43, 0x7d, 0x96, 0xe7, 0x93, 0x08,
1435 0x15, 0xd0, 0x90, 0xf6, 0x2d, 0x67,
1436 ],
1437 d0: None,
1438 d1: Some([
1439 0x03, 0x0f, 0xfb, 0x26, 0x3a, 0x93, 0x9e, 0x23, 0x0e, 0x96, 0xdd,
1440 ]),
1441 d2: Some([
1442 0x7b, 0xbf, 0x63, 0x93, 0x4c, 0x7e, 0x92, 0x67, 0x0c, 0xdb, 0x55,
1443 ]),
1444 dmax: Some([
1445 0x1a, 0x73, 0x0f, 0xeb, 0x00, 0x59, 0xcf, 0x1f, 0x5b, 0xde, 0xa8,
1446 ]),
1447 internal_nsk: None,
1448 internal_ovk: [
1449 0xbf, 0x19, 0xe2, 0x57, 0xdd, 0x83, 0x3e, 0x02, 0x94, 0xec, 0x2a, 0xcb, 0xdf,
1450 0xa4, 0x0e, 0x14, 0x52, 0xf8, 0xe6, 0xa1, 0xf0, 0xc7, 0xf6, 0xf3, 0xab, 0xe5,
1451 0x6a, 0xfd, 0x5f, 0x6e, 0x26, 0x18,
1452 ],
1453 internal_dk: [
1454 0x1f, 0xfd, 0x6f, 0x81, 0xfe, 0x85, 0xc4, 0x9f, 0xe3, 0xe7, 0x3e, 0xf7, 0x3e,
1455 0x50, 0x11, 0x38, 0x22, 0xca, 0x62, 0x67, 0x31, 0x2b, 0x7a, 0xce, 0xd0, 0xc1,
1456 0x56, 0xa3, 0x2b, 0x3f, 0x24, 0x38,
1457 ],
1458 internal_nk: [
1459 0x82, 0x2f, 0x2f, 0x70, 0x96, 0x0f, 0x05, 0xd6, 0x96, 0x74, 0x58, 0xe3, 0x92,
1460 0x10, 0xd5, 0x77, 0x1f, 0x98, 0x47, 0xae, 0xf9, 0xe3, 0x4d, 0x94, 0xb8, 0xaf,
1461 0xbf, 0x95, 0xbb, 0xc4, 0xd2, 0x27,
1462 ],
1463 internal_ivk: [
1464 0xf9, 0x8a, 0x76, 0x09, 0x8e, 0x91, 0x05, 0x03, 0xe8, 0x02, 0x77, 0x52, 0x04,
1465 0x2d, 0xe8, 0x7e, 0x7d, 0x89, 0x3a, 0xb0, 0x14, 0x5e, 0xbc, 0x3b, 0x05, 0x97,
1466 0xc2, 0x39, 0x7f, 0x69, 0xd2, 0x01,
1467 ],
1468 internal_xsk: None,
1469 internal_xfvk: [
1470 0x03, 0x48, 0xc1, 0x83, 0x75, 0x03, 0x00, 0x00, 0x00, 0x8d, 0x93, 0x7b, 0xcf,
1471 0x81, 0xba, 0x43, 0x0d, 0x5b, 0x49, 0xaf, 0xc0, 0xa4, 0x03, 0x36, 0x7b, 0x1f,
1472 0xd9, 0x98, 0x79, 0xec, 0xba, 0x41, 0xbe, 0x05, 0x1c, 0x5a, 0x4a, 0xa7, 0xd6,
1473 0xe7, 0xe8, 0xb1, 0x85, 0xc5, 0x7b, 0x50, 0x9c, 0x25, 0x36, 0xc4, 0xf2, 0xd3,
1474 0x26, 0xd7, 0x66, 0xc8, 0xfa, 0xb2, 0x54, 0x47, 0xde, 0x53, 0x75, 0xa9, 0x32,
1475 0x8d, 0x64, 0x9d, 0xda, 0xbd, 0x97, 0xa6, 0xa3, 0x82, 0x2f, 0x2f, 0x70, 0x96,
1476 0x0f, 0x05, 0xd6, 0x96, 0x74, 0x58, 0xe3, 0x92, 0x10, 0xd5, 0x77, 0x1f, 0x98,
1477 0x47, 0xae, 0xf9, 0xe3, 0x4d, 0x94, 0xb8, 0xaf, 0xbf, 0x95, 0xbb, 0xc4, 0xd2,
1478 0x27, 0xbf, 0x19, 0xe2, 0x57, 0xdd, 0x83, 0x3e, 0x02, 0x94, 0xec, 0x2a, 0xcb,
1479 0xdf, 0xa4, 0x0e, 0x14, 0x52, 0xf8, 0xe6, 0xa1, 0xf0, 0xc7, 0xf6, 0xf3, 0xab,
1480 0xe5, 0x6a, 0xfd, 0x5f, 0x6e, 0x26, 0x18, 0x1f, 0xfd, 0x6f, 0x81, 0xfe, 0x85,
1481 0xc4, 0x9f, 0xe3, 0xe7, 0x3e, 0xf7, 0x3e, 0x50, 0x11, 0x38, 0x22, 0xca, 0x62,
1482 0x67, 0x31, 0x2b, 0x7a, 0xce, 0xd0, 0xc1, 0x56, 0xa3, 0x2b, 0x3f, 0x24, 0x38,
1483 ],
1484 internal_fp: [
1485 0xba, 0x64, 0xe4, 0x0d, 0x08, 0x6d, 0x36, 0x2c, 0xa5, 0xa1, 0x7f, 0x5e, 0x3b,
1486 0x1b, 0xee, 0x63, 0x24, 0xc8, 0x4f, 0x10, 0x12, 0x44, 0xa4, 0x00, 0x2a, 0x2e,
1487 0xca, 0xaf, 0x05, 0xbd, 0xd9, 0x81,
1488 ],
1489 },
1490 ];
1491
1492 let seed = [
1493 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
1494 24, 25, 26, 27, 28, 29, 30, 31,
1495 ];
1496
1497 let i1 = ChildIndex::NonHardened(1);
1498 let i2h = ChildIndex::Hardened(2);
1499 let i3 = ChildIndex::NonHardened(3);
1500
1501 let m = ExtendedSpendingKey::master(&seed);
1502 let m_1 = m.derive_child(i1);
1503 let m_1_2h = ExtendedSpendingKey::from_path(&m, &[i1, i2h]);
1504 let m_1_2hv = ExtendedFullViewingKey::from(&m_1_2h);
1505 let m_1_2hv_3 = m_1_2hv.derive_child(i3).unwrap();
1506
1507 let xfvks = [
1508 ExtendedFullViewingKey::from(&m),
1509 ExtendedFullViewingKey::from(&m_1),
1510 ExtendedFullViewingKey::from(&m_1_2h),
1511 m_1_2hv, m_1_2hv_3,
1513 ];
1514 assert_eq!(test_vectors.len(), xfvks.len());
1515
1516 let xsks = [m, m_1, m_1_2h];
1517
1518 for (xsk, tv) in xsks.iter().zip(test_vectors.iter()) {
1519 assert_eq!(xsk.expsk.ask.to_repr().as_ref(), tv.ask.unwrap());
1520 assert_eq!(xsk.expsk.nsk.to_repr().as_ref(), tv.nsk.unwrap());
1521
1522 assert_eq!(xsk.expsk.ovk.0, tv.ovk);
1523 assert_eq!(xsk.dk.0, tv.dk);
1524 assert_eq!(xsk.chain_code.0, tv.c);
1525
1526 let mut ser = vec![];
1527 xsk.write(&mut ser).unwrap();
1528 assert_eq!(&ser[..], &tv.xsk.unwrap()[..]);
1529
1530 let internal_xsk = xsk.derive_internal();
1531 assert_eq!(internal_xsk.expsk.ask.to_repr().as_ref(), tv.ask.unwrap());
1532 assert_eq!(
1533 internal_xsk.expsk.nsk.to_repr().as_ref(),
1534 tv.internal_nsk.unwrap()
1535 );
1536
1537 assert_eq!(internal_xsk.expsk.ovk.0, tv.internal_ovk);
1538 assert_eq!(internal_xsk.dk.0, tv.internal_dk);
1539 assert_eq!(internal_xsk.chain_code.0, tv.c);
1540
1541 let mut ser = vec![];
1542 internal_xsk.write(&mut ser).unwrap();
1543 assert_eq!(&ser[..], &tv.internal_xsk.unwrap()[..]);
1544 }
1545
1546 for (xfvk, tv) in xfvks.iter().zip(test_vectors.iter()) {
1547 assert_eq!(xfvk.fvk.vk.ak.to_bytes(), tv.ak);
1548 assert_eq!(xfvk.fvk.vk.nk.to_bytes(), tv.nk);
1549
1550 assert_eq!(xfvk.fvk.ovk.0, tv.ovk);
1551 assert_eq!(xfvk.dk.0, tv.dk);
1552 assert_eq!(xfvk.chain_code.0, tv.c);
1553
1554 assert_eq!(xfvk.fvk.vk.ivk().to_repr().as_ref(), tv.ivk);
1555
1556 let mut ser = vec![];
1557 xfvk.write(&mut ser).unwrap();
1558 assert_eq!(&ser[..], &tv.xfvk[..]);
1559 assert_eq!(FvkFingerprint::from(&xfvk.fvk).0, tv.fp);
1560
1561 let mut di = DiversifierIndex::new();
1563 match xfvk.dk.find_diversifier(di).unwrap() {
1564 (l, d) if l == di => assert_eq!(d.0, tv.d0.unwrap()),
1565 (_, _) => assert!(tv.d0.is_none()),
1566 }
1567
1568 di.increment().unwrap();
1570 match xfvk.dk.find_diversifier(di).unwrap() {
1571 (l, d) if l == di => assert_eq!(d.0, tv.d1.unwrap()),
1572 (_, _) => assert!(tv.d1.is_none()),
1573 }
1574
1575 di.increment().unwrap();
1577 match xfvk.dk.find_diversifier(di).unwrap() {
1578 (l, d) if l == di => assert_eq!(d.0, tv.d2.unwrap()),
1579 (_, _) => assert!(tv.d2.is_none()),
1580 }
1581
1582 let dmax = DiversifierIndex([0xff; 11]);
1584 match xfvk.dk.find_diversifier(dmax) {
1585 Some((l, d)) if l == dmax => assert_eq!(d.0, tv.dmax.unwrap()),
1586 Some((_, _)) => panic!(),
1587 None => assert!(tv.dmax.is_none()),
1588 }
1589
1590 let internal_xfvk = xfvk.derive_internal();
1591 assert_eq!(internal_xfvk.fvk.vk.ak.to_bytes(), tv.ak);
1592 assert_eq!(internal_xfvk.fvk.vk.nk.to_bytes(), tv.internal_nk);
1593
1594 assert_eq!(internal_xfvk.fvk.ovk.0, tv.internal_ovk);
1595 assert_eq!(internal_xfvk.dk.0, tv.internal_dk);
1596 assert_eq!(internal_xfvk.chain_code.0, tv.c);
1597
1598 assert_eq!(
1599 internal_xfvk.fvk.vk.ivk().to_repr().as_ref(),
1600 tv.internal_ivk
1601 );
1602
1603 let mut ser = vec![];
1604 internal_xfvk.write(&mut ser).unwrap();
1605 assert_eq!(&ser[..], &tv.internal_xfvk[..]);
1606 assert_eq!(FvkFingerprint::from(&internal_xfvk.fvk).0, tv.internal_fp);
1607 }
1608 }
1609}
1610
1611#[cfg(any(test, feature = "test-dependencies"))]
1612pub mod testing {
1613 use proptest::prelude::*;
1614
1615 use super::ExtendedSpendingKey;
1616
1617 prop_compose! {
1618 pub fn arb_extended_spending_key()(seed in prop::array::uniform32(prop::num::u8::ANY)) -> ExtendedSpendingKey {
1619 ExtendedSpendingKey::master(&seed)
1620 }
1621 }
1622}