1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
use ed25519_dalek as ed25519;

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Hash([u8; 32]);

#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(
    any(test, feature = "property-test-api"),
    derive(test_strategy::Arbitrary)
)]
pub struct Seed([u8; 32]);

impl AsRef<[u8]> for Seed {
    fn as_ref(&self) -> &[u8] {
        &self.0
    }
}

impl Seed {
    pub const SIZE: usize = 32;

    pub fn zero() -> Seed {
        Seed([0u8; Self::SIZE])
    }

    pub fn set_zero(&mut self) {
        self.0.copy_from_slice(&[0u8; Self::SIZE])
    }

    pub fn from_bytes(b: [u8; Self::SIZE]) -> Seed {
        Seed(b)
    }

    pub fn from_slice(b: &[u8]) -> Seed {
        assert_eq!(b.len(), Self::SIZE);
        let mut out = [0u8; Self::SIZE];
        out.copy_from_slice(b);
        Seed(out)
    }
}

#[derive(Debug, Copy, Clone)]
#[cfg_attr(
    any(test, feature = "property-test-api"),
    derive(test_strategy::Arbitrary)
)]
pub struct Depth(
    // a bigger range here would result into unreasobable testing times and
    // possible segfaults due to excessive allocations
    #[cfg_attr(
        any(test, feature = "property-test-api"),
        strategy(..10usize)
    )]
    pub usize,
);

impl Depth {
    pub const fn total(self) -> usize {
        usize::pow(2, self.0 as u32)
    }

    pub fn half(self) -> usize {
        assert!(self.0 > 0);
        usize::pow(2, (self.0 - 1) as u32)
    }

    pub fn decr(self) -> Self {
        assert!(self.0 > 0);
        Depth(self.0 - 1)
    }
    pub fn incr(self) -> Self {
        Depth(self.0 + 1)
    }
}

pub fn split_seed(r: &Seed) -> (Seed, Seed) {
    use sha2::Digest;
    let mut hleft = sha2::Sha256::default();
    let mut hright = sha2::Sha256::default();

    hleft.update([1]);
    hleft.update(r.0);

    hright.update([2]);
    hright.update(r.0);

    let o1 = hleft.finalize();
    let o2 = hright.finalize();
    let s1 = Seed::from_slice(&o1);
    let s2 = Seed::from_slice(&o2);
    (s1, s2)
}

pub fn keygen_1(r: &Seed) -> ed25519::Keypair {
    let sk = ed25519::SecretKey::from_bytes(&r.0).unwrap();
    let pk = (&sk).into();
    ed25519::Keypair {
        secret: sk,
        public: pk,
    }
}