@@ -25,10 +25,13 @@ use witnet_data_structures::{
25
25
} ,
26
26
transaction_factory:: { self , NodeBalance } ,
27
27
types:: LastBeacon ,
28
- utxo_pool:: { get_utxo_info, UtxoInfo } ,
28
+ utxo_pool:: { get_utxo_info, UtxoDiff , UtxoInfo } ,
29
29
} ;
30
30
use witnet_util:: timestamp:: get_timestamp;
31
- use witnet_validations:: validations:: { block_reward, total_block_reward, validate_rad_request} ;
31
+ use witnet_validations:: validations:: {
32
+ block_reward, total_block_reward, validate_rad_request, validate_stake_transaction,
33
+ validate_unstake_transaction,
34
+ } ;
32
35
33
36
use crate :: {
34
37
actors:: {
@@ -232,10 +235,87 @@ impl Handler<EpochNotification<EveryEpochPayload>> for ChainManager {
232
235
self . candidates . clear ( ) ;
233
236
self . seen_candidates . clear ( ) ;
234
237
238
+ // Periodically revalidate pending stake transactions since they can become invalid
239
+ if get_protocol_version ( Some ( current_epoch) ) >= ProtocolVersion :: V1_8
240
+ && current_epoch % 10 == 0
241
+ {
242
+ let utxo_diff = UtxoDiff :: new (
243
+ & self . chain_state . unspent_outputs_pool ,
244
+ self . chain_state . block_number ( ) ,
245
+ ) ;
246
+ let min_stake = self
247
+ . consensus_constants_wit2
248
+ . get_validator_min_stake_nanowits ( current_epoch) ;
249
+ let max_stake = self
250
+ . consensus_constants_wit2
251
+ . get_validator_max_stake_nanowits ( current_epoch) ;
252
+
253
+ let mut invalid_stake_transactions = Vec :: < Hash > :: new ( ) ;
254
+ for st_tx in self . transactions_pool . st_iter ( ) {
255
+ if let Err ( e) = validate_stake_transaction (
256
+ st_tx,
257
+ & utxo_diff,
258
+ current_epoch,
259
+ self . epoch_constants . unwrap ( ) ,
260
+ & mut vec ! [ ] ,
261
+ & self . chain_state . stakes ,
262
+ min_stake,
263
+ max_stake,
264
+ ) {
265
+ log:: debug!(
266
+ "Removing stake transaction {} as it became invalid: {}" ,
267
+ st_tx. hash( ) ,
268
+ e
269
+ ) ;
270
+ invalid_stake_transactions. push ( st_tx. hash ( ) ) ;
271
+ continue ;
272
+ }
273
+ }
274
+
275
+ self . transactions_pool
276
+ . remove_invalid_stake_transactions ( invalid_stake_transactions) ;
277
+ }
278
+
279
+ // Periodically revalidate pending unstake transactions since they can become invalid
280
+ if get_protocol_version ( Some ( current_epoch) ) >= ProtocolVersion :: V2_0
281
+ && current_epoch % 10 == 0
282
+ {
283
+ let min_stake = self
284
+ . consensus_constants_wit2
285
+ . get_validator_min_stake_nanowits ( current_epoch) ;
286
+ let unstake_delay = self
287
+ . consensus_constants_wit2
288
+ . get_unstaking_delay_seconds ( current_epoch) ;
289
+
290
+ let mut invalid_unstake_transactions = Vec :: < Hash > :: new ( ) ;
291
+ for ut_tx in self . transactions_pool . ut_iter ( ) {
292
+ if let Err ( e) = validate_unstake_transaction (
293
+ ut_tx,
294
+ current_epoch,
295
+ & self . chain_state . stakes ,
296
+ min_stake,
297
+ unstake_delay,
298
+ ) {
299
+ log:: debug!(
300
+ "Removing unstake transaction {} as it became invalid: {}" ,
301
+ ut_tx. hash( ) ,
302
+ e
303
+ ) ;
304
+ invalid_unstake_transactions. push ( ut_tx. hash ( ) ) ;
305
+ continue ;
306
+ }
307
+ }
308
+
309
+ self . transactions_pool
310
+ . remove_invalid_unstake_transactions ( invalid_unstake_transactions) ;
311
+ }
312
+
235
313
log:: debug!(
236
- "Transactions pool size: {} value transfer, {} data request" ,
314
+ "Transactions pool size: {} value transfer, {} data request, {} stake, {} unstake " ,
237
315
self . transactions_pool. vt_len( ) ,
238
- self . transactions_pool. dr_len( )
316
+ self . transactions_pool. dr_len( ) ,
317
+ self . transactions_pool. st_len( ) ,
318
+ self . transactions_pool. ut_len( )
239
319
) ;
240
320
}
241
321
0 commit comments