diff --git a/libraries/chain/db_init.cpp b/libraries/chain/db_init.cpp index 52e2c7c4..2909d6c0 100644 --- a/libraries/chain/db_init.cpp +++ b/libraries/chain/db_init.cpp @@ -249,44 +249,42 @@ void database::init_genesis(const genesis_state_type& genesis_state) create([&](block_summary_object&) {}); // Create initial accounts - if( !genesis_state.initial_accounts.empty() ) + for( const auto& account : genesis_state.initial_accounts ) { - for( const auto& account : genesis_state.initial_accounts ) + /* + key_id_type key_id = apply_operation(genesis_eval_state, + key_create_operation({asset(), + GRAPHENE_TEMP_ACCOUNT, + account.owner_key})).get(); + */ + account_create_operation cop; + cop.name = account.name; + cop.registrar = GRAPHENE_TEMP_ACCOUNT; + cop.owner = authority(1, account.owner_key, 1); + if( account.owner_key != account.active_key ) { /* - key_id_type key_id = apply_operation(genesis_eval_state, - key_create_operation({asset(), - GRAPHENE_TEMP_ACCOUNT, - account.owner_key})).get(); - */ - account_create_operation cop; - cop.name = account.name; - cop.registrar = GRAPHENE_TEMP_ACCOUNT; - cop.owner = authority(1, account.owner_key, 1); - if( account.owner_key != account.active_key ) - { - /* - key_id = apply_operation(genesis_eval_state, - key_create_operation({asset(), - GRAPHENE_TEMP_ACCOUNT, - account.owner_key})).get(); - */ - cop.active = authority(1, account.owner_key, 1); - } else { - cop.active = cop.owner; - } - cop.options.memo_key = account.owner_key; - account_id_type account_id(apply_operation(genesis_eval_state, cop).get()); + key_id = apply_operation(genesis_eval_state, + key_create_operation({asset(), + GRAPHENE_TEMP_ACCOUNT, + account.owner_key})).get(); + */ + cop.active = authority(1, account.owner_key, 1); + } else { + cop.active = cop.owner; + } + cop.options.memo_key = account.owner_key; + account_id_type account_id(apply_operation(genesis_eval_state, cop).get()); - if( account.is_lifetime_member ) - { - account_upgrade_operation op; - op.account_to_upgrade = account_id; - op.upgrade_to_lifetime_member = true; - apply_operation(genesis_eval_state, op); - } + if( account.is_lifetime_member ) + { + account_upgrade_operation op; + op.account_to_upgrade = account_id; + op.upgrade_to_lifetime_member = true; + apply_operation(genesis_eval_state, op); } } + const auto& accounts_by_name = get_index_type().indices().get(); auto get_account_id = [&accounts_by_name](const string& name) { auto itr = accounts_by_name.find(name); @@ -301,113 +299,107 @@ void database::init_genesis(const genesis_state_type& genesis_state) FC_ASSERT(itr != assets_by_symbol.end()); return itr->get_id(); }; - if( !genesis_state.initial_assets.empty() ) + + for( const genesis_state_type::initial_asset_type& asset : genesis_state.initial_assets ) { - for( const genesis_state_type::initial_asset_type& asset : genesis_state.initial_assets ) + asset_dynamic_data_id_type dynamic_data_id; + optional bitasset_data_id; + if( asset.bitasset_options.valid() ) { - asset_dynamic_data_id_type dynamic_data_id; - optional bitasset_data_id; - if( asset.bitasset_options.valid() ) + share_type total_allocated; + asset_id_type new_asset_id = get_index_type().get_next_id(); + asset_id_type collateral_asset_id = get_asset_id(asset.bitasset_options->backing_asset_symbol); + + int collateral_holder_number = 0; + for( const auto& collateral_rec : asset.bitasset_options->collateral_records ) { - share_type total_allocated; - asset_id_type new_asset_id = get_index_type().get_next_id(); - asset_id_type collateral_asset_id = get_asset_id(asset.bitasset_options->backing_asset_symbol); + /* + key_id_type key_id = apply_operation(genesis_eval_state, + key_create_operation{{}, + GRAPHENE_TEMP_ACCOUNT, + collateral_rec.owner}).get(); + */ + account_create_operation cop; + cop.name = asset.symbol + "-collateral-holder-" + std::to_string(collateral_holder_number); + boost::algorithm::to_lower(cop.name); + cop.registrar = GRAPHENE_TEMP_ACCOUNT; + cop.owner = authority(1, collateral_rec.owner, 1); + cop.active = cop.owner; + account_id_type owner_account_id = apply_operation(genesis_eval_state, cop).get(); - int collateral_holder_number = 0; - for( const auto& collateral_rec : asset.bitasset_options->collateral_records ) - { - /* - key_id_type key_id = apply_operation(genesis_eval_state, - key_create_operation{{}, - GRAPHENE_TEMP_ACCOUNT, - collateral_rec.owner}).get(); - */ - account_create_operation cop; - cop.name = asset.symbol + "-collateral-holder-" + std::to_string(collateral_holder_number); - boost::algorithm::to_lower(cop.name); - cop.registrar = GRAPHENE_TEMP_ACCOUNT; - cop.owner = authority(1, collateral_rec.owner, 1); - cop.active = cop.owner; - account_id_type owner_account_id = apply_operation(genesis_eval_state, cop).get(); + create([&](call_order_object& c) { + c.borrower = owner_account_id; + c.collateral = collateral_rec.collateral; + c.debt = collateral_rec.debt; + c.call_price = price::call_price(chain::asset(c.debt, new_asset_id), + chain::asset(c.collateral, collateral_asset_id), + asset.bitasset_options->maintenance_collateral_ratio); + }); - create([&](call_order_object& c) { - c.borrower = owner_account_id; - c.collateral = collateral_rec.collateral; - c.debt = collateral_rec.debt; - c.call_price = price::call_price(chain::asset(c.debt, new_asset_id), - chain::asset(c.collateral, collateral_asset_id), - asset.bitasset_options->maintenance_collateral_ratio); - }); + total_allocated += collateral_rec.debt; + } - total_allocated += collateral_rec.debt; - } + bitasset_data_id = create([&](asset_bitasset_data_object& b) { + b.options.feed_lifetime_sec = asset.bitasset_options->feed_lifetime_sec; + b.options.minimum_feeds = asset.bitasset_options->minimum_feeds; + b.options.force_settlement_delay_sec = asset.bitasset_options->force_settlement_delay_sec; + b.options.force_settlement_offset_percent = asset.bitasset_options->force_settlement_offset_percent; + b.options.maximum_force_settlement_volume = asset.bitasset_options->maximum_force_settlement_volume; + b.options.short_backing_asset = get_asset_id(asset.bitasset_options->backing_asset_symbol); + }).id; - bitasset_data_id = create([&](asset_bitasset_data_object& b) { - b.options.feed_lifetime_sec = asset.bitasset_options->feed_lifetime_sec; - b.options.minimum_feeds = asset.bitasset_options->minimum_feeds; - b.options.force_settlement_delay_sec = asset.bitasset_options->force_settlement_delay_sec; - b.options.force_settlement_offset_percent = asset.bitasset_options->force_settlement_offset_percent; - b.options.maximum_force_settlement_volume = asset.bitasset_options->maximum_force_settlement_volume; - b.options.short_backing_asset = get_asset_id(asset.bitasset_options->backing_asset_symbol); - }).id; + dynamic_data_id = create([&](asset_dynamic_data_object& d) { + d.current_supply = total_allocated; + d.accumulated_fees = asset.initial_accumulated_fees; + }).id; + } else + dynamic_data_id = create([&](asset_dynamic_data_object& d) { + d.accumulated_fees = asset.initial_accumulated_fees; + }).id; - dynamic_data_id = create([&](asset_dynamic_data_object& d) { - d.current_supply = total_allocated; - d.accumulated_fees = asset.initial_accumulated_fees; - }).id; - } else - dynamic_data_id = create([&](asset_dynamic_data_object& d) { - d.accumulated_fees = asset.initial_accumulated_fees; - }).id; + create([&](asset_object& a) { + a.symbol = asset.symbol; + a.options.description = asset.description; + a.precision = asset.precision; + a.issuer = get_account_id(asset.issuer_name); + a.options.max_supply = asset.max_supply; + a.options.market_fee_percent = asset.market_fee_percent; + a.options.max_market_fee = asset.max_market_fee; + a.options.issuer_permissions = asset.issuer_permissions; + a.options.flags = asset.flags; - create([&](asset_object& a) { - a.symbol = asset.symbol; - a.options.description = asset.description; - a.precision = asset.precision; - a.issuer = get_account_id(asset.issuer_name); - a.options.max_supply = asset.max_supply; - a.options.market_fee_percent = asset.market_fee_percent; - a.options.max_market_fee = asset.max_market_fee; - a.options.issuer_permissions = asset.issuer_permissions; - a.options.flags = asset.flags; - - a.dynamic_asset_data_id = dynamic_data_id; - a.bitasset_data_id = bitasset_data_id; - }); - } + a.dynamic_asset_data_id = dynamic_data_id; + a.bitasset_data_id = bitasset_data_id; + }); } // Create initial balances share_type total_allocation; - if( !genesis_state.initial_balances.empty() ) + for( const auto& handout : genesis_state.initial_balances ) { - for( const auto& handout : genesis_state.initial_balances ) - { - create([&handout,&assets_by_symbol,total_allocation](balance_object& b) { - b.balance = asset(handout.amount, assets_by_symbol.find(handout.asset_symbol)->get_id()); - b.owner = handout.owner; - }); - total_allocation += handout.amount; - } + create([&handout,&assets_by_symbol,total_allocation](balance_object& b) { + b.balance = asset(handout.amount, assets_by_symbol.find(handout.asset_symbol)->get_id()); + b.owner = handout.owner; + }); + total_allocation += handout.amount; } // Create initial vesting balances - if( !genesis_state.initial_vesting_balances.empty() ) + for( const genesis_state_type::initial_vesting_balance_type& vest : genesis_state.initial_vesting_balances ) { - for( const genesis_state_type::initial_vesting_balance_type& vest : genesis_state.initial_vesting_balances ) - { - create([&](balance_object& b) { - b.balance = asset(vest.amount, assets_by_symbol.find(vest.asset_symbol)->get_id()); - b.owner = vest.owner; - linear_vesting_policy policy; - policy.earliest_withdraw_time = vest.earliest_withdrawal_date; - policy.begin_date = vest.vesting_start_date; - policy.vesting_seconds = (vest.vesting_end_date - vest.vesting_start_date).to_seconds(); - policy.begin_balance = b.balance.amount; - b.vesting_policy = policy; - }); - total_allocation += vest.amount; - } + create([&](balance_object& b) { + b.owner = vest.owner; + b.balance = asset( vest.amount, assets_by_symbol.find( vest.asset_symbol )->get_id() ); + + linear_vesting_policy policy; + policy.begin_timestamp = vest.begin_timestamp; + policy.vesting_cliff_seconds = 0; + policy.vesting_duration_seconds = vest.vesting_duration_seconds; + policy.begin_balance = vest.begin_balance; + + b.vesting_policy = std::move( policy ); + }); + total_allocation += vest.amount; } // Set current supply based on allocations, if they happened diff --git a/libraries/chain/include/graphene/chain/genesis_state.hpp b/libraries/chain/include/graphene/chain/genesis_state.hpp index d193d5f6..a35d74f4 100644 --- a/libraries/chain/include/graphene/chain/genesis_state.hpp +++ b/libraries/chain/include/graphene/chain/genesis_state.hpp @@ -66,9 +66,9 @@ struct genesis_state_type { address owner; string asset_symbol; share_type amount; - time_point_sec vesting_start_date; - time_point_sec earliest_withdrawal_date; - time_point_sec vesting_end_date; + time_point_sec begin_timestamp; + uint32_t vesting_duration_seconds = 0; + share_type begin_balance; }; struct initial_witness_type { /// Must correspond to one of the initial accounts @@ -97,7 +97,7 @@ FC_REFLECT(graphene::chain::genesis_state_type::initial_account_type, (name)(own FC_REFLECT(graphene::chain::genesis_state_type::initial_balance_type, (owner)(asset_symbol)(amount)) FC_REFLECT(graphene::chain::genesis_state_type::initial_vesting_balance_type, - (owner)(asset_symbol)(amount)(vesting_start_date)(earliest_withdrawal_date)(vesting_end_date)) + (owner)(asset_symbol)(amount)(begin_timestamp)(vesting_duration_seconds)(begin_balance)) FC_REFLECT(graphene::chain::genesis_state_type::initial_witness_type, (owner_name)(block_signing_key)(initial_secret)) FC_REFLECT(graphene::chain::genesis_state_type::initial_committee_member_type, (owner_name)) FC_REFLECT(graphene::chain::genesis_state_type::initial_asset_type::initial_bitasset_options::initial_collateral_position, diff --git a/libraries/chain/include/graphene/chain/operations.hpp b/libraries/chain/include/graphene/chain/operations.hpp index b01c8803..cbec3db8 100644 --- a/libraries/chain/include/graphene/chain/operations.hpp +++ b/libraries/chain/include/graphene/chain/operations.hpp @@ -1239,10 +1239,10 @@ namespace graphene { namespace chain { struct linear_vesting_policy_initializer { - /** while vesting begins on begin_date, none may be claimed before the start_claim time */ - fc::time_point_sec start_claim; - fc::time_point_sec begin_date; - uint32_t vesting_seconds = 0; + /** while vesting begins on begin_timestamp, none may be claimed before vesting_cliff_seconds have passed */ + fc::time_point_sec begin_timestamp; + uint32_t vesting_cliff_seconds = 0; + uint32_t vesting_duration_seconds = 0; }; struct cdd_vesting_policy_initializer @@ -1673,6 +1673,6 @@ FC_REFLECT( graphene::chain::balance_claim_operation, FC_REFLECT_TYPENAME( graphene::chain::operation ) FC_REFLECT_TYPENAME( graphene::chain::operation_result ) FC_REFLECT_TYPENAME( fc::flat_set ) -FC_REFLECT(graphene::chain::linear_vesting_policy_initializer, (start_claim)(begin_date)(vesting_seconds) ) +FC_REFLECT(graphene::chain::linear_vesting_policy_initializer, (begin_timestamp)(vesting_cliff_seconds)(vesting_duration_seconds) ) FC_REFLECT(graphene::chain::cdd_vesting_policy_initializer, (start_claim)(vesting_seconds) ) FC_REFLECT_TYPENAME( graphene::chain::vesting_policy_initializer ) diff --git a/libraries/chain/include/graphene/chain/vesting_balance_object.hpp b/libraries/chain/include/graphene/chain/vesting_balance_object.hpp index f47c6ead..e935f434 100644 --- a/libraries/chain/include/graphene/chain/vesting_balance_object.hpp +++ b/libraries/chain/include/graphene/chain/vesting_balance_object.hpp @@ -54,17 +54,14 @@ namespace graphene { namespace chain { */ struct linear_vesting_policy { - /// No amount may be withdrawn before this time, regardless of how much has vested. - fc::time_point_sec earliest_withdraw_time; /// This is the time at which funds begin vesting. - /// Note that withdrawals are still not available until @ref earliest_withdraw_time - fc::time_point_sec begin_date; - /// Duration of vesting period, in seconds. Must be greater than zero. - uint32_t vesting_seconds = 0; - /// The total amount of asset to vest + fc::time_point_sec begin_timestamp; + /// No amount may be withdrawn before this many seconds of the vesting period have elapsed. + uint32_t vesting_cliff_seconds = 0; + /// Duration of the vesting period, in seconds. Must be greater than 0 and greater than vesting_cliff_seconds. + uint32_t vesting_duration_seconds = 0; + /// The total amount of asset to vest. share_type begin_balance; - /// The total amount of asset which has already been withdrawn - share_type total_withdrawn; asset get_allowed_withdraw(const vesting_policy_context& ctx)const; bool is_deposit_allowed(const vesting_policy_context& ctx)const; @@ -174,11 +171,10 @@ namespace graphene { namespace chain { } } // graphene::chain FC_REFLECT(graphene::chain::linear_vesting_policy, - (earliest_withdraw_time) - (begin_date) - (vesting_seconds) + (begin_timestamp) + (vesting_cliff_seconds) + (vesting_duration_seconds) (begin_balance) - (total_withdrawn) ) FC_REFLECT(graphene::chain::cdd_vesting_policy, diff --git a/libraries/chain/vesting_balance_evaluator.cpp b/libraries/chain/vesting_balance_evaluator.cpp index e43a535f..48bc8492 100644 --- a/libraries/chain/vesting_balance_evaluator.cpp +++ b/libraries/chain/vesting_balance_evaluator.cpp @@ -54,10 +54,10 @@ struct init_policy_visitor void operator()( const linear_vesting_policy_initializer& i )const { linear_vesting_policy policy; - policy.vesting_seconds = i.vesting_seconds; - policy.begin_date = i.begin_date; - policy.earliest_withdraw_time = i.start_claim; - policy.begin_balance = init_balance; + policy.begin_timestamp = i.begin_timestamp; + policy.vesting_cliff_seconds = i.vesting_cliff_seconds; + policy.vesting_duration_seconds = i.vesting_duration_seconds; + policy.begin_balance = init_balance; p = policy; } diff --git a/libraries/chain/vesting_balance_object.cpp b/libraries/chain/vesting_balance_object.cpp index a7242947..d4f70d75 100644 --- a/libraries/chain/vesting_balance_object.cpp +++ b/libraries/chain/vesting_balance_object.cpp @@ -28,30 +28,37 @@ inline bool sum_below_max_shares(const asset& a, const asset& b) && ((a.amount + b.amount) <= GRAPHENE_MAX_SHARE_SUPPLY); } -asset linear_vesting_policy::get_allowed_withdraw(const vesting_policy_context& ctx) const +asset linear_vesting_policy::get_allowed_withdraw( const vesting_policy_context& ctx )const { - if(ctx.now <= earliest_withdraw_time) - return asset(0, ctx.balance.asset_id); - if(ctx.now <= begin_date) - return asset(0, ctx.balance.asset_id); - if(vesting_seconds == 0) - return ctx.balance; + share_type allowed_withdraw = 0; - int64_t elapsed_seconds = (ctx.now - begin_date).to_seconds(); + if( ctx.now > begin_timestamp ) + { + const auto elapsed_seconds = (ctx.now - begin_timestamp).to_seconds(); + assert( elapsed_seconds > 0 ); - // if elapsed_seconds <= 0, then ctx.now <= begin_date, - // and we should have returned above. - assert(elapsed_seconds > 0); + if( elapsed_seconds >= vesting_cliff_seconds ) + { + share_type total_vested = 0; + if( elapsed_seconds < vesting_duration_seconds ) + { + total_vested = (fc::uint128_t( begin_balance.value ) * elapsed_seconds / vesting_duration_seconds).to_uint64(); + } + else + { + total_vested = begin_balance; + } + assert( total_vested >= 0 ); - fc::uint128_t total_allowed = begin_balance.value; - total_allowed *= uint64_t(elapsed_seconds); - total_allowed /= vesting_seconds; + const share_type withdrawn_already = begin_balance - ctx.balance.amount; + assert( withdrawn_already >= 0 ); - if(total_allowed <= total_withdrawn.value) - return asset(0, ctx.balance.asset_id); - total_allowed -= total_withdrawn.value; - FC_ASSERT(total_allowed <= GRAPHENE_MAX_SHARE_SUPPLY); - return asset(total_allowed.to_uint64(), ctx.balance.asset_id); + allowed_withdraw = total_vested - withdrawn_already; + assert( allowed_withdraw >= 0 ); + } + } + + return asset( allowed_withdraw, ctx.amount.asset_id ); } void linear_vesting_policy::on_deposit(const vesting_policy_context& ctx) @@ -66,12 +73,12 @@ bool linear_vesting_policy::is_deposit_allowed(const vesting_policy_context& ctx void linear_vesting_policy::on_withdraw(const vesting_policy_context& ctx) { - total_withdrawn += ctx.amount.amount; } bool linear_vesting_policy::is_withdraw_allowed(const vesting_policy_context& ctx)const { - return (ctx.amount <= get_allowed_withdraw(ctx)); + return (ctx.amount.asset_id == ctx.balance.asset_id) + && (ctx.amount <= get_allowed_withdraw(ctx)); } fc::uint128_t cdd_vesting_policy::compute_coin_seconds_earned(const vesting_policy_context& ctx)const diff --git a/libraries/fc b/libraries/fc index 7bd47af8..d462be0e 160000 --- a/libraries/fc +++ b/libraries/fc @@ -1 +1 @@ -Subproject commit 7bd47af88eaba93711da58cf7ddfe866deb21948 +Subproject commit d462be0e92a576b93a83194e9649af528162bb4a