diff --git a/libraries/chain/include/graphene/chain/balance_evaluator.hpp b/libraries/chain/include/graphene/chain/balance_evaluator.hpp index 0121f3a5..5f0895d0 100644 --- a/libraries/chain/include/graphene/chain/balance_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/balance_evaluator.hpp @@ -15,9 +15,8 @@ public: typedef balance_claim_operation operation_type; const balance_object* balance = nullptr; - asset amount_withdrawn; - asset do_evaluate(const balance_claim_operation& op) + void_result do_evaluate(const balance_claim_operation& op) { database& d = db(); balance = &op.balance_to_claim(d); @@ -33,39 +32,42 @@ public: FC_ASSERT(trx_state->signed_by(op.balance_owner_key)); FC_ASSERT(op.total_claimed.asset_id == balance->asset_type()); - if( balance->vesting_policy.valid() ) { - FC_ASSERT(op.total_claimed.amount == 0); + if( balance->is_vesting_balance() ) { + if( !balance->vesting_policy->is_withdraw_allowed({balance->balance, + d.head_block_time(), + op.total_claimed}) ) + FC_THROW_EXCEPTION(invalid_claim_amount, + "Attempted to claim ${c} from a vesting balance with ${a} available", + ("c", op.total_claimed)("a", balance->available(d.head_block_time()))); if( d.head_block_time() - balance->last_claim_date < fc::days(1) ) FC_THROW_EXCEPTION(balance_claimed_too_often, "Genesis vesting balances may not be claimed more than once per day."); - return amount_withdrawn = balance->vesting_policy->get_allowed_withdraw({balance->balance, - d.head_block_time(), - {}}); + return {}; } FC_ASSERT(op.total_claimed == balance->balance); - return amount_withdrawn = op.total_claimed; + return {}; } /** * @note the fee is always 0 for this particular operation because once the * balance is claimed it frees up memory and it cannot be used to spam the network */ - asset do_apply(const balance_claim_operation& op) + void_result do_apply(const balance_claim_operation& op) { database& d = db(); - if( balance->vesting_policy.valid() && amount_withdrawn < balance->balance ) + if( balance->is_vesting_balance() && op.total_claimed < balance->balance ) d.modify(*balance, [&](balance_object& b) { - b.vesting_policy->on_withdraw({b.balance, d.head_block_time(), amount_withdrawn}); - b.balance -= amount_withdrawn; + b.vesting_policy->on_withdraw({b.balance, d.head_block_time(), op.total_claimed}); + b.balance -= op.total_claimed; b.last_claim_date = d.head_block_time(); }); else d.remove(*balance); - d.adjust_balance(op.deposit_to_account, amount_withdrawn); - return amount_withdrawn; + d.adjust_balance(op.deposit_to_account, op.total_claimed); + return {}; } }; diff --git a/libraries/chain/include/graphene/chain/balance_object.hpp b/libraries/chain/include/graphene/chain/balance_object.hpp index 5bc61a41..82828f7c 100644 --- a/libraries/chain/include/graphene/chain/balance_object.hpp +++ b/libraries/chain/include/graphene/chain/balance_object.hpp @@ -10,6 +10,14 @@ namespace graphene { namespace chain { static const uint8_t space_id = protocol_ids; static const uint8_t type_id = balance_object_type; + bool is_vesting_balance()const + { return vesting_policy.valid(); } + asset available(fc::time_point_sec now)const + { + return is_vesting_balance()? vesting_policy->get_allowed_withdraw({balance, now, {}}) + : balance; + } + address owner; asset balance; optional vesting_policy; diff --git a/libraries/chain/include/graphene/chain/evaluator.hpp b/libraries/chain/include/graphene/chain/evaluator.hpp index 2403082c..386834f7 100644 --- a/libraries/chain/include/graphene/chain/evaluator.hpp +++ b/libraries/chain/include/graphene/chain/evaluator.hpp @@ -133,7 +133,7 @@ namespace graphene { namespace chain { // after all observers receive evaluation_failed) T eval; - optional< fc::exception > evaluation_exception; + shared_ptr evaluation_exception; size_t observer_count = 0; operation_result result; @@ -156,7 +156,7 @@ namespace graphene { namespace chain { } catch( const fc::exception& e ) { - evaluation_exception = e; + evaluation_exception = e.dynamic_copy_exception(); } while( observer_count > 0 ) @@ -165,7 +165,7 @@ namespace graphene { namespace chain { const auto& obs = eval_observers[observer_count]; try { - if( !evaluation_exception.valid() ) + if( evaluation_exception ) obs->post_evaluate(eval_state, op, apply, &eval, result); else obs->evaluation_failed(eval_state, op, apply, &eval, result); @@ -176,8 +176,8 @@ namespace graphene { namespace chain { } } - if( evaluation_exception.valid() ) - throw *evaluation_exception; + if( evaluation_exception ) + evaluation_exception->dynamic_rethrow_exception(); return result; } }; diff --git a/libraries/chain/include/graphene/chain/exceptions.hpp b/libraries/chain/include/graphene/chain/exceptions.hpp index dd51e8d6..f06ecb02 100644 --- a/libraries/chain/include/graphene/chain/exceptions.hpp +++ b/libraries/chain/include/graphene/chain/exceptions.hpp @@ -22,93 +22,94 @@ namespace graphene { namespace chain { // registered in chain_database.cpp - FC_DECLARE_EXCEPTION( chain_exception, 30000, "Blockchain Exception" ); - FC_DECLARE_DERIVED_EXCEPTION( invalid_pts_address, graphene::chain::chain_exception, 30001, "invalid pts address" ); - FC_DECLARE_DERIVED_EXCEPTION( addition_overflow, graphene::chain::chain_exception, 30002, "addition overflow" ); - FC_DECLARE_DERIVED_EXCEPTION( subtraction_overflow, graphene::chain::chain_exception, 30003, "subtraction overflow" ); - FC_DECLARE_DERIVED_EXCEPTION( asset_type_mismatch, graphene::chain::chain_exception, 30004, "asset/price mismatch" ); - FC_DECLARE_DERIVED_EXCEPTION( unsupported_chain_operation, graphene::chain::chain_exception, 30005, "unsupported chain operation" ); - FC_DECLARE_DERIVED_EXCEPTION( unknown_transaction, graphene::chain::chain_exception, 30006, "unknown transaction" ); - FC_DECLARE_DERIVED_EXCEPTION( duplicate_transaction, graphene::chain::chain_exception, 30007, "duplicate transaction" ); - FC_DECLARE_DERIVED_EXCEPTION( zero_amount, graphene::chain::chain_exception, 30008, "zero amount" ); - FC_DECLARE_DERIVED_EXCEPTION( zero_price, graphene::chain::chain_exception, 30009, "zero price" ); - FC_DECLARE_DERIVED_EXCEPTION( asset_divide_by_self, graphene::chain::chain_exception, 30010, "asset divide by self" ); - FC_DECLARE_DERIVED_EXCEPTION( asset_divide_by_zero, graphene::chain::chain_exception, 30011, "asset divide by zero" ); - FC_DECLARE_DERIVED_EXCEPTION( new_database_version, graphene::chain::chain_exception, 30012, "new database version" ); - FC_DECLARE_DERIVED_EXCEPTION( unlinkable_block, graphene::chain::chain_exception, 30013, "unlinkable block" ); - FC_DECLARE_DERIVED_EXCEPTION( price_out_of_range, graphene::chain::chain_exception, 30014, "price out of range" ); + FC_DECLARE_EXCEPTION( chain_exception, 30000, "Blockchain Exception" ) + FC_DECLARE_DERIVED_EXCEPTION( invalid_pts_address, graphene::chain::chain_exception, 30001, "invalid pts address" ) + FC_DECLARE_DERIVED_EXCEPTION( addition_overflow, graphene::chain::chain_exception, 30002, "addition overflow" ) + FC_DECLARE_DERIVED_EXCEPTION( subtraction_overflow, graphene::chain::chain_exception, 30003, "subtraction overflow" ) + FC_DECLARE_DERIVED_EXCEPTION( asset_type_mismatch, graphene::chain::chain_exception, 30004, "asset/price mismatch" ) + FC_DECLARE_DERIVED_EXCEPTION( unsupported_chain_operation, graphene::chain::chain_exception, 30005, "unsupported chain operation" ) + FC_DECLARE_DERIVED_EXCEPTION( unknown_transaction, graphene::chain::chain_exception, 30006, "unknown transaction" ) + FC_DECLARE_DERIVED_EXCEPTION( duplicate_transaction, graphene::chain::chain_exception, 30007, "duplicate transaction" ) + FC_DECLARE_DERIVED_EXCEPTION( zero_amount, graphene::chain::chain_exception, 30008, "zero amount" ) + FC_DECLARE_DERIVED_EXCEPTION( zero_price, graphene::chain::chain_exception, 30009, "zero price" ) + FC_DECLARE_DERIVED_EXCEPTION( asset_divide_by_self, graphene::chain::chain_exception, 30010, "asset divide by self" ) + FC_DECLARE_DERIVED_EXCEPTION( asset_divide_by_zero, graphene::chain::chain_exception, 30011, "asset divide by zero" ) + FC_DECLARE_DERIVED_EXCEPTION( new_database_version, graphene::chain::chain_exception, 30012, "new database version" ) + FC_DECLARE_DERIVED_EXCEPTION( unlinkable_block, graphene::chain::chain_exception, 30013, "unlinkable block" ) + FC_DECLARE_DERIVED_EXCEPTION( price_out_of_range, graphene::chain::chain_exception, 30014, "price out of range" ) - FC_DECLARE_DERIVED_EXCEPTION( block_numbers_not_sequential, graphene::chain::chain_exception, 30015, "block numbers not sequential" ); - FC_DECLARE_DERIVED_EXCEPTION( invalid_previous_block_id, graphene::chain::chain_exception, 30016, "invalid previous block" ); - FC_DECLARE_DERIVED_EXCEPTION( invalid_block_time, graphene::chain::chain_exception, 30017, "invalid block time" ); - FC_DECLARE_DERIVED_EXCEPTION( time_in_past, graphene::chain::chain_exception, 30018, "time is in the past" ); - FC_DECLARE_DERIVED_EXCEPTION( time_in_future, graphene::chain::chain_exception, 30019, "time is in the future" ); - FC_DECLARE_DERIVED_EXCEPTION( invalid_block_digest, graphene::chain::chain_exception, 30020, "invalid block digest" ); - FC_DECLARE_DERIVED_EXCEPTION( invalid_delegate_signee, graphene::chain::chain_exception, 30021, "invalid delegate signee" ); - FC_DECLARE_DERIVED_EXCEPTION( failed_checkpoint_verification, graphene::chain::chain_exception, 30022, "failed checkpoint verification" ); - FC_DECLARE_DERIVED_EXCEPTION( wrong_chain_id, graphene::chain::chain_exception, 30023, "wrong chain id" ); - FC_DECLARE_DERIVED_EXCEPTION( unknown_block, graphene::chain::chain_exception, 30024, "unknown block" ); - FC_DECLARE_DERIVED_EXCEPTION( block_older_than_undo_history, graphene::chain::chain_exception, 30025, "block is older than our undo history allows us to process" ); + FC_DECLARE_DERIVED_EXCEPTION( block_numbers_not_sequential, graphene::chain::chain_exception, 30015, "block numbers not sequential" ) + FC_DECLARE_DERIVED_EXCEPTION( invalid_previous_block_id, graphene::chain::chain_exception, 30016, "invalid previous block" ) + FC_DECLARE_DERIVED_EXCEPTION( invalid_block_time, graphene::chain::chain_exception, 30017, "invalid block time" ) + FC_DECLARE_DERIVED_EXCEPTION( time_in_past, graphene::chain::chain_exception, 30018, "time is in the past" ) + FC_DECLARE_DERIVED_EXCEPTION( time_in_future, graphene::chain::chain_exception, 30019, "time is in the future" ) + FC_DECLARE_DERIVED_EXCEPTION( invalid_block_digest, graphene::chain::chain_exception, 30020, "invalid block digest" ) + FC_DECLARE_DERIVED_EXCEPTION( invalid_delegate_signee, graphene::chain::chain_exception, 30021, "invalid delegate signee" ) + FC_DECLARE_DERIVED_EXCEPTION( failed_checkpoint_verification, graphene::chain::chain_exception, 30022, "failed checkpoint verification" ) + FC_DECLARE_DERIVED_EXCEPTION( wrong_chain_id, graphene::chain::chain_exception, 30023, "wrong chain id" ) + FC_DECLARE_DERIVED_EXCEPTION( unknown_block, graphene::chain::chain_exception, 30024, "unknown block" ) + FC_DECLARE_DERIVED_EXCEPTION( block_older_than_undo_history, graphene::chain::chain_exception, 30025, "block is older than our undo history allows us to process" ) - FC_DECLARE_EXCEPTION( evaluation_error, 31000, "Evaluation Error" ); - FC_DECLARE_DERIVED_EXCEPTION( negative_deposit, graphene::chain::evaluation_error, 31001, "negative deposit" ); - FC_DECLARE_DERIVED_EXCEPTION( not_a_delegate, graphene::chain::evaluation_error, 31002, "not a delegate" ); - FC_DECLARE_DERIVED_EXCEPTION( unknown_balance_record, graphene::chain::evaluation_error, 31003, "unknown balance record" ); - FC_DECLARE_DERIVED_EXCEPTION( insufficient_funds, graphene::chain::evaluation_error, 31004, "insufficient funds" ); - FC_DECLARE_DERIVED_EXCEPTION( missing_signature, graphene::chain::evaluation_error, 31005, "missing signature" ); - FC_DECLARE_DERIVED_EXCEPTION( invalid_claim_password, graphene::chain::evaluation_error, 31006, "invalid claim password" ); - FC_DECLARE_DERIVED_EXCEPTION( invalid_withdraw_condition, graphene::chain::evaluation_error, 31007, "invalid withdraw condition" ); - FC_DECLARE_DERIVED_EXCEPTION( negative_withdraw, graphene::chain::evaluation_error, 31008, "negative withdraw" ); - FC_DECLARE_DERIVED_EXCEPTION( not_an_active_delegate, graphene::chain::evaluation_error, 31009, "not an active delegate" ); - FC_DECLARE_DERIVED_EXCEPTION( expired_transaction, graphene::chain::evaluation_error, 31010, "expired transaction" ); - FC_DECLARE_DERIVED_EXCEPTION( invalid_transaction_expiration, graphene::chain::evaluation_error, 31011, "invalid transaction expiration" ); - FC_DECLARE_DERIVED_EXCEPTION( oversized_transaction, graphene::chain::evaluation_error, 31012, "transaction exceeded the maximum transaction size" ); - FC_DECLARE_DERIVED_EXCEPTION( balance_claimed_too_often, graphene::chain::evaluation_error, 31013, "balance claimed too often" ); + FC_DECLARE_EXCEPTION( evaluation_error, 31000, "Evaluation Error" ) + FC_DECLARE_DERIVED_EXCEPTION( negative_deposit, graphene::chain::evaluation_error, 31001, "negative deposit" ) + FC_DECLARE_DERIVED_EXCEPTION( not_a_delegate, graphene::chain::evaluation_error, 31002, "not a delegate" ) + FC_DECLARE_DERIVED_EXCEPTION( unknown_balance_record, graphene::chain::evaluation_error, 31003, "unknown balance record" ) + FC_DECLARE_DERIVED_EXCEPTION( insufficient_funds, graphene::chain::evaluation_error, 31004, "insufficient funds" ) + FC_DECLARE_DERIVED_EXCEPTION( missing_signature, graphene::chain::evaluation_error, 31005, "missing signature" ) + FC_DECLARE_DERIVED_EXCEPTION( invalid_claim_password, graphene::chain::evaluation_error, 31006, "invalid claim password" ) + FC_DECLARE_DERIVED_EXCEPTION( invalid_withdraw_condition, graphene::chain::evaluation_error, 31007, "invalid withdraw condition" ) + FC_DECLARE_DERIVED_EXCEPTION( negative_withdraw, graphene::chain::evaluation_error, 31008, "negative withdraw" ) + FC_DECLARE_DERIVED_EXCEPTION( not_an_active_delegate, graphene::chain::evaluation_error, 31009, "not an active delegate" ) + FC_DECLARE_DERIVED_EXCEPTION( expired_transaction, graphene::chain::evaluation_error, 31010, "expired transaction" ) + FC_DECLARE_DERIVED_EXCEPTION( invalid_transaction_expiration, graphene::chain::evaluation_error, 31011, "invalid transaction expiration" ) + FC_DECLARE_DERIVED_EXCEPTION( oversized_transaction, graphene::chain::evaluation_error, 31012, "transaction exceeded the maximum transaction size" ) + FC_DECLARE_DERIVED_EXCEPTION( balance_claimed_too_often, graphene::chain::evaluation_error, 31013, "balance claimed too often" ) + FC_DECLARE_DERIVED_EXCEPTION( invalid_claim_amount, graphene::chain::evaluation_error, 31013, "invalid claim amount" ) - FC_DECLARE_DERIVED_EXCEPTION( invalid_account_name, graphene::chain::evaluation_error, 32001, "invalid account name" ); - FC_DECLARE_DERIVED_EXCEPTION( unknown_account_id, graphene::chain::evaluation_error, 32002, "unknown account id" ); - FC_DECLARE_DERIVED_EXCEPTION( unknown_account_name, graphene::chain::evaluation_error, 32003, "unknown account name" ); - FC_DECLARE_DERIVED_EXCEPTION( missing_parent_account_signature, graphene::chain::evaluation_error, 32004, "missing parent account signature" ); - FC_DECLARE_DERIVED_EXCEPTION( parent_account_retracted, graphene::chain::evaluation_error, 32005, "parent account retracted" ); - FC_DECLARE_DERIVED_EXCEPTION( account_expired, graphene::chain::evaluation_error, 32006, "account expired" ); - FC_DECLARE_DERIVED_EXCEPTION( account_already_registered, graphene::chain::evaluation_error, 32007, "account already registered" ); - FC_DECLARE_DERIVED_EXCEPTION( account_key_in_use, graphene::chain::evaluation_error, 32008, "account key already in use" ); - FC_DECLARE_DERIVED_EXCEPTION( account_retracted, graphene::chain::evaluation_error, 32009, "account retracted" ); - FC_DECLARE_DERIVED_EXCEPTION( unknown_parent_account_name, graphene::chain::evaluation_error, 32010, "unknown parent account name" ); - FC_DECLARE_DERIVED_EXCEPTION( unknown_delegate_slate, graphene::chain::evaluation_error, 32011, "unknown delegate slate" ); - FC_DECLARE_DERIVED_EXCEPTION( too_may_delegates_in_slate, graphene::chain::evaluation_error, 32012, "too many delegates in slate" ); - FC_DECLARE_DERIVED_EXCEPTION( pay_balance_remaining, graphene::chain::evaluation_error, 32013, "pay balance remaining" ); + FC_DECLARE_DERIVED_EXCEPTION( invalid_account_name, graphene::chain::evaluation_error, 32001, "invalid account name" ) + FC_DECLARE_DERIVED_EXCEPTION( unknown_account_id, graphene::chain::evaluation_error, 32002, "unknown account id" ) + FC_DECLARE_DERIVED_EXCEPTION( unknown_account_name, graphene::chain::evaluation_error, 32003, "unknown account name" ) + FC_DECLARE_DERIVED_EXCEPTION( missing_parent_account_signature, graphene::chain::evaluation_error, 32004, "missing parent account signature" ) + FC_DECLARE_DERIVED_EXCEPTION( parent_account_retracted, graphene::chain::evaluation_error, 32005, "parent account retracted" ) + FC_DECLARE_DERIVED_EXCEPTION( account_expired, graphene::chain::evaluation_error, 32006, "account expired" ) + FC_DECLARE_DERIVED_EXCEPTION( account_already_registered, graphene::chain::evaluation_error, 32007, "account already registered" ) + FC_DECLARE_DERIVED_EXCEPTION( account_key_in_use, graphene::chain::evaluation_error, 32008, "account key already in use" ) + FC_DECLARE_DERIVED_EXCEPTION( account_retracted, graphene::chain::evaluation_error, 32009, "account retracted" ) + FC_DECLARE_DERIVED_EXCEPTION( unknown_parent_account_name, graphene::chain::evaluation_error, 32010, "unknown parent account name" ) + FC_DECLARE_DERIVED_EXCEPTION( unknown_delegate_slate, graphene::chain::evaluation_error, 32011, "unknown delegate slate" ) + FC_DECLARE_DERIVED_EXCEPTION( too_may_delegates_in_slate, graphene::chain::evaluation_error, 32012, "too many delegates in slate" ) + FC_DECLARE_DERIVED_EXCEPTION( pay_balance_remaining, graphene::chain::evaluation_error, 32013, "pay balance remaining" ) - FC_DECLARE_DERIVED_EXCEPTION( not_a_delegate_signature, graphene::chain::evaluation_error, 33002, "not delegates signature" ); + FC_DECLARE_DERIVED_EXCEPTION( not_a_delegate_signature, graphene::chain::evaluation_error, 33002, "not delegates signature" ) - FC_DECLARE_DERIVED_EXCEPTION( invalid_precision, graphene::chain::evaluation_error, 35001, "invalid precision" ); - FC_DECLARE_DERIVED_EXCEPTION( invalid_asset_symbol, graphene::chain::evaluation_error, 35002, "invalid asset symbol" ); - FC_DECLARE_DERIVED_EXCEPTION( unknown_asset_id, graphene::chain::evaluation_error, 35003, "unknown asset id" ); - FC_DECLARE_DERIVED_EXCEPTION( asset_symbol_in_use, graphene::chain::evaluation_error, 35004, "asset symbol in use" ); - FC_DECLARE_DERIVED_EXCEPTION( invalid_asset_amount, graphene::chain::evaluation_error, 35005, "invalid asset amount" ); - FC_DECLARE_DERIVED_EXCEPTION( negative_issue, graphene::chain::evaluation_error, 35006, "negative issue" ); - FC_DECLARE_DERIVED_EXCEPTION( over_issue, graphene::chain::evaluation_error, 35007, "over issue" ); - FC_DECLARE_DERIVED_EXCEPTION( unknown_asset_symbol, graphene::chain::evaluation_error, 35008, "unknown asset symbol" ); - FC_DECLARE_DERIVED_EXCEPTION( asset_id_in_use, graphene::chain::evaluation_error, 35009, "asset id in use" ); - FC_DECLARE_DERIVED_EXCEPTION( not_user_issued, graphene::chain::evaluation_error, 35010, "not user issued" ); - FC_DECLARE_DERIVED_EXCEPTION( invalid_asset_name, graphene::chain::evaluation_error, 35011, "invalid asset name" ); + FC_DECLARE_DERIVED_EXCEPTION( invalid_precision, graphene::chain::evaluation_error, 35001, "invalid precision" ) + FC_DECLARE_DERIVED_EXCEPTION( invalid_asset_symbol, graphene::chain::evaluation_error, 35002, "invalid asset symbol" ) + FC_DECLARE_DERIVED_EXCEPTION( unknown_asset_id, graphene::chain::evaluation_error, 35003, "unknown asset id" ) + FC_DECLARE_DERIVED_EXCEPTION( asset_symbol_in_use, graphene::chain::evaluation_error, 35004, "asset symbol in use" ) + FC_DECLARE_DERIVED_EXCEPTION( invalid_asset_amount, graphene::chain::evaluation_error, 35005, "invalid asset amount" ) + FC_DECLARE_DERIVED_EXCEPTION( negative_issue, graphene::chain::evaluation_error, 35006, "negative issue" ) + FC_DECLARE_DERIVED_EXCEPTION( over_issue, graphene::chain::evaluation_error, 35007, "over issue" ) + FC_DECLARE_DERIVED_EXCEPTION( unknown_asset_symbol, graphene::chain::evaluation_error, 35008, "unknown asset symbol" ) + FC_DECLARE_DERIVED_EXCEPTION( asset_id_in_use, graphene::chain::evaluation_error, 35009, "asset id in use" ) + FC_DECLARE_DERIVED_EXCEPTION( not_user_issued, graphene::chain::evaluation_error, 35010, "not user issued" ) + FC_DECLARE_DERIVED_EXCEPTION( invalid_asset_name, graphene::chain::evaluation_error, 35011, "invalid asset name" ) - FC_DECLARE_DERIVED_EXCEPTION( delegate_vote_limit, graphene::chain::evaluation_error, 36001, "delegate_vote_limit" ); - FC_DECLARE_DERIVED_EXCEPTION( insufficient_fee, graphene::chain::evaluation_error, 36002, "insufficient fee" ); - FC_DECLARE_DERIVED_EXCEPTION( negative_fee, graphene::chain::evaluation_error, 36003, "negative fee" ); - FC_DECLARE_DERIVED_EXCEPTION( missing_deposit, graphene::chain::evaluation_error, 36004, "missing deposit" ); - FC_DECLARE_DERIVED_EXCEPTION( insufficient_relay_fee, graphene::chain::evaluation_error, 36005, "insufficient relay fee" ); + FC_DECLARE_DERIVED_EXCEPTION( delegate_vote_limit, graphene::chain::evaluation_error, 36001, "delegate_vote_limit" ) + FC_DECLARE_DERIVED_EXCEPTION( insufficient_fee, graphene::chain::evaluation_error, 36002, "insufficient fee" ) + FC_DECLARE_DERIVED_EXCEPTION( negative_fee, graphene::chain::evaluation_error, 36003, "negative fee" ) + FC_DECLARE_DERIVED_EXCEPTION( missing_deposit, graphene::chain::evaluation_error, 36004, "missing deposit" ) + FC_DECLARE_DERIVED_EXCEPTION( insufficient_relay_fee, graphene::chain::evaluation_error, 36005, "insufficient relay fee" ) - FC_DECLARE_DERIVED_EXCEPTION( invalid_market, graphene::chain::evaluation_error, 37001, "invalid market" ); - FC_DECLARE_DERIVED_EXCEPTION( unknown_market_order, graphene::chain::evaluation_error, 37002, "unknown market order" ); - FC_DECLARE_DERIVED_EXCEPTION( shorting_base_shares, graphene::chain::evaluation_error, 37003, "shorting base shares" ); - FC_DECLARE_DERIVED_EXCEPTION( insufficient_collateral, graphene::chain::evaluation_error, 37004, "insufficient collateral" ); - FC_DECLARE_DERIVED_EXCEPTION( insufficient_depth, graphene::chain::evaluation_error, 37005, "insufficient depth" ); - FC_DECLARE_DERIVED_EXCEPTION( insufficient_feeds, graphene::chain::evaluation_error, 37006, "insufficient feeds" ); - FC_DECLARE_DERIVED_EXCEPTION( invalid_feed_price, graphene::chain::evaluation_error, 37007, "invalid feed price" ); + FC_DECLARE_DERIVED_EXCEPTION( invalid_market, graphene::chain::evaluation_error, 37001, "invalid market" ) + FC_DECLARE_DERIVED_EXCEPTION( unknown_market_order, graphene::chain::evaluation_error, 37002, "unknown market order" ) + FC_DECLARE_DERIVED_EXCEPTION( shorting_base_shares, graphene::chain::evaluation_error, 37003, "shorting base shares" ) + FC_DECLARE_DERIVED_EXCEPTION( insufficient_collateral, graphene::chain::evaluation_error, 37004, "insufficient collateral" ) + FC_DECLARE_DERIVED_EXCEPTION( insufficient_depth, graphene::chain::evaluation_error, 37005, "insufficient depth" ) + FC_DECLARE_DERIVED_EXCEPTION( insufficient_feeds, graphene::chain::evaluation_error, 37006, "insufficient feeds" ) + FC_DECLARE_DERIVED_EXCEPTION( invalid_feed_price, graphene::chain::evaluation_error, 37007, "invalid feed price" ) - FC_DECLARE_DERIVED_EXCEPTION( price_multiplication_overflow, graphene::chain::evaluation_error, 38001, "price multiplication overflow" ); - FC_DECLARE_DERIVED_EXCEPTION( price_multiplication_underflow, graphene::chain::evaluation_error, 38002, "price multiplication underflow" ); - FC_DECLARE_DERIVED_EXCEPTION( price_multiplication_undefined, graphene::chain::evaluation_error, 38003, "price multiplication undefined product 0*inf" ); + FC_DECLARE_DERIVED_EXCEPTION( price_multiplication_overflow, graphene::chain::evaluation_error, 38001, "price multiplication overflow" ) + FC_DECLARE_DERIVED_EXCEPTION( price_multiplication_underflow, graphene::chain::evaluation_error, 38002, "price multiplication underflow" ) + FC_DECLARE_DERIVED_EXCEPTION( price_multiplication_undefined, graphene::chain::evaluation_error, 38003, "price multiplication undefined product 0*inf" ) } } // graphene::chain diff --git a/tests/tests/operation_tests2.cpp b/tests/tests/operation_tests2.cpp index c5edce81..f1cf9dab 100644 --- a/tests/tests/operation_tests2.cpp +++ b/tests/tests/operation_tests2.cpp @@ -28,7 +28,7 @@ #include #include #include - +#include #include #include @@ -980,9 +980,28 @@ BOOST_AUTO_TEST_CASE( balance_object_test ) fc::temp_directory td; genesis_state.initial_balances.push_back({generate_private_key("n").get_public_key(), GRAPHENE_SYMBOL, 1}); genesis_state.initial_balances.push_back({generate_private_key("x").get_public_key(), GRAPHENE_SYMBOL, 1}); -// genesis_state.initial_vesting_balances.push_back({generate_private_key("v").get_public_key(), GRAPHENE_SYMBOL, 1}); - // TODO: vesting genesis balances - genesis_state.initial_accounts.emplace_back("n", generate_private_key("n").get_public_key()); + auto starting_time = time_point_sec((time_point::now().sec_since_epoch() / GRAPHENE_DEFAULT_BLOCK_INTERVAL + 1) * + GRAPHENE_DEFAULT_BLOCK_INTERVAL); + + auto n_key = generate_private_key("n"); + auto x_key = generate_private_key("x"); + auto v1_key = generate_private_key("v1"); + auto v2_key = generate_private_key("v2"); + + genesis_state_type::initial_vesting_balance_type vest; + vest.owner = v1_key.get_public_key(); + vest.asset_symbol = GRAPHENE_SYMBOL; + vest.amount = 500; + vest.begin_balance = vest.amount; + vest.begin_timestamp = starting_time; + vest.vesting_duration_seconds = 60; + genesis_state.initial_vesting_balances.push_back(vest); + vest.owner = v2_key.get_public_key(); + vest.begin_timestamp -= fc::seconds(30); + vest.amount = 400; + genesis_state.initial_vesting_balances.push_back(vest); + + genesis_state.initial_accounts.emplace_back("n", n_key.get_public_key()); db.open(td.path(), genesis_state); const balance_object& balance = balance_id_type()(db); @@ -993,22 +1012,87 @@ BOOST_AUTO_TEST_CASE( balance_object_test ) op.deposit_to_account = db.get_index_type().indices().get().find("n")->get_id(); op.total_claimed = asset(1); op.balance_to_claim = balance_id_type(1); - op.balance_owner_key = generate_private_key("x").get_public_key(); + op.balance_owner_key = x_key.get_public_key(); trx.operations = {op}; - trx.sign(generate_private_key("n")); + trx.sign(n_key); // Fail because I'm claiming from an address which hasn't signed BOOST_CHECK_THROW(db.push_transaction(trx), fc::exception); trx.clear(); op.balance_to_claim = balance_id_type(); - op.balance_owner_key = generate_private_key("n").get_public_key(); + op.balance_owner_key = n_key.get_public_key(); trx.operations = {op}; - trx.sign(generate_private_key("n")); + trx.sign(n_key); db.push_transaction(trx); // Not using fixture's get_balance() here because it uses fixture's db, not my override BOOST_CHECK_EQUAL(db.get_balance(op.deposit_to_account, asset_id_type()).amount.value, 1); BOOST_CHECK(db.find_object(balance_id_type()) == nullptr); BOOST_CHECK(db.find_object(balance_id_type(1)) != nullptr); + + auto slot = db.get_slot_at_time(starting_time); + db.generate_block(starting_time, db.get_scheduled_witness(slot).first, delegate_priv_key, database::skip_nothing); + + const balance_object& vesting_balance_1 = balance_id_type(2)(db); + const balance_object& vesting_balance_2 = balance_id_type(3)(db); + BOOST_CHECK(vesting_balance_1.is_vesting_balance()); + BOOST_CHECK_EQUAL(vesting_balance_1.balance.amount.value, 500); + BOOST_CHECK_EQUAL(vesting_balance_1.available(db.head_block_time()).amount.value, 0); + BOOST_CHECK(vesting_balance_2.is_vesting_balance()); + BOOST_CHECK_EQUAL(vesting_balance_2.balance.amount.value, 400); + BOOST_CHECK_EQUAL(vesting_balance_2.available(db.head_block_time()).amount.value, 150); + + op.balance_to_claim = vesting_balance_1.id; + op.total_claimed = asset(1); + op.balance_owner_key = v1_key.get_public_key(); + trx.clear(); + trx.set_expiration(db.head_block_id()); + trx.operations = {op}; + trx.sign(n_key); + trx.sign(v1_key); + // Attempting to claim 1 from a balance with 0 available + BOOST_CHECK_THROW(db.push_transaction(trx), invalid_claim_amount); + + op.balance_to_claim = vesting_balance_2.id; + op.total_claimed.amount = 151; + op.balance_owner_key = v2_key.get_public_key(); + trx.operations = {op}; + trx.signatures.clear(); + trx.sign(n_key); + trx.sign(v2_key); + // Attempting to claim 151 from a balance with 150 available + BOOST_CHECK_THROW(db.push_transaction(trx), invalid_claim_amount); + + op.balance_to_claim = vesting_balance_2.id; + op.total_claimed.amount = 100; + op.balance_owner_key = v2_key.get_public_key(); + trx.operations = {op}; + trx.signatures.clear(); + trx.sign(n_key); + trx.sign(v2_key); + db.push_transaction(trx); + + BOOST_CHECK_EQUAL(db.get_balance(op.deposit_to_account, asset_id_type()).amount.value, 101); + op.total_claimed.amount = 10; + trx.operations = {op}; + trx.signatures.clear(); + trx.sign(n_key); + trx.sign(v2_key); + // Attempting to claim twice within a day + BOOST_CHECK_THROW(db.push_transaction(trx), balance_claimed_too_often); + +// TODO: test withdrawing entire vesting_balance_1 balance, remainder of vesting_balance_2 balance +// slot = db.get_slot_at_time(vesting_balance_1.vesting_policy->begin_timestamp + 60); +// db.generate_block(starting_time, db.get_scheduled_witness(slot).first, delegate_priv_key, database::skip_nothing); + +// op.balance_to_claim = vesting_balance_1.id; +// op.total_claimed.amount = 500; +// op.balance_owner_key = v1_key.get_public_key(); +// trx.operations = {op}; +// trx.signatures.clear(); +// trx.sign(n_key); +// trx.sign(v2_key); +// db.push_transaction(trx); +// BOOST_CHECK(db.find_object(op.balance_to_claim) == nullptr); } FC_LOG_AND_RETHROW() } // TODO: Write linear VBO tests