Move witness pay to VBO, update test #142
This commit is contained in:
parent
b24006cca3
commit
a751d90e00
17 changed files with 126 additions and 157 deletions
|
|
@ -21,6 +21,7 @@
|
|||
#include <graphene/chain/account_object.hpp>
|
||||
#include <graphene/chain/asset_object.hpp>
|
||||
#include <graphene/chain/vesting_balance_object.hpp>
|
||||
#include <graphene/chain/witness_object.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
|
|
@ -86,6 +87,54 @@ void database::adjust_core_in_orders( const account_object& acnt, asset delta )
|
|||
}
|
||||
}
|
||||
|
||||
optional< vesting_balance_id_type > database::deposit_lazy_vesting(
|
||||
const optional< vesting_balance_id_type >& ovbid,
|
||||
share_type amount, uint32_t req_vesting_seconds,
|
||||
account_id_type req_owner,
|
||||
bool require_vesting )
|
||||
{
|
||||
if( amount == 0 )
|
||||
return optional< vesting_balance_id_type >();
|
||||
|
||||
fc::time_point_sec now = head_block_time();
|
||||
|
||||
while( true )
|
||||
{
|
||||
if( !ovbid.valid() )
|
||||
break;
|
||||
const vesting_balance_object& vbo = (*ovbid)(*this);
|
||||
if( vbo.owner != req_owner )
|
||||
break;
|
||||
if( vbo.policy.which() != vesting_policy::tag< cdd_vesting_policy >::value )
|
||||
break;
|
||||
if( vbo.policy.get< cdd_vesting_policy >().vesting_seconds != req_vesting_seconds )
|
||||
break;
|
||||
modify( vbo, [&]( vesting_balance_object& _vbo )
|
||||
{
|
||||
if( require_vesting )
|
||||
_vbo.deposit(now, amount);
|
||||
else
|
||||
_vbo.deposit_vested(now, amount);
|
||||
} );
|
||||
return optional< vesting_balance_id_type >();
|
||||
}
|
||||
|
||||
const vesting_balance_object& vbo = create< vesting_balance_object >( [&]( vesting_balance_object& _vbo )
|
||||
{
|
||||
_vbo.owner = req_owner;
|
||||
_vbo.balance = amount;
|
||||
|
||||
cdd_vesting_policy policy;
|
||||
policy.vesting_seconds = req_vesting_seconds;
|
||||
policy.coin_seconds_earned = require_vesting ? 0 : amount.value * policy.vesting_seconds;
|
||||
policy.coin_seconds_earned_last_update = now;
|
||||
|
||||
_vbo.policy = policy;
|
||||
} );
|
||||
|
||||
return vbo.id;
|
||||
}
|
||||
|
||||
void database::deposit_cashback(const account_object& acct, share_type amount, bool require_vesting)
|
||||
{
|
||||
// If we don't have a VBO, or if it has the wrong maturity
|
||||
|
|
@ -105,46 +154,43 @@ void database::deposit_cashback(const account_object& acct, share_type amount, b
|
|||
return;
|
||||
}
|
||||
|
||||
uint32_t global_vesting_seconds = get_global_properties().parameters.cashback_vesting_period_seconds;
|
||||
fc::time_point_sec now = head_block_time();
|
||||
optional< vesting_balance_id_type > new_vbid = deposit_lazy_vesting(
|
||||
acct.cashback_vb,
|
||||
amount,
|
||||
get_global_properties().parameters.cashback_vesting_period_seconds,
|
||||
acct.id,
|
||||
require_vesting );
|
||||
|
||||
while( true )
|
||||
if( new_vbid.valid() )
|
||||
{
|
||||
if( !acct.cashback_vb.valid() )
|
||||
break;
|
||||
const vesting_balance_object& cashback_vb = (*acct.cashback_vb)(*this);
|
||||
if( cashback_vb.policy.which() != vesting_policy::tag< cdd_vesting_policy >::value )
|
||||
break;
|
||||
if( cashback_vb.policy.get< cdd_vesting_policy >().vesting_seconds != global_vesting_seconds )
|
||||
break;
|
||||
|
||||
modify( cashback_vb, [&]( vesting_balance_object& obj )
|
||||
modify( acct, [&]( account_object& _acct )
|
||||
{
|
||||
if( require_vesting )
|
||||
obj.deposit(now, amount);
|
||||
else
|
||||
obj.deposit_vested(now, amount);
|
||||
_acct.cashback_vb = *new_vbid;
|
||||
} );
|
||||
return;
|
||||
}
|
||||
|
||||
const vesting_balance_object& cashback_vb = create< vesting_balance_object >( [&]( vesting_balance_object& obj )
|
||||
return;
|
||||
}
|
||||
|
||||
void database::deposit_witness_pay(const witness_object& wit, share_type amount)
|
||||
{
|
||||
if( amount == 0 )
|
||||
return;
|
||||
|
||||
optional< vesting_balance_id_type > new_vbid = deposit_lazy_vesting(
|
||||
wit.pay_vb,
|
||||
amount,
|
||||
get_global_properties().parameters.witness_pay_vesting_seconds,
|
||||
wit.witness_account,
|
||||
true );
|
||||
|
||||
if( new_vbid.valid() )
|
||||
{
|
||||
obj.owner = acct.id;
|
||||
obj.balance = amount;
|
||||
|
||||
cdd_vesting_policy policy;
|
||||
policy.vesting_seconds = global_vesting_seconds;
|
||||
policy.coin_seconds_earned = require_vesting? 0 : amount.value * policy.vesting_seconds;
|
||||
policy.coin_seconds_earned_last_update = now;
|
||||
|
||||
obj.policy = policy;
|
||||
} );
|
||||
|
||||
modify( acct, [&]( account_object& _acct )
|
||||
{
|
||||
_acct.cashback_vb = cashback_vb.id;
|
||||
} );
|
||||
modify( wit, [&]( witness_object& _wit )
|
||||
{
|
||||
_wit.pay_vb = *new_vbid;
|
||||
} );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,11 +72,6 @@ void database::debug_dump()
|
|||
total_balances[asset_obj.id] += asset_obj.dynamic_asset_data_id(db).accumulated_fees;
|
||||
total_balances[asset_id_type()] += asset_obj.dynamic_asset_data_id(db).fee_pool;
|
||||
}
|
||||
for( const witness_object& witness_obj : db.get_index_type<witness_index>().indices() )
|
||||
{
|
||||
//idump((witness_obj));
|
||||
total_balances[asset_id_type()] += witness_obj.accumulated_income;
|
||||
}
|
||||
if( total_balances[asset_id_type()].value != core_asset_data.current_supply.value )
|
||||
{
|
||||
edump( (total_balances[asset_id_type()].value)(core_asset_data.current_supply.value ));
|
||||
|
|
|
|||
|
|
@ -142,7 +142,6 @@ void database::initialize_evaluators()
|
|||
register_evaluator<proposal_update_evaluator>();
|
||||
register_evaluator<proposal_delete_evaluator>();
|
||||
register_evaluator<witness_create_evaluator>();
|
||||
register_evaluator<witness_withdraw_pay_evaluator>();
|
||||
register_evaluator<vesting_balance_create_evaluator>();
|
||||
register_evaluator<vesting_balance_withdraw_evaluator>();
|
||||
register_evaluator<withdraw_permission_create_evaluator>();
|
||||
|
|
|
|||
|
|
@ -63,11 +63,12 @@ void database::update_signing_witness(const witness_object& signing_witness, con
|
|||
_dpo.witness_budget -= witness_pay;
|
||||
} );
|
||||
|
||||
deposit_witness_pay( signing_witness, witness_pay );
|
||||
|
||||
modify( signing_witness, [&]( witness_object& _wit )
|
||||
{
|
||||
_wit.previous_secret = new_block.previous_secret;
|
||||
_wit.next_secret_hash = new_block.next_secret_hash;
|
||||
_wit.accumulated_income += witness_pay;
|
||||
} );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -133,6 +133,7 @@
|
|||
#define GRAPHENE_CORE_ASSET_CYCLE_RATE_BITS 32
|
||||
|
||||
#define GRAPHENE_DEFAULT_WITNESS_PAY_PER_BLOCK (GRAPHENE_BLOCKCHAIN_PRECISION * int64_t( 10) )
|
||||
#define GRAPHENE_DEFAULT_WITNESS_PAY_VESTING_SECONDS (60*60*24)
|
||||
#define GRAPHENE_DEFAULT_WORKER_BUDGET_PER_DAY (GRAPHENE_BLOCKCHAIN_PRECISION * int64_t(500) * 1000 )
|
||||
|
||||
#define GRAPHENE_MAX_INTEREST_APR uint16_t( 10000 )
|
||||
|
|
|
|||
|
|
@ -326,8 +326,30 @@ namespace graphene { namespace chain {
|
|||
*/
|
||||
void adjust_core_in_orders( const account_object& acnt, asset delta );
|
||||
|
||||
/**
|
||||
* @brief Helper to make lazy deposit to CDD VBO.
|
||||
*
|
||||
* If the given optional VBID is not valid(),
|
||||
* or it does not have a CDD vesting policy,
|
||||
* or the owner / vesting_seconds of the policy
|
||||
* does not match the parameter, then credit amount
|
||||
* to newly created VBID and return it.
|
||||
*
|
||||
* Otherwise, credit amount to ovbid.
|
||||
*
|
||||
* @return ID of newly created VBO, but only if VBO was created.
|
||||
*/
|
||||
optional< vesting_balance_id_type > deposit_lazy_vesting(
|
||||
const optional< vesting_balance_id_type >& ovbid,
|
||||
share_type amount,
|
||||
uint32_t req_vesting_seconds,
|
||||
account_id_type req_owner,
|
||||
bool require_vesting );
|
||||
|
||||
// helper to handle cashback rewards
|
||||
void deposit_cashback(const account_object& acct, share_type amount, bool require_vesting = true);
|
||||
// helper to handle witness pay
|
||||
void deposit_witness_pay(const witness_object& wit, share_type amount);
|
||||
|
||||
//////////////////// db_debug.cpp ////////////////////
|
||||
|
||||
|
|
|
|||
|
|
@ -102,7 +102,6 @@ namespace graphene { namespace chain {
|
|||
//GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( asset_publish_feed );
|
||||
//GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( committee_member_create );
|
||||
//GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( witness_create );
|
||||
//GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( witness_withdraw_pay );
|
||||
|
||||
GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( proposal_create );
|
||||
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ namespace graphene { namespace chain {
|
|||
bool count_non_member_votes = true; ///< set to false to restrict voting privlegages to member accounts
|
||||
bool allow_non_member_whitelists = false; ///< true if non-member accounts may set whitelists and blacklists; false otherwise
|
||||
share_type witness_pay_per_block = GRAPHENE_DEFAULT_WITNESS_PAY_PER_BLOCK; ///< CORE to be allocated to witnesses (per block)
|
||||
uint32_t witness_pay_vesting_seconds = GRAPHENE_DEFAULT_WITNESS_PAY_VESTING_SECONDS; ///< vesting_seconds parameter for witness VBO's
|
||||
share_type worker_budget_per_day = GRAPHENE_DEFAULT_WORKER_BUDGET_PER_DAY; ///< CORE to be allocated to workers (per day)
|
||||
uint16_t max_predicate_opcode = GRAPHENE_DEFAULT_MAX_ASSERT_OPCODE; ///< predicate_opcode must be less than this number
|
||||
share_type fee_liquidation_threshold = GRAPHENE_DEFAULT_FEE_LIQUIDATION_THRESHOLD; ///< value in CORE at which accumulated fees in blockchain-issued market assets should be liquidated
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@ namespace graphene { namespace chain {
|
|||
asset_global_settle_operation,
|
||||
asset_publish_feed_operation,
|
||||
witness_create_operation,
|
||||
witness_withdraw_pay_operation,
|
||||
proposal_create_operation,
|
||||
proposal_update_operation,
|
||||
proposal_delete_operation,
|
||||
|
|
|
|||
|
|
@ -25,35 +25,10 @@ namespace graphene { namespace chain {
|
|||
void validate()const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @ingroup operations
|
||||
* Used to move witness pay from accumulated_income to their account balance.
|
||||
*
|
||||
* TODO: remove this operation, send witness pay into a vesting balance object and
|
||||
* have the witness claim the funds from there.
|
||||
*/
|
||||
struct witness_withdraw_pay_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type { uint64_t fee = 20 * GRAPHENE_BLOCKCHAIN_PRECISION; };
|
||||
|
||||
asset fee;
|
||||
/// The account to pay. Must match from_witness->witness_account. This account pays the fee for this operation.
|
||||
account_id_type to_account;
|
||||
witness_id_type from_witness;
|
||||
share_type amount;
|
||||
|
||||
account_id_type fee_payer()const { return to_account; }
|
||||
void validate()const;
|
||||
};
|
||||
|
||||
|
||||
/// TODO: witness_resign_operation : public base_operation
|
||||
|
||||
} } // graphene::chain
|
||||
|
||||
FC_REFLECT( graphene::chain::witness_create_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT( graphene::chain::witness_withdraw_pay_operation::fee_parameters_type, (fee) )
|
||||
|
||||
FC_REFLECT( graphene::chain::witness_create_operation, (fee)(witness_account)(url)(block_signing_key)(initial_secret) )
|
||||
FC_REFLECT( graphene::chain::witness_withdraw_pay_operation, (fee)(from_witness)(to_account)(amount) )
|
||||
|
|
|
|||
|
|
@ -30,15 +30,4 @@ namespace graphene { namespace chain {
|
|||
object_id_type do_apply( const witness_create_operation& o );
|
||||
};
|
||||
|
||||
class witness_withdraw_pay_evaluator : public evaluator<witness_withdraw_pay_evaluator>
|
||||
{
|
||||
public:
|
||||
typedef witness_withdraw_pay_operation operation_type;
|
||||
|
||||
void_result do_evaluate( const operation_type& o );
|
||||
void_result do_apply( const operation_type& o );
|
||||
|
||||
const witness_object* witness;
|
||||
const account_object* to_account;
|
||||
};
|
||||
} } // graphene::chain
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ namespace graphene { namespace chain {
|
|||
public_key_type signing_key;
|
||||
secret_hash_type next_secret_hash;
|
||||
secret_hash_type previous_secret;
|
||||
share_type accumulated_income;
|
||||
optional< vesting_balance_id_type > pay_vb;
|
||||
vote_id_type vote_id;
|
||||
string url;
|
||||
|
||||
|
|
@ -62,6 +62,6 @@ FC_REFLECT_DERIVED( graphene::chain::witness_object, (graphene::db::object),
|
|||
(signing_key)
|
||||
(next_secret_hash)
|
||||
(previous_secret)
|
||||
(accumulated_income)
|
||||
(pay_vb)
|
||||
(vote_id)
|
||||
(url) )
|
||||
|
|
|
|||
|
|
@ -3,17 +3,10 @@
|
|||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
|
||||
void witness_create_operation::validate() const
|
||||
{
|
||||
FC_ASSERT(fee.amount >= 0);
|
||||
FC_ASSERT(url.size() < GRAPHENE_MAX_URL_LENGTH );
|
||||
}
|
||||
|
||||
void witness_withdraw_pay_operation::validate() const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT( amount >= 0 );
|
||||
}
|
||||
|
||||
} } // graphene::chain
|
||||
|
|
|
|||
|
|
@ -46,30 +46,4 @@ object_id_type witness_create_evaluator::do_apply( const witness_create_operatio
|
|||
return new_witness_object.id;
|
||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||
|
||||
void_result witness_withdraw_pay_evaluator::do_evaluate(const witness_withdraw_pay_evaluator::operation_type& o)
|
||||
{ try {
|
||||
database& d = db();
|
||||
|
||||
witness = &d.get(o.from_witness);
|
||||
FC_ASSERT( o.to_account == witness->witness_account );
|
||||
FC_ASSERT( o.amount <= witness->accumulated_income, "Attempting to withdraw ${w}, but witness has only earned ${e}.",
|
||||
("w", o.amount)("e", witness->accumulated_income) );
|
||||
to_account = &d.get(o.to_account);
|
||||
|
||||
return void_result();
|
||||
} FC_CAPTURE_AND_RETHROW( (o) ) }
|
||||
|
||||
void_result witness_withdraw_pay_evaluator::do_apply(const witness_withdraw_pay_evaluator::operation_type& o)
|
||||
{ try {
|
||||
database& d = db();
|
||||
|
||||
d.adjust_balance(o.to_account, asset(o.amount));
|
||||
|
||||
d.modify(*witness, [&o](witness_object& w) {
|
||||
w.accumulated_income -= o.amount;
|
||||
});
|
||||
|
||||
return void_result();
|
||||
} FC_CAPTURE_AND_RETHROW( (o) ) }
|
||||
|
||||
} } // graphene::chain
|
||||
|
|
|
|||
|
|
@ -2196,8 +2196,6 @@ operation wallet_api::get_prototype_operation(string operation_name)
|
|||
return graphene::chain::committee_member_create_operation();
|
||||
if (operation_name == "witness_create_operation")
|
||||
return graphene::chain::witness_create_operation();
|
||||
if (operation_name == "witness_withdraw_pay_operation")
|
||||
return graphene::chain::witness_withdraw_pay_operation();
|
||||
if (operation_name == "committee_member_update_global_parameters_operation")
|
||||
return graphene::chain::committee_member_update_global_parameters_operation();
|
||||
if (operation_name == "transfer_operation")
|
||||
|
|
|
|||
|
|
@ -181,10 +181,6 @@ void database_fixture::verify_asset_supplies( const database& db )
|
|||
total_balances[bad.options.short_backing_asset] += bad.settlement_fund;
|
||||
}
|
||||
}
|
||||
for( const witness_object& witness_obj : db.get_index_type<witness_index>().indices() )
|
||||
{
|
||||
total_balances[asset_id_type()] += witness_obj.accumulated_income;
|
||||
}
|
||||
for( const vesting_balance_object& vbo : db.get_index_type< simple_index<vesting_balance_object> >() )
|
||||
total_balances[ vbo.balance.asset_id ] += vbo.balance.amount;
|
||||
|
||||
|
|
|
|||
|
|
@ -1100,7 +1100,7 @@ BOOST_AUTO_TEST_CASE( fill_order )
|
|||
//o.calculate_fee(db.current_fee_schedule());
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
BOOST_AUTO_TEST_CASE( witness_withdraw_pay_test )
|
||||
BOOST_AUTO_TEST_CASE( witness_pay_test )
|
||||
{ try {
|
||||
// there is an immediate maintenance interval in the first block
|
||||
// which will initialize last_budget_time
|
||||
|
|
@ -1112,9 +1112,17 @@ BOOST_AUTO_TEST_CASE( witness_withdraw_pay_test )
|
|||
transfer(account_id_type()(db), get_account("init3"), asset(20*CORE));
|
||||
generate_block();
|
||||
|
||||
auto last_witness_vbo_balance = [&]() -> share_type
|
||||
{
|
||||
const witness_object& wit = db.fetch_block_by_number(db.head_block_num())->witness(db);
|
||||
if( !wit.pay_vb.valid() )
|
||||
return 0;
|
||||
return (*wit.pay_vb)(db).balance.amount;
|
||||
};
|
||||
|
||||
const asset_object* core = &asset_id_type()(db);
|
||||
const account_object* nathan = &get_account("nathan");
|
||||
enable_fees();//105000000);
|
||||
enable_fees();
|
||||
BOOST_CHECK_GT(db.current_fee_schedule().get<account_upgrade_operation>().membership_lifetime_fee, 0);
|
||||
// Based on the size of the reserve fund later in the test, the witness budget will be set to this value
|
||||
const uint64_t ref_budget =
|
||||
|
|
@ -1156,9 +1164,7 @@ BOOST_AUTO_TEST_CASE( witness_withdraw_pay_test )
|
|||
generate_block();
|
||||
nathan = &get_account("nathan");
|
||||
core = &asset_id_type()(db);
|
||||
const witness_object* witness = &db.fetch_block_by_number(db.head_block_num())->witness(db);
|
||||
|
||||
BOOST_CHECK_EQUAL(witness->accumulated_income.value, 0);
|
||||
BOOST_CHECK_EQUAL( last_witness_vbo_balance().value, 0 );
|
||||
|
||||
auto schedule_maint = [&]()
|
||||
{
|
||||
|
|
@ -1174,8 +1180,7 @@ BOOST_AUTO_TEST_CASE( witness_withdraw_pay_test )
|
|||
while( db.head_block_num() < 30 )
|
||||
{
|
||||
generate_block();
|
||||
witness = &db.fetch_block_by_number(db.head_block_num())->witness(db);
|
||||
BOOST_CHECK_EQUAL( witness->accumulated_income.value, 0 );
|
||||
BOOST_CHECK_EQUAL( last_witness_vbo_balance().value, 0 );
|
||||
}
|
||||
BOOST_CHECK_EQUAL( db.head_block_num(), 30 );
|
||||
// maintenance will be in block 31. time of block 31 - time of block 1 = 30 * 5 seconds.
|
||||
|
|
@ -1186,51 +1191,27 @@ BOOST_AUTO_TEST_CASE( witness_withdraw_pay_test )
|
|||
generate_block();
|
||||
BOOST_CHECK_EQUAL( core->reserved(db).value, 999999406 );
|
||||
BOOST_CHECK_EQUAL( db.get_dynamic_global_properties().witness_budget.value, ref_budget );
|
||||
witness = &db.fetch_block_by_number(db.head_block_num())->witness(db);
|
||||
// first witness paid from old budget (so no pay)
|
||||
BOOST_CHECK_EQUAL( witness->accumulated_income.value, 0 );
|
||||
BOOST_CHECK_EQUAL( last_witness_vbo_balance().value, 0 );
|
||||
// second witness finally gets paid!
|
||||
generate_block();
|
||||
witness = &db.fetch_block_by_number(db.head_block_num())->witness(db);
|
||||
const witness_object* paid_witness = witness;
|
||||
BOOST_CHECK_EQUAL( witness->accumulated_income.value, witness_ppb );
|
||||
BOOST_CHECK_EQUAL( last_witness_vbo_balance().value, witness_ppb );
|
||||
BOOST_CHECK_EQUAL( db.get_dynamic_global_properties().witness_budget.value, ref_budget - witness_ppb );
|
||||
|
||||
generate_block();
|
||||
witness = &db.fetch_block_by_number(db.head_block_num())->witness(db);
|
||||
BOOST_CHECK_EQUAL( witness->accumulated_income.value, witness_ppb );
|
||||
BOOST_CHECK_EQUAL( last_witness_vbo_balance().value, witness_ppb );
|
||||
BOOST_CHECK_EQUAL( db.get_dynamic_global_properties().witness_budget.value, ref_budget - 2 * witness_ppb );
|
||||
|
||||
generate_block();
|
||||
witness = &db.fetch_block_by_number(db.head_block_num())->witness(db);
|
||||
BOOST_CHECK_LT( witness->accumulated_income.value, witness_ppb );
|
||||
BOOST_CHECK_EQUAL( witness->accumulated_income.value, ref_budget - 2 * witness_ppb );
|
||||
BOOST_CHECK_LT( last_witness_vbo_balance().value, witness_ppb );
|
||||
BOOST_CHECK_EQUAL( last_witness_vbo_balance().value, ref_budget - 2 * witness_ppb );
|
||||
BOOST_CHECK_EQUAL( db.get_dynamic_global_properties().witness_budget.value, 0 );
|
||||
|
||||
generate_block();
|
||||
witness = &db.fetch_block_by_number(db.head_block_num())->witness(db);
|
||||
BOOST_CHECK_EQUAL( witness->accumulated_income.value, 0 );
|
||||
BOOST_CHECK_EQUAL( last_witness_vbo_balance().value, 0 );
|
||||
BOOST_CHECK_EQUAL( db.get_dynamic_global_properties().witness_budget.value, 0 );
|
||||
|
||||
trx.set_expiration(db.head_block_time() + GRAPHENE_DEFAULT_MAX_TIME_UNTIL_EXPIRATION);
|
||||
// Withdraw the witness's pay
|
||||
enable_fees();//1);
|
||||
witness = paid_witness;
|
||||
witness_withdraw_pay_operation wop;
|
||||
wop.from_witness = witness->id;
|
||||
wop.to_account = witness->witness_account;
|
||||
wop.amount = witness->accumulated_income;
|
||||
trx.operations.push_back(wop);
|
||||
REQUIRE_THROW_WITH_VALUE(wop, amount, witness->accumulated_income.value * 2);
|
||||
trx.operations.back() = wop;
|
||||
for( auto& op : trx.operations ) db.current_fee_schedule().set_fee(op);
|
||||
trx.validate();
|
||||
db.push_transaction(trx, database::skip_authority_check);
|
||||
trx.clear();
|
||||
|
||||
BOOST_CHECK_EQUAL(get_balance(witness->witness_account(db), *core), witness_ppb );
|
||||
BOOST_CHECK_EQUAL(core->reserved(db).value, 999999406 );
|
||||
BOOST_CHECK_EQUAL(witness->accumulated_income.value, 0);
|
||||
|
||||
} FC_LOG_AND_RETHROW() }
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in a new issue