forked from dfinity/response-verification
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtests.rs
More file actions
137 lines (105 loc) · 4.31 KB
/
Copy pathtests.rs
File metadata and controls
137 lines (105 loc) · 4.31 KB
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
use super::signature_cache::SignatureCacheEntry;
use crate::signature_verification::{
reproducible_rng::reproducible_rng,
signature_cache::{SignatureCache, SignatureCacheStatistics},
verify_signature,
};
use rand::RngCore;
fn random_signature_cache_entry<R: RngCore>(rng: &mut R) -> SignatureCacheEntry {
let mut pk = [0u8; 96];
let mut sig = [0u8; 48];
let mut msg = [0u8; 32];
rng.fill_bytes(&mut pk);
rng.fill_bytes(&mut sig);
rng.fill_bytes(&mut msg);
SignatureCacheEntry::new(&pk, &sig, &msg)
}
#[test]
fn should_have_signature_cache_behave_like_a_lru_cache() {
let cache_size = 1000;
let cache = SignatureCache::new(cache_size);
let rng = &mut reproducible_rng();
let mut entries = Vec::with_capacity(cache_size);
for i in 0..cache_size {
// in each loop of this test we have one cache miss and then 2 hits
let expected_stats = SignatureCacheStatistics::new(i, 2 * i as u64, i as u64);
assert_eq!(cache.cache_statistics(), expected_stats);
let entry = random_signature_cache_entry(rng);
// the entry is randomly generated so has not been seen before
assert!(!cache.contains(&entry));
cache.insert(&entry);
// now the entry exists
// we check the cache twice to exercise the hit vs miss logic better
assert!(cache.contains(&entry));
assert!(cache.contains(&entry));
entries.push(entry);
}
let expected_stats =
SignatureCacheStatistics::new(cache_size, 2 * cache_size as u64, cache_size as u64);
assert_eq!(cache.cache_statistics(), expected_stats);
// all of the elements we just added are still in the cache
for entry in &entries {
assert!(cache.contains(entry));
}
let expected_stats =
SignatureCacheStatistics::new(cache_size, 3 * cache_size as u64, cache_size as u64);
assert_eq!(cache.cache_statistics(), expected_stats);
for i in 0..cache_size {
let entry = random_signature_cache_entry(rng);
assert_eq!(cache.cache_statistics().size, cache_size);
assert!(!cache.contains(&entry));
cache.insert(&entry);
assert!(cache.contains(&entry));
// the cache does not grow at this point
assert_eq!(cache.cache_statistics().size, cache_size);
// since the cache is LRU, the first n of the elements we added first are gone now
for entry in entries.iter().take(i) {
assert!(!cache.contains(entry));
}
}
// since the cache is LRU, all of the elements we added first are gone now
for entry in &entries {
assert!(!cache.contains(entry));
}
}
#[test]
fn verify_signature_uses_cache_for_known_entries() {
// Pre-populate the global cache with inputs that are not valid BLS signatures.
// If the signature_cache feature gate is correctly applied, verify_signature
// returns Ok() on a cache hit without ever calling the BLS verifier.
// If the cfg gates are wrong and the uncached path is compiled instead,
// this test will fail with SignatureVerificationFailed.
let pk = [1u8; 96];
let sig = [2u8; 48];
let msg = [3u8; 32];
SignatureCache::global().insert(&SignatureCacheEntry::new(&pk, &sig, &msg));
assert!(verify_signature(&pk, &sig, &msg).is_ok());
}
#[test]
fn should_have_signature_cache_update_lru_status_after_cache_hit() {
let cache_size = 3;
let cache = SignatureCache::new(cache_size);
let rng = &mut reproducible_rng();
let entry1 = random_signature_cache_entry(rng);
let entry2 = random_signature_cache_entry(rng);
let entry3 = random_signature_cache_entry(rng);
let entry4 = random_signature_cache_entry(rng);
cache.insert(&entry1);
cache.insert(&entry2);
cache.insert(&entry3);
assert!(cache.contains(&entry1));
assert!(cache.contains(&entry2));
assert!(cache.contains(&entry3));
assert!(!cache.contains(&entry4));
cache.insert(&entry4); // bumps 1
// reverse order of cache hits so 4 is LRU
assert!(cache.contains(&entry4));
assert!(cache.contains(&entry3));
assert!(cache.contains(&entry2));
assert!(!cache.contains(&entry1));
cache.insert(&entry1); // bumps 4
assert!(cache.contains(&entry1));
assert!(cache.contains(&entry2));
assert!(cache.contains(&entry3));
assert!(!cache.contains(&entry4));
}