Skip to main content

transact/contract/address/
triple_key_hash.rs

1// Copyright 2019 Cargill Incorporated
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::contract::address::{hash, Addresser, AddresserError, ADDRESS_LENGTH};
16
17pub struct TripleKeyHashAddresser {
18    prefix: String,
19    first_hash_length: usize,
20    second_hash_length: usize,
21}
22
23impl TripleKeyHashAddresser {
24    pub fn new(
25        prefix: String,
26        first_hash_length: Option<usize>,
27        second_hash_length: Option<usize>,
28    ) -> Result<TripleKeyHashAddresser, AddresserError> {
29        let (first, second) =
30            calculate_hash_lengths(prefix.len(), first_hash_length, second_hash_length)?;
31        Ok(TripleKeyHashAddresser {
32            prefix,
33            first_hash_length: first,
34            second_hash_length: second,
35        })
36    }
37}
38
39impl Addresser<(String, String, String)> for TripleKeyHashAddresser {
40    fn compute(&self, key: &(String, String, String)) -> Result<String, AddresserError> {
41        let last_hash_length =
42            ADDRESS_LENGTH - self.prefix.len() - (self.first_hash_length + self.second_hash_length);
43
44        let first_hash = &hash(self.first_hash_length, &key.0);
45        let second_hash = &hash(self.second_hash_length, &key.1);
46        let third_hash = &hash(last_hash_length, &key.2);
47
48        Ok(String::from(&self.prefix) + first_hash + second_hash + third_hash)
49    }
50
51    fn normalize(&self, key: &(String, String, String)) -> String {
52        key.0.to_string() + "_" + &key.1 + "_" + &key.2
53    }
54}
55
56// Used to calculate the lengths of the key hashes to be used to create an address by the
57// TripleKeyHashAddresser.
58fn calculate_hash_lengths(
59    prefix_length: usize,
60    first_length: Option<usize>,
61    second_length: Option<usize>,
62) -> Result<(usize, usize), AddresserError> {
63    // Validate the length of the provided prefix is not greater than the ADDRESS_LENGTH.
64    if prefix_length > ADDRESS_LENGTH {
65        return Err(AddresserError {
66            message: format!(
67                "Prefix length ({}) is greater than total address length ({})",
68                prefix_length, ADDRESS_LENGTH
69            ),
70        });
71    }
72    match (first_length, second_length) {
73        (Some(first), Some(second)) => {
74            // Validate the hash lengths plus the prefix length is not greater than ADDRESS_LENGTH.
75            if prefix_length + first + second > ADDRESS_LENGTH {
76                return Err(AddresserError {
77                    message: format!(
78                        "Prefix length ({}) and hash lengths ({}) combined are greater than \
79                         total address length ({})",
80                        prefix_length,
81                        (first + second),
82                        ADDRESS_LENGTH
83                    ),
84                });
85            }
86            Ok((first, second))
87        }
88        (None, Some(second)) => {
89            // Validate the hash length plus the prefix length is not greater than ADDRESS_LENGTH.
90            if prefix_length + second > ADDRESS_LENGTH {
91                return Err(AddresserError {
92                    message: format!(
93                        "Prefix length ({}) and hash length ({}) combined are greater than \
94                         total address length ({})",
95                        prefix_length, second, ADDRESS_LENGTH
96                    ),
97                });
98            }
99            // If the prefix length and hash length are not greater than ADDRESS_LENGTH, the
100            // other hash length can be calculated and returned.
101            let calculated_length = (ADDRESS_LENGTH - prefix_length - second) / 2;
102            Ok((calculated_length, second))
103        }
104        (Some(first), None) => {
105            // Validate the hash length plus the prefix length is not greater than ADDRESS_LENGTH.
106            if prefix_length + first > ADDRESS_LENGTH {
107                return Err(AddresserError {
108                    message: format!(
109                        "Prefix length ({}) and hash length ({}) combined are greater than \
110                         total address length ({})",
111                        prefix_length, first, ADDRESS_LENGTH
112                    ),
113                });
114            }
115            // If the prefix length and hash ength are not greater than ADDRESS_LENGTH, the other
116            // hash length can be calculated and returned.
117            let calculated_length = (ADDRESS_LENGTH - prefix_length - first) / 2;
118            Ok((first, calculated_length))
119        }
120        (None, None) => {
121            // Calculate the first and second hash length.
122            let calculated_first = (ADDRESS_LENGTH - prefix_length) / 3;
123            let calculated_second = calculated_first;
124            // Validate the calculated hash lengths plus the prefix length is not greater than the
125            // ADDRESS_LENGTH.
126            if prefix_length + calculated_first + calculated_second > ADDRESS_LENGTH {
127                return Err(AddresserError {
128                    message: format!(
129                        "Prefix length ({}) and hash lengths ({}) combined are greater than \
130                         total address length ({})",
131                        prefix_length,
132                        (calculated_first + calculated_second),
133                        ADDRESS_LENGTH
134                    ),
135                });
136            }
137            // If the validation is passed, return the calculated hash lengths.
138            Ok((calculated_first, calculated_second))
139        }
140    }
141}
142
143#[cfg(test)]
144mod tests {
145    use super::*;
146
147    #[test]
148    /// This test constructs a TripleKeyHashAddresser with a 6 character `prefix` and a None option
149    /// for the `first_hash_length` and `second_hash_length.` The default value for these hash lengths
150    /// is the ADDRESS_LENGTH const minus the length of the prefix, then divided by 3. This test
151    /// ensures this addresser computes a valid radix address from the provided key, `('a', 'b', 'c')`.
152    /// Specifically, this test validates:
153    ///
154    /// 1. The address length matches the ADDRESS_LENGTH const
155    /// 2. The prefix is present in the beginning of the address
156    /// 3. The next characters, the length of which matches the default value `first_hash_length`,
157    ///    match the hash of the first key, 'a', of the tuple provided to the `compute` method
158    /// 4. The next characters, the length of which matches the default `second_hash_length`,
159    ///    match the hash of the second key, 'b', of the tuple provided to the `compute` method
160    /// 5. The remaining characters, the length of which matches the ADDRESS_LENGTH const less the
161    ///    length of the provided `prefix`, the default `first_hash_length` and `second_hash_length`,
162    ///    match the hash of the last key, 'c', of the tuple provided to the `compute` method
163    ///
164    /// This test also ensures that the instantiated TripleKeyHashAddresser can transform the natural
165    /// key into a single string with the individual keys within the tuple of three strings separated
166    /// by an underscore(`_`), using the `normalize` method.
167    fn test_triple_key_default_length() {
168        // Creating a DoubleKeyHashAddresser with a 6 character `prefix` and None options for the
169        // `first_hash_length` and `second_hash_length`
170        let addresser = TripleKeyHashAddresser::new("prefix".to_string(), None, None)
171            .expect("Unable to construct TripleKeyHashAddresser");
172        // Create the hashes of the individual keys to verify the constructed address
173        let key1 = "a";
174        let key1_hash = hash(21, key1);
175        let key2 = "b";
176        let key2_hash = hash(21, key2);
177        let key3 = "c";
178        let key3_hash = hash(22, key3);
179        // Compute the address
180        let addr = addresser
181            .compute(&(key1.to_string(), key2.to_string(), key3.to_string()))
182            .unwrap();
183        // Verify the `prefix` characters and the length
184        assert_eq!(addr[..6], "prefix".to_string());
185        assert_eq!(addr.len(), ADDRESS_LENGTH);
186        // Verify the remaining characters match the hash of each key created above
187        assert_eq!(addr[6..27], key1_hash[..21]);
188        assert_eq!(addr[27..48], key2_hash[..21]);
189        assert_eq!(addr[48..], key3_hash[..22]);
190        // Verify the `normalize` method generates the correct single string
191        let normalized =
192            addresser.normalize(&(key1.to_string(), key2.to_string(), key3.to_string()));
193        assert_eq!(normalized, "a_b_c".to_string());
194    }
195
196    #[test]
197    /// This test constructs a TripleKeyHashAddresser with a 6 character `prefix` and a Some option
198    /// with a value of 14 for the `first_hash_length` and a None option for `second_hash_length.`
199    /// The `second_hash_length` should be equal to the ADDRESS_LENGTH minus the length of the
200    /// prefix and the `first_hash_length`, then divided by two.
201    /// This test ensures this addresser computes a valid radix address from the provided key,
202    /// `('a', 'b', 'c')`. Specifically, this test validates:
203    ///
204    /// 1. The address length matches the ADDRESS_LENGTH const
205    /// 2. The prefix is present in the beginning of the address
206    /// 3. The next characters, the length of which matches the value `first_hash_length` (14)
207    ///    used to construct the TripleKeyHashAddresser, match the hash of the first key, 'a', of
208    ///    the tuple provided to the `compute` method
209    /// 4. The next characters, the length of which matches the calculated `second_hash_length`,
210    ///    match the hash of the second key, 'b', of the tuple provided to the `compute` method
211    /// 5. The remaining characters, the length of which matches the ADDRESS_LENGTH const less the
212    ///    length of the provided `prefix`, the `first_hash_length` and `second_hash_length`,
213    ///    match the hash of the last key, 'c', of the tuple provided to the `compute` method
214    ///
215    /// This test also ensures that the instantiated TripleKeyHashAddresser can transform the natural
216    /// key into a single string with the individual keys within the tuple of three strings separated
217    /// by an underscore(`_`), using the `normalize` method.
218    fn test_triple_key_custom_first_length() {
219        // Creating a DoubleKeyHashAddresser with a 6 character `prefix,` a Some option for the
220        // `first_hash_length` and a None option for the `second_hash_length`
221        let addresser = TripleKeyHashAddresser::new("prefix".to_string(), Some(14), None)
222            .expect("Unable to construct TripleKeyHashAddresser");
223        // Create the hashes of the individual keys to verify the constructed address
224        let key1 = "a";
225        let key1_hash = hash(14, key1);
226        let key2 = "b";
227        let key2_hash = hash(25, key2);
228        let key3 = "c";
229        let key3_hash = hash(25, key3);
230        // Compute the address
231        let addr = addresser
232            .compute(&(key1.to_string(), key2.to_string(), key3.to_string()))
233            .unwrap();
234        // Verify the `prefix` characters and the length
235        assert_eq!(addr[..6], "prefix".to_string());
236        assert_eq!(addr.len(), ADDRESS_LENGTH);
237        // Verify the remaining characters match the hash of each key created above
238        assert_eq!(addr[6..20], key1_hash[..14]);
239        assert_eq!(addr[20..45], key2_hash[..25]);
240        assert_eq!(addr[45..], key3_hash[..25]);
241        // Verify the `normalize` method generates the correct single string
242        let normalized =
243            addresser.normalize(&(key1.to_string(), key2.to_string(), key3.to_string()));
244        assert_eq!(normalized, "a_b_c".to_string());
245    }
246
247    #[test]
248    /// This test constructs a TripleKeyHashAddresser with a 6 character `prefix` and a None optional
249    /// for the `first_hash_length` and a Some option for `second_hash_length` with a value of 14.
250    /// The `first_hash_length` should be equal to the ADDRESS_LENGTH minus the length of the prefix
251    /// and the `second_hash_length`, then divided by two.
252    /// This test ensures this addresser computes a valid radix address from the provided key,
253    /// `('a', 'b', 'c')`. Specifically, this test validates:
254    ///
255    /// 1. The address length matches the ADDRESS_LENGTH const
256    /// 2. The prefix is present in the beginning of the address
257    /// 3. The next characters, the length of which matches the calculated `first_hash_length`,
258    ///    match the hash of the first key, 'a', of the tuple provided to the `compute` method
259    /// 4. The next characters, the length of which matches the `second_hash_length` value (14),
260    ///    match the hash of the second key, 'a', of the tuple provided to the `compute` method
261    /// 5. The remaining characters, the length of which matches the ADDRESS_LENGTH const less the
262    ///    length of the provided `prefix`, the `first_hash_length` and `second_hash_length`,
263    ///    match the hash of the last key, 'c', of the tuple provided to the `compute` method
264    ///
265    /// This test also ensures that the instantiated TripleKeyHashAddresser can transform the natural
266    /// key into a single string with the individual keys within the tuple of three strings separated
267    /// by an underscore(`_`), using the `normalize` method.
268    fn test_triple_key_custom_second_length() {
269        // Creating a DoubleKeyHashAddresser with a 6 character `prefix,` a Some option for the
270        // `second_hash_length` and a None option for the `first_hash_length`
271        let addresser = TripleKeyHashAddresser::new("prefix".to_string(), None, Some(14))
272            .expect("Unable to construct TripleKeyHashAddresser");
273        // Create the hashes of the individual keys to verify the constructed address
274        let key1 = "a";
275        let key1_hash = hash(25, key1);
276        let key2 = "b";
277        let key2_hash = hash(14, key2);
278        let key3 = "c";
279        let key3_hash = hash(25, key3);
280        // Compute the address
281        let addr = addresser
282            .compute(&(key1.to_string(), key2.to_string(), key3.to_string()))
283            .unwrap();
284        // Verify the `prefix` characters and the length
285        assert_eq!(addr[..6], "prefix".to_string());
286        assert_eq!(addr.len(), ADDRESS_LENGTH);
287        // Verify the remaining characters match the hash of each key created above
288        assert_eq!(addr[6..31], key1_hash[..25]);
289        assert_eq!(addr[31..45], key2_hash[..14]);
290        assert_eq!(addr[45..], key3_hash[..25]);
291        // Verify the `normalize` method generates the correct single string
292        let normalized =
293            addresser.normalize(&(key1.to_string(), key2.to_string(), key3.to_string()));
294        assert_eq!(normalized, "a_b_c".to_string());
295    }
296
297    #[test]
298    /// This test constructs a TripleKeyHashAddresser with a 6 character `prefix` and a Some option
299    /// with a value of 10 for `first_hash_length` and a Some option with a value of 10 for
300    /// `second_hash_length.`
301    /// This test ensures this addresser computes a valid radix address from the provided key,
302    /// `('a', 'b', 'c')`. Specifically, this test validates:
303    ///
304    /// 1. The address length matches the ADDRESS_LENGTH const
305    /// 2. The prefix is present in the beginning of the address
306    /// 3. The next characters, the length of which matches the `first_hash_length` value (10),
307    ///    match the hash of the first key, 'a', of the tuple provided to the `compute` method
308    /// 4. The next characters, the length of which matches the `second_hash_length` value (10),
309    ///    match the hash of the second key, 'a', of the tuple provided to the `compute` method
310    /// 5. The remaining characters, the length of which matches the ADDRESS_LENGTH const less the
311    ///    length of the provided `prefix`, the `first_hash_length` and `second_hash_length`,
312    ///    match the hash of the last key, 'c', of the tuple provided to the `compute` method
313    ///
314    /// This test also ensures that the instantiated TripleKeyHashAddresser can transform the natural
315    /// key into a single string with the individual keys within the tuple of three strings separated
316    /// by an underscore(`_`), using the `normalize` method.
317    fn test_triple_key_custom_lengths() {
318        // Creating a DoubleKeyHashAddresser with a 6 character `prefix,` and Some options for the
319        // `first_hash_length` and `second_hash_length`
320        let addresser = TripleKeyHashAddresser::new("prefix".to_string(), Some(10), Some(10))
321            .expect("Unable to construct TripleKeyHashAddresser");
322        // Create the hashes of the individual keys to verify the constructed address
323        let key1 = "a";
324        let key1_hash = hash(10, key1);
325        let key2 = "b";
326        let key2_hash = hash(10, key2);
327        let key3 = "c";
328        let key3_hash = hash(44, key3);
329        // Compute the address
330        let addr = addresser
331            .compute(&(key1.to_string(), key2.to_string(), key3.to_string()))
332            .unwrap();
333        // Verify the `prefix` characters and the length
334        assert_eq!(addr[..6], "prefix".to_string());
335        assert_eq!(addr.len(), ADDRESS_LENGTH);
336        // Verify the remaining characters match the hash of each key created above
337        assert_eq!(addr[6..16], key1_hash[..10]);
338        assert_eq!(addr[16..26], key2_hash[..10]);
339        assert_eq!(addr[26..], key3_hash[..44]);
340        // Verify the `normalize` method generates the correct single string
341        let normalized =
342            addresser.normalize(&(key1.to_string(), key2.to_string(), key3.to_string()));
343        assert_eq!(normalized, "a_b_c".to_string());
344    }
345
346    #[test]
347    /// Tests the `calculate_hash_lengths` function to ensure it provides the correct values from
348    /// various inputs. Specifically, this test validates the correct output when provided with a
349    /// `prefix_length` of 6, a Some option with various values as the `first_hash_length`,
350    /// and a None option as the `second_hash_length.` As the `second_hash_length` is None, the
351    /// resulting value should be equal to ADDRESS_LENGTH less the `prefix_length` and
352    /// `first_hash_length`, then divided by 2.
353    ///
354    /// This test validates the correct calculation for the `second_hash_length` and the matching
355    /// value of the Some option for the `first_hash_length`
356    fn test_calculate_hash_custom_first_length() {
357        let (first_length, second_length) = calculate_hash_lengths(6, Some(21), None).unwrap();
358        assert_eq!(first_length, 21);
359        let remaining = ADDRESS_LENGTH - 6 - 21;
360        assert_eq!(second_length, (remaining / 2));
361
362        let (first_length, second_length) = calculate_hash_lengths(6, Some(41), None).unwrap();
363        assert_eq!(first_length, 41);
364        let remaining = ADDRESS_LENGTH - 6 - 41;
365        assert_eq!(second_length, (remaining / 2));
366
367        let (first_length, second_length) = calculate_hash_lengths(6, Some(61), None).unwrap();
368        assert_eq!(first_length, 61);
369        let remaining = ADDRESS_LENGTH - 6 - 61;
370        assert_eq!(second_length, (remaining / 2));
371    }
372
373    #[test]
374    /// Tests the `calculate_hash_lengths` function to ensure it provides the correct values from
375    /// various inputs. Specifically, this test validates the correct output when provided with a
376    /// `prefix_length` of 6, a Some option with various values as the `second_hash_length`,
377    /// and a None option as the `first_hash_length.` As the `first_hash_length` is None, the
378    /// resulting value should be equal to ADDRESS_LENGTH less the `prefix_length` and
379    /// `second_hash_length`, then divided by 2.
380    ///
381    /// This test validates the correct calculation for the `first_hash_length` and the matching
382    /// value of the Some option for the `second_hash_length`
383    fn test_calculate_hash_custom_second_length() {
384        let (first_length, second_length) = calculate_hash_lengths(6, None, Some(21)).unwrap();
385        let remaining = ADDRESS_LENGTH - 6 - 21;
386        assert_eq!(first_length, (remaining / 2));
387        assert_eq!(second_length, 21);
388
389        let (first_length, second_length) = calculate_hash_lengths(6, None, Some(41)).unwrap();
390        let remaining = ADDRESS_LENGTH - 6 - 41;
391        assert_eq!(first_length, (remaining / 2));
392        assert_eq!(second_length, 41);
393
394        let (first_length, second_length) = calculate_hash_lengths(6, None, Some(61)).unwrap();
395        let remaining = ADDRESS_LENGTH - 6 - 61;
396        assert_eq!(first_length, (remaining / 2));
397        assert_eq!(second_length, 61);
398    }
399
400    #[test]
401    /// Tests the `calculate_hash_lengths` function to ensure it provides the correct values from
402    /// various inputs. Specifically, this test validates the correct output when provided with a
403    /// `prefix_length` of 6, and Some options with various values for the `first_hash_length` and
404    /// `second_hash_length.`
405    ///
406    /// This test validates the matching value of the Some option for the `first_hash_length` and
407    /// `second_hash_length`
408    fn test_calculate_hash_custom_lengths() {
409        let (first_length, second_length) = calculate_hash_lengths(6, Some(42), Some(12)).unwrap();
410        assert_eq!(first_length, 42);
411        assert_eq!(second_length, 12);
412
413        let (first_length, second_length) = calculate_hash_lengths(6, Some(12), Some(42)).unwrap();
414        assert_eq!(first_length, 12);
415        assert_eq!(second_length, 42);
416
417        let (first_length, second_length) = calculate_hash_lengths(6, Some(20), Some(20)).unwrap();
418        assert_eq!(first_length, 20);
419        assert_eq!(second_length, 20);
420    }
421
422    #[test]
423    /// Tests the `calculate_hash_lengths` function to ensure it provides the correct values from
424    /// various inputs. Specifically, this test validates the correct output when provided with
425    /// various values for the `prefix_length`, and a None option for the `first_hash_length` and
426    /// `second_hash_length.` As both the provided hash lengths are None, they must be calculated.
427    /// The resulting values should both be equal to ADDRESS_LENGTH less the `prefix_length`, then
428    /// divided by 3.
429    ///
430    /// This test validates the correct calculation for the `first_hash_length` and `second_hash_length`
431    fn test_calculate_hash_no_custom_lengths() {
432        let (first_length, second_length) = calculate_hash_lengths(6, None, None).unwrap();
433        let remaining = ADDRESS_LENGTH - 6;
434        assert_eq!(first_length, (remaining / 3));
435        assert_eq!(second_length, (remaining / 3));
436
437        let (first_length, second_length) = calculate_hash_lengths(30, None, None).unwrap();
438        let remaining = ADDRESS_LENGTH - 30;
439        assert_eq!(first_length, (remaining / 3));
440        assert_eq!(second_length, (remaining / 3));
441
442        let (first_length, second_length) = calculate_hash_lengths(50, None, None).unwrap();
443        let remaining = ADDRESS_LENGTH - 50;
444        assert_eq!(first_length, (remaining / 3));
445        assert_eq!(second_length, (remaining / 3));
446    }
447
448    #[test]
449    #[should_panic]
450    /// This test constructs a TripleKeyHashAddresser with a 6 character `prefix` and an optional
451    /// value of the ADDRESS_LENGTH for the `first_hash_length` and None for the `second_hash_length.`
452    /// This test ensures that an error will be returned as the length of the prefix and the custom
453    /// length combined are greater than the const ADDRESS_LENGTH, currently set to 70.
454    ///
455    /// This test will attempt to construct a TripleKeyHashAddresser with an invalid custom hash
456    /// length and should return an error. Also validates the expected error message.
457    fn test_invalid_first_custom_length_construction() {
458        // Creating a TripleKeyHashAddresser with a 6 character `prefix` and the `first_hash_length`
459        // equal to the ADDRESS_LENGTH const which will return an error as the prefix length and
460        // custom length combined are greater than the ADDRESS_LENGTH.
461        let addresser =
462            TripleKeyHashAddresser::new("prefix".to_string(), Some(ADDRESS_LENGTH), None);
463
464        // Assert the Addresser constructor returned an error.
465        assert!(addresser.is_err());
466        // Unwrap to validate that this will panic.
467        addresser.unwrap();
468    }
469
470    #[test]
471    #[should_panic]
472    /// This test constructs a TripleKeyHashAddresser with a 6 character `prefix` and an optional
473    /// value of the ADDRESS_LENGTH for the `second_hash_length` and None for the `first_hash_length.`
474    /// This test ensures that an error will be returned as the length of the prefix and the custom
475    /// length combined are greater than the const ADDRESS_LENGTH, currently set to 70.
476    ///
477    /// This test will attempt to construct a TripleKeyHashAddresser with an invalid custom hash
478    /// length and should return an error.
479    fn test_invalid_second_custom_length_construction() {
480        // Creating a TripleKeyHashAddresser with a 6 character `prefix` and the `second_hash_length`
481        // equal to the ADDRESS_LENGTH const which will return an error as the prefix length and
482        // custom length combined are greater than the ADDRESS_LENGTH.
483        let addresser =
484            TripleKeyHashAddresser::new("prefix".to_string(), None, Some(ADDRESS_LENGTH));
485
486        // Assert the Addresser constructor returned an error.
487        assert!(addresser.is_err());
488        // Unwrap to validate that this will panic.
489        addresser.unwrap();
490    }
491
492    #[test]
493    #[should_panic]
494    /// This test constructs a TripleKeyHashAddresser with a 6 character `prefix` and an optional
495    /// value of half the ADDRESS_LENGTH const for both `second_hash_length` and `first_hash_length.`
496    /// This test ensures that an error will be returned as the length of the prefix and the custom
497    /// lengths combined are greater than the const ADDRESS_LENGTH, currently set to 70.
498    ///
499    /// This test will attempt to construct a TripleKeyHashAddresser with invalid custom hash
500    /// lengths and should return an error.
501    fn test_invalid_custom_lengths_construction() {
502        // Creating a TripleKeyHashAddresser with a 6 character `prefix` and value of half the
503        // ADDRESS_LENGTH const for the `first_hash_length` and `second_hash_length` which will
504        // return an error as the prefixlength and custom lengths combined are greater than the
505        // ADDRESS_LENGTH.
506        let addresser = TripleKeyHashAddresser::new(
507            "prefix".to_string(),
508            Some(ADDRESS_LENGTH / 2),
509            Some(ADDRESS_LENGTH / 2),
510        );
511
512        // Assert the Addresser constructor returned an error.
513        assert!(addresser.is_err());
514        // Unwrap to validate that this will panic.
515        addresser.unwrap();
516    }
517
518    #[test]
519    #[should_panic]
520    /// This test constructs a TripleKeyHashAddresser with a 72 character `prefix` and a None
521    /// value for both `second_hash_length` and `first_hash_length.` This test ensures that an error
522    /// will be returned as the length of the prefix and the custom lengths combined are greater
523    /// than the const ADDRESS_LENGTH, currently set to 70.
524    ///
525    /// This test will attempt to construct a TripleKeyHashAddresser with invalid prefix
526    /// length and should return an error.
527    fn test_invalid_prefix_length_construction() {
528        // Creating a TripleKeyHashAddresser with a 72 character `prefix` and value of None for the
529        // `first_hash_length` and `second_hash_length` which will return an error as the prefix
530        //  length is greater than the ADDRESS_LENGTH const.
531        let addresser = TripleKeyHashAddresser::new(
532            "prefixprefixprefixprefixprefixprefixprefixprefixprefixprefixprefixprefix".to_string(),
533            None,
534            None,
535        );
536
537        // Assert the Addresser constructor returned an error.
538        assert!(addresser.is_err());
539        // Unwrap to validate that this will panic.
540        addresser.unwrap();
541    }
542}