Skip to content
Snippets Groups Projects

Recurrent transfers feature

Merged Howo requested to merge recurrent_transfers_class into develop
Compare and Show latest version
1 file
+ 1
1
Compare changes
  • Side-by-side
  • Inline
@@ -2352,6 +2352,92 @@ void database::process_delayed_voting( const block_notification& note )
}
}
/**
* Iterates over all recurrent transfers with a due date date before
* the head block time and then executes the transfers
*/
void database::process_recurrent_transfers()
{
if( has_hardfork( HIVE_HARDFORK_1_25 ) ) {
auto now = head_block_time();
const auto& recurrent_transfers_by_date = get_index< recurrent_transfer_index >().indices().get< by_trigger_date >();
auto itr = recurrent_transfers_by_date.begin();
// uint16_t is okay because we stop at 1000, if the limit changes, make sure to check if it fits in the integer.
uint16_t processed_transfers = 0;
while( itr != recurrent_transfers_by_date.end() && itr->get_trigger_date() <= now ) {
// Since this is an intensive process, we don't want to process too many recurrent transfers in a single block
if (processed_transfers >= HIVE_MAX_RECURRENT_TRANSFERS_PER_BLOCK) {
ilog("Reached max processed recurrent transfers this block");
return;
}
auto &current_recurrent_transfer = *itr;
++itr;
const auto &from_account = get_account(current_recurrent_transfer.from_id);
const auto &to_account = get_account(current_recurrent_transfer.to_id);
asset available = get_balance(from_account, current_recurrent_transfer.amount.symbol);
FC_ASSERT(current_recurrent_transfer.remaining_executions > 0);
const auto remaining_executions = current_recurrent_transfer.remaining_executions -1;
bool remove_recurrent_transfer = false;
// If we have enough money, we proceed with the transfer
if (available >= current_recurrent_transfer.amount) {
adjust_balance(from_account, -current_recurrent_transfer.amount);
adjust_balance(to_account, current_recurrent_transfer.amount);
// No need to update the object if we know that we will remove it
if (remaining_executions == 0) {
remove_recurrent_transfer = true;
} else {
modify(current_recurrent_transfer, [&](recurrent_transfer_object &rt) {
rt.consecutive_failures = 0; // reset the consecutive failures counter
rt.update_next_trigger_date();
rt.remaining_executions = remaining_executions;
});
}
push_virtual_operation(fill_recurrent_transfer_operation(from_account.name, to_account.name, current_recurrent_transfer.amount, to_string(current_recurrent_transfer.memo), remaining_executions));
} else {
uint8_t consecutive_failures = current_recurrent_transfer.consecutive_failures + 1;
if (consecutive_failures < HIVE_MAX_CONSECUTIVE_RECURRENT_TRANSFER_FAILURES) {
// No need to update the object if we know that we will remove it
if (remaining_executions == 0) {
remove_recurrent_transfer = true;
} else {
modify(current_recurrent_transfer, [&](recurrent_transfer_object &rt) {
++rt.consecutive_failures;
rt.update_next_trigger_date();
rt.remaining_executions = remaining_executions;
});
}
// false means the recurrent transfer was not deleted
push_virtual_operation(failed_recurrent_transfer_operation(from_account.name, to_account.name, current_recurrent_transfer.amount, consecutive_failures, to_string(current_recurrent_transfer.memo), remaining_executions, false));
} else {
// if we had too many consecutive failures, remove the recurrent payment object
remove_recurrent_transfer = true;
// true means the recurrent transfer was deleted
push_virtual_operation(failed_recurrent_transfer_operation(from_account.name, to_account.name, current_recurrent_transfer.amount, consecutive_failures, to_string(current_recurrent_transfer.memo), remaining_executions, true));
}
}
if (remove_recurrent_transfer) {
remove( current_recurrent_transfer );
modify(from_account, [&](account_object& a )
{
FC_ASSERT( a.open_recurrent_transfers > 0 );
a.open_recurrent_transfers--;
});
}
processed_transfers++;
}
}
}
/**
* This method updates total_reward_shares2 on DGPO, and children_rshares2 on comments, when a comment's rshares2 changes
* from old_rshares2 to new_rshares2. Maintaining invariants that children_rshares2 is the sum of all descendants' rshares2,
@@ -3529,6 +3615,7 @@ void database::initialize_evaluators()
_my->_evaluator_registry.register_evaluator< update_proposal_evaluator >();
_my->_evaluator_registry.register_evaluator< update_proposal_votes_evaluator >();
_my->_evaluator_registry.register_evaluator< remove_proposal_evaluator >();
_my->_evaluator_registry.register_evaluator< recurrent_transfer_evaluator >();
#ifdef IS_TEST_NET
@@ -4064,6 +4151,8 @@ void database::_apply_block( const signed_block& next_block )
process_delayed_voting( note );
remove_expired_governance_votes();
process_recurrent_transfers();
generate_required_actions();
generate_optional_actions();
Loading