diff --git a/libraries/chain/account_evaluator.cpp b/libraries/chain/account_evaluator.cpp index 3fd2b0ec..5883459c 100644 --- a/libraries/chain/account_evaluator.cpp +++ b/libraries/chain/account_evaluator.cpp @@ -24,22 +24,13 @@ namespace graphene { namespace chain { void_result account_create_evaluator::do_evaluate( const account_create_operation& op ) { try { - FC_ASSERT( db().find_object(op.voting_account) ); - FC_ASSERT( is_relative(op.memo_key) || db().find_object(op.memo_key) ); + database& d = db(); + FC_ASSERT( d.find_object(op.voting_account) ); + FC_ASSERT( is_relative(op.memo_key) || d.find_object(op.memo_key) ); + FC_ASSERT( fee_paying_account->is_lifetime_member() ); + FC_ASSERT( op.referrer(d).is_member(d.head_block_time()) ); - if( fee_paying_account->is_prime() ) - { - FC_ASSERT( op.referrer(db()).is_prime() ); - } - else - { - FC_ASSERT( op.referrer == fee_paying_account->referrer ); - FC_ASSERT( op.referrer_percent == fee_paying_account->referrer_percent, "", - ("op",op) - ("fee_paying_account->referral_percent",fee_paying_account->referrer_percent) ); - } - - const auto& global_props = db().get_global_properties(); + const auto& global_props = d.get_global_properties(); uint32_t max_vote_id = global_props.next_available_vote_id; const auto& chain_params = global_props.parameters; FC_ASSERT( op.num_witness <= chain_params.maximum_witness_count ); @@ -48,11 +39,11 @@ void_result account_create_evaluator::do_evaluate( const account_create_operatio FC_ASSERT( op.active.auths.size() <= chain_params.maximum_authority_membership ); for( auto id : op.owner.auths ) { - FC_ASSERT( is_relative(id.first) || db().find(id.first) ); + FC_ASSERT( is_relative(id.first) || d.find_object(id.first) ); } for( auto id : op.active.auths ) { - FC_ASSERT( is_relative(id.first) || db().find(id.first) ); + FC_ASSERT( is_relative(id.first) || d.find_object(id.first) ); } safe counts[vote_id_type::VOTE_TYPE_COUNT]; for( auto id : op.vote ) @@ -67,7 +58,7 @@ void_result account_create_evaluator::do_evaluate( const account_create_operatio "", ("count", counts[vote_id_type::committee])("num", op.num_committee)); - auto& acnt_indx = db().get_index_type(); + auto& acnt_indx = d.get_index_type(); if( op.name.size() ) { auto current_account_itr = acnt_indx.indices().get().find( op.name ); @@ -76,7 +67,7 @@ void_result account_create_evaluator::do_evaluate( const account_create_operatio // TODO: this check can be removed after GRAPHENE_LEGACY_NAME_IMPORT_PERIOD // legacy account check - if( db().get_dynamic_global_properties().head_block_number < GRAPHENE_LEGACY_NAME_IMPORT_PERIOD ) + if( d.get_dynamic_global_properties().head_block_number < GRAPHENE_LEGACY_NAME_IMPORT_PERIOD ) { auto legacy_account_itr = acnt_indx.indices().get().find( "bts-"+op.name ); if( legacy_account_itr != acnt_indx.indices().get().end() ) @@ -109,18 +100,15 @@ object_id_type account_create_evaluator::do_apply( const account_create_operatio }); const auto& new_acnt_object = db().create( [&]( account_object& obj ){ - if( fee_paying_account->is_prime() ) - { - obj.registrar = o.registrar; - obj.referrer = o.referrer; - obj.referrer_percent = o.referrer_percent; - } - else - { - obj.registrar = fee_paying_account->registrar; - obj.referrer = fee_paying_account->referrer; - obj.referrer_percent = fee_paying_account->referrer_percent; - } + obj.registrar = o.registrar; + obj.referrer = o.referrer; + obj.lifetime_referrer = o.referrer(db()).lifetime_referrer; + + auto& params = db().get_global_properties().parameters; + obj.network_fee_percentage = params.network_percent_of_fee; + obj.lifetime_referrer_fee_percentage = params.lifetime_referrer_percent_of_fee; + obj.referrer_rewards_percentage = o.referrer_percent; + obj.name = o.name; obj.owner = owner; obj.active = active; @@ -138,7 +126,7 @@ object_id_type account_create_evaluator::do_apply( const account_create_operatio void_result account_update_evaluator::do_evaluate( const account_update_operation& o ) { - database& d = db(); + database& d = db(); FC_ASSERT( !o.memo_key || is_relative(*o.memo_key) || db().find_object(*o.memo_key) ); @@ -163,7 +151,6 @@ void_result account_update_evaluator::do_evaluate( const account_update_operatio } acnt = &o.account(d); - if( o.upgrade_to_prime ) FC_ASSERT( !acnt->is_prime() ); if( o.vote ) { @@ -184,11 +171,6 @@ void_result account_update_evaluator::do_apply( const account_update_operation& if( o.voting_account ) a.voting_account = *o.voting_account; if( o.memo_key ) a.memo_key = *o.memo_key; if( o.vote ) a.votes = *o.vote; - if( o.upgrade_to_prime ) - { - a.referrer_percent = 100; - a.referrer = a.id; - } a.num_witness = o.num_witness; a.num_committee = o.num_committee; }); @@ -200,8 +182,8 @@ void_result account_whitelist_evaluator::do_evaluate(const account_whitelist_ope database& d = db(); listed_account = &o.account_to_list(d); - if( !d.get_global_properties().parameters.allow_non_prime_whitelists ) - FC_ASSERT(listed_account->is_prime()); + if( !d.get_global_properties().parameters.allow_non_member_whitelists ) + FC_ASSERT(o.authorizing_account(d).is_lifetime_member()); return void_result(); } FC_CAPTURE_AND_RETHROW( (o) ) } diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index df397870..b0adbd1c 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -174,74 +174,6 @@ void database::update_active_delegates() }); } FC_CAPTURE_AND_RETHROW() } -void database::update_vote_totals(const global_property_object& props) -{ try { - _vote_tally_buffer.resize(props.next_available_vote_id); - _witness_count_histogram_buffer.resize(props.parameters.maximum_witness_count / 2 + 1); - _committee_count_histogram_buffer.resize(props.parameters.maximum_committee_count / 2 + 1); - - const account_index& account_idx = get_index_type(); - _total_voting_stake = 0; - - bool count_non_prime_votes = props.parameters.count_non_prime_votes; - auto timestamp = fc::time_point::now(); - for( const account_object& stake_account : account_idx.indices() ) - { - if( count_non_prime_votes || stake_account.is_prime() ) - { - // There may be a difference between the account whose stake is voting and the one specifying opinions. - // Usually they're the same, but if the stake account has specified a voting_account, that account is the one - // specifying the opinions. - const account_object& opinion_account = - (stake_account.voting_account == account_id_type())? stake_account - : get(stake_account.voting_account); - - const auto& stats = stake_account.statistics(*this); - uint64_t voting_stake = stats.total_core_in_orders.value - + (stake_account.cashback_vb.valid() ? (*stake_account.cashback_vb)(*this).balance.amount.value: 0) - + get_balance(stake_account.get_id(), asset_id_type()).amount.value; - - for( vote_id_type id : opinion_account.votes ) - { - uint32_t offset = id.instance(); - // if they somehow managed to specify an illegal offset, ignore it. - if( offset < _vote_tally_buffer.size() ) - _vote_tally_buffer[ offset ] += voting_stake; - } - - if( opinion_account.num_witness <= props.parameters.maximum_witness_count ) - { - uint16_t offset = std::min(size_t(opinion_account.num_witness/2), - _witness_count_histogram_buffer.size() - 1); - // - // votes for a number greater than maximum_witness_count - // are turned into votes for maximum_witness_count. - // - // in particular, this takes care of the case where a - // member was voting for a high number, then the - // parameter was lowered. - // - _witness_count_histogram_buffer[ offset ] += voting_stake; - } - if( opinion_account.num_committee <= props.parameters.maximum_committee_count ) - { - uint16_t offset = std::min(size_t(opinion_account.num_committee/2), - _committee_count_histogram_buffer.size() - 1); - // - // votes for a number greater than maximum_committee_count - // are turned into votes for maximum_committee_count. - // - // same rationale as for witnesses - // - _committee_count_histogram_buffer[ offset ] += voting_stake; - } - - _total_voting_stake += voting_stake; - } - } - ilog("Tallied votes in ${time} milliseconds.", ("time", (fc::time_point::now() - timestamp).count() / 1000.0)); -} FC_CAPTURE_AND_RETHROW() } - share_type database::get_max_budget( fc::time_point_sec now )const { const dynamic_global_property_object& dpo = get_dynamic_global_properties(); @@ -352,7 +284,154 @@ void database::process_budget() void database::perform_chain_maintenance(const signed_block& next_block, const global_property_object& global_props) { - update_vote_totals(global_props); + const auto& gpo = get_global_properties(); + + struct vote_tally_helper { + database& d; + const global_property_object& props; + + vote_tally_helper(database& d, const global_property_object& gpo) + : d(d), props(gpo) + { + d._vote_tally_buffer.resize(props.next_available_vote_id); + d._witness_count_histogram_buffer.resize(props.parameters.maximum_witness_count / 2 + 1); + d._committee_count_histogram_buffer.resize(props.parameters.maximum_committee_count / 2 + 1); + d._total_voting_stake = 0; + } + + void operator()(const account_object& stake_account) { + if( props.parameters.count_non_member_votes || stake_account.is_member(d.head_block_time()) ) + { + // There may be a difference between the account whose stake is voting and the one specifying opinions. + // Usually they're the same, but if the stake account has specified a voting_account, that account is the one + // specifying the opinions. + const account_object& opinion_account = + (stake_account.voting_account == account_id_type())? stake_account + : d.get(stake_account.voting_account); + + const auto& stats = stake_account.statistics(d); + uint64_t voting_stake = stats.total_core_in_orders.value + + (stake_account.cashback_vb.valid() ? (*stake_account.cashback_vb)(d).balance.amount.value: 0) + + d.get_balance(stake_account.get_id(), asset_id_type()).amount.value; + + for( vote_id_type id : opinion_account.votes ) + { + uint32_t offset = id.instance(); + // if they somehow managed to specify an illegal offset, ignore it. + if( offset < d._vote_tally_buffer.size() ) + d._vote_tally_buffer[ offset ] += voting_stake; + } + + if( opinion_account.num_witness <= props.parameters.maximum_witness_count ) + { + uint16_t offset = std::min(size_t(opinion_account.num_witness/2), + d._witness_count_histogram_buffer.size() - 1); + // votes for a number greater than maximum_witness_count + // are turned into votes for maximum_witness_count. + // + // in particular, this takes care of the case where a + // member was voting for a high number, then the + // parameter was lowered. + d._witness_count_histogram_buffer[ offset ] += voting_stake; + } + if( opinion_account.num_committee <= props.parameters.maximum_committee_count ) + { + uint16_t offset = std::min(size_t(opinion_account.num_committee/2), + d._committee_count_histogram_buffer.size() - 1); + // votes for a number greater than maximum_committee_count + // are turned into votes for maximum_committee_count. + // + // same rationale as for witnesses + d._committee_count_histogram_buffer[ offset ] += voting_stake; + } + + d._total_voting_stake += voting_stake; + } + } + } tally_helper(*this, gpo); + struct process_fees_helper { + database& d; + const global_property_object& props; + + process_fees_helper(database& d, const global_property_object& gpo) + : d(d), props(gpo) {} + + void operator()(const account_object& a) { + const account_statistics_object& stats = a.statistics(d); + + auto cut_fee = [](share_type a, uint16_t p) -> share_type + { + fc::uint128 r(a.value); + r *= p; + r /= GRAPHENE_100_PERCENT; + return r.to_uint64(); + }; + + if( stats.pending_fees > 0 ) + { + share_type core_fee_subtotal(stats.pending_fees); + share_type bulk_cashback = share_type(0); + if( stats.lifetime_fees_paid > props.parameters.bulk_discount_threshold_min && + a.is_member(d.head_block_time()) ) + { + uint64_t bulk_discount_percent = 0; + if( stats.lifetime_fees_paid >= props.parameters.bulk_discount_threshold_max ) + bulk_discount_percent = props.parameters.max_bulk_discount_percent_of_fee; + else if(props.parameters.bulk_discount_threshold_max.value != + props.parameters.bulk_discount_threshold_min.value) + { + bulk_discount_percent = + (props.parameters.max_bulk_discount_percent_of_fee * + (stats.lifetime_fees_paid.value - + props.parameters.bulk_discount_threshold_min.value)) / + (props.parameters.bulk_discount_threshold_max.value - + props.parameters.bulk_discount_threshold_min.value); + } + assert( bulk_discount_percent <= GRAPHENE_100_PERCENT ); + assert( bulk_discount_percent >= 0 ); + + bulk_cashback = cut_fee(core_fee_subtotal, bulk_discount_percent); + assert( bulk_cashback <= core_fee_subtotal ); + } + + share_type core_fee_total = core_fee_subtotal - bulk_cashback; + share_type network_cut = cut_fee(core_fee_total, a.network_fee_percentage); + assert( network_cut <= core_fee_total ); + 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; + + d.modify(dynamic_asset_data_id_type()(d), [burned,accumulated](asset_dynamic_data_object& d) { + d.accumulated_fees += accumulated + burned; + }); + + d.modify(a.statistics(d), [core_fee_total](account_statistics_object& s) { + s.lifetime_fees_paid += core_fee_total; + s.pending_fees = 0; + }); + + 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; + + 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 ); + } + } + } fees_helper(*this, gpo); + + perform_account_maintenance(std::tie(tally_helper, fees_helper)); struct clear_canary { clear_canary(vector& target): target(target){} diff --git a/libraries/chain/delegate_evaluator.cpp b/libraries/chain/delegate_evaluator.cpp index 06fca086..b86409f8 100644 --- a/libraries/chain/delegate_evaluator.cpp +++ b/libraries/chain/delegate_evaluator.cpp @@ -24,7 +24,7 @@ namespace graphene { namespace chain { object_id_type delegate_create_evaluator::do_evaluate( const delegate_create_operation& op ) { - FC_ASSERT(db().get(op.delegate_account).is_prime()); + FC_ASSERT(db().get(op.delegate_account).is_lifetime_member()); return object_id_type(); } diff --git a/libraries/chain/evaluator.cpp b/libraries/chain/evaluator.cpp index 8614d0fb..74cf5c14 100644 --- a/libraries/chain/evaluator.cpp +++ b/libraries/chain/evaluator.cpp @@ -61,55 +61,14 @@ namespace graphene { namespace chain { void generic_evaluator::pay_fee() { try { - asset core_fee_subtotal(core_fee_paid); - const auto& gp = db().get_global_properties(); - share_type bulk_cashback = share_type(0); - if( fee_paying_account_statistics->lifetime_fees_paid > gp.parameters.bulk_discount_threshold_min && - fee_paying_account->is_prime() ) - { - uint64_t bulk_discount_percent = 0; - if( fee_paying_account_statistics->lifetime_fees_paid > gp.parameters.bulk_discount_threshold_max ) - bulk_discount_percent = gp.parameters.max_bulk_discount_percent_of_fee; - else if(gp.parameters.bulk_discount_threshold_max.value - gp.parameters.bulk_discount_threshold_min.value != 0) - { - bulk_discount_percent = - (gp.parameters.max_bulk_discount_percent_of_fee * - (fee_paying_account_statistics->lifetime_fees_paid.value - - gp.parameters.bulk_discount_threshold_min.value)) / - (gp.parameters.bulk_discount_threshold_max.value - gp.parameters.bulk_discount_threshold_min.value); - } - assert( bulk_discount_percent <= GRAPHENE_100_PERCENT ); - assert( bulk_discount_percent >= 0 ); - - bulk_cashback = (core_fee_subtotal.amount.value * bulk_discount_percent) / GRAPHENE_100_PERCENT; - assert( bulk_cashback <= core_fee_subtotal.amount ); - } - - share_type core_fee_total = core_fee_subtotal.amount - bulk_cashback; - share_type accumulated = (core_fee_total.value * gp.parameters.witness_percent_of_fee)/GRAPHENE_100_PERCENT; - share_type burned = (core_fee_total.value * gp.parameters.burn_percent_of_fee)/GRAPHENE_100_PERCENT; - share_type referral = core_fee_total.value - accumulated - burned; - auto& d = db(); - - assert( accumulated + burned <= core_fee_total ); - if( fee_asset->get_id() != asset_id_type() ) - d.modify(*fee_asset_dyn_data, [this](asset_dynamic_data_object& d) { + db().modify(*fee_asset_dyn_data, [this](asset_dynamic_data_object& d) { d.accumulated_fees += fee_from_account.amount; d.fee_pool -= core_fee_paid; }); - d.modify(dynamic_asset_data_id_type()(d), [burned,accumulated](asset_dynamic_data_object& d) { - d.accumulated_fees += accumulated + burned; + db().modify(*fee_paying_account_statistics, [&](account_statistics_object& s) { + s.pending_fees += core_fee_paid; }); - - d.modify(fee_paying_account->statistics(d), [core_fee_total](account_statistics_object& s) { - s.lifetime_fees_paid += core_fee_total; - }); - - d.deposit_cashback( fee_paying_account->referrer(d), referral ); - d.deposit_cashback( *fee_paying_account, bulk_cashback ); - - assert( referral + bulk_cashback + accumulated + burned == core_fee_subtotal.amount ); } FC_CAPTURE_AND_RETHROW() } bool generic_evaluator::verify_authority( const account_object& a, authority::classification c ) diff --git a/libraries/chain/include/graphene/chain/account_object.hpp b/libraries/chain/include/graphene/chain/account_object.hpp index fa63da5f..9306a486 100644 --- a/libraries/chain/include/graphene/chain/account_object.hpp +++ b/libraries/chain/include/graphene/chain/account_object.hpp @@ -39,32 +39,34 @@ namespace graphene { namespace chain { static const uint8_t type_id = impl_account_statistics_object_type; /** - * Keep the most recent operation as a root pointer to - * a linked list of the transaction history. This field is - * not required by core validation and could in theory be - * made an annotation on the account object, but because - * transaction history is so common and this object is already - * cached in the undo buffer (because it likely affected the - * balances of this account) it is convienent to simply - * track this data here. Account balance objects don't currenty - * inherit from annotated object. + * Keep the most recent operation as a root pointer to a linked list of the transaction history. This field is + * not required by core validation and could in theory be made an annotation on the account object, but + * because transaction history is so common and this object is already cached in the undo buffer (because it + * likely affected the balances of this account) it is convienent to simply track this data here. Account + * balance objects don't currenty inherit from annotated object. */ account_transaction_history_id_type most_recent_op; /** - * When calculating votes it is necessary to know how much is - * stored in orders (and thus unavailable for transfers). Rather - * than maintaining an index of [asset,owner,order_id] we will - * simply maintain the running total here and update it every - * time an order is created or modified. + * When calculating votes it is necessary to know how much is stored in orders (and thus unavailable for + * transfers). Rather than maintaining an index of [asset,owner,order_id] we will simply maintain the running + * total here and update it every time an order is created or modified. */ - share_type total_core_in_orders; + share_type total_core_in_orders; /** - * Tracks the total fees paid by this account for the purpose - * of calculating bulk discounts. + * Tracks the total fees paid by this account for the purpose of calculating bulk discounts. */ - share_type lifetime_fees_paid; + share_type lifetime_fees_paid; + + /** + * Tracks the fees paid by this account which have not been disseminated to the various parties that receive + * them yet (registrar, referrer, lifetime referrer, network, etc). This is used as an optimization to avoid + * doing massive amounts of uint128 math on each and every operation. + * + * These fees will be paid out and this counter will reset during the maintenance interval. + */ + share_type pending_fees; }; /** @@ -102,53 +104,54 @@ namespace graphene { namespace chain { public: static const uint8_t space_id = protocol_ids; static const uint8_t type_id = account_object_type; - /** - * The account that paid the fee to register this account, this account is - * known as the primary referrer and is entitled to a percent of transaction - * fees. - */ - account_id_type registrar; /** - * The registrar may be a faucet with its own revenue sharing model that allows - * users to refer each other. + * The time at which this account's membership expires. + * If set to any time in the past, the account is a basic account. + * If set to time_point_sec::maximum(), the account is a lifetime member. + * If set to any time not in the past less than time_point_sec::maximum(), the account is an annual member. + * + * See @ref is_lifetime_member, @ref is_basic_account, @ref is_annual_member, and @ref is_member */ - account_id_type referrer; + time_point_sec membership_expiration_date; - /** - * Any referral fees not paid to referrer are paid to registrar - */ - uint8_t referrer_percent = 0; + ///The account that paid the fee to register this account. Receives a percentage of referral rewards. + account_id_type registrar; + /// The account credited as referring this account. Receives a percentage of referral rewards. + account_id_type referrer; + /// The lifetime member at the top of the referral tree. Receives a percentage of referral rewards. + account_id_type lifetime_referrer; + /// Percentage of fee which should go to network. + uint16_t network_fee_percentage; + /// Percentage of fee which should go to lifetime referrer. + uint16_t lifetime_referrer_fee_percentage = 0; + /// Percentage of referral rewards (leftover fee after paying network and lifetime referrer) which should go + /// to referrer. The remainder of referral rewards goes to the registrar. + uint16_t referrer_rewards_percentage = 0; - /// The account's name. This name must be unique among all account names on the graph. The name may be empty. - string name; - + /// The account's name. This name must be unique among all account names on the graph. May not be empty. + string name; /** * The owner authority represents absolute control over the account. Usually the keys in this authority will * be kept in cold storage, as they should not be needed very often and compromise of these keys constitutes * complete and irrevocable loss of the account. Generally the only time the owner authority is required is to * update the active authority. */ - authority owner; - + authority owner; /// The owner authority contains the hot keys of the account. This authority has control over nearly all /// operations the account may perform. - authority active; - + authority active; /// The memo key is the key this account will typically use to encrypt/sign transaction memos and other non- /// validated account activities. This field is here to prevent confusion if the active authority has zero or /// multiple keys in it. - key_id_type memo_key; - + key_id_type memo_key; /// If this field is set to an account ID other than 0, this account's votes will be ignored and its stake /// will be counted as voting for the referenced account's selected votes instead. - account_id_type voting_account; - - - uint16_t num_witness = 0; - uint16_t num_committee = 0; + account_id_type voting_account; + uint16_t num_witness = 0; + uint16_t num_committee = 0; /// This is the list of vote IDs this account votes for. The weight of these votes is determined by this /// account's balance of core asset. flat_set votes; @@ -163,7 +166,7 @@ namespace graphene { namespace chain { * account cannot update this set, except by transferring ownership of the account, which will clear it. Other * accounts may add or remove their IDs from this set. */ - flat_set whitelisting_accounts; + flat_set whitelisting_accounts; /** * This is a set of all accounts which have 'blacklisted' this account. Blacklisting is only used in core @@ -171,20 +174,34 @@ namespace graphene { namespace chain { * account cannot update this set, and it will be preserved even if the account is transferred. Other accounts * may add or remove their IDs from this set. */ - flat_set blacklisting_accounts; + flat_set blacklisting_accounts; /** * Vesting balance which receives cashback_reward deposits. */ optional cashback_vb; - /** - * @return true if this is a prime account, false otherwise. - */ - bool is_prime()const + /// @return true if this is a lifetime member account; false otherwise. + bool is_lifetime_member()const { return get_id() == referrer; } + /// @return true if this is a basic account; false otherwise. + bool is_basic_account(time_point_sec now)const + { + return now > membership_expiration_date; + } + /// @return true if the account is an unexpired annual member; false otherwise. + /// @note This method will return false for lifetime members. + bool is_annual_member(time_point_sec now)const + { + return !is_lifetime_member() && !is_basic_account(now); + } + /// @return true if the account is an annual or lifetime member; false otherwise. + bool is_member(time_point_sec now)const + { + return !is_basic_account(now); + } /** * @return true if this account is whitelisted and not blacklisted to transact in the provided asset; false @@ -253,9 +270,12 @@ namespace graphene { namespace chain { typedef generic_index account_index; }} + FC_REFLECT_DERIVED( graphene::chain::account_object, (graphene::db::annotated_object), - (registrar)(referrer)(referrer_percent)(name)(owner)(active)(memo_key)(voting_account)(num_witness)(num_committee)(votes) + (membership_expiration_date)(registrar)(referrer)(lifetime_referrer) + (network_fee_percentage)(lifetime_referrer_fee_percentage)(referrer_rewards_percentage) + (name)(owner)(active)(memo_key)(voting_account)(num_witness)(num_committee)(votes) (statistics)(whitelisting_accounts)(blacklisting_accounts)(cashback_vb) ) FC_REFLECT_DERIVED( graphene::chain::account_balance_object, diff --git a/libraries/chain/include/graphene/chain/config.hpp b/libraries/chain/include/graphene/chain/config.hpp index 74ae5163..75ca540c 100644 --- a/libraries/chain/include/graphene/chain/config.hpp +++ b/libraries/chain/include/graphene/chain/config.hpp @@ -49,6 +49,7 @@ #define GRAPHENE_DEFAULT_TRANSFER_FEE (1*GRAPHENE_BLOCKCHAIN_PRECISION) #define GRAPHENE_MAX_INSTANCE_ID (uint64_t(-1)>>16) #define GRAPHENE_100_PERCENT 10000 +#define GRAPHENE_1_PERCENT (GRAPHENE_100_PERCENT/100) /** NOTE: making this a power of 2 (say 2^15) would greatly accelerate fee calcs */ #define GRAPHENE_MAX_MARKET_FEE_PERCENT GRAPHENE_100_PERCENT #define GRAPHENE_DEFAULT_FORCE_SETTLEMENT_DELAY (60*60*24) ///< 1 day @@ -72,12 +73,14 @@ #define GRAPHENE_DEFAULT_MAX_COMMITTEE (1001) // SHOULD BE ODD #define GRAPHENE_DEFAULT_MAX_PROPOSAL_LIFETIME_SEC (60*60*24*7*4) // Four weeks #define GRAPHENE_DEFAULT_GENESIS_PROPOSAL_REVIEW_PERIOD_SEC (60*60*24*7*2) // Two weeks -#define GRAPHENE_DEFAULT_WITNESS_PERCENT (10000/100) // 1% -#define GRAPHENE_DEFAULT_MAX_BULK_DISCOUNT_PERCENT (10000/2) // 50% +#define GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE (20*GRAPHENE_1_PERCENT) +#define GRAPHENE_DEFAULT_LIFETIME_REFERRER_PERCENT_OF_FEE (30*GRAPHENE_1_PERCENT) +#define GRAPHENE_DEFAULT_MAX_BULK_DISCOUNT_PERCENT (50*GRAPHENE_1_PERCENT) #define GRAPHENE_DEFAULT_BULK_DISCOUNT_THRESHOLD_MIN ( GRAPHENE_BLOCKCHAIN_PRECISION*int64_t(1000) ) #define GRAPHENE_DEFAULT_BULK_DISCOUNT_THRESHOLD_MAX ( GRAPHENE_DEFAULT_BULK_DISCOUNT_THRESHOLD_MIN*int64_t(100) ) #define GRAPHENE_DEFAULT_CASHBACK_VESTING_PERIOD_SEC (60*60*24*365) ///< 1 year -#define GRAPHENE_DEFAULT_BURN_PERCENT_OF_FEE (10000/5) // 20% +#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 diff --git a/libraries/chain/include/graphene/chain/database.hpp b/libraries/chain/include/graphene/chain/database.hpp index 2580d63a..7a3f320d 100644 --- a/libraries/chain/include/graphene/chain/database.hpp +++ b/libraries/chain/include/graphene/chain/database.hpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -357,7 +358,9 @@ namespace graphene { namespace chain { void perform_chain_maintenance(const signed_block& next_block, const global_property_object& global_props); void update_active_witnesses(); void update_active_delegates(); - void update_vote_totals(const global_property_object& props); + + template + void perform_account_maintenance(std::tuple helpers); ///@} ///@} @@ -394,4 +397,29 @@ namespace graphene { namespace chain { uint64_t _total_voting_stake; }; + namespace detail + { + template + struct seq { }; + + template + struct gen_seq : gen_seq { }; + + template + struct gen_seq<0, Is...> : seq { }; + + template + void for_each(T&& t, const account_object& a, seq) + { + auto l = { (std::get(t)(a), 0)... }; + } + } + template + void database::perform_account_maintenance(std::tuple helpers) + { + const auto& idx = get_index_type().indices(); + for( const account_object& a : idx ) + detail::for_each(helpers, a, detail::gen_seq()); + } + } } diff --git a/libraries/chain/include/graphene/chain/operations.hpp b/libraries/chain/include/graphene/chain/operations.hpp index 9353568b..4f86f7e0 100644 --- a/libraries/chain/include/graphene/chain/operations.hpp +++ b/libraries/chain/include/graphene/chain/operations.hpp @@ -15,7 +15,7 @@ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* Copyright (C) Cryptonomex, Inc - All Rights Reserved +/* Copyright (C) Cryptonomex, Inc - All Rights Reserved * * All modifications become property of Cryptonomex, Inc. * @@ -125,14 +125,13 @@ namespace graphene { namespace chain { struct account_create_operation { asset fee; + /// This account pays the fee. Must be a lifetime member. account_id_type registrar; - /** - * If fee_paying_account->is_prime then referrer can be - * any other account that is also prime. Otherwise referrer must - * equal fee_paying_account->referrer. - */ + /// This account receives a portion of the fee split between registrar and referrer. Must be a member. account_id_type referrer; + /// Of the fee split between registrar and referrer, this percentage goes to the referrer. The rest goes to the + /// registrar. uint8_t referrer_percent = 0; string name; @@ -214,12 +213,6 @@ namespace graphene { namespace chain { uint16_t num_witness = 0; uint16_t num_committee = 0; - /** - * If set to true, upgrades the account to a prime account by setting the account's referrer to itself. This may - * only be set to true when the account being modified is not already a prime account. - */ - bool upgrade_to_prime = false; - account_id_type fee_payer()const { return account; } void get_required_auth(flat_set& active_auth_set , flat_set& owner_auth_set)const; void validate()const; @@ -1089,13 +1082,13 @@ namespace graphene { namespace chain { * authorizing account. This operation is primarily useful for scheduling recurring payments. * * Withdrawal permissions define withdrawal periods, which is a span of time during which the authorized account may - * make a withdrawal. Any number of withdraws may be made so long as the total amount withdrawn is less than the limit - * for any given period. + * make a withdrawal. Any number of withdrawals may be made so long as the total amount withdrawn per period does + * not exceed the limit for any given period. * * Withdrawal permissions authorize only a specific pairing, i.e. a permission only authorizes one specified * authorized account to withdraw from one specified authorizing account. Withdrawals are limited and may not exceet - * the withdrawal limit. The withdrawal must be made in the same asset as the limit; attempts with withdraw any other - * asset type will be rejected. + * the withdrawal limit. The withdrawal must be made in the same asset as the limit; attempts with withdraw any + * other asset type will be rejected. * * The fee for this operation is paid by withdraw_from_account, and this account is required to authorize this * operation. @@ -1748,7 +1741,7 @@ FC_REFLECT( graphene::chain::account_create_operation, FC_REFLECT_TYPENAME( fc::flat_set ) FC_REFLECT( graphene::chain::account_update_operation, - (fee)(account)(owner)(active)(voting_account)(memo_key)(num_witness)(num_committee)(vote)(upgrade_to_prime) + (fee)(account)(owner)(active)(voting_account)(memo_key)(num_witness)(num_committee)(vote) ) FC_REFLECT_TYPENAME( graphene::chain::account_whitelist_operation::account_listing) diff --git a/libraries/chain/include/graphene/chain/types.hpp b/libraries/chain/include/graphene/chain/types.hpp index 2fe3e855..70b3ecec 100644 --- a/libraries/chain/include/graphene/chain/types.hpp +++ b/libraries/chain/include/graphene/chain/types.hpp @@ -460,23 +460,26 @@ namespace graphene { namespace chain { uint16_t maximum_witness_count = GRAPHENE_DEFAULT_MAX_WITNESSES; ///< maximum number of active witnesses uint16_t maximum_committee_count = GRAPHENE_DEFAULT_MAX_COMMITTEE; ///< maximum number of active delegates uint16_t maximum_authority_membership = GRAPHENE_DEFAULT_MAX_AUTHORITY_MEMBERSHIP; ///< largest number of keys/accounts an authority can have - uint16_t burn_percent_of_fee = GRAPHENE_DEFAULT_BURN_PERCENT_OF_FEE; ///< the percentage of every fee that is taken out of circulation - uint16_t witness_percent_of_fee = GRAPHENE_DEFAULT_WITNESS_PERCENT; ///< percent of revenue paid to witnesses + uint16_t burn_percent_of_fee = GRAPHENE_DEFAULT_BURN_PERCENT_OF_FEE; ///< the percentage of the network's allocation of a fee that is taken out of circulation + uint16_t network_percent_of_fee = GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE; ///< percent of transaction fees paid to network + uint16_t lifetime_referrer_percent_of_fee = GRAPHENE_DEFAULT_LIFETIME_REFERRER_PERCENT_OF_FEE; ///< percent of transaction fees paid to network uint32_t cashback_vesting_period_seconds = GRAPHENE_DEFAULT_CASHBACK_VESTING_PERIOD_SEC; ///< time after cashback rewards are accrued before they become liquid + share_type cashback_vesting_threshold = GRAPHENE_DEFAULT_CASHBACK_VESTING_THRESHOLD; ///< the maximum cashback that can be received without vesting uint16_t max_bulk_discount_percent_of_fee = GRAPHENE_DEFAULT_MAX_BULK_DISCOUNT_PERCENT; ///< the maximum percentage discount for bulk discounts share_type bulk_discount_threshold_min = GRAPHENE_DEFAULT_BULK_DISCOUNT_THRESHOLD_MIN; ///< the minimum amount of fees paid to qualify for bulk discounts share_type bulk_discount_threshold_max = GRAPHENE_DEFAULT_BULK_DISCOUNT_THRESHOLD_MAX; ///< the amount of fees paid to qualify for the max bulk discount percent - bool count_non_prime_votes = true; ///< set to false to restrict voting privlegages to prime accounts - bool allow_non_prime_whitelists = false; ///< true if non-prime accounts may set whitelists and blacklists; false otherwise + 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) share_type worker_budget_per_day = GRAPHENE_DEFAULT_WORKER_BUDGET_PER_DAY; ///< CORE to be allocated to workers (per day) void validate()const { - FC_ASSERT( witness_percent_of_fee <= GRAPHENE_100_PERCENT ); FC_ASSERT( burn_percent_of_fee <= GRAPHENE_100_PERCENT ); + FC_ASSERT( network_percent_of_fee <= GRAPHENE_100_PERCENT ); FC_ASSERT( max_bulk_discount_percent_of_fee <= GRAPHENE_100_PERCENT ); - FC_ASSERT( burn_percent_of_fee + witness_percent_of_fee <= GRAPHENE_100_PERCENT ); + FC_ASSERT( lifetime_referrer_percent_of_fee <= GRAPHENE_100_PERCENT ); + FC_ASSERT( network_percent_of_fee + lifetime_referrer_percent_of_fee <= GRAPHENE_100_PERCENT ); FC_ASSERT( bulk_discount_threshold_min <= bulk_discount_threshold_max ); FC_ASSERT( bulk_discount_threshold_min > 0 ); @@ -656,13 +659,15 @@ FC_REFLECT( graphene::chain::chain_parameters, (maximum_asset_feed_publishers) (maximum_authority_membership) (burn_percent_of_fee) - (witness_percent_of_fee) + (network_percent_of_fee) + (lifetime_referrer_percent_of_fee) (max_bulk_discount_percent_of_fee) (cashback_vesting_period_seconds) + (cashback_vesting_threshold) (bulk_discount_threshold_min) (bulk_discount_threshold_max) - (count_non_prime_votes) - (allow_non_prime_whitelists) + (count_non_member_votes) + (allow_non_member_whitelists) (witness_pay_per_block) (worker_budget_per_day) ) diff --git a/libraries/chain/include/graphene/chain/withdraw_permission_object.hpp b/libraries/chain/include/graphene/chain/withdraw_permission_object.hpp index 8cb9bd59..a89d1cc1 100644 --- a/libraries/chain/include/graphene/chain/withdraw_permission_object.hpp +++ b/libraries/chain/include/graphene/chain/withdraw_permission_object.hpp @@ -28,9 +28,9 @@ namespace graphene { namespace chain { * * The primary purpose of this object is to enable recurring payments on the blockchain. An account which wishes to * process a recurring payment may use a @ref withdraw_permission_claim_operation to reference an object of this type - * and withdraw up to @ref withdrawal_limit from @ref withdraw_from_account. Only @ref authorized_account may do this. - * Any number of withdraws may be made so long as the total amount withdrawn is less than the limit for any given - * period. + * and withdraw up to @ref withdrawal_limit from @ref withdraw_from_account. Only @ref authorized_account may do + * this. Any number of withdrawals may be made so long as the total amount withdrawn per period does not exceed the + * limit for any given period. */ class withdraw_permission_object : public graphene::db::abstract_object { @@ -54,14 +54,14 @@ namespace graphene { namespace chain { /// tracks the total amount share_type claimed_this_period; /// True if the permission may still be claimed for this period; false if it has already been used - asset available_this_period( fc::time_point_sec current_time )const + asset available_this_period( fc::time_point_sec current_time )const { if( current_time >= period_start_time + withdrawal_period_sec ) return withdrawal_limit; return asset( ( withdrawal_limit.amount > claimed_this_period ) ? withdrawal_limit.amount - claimed_this_period - : 0, withdrawal_limit.asset_id ); + : 0, withdrawal_limit.asset_id ); } }; diff --git a/libraries/chain/operations.cpp b/libraries/chain/operations.cpp index ddd63008..70c7d75f 100644 --- a/libraries/chain/operations.cpp +++ b/libraries/chain/operations.cpp @@ -122,7 +122,6 @@ share_type account_create_operation::calculate_fee( const fee_schedule_type& sch } share_type account_update_operation::calculate_fee( const fee_schedule_type& schedule )const { - if( upgrade_to_prime ) return schedule.at(prime_upgrade_fee_type); return schedule.at(account_create_fee_type); } void account_update_operation::get_required_auth(flat_set& active_auth_set, @@ -138,7 +137,7 @@ void account_update_operation::validate()const { FC_ASSERT( fee.amount >= 0 ); FC_ASSERT( account != account_id_type() ); - FC_ASSERT( owner || active || voting_account || memo_key || vote || upgrade_to_prime ); + FC_ASSERT( owner || active || voting_account || memo_key || vote ); } diff --git a/libraries/chain/witness_evaluator.cpp b/libraries/chain/witness_evaluator.cpp index ee007122..b8f9a19f 100644 --- a/libraries/chain/witness_evaluator.cpp +++ b/libraries/chain/witness_evaluator.cpp @@ -25,7 +25,7 @@ namespace graphene { namespace chain { object_id_type witness_create_evaluator::do_evaluate( const witness_create_operation& op ) { - FC_ASSERT(db().get(op.witness_account).is_prime()); + FC_ASSERT(db().get(op.witness_account).is_lifetime_member()); return object_id_type(); } diff --git a/libraries/chain/worker_evaluator.cpp b/libraries/chain/worker_evaluator.cpp index a20e68ab..9faa8f29 100644 --- a/libraries/chain/worker_evaluator.cpp +++ b/libraries/chain/worker_evaluator.cpp @@ -26,7 +26,7 @@ object_id_type worker_create_evaluator::do_evaluate(const worker_create_evaluato { try { database& d = db(); - FC_ASSERT(d.get(o.owner).is_prime()); + FC_ASSERT(d.get(o.owner).is_lifetime_member()); FC_ASSERT(o.work_begin_date >= d.head_block_time()); return object_id_type(); diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index edc9b761..3af8a3be 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -695,7 +695,7 @@ public: account_object registrar_account_object = this->get_account( registrar_account ); - FC_ASSERT( registrar_account_object.is_prime() ); + FC_ASSERT( registrar_account_object.is_lifetime_member() ); account_id_type registrar_account_id = registrar_account_object.id; @@ -761,17 +761,11 @@ public: { try { FC_ASSERT( !self.is_locked() ); account_object account_obj = get_account(name); - FC_ASSERT( !account_obj.is_prime() ); - - account_update_operation update_op; - update_op.account = account_obj.id; - update_op.num_witness = account_obj.num_witness; - update_op.num_committee = account_obj.num_committee; - update_op.upgrade_to_prime = true; + FC_ASSERT( !account_obj.is_lifetime_member() ); + // TODO signed_transaction tx; - tx.operations.push_back( update_op ); tx.visit( operation_set_fee( _remote_db->get_global_properties().parameters.current_fees ) ); tx.validate(); @@ -802,7 +796,7 @@ public: account_object referrer_account_object = this->get_account( referrer_account ); account_create_op.referrer = referrer_account_object.id; - account_create_op.referrer_percent = referrer_account_object.referrer_percent; + account_create_op.referrer_percent = referrer_account_object.referrer_rewards_percentage; // get pay_from_account_id key_create_operation owner_key_create_op; diff --git a/tests/common/database_fixture.cpp b/tests/common/database_fixture.cpp index 713ad37d..7be7e4ed 100644 --- a/tests/common/database_fixture.cpp +++ b/tests/common/database_fixture.cpp @@ -676,21 +676,18 @@ void database_fixture::enable_fees( } ); } -void database_fixture::upgrade_to_prime(account_id_type account) +void database_fixture::upgrade_to_lifetime_member(account_id_type account) { - upgrade_to_prime(account(db)); + upgrade_to_lifetime_member(account(db)); } -void database_fixture::upgrade_to_prime( const account_object& account ) +void database_fixture::upgrade_to_lifetime_member( const account_object& account ) { try { - account_update_operation op; - op.account = account.id; - op.upgrade_to_prime = true; - trx.operations.emplace_back(operation(op)); + // TODO db.push_transaction( trx, ~0 ); - FC_ASSERT( account.is_prime() ); + FC_ASSERT( account.is_lifetime_member() ); trx.clear(); } FC_CAPTURE_AND_RETHROW((account)) diff --git a/tests/common/database_fixture.hpp b/tests/common/database_fixture.hpp index 2a80d9cc..66b2ceeb 100644 --- a/tests/common/database_fixture.hpp +++ b/tests/common/database_fixture.hpp @@ -202,8 +202,8 @@ struct database_fixture { void transfer( const account_object& from, const account_object& to, const asset& amount, const asset& fee = asset() ); void fund_fee_pool( const account_object& from, const asset_object& asset_to_fund, const share_type amount ); void enable_fees( share_type fee = GRAPHENE_BLOCKCHAIN_PRECISION ); - void upgrade_to_prime( account_id_type account ); - void upgrade_to_prime( const account_object& account ); + void upgrade_to_lifetime_member( account_id_type account ); + void upgrade_to_lifetime_member( const account_object& account ); void print_market( const string& syma, const string& symb )const; string pretty( const asset& a )const; void print_short_order( const short_order_object& cur )const; diff --git a/tests/tests/authority_tests.cpp b/tests/tests/authority_tests.cpp index 05bb91dc..8aac3ef0 100644 --- a/tests/tests/authority_tests.cpp +++ b/tests/tests/authority_tests.cpp @@ -434,7 +434,7 @@ BOOST_FIXTURE_TEST_CASE( fired_delegates, database_fixture ) for( int i = 0; i < 15; ++i ) { const auto& account = create_account("delegate" + fc::to_string(i+1), delegate_key_object.id); - upgrade_to_prime(account); + upgrade_to_lifetime_member(account); delegates.insert(create_delegate(account).vote_id); } @@ -980,8 +980,8 @@ BOOST_FIXTURE_TEST_CASE( bogus_signature, database_fixture ) BOOST_FIXTURE_TEST_CASE( voting_account, database_fixture ) { try { ACTORS((nathan)(vikram)); - upgrade_to_prime(nathan_id); - upgrade_to_prime(vikram_id); + upgrade_to_lifetime_member(nathan_id); + upgrade_to_lifetime_member(vikram_id); delegate_id_type nathan_delegate = create_delegate(nathan_id(db)).id; delegate_id_type vikram_delegate = create_delegate(vikram_id(db)).id; diff --git a/tests/tests/block_tests.cpp b/tests/tests/block_tests.cpp index 25a0eded..c74e182d 100644 --- a/tests/tests/block_tests.cpp +++ b/tests/tests/block_tests.cpp @@ -424,7 +424,7 @@ BOOST_FIXTURE_TEST_CASE( maintenance_interval, database_fixture ) BOOST_CHECK_GT(maintenence_time.sec_since_epoch(), db.head_block_time().sec_since_epoch()); auto initial_properties = db.get_global_properties(); const account_object& nathan = create_account("nathan"); - upgrade_to_prime(nathan); + upgrade_to_lifetime_member(nathan); const delegate_object nathans_delegate = create_delegate(nathan); { account_update_operation op; diff --git a/tests/tests/operation_tests.cpp b/tests/tests/operation_tests.cpp index 29c8ec57..79ce95a2 100644 --- a/tests/tests/operation_tests.cpp +++ b/tests/tests/operation_tests.cpp @@ -186,13 +186,13 @@ BOOST_AUTO_TEST_CASE( update_account ) transfer(account_id_type()(db), nathan, asset(3000000)); enable_fees(); - op.upgrade_to_prime = true; + // 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); BOOST_CHECK( nathan.referrer == nathan.id ); - BOOST_CHECK( nathan.referrer_percent == 100 ); + BOOST_CHECK( nathan.referrer_rewards_percentage == 100 ); } catch (fc::exception& e) { edump((e.to_detail_string())); throw; @@ -1872,7 +1872,7 @@ BOOST_AUTO_TEST_CASE( witness_withdraw_pay_test ) BOOST_CHECK_EQUAL(core->dynamic_asset_data_id(db).accumulated_fees.value, 0); account_update_operation uop; uop.account = nathan->get_id(); - uop.upgrade_to_prime = true; + // TODO: uop.upgrade_to_prime = true; trx.set_expiration(db.head_block_id()); trx.operations.push_back(uop); trx.visit(operation_set_fee(db.current_fee_schedule())); @@ -2124,7 +2124,7 @@ BOOST_AUTO_TEST_CASE( unimp_transfer_cashback_test ) const account_object& sam = create_account( "sam" ); transfer(account_id_type()(db), sam, asset(30000)); - upgrade_to_prime(sam); + upgrade_to_lifetime_member(sam); ilog( "Creating alice" ); const account_object& alice = create_account( "alice", sam, sam, 0 ); diff --git a/tests/tests/operation_tests2.cpp b/tests/tests/operation_tests2.cpp index cb7c11d9..67f11d19 100644 --- a/tests/tests/operation_tests2.cpp +++ b/tests/tests/operation_tests2.cpp @@ -388,7 +388,7 @@ BOOST_AUTO_TEST_CASE( mia_feeds ) BOOST_AUTO_TEST_CASE( witness_create ) { try { ACTOR(nathan); - upgrade_to_prime(nathan_id); + upgrade_to_lifetime_member(nathan_id); trx.clear(); witness_id_type nathan_witness_id = create_witness(nathan_id, nathan_key_id, nathan_private_key).id; // Give nathan some voting stake @@ -494,7 +494,7 @@ BOOST_AUTO_TEST_CASE( global_settle_test ) BOOST_AUTO_TEST_CASE( worker_create_test ) { try { ACTOR(nathan); - upgrade_to_prime(nathan_id); + upgrade_to_lifetime_member(nathan_id); generate_block(); { @@ -615,7 +615,7 @@ BOOST_AUTO_TEST_CASE( worker_pay_test ) BOOST_AUTO_TEST_CASE( refund_worker_test ) {try{ ACTOR(nathan); - upgrade_to_prime(nathan_id); + upgrade_to_lifetime_member(nathan_id); generate_block(); generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); trx.set_expiration(db.head_block_id()); diff --git a/tests/tests/uia_tests.cpp b/tests/tests/uia_tests.cpp index 8eb3e68e..c896d7fb 100644 --- a/tests/tests/uia_tests.cpp +++ b/tests/tests/uia_tests.cpp @@ -76,7 +76,7 @@ BOOST_AUTO_TEST_CASE( issue_whitelist_uia ) INVOKE(create_advanced_uia); const asset_object& advanced = get_asset("ADVANCED"); const account_object& nathan = create_account("nathan"); - upgrade_to_prime(nathan); + upgrade_to_lifetime_member(nathan); trx.clear(); asset_issue_operation op({asset(), advanced.issuer, advanced.amount(1000), nathan.id}); @@ -107,7 +107,7 @@ BOOST_AUTO_TEST_CASE( transfer_whitelist_uia ) const asset_object& advanced = get_asset("ADVANCED"); const account_object& nathan = get_account("nathan"); const account_object& dan = create_account("dan"); - upgrade_to_prime(dan); + upgrade_to_lifetime_member(dan); trx.clear(); transfer_operation op({advanced.amount(0), nathan.id, dan.id, advanced.amount(100)});