@@ -21,18 +21,20 @@ use {
21
21
22
22
#[ derive( Clone , Debug , Copy ) ]
23
23
pub struct DataEvent {
24
- price : i64 ,
25
- conf : u64 ,
26
- slot_gap : u64 ,
24
+ price : i64 ,
25
+ conf : u64 ,
26
+ slot_gap : u64 ,
27
+ max_latency : u8 ,
27
28
}
28
29
29
30
impl Arbitrary for DataEvent {
30
31
fn arbitrary ( g : & mut quickcheck:: Gen ) -> Self {
31
32
DataEvent {
32
- slot_gap : u64:: from ( u8:: arbitrary ( g) ) + 1 , /* Slot gap is always > 1, because there
33
- * has been a succesful aggregation */
34
- price : i64:: arbitrary ( g) ,
35
- conf : u64:: arbitrary ( g) ,
33
+ slot_gap : u64:: from ( u8:: arbitrary ( g) ) + 1 , /* Slot gap is always > 1, because there
34
+ * has been a succesful aggregation */
35
+ price : i64:: arbitrary ( g) ,
36
+ conf : u64:: arbitrary ( g) ,
37
+ max_latency : u8:: arbitrary ( g) ,
36
38
}
37
39
}
38
40
}
@@ -44,6 +46,7 @@ impl Arbitrary for DataEvent {
44
46
/// - slot_gap is a random number between 1 and u8::MAX + 1 (256)
45
47
/// - price is a random i64
46
48
/// - conf is a random u64
49
+ /// - max_latency is a random u8
47
50
#[ quickcheck]
48
51
fn test_twap ( input : Vec < DataEvent > ) -> bool {
49
52
let mut price_cumulative = PriceCumulative {
@@ -56,7 +59,12 @@ fn test_twap(input: Vec<DataEvent>) -> bool {
56
59
let mut data = Vec :: < DataEvent > :: new ( ) ;
57
60
58
61
for data_event in input {
59
- price_cumulative. update ( data_event. price , data_event. conf , data_event. slot_gap ) ;
62
+ price_cumulative. update (
63
+ data_event. price ,
64
+ data_event. conf ,
65
+ data_event. slot_gap ,
66
+ data_event. max_latency ,
67
+ ) ;
60
68
data. push ( data_event) ;
61
69
price_cumulative. check_price ( data. as_slice ( ) ) ;
62
70
price_cumulative. check_conf ( data. as_slice ( ) ) ;
@@ -67,7 +75,6 @@ fn test_twap(input: Vec<DataEvent>) -> bool {
67
75
true
68
76
}
69
77
70
-
71
78
impl PriceCumulative {
72
79
pub fn check_price ( & self , data : & [ DataEvent ] ) {
73
80
assert_eq ! (
@@ -87,12 +94,18 @@ impl PriceCumulative {
87
94
}
88
95
pub fn check_num_down_slots ( & self , data : & [ DataEvent ] ) {
89
96
assert_eq ! (
90
- data. iter( )
91
- . fold( 0 , |acc, x| if x. slot_gap > PC_MAX_SEND_LATENCY . into( ) {
92
- acc + ( x. slot_gap - PC_MAX_SEND_LATENCY as u64 )
97
+ data. iter( ) . fold( 0 , |acc, x| {
98
+ let latency_threshold = if x. max_latency == 0 {
99
+ PC_MAX_SEND_LATENCY . into( )
100
+ } else {
101
+ x. max_latency. into( )
102
+ } ;
103
+ if x. slot_gap > latency_threshold {
104
+ acc + ( x. slot_gap - latency_threshold)
93
105
} else {
94
106
acc
95
- } ) ,
107
+ }
108
+ } ) ,
96
109
self . num_down_slots
97
110
) ;
98
111
}
@@ -112,35 +125,65 @@ fn test_twap_unit() {
112
125
113
126
let data = vec ! [
114
127
DataEvent {
115
- price: 1 ,
116
- conf: 2 ,
117
- slot_gap: 4 ,
128
+ price: 1 ,
129
+ conf: 2 ,
130
+ slot_gap: 4 ,
131
+ max_latency: 0 ,
132
+ } ,
133
+ DataEvent {
134
+ price: i64 :: MAX ,
135
+ conf: u64 :: MAX ,
136
+ slot_gap: 1 ,
137
+ max_latency: 0 ,
118
138
} ,
119
139
DataEvent {
120
- price: i64 :: MAX ,
121
- conf: u64 :: MAX ,
122
- slot_gap: 1 ,
140
+ price: -10 ,
141
+ conf: 4 ,
142
+ slot_gap: 30 ,
143
+ max_latency: 0 ,
123
144
} ,
124
145
DataEvent {
125
- price: -10 ,
126
- conf: 4 ,
127
- slot_gap: 30 ,
146
+ price: 1 ,
147
+ conf: 2 ,
148
+ slot_gap: 4 ,
149
+ max_latency: 5 ,
150
+ } ,
151
+ DataEvent {
152
+ price: 6 ,
153
+ conf: 7 ,
154
+ slot_gap: 8 ,
155
+ max_latency: 5 ,
128
156
} ,
129
157
] ;
130
158
131
- price_cumulative. update ( data[ 0 ] . price , data[ 0 ] . conf , data[ 0 ] . slot_gap ) ;
159
+ price_cumulative. update (
160
+ data[ 0 ] . price ,
161
+ data[ 0 ] . conf ,
162
+ data[ 0 ] . slot_gap ,
163
+ data[ 0 ] . max_latency ,
164
+ ) ;
132
165
assert_eq ! ( price_cumulative. price, 5 ) ;
133
166
assert_eq ! ( price_cumulative. conf, 10 ) ;
134
167
assert_eq ! ( price_cumulative. num_down_slots, 3 ) ;
135
168
assert_eq ! ( price_cumulative. unused, 0 ) ;
136
169
137
- price_cumulative. update ( data[ 1 ] . price , data[ 1 ] . conf , data[ 1 ] . slot_gap ) ;
170
+ price_cumulative. update (
171
+ data[ 1 ] . price ,
172
+ data[ 1 ] . conf ,
173
+ data[ 1 ] . slot_gap ,
174
+ data[ 1 ] . max_latency ,
175
+ ) ;
138
176
assert_eq ! ( price_cumulative. price, 9_223_372_036_854_775_812i128 ) ;
139
177
assert_eq ! ( price_cumulative. conf, 18_446_744_073_709_551_625u128 ) ;
140
178
assert_eq ! ( price_cumulative. num_down_slots, 3 ) ;
141
179
assert_eq ! ( price_cumulative. unused, 0 ) ;
142
180
143
- price_cumulative. update ( data[ 2 ] . price , data[ 2 ] . conf , data[ 2 ] . slot_gap ) ;
181
+ price_cumulative. update (
182
+ data[ 2 ] . price ,
183
+ data[ 2 ] . conf ,
184
+ data[ 2 ] . slot_gap ,
185
+ data[ 2 ] . max_latency ,
186
+ ) ;
144
187
assert_eq ! ( price_cumulative. price, 9_223_372_036_854_775_512i128 ) ;
145
188
assert_eq ! ( price_cumulative. conf, 18_446_744_073_709_551_745u128 ) ;
146
189
assert_eq ! ( price_cumulative. num_down_slots, 8 ) ;
@@ -152,7 +195,7 @@ fn test_twap_unit() {
152
195
num_down_slots : 0 ,
153
196
unused : 0 ,
154
197
} ;
155
- price_cumulative_overflow. update ( i64:: MIN , u64:: MAX , u64:: MAX ) ;
198
+ price_cumulative_overflow. update ( i64:: MIN , u64:: MAX , u64:: MAX , u8 :: MAX ) ;
156
199
assert_eq ! (
157
200
price_cumulative_overflow. price,
158
201
i128 :: MIN - i128 :: from( i64 :: MIN )
@@ -163,9 +206,38 @@ fn test_twap_unit() {
163
206
) ;
164
207
assert_eq ! (
165
208
price_cumulative_overflow. num_down_slots,
166
- u64 :: MAX - PC_MAX_SEND_LATENCY as u64
209
+ u64 :: MAX - u64 :: from ( u8 :: MAX )
167
210
) ;
168
211
assert_eq ! ( price_cumulative_overflow. unused, 0 ) ;
212
+
213
+ let mut price_cumulative_nonzero_max_latency = PriceCumulative {
214
+ price : 1 ,
215
+ conf : 2 ,
216
+ num_down_slots : 3 ,
217
+ unused : 0 ,
218
+ } ;
219
+
220
+ price_cumulative_nonzero_max_latency. update (
221
+ data[ 3 ] . price ,
222
+ data[ 3 ] . conf ,
223
+ data[ 3 ] . slot_gap ,
224
+ data[ 3 ] . max_latency ,
225
+ ) ;
226
+ assert_eq ! ( price_cumulative_nonzero_max_latency. price, 5 ) ;
227
+ assert_eq ! ( price_cumulative_nonzero_max_latency. conf, 10 ) ;
228
+ assert_eq ! ( price_cumulative_nonzero_max_latency. num_down_slots, 3 ) ;
229
+ assert_eq ! ( price_cumulative_nonzero_max_latency. unused, 0 ) ;
230
+
231
+ price_cumulative_nonzero_max_latency. update (
232
+ data[ 4 ] . price ,
233
+ data[ 4 ] . conf ,
234
+ data[ 4 ] . slot_gap ,
235
+ data[ 4 ] . max_latency ,
236
+ ) ;
237
+ assert_eq ! ( price_cumulative_nonzero_max_latency. price, 53 ) ;
238
+ assert_eq ! ( price_cumulative_nonzero_max_latency. conf, 66 ) ;
239
+ assert_eq ! ( price_cumulative_nonzero_max_latency. num_down_slots, 6 ) ;
240
+ assert_eq ! ( price_cumulative_nonzero_max_latency. unused, 0 ) ;
169
241
}
170
242
171
243
#[ test]
@@ -224,7 +296,6 @@ fn test_twap_with_price_account() {
224
296
Err ( OracleError :: NeedsSuccesfulAggregation )
225
297
) ;
226
298
227
-
228
299
assert_eq ! ( price_data. price_cumulative. price, 1 - 2 * 10 ) ;
229
300
assert_eq ! ( price_data. price_cumulative. conf, 2 + 2 * 5 ) ;
230
301
assert_eq ! ( price_data. price_cumulative. num_down_slots, 3 ) ;
0 commit comments