@@ -24,16 +24,46 @@ module TestFeatures {
24
24
25
25
spec contains {
26
26
pragma bv=b"0 ";
27
+ pragma opaque;
27
28
aborts_if false ;
28
29
ensures result == ((feature / 8 ) < len (features) && spec_contains (features, feature));
29
30
}
30
31
32
+ fun is_enabled (feature: u64 ): bool acquires Features {
33
+ exists <Features >(@std ) &&
34
+ contains (&borrow_global <Features >(@std ).features, feature)
35
+ }
36
+
37
+ spec is_enabled {
38
+ aborts_if false ;
39
+ pragma timeout = 120 ;
40
+ ensures result == (
41
+ exists <Features>(@std ) // this one does not verify
42
+ && (((feature / 8 ) < len (global <Features>(@std ).features)
43
+ && spec_contains (global <Features>(@std ).features, feature)))
44
+ );
45
+ }
46
+
31
47
fun set (features: &mut vector <u8 >, feature: u64 , include: bool ) {
48
+ let old_n = vector ::length (features); // ghost var
49
+ let old_features = *features; // ghost var
50
+ let n = old_n; // ghost var
51
+
32
52
let byte_index = feature / 8 ;
33
53
let bit_mask = 1 << ((feature % 8 ) as u8 );
34
- while (vector ::length (features) <= byte_index) {
35
- let len = vector ::length (features);
36
- vector ::insert (features, 0 , len)
54
+ while ({
55
+ spec {
56
+ invariant n == len (features);
57
+ invariant n >= old_n;
58
+ invariant byte_index < old_n ==> len (features) == old_n;
59
+ invariant byte_index >= old_n ==> len (features) <= byte_index + 1 ;
60
+ invariant forall i in 0 ..old_n: features[i] == old_features[i];
61
+ invariant forall i in old_n..n: (features[i] as u8 ) == (0 as u8 );
62
+ };
63
+ vector ::length (features) <= byte_index
64
+ }) {
65
+ vector ::push_back (features, 0 );
66
+ n = n + 1 ;
37
67
};
38
68
let entry = vector ::borrow_mut (features, byte_index);
39
69
if (include)
@@ -44,6 +74,7 @@ module TestFeatures {
44
74
45
75
spec set {
46
76
pragma bv=b"0 ";
77
+ pragma timeout = 120 ;
47
78
aborts_if false ;
48
79
ensures feature / 8 < len (features);
49
80
ensures include == spec_contains (features, feature);
@@ -92,14 +123,58 @@ module TestFeatures {
92
123
aborts_if signer ::address_of (framework) != @std ;
93
124
}
94
125
95
- fun enable_feature_flags (feature: u64 ) acquires Features {
126
+ public fun disable_feature_flags (disable: vector < u64 > ) acquires Features {
96
127
let features = &mut borrow_global_mut <Features >(@std ).features;
97
- set (features, feature, true );
128
+ let i = 0 ;
129
+ let n = vector ::length (&disable);
130
+ while ({
131
+ spec {
132
+ invariant i <= n;
133
+ invariant forall j in 0 ..i: disable[j] / 8 < len (features) && !spec_contains (features, disable[j]);
134
+ };
135
+ i < n
136
+ }) {
137
+ set (features, *vector ::borrow (&disable, i), false );
138
+ spec {
139
+ assert (disable[i] / 8 < len (features) && !spec_contains (features, disable[i]));
140
+ };
141
+ i = i + 1 ;
142
+ };
143
+ }
144
+
145
+ spec disable_feature_flags {
146
+ pragma opaque;
147
+ pragma timeout = 120 ;
148
+ modifies global <Features>(@std );
149
+ let post features = global <Features>(@std ).features;
150
+ ensures forall i in 0 ..len (disable): (disable[i] / 8 < len (features) && !spec_contains (features, disable[i]));
151
+ }
152
+
153
+ public fun enable_feature_flags (enable: vector <u64 >) acquires Features {
154
+ let features = &mut borrow_global_mut <Features >(@std ).features;
155
+ let i = 0 ;
156
+ let n = vector ::length (&enable);
157
+ while ({
158
+ spec {
159
+ invariant i <= n;
160
+ invariant forall j in 0 ..i: enable[j] / 8 < len (features) && spec_contains (features, enable[j]);
161
+ };
162
+ i < n
163
+ }) {
164
+ set (features, *vector ::borrow (&enable, i), true );
165
+ spec {
166
+ assert (enable[i] / 8 < len (features) && spec_contains (features, enable[i]));
167
+ };
168
+ i = i + 1 ;
169
+ };
98
170
}
99
171
100
172
spec enable_feature_flags {
101
- let post features = borrow_global <Features>(@std ).features;
102
- ensures spec_contains (features, feature);
173
+ pragma opaque;
174
+ pragma timeout = 120 ;
175
+ modifies global <Features>(@std );
176
+ let post features = global <Features>(@std ).features;
177
+ ensures forall i in 0 ..len (enable): (enable[i] / 8 < len (features) && spec_contains (features, enable[i]));
103
178
}
104
179
105
180
}
0 commit comments