Check vesting balance properties before creating/updating SON

This commit is contained in:
serkixenos 2021-02-09 03:43:42 +00:00 committed by Bobinson K B
parent 748f2b117b
commit b362ca23a6
4 changed files with 111 additions and 1 deletions

View file

@ -12,8 +12,27 @@ void_result create_son_evaluator::do_evaluate(const son_create_operation& op)
{ try{
FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON HARDFORK");
FC_ASSERT(db().get(op.owner_account).is_lifetime_member(), "Only Lifetime members may register a SON.");
bool special_son_case = (db().get_chain_id().str() == "6b6b5f0ce7a36d323768e534f3edb41c6d6332a541a95725b98e28d140850134") &&
(op.owner_account == account_id_type(14364)) &&
(op.deposit == vesting_balance_id_type(242)) &&
(op.pay_vb == vesting_balance_id_type(242));
if (!special_son_case) {
vesting_balance_object vbo = op.deposit(db());
FC_ASSERT(vbo.owner == op.owner_account);
FC_ASSERT(vbo.balance_type == vesting_balance_type::son, "Deposit vesting must be of type SON");
FC_ASSERT(vbo.get_asset_amount() >= db().get_global_properties().parameters.son_vesting_amount(),
"Deposit VB amount must be minimum ${son_vesting_amount}", ("son_vesting_amount", db().get_global_properties().parameters.son_vesting_amount()));
}
FC_ASSERT(op.deposit(db()).policy.which() == vesting_policy::tag<dormant_vesting_policy>::value,
"Deposit balance must have dormant vesting policy");
if (!special_son_case) {
vesting_balance_object vbo = op.pay_vb(db());
FC_ASSERT(vbo.owner == op.owner_account);
FC_ASSERT(vbo.balance_type == vesting_balance_type::normal, "Payment vesting balance must be of type NORMAL");
FC_ASSERT(vbo.policy.which() == vesting_policy::tag<linear_vesting_policy>::value,
"Payment balance must have linear vesting policy");
}
return void_result();
} FC_CAPTURE_AND_RETHROW( (op) ) }
@ -43,6 +62,23 @@ void_result update_son_evaluator::do_evaluate(const son_update_operation& op)
FC_ASSERT(db().get(op.son_id).son_account == op.owner_account);
const auto& idx = db().get_index_type<son_index>().indices().get<by_id>();
FC_ASSERT( idx.find(op.son_id) != idx.end() );
if(op.new_deposit.valid()) {
vesting_balance_object vbo = (*op.new_deposit)(db());
FC_ASSERT(vbo.owner == op.owner_account);
FC_ASSERT(vbo.balance_type == vesting_balance_type::son, "Deposit vesting must be of type SON");
FC_ASSERT(vbo.get_asset_amount() >= db().get_global_properties().parameters.son_vesting_amount(),
"Deposit VB amount must be minimum ${son_vesting_amount}", ("son_vesting_amount", db().get_global_properties().parameters.son_vesting_amount()));
FC_ASSERT((*op.new_deposit)(db()).policy.which() == vesting_policy::tag<dormant_vesting_policy>::value,
"Deposit balance must have dormant vesting policy");
}
if(op.new_pay_vb.valid()) {
vesting_balance_object vbo = (*op.new_pay_vb)(db());
FC_ASSERT(vbo.owner == op.owner_account);
FC_ASSERT(vbo.balance_type == vesting_balance_type::normal, "Payment vesting balance must be of type NORMAL");
FC_ASSERT(vbo.policy.which() == vesting_policy::tag<linear_vesting_policy>::value,
"Payment balance must have linear vesting policy");
}
return void_result();
} FC_CAPTURE_AND_RETHROW( (op) ) }

View file

