mithril_aggregator/http_server/validators/
prover_transactions_hash_validator.rs1use mithril_common::entities::ClientError;
2
3pub struct ProverTransactionsHashValidator {
4 max_hashes: usize,
5}
6
7impl ProverTransactionsHashValidator {
8 const LABEL: &'static str = "invalid_transaction_hashes";
9
10 pub fn new(max_hashes: usize) -> Self {
11 Self { max_hashes }
12 }
13
14 pub fn validate(&self, hashes: &[String]) -> Result<(), ClientError> {
15 if hashes.len() > self.max_hashes {
16 return Err(ClientError::new(
17 Self::LABEL,
18 format!(
19 "Transaction hashes list contains more than maximum allowed number of hashes: '{}'",
20 self.max_hashes
21 ),
22 ));
23 }
24
25 for hash in hashes {
26 if hash.is_empty() {
27 return Err(ClientError::new(
28 Self::LABEL,
29 "Transaction hash cannot be empty",
30 ));
31 }
32
33 if hash.chars().count() != 64 {
34 return Err(ClientError::new(
35 Self::LABEL,
36 "Transaction hash must have 64 characters",
37 ));
38 }
39
40 if !hash.chars().all(|c| c.is_ascii_hexdigit()) {
41 return Err(ClientError::new(
42 Self::LABEL,
43 "Transaction hash must contain only hexadecimal characters",
44 ));
45 }
46 }
47
48 Ok(())
49 }
50}
51
52#[cfg(test)]
53impl Default for ProverTransactionsHashValidator {
54 fn default() -> Self {
55 Self::new(usize::MAX)
56 }
57}
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62
63 #[test]
64 fn prover_transactions_hash_validator_return_error_when_empty_hash() {
65 let error = ProverTransactionsHashValidator::default()
66 .validate(&["".to_string()])
67 .expect_err("Should return an error");
68
69 assert_eq!(
70 error,
71 ClientError::new(
72 "invalid_transaction_hashes",
73 "Transaction hash cannot be empty"
74 )
75 );
76 }
77
78 #[test]
79 fn prover_transactions_hash_validator_return_error_when_hash_size_different_than_64() {
80 let error = ProverTransactionsHashValidator::default()
81 .validate(&["abc".to_string()])
82 .expect_err("Should return an error");
83
84 assert_eq!(
85 error,
86 ClientError::new(
87 "invalid_transaction_hashes",
88 "Transaction hash must have 64 characters"
89 )
90 );
91 }
92
93 #[test]
94 fn prover_transactions_hash_validator_return_error_when_hash_contains_non_hexadecimal_characters(
95 ) {
96 for invalid_char in ["g", "x", ";", " ", "à"].iter() {
97 let hash = format!("{}{}", "a".repeat(63), invalid_char);
98 let error = ProverTransactionsHashValidator::default()
99 .validate(&[hash.clone()])
100 .expect_err("Should return an error");
101 assert_eq!(
102 error,
103 ClientError::new(
104 "invalid_transaction_hashes",
105 "Transaction hash must contain only hexadecimal characters"
106 ),
107 "Invalid hash: {}",
108 hash
109 );
110 }
111 }
112
113 #[test]
114 fn prover_transactions_hash_validator_when_hash_contains_only_hexadecimal_characters() {
115 ProverTransactionsHashValidator::default()
116 .validate(&[format!("bcd9{}", "a".repeat(60))])
117 .expect("Should succeed");
118 }
119
120 #[test]
121 fn prover_transactions_hash_validator_return_error_when_more_hashes_than_max_allowed() {
122 let transactions_hashes = vec!["a".repeat(64), "b".repeat(64), "c".repeat(64)];
123 let validator = ProverTransactionsHashValidator::new(2);
124
125 let error = validator
126 .validate(&transactions_hashes)
127 .expect_err("Should return an error");
128
129 assert_eq!(
130 error,
131 ClientError::new(
132 "invalid_transaction_hashes",
133 format!(
134 "Transaction hashes list contains more than maximum allowed number of hashes: '{}'",
135 validator.max_hashes
136 )
137 )
138 );
139 }
140}