From 0b6f7fe430ce1ff15e01d76ea4762dbf0700e952 Mon Sep 17 00:00:00 2001 From: theoreticalbts Date: Thu, 10 Sep 2015 11:16:23 -0400 Subject: [PATCH 1/4] wallet.cpp: Ask remote DB for accounts on startup --- libraries/wallet/wallet.cpp | 52 ++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 9 deletions(-) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index 575db736..7a0608b7 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -649,15 +649,49 @@ public: ("wallet.chain_id", _wallet.chain_id) ("chain_id", _chain_id) ); - vector< account_id_type > my_account_ids; - my_account_ids.reserve( _wallet.my_accounts.size() ); - for( const account_object& acct : _wallet.my_accounts ) - my_account_ids.push_back( acct.id ); - // TODO: Batch requests using _remote_db->get_accounts() - // to reduce number of round-trips. Remember get_accounts() has - // a limit of 100 results per call! - for( const account_id_type& acct_id : my_account_ids ) - _wallet.update_account( get_account( acct_id ) ); + size_t account_pagination = 100; + vector< account_id_type > account_ids_to_send; + size_t n = _wallet.my_accounts.size(); + account_ids_to_send.reserve( std::min( account_pagination, n ) ); + auto it = _wallet.my_accounts.begin(); + + for( size_t start=0; start start ); + account_ids_to_send.clear(); + std::vector< account_object > old_accounts; + for( size_t i=start; i > accounts = _remote_db->get_accounts(account_ids_to_send); + // server response should be same length as request + FC_ASSERT( accounts.size() == account_ids_to_send.size() ); + size_t i = 0; + for( const optional< account_object >& acct : accounts ) + { + account_object& old_acct = old_accounts[i]; + if( !acct.valid() ) + { + elog( "Could not find account ${id} : \"${name}\" does not exist on the chain!", ("id", old_acct.id)("name", old_acct.name) ); + i++; + continue; + } + // this check makes sure the server didn't send results + // in a different order, or accounts we didn't request + FC_ASSERT( acct->id == old_acct.id ); + if( fc::json::to_string(*acct) != fc::json::to_string(old_acct) ) + { + wlog( "Account ${id} : \"${name}\" updated on chain", ("id", acct->id)("name", acct->name) ); + } + _wallet.update_account( *acct ); + i++; + } + } return true; } From e1530709d973c092526977c09cd00574ebba2f9e Mon Sep 17 00:00:00 2001 From: theoreticalbts Date: Thu, 10 Sep 2015 12:08:01 -0400 Subject: [PATCH 2/4] witness.cpp: Set skip_undo_history_check when --enable-stale-production is specified --- .../witness/include/graphene/witness/witness.hpp | 1 + libraries/plugins/witness/witness.cpp | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/libraries/plugins/witness/include/graphene/witness/witness.hpp b/libraries/plugins/witness/include/graphene/witness/witness.hpp index c82b83d8..df033094 100644 --- a/libraries/plugins/witness/include/graphene/witness/witness.hpp +++ b/libraries/plugins/witness/include/graphene/witness/witness.hpp @@ -75,6 +75,7 @@ private: bool _production_enabled = false; bool _consecutive_production_enabled = false; uint32_t _required_witness_participation = 33 * GRAPHENE_1_PERCENT; + uint32_t _production_skip_flags = graphene::chain::database::skip_nothing; std::map _private_keys; std::set _witnesses; diff --git a/libraries/plugins/witness/witness.cpp b/libraries/plugins/witness/witness.cpp index 24eb0309..db5154ec 100644 --- a/libraries/plugins/witness/witness.cpp +++ b/libraries/plugins/witness/witness.cpp @@ -123,8 +123,12 @@ void witness_plugin::plugin_startup() { ilog("Launching block production for ${n} witnesses.", ("n", _witnesses.size())); app().set_block_production(true); - if( _production_enabled && (d.head_block_num() == 0) ) - new_chain_banner(d); + if( _production_enabled ) + { + if( d.head_block_num() == 0 ) + new_chain_banner(d); + _production_skip_flags |= graphene::chain::database::skip_undo_history_check; + } schedule_production_loop(); } else elog("No witnesses configured! Please add witness IDs and private keys to configuration."); @@ -278,7 +282,7 @@ block_production_condition::block_production_condition_enum witness_plugin::mayb scheduled_time, scheduled_witness, private_key_itr->second, - graphene::chain::database::skip_nothing + _production_skip_flags ); capture("n", block.block_num())("t", block.timestamp)("c", now); p2p_node().broadcast(net::block_message(block)); From 77ac6eb689eeafad17aa1f59757977700614691e Mon Sep 17 00:00:00 2001 From: theoreticalbts Date: Thu, 10 Sep 2015 15:41:13 -0400 Subject: [PATCH 3/4] db_init.cpp: Don't allocate unnecessary asset_dynamic_data_object --- libraries/chain/db_init.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/chain/db_init.cpp b/libraries/chain/db_init.cpp index f3361bf1..55122d12 100644 --- a/libraries/chain/db_init.cpp +++ b/libraries/chain/db_init.cpp @@ -331,13 +331,13 @@ void database::init_genesis(const genesis_state_type& genesis_state) // Create more special assets while( true ) { + uint64_t id = get_index().get_next_id().instance(); + if( id >= genesis_state.immutable_parameters.num_special_assets ) + break; const asset_dynamic_data_object& dyn_asset = create([&](asset_dynamic_data_object& a) { a.current_supply = 0; }); - uint64_t id = get_index().get_next_id().instance(); - if( id >= genesis_state.immutable_parameters.num_special_assets ) - break; const asset_object& asset_obj = create( [&]( asset_object& a ) { a.symbol = "SPECIAL" + std::to_string( id ); a.options.max_supply = 0; From 358a88037c069b0b61ebdc0ac510e846b1fc9764 Mon Sep 17 00:00:00 2001 From: theoreticalbts Date: Thu, 10 Sep 2015 15:41:49 -0400 Subject: [PATCH 4/4] wallet.cpp: Subscribe to block updates, fix #302 --- libraries/app/api.cpp | 10 +++++++++- libraries/app/include/graphene/app/api.hpp | 3 +++ libraries/wallet/wallet.cpp | 11 +++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/libraries/app/api.cpp b/libraries/app/api.cpp index 5b61bc61..e440854f 100644 --- a/libraries/app/api.cpp +++ b/libraries/app/api.cpp @@ -923,10 +923,18 @@ namespace graphene { namespace app { */ void database_api::on_applied_block() { + if (_block_applied_callback) + { + auto capture_this = shared_from_this(); + block_id_type block_id = _db.head_block_id(); + fc::async([this,capture_this,block_id](){ + _block_applied_callback(fc::variant(block_id)); + }); + } + if(_market_subscriptions.size() == 0) return; - const auto& ops = _db.get_applied_operations(); map< std::pair, vector> > subscribed_markets_ops; for(const auto& op : ops) diff --git a/libraries/app/include/graphene/app/api.hpp b/libraries/app/include/graphene/app/api.hpp index ca83accd..8a94706f 100644 --- a/libraries/app/include/graphene/app/api.hpp +++ b/libraries/app/include/graphene/app/api.hpp @@ -367,6 +367,7 @@ namespace graphene { namespace app { void set_subscribe_callback( std::function cb, bool clear_filter ); void set_pending_transaction_callback( std::function cb ){ _pending_trx_callback = cb; } + void set_block_applied_callback( std::function cb ){ _block_applied_callback = cb; } private: template void subscribe_to_item( const T& i )const @@ -398,6 +399,7 @@ namespace graphene { namespace app { mutable fc::bloom_filter _subscribe_filter; std::function _subscribe_callback; std::function _pending_trx_callback; + std::function _block_applied_callback; boost::signals2::scoped_connection _change_connection; boost::signals2::scoped_connection _removed_connection; @@ -606,6 +608,7 @@ FC_API(graphene::app::database_api, (get_required_fees) (set_subscribe_callback) (set_pending_transaction_callback) + (set_block_applied_callback) (validate_transaction) ) FC_API(graphene::app::history_api, diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index 7a0608b7..7d5cef4b 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -375,6 +375,12 @@ public: ("chain_id", _chain_id) ); } init_prototype_ops(); + + _remote_db->set_block_applied_callback( [this](const variant& block_id ) + { + on_block_applied( block_id ); + } ); + _wallet.chain_id = _chain_id; _wallet.ws_server = initial_data.ws_server; _wallet.ws_user = initial_data.ws_user; @@ -408,6 +414,11 @@ public: } } + void on_block_applied( const variant& block_id ) + { + fc::async([this]{resync();}, "Resync after block"); + } + bool copy_wallet_file( string destination_filename ) { fc::path src_path = get_wallet_filename();