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
102
103
104
105
106
use blake2::{
digest::{Input, VariableOutput},
VarBlake2b,
};
use rand::{RngCore, SeedableRng};
use rand_chacha::ChaChaRng;
use types::Phase;
use crate::{Address, ADDRESS_LENGTH};
const SEED_LENGTH: usize = 32;
pub struct AddressGenerator(ChaChaRng);
impl AddressGenerator {
pub fn new(hash: &[u8], phase: Phase) -> AddressGenerator {
AddressGeneratorBuilder::new()
.seed_with(&hash)
.seed_with(&[phase as u8])
.build()
}
pub fn create_address(&mut self) -> Address {
let mut buff = [0u8; ADDRESS_LENGTH];
self.0.fill_bytes(&mut buff);
buff
}
}
#[derive(Default)]
pub struct AddressGeneratorBuilder {
data: Vec<u8>,
}
impl AddressGeneratorBuilder {
pub fn new() -> Self {
Default::default()
}
pub fn seed_with(mut self, bytes: &[u8]) -> Self {
self.data.extend(bytes);
self
}
pub fn build(self) -> AddressGenerator {
let mut seed: [u8; SEED_LENGTH] = [0u8; SEED_LENGTH];
let mut hasher = VarBlake2b::new(SEED_LENGTH).unwrap();
hasher.input(self.data);
hasher.variable_result(|hash| seed.clone_from_slice(hash));
AddressGenerator(ChaChaRng::from_seed(seed))
}
}
#[cfg(test)]
mod tests {
use types::Phase;
use super::AddressGenerator;
const DEPLOY_HASH_1: [u8; 32] = [1u8; 32];
const DEPLOY_HASH_2: [u8; 32] = [2u8; 32];
#[test]
fn should_generate_different_numbers_for_different_seeds() {
let mut ag_a = AddressGenerator::new(&DEPLOY_HASH_1, Phase::Session);
let mut ag_b = AddressGenerator::new(&DEPLOY_HASH_2, Phase::Session);
let random_a = ag_a.create_address();
let random_b = ag_b.create_address();
assert_ne!(random_a, random_b)
}
#[test]
fn should_generate_same_numbers_for_same_seed() {
let mut ag_a = AddressGenerator::new(&DEPLOY_HASH_1, Phase::Session);
let mut ag_b = AddressGenerator::new(&DEPLOY_HASH_1, Phase::Session);
let random_a = ag_a.create_address();
let random_b = ag_b.create_address();
assert_eq!(random_a, random_b)
}
#[test]
fn should_not_generate_same_numbers_for_different_phase() {
let mut ag_a = AddressGenerator::new(&DEPLOY_HASH_1, Phase::Payment);
let mut ag_b = AddressGenerator::new(&DEPLOY_HASH_1, Phase::Session);
let mut ag_c = AddressGenerator::new(&DEPLOY_HASH_1, Phase::FinalizePayment);
let random_a = ag_a.create_address();
let random_b = ag_b.create_address();
let random_c = ag_c.create_address();
assert_ne!(
random_a, random_b,
"different phase should have different output"
);
assert_ne!(
random_a, random_c,
"different phase should have different output"
);
}
}