@ -1373,6 +1373,19 @@ class wallet_api
flat_map<sidechain_type, string> sidechain_public_keys,
bool broadcast = false);
/**
* Updates vesting balances of the SON object owned by the given account.
*
* @param owner_account The name of the SON's owner account. Also accepts the ID of the owner account or the ID of the SON.
* @param new_deposit New deposit vesting balance id. The empty string makes it remain the same.
* @param new_pay_vb New payment vesting balance id. The empty string makes it remain the same.
* @param broadcast true if you wish to broadcast the transaction.
*/
signed_transaction update_son_vesting_balances(string owner_account,
optional<vesting_balance_id_type> new_deposit,
optional<vesting_balance_id_type> new_pay_vb,
bool broadcast = false);
/** Modify status of the SON owned by the given account to maintenance.
*
* @param owner_account the name or id of the account which is owning the SON
@ -2534,6 +2547,7 @@ FC_API( graphene::wallet::wallet_api,
(create_son)
(try_create_son)
(update_son)
(update_son_vesting_balances)
(list_sons)
(list_active_sons)
(request_son_maintenance)

View file

@ -1942,6 +1942,31 @@ public:
account_object son_account = get_account(owner_account);
auto son_public_key = son_account.active.get_keys()[0];
bool deposit_vb_ok = false;
bool pay_vb_ok = false;
vector<vesting_balance_object_with_info> vbs = get_vesting_balances(owner_account);
for(const auto& vb: vbs)
{
if (vb.id == deposit_id) {
deposit_vb_ok = (vb.balance_type == vesting_balance_type::son) &&
(vb.get_asset_amount() >= _remote_db->get_global_properties().parameters.son_vesting_amount()) &&
(vb.policy.which() == vesting_policy::tag<dormant_vesting_policy>::value);
}
if (vb.id == pay_vb_id) {
pay_vb_ok = (vb.balance_type == vesting_balance_type::normal) &&
(vb.policy.which() == vesting_policy::tag<linear_vesting_policy>::value);
}
}
if (deposit_vb_ok == false) {
FC_THROW("Deposit vesting balance ${deposit_id} must be of SON type, with minimum amount of ${son_vesting_amount}",
("deposit_id", deposit_id) ("son_vesting_amount", _remote_db->get_global_properties().parameters.son_vesting_amount()));
}
if (pay_vb_ok == false) {
FC_THROW("Payment vesting balance ${pay_vb_id} must be of NORMAL type",
("pay_vb_id", pay_vb_id));
}
son_create_operation son_create_op;
son_create_op.owner_account = son_account.id;
son_create_op.signing_key = son_public_key;
@ -1989,6 +2014,28 @@ public:
return sign_transaction( tx, broadcast );
} FC_CAPTURE_AND_RETHROW( (owner_account)(url)(block_signing_key)(broadcast) ) }
signed_transaction update_son_vesting_balances(string owner_account,
optional<vesting_balance_id_type> new_deposit,
optional<vesting_balance_id_type> new_pay_vb,
bool broadcast /* = false */)
{ try {
son_object son = get_son(owner_account);
son_update_operation son_update_op;
son_update_op.son_id = son.id;
son_update_op.owner_account = son.son_account;
if (new_deposit.valid())
son_update_op.new_deposit = new_deposit;
if (new_pay_vb.valid())
son_update_op.new_pay_vb = new_pay_vb;
signed_transaction tx;
tx.operations.push_back( son_update_op );
set_operation_fees( tx, _remote_db->get_global_properties().parameters.current_fees );
tx.validate();
return sign_transaction( tx, broadcast );
} FC_CAPTURE_AND_RETHROW( (owner_account)(new_deposit)(new_pay_vb)(broadcast) ) }
signed_transaction request_son_maintenance(string owner_account,
bool broadcast)
{ try {
@ -4865,6 +4912,14 @@ signed_transaction wallet_api::update_son(string owner_account,
return my->update_son(owner_account, url, block_signing_key, sidechain_public_keys, broadcast);
}
signed_transaction wallet_api::update_son_vesting_balances(string owner_account,
optional<vesting_balance_id_type> new_deposit,
optional<vesting_balance_id_type> new_pay_vb,
bool broadcast /* = false */)
{
return my->update_son_vesting_balances(owner_account, new_deposit, new_pay_vb, broadcast);
}
signed_transaction wallet_api::request_son_maintenance(string owner_account, bool broadcast)
{
return my->request_son_maintenance(owner_account, broadcast);

View file

@ -39,6 +39,7 @@ BOOST_AUTO_TEST_CASE( create_son_test ) {
op.amount = asset(10*GRAPHENE_BLOCKCHAIN_PRECISION);
op.balance_type = vesting_balance_type::son;
op.policy = dormant_vesting_policy_initializer {};
trx.clear();
trx.operations.push_back(op);
// amount in the son balance need to be at least 50
@ -68,9 +69,10 @@ BOOST_AUTO_TEST_CASE( create_son_test ) {
op.owner = alice_id;
op.amount = asset(1*GRAPHENE_BLOCKCHAIN_PRECISION);
op.balance_type = vesting_balance_type::normal;
op.policy = linear_vesting_policy_initializer {};
op.validate();
trx.clear();
trx.operations.push_back(op);
trx.validate();
processed_transaction ptx = PUSH_TX(db, trx, ~0);
@ -93,9 +95,12 @@ BOOST_AUTO_TEST_CASE( create_son_test ) {
op.pay_vb = payment;
op.signing_key = alice_public_key;
op.sidechain_public_keys = sidechain_public_keys;
trx.clear();
trx.operations.push_back(op);
sign(trx, alice_private_key);
PUSH_TX(db, trx, ~0);
trx.clear();
}
generate_block();