Resolve #31: Wrap it up and fix the failing tests

This commit is contained in:
Nathan Hourt 2015-06-10 14:17:13 -04:00
parent 4df4e8014a
commit 876e9a125d
10 changed files with 60 additions and 42 deletions

View file

@ -226,6 +226,7 @@ void_result account_upgrade_evaluator::do_apply(const account_upgrade_evaluator:
// Upgrade to lifetime member. I don't care what the account was before.
a.membership_expiration_date = time_point_sec::maximum();
a.referrer = a.registrar = a.lifetime_referrer = a.get_id();
a.lifetime_referrer_fee_percentage = GRAPHENE_100_PERCENT - a.network_fee_percentage;
} else if( a.is_annual_member(d.head_block_time()) ) {
// Renew an annual subscription that's still in effect.
FC_ASSERT(a.membership_expiration_date - d.head_block_time() < fc::days(3650),

View file

@ -155,6 +155,8 @@ void database::init_genesis(const genesis_allocation& initial_allocation)
const account_object& genesis_account =
create<account_object>( [&](account_object& n) {
n.membership_expiration_date = time_point_sec::maximum();
n.network_fee_percentage = GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE;
n.lifetime_referrer_fee_percentage = GRAPHENE_100_PERCENT - GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE;
n.name = "genesis";
n.owner.add_authority(genesis_key.get_id(), 1);
n.owner.weight_threshold = 1;
@ -179,6 +181,8 @@ void database::init_genesis(const genesis_allocation& initial_allocation)
a.referrer = account_id_type(i);
a.registrar = account_id_type(i);
a.lifetime_referrer = account_id_type(i);
a.network_fee_percentage = GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE;
a.lifetime_referrer_fee_percentage = GRAPHENE_100_PERCENT - GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE;
a.membership_expiration_date = fc::time_point_sec::maximum();
a.name = string("init") + fc::to_string(i);
a.statistics = stats_obj.id;

View file

@ -242,10 +242,10 @@ void database::process_budget()
// blocks_to_maint > 0 because time_to_maint > 0,
// which means numerator is at least equal to block_interval
share_type available_funds = get_max_budget( now );
share_type available_funds = get_max_budget(now);
share_type witness_budget = gpo.parameters.witness_pay_per_block.value * blocks_to_maint;
witness_budget = std::min( witness_budget, available_funds );
witness_budget = std::min(witness_budget, available_funds);
available_funds -= witness_budget;
fc::uint128_t worker_budget_u128 = gpo.parameters.worker_budget_per_day.value;
@ -260,21 +260,22 @@ void database::process_budget()
available_funds -= worker_budget;
share_type leftover_worker_funds = worker_budget;
pay_workers( leftover_worker_funds );
pay_workers(leftover_worker_funds);
available_funds += leftover_worker_funds;
modify( core, [&]( asset_dynamic_data_object& _core )
modify(core, [&]( asset_dynamic_data_object& _core )
{
_core.current_supply = (_core.current_supply + witness_budget +
worker_budget - leftover_worker_funds -
_core.accumulated_fees);
_core.accumulated_fees = 0;
} );
modify( dpo, [&]( dynamic_global_property_object& _dpo )
});
modify(dpo, [&]( dynamic_global_property_object& _dpo )
{
// Should this be +=?
_dpo.witness_budget = witness_budget;
_dpo.last_budget_time = now;
} );
});
// available_funds is money we could spend, but don't want to.
// we simply let it evaporate back into the reserve.
@ -361,6 +362,11 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
auto cut_fee = [](share_type a, uint16_t p) -> share_type
{
if( a == 0 || p == 0 )
return 0;
if( p == GRAPHENE_100_PERCENT )
return a;
fc::uint128 r(a.value);
r *= p;
r /= GRAPHENE_100_PERCENT;
@ -400,10 +406,11 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
share_type burned = cut_fee(network_cut, props.parameters.burn_percent_of_fee);
share_type accumulated = network_cut - burned;
assert( accumulated + burned == network_cut );
share_type referral = core_fee_total - network_cut;
share_type lifetime_cut = cut_fee(core_fee_total, a.lifetime_referrer_fee_percentage);
share_type referral = core_fee_total - network_cut - lifetime_cut;
d.modify(dynamic_asset_data_id_type()(d), [burned,accumulated](asset_dynamic_data_object& d) {
d.accumulated_fees += accumulated + burned;
d.modify(dynamic_asset_data_id_type()(d), [network_cut](asset_dynamic_data_object& d) {
d.accumulated_fees += network_cut;
});
d.modify(a.statistics(d), [core_fee_total](account_statistics_object& s) {
@ -413,20 +420,18 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
d.deposit_cashback( a, bulk_cashback );
assert( referral + bulk_cashback + accumulated + burned == core_fee_subtotal );
// Potential optimization: Skip some of this math and object lookups by special casing on the account type.
// For example, if the account is a lifetime member, we can skip all this and just deposit the referral to
// it directly.
share_type lifetime_cut = cut_fee(referral, a.lifetime_referrer_fee_percentage);
share_type referrer_cut = cut_fee(referral, a.referrer_rewards_percentage);
share_type registrar_cut = referral - lifetime_cut = referrer_cut;
share_type registrar_cut = referral - referrer_cut;
d.deposit_cashback(d.get(a.lifetime_referrer), lifetime_cut);
d.deposit_cashback(d.get(a.referrer), referrer_cut);
d.deposit_cashback(d.get(a.registrar), registrar_cut);
assert( lifetime_cut + referrer_cut + registrar_cut == referral );
idump((referrer_cut)(registrar_cut)(bulk_cashback)(accumulated)(burned)(lifetime_cut)(core_fee_subtotal));
assert( referrer_cut + registrar_cut + bulk_cashback + accumulated + burned + lifetime_cut == core_fee_subtotal );
}
}
} fees_helper(*this, gpo);

View file

@ -81,7 +81,6 @@
#define GRAPHENE_DEFAULT_CASHBACK_VESTING_PERIOD_SEC (60*60*24*365) ///< 1 year
#define GRAPHENE_DEFAULT_CASHBACK_VESTING_THRESHOLD (GRAPHENE_BLOCKCHAIN_PRECISION*int64_t(100))
#define GRAPHENE_DEFAULT_BURN_PERCENT_OF_FEE (20*GRAPHENE_1_PERCENT)
#define GRAPHENE_DEFAULT_WITNESS_PAY_PERCENT_OF_ACCUMULATED ( 1728000) /// gives a half life of 1 year assuming 1 second blocks
#define GRAPHENE_WITNESS_PAY_PERCENT_PRECISION (1000000000)
#define GRAPHENE_GENESIS_TIMESTAMP (1431700000) /// Should be divisible by GRAPHENE_DEFAULT_BLOCK_INTERVAL

View file

@ -19,6 +19,8 @@
#include <graphene/chain/types.hpp>
#include <graphene/chain/operations.hpp>
#include <numeric>
// this is for htonl() and ntohl() functions
// TODO: write and use FC wrappers for these functions
#ifndef WIN32

View file

@ -416,8 +416,7 @@ namespace graphene { namespace chain {
struct chain_parameters
{
fee_schedule_type current_fees; ///< current schedule of fees, indexed by @ref fee_type
uint32_t witness_pay_percent_of_accumulated = GRAPHENE_DEFAULT_WITNESS_PAY_PERCENT_OF_ACCUMULATED; ///< percentage of accumulated fees in core asset to pay to witnesses for block production
fee_schedule_type current_fees; ///< current schedule of fees
uint8_t block_interval = GRAPHENE_DEFAULT_BLOCK_INTERVAL; ///< interval in seconds between blocks
uint32_t maintenance_interval = GRAPHENE_DEFAULT_MAINTENANCE_INTERVAL; ///< interval in sections between blockchain maintenance events
uint32_t maximum_transaction_size = GRAPHENE_DEFAULT_MAX_TRANSACTION_SIZE; ///< maximum allowable size in bytes for a transaction
@ -454,7 +453,6 @@ namespace graphene { namespace chain {
FC_ASSERT( bulk_discount_threshold_min <= bulk_discount_threshold_max );
FC_ASSERT( bulk_discount_threshold_min > 0 );
FC_ASSERT( witness_pay_percent_of_accumulated < GRAPHENE_WITNESS_PAY_PERCENT_PRECISION );
FC_ASSERT( block_interval <= GRAPHENE_MAX_BLOCK_INTERVAL );
FC_ASSERT( block_interval > 0 );
FC_ASSERT( maintenance_interval > block_interval,
@ -575,7 +573,6 @@ FC_REFLECT( graphene::chain::fee_schedule_type,
FC_REFLECT( graphene::chain::chain_parameters,
(current_fees)
(witness_pay_percent_of_accumulated)
(block_interval)
(maintenance_interval)
(maximum_transaction_size)

View file

@ -763,9 +763,11 @@ public:
account_object account_obj = get_account(name);
FC_ASSERT( !account_obj.is_lifetime_member() );
// TODO
signed_transaction tx;
account_upgrade_operation op;
op.account_to_upgrade = account_obj.get_id();
op.upgrade_to_lifetime_member = true;
tx.operations = {op};
tx.visit( operation_set_fee( _remote_db->get_global_properties().parameters.current_fees ) );
tx.validate();

View file

@ -119,6 +119,7 @@ void database_fixture::verify_asset_supplies( )const
for( const account_statistics_object& a : statistics_index )
{
reported_core_in_orders += a.total_core_in_orders;
total_balances[asset_id_type()] += a.pending_fees;
}
for( const limit_order_object& o : db.get_index_type<limit_order_index>().indices() )
{
@ -672,7 +673,8 @@ void database_fixture::enable_fees(
{
fc::reflector<fee_schedule_type>::visit(fee_schedule_type::fee_set_visitor{gpo.parameters.current_fees,
uint32_t(fee.value)});
gpo.parameters.current_fees.membership_annual_fee = 10*fee.value;
gpo.parameters.current_fees.membership_annual_fee = 3*fee.value;
gpo.parameters.current_fees.membership_lifetime_fee = 10*fee.value;
} );
}
@ -685,9 +687,12 @@ void database_fixture::upgrade_to_lifetime_member( const account_object& account
{
try
{
// TODO
account_upgrade_operation op;
op.account_to_upgrade = account.get_id();
op.upgrade_to_lifetime_member = true;
trx.operations = {op};
db.push_transaction( trx, ~0 );
FC_ASSERT( account.is_lifetime_member() );
FC_ASSERT( op.account_to_upgrade(db).is_lifetime_member() );
trx.clear();
}
FC_CAPTURE_AND_RETHROW((account))

View file

@ -816,6 +816,7 @@ BOOST_FIXTURE_TEST_CASE( max_authority_membership, database_fixture )
private_key_type sam_key = generate_private_key("sam");
account_object sam_account_object = create_account( "sam", sam_key );
upgrade_to_lifetime_member(sam_account_object);
account_object genesis_account_object = genesis_account(db);
const asset_object& core = asset_id_type()(db);

View file

@ -107,6 +107,7 @@ BOOST_AUTO_TEST_CASE( child_account )
const auto& nathan_key = register_key(nathan_private_key.get_public_key());
const account_object& nathan = get_account("nathan");
const account_object& root = create_account("root");
upgrade_to_lifetime_member(root);
skip_key_index_test = true;
db.modify(nathan, [nathan_key](account_object& a) {
@ -128,7 +129,7 @@ BOOST_AUTO_TEST_CASE( child_account )
BOOST_REQUIRE_THROW(db.push_transaction(trx), fc::exception);
trx.signatures.clear();
op.owner = authority(1, account_id_type(nathan.id), 1);
trx.operations.back() = op;
trx.operations = {op};
sign(trx, key_id_type(), fc::ecc::private_key::regenerate(fc::sha256::hash(string("genesis"))));
sign(trx, nathan_key.id, nathan_private_key);
db.push_transaction(trx);
@ -186,13 +187,16 @@ BOOST_AUTO_TEST_CASE( update_account )
transfer(account_id_type()(db), nathan, asset(3000000));
enable_fees();
// TODO: op.upgrade_to_prime = true;
op.fee = op.calculate_fee( db.get_global_properties().parameters.current_fees );
trx.operations.push_back(op);
db.push_transaction(trx, ~0);
{
account_upgrade_operation op;
op.account_to_upgrade = nathan.id;
op.upgrade_to_lifetime_member = true;
op.fee = op.calculate_fee(db.get_global_properties().parameters.current_fees);
trx.operations = {op};
db.push_transaction(trx, ~0);
}
BOOST_CHECK( nathan.referrer == nathan.id );
BOOST_CHECK( nathan.referrer_rewards_percentage == 100 );
BOOST_CHECK( nathan.is_lifetime_member() );
} catch (fc::exception& e) {
edump((e.to_detail_string()));
throw;
@ -1866,13 +1870,13 @@ BOOST_AUTO_TEST_CASE( witness_withdraw_pay_test )
const asset_object* core = &asset_id_type()(db);
const account_object* nathan = &get_account("nathan");
enable_fees(100000000);
enable_fees(105000000);
BOOST_CHECK_GT(db.current_fee_schedule().membership_lifetime_fee, 0);
BOOST_CHECK_EQUAL(core->dynamic_asset_data_id(db).accumulated_fees.value, 0);
account_update_operation uop;
uop.account = nathan->get_id();
// TODO: uop.upgrade_to_prime = true;
account_upgrade_operation uop;
uop.account_to_upgrade = nathan->get_id();
uop.upgrade_to_lifetime_member = true;
trx.set_expiration(db.head_block_id());
trx.operations.push_back(uop);
trx.visit(operation_set_fee(db.current_fee_schedule()));
@ -1880,17 +1884,13 @@ BOOST_AUTO_TEST_CASE( witness_withdraw_pay_test )
trx.sign(key_id_type(),generate_private_key("genesis"));
db.push_transaction(trx);
trx.clear();
BOOST_CHECK_EQUAL(get_balance(*nathan, *core), 9000000000);
BOOST_CHECK_EQUAL(core->dynamic_asset_data_id(db).accumulated_fees.value, 210000000);
// TODO: Replace this with another check
//BOOST_CHECK_EQUAL(account_id_type()(db).statistics(db).cashback_rewards.value, 1000000000-210000000);
BOOST_CHECK_EQUAL(get_balance(*nathan, *core), 8950000000);
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_GT(core->dynamic_asset_data_id(db).accumulated_fees.value, 0);
BOOST_CHECK_EQUAL(witness->accumulated_income.value, 0);
auto schedule_maint = [&]()
@ -1900,7 +1900,7 @@ BOOST_AUTO_TEST_CASE( witness_withdraw_pay_test )
{
_dpo.next_maintenance_time = db.head_block_time() + 1;
} );
} ;
};
// generate some blocks
while( db.head_block_num() < 30 )
@ -1913,6 +1913,8 @@ BOOST_AUTO_TEST_CASE( witness_withdraw_pay_test )
// maintenance will be in block 31. time of block 31 - time of block 1 = 30 * 5 seconds.
schedule_maint();
// TODO: Replace this with another check
//BOOST_CHECK_EQUAL(account_id_type()(db).statistics(db).cashback_rewards.value, 1000000000-200000000);
// first witness paid from old budget (so no pay)
BOOST_CHECK_EQUAL( core->burned(db).value, 0 );
generate_block();