@@ -457,14 +457,14 @@ void resource_credits::update_rc_for_custom_action( std::function<void()>&& call
457
457
update_account_after_vest_change ( account, now );
458
458
}
459
459
460
- void resource_credits::use_account_rcs ( int64_t rc )
460
+ bool resource_credits::use_account_rcs ( int64_t rc )
461
461
{
462
462
const account_name_type& account_name = tx_info.payer ;
463
463
if ( account_name == account_name_type () )
464
464
{
465
465
if ( db.is_in_control () )
466
466
HIVE_ASSERT ( false , plugin_exception, " Tried to execute transaction with no resource user" , );
467
- return ;
467
+ return false ;
468
468
}
469
469
470
470
const account_object& account = db.get_account ( account_name );
@@ -476,10 +476,10 @@ void resource_credits::use_account_rcs( int64_t rc )
476
476
tx_info.max = max_mana;
477
477
tx_info.rc = account.rc_manabar .current_mana ; // initialize before regen in case of exception
478
478
mbparams.regen_time = HIVE_RC_REGEN_TIME;
479
+ bool is_privileged = false ;
479
480
480
481
try
481
482
{
482
-
483
483
db.modify ( account, [&]( account_object& acc )
484
484
{
485
485
acc.rc_manabar .regenerate_mana < true >( mbparams, dgpo.time .sec_since_epoch () );
@@ -490,11 +490,32 @@ void resource_credits::use_account_rcs( int64_t rc )
490
490
uint64_t blocks_in_mempool = db._pending_tx_size / dgpo.maximum_block_size ;
491
491
if ( blocks_in_mempool > flood_level )
492
492
{
493
- uint128_t sc = ( blocks_in_mempool - flood_level ) * flood_surcharge;
494
- sc *= rc;
495
- sc /= HIVE_100_PERCENT;
496
- FC_ASSERT ( sc <= static_cast < uint64_t >( std::numeric_limits<int64_t >::max () - rc ) );
497
- surcharge = static_cast < int64_t >( sc );
493
+ // check if transaction might be privileged - top witness transaction containing only
494
+ // one witness related operation is privileged because its execution might fix flood problem
495
+ // and is at the very least important for chain to function properly
496
+ if ( tx_info.op .valid () )
497
+ {
498
+ auto op = tx_info.op .value ();
499
+ switch ( op )
500
+ {
501
+ case operation::tag<feed_publish_operation>::value:
502
+ case operation::tag<witness_update_operation>::value:
503
+ case operation::tag<witness_set_properties_operation>::value:
504
+ {
505
+ const auto * witness = db.find_witness ( tx_info.payer );
506
+ is_privileged = ( witness != nullptr ) && ( witness->schedule == witness_object::elected );
507
+ } break ;
508
+ }
509
+ }
510
+
511
+ if ( !is_privileged )
512
+ {
513
+ uint128_t sc = ( blocks_in_mempool - flood_level ) * flood_surcharge;
514
+ sc *= rc;
515
+ sc /= HIVE_100_PERCENT;
516
+ FC_ASSERT ( sc <= static_cast < uint64_t >( std::numeric_limits<int64_t >::max () - rc ) );
517
+ surcharge = static_cast < int64_t >( sc );
518
+ }
498
519
}
499
520
}
500
521
bool has_mana = acc.rc_manabar .has_mana ( rc + surcharge );
@@ -547,6 +568,7 @@ void resource_credits::use_account_rcs( int64_t rc )
547
568
tx_info.rc = acc.rc_manabar .current_mana ;
548
569
} );
549
570
} FC_CAPTURE_AND_RETHROW ( (tx_info) )
571
+ return is_privileged;
550
572
}
551
573
552
574
bool resource_credits::has_expired_delegation ( const account_object& account ) const
@@ -775,7 +797,8 @@ void resource_credits::finalize_transaction( const full_transaction_type& full_t
775
797
776
798
// note: since transaction can influence amount of RC the payer has, we can't check if the payer has
777
799
// enough RC mana prior to actual execution of transaction
778
- use_account_rcs ( total_cost );
800
+ if ( use_account_rcs ( total_cost ) )
801
+ full_tx.set_privilege ();
779
802
780
803
if ( db.is_validating_block () || db.is_replaying_block () )
781
804
{
0 commit comments