From 33728e3e6a3e05a4cfacbe8b6a8be3bbe191574e Mon Sep 17 00:00:00 2001 From: root Date: Tue, 5 Jan 2016 16:16:43 +0800 Subject: [PATCH 01/37] Update bitcube's seed node address --- libraries/app/application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/app/application.cpp b/libraries/app/application.cpp index f120ea54..b6c39522 100644 --- a/libraries/app/application.cpp +++ b/libraries/app/application.cpp @@ -157,7 +157,7 @@ namespace detail { "seed05.bitsharesnodes.com:1776", // thom "seed06.bitsharesnodes.com:1776", // thom "seed07.bitsharesnodes.com:1776", // thom - "128.199.131.4:1777", // cube + "seed.cubeconnex.com:1777", // cube "54.85.252.77:39705", // lafona "104.236.144.84:1777", // puppies "40.127.190.171:1777", // betax From 16b34f66be971171eb79e2eb9fc9918e010db75f Mon Sep 17 00:00:00 2001 From: abitmore Date: Tue, 12 Jan 2016 22:48:21 +0100 Subject: [PATCH 02/37] Add harvey's seed node --- libraries/app/application.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/app/application.cpp b/libraries/app/application.cpp index f120ea54..73cef53c 100644 --- a/libraries/app/application.cpp +++ b/libraries/app/application.cpp @@ -151,7 +151,7 @@ namespace detail { vector seeds = { "faucet.bitshares.org:1776", "bitshares.openledger.info:1776", - "114.92.254.159:62015", + "114.92.254.159:62015", // abit "seed.blocktrades.us:1776", "seed04.bitsharesnodes.com:1776", // thom "seed05.bitsharesnodes.com:1776", // thom @@ -163,7 +163,8 @@ namespace detail { "40.127.190.171:1777", // betax "185.25.22.21:1776", // liondani (greece) "23.95.43.126:50696", // iHashFury - "109.73.172.144:50696" // iHashFury + "109.73.172.144:50696", // iHashFury + "128.199.143.47:2015", // Harvey }; for( const string& endpoint_string : seeds ) { From 65f7c1ca62833b6f840be4c5e1d75b05775cc977 Mon Sep 17 00:00:00 2001 From: abitmore Date: Tue, 12 Jan 2016 23:04:27 +0100 Subject: [PATCH 03/37] Remove the extra comma from seed node list --- libraries/app/application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/app/application.cpp b/libraries/app/application.cpp index 73cef53c..7308dead 100644 --- a/libraries/app/application.cpp +++ b/libraries/app/application.cpp @@ -164,7 +164,7 @@ namespace detail { "185.25.22.21:1776", // liondani (greece) "23.95.43.126:50696", // iHashFury "109.73.172.144:50696", // iHashFury - "128.199.143.47:2015", // Harvey + "128.199.143.47:2015" // Harvey }; for( const string& endpoint_string : seeds ) { From d6db28971715dfa6d95ec265fc85cdeb961801ce Mon Sep 17 00:00:00 2001 From: abitmore Date: Wed, 13 Jan 2016 10:30:33 +0100 Subject: [PATCH 04/37] Add alt's seed node --- libraries/app/application.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/app/application.cpp b/libraries/app/application.cpp index 7308dead..d8a8b1c7 100644 --- a/libraries/app/application.cpp +++ b/libraries/app/application.cpp @@ -164,7 +164,8 @@ namespace detail { "185.25.22.21:1776", // liondani (greece) "23.95.43.126:50696", // iHashFury "109.73.172.144:50696", // iHashFury - "128.199.143.47:2015" // Harvey + "128.199.143.47:2015", // Harvey + "106.185.26.162:34045" // alt }; for( const string& endpoint_string : seeds ) { From dad47e29fbdd2c6bb264be1080f5d45209bfef63 Mon Sep 17 00:00:00 2001 From: Daniel Larimer Date: Mon, 29 Feb 2016 19:42:53 -0500 Subject: [PATCH 05/37] adding ability to pass wallet password on CLI --- programs/cli_wallet/main.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/programs/cli_wallet/main.cpp b/programs/cli_wallet/main.cpp index 040b6fac..794374b2 100644 --- a/programs/cli_wallet/main.cpp +++ b/programs/cli_wallet/main.cpp @@ -77,8 +77,9 @@ int main( int argc, char** argv ) ("rpc-tls-endpoint,t", bpo::value()->implicit_value("127.0.0.1:8092"), "Endpoint for wallet websocket TLS RPC to listen on") ("rpc-tls-certificate,c", bpo::value()->implicit_value("server.pem"), "PEM certificate for wallet websocket TLS RPC") ("rpc-http-endpoint,H", bpo::value()->implicit_value("127.0.0.1:8093"), "Endpoint for wallet HTTP RPC to listen on") + ("unlock", bpo::value(), "Password to automatically unlock wallet with") ("daemon,d", "Run the wallet in daemon mode" ) - ("wallet-file,w", bpo::value()->implicit_value("wallet.json"), "wallet to load") + ("wallet-file,W", bpo::value()->implicit_value("wallet.json"), "wallet to load") ("chain-id", bpo::value(), "chain ID to connect to"); bpo::variables_map options; @@ -254,6 +255,9 @@ int main( int argc, char** argv ) conn->on_request( req, resp ); } ); } + if( options.count("unlock" ) ) { + wapi->unlock( options.at("unlock").as() ); + } if( !options.count( "daemon" ) ) { From 02d9836ef5a8b2843d22d27aa9e4962c29fdcfff Mon Sep 17 00:00:00 2001 From: valzav Date: Wed, 2 Mar 2016 18:42:18 -0500 Subject: [PATCH 06/37] bump gui_version --- gui_version | 2 +- libraries/fc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gui_version b/gui_version index b16e8d03..456ffbec 100644 --- a/gui_version +++ b/gui_version @@ -1 +1 @@ -2.0.160208 +2.0.160302 diff --git a/libraries/fc b/libraries/fc index e5ca765f..64950043 160000 --- a/libraries/fc +++ b/libraries/fc @@ -1 +1 @@ -Subproject commit e5ca765f1508f2a05bb980231ee8e4b8985b51cf +Subproject commit 6495004302239ae0c775f05a0e78780c3b189502 From 24e132112da3614d275794fe74203c10bb47c302 Mon Sep 17 00:00:00 2001 From: Eric Frias Date: Thu, 3 Mar 2016 17:31:05 -0500 Subject: [PATCH 07/37] Update fc submodule --- libraries/fc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/fc b/libraries/fc index 64950043..d5370fc2 160000 --- a/libraries/fc +++ b/libraries/fc @@ -1 +1 @@ -Subproject commit 6495004302239ae0c775f05a0e78780c3b189502 +Subproject commit d5370fc2ea436fa4340cda01af98c7993fbc67d5 From 6189ebb86c537c31bc39baaa6de5350cdc8dcbe5 Mon Sep 17 00:00:00 2001 From: theoreticalbts Date: Fri, 4 Mar 2016 10:58:54 -0500 Subject: [PATCH 08/37] Revert "adding ability to pass wallet password on CLI" This reverts commit dad47e29fbdd2c6bb264be1080f5d45209bfef63. --- programs/cli_wallet/main.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/programs/cli_wallet/main.cpp b/programs/cli_wallet/main.cpp index 794374b2..040b6fac 100644 --- a/programs/cli_wallet/main.cpp +++ b/programs/cli_wallet/main.cpp @@ -77,9 +77,8 @@ int main( int argc, char** argv ) ("rpc-tls-endpoint,t", bpo::value()->implicit_value("127.0.0.1:8092"), "Endpoint for wallet websocket TLS RPC to listen on") ("rpc-tls-certificate,c", bpo::value()->implicit_value("server.pem"), "PEM certificate for wallet websocket TLS RPC") ("rpc-http-endpoint,H", bpo::value()->implicit_value("127.0.0.1:8093"), "Endpoint for wallet HTTP RPC to listen on") - ("unlock", bpo::value(), "Password to automatically unlock wallet with") ("daemon,d", "Run the wallet in daemon mode" ) - ("wallet-file,W", bpo::value()->implicit_value("wallet.json"), "wallet to load") + ("wallet-file,w", bpo::value()->implicit_value("wallet.json"), "wallet to load") ("chain-id", bpo::value(), "chain ID to connect to"); bpo::variables_map options; @@ -255,9 +254,6 @@ int main( int argc, char** argv ) conn->on_request( req, resp ); } ); } - if( options.count("unlock" ) ) { - wapi->unlock( options.at("unlock").as() ); - } if( !options.count( "daemon" ) ) { From 71a07e701cf0627763524ad523ba9fbcedbf5751 Mon Sep 17 00:00:00 2001 From: Krzysztof Szumny Date: Sun, 6 Mar 2016 16:46:32 +0100 Subject: [PATCH 09/37] Badge with link to slack --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 567aca96..22892354 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +[![Slack](http://slack.bitshares.org/badge.svg)](http://slack.bitshares.org/) + Intro for new developers ------------------------ From 4138ec29cce8d008a3ae99b20991899f61f2a02a Mon Sep 17 00:00:00 2001 From: theoreticalbts Date: Mon, 7 Mar 2016 13:40:47 -0500 Subject: [PATCH 10/37] account_evaluator.cpp: Remove redundant vote check #611 --- libraries/chain/account_evaluator.cpp | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/libraries/chain/account_evaluator.cpp b/libraries/chain/account_evaluator.cpp index 1f29bb0a..e5fcc454 100644 --- a/libraries/chain/account_evaluator.cpp +++ b/libraries/chain/account_evaluator.cpp @@ -85,26 +85,16 @@ void_result account_create_evaluator::do_evaluate( const account_create_operatio if( op.extensions.value.buyback_options.valid() ) evaluate_buyback_account_options( d, *op.extensions.value.buyback_options ); - uint32_t max_vote_id = global_props.next_available_vote_id; - - FC_ASSERT( op.options.num_witness <= chain_params.maximum_witness_count, + FC_ASSERT( op.options.num_witness <= chain_params.maximum_witness_count, "Voted for more witnesses than currently allowed (${c})", ("c", chain_params.maximum_witness_count) ); - FC_ASSERT( op.options.num_committee <= chain_params.maximum_committee_count, "Voted for more committee members than currently allowed (${c})", ("c", chain_params.maximum_committee_count) ); - safe counts[vote_id_type::VOTE_TYPE_COUNT]; + uint32_t max_vote_id = global_props.next_available_vote_id; for( auto id : op.options.votes ) { FC_ASSERT( id < max_vote_id ); - counts[id.type()]++; } - FC_ASSERT(counts[vote_id_type::witness] <= op.options.num_witness, - "", - ("count", counts[vote_id_type::witness])("num", op.options.num_witness)); - FC_ASSERT(counts[vote_id_type::committee] <= op.options.num_committee, - "", - ("count", counts[vote_id_type::committee])("num", op.options.num_committee)); auto& acnt_indx = d.get_index_type(); if( op.name.size() ) From 241a7b0c3ad3e330c09b0ff2d959a92d51c77254 Mon Sep 17 00:00:00 2001 From: theoreticalbts Date: Mon, 7 Mar 2016 13:49:23 -0500 Subject: [PATCH 11/37] account_evaluator.cpp: Refactor verify_account_votes() into own method #611 --- libraries/chain/account_evaluator.cpp | 51 +++++++++++++-------------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/libraries/chain/account_evaluator.cpp b/libraries/chain/account_evaluator.cpp index e5fcc454..b44597e4 100644 --- a/libraries/chain/account_evaluator.cpp +++ b/libraries/chain/account_evaluator.cpp @@ -54,6 +54,28 @@ void verify_authority_accounts( const database& db, const authority& a ) } } +void verify_account_votes( const database& db, const account_options& options ) +{ + // ensure account's votes satisfy requirements + // NB only the part of vote checking that requires chain state is here, + // the rest occurs in account_options::validate() + + const auto& gpo = db.get_global_properties(); + const auto& chain_params = gpo.parameters; + + FC_ASSERT( options.num_witness <= chain_params.maximum_witness_count, + "Voted for more witnesses than currently allowed (${c})", ("c", chain_params.maximum_witness_count) ); + FC_ASSERT( options.num_committee <= chain_params.maximum_committee_count, + "Voted for more committee members than currently allowed (${c})", ("c", chain_params.maximum_committee_count) ); + + uint32_t max_vote_id = gpo.next_available_vote_id; + for( auto id : options.votes ) + { + FC_ASSERT( id < max_vote_id ); + } +} + + void_result account_create_evaluator::do_evaluate( const account_create_operation& op ) { try { database& d = db(); @@ -67,9 +89,6 @@ void_result account_create_evaluator::do_evaluate( const account_create_operatio FC_ASSERT( fee_paying_account->is_lifetime_member(), "Only Lifetime members may register an account." ); FC_ASSERT( op.referrer(d).is_member(d.head_block_time()), "The referrer must be either a lifetime or annual subscriber." ); - const auto& global_props = d.get_global_properties(); - const auto& chain_params = global_props.parameters; - try { verify_authority_accounts( d, op.owner ); @@ -84,17 +103,7 @@ void_result account_create_evaluator::do_evaluate( const account_create_operatio evaluate_special_authority( d, *op.extensions.value.active_special_authority ); if( op.extensions.value.buyback_options.valid() ) evaluate_buyback_account_options( d, *op.extensions.value.buyback_options ); - - FC_ASSERT( op.options.num_witness <= chain_params.maximum_witness_count, - "Voted for more witnesses than currently allowed (${c})", ("c", chain_params.maximum_witness_count) ); - FC_ASSERT( op.options.num_committee <= chain_params.maximum_committee_count, - "Voted for more committee members than currently allowed (${c})", ("c", chain_params.maximum_committee_count) ); - - uint32_t max_vote_id = global_props.next_available_vote_id; - for( auto id : op.options.votes ) - { - FC_ASSERT( id < max_vote_id ); - } + verify_account_votes( d, op.options ); auto& acnt_indx = d.get_index_type(); if( op.name.size() ) @@ -214,8 +223,6 @@ void_result account_update_evaluator::do_evaluate( const account_update_operatio FC_ASSERT( !o.extensions.value.active_special_authority.valid() ); } - const auto& chain_params = d.get_global_properties().parameters; - try { if( o.owner ) verify_authority_accounts( d, *o.owner ); @@ -231,16 +238,8 @@ void_result account_update_evaluator::do_evaluate( const account_update_operatio acnt = &o.account(d); - if( o.new_options ) - { - FC_ASSERT( o.new_options->num_witness <= chain_params.maximum_witness_count ); - FC_ASSERT( o.new_options->num_committee <= chain_params.maximum_committee_count ); - uint32_t max_vote_id = d.get_global_properties().next_available_vote_id; - for( auto id : o.new_options->votes ) - { - FC_ASSERT( id < max_vote_id ); - } - } + if( o.new_options.valid() ) + verify_account_votes( d, *o.new_options ); return void_result(); } FC_CAPTURE_AND_RETHROW( (o) ) } From 6684fb75ac8d07c0f580c02e7089d51e9cfa6c69 Mon Sep 17 00:00:00 2001 From: valzav Date: Wed, 9 Mar 2016 18:03:52 -0500 Subject: [PATCH 12/37] bump gui version --- gui_version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui_version b/gui_version index 456ffbec..684008f4 100644 --- a/gui_version +++ b/gui_version @@ -1 +1 @@ -2.0.160302 +2.0.160309 From f1cd2c245489d66adc9de2468acaf389d9fad0b4 Mon Sep 17 00:00:00 2001 From: abitmore Date: Thu, 10 Mar 2016 06:12:58 +0800 Subject: [PATCH 13/37] Add hard fork logic for #615 feed expiration check issue, fix #540 --- libraries/chain/db_update.cpp | 7 ++++++- libraries/chain/hardfork.d/615.hf | 4 ++++ libraries/chain/include/graphene/chain/asset_object.hpp | 2 ++ 3 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 libraries/chain/hardfork.d/615.hf diff --git a/libraries/chain/db_update.cpp b/libraries/chain/db_update.cpp index da96eef9..aa4d5969 100644 --- a/libraries/chain/db_update.cpp +++ b/libraries/chain/db_update.cpp @@ -434,7 +434,12 @@ void database::update_expired_feeds() assert( a.is_market_issued() ); const asset_bitasset_data_object& b = a.bitasset_data(*this); - if( b.feed_is_expired(head_block_time()) ) + bool feed_is_expired; + if( head_block_time() < HARDFORK_615_TIME ) + feed_is_expired = b.feed_is_expired_before_hardfork_615( head_block_time() ); + else + feed_is_expired = b.feed_is_expired( head_block_time() ); + if( feed_is_expired ) { modify(b, [this](asset_bitasset_data_object& a) { a.update_median_feeds(head_block_time()); diff --git a/libraries/chain/hardfork.d/615.hf b/libraries/chain/hardfork.d/615.hf new file mode 100644 index 00000000..a5599bbc --- /dev/null +++ b/libraries/chain/hardfork.d/615.hf @@ -0,0 +1,4 @@ +// #615 Fix price feed expiration check, so websocket server will never spam too much data +#ifndef HARDFORK_615_TIME +#define HARDFORK_615_TIME (fc::time_point_sec( 1457550000 )) +#endif diff --git a/libraries/chain/include/graphene/chain/asset_object.hpp b/libraries/chain/include/graphene/chain/asset_object.hpp index 3bde61b3..28d5974e 100644 --- a/libraries/chain/include/graphene/chain/asset_object.hpp +++ b/libraries/chain/include/graphene/chain/asset_object.hpp @@ -211,6 +211,8 @@ namespace graphene { namespace chain { time_point_sec feed_expiration_time()const { return current_feed_publication_time + options.feed_lifetime_sec; } + bool feed_is_expired_before_hardfork_615(time_point_sec current_time)const + { return feed_expiration_time() >= current_time; } bool feed_is_expired(time_point_sec current_time)const { return feed_expiration_time() <= current_time; } void update_median_feeds(time_point_sec current_time); From b175cc7feb4accaeab5e85ebfcddfe7d2264c422 Mon Sep 17 00:00:00 2001 From: Eric Frias Date: Fri, 11 Mar 2016 14:19:31 -0500 Subject: [PATCH 14/37] Revert "Merge branch 'graphene_master' into bitshares" This reverts commit 2d0a7a2a4dd0eb9ef17446d6a7b7a47f99100520, reversing changes made to 6684fb75ac8d07c0f580c02e7089d51e9cfa6c69. --- libraries/app/application.cpp | 9 ++----- .../include/graphene/chain/asset_object.hpp | 2 +- .../include/graphene/chain/protocol/ext.hpp | 4 +-- libraries/fc | 2 +- libraries/net/node.cpp | 13 +++------- tests/tests/serialization_tests.cpp | 26 ------------------- 6 files changed, 8 insertions(+), 48 deletions(-) diff --git a/libraries/app/application.cpp b/libraries/app/application.cpp index fe66b3d9..9a22ca70 100644 --- a/libraries/app/application.cpp +++ b/libraries/app/application.cpp @@ -226,9 +226,7 @@ namespace detail { if( !_options->count("rpc-endpoint") ) return; - bool enable_deflate_compression = _options->count("disable-permessage-deflate") == 0; - - _websocket_server = std::make_shared(enable_deflate_compression); + _websocket_server = std::make_shared(); _websocket_server->on_connection([&]( const fc::http::websocket_connection_ptr& c ){ auto wsc = std::make_shared(*c); @@ -255,8 +253,7 @@ namespace detail { } string password = _options->count("server-pem-password") ? _options->at("server-pem-password").as() : ""; - bool enable_deflate_compression = _options->count("disable-permessage-deflate") == 0; - _websocket_tls_server = std::make_shared( _options->at("server-pem").as(), password, enable_deflate_compression ); + _websocket_tls_server = std::make_shared( _options->at("server-pem").as(), password ); _websocket_tls_server->on_connection([&]( const fc::http::websocket_connection_ptr& c ){ auto wsc = std::make_shared(*c); @@ -950,8 +947,6 @@ void application::set_program_options(boost::program_options::options_descriptio ("checkpoint,c", bpo::value>()->composing(), "Pairs of [BLOCK_NUM,BLOCK_ID] that should be enforced as checkpoints.") ("rpc-endpoint", bpo::value()->implicit_value("127.0.0.1:8090"), "Endpoint for websocket RPC to listen on") ("rpc-tls-endpoint", bpo::value()->implicit_value("127.0.0.1:8089"), "Endpoint for TLS websocket RPC to listen on") - ("disable-permessage-deflate", "Disable support for per-message deflate compression in the websocket servers " - "(--rpc-endpoint and --rpc-tls-endpoint), enabled by default") ("server-pem,p", bpo::value()->implicit_value("server.pem"), "The TLS certificate file for this server") ("server-pem-password,P", bpo::value()->implicit_value(""), "Password for this certificate") ("genesis-json", bpo::value(), "File to read Genesis State from") diff --git a/libraries/chain/include/graphene/chain/asset_object.hpp b/libraries/chain/include/graphene/chain/asset_object.hpp index 3bde61b3..f893f34a 100644 --- a/libraries/chain/include/graphene/chain/asset_object.hpp +++ b/libraries/chain/include/graphene/chain/asset_object.hpp @@ -212,7 +212,7 @@ namespace graphene { namespace chain { time_point_sec feed_expiration_time()const { return current_feed_publication_time + options.feed_lifetime_sec; } bool feed_is_expired(time_point_sec current_time)const - { return feed_expiration_time() <= current_time; } + { return feed_expiration_time() >= current_time; } void update_median_feeds(time_point_sec current_time); }; diff --git a/libraries/chain/include/graphene/chain/protocol/ext.hpp b/libraries/chain/include/graphene/chain/protocol/ext.hpp index ac775535..7e8636f5 100644 --- a/libraries/chain/include/graphene/chain/protocol/ext.hpp +++ b/libraries/chain/include/graphene/chain/protocol/ext.hpp @@ -82,8 +82,6 @@ void operator<<( Stream& stream, const graphene::chain::extension& value ) fc::reflector::visit( read_vtor ); } - - template< typename Stream, typename T > struct graphene_extension_unpack_visitor { @@ -110,7 +108,7 @@ struct graphene_extension_unpack_visitor { if( (count_left > 0) && (which == next_which) ) { - typename Member::value_type temp; + Member temp; fc::raw::unpack( stream, temp ); (value.*member) = temp; --count_left; diff --git a/libraries/fc b/libraries/fc index 21045dde..d5370fc2 160000 --- a/libraries/fc +++ b/libraries/fc @@ -1 +1 @@ -Subproject commit 21045dde5faa8fcf5f43b97c85f9df210317633b +Subproject commit d5370fc2ea436fa4340cda01af98c7993fbc67d5 diff --git a/libraries/net/node.cpp b/libraries/net/node.cpp index 6fb212c7..db2369a0 100644 --- a/libraries/net/node.cpp +++ b/libraries/net/node.cpp @@ -3952,20 +3952,12 @@ namespace graphene { namespace net { namespace detail { } unsigned handle_message_call_count = 0; - while( true ) + for (fc::future& handle_message_call : _handle_message_calls_in_progress) { - auto it = _handle_message_calls_in_progress.begin(); - if( it == _handle_message_calls_in_progress.end() ) - break; - if( it->ready() || it->error() || it->canceled() ) - { - _handle_message_calls_in_progress.erase( it ); - continue; - } ++handle_message_call_count; try { - it->cancel_and_wait("node_impl::close()"); + handle_message_call.cancel_and_wait("node_impl::close()"); dlog("handle_message call #${count} task terminated", ("count", handle_message_call_count)); } catch ( const fc::canceled_exception& ) @@ -3981,6 +3973,7 @@ namespace graphene { namespace net { namespace detail { wlog("Exception thrown while terminating handle_message call #${count} task, ignoring",("count", handle_message_call_count)); } } + _handle_message_calls_in_progress.clear(); try { diff --git a/tests/tests/serialization_tests.cpp b/tests/tests/serialization_tests.cpp index fb87c4c4..84fced8e 100644 --- a/tests/tests/serialization_tests.cpp +++ b/tests/tests/serialization_tests.cpp @@ -122,30 +122,4 @@ BOOST_AUTO_TEST_CASE( extended_public_key_type_test ) } } -BOOST_AUTO_TEST_CASE( extension_serialization_test ) -{ - try - { - buyback_account_options bbo; - bbo.asset_to_buy = asset_id_type(1000); - bbo.asset_to_buy_issuer = account_id_type(2000); - bbo.markets.emplace( asset_id_type() ); - bbo.markets.emplace( asset_id_type(777) ); - account_create_operation create_op = make_account( "rex" ); - create_op.registrar = account_id_type(1234); - create_op.extensions.value.buyback_options = bbo; - - auto packed = fc::raw::pack( create_op ); - account_create_operation unpacked = fc::raw::unpack(packed); - - ilog( "original: ${x}", ("x", create_op) ); - ilog( "unpacked: ${x}", ("x", unpacked) ); - } - catch ( const fc::exception& e ) - { - edump((e.to_detail_string())); - throw; - } -} - BOOST_AUTO_TEST_SUITE_END() From c39f97885d72ef291e63479560b58b4565549999 Mon Sep 17 00:00:00 2001 From: Eric Frias Date: Thu, 10 Mar 2016 17:33:14 -0500 Subject: [PATCH 15/37] Add a command-line option to witness_node, --disable-permessage-deflate to prevent the websocket server from allowing compression on clients that support it. #619 --- libraries/app/application.cpp | 9 +++++++-- libraries/fc | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/libraries/app/application.cpp b/libraries/app/application.cpp index 9a22ca70..fe66b3d9 100644 --- a/libraries/app/application.cpp +++ b/libraries/app/application.cpp @@ -226,7 +226,9 @@ namespace detail { if( !_options->count("rpc-endpoint") ) return; - _websocket_server = std::make_shared(); + bool enable_deflate_compression = _options->count("disable-permessage-deflate") == 0; + + _websocket_server = std::make_shared(enable_deflate_compression); _websocket_server->on_connection([&]( const fc::http::websocket_connection_ptr& c ){ auto wsc = std::make_shared(*c); @@ -253,7 +255,8 @@ namespace detail { } string password = _options->count("server-pem-password") ? _options->at("server-pem-password").as() : ""; - _websocket_tls_server = std::make_shared( _options->at("server-pem").as(), password ); + bool enable_deflate_compression = _options->count("disable-permessage-deflate") == 0; + _websocket_tls_server = std::make_shared( _options->at("server-pem").as(), password, enable_deflate_compression ); _websocket_tls_server->on_connection([&]( const fc::http::websocket_connection_ptr& c ){ auto wsc = std::make_shared(*c); @@ -947,6 +950,8 @@ void application::set_program_options(boost::program_options::options_descriptio ("checkpoint,c", bpo::value>()->composing(), "Pairs of [BLOCK_NUM,BLOCK_ID] that should be enforced as checkpoints.") ("rpc-endpoint", bpo::value()->implicit_value("127.0.0.1:8090"), "Endpoint for websocket RPC to listen on") ("rpc-tls-endpoint", bpo::value()->implicit_value("127.0.0.1:8089"), "Endpoint for TLS websocket RPC to listen on") + ("disable-permessage-deflate", "Disable support for per-message deflate compression in the websocket servers " + "(--rpc-endpoint and --rpc-tls-endpoint), enabled by default") ("server-pem,p", bpo::value()->implicit_value("server.pem"), "The TLS certificate file for this server") ("server-pem-password,P", bpo::value()->implicit_value(""), "Password for this certificate") ("genesis-json", bpo::value(), "File to read Genesis State from") diff --git a/libraries/fc b/libraries/fc index d5370fc2..21045dde 160000 --- a/libraries/fc +++ b/libraries/fc @@ -1 +1 @@ -Subproject commit d5370fc2ea436fa4340cda01af98c7993fbc67d5 +Subproject commit 21045dde5faa8fcf5f43b97c85f9df210317633b From 8c4ce14457002cb9c741a9705909cc45546cbed0 Mon Sep 17 00:00:00 2001 From: abitmore Date: Sat, 12 Mar 2016 10:32:39 +0100 Subject: [PATCH 16/37] Update abit's seed node; Remove alt's seed node --- libraries/app/application.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libraries/app/application.cpp b/libraries/app/application.cpp index fe66b3d9..fce4453c 100644 --- a/libraries/app/application.cpp +++ b/libraries/app/application.cpp @@ -154,7 +154,7 @@ namespace detail { vector seeds = { "faucet.bitshares.org:1776", "bitshares.openledger.info:1776", - "114.92.254.159:62015", // abit + "114.92.236.175:62015", // abit "seed.blocktrades.us:1776", "seed04.bitsharesnodes.com:1776", // thom "seed05.bitsharesnodes.com:1776", // thom @@ -167,8 +167,7 @@ namespace detail { "185.25.22.21:1776", // liondani (greece) "23.95.43.126:50696", // iHashFury "109.73.172.144:50696", // iHashFury - "128.199.143.47:2015", // Harvey - "106.185.26.162:34045" // alt + "128.199.143.47:2015" // Harvey }; for( const string& endpoint_string : seeds ) { From ff0da572889635af633e3f92837508b0f03dea11 Mon Sep 17 00:00:00 2001 From: valzav Date: Mon, 14 Mar 2016 18:02:58 -0400 Subject: [PATCH 17/37] bump gui version to 2.0.160314 --- gui_version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui_version b/gui_version index 684008f4..d1ce3978 100644 --- a/gui_version +++ b/gui_version @@ -1 +1 @@ -2.0.160309 +2.0.160314 From 7f4b40f57d7e6f308a1185f498918fbd66ae032c Mon Sep 17 00:00:00 2001 From: Daniel Larimer Date: Wed, 9 Dec 2015 13:53:01 -0500 Subject: [PATCH 18/37] Improve index on account operation history - operations are now indexed by account and sequence for effecient traversal and query --- .../include/graphene/chain/account_object.hpp | 2 ++ .../chain/operation_history_object.hpp | 7 +++- .../account_history_plugin.cpp | 34 ++++++++++++++++++- 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/libraries/chain/include/graphene/chain/account_object.hpp b/libraries/chain/include/graphene/chain/account_object.hpp index 5067292d..9f0df9c8 100644 --- a/libraries/chain/include/graphene/chain/account_object.hpp +++ b/libraries/chain/include/graphene/chain/account_object.hpp @@ -47,6 +47,7 @@ namespace graphene { namespace chain { * Keep the most recent operation as a root pointer to a linked list of the transaction history. */ account_transaction_history_id_type most_recent_op; + uint32_t total_ops = 0; /** * When calculating votes it is necessary to know how much is stored in orders (and thus unavailable for @@ -342,6 +343,7 @@ FC_REFLECT_DERIVED( graphene::chain::account_statistics_object, (graphene::chain::object), (owner) (most_recent_op) + (total_ops) (total_core_in_orders) (lifetime_fees_paid) (pending_fees)(pending_vested_fees) diff --git a/libraries/chain/include/graphene/chain/operation_history_object.hpp b/libraries/chain/include/graphene/chain/operation_history_object.hpp index b1e9d834..4bf6b527 100644 --- a/libraries/chain/include/graphene/chain/operation_history_object.hpp +++ b/libraries/chain/include/graphene/chain/operation_history_object.hpp @@ -86,8 +86,13 @@ namespace graphene { namespace chain { public: static const uint8_t space_id = implementation_ids; static const uint8_t type_id = impl_account_transaction_history_object_type; + account_id_type account; /// the account this operation applies to operation_history_id_type operation_id; + uint32_t sequence = 0; /// the operation position within the given account account_transaction_history_id_type next; + + std::pair account_op()const { return std::tie( account, operation_id ); } + std::pair account_seq()const { return std::tie( account, sequence ); } }; } } // graphene::chain @@ -95,4 +100,4 @@ FC_REFLECT_DERIVED( graphene::chain::operation_history_object, (graphene::chain: (op)(result)(block_num)(trx_in_block)(op_in_trx)(virtual_op) ) FC_REFLECT_DERIVED( graphene::chain::account_transaction_history_object, (graphene::chain::object), - (operation_id)(next) ) + (account)(operation_id)(sequence)(next) ) diff --git a/libraries/plugins/account_history/account_history_plugin.cpp b/libraries/plugins/account_history/account_history_plugin.cpp index f45610fb..58d4293e 100644 --- a/libraries/plugins/account_history/account_history_plugin.cpp +++ b/libraries/plugins/account_history/account_history_plugin.cpp @@ -105,10 +105,13 @@ void account_history_plugin_impl::update_account_histories( const signed_block& const auto& stats_obj = account_id(db).statistics(db); const auto& ath = db.create( [&]( account_transaction_history_object& obj ){ obj.operation_id = oho.id; + obj.account = account_id; + obj.sequence = stats_obj.total_ops+1; obj.next = stats_obj.most_recent_op; }); db.modify( stats_obj, [&]( account_statistics_object& obj ){ obj.most_recent_op = ath.id; + obj.total_ops = ath.sequence; }); } } @@ -134,6 +137,35 @@ void account_history_plugin_impl::update_account_histories( const signed_block& } } // end namespace detail + +struct by_id; +struct by_seq; +struct by_op; +typedef multi_index_container< + account_transaction_history_object, + indexed_by< + ordered_unique< tag, + member< object, object_id_type, &object::id > >, + ordered_unique< tag, + composite_key< account_transaction_history_object, + member< account_transaction_history_object, account_id_type, &account_transaction_history_object::account>, + member< account_transaction_history_object, uint32_t, &account_transaction_history_object::sequence> + > + >, + ordered_unique< tag, + composite_key< account_transaction_history_object, + member< account_transaction_history_object, account_id_type, &account_transaction_history_object::account>, + member< account_transaction_history_object, operation_history_id_type, &account_transaction_history_object::operation_id> + > + > + > +> account_transaction_history_multi_index_type; + +typedef generic_index account_transaction_history_index; + + + + account_history_plugin::account_history_plugin() : my( new detail::account_history_plugin_impl(*this) ) { @@ -163,7 +195,7 @@ void account_history_plugin::plugin_initialize(const boost::program_options::var { database().applied_block.connect( [&]( const signed_block& b){ my->update_account_histories(b); } ); database().add_index< primary_index< simple_index< operation_history_object > > >(); - database().add_index< primary_index< simple_index< account_transaction_history_object > > >(); + database().add_index< primary_index< account_transaction_history_index > >(); LOAD_VALUE_SET(options, "tracked-accounts", my->_tracked_accounts, graphene::chain::account_id_type); } From c89d60ba92800967ce814d63813b976168fa4081 Mon Sep 17 00:00:00 2001 From: Michael Vandeberg Date: Thu, 10 Dec 2015 14:13:49 -0500 Subject: [PATCH 19/37] First implementation of get_account_history api changes. --- libraries/app/CMakeLists.txt | 2 +- libraries/app/api.cpp | 22 +++++++++++++ libraries/app/include/graphene/app/api.hpp | 5 +++ .../chain/operation_history_object.hpp | 31 +++++++++++++++++-- .../account_history_plugin.cpp | 24 -------------- .../account_history_plugin.hpp | 31 ++++++++++++++++++- 6 files changed, 87 insertions(+), 28 deletions(-) diff --git a/libraries/app/CMakeLists.txt b/libraries/app/CMakeLists.txt index caef157e..b01e3bde 100644 --- a/libraries/app/CMakeLists.txt +++ b/libraries/app/CMakeLists.txt @@ -11,7 +11,7 @@ add_library( graphene_app ${EGENESIS_HEADERS} ) -target_link_libraries( graphene_app graphene_market_history graphene_chain fc graphene_db graphene_net graphene_time graphene_utilities ) +target_link_libraries( graphene_app graphene_market_history graphene_account_history graphene_chain fc graphene_db graphene_net graphene_time graphene_utilities ) target_include_directories( graphene_app PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/../egenesis/include" ) diff --git a/libraries/app/api.cpp b/libraries/app/api.cpp index 9533588b..635867a4 100644 --- a/libraries/app/api.cpp +++ b/libraries/app/api.cpp @@ -357,6 +357,28 @@ namespace graphene { namespace app { } return result; } + + vector history_api::get_relative_account_history( account_id_type account, uint32_t stop, unsigned limit, uint32_t start) const + { + FC_ASSERT(_app.chain_database()); + const auto& db = *_app.chain_database(); + FC_ASSERT(limit <= 100); + vector result; + if (start == 0) + start = account(db).statistics(db).total_ops; + const auto& hist_idx = db.get_index_type(); + const auto& by_seq_idx = hist_idx.indices().get(); + + auto itr = by_seq_idx.upper_bound( boost::make_tuple( account, start ) ); + + while ( itr != by_seq_idx.end() && itr->sequence > stop && result.size() < limit ) + { + result.push_back( itr->operation_id(db) ); + ++itr; + } + + return result; + } flat_set history_api::get_market_history_buckets()const { diff --git a/libraries/app/include/graphene/app/api.hpp b/libraries/app/include/graphene/app/api.hpp index 46c6d457..9f092902 100644 --- a/libraries/app/include/graphene/app/api.hpp +++ b/libraries/app/include/graphene/app/api.hpp @@ -70,6 +70,11 @@ namespace graphene { namespace app { unsigned limit = 100, operation_history_id_type start = operation_history_id_type())const; + vector get_relative_account_history( account_id_type account, + uint32_t stop = 0, + unsigned limit = 100, + uint32_t start = 0) const; + vector get_fill_order_history( asset_id_type a, asset_id_type b, uint32_t limit )const; vector get_market_history( asset_id_type a, asset_id_type b, uint32_t bucket_seconds, fc::time_point_sec start, fc::time_point_sec end )const; diff --git a/libraries/chain/include/graphene/chain/operation_history_object.hpp b/libraries/chain/include/graphene/chain/operation_history_object.hpp index 4bf6b527..746d8eba 100644 --- a/libraries/chain/include/graphene/chain/operation_history_object.hpp +++ b/libraries/chain/include/graphene/chain/operation_history_object.hpp @@ -21,6 +21,7 @@ #pragma once #include #include +#include namespace graphene { namespace chain { @@ -91,9 +92,35 @@ namespace graphene { namespace chain { uint32_t sequence = 0; /// the operation position within the given account account_transaction_history_id_type next; - std::pair account_op()const { return std::tie( account, operation_id ); } - std::pair account_seq()const { return std::tie( account, sequence ); } + //std::pair account_op()const { return std::tie( account, operation_id ); } + //std::pair account_seq()const { return std::tie( account, sequence ); } }; + + struct by_id; +struct by_seq; +struct by_op; +typedef multi_index_container< + account_transaction_history_object, + indexed_by< + ordered_unique< tag, member< object, object_id_type, &object::id > >, + ordered_unique< tag, + composite_key< account_transaction_history_object, + member< account_transaction_history_object, account_id_type, &account_transaction_history_object::account>, + member< account_transaction_history_object, uint32_t, &account_transaction_history_object::sequence> + > + >, + ordered_unique< tag, + composite_key< account_transaction_history_object, + member< account_transaction_history_object, account_id_type, &account_transaction_history_object::account>, + member< account_transaction_history_object, operation_history_id_type, &account_transaction_history_object::operation_id> + > + > + > +> account_transaction_history_multi_index_type; + +typedef generic_index account_transaction_history_index; + + } } // graphene::chain FC_REFLECT_DERIVED( graphene::chain::operation_history_object, (graphene::chain::object), diff --git a/libraries/plugins/account_history/account_history_plugin.cpp b/libraries/plugins/account_history/account_history_plugin.cpp index 58d4293e..0d1c4f59 100644 --- a/libraries/plugins/account_history/account_history_plugin.cpp +++ b/libraries/plugins/account_history/account_history_plugin.cpp @@ -138,30 +138,6 @@ void account_history_plugin_impl::update_account_histories( const signed_block& } // end namespace detail -struct by_id; -struct by_seq; -struct by_op; -typedef multi_index_container< - account_transaction_history_object, - indexed_by< - ordered_unique< tag, - member< object, object_id_type, &object::id > >, - ordered_unique< tag, - composite_key< account_transaction_history_object, - member< account_transaction_history_object, account_id_type, &account_transaction_history_object::account>, - member< account_transaction_history_object, uint32_t, &account_transaction_history_object::sequence> - > - >, - ordered_unique< tag, - composite_key< account_transaction_history_object, - member< account_transaction_history_object, account_id_type, &account_transaction_history_object::account>, - member< account_transaction_history_object, operation_history_id_type, &account_transaction_history_object::operation_id> - > - > - > -> account_transaction_history_multi_index_type; - -typedef generic_index account_transaction_history_index; diff --git a/libraries/plugins/account_history/include/graphene/account_history/account_history_plugin.hpp b/libraries/plugins/account_history/include/graphene/account_history/account_history_plugin.hpp index e6edc8a5..61e71c77 100644 --- a/libraries/plugins/account_history/include/graphene/account_history/account_history_plugin.hpp +++ b/libraries/plugins/account_history/include/graphene/account_history/account_history_plugin.hpp @@ -23,10 +23,15 @@ #include #include +#include + #include namespace graphene { namespace account_history { -using namespace chain; + using namespace chain; + //using namespace graphene::db; + //using boost::multi_index_container; + //using namespace boost::multi_index; // // Plugins should #define their SPACE_ID's so plugins with @@ -75,3 +80,27 @@ class account_history_plugin : public graphene::app::plugin } } //graphene::account_history +/*struct by_id; +struct by_seq; +struct by_op; +typedef boost::multi_index_container< + graphene::chain::account_transaction_history_object, + boost::multi_index::indexed_by< + boost::multi_index::ordered_unique< tag, member< object, object_id_type, &object::id > >, + boost::multi_index::ordered_unique< tag, + composite_key< account_transaction_history_object, + member< account_transaction_history_object, account_id_type, &account_transaction_history_object::account>, + member< account_transaction_history_object, uint32_t, &account_transaction_history_object::sequence> + > + >, + boost::multi_index::ordered_unique< tag, + composite_key< account_transaction_history_object, + member< account_transaction_history_object, account_id_type, &account_transaction_history_object::account>, + member< account_transaction_history_object, operation_history_id_type, &account_transaction_history_object::operation_id> + > + > + > +> account_transaction_history_multi_index_type; + +typedef graphene::account_history::generic_index account_transaction_history_index; +*/ \ No newline at end of file From 9485ebfd647d34c56e4b36ff4cbf23bafc71f033 Mon Sep 17 00:00:00 2001 From: Michael Vandeberg Date: Fri, 11 Dec 2015 11:11:36 -0500 Subject: [PATCH 20/37] Fixed bug in get_account_history that prevented all operations from being returned when specific bounds were set. --- libraries/app/api.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libraries/app/api.cpp b/libraries/app/api.cpp index 635867a4..e9f7d197 100644 --- a/libraries/app/api.cpp +++ b/libraries/app/api.cpp @@ -339,22 +339,24 @@ namespace graphene { namespace app { vector history_api::get_account_history(account_id_type account, operation_history_id_type stop, unsigned limit, operation_history_id_type start) const { FC_ASSERT(_app.chain_database()); - const auto& db = *_app.chain_database(); + const auto& db = *_app.chain_database(); FC_ASSERT(limit <= 100); vector result; const auto& stats = account(db).statistics(db); if(stats.most_recent_op == account_transaction_history_id_type()) return result; const account_transaction_history_object* node = &stats.most_recent_op(db); if(start == operation_history_id_type()) - start = node->id; + start = node->operation_id; + while(node && node->operation_id.instance.value > stop.instance.value && result.size() < limit) { - if(node->id.instance() <= start.instance.value) + if (node->operation_id.instance.value <= start.instance.value) result.push_back(node->operation_id(db)); if(node->next == account_transaction_history_id_type()) node = nullptr; - else node = db.find(node->next); + else node = &node->next(db); } + return result; } From ae82e0a9a686fea3a97e9baff70542bca6d35373 Mon Sep 17 00:00:00 2001 From: Michael Vandeberg Date: Fri, 11 Dec 2015 14:07:03 -0500 Subject: [PATCH 21/37] Tested and validated the new get_relative_account_history API call. --- libraries/app/api.cpp | 35 ++++++++++++++-------- libraries/app/include/graphene/app/api.hpp | 14 ++++++++- 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/libraries/app/api.cpp b/libraries/app/api.cpp index e9f7d197..5e6d57cb 100644 --- a/libraries/app/api.cpp +++ b/libraries/app/api.cpp @@ -336,23 +336,26 @@ namespace graphene { namespace app { return result; } - vector history_api::get_account_history(account_id_type account, operation_history_id_type stop, unsigned limit, operation_history_id_type start) const + vector history_api::get_account_history( account_id_type account, + operation_history_id_type stop, + unsigned limit, + operation_history_id_type start ) const { - FC_ASSERT(_app.chain_database()); + FC_ASSERT( _app.chain_database() ); const auto& db = *_app.chain_database(); - FC_ASSERT(limit <= 100); + FC_ASSERT( limit <= 100 ); vector result; const auto& stats = account(db).statistics(db); - if(stats.most_recent_op == account_transaction_history_id_type()) return result; + if( stats.most_recent_op == account_transaction_history_id_type() ) return result; const account_transaction_history_object* node = &stats.most_recent_op(db); - if(start == operation_history_id_type()) + if( start == operation_history_id_type() ) start = node->operation_id; while(node && node->operation_id.instance.value > stop.instance.value && result.size() < limit) { - if (node->operation_id.instance.value <= start.instance.value) - result.push_back(node->operation_id(db)); - if(node->next == account_transaction_history_id_type()) + if( node->operation_id.instance.value <= start.instance.value ) + result.push_back( node->operation_id(db) ); + if( node->next == account_transaction_history_id_type() ) node = nullptr; else node = &node->next(db); } @@ -360,23 +363,29 @@ namespace graphene { namespace app { return result; } - vector history_api::get_relative_account_history( account_id_type account, uint32_t stop, unsigned limit, uint32_t start) const + vector history_api::get_relative_account_history( account_id_type account, + uint32_t stop, + unsigned limit, + uint32_t start) const { - FC_ASSERT(_app.chain_database()); + FC_ASSERT( _app.chain_database() ); const auto& db = *_app.chain_database(); FC_ASSERT(limit <= 100); vector result; - if (start == 0) + if( start == 0 ) start = account(db).statistics(db).total_ops; + else start = min( account(db).statistics(db).total_ops, start ); const auto& hist_idx = db.get_index_type(); const auto& by_seq_idx = hist_idx.indices().get(); auto itr = by_seq_idx.upper_bound( boost::make_tuple( account, start ) ); + auto itr_stop = by_seq_idx.lower_bound( boost::make_tuple( account, stop ) ); + --itr; - while ( itr != by_seq_idx.end() && itr->sequence > stop && result.size() < limit ) + while ( itr != itr_stop && result.size() < limit ) { result.push_back( itr->operation_id(db) ); - ++itr; + --itr; } return result; diff --git a/libraries/app/include/graphene/app/api.hpp b/libraries/app/include/graphene/app/api.hpp index 9f092902..fb31033a 100644 --- a/libraries/app/include/graphene/app/api.hpp +++ b/libraries/app/include/graphene/app/api.hpp @@ -69,7 +69,18 @@ namespace graphene { namespace app { operation_history_id_type stop = operation_history_id_type(), unsigned limit = 100, operation_history_id_type start = operation_history_id_type())const; - + /** + * @breif Get operations relevant to the specified account referenced + * by an event numbering specific to the account. The current number of operations + * for the account can be found in the account statistics (or use 0 for start). + * @param account The account whose history should be queried + * @param stop Sequence number of earliest operation. 0 is default and will + * query 'limit' number of operations. + * @param limit Maximum number of operations to retrieve (must not exceed 100) + * @param start Sequence number of the most recent operation to retrieve. + * 0 is default, which will start querying from the most recent operation. + * @return A list of operations performed by account, ordered from most recent to oldest. + */ vector get_relative_account_history( account_id_type account, uint32_t stop = 0, unsigned limit = 100, @@ -209,6 +220,7 @@ FC_REFLECT( graphene::app::network_broadcast_api::transaction_confirmation, FC_API(graphene::app::history_api, (get_account_history) + (get_relative_account_history) (get_fill_order_history) (get_market_history) (get_market_history_buckets) From 77ac461a8afc5e18af1190fe4c5d0f7e33257241 Mon Sep 17 00:00:00 2001 From: theoreticalbts Date: Thu, 3 Mar 2016 14:12:27 -0500 Subject: [PATCH 22/37] Implement debug_node target #606 --- libraries/app/CMakeLists.txt | 3 +- libraries/app/api.cpp | 12 + libraries/app/include/graphene/app/api.hpp | 6 + libraries/chain/db_block.cpp | 2 + libraries/chain/db_debug.cpp | 103 ++++++ .../chain/include/graphene/chain/database.hpp | 2 + .../graphene/chain/node_property_object.hpp | 1 + libraries/db/include/graphene/db/index.hpp | 20 ++ libraries/plugins/CMakeLists.txt | 1 + .../plugins/debug_witness/CMakeLists.txt | 18 + libraries/plugins/debug_witness/debug_api.cpp | 122 +++++++ .../plugins/debug_witness/debug_witness.cpp | 126 +++++++ .../graphene/debug_witness/debug_api.hpp | 83 +++++ .../graphene/debug_witness/debug_witness.hpp | 59 ++++ .../wallet/include/graphene/wallet/wallet.hpp | 7 + libraries/wallet/wallet.cpp | 55 ++++ programs/CMakeLists.txt | 1 + programs/debug_node/CMakeLists.txt | 21 ++ programs/debug_node/main.cpp | 307 ++++++++++++++++++ programs/witness_node/CMakeLists.txt | 3 +- 20 files changed, 950 insertions(+), 2 deletions(-) create mode 100644 libraries/plugins/debug_witness/CMakeLists.txt create mode 100644 libraries/plugins/debug_witness/debug_api.cpp create mode 100644 libraries/plugins/debug_witness/debug_witness.cpp create mode 100644 libraries/plugins/debug_witness/include/graphene/debug_witness/debug_api.hpp create mode 100644 libraries/plugins/debug_witness/include/graphene/debug_witness/debug_witness.hpp create mode 100644 programs/debug_node/CMakeLists.txt create mode 100644 programs/debug_node/main.cpp diff --git a/libraries/app/CMakeLists.txt b/libraries/app/CMakeLists.txt index caef157e..19742cb8 100644 --- a/libraries/app/CMakeLists.txt +++ b/libraries/app/CMakeLists.txt @@ -11,7 +11,8 @@ add_library( graphene_app ${EGENESIS_HEADERS} ) -target_link_libraries( graphene_app graphene_market_history graphene_chain fc graphene_db graphene_net graphene_time graphene_utilities ) +# need to link graphene_debug_witness because plugins aren't sufficiently isolated #246 +target_link_libraries( graphene_app graphene_market_history graphene_chain fc graphene_db graphene_net graphene_time graphene_utilities graphene_debug_witness ) target_include_directories( graphene_app PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/../egenesis/include" ) diff --git a/libraries/app/api.cpp b/libraries/app/api.cpp index 35cf3880..4e6120d6 100644 --- a/libraries/app/api.cpp +++ b/libraries/app/api.cpp @@ -95,6 +95,12 @@ namespace graphene { namespace app { { _crypto_api = std::make_shared< crypto_api >(); } + else if( api_name == "debug_api" ) + { + // can only enable this API if the plugin was loaded + if( _app.get_plugin( "debug_witness" ) ) + _debug_api = std::make_shared< graphene::debug_witness::debug_api >( _app.chain_database() ); + } return; } @@ -211,6 +217,12 @@ namespace graphene { namespace app { return *_crypto_api; } + fc::api login_api::debug() const + { + FC_ASSERT(_debug_api); + return *_debug_api; + } + vector get_relevant_accounts( const object* obj ) { vector result; diff --git a/libraries/app/include/graphene/app/api.hpp b/libraries/app/include/graphene/app/api.hpp index 59c905d4..a898649a 100644 --- a/libraries/app/include/graphene/app/api.hpp +++ b/libraries/app/include/graphene/app/api.hpp @@ -30,6 +30,8 @@ #include +#include + #include #include @@ -265,6 +267,8 @@ namespace graphene { namespace app { fc::api network_node()const; /// @brief Retrieve the cryptography API fc::api crypto()const; + /// @brief Retrieve the debug API (if available) + fc::api debug()const; private: /// @brief Called to enable an API, not reflected. @@ -276,6 +280,7 @@ namespace graphene { namespace app { optional< fc::api > _network_node_api; optional< fc::api > _history_api; optional< fc::api > _crypto_api; + optional< fc::api > _debug_api; }; }} // graphene::app @@ -326,4 +331,5 @@ FC_API(graphene::app::login_api, (history) (network_node) (crypto) + (debug) ) diff --git a/libraries/chain/db_block.cpp b/libraries/chain/db_block.cpp index 2e511591..8f4f1f1e 100644 --- a/libraries/chain/db_block.cpp +++ b/libraries/chain/db_block.cpp @@ -534,6 +534,8 @@ void database::_apply_block( const signed_block& next_block ) // to be called for header validation? update_maintenance_flag( maint_needed ); update_witness_schedule(); + if( !_node_property_object.debug_updates.empty() ) + apply_debug_updates(); // notify observers that the block has been applied applied_block( next_block ); //emit diff --git a/libraries/chain/db_debug.cpp b/libraries/chain/db_debug.cpp index 7fafcf57..aa91fd44 100644 --- a/libraries/chain/db_debug.cpp +++ b/libraries/chain/db_debug.cpp @@ -95,4 +95,107 @@ void database::debug_dump() */ } +void debug_apply_update( database& db, const fc::variant_object& vo ) +{ + static const uint8_t + db_action_nil = 0, + db_action_create = 1, + db_action_write = 2, + db_action_update = 3, + db_action_delete = 4; + + // "_action" : "create" object must not exist, unspecified fields take defaults + // "_action" : "write" object may exist, is replaced entirely, unspecified fields take defaults + // "_action" : "update" object must exist, unspecified fields don't change + // "_action" : "delete" object must exist, will be deleted + + // if _action is unspecified: + // - delete if object contains only ID field + // - otherwise, write + + object_id_type oid; + uint8_t action = db_action_nil; + auto it_id = vo.find("id"); + FC_ASSERT( it_id != vo.end() ); + + from_variant( it_id->value(), oid ); + action = ( vo.size() == 1 ) ? db_action_delete : db_action_write; + + from_variant( vo["id"], oid ); + if( vo.size() == 1 ) + action = db_action_delete; + auto it_action = vo.find("_action" ); + if( it_action != vo.end() ) + { + const std::string& str_action = it_action->value().get_string(); + if( str_action == "create" ) + action = db_action_create; + else if( str_action == "write" ) + action = db_action_write; + else if( str_action == "update" ) + action = db_action_update; + else if( str_action == "delete" ) + action = db_action_delete; + } + + auto& idx = db.get_index( oid ); + + switch( action ) + { + case db_action_create: + /* + idx.create( [&]( object& obj ) + { + idx.object_from_variant( vo, obj ); + } ); + */ + FC_ASSERT( false ); + break; + case db_action_write: + db.modify( db.get_object( oid ), [&]( object& obj ) + { + idx.object_default( obj ); + idx.object_from_variant( vo, obj ); + } ); + break; + case db_action_update: + db.modify( db.get_object( oid ), [&]( object& obj ) + { + idx.object_from_variant( vo, obj ); + } ); + break; + case db_action_delete: + db.remove( db.get_object( oid ) ); + break; + default: + FC_ASSERT( false ); + } +} + +void database::apply_debug_updates() +{ + block_id_type head_id = head_block_id(); + auto it = _node_property_object.debug_updates.find( head_id ); + if( it == _node_property_object.debug_updates.end() ) + return; + for( const fc::variant_object& update : it->second ) + debug_apply_update( *this, update ); +} + +void database::debug_update( const fc::variant_object& update ) +{ + block_id_type head_id = head_block_id(); + auto it = _node_property_object.debug_updates.find( head_id ); + if( it == _node_property_object.debug_updates.end() ) + it = _node_property_object.debug_updates.emplace( head_id, std::vector< fc::variant_object >() ).first; + it->second.emplace_back( update ); + + optional head_block = fetch_block_by_id( head_id ); + FC_ASSERT( head_block.valid() ); + + // What the last block does has been changed by adding to node_property_object, so we have to re-apply it + pop_block(); + push_block( *head_block ); +} + } } diff --git a/libraries/chain/include/graphene/chain/database.hpp b/libraries/chain/include/graphene/chain/database.hpp index b73b8931..1b721253 100644 --- a/libraries/chain/include/graphene/chain/database.hpp +++ b/libraries/chain/include/graphene/chain/database.hpp @@ -322,6 +322,8 @@ namespace graphene { namespace chain { //////////////////// db_debug.cpp //////////////////// void debug_dump(); + void apply_debug_updates(); + void debug_update( const fc::variant_object& update ); //////////////////// db_market.cpp //////////////////// diff --git a/libraries/chain/include/graphene/chain/node_property_object.hpp b/libraries/chain/include/graphene/chain/node_property_object.hpp index cf2285a8..b9cdfb6e 100644 --- a/libraries/chain/include/graphene/chain/node_property_object.hpp +++ b/libraries/chain/include/graphene/chain/node_property_object.hpp @@ -43,5 +43,6 @@ namespace graphene { namespace chain { ~node_property_object(){} uint32_t skip_flags = 0; + std::map< block_id_type, std::vector< fc::variant_object > > debug_updates; }; } } // graphene::chain diff --git a/libraries/db/include/graphene/db/index.hpp b/libraries/db/include/graphene/db/index.hpp index 6c1c975e..7ecf5a66 100644 --- a/libraries/db/include/graphene/db/index.hpp +++ b/libraries/db/include/graphene/db/index.hpp @@ -130,6 +130,8 @@ namespace graphene { namespace db { virtual fc::uint128 hash()const = 0; virtual void add_observer( const shared_ptr& ) = 0; + virtual void object_from_variant( const fc::variant& var, object& obj )const = 0; + virtual void object_default( object& obj )const = 0; }; class secondary_index @@ -298,6 +300,24 @@ namespace graphene { namespace db { _observers.emplace_back( o ); } + virtual void object_from_variant( const fc::variant& var, object& obj )const override + { + object_id_type id = obj.id; + object_type* result = dynamic_cast( &obj ); + FC_ASSERT( result != nullptr ); + fc::from_variant( var, *result ); + obj.id = id; + } + + virtual void object_default( object& obj )const override + { + object_id_type id = obj.id; + object_type* result = dynamic_cast( &obj ); + FC_ASSERT( result != nullptr ); + (*result) = object_type(); + obj.id = id; + } + private: object_id_type _next_id; }; diff --git a/libraries/plugins/CMakeLists.txt b/libraries/plugins/CMakeLists.txt index 128d8aa1..7a02ceba 100644 --- a/libraries/plugins/CMakeLists.txt +++ b/libraries/plugins/CMakeLists.txt @@ -2,3 +2,4 @@ add_subdirectory( witness ) add_subdirectory( account_history ) add_subdirectory( market_history ) add_subdirectory( delayed_node ) +add_subdirectory( debug_witness ) \ No newline at end of file diff --git a/libraries/plugins/debug_witness/CMakeLists.txt b/libraries/plugins/debug_witness/CMakeLists.txt new file mode 100644 index 00000000..f0fcb7fb --- /dev/null +++ b/libraries/plugins/debug_witness/CMakeLists.txt @@ -0,0 +1,18 @@ +file(GLOB HEADERS "include/graphene/debug_witness/*.hpp") + +add_library( graphene_debug_witness + debug_api.cpp + debug_witness.cpp + ) + +target_link_libraries( graphene_debug_witness graphene_chain graphene_app ) +target_include_directories( graphene_debug_witness + PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" ) + +install( TARGETS + graphene_debug_witness + + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib +) diff --git a/libraries/plugins/debug_witness/debug_api.cpp b/libraries/plugins/debug_witness/debug_api.cpp new file mode 100644 index 00000000..53b2e7a8 --- /dev/null +++ b/libraries/plugins/debug_witness/debug_api.cpp @@ -0,0 +1,122 @@ + +#include +#include +#include + +#include +#include +#include + +#include + +#include + +namespace graphene { namespace debug_witness { + +namespace detail { + +class debug_api_impl +{ + public: + debug_api_impl( std::shared_ptr< graphene::chain::database >& _db ); + + void debug_push_blocks( const std::string& src_filename, uint32_t count ); + void debug_generate_blocks( const std::string& debug_key, uint32_t count ); + void debug_update_object( const fc::variant_object& update ); + //void debug_save_db( std::string db_path ); + + std::shared_ptr< graphene::chain::database > db; +}; + +debug_api_impl::debug_api_impl( std::shared_ptr< graphene::chain::database >& _db ) : db( _db ) +{} + + +void debug_api_impl::debug_push_blocks( const std::string& src_filename, uint32_t count ) +{ + if( count == 0 ) + return; + + fc::path src_path = fc::path( src_filename ); + if( fc::is_directory( src_path ) ) + { + ilog( "Loading ${n} from block_database ${fn}", ("n", count)("fn", src_filename) ); + graphene::chain::block_database bdb; + bdb.open( src_path ); + uint32_t first_block = db->head_block_num()+1; + for( uint32_t i=0; i block = bdb.fetch_by_number( first_block+i ); + if( !block.valid() ) + { + wlog( "Block database ${fn} only contained ${i} of ${n} requested blocks", ("i", i)("n", count)("fn", src_filename) ); + return; + } + try + { + db->push_block( *block ); + } + catch( const fc::exception& e ) + { + elog( "Got exception pushing block ${bn} : ${bid} (${i} of ${n})", ("bn", block->block_num())("bid", block->id())("i", i)("n", count) ); + elog( "Exception backtrace: ${bt}", ("bt", e.to_detail_string()) ); + } + } + ilog( "Completed loading block_database successfully" ); + return; + } +} + +void debug_api_impl::debug_generate_blocks( const std::string& debug_key, uint32_t count ) +{ + if( count == 0 ) + return; + + fc::optional debug_private_key = graphene::utilities::wif_to_key( debug_key ); + FC_ASSERT( debug_private_key.valid() ); + graphene::chain::public_key_type debug_public_key = debug_private_key->get_public_key(); + + for( uint32_t i=0; iget_scheduled_witness( 1 ); + fc::time_point_sec scheduled_time = db->get_slot_time( 1 ); + graphene::chain::public_key_type scheduled_key = scheduled_witness( *db ).signing_key; + if( scheduled_key != debug_public_key ) + { + ilog( "Modified key for witness ${w}", ("w", scheduled_witness) ); + fc::mutable_variant_object update; + update("_action", "update")("id", scheduled_witness)("signing_key", debug_public_key); + db->debug_update( update ); + } + db->generate_block( scheduled_time, scheduled_witness, *debug_private_key, graphene::chain::database::skip_nothing ); + } +} + +void debug_api_impl::debug_update_object( const fc::variant_object& update ) +{ + db->debug_update( update ); +} + +} // detail + +debug_api::debug_api( std::shared_ptr< graphene::chain::database > db ) +{ + my = std::make_shared< detail::debug_api_impl >(db); +} + +void debug_api::debug_push_blocks( std::string source_filename, uint32_t count ) +{ + my->debug_push_blocks( source_filename, count ); +} + +void debug_api::debug_generate_blocks( std::string debug_key, uint32_t count ) +{ + my->debug_generate_blocks( debug_key, count ); +} + +void debug_api::debug_update_object( fc::variant_object update ) +{ + my->debug_update_object( update ); +} + +} } // graphene::debug_witness diff --git a/libraries/plugins/debug_witness/debug_witness.cpp b/libraries/plugins/debug_witness/debug_witness.cpp new file mode 100644 index 00000000..9d6601c4 --- /dev/null +++ b/libraries/plugins/debug_witness/debug_witness.cpp @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2015 Cryptonomex, Inc., and contributors. + * + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include + +#include +#include +#include + +#include + +#include +#include + +#include + +using namespace graphene::debug_witness_plugin; +using std::string; +using std::vector; + +namespace bpo = boost::program_options; + +debug_witness_plugin::~debug_witness_plugin() {} + +void debug_witness_plugin::plugin_set_program_options( + boost::program_options::options_description& command_line_options, + boost::program_options::options_description& config_file_options) +{ + auto default_priv_key = fc::ecc::private_key::regenerate(fc::sha256::hash(std::string("nathan"))); + command_line_options.add_options() + ("private-key", bpo::value>()->composing()->multitoken()-> + DEFAULT_VALUE_VECTOR(std::make_pair(chain::public_key_type(default_priv_key.get_public_key()), graphene::utilities::key_to_wif(default_priv_key))), + "Tuple of [PublicKey, WIF private key] (may specify multiple times)"); + config_file_options.add(command_line_options); +} + +std::string debug_witness_plugin::plugin_name()const +{ + return "debug_witness"; +} + +void debug_witness_plugin::plugin_initialize(const boost::program_options::variables_map& options) +{ try { + ilog("debug_witness plugin: plugin_initialize() begin"); + _options = &options; + + if( options.count("private-key") ) + { + const std::vector key_id_to_wif_pair_strings = options["private-key"].as>(); + for (const std::string& key_id_to_wif_pair_string : key_id_to_wif_pair_strings) + { + auto key_id_to_wif_pair = graphene::app::dejsonify >(key_id_to_wif_pair_string); + idump((key_id_to_wif_pair)); + fc::optional private_key = graphene::utilities::wif_to_key(key_id_to_wif_pair.second); + if (!private_key) + { + // the key isn't in WIF format; see if they are still passing the old native private key format. This is + // just here to ease the transition, can be removed soon + try + { + private_key = fc::variant(key_id_to_wif_pair.second).as(); + } + catch (const fc::exception&) + { + FC_THROW("Invalid WIF-format private key ${key_string}", ("key_string", key_id_to_wif_pair.second)); + } + } + _private_keys[key_id_to_wif_pair.first] = *private_key; + } + } + ilog("debug_witness plugin: plugin_initialize() end"); +} FC_LOG_AND_RETHROW() } + +void debug_witness_plugin::plugin_startup() +{ + ilog("debug_witness_plugin::plugin_startup() begin"); + chain::database& db = database(); + + // connect needed signals + + db.applied_block.connect([this](const graphene::chain::signed_block& b){ on_applied_block(b); }); + db.changed_objects.connect([this](const std::vector& ids){ on_changed_objects(ids); }); + db.removed_objects.connect([this](const std::vector& objs){ on_removed_objects(objs); }); + + return; +} + +void debug_witness_plugin::on_changed_objects( const std::vector& ids ) +{ + +} + +void debug_witness_plugin::on_removed_objects( const std::vector objs ) +{ + +} + +void debug_witness_plugin::on_applied_block( const graphene::chain::signed_block& b ) +{ + +} + +void debug_witness_plugin::plugin_shutdown() +{ + return; +} diff --git a/libraries/plugins/debug_witness/include/graphene/debug_witness/debug_api.hpp b/libraries/plugins/debug_witness/include/graphene/debug_witness/debug_api.hpp new file mode 100644 index 00000000..126f2708 --- /dev/null +++ b/libraries/plugins/debug_witness/include/graphene/debug_witness/debug_api.hpp @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2015 Cryptonomex, Inc., and contributors. + * + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#pragma once + +#include +#include + +#include +#include + +namespace graphene { namespace chain { +class database; +} } + +namespace graphene { namespace debug_witness { + +namespace detail { +class debug_api_impl; +} + +class debug_api +{ + public: + debug_api( std::shared_ptr db ); + + /** + * Push blocks from existing database. + */ + void debug_push_blocks( std::string src_filename, uint32_t count ); + + /** + * Generate blocks locally. + */ + void debug_generate_blocks( std::string debug_key, uint32_t count ); + + /** + * Directly manipulate database objects (will undo and re-apply last block with new changes post-applied). + */ + void debug_update_object( fc::variant_object update ); + + /** + * Start a node with given initial path. + */ + // not implemented + //void start_node( std::string name, std::string initial_db_path ); + + /** + * Save the database to disk. + */ + // not implemented + //void save_db( std::string db_path ); + + std::shared_ptr< detail::debug_api_impl > my; +}; + +} } + +FC_API(graphene::debug_witness::debug_api, + (debug_push_blocks) + (debug_generate_blocks) + (debug_update_object) + ) diff --git a/libraries/plugins/debug_witness/include/graphene/debug_witness/debug_witness.hpp b/libraries/plugins/debug_witness/include/graphene/debug_witness/debug_witness.hpp new file mode 100644 index 00000000..1dde26cc --- /dev/null +++ b/libraries/plugins/debug_witness/include/graphene/debug_witness/debug_witness.hpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015 Cryptonomex, Inc., and contributors. + * + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#pragma once + +#include +#include + +#include + +namespace graphene { namespace debug_witness_plugin { + +class debug_witness_plugin : public graphene::app::plugin { +public: + ~debug_witness_plugin(); + + std::string plugin_name()const override; + + virtual void plugin_set_program_options( + boost::program_options::options_description &command_line_options, + boost::program_options::options_description &config_file_options + ) override; + + virtual void plugin_initialize( const boost::program_options::variables_map& options ) override; + virtual void plugin_startup() override; + virtual void plugin_shutdown() override; + +private: + + void on_changed_objects( const std::vector& ids ); + void on_removed_objects( const std::vector objs ); + void on_applied_block( const graphene::chain::signed_block& b ); + + boost::program_options::variables_map _options; + + std::map _private_keys; +}; + +} } //graphene::debug_witness_plugin diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index cdb9036e..847f2d6e 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -1404,6 +1404,10 @@ class wallet_api void dbg_make_uia(string creator, string symbol); void dbg_make_mia(string creator, string symbol); + void dbg_push_blocks( std::string src_filename, uint32_t count ); + void dbg_generate_blocks( std::string debug_wif_key, uint32_t count ); + void dbg_update_object( fc::variant_object update ); + void flood_network(string prefix, uint32_t number_of_transactions); void network_add_nodes( const vector& nodes ); @@ -1574,6 +1578,9 @@ FC_API( graphene::wallet::wallet_api, (approve_proposal) (dbg_make_uia) (dbg_make_mia) + (dbg_push_blocks) + (dbg_generate_blocks) + (dbg_update_object) (flood_network) (network_add_nodes) (network_get_connected_peers) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index 3dd8b9e3..3dbeda82 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -69,6 +69,7 @@ #include #include #include +#include #include #ifndef WIN32 @@ -2338,6 +2339,24 @@ public: create_asset(get_account(creator).name, symbol, 2, opts, bopts, true); } + void dbg_push_blocks( const std::string& src_filename, uint32_t count ) + { + use_debug_api(); + (*_remote_debug)->debug_push_blocks( src_filename, count ); + } + + void dbg_generate_blocks( const std::string& debug_wif_key, uint32_t count ) + { + use_debug_api(); + (*_remote_debug)->debug_generate_blocks( debug_wif_key, count ); + } + + void dbg_update_object( const fc::variant_object& update ) + { + use_debug_api(); + (*_remote_debug)->debug_update_object( update ); + } + void use_network_node_api() { if( _remote_net_node ) @@ -2356,6 +2375,26 @@ public: } } + void use_debug_api() + { + if( _remote_debug ) + return; + try + { + _remote_debug = _remote_api->debug(); + } + catch( const fc::exception& e ) + { + std::cerr << "\nCouldn't get debug node API. You probably are not configured\n" + "to access the debug API on the node you are connecting to.\n" + "\n" + "To fix this problem:\n" + "- Please ensure you are running debug_node, not witness_node.\n" + "- Please follow the instructions in README.md to set up an apiaccess file.\n" + "\n"; + } + } + void network_add_nodes( const vector& nodes ) { use_network_node_api(); @@ -2449,6 +2488,7 @@ public: fc::api _remote_net_broadcast; fc::api _remote_hist; optional< fc::api > _remote_net_node; + optional< fc::api > _remote_debug; flat_map _prototype_ops; @@ -3214,6 +3254,21 @@ void wallet_api::dbg_make_mia(string creator, string symbol) my->dbg_make_mia(creator, symbol); } +void wallet_api::dbg_push_blocks( std::string src_filename, uint32_t count ) +{ + my->dbg_push_blocks( src_filename, count ); +} + +void wallet_api::dbg_generate_blocks( std::string debug_wif_key, uint32_t count ) +{ + my->dbg_generate_blocks( debug_wif_key, count ); +} + +void wallet_api::dbg_update_object( fc::variant_object update ) +{ + my->dbg_update_object( update ); +} + void wallet_api::network_add_nodes( const vector& nodes ) { my->network_add_nodes( nodes ); diff --git a/programs/CMakeLists.txt b/programs/CMakeLists.txt index b17a972c..932e69b7 100644 --- a/programs/CMakeLists.txt +++ b/programs/CMakeLists.txt @@ -2,6 +2,7 @@ add_subdirectory( build_helpers ) add_subdirectory( cli_wallet ) add_subdirectory( genesis_util ) add_subdirectory( witness_node ) +add_subdirectory( debug_node ) add_subdirectory( delayed_node ) add_subdirectory( js_operation_serializer ) add_subdirectory( size_checker ) diff --git a/programs/debug_node/CMakeLists.txt b/programs/debug_node/CMakeLists.txt new file mode 100644 index 00000000..8ec7362b --- /dev/null +++ b/programs/debug_node/CMakeLists.txt @@ -0,0 +1,21 @@ +add_executable( debug_node main.cpp ) +if( UNIX AND NOT APPLE ) + set(rt_library rt ) +endif() + +find_package( Gperftools QUIET ) +if( GPERFTOOLS_FOUND ) + message( STATUS "Found gperftools; compiling debug_node with TCMalloc") + list( APPEND PLATFORM_SPECIFIC_LIBS tcmalloc ) +endif() + +target_link_libraries( debug_node + PRIVATE graphene_app graphene_account_history graphene_market_history graphene_witness graphene_debug_witness graphene_chain graphene_egenesis_full fc ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} ) + +install( TARGETS + debug_node + + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib +) diff --git a/programs/debug_node/main.cpp b/programs/debug_node/main.cpp new file mode 100644 index 00000000..4b89c199 --- /dev/null +++ b/programs/debug_node/main.cpp @@ -0,0 +1,307 @@ +/* + * Copyright (c) 2015 Cryptonomex, Inc., and contributors. + * + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#ifdef WIN32 +# include +#else +# include +#endif + +using namespace graphene; +namespace bpo = boost::program_options; + +void write_default_logging_config_to_stream(std::ostream& out); +fc::optional load_logging_config_from_ini_file(const fc::path& config_ini_filename); + +int main(int argc, char** argv) { + app::application* node = new app::application(); + fc::oexception unhandled_exception; + try { + bpo::options_description app_options("Graphene Witness Node"); + bpo::options_description cfg_options("Graphene Witness Node"); + app_options.add_options() + ("help,h", "Print this help message and exit.") + ("data-dir,d", bpo::value()->default_value("witness_node_data_dir"), "Directory containing databases, configuration file, etc.") + ; + + bpo::variables_map options; + + auto witness_plug = node->register_plugin(); + auto history_plug = node->register_plugin(); + auto market_history_plug = node->register_plugin(); + + try + { + bpo::options_description cli, cfg; + node->set_program_options(cli, cfg); + app_options.add(cli); + cfg_options.add(cfg); + bpo::store(bpo::parse_command_line(argc, argv, app_options), options); + } + catch (const boost::program_options::error& e) + { + std::cerr << "Error parsing command line: " << e.what() << "\n"; + return 1; + } + + if( options.count("help") ) + { + std::cout << app_options << "\n"; + return 0; + } + + fc::path data_dir; + if( options.count("data-dir") ) + { + data_dir = options["data-dir"].as(); + if( data_dir.is_relative() ) + data_dir = fc::current_path() / data_dir; + } + + fc::path config_ini_path = data_dir / "config.ini"; + if( fc::exists(config_ini_path) ) + { + // get the basic options + bpo::store(bpo::parse_config_file(config_ini_path.preferred_string().c_str(), cfg_options, true), options); + + // try to get logging options from the config file. + try + { + fc::optional logging_config = load_logging_config_from_ini_file(config_ini_path); + if (logging_config) + fc::configure_logging(*logging_config); + } + catch (const fc::exception&) + { + wlog("Error parsing logging config from config file ${config}, using default config", ("config", config_ini_path.preferred_string())); + } + } + else + { + ilog("Writing new config file at ${path}", ("path", config_ini_path)); + if( !fc::exists(data_dir) ) + fc::create_directories(data_dir); + + std::ofstream out_cfg(config_ini_path.preferred_string()); + for( const boost::shared_ptr od : cfg_options.options() ) + { + if( !od->description().empty() ) + out_cfg << "# " << od->description() << "\n"; + boost::any store; + if( !od->semantic()->apply_default(store) ) + out_cfg << "# " << od->long_name() << " = \n"; + else { + auto example = od->format_parameter(); + if( example.empty() ) + // This is a boolean switch + out_cfg << od->long_name() << " = " << "false\n"; + else { + // The string is formatted "arg (=)" + example.erase(0, 6); + example.erase(example.length()-1); + out_cfg << od->long_name() << " = " << example << "\n"; + } + } + out_cfg << "\n"; + } + write_default_logging_config_to_stream(out_cfg); + out_cfg.close(); + // read the default logging config we just wrote out to the file and start using it + fc::optional logging_config = load_logging_config_from_ini_file(config_ini_path); + if (logging_config) + fc::configure_logging(*logging_config); + } + + bpo::notify(options); + node->initialize(data_dir, options); + node->initialize_plugins( options ); + + node->startup(); + node->startup_plugins(); + + fc::promise::ptr exit_promise = new fc::promise("UNIX Signal Handler"); + + fc::set_signal_handler([&exit_promise](int signal) { + elog( "Caught SIGINT attempting to exit cleanly" ); + exit_promise->set_value(signal); + }, SIGINT); + + fc::set_signal_handler([&exit_promise](int signal) { + elog( "Caught SIGTERM attempting to exit cleanly" ); + exit_promise->set_value(signal); + }, SIGTERM); + + ilog("Started witness node on a chain with ${h} blocks.", ("h", node->chain_database()->head_block_num())); + ilog("Chain ID is ${id}", ("id", node->chain_database()->get_chain_id()) ); + + int signal = exit_promise->wait(); + ilog("Exiting from signal ${n}", ("n", signal)); + node->shutdown_plugins(); + node->shutdown(); + delete node; + return 0; + } catch( const fc::exception& e ) { + // deleting the node can yield, so do this outside the exception handler + unhandled_exception = e; + } + + if (unhandled_exception) + { + elog("Exiting with error:\n${e}", ("e", unhandled_exception->to_detail_string())); + node->shutdown(); + delete node; + return 1; + } +} + +// logging config is too complicated to be parsed by boost::program_options, +// so we do it by hand +// +// Currently, you can only specify the filenames and logging levels, which +// are all most users would want to change. At a later time, options can +// be added to control rotation intervals, compression, and other seldom- +// used features +void write_default_logging_config_to_stream(std::ostream& out) +{ + out << "# declare an appender named \"stderr\" that writes messages to the console\n" + "[log.console_appender.stderr]\n" + "stream=std_error\n\n" + "# declare an appender named \"p2p\" that writes messages to p2p.log\n" + "[log.file_appender.p2p]\n" + "filename=logs/p2p/p2p.log\n" + "# filename can be absolute or relative to this config file\n\n" + "# route any messages logged to the default logger to the \"stderr\" logger we\n" + "# declared above, if they are info level are higher\n" + "[logger.default]\n" + "level=info\n" + "appenders=stderr\n\n" + "# route messages sent to the \"p2p\" logger to the p2p appender declared above\n" + "[logger.p2p]\n" + "level=debug\n" + "appenders=p2p\n\n"; +} + +fc::optional load_logging_config_from_ini_file(const fc::path& config_ini_filename) +{ + try + { + fc::logging_config logging_config; + bool found_logging_config = false; + + boost::property_tree::ptree config_ini_tree; + boost::property_tree::ini_parser::read_ini(config_ini_filename.preferred_string().c_str(), config_ini_tree); + for (const auto& section : config_ini_tree) + { + const std::string& section_name = section.first; + const boost::property_tree::ptree& section_tree = section.second; + + const std::string console_appender_section_prefix = "log.console_appender."; + const std::string file_appender_section_prefix = "log.file_appender."; + const std::string logger_section_prefix = "logger."; + + if (boost::starts_with(section_name, console_appender_section_prefix)) + { + std::string console_appender_name = section_name.substr(console_appender_section_prefix.length()); + std::string stream_name = section_tree.get("stream"); + + // construct a default console appender config here + // stdout/stderr will be taken from ini file, everything else hard-coded here + fc::console_appender::config console_appender_config; + console_appender_config.level_colors.emplace_back( + fc::console_appender::level_color(fc::log_level::debug, + fc::console_appender::color::green)); + console_appender_config.level_colors.emplace_back( + fc::console_appender::level_color(fc::log_level::warn, + fc::console_appender::color::brown)); + console_appender_config.level_colors.emplace_back( + fc::console_appender::level_color(fc::log_level::error, + fc::console_appender::color::cyan)); + console_appender_config.stream = fc::variant(stream_name).as(); + logging_config.appenders.push_back(fc::appender_config(console_appender_name, "console", fc::variant(console_appender_config))); + found_logging_config = true; + } + else if (boost::starts_with(section_name, file_appender_section_prefix)) + { + std::string file_appender_name = section_name.substr(file_appender_section_prefix.length()); + fc::path file_name = section_tree.get("filename"); + if (file_name.is_relative()) + file_name = fc::absolute(config_ini_filename).parent_path() / file_name; + + + // construct a default file appender config here + // filename will be taken from ini file, everything else hard-coded here + fc::file_appender::config file_appender_config; + file_appender_config.filename = file_name; + file_appender_config.flush = true; + file_appender_config.rotate = true; + file_appender_config.rotation_interval = fc::hours(1); + file_appender_config.rotation_limit = fc::days(1); + logging_config.appenders.push_back(fc::appender_config(file_appender_name, "file", fc::variant(file_appender_config))); + found_logging_config = true; + } + else if (boost::starts_with(section_name, logger_section_prefix)) + { + std::string logger_name = section_name.substr(logger_section_prefix.length()); + std::string level_string = section_tree.get("level"); + std::string appenders_string = section_tree.get("appenders"); + fc::logger_config logger_config(logger_name); + logger_config.level = fc::variant(level_string).as(); + boost::split(logger_config.appenders, appenders_string, + boost::is_any_of(" ,"), + boost::token_compress_on); + logging_config.loggers.push_back(logger_config); + found_logging_config = true; + } + } + if (found_logging_config) + return logging_config; + else + return fc::optional(); + } + FC_RETHROW_EXCEPTIONS(warn, "") +} diff --git a/programs/witness_node/CMakeLists.txt b/programs/witness_node/CMakeLists.txt index 41bd784d..0509a0af 100644 --- a/programs/witness_node/CMakeLists.txt +++ b/programs/witness_node/CMakeLists.txt @@ -9,8 +9,9 @@ if( GPERFTOOLS_FOUND ) list( APPEND PLATFORM_SPECIFIC_LIBS tcmalloc ) endif() +# We have to link against graphene_debug_witness because deficiency in our API infrastructure doesn't allow plugins to be fully abstracted #246 target_link_libraries( witness_node - PRIVATE graphene_app graphene_account_history graphene_market_history graphene_witness graphene_chain graphene_egenesis_full fc ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} ) + PRIVATE graphene_app graphene_account_history graphene_market_history graphene_witness graphene_chain graphene_debug_witness graphene_egenesis_full fc ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} ) install( TARGETS witness_node From c37c2d4543bc97068528c0b170e2ab6ab79d2ab9 Mon Sep 17 00:00:00 2001 From: theoreticalbts Date: Tue, 15 Mar 2016 00:38:33 -0400 Subject: [PATCH 23/37] debug_api: Take application object, not database, as parameter #606 --- libraries/app/api.cpp | 2 +- libraries/plugins/debug_witness/debug_api.cpp | 15 ++++++++++----- .../include/graphene/debug_witness/debug_api.hpp | 6 +++--- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/libraries/app/api.cpp b/libraries/app/api.cpp index 4e6120d6..53e8f53e 100644 --- a/libraries/app/api.cpp +++ b/libraries/app/api.cpp @@ -99,7 +99,7 @@ namespace graphene { namespace app { { // can only enable this API if the plugin was loaded if( _app.get_plugin( "debug_witness" ) ) - _debug_api = std::make_shared< graphene::debug_witness::debug_api >( _app.chain_database() ); + _debug_api = std::make_shared< graphene::debug_witness::debug_api >( std::ref(_app) ); } return; } diff --git a/libraries/plugins/debug_witness/debug_api.cpp b/libraries/plugins/debug_witness/debug_api.cpp index 53b2e7a8..885ecef7 100644 --- a/libraries/plugins/debug_witness/debug_api.cpp +++ b/libraries/plugins/debug_witness/debug_api.cpp @@ -3,6 +3,8 @@ #include #include +#include + #include #include #include @@ -18,17 +20,17 @@ namespace detail { class debug_api_impl { public: - debug_api_impl( std::shared_ptr< graphene::chain::database >& _db ); + debug_api_impl( graphene::app::application& _app ); void debug_push_blocks( const std::string& src_filename, uint32_t count ); void debug_generate_blocks( const std::string& debug_key, uint32_t count ); void debug_update_object( const fc::variant_object& update ); //void debug_save_db( std::string db_path ); - std::shared_ptr< graphene::chain::database > db; + graphene::app::application& app; }; -debug_api_impl::debug_api_impl( std::shared_ptr< graphene::chain::database >& _db ) : db( _db ) +debug_api_impl::debug_api_impl( graphene::app::application& _app ) : app( _app ) {} @@ -37,6 +39,7 @@ void debug_api_impl::debug_push_blocks( const std::string& src_filename, uint32_ if( count == 0 ) return; + std::shared_ptr< graphene::chain::database > db = app.chain_database(); fc::path src_path = fc::path( src_filename ); if( fc::is_directory( src_path ) ) { @@ -76,6 +79,7 @@ void debug_api_impl::debug_generate_blocks( const std::string& debug_key, uint32 FC_ASSERT( debug_private_key.valid() ); graphene::chain::public_key_type debug_public_key = debug_private_key->get_public_key(); + std::shared_ptr< graphene::chain::database > db = app.chain_database(); for( uint32_t i=0; iget_scheduled_witness( 1 ); @@ -94,14 +98,15 @@ void debug_api_impl::debug_generate_blocks( const std::string& debug_key, uint32 void debug_api_impl::debug_update_object( const fc::variant_object& update ) { + std::shared_ptr< graphene::chain::database > db = app.chain_database(); db->debug_update( update ); } } // detail -debug_api::debug_api( std::shared_ptr< graphene::chain::database > db ) +debug_api::debug_api( graphene::app::application& app ) { - my = std::make_shared< detail::debug_api_impl >(db); + my = std::make_shared< detail::debug_api_impl >(app); } void debug_api::debug_push_blocks( std::string source_filename, uint32_t count ) diff --git a/libraries/plugins/debug_witness/include/graphene/debug_witness/debug_api.hpp b/libraries/plugins/debug_witness/include/graphene/debug_witness/debug_api.hpp index 126f2708..9306e4be 100644 --- a/libraries/plugins/debug_witness/include/graphene/debug_witness/debug_api.hpp +++ b/libraries/plugins/debug_witness/include/graphene/debug_witness/debug_api.hpp @@ -29,8 +29,8 @@ #include #include -namespace graphene { namespace chain { -class database; +namespace graphene { namespace app { +class application; } } namespace graphene { namespace debug_witness { @@ -42,7 +42,7 @@ class debug_api_impl; class debug_api { public: - debug_api( std::shared_ptr db ); + debug_api( graphene::app::application& app ); /** * Push blocks from existing database. From da9ee0c4998c78f80a70123f04bdfa53d22f69f7 Mon Sep 17 00:00:00 2001 From: theoreticalbts Date: Tue, 15 Mar 2016 01:17:07 -0400 Subject: [PATCH 24/37] db_block.cpp: Include smart_ref_impl --- libraries/chain/db_block.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/chain/db_block.cpp b/libraries/chain/db_block.cpp index e141cd08..2e511591 100644 --- a/libraries/chain/db_block.cpp +++ b/libraries/chain/db_block.cpp @@ -36,6 +36,8 @@ #include #include +#include + namespace graphene { namespace chain { bool database::is_known_block( const block_id_type& id )const From a7c88be7c72ee8c3619b07c617cd9f13cd3f364c Mon Sep 17 00:00:00 2001 From: theoreticalbts Date: Tue, 15 Mar 2016 00:38:55 -0400 Subject: [PATCH 25/37] debug_api: Add API call to stream JSON objects to file --- libraries/plugins/debug_witness/debug_api.cpp | 30 ++++++++++ .../plugins/debug_witness/debug_witness.cpp | 57 +++++++++++++++++-- .../graphene/debug_witness/debug_api.hpp | 13 +++++ .../graphene/debug_witness/debug_witness.hpp | 8 +++ .../wallet/include/graphene/wallet/wallet.hpp | 2 + libraries/wallet/wallet.cpp | 15 +++++ 6 files changed, 120 insertions(+), 5 deletions(-) diff --git a/libraries/plugins/debug_witness/debug_api.cpp b/libraries/plugins/debug_witness/debug_api.cpp index 885ecef7..5c2d9a37 100644 --- a/libraries/plugins/debug_witness/debug_api.cpp +++ b/libraries/plugins/debug_witness/debug_api.cpp @@ -12,6 +12,7 @@ #include #include +#include namespace graphene { namespace debug_witness { @@ -26,6 +27,9 @@ class debug_api_impl void debug_generate_blocks( const std::string& debug_key, uint32_t count ); void debug_update_object( const fc::variant_object& update ); //void debug_save_db( std::string db_path ); + void debug_stream_json_objects( const std::string& filename ); + void debug_stream_json_objects_flush(); + std::shared_ptr< graphene::debug_witness_plugin::debug_witness_plugin > get_plugin(); graphene::app::application& app; }; @@ -102,6 +106,21 @@ void debug_api_impl::debug_update_object( const fc::variant_object& update ) db->debug_update( update ); } +std::shared_ptr< graphene::debug_witness_plugin::debug_witness_plugin > debug_api_impl::get_plugin() +{ + return app.get_plugin< graphene::debug_witness_plugin::debug_witness_plugin >( "debug_witness" ); +} + +void debug_api_impl::debug_stream_json_objects( const std::string& filename ) +{ + get_plugin()->set_json_object_stream( filename ); +} + +void debug_api_impl::debug_stream_json_objects_flush() +{ + get_plugin()->flush_json_object_stream(); +} + } // detail debug_api::debug_api( graphene::app::application& app ) @@ -124,4 +143,15 @@ void debug_api::debug_update_object( fc::variant_object update ) my->debug_update_object( update ); } +void debug_api::debug_stream_json_objects( std::string filename ) +{ + my->debug_stream_json_objects( filename ); +} + +void debug_api::debug_stream_json_objects_flush() +{ + my->debug_stream_json_objects_flush(); +} + + } } // graphene::debug_witness diff --git a/libraries/plugins/debug_witness/debug_witness.cpp b/libraries/plugins/debug_witness/debug_witness.cpp index 9d6601c4..7bb5562d 100644 --- a/libraries/plugins/debug_witness/debug_witness.cpp +++ b/libraries/plugins/debug_witness/debug_witness.cpp @@ -98,29 +98,76 @@ void debug_witness_plugin::plugin_startup() // connect needed signals - db.applied_block.connect([this](const graphene::chain::signed_block& b){ on_applied_block(b); }); - db.changed_objects.connect([this](const std::vector& ids){ on_changed_objects(ids); }); - db.removed_objects.connect([this](const std::vector& objs){ on_removed_objects(objs); }); + _applied_block_conn = db.applied_block.connect([this](const graphene::chain::signed_block& b){ on_applied_block(b); }); + _changed_objects_conn = db.changed_objects.connect([this](const std::vector& ids){ on_changed_objects(ids); }); + _removed_objects_conn = db.removed_objects.connect([this](const std::vector& objs){ on_removed_objects(objs); }); return; } void debug_witness_plugin::on_changed_objects( const std::vector& ids ) { - + if( _json_object_stream && (ids.size() > 0) ) + { + const chain::database& db = database(); + for( const graphene::db::object_id_type& oid : ids ) + { + const graphene::db::object* obj = db.find_object( oid ); + if( obj == nullptr ) + { + (*_json_object_stream) << "{\"id\":" << fc::json::to_string( oid ) << "}\n"; + } + else + { + (*_json_object_stream) << fc::json::to_string( obj->to_variant() ) << '\n'; + } + } + } } void debug_witness_plugin::on_removed_objects( const std::vector objs ) { - + /* + if( _json_object_stream ) + { + for( const graphene::db::object* obj : objs ) + { + (*_json_object_stream) << "{\"id\":" << fc::json::to_string( obj->id ) << "}\n"; + } + } + */ } void debug_witness_plugin::on_applied_block( const graphene::chain::signed_block& b ) { + if( _json_object_stream ) + { + (*_json_object_stream) << "{\"bn\":" << fc::to_string( b.block_num() ) << "}\n"; + } +} +void debug_witness_plugin::set_json_object_stream( const std::string& filename ) +{ + if( _json_object_stream ) + { + _json_object_stream->close(); + _json_object_stream.reset(); + } + _json_object_stream = std::make_shared< std::ofstream >( filename ); +} + +void debug_witness_plugin::flush_json_object_stream() +{ + if( _json_object_stream ) + _json_object_stream->flush(); } void debug_witness_plugin::plugin_shutdown() { + if( _json_object_stream ) + { + _json_object_stream->close(); + _json_object_stream.reset(); + } return; } diff --git a/libraries/plugins/debug_witness/include/graphene/debug_witness/debug_api.hpp b/libraries/plugins/debug_witness/include/graphene/debug_witness/debug_api.hpp index 9306e4be..7985f27f 100644 --- a/libraries/plugins/debug_witness/include/graphene/debug_witness/debug_api.hpp +++ b/libraries/plugins/debug_witness/include/graphene/debug_witness/debug_api.hpp @@ -71,6 +71,17 @@ class debug_api // not implemented //void save_db( std::string db_path ); + /** + * Stream objects to file. (Hint: Create with mkfifo and pipe it to a script) + */ + + void debug_stream_json_objects( std::string filename ); + + /** + * Flush streaming file. + */ + void debug_stream_json_objects_flush(); + std::shared_ptr< detail::debug_api_impl > my; }; @@ -80,4 +91,6 @@ FC_API(graphene::debug_witness::debug_api, (debug_push_blocks) (debug_generate_blocks) (debug_update_object) + (debug_stream_json_objects) + (debug_stream_json_objects_flush) ) diff --git a/libraries/plugins/debug_witness/include/graphene/debug_witness/debug_witness.hpp b/libraries/plugins/debug_witness/include/graphene/debug_witness/debug_witness.hpp index 1dde26cc..0e5c173f 100644 --- a/libraries/plugins/debug_witness/include/graphene/debug_witness/debug_witness.hpp +++ b/libraries/plugins/debug_witness/include/graphene/debug_witness/debug_witness.hpp @@ -45,6 +45,9 @@ public: virtual void plugin_startup() override; virtual void plugin_shutdown() override; + void set_json_object_stream( const std::string& filename ); + void flush_json_object_stream(); + private: void on_changed_objects( const std::vector& ids ); @@ -54,6 +57,11 @@ private: boost::program_options::variables_map _options; std::map _private_keys; + + std::shared_ptr< std::ofstream > _json_object_stream; + boost::signals2::scoped_connection _applied_block_conn; + boost::signals2::scoped_connection _changed_objects_conn; + boost::signals2::scoped_connection _removed_objects_conn; }; } } //graphene::debug_witness_plugin diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index 847f2d6e..9f5d26eb 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -1406,6 +1406,7 @@ class wallet_api void dbg_make_mia(string creator, string symbol); void dbg_push_blocks( std::string src_filename, uint32_t count ); void dbg_generate_blocks( std::string debug_wif_key, uint32_t count ); + void dbg_stream_json_objects( const std::string& filename ); void dbg_update_object( fc::variant_object update ); void flood_network(string prefix, uint32_t number_of_transactions); @@ -1580,6 +1581,7 @@ FC_API( graphene::wallet::wallet_api, (dbg_make_mia) (dbg_push_blocks) (dbg_generate_blocks) + (dbg_stream_json_objects) (dbg_update_object) (flood_network) (network_add_nodes) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index 3dbeda82..3904967e 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -2343,18 +2343,28 @@ public: { use_debug_api(); (*_remote_debug)->debug_push_blocks( src_filename, count ); + (*_remote_debug)->debug_stream_json_objects_flush(); } void dbg_generate_blocks( const std::string& debug_wif_key, uint32_t count ) { use_debug_api(); (*_remote_debug)->debug_generate_blocks( debug_wif_key, count ); + (*_remote_debug)->debug_stream_json_objects_flush(); + } + + void dbg_stream_json_objects( const std::string& filename ) + { + use_debug_api(); + (*_remote_debug)->debug_stream_json_objects( filename ); + (*_remote_debug)->debug_stream_json_objects_flush(); } void dbg_update_object( const fc::variant_object& update ) { use_debug_api(); (*_remote_debug)->debug_update_object( update ); + (*_remote_debug)->debug_stream_json_objects_flush(); } void use_network_node_api() @@ -3264,6 +3274,11 @@ void wallet_api::dbg_generate_blocks( std::string debug_wif_key, uint32_t count my->dbg_generate_blocks( debug_wif_key, count ); } +void wallet_api::dbg_stream_json_objects( const std::string& filename ) +{ + my->dbg_stream_json_objects( filename ); +} + void wallet_api::dbg_update_object( fc::variant_object update ) { my->dbg_update_object( update ); From 14f7b520bd58716d6fa28959474a4e857c67a7e0 Mon Sep 17 00:00:00 2001 From: theoreticalbts Date: Mon, 7 Mar 2016 14:30:09 -0500 Subject: [PATCH 26/37] Disable negative voting on workers #607 --- libraries/chain/account_evaluator.cpp | 16 ++++++++++++++++ libraries/chain/db_maint.cpp | 3 ++- libraries/chain/hardfork.d/607.hf | 4 ++++ 3 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 libraries/chain/hardfork.d/607.hf diff --git a/libraries/chain/account_evaluator.cpp b/libraries/chain/account_evaluator.cpp index b44597e4..eb86764c 100644 --- a/libraries/chain/account_evaluator.cpp +++ b/libraries/chain/account_evaluator.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include @@ -69,10 +70,25 @@ void verify_account_votes( const database& db, const account_options& options ) "Voted for more committee members than currently allowed (${c})", ("c", chain_params.maximum_committee_count) ); uint32_t max_vote_id = gpo.next_available_vote_id; + bool has_worker_votes = false; for( auto id : options.votes ) { FC_ASSERT( id < max_vote_id ); + has_worker_votes |= (id.type() == vote_id_type::worker); } + + if( has_worker_votes && (db.head_block_time() >= HARDFORK_607_TIME) ) + { + const auto& against_worker_idx = db.get_index_type().indices().get(); + for( auto id : options.votes ) + { + if( id.type() == vote_id_type::worker ) + { + FC_ASSERT( against_worker_idx.find( id ) == against_worker_idx.end() ); + } + } + } + } diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index c7e39d75..709cd583 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -102,11 +102,12 @@ void database::update_worker_votes() { auto& idx = get_index_type(); auto itr = idx.indices().get().begin(); + bool allow_negative_votes = (head_block_time() < HARDFORK_607_TIME); while( itr != idx.indices().get().end() ) { modify( *itr, [&]( worker_object& obj ){ obj.total_votes_for = _vote_tally_buffer[obj.vote_for]; - obj.total_votes_against = _vote_tally_buffer[obj.vote_against]; + obj.total_votes_against = allow_negative_votes ? _vote_tally_buffer[obj.vote_against] : 0; }); ++itr; } diff --git a/libraries/chain/hardfork.d/607.hf b/libraries/chain/hardfork.d/607.hf new file mode 100644 index 00000000..135619c2 --- /dev/null +++ b/libraries/chain/hardfork.d/607.hf @@ -0,0 +1,4 @@ +// #607 Disable negative voting on workers +#ifndef HARDFORK_607_TIME +#define HARDFORK_607_TIME (fc::time_point_sec( 1458061200 )) +#endif From 2a745f5882770161c369af9eae2d23ee87f9d8ee Mon Sep 17 00:00:00 2001 From: theoreticalbts Date: Tue, 15 Mar 2016 15:07:53 -0400 Subject: [PATCH 27/37] db_update.cpp: Include hardfork.hpp, fix non-unity build broken by #615 fix --- libraries/chain/db_update.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/chain/db_update.cpp b/libraries/chain/db_update.cpp index aa4d5969..2219136e 100644 --- a/libraries/chain/db_update.cpp +++ b/libraries/chain/db_update.cpp @@ -27,6 +27,7 @@ #include #include +#include #include #include #include From c4fc67602a06d9e95d9732b7f90912c343e38e72 Mon Sep 17 00:00:00 2001 From: theoreticalbts Date: Tue, 15 Mar 2016 12:34:57 -0400 Subject: [PATCH 28/37] Implement hardfork for serialization fix #599 --- libraries/chain/account_evaluator.cpp | 13 +++++++++++++ libraries/chain/hardfork.d/599.hf | 4 ++++ 2 files changed, 17 insertions(+) create mode 100644 libraries/chain/hardfork.d/599.hf diff --git a/libraries/chain/account_evaluator.cpp b/libraries/chain/account_evaluator.cpp index 1f29bb0a..f34af18f 100644 --- a/libraries/chain/account_evaluator.cpp +++ b/libraries/chain/account_evaluator.cpp @@ -62,6 +62,13 @@ void_result account_create_evaluator::do_evaluate( const account_create_operatio FC_ASSERT( !op.extensions.value.owner_special_authority.valid() ); FC_ASSERT( !op.extensions.value.active_special_authority.valid() ); } + if( d.head_block_time() < HARDFORK_599_TIME ) + { + FC_ASSERT( !op.extensions.value.null_ext.valid() ); + FC_ASSERT( !op.extensions.value.owner_special_authority.valid() ); + FC_ASSERT( !op.extensions.value.active_special_authority.valid() ); + FC_ASSERT( !op.extensions.value.buyback_options.valid() ); + } FC_ASSERT( d.find_object(op.options.voting_account), "Invalid proxy account specified." ); FC_ASSERT( fee_paying_account->is_lifetime_member(), "Only Lifetime members may register an account." ); @@ -223,6 +230,12 @@ void_result account_update_evaluator::do_evaluate( const account_update_operatio FC_ASSERT( !o.extensions.value.owner_special_authority.valid() ); FC_ASSERT( !o.extensions.value.active_special_authority.valid() ); } + if( d.head_block_time() < HARDFORK_599_TIME ) + { + FC_ASSERT( !o.extensions.value.null_ext.valid() ); + FC_ASSERT( !o.extensions.value.owner_special_authority.valid() ); + FC_ASSERT( !o.extensions.value.active_special_authority.valid() ); + } const auto& chain_params = d.get_global_properties().parameters; diff --git a/libraries/chain/hardfork.d/599.hf b/libraries/chain/hardfork.d/599.hf new file mode 100644 index 00000000..71f7e94e --- /dev/null +++ b/libraries/chain/hardfork.d/599.hf @@ -0,0 +1,4 @@ +// #599 Unpacking of extension is incorrect +#ifndef HARDFORK_599_TIME +#define HARDFORK_599_TIME (fc::time_point_sec( 1458061200 )) +#endif From e0c4c5e91469871db652476cb2a3d12ab9348695 Mon Sep 17 00:00:00 2001 From: theoreticalbts Date: Tue, 15 Mar 2016 16:15:36 -0400 Subject: [PATCH 29/37] Wait for HARDFORK_599_TIME when needed in tests #599 --- tests/tests/fee_tests.cpp | 1 + tests/tests/operation_tests2.cpp | 2 ++ 2 files changed, 3 insertions(+) diff --git a/tests/tests/fee_tests.cpp b/tests/tests/fee_tests.cpp index 984c6fce..d6f26170 100644 --- a/tests/tests/fee_tests.cpp +++ b/tests/tests/fee_tests.cpp @@ -747,6 +747,7 @@ BOOST_AUTO_TEST_CASE( stealth_fba_test ) generate_blocks( HARDFORK_555_TIME ); generate_blocks( HARDFORK_563_TIME ); generate_blocks( HARDFORK_572_TIME ); + generate_blocks( HARDFORK_599_TIME ); // Philbin (registrar who registers Rex) diff --git a/tests/tests/operation_tests2.cpp b/tests/tests/operation_tests2.cpp index 6d08d686..8cefec4e 100644 --- a/tests/tests/operation_tests2.cpp +++ b/tests/tests/operation_tests2.cpp @@ -1338,6 +1338,7 @@ BOOST_AUTO_TEST_CASE( top_n_special ) ACTORS( (alice)(bob)(chloe)(dan)(izzy)(stan) ); generate_blocks( HARDFORK_516_TIME ); + generate_blocks( HARDFORK_599_TIME ); try { @@ -1490,6 +1491,7 @@ BOOST_AUTO_TEST_CASE( buyback ) generate_blocks( HARDFORK_538_TIME ); generate_blocks( HARDFORK_555_TIME ); + generate_blocks( HARDFORK_599_TIME ); try { From b7b4d4fc5de01c2547e5748a582de97a7e09f247 Mon Sep 17 00:00:00 2001 From: theoreticalbts Date: Mon, 14 Mar 2016 23:32:43 -0400 Subject: [PATCH 30/37] Deprecate annual memberships #613 --- libraries/chain/account_evaluator.cpp | 2 ++ libraries/chain/db_maint.cpp | 38 ++++++++++++++++++++++++++- libraries/chain/hardfork.d/613.hf | 4 +++ 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 libraries/chain/hardfork.d/613.hf diff --git a/libraries/chain/account_evaluator.cpp b/libraries/chain/account_evaluator.cpp index 1f29bb0a..42922473 100644 --- a/libraries/chain/account_evaluator.cpp +++ b/libraries/chain/account_evaluator.cpp @@ -371,11 +371,13 @@ void_result account_upgrade_evaluator::do_apply(const account_upgrade_evaluator: a.lifetime_referrer_fee_percentage = GRAPHENE_100_PERCENT - a.network_fee_percentage; } else if( a.is_annual_member(d.head_block_time()) ) { // Renew an annual subscription that's still in effect. + FC_ASSERT( d.head_block_time() <= HARDFORK_613_TIME ); FC_ASSERT(a.membership_expiration_date - d.head_block_time() < fc::days(3650), "May not extend annual membership more than a decade into the future."); a.membership_expiration_date += fc::days(365); } else { // Upgrade from basic account. + FC_ASSERT( d.head_block_time() <= HARDFORK_613_TIME ); a.statistics(d).process_fees(a, d); assert(a.is_basic_account(d.head_block_time())); a.referrer = a.get_id(); diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index c7e39d75..bccf4958 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -684,6 +684,37 @@ void create_buyback_orders( database& db ) return; } +void deprecate_annual_members( database& db ) +{ + const auto& account_idx = db.get_index_type().indices().get(); + fc::time_point_sec now = db.head_block_time(); + for( const account_object& acct : account_idx ) + { + try + { + transaction_evaluation_state upgrade_context(&db); + upgrade_context.skip_fee_schedule_check = true; + + if( acct.is_annual_member( now ) ) + { + account_upgrade_operation upgrade_vop; + upgrade_vop.fee = asset( 0, asset_id_type() ); + upgrade_vop.account_to_upgrade = acct.id; + upgrade_vop.upgrade_to_lifetime_member = true; + db.apply_operation( upgrade_context, upgrade_vop ); + } + } + catch( const fc::exception& e ) + { + // we can in fact get here, e.g. if asset issuer of buy/sell asset blacklists/whitelists the buyback account + wlog( "Skipping annual member deprecate processing for account ${a} (${an}) at block ${n}; exception was ${e}", + ("a", acct.id)("an", acct.name)("n", db.head_block_num())("e", e.to_detail_string()) ); + continue; + } + } + return; +} + void database::perform_chain_maintenance(const signed_block& next_block, const global_property_object& global_props) { const auto& gpo = get_global_properties(); @@ -830,7 +861,12 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g } } - modify(get_dynamic_global_properties(), [next_maintenance_time](dynamic_global_property_object& d) { + const dynamic_global_property_object& dgpo = get_dynamic_global_properties(); + + if( (dgpo.next_maintenance_time < HARDFORK_613_TIME) && (next_maintenance_time >= HARDFORK_613_TIME) ) + deprecate_annual_members(*this); + + modify(dgpo, [next_maintenance_time](dynamic_global_property_object& d) { d.next_maintenance_time = next_maintenance_time; d.accounts_registered_this_interval = 0; }); diff --git a/libraries/chain/hardfork.d/613.hf b/libraries/chain/hardfork.d/613.hf new file mode 100644 index 00000000..74c740fb --- /dev/null +++ b/libraries/chain/hardfork.d/613.hf @@ -0,0 +1,4 @@ +// #613 Deprecate annual membership +#ifndef HARDFORK_613_TIME +#define HARDFORK_613_TIME (fc::time_point_sec( 1458061200 )) +#endif From 755f9ecf382b99896f54dfe912aab63908df62ec Mon Sep 17 00:00:00 2001 From: theoreticalbts Date: Tue, 15 Mar 2016 17:37:05 -0400 Subject: [PATCH 31/37] Prepare for release - Bump GRAPHENE_CURRENT_DB_VERSION to force re-index - Set hardfork date --- libraries/chain/hardfork.d/599.hf | 2 +- libraries/chain/hardfork.d/607.hf | 2 +- libraries/chain/hardfork.d/613.hf | 2 +- libraries/chain/hardfork.d/615.hf | 2 +- libraries/chain/include/graphene/chain/config.hpp | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/chain/hardfork.d/599.hf b/libraries/chain/hardfork.d/599.hf index 71f7e94e..f92dbf04 100644 --- a/libraries/chain/hardfork.d/599.hf +++ b/libraries/chain/hardfork.d/599.hf @@ -1,4 +1,4 @@ // #599 Unpacking of extension is incorrect #ifndef HARDFORK_599_TIME -#define HARDFORK_599_TIME (fc::time_point_sec( 1458061200 )) +#define HARDFORK_599_TIME (fc::time_point_sec( 1458752400 )) #endif diff --git a/libraries/chain/hardfork.d/607.hf b/libraries/chain/hardfork.d/607.hf index 135619c2..77c8c9e0 100644 --- a/libraries/chain/hardfork.d/607.hf +++ b/libraries/chain/hardfork.d/607.hf @@ -1,4 +1,4 @@ // #607 Disable negative voting on workers #ifndef HARDFORK_607_TIME -#define HARDFORK_607_TIME (fc::time_point_sec( 1458061200 )) +#define HARDFORK_607_TIME (fc::time_point_sec( 1458752400 )) #endif diff --git a/libraries/chain/hardfork.d/613.hf b/libraries/chain/hardfork.d/613.hf index 74c740fb..9978d33c 100644 --- a/libraries/chain/hardfork.d/613.hf +++ b/libraries/chain/hardfork.d/613.hf @@ -1,4 +1,4 @@ // #613 Deprecate annual membership #ifndef HARDFORK_613_TIME -#define HARDFORK_613_TIME (fc::time_point_sec( 1458061200 )) +#define HARDFORK_613_TIME (fc::time_point_sec( 1458752400 )) #endif diff --git a/libraries/chain/hardfork.d/615.hf b/libraries/chain/hardfork.d/615.hf index a5599bbc..ac0535dc 100644 --- a/libraries/chain/hardfork.d/615.hf +++ b/libraries/chain/hardfork.d/615.hf @@ -1,4 +1,4 @@ // #615 Fix price feed expiration check, so websocket server will never spam too much data #ifndef HARDFORK_615_TIME -#define HARDFORK_615_TIME (fc::time_point_sec( 1457550000 )) +#define HARDFORK_615_TIME (fc::time_point_sec( 1458752400 )) #endif diff --git a/libraries/chain/include/graphene/chain/config.hpp b/libraries/chain/include/graphene/chain/config.hpp index 07dff7ff..cd46a60c 100644 --- a/libraries/chain/include/graphene/chain/config.hpp +++ b/libraries/chain/include/graphene/chain/config.hpp @@ -144,7 +144,7 @@ #define GRAPHENE_RECENTLY_MISSED_COUNT_INCREMENT 4 #define GRAPHENE_RECENTLY_MISSED_COUNT_DECREMENT 3 -#define GRAPHENE_CURRENT_DB_VERSION "BTS2.8" +#define GRAPHENE_CURRENT_DB_VERSION "BTS2.9" #define GRAPHENE_IRREVERSIBLE_THRESHOLD (70 * GRAPHENE_1_PERCENT) From e955b06c42cf93c42414f74cd54b94092451892e Mon Sep 17 00:00:00 2001 From: theoreticalbts Date: Wed, 16 Mar 2016 15:50:03 -0400 Subject: [PATCH 32/37] Fix accidental reversion of #615 fix by b175cc7feb4accaeab5e85ebfcddfe7d2264c422 --- libraries/chain/include/graphene/chain/asset_object.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/chain/include/graphene/chain/asset_object.hpp b/libraries/chain/include/graphene/chain/asset_object.hpp index 4f4a5357..28d5974e 100644 --- a/libraries/chain/include/graphene/chain/asset_object.hpp +++ b/libraries/chain/include/graphene/chain/asset_object.hpp @@ -214,7 +214,7 @@ namespace graphene { namespace chain { bool feed_is_expired_before_hardfork_615(time_point_sec current_time)const { return feed_expiration_time() >= current_time; } bool feed_is_expired(time_point_sec current_time)const - { return feed_expiration_time() >= current_time; } + { return feed_expiration_time() <= current_time; } void update_median_feeds(time_point_sec current_time); }; From 6456d7b55f058c82c8b8d2f5618473eb3d3ca999 Mon Sep 17 00:00:00 2001 From: valzav Date: Wed, 23 Mar 2016 18:00:39 -0400 Subject: [PATCH 33/37] bump gui version 2.0.160323-stealth-beta --- gui_version | 2 +- libraries/fc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gui_version b/gui_version index d1ce3978..af96d79b 100644 --- a/gui_version +++ b/gui_version @@ -1 +1 @@ -2.0.160314 +2.0.160323-stealth-beta diff --git a/libraries/fc b/libraries/fc index 622ff580..64950043 160000 --- a/libraries/fc +++ b/libraries/fc @@ -1 +1 @@ -Subproject commit 622ff58039f2388433272a44fe416f5b8025589a +Subproject commit 6495004302239ae0c775f05a0e78780c3b189502 From 3a19b22bf66c95cfd872caa593ee878fec4fb3d9 Mon Sep 17 00:00:00 2001 From: valzav Date: Fri, 25 Mar 2016 15:11:56 -0400 Subject: [PATCH 34/37] Revert "bump gui version 2.0.160323-stealth-beta" This reverts commit 6456d7b55f058c82c8b8d2f5618473eb3d3ca999. --- gui_version | 2 +- libraries/fc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gui_version b/gui_version index af96d79b..d1ce3978 100644 --- a/gui_version +++ b/gui_version @@ -1 +1 @@ -2.0.160323-stealth-beta +2.0.160314 diff --git a/libraries/fc b/libraries/fc index 64950043..622ff580 160000 --- a/libraries/fc +++ b/libraries/fc @@ -1 +1 @@ -Subproject commit 6495004302239ae0c775f05a0e78780c3b189502 +Subproject commit 622ff58039f2388433272a44fe416f5b8025589a From e68268cca7d2f75645a66376bd19f10e2fd486fb Mon Sep 17 00:00:00 2001 From: valzav Date: Fri, 25 Mar 2016 15:13:05 -0400 Subject: [PATCH 35/37] reverse prev. commit's fc upate --- libraries/fc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/fc b/libraries/fc index 622ff580..64950043 160000 --- a/libraries/fc +++ b/libraries/fc @@ -1 +1 @@ -Subproject commit 622ff58039f2388433272a44fe416f5b8025589a +Subproject commit 6495004302239ae0c775f05a0e78780c3b189502 From 7ce088471a228dcabd14139cd623189df89a0b23 Mon Sep 17 00:00:00 2001 From: valzav Date: Fri, 25 Mar 2016 15:46:31 -0400 Subject: [PATCH 36/37] Revert "reverse prev. commit's fc upate" This reverts commit e68268cca7d2f75645a66376bd19f10e2fd486fb. --- libraries/fc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/fc b/libraries/fc index 64950043..622ff580 160000 --- a/libraries/fc +++ b/libraries/fc @@ -1 +1 @@ -Subproject commit 6495004302239ae0c775f05a0e78780c3b189502 +Subproject commit 622ff58039f2388433272a44fe416f5b8025589a From c777a88649d50edf6c5e4a8c3b13dda88a66e9d0 Mon Sep 17 00:00:00 2001 From: theoreticalbts Date: Fri, 25 Mar 2016 01:43:46 -0400 Subject: [PATCH 37/37] Rebased "Fix iteration logic in _handle_message_calls_in_progress shutdown loop to handle concurrent modification #598" to fix revert #637 --- libraries/net/node.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/libraries/net/node.cpp b/libraries/net/node.cpp index db2369a0..6fb212c7 100644 --- a/libraries/net/node.cpp +++ b/libraries/net/node.cpp @@ -3952,12 +3952,20 @@ namespace graphene { namespace net { namespace detail { } unsigned handle_message_call_count = 0; - for (fc::future& handle_message_call : _handle_message_calls_in_progress) + while( true ) { + auto it = _handle_message_calls_in_progress.begin(); + if( it == _handle_message_calls_in_progress.end() ) + break; + if( it->ready() || it->error() || it->canceled() ) + { + _handle_message_calls_in_progress.erase( it ); + continue; + } ++handle_message_call_count; try { - handle_message_call.cancel_and_wait("node_impl::close()"); + it->cancel_and_wait("node_impl::close()"); dlog("handle_message call #${count} task terminated", ("count", handle_message_call_count)); } catch ( const fc::canceled_exception& ) @@ -3973,7 +3981,6 @@ namespace graphene { namespace net { namespace detail { wlog("Exception thrown while terminating handle_message call #${count} task, ignoring",("count", handle_message_call_count)); } } - _handle_message_calls_in_progress.clear(); try {