casper_storage/
address_generator.rs1use rand::{RngCore, SeedableRng};
3use rand_chacha::ChaChaRng;
4
5use casper_types::{AccessRights, Digest, Phase, URef};
6
7pub const ADDRESS_LENGTH: usize = 32;
9
10pub type Address = [u8; ADDRESS_LENGTH];
12
13const SEED_LENGTH: usize = 32;
14
15pub struct AddressGenerator(ChaChaRng);
17
18impl AddressGenerator {
19 pub fn new(hash: &[u8], phase: Phase) -> AddressGenerator {
21 AddressGeneratorBuilder::new()
22 .seed_with(hash)
23 .seed_with(&[phase as u8])
24 .build()
25 }
26
27 pub fn create_address(&mut self) -> Address {
29 let mut buff = [0u8; ADDRESS_LENGTH];
30 self.0.fill_bytes(&mut buff);
31 buff
32 }
33
34 pub fn new_hash_address(&mut self) -> Address {
37 Digest::hash(self.create_address()).value()
38 }
39
40 pub fn new_uref(&mut self, access_rights: AccessRights) -> URef {
42 let addr = self.create_address();
43 URef::new(addr, access_rights)
44 }
45}
46
47#[derive(Default)]
49pub struct AddressGeneratorBuilder {
50 data: Vec<u8>,
51}
52
53impl AddressGeneratorBuilder {
54 pub fn new() -> Self {
56 Default::default()
57 }
58
59 pub fn seed_with(mut self, bytes: &[u8]) -> Self {
61 self.data.extend(bytes);
62 self
63 }
64
65 pub fn build(self) -> AddressGenerator {
69 let seed: [u8; SEED_LENGTH] = Digest::hash(self.data).value();
70 AddressGenerator(ChaChaRng::from_seed(seed))
71 }
72}
73
74#[cfg(test)]
75mod tests {
76 use casper_types::Phase;
77
78 use super::AddressGenerator;
79
80 const DEPLOY_HASH_1: [u8; 32] = [1u8; 32];
81 const DEPLOY_HASH_2: [u8; 32] = [2u8; 32];
82
83 #[test]
84 fn should_generate_different_numbers_for_different_seeds() {
85 let mut ag_a = AddressGenerator::new(&DEPLOY_HASH_1, Phase::Session);
86 let mut ag_b = AddressGenerator::new(&DEPLOY_HASH_2, Phase::Session);
87 let random_a = ag_a.create_address();
88 let random_b = ag_b.create_address();
89
90 assert_ne!(random_a, random_b)
91 }
92
93 #[test]
94 fn should_generate_same_numbers_for_same_seed() {
95 let mut ag_a = AddressGenerator::new(&DEPLOY_HASH_1, Phase::Session);
96 let mut ag_b = AddressGenerator::new(&DEPLOY_HASH_1, Phase::Session);
97 let random_a = ag_a.create_address();
98 let random_b = ag_b.create_address();
99
100 assert_eq!(random_a, random_b)
101 }
102
103 #[test]
104 fn should_not_generate_same_numbers_for_different_phase() {
105 let mut ag_a = AddressGenerator::new(&DEPLOY_HASH_1, Phase::Payment);
106 let mut ag_b = AddressGenerator::new(&DEPLOY_HASH_1, Phase::Session);
107 let mut ag_c = AddressGenerator::new(&DEPLOY_HASH_1, Phase::FinalizePayment);
108 let random_a = ag_a.create_address();
109 let random_b = ag_b.create_address();
110 let random_c = ag_c.create_address();
111
112 assert_ne!(
113 random_a, random_b,
114 "different phase should have different output"
115 );
116
117 assert_ne!(
118 random_a, random_c,
119 "different phase should have different output"
120 );
121 }
122}