From 666ced390ee9eeab0cdd7f2d69fa0eef31bed5fe Mon Sep 17 00:00:00 2001 From: satyakoneru Date: Thu, 24 Oct 2019 03:46:04 +1100 Subject: [PATCH 01/10] SON126 - Witness Proposals to deregister SONs (#192) * SON126 - Witness Proposals to deregister SONs * SON126 - Approval by witness, removal of son_proposal_object, commenting * SON126 - Witness proposal tests and related fixes * SON126 - Proper commenting --- libraries/chain/db_block.cpp | 29 +++ libraries/chain/db_getter.cpp | 117 +++++++++- libraries/chain/db_init.cpp | 2 + .../chain/include/graphene/chain/config.hpp | 3 +- .../chain/include/graphene/chain/database.hpp | 7 + .../graphene/chain/proposal_evaluator.hpp | 15 ++ .../include/graphene/chain/protocol/son.hpp | 3 +- .../include/graphene/chain/protocol/types.hpp | 5 + .../include/graphene/chain/son_object.hpp | 13 ++ .../graphene/chain/son_proposal_object.hpp | 41 ++++ libraries/chain/proposal_evaluator.cpp | 16 ++ libraries/chain/son_evaluator.cpp | 7 +- libraries/wallet/wallet.cpp | 1 + tests/tests/son_operations_tests.cpp | 210 ++++++++++++++++++ 14 files changed, 465 insertions(+), 4 deletions(-) create mode 100644 libraries/chain/include/graphene/chain/son_proposal_object.hpp diff --git a/libraries/chain/db_block.cpp b/libraries/chain/db_block.cpp index 1ad84fa0..dafdc3ff 100644 --- a/libraries/chain/db_block.cpp +++ b/libraries/chain/db_block.cpp @@ -350,6 +350,7 @@ processed_transaction database::push_proposal(const proposal_object& proposal) auto session = _undo_db.start_undo_session(true); for( auto& op : proposal.proposed_transaction.operations ) eval_state.operation_results.emplace_back(apply_operation(eval_state, op)); + remove_son_proposal(proposal); remove(proposal); session.merge(); } catch ( const fc::exception& e ) { @@ -426,6 +427,34 @@ signed_block database::_generate_block( _pending_tx_session.reset(); _pending_tx_session = _undo_db.start_undo_session(); + if( head_block_time() > HARDFORK_SON_TIME ) + { + // Approve proposals raised by me in previous schedule or before + process_son_proposals( witness_obj, block_signing_private_key ); + // Check for new SON Deregistration Proposals to be raised + std::set sons_to_be_dereg = get_sons_to_be_deregistered(); + if(sons_to_be_dereg.size() > 0) + { + // We shouldn't raise proposals for the SONs for which a de-reg + // proposal is already raised. + std::set sons_being_dereg = get_sons_being_deregistered(); + for( auto& son : sons_to_be_dereg) + { + // New SON to be deregistered + if(sons_being_dereg.find(son) == sons_being_dereg.end()) + { + // Creating the de-reg proposal + auto op = create_son_deregister_proposal(son, witness_obj); + if(op.valid()) + { + // Signing and pushing into the txs to be included in the block + _pending_tx.insert( _pending_tx.begin(), create_signed_transaction( block_signing_private_key, *op ) ); + } + } + } + } + } + uint64_t postponed_tx_count = 0; // pop pending state (reset to head block state) for( const processed_transaction& tx : _pending_tx ) diff --git a/libraries/chain/db_getter.cpp b/libraries/chain/db_getter.cpp index aa50b551..a23ff6de 100644 --- a/libraries/chain/db_getter.cpp +++ b/libraries/chain/db_getter.cpp @@ -27,7 +27,8 @@ #include #include #include - +#include +#include #include #include @@ -141,4 +142,118 @@ const std::vector database::get_winner_numbers( asset_id_type for_asse return result; } +std::set database::get_sons_being_deregistered() +{ + std::set ret; + const auto& son_proposal_idx = get_index_type().indices().get< by_id >(); + + for( auto& son_proposal : son_proposal_idx ) + { + if(son_proposal.proposal_type == son_proposal_type::son_deregister_proposal) + { + ret.insert(son_proposal.son_id); + } + } + return ret; +} + +std::set database::get_sons_to_be_deregistered() +{ + std::set ret; + const auto& son_idx = get_index_type().indices().get< by_id >(); + + for( auto& son : son_idx ) + { + if(son.status == son_status::in_maintenance) + { + auto stats = son.statistics(*this); + // TODO : We need to add a function that returns if we can deregister SON + // i.e. with introduction of PW code, we have to make a decision if the SON + // is needed for release of funds from the PW + if(head_block_time() - stats.last_down_timestamp >= fc::hours(SON_DEREGISTER_TIME)) + { + ret.insert(son.id); + } + } + } + return ret; +} + +fc::optional database::create_son_deregister_proposal(const son_id_type& son_id, const witness_object& current_witness ) +{ + son_delete_operation son_dereg_op; + son_dereg_op.payer = current_witness.witness_account; + son_dereg_op.son_id = son_id; + + proposal_create_operation proposal_op; + proposal_op.fee_paying_account = current_witness.witness_account; + proposal_op.proposed_ops.push_back( op_wrapper( son_dereg_op ) ); + uint32_t lifetime = ( get_global_properties().parameters.block_interval * get_global_properties().active_witnesses.size() ) * 3; + proposal_op.expiration_time = time_point_sec( head_block_time().sec_since_epoch() + lifetime ); + return proposal_op; +} + +signed_transaction database::create_signed_transaction( const fc::ecc::private_key& signing_private_key, const operation& op ) +{ + signed_transaction processed_trx; + auto dyn_props = get_dynamic_global_properties(); + processed_trx.set_reference_block( dyn_props.head_block_id ); + processed_trx.set_expiration( head_block_time() + get_global_properties().parameters.maximum_time_until_expiration ); + processed_trx.operations.push_back( op ); + current_fee_schedule().set_fee( processed_trx.operations.back() ); + + processed_trx.sign( signing_private_key, get_chain_id() ); + + return processed_trx; +} + +void database::process_son_proposals( const witness_object& current_witness, const fc::ecc::private_key& private_key ) +{ + const auto& son_proposal_idx = get_index_type().indices().get< by_id >(); + const auto& proposal_idx = get_index_type().indices().get< by_id >(); + + auto approve_proposal = [ & ]( const proposal_id_type& id ) + { + proposal_update_operation puo; + puo.fee_paying_account = current_witness.witness_account; + puo.proposal = id; + puo.active_approvals_to_add = { current_witness.witness_account }; + _pending_tx.insert( _pending_tx.begin(), create_signed_transaction( private_key, puo ) ); + }; + + for( auto& son_proposal : son_proposal_idx ) + { + const auto& proposal = proposal_idx.find( son_proposal.proposal_id ); + FC_ASSERT( proposal != proposal_idx.end() ); + if( proposal->proposer == current_witness.witness_account) + { + approve_proposal( proposal->id ); + } + } +} + +void database::remove_son_proposal( const proposal_object& proposal ) +{ try { + if( proposal.proposed_transaction.operations.size() == 1 && + ( proposal.proposed_transaction.operations.back().which() == operation::tag::value) ) + { + const auto& son_proposal_idx = get_index_type().indices().get(); + auto son_proposal_itr = son_proposal_idx.find( proposal.id ); + if( son_proposal_itr == son_proposal_idx.end() ) { + return; + } + remove( *son_proposal_itr ); + } +} FC_CAPTURE_AND_RETHROW( (proposal) ) } + +bool database::is_son_dereg_valid( const son_id_type& son_id ) +{ + const auto& son_idx = get_index_type().indices().get< by_id >(); + auto son = son_idx.find( son_id ); + FC_ASSERT( son != son_idx.end() ); + bool ret = ( son->status == son_status::in_maintenance && + (head_block_time() - son->statistics(*this).last_down_timestamp >= fc::hours(SON_DEREGISTER_TIME))); + return ret; +} + } } diff --git a/libraries/chain/db_init.cpp b/libraries/chain/db_init.cpp index 445e3adc..7dc986a4 100644 --- a/libraries/chain/db_init.cpp +++ b/libraries/chain/db_init.cpp @@ -55,6 +55,7 @@ #include #include #include +#include #include #include @@ -288,6 +289,7 @@ void database::initialize_indexes() tournament_details_idx->add_secondary_index(); add_index< primary_index >(); add_index< primary_index >(); + add_index< primary_index >(); //Implementation object indexes add_index< primary_index >(); diff --git a/libraries/chain/include/graphene/chain/config.hpp b/libraries/chain/include/graphene/chain/config.hpp index cf02b968..37b0885d 100644 --- a/libraries/chain/include/graphene/chain/config.hpp +++ b/libraries/chain/include/graphene/chain/config.hpp @@ -233,7 +233,8 @@ #define TOURNAMENT_MAX_START_DELAY (60*60*24*7) // 1 week #define MIN_SON_MEMBER_COUNT 15 #define SON_VESTING_AMOUNT (50*GRAPHENE_BLOCKCHAIN_PRECISION) // 50 PPY -#define SON_VESTING_PERIOD (60*60*24*30) // 2 days +#define SON_VESTING_PERIOD (60*60*24*2) // 2 days +#define SON_DEREGISTER_TIME (12) // 12 Hours #define MIN_SON_PAY_DAILY_MAX (GRAPHENE_BLOCKCHAIN_PRECISION * int64_t(200)) #define SWEEPS_DEFAULT_DISTRIBUTION_PERCENTAGE (2*GRAPHENE_1_PERCENT) #define SWEEPS_DEFAULT_DISTRIBUTION_ASSET (graphene::chain::asset_id_type(0)) diff --git a/libraries/chain/include/graphene/chain/database.hpp b/libraries/chain/include/graphene/chain/database.hpp index 5f34eeaa..1e989a21 100644 --- a/libraries/chain/include/graphene/chain/database.hpp +++ b/libraries/chain/include/graphene/chain/database.hpp @@ -279,6 +279,13 @@ namespace graphene { namespace chain { const std::vector get_winner_numbers( asset_id_type for_asset, uint32_t count_members, uint8_t count_winners ) const; std::vector get_seeds( asset_id_type for_asset, uint8_t count_winners )const; uint64_t get_random_bits( uint64_t bound ); + std::set get_sons_being_deregistered(); + std::set get_sons_to_be_deregistered(); + fc::optional create_son_deregister_proposal(const son_id_type& son_id, const witness_object& current_witness ); + signed_transaction create_signed_transaction( const fc::ecc::private_key& signing_private_key, const operation& op ); + void process_son_proposals( const witness_object& current_witness, const fc::ecc::private_key& private_key ); + void remove_son_proposal( const proposal_object& proposal ); + bool is_son_dereg_valid( const son_id_type& son_id ); time_point_sec head_block_time()const; uint32_t head_block_num()const; diff --git a/libraries/chain/include/graphene/chain/proposal_evaluator.hpp b/libraries/chain/include/graphene/chain/proposal_evaluator.hpp index bf6fc547..a7b76471 100644 --- a/libraries/chain/include/graphene/chain/proposal_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/proposal_evaluator.hpp @@ -30,6 +30,21 @@ namespace graphene { namespace chain { + class son_hardfork_visitor + { + public: + typedef void result_type; + database& db; + proposal_id_type prop_id; + + son_hardfork_visitor( database& _db, const proposal_id_type& _prop_id ) : db( _db ), prop_id( _prop_id ) {} + + template + void operator()( const T &v ) const {} + + void operator()( const son_delete_operation &v ); + }; + class proposal_create_evaluator : public evaluator { public: diff --git a/libraries/chain/include/graphene/chain/protocol/son.hpp b/libraries/chain/include/graphene/chain/protocol/son.hpp index efea3ef7..7b7796fc 100644 --- a/libraries/chain/include/graphene/chain/protocol/son.hpp +++ b/libraries/chain/include/graphene/chain/protocol/son.hpp @@ -40,9 +40,10 @@ namespace graphene { namespace chain { asset fee; son_id_type son_id; + account_id_type payer; account_id_type owner_account; - account_id_type fee_payer()const { return owner_account; } + account_id_type fee_payer()const { return payer; } share_type calculate_fee(const fee_parameters_type& k)const { return 0; } }; diff --git a/libraries/chain/include/graphene/chain/protocol/types.hpp b/libraries/chain/include/graphene/chain/protocol/types.hpp index c1e592f8..bcdd1a83 100644 --- a/libraries/chain/include/graphene/chain/protocol/types.hpp +++ b/libraries/chain/include/graphene/chain/protocol/types.hpp @@ -146,6 +146,7 @@ namespace graphene { namespace chain { betting_market_object_type, bet_object_type, son_object_type, + son_proposal_object_type, OBJECT_TYPE_COUNT ///< Sentry value which contains the number of different object types }; @@ -207,6 +208,7 @@ namespace graphene { namespace chain { class betting_market_object; class bet_object; class son_object; + class son_proposal_object; typedef object_id< protocol_ids, account_object_type, account_object> account_id_type; typedef object_id< protocol_ids, asset_object_type, asset_object> asset_id_type; @@ -234,6 +236,7 @@ namespace graphene { namespace chain { typedef object_id< protocol_ids, betting_market_object_type, betting_market_object> betting_market_id_type; typedef object_id< protocol_ids, bet_object_type, bet_object> bet_id_type; typedef object_id< protocol_ids, son_object_type, son_object> son_id_type; + typedef object_id< protocol_ids, son_proposal_object_type, son_proposal_object> son_proposal_id_type; // implementation types class global_property_object; @@ -417,6 +420,7 @@ FC_REFLECT_ENUM( graphene::chain::object_type, (betting_market_object_type) (bet_object_type) (son_object_type) + (son_proposal_object_type) (OBJECT_TYPE_COUNT) ) FC_REFLECT_ENUM( graphene::chain::impl_object_type, @@ -488,6 +492,7 @@ FC_REFLECT_TYPENAME( graphene::chain::betting_market_position_id_type ) FC_REFLECT_TYPENAME( graphene::chain::global_betting_statistics_id_type ) FC_REFLECT_TYPENAME( graphene::chain::tournament_details_id_type ) FC_REFLECT_TYPENAME( graphene::chain::son_id_type ) +FC_REFLECT_TYPENAME( graphene::chain::son_proposal_id_type ) FC_REFLECT( graphene::chain::void_t, ) diff --git a/libraries/chain/include/graphene/chain/son_object.hpp b/libraries/chain/include/graphene/chain/son_object.hpp index dc5d3285..77316a4d 100644 --- a/libraries/chain/include/graphene/chain/son_object.hpp +++ b/libraries/chain/include/graphene/chain/son_object.hpp @@ -6,6 +6,12 @@ namespace graphene { namespace chain { using namespace graphene::db; + enum class son_status + { + inactive, + active, + in_maintenance + }; /** * @class son_statistics_object * @ingroup object @@ -23,6 +29,10 @@ namespace graphene { namespace chain { son_id_type owner; // Transactions signed since the last son payouts uint64_t txs_signed = 0; + // Total Downtime barring the current down time in seconds, used for stats to present to user + uint64_t total_downtime = 0; + // Down timestamp, if son status is in_maintenance use this + fc::time_point_sec last_down_timestamp; }; /** @@ -44,6 +54,7 @@ namespace graphene { namespace chain { public_key_type signing_key; vesting_balance_id_type pay_vb; son_statistics_id_type statistics; + son_status status = son_status::inactive; void pay_son_fee(share_type pay, database& db); }; @@ -76,6 +87,8 @@ namespace graphene { namespace chain { using son_stats_index = generic_index; } } // graphene::chain +FC_REFLECT_ENUM(graphene::chain::son_status, (inactive)(active)(in_maintenance) ) + FC_REFLECT_DERIVED( graphene::chain::son_object, (graphene::db::object), (son_account)(vote_id)(total_votes)(url)(deposit)(signing_key)(pay_vb) ) diff --git a/libraries/chain/include/graphene/chain/son_proposal_object.hpp b/libraries/chain/include/graphene/chain/son_proposal_object.hpp new file mode 100644 index 00000000..a8eb5384 --- /dev/null +++ b/libraries/chain/include/graphene/chain/son_proposal_object.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include +#include +#include + +namespace graphene { namespace chain { + +enum class son_proposal_type +{ + son_deregister_proposal +}; + +class son_proposal_object : public abstract_object +{ + public: + static const uint8_t space_id = protocol_ids; + static const uint8_t type_id = son_proposal_object_type; + + son_proposal_id_type get_id()const { return id; } + + proposal_id_type proposal_id; + son_id_type son_id; + son_proposal_type proposal_type; +}; + +struct by_proposal; +using son_proposal_multi_index_container = multi_index_container< + son_proposal_object, + indexed_by< + ordered_unique< tag< by_id >, member< object, object_id_type, &object::id > >, + ordered_unique< tag< by_proposal >, member< son_proposal_object, proposal_id_type, &son_proposal_object::proposal_id > > + > +>; +using son_proposal_index = generic_index; + +} } // graphene::chain + +FC_REFLECT_ENUM(graphene::chain::son_proposal_type, (son_deregister_proposal) ) + +FC_REFLECT_DERIVED( graphene::chain::son_proposal_object, (graphene::chain::object), (proposal_id)(son_id)(proposal_type) ) diff --git a/libraries/chain/proposal_evaluator.cpp b/libraries/chain/proposal_evaluator.cpp index 245e1a53..d377e0d8 100644 --- a/libraries/chain/proposal_evaluator.cpp +++ b/libraries/chain/proposal_evaluator.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -154,6 +155,15 @@ struct proposal_operation_hardfork_visitor } }; +void son_hardfork_visitor::operator()( const son_delete_operation &v ) +{ + db.create([&]( son_proposal_object& son_prop ) { + son_prop.proposal_type = son_proposal_type::son_deregister_proposal; + son_prop.proposal_id = prop_id; + son_prop.son_id = v.son_id; + }); +} + void_result proposal_create_evaluator::do_evaluate(const proposal_create_operation& o) { try { const database& d = db(); @@ -232,6 +242,12 @@ object_id_type proposal_create_evaluator::do_apply(const proposal_create_operati std::inserter(proposal.required_active_approvals, proposal.required_active_approvals.begin())); }); + son_hardfork_visitor son_vtor(d, proposal.id); + for(auto& op: o.proposed_ops) + { + op.op.visit(son_vtor); + } + return proposal.id; } FC_CAPTURE_AND_RETHROW( (o) ) } diff --git a/libraries/chain/son_evaluator.cpp b/libraries/chain/son_evaluator.cpp index 92bc7af6..c54d1391 100644 --- a/libraries/chain/son_evaluator.cpp +++ b/libraries/chain/son_evaluator.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -63,7 +64,11 @@ object_id_type update_son_evaluator::do_apply(const son_update_operation& op) void_result delete_son_evaluator::do_evaluate(const son_delete_operation& op) { try { FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON_HARDFORK"); // can be removed after HF date pass - FC_ASSERT(db().get(op.son_id).son_account == op.owner_account); + // Get the current block witness signatory + witness_id_type wit_id = db().get_scheduled_witness(1); + const witness_object& current_witness = wit_id(db()); + // Either owner can remove or witness + FC_ASSERT(db().get(op.son_id).son_account == op.owner_account || (db().is_son_dereg_valid(op.son_id) && op.payer == current_witness.witness_account)); const auto& idx = db().get_index_type().indices().get(); FC_ASSERT( idx.find(op.son_id) != idx.end() ); return void_result(); diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index d77a2a94..4244b7ef 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -1922,6 +1922,7 @@ public: son_delete_operation son_delete_op; son_delete_op.son_id = son.id; son_delete_op.owner_account = son.son_account; + son_delete_op.payer = son.son_account; signed_transaction tx; tx.operations.push_back( son_delete_op ); diff --git a/tests/tests/son_operations_tests.cpp b/tests/tests/son_operations_tests.cpp index 8d5ae3f2..a458b45e 100644 --- a/tests/tests/son_operations_tests.cpp +++ b/tests/tests/son_operations_tests.cpp @@ -4,6 +4,8 @@ #include #include +#include +#include #include #include @@ -142,6 +144,7 @@ try { son_delete_operation op; op.owner_account = alice_id; op.son_id = son_id_type(0); + op.payer = alice_id; trx.operations.push_back(op); sign(trx, alice_private_key); @@ -205,6 +208,7 @@ try { son_delete_operation op; op.owner_account = bob_id; op.son_id = son_id_type(0); + op.payer = bob_id; trx.operations.push_back(op); sign(trx, bob_private_key); @@ -442,4 +446,210 @@ BOOST_AUTO_TEST_CASE( son_pay_test ) BOOST_CHECK( dpo.witness_budget.value == 0); }FC_LOG_AND_RETHROW() + } + +BOOST_AUTO_TEST_CASE( son_witness_proposal_test ) +{ + try + { + const dynamic_global_property_object& dpo = db.get_dynamic_global_properties(); + generate_blocks(HARDFORK_SON_TIME); + generate_block(); + generate_block(); + set_expiration(db, trx); + + ACTORS((alice)(bob)); + + upgrade_to_lifetime_member(alice); + upgrade_to_lifetime_member(bob); + + transfer( committee_account, alice_id, asset( 1000*GRAPHENE_BLOCKCHAIN_PRECISION ) ); + transfer( committee_account, bob_id, asset( 1000*GRAPHENE_BLOCKCHAIN_PRECISION ) ); + + set_expiration(db, trx); + generate_block(); + // Now create SONs + std::string test_url1 = "https://create_son_test1"; + std::string test_url2 = "https://create_son_test2"; + + // create deposit vesting + vesting_balance_id_type deposit1; + { + vesting_balance_create_operation op; + op.creator = alice_id; + op.owner = alice_id; + op.amount = asset(50*GRAPHENE_BLOCKCHAIN_PRECISION); + op.balance_type = vesting_balance_type::son; + op.policy = dormant_vesting_policy_initializer {}; + + trx.operations.push_back(op); + for( auto& op : trx.operations ) db.current_fee_schedule().set_fee(op); + set_expiration(db, trx); + processed_transaction ptx = PUSH_TX(db, trx, ~0); + trx.clear(); + deposit1 = ptx.operation_results[0].get(); + } + + // create payment vesting + vesting_balance_id_type payment1; + { + vesting_balance_create_operation op; + op.creator = alice_id; + op.owner = alice_id; + op.amount = asset(1*GRAPHENE_BLOCKCHAIN_PRECISION); + op.balance_type = vesting_balance_type::normal; + + trx.operations.push_back(op); + for( auto& op : trx.operations ) db.current_fee_schedule().set_fee(op); + set_expiration(db, trx); + processed_transaction ptx = PUSH_TX(db, trx, ~0); + trx.clear(); + payment1 = ptx.operation_results[0].get(); + } + + // create deposit vesting + vesting_balance_id_type deposit2; + { + vesting_balance_create_operation op; + op.creator = bob_id; + op.owner = bob_id; + op.amount = asset(50*GRAPHENE_BLOCKCHAIN_PRECISION); + op.balance_type = vesting_balance_type::son; + op.policy = dormant_vesting_policy_initializer {}; + + trx.operations.push_back(op); + for( auto& op : trx.operations ) db.current_fee_schedule().set_fee(op); + set_expiration(db, trx); + processed_transaction ptx = PUSH_TX(db, trx, ~0); + trx.clear(); + deposit2 = ptx.operation_results[0].get(); + } + + // create payment vesting + vesting_balance_id_type payment2; + { + vesting_balance_create_operation op; + op.creator = bob_id; + op.owner = bob_id; + op.amount = asset(1*GRAPHENE_BLOCKCHAIN_PRECISION); + op.balance_type = vesting_balance_type::normal; + + trx.operations.push_back(op); + for( auto& op : trx.operations ) db.current_fee_schedule().set_fee(op); + set_expiration(db, trx); + processed_transaction ptx = PUSH_TX(db, trx, ~0); + trx.clear(); + payment2 = ptx.operation_results[0].get(); + } + + // alice becomes son + { + son_create_operation op; + op.owner_account = alice_id; + op.url = test_url1; + op.deposit = deposit1; + op.pay_vb = payment1; + op.fee = asset(0); + op.signing_key = alice_public_key; + trx.operations.push_back(op); + for( auto& op : trx.operations ) db.current_fee_schedule().set_fee(op); + sign(trx, alice_private_key); + PUSH_TX(db, trx, ~0); + trx.clear(); + } + + // bob becomes son + { + son_create_operation op; + op.owner_account = bob_id; + op.url = test_url2; + op.deposit = deposit2; + op.pay_vb = payment2; + op.fee = asset(0); + op.signing_key = bob_public_key; + trx.operations.push_back(op); + for( auto& op : trx.operations ) db.current_fee_schedule().set_fee(op); + sign(trx, bob_private_key); + PUSH_TX(db, trx, ~0); + trx.clear(); + } + + generate_block(); + // Check if SONs are created properly + const auto& idx = db.get_index_type().indices().get(); + BOOST_REQUIRE( idx.size() == 2 ); + // Alice's SON + auto obj1 = idx.find( alice_id ); + BOOST_REQUIRE( obj1 != idx.end() ); + BOOST_CHECK( obj1->url == test_url1 ); + BOOST_CHECK( obj1->signing_key == alice_public_key ); + BOOST_CHECK( obj1->deposit.instance == deposit1.instance.value ); + BOOST_CHECK( obj1->pay_vb.instance == payment1.instance.value ); + // Bob's SON + auto obj2 = idx.find( bob_id ); + BOOST_REQUIRE( obj2 != idx.end() ); + BOOST_CHECK( obj2->url == test_url2 ); + BOOST_CHECK( obj2->signing_key == bob_public_key ); + BOOST_CHECK( obj2->deposit.instance == deposit2.instance.value ); + BOOST_CHECK( obj2->pay_vb.instance == payment2.instance.value ); + // Get the statistics object for the SONs + const auto& sidx = db.get_index_type().indices().get(); + BOOST_REQUIRE( sidx.size() == 2 ); + auto son_stats_obj1 = sidx.find( obj1->statistics ); + auto son_stats_obj2 = sidx.find( obj2->statistics ); + BOOST_REQUIRE( son_stats_obj1 != sidx.end() ); + BOOST_REQUIRE( son_stats_obj2 != sidx.end() ); + + + // Modify SON's status to in_maintenance + db.modify( *obj1, [&]( son_object& _s) + { + _s.status = son_status::in_maintenance; + }); + + // Modify the Alice's SON down timestamp to now-12 hours + db.modify( *son_stats_obj1, [&]( son_statistics_object& _s) + { + _s.last_down_timestamp = fc::time_point_sec(db.head_block_time() - fc::hours(12)); + }); + + // Modify SON's status to in_maintenance + db.modify( *obj2, [&]( son_object& _s) + { + _s.status = son_status::in_maintenance; + }); + + // Modify the Bob's SON down timestamp to now-12 hours + db.modify( *son_stats_obj2, [&]( son_statistics_object& _s) + { + _s.last_down_timestamp = fc::time_point_sec(db.head_block_time() - fc::hours(12)); + }); + + const auto& son_proposal_idx = db.get_index_type().indices().get(); + const auto& proposal_idx = db.get_index_type().indices().get(); + + BOOST_CHECK( son_proposal_idx.size() == 0 && proposal_idx.size() == 0 ); + + generate_block(); + witness_id_type proposal_initiator = dpo.current_witness; + + BOOST_CHECK( son_proposal_idx.size() == 2 && proposal_idx.size() == 2 ); + + for(size_t i = 0 ; i < 3 * db.get_global_properties().active_witnesses.size() ; i++ ) + { + generate_block(); + if( dpo.current_witness != proposal_initiator) + { + BOOST_CHECK( son_proposal_idx.size() == 2 && proposal_idx.size() == 2 ); + } + else + { + break; + } + } + BOOST_CHECK( son_proposal_idx.size() == 0 && proposal_idx.size() == 0 ); + BOOST_REQUIRE( idx.size() == 0 ); + generate_block(); + } FC_LOG_AND_RETHROW() + } BOOST_AUTO_TEST_SUITE_END() From 11e98301946d7c62d513033ce73323feaa603684 Mon Sep 17 00:00:00 2001 From: gladcow Date: Wed, 30 Oct 2019 13:31:15 +0300 Subject: [PATCH 02/10] fix son_delete_operation reflection --- libraries/chain/include/graphene/chain/protocol/son.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/chain/include/graphene/chain/protocol/son.hpp b/libraries/chain/include/graphene/chain/protocol/son.hpp index 7b7796fc..93b8a0a4 100644 --- a/libraries/chain/include/graphene/chain/protocol/son.hpp +++ b/libraries/chain/include/graphene/chain/protocol/son.hpp @@ -58,4 +58,4 @@ FC_REFLECT(graphene::chain::son_update_operation, (fee)(son_id)(owner_account)(n (new_signing_key)(new_pay_vb) ) FC_REFLECT(graphene::chain::son_delete_operation::fee_parameters_type, (fee) ) -FC_REFLECT(graphene::chain::son_delete_operation, (fee)(son_id)(owner_account) ) +FC_REFLECT(graphene::chain::son_delete_operation, (fee)(son_id)(payer)(owner_account) ) From a0e4ac59ff5d6b9874f94bab63265d70038f8ea5 Mon Sep 17 00:00:00 2001 From: gladcow Date: Fri, 1 Nov 2019 16:43:34 +0300 Subject: [PATCH 03/10] [SON-160] Fix create_vesting wallet_api call (#206) * Fix create_vesting wallet_api call * change type for vesting_type in create_vesting_balance --- .../wallet/include/graphene/wallet/wallet.hpp | 12 +++++---- libraries/wallet/wallet.cpp | 27 ++++++++----------- tests/cli/son.cpp | 5 ++-- 3 files changed, 21 insertions(+), 23 deletions(-) diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index 9b3282c4..349ccea8 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -1429,15 +1429,17 @@ class wallet_api /** Creates a vesting deposit owned by the given account. * - * @param owner_account the name or id of the account - * @param amount the amount to deposit + * @param owner_account vesting balance owner and creator (the name or id) + * @param amount amount to vest + * @param asset_symbol the symbol of the asset to vest * @param vesting_type "normal", "gpos" or "son" * @param broadcast true to broadcast the transaction on the network * @returns the signed transaction registering a vesting object */ - signed_transaction create_vesting(string owner_account, + signed_transaction create_vesting_balance(string owner_account, string amount, - string vesting_type, + string asset_symbol, + vesting_balance_type vesting_type, bool broadcast = false); /** @@ -2118,7 +2120,7 @@ FC_API( graphene::wallet::wallet_api, (update_witness) (create_worker) (update_worker_votes) - (create_vesting) + (create_vesting_balance) (get_vesting_balances) (withdraw_vesting) (vote_for_committee_member) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index 4244b7ef..edc59a65 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -2107,27 +2107,21 @@ public: return sign_transaction( tx, broadcast ); } - signed_transaction create_vesting(string owner_account, + signed_transaction create_vesting_balance(string owner_account, string amount, - string vesting_type, + string asset_symbol, + vesting_balance_type vesting_type, bool broadcast /* = false */) { try { account_object son_account = get_account(owner_account); + fc::optional asset_obj = get_asset(asset_symbol); + FC_ASSERT(asset_obj, "Invalid asset symbol {asst}", ("asst", asset_symbol)); vesting_balance_create_operation op; op.creator = son_account.get_id(); op.owner = son_account.get_id(); - op.amount = asset_object().amount_from_string(amount); - if (vesting_type == "normal") - op.balance_type = vesting_balance_type::normal; - else if (vesting_type == "gpos") - op.balance_type = vesting_balance_type::gpos; - else if (vesting_type == "son") - op.balance_type = vesting_balance_type::son; - else - { - FC_ASSERT( false, "unknown vesting type value ${vt}", ("vt", vesting_type) ); - } + op.amount = asset_obj->amount_from_string(amount); + op.balance_type = vesting_type; if (op.balance_type == vesting_balance_type::son) op.policy = dormant_vesting_policy_initializer {}; @@ -4271,12 +4265,13 @@ committee_member_object wallet_api::get_committee_member(string owner_account) return my->get_committee_member(owner_account); } -signed_transaction wallet_api::create_vesting(string owner_account, +signed_transaction wallet_api::create_vesting_balance(string owner_account, string amount, - string vesting_type, + string asset_symbol, + vesting_balance_type vesting_type, bool broadcast /* = false */) { - return my->create_vesting(owner_account, amount, vesting_type, broadcast); + return my->create_vesting_balance(owner_account, amount, asset_symbol, vesting_type, broadcast); } signed_transaction wallet_api::create_son(string owner_account, diff --git a/tests/cli/son.cpp b/tests/cli/son.cpp index 1dfd8381..49779dfd 100644 --- a/tests/cli/son.cpp +++ b/tests/cli/son.cpp @@ -78,11 +78,12 @@ public: BOOST_CHECK(fixture_.generate_block()); // create deposit vesting - fixture_.con.wallet_api_ptr->create_vesting(account_name, "50000000", "son", true); + fixture_.con.wallet_api_ptr->create_vesting_balance(account_name, + "50", "1.3.0", vesting_balance_type::son, true); BOOST_CHECK(fixture_.generate_block()); // create pay_vb vesting - fixture_.con.wallet_api_ptr->create_vesting(account_name, "1000000", "normal", true); + fixture_.con.wallet_api_ptr->create_vesting_balance(account_name, "1", "1.3.0", vesting_balance_type::normal, true); BOOST_CHECK(fixture_.generate_block()); // check deposits are here From e4eb3e6ce3c519729dcb1876486827f1af9bbb6c Mon Sep 17 00:00:00 2001 From: gladcow Date: Fri, 1 Nov 2019 19:56:00 +0300 Subject: [PATCH 04/10] [SON-113] Fix several issues in update_son_votes call in wallet_api (#208) * do not allow update votes with both empty lists * fix error messages * check number of sons against votes number in account_object * Update error message --- libraries/chain/protocol/account.cpp | 11 +++++++++-- libraries/wallet/wallet.cpp | 9 +++++---- tests/cli/son.cpp | 27 ++++++++++++++++++++++----- 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/libraries/chain/protocol/account.cpp b/libraries/chain/protocol/account.cpp index cf592d5c..6721bb07 100644 --- a/libraries/chain/protocol/account.cpp +++ b/libraries/chain/protocol/account.cpp @@ -171,15 +171,22 @@ void account_options::validate() const { auto needed_witnesses = num_witness; auto needed_committee = num_committee; + auto needed_sons = num_son; for( vote_id_type id : votes ) if( id.type() == vote_id_type::witness && needed_witnesses ) --needed_witnesses; else if ( id.type() == vote_id_type::committee && needed_committee ) --needed_committee; + else if ( id.type() == vote_id_type::son && needed_sons ) + --needed_sons; - FC_ASSERT( needed_witnesses == 0 && needed_committee == 0, - "May not specify fewer witnesses or committee members than the number voted for."); + FC_ASSERT( needed_witnesses == 0, + "May not specify fewer witnesses than the number voted for."); + FC_ASSERT( needed_committee == 0, + "May not specify fewer committee members than the number voted for."); + FC_ASSERT( needed_sons == 0, + "May not specify fewer SONs than the number voted for."); } void affiliate_reward_distribution::validate() const diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index edc59a65..69f3cb7a 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -2266,26 +2266,27 @@ public: uint16_t desired_number_of_sons, bool broadcast /* = false */) { try { + FC_ASSERT(sons_to_approve.size() || sons_to_reject.size(), "Both accepted and rejected lists can't be empty simultaneously"); account_object voting_account_object = get_account(voting_account); for (const std::string& son : sons_to_approve) { account_id_type son_owner_account_id = get_account_id(son); fc::optional son_obj = _remote_db->get_son_by_account(son_owner_account_id); if (!son_obj) - FC_THROW("Account ${son} is not registered as a witness", ("son", son)); + FC_THROW("Account ${son} is not registered as a SON", ("son", son)); auto insert_result = voting_account_object.options.votes.insert(son_obj->vote_id); if (!insert_result.second) - FC_THROW("Account ${account} was already voting for son ${son}", ("account", voting_account)("son", son)); + FC_THROW("Account ${account} was already voting for SON ${son}", ("account", voting_account)("son", son)); } for (const std::string& son : sons_to_reject) { account_id_type son_owner_account_id = get_account_id(son); fc::optional son_obj = _remote_db->get_son_by_account(son_owner_account_id); if (!son_obj) - FC_THROW("Account ${son} is not registered as a son", ("son", son)); + FC_THROW("Account ${son} is not registered as a SON", ("son", son)); unsigned votes_removed = voting_account_object.options.votes.erase(son_obj->vote_id); if (!votes_removed) - FC_THROW("Account ${account} is already not voting for son ${son}", ("account", voting_account)("son", son)); + FC_THROW("Account ${account} is already not voting for SON ${son}", ("account", voting_account)("son", son)); } voting_account_object.options.num_son = desired_number_of_sons; diff --git a/tests/cli/son.cpp b/tests/cli/son.cpp index 49779dfd..b6c7b887 100644 --- a/tests/cli/son.cpp +++ b/tests/cli/son.cpp @@ -393,7 +393,7 @@ BOOST_AUTO_TEST_CASE( update_son_votes_test ) accepted.push_back("son1account"); accepted.push_back("son2account"); update_votes_tx = con.wallet_api_ptr->update_son_votes("nathan", accepted, - rejected, 15, true); + rejected, 2, true); BOOST_CHECK(generate_block()); BOOST_CHECK(generate_maintenance_block()); @@ -413,7 +413,7 @@ BOOST_AUTO_TEST_CASE( update_son_votes_test ) rejected.clear(); rejected.push_back("son1account"); update_votes_tx = con.wallet_api_ptr->update_son_votes("nathan", accepted, - rejected, 15, true); + rejected, 1, true); BOOST_CHECK(generate_maintenance_block()); // Verify the votes @@ -432,7 +432,7 @@ BOOST_AUTO_TEST_CASE( update_son_votes_test ) rejected.clear(); rejected.push_back("son1accnt"); BOOST_CHECK_THROW(update_votes_tx = con.wallet_api_ptr->update_son_votes("nathan", accepted, - rejected, 15, true), fc::exception); + rejected, 1, true), fc::exception); BOOST_CHECK(generate_block()); // Verify the votes @@ -450,7 +450,7 @@ BOOST_AUTO_TEST_CASE( update_son_votes_test ) rejected.clear(); rejected.push_back("son2account"); update_votes_tx = con.wallet_api_ptr->update_son_votes("nathan", accepted, - rejected, 15, true); + rejected, 0, true); BOOST_CHECK(generate_maintenance_block()); // Verify the votes @@ -469,7 +469,24 @@ BOOST_AUTO_TEST_CASE( update_son_votes_test ) rejected.push_back("son1accnt"); accepted.push_back("son1accnt"); BOOST_REQUIRE_THROW(update_votes_tx = con.wallet_api_ptr->update_son_votes("nathan", accepted, - rejected, 15, true), fc::exception); + rejected, 1, true), fc::exception); + BOOST_CHECK(generate_maintenance_block()); + + // Verify the votes + son1_obj = con.wallet_api_ptr->get_son("son1account"); + son1_end_votes = son1_obj.total_votes; + BOOST_CHECK(son1_end_votes == son1_start_votes); + son1_start_votes = son1_end_votes; + son2_obj = con.wallet_api_ptr->get_son("son2account"); + son2_end_votes = son2_obj.total_votes; + BOOST_CHECK(son2_end_votes == son2_start_votes); + son2_start_votes = son2_end_votes; + + // Try to accept and reject empty lists + accepted.clear(); + rejected.clear(); + BOOST_REQUIRE_THROW(update_votes_tx = con.wallet_api_ptr->update_son_votes("nathan", accepted, + rejected, 1, true), fc::exception); BOOST_CHECK(generate_maintenance_block()); // Verify the votes From 22f76a04c01c0fe68ef8346bacae3c6d1e95ec90 Mon Sep 17 00:00:00 2001 From: gladcow Date: Wed, 6 Nov 2019 17:58:32 +0300 Subject: [PATCH 05/10] list_active_sons api call implementation --- .../wallet/include/graphene/wallet/wallet.hpp | 7 +++++ libraries/wallet/wallet.cpp | 31 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index 349ccea8..2b511ba7 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -1363,6 +1363,13 @@ class wallet_api */ map list_sons(const string& lowerbound, uint32_t limit); + /** Lists active at the moment SONs. + * This returns a list of all account names that own active SON, and the associated SON id, + * sorted by name. + * @returns a list of active SONs mapping SON names to SON ids + */ + map list_active_sons(); + /** Creates a witness object owned by the given account. * * An account can have at most one witness object. diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index 69f3cb7a..c427f373 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -1932,6 +1932,32 @@ public: return sign_transaction( tx, broadcast ); } FC_CAPTURE_AND_RETHROW( (owner_account)(broadcast) ) } + map list_active_sons() + { try { + global_property_object gpo = get_global_properties(); + std::vector> son_objects = + _remote_db->get_sons(gpo.active_sons); + vector owners; + owners.resize(son_objects.size()); + std::transform(son_objects.begin(), son_objects.end(), owners.begin(), + [](const fc::optional& obj) { + if(!obj) + FC_THROW("Invalid active SONs list in global properties."); + return obj->son_account; + }); + vector> accs = _remote_db->get_accounts(owners); + map result; + std::transform(accs.begin(), accs.end(), gpo.active_sons.begin(), + std::inserter(result, result.end()), + [](fc::optional& acct, + son_id_type& sid) { + if(!acct) + FC_THROW("Invalid active SONs list in global properties."); + return std::make_pair(string(acct->name), std::move(sid)); + }); + return result; + } FC_CAPTURE_AND_RETHROW() } + signed_transaction create_witness(string owner_account, string url, bool broadcast /* = false */) @@ -4303,6 +4329,11 @@ map wallet_api::list_sons(const string& lowerbound, uint32_ return my->_remote_db->lookup_son_accounts(lowerbound, limit); } +map wallet_api::list_active_sons() +{ + return my->list_active_sons(); +} + signed_transaction wallet_api::create_witness(string owner_account, string url, bool broadcast /* = false */) From 8c4eb579a724ec52265b3e0a8553637c5964e006 Mon Sep 17 00:00:00 2001 From: gladcow Date: Thu, 7 Nov 2019 13:03:32 +0300 Subject: [PATCH 06/10] unit test for list_active_sons --- tests/cli/son.cpp | 56 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/tests/cli/son.cpp b/tests/cli/son.cpp index b6c7b887..b72bf567 100644 --- a/tests/cli/son.cpp +++ b/tests/cli/son.cpp @@ -530,6 +530,62 @@ BOOST_AUTO_TEST_CASE( related_functions ) BOOST_TEST_MESSAGE("SON-related functions cli wallet tests end"); } +BOOST_FIXTURE_TEST_CASE( cli_list_active_sons, cli_fixture ) +{ + BOOST_TEST_MESSAGE("SON cli wallet tests for list_active_sons begin"); + try + { + son_test_helper sth(*this); + + signed_transaction vote_tx; + global_property_object gpo; + + gpo = con.wallet_api_ptr->get_global_properties(); + unsigned int son_number = gpo.parameters.maximum_son_count; + + // create son accounts + for(unsigned int i = 0; i < son_number + 1; i++) + { + sth.create_son("sonaccount" + fc::to_pretty_string(i), + "http://son" + fc::to_pretty_string(i), false); + } + BOOST_CHECK(generate_maintenance_block()); + + BOOST_TEST_MESSAGE("Voting for SONs"); + for(unsigned int i = 1; i < son_number + 1; i++) + { + std::string name = "sonaccount" + fc::to_pretty_string(i); + vote_tx = con.wallet_api_ptr->vote_for_son(name, name, true, true); + } + BOOST_CHECK(generate_maintenance_block()); + + for(unsigned int i = 1; i < son_number; i++) + { + std::string name1 = "sonaccount" + fc::to_pretty_string(i); + std::string name2 = "sonaccount" + fc::to_pretty_string(i + 1); + vote_tx = con.wallet_api_ptr->vote_for_son(name1, name2, true, true); + } + BOOST_CHECK(generate_maintenance_block()); + gpo = con.wallet_api_ptr->get_global_properties(); + BOOST_TEST_MESSAGE("gpo: " << gpo.active_sons.size()); + + BOOST_CHECK(gpo.active_sons.size() == son_number); + + map active_sons = con.wallet_api_ptr->list_active_sons(); + BOOST_CHECK(active_sons.size() == son_number); + for(unsigned int i = 1; i < son_number + 1; i++) + { + std::string name = "sonaccount" + fc::to_pretty_string(i); + BOOST_CHECK(active_sons.find(name) != active_sons.end()); + } + + } catch( fc::exception& e ) { + BOOST_TEST_MESSAGE("SON cli wallet tests exception"); + edump((e.to_detail_string())); + throw; + } + BOOST_TEST_MESSAGE("SON cli wallet tests for list_active_sons end"); +} BOOST_AUTO_TEST_SUITE_END() From 62f973ca80ad3a2b8359300f6196a488b9eb20ed Mon Sep 17 00:00:00 2001 From: gladcow Date: Mon, 11 Nov 2019 12:54:54 +0300 Subject: [PATCH 07/10] fix code style --- libraries/wallet/wallet.cpp | 42 ++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index c427f373..f769fd12 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -1934,28 +1934,26 @@ public: map list_active_sons() { try { - global_property_object gpo = get_global_properties(); - std::vector> son_objects = - _remote_db->get_sons(gpo.active_sons); - vector owners; - owners.resize(son_objects.size()); - std::transform(son_objects.begin(), son_objects.end(), owners.begin(), - [](const fc::optional& obj) { - if(!obj) - FC_THROW("Invalid active SONs list in global properties."); - return obj->son_account; - }); - vector> accs = _remote_db->get_accounts(owners); - map result; - std::transform(accs.begin(), accs.end(), gpo.active_sons.begin(), - std::inserter(result, result.end()), - [](fc::optional& acct, - son_id_type& sid) { - if(!acct) - FC_THROW("Invalid active SONs list in global properties."); - return std::make_pair(string(acct->name), std::move(sid)); - }); - return result; + global_property_object gpo = get_global_properties(); + std::vector> son_objects = _remote_db->get_sons(gpo.active_sons); + vector owners; + owners.resize(son_objects.size()); + std::transform(son_objects.begin(), son_objects.end(), owners.begin(), + [](const fc::optional& obj) { + if(!obj) + FC_THROW("Invalid active SONs list in global properties."); + return obj->son_account; + }); + vector> accs = _remote_db->get_accounts(owners); + map result; + std::transform(accs.begin(), accs.end(), gpo.active_sons.begin(), + std::inserter(result, result.end()), + [](fc::optional& acct, son_id_type& sid) { + if(!acct) + FC_THROW("Invalid active SONs list in global properties."); + return std::make_pair(string(acct->name), std::move(sid)); + }); + return result; } FC_CAPTURE_AND_RETHROW() } signed_transaction create_witness(string owner_account, From dbf6be02c5a4def3d4c2e4405bc9ec517b9a8386 Mon Sep 17 00:00:00 2001 From: gladcow Date: Mon, 11 Nov 2019 13:13:57 +0300 Subject: [PATCH 08/10] use assert instead of checking condition with low possibility --- libraries/wallet/wallet.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index f769fd12..f7cc2a51 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -1940,8 +1940,7 @@ public: owners.resize(son_objects.size()); std::transform(son_objects.begin(), son_objects.end(), owners.begin(), [](const fc::optional& obj) { - if(!obj) - FC_THROW("Invalid active SONs list in global properties."); + FC_ASSERT(obj, "Invalid active SONs list in global properties."); return obj->son_account; }); vector> accs = _remote_db->get_accounts(owners); @@ -1949,8 +1948,7 @@ public: std::transform(accs.begin(), accs.end(), gpo.active_sons.begin(), std::inserter(result, result.end()), [](fc::optional& acct, son_id_type& sid) { - if(!acct) - FC_THROW("Invalid active SONs list in global properties."); + FC_ASSERT(acct, "Invalid active SONs list in global properties."); return std::make_pair(string(acct->name), std::move(sid)); }); return result; From ae781e48afb2f080aa8e60e562a6945ce9bf235f Mon Sep 17 00:00:00 2001 From: Sandip Patel Date: Tue, 12 Nov 2019 00:23:14 +0530 Subject: [PATCH 09/10] Fixed betting tests (#217) * Fixed betting tests * Removed comments --- libraries/chain/db_init.cpp | 2 +- libraries/db/include/graphene/db/index.hpp | 9 --------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/libraries/chain/db_init.cpp b/libraries/chain/db_init.cpp index 7dc986a4..72841afe 100644 --- a/libraries/chain/db_init.cpp +++ b/libraries/chain/db_init.cpp @@ -263,7 +263,7 @@ void database::initialize_indexes() acnt_index->add_secondary_index(); add_index< primary_index >(); // 256 members per chunk - add_index< primary_index >(); // 256 sons per chunk + add_index< primary_index >(); add_index< primary_index >(); // 1024 witnesses per chunk add_index< primary_index >(); add_index< primary_index >(); diff --git a/libraries/db/include/graphene/db/index.hpp b/libraries/db/include/graphene/db/index.hpp index e8d4fa11..1bc593f4 100644 --- a/libraries/db/include/graphene/db/index.hpp +++ b/libraries/db/include/graphene/db/index.hpp @@ -402,15 +402,6 @@ namespace graphene { namespace db { DerivedIndex::remove(obj); } - virtual const object& insert( object&& obj )override - { - const auto& res = DerivedIndex::insert(std::move(obj)); - for( const auto& item : _sindex ) - item->object_inserted( res ); - on_add(res); - return res; - } - virtual void modify( const object& obj, const std::function& m )override { save_undo( obj ); From 76b95729e1c0208715b1e4e18ea43835f4c1eab4 Mon Sep 17 00:00:00 2001 From: Sandip Patel Date: Thu, 21 Nov 2019 13:34:29 +0530 Subject: [PATCH 10/10] removed unrelated parameter description from delete_son --- libraries/wallet/include/graphene/wallet/wallet.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index 2b511ba7..6a78d8d3 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -1340,8 +1340,6 @@ class wallet_api * An account can have at most one witness object. * * @param owner_account the name or id of the account which is creating the witness - * @param url a URL to include in the witness record in the blockchain. Clients may - * display this when showing a list of witnesses. May be blank. * @param broadcast true to broadcast the transaction on the network * @returns the signed transaction registering a witness */