From 10a382fd0c0a53391ba71023aea0ba41c23caebd Mon Sep 17 00:00:00 2001 From: Alfredo Date: Fri, 19 Apr 2019 21:11:17 -0300 Subject: [PATCH 001/111] serve get_account_history with elasticsearch plugin --- libraries/app/CMakeLists.txt | 2 +- libraries/app/api.cpp | 4 + libraries/app/include/graphene/app/api.hpp | 2 + .../elasticsearch/elasticsearch_plugin.cpp | 152 +++++++- .../elasticsearch/elasticsearch_plugin.hpp | 11 + tests/common/database_fixture.cpp | 9 +- tests/elasticsearch/main.cpp | 324 +++++++++++++++++- 7 files changed, 495 insertions(+), 9 deletions(-) diff --git a/libraries/app/CMakeLists.txt b/libraries/app/CMakeLists.txt index bf4f5c2b00..1d1cb65f9b 100644 --- a/libraries/app/CMakeLists.txt +++ b/libraries/app/CMakeLists.txt @@ -13,7 +13,7 @@ add_library( graphene_app ) # need to link graphene_debug_witness because plugins aren't sufficiently isolated #246 -target_link_libraries( graphene_app graphene_market_history graphene_account_history graphene_grouped_orders graphene_chain fc graphene_db graphene_net graphene_utilities graphene_debug_witness ) +target_link_libraries( graphene_app graphene_market_history graphene_account_history graphene_elasticsearch graphene_grouped_orders graphene_chain fc graphene_db graphene_net 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 c2631b1293..f1a8b909f7 100644 --- a/libraries/app/api.cpp +++ b/libraries/app/api.cpp @@ -328,6 +328,10 @@ namespace graphene { namespace app { start = node.operation_id; } catch(...) { return result; } + auto es = _app.get_plugin("elasticsearch"); + if(es) + return es->get_account_history(account, stop, limit, start); + const auto& hist_idx = db.get_index_type(); const auto& by_op_idx = hist_idx.indices().get(); auto index_start = by_op_idx.begin(); diff --git a/libraries/app/include/graphene/app/api.hpp b/libraries/app/include/graphene/app/api.hpp index 484cde78c5..14193bcf42 100644 --- a/libraries/app/include/graphene/app/api.hpp +++ b/libraries/app/include/graphene/app/api.hpp @@ -32,6 +32,8 @@ #include +#include + #include #include diff --git a/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp b/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp index 0719fc06b4..d2e873b92c 100644 --- a/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp +++ b/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp @@ -26,7 +26,6 @@ #include #include #include -#include namespace graphene { namespace elasticsearch { @@ -59,6 +58,7 @@ class elasticsearch_plugin_impl std::string _elasticsearch_index_prefix = "bitshares-"; bool _elasticsearch_operation_object = false; uint32_t _elasticsearch_start_es_after_block = 0; + bool _elasticsearch_operation_string = true; CURL *curl; // curl handler vector bulk_lines; // vector of op lines vector prepare; @@ -223,9 +223,8 @@ void elasticsearch_plugin_impl::doOperationHistory(const optional op); - } void elasticsearch_plugin_impl::doBlock(uint32_t trx_in_block, const signed_block& b) @@ -436,6 +435,7 @@ void elasticsearch_plugin::plugin_set_program_options( ("elasticsearch-index-prefix", boost::program_options::value(), "Add a prefix to the index(bitshares-)") ("elasticsearch-operation-object", boost::program_options::value(), "Save operation as object(false)") ("elasticsearch-start-es-after-block", boost::program_options::value(), "Start doing ES job after block(0)") + ("elasticsearch-operation-string", boost::program_options::value(), "Save operation as string. Needed to serve history api calls(true)") ; cfg.add(cli); } @@ -473,7 +473,10 @@ void elasticsearch_plugin::plugin_initialize(const boost::program_options::varia } if (options.count("elasticsearch-start-es-after-block")) { my->_elasticsearch_start_es_after_block = options["elasticsearch-start-es-after-block"].as(); - } + } + if (options.count("elasticsearch-operation-string")) { + my->_elasticsearch_operation_string = options["elasticsearch-operation-string"].as(); + } } void elasticsearch_plugin::plugin_startup() @@ -488,4 +491,145 @@ void elasticsearch_plugin::plugin_startup() ilog("elasticsearch ACCOUNT HISTORY: plugin_startup() begin"); } +operation_history_object elasticsearch_plugin::get_operation_by_id(operation_history_id_type id) +{ + const string operation_id_string = idToString(id); + + const string query = R"( + { + "query": { + "bool": { + "must": [ + { + "query_string": { + "query": "account_history.operation_id: )" + operation_id_string + R"(" + } + }, + { + "range": { + "block_data.block_time": { + "gte": "now-20y", + "lte": "now" + } + } + } + ] + } + } + } + )"; + + auto es = prepareHistoryQuery(query); + const auto response = graphene::utilities::simpleQuery(es); + variant variant_response = fc::json::from_string(response); + const auto source = variant_response["hits"]["hits"][size_t(0)]["_source"]; + return fromEStoOperation(source); +} + +vector elasticsearch_plugin::get_account_history( + const account_id_type account_id, + operation_history_id_type stop = operation_history_id_type(), + unsigned limit = 100, + operation_history_id_type start = operation_history_id_type()) +{ + const string account_id_string = idToString(account_id); + + const auto stop_number = stop.instance.value; + const auto start_number = start.instance.value; + + string range = ""; + if(stop_number == 0) + range = " AND operation_id_num: ["+fc::to_string(stop_number)+" TO "+fc::to_string(start_number)+"]"; + else if(stop_number > 0) + range = " AND operation_id_num: {"+fc::to_string(stop_number)+" TO "+fc::to_string(start_number)+"]"; + + const string query = R"( + { + "size": )" + fc::to_string(limit) + R"(, + "sort" : [{ "operation_id_num" : {"order" : "desc"}}], + "query": { + "bool": { + "must": [ + { + "query_string": { + "query": "account_history.account: )" + account_id_string + range + R"(" + } + }, + { + "range": { + "block_data.block_time": { + "gte": "now-20y", + "lte": "now" + } + } + } + ] + } + } + } + )"; + + auto es = prepareHistoryQuery(query); + + vector result; + + if(!graphene::utilities::checkES(es)) + return result; + + const auto response = graphene::utilities::simpleQuery(es); + variant variant_response = fc::json::from_string(response); + + const auto hits = variant_response["hits"]["total"]; + const auto size = std::min(static_cast(hits.as_uint64()), limit); + + for(unsigned i=0; i +std::string elasticsearch_plugin::idToString(T id) +{ + return fc::to_string(id.space_id) + "." + fc::to_string(id.type_id) + "." + fc::to_string(id.instance.value); +} + +graphene::utilities::ES elasticsearch_plugin::prepareHistoryQuery(string query) +{ + CURL *curl; + curl = curl_easy_init(); + + graphene::utilities::ES es; + es.curl = curl; + es.elasticsearch_url = my->_elasticsearch_node_url; + es.index_prefix = my->_elasticsearch_index_prefix; + es.endpoint = es.index_prefix + "*/data/_search"; + es.query = query; + + return es; +} + } } diff --git a/libraries/plugins/elasticsearch/include/graphene/elasticsearch/elasticsearch_plugin.hpp b/libraries/plugins/elasticsearch/include/graphene/elasticsearch/elasticsearch_plugin.hpp index a5ee7417c7..d6ec1191aa 100644 --- a/libraries/plugins/elasticsearch/include/graphene/elasticsearch/elasticsearch_plugin.hpp +++ b/libraries/plugins/elasticsearch/include/graphene/elasticsearch/elasticsearch_plugin.hpp @@ -26,6 +26,7 @@ #include #include #include +#include namespace graphene { namespace elasticsearch { using namespace chain; @@ -63,8 +64,18 @@ class elasticsearch_plugin : public graphene::app::plugin virtual void plugin_initialize(const boost::program_options::variables_map& options) override; virtual void plugin_startup() override; + operation_history_object get_operation_by_id(operation_history_id_type id); + vector get_account_history(const account_id_type account_id, + operation_history_id_type stop, unsigned limit, operation_history_id_type start); + friend class detail::elasticsearch_plugin_impl; std::unique_ptr my; + + private: + operation_history_object fromEStoOperation(variant source); + template + std::string idToString(T id); + graphene::utilities::ES prepareHistoryQuery(string query); }; struct operation_visitor diff --git a/tests/common/database_fixture.cpp b/tests/common/database_fixture.cpp index af0e9513e5..9bb5691540 100644 --- a/tests/common/database_fixture.cpp +++ b/tests/common/database_fixture.cpp @@ -186,15 +186,18 @@ database_fixture::database_fixture(const fc::time_point_sec &initial_timestamp) boost::unit_test::framework::current_test_case().p_name.value == "track_votes_committee_disabled") { app.chain_database()->enable_standby_votes_tracking( false ); } - if(current_test_name == "elasticsearch_account_history" || current_test_name == "elasticsearch_suite") { + if(current_test_name == "elasticsearch_account_history" || current_test_name == "elasticsearch_suite" || + current_test_name == "elasticsearch_history_api") { auto esplugin = app.register_plugin(); esplugin->plugin_set_app(&app); options.insert(std::make_pair("elasticsearch-node-url", boost::program_options::variable_value(string("http://localhost:9200/"), false))); options.insert(std::make_pair("elasticsearch-bulk-replay", boost::program_options::variable_value(uint32_t(2), false))); options.insert(std::make_pair("elasticsearch-bulk-sync", boost::program_options::variable_value(uint32_t(2), false))); - options.insert(std::make_pair("elasticsearch-visitor", boost::program_options::variable_value(true, false))); - //options.insert(std::make_pair("elasticsearch-basic-auth", boost::program_options::variable_value(string("elastic:changeme"), false))); + options.insert(std::make_pair("elasticsearch-start-es-after-block", boost::program_options::variable_value(uint32_t(0), false))); + options.insert(std::make_pair("elasticsearch-visitor", boost::program_options::variable_value(false, false))); + options.insert(std::make_pair("elasticsearch-operation-object", boost::program_options::variable_value(true, false))); + options.insert(std::make_pair("elasticsearch-operation-string", boost::program_options::variable_value(true, false))); esplugin->plugin_initialize(options); esplugin->plugin_startup(); diff --git a/tests/elasticsearch/main.cpp b/tests/elasticsearch/main.cpp index 33f8b11db9..24eb9382e8 100644 --- a/tests/elasticsearch/main.cpp +++ b/tests/elasticsearch/main.cpp @@ -27,6 +27,7 @@ #include #include +#include #include "../common/database_fixture.hpp" @@ -118,7 +119,7 @@ BOOST_AUTO_TEST_CASE(elasticsearch_account_history) { es.endpoint = index_name + "/data/2.9.12"; // we know last op is a transfer of amount 300 res = graphene::utilities::getEndPoint(es); j = fc::json::from_string(res); - auto last_transfer_amount = j["_source"]["additional_data"]["transfer_data"]["amount"].as_string(); + auto last_transfer_amount = j["_source"]["operation_history"]["op_object"]["amount_"]["amount"].as_string(); BOOST_CHECK_EQUAL(last_transfer_amount, "300"); } } @@ -210,4 +211,325 @@ BOOST_AUTO_TEST_CASE(elasticsearch_suite) { } } +BOOST_AUTO_TEST_CASE(elasticsearch_history_api) { + try { + CURL *curl; // curl handler + curl = curl_easy_init(); + + graphene::utilities::ES es; + es.curl = curl; + es.elasticsearch_url = "http://localhost:9200/"; + es.index_prefix = "bitshares-"; + + auto delete_account_history = graphene::utilities::deleteAll(es); + + generate_block(); + fc::usleep(fc::milliseconds(1000)); + + if(delete_account_history) { + + create_bitasset("USD", account_id_type()); // create op 0 + const account_object& dan = create_account("dan"); // create op 1 + create_bitasset("CNY", dan.id); // create op 2 + create_bitasset("BTC", account_id_type()); // create op 3 + create_bitasset("XMR", dan.id); // create op 4 + create_bitasset("EUR", account_id_type()); // create op 5 + create_bitasset("OIL", dan.id); // create op 6 + + generate_block(); + fc::usleep(fc::milliseconds(1000)); + + graphene::app::history_api hist_api(app); + app.enable_plugin("elasticsearch"); + + // f(A, 0, 4, 9) = { 5, 3, 1, 0 } + auto histories = hist_api.get_account_history("1.2.0", operation_history_id_type(), 4, operation_history_id_type(9)); + + BOOST_CHECK_EQUAL(histories.size(), 4u); + BOOST_CHECK_EQUAL(histories[0].id.instance(), 5u); + BOOST_CHECK_EQUAL(histories[1].id.instance(), 3u); + BOOST_CHECK_EQUAL(histories[2].id.instance(), 1u); + BOOST_CHECK_EQUAL(histories[3].id.instance(), 0u); + + // f(A, 0, 4, 6) = { 5, 3, 1, 0 } + histories = hist_api.get_account_history("1.2.0", operation_history_id_type(), 4, operation_history_id_type(6)); + BOOST_CHECK_EQUAL(histories.size(), 4u); + BOOST_CHECK_EQUAL(histories[0].id.instance(), 5u); + BOOST_CHECK_EQUAL(histories[1].id.instance(), 3u); + BOOST_CHECK_EQUAL(histories[2].id.instance(), 1u); + BOOST_CHECK_EQUAL(histories[3].id.instance(), 0u); + + // f(A, 0, 4, 5) = { 5, 3, 1, 0 } + histories = hist_api.get_account_history("1.2.0", operation_history_id_type(), 4, operation_history_id_type(5)); + BOOST_CHECK_EQUAL(histories.size(), 4u); + BOOST_CHECK_EQUAL(histories[0].id.instance(), 5u); + BOOST_CHECK_EQUAL(histories[1].id.instance(), 3u); + BOOST_CHECK_EQUAL(histories[2].id.instance(), 1u); + BOOST_CHECK_EQUAL(histories[3].id.instance(), 0u); + + // f(A, 0, 4, 4) = { 3, 1, 0 } + histories = hist_api.get_account_history("1.2.0", operation_history_id_type(), 4, operation_history_id_type(4)); + BOOST_CHECK_EQUAL(histories.size(), 3u); + BOOST_CHECK_EQUAL(histories[0].id.instance(), 3u); + BOOST_CHECK_EQUAL(histories[1].id.instance(), 1u); + BOOST_CHECK_EQUAL(histories[2].id.instance(), 0u); + + // f(A, 0, 4, 3) = { 3, 1, 0 } + histories = hist_api.get_account_history("1.2.0", operation_history_id_type(), 4, operation_history_id_type(3)); + BOOST_CHECK_EQUAL(histories.size(), 3u); + BOOST_CHECK_EQUAL(histories[0].id.instance(), 3u); + BOOST_CHECK_EQUAL(histories[1].id.instance(), 1u); + BOOST_CHECK_EQUAL(histories[2].id.instance(), 0u); + + // f(A, 0, 4, 2) = { 1, 0 } + histories = hist_api.get_account_history("1.2.0", operation_history_id_type(), 4, operation_history_id_type(2)); + BOOST_CHECK_EQUAL(histories.size(), 2u); + BOOST_CHECK_EQUAL(histories[0].id.instance(), 1u); + BOOST_CHECK_EQUAL(histories[1].id.instance(), 0u); + + // f(A, 0, 4, 1) = { 1, 0 } + histories = hist_api.get_account_history("1.2.0", operation_history_id_type(), 4, operation_history_id_type(1)); + BOOST_CHECK_EQUAL(histories.size(), 2u); + BOOST_CHECK_EQUAL(histories[0].id.instance(), 1u); + BOOST_CHECK_EQUAL(histories[1].id.instance(), 0u); + + // f(A, 0, 4, 0) = { 5, 3, 1, 0 } + histories = hist_api.get_account_history("1.2.0", operation_history_id_type(), 4, operation_history_id_type()); + BOOST_CHECK_EQUAL(histories.size(), 4u); + BOOST_CHECK_EQUAL(histories[0].id.instance(), 5u); + BOOST_CHECK_EQUAL(histories[1].id.instance(), 3u); + BOOST_CHECK_EQUAL(histories[2].id.instance(), 1u); + BOOST_CHECK_EQUAL(histories[3].id.instance(), 0u); + + // f(A, 1, 5, 9) = { 5, 3 } + histories = hist_api.get_account_history("1.2.0", operation_history_id_type(1), 5, operation_history_id_type(9)); + BOOST_CHECK_EQUAL(histories.size(), 2u); + BOOST_CHECK_EQUAL(histories[0].id.instance(), 5u); + BOOST_CHECK_EQUAL(histories[1].id.instance(), 3u); + + // f(A, 1, 5, 6) = { 5, 3 } + histories = hist_api.get_account_history("1.2.0", operation_history_id_type(1), 5, operation_history_id_type(6)); + BOOST_CHECK_EQUAL(histories.size(), 2u); + BOOST_CHECK_EQUAL(histories[0].id.instance(), 5u); + BOOST_CHECK_EQUAL(histories[1].id.instance(), 3u); + + // f(A, 1, 5, 5) = { 5, 3 } + histories = hist_api.get_account_history("1.2.0", operation_history_id_type(1), 5, operation_history_id_type(5)); + BOOST_CHECK_EQUAL(histories.size(), 2u); + BOOST_CHECK_EQUAL(histories[0].id.instance(), 5u); + BOOST_CHECK_EQUAL(histories[1].id.instance(), 3u); + + // f(A, 1, 5, 4) = { 3 } + histories = hist_api.get_account_history("1.2.0", operation_history_id_type(1), 5, operation_history_id_type(4)); + BOOST_CHECK_EQUAL(histories.size(), 1u); + BOOST_CHECK_EQUAL(histories[0].id.instance(), 3u); + + // f(A, 1, 5, 3) = { 3 } + histories = hist_api.get_account_history("1.2.0", operation_history_id_type(1), 5, operation_history_id_type(3)); + BOOST_CHECK_EQUAL(histories.size(), 1u); + BOOST_CHECK_EQUAL(histories[0].id.instance(), 3u); + + // f(A, 1, 5, 2) = { } + histories = hist_api.get_account_history("1.2.0", operation_history_id_type(1), 5, operation_history_id_type(2)); + BOOST_CHECK_EQUAL(histories.size(), 0u); + + // f(A, 1, 5, 1) = { } + histories = hist_api.get_account_history("1.2.0", operation_history_id_type(1), 5, operation_history_id_type(1)); + BOOST_CHECK_EQUAL(histories.size(), 0u); + + // f(A, 1, 5, 0) = { 5, 3 } + histories = hist_api.get_account_history("1.2.0", operation_history_id_type(1), 5, operation_history_id_type(0)); + BOOST_CHECK_EQUAL(histories.size(), 2u); + BOOST_CHECK_EQUAL(histories[0].id.instance(), 5u); + BOOST_CHECK_EQUAL(histories[1].id.instance(), 3u); + + // f(A, 0, 3, 9) = { 5, 3, 1 } + histories = hist_api.get_account_history("1.2.0", operation_history_id_type(), 3, operation_history_id_type(9)); + BOOST_CHECK_EQUAL(histories.size(), 3u); + BOOST_CHECK_EQUAL(histories[0].id.instance(), 5u); + BOOST_CHECK_EQUAL(histories[1].id.instance(), 3u); + BOOST_CHECK_EQUAL(histories[2].id.instance(), 1u); + + // f(A, 0, 3, 6) = { 5, 3, 1 } + histories = hist_api.get_account_history("1.2.0", operation_history_id_type(), 3, operation_history_id_type(6)); + BOOST_CHECK_EQUAL(histories.size(), 3u); + BOOST_CHECK_EQUAL(histories[0].id.instance(), 5u); + BOOST_CHECK_EQUAL(histories[1].id.instance(), 3u); + BOOST_CHECK_EQUAL(histories[2].id.instance(), 1u); + + // f(A, 0, 3, 5) = { 5, 3, 1 } + histories = hist_api.get_account_history("1.2.0", operation_history_id_type(), 3, operation_history_id_type(5)); + BOOST_CHECK_EQUAL(histories.size(), 3u); + BOOST_CHECK_EQUAL(histories[0].id.instance(), 5u); + BOOST_CHECK_EQUAL(histories[1].id.instance(), 3u); + BOOST_CHECK_EQUAL(histories[2].id.instance(), 1u); + + // f(A, 0, 3, 4) = { 3, 1, 0 } + histories = hist_api.get_account_history("1.2.0", operation_history_id_type(), 3, operation_history_id_type(4)); + BOOST_CHECK_EQUAL(histories.size(), 3u); + BOOST_CHECK_EQUAL(histories[0].id.instance(), 3u); + BOOST_CHECK_EQUAL(histories[1].id.instance(), 1u); + BOOST_CHECK_EQUAL(histories[2].id.instance(), 0u); + + // f(A, 0, 3, 3) = { 3, 1, 0 } + histories = hist_api.get_account_history("1.2.0", operation_history_id_type(), 3, operation_history_id_type(3)); + BOOST_CHECK_EQUAL(histories.size(), 3u); + BOOST_CHECK_EQUAL(histories[0].id.instance(), 3u); + BOOST_CHECK_EQUAL(histories[1].id.instance(), 1u); + BOOST_CHECK_EQUAL(histories[2].id.instance(), 0u); + + // f(A, 0, 3, 2) = { 1, 0 } + histories = hist_api.get_account_history("1.2.0", operation_history_id_type(), 3, operation_history_id_type(2)); + BOOST_CHECK_EQUAL(histories.size(), 2u); + BOOST_CHECK_EQUAL(histories[0].id.instance(), 1u); + BOOST_CHECK_EQUAL(histories[1].id.instance(), 0u); + + // f(A, 0, 3, 1) = { 1, 0 } + histories = hist_api.get_account_history("1.2.0", operation_history_id_type(), 3, operation_history_id_type(1)); + BOOST_CHECK_EQUAL(histories.size(), 2u); + BOOST_CHECK_EQUAL(histories[0].id.instance(), 1u); + BOOST_CHECK_EQUAL(histories[1].id.instance(), 0u); + + // f(A, 0, 3, 0) = { 5, 3, 1 } + histories = hist_api.get_account_history("1.2.0", operation_history_id_type(), 3, operation_history_id_type()); + BOOST_CHECK_EQUAL(histories.size(), 3u); + BOOST_CHECK_EQUAL(histories[0].id.instance(), 5u); + BOOST_CHECK_EQUAL(histories[1].id.instance(), 3u); + BOOST_CHECK_EQUAL(histories[2].id.instance(), 1u); + + // f(B, 0, 4, 9) = { 6, 4, 2, 1 } + histories = hist_api.get_account_history("dan", operation_history_id_type(), 4, operation_history_id_type(9)); + BOOST_CHECK_EQUAL(histories.size(), 4u); + BOOST_CHECK_EQUAL(histories[0].id.instance(), 6u); + BOOST_CHECK_EQUAL(histories[1].id.instance(), 4u); + BOOST_CHECK_EQUAL(histories[2].id.instance(), 2u); + BOOST_CHECK_EQUAL(histories[3].id.instance(), 1u); + + // f(B, 0, 4, 6) = { 6, 4, 2, 1 } + histories = hist_api.get_account_history("dan", operation_history_id_type(), 4, operation_history_id_type(6)); + BOOST_CHECK_EQUAL(histories.size(), 4u); + BOOST_CHECK_EQUAL(histories[0].id.instance(), 6u); + BOOST_CHECK_EQUAL(histories[1].id.instance(), 4u); + BOOST_CHECK_EQUAL(histories[2].id.instance(), 2u); + BOOST_CHECK_EQUAL(histories[3].id.instance(), 1u); + + // f(B, 0, 4, 5) = { 4, 2, 1 } + histories = hist_api.get_account_history("dan", operation_history_id_type(), 4, operation_history_id_type(5)); + BOOST_CHECK_EQUAL(histories.size(), 3u); + BOOST_CHECK_EQUAL(histories[0].id.instance(), 4u); + BOOST_CHECK_EQUAL(histories[1].id.instance(), 2u); + BOOST_CHECK_EQUAL(histories[2].id.instance(), 1u); + + // f(B, 0, 4, 4) = { 4, 2, 1 } + histories = hist_api.get_account_history("dan", operation_history_id_type(), 4, operation_history_id_type(4)); + BOOST_CHECK_EQUAL(histories.size(), 3u); + BOOST_CHECK_EQUAL(histories[0].id.instance(), 4u); + BOOST_CHECK_EQUAL(histories[1].id.instance(), 2u); + BOOST_CHECK_EQUAL(histories[2].id.instance(), 1u); + + // f(B, 0, 4, 3) = { 2, 1 } + histories = hist_api.get_account_history("dan", operation_history_id_type(), 4, operation_history_id_type(3)); + BOOST_CHECK_EQUAL(histories.size(), 2u); + BOOST_CHECK_EQUAL(histories[0].id.instance(), 2u); + BOOST_CHECK_EQUAL(histories[1].id.instance(), 1u); + + // f(B, 0, 4, 2) = { 2, 1 } + histories = hist_api.get_account_history("dan", operation_history_id_type(), 4, operation_history_id_type(2)); + BOOST_CHECK_EQUAL(histories.size(), 2u); + BOOST_CHECK_EQUAL(histories[0].id.instance(), 2u); + BOOST_CHECK_EQUAL(histories[1].id.instance(), 1u); + + // f(B, 0, 4, 1) = { 1 } + histories = hist_api.get_account_history("dan", operation_history_id_type(), 4, operation_history_id_type(1)); + BOOST_CHECK_EQUAL(histories.size(), 1u); + BOOST_CHECK_EQUAL(histories[0].id.instance(), 1u); + + // f(B, 0, 4, 0) = { 6, 4, 2, 1 } + histories = hist_api.get_account_history("dan", operation_history_id_type(), 4, operation_history_id_type()); + BOOST_CHECK_EQUAL(histories.size(), 4u); + BOOST_CHECK_EQUAL(histories[0].id.instance(), 6u); + BOOST_CHECK_EQUAL(histories[1].id.instance(), 4u); + BOOST_CHECK_EQUAL(histories[2].id.instance(), 2u); + BOOST_CHECK_EQUAL(histories[3].id.instance(), 1u); + + // f(B, 2, 4, 9) = { 6, 4 } + histories = hist_api.get_account_history("dan", operation_history_id_type(2), 4, operation_history_id_type(9)); + BOOST_CHECK_EQUAL(histories.size(), 2u); + BOOST_CHECK_EQUAL(histories[0].id.instance(), 6u); + BOOST_CHECK_EQUAL(histories[1].id.instance(), 4u); + + // f(B, 2, 4, 6) = { 6, 4 } + histories = hist_api.get_account_history("dan", operation_history_id_type(2), 4, operation_history_id_type(6)); + BOOST_CHECK_EQUAL(histories.size(), 2u); + BOOST_CHECK_EQUAL(histories[0].id.instance(), 6u); + BOOST_CHECK_EQUAL(histories[1].id.instance(), 4u); + + // f(B, 2, 4, 5) = { 4 } + histories = hist_api.get_account_history("dan", operation_history_id_type(2), 4, operation_history_id_type(5)); + BOOST_CHECK_EQUAL(histories.size(), 1u); + BOOST_CHECK_EQUAL(histories[0].id.instance(), 4u); + + // f(B, 2, 4, 4) = { 4 } + histories = hist_api.get_account_history("dan", operation_history_id_type(2), 4, operation_history_id_type(4)); + BOOST_CHECK_EQUAL(histories.size(), 1u); + BOOST_CHECK_EQUAL(histories[0].id.instance(), 4u); + + // f(B, 2, 4, 3) = { } + histories = hist_api.get_account_history("dan", operation_history_id_type(2), 4, operation_history_id_type(3)); + BOOST_CHECK_EQUAL(histories.size(), 0u); + + // f(B, 2, 4, 2) = { } + histories = hist_api.get_account_history("dan", operation_history_id_type(2), 4, operation_history_id_type(2)); + BOOST_CHECK_EQUAL(histories.size(), 0u); + + // f(B, 2, 4, 1) = { } + histories = hist_api.get_account_history("dan", operation_history_id_type(2), 4, operation_history_id_type(1)); + BOOST_CHECK_EQUAL(histories.size(), 0u); + + // f(B, 2, 4, 0) = { 6, 4 } + histories = hist_api.get_account_history("dan", operation_history_id_type(2), 4, operation_history_id_type(0)); + BOOST_CHECK_EQUAL(histories.size(), 2u); + BOOST_CHECK_EQUAL(histories[0].id.instance(), 6u); + BOOST_CHECK_EQUAL(histories[1].id.instance(), 4u); + + // 0 limits + histories = hist_api.get_account_history("dan", operation_history_id_type(0), 0, operation_history_id_type(0)); + BOOST_CHECK_EQUAL(histories.size(), 0u); + histories = hist_api.get_account_history("1.2.0", operation_history_id_type(3), 0, operation_history_id_type(9)); + BOOST_CHECK_EQUAL(histories.size(), 0u); + + // non existent account + histories = hist_api.get_account_history("1.2.18", operation_history_id_type(0), 4, operation_history_id_type(0)); + BOOST_CHECK_EQUAL(histories.size(), 0u); + + // create a new account C = alice { 7 } + create_account("alice"); + + generate_block(); + fc::usleep(fc::milliseconds(1000)); + + // f(C, 0, 4, 10) = { 7 } + histories = hist_api.get_account_history("alice", operation_history_id_type(0), 4, operation_history_id_type(10)); + BOOST_CHECK_EQUAL(histories.size(), 1u); + BOOST_CHECK_EQUAL(histories[0].id.instance(), 7u); + + // f(C, 8, 4, 10) = { } + histories = hist_api.get_account_history("alice", operation_history_id_type(8), 4, operation_history_id_type(10)); + BOOST_CHECK_EQUAL(histories.size(), 0u); + + // f(A, 0, 10, 0) = { 7, 5, 3, 1, 0 } + histories = hist_api.get_account_history("1.2.0", operation_history_id_type(0), 10, operation_history_id_type(0)); + BOOST_CHECK_EQUAL(histories.size(), 5u); + BOOST_CHECK_EQUAL(histories[0].id.instance(), 7u); + BOOST_CHECK_EQUAL(histories[1].id.instance(), 5u); + BOOST_CHECK_EQUAL(histories[2].id.instance(), 3u); + BOOST_CHECK_EQUAL(histories[3].id.instance(), 1u); + BOOST_CHECK_EQUAL(histories[4].id.instance(), 0u); + } + } + catch (fc::exception &e) { + edump((e.to_detail_string())); + throw; + } +} BOOST_AUTO_TEST_SUITE_END() From 00496a96b4abf10c37704c9dff95e22500784ad9 Mon Sep 17 00:00:00 2001 From: Alfredo Date: Sat, 20 Apr 2019 10:32:12 -0300 Subject: [PATCH 002/111] replace IdToString --- .../plugins/elasticsearch/elasticsearch_plugin.cpp | 10 ++-------- .../graphene/elasticsearch/elasticsearch_plugin.hpp | 2 -- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp b/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp index d2e873b92c..9f3e70599a 100644 --- a/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp +++ b/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp @@ -493,7 +493,7 @@ void elasticsearch_plugin::plugin_startup() operation_history_object elasticsearch_plugin::get_operation_by_id(operation_history_id_type id) { - const string operation_id_string = idToString(id); + const string operation_id_string = std::string(object_id_type(id)); const string query = R"( { @@ -532,7 +532,7 @@ vector elasticsearch_plugin::get_account_history( unsigned limit = 100, operation_history_id_type start = operation_history_id_type()) { - const string account_id_string = idToString(account_id); + const string account_id_string = std::string(object_id_type(account_id)); const auto stop_number = stop.instance.value; const auto start_number = start.instance.value; @@ -611,12 +611,6 @@ operation_history_object elasticsearch_plugin::fromEStoOperation(variant source) return result; } -template -std::string elasticsearch_plugin::idToString(T id) -{ - return fc::to_string(id.space_id) + "." + fc::to_string(id.type_id) + "." + fc::to_string(id.instance.value); -} - graphene::utilities::ES elasticsearch_plugin::prepareHistoryQuery(string query) { CURL *curl; diff --git a/libraries/plugins/elasticsearch/include/graphene/elasticsearch/elasticsearch_plugin.hpp b/libraries/plugins/elasticsearch/include/graphene/elasticsearch/elasticsearch_plugin.hpp index d6ec1191aa..7cff0b73b8 100644 --- a/libraries/plugins/elasticsearch/include/graphene/elasticsearch/elasticsearch_plugin.hpp +++ b/libraries/plugins/elasticsearch/include/graphene/elasticsearch/elasticsearch_plugin.hpp @@ -73,8 +73,6 @@ class elasticsearch_plugin : public graphene::app::plugin private: operation_history_object fromEStoOperation(variant source); - template - std::string idToString(T id); graphene::utilities::ES prepareHistoryQuery(string query); }; From 9a53b354cfdab0ce8283962d2af92048747e21c8 Mon Sep 17 00:00:00 2001 From: crypto-ape <43807588+crypto-ape@users.noreply.github.com> Date: Mon, 24 Jun 2019 19:58:59 +0200 Subject: [PATCH 003/111] harden binaries through defensive compilation and linking --- CMakeLists.txt | 72 ++++++++++++++++++++++++++++++++++++++-- CMakeModules/Utils.cmake | 13 ++++++++ 2 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 CMakeModules/Utils.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 6052748601..91f4dd95d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ # Defines BitShares library target. -project( BitShares ) -cmake_minimum_required( VERSION 3.1 ) +cmake_minimum_required( VERSION 3.2 FATAL_ERROR ) +project( BitShares LANGUAGES CXX C) set( BLOCKCHAIN_NAME "BitShares" ) @@ -26,6 +26,74 @@ endif() list( APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules" ) +include(CheckCCompilerFlag) +include(Utils) + +# Fortify source +if (CMAKE_COMPILER_IS_GNUCXX) + if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + message ("-- Setting optimizations for clang++") + set(CMAKE_CXX_FLAGS_RELEASE "-D_FORTIFY_SOURCE=2 -O3 -DNDEBUG=1") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-D_FORTIFY_SOURCE=2 -O3 -DNDEBUG=1 -g") + + # check and add data execution prevention + message ("-- Enabling data execution prevention") + add_linker_flag("-fsanitize=safe-stack") + + # check and add Stack-based buffer overrun detection + set(CMAKE_REQUIRED_FLAGS "-fstack-protector") + check_c_compiler_flag("" HAVE_STACKPROTECTOR) + if(HAVE_STACKPROTECTOR) + message ("-- Enabling stack-based buffer overrun detection") + add_flag_append(CMAKE_C_FLAGS "-fstack-protector") + add_flag_append(CMAKE_CXX_FLAGS "-fstack-protector") + endif() + else () + message ("-- Setting optimizations for g++") + set(CMAKE_CXX_FLAGS_RELEASE "-D_FORTIFY_SOURCE=2 -O3 -DNDEBUG=1") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-D_FORTIFY_SOURCE=2 -O3 -DNDEBUG=1 -g") + + # check and add data execution prevention + set(CMAKE_REQUIRED_FLAGS "-Wl,-znoexecstack") + check_c_compiler_flag("" HAVE_NOEXECSTACK) + if(HAVE_NOEXECSTACK) + message ("-- Enabling data execution prevention") + add_linker_flag("-znoexecstack") + endif() + + # check and add Stack-based buffer overrun detection + set(CMAKE_REQUIRED_FLAGS "-fstack-protector-strong") + check_c_compiler_flag("" HAVE_STACKPROTECTOR) + if(HAVE_STACKPROTECTOR) + message ("-- Enabling stack-based buffer overrun detection") + add_flag_append(CMAKE_C_FLAGS "-fstack-protector-strong") + add_flag_append(CMAKE_CXX_FLAGS "-fstack-protector-strong") + endif() + + endif () +endif () + +# check for Data relocation and Protection (RELRO) +set(CMAKE_REQUIRED_FLAGS "-Wl,-zrelro,-znow") +check_c_compiler_flag("" HAVE_RELROFULL) +if(HAVE_RELROFULL) + message ("-- Enabling full data relocation and protection") + add_linker_flag("-zrelro") + add_linker_flag("-znow") +else() + #if full relro is not available, try partial relro + set(CMAKE_REQUIRED_FLAGS "-Wl,-zrelro") + check_c_compiler_flag("" HAVE_RELROPARTIAL) + if(HAVE_RELROPARTIAL) + message ("-- Enabling partial data relocation and protection") + add_linker_flag("-zrelro") + endif() +endif() + +# position independent executetable (PIE) +# position independent code (PIC) +add_definitions (-fPIC) + set(CMAKE_EXPORT_COMPILE_COMMANDS "ON") set(GRAPHENE_EGENESIS_JSON "${CMAKE_CURRENT_SOURCE_DIR}/libraries/egenesis/genesis.json" ) diff --git a/CMakeModules/Utils.cmake b/CMakeModules/Utils.cmake new file mode 100644 index 0000000000..4fdd6bb9f4 --- /dev/null +++ b/CMakeModules/Utils.cmake @@ -0,0 +1,13 @@ +macro(add_flag_append _VAR_NAME _FLAG) + set(${_VAR_NAME} "${${_VAR_NAME}} ${_FLAG}") +endmacro(add_flag_append _VAR_NAME _FLAG) + +macro(add_linker_flag _FLAG) + #executables + add_flag_append(CMAKE_C_LINK_FLAGS "-Wl,${_FLAG}") + add_flag_append(CMAKE_CXX_LINK_FLAGS "-Wl,${_FLAG}") + #libraries + add_flag_append(CMAKE_SHARED_LIBRARY_C_FLAGS "-Wl,${_FLAG}") + add_flag_append(CMAKE_SHARED_LIBRARY_CXX_FLAGS "-Wl,${_FLAG}") +endmacro(add_linker_flag _FLAG) + From b228820e04b7301de747e6999f1e58949ee95c1e Mon Sep 17 00:00:00 2001 From: crypto-ape <43807588+crypto-ape@users.noreply.github.com> Date: Mon, 24 Jun 2019 21:09:15 +0200 Subject: [PATCH 004/111] put seed nodes into separate file --- libraries/app/application.cpp | 20 +------------------- libraries/egenesis/seed-nodes.txt | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 19 deletions(-) create mode 100644 libraries/egenesis/seed-nodes.txt diff --git a/libraries/app/application.cpp b/libraries/app/application.cpp index cdb75f57fe..51d01628ce 100644 --- a/libraries/app/application.cpp +++ b/libraries/app/application.cpp @@ -165,25 +165,7 @@ void application_impl::reset_p2p_node(const fc::path& data_dir) { // https://bitsharestalk.org/index.php/topic,23715.0.html vector seeds = { - "seed01.liondani.com:1776", // liondani (GERMANY) - "104.236.144.84:1777", // puppies (USA) - "128.199.143.47:2015", // Harvey (Singapore) - "209.105.239.13:1776", // sahkan (USA) - "45.35.12.22:1776", // sahkan (USA) - "51.15.61.160:1776", // lafona (France) - "bts-seed1.abit-more.com:62015", // abit (China) - "node.blckchnd.com:4243", // blckchnd (Germany) - "seed.bitsharesdex.com:50696", // iHashFury (Europe) - "seed.bitsharesnodes.com:1776", // wackou (Netherlands) - "seed.blocktrades.us:1776", // BlockTrades (USA) - "seed.cubeconnex.com:1777", // cube (USA) - "seed.roelandp.nl:1776", // roelandp (Canada) - "seed04.bts-nodes.net:1776", // Thom (Australia) - "seed05.bts-nodes.net:1776", // Thom (USA) - "seed06.bts-nodes.net:1776", // Thom (USA) - "seed07.bts-nodes.net:1776", // Thom (Singapore) - "seed.bts.bangzi.info:55501", // Bangzi (Germany) - "seeds.bitshares.eu:1776" // pc (http://seeds.quisquis.de/bitshares.html) + #include "../egenesis/seed-nodes.txt" }; for( const string& endpoint_string : seeds ) { diff --git a/libraries/egenesis/seed-nodes.txt b/libraries/egenesis/seed-nodes.txt new file mode 100644 index 0000000000..a372b79e43 --- /dev/null +++ b/libraries/egenesis/seed-nodes.txt @@ -0,0 +1,15 @@ +// https://bitsharestalk.org/index.php/topic,23715.0.html +"seed01.liondani.com:1776", // liondani (GERMANY) +"209.105.239.13:1776", // sahkan (USA) +"45.35.12.22:1776", // sahkan (USA) +"bts.lafona.net:1776", // lafona (France) +"bts-seed1.abit-more.com:62015", // abit (China) +"node.blckchnd.com:4243", // blckchnd (Germany) +"seed.bitsharesdex.com:50696", // iHashFury (Europe) +"seed.roelandp.nl:1776", // roelandp (Canada) +"seed04.bts-nodes.net:1776", // Thom (Australia) +"seed05.bts-nodes.net:1776", // Thom (USA) +"seed06.bts-nodes.net:1776", // Thom (USA) +"seed07.bts-nodes.net:1776", // Thom (Singapore) +"seed.bts.bangzi.info:55501", // Bangzi (Germany) +"seeds.bitshares.eu:1776", // pc (http://seeds.quisquis.de/bitshares.html) From 649709f5db0bbeab2da6f14033b489625e29372b Mon Sep 17 00:00:00 2001 From: crypto-ape <43807588+crypto-ape@users.noreply.github.com> Date: Wed, 26 Jun 2019 12:21:03 +0200 Subject: [PATCH 005/111] small refactor of cli_wallet to get rid of transaction expiration constant duplicities --- libraries/wallet/wallet.cpp | 49 ++----------------------------------- 1 file changed, 2 insertions(+), 47 deletions(-) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index a2783a8584..2f964bb811 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -1159,35 +1159,11 @@ class wallet_api_impl account_create_op.options.memo_key = active; signed_transaction tx; - tx.operations.push_back( account_create_op ); - set_operation_fees( tx, _remote_db->get_global_properties().parameters.get_current_fees() ); - - vector paying_keys = registrar_account_object.active.get_keys(); - - auto dyn_props = get_dynamic_global_properties(); - tx.set_reference_block( dyn_props.head_block_id ); - tx.set_expiration( dyn_props.time + fc::seconds(30) ); tx.validate(); - for( public_key_type& key : paying_keys ) - { - auto it = _keys.find(key); - if( it != _keys.end() ) - { - fc::optional< fc::ecc::private_key > privkey = wif_to_key( it->second ); - if( !privkey.valid() ) - { - FC_ASSERT( false, "Malformed private key in _keys" ); - } - tx.sign( *privkey, _chain_id ); - } - } - - if( broadcast ) - _remote_net_broadcast->broadcast_transaction( tx ); - return tx; + return sign_transaction(tx, broadcast); } FC_CAPTURE_AND_RETHROW( (name)(owner)(active)(registrar_account) (referrer_account)(referrer_percent)(broadcast) ) } @@ -1284,38 +1260,17 @@ class wallet_api_impl // account_create_op.fee = account_create_op.calculate_fee(db.current_fee_schedule()); signed_transaction tx; - tx.operations.push_back( account_create_op ); - set_operation_fees( tx, _remote_db->get_global_properties().parameters.get_current_fees()); - - vector paying_keys = registrar_account_object.active.get_keys(); - - auto dyn_props = get_dynamic_global_properties(); - tx.set_reference_block( dyn_props.head_block_id ); - tx.set_expiration( dyn_props.time + fc::seconds(30) ); tx.validate(); - for( public_key_type& key : paying_keys ) - { - auto it = _keys.find(key); - if( it != _keys.end() ) - { - fc::optional< fc::ecc::private_key > privkey = wif_to_key( it->second ); - FC_ASSERT( privkey.valid(), "Malformed private key in _keys" ); - tx.sign( *privkey, _chain_id ); - } - } - // we do not insert owner_privkey here because // it is intended to only be used for key recovery _wallet.pending_account_registrations[account_name].push_back(key_to_wif( active_privkey )); _wallet.pending_account_registrations[account_name].push_back(key_to_wif( memo_privkey )); if( save_wallet ) save_wallet_file(); - if( broadcast ) - _remote_net_broadcast->broadcast_transaction( tx ); - return tx; + return sign_transaction(tx, broadcast); } FC_CAPTURE_AND_RETHROW( (account_name)(registrar_account)(referrer_account)(broadcast) ) } signed_transaction create_account_with_brain_key(string brain_key, From c2960fff5d2557cf2e064aa66de997a5889c2b6f Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Wed, 26 Jun 2019 15:23:07 +0200 Subject: [PATCH 006/111] Moved undo_point forward to MAX_UNDO_HISTORY --- libraries/chain/db_management.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libraries/chain/db_management.cpp b/libraries/chain/db_management.cpp index 3a8f038f52..9ca657ef6f 100644 --- a/libraries/chain/db_management.cpp +++ b/libraries/chain/db_management.cpp @@ -65,8 +65,7 @@ void database::reindex( fc::path data_dir ) ilog( "reindexing blockchain" ); auto start = fc::time_point::now(); const auto last_block_num = last_block->block_num(); - uint32_t flush_point = last_block_num < 10000 ? 0 : last_block_num - 10000; - uint32_t undo_point = last_block_num < 50 ? 0 : last_block_num - 50; + uint32_t undo_point = last_block_num < GRAPHENE_MAX_UNDO_HISTORY ? 0 : last_block_num - GRAPHENE_MAX_UNDO_HISTORY; ilog( "Replaying blocks, starting at ${next}...", ("next",head_block_num() + 1) ); if( head_block_num() >= undo_point ) @@ -138,7 +137,7 @@ void database::reindex( fc::path data_dir ) ("last", last_block_num) ); } - if( i == flush_point ) + if( i == undo_point ) { ilog( "Writing database to disk at block ${i}", ("i",i) ); flush(); From 50884966b9ea8af88c51e853017377cee7f915d0 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Wed, 26 Jun 2019 19:36:43 -0300 Subject: [PATCH 007/111] add htlc parameters to developer genesis --- libraries/egenesis/genesis-dev.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libraries/egenesis/genesis-dev.json b/libraries/egenesis/genesis-dev.json index 7d6f03a46c..dcc2cdd913 100644 --- a/libraries/egenesis/genesis-dev.json +++ b/libraries/egenesis/genesis-dev.json @@ -237,7 +237,12 @@ "accounts_per_fee_scale": 1000, "account_fee_scale_bitshifts": 4, "max_authority_depth": 2, - "extensions": [] + "extensions": { + "updatable_htlc_options": { + "max_timeout_secs": 2592000, + "max_preimage_size": 1024000 + } + } }, "initial_accounts": [{ "name": "init0", From a905a78df842156d4b04347c65a90cb1b2fad572 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Thu, 27 Jun 2019 13:13:34 +0200 Subject: [PATCH 008/111] Initial implementation of secondary index plugin --- libraries/plugins/CMakeLists.txt | 1 + .../plugins/api_helper_indexes/CMakeLists.txt | 22 +++ .../api_helper_indexes/api_helper_indexes.cpp | 125 ++++++++++++++++++ .../api_helper_indexes/api_helper_indexes.hpp | 75 +++++++++++ programs/witness_node/CMakeLists.txt | 4 +- programs/witness_node/main.cpp | 2 + 6 files changed, 228 insertions(+), 1 deletion(-) create mode 100644 libraries/plugins/api_helper_indexes/CMakeLists.txt create mode 100644 libraries/plugins/api_helper_indexes/api_helper_indexes.cpp create mode 100644 libraries/plugins/api_helper_indexes/include/graphene/api_helper_indexes/api_helper_indexes.hpp diff --git a/libraries/plugins/CMakeLists.txt b/libraries/plugins/CMakeLists.txt index caacb8bd53..412b185e08 100644 --- a/libraries/plugins/CMakeLists.txt +++ b/libraries/plugins/CMakeLists.txt @@ -7,3 +7,4 @@ add_subdirectory( delayed_node ) add_subdirectory( debug_witness ) add_subdirectory( snapshot ) add_subdirectory( es_objects ) +add_subdirectory( api_helper_indexes ) diff --git a/libraries/plugins/api_helper_indexes/CMakeLists.txt b/libraries/plugins/api_helper_indexes/CMakeLists.txt new file mode 100644 index 0000000000..26c1f16699 --- /dev/null +++ b/libraries/plugins/api_helper_indexes/CMakeLists.txt @@ -0,0 +1,22 @@ +file(GLOB HEADERS "include/graphene/api_helper_indexes/*.hpp") + +add_library( graphene_api_helper_indexes + api_helper_indexes.cpp + ) + +target_link_libraries( graphene_api_helper_indexes graphene_chain graphene_app ) +target_include_directories( graphene_api_helper_indexes + PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" ) + +if(MSVC) + set_source_files_properties(api_helper_indexes.cpp PROPERTIES COMPILE_FLAGS "/bigobj" ) +endif(MSVC) + +install( TARGETS + graphene_api_helper_indexes + + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib +) +INSTALL( FILES ${HEADERS} DESTINATION "include/graphene/api_helper_indexes" ) diff --git a/libraries/plugins/api_helper_indexes/api_helper_indexes.cpp b/libraries/plugins/api_helper_indexes/api_helper_indexes.cpp new file mode 100644 index 0000000000..eabff46718 --- /dev/null +++ b/libraries/plugins/api_helper_indexes/api_helper_indexes.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2018 api_helper_indexes 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 + +namespace graphene { namespace api_helper_indexes { + +void amount_in_collateral_index::object_inserted( const object& objct ) +{ try { + const call_order_object& o = static_cast( objct ); + auto itr = amounts.find( o.collateral_type() ); + if( itr == amounts.end() ) + amounts[o.collateral_type()] = o.collateral; + else + itr->second += o.collateral; +} FC_CAPTURE_AND_RETHROW( (objct) ); } + +void amount_in_collateral_index::object_removed( const object& objct ) +{ try { + const call_order_object& o = static_cast( objct ); + auto itr = amounts.find( o.collateral_type() ); + if( itr == amounts.end() ) return; // should never happen + itr->second -= o.collateral; +} FC_CAPTURE_AND_RETHROW( (objct) ); } + +void amount_in_collateral_index::about_to_modify( const object& objct ) +{ try { + object_removed( objct ); +} FC_CAPTURE_AND_RETHROW( (objct) ); } + +void amount_in_collateral_index::object_modified( const object& objct ) +{ try { + object_inserted( objct ); +} FC_CAPTURE_AND_RETHROW( (objct) ); } + +share_type amount_in_collateral_index::get_amount_in_collateral( const asset_id_type& asset )const +{ try { + auto itr = amounts.find( asset ); + if( itr == amounts.end() ) return 0; + return itr->second; +} FC_CAPTURE_AND_RETHROW( (asset) ); } + +namespace detail +{ + +class api_helper_indexes_impl +{ + public: + api_helper_indexes_impl(api_helper_indexes& _plugin) + : _self( _plugin ) + { } + + graphene::chain::database& database() + { + return _self.database(); + } + + api_helper_indexes& _self; + + private: + +}; + +} // end namespace detail + +api_helper_indexes::api_helper_indexes() : + my( new detail::api_helper_indexes_impl(*this) ) +{ +} + +api_helper_indexes::~api_helper_indexes() +{ +} + +std::string api_helper_indexes::plugin_name()const +{ + return "api_helper_indexes"; +} +std::string api_helper_indexes::plugin_description()const +{ + return "Provides some helper indexes used by various API calls"; +} + +void api_helper_indexes::plugin_set_program_options( + boost::program_options::options_description& cli, + boost::program_options::options_description& cfg + ) +{ +} + +void api_helper_indexes::plugin_initialize(const boost::program_options::variables_map& options) +{ +} + +void api_helper_indexes::plugin_startup() +{ + ilog("api_helper_indexes: plugin_startup() begin"); + amount_in_collateral = database().add_secondary_index< primary_index, amount_in_collateral_index >(); + for( const auto& call : database().get_index_type().indices() ) + amount_in_collateral->object_inserted( call ); +} + +} } diff --git a/libraries/plugins/api_helper_indexes/include/graphene/api_helper_indexes/api_helper_indexes.hpp b/libraries/plugins/api_helper_indexes/include/graphene/api_helper_indexes/api_helper_indexes.hpp new file mode 100644 index 0000000000..69d6a96456 --- /dev/null +++ b/libraries/plugins/api_helper_indexes/include/graphene/api_helper_indexes/api_helper_indexes.hpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018 api_helper_indexes 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 + +namespace graphene { namespace api_helper_indexes { +using namespace chain; + +/** + * @brief This secondary index tracks how much of each asset is locked up as collateral for MPAs. + */ +class amount_in_collateral_index : public secondary_index +{ + public: + virtual void object_inserted( const object& obj ) override; + virtual void object_removed( const object& obj ) override; + virtual void about_to_modify( const object& before ) override; + virtual void object_modified( const object& after ) override; + + share_type get_amount_in_collateral( const asset_id_type& asset )const; + + private: + flat_map amounts; +}; + +namespace detail +{ + class api_helper_indexes_impl; +} + +class api_helper_indexes : public graphene::app::plugin +{ + public: + api_helper_indexes(); + virtual ~api_helper_indexes(); + + std::string plugin_name()const override; + std::string plugin_description()const override; + virtual void plugin_set_program_options( + boost::program_options::options_description& cli, + boost::program_options::options_description& cfg) override; + virtual void plugin_initialize(const boost::program_options::variables_map& options) override; + virtual void plugin_startup() override; + + friend class detail::api_helper_indexes_impl; + std::unique_ptr my; + + private: + amount_in_collateral_index* amount_in_collateral = nullptr; +}; + +} } //graphene::template diff --git a/programs/witness_node/CMakeLists.txt b/programs/witness_node/CMakeLists.txt index 4815879a40..d671a93c17 100644 --- a/programs/witness_node/CMakeLists.txt +++ b/programs/witness_node/CMakeLists.txt @@ -12,7 +12,9 @@ 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_delayed_node graphene_account_history graphene_elasticsearch graphene_market_history graphene_grouped_orders graphene_witness graphene_chain graphene_debug_witness graphene_egenesis_full graphene_snapshot graphene_es_objects fc ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} ) +PRIVATE graphene_app graphene_delayed_node graphene_account_history graphene_elasticsearch graphene_market_history graphene_grouped_orders graphene_witness graphene_chain graphene_debug_witness graphene_egenesis_full graphene_snapshot graphene_es_objects + graphene_api_helper_indexes + fc ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} ) install( TARGETS witness_node diff --git a/programs/witness_node/main.cpp b/programs/witness_node/main.cpp index c4748697c6..016e53f2e2 100644 --- a/programs/witness_node/main.cpp +++ b/programs/witness_node/main.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -90,6 +91,7 @@ int main(int argc, char** argv) { auto snapshot_plug = node->register_plugin(); auto es_objects_plug = node->register_plugin(); auto grouped_orders_plug = node->register_plugin(); + auto api_helper_indexes_plug = node->register_plugin(); // add plugin options to config try From 42775b4814f4314714bce76149a858269ecc77e5 Mon Sep 17 00:00:00 2001 From: Alexey Frolov Date: Fri, 28 Jun 2019 19:19:06 +0300 Subject: [PATCH 009/111] Committee and witnesses initialization in genesis --- tests/common/database_fixture.cpp | 43 +++++++++++ tests/common/database_fixture.hpp | 4 + tests/tests/bitasset_tests.cpp | 2 +- tests/tests/block_tests.cpp | 25 ++++-- tests/tests/operation_tests.cpp | 2 +- tests/tests/smartcoin_tests.cpp | 15 ++-- tests/tests/voting_tests.cpp | 123 ++++++++++++++++++++---------- 7 files changed, 158 insertions(+), 56 deletions(-) diff --git a/tests/common/database_fixture.cpp b/tests/common/database_fixture.cpp index 0760f68bc2..afbc50c4e9 100644 --- a/tests/common/database_fixture.cpp +++ b/tests/common/database_fixture.cpp @@ -91,6 +91,9 @@ database_fixture::database_fixture(const fc::time_point_sec &initial_timestamp) else genesis_state.initial_active_witnesses = 10; + genesis_state.immutable_parameters.min_committee_member_count = INITIAL_COMMITTEE_MEMBER_COUNT; + genesis_state.immutable_parameters.min_witness_count = INITIAL_WITNESS_COUNT; + for( unsigned int i = 0; i < genesis_state.initial_active_witnesses; ++i ) { auto name = "init"+fc::to_string(i); @@ -310,6 +313,46 @@ database_fixture::~database_fixture() } } +void database_fixture::vote_for_committee_and_witnesses(uint16_t num_committee, uint16_t num_witness) +{ try { + + auto &init0 = get_account("init0"); + fund(init0, asset(10)); + + flat_set votes; + + const auto& wits = db.get_index_type().indices().get(); + num_witness = std::min(num_witness, (uint16_t) wits.size()); + auto wit_end = wits.begin(); + std::advance(wit_end, num_witness); + std::transform(wits.begin(), wit_end, + std::inserter(votes, votes.end()), + [](const witness_object& w) { return w.vote_id; }); + + const auto& comms = db.get_index_type().indices().get(); + num_committee = std::min(num_committee, (uint16_t) comms.size()); + auto comm_end = comms.begin(); + std::advance(comm_end, num_committee); + std::transform(comms.begin(), comm_end, + std::inserter(votes, votes.end()), + [](const committee_member_object& cm) { return cm.vote_id; }); + + account_update_operation op; + op.account = init0.get_id(); + op.new_options = init0.options; + op.new_options->votes = votes; + op.new_options->num_witness = num_witness; + op.new_options->num_committee = num_committee; + + op.fee = db.current_fee_schedule().calculate_fee( op ); + + trx.operations.push_back(op); + trx.validate(); + PUSH_TX(db, trx, ~0); + trx.operations.clear(); + +} FC_CAPTURE_AND_RETHROW() } + fc::ecc::private_key database_fixture::generate_private_key(string seed) { static const fc::ecc::private_key committee = fc::ecc::private_key::regenerate(fc::sha256::hash(string("null_key"))); diff --git a/tests/common/database_fixture.hpp b/tests/common/database_fixture.hpp index bf764f45f6..5368ce018b 100644 --- a/tests/common/database_fixture.hpp +++ b/tests/common/database_fixture.hpp @@ -171,6 +171,9 @@ extern uint32_t GRAPHENE_TESTING_GENESIS_TIMESTAMP; #define ACTORS_IMPL(r, data, elem) ACTOR(elem) #define ACTORS(names) BOOST_PP_SEQ_FOR_EACH(ACTORS_IMPL, ~, names) +#define INITIAL_WITNESS_COUNT (9u) +#define INITIAL_COMMITTEE_MEMBER_COUNT INITIAL_WITNESS_COUNT + namespace graphene { namespace chain { class clearable_block : public signed_block { @@ -205,6 +208,7 @@ struct database_fixture { string generate_anon_acct_name(); static void verify_asset_supplies( const database& db ); void open_database(); + void vote_for_committee_and_witnesses(uint16_t num_committee, uint16_t num_witness); signed_block generate_block(uint32_t skip = ~0, const fc::ecc::private_key& key = generate_private_key("null_key"), int miss_blocks = 0); diff --git a/tests/tests/bitasset_tests.cpp b/tests/tests/bitasset_tests.cpp index 03062fbe6e..62bc8b943d 100644 --- a/tests/tests/bitasset_tests.cpp +++ b/tests/tests/bitasset_tests.cpp @@ -192,7 +192,7 @@ BOOST_AUTO_TEST_CASE( reset_backing_asset_on_witness_asset ) std::vector active_witnesses; for(const witness_id_type& wit_id : global_props.active_witnesses) active_witnesses.push_back(wit_id(db).witness_account); - BOOST_REQUIRE_EQUAL(active_witnesses.size(), 10lu); + BOOST_REQUIRE_EQUAL(active_witnesses.size(), INITIAL_WITNESS_COUNT); { BOOST_TEST_MESSAGE("Adding price feed 1"); diff --git a/tests/tests/block_tests.cpp b/tests/tests/block_tests.cpp index 9b336eb2d5..22ba8c45ab 100644 --- a/tests/tests/block_tests.cpp +++ b/tests/tests/block_tests.cpp @@ -52,6 +52,9 @@ genesis_state_type make_genesis() { auto init_account_priv_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("null_key"))); genesis_state.initial_active_witnesses = 10; + genesis_state.immutable_parameters.min_committee_member_count = INITIAL_COMMITTEE_MEMBER_COUNT; + genesis_state.immutable_parameters.min_witness_count = INITIAL_WITNESS_COUNT; + for( unsigned int i = 0; i < genesis_state.initial_active_witnesses; ++i ) { auto name = "init"+fc::to_string(i); @@ -1418,25 +1421,33 @@ BOOST_AUTO_TEST_CASE( genesis_reserve_ids ) BOOST_FIXTURE_TEST_CASE( miss_some_blocks, database_fixture ) { try { + // Witnesses scheduled incorrectly in genesis block - reschedule + generate_blocks( witness_schedule_id_type()(db).current_shuffled_witnesses.size() ); + generate_blocks( db.get_dynamic_global_properties().next_maintenance_time ); + std::vector witnesses = witness_schedule_id_type()(db).current_shuffled_witnesses; - BOOST_CHECK_EQUAL( 10u, witnesses.size() ); + BOOST_CHECK_EQUAL( INITIAL_WITNESS_COUNT, witnesses.size() ); // database_fixture constructor calls generate_block once, signed by witnesses[0] generate_block(); // witnesses[1] generate_block(); // witnesses[2] for( const auto& id : witnesses ) BOOST_CHECK_EQUAL( 0, id(db).total_missed ); // generate_blocks generates another block *now* (witnesses[3]) - // and one at now+10 blocks (witnesses[12%10]) - generate_blocks( db.head_block_time() + db.get_global_properties().parameters.block_interval * 10, true ); - // i. e. 8 blocks are missed in between by witness[4..11%10] + // and one at now+9 blocks (witnesses[12%9]) + generate_blocks( db.head_block_time() + db.get_global_properties().parameters.block_interval * 9, true ); + // i. e. 7 blocks are missed in between by witness[4..11%9] for( uint32_t i = 0; i < witnesses.size(); i++ ) - BOOST_CHECK_EQUAL( (i+7) % 10 < 2 ? 0 : 1, witnesses[i](db).total_missed ); + BOOST_CHECK_EQUAL( (i+6) % 9 < 2 ? 0 : 1, witnesses[i](db).total_missed ); } FC_LOG_AND_RETHROW() } BOOST_FIXTURE_TEST_CASE( miss_many_blocks, database_fixture ) { try { + // Witnesses scheduled incorrectly in genesis block - reschedule + generate_blocks( witness_schedule_id_type()(db).current_shuffled_witnesses.size() ); + generate_blocks( db.get_dynamic_global_properties().next_maintenance_time ); + auto get_misses = []( database& db ) { std::map< witness_id_type, uint32_t > misses; for( const auto& witness_id : witness_schedule_id_type()(db).current_shuffled_witnesses ) @@ -1447,8 +1458,8 @@ BOOST_FIXTURE_TEST_CASE( miss_many_blocks, database_fixture ) generate_block(); generate_block(); auto missed_before = get_misses( db ); - // miss 10 maintenance intervals - generate_blocks( db.get_dynamic_global_properties().next_maintenance_time + db.get_global_properties().parameters.maintenance_interval * 10, true ); + // miss 9 maintenance intervals + generate_blocks( db.get_dynamic_global_properties().next_maintenance_time + db.get_global_properties().parameters.maintenance_interval * 9, true ); generate_block(); generate_block(); generate_block(); diff --git a/tests/tests/operation_tests.cpp b/tests/tests/operation_tests.cpp index ce5255f4e8..f5deed6ddd 100644 --- a/tests/tests/operation_tests.cpp +++ b/tests/tests/operation_tests.cpp @@ -1705,7 +1705,7 @@ BOOST_AUTO_TEST_CASE( witness_feeds ) vector active_witnesses; for( const witness_id_type& wit_id : global_props.active_witnesses ) active_witnesses.push_back( wit_id(db).witness_account ); - BOOST_REQUIRE_EQUAL(active_witnesses.size(), 10u); + BOOST_REQUIRE_EQUAL(active_witnesses.size(), INITIAL_WITNESS_COUNT); asset_publish_feed_operation op; op.publisher = active_witnesses[0]; diff --git a/tests/tests/smartcoin_tests.cpp b/tests/tests/smartcoin_tests.cpp index 9610e456ab..7d69caaa05 100644 --- a/tests/tests/smartcoin_tests.cpp +++ b/tests/tests/smartcoin_tests.cpp @@ -132,7 +132,7 @@ BOOST_AUTO_TEST_CASE(bsip36) // Check current default witnesses, default chain is configured with 10 witnesses auto witnesses = db.get_global_properties().active_witnesses; - BOOST_CHECK_EQUAL(witnesses.size(), 10u); + BOOST_CHECK_EQUAL(witnesses.size(), INITIAL_WITNESS_COUNT); BOOST_CHECK_EQUAL(witnesses.begin()[0].instance.value, 1u); BOOST_CHECK_EQUAL(witnesses.begin()[1].instance.value, 2u); BOOST_CHECK_EQUAL(witnesses.begin()[2].instance.value, 3u); @@ -142,13 +142,18 @@ BOOST_AUTO_TEST_CASE(bsip36) BOOST_CHECK_EQUAL(witnesses.begin()[6].instance.value, 7u); BOOST_CHECK_EQUAL(witnesses.begin()[7].instance.value, 8u); BOOST_CHECK_EQUAL(witnesses.begin()[8].instance.value, 9u); - BOOST_CHECK_EQUAL(witnesses.begin()[9].instance.value, 10u); // We need to activate 11 witnesses by voting for each of them. // Each witness is voted with incremental stake so last witness created will be the ones with more votes + + // by default we have 9 witnesses, we need to vote for desired witness count (11) to increase them + vote_for_committee_and_witnesses(9, 11); + int c = 0; for (auto l : witness_map) { - int stake = 100 + c + 1; + // voting stake have step of 100 + // so vote_for_committee_and_witnesses() with stake=10 does not affect the expected result + int stake = 100 * (c + 1); transfer(committee_account, l.first, asset(stake)); { account_update_operation op; @@ -206,7 +211,7 @@ BOOST_AUTO_TEST_CASE(bsip36) BOOST_CHECK_EQUAL(itr[1].first.instance.value, 17u); // Activate witness11 with voting stake, will kick the witness with less votes(witness0) out of the active list - transfer(committee_account, witness11_id, asset(121)); + transfer(committee_account, witness11_id, asset(1200)); set_expiration(db, trx); { account_update_operation op; @@ -328,7 +333,7 @@ BOOST_AUTO_TEST_CASE(bsip36) BOOST_CHECK_EQUAL(itr[0].first.instance.value, 17u); // Reactivate witness0 - transfer(committee_account, witness0_id, asset(100)); + transfer(committee_account, witness0_id, asset(1000)); set_expiration(db, trx); { account_update_operation op; diff --git a/tests/tests/voting_tests.cpp b/tests/tests/voting_tests.cpp index df92ccf061..1d61c65bc9 100644 --- a/tests/tests/voting_tests.cpp +++ b/tests/tests/voting_tests.cpp @@ -26,6 +26,7 @@ #include #include +#include #include @@ -37,12 +38,53 @@ using namespace graphene::chain::test; BOOST_FIXTURE_TEST_SUITE(voting_tests, database_fixture) +BOOST_FIXTURE_TEST_CASE( committee_account_initialization_test, database_fixture ) +{ try { + // Check current default committee + // By default chain is configured with INITIAL_COMMITTEE_MEMBER_COUNT=9 members + const auto &committee_members = db.get_global_properties().active_committee_members; + const auto &committee = committee_account(db); + + BOOST_CHECK_EQUAL(committee_members.size(), INITIAL_COMMITTEE_MEMBER_COUNT); + BOOST_CHECK_EQUAL(committee.active.num_auths(), INITIAL_COMMITTEE_MEMBER_COUNT); + + generate_blocks(HARDFORK_533_TIME); + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + generate_block(); + set_expiration(db, trx); + + // Check that committee not changed after 533 hardfork + // vote counting method changed, but any votes are absent + const auto &committee_members_after_hf533 = db.get_global_properties().active_committee_members; + const auto &committee_after_hf533 = committee_account(db); + BOOST_CHECK_EQUAL(committee_members_after_hf533.size(), INITIAL_COMMITTEE_MEMBER_COUNT); + BOOST_CHECK_EQUAL(committee_after_hf533.active.num_auths(), INITIAL_COMMITTEE_MEMBER_COUNT); + + // You can't use uninitialized committee after 533 hardfork + // when any user with stake created (create_account method automatically set up votes for committee) + // committee is incomplete and consist of random active members + ACTOR(alice); + fund(alice); + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + + const auto &committee_after_hf533_with_stake = committee_account(db); + BOOST_CHECK_LT(committee_after_hf533_with_stake.active.num_auths(), INITIAL_COMMITTEE_MEMBER_COUNT); + + // Initialize committee by voting for each memeber and for desired count + vote_for_committee_and_witnesses(INITIAL_COMMITTEE_MEMBER_COUNT, INITIAL_WITNESS_COUNT); + generate_blocks(db.get_dynamic_global_properties().next_maintenance_time); + + const auto &committee_members_after_hf533_and_init = db.get_global_properties().active_committee_members; + const auto &committee_after_hf533_and_init = committee_account(db); + BOOST_CHECK_EQUAL(committee_members_after_hf533_and_init.size(), INITIAL_COMMITTEE_MEMBER_COUNT); + BOOST_CHECK_EQUAL(committee_after_hf533_and_init.active.num_auths(), INITIAL_COMMITTEE_MEMBER_COUNT); + +} FC_LOG_AND_RETHROW() } + BOOST_AUTO_TEST_CASE(put_my_witnesses) { try { - graphene::app::database_api db_api1(db); - ACTORS( (witness0) (witness1) (witness2) @@ -90,7 +132,7 @@ BOOST_AUTO_TEST_CASE(put_my_witnesses) const witness_id_type witness12_witness_id = create_witness(witness12_id, witness12_private_key).id; const witness_id_type witness13_witness_id = create_witness(witness13_id, witness13_private_key).id; - // Create a vector with private key of all witnesses, will be used to activate 11 witnesses at a time + // Create a vector with private key of all witnesses, will be used to activate 9 witnesses at a time const vector private_keys = { witness0_private_key, witness1_private_key, @@ -109,7 +151,7 @@ BOOST_AUTO_TEST_CASE(put_my_witnesses) }; - // create a map with account id and witness id of the first 11 witnesses + // create a map with account id and witness id const flat_map witness_map = { {witness0_id, witness0_witness_id}, {witness1_id, witness1_witness_id}, @@ -127,9 +169,9 @@ BOOST_AUTO_TEST_CASE(put_my_witnesses) {witness13_id, witness13_witness_id} }; - // Check current default witnesses, default chain is configured with 10 witnesses + // Check current default witnesses, default chain is configured with 9 witnesses auto witnesses = db.get_global_properties().active_witnesses; - BOOST_CHECK_EQUAL(witnesses.size(), 10u); + BOOST_CHECK_EQUAL(witnesses.size(), INITIAL_WITNESS_COUNT); BOOST_CHECK_EQUAL(witnesses.begin()[0].instance.value, 1u); BOOST_CHECK_EQUAL(witnesses.begin()[1].instance.value, 2u); BOOST_CHECK_EQUAL(witnesses.begin()[2].instance.value, 3u); @@ -139,7 +181,6 @@ BOOST_AUTO_TEST_CASE(put_my_witnesses) BOOST_CHECK_EQUAL(witnesses.begin()[6].instance.value, 7u); BOOST_CHECK_EQUAL(witnesses.begin()[7].instance.value, 8u); BOOST_CHECK_EQUAL(witnesses.begin()[8].instance.value, 9u); - BOOST_CHECK_EQUAL(witnesses.begin()[9].instance.value, 10u); // Activate all witnesses // Each witness is voted with incremental stake so last witness created will be the ones with more votes @@ -168,18 +209,16 @@ BOOST_AUTO_TEST_CASE(put_my_witnesses) // Check my witnesses are now in control of the system witnesses = db.get_global_properties().active_witnesses; - BOOST_CHECK_EQUAL(witnesses.size(), 11u); - BOOST_CHECK_EQUAL(witnesses.begin()[0].instance.value, 14u); - BOOST_CHECK_EQUAL(witnesses.begin()[1].instance.value, 15u); - BOOST_CHECK_EQUAL(witnesses.begin()[2].instance.value, 16u); - BOOST_CHECK_EQUAL(witnesses.begin()[3].instance.value, 17u); - BOOST_CHECK_EQUAL(witnesses.begin()[4].instance.value, 18u); - BOOST_CHECK_EQUAL(witnesses.begin()[5].instance.value, 19u); - BOOST_CHECK_EQUAL(witnesses.begin()[6].instance.value, 20u); - BOOST_CHECK_EQUAL(witnesses.begin()[7].instance.value, 21u); - BOOST_CHECK_EQUAL(witnesses.begin()[8].instance.value, 22u); - BOOST_CHECK_EQUAL(witnesses.begin()[9].instance.value, 23u); - BOOST_CHECK_EQUAL(witnesses.begin()[10].instance.value, 24u); + BOOST_CHECK_EQUAL(witnesses.size(), INITIAL_WITNESS_COUNT); + BOOST_CHECK_EQUAL(witnesses.begin()[0].instance.value, 16u); + BOOST_CHECK_EQUAL(witnesses.begin()[1].instance.value, 17u); + BOOST_CHECK_EQUAL(witnesses.begin()[2].instance.value, 18u); + BOOST_CHECK_EQUAL(witnesses.begin()[3].instance.value, 19u); + BOOST_CHECK_EQUAL(witnesses.begin()[4].instance.value, 20u); + BOOST_CHECK_EQUAL(witnesses.begin()[5].instance.value, 21u); + BOOST_CHECK_EQUAL(witnesses.begin()[6].instance.value, 22u); + BOOST_CHECK_EQUAL(witnesses.begin()[7].instance.value, 23u); + BOOST_CHECK_EQUAL(witnesses.begin()[8].instance.value, 24u); } FC_LOG_AND_RETHROW() } @@ -218,8 +257,6 @@ BOOST_AUTO_TEST_CASE(put_my_committee_members) { try { - graphene::app::database_api db_api1(db); - ACTORS( (committee0) (committee1) (committee2) @@ -267,7 +304,7 @@ BOOST_AUTO_TEST_CASE(put_my_committee_members) const committee_member_id_type committee12_committee_id = create_committee_member(committee12_id(db)).id; const committee_member_id_type committee13_committee_id = create_committee_member(committee13_id(db)).id; - // Create a vector with private key of all witnesses, will be used to activate 11 witnesses at a time + // Create a vector with private key of all committee members, will be used to activate 9 members at a time const vector private_keys = { committee0_private_key, committee1_private_key, @@ -285,7 +322,7 @@ BOOST_AUTO_TEST_CASE(put_my_committee_members) committee13_private_key }; - // create a map with account id and committee id of the first 11 witnesses + // create a map with account id and committee member id const flat_map committee_map = { {committee0_id, committee0_committee_id}, {committee1_id, committee1_committee_id}, @@ -303,10 +340,10 @@ BOOST_AUTO_TEST_CASE(put_my_committee_members) {committee13_id, committee13_committee_id} }; - // Check current default witnesses, default chain is configured with 10 witnesses + // Check current default committee, default chain is configured with 9 committee members auto committee_members = db.get_global_properties().active_committee_members; - BOOST_CHECK_EQUAL(committee_members.size(), 10u); + BOOST_CHECK_EQUAL(committee_members.size(), INITIAL_COMMITTEE_MEMBER_COUNT); BOOST_CHECK_EQUAL(committee_members.begin()[0].instance.value, 0u); BOOST_CHECK_EQUAL(committee_members.begin()[1].instance.value, 1u); BOOST_CHECK_EQUAL(committee_members.begin()[2].instance.value, 2u); @@ -316,10 +353,9 @@ BOOST_AUTO_TEST_CASE(put_my_committee_members) BOOST_CHECK_EQUAL(committee_members.begin()[6].instance.value, 6u); BOOST_CHECK_EQUAL(committee_members.begin()[7].instance.value, 7u); BOOST_CHECK_EQUAL(committee_members.begin()[8].instance.value, 8u); - BOOST_CHECK_EQUAL(committee_members.begin()[9].instance.value, 9u); // Activate all committee - // Each witness is voted with incremental stake so last witness created will be the ones with more votes + // Each committee is voted with incremental stake so last member created will be the ones with more votes int c = 0; for (auto committee : committee_map) { int stake = 100 + c + 10; @@ -329,7 +365,10 @@ BOOST_AUTO_TEST_CASE(put_my_committee_members) account_update_operation op; op.account = committee.first; op.new_options = committee.first(db).options; + + op.new_options->votes.clear(); op.new_options->votes.insert(committee.second(db).vote_id); + op.new_options->num_committee = 1; trx.operations.push_back(op); sign(trx, private_keys.at(c)); @@ -345,21 +384,21 @@ BOOST_AUTO_TEST_CASE(put_my_committee_members) // Check my witnesses are now in control of the system committee_members = db.get_global_properties().active_committee_members; - BOOST_CHECK_EQUAL(committee_members.size(), 11u); - - /* TODO we are not in full control, seems to committee members have votes by default - BOOST_CHECK_EQUAL(committee_members.begin()[0].instance.value, 14); - BOOST_CHECK_EQUAL(committee_members.begin()[1].instance.value, 15); - BOOST_CHECK_EQUAL(committee_members.begin()[2].instance.value, 16); - BOOST_CHECK_EQUAL(committee_members.begin()[3].instance.value, 17); - BOOST_CHECK_EQUAL(committee_members.begin()[4].instance.value, 18); - BOOST_CHECK_EQUAL(committee_members.begin()[5].instance.value, 19); - BOOST_CHECK_EQUAL(committee_members.begin()[6].instance.value, 20); - BOOST_CHECK_EQUAL(committee_members.begin()[7].instance.value, 21); - BOOST_CHECK_EQUAL(committee_members.begin()[8].instance.value, 22); - BOOST_CHECK_EQUAL(committee_members.begin()[9].instance.value, 23); - BOOST_CHECK_EQUAL(committee_members.begin()[10].instance.value, 24); - */ + std::sort(committee_members.begin(), committee_members.end()); + + BOOST_CHECK_EQUAL(committee_members.size(), INITIAL_COMMITTEE_MEMBER_COUNT); + + // Check my committee members are now in control of the system + BOOST_CHECK_EQUAL(committee_members.begin()[0].instance.value, 15); + BOOST_CHECK_EQUAL(committee_members.begin()[1].instance.value, 16); + BOOST_CHECK_EQUAL(committee_members.begin()[2].instance.value, 17); + BOOST_CHECK_EQUAL(committee_members.begin()[3].instance.value, 18); + BOOST_CHECK_EQUAL(committee_members.begin()[4].instance.value, 19); + BOOST_CHECK_EQUAL(committee_members.begin()[5].instance.value, 20); + BOOST_CHECK_EQUAL(committee_members.begin()[6].instance.value, 21); + BOOST_CHECK_EQUAL(committee_members.begin()[7].instance.value, 22); + BOOST_CHECK_EQUAL(committee_members.begin()[8].instance.value, 23); + } FC_LOG_AND_RETHROW() } From d40f70a3503fc620ab2feb654fbd72135be0136f Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Thu, 27 Jun 2019 18:16:51 +0200 Subject: [PATCH 010/111] Added total_in_collateral to asset API calls --- libraries/app/CMakeLists.txt | 5 +- libraries/app/database_api.cpp | 86 ++++++++++++------- .../app/include/graphene/app/database_api.hpp | 22 +++-- libraries/chain/asset_object.cpp | 10 --- .../include/graphene/chain/asset_object.hpp | 11 ++- .../wallet/include/graphene/wallet/wallet.hpp | 4 +- libraries/wallet/wallet.cpp | 14 +-- 7 files changed, 95 insertions(+), 57 deletions(-) diff --git a/libraries/app/CMakeLists.txt b/libraries/app/CMakeLists.txt index bf4f5c2b00..22f2dc2540 100644 --- a/libraries/app/CMakeLists.txt +++ b/libraries/app/CMakeLists.txt @@ -13,7 +13,10 @@ add_library( graphene_app ) # need to link graphene_debug_witness because plugins aren't sufficiently isolated #246 -target_link_libraries( graphene_app graphene_market_history graphene_account_history graphene_grouped_orders graphene_chain fc graphene_db graphene_net graphene_utilities graphene_debug_witness ) +target_link_libraries( graphene_app + graphene_market_history graphene_account_history graphene_grouped_orders + graphene_api_helper_indexes + graphene_chain fc graphene_db graphene_net 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/database_api.cpp b/libraries/app/database_api.cpp index 6c12eeecf5..161fa3fddd 100644 --- a/libraries/app/database_api.cpp +++ b/libraries/app/database_api.cpp @@ -103,13 +103,13 @@ class database_api_impl : public std::enable_shared_from_this vector get_vesting_balances( const std::string account_id_or_name )const; // Assets + uint64_t get_asset_count()const; asset_id_type get_asset_id_from_string(const std::string& symbol_or_id)const; - vector> get_assets(const vector& asset_symbols_or_ids)const; - vector list_assets(const string& lower_bound_symbol, uint32_t limit)const; - vector> lookup_asset_symbols(const vector& symbols_or_ids)const; - uint64_t get_asset_count()const; - vector get_assets_by_issuer(const std::string& issuer_name_or_id, - asset_id_type start, uint32_t limit)const; + vector> get_assets(const vector& asset_symbols_or_ids)const; + vector list_assets(const string& lower_bound_symbol, uint32_t limit)const; + vector> lookup_asset_symbols(const vector& symbols_or_ids)const; + vector get_assets_by_issuer(const std::string& issuer_name_or_id, + asset_id_type start, uint32_t limit)const; // Markets / feeds vector get_limit_orders(const std::string& a, const std::string& b, uint32_t limit)const; @@ -262,6 +262,30 @@ class database_api_impl : public std::enable_shared_from_this return account; } + const graphene::api_helper_indexes::amount_in_collateral_index* get_helper_index()const + { + try + { + return &_db.get_index_type< primary_index< call_order_index > >() + .get_secondary_index(); + } + catch( fc::assert_exception& e ) + { + return nullptr; + } + } + + template + extended_asset_object extend_asset( ASSET&& a )const + { + static const graphene::api_helper_indexes::amount_in_collateral_index* helper = get_helper_index(); + asset_id_type id = a.id; + extended_asset_object result = extended_asset_object( std::forward( a ) ); + if( helper ) + result.total_in_collateral = helper->get_amount_in_collateral( id ); + return result; + } + const asset_object* get_asset_from_string( const std::string& symbol_or_id, bool throw_if_not_found = true ) const { // TODO cache the result to avoid repeatly fetching from db @@ -280,16 +304,16 @@ class database_api_impl : public std::enable_shared_from_this FC_ASSERT( asset, "no such asset" ); return asset; } - vector> get_assets(const vector& asset_ids)const + vector> get_assets(const vector& asset_ids)const { - vector> result; result.reserve(asset_ids.size()); + vector> result; result.reserve(asset_ids.size()); std::transform(asset_ids.begin(), asset_ids.end(), std::back_inserter(result), - [this](asset_id_type id) -> optional { + [this](asset_id_type id) -> optional { if(auto o = _db.find(id)) { if( _enabled_auto_subscription ) subscribe_to_item( id ); - return *o; + return extend_asset( *o ); } return {}; }); @@ -1291,39 +1315,39 @@ asset_id_type database_api::get_asset_id_from_string(const std::string& symbol_o return my->get_asset_from_string( symbol_or_id )->id; } -vector> database_api::get_assets(const vector& asset_symbols_or_ids)const +vector> database_api::get_assets(const vector& asset_symbols_or_ids)const { return my->get_assets( asset_symbols_or_ids ); } -vector> database_api_impl::get_assets(const vector& asset_symbols_or_ids)const +vector> database_api_impl::get_assets(const vector& asset_symbols_or_ids)const { - vector> result; result.reserve(asset_symbols_or_ids.size()); + vector> result; result.reserve(asset_symbols_or_ids.size()); std::transform(asset_symbols_or_ids.begin(), asset_symbols_or_ids.end(), std::back_inserter(result), - [this](std::string id_or_name) -> optional { + [this](std::string id_or_name) -> optional { const asset_object* asset_obj = get_asset_from_string( id_or_name, false ); if( asset_obj == nullptr ) return {}; if( _enabled_auto_subscription ) subscribe_to_item( asset_obj->id ); - return *asset_obj; + return extend_asset( *asset_obj ); }); return result; } -vector database_api::list_assets(const string& lower_bound_symbol, uint32_t limit)const +vector database_api::list_assets(const string& lower_bound_symbol, uint32_t limit)const { return my->list_assets( lower_bound_symbol, limit ); } -vector database_api_impl::list_assets(const string& lower_bound_symbol, uint32_t limit)const +vector database_api_impl::list_assets(const string& lower_bound_symbol, uint32_t limit)const { uint64_t api_limit_get_assets = _app_options->api_limit_get_assets; FC_ASSERT( limit <= api_limit_get_assets ); const auto& assets_by_symbol = _db.get_index_type().indices().get(); - vector result; + vector result; result.reserve(limit); auto itr = assets_by_symbol.lower_bound(lower_bound_symbol); @@ -1332,7 +1356,7 @@ vector database_api_impl::list_assets(const string& lower_bound_sy itr = assets_by_symbol.begin(); while(limit-- && itr != assets_by_symbol.end()) - result.emplace_back(*itr++); + result.emplace_back( extend_asset( *itr++ ) ); return result; } @@ -1347,50 +1371,50 @@ uint64_t database_api_impl::get_asset_count()const return _db.get_index_type().indices().size(); } -vector database_api::get_assets_by_issuer(const std::string& issuer_name_or_id, - asset_id_type start, uint32_t limit)const +vector database_api::get_assets_by_issuer(const std::string& issuer_name_or_id, + asset_id_type start, uint32_t limit)const { return my->get_assets_by_issuer(issuer_name_or_id, start, limit); } -vector database_api_impl::get_assets_by_issuer(const std::string& issuer_name_or_id, - asset_id_type start, uint32_t limit)const +vector database_api_impl::get_assets_by_issuer(const std::string& issuer_name_or_id, + asset_id_type start, uint32_t limit)const { uint64_t api_limit_get_assets = _app_options->api_limit_get_assets; FC_ASSERT( limit <= api_limit_get_assets ); - vector result; + vector result; const account_id_type account = get_account_from_string(issuer_name_or_id)->id; const auto& asset_idx = _db.get_index_type().indices().get(); auto asset_index_end = asset_idx.end(); auto asset_itr = asset_idx.lower_bound(boost::make_tuple(account, start)); while(asset_itr != asset_index_end && asset_itr->issuer == account && result.size() < limit) { - result.push_back(*asset_itr); + result.emplace_back( extend_asset( *asset_itr ) ); ++asset_itr; } return result; } -vector> database_api::lookup_asset_symbols(const vector& symbols_or_ids)const +vector> database_api::lookup_asset_symbols(const vector& symbols_or_ids)const { return my->lookup_asset_symbols( symbols_or_ids ); } -vector> database_api_impl::lookup_asset_symbols(const vector& symbols_or_ids)const +vector> database_api_impl::lookup_asset_symbols(const vector& symbols_or_ids)const { const auto& assets_by_symbol = _db.get_index_type().indices().get(); - vector > result; + vector > result; result.reserve(symbols_or_ids.size()); std::transform(symbols_or_ids.begin(), symbols_or_ids.end(), std::back_inserter(result), - [this, &assets_by_symbol](const string& symbol_or_id) -> optional { + [this, &assets_by_symbol](const string& symbol_or_id) -> optional { if( !symbol_or_id.empty() && std::isdigit(symbol_or_id[0]) ) { auto ptr = _db.find(variant(symbol_or_id, 1).as(1)); - return ptr == nullptr? optional() : *ptr; + return ptr == nullptr? optional() : extend_asset( *ptr ); } auto itr = assets_by_symbol.find(symbol_or_id); - return itr == assets_by_symbol.end()? optional() : *itr; + return itr == assets_by_symbol.end()? optional() : extend_asset( *itr ); }); return result; } diff --git a/libraries/app/include/graphene/app/database_api.hpp b/libraries/app/include/graphene/app/database_api.hpp index 13734e751b..a7d1b607ac 100644 --- a/libraries/app/include/graphene/app/database_api.hpp +++ b/libraries/app/include/graphene/app/database_api.hpp @@ -42,6 +42,7 @@ #include #include +#include #include #include @@ -125,6 +126,15 @@ struct market_trade account_id_type side2_account_id = GRAPHENE_NULL_ACCOUNT; }; +struct extended_asset_object : asset_object +{ + extended_asset_object() {} + template + explicit extended_asset_object( ASSET&& a ) : asset_object( std::forward(a) ) {} + + optional total_in_collateral; +}; + /** * @brief The database_api class implements the RPC API for the chain database. * @@ -416,7 +426,7 @@ class database_api * * This function has semantics identical to @ref get_objects */ - vector> get_assets(const vector& asset_symbols_or_ids)const; + vector> get_assets(const vector& asset_symbols_or_ids)const; /** * @brief Get assets alphabetically by symbol name @@ -424,7 +434,7 @@ class database_api * @param limit Maximum number of assets to fetch (must not exceed 101) * @return The assets found */ - vector list_assets(const string& lower_bound_symbol, uint32_t limit)const; + vector list_assets(const string& lower_bound_symbol, uint32_t limit)const; /** * @brief Get a list of assets by symbol @@ -433,7 +443,7 @@ class database_api * * This function has semantics identical to @ref get_objects */ - vector> lookup_asset_symbols(const vector& symbols_or_ids)const; + vector> lookup_asset_symbols(const vector& symbols_or_ids)const; /** * @brief Get assets count @@ -448,8 +458,8 @@ class database_api * @param limit Maximum number of orders to retrieve * @return The assets issued by the account */ - vector get_assets_by_issuer(const std::string& issuer_name_or_id, - asset_id_type start, uint32_t limit)const; + vector get_assets_by_issuer(const std::string& issuer_name_or_id, + asset_id_type start, uint32_t limit)const; ///////////////////// // Markets / feeds // @@ -836,6 +846,8 @@ FC_REFLECT( graphene::app::market_ticker, FC_REFLECT( graphene::app::market_volume, (time)(base)(quote)(base_volume)(quote_volume) ); FC_REFLECT( graphene::app::market_trade, (sequence)(date)(price)(amount)(value)(side1_account_id)(side2_account_id) ); +FC_REFLECT_DERIVED( graphene::app::extended_asset_object, (graphene::chain::asset_object), (total_in_collateral) ); + FC_API(graphene::app::database_api, // Objects (get_objects) diff --git a/libraries/chain/asset_object.cpp b/libraries/chain/asset_object.cpp index 549159da72..2244043920 100644 --- a/libraries/chain/asset_object.cpp +++ b/libraries/chain/asset_object.cpp @@ -194,16 +194,6 @@ FC_REFLECT_DERIVED_NO_TYPENAME( graphene::chain::asset_bitasset_data_object, (gr (feed_cer_updated) ) -FC_REFLECT_DERIVED_NO_TYPENAME( graphene::chain::asset_object, (graphene::db::object), - (symbol) - (precision) - (issuer) - (options) - (dynamic_asset_data_id) - (bitasset_data_id) - (buyback_account) - ) - GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::chain::asset_object ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::chain::asset_bitasset_data_object ) GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION( graphene::chain::asset_dynamic_data_object ) diff --git a/libraries/chain/include/graphene/chain/asset_object.hpp b/libraries/chain/include/graphene/chain/asset_object.hpp index 1a4ad3e47d..3541f87f5b 100644 --- a/libraries/chain/include/graphene/chain/asset_object.hpp +++ b/libraries/chain/include/graphene/chain/asset_object.hpp @@ -323,7 +323,16 @@ MAP_OBJECT_ID_TO_TYPE(graphene::chain::asset_object) MAP_OBJECT_ID_TO_TYPE(graphene::chain::asset_dynamic_data_object) MAP_OBJECT_ID_TO_TYPE(graphene::chain::asset_bitasset_data_object) -FC_REFLECT_TYPENAME( graphene::chain::asset_object ) +FC_REFLECT_DERIVED( graphene::chain::asset_object, (graphene::db::object), + (symbol) + (precision) + (issuer) + (options) + (dynamic_asset_data_id) + (bitasset_data_id) + (buyback_account) + ) + FC_REFLECT_TYPENAME( graphene::chain::asset_bitasset_data_object ) FC_REFLECT_TYPENAME( graphene::chain::asset_dynamic_data_object ) diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index 1fc432ce1c..9e17fd86a5 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -367,7 +367,7 @@ class wallet_api * @param limit the maximum number of assets to return (max: 100) * @returns the list of asset objects, ordered by symbol */ - vector list_assets(const string& lowerbound, uint32_t limit)const; + vector list_assets(const string& lowerbound, uint32_t limit)const; /** Returns assets count registered on the blockchain. * * @returns assets count @@ -483,7 +483,7 @@ class wallet_api * @param asset_name_or_id the symbol or id of the asset in question * @returns the information about the asset stored in the block chain */ - asset_object get_asset(string asset_name_or_id) const; + extended_asset_object get_asset(string asset_name_or_id) const; /** Returns the BitAsset-specific data for a given asset. * Market-issued assets's behavior are determined both by their "BitAsset Data" and diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index a2783a8584..b97dffac80 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -684,12 +684,12 @@ class wallet_api_impl "." + fc::to_string(id.instance.value); return asset_id; } - optional find_asset(asset_id_type id)const + optional find_asset(asset_id_type id)const { auto rec = _remote_db->get_assets({asset_id_to_string(id)}).front(); return rec; } - optional find_asset(string asset_symbol_or_id)const + optional find_asset(string asset_symbol_or_id)const { FC_ASSERT( asset_symbol_or_id.size() > 0 ); @@ -708,13 +708,13 @@ class wallet_api_impl return rec; } } - asset_object get_asset(asset_id_type id)const + extended_asset_object get_asset(asset_id_type id)const { auto opt = find_asset(id); FC_ASSERT(opt); return *opt; } - asset_object get_asset(string asset_symbol_or_id)const + extended_asset_object get_asset(string asset_symbol_or_id)const { auto opt = find_asset(asset_symbol_or_id); FC_ASSERT(opt); @@ -736,7 +736,7 @@ class wallet_api_impl asset_id_type get_asset_id(string asset_symbol_or_id) const { FC_ASSERT( asset_symbol_or_id.size() > 0 ); - vector> opt_asset; + vector> opt_asset; if( std::isdigit( asset_symbol_or_id.front() ) ) return fc::variant(asset_symbol_or_id, 1).as( 1 ); opt_asset = _remote_db->lookup_asset_symbols( {asset_symbol_or_id} ); @@ -3275,7 +3275,7 @@ vector wallet_api::list_account_balances(const string& id) return my->_remote_db->get_account_balances(id, flat_set()); } -vector wallet_api::list_assets(const string& lowerbound, uint32_t limit)const +vector wallet_api::list_assets(const string& lowerbound, uint32_t limit)const { return my->_remote_db->list_assets( lowerbound, limit ); } @@ -3645,7 +3645,7 @@ account_object wallet_api::get_account(string account_name_or_id) const return my->get_account(account_name_or_id); } -asset_object wallet_api::get_asset(string asset_name_or_id) const +extended_asset_object wallet_api::get_asset(string asset_name_or_id) const { auto a = my->find_asset(asset_name_or_id); FC_ASSERT(a); From 6bb8213ae39a6edf4723b3d3c0c4242653f853a6 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Thu, 27 Jun 2019 18:45:47 +0200 Subject: [PATCH 011/111] Resolve #1781 --- libraries/app/database_api.cpp | 4 ++ .../app/include/graphene/app/database_api.hpp | 4 +- .../api_helper_indexes/api_helper_indexes.cpp | 49 +++++++++++++++---- .../api_helper_indexes/api_helper_indexes.hpp | 7 ++- 4 files changed, 51 insertions(+), 13 deletions(-) diff --git a/libraries/app/database_api.cpp b/libraries/app/database_api.cpp index 161fa3fddd..4d6cfacc30 100644 --- a/libraries/app/database_api.cpp +++ b/libraries/app/database_api.cpp @@ -282,7 +282,11 @@ class database_api_impl : public std::enable_shared_from_this asset_id_type id = a.id; extended_asset_object result = extended_asset_object( std::forward( a ) ); if( helper ) + { result.total_in_collateral = helper->get_amount_in_collateral( id ); + if( result.bitasset_data_id.valid() ) + result.total_backing_collateral = helper->get_backing_collateral( id ); + } return result; } diff --git a/libraries/app/include/graphene/app/database_api.hpp b/libraries/app/include/graphene/app/database_api.hpp index a7d1b607ac..12092ab25c 100644 --- a/libraries/app/include/graphene/app/database_api.hpp +++ b/libraries/app/include/graphene/app/database_api.hpp @@ -133,6 +133,7 @@ struct extended_asset_object : asset_object explicit extended_asset_object( ASSET&& a ) : asset_object( std::forward(a) ) {} optional total_in_collateral; + optional total_backing_collateral; }; /** @@ -846,7 +847,8 @@ FC_REFLECT( graphene::app::market_ticker, FC_REFLECT( graphene::app::market_volume, (time)(base)(quote)(base_volume)(quote_volume) ); FC_REFLECT( graphene::app::market_trade, (sequence)(date)(price)(amount)(value)(side1_account_id)(side2_account_id) ); -FC_REFLECT_DERIVED( graphene::app::extended_asset_object, (graphene::chain::asset_object), (total_in_collateral) ); +FC_REFLECT_DERIVED( graphene::app::extended_asset_object, (graphene::chain::asset_object), + (total_in_collateral)(total_backing_collateral) ); FC_API(graphene::app::database_api, // Objects diff --git a/libraries/plugins/api_helper_indexes/api_helper_indexes.cpp b/libraries/plugins/api_helper_indexes/api_helper_indexes.cpp index eabff46718..e99e29b9c1 100644 --- a/libraries/plugins/api_helper_indexes/api_helper_indexes.cpp +++ b/libraries/plugins/api_helper_indexes/api_helper_indexes.cpp @@ -30,19 +30,41 @@ namespace graphene { namespace api_helper_indexes { void amount_in_collateral_index::object_inserted( const object& objct ) { try { const call_order_object& o = static_cast( objct ); - auto itr = amounts.find( o.collateral_type() ); - if( itr == amounts.end() ) - amounts[o.collateral_type()] = o.collateral; - else - itr->second += o.collateral; + + { + auto itr = in_collateral.find( o.collateral_type() ); + if( itr == in_collateral.end() ) + in_collateral[o.collateral_type()] = o.collateral; + else + itr->second += o.collateral; + } + + { + auto itr = backing_collateral.find( o.debt_type() ); + if( itr == backing_collateral.end() ) + backing_collateral[o.debt_type()] = o.collateral; + else + itr->second += o.collateral; + } + } FC_CAPTURE_AND_RETHROW( (objct) ); } void amount_in_collateral_index::object_removed( const object& objct ) { try { const call_order_object& o = static_cast( objct ); - auto itr = amounts.find( o.collateral_type() ); - if( itr == amounts.end() ) return; // should never happen - itr->second -= o.collateral; + + { + auto itr = in_collateral.find( o.collateral_type() ); + if( itr != in_collateral.end() ) // should always be true + itr->second -= o.collateral; + } + + { + auto itr = backing_collateral.find( o.debt_type() ); + if( itr != backing_collateral.end() ) // should always be true + itr->second -= o.collateral; + } + } FC_CAPTURE_AND_RETHROW( (objct) ); } void amount_in_collateral_index::about_to_modify( const object& objct ) @@ -57,8 +79,15 @@ void amount_in_collateral_index::object_modified( const object& objct ) share_type amount_in_collateral_index::get_amount_in_collateral( const asset_id_type& asset )const { try { - auto itr = amounts.find( asset ); - if( itr == amounts.end() ) return 0; + auto itr = in_collateral.find( asset ); + if( itr == in_collateral.end() ) return 0; + return itr->second; +} FC_CAPTURE_AND_RETHROW( (asset) ); } + +share_type amount_in_collateral_index::get_backing_collateral( const asset_id_type& asset )const +{ try { + auto itr = backing_collateral.find( asset ); + if( itr == backing_collateral.end() ) return 0; return itr->second; } FC_CAPTURE_AND_RETHROW( (asset) ); } diff --git a/libraries/plugins/api_helper_indexes/include/graphene/api_helper_indexes/api_helper_indexes.hpp b/libraries/plugins/api_helper_indexes/include/graphene/api_helper_indexes/api_helper_indexes.hpp index 69d6a96456..400b3000b1 100644 --- a/libraries/plugins/api_helper_indexes/include/graphene/api_helper_indexes/api_helper_indexes.hpp +++ b/libraries/plugins/api_helper_indexes/include/graphene/api_helper_indexes/api_helper_indexes.hpp @@ -30,7 +30,8 @@ namespace graphene { namespace api_helper_indexes { using namespace chain; /** - * @brief This secondary index tracks how much of each asset is locked up as collateral for MPAs. + * @brief This secondary index tracks how much of each asset is locked up as collateral for MPAs, and how much + * collateral is backing an MPA in total. */ class amount_in_collateral_index : public secondary_index { @@ -41,9 +42,11 @@ class amount_in_collateral_index : public secondary_index virtual void object_modified( const object& after ) override; share_type get_amount_in_collateral( const asset_id_type& asset )const; + share_type get_backing_collateral( const asset_id_type& asset )const; private: - flat_map amounts; + flat_map in_collateral; + flat_map backing_collateral; }; namespace detail From 8691fed33475b9e395cc59558930d2aa5bc9b972 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Thu, 27 Jun 2019 18:50:22 +0200 Subject: [PATCH 012/111] Log warning if index isnt available --- libraries/app/database_api.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/app/database_api.cpp b/libraries/app/database_api.cpp index 4d6cfacc30..79b4a98b25 100644 --- a/libraries/app/database_api.cpp +++ b/libraries/app/database_api.cpp @@ -271,6 +271,7 @@ class database_api_impl : public std::enable_shared_from_this } catch( fc::assert_exception& e ) { + wlog( "amount_in_collateral_index not found - please enable api_helper_indexes plugin!" ); return nullptr; } } From 1da7a5b6702f3e72e8d1eeedb8e6b09153bda3dd Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Sat, 29 Jun 2019 10:19:36 +0200 Subject: [PATCH 013/111] Added unit tests --- tests/CMakeLists.txt | 20 ++++- tests/common/database_fixture.cpp | 13 +++ tests/tests/database_api_tests.cpp | 136 +++++++++++++++++++++++++++++ 3 files changed, 165 insertions(+), 4 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index b863c6347e..d05bf13183 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -8,7 +8,10 @@ endif() file(GLOB UNIT_TESTS "tests/*.cpp") add_executable( chain_test ${COMMON_SOURCES} ${UNIT_TESTS} ) -target_link_libraries( chain_test graphene_chain graphene_app graphene_witness graphene_account_history graphene_elasticsearch graphene_es_objects graphene_egenesis_none fc graphene_wallet ${PLATFORM_SPECIFIC_LIBS} ) +target_link_libraries( chain_test + graphene_chain graphene_app graphene_witness graphene_account_history graphene_elasticsearch + graphene_es_objects graphene_egenesis_none graphene_api_helper_indexes + fc graphene_wallet ${PLATFORM_SPECIFIC_LIBS} ) if(MSVC) set_source_files_properties( tests/serialization_tests.cpp PROPERTIES COMPILE_FLAGS "/bigobj" ) set_source_files_properties( tests/common/database_fixture.cpp PROPERTIES COMPILE_FLAGS "/bigobj" ) @@ -16,11 +19,17 @@ endif(MSVC) file(GLOB PERFORMANCE_TESTS "performance/*.cpp") add_executable( performance_test ${COMMON_SOURCES} ${PERFORMANCE_TESTS} ) -target_link_libraries( performance_test graphene_chain graphene_app graphene_account_history graphene_elasticsearch graphene_es_objects graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} ) +target_link_libraries( performance_test + graphene_chain graphene_app graphene_account_history graphene_elasticsearch + graphene_es_objects graphene_egenesis_none graphene_api_helper_indexes + fc ${PLATFORM_SPECIFIC_LIBS} ) file(GLOB BENCH_MARKS "benchmarks/*.cpp") add_executable( chain_bench ${COMMON_SOURCES} ${BENCH_MARKS} ) -target_link_libraries( chain_bench graphene_chain graphene_app graphene_account_history graphene_elasticsearch graphene_es_objects graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} ) +target_link_libraries( chain_bench + graphene_chain graphene_app graphene_account_history graphene_elasticsearch + graphene_es_objects graphene_egenesis_none graphene_api_helper_indexes + fc ${PLATFORM_SPECIFIC_LIBS} ) file(GLOB APP_SOURCES "app/*.cpp") add_executable( app_test ${APP_SOURCES} ) @@ -38,6 +47,9 @@ endif(MSVC) file(GLOB ES_SOURCES "elasticsearch/*.cpp") add_executable( es_test ${COMMON_SOURCES} ${ES_SOURCES} ) -target_link_libraries( es_test graphene_chain graphene_app graphene_account_history graphene_elasticsearch graphene_es_objects graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} ) +target_link_libraries( es_test + graphene_chain graphene_app graphene_account_history graphene_elasticsearch + graphene_es_objects graphene_egenesis_none graphene_api_helper_indexes + fc ${PLATFORM_SPECIFIC_LIBS} ) add_subdirectory( generate_empty_blocks ) diff --git a/tests/common/database_fixture.cpp b/tests/common/database_fixture.cpp index 0760f68bc2..c9af91ccff 100644 --- a/tests/common/database_fixture.cpp +++ b/tests/common/database_fixture.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -192,6 +193,11 @@ database_fixture::database_fixture(const fc::time_point_sec &initial_timestamp) options.insert(std::make_pair("plugins", boost::program_options::variable_value( string("account_history"), false))); } + if( current_test_name == "asset_in_collateral" ) + { + options.insert( std::make_pair( "plugins", + boost::program_options::variable_value( string("api_helper_indexes"), false ) ) ); + } // add account tracking for ahplugin for special test case with track-account enabled if( !options.count("track-account") && current_test_name == "track_account") { @@ -263,6 +269,13 @@ database_fixture::database_fixture(const fc::time_point_sec &initial_timestamp) esobjects_plugin->plugin_initialize(options); esobjects_plugin->plugin_startup(); } + else if( current_test_name == "asset_in_collateral" ) + { + auto ahiplugin = app.register_plugin(); + ahiplugin->plugin_set_app(&app); + ahiplugin->plugin_initialize(options); + ahiplugin->plugin_startup(); + } options.insert(std::make_pair("bucket-size", boost::program_options::variable_value(string("[15]"),false))); mhplugin->plugin_set_app(&app); diff --git a/tests/tests/database_api_tests.cpp b/tests/tests/database_api_tests.cpp index a8ba90c63e..6bafcd3caa 100644 --- a/tests/tests/database_api_tests.cpp +++ b/tests/tests/database_api_tests.cpp @@ -1542,4 +1542,140 @@ BOOST_AUTO_TEST_CASE( api_limit_get_order_book ){ throw; } } + +BOOST_AUTO_TEST_CASE( asset_in_collateral ) +{ try { + ACTORS( (dan)(nathan) ); + fund( nathan ); + fund( dan ); + + graphene::app::database_api db_api( db, &( app.get_options() ) ); + + auto oassets = db_api.get_assets( { GRAPHENE_SYMBOL } ); + BOOST_REQUIRE( !oassets.empty() ); + BOOST_REQUIRE( oassets[0].valid() ); + BOOST_REQUIRE( oassets[0]->total_in_collateral.valid() ); + BOOST_CHECK_EQUAL( 0, oassets[0]->total_in_collateral->value ); + BOOST_CHECK( !oassets[0]->total_backing_collateral.valid() ); + + asset_id_type bitusd_id = create_bitasset( "USDBIT", nathan_id, 100, charge_market_fee ).id; + update_feed_producers( bitusd_id, { nathan_id } ); + asset_id_type bitdan_id = create_bitasset( "DANBIT", dan_id, 100, charge_market_fee ).id; + update_feed_producers( bitdan_id, { nathan_id } ); + asset_id_type btc_id = create_bitasset( "BTC", nathan_id, 100, charge_market_fee, 8, bitusd_id ).id; + update_feed_producers( btc_id, { nathan_id } ); + + oassets = db_api.get_assets( { GRAPHENE_SYMBOL, "USDBIT", "DANBIT", "BTC" } ); + BOOST_REQUIRE_EQUAL( 4, oassets.size() ); + BOOST_REQUIRE( oassets[0].valid() ); + BOOST_REQUIRE( oassets[0]->total_in_collateral.valid() ); + BOOST_CHECK( !oassets[0]->total_backing_collateral.valid() ); + BOOST_REQUIRE( oassets[1].valid() ); + BOOST_REQUIRE( oassets[1]->total_in_collateral.valid() ); + BOOST_REQUIRE( oassets[1]->total_backing_collateral.valid() ); + BOOST_REQUIRE( oassets[2].valid() ); + BOOST_REQUIRE( oassets[2]->total_in_collateral.valid() ); + BOOST_REQUIRE( oassets[2]->total_backing_collateral.valid() ); + BOOST_REQUIRE( oassets[3].valid() ); + BOOST_REQUIRE( oassets[3]->total_in_collateral.valid() ); + BOOST_REQUIRE( oassets[3]->total_backing_collateral.valid() ); + BOOST_CHECK_EQUAL( 0, oassets[0]->total_in_collateral->value ); + BOOST_CHECK_EQUAL( 0, oassets[1]->total_in_collateral->value ); + BOOST_CHECK_EQUAL( 0, oassets[1]->total_backing_collateral->value ); + BOOST_CHECK_EQUAL( 0, oassets[2]->total_in_collateral->value ); + BOOST_CHECK_EQUAL( 0, oassets[2]->total_backing_collateral->value ); + BOOST_CHECK_EQUAL( 0, oassets[3]->total_in_collateral->value ); + BOOST_CHECK_EQUAL( 0, oassets[3]->total_backing_collateral->value ); + + generate_block(); + + const auto& bitusd = bitusd_id( db ); + const auto& bitdan = bitdan_id( db ); + const auto& btc = btc_id( db ); + + { + const auto& core = asset_id_type()( db ); + price_feed current_feed; + current_feed.maintenance_collateral_ratio = 1750; + current_feed.maximum_short_squeeze_ratio = 1100; + current_feed.settlement_price = bitusd.amount(1) / core.amount(5); + publish_feed( bitusd_id, nathan_id, current_feed ); + current_feed.settlement_price = bitdan.amount(1) / core.amount(5); + publish_feed( bitdan_id, nathan_id, current_feed ); + current_feed.settlement_price = btc.amount(1) / bitusd.amount(100); + publish_feed( btc_id, nathan_id, current_feed ); + } + + borrow( nathan_id, bitusd.amount(1000), asset(15000) ); + borrow( dan_id, bitusd.amount(100), asset(2000) ); + + oassets = db_api.get_assets( { GRAPHENE_SYMBOL, "USDBIT", "DANBIT", "BTC" } ); + BOOST_REQUIRE_EQUAL( 4, oassets.size() ); + BOOST_REQUIRE( oassets[0].valid() ); + BOOST_REQUIRE( oassets[0]->total_in_collateral.valid() ); + BOOST_CHECK( !oassets[0]->total_backing_collateral.valid() ); + BOOST_REQUIRE( oassets[1].valid() ); + BOOST_REQUIRE( oassets[1]->total_in_collateral.valid() ); + BOOST_REQUIRE( oassets[1]->total_backing_collateral.valid() ); + BOOST_REQUIRE( oassets[2].valid() ); + BOOST_REQUIRE( oassets[2]->total_in_collateral.valid() ); + BOOST_REQUIRE( oassets[2]->total_backing_collateral.valid() ); + BOOST_REQUIRE( oassets[3].valid() ); + BOOST_REQUIRE( oassets[3]->total_in_collateral.valid() ); + BOOST_REQUIRE( oassets[3]->total_backing_collateral.valid() ); + BOOST_CHECK_EQUAL( 17000, oassets[0]->total_in_collateral->value ); + BOOST_CHECK_EQUAL( 0, oassets[1]->total_in_collateral->value ); + BOOST_CHECK_EQUAL( 17000, oassets[1]->total_backing_collateral->value ); + BOOST_CHECK_EQUAL( 0, oassets[2]->total_in_collateral->value ); + BOOST_CHECK_EQUAL( 0, oassets[2]->total_backing_collateral->value ); + BOOST_CHECK_EQUAL( 0, oassets[3]->total_in_collateral->value ); + BOOST_CHECK_EQUAL( 0, oassets[3]->total_backing_collateral->value ); + + borrow( nathan_id, bitdan.amount(1000), asset(15000) ); + borrow( nathan_id, btc.amount(5), bitusd.amount(1000) ); + + oassets = db_api.lookup_asset_symbols( { GRAPHENE_SYMBOL, "USDBIT", "DANBIT", "BTC" } ); + BOOST_REQUIRE_EQUAL( 4, oassets.size() ); + BOOST_REQUIRE( oassets[0].valid() ); + BOOST_REQUIRE( oassets[0]->total_in_collateral.valid() ); + BOOST_CHECK( !oassets[0]->total_backing_collateral.valid() ); + BOOST_REQUIRE( oassets[1].valid() ); + BOOST_REQUIRE( oassets[1]->total_in_collateral.valid() ); + BOOST_REQUIRE( oassets[1]->total_backing_collateral.valid() ); + BOOST_REQUIRE( oassets[2].valid() ); + BOOST_REQUIRE( oassets[2]->total_in_collateral.valid() ); + BOOST_REQUIRE( oassets[2]->total_backing_collateral.valid() ); + BOOST_REQUIRE( oassets[3].valid() ); + BOOST_REQUIRE( oassets[3]->total_in_collateral.valid() ); + BOOST_REQUIRE( oassets[3]->total_backing_collateral.valid() ); + BOOST_CHECK_EQUAL( 32000, oassets[0]->total_in_collateral->value ); + BOOST_CHECK_EQUAL( 1000, oassets[1]->total_in_collateral->value ); + BOOST_CHECK_EQUAL( 17000, oassets[1]->total_backing_collateral->value ); + BOOST_CHECK_EQUAL( 0, oassets[2]->total_in_collateral->value ); + BOOST_CHECK_EQUAL( 15000, oassets[2]->total_backing_collateral->value ); + BOOST_CHECK_EQUAL( 0, oassets[3]->total_in_collateral->value ); + BOOST_CHECK_EQUAL( 1000, oassets[3]->total_backing_collateral->value ); + + force_settle( dan_id(db), bitusd.amount(100) ); // settles against nathan, receives 500 CORE collateral + generate_blocks( db.head_block_time() + fc::days(2) ); + + auto assets = db_api.list_assets( GRAPHENE_SYMBOL, 1 ); + BOOST_REQUIRE( !assets.empty() ); + BOOST_REQUIRE( assets[0].total_in_collateral.valid() ); + BOOST_CHECK( !assets[0].total_backing_collateral.valid() ); + BOOST_CHECK_EQUAL( 31500, assets[0].total_in_collateral->value ); + + assets = db_api.get_assets_by_issuer( "nathan", asset_id_type(1), 2 ); + BOOST_REQUIRE_EQUAL( 2, assets.size() ); + BOOST_REQUIRE( assets[0].total_in_collateral.valid() ); + BOOST_REQUIRE( assets[0].total_backing_collateral.valid() ); + BOOST_REQUIRE( assets[1].total_in_collateral.valid() ); + BOOST_REQUIRE( assets[1].total_backing_collateral.valid() ); + BOOST_CHECK_EQUAL( 1000, assets[0].total_in_collateral->value ); + BOOST_CHECK_EQUAL( 16500, assets[0].total_backing_collateral->value ); + BOOST_CHECK_EQUAL( 0, assets[1].total_in_collateral->value ); + BOOST_CHECK_EQUAL( 1000, assets[1].total_backing_collateral->value ); + +} FC_LOG_AND_RETHROW() } + BOOST_AUTO_TEST_SUITE_END() From 21778df89dbfcbdc3853bb4a8577910e5c2bc61b Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Sat, 29 Jun 2019 14:26:42 +0200 Subject: [PATCH 014/111] Avoid local static variable --- libraries/app/database_api.cpp | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/libraries/app/database_api.cpp b/libraries/app/database_api.cpp index 79b4a98b25..f04bfff9af 100644 --- a/libraries/app/database_api.cpp +++ b/libraries/app/database_api.cpp @@ -262,31 +262,16 @@ class database_api_impl : public std::enable_shared_from_this return account; } - const graphene::api_helper_indexes::amount_in_collateral_index* get_helper_index()const - { - try - { - return &_db.get_index_type< primary_index< call_order_index > >() - .get_secondary_index(); - } - catch( fc::assert_exception& e ) - { - wlog( "amount_in_collateral_index not found - please enable api_helper_indexes plugin!" ); - return nullptr; - } - } - template extended_asset_object extend_asset( ASSET&& a )const { - static const graphene::api_helper_indexes::amount_in_collateral_index* helper = get_helper_index(); asset_id_type id = a.id; extended_asset_object result = extended_asset_object( std::forward( a ) ); - if( helper ) + if( amount_in_collateral_index ) { - result.total_in_collateral = helper->get_amount_in_collateral( id ); + result.total_in_collateral = amount_in_collateral_index->get_amount_in_collateral( id ); if( result.bitasset_data_id.valid() ) - result.total_backing_collateral = helper->get_backing_collateral( id ); + result.total_backing_collateral = amount_in_collateral_index->get_backing_collateral( id ); } return result; } @@ -403,6 +388,7 @@ class database_api_impl : public std::enable_shared_from_this map< pair, std::function > _market_subscriptions; graphene::chain::database& _db; const application_options* _app_options = nullptr; + const graphene::api_helper_indexes::amount_in_collateral_index* amount_in_collateral_index; }; ////////////////////////////////////////////////////////////////////// @@ -434,6 +420,16 @@ database_api_impl::database_api_impl( graphene::chain::database& db, const appli _pending_trx_connection = _db.on_pending_transaction.connect([this](const signed_transaction& trx ){ if( _pending_trx_callback ) _pending_trx_callback( fc::variant(trx, GRAPHENE_MAX_NESTED_OBJECTS) ); }); + try + { + amount_in_collateral_index = &_db.get_index_type< primary_index< call_order_index > >() + .get_secondary_index(); + } + catch( fc::assert_exception& e ) + { + wlog( "amount_in_collateral_index not found - please enable api_helper_indexes plugin!" ); + amount_in_collateral_index = nullptr; + } } database_api_impl::~database_api_impl() From 4bbbe1356030a856946f092c8676b8b82ecb0173 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Sat, 29 Jun 2019 17:00:00 +0200 Subject: [PATCH 015/111] Attempt to fix test timing --- tests/tests/database_api_tests.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/tests/database_api_tests.cpp b/tests/tests/database_api_tests.cpp index 6bafcd3caa..4b1d2b6b32 100644 --- a/tests/tests/database_api_tests.cpp +++ b/tests/tests/database_api_tests.cpp @@ -1588,6 +1588,7 @@ BOOST_AUTO_TEST_CASE( asset_in_collateral ) BOOST_CHECK_EQUAL( 0, oassets[3]->total_backing_collateral->value ); generate_block(); + fc::usleep(fc::milliseconds(100)); const auto& bitusd = bitusd_id( db ); const auto& bitdan = bitdan_id( db ); @@ -1658,6 +1659,7 @@ BOOST_AUTO_TEST_CASE( asset_in_collateral ) force_settle( dan_id(db), bitusd.amount(100) ); // settles against nathan, receives 500 CORE collateral generate_blocks( db.head_block_time() + fc::days(2) ); + fc::usleep(fc::milliseconds(100)); auto assets = db_api.list_assets( GRAPHENE_SYMBOL, 1 ); BOOST_REQUIRE( !assets.empty() ); From c567ee7885447d95c8e00086b100748b03341de7 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Sun, 30 Jun 2019 10:42:39 +0200 Subject: [PATCH 016/111] Avoid confusion with default copy/move constructors --- libraries/app/include/graphene/app/database_api.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/app/include/graphene/app/database_api.hpp b/libraries/app/include/graphene/app/database_api.hpp index 12092ab25c..604c797b94 100644 --- a/libraries/app/include/graphene/app/database_api.hpp +++ b/libraries/app/include/graphene/app/database_api.hpp @@ -129,8 +129,8 @@ struct market_trade struct extended_asset_object : asset_object { extended_asset_object() {} - template - explicit extended_asset_object( ASSET&& a ) : asset_object( std::forward(a) ) {} + explicit extended_asset_object( const asset_object& a ) : asset_object( a ) {} + explicit extended_asset_object( asset_object&& a ) : asset_object( std::move(a) ) {} optional total_in_collateral; optional total_backing_collateral; From 238a5995d2e32f1ad22aa08281f5bfcb70bd4361 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Mon, 1 Jul 2019 15:43:11 +0200 Subject: [PATCH 017/111] Enable new plugin by default --- programs/witness_node/main.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/programs/witness_node/main.cpp b/programs/witness_node/main.cpp index 016e53f2e2..acbda6386c 100644 --- a/programs/witness_node/main.cpp +++ b/programs/witness_node/main.cpp @@ -69,7 +69,8 @@ int main(int argc, char** argv) { ("data-dir,d", bpo::value()->default_value("witness_node_data_dir"), "Directory containing databases, configuration file, etc.") ("version,v", "Display version information") - ("plugins", bpo::value()->default_value("witness account_history market_history grouped_orders"), + ("plugins", bpo::value() + ->default_value("witness account_history market_history grouped_orders api_helper_indexes"), "Space-separated list of plugins to activate"); bpo::variables_map options; @@ -79,7 +80,8 @@ int main(int argc, char** argv) { cfg_options.add(cfg); cfg_options.add_options() - ("plugins", bpo::value()->default_value("witness account_history market_history grouped_orders"), + ("plugins", bpo::value() + ->default_value("witness account_history market_history grouped_orders api_helper_indexes"), "Space-separated list of plugins to activate"); auto witness_plug = node->register_plugin(); From 61364a6772f97a8375d585e70dab0fbc0505f7dc Mon Sep 17 00:00:00 2001 From: John Jones Date: Fri, 5 Jul 2019 15:08:52 -0500 Subject: [PATCH 018/111] Fix test for MSVC --- tests/tests/htlc_tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/tests/htlc_tests.cpp b/tests/tests/htlc_tests.cpp index b75aeed456..16a355b3a8 100644 --- a/tests/tests/htlc_tests.cpp +++ b/tests/tests/htlc_tests.cpp @@ -58,7 +58,7 @@ BOOST_FIXTURE_TEST_SUITE( htlc_tests, database_fixture ) void generate_random_preimage(uint16_t key_size, std::vector& vec) { - std::independent_bits_engine rbe; + std::independent_bits_engine rbe; std::generate(begin(vec), end(vec), std::ref(rbe)); return; } From 1c6fb9aff2eca7074c1cf09dee11daab3d4980aa Mon Sep 17 00:00:00 2001 From: John Jones Date: Fri, 5 Jul 2019 15:38:22 -0500 Subject: [PATCH 019/111] fix another independent_bits --- tests/tests/htlc_tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/tests/htlc_tests.cpp b/tests/tests/htlc_tests.cpp index 16a355b3a8..99b9295576 100644 --- a/tests/tests/htlc_tests.cpp +++ b/tests/tests/htlc_tests.cpp @@ -848,7 +848,7 @@ try { uint16_t preimage_size = 256; std::vector pre_image(256); - std::independent_bits_engine rbe; + std::independent_bits_engine rbe; std::generate(begin(pre_image), end(pre_image), std::ref(rbe)); graphene::chain::htlc_id_type alice_htlc_id_bob; graphene::chain::htlc_id_type alice_htlc_id_carl; From cc96750e6492dd8607222f395e8617e290c76dcf Mon Sep 17 00:00:00 2001 From: Alexey Frolov Date: Mon, 8 Jul 2019 14:31:37 +0300 Subject: [PATCH 020/111] code formatting --- tests/tests/block_tests.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/tests/block_tests.cpp b/tests/tests/block_tests.cpp index 22ba8c45ab..d93d9820a2 100644 --- a/tests/tests/block_tests.cpp +++ b/tests/tests/block_tests.cpp @@ -1459,7 +1459,8 @@ BOOST_FIXTURE_TEST_CASE( miss_many_blocks, database_fixture ) generate_block(); auto missed_before = get_misses( db ); // miss 9 maintenance intervals - generate_blocks( db.get_dynamic_global_properties().next_maintenance_time + db.get_global_properties().parameters.maintenance_interval * 9, true ); + generate_blocks( db.get_dynamic_global_properties().next_maintenance_time + + db.get_global_properties().parameters.maintenance_interval * 9, true ); generate_block(); generate_block(); generate_block(); From 6ca701cc46299488aa55d401f8ae81825adaee47 Mon Sep 17 00:00:00 2001 From: Alfredo Date: Sun, 14 Jul 2019 12:19:20 -0300 Subject: [PATCH 021/111] add list_htlcs database api call --- libraries/app/application.cpp | 3 ++ libraries/app/database_api.cpp | 21 +++++++++++++ .../app/include/graphene/app/application.hpp | 1 + .../app/include/graphene/app/database_api.hpp | 10 ++++++ tests/tests/htlc_tests.cpp | 31 +++++++++++++++++++ 5 files changed, 66 insertions(+) diff --git a/libraries/app/application.cpp b/libraries/app/application.cpp index cdb75f57fe..6ee4c74a08 100644 --- a/libraries/app/application.cpp +++ b/libraries/app/application.cpp @@ -364,6 +364,9 @@ void application_impl::set_api_limit() { if(_options->count("api-limit-get-order-book")){ _app_options.api_limit_get_order_book = _options->at("api-limit-get-order-book").as(); } + if(_options->count("api-limit-list-htlcs")){ + _app_options.api_limit_list_htlcs = _options->at("api-limit-list-htlcs").as(); + } } void application_impl::startup() diff --git a/libraries/app/database_api.cpp b/libraries/app/database_api.cpp index 6c12eeecf5..1e15857f0a 100644 --- a/libraries/app/database_api.cpp +++ b/libraries/app/database_api.cpp @@ -183,6 +183,7 @@ class database_api_impl : public std::enable_shared_from_this optional get_htlc(htlc_id_type id) const; vector get_htlc_by_from(const std::string account_id_or_name, htlc_id_type start, uint32_t limit) const; vector get_htlc_by_to(const std::string account_id_or_name, htlc_id_type start, uint32_t limit) const; + vector list_htlcs(const htlc_id_type lower_bound_id, uint32_t limit) const; //private: static string price_to_string( const price& _price, const asset_object& _base, const asset_object& _quote ); @@ -2642,6 +2643,26 @@ vector database_api_impl::get_htlc_by_to(const std::string account_ return result; } +vector database_api::list_htlcs(const htlc_id_type start, uint32_t limit)const +{ + return my->list_htlcs(start, limit); +} + +vector database_api_impl::list_htlcs(const htlc_id_type start, uint32_t limit) const +{ + FC_ASSERT( limit <= _app_options->api_limit_list_htlcs ); + + vector result; + const auto& htlc_idx = _db.get_index_type().indices().get(); + auto itr = htlc_idx.lower_bound(start); + while(itr != htlc_idx.end() && result.size() < limit) + { + result.push_back(*itr); + ++itr; + } + return result; +} + ////////////////////////////////////////////////////////////////////// // // // Private methods // diff --git a/libraries/app/include/graphene/app/application.hpp b/libraries/app/include/graphene/app/application.hpp index 30dfc53f2a..4df4cf6100 100644 --- a/libraries/app/include/graphene/app/application.hpp +++ b/libraries/app/include/graphene/app/application.hpp @@ -55,6 +55,7 @@ namespace graphene { namespace app { uint64_t api_limit_get_assets = 101; uint64_t api_limit_get_limit_orders = 300; uint64_t api_limit_get_order_book = 50; + uint64_t api_limit_list_htlcs = 100; }; class application diff --git a/libraries/app/include/graphene/app/database_api.hpp b/libraries/app/include/graphene/app/database_api.hpp index 13734e751b..b56e9df169 100644 --- a/libraries/app/include/graphene/app/database_api.hpp +++ b/libraries/app/include/graphene/app/database_api.hpp @@ -821,6 +821,15 @@ class database_api */ vector get_htlc_by_to(const std::string account_id_or_name, htlc_id_type start, uint32_t limit) const; + /** + * @brief Get all HTLCs + * @param start Lower bound of htlc id to start getting results + * @param limit Maximum number of htlc objects to fetch + * @return The htlc object list + */ + vector list_htlcs(const htlc_id_type start, uint32_t limit) const; + + private: std::shared_ptr< database_api_impl > my; }; @@ -953,4 +962,5 @@ FC_API(graphene::app::database_api, (get_htlc) (get_htlc_by_from) (get_htlc_by_to) + (list_htlcs) ) diff --git a/tests/tests/htlc_tests.cpp b/tests/tests/htlc_tests.cpp index b75aeed456..6dd16e3733 100644 --- a/tests/tests/htlc_tests.cpp +++ b/tests/tests/htlc_tests.cpp @@ -978,6 +978,37 @@ try { full = db_api.get_full_accounts({bob.name}, false); BOOST_CHECK_EQUAL( full[bob.name].htlcs_to.size(), 1 ); + auto list = db_api.list_htlcs(graphene::chain::htlc_id_type(0), 1); + BOOST_CHECK_EQUAL( list.size(), 1 ); + BOOST_CHECK_EQUAL( list[0].id.instance(), 0 ); + + list = db_api.list_htlcs(graphene::chain::htlc_id_type(1), 1); + BOOST_CHECK_EQUAL( list.size(), 1 ); + BOOST_CHECK_EQUAL( list[0].id.instance(), 1 ); + + list = db_api.list_htlcs(graphene::chain::htlc_id_type(2), 1); + BOOST_CHECK_EQUAL( list.size(), 1 ); + BOOST_CHECK_EQUAL( list[0].id.instance(), 2 ); + + list = db_api.list_htlcs(graphene::chain::htlc_id_type(1), 2); + BOOST_CHECK_EQUAL( list.size(), 2 ); + BOOST_CHECK_EQUAL( list[0].id.instance(), 1 ); + BOOST_CHECK_EQUAL( list[1].id.instance(), 2 ); + + list = db_api.list_htlcs(graphene::chain::htlc_id_type(1), 3); + BOOST_CHECK_EQUAL( list.size(), 2 ); + BOOST_CHECK_EQUAL( list[0].id.instance(), 1 ); + BOOST_CHECK_EQUAL( list[1].id.instance(), 2 ); + + list = db_api.list_htlcs(graphene::chain::htlc_id_type(0), 100); + BOOST_CHECK_EQUAL( list.size(), 3 ); + BOOST_CHECK_EQUAL( list[0].id.instance(), 0 ); + BOOST_CHECK_EQUAL( list[1].id.instance(), 1 ); + BOOST_CHECK_EQUAL( list[2].id.instance(), 2 ); + + list = db_api.list_htlcs(graphene::chain::htlc_id_type(10), 100); + BOOST_CHECK_EQUAL( list.size(), 0 ); + } catch (fc::exception &e) { edump((e.to_detail_string())); throw; From 2a6d7b26c861dfbe691d8e1233792c121a0eee8e Mon Sep 17 00:00:00 2001 From: Alfredo Date: Mon, 15 Jul 2019 13:45:12 -0300 Subject: [PATCH 022/111] add is_plugin_enabled to application --- libraries/app/api.cpp | 5 +++-- libraries/app/application.cpp | 7 +++++++ libraries/app/include/graphene/app/application.hpp | 5 ++++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/libraries/app/api.cpp b/libraries/app/api.cpp index f1a8b909f7..2bdc8de93e 100644 --- a/libraries/app/api.cpp +++ b/libraries/app/api.cpp @@ -328,9 +328,10 @@ namespace graphene { namespace app { start = node.operation_id; } catch(...) { return result; } - auto es = _app.get_plugin("elasticsearch"); - if(es) + if(_app.is_plugin_enabled("elasticsearch")) { + auto es = _app.get_plugin("elasticsearch"); return es->get_account_history(account, stop, limit, start); + } const auto& hist_idx = db.get_index_type(); const auto& by_op_idx = hist_idx.indices().get(); diff --git a/libraries/app/application.cpp b/libraries/app/application.cpp index 4217b2e934..909bfd87e1 100644 --- a/libraries/app/application.cpp +++ b/libraries/app/application.cpp @@ -1073,6 +1073,13 @@ std::shared_ptr application::get_plugin(const string& name) con return my->_active_plugins[name]; } +bool application::is_plugin_enabled(const string& name) const +{ + if(my->_active_plugins.find(name) == my->_active_plugins.end()) + return false; + return true; +} + net::node_ptr application::p2p_node() { return my->_p2p_network; diff --git a/libraries/app/include/graphene/app/application.hpp b/libraries/app/include/graphene/app/application.hpp index 6f1a0d6e90..c1feb73422 100644 --- a/libraries/app/include/graphene/app/application.hpp +++ b/libraries/app/include/graphene/app/application.hpp @@ -117,7 +117,10 @@ namespace graphene { namespace app { void enable_plugin( const string& name ); - private: + bool is_plugin_enabled(const string& name) const; + + + private: void add_available_plugin( std::shared_ptr p ); std::shared_ptr my; From 1737d455e9c087159287133f55f4a879b9c0d913 Mon Sep 17 00:00:00 2001 From: Alfredo Date: Mon, 15 Jul 2019 18:40:52 -0300 Subject: [PATCH 023/111] add elasticsearch-mode command for save, query or all --- .../elasticsearch/elasticsearch_plugin.cpp | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp b/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp index 9f3e70599a..c68454a153 100644 --- a/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp +++ b/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp @@ -59,6 +59,7 @@ class elasticsearch_plugin_impl bool _elasticsearch_operation_object = false; uint32_t _elasticsearch_start_es_after_block = 0; bool _elasticsearch_operation_string = true; + std::string _elasticsearch_mode = "only_save"; CURL *curl; // curl handler vector bulk_lines; // vector of op lines vector prepare; @@ -436,17 +437,13 @@ void elasticsearch_plugin::plugin_set_program_options( ("elasticsearch-operation-object", boost::program_options::value(), "Save operation as object(false)") ("elasticsearch-start-es-after-block", boost::program_options::value(), "Start doing ES job after block(0)") ("elasticsearch-operation-string", boost::program_options::value(), "Save operation as string. Needed to serve history api calls(true)") + ("elasticsearch-mode", boost::program_options::value(), "Mode of operation: only_save, only_query, all(only_save)") ; cfg.add(cli); } void elasticsearch_plugin::plugin_initialize(const boost::program_options::variables_map& options) { - database().applied_block.connect( [&]( const signed_block& b) { - if (!my->update_account_histories(b)) - FC_THROW_EXCEPTION(graphene::chain::plugin_exception, "Error populating ES database, we are going to keep trying."); - } ); - my->_oho_index = database().add_index< primary_index< operation_history_index > >(); database().add_index< primary_index< account_transaction_history_index > >(); @@ -477,6 +474,19 @@ void elasticsearch_plugin::plugin_initialize(const boost::program_options::varia if (options.count("elasticsearch-operation-string")) { my->_elasticsearch_operation_string = options["elasticsearch-operation-string"].as(); } + if (options.count("elasticsearch-mode")) { + my->_elasticsearch_mode = options["elasticsearch-mode"].as(); + } + + if(my->_elasticsearch_mode != "only_query") { + if (my->_elasticsearch_mode == "all") + my->_elasticsearch_operation_string = true; + + database().applied_block.connect([&](const signed_block &b) { + if (!my->update_account_histories(b)) + FC_THROW_EXCEPTION(graphene::chain::plugin_exception, "Error populating ES database, we are going to keep trying."); + }); + } } void elasticsearch_plugin::plugin_startup() From 6dda9fe28c9418570a749a83f09e4bb7e5325cd1 Mon Sep 17 00:00:00 2001 From: Alfredo Date: Tue, 16 Jul 2019 11:52:28 -0300 Subject: [PATCH 024/111] execute elasticsearch account_history in a new thread --- libraries/app/api.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/app/api.cpp b/libraries/app/api.cpp index 2bdc8de93e..7b3d36a02f 100644 --- a/libraries/app/api.cpp +++ b/libraries/app/api.cpp @@ -330,7 +330,9 @@ namespace graphene { namespace app { if(_app.is_plugin_enabled("elasticsearch")) { auto es = _app.get_plugin("elasticsearch"); - return es->get_account_history(account, stop, limit, start); + auto _thread = std::make_shared("elasticsearch"); + return _thread->async([&](){ return es->get_account_history(account, stop, limit, start); }, + "thread invoke for method " BOOST_PP_STRINGIZE(method_name)).wait(); } const auto& hist_idx = db.get_index_type(); From 048cc49834f50e179d5b6e26ed3ebb5a43c2d25e Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Mon, 22 Jul 2019 09:30:12 -0300 Subject: [PATCH 025/111] typo in vote_for_committee_member description --- libraries/wallet/include/graphene/wallet/wallet.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index 1fc432ce1c..2205e724cf 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -1519,8 +1519,8 @@ class wallet_api /** Vote for a given committee_member. * - * An account can publish a list of all committee_memberes they approve of. This - * command allows you to add or remove committee_memberes from this list. + * An account can publish a list of all committee_members they approve of. This + * command allows you to add or remove committee_members from this list. * Each account's vote is weighted according to the number of shares of the * core asset owned by that account at the time the votes are tallied. * From ee0169ded266219f9a04ceaebe1a7f923013e2db Mon Sep 17 00:00:00 2001 From: abitmore Date: Tue, 23 Jul 2019 07:17:20 -0400 Subject: [PATCH 026/111] Fix API docs --- libraries/app/include/graphene/app/database_api.hpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/libraries/app/include/graphene/app/database_api.hpp b/libraries/app/include/graphene/app/database_api.hpp index 13734e751b..cf9dddba04 100644 --- a/libraries/app/include/graphene/app/database_api.hpp +++ b/libraries/app/include/graphene/app/database_api.hpp @@ -335,9 +335,9 @@ class database_api optional ostart_price = optional()); /** - * @brief Fetch all objects relevant to the specified accounts and subscribe to updates - * @param callback Function to call with updates + * @brief Fetch all objects relevant to the specified accounts and optionally subscribe to updates * @param names_or_ids Each item must be the name or ID of an account to retrieve + * @param subscribe whether subscribe to updates * @return Map of string from @ref names_or_ids to the corresponding account * * This function fetches all relevant objects for the given accounts, and subscribes to updates to the given @@ -347,10 +347,17 @@ class database_api */ std::map get_full_accounts( const vector& names_or_ids, bool subscribe ); + /** + * @brief Get info of an account by name + * @param name Name of the account to retrieve + * @return The account holding the provided name + */ optional get_account_by_name( string name )const; /** - * @return all accounts that referr to the key or account id in their owner or active authorities. + * @brief Get all accounts that refer to the specified account in their owner or active authorities + * @param account_id_or_name Account ID or name to query + * @return all accounts that refer to the specified account in their owner or active authorities */ vector get_account_references( const std::string account_id_or_name )const; From bac458a8ad0400da663b3cbd19504eceb08e0dbb Mon Sep 17 00:00:00 2001 From: abitmore Date: Tue, 23 Jul 2019 17:58:34 -0400 Subject: [PATCH 027/111] Update database API docs, wrap long lines --- .../app/include/graphene/app/database_api.hpp | 365 +++++++++++------- 1 file changed, 225 insertions(+), 140 deletions(-) diff --git a/libraries/app/include/graphene/app/database_api.hpp b/libraries/app/include/graphene/app/database_api.hpp index cf9dddba04..28424f0d65 100644 --- a/libraries/app/include/graphene/app/database_api.hpp +++ b/libraries/app/include/graphene/app/database_api.hpp @@ -158,13 +158,13 @@ class database_api /** * @brief Register a callback handle which then can be used to subscribe to object database changes * @param cb The callback handle to register - * @param nofity_remove_create Whether subscribe to universal object creation and removal events. + * @param notify_remove_create Whether subscribe to universal object creation and removal events. * If this is set to true, the API server will notify all newly created objects and ID of all * newly removed objects to the client, no matter whether client subscribed to the objects. * By default, API servers don't allow subscribing to universal events, which can be changed * on server startup. * - * Note: auto-subscription is enabled by default and can be disabled with "set_auto_subscription" API. + * Note: auto-subscription is enabled by default and can be disabled with @ref set_auto_subscription API. */ void set_subscribe_callback( std::function cb, bool notify_remove_create ); /** @@ -215,12 +215,11 @@ class database_api /** * @brief Retrieve multiple block header by block numbers - * @param block_num vector containing heights of the block whose header should be returned + * @param block_nums vector containing heights of the block whose header should be returned * @return array of headers of the referenced blocks, or null if no matching block was found */ map> get_block_header_batch(const vector block_nums)const; - /** * @brief Retrieve a full, signed block * @param block_num Height of the block to be returned @@ -230,6 +229,9 @@ class database_api /** * @brief used to fetch an individual transaction. + * @param block_num height of the block to fetch + * @param trx_in_block the index (sequence number) of the transaction in the block, starts from 0 + * @return the transaction at the given position */ processed_transaction get_transaction( uint32_t block_num, uint32_t trx_in_block )const; @@ -237,20 +239,23 @@ class database_api * If the transaction has not expired, this method will return the transaction for the given ID or * it will return NULL if it is not known. Just because it is not known does not mean it wasn't * included in the blockchain. + * + * @param txid hash of the transaction + * @return the corresponding transaction if found, or null if not found */ - optional get_recent_transaction_by_id( const transaction_id_type& id )const; + optional get_recent_transaction_by_id( const transaction_id_type& txid )const; ///////////// // Globals // ///////////// /** - * @brief Retrieve the @ref chain_property_object associated with the chain + * @brief Retrieve the @ref graphene::chain::chain_property_object associated with the chain */ chain_property_object get_chain_properties()const; /** - * @brief Retrieve the current @ref global_property_object + * @brief Retrieve the current @ref graphene::chain::global_property_object */ global_property_object get_global_properties()const; @@ -265,7 +270,7 @@ class database_api chain_id_type get_chain_id()const; /** - * @brief Retrieve the current @ref dynamic_global_property_object + * @brief Retrieve the current @ref graphene::chain::dynamic_global_property_object */ dynamic_global_property_object get_dynamic_global_properties()const; @@ -273,75 +278,52 @@ class database_api // Keys // ////////// - vector> get_key_references( vector key )const; + /** + * @brief Get all accounts that refer to the specified public keys in their owner authority, active authorities + * or memo key + * @param keys a list of public keys to query + * @return ID of all accounts that refer to the specified keys + */ + vector> get_key_references( vector keys )const; - /** - * Determine whether a textual representation of a public key - * (in Base-58 format) is *currently* linked - * to any *registered* (i.e. non-stealth) account on the blockchain - * @param public_key Public key - * @return Whether a public key is known - */ - bool is_public_key_registered(string public_key) const; + /** + * Determine whether a textual representation of a public key + * (in Base-58 format) is *currently* linked + * to any *registered* (i.e. non-stealth) account on the blockchain + * @param public_key Public key + * @return Whether a public key is known + */ + bool is_public_key_registered(string public_key) const; ////////////// // Accounts // ////////////// - /** - * @brief Get account object from a name or ID - * @param account_name_or_id ID or name of the accounts - * @return Account ID - * - */ - account_id_type get_account_id_from_string(const std::string& name_or_id) const; - /** - * @brief Get a list of accounts by ID - * @param account_names_or_ids IDs or names of the accounts to retrieve - * @return The accounts corresponding to the provided IDs + * @brief Get account object from a name or ID + * @param name_or_id name or ID of the account + * @return Account ID * - * This function has semantics identical to @ref get_objects */ - vector> get_accounts(const vector& account_names_or_ids)const; + account_id_type get_account_id_from_string(const std::string& name_or_id) const; /** - * @brief Fetch all orders relevant to the specified account and specified market, result orders - * are sorted descendingly by price + * @brief Get a list of accounts by IDs or names + * @param account_names_or_ids names or IDs of the accounts to retrieve + * @return The accounts corresponding to the provided IDs or names * - * @param account_name_or_id The name or ID of an account to retrieve - * @param base Base asset - * @param quote Quote asset - * @param limit The limitation of items each query can fetch, not greater than 101 - * @param start_id Start order id, fetch orders which price lower than this order, or price equal to this order - * but order ID greater than this order - * @param start_price Fetch orders with price lower than or equal to this price - * - * @return List of orders from @ref account_name_or_id to the corresponding account - * - * @note - * 1. if @ref account_name_or_id cannot be tied to an account, empty result will be returned - * 2. @ref start_id and @ref start_price can be empty, if so the api will return the "first page" of orders; - * if start_id is specified, its price will be used to do page query preferentially, otherwise the start_price - * will be used; start_id and start_price may be used cooperatively in case of the order specified by start_id - * was just canceled accidentally, in such case, the result orders' price may lower or equal to start_price, - * but orders' id greater than start_id + * This function has semantics identical to @ref get_objects */ - vector get_account_limit_orders( const string& account_name_or_id, - const string &base, - const string "e, - uint32_t limit = 101, - optional ostart_id = optional(), - optional ostart_price = optional()); + vector> get_accounts(const vector& account_names_or_ids)const; /** * @brief Fetch all objects relevant to the specified accounts and optionally subscribe to updates * @param names_or_ids Each item must be the name or ID of an account to retrieve * @param subscribe whether subscribe to updates - * @return Map of string from @ref names_or_ids to the corresponding account + * @return Map of string from @p names_or_ids to the corresponding account * * This function fetches all relevant objects for the given accounts, and subscribes to updates to the given - * accounts. If any of the strings in @ref names_or_ids cannot be tied to an account, that input will be + * accounts. If any of the strings in @p names_or_ids cannot be tied to an account, that input will be * ignored. All other accounts will be retrieved and subscribed. * */ @@ -356,10 +338,10 @@ class database_api /** * @brief Get all accounts that refer to the specified account in their owner or active authorities - * @param account_id_or_name Account ID or name to query + * @param account_name_or_id Account name or ID to query * @return all accounts that refer to the specified account in their owner or active authorities */ - vector get_account_references( const std::string account_id_or_name )const; + vector get_account_references( const std::string account_name_or_id )const; /** * @brief Get a list of accounts by name @@ -384,21 +366,37 @@ class database_api /** * @brief Get an account's balances in various assets - * @param account_name_or_id ID or name of the account to get balances for + * @param account_name_or_id name or ID of the account to get balances for * @param assets IDs of the assets to get balances of; if empty, get all assets account has a balance in * @return Balances of the account */ - vector get_account_balances(const std::string& account_name_or_id, const flat_set& assets)const; + vector get_account_balances( const std::string& account_name_or_id, + const flat_set& assets )const; - /// Semantically equivalent to @ref get_account_balances, but takes a name instead of an ID. + /// Semantically equivalent to @ref get_account_balances. vector get_named_account_balances(const std::string& name, const flat_set& assets)const; - /** @return all unclaimed balance objects for a set of addresses */ + /** + * @brief Return all unclaimed balance objects for a list of addresses + * @param addrs a list of addresses + * @return all unclaimed balance objects for the addresses + */ vector get_balance_objects( const vector
& addrs )const; + /** + * @brief Calculate how much assets in the given balance objects are able to be claimed at current head + * block time + * @param objs a list of balance object IDs + * @return a list indicating how much asset in each balance object is available to be claimed + */ vector get_vested_balances( const vector& objs )const; - vector get_vesting_balances( const std::string account_id_or_name )const; + /** + * @brief Return all vesting balance objects owned by an account + * @param account_name_or_id name or ID of an account + * @return all vesting balance objects owned by the account + */ + vector get_vesting_balances( const std::string account_name_or_id )const; /** * @brief Get the total number of accounts registered with the blockchain @@ -409,17 +407,17 @@ class database_api // Assets // //////////// - /** - * @brief Get asset id from a symbol or ID - * @param symbol_or_id ID or symbol of the asset - * @return asset id - */ + /** + * @brief Get asset ID from an asset symbol or ID + * @param symbol_or_id symbol name or ID of the asset + * @return asset ID + */ asset_id_type get_asset_id_from_string(const std::string& symbol_or_id) const; /** - * @brief Get a list of assets by ID - * @param asset_symbols_or_ids Symbol names or IDs of the assets to retrieve - * @return The assets corresponding to the provided IDs + * @brief Get a list of assets by symbol names or IDs + * @param asset_symbols_or_ids symbol names or IDs of the assets to retrieve + * @return The assets corresponding to the provided symbol names or IDs * * This function has semantics identical to @ref get_objects */ @@ -434,11 +432,11 @@ class database_api vector list_assets(const string& lower_bound_symbol, uint32_t limit)const; /** - * @brief Get a list of assets by symbol - * @param asset_symbols Symbols or stringified IDs of the assets to retrieve + * @brief Get a list of assets by symbol names or IDs + * @param symbols_or_ids symbol names or IDs of the assets to retrieve * @return The assets corresponding to the provided symbols or IDs * - * This function has semantics identical to @ref get_objects + * This function has semantics identical to @ref get_objects, but doesn't subscribe */ vector> lookup_asset_symbols(const vector& symbols_or_ids)const; @@ -449,11 +447,11 @@ class database_api uint64_t get_asset_count()const; /** - * @brief Get asset objects issued from a given account - * @param account_name_or_id Account name or ID to get objects from + * @brief Get assets issued (owned) by a given account + * @param issuer_name_or_id Account name or ID to get objects from * @param start Asset objects(1.3.X) before this ID will be skipped in results. Pagination purposes. * @param limit Maximum number of orders to retrieve - * @return The assets issued by the account + * @return The assets issued (owned) by the account */ vector get_assets_by_issuer(const std::string& issuer_name_or_id, asset_id_type start, uint32_t limit)const; @@ -464,23 +462,53 @@ class database_api /** * @brief Get limit orders in a given market - * @param a Symbol or ID of asset being sold - * @param b Symbol or ID of asset being purchased + * @param a symbol or ID of asset being sold + * @param b symbol or ID of asset being purchased * @param limit Maximum number of orders to retrieve * @return The limit orders, ordered from least price to greatest */ vector get_limit_orders(std::string a, std::string b, uint32_t limit)const; /** - * @brief Get call orders in a given asset - * @param a Symbol or ID of asset being called + * @brief Fetch all orders relevant to the specified account and specified market, result orders + * are sorted descendingly by price + * + * @param account_name_or_id The name or ID of an account to retrieve + * @param base Base asset + * @param quote Quote asset + * @param limit The limitation of items each query can fetch, not greater than 101 + * @param ostart_id Start order id, fetch orders which price lower than this order, + * or price equal to this order but order ID greater than this order + * @param ostart_price Fetch orders with price lower than or equal to this price + * + * @return List of orders from @p account_name_or_id to the corresponding account + * + * @note + * 1. if @p account_name_or_id cannot be tied to an account, empty result will be returned + * 2. @p ostart_id and @p ostart_price can be empty, if so the api will return the "first page" of orders; + * if @p ostart_id is specified, its price will be used to do page query preferentially, + * otherwise the @p ostart_price will be used; + * @p ostart_id and @p ostart_price may be used cooperatively in case of the order specified by @p ostart_id + * was just canceled accidentally, in such case, the result orders' price may lower or equal to + * @p ostart_price, but orders' id greater than @p ostart_id + */ + vector get_account_limit_orders( const string& account_name_or_id, + const string &base, + const string "e, + uint32_t limit = 101, + optional ostart_id = optional(), + optional ostart_price = optional()); + + /** + * @brief Get call orders (aka margin positions) for a given asset + * @param a symbol name or ID of the debt asset * @param limit Maximum number of orders to retrieve * @return The call orders, ordered from earliest to be called to latest */ vector get_call_orders(const std::string& a, uint32_t limit)const; /** - * @brief Get call orders from a given account + * @brief Get call orders (aka margin positions) of a given account * @param account_name_or_id Account name or ID to get objects from * @param start Asset objects(1.3.X) before this ID will be skipped in results. Pagination purposes. * @param limit Maximum number of objects to retrieve @@ -504,8 +532,9 @@ class database_api * @param limit Maximum number of orders to retrieve * @return The settle orders of the account */ - vector get_settle_orders_by_account(const std::string& account_name_or_id, - force_settlement_id_type start, uint32_t limit)const; + vector get_settle_orders_by_account( const std::string& account_name_or_id, + force_settlement_id_type start, + uint32_t limit )const; /** * @brief Get collateral_bid_objects for a given asset @@ -517,15 +546,19 @@ class database_api vector get_collateral_bids(const std::string& a, uint32_t limit, uint32_t start)const; /** - * @return all open margin positions for a given account id or name. + * @brief Get all open margin positions of a given account + * @param account_name_or_id name or ID of an account + * @return all open margin positions of the account + * + * Similar to @ref get_call_orders_by_account, but without pagination. */ - vector get_margin_positions( const std::string account_id_or_name )const; + vector get_margin_positions( const std::string account_name_or_id )const; /** * @brief Request notification when the active orders in the market between two assets changes * @param callback Callback method which is called when the market changes - * @param a First asset Symbol or ID - * @param b Second asset Symbol or ID + * @param a symbol name or ID of the first asset + * @param b symbol name or ID of the second asset * * Callback will be passed a variant containing a vector>. The vector will * contain, in order, the operations which changed the market, and their results. @@ -535,32 +568,32 @@ class database_api /** * @brief Unsubscribe from updates to a given market - * @param a First asset Symbol ID - * @param b Second asset Symbol ID + * @param a symbol name or ID of the first asset + * @param b symbol name or ID of the second asset */ void unsubscribe_from_market( const std::string& a, const std::string& b ); /** * @brief Returns the ticker for the market assetA:assetB - * @param a String name of the first asset - * @param b String name of the second asset + * @param base symbol name or ID of the base asset + * @param quote symbol name or ID of the quote asset * @return The market ticker for the past 24 hours. */ market_ticker get_ticker( const string& base, const string& quote )const; /** * @brief Returns the 24 hour volume for the market assetA:assetB - * @param a String name of the first asset - * @param b String name of the second asset + * @param base symbol name or ID of the base asset + * @param quote symbol name or ID of the quote asset * @return The market volume over the past 24 hours */ market_volume get_24_volume( const string& base, const string& quote )const; /** * @brief Returns the order book for the market base:quote - * @param base String name of the first asset - * @param quote String name of the second asset - * @param depth of the order book. Up to depth of each asks and bids, capped at 50. Prioritizes most moderate of each + * @param base symbol name or ID of the base asset + * @param quote symbol name or ID of the quote asset + * @param limit depth of the order book to retrieve, for bids and asks each, capped at 50 * @return Order book of the market */ order_book get_order_book( const string& base, const string& quote, unsigned limit = 50 )const; @@ -577,7 +610,7 @@ class database_api * @brief Returns recent trades for the market base:quote, ordered by time, most recent first. * Note: Currently, timezone offsets are not supported. The time must be UTC. The range is [stop, start). * In case when there are more than 100 trades occurred in the same second, this API only returns - * the first 100 records, can use another API `get_trade_history_by_sequence` to query for the rest. + * the first 100 records, can use another API @ref get_trade_history_by_sequence to query for the rest. * @param base symbol or ID of the base asset * @param quote symbol or ID of the quote asset * @param start Start time as a UNIX timestamp, the latest trade to retrieve @@ -620,10 +653,10 @@ class database_api /** * @brief Get the witness owned by a given account - * @param account_id_or_name The ID of the account whose witness should be retrieved + * @param account_name_or_id The name or ID of the account whose witness should be retrieved * @return The witness object, or null if the account does not have a witness */ - fc::optional get_witness_by_account(const std::string account_id_or_name)const; + fc::optional get_witness_by_account(const std::string account_name_or_id)const; /** * @brief Get names and IDs for registered witnesses @@ -649,14 +682,15 @@ class database_api * * This function has semantics identical to @ref get_objects */ - vector> get_committee_members(const vector& committee_member_ids)const; + vector> get_committee_members( + const vector& committee_member_ids)const; /** * @brief Get the committee_member owned by a given account - * @param account The ID or name of the account whose committee_member should be retrieved + * @param account_name_or_id The name or ID of the account whose committee_member should be retrieved * @return The committee_member object, or null if the account does not have a committee_member */ - fc::optional get_committee_member_by_account(const std::string account_id_or_name)const; + fc::optional get_committee_member_by_account( const string account_name_or_id )const; /** * @brief Get names and IDs for registered committee_members @@ -664,7 +698,8 @@ class database_api * @param limit Maximum number of results to return -- must not exceed 1000 * @return Map of committee_member names to corresponding IDs */ - map lookup_committee_member_accounts(const string& lower_bound_name, uint32_t limit)const; + map lookup_committee_member_accounts( const string& lower_bound_name, + uint32_t limit )const; /** * @brief Get the total number of committee registered with the blockchain @@ -685,10 +720,10 @@ class database_api /** * @brief Get the workers owned by a given account - * @param account_id_or_name The ID or name of the account whose worker should be retrieved - * @return The worker object, or null if the account does not have a worker + * @param account_name_or_id The name or ID of the account whose worker should be retrieved + * @return A list of worker objects owned by the account */ - vector> get_workers_by_account(const std::string account_id_or_name)const; + vector> get_workers_by_account(const std::string account_name_or_id)const; /** * @brief Get the total number of workers registered with the blockchain @@ -702,12 +737,14 @@ class database_api /////////// /** - * @brief Given a set of votes, return the objects they are voting for. + * @brief Given a set of votes, return the objects they are voting for + * @param votes a list of vote IDs + * @return the referenced objects * - * This will be a mixture of committee_member_object, witness_objects, and worker_objects + * This will be a mixture of committee_member_objects, witness_objects, and worker_objects * - * The results will be in the same order as the votes. Null will be returned for - * any vote ids that are not found. + * The results will be in the same order as the votes. Null will be returned for + * any vote IDs that are not found. */ vector lookup_vote_ids( const vector& votes )const; @@ -715,65 +752,103 @@ class database_api // Authority / validation // //////////////////////////// - /// @brief Get a hexdump of the serialized binary form of a transaction + /** + * @brief Get a hexdump of the serialized binary form of a transaction + * @param trx a transaction to get hexdump from + * @return the hexdump of the transaction + */ std::string get_transaction_hex(const signed_transaction& trx)const; - /// @brief Get a hexdump of the serialized binary form of a - /// signatures-stripped transaction + /** + * @brief Get a hexdump of the serialized binary form of a signatures-stripped transaction + * @param trx a transaction to get hexdump from + * @return the hexdump of the transaction without the signatures + */ std::string get_transaction_hex_without_sig( const signed_transaction &trx ) const; /** - * This API will take a partially signed transaction and a set of public keys that the owner has the ability to sign for - * and return the minimal subset of public keys that should add signatures to the transaction. + * This API will take a partially signed transaction and a set of public keys that the owner + * has the ability to sign for and return the minimal subset of public keys that should add + * signatures to the transaction. + * + * @param trx the transaction to be signed + * @param available_keys a set of public keys + * @return a subset of @p available_keys that could sign for the given transaction */ - set get_required_signatures( const signed_transaction& trx, const flat_set& available_keys )const; + set get_required_signatures( const signed_transaction& trx, + const flat_set& available_keys )const; /** - * This method will return the set of all public keys that could possibly sign for a given transaction. This call can - * be used by wallets to filter their set of public keys to just the relevant subset prior to calling @ref get_required_signatures - * to get the minimum subset. + * This method will return the set of all public keys that could possibly sign for a given transaction. + * This call can be used by wallets to filter their set of public keys to just the relevant subset prior + * to calling @ref get_required_signatures to get the minimum subset. + * + * @param trx the transaction to be signed + * @return a set of public keys that could possibly sign for the given transaction */ set get_potential_signatures( const signed_transaction& trx )const; + + /** + * This method will return the set of all addresses that could possibly sign for a given transaction. + * + * @param trx the transaction to be signed + * @return a set of addresses that could possibly sign for the given transaction + */ set
get_potential_address_signatures( const signed_transaction& trx )const; /** - * @return true of the @ref trx has all of the required signatures, otherwise throws an exception + * Check whether a transaction has all of the required signatures + * @param trx a transaction to be verified + * @return true if the @p trx has all of the required signatures, otherwise throws an exception */ bool verify_authority( const signed_transaction& trx )const; /** * @brief Verify that the public keys have enough authority to approve an operation for this account - * @param account_name_or_id the account to check + * @param account_name_or_id name or ID of an account to check * @param signers the public keys * @return true if the passed in keys have enough authority to approve an operation for this account */ - bool verify_account_authority( const string& account_name_or_id, const flat_set& signers )const; + bool verify_account_authority( const string& account_name_or_id, + const flat_set& signers )const; /** - * Validates a transaction against the current state without broadcasting it on the network. + * @brief Validates a transaction against the current state without broadcasting it on the network + * @param trx a transaction to be validated + * @return a processed_transaction object if the transaction passes the validation, + otherwise an exception will be thrown */ processed_transaction validate_transaction( const signed_transaction& trx )const; /** - * For each operation calculate the required fee in the specified asset type. + * @brief For each operation calculate the required fee in the specified asset type + * @param ops a list of operations to be query for required fees + * @param asset_symbol_or_id symbol name or ID of an asset that to be used to pay the fees + * @return a list of objects which indicates required fees of each operation */ - vector< fc::variant > get_required_fees( const vector& ops, const std::string& asset_id_or_symbol )const; + vector< fc::variant > get_required_fees( const vector& ops, + const std::string& asset_symbol_or_id )const; /////////////////////////// // Proposed transactions // /////////////////////////// /** - * @return the set of proposed transactions relevant to the specified account id. + * @brief return a set of proposed transactions (aka proposals) that the specified account + * can add approval to or remove approval from + * @param account_name_or_id The name or ID of an account + * @return a set of proposed transactions that the specified account can act on */ - vector get_proposed_transactions( const std::string account_id_or_name )const; + vector get_proposed_transactions( const std::string account_name_or_id )const; ////////////////////// // Blinded balances // ////////////////////// /** - * @return the set of blinded balance objects by commitment ID + * @brief return the set of blinded balance objects by commitment ID + * @param commitments a set of commitments to query for + * @return the set of blinded balance objects by commitment ID */ vector get_blinded_balances( const flat_set& commitments )const; @@ -783,21 +858,27 @@ class database_api /** * @brief Get non expired withdraw permission objects for a giver(ex:recurring customer) - * @param account Account ID or name to get objects from - * @param start Withdraw permission objects(1.12.X) before this ID will be skipped in results. Pagination purposes. + * @param account_name_or_id Account name or ID to get objects from + * @param start Withdraw permission objects(1.12.X) before this ID will be skipped in results. + * Pagination purposes. * @param limit Maximum number of objects to retrieve * @return Withdraw permission objects for the account */ - vector get_withdraw_permissions_by_giver(const std::string account_id_or_name, withdraw_permission_id_type start, uint32_t limit)const; + vector get_withdraw_permissions_by_giver( const std::string account_name_or_id, + withdraw_permission_id_type start, + uint32_t limit )const; /** * @brief Get non expired withdraw permission objects for a recipient(ex:service provider) - * @param account Account ID or name to get objects from - * @param start Withdraw permission objects(1.12.X) before this ID will be skipped in results. Pagination purposes. + * @param account_name_or_id Account name or ID to get objects from + * @param start Withdraw permission objects(1.12.X) before this ID will be skipped in results. + * Pagination purposes. * @param limit Maximum number of objects to retrieve * @return Withdraw permission objects for the account */ - vector get_withdraw_permissions_by_recipient(const std::string account_id_or_name, withdraw_permission_id_type start, uint32_t limit)const; + vector get_withdraw_permissions_by_recipient( const std::string account_name_or_id, + withdraw_permission_id_type start, + uint32_t limit )const; ////////// // HTLC // @@ -812,21 +893,25 @@ class database_api /** * @brief Get non expired HTLC objects using the sender account - * @param account_id_or_name Account ID or name to get objects from + * @param account_name_or_id Account name or ID to get objects from * @param start htlc objects before this ID will be skipped in results. Pagination purposes. * @param limit Maximum number of objects to retrieve * @return HTLC objects for the account */ - vector get_htlc_by_from(const std::string account_id_or_name, htlc_id_type start, uint32_t limit) const; + vector get_htlc_by_from( const std::string account_name_or_id, + htlc_id_type start, + uint32_t limit ) const; /** * @brief Get non expired HTLC objects using the receiver account - * @param account_id_or_name Account ID or name to get objects from + * @param account_name_or_id Account name or ID to get objects from * @param start htlc objects before this ID will be skipped in results. Pagination purposes. * @param limit Maximum number of objects to retrieve * @return HTLC objects for the account */ - vector get_htlc_by_to(const std::string account_id_or_name, htlc_id_type start, uint32_t limit) const; + vector get_htlc_by_to( const std::string account_name_or_id, + htlc_id_type start, + uint32_t limit ) const; private: std::shared_ptr< database_api_impl > my; From d64578b97b6cf1a7b4363949459296314f69b1d0 Mon Sep 17 00:00:00 2001 From: abitmore Date: Tue, 23 Jul 2019 21:42:22 -0400 Subject: [PATCH 028/111] Update CLI wallet API docs, wrap long lines --- libraries/app/include/graphene/app/api.hpp | 16 +- .../wallet/include/graphene/wallet/wallet.hpp | 510 +++++++++++++----- libraries/wallet/wallet.cpp | 4 +- 3 files changed, 375 insertions(+), 155 deletions(-) diff --git a/libraries/app/include/graphene/app/api.hpp b/libraries/app/include/graphene/app/api.hpp index c7e0f7f9bc..910c5073fc 100644 --- a/libraries/app/include/graphene/app/api.hpp +++ b/libraries/app/include/graphene/app/api.hpp @@ -171,7 +171,7 @@ namespace graphene { namespace app { )const; /** - * @breif Get operations relevant to the specified account referenced + * @brief 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_id_or_name The account ID or name whose history should be queried @@ -398,7 +398,7 @@ namespace graphene { namespace app { * @param commit 33-byte pedersen commitment * @param commit_blind Sha-256 blind factor type for the correct digits * @param nonce Sha-256 blind factor type for our non-forged signatures - * @param exp Exponents base 10 in range [-1 ; 18] inclusively + * @param base10_exp Exponents base 10 in range [-1 ; 18] inclusively * @param min_bits 8-bit positive integer, must be in range [0 ; 64] inclusively * @param actual_value 64-bit positive integer, must be greater or equal min_value * @return A list of characters as proof in proof @@ -481,13 +481,13 @@ namespace graphene { namespace app { //virtual ~orders_api() {} /** - * @breif Get tracked groups configured by the server. + * @brief Get tracked groups configured by the server. * @return A list of numbers which indicate configured groups, of those, 1 means 0.01% diff on price. */ flat_set get_tracked_groups()const; /** - * @breif Get grouped limit orders in given market. + * @brief Get grouped limit orders in given market. * * @param base_asset ID or symbol of asset being sold * @param quote_asset ID or symbol of asset being purchased @@ -588,11 +588,11 @@ FC_REFLECT( graphene::app::history_operation_detail, (total_count)(operation_history_objs) ) FC_REFLECT( graphene::app::limit_order_group, (min_price)(max_price)(total_for_sale) ) -//FC_REFLECT_TYPENAME( fc::ecc::compact_signature ); -//FC_REFLECT_TYPENAME( fc::ecc::commitment_type ); +//FC_REFLECT_TYPENAME( fc::ecc::compact_signature ) +//FC_REFLECT_TYPENAME( fc::ecc::commitment_type ) -FC_REFLECT( graphene::app::account_asset_balance, (name)(account_id)(amount) ); -FC_REFLECT( graphene::app::asset_holders, (asset_id)(count) ); +FC_REFLECT( graphene::app::account_asset_balance, (name)(account_id)(amount) ) +FC_REFLECT( graphene::app::asset_holders, (asset_id)(count) ) FC_API(graphene::app::history_api, (get_account_history) diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index 2205e724cf..ad19558ddb 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -70,7 +70,7 @@ struct brain_key_info * the meta data about the receipt that helps the sender identify which receipt is * for the receiver and which is for the change address. */ -struct blind_confirmation +struct blind_confirmation { struct output { @@ -101,7 +101,9 @@ struct blind_receipt { std::pair from_date()const { return std::make_pair(from_key,date); } std::pair to_date()const { return std::make_pair(to_key,date); } - std::tuple to_asset_used()const { return std::make_tuple(to_key,amount.asset_id,used); } + std::tuple to_asset_used()const + { return std::make_tuple(to_key,amount.asset_id,used); } + const commitment_type& commitment()const { return data.commitment; } fc::time_point date; @@ -124,10 +126,20 @@ struct by_commitment; typedef multi_index_container< blind_receipt, indexed_by< - ordered_unique< tag, const_mem_fun< blind_receipt, const commitment_type&, &blind_receipt::commitment > >, - ordered_unique< tag, const_mem_fun< blind_receipt, std::pair, &blind_receipt::to_date > >, - ordered_non_unique< tag, const_mem_fun< blind_receipt, std::tuple, &blind_receipt::to_asset_used > >, - ordered_unique< tag, const_mem_fun< blind_receipt, std::pair, &blind_receipt::from_date > > + ordered_unique< tag, + const_mem_fun< blind_receipt, const commitment_type&, &blind_receipt::commitment > >, + ordered_unique< tag, + const_mem_fun< blind_receipt, + std::pair, + &blind_receipt::to_date > >, + ordered_non_unique< tag, + const_mem_fun< blind_receipt, + std::tuple, + &blind_receipt::to_asset_used > >, + ordered_unique< tag, + const_mem_fun< blind_receipt, + std::pair, + &blind_receipt::from_date > > > > blind_receipt_index_type; @@ -276,7 +288,8 @@ class utility { * @param number_of_desired_keys Number of desired keys * @return A list of keys that are deterministically derived from the brainkey */ - static vector derive_owner_keys_from_brain_key(string brain_key, int number_of_desired_keys = 1); + static vector derive_owner_keys_from_brain_key( string brain_key, + int number_of_desired_keys = 1 ); /** Suggests a safe brain key to use for creating your account. * \c create_account_with_brain_key() requires you to specify a 'brain key', @@ -321,18 +334,26 @@ class wallet_api fc::ecc::private_key derive_private_key(const std::string& prefix_string, int sequence_number) const; + /** Returns info about head block, chain_id, maintenance, participation, current active witnesses and + * committee members. + * @returns runtime info about the blockchain + */ variant info(); /** Returns info such as client version, git version of graphene/fc, version of boost, openssl. * @returns compile time info and client and dependencies versions */ variant_object about() const; + /** Returns info about a specified block. + * @param num height of the block to retrieve + * @returns info about the block, or null if not found + */ optional get_block( uint32_t num ); /** Returns the number of accounts registered on the blockchain * @returns the number of registered accounts */ uint64_t get_account_count()const; /** Lists all accounts controlled by this wallet. - * This returns a list of the full account objects for all accounts whose private keys + * This returns a list of the full account objects for all accounts whose private keys * we possess. * @returns a list of account objects */ @@ -344,14 +365,14 @@ class wallet_api * start by setting \c lowerbound to the empty string \c "", and then each iteration, pass * the last account name returned as the \c lowerbound for the next \c list_accounts() call. * - * @param lowerbound the name of the first account to return. If the named account does not exist, + * @param lowerbound the name of the first account to return. If the named account does not exist, * the list will start at the account that comes after \c lowerbound * @param limit the maximum number of accounts to return (max: 1000) * @returns a list of accounts mapping account names to account ids */ map list_accounts(const string& lowerbound, uint32_t limit); /** List the balances of an account. - * Each account can have multiple balances, one for each type of asset owned by that + * Each account can have multiple balances, one for each type of asset owned by that * account. The returned list will only contain assets for which the account has a * nonzero balance * @param id the name or id of the account whose balances you want @@ -359,7 +380,7 @@ class wallet_api */ vector list_account_balances(const string& id); /** Lists all assets registered on the blockchain. - * + * * To list all assets, pass the empty string \c "" for the lowerbound to start * at the beginning of the list, and iterate as necessary. * @@ -369,7 +390,7 @@ class wallet_api */ vector list_assets(const string& lowerbound, uint32_t limit)const; /** Returns assets count registered on the blockchain. - * + * * @returns assets count */ uint64_t get_asset_count()const; @@ -392,7 +413,8 @@ class wallet_api * @param start the sequence number where to start looping back throw the history * @returns a list of \c operation_history_objects */ - vector get_relative_account_history(string name, uint32_t stop, int limit, uint32_t start)const; + vector get_relative_account_history( string name, uint32_t stop, + int limit, uint32_t start )const; /** * @brief Fetch all objects relevant to the specified account @@ -403,8 +425,19 @@ class wallet_api * of \c name_or_id cannot be tied to an account, that input will be ignored. * */ - full_account get_full_account( const string& name_or_id); - vector get_market_history(string symbol, string symbol2, uint32_t bucket, fc::time_point_sec start, fc::time_point_sec end)const; + full_account get_full_account( const string& name_or_id ); + + /** + * @brief Get OHLCV data of a trading pair in a time range + * @param symbol name or ID of the base asset + * @param symbol2 name or ID of the quote asset + * @param bucket length of each time bucket in seconds. + * @param start the start of a time range, E.G. "2018-01-01T00:00:00" + * @param end the end of the time range + * @return A list of OHLCV data, in "least recent first" order. + */ + vector get_market_history( string symbol, string symbol2, uint32_t bucket, + fc::time_point_sec start, fc::time_point_sec end )const; /** * @brief Fetch all orders relevant to the specified account sorted descendingly by price @@ -422,7 +455,7 @@ class wallet_api * 1. if \c name_or_id cannot be tied to an account, empty result will be returned * 2. \c ostart_id and \c ostart_price can be \c null, if so the api will return the "first page" of orders; * if \c ostart_id is specified and valid, its price will be used to do page query preferentially, - * otherwise the \c ostart_price will be used + * otherwise the \c ostart_price will be used */ vector get_account_limit_orders( const string& name_or_id, const string &base, @@ -431,8 +464,29 @@ class wallet_api optional ostart_id = optional(), optional ostart_price = optional()); + /** + * @brief Get limit orders in a given market + * @param a symbol or ID of asset being sold + * @param b symbol or ID of asset being purchased + * @param limit Maximum number of orders to retrieve + * @return The limit orders, ordered from least price to greatest + */ vector get_limit_orders(string a, string b, uint32_t limit)const; + + /** + * @brief Get call orders (aka margin positions) for a given asset + * @param a symbol name or ID of the debt asset + * @param limit Maximum number of orders to retrieve + * @return The call orders, ordered from earliest to be called to latest + */ vector get_call_orders(string a, uint32_t limit)const; + + /** + * @brief Get forced settlement orders in a given asset + * @param a Symbol or ID of asset being settled + * @param limit Maximum number of orders to retrieve + * @return The settle orders, ordered from earliest settlement date to latest + */ vector get_settle_orders(string a, uint32_t limit)const; /** Returns the collateral_bid object for the given MPA @@ -443,7 +497,7 @@ class wallet_api * @returns a list of \c collateral_bid_objects */ vector get_collateral_bids(string asset, uint32_t limit = 100, uint32_t start = 0)const; - + /** Returns the block chain's slowly-changing settings. * This object contains all of the properties of the blockchain that are fixed * or that change only once per maintenance interval (daily) such as the @@ -457,12 +511,15 @@ class wallet_api * Get operations relevant to the specified account filtering by operation type, with transaction id * * @param name the name or id of the account, whose history shoulde be queried - * @param operation_types The IDs of the operation we want to get operations in the account( 0 = transfer , 1 = limit order create, ...) + * @param operation_types The IDs of the operation we want to get operations in the account + * ( 0 = transfer , 1 = limit order create, ...) * @param start the sequence number where to start looping back throw the history * @param limit the max number of entries to return (from start number) * @returns account_history_operation_detail */ - account_history_operation_detail get_account_history_by_operations(string name, vector operation_types, uint32_t start, int limit); + account_history_operation_detail get_account_history_by_operations( string name, + vector operation_types, + uint32_t start, int limit); /** Returns the block chain's rapidly-changing properties. * The returned object contains information that changes every block interval @@ -474,7 +531,7 @@ class wallet_api /** Returns information about the given account. * - * @param account_name_or_id the name or id of the account to provide information about + * @param account_name_or_id the name or ID of the account to provide information about * @returns the public account data stored in the blockchain */ account_object get_account(string account_name_or_id) const; @@ -501,14 +558,14 @@ class wallet_api fc::optional get_htlc(string htlc_id) const; /** Lookup the id of a named account. - * @param account_name_or_id the name of the account to look up + * @param account_name_or_id the name or ID of the account to look up * @returns the id of the named account */ account_id_type get_account_id(string account_name_or_id) const; /** * Lookup the id of a named asset. - * @param asset_name_or_id the symbol of an asset to look up + * @param asset_name_or_id the symbol or ID of an asset to look up * @returns the id of the given asset */ asset_id_type get_asset_id(string asset_name_or_id) const; @@ -517,8 +574,8 @@ class wallet_api * Returns the blockchain object corresponding to the given id. * * This generic function can be used to retrieve any object from the blockchain - * that is assigned an ID. Certain types of objects have specialized convenience - * functions to return their objects -- e.g., assets have \c get_asset(), accounts + * that is assigned an ID. Certain types of objects have specialized convenience + * functions to return their objects -- e.g., assets have \c get_asset(), accounts * have \c get_account(), but this function will work for any object. * * @param id the id of the object to return @@ -526,7 +583,7 @@ class wallet_api */ variant get_object(object_id_type id) const; - /** Returns the current wallet filename. + /** Returns the current wallet filename. * * This is the filename that will be used when automatically saving the wallet. * @@ -538,33 +595,61 @@ class wallet_api /** * Get the WIF private key corresponding to a public key. The * private key must already be in the wallet. + * @param pubkey a public key in Base58 format + * @return the WIF private key */ string get_private_key( public_key_type pubkey )const; /** * @ingroup Transaction Builder API + * + * Create a new transaction builder. + * @return handle of the new transaction builder */ transaction_handle_type begin_builder_transaction(); /** * @ingroup Transaction Builder API + * + * Append a new operation to a transaction builder. + * @param transaction_handle handle of the transaction builder + * @param op the operation in JSON format */ void add_operation_to_builder_transaction(transaction_handle_type transaction_handle, const operation& op); /** * @ingroup Transaction Builder API + * + * Replace an operation in a transaction builder with a new operation. + * @param handle handle of the transaction builder + * @param operation_index the index of the old operation in the builder to be replaced + * @param new_op the new operation in JSON format */ void replace_operation_in_builder_transaction(transaction_handle_type handle, unsigned operation_index, const operation& new_op); /** * @ingroup Transaction Builder API + * + * Calculate and update fees for the operations in a transaction builder. + * @param handle handle of the transaction builder + * @param fee_asset name or ID of an asset that to be used to pay fees + * @return total fees */ asset set_fees_on_builder_transaction(transaction_handle_type handle, string fee_asset = GRAPHENE_SYMBOL); /** * @ingroup Transaction Builder API + * + * Show content of a transaction builder. + * @param handle handle of the transaction builder + * @return a transaction */ transaction preview_builder_transaction(transaction_handle_type handle); /** * @ingroup Transaction Builder API + * + * Sign the transaction in a transaction builder and optionally broadcast to the network. + * @param transaction_handle handle of the transaction builder + * @param broadcast whether to broadcast the signed transaction to the network + * @return a signed transaction */ signed_transaction sign_builder_transaction(transaction_handle_type transaction_handle, bool broadcast = true); @@ -576,6 +661,19 @@ class wallet_api /** * @ingroup Transaction Builder API + * + * Create a proposal containing the operations in a transaction builder (create a new proposal_create + * operation, then replace the transaction builder with the new operation), then sign the transaction + * and optionally broadcast to the network. + * + * Note: this command is buggy because unable to specify proposer. It will be deprecated in a future release. + * Please use \c propose_builder_transaction2() instead. + * + * @param handle handle of the transaction builder + * @param expiration when the proposal will expire + * @param review_period_seconds review period of the proposal in seconds + * @param broadcast whether to broadcast the signed transaction to the network + * @return a signed transaction */ signed_transaction propose_builder_transaction( transaction_handle_type handle, @@ -584,6 +682,20 @@ class wallet_api bool broadcast = true ); + /** + * @ingroup Transaction Builder API + * + * Create a proposal containing the operations in a transaction builder (create a new proposal_create + * operation, then replace the transaction builder with the new operation), then sign the transaction + * and optionally broadcast to the network. + * + * @param handle handle of the transaction builder + * @param account_name_or_id name or ID of the account who would pay fees for creating the proposal + * @param expiration when the proposal will expire + * @param review_period_seconds review period of the proposal in seconds + * @param broadcast whether to broadcast the signed transaction to the network + * @return a signed transaction + */ signed_transaction propose_builder_transaction2( transaction_handle_type handle, string account_name_or_id, @@ -594,6 +706,9 @@ class wallet_api /** * @ingroup Transaction Builder API + * + * Destroy a transaction builder. + * @param handle handle of the transaction builder */ void remove_builder_transaction(transaction_handle_type handle); @@ -604,33 +719,42 @@ class wallet_api * @ingroup Wallet Management */ bool is_new()const; - - /** Checks whether the wallet is locked (is unable to use its private keys). + + /** Checks whether the wallet is locked (is unable to use its private keys). * * This state can be changed by calling \c lock() or \c unlock(). * @return true if the wallet is locked * @ingroup Wallet Management */ bool is_locked()const; - + /** Locks the wallet immediately. * @ingroup Wallet Management */ void lock(); - - /** Unlocks the wallet. + + /** Unlocks the wallet. * * The wallet remain unlocked until the \c lock is called * or the program exits. + * + * When used in command line, if typed "unlock" without a password followed, the user will be prompted + * to input a password without echo. + * * @param password the password previously set with \c set_password() * @ingroup Wallet Management */ void unlock(string password); - + /** Sets a new password on the wallet. * * The wallet must be either 'new' or 'unlocked' to * execute this command. + * + * When used in command line, if typed "set_password" without a password followed, the user will be prompted + * to input a password without echo. + * + * @param password a new password * @ingroup Wallet Management */ void set_password(string password); @@ -639,14 +763,14 @@ class wallet_api * * The keys are printed in WIF format. You can import these keys into another wallet * using \c import_key() - * @returns a map containing the private keys, indexed by their public key + * @returns a map containing the private keys, indexed by their public key */ map dump_private_keys(); /** Returns a list of all commands supported by the wallet API. * * This lists each command, along with its arguments and return types. - * For more detailed help on a single command, use \c get_help() + * For more detailed help on a single command, use \c gethelp() * * @returns a multi-line string suitable for displaying on a terminal */ @@ -673,14 +797,14 @@ class wallet_api */ bool load_wallet_file(string wallet_filename = ""); - /** Quitting from BitShares wallet. - * - * The current wallet will be closed. + /** Quitting from the wallet. + * + * The current wallet will be closed and saved. */ void quit(); /** Saves the current wallet to the given filename. - * + * * @warning This does not change the wallet filename that will be used for future * writes, so think of this function as 'Save a Copy As...' instead of * 'Save As...'. Use \c set_wallet_filename() to make the filename @@ -735,8 +859,8 @@ class wallet_api /** Converts a signed_transaction in JSON form to its binary representation. * * @param tx the transaction to serialize - * @returns the binary form of the transaction. It will not be hex encoded, - * this returns a raw string that may have null characters embedded + * @returns the binary form of the transaction. It will not be hex encoded, + * this returns a raw string that may have null characters embedded * in it */ string serialize_transaction(signed_transaction tx) const; @@ -744,7 +868,7 @@ class wallet_api /** Imports the private key for an existing account. * * The private key must match either an owner key or an active key for the - * named account. + * named account. * * @see dump_private_keys() * @@ -754,15 +878,38 @@ class wallet_api */ bool import_key(string account_name_or_id, string wif_key); + /** Imports accounts from a BitShares 0.x wallet file. + * Current wallet file must be unlocked to perform the import. + * + * @param filename the BitShares 0.x wallet file to import + * @param password the password to encrypt the BitShares 0.x wallet file + * @returns a map containing the accounts found and whether imported + */ map import_accounts( string filename, string password ); + /** Imports from a BitShares 0.x wallet file, find keys that were bound to a given account name on the + * BitShares 0.x chain, rebind them to an account name on the 2.0 chain. + * Current wallet file must be unlocked to perform the import. + * + * @param filename the BitShares 0.x wallet file to import + * @param password the password to encrypt the BitShares 0.x wallet file + * @param src_account_name name of the account on BitShares 0.x chain + * @param dest_account_name name of the account on BitShares 2.0 chain, + * can be same or different to \c src_account_name + * @returns whether the import has succeeded + */ bool import_account_keys( string filename, string password, string src_account_name, string dest_account_name ); /** * This call will construct transaction(s) that will claim all balances controled * by wif_keys and deposit them into the given account. + * + * @param account_name_or_id name or ID of an account that to claim balances to + * @param wif_keys private WIF keys of balance objects to claim balances from + * @param broadcast true to broadcast the transaction on the network */ - vector< signed_transaction > import_balance( string account_name_or_id, const vector& wif_keys, bool broadcast ); + vector< signed_transaction > import_balance( string account_name_or_id, const vector& wif_keys, + bool broadcast ); /** Transforms a brain key to reduce the chance of errors when re-entering the key from memory. * @@ -811,8 +958,7 @@ class wallet_api * Upgrades an account to prime status. * This makes the account holder a 'lifetime member'. * - * @todo there is no option for annual membership - * @param name the name or id of the account to upgrade + * @param name the name or id of the account to upgrade * @param broadcast true to broadcast the transaction on the network * @returns the signed transaction upgrading the account */ @@ -847,7 +993,7 @@ class wallet_api * @param to the name or id of the account receiving the funds * @param amount the amount to send (in nominal units -- to send half of a BTS, specify 0.5) * @param asset_symbol the symbol or id of the asset to send - * @param memo a memo to attach to the transaction. The memo will be encrypted in the + * @param memo a memo to attach to the transaction. The memo will be encrypted in the * transaction and readable for the receiver. There is no length limit * other than the limit imposed by maximum transaction size, but transaction * increase with transaction size @@ -863,7 +1009,16 @@ class wallet_api /** * This method works just like transfer, except it always broadcasts and - * returns the transaction ID along with the signed transaction. + * returns the transaction ID (hash) along with the signed transaction. + * @param from the name or id of the account sending the funds + * @param to the name or id of the account receiving the funds + * @param amount the amount to send (in nominal units -- to send half of a BTS, specify 0.5) + * @param asset_symbol the symbol or id of the asset to send + * @param memo a memo to attach to the transaction. The memo will be encrypted in the + * transaction and readable for the receiver. There is no length limit + * other than the limit imposed by maximum transaction size, but transaction + * increase with transaction size + * @returns the transaction ID (hash) along with the signed transaction transferring funds */ pair transfer2(string from, string to, @@ -877,22 +1032,25 @@ class wallet_api /** * This method is used to convert a JSON transaction to its transactin ID. + * @param trx a JSON transaction + * @return the ID (hash) of the transaction */ transaction_id_type get_transaction_id( const signed_transaction& trx )const { return trx.id(); } /** Sign a memo message. * - * @param from the name or id of signing account; or a public key. - * @param to the name or id of receiving account; or a public key. - * @param memo text to sign. + * @param from the name or id of signing account; or a public key + * @param to the name or id of receiving account; or a public key + * @param memo text to sign + * @return the signed memo data */ memo_data sign_memo(string from, string to, string memo); /** Read a memo. * * @param memo JSON-enconded memo. - * @returns string with decrypted message.. + * @returns string with decrypted message. */ string read_memo(const memo_data& memo); @@ -900,72 +1058,114 @@ class wallet_api /** These methods are used for stealth transfers */ ///@{ /** - * This method can be used to set the label for a public key - * - * @note No two keys can have the same label. + * This method can be used to set a label for a public key * - * @return true if the label was set, otherwise false + * @note No two keys can have the same label. + * @param key a public key + * @param label a user-defined string as label + * @return true if the label was set, otherwise false + */ + bool set_key_label( public_key_type key, string label ); + + /** + * Get label of a public key. + * @param key a public key + * @return the label if already set by \c set_key_label(), or an empty string if not set */ - bool set_key_label( public_key_type, string label ); - string get_key_label( public_key_type )const; + string get_key_label( public_key_type key )const; /** - * Generates a new blind account for the given brain key and assigns it the given label. + * Generates a new blind account for the given brain key and assigns it the given label. + * @param label a label + * @param brain_key the brain key to be used to generate a new blind account + * @return the public key of the new account */ public_key_type create_blind_account( string label, string brain_key ); /** - * @return the total balance of all blinded commitments that can be claimed by the + * Return the total balances of all blinded commitments that can be claimed by the + * given account key or label. + * @param key_or_label a public key in Base58 format or a label + * @return the total balances of all blinded commitments that can be claimed by the * given account key or label */ vector get_blind_balances( string key_or_label ); - /** @return all blind accounts */ + /** + * Get all blind accounts. + * @return all blind accounts + */ map get_blind_accounts()const; - /** @return all blind accounts for which this wallet has the private key */ + /** + * Get all blind accounts for which this wallet has the private key. + * @return all blind accounts for which this wallet has the private key + */ map get_my_blind_accounts()const; - /** @return the public key associated with the given label */ + /** + * Get the public key associated with a given label. + * @param label a label + * @return the public key associated with the given label + */ public_key_type get_public_key( string label )const; ///@} /** - * @return all blind receipts to/form a particular account + * Get all blind receipts to/form a particular account + * @param key_or_account a public key in Base58 format or an account + * @return all blind receipts to/form the account */ vector blind_history( string key_or_account ); /** - * Given a confirmation receipt, this method will parse it for a blinded balance and confirm - * that it exists in the blockchain. If it exists then it will report the amount received and - * who sent it. + * Given a confirmation receipt, this method will parse it for a blinded balance and confirm + * that it exists in the blockchain. If it exists then it will report the amount received and + * who sent it. * - * @param opt_from if not empty and the sender is a unknown public key, - * then the unknown public key will be given the label \c opt_from - * @param confirmation_receipt a base58 encoded stealth confirmation - * @param opt_memo a self-defined label for this transfer to be saved in local wallet file + * @param confirmation_receipt a base58 encoded stealth confirmation + * @param opt_from if not empty and the sender is a unknown public key, + * then the unknown public key will be given the label \c opt_from + * @param opt_memo a self-defined label for this transfer to be saved in local wallet file + * @return a blind receipt */ blind_receipt receive_blind_transfer( string confirmation_receipt, string opt_from, string opt_memo ); /** - * Transfers a public balance from \c from_account_id_or_name to one or more blinded balances using a - * stealth transfer. + * Transfers a public balance from \c from_account_id_or_name to one or more blinded balances using a + * stealth transfer. + * @param from_account_id_or_name ID or name of an account to transfer from + * @param asset_symbol symbol or ID of the asset to be transferred + * @param to_amounts map from key or label to amount + * @param broadcast true to broadcast the transaction on the network + * @return a blind confirmation */ - blind_confirmation transfer_to_blind( string from_account_id_or_name, + blind_confirmation transfer_to_blind( string from_account_id_or_name, string asset_symbol, - /** map from key or label to amount */ - vector> to_amounts, + vector> to_amounts, bool broadcast = false ); /** * Transfers funds from a set of blinded balances to a public account balance. + * @param from_blind_account_key_or_label a public key in Base58 format or a label to transfer from + * @param to_account_id_or_name ID or name of an account to transfer to + * @param amount the amount to be transferred + * @param asset_symbol symbol or ID of the asset to be transferred + * @param broadcast true to broadcast the transaction on the network + * @return a blind confirmation */ - blind_confirmation transfer_from_blind( + blind_confirmation transfer_from_blind( string from_blind_account_key_or_label, - string to_account_id_or_name, + string to_account_id_or_name, string amount, string asset_symbol, bool broadcast = false ); /** - * Used to transfer from one set of blinded balances to another + * Transfer from one set of blinded balances to another. + * @param from_key_or_label a public key in Base58 format or a label to transfer from + * @param to_key_or_label a public key in Base58 format or a label to transfer to + * @param amount the amount to be transferred + * @param symbol symbol or ID of the asset to be transferred + * @param broadcast true to broadcast the transaction on the network + * @return a blind confirmation */ blind_confirmation blind_transfer( string from_key_or_label, string to_key_or_label, @@ -975,14 +1175,14 @@ class wallet_api /** Place a limit order attempting to sell one asset for another. * - * Buying and selling are the same operation on Graphene; if you want to buy BTS + * Buying and selling are the same operation on Graphene; if you want to buy BTS * with USD, you should sell USD for BTS. * * The blockchain will attempt to sell the \c symbol_to_sell for as - * much \c symbol_to_receive as possible, as long as the price is at - * least \c min_to_receive / \c amount_to_sell. + * much \c symbol_to_receive as possible, as long as the price is at + * least \c min_to_receive / \c amount_to_sell. * - * In addition to the transaction fees, market fees will apply as specified + * In addition to the transaction fees, market fees will apply as specified * by the issuer of both the selling asset and the receiving asset as * a percentage of the amount exchanged. * @@ -993,18 +1193,18 @@ class wallet_api * Market orders are matched in the order they are included * in the block chain. * - * @todo Allow order expiration to be set here. Document default/max expiration time + * @todo Document default/max expiration time * - * @param seller_account the account providing the asset being sold, and which will + * @param seller_account the account providing the asset being sold, and which will * receive the proceeds of the sale. * @param amount_to_sell the amount of the asset being sold to sell (in nominal units) * @param symbol_to_sell the name or id of the asset to sell * @param min_to_receive the minimum amount you are willing to receive in return for * selling the entire amount_to_sell * @param symbol_to_receive the name or id of the asset you wish to receive - * @param timeout_sec if the order does not fill immediately, this is the length of - * time the order will remain on the order books before it is - * cancelled and the un-spent funds are returned to the seller's + * @param timeout_sec if the order does not fill immediately, this is the length of + * time the order will remain on the order books before it is + * cancelled and the un-spent funds are returned to the seller's * account * @param fill_or_kill if true, the order will only be included in the blockchain * if it is filled immediately; if false, an open order will be @@ -1074,14 +1274,14 @@ class wallet_api * Right now this function is difficult to use because you must provide raw JSON data * structures for the options objects, and those include prices and asset ids. * - * @param issuer the name or id of the account who will pay the fee and become the + * @param issuer the name or id of the account who will pay the fee and become the * issuer of the new asset. This can be updated later * @param symbol the ticker symbol of the new asset * @param precision the number of digits of precision to the right of the decimal point, * must be less than or equal to 12 * @param common asset options required for all new assets. - * Note that core_exchange_rate technically needs to store the asset ID of - * this new asset. Since this ID is not known at the time this operation is + * Note that core_exchange_rate technically needs to store the asset ID of + * this new asset. Since this ID is not known at the time this operation is * created, create this price as though the new asset has instance ID 1, and * the chain will overwrite it with the new asset's ID. * @param bitasset_opts options specific to BitAssets. This may be null unless the @@ -1111,8 +1311,8 @@ class wallet_api bool broadcast = false); /** Update the core options on an asset. - * There are a number of options which all assets in the network use. These options are - * enumerated in the asset_object::asset_options struct. This command is used to update + * There are a number of options which all assets in the network use. These options are + * enumerated in the asset_object::asset_options struct. This command is used to update * these options for an existing asset. * * @note This operation cannot be used to update BitAsset-specific options. For these options, @@ -1176,7 +1376,7 @@ class wallet_api signed_transaction update_asset_feed_producers(string symbol, flat_set new_feed_producers, bool broadcast = false); - + /** Publishes a price feed for the named asset. * * Price feed providers use this command to publish their price feeds for market-issued assets. A price feed is @@ -1204,7 +1404,7 @@ class wallet_api /** Pay into the fee pool for the given asset. * - * User-issued assets can optionally have a pool of the core asset which is + * User-issued assets can optionally have a pool of the core asset which is * automatically used to pay transaction fees for any transaction using that * asset (using the asset's core exchange rate). * @@ -1223,7 +1423,7 @@ class wallet_api /** Claim funds from the fee pool for the given asset. * - * User-issued assets can optionally have a pool of the core asset which is + * User-issued assets can optionally have a pool of the core asset which is * automatically used to pay transaction fees for any transaction using that * asset (using the asset's core exchange rate). * @@ -1238,9 +1438,9 @@ class wallet_api string amount, bool broadcast = false); - /** Burns the given user-issued asset. + /** Burns an amount of given asset. * - * This command burns the user-issued asset to reduce the amount in circulation. + * This command burns an amount of given asset to reduce the amount in circulation. * @note you cannot burn market-issued assets. * @param from the account containing the asset you wish to burn * @param amount the amount to burn, in nominal units @@ -1257,15 +1457,15 @@ class wallet_api * * In order to use this operation, asset_to_settle must have the global_settle flag set * - * When this operation is executed all balances are converted into the backing asset at the - * settle_price and all open margin positions are called at the settle price. If this asset is - * used as backing for other bitassets, those bitassets will be force settled at their current - * feed price. + * When this operation is executed all open margin positions are called at the settle price. + * A pool will be formed containing the collateral got from the margin positions. + * Users owning an amount of the asset may use \c settle_asset() to claim collateral instantly + * at the settle price from the pool. + * If this asset is used as backing for other bitassets, those bitassets will not be affected. * - * @note this operation is used only by the asset issuer, \c settle_asset() may be used by - * any user owning the asset + * @note this operation is used only by the asset issuer. * - * @param symbol the name or id of the asset to force settlement on + * @param symbol the name or id of the asset to globally settle * @param settle_price the price at which to settle * @param broadcast true to broadcast the transaction on the network * @returns the signed transaction settling the named asset @@ -1276,16 +1476,19 @@ class wallet_api /** Schedules a market-issued asset for automatic settlement. * - * Holders of market-issued assests may request a forced settlement for some amount of their asset. This means that - * the specified sum will be locked by the chain and held for the settlement period, after which time the chain will - * choose a margin posision holder and buy the settled asset using the margin's collateral. The price of this sale - * will be based on the feed price for the market-issued asset being settled. The exact settlement price will be the + * Holders of market-issued assests may request a forced settlement for some amount of their asset. + * This means that the specified sum will be locked by the chain and held for the settlement period, + * after which time the chain will + * choose a margin posision holder and buy the settled asset using the margin's collateral. + * The price of this sale + * will be based on the feed price for the market-issued asset being settled. + * The exact settlement price will be the * feed price at the time of settlement with an offset in favor of the margin position, where the offset is a * blockchain parameter set in the global_property_object. * * @param account_to_settle the name or id of the account owning the asset * @param amount_to_settle the amount of the named asset to schedule for settlement - * @param symbol the name or id of the asset to settlement on + * @param symbol the name or id of the asset to settle * @param broadcast true to broadcast the transaction on the network * @returns the signed transaction settling the named asset */ @@ -1316,16 +1519,16 @@ class wallet_api /** Whitelist and blacklist accounts, primarily for transacting in whitelisted assets. * * Accounts can freely specify opinions about other accounts, in the form of either whitelisting or blacklisting - * them. This information is used in chain validation only to determine whether an account is authorized to transact - * in an asset type which enforces a whitelist, but third parties can use this information for other uses as well, - * as long as it does not conflict with the use of whitelisted assets. + * them. This information is used in chain validation only to determine whether an account is authorized to + * transact in an asset type which enforces a whitelist, but third parties can use this information for other + * uses as well, as long as it does not conflict with the use of whitelisted assets. * * An asset which enforces a whitelist specifies a list of accounts to maintain its whitelist, and a list of - * accounts to maintain its blacklist. In order for a given account A to hold and transact in a whitelisted asset S, - * A must be whitelisted by at least one of S's whitelist_authorities and blacklisted by none of S's - * blacklist_authorities. If A receives a balance of S, and is later removed from the whitelist(s) which allowed it - * to hold S, or added to any blacklist S specifies as authoritative, A's balance of S will be frozen until A's - * authorization is reinstated. + * accounts to maintain its blacklist. In order for a given account A to hold and transact in a whitelisted + * asset S, A must be whitelisted by at least one of S's whitelist_authorities and blacklisted by none of S's + * blacklist_authorities. If A receives a balance of S, and is later removed from the whitelist(s) which allowed + * it to hold S, or added to any blacklist S specifies as authoritative, A's balance of S will be frozen until + * A's authorization is reinstated. * * @param authorizing_account the account who is doing the whitelisting * @param account_to_list the account being whitelisted @@ -1349,7 +1552,7 @@ class wallet_api * @returns the signed transaction registering a committee_member */ signed_transaction create_committee_member(string owner_account, - string url, + string url, bool broadcast = false); /** Lists all witnesses registered in the blockchain. @@ -1360,7 +1563,7 @@ class wallet_api * start by setting \c lowerbound to the empty string \c "", and then each iteration, pass * the last witness name returned as the \c lowerbound for the next \c list_witnesss() call. * - * @param lowerbound the name of the first witness to return. If the named witness does not exist, + * @param lowerbound the name of the first witness to return. If the named witness does not exist, * the list will start at the witness that comes after \c lowerbound * @param limit the maximum number of witnesss to return (max: 1000) * @returns a list of witnesss mapping witness names to witness ids @@ -1375,8 +1578,8 @@ class wallet_api * start by setting \c lowerbound to the empty string \c "", and then each iteration, pass * the last committee_member name returned as the \c lowerbound for the next \c list_committee_members() call. * - * @param lowerbound the name of the first committee_member to return. If the named committee_member does not exist, - * the list will start at the committee_member that comes after \c lowerbound + * @param lowerbound the name of the first committee_member to return. If the named committee_member does not + * exist, the list will start at the committee_member that comes after \c lowerbound * @param limit the maximum number of committee_members to return (max: 1000) * @returns a list of committee_members mapping committee_member names to committee_member ids */ @@ -1411,10 +1614,12 @@ class wallet_api /** * Update a witness object owned by the given account. * - * @param witness_name The name of the witness's owner account. Also accepts the ID of the owner account or the ID of the witness. + * @param witness_name The name of the witness's owner account. + * Also accepts the ID of the owner account or the ID of the witness. * @param url Same as for create_witness. The empty string makes it remain the same. * @param block_signing_key The new block signing public key. The empty string makes it remain the same. * @param broadcast true if you wish to broadcast the transaction. + * @return the signed transaction */ signed_transaction update_witness(string witness_name, string url, @@ -1433,6 +1638,7 @@ class wallet_api * @param url Any text * @param worker_settings {"type" : "burn"|"refund"|"vesting", "pay_vesting_period_days" : x} * @param broadcast true if you wish to broadcast the transaction. + * @return the signed transaction */ signed_transaction create_worker( string owner_account, @@ -1446,11 +1652,12 @@ class wallet_api ); /** - * Update your votes for a worker + * Update your votes for workers * * @param account The account which will pay the fee and update votes. * @param delta {"vote_for" : [...], "vote_against" : [...], "vote_abstain" : [...]} * @param broadcast true if you wish to broadcast the transaction. + * @return the signed transaction */ signed_transaction update_worker_votes( string account, @@ -1460,7 +1667,7 @@ class wallet_api /** * Create a hashed time lock contract - * + * * @param source The account that will reserve the funds (and pay the fee) * @param destination The account that will receive the funds if the preimage is presented * @param amount the amount of the asset that is to be traded @@ -1470,36 +1677,40 @@ class wallet_api * @param preimage_size the size of the preimage in bytes * @param claim_period_seconds how long after creation until the lock expires * @param broadcast true if you wish to broadcast the transaction + * @return the signed transaction */ signed_transaction htlc_create( string source, string destination, string amount, string asset_symbol, - string hash_algorithm, const std::string& preimage_hash, uint32_t preimage_size, + string hash_algorithm, const std::string& preimage_hash, uint32_t preimage_size, const uint32_t claim_period_seconds, bool broadcast = false ); /**** * Update a hashed time lock contract - * + * * @param htlc_id The object identifier of the HTLC on the blockchain * @param issuer Who is performing this operation (and paying the fee) * @param preimage the preimage that should evaluate to the preimage_hash + * @return the signed transaction */ - signed_transaction htlc_redeem( string htlc_id, string issuer, const std::string& preimage, + signed_transaction htlc_redeem( string htlc_id, string issuer, const std::string& preimage, bool broadcast = false ); /***** * Increase the timelock on an existing HTLC - * + * * @param htlc_id The object identifier of the HTLC on the blockchain * @param issuer Who is performing this operation (and paying the fee) * @param seconds_to_add how many seconds to add to the existing timelock * @param broadcast true to broadcast to the network + * @return the signed transaction */ signed_transaction htlc_extend(string htlc_id, string issuer, const uint32_t seconds_to_add, bool broadcast = false); /** - * Get information about a vesting balance object. + * Get information about a vesting balance object or vesting balance objects owned by an account. * * @param account_name An account name, account ID, or vesting balance object ID. + * @return a list of vesting balance objects with additional info */ vector< vesting_balance_object_with_info > get_vesting_balances( string account_name ); @@ -1510,6 +1721,7 @@ class wallet_api * @param amount The amount to withdraw. * @param asset_symbol The symbol of the asset to withdraw. * @param broadcast true if you wish to broadcast the transaction + * @return the signed transaction */ signed_transaction withdraw_vesting( string witness_name, @@ -1519,7 +1731,7 @@ class wallet_api /** Vote for a given committee_member. * - * An account can publish a list of all committee_members they approve of. This + * An account can publish a list of all committee_members they approve of. This * command allows you to add or remove committee_members from this list. * Each account's vote is weighted according to the number of shares of the * core asset owned by that account at the time the votes are tallied. @@ -1529,7 +1741,7 @@ class wallet_api * * @param voting_account the name or id of the account who is voting with their shares * @param committee_member the name or id of the committee_member' owner account - * @param approve true if you wish to vote in favor of that committee_member, false to + * @param approve true if you wish to vote in favor of that committee_member, false to * remove your vote in favor of that committee_member * @param broadcast true if you wish to broadcast the transaction * @return the signed transaction changing your vote for the given committee_member @@ -1541,7 +1753,7 @@ class wallet_api /** Vote for a given witness. * - * An account can publish a list of all witnesses they approve of. This + * An account can publish a list of all witnesses they approve of. This * command allows you to add or remove witnesses from this list. * Each account's vote is weighted according to the number of shares of the * core asset owned by that account at the time the votes are tallied. @@ -1551,7 +1763,7 @@ class wallet_api * * @param voting_account the name or id of the account who is voting with their shares * @param witness the name or id of the witness' owner account - * @param approve true if you wish to vote in favor of that witness, false to + * @param approve true if you wish to vote in favor of that witness, false to * remove your vote in favor of that witness * @param broadcast true if you wish to broadcast the transaction * @return the signed transaction changing your vote for the given witness @@ -1582,16 +1794,16 @@ class wallet_api signed_transaction set_voting_proxy(string account_to_modify, optional voting_account, bool broadcast = false); - + /** Set your vote for the number of witnesses and committee_members in the system. * - * Each account can voice their opinion on how many committee_members and how many + * Each account can voice their opinion on how many committee_members and how many * witnesses there should be in the active committee_member/active witness list. These * are independent of each other. You must vote your approval of at least as many * committee_members or witnesses as you claim there should be (you can't say that there should - * be 20 committee_members but only vote for 10). + * be 20 committee_members but only vote for 10). * - * There are maximum values for each set in the blockchain parameters (currently + * There are maximum values for each set in the blockchain parameters (currently * defaulting to 1001). * * This setting can be changed at any time. If your account has a voting proxy @@ -1638,17 +1850,17 @@ class wallet_api /** Returns an uninitialized object representing a given blockchain operation. * - * This returns a default-initialized object of the given type; it can be used + * This returns a default-initialized object of the given type; it can be used * during early development of the wallet when we don't yet have custom commands for - * creating all of the operations the blockchain supports. + * creating all of the operations the blockchain supports. * * Any operation the blockchain supports can be created using the transaction builder's - * \c add_operation_to_builder_transaction() , but to do that from the CLI you need to + * \c add_operation_to_builder_transaction() , but to do that from the CLI you need to * know what the JSON form of the operation looks like. This will give you a template * you can fill in. It's better than nothing. - * - * @param operation_type the type of operation to return, must be one of the - * operations defined in `graphene/chain/operations.hpp` + * + * @param operation_type the type of operation to return, must be one of the + * operations defined in `graphene/protocol/operations.hpp` * (e.g., "global_parameters_update_operation") * @return a default-constructed operation of the given type */ @@ -1672,7 +1884,7 @@ class wallet_api bool broadcast = false); /** Propose a fee change. - * + * * @param proposing_account The account paying the fee to propose the tx * @param expiration_time Timestamp specifying when the proposal will either take effect or expire. * @param changed_values Map of operation type to new fee. Operations may be specified by name or ID. @@ -1700,7 +1912,14 @@ class wallet_api const approval_delta& delta, bool broadcast /* = false */ ); - + + /** + * Returns the order book for the market base:quote. + * @param base symbol name or ID of the base asset + * @param quote symbol name or ID of the quote asset + * @param limit depth of the order book to retrieve, for bids and asks each, capped at 50 + * @return Order book of the market + */ order_book get_order_book( const string& base, const string& quote, unsigned limit = 50); /** Signs a transaction. @@ -1753,7 +1972,8 @@ extern template class fc::api; FC_REFLECT( graphene::wallet::key_label, (label)(key) ) FC_REFLECT( graphene::wallet::blind_balance, (amount)(from)(to)(one_time_key)(blinding_factor)(commitment)(used) ) -FC_REFLECT( graphene::wallet::blind_confirmation::output, (label)(pub_key)(decrypted_memo)(confirmation)(auth)(confirmation_receipt) ) +FC_REFLECT( graphene::wallet::blind_confirmation::output, + (label)(pub_key)(decrypted_memo)(confirmation)(auth)(confirmation_receipt) ) FC_REFLECT( graphene::wallet::blind_confirmation, (trx)(outputs) ) FC_REFLECT( graphene::wallet::plain_keys, (keys)(checksum) ) @@ -1805,7 +2025,7 @@ FC_REFLECT_DERIVED( graphene::wallet::signed_block_with_info, (graphene::chain:: FC_REFLECT_DERIVED( graphene::wallet::vesting_balance_object_with_info, (graphene::chain::vesting_balance_object), (allowed_withdraw)(allowed_withdraw_time) ) -FC_REFLECT( graphene::wallet::operation_detail, +FC_REFLECT( graphene::wallet::operation_detail, (memo)(description)(op) ) FC_REFLECT(graphene::wallet::operation_detail_ex, diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index 2f964bb811..8ae31ab48d 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -4834,13 +4834,13 @@ blind_confirmation wallet_api::blind_transfer_help( string from_key_or_label, -/** +/* * Transfers a public balance from @from to one or more blinded balances using a * stealth transfer. */ blind_confirmation wallet_api::transfer_to_blind( string from_account_id_or_name, string asset_symbol, - /** map from key or label to amount */ + /* map from key or label to amount */ vector> to_amounts, bool broadcast ) { try { From 988621993ef5689fd60548db3bc3d7891ee39180 Mon Sep 17 00:00:00 2001 From: abitmore Date: Tue, 23 Jul 2019 21:50:20 -0400 Subject: [PATCH 029/111] Update API docs, wrap long lines --- libraries/app/include/graphene/app/api.hpp | 88 ++++++++++++---------- 1 file changed, 49 insertions(+), 39 deletions(-) diff --git a/libraries/app/include/graphene/app/api.hpp b/libraries/app/include/graphene/app/api.hpp index 910c5073fc..c85fab14b2 100644 --- a/libraries/app/include/graphene/app/api.hpp +++ b/libraries/app/include/graphene/app/api.hpp @@ -65,7 +65,7 @@ namespace graphene { namespace app { uint64_t min_val; uint64_t max_val; }; - + struct verify_range_proof_rewind_result { bool success; @@ -109,7 +109,7 @@ namespace graphene { namespace app { price max_price; ///< possible highest price in the group share_type total_for_sale; ///< total amount of asset for sale, asset id is min_price.base.asset_id }; - + /** * @brief The history_api class implements the RPC API for account history * @@ -200,11 +200,11 @@ namespace graphene { namespace app { * @brief Get OHLCV data of a trading pair in a time range * @param a Asset symbol or ID in a trading pair * @param b The other asset symbol or ID in the trading pair - * @param bucket_seconds Length of each time bucket in seconds. + * @param bucket_seconds Length of each time bucket in seconds. * Note: it need to be within result of get_market_history_buckets() API, otherwise no data will be returned * @param start The start of a time range, E.G. "2018-01-01T00:00:00" * @param end The end of the time range - * @return A list of OHLCV data, in "least recent first" order. + * @return A list of OHLCV data, in "least recent first" order. * If there are more than 200 records in the specified time range, the first 200 records will be returned. */ vector get_market_history( std::string a, std::string b, uint32_t bucket_seconds, @@ -212,9 +212,9 @@ namespace graphene { namespace app { /** * @brief Get OHLCV time bucket lengths supported (configured) by this API server - * @return A list of time bucket lengths in seconds. E.G. if the result contains a number "300", + * @return A list of time bucket lengths in seconds. E.G. if the result contains a number "300", * it means this API server supports OHLCV data aggregated in 5-minute buckets. - */ + */ flat_set get_market_history_buckets()const; private: application& _app; @@ -270,15 +270,18 @@ namespace graphene { namespace app { */ void broadcast_transaction(const precomputable_transaction& trx); - /** this version of broadcast transaction registers a callback method that will be called when the transaction is - * included into a block. The callback method includes the transaction id, block number, and transaction number in the - * block. + /** This version of broadcast transaction registers a callback method that will be called when the + * transaction is included into a block. The callback method includes the transaction id, block number, + * and transaction number in the block. + * @param cb the callback method + * @param trx the transaction */ void broadcast_transaction_with_callback( confirmation_callback cb, const precomputable_transaction& trx); - /** this version of broadcast transaction registers a callback method that will be called when the transaction is - * included into a block. The callback method includes the transaction id, block number, and transaction number in the - * block. + /** This version of broadcast transaction waits until the transaction is included into a block, + * then the transaction id, block number, and transaction number in the block will be returned. + * @param trx the transaction + * @return info about the block including the transaction */ fc::variant broadcast_transaction_synchronous(const precomputable_transaction& trx); @@ -348,22 +351,25 @@ namespace graphene { namespace app { private: application& _app; }; - + + /** + * @brief The crypto_api class allows computations related to blinded transfers. + */ class crypto_api { public: crypto_api(); - + /** - * @brief Generates a pedersen commitment: *commit = blind * G + value * G2. + * @brief Generates a pedersen commitment: *commit = blind * G + value * G2. * The commitment is 33 bytes, the blinding factor is 32 bytes. - * For more information about pederson commitment check next url https://en.wikipedia.org/wiki/Commitment_scheme + * For more information about pederson commitment check url https://en.wikipedia.org/wiki/Commitment_scheme * @param blind Sha-256 blind factor type * @param value Positive 64-bit integer value * @return A 33-byte pedersen commitment: *commit = blind * G + value * G2 */ fc::ecc::commitment_type blind( const fc::ecc::blind_factor_type& blind, uint64_t value ); - + /** * @brief Get sha-256 blind factor type * @param blinds_in List of sha-256 blind factor types @@ -371,18 +377,21 @@ namespace graphene { namespace app { * @return A blind factor type */ fc::ecc::blind_factor_type blind_sum( const std::vector& blinds_in, uint32_t non_neg ); - + /** * @brief Verifies that commits + neg_commits + excess == 0 * @param commits_in List of 33-byte pedersen commitments * @param neg_commits_in List of 33-byte pedersen commitments - * @param excess Sum of two list of 33-byte pedersen commitments where sums the first set and subtracts the second - * @return Boolean - true in event of commits + neg_commits + excess == 0, otherwise false + * @param excess Sum of two list of 33-byte pedersen commitments + * where sums the first set and subtracts the second + * @return Boolean - true in event of commits + neg_commits + excess == 0, otherwise false */ - bool verify_sum( - const std::vector& commits_in, const std::vector& neg_commits_in, int64_t excess + bool verify_sum( + const std::vector& commits_in, + const std::vector& neg_commits_in, + int64_t excess ); - + /** * @brief Verifies range proof for 33-byte pedersen commitment * @param commit 33-byte pedersen commitment @@ -390,9 +399,9 @@ namespace graphene { namespace app { * @return A structure with success, min and max values */ verify_range_result verify_range( const fc::ecc::commitment_type& commit, const std::vector& proof ); - + /** - * @brief Proves with respect to min_value the range for pedersen + * @brief Proves with respect to min_value the range for pedersen * commitment which has the provided blinding factor and value * @param min_value Positive 64-bit integer value * @param commit 33-byte pedersen commitment @@ -403,14 +412,14 @@ namespace graphene { namespace app { * @param actual_value 64-bit positive integer, must be greater or equal min_value * @return A list of characters as proof in proof */ - std::vector range_proof_sign( uint64_t min_value, - const commitment_type& commit, - const blind_factor_type& commit_blind, + std::vector range_proof_sign( uint64_t min_value, + const commitment_type& commit, + const blind_factor_type& commit_blind, const blind_factor_type& nonce, int8_t base10_exp, uint8_t min_bits, uint64_t actual_value ); - + /** * @brief Verifies range proof rewind for 33-byte pedersen commitment * @param nonce Sha-256 blind refactor type @@ -419,23 +428,23 @@ namespace graphene { namespace app { * @return A structure with success, min, max, value_out, blind_out and message_out values */ verify_range_proof_rewind_result verify_range_proof_rewind( const blind_factor_type& nonce, - const fc::ecc::commitment_type& commit, + const fc::ecc::commitment_type& commit, const std::vector& proof ); - + /** - * @brief Gets "range proof" info. The cli_wallet includes functionality for sending blind transfers + * @brief Gets "range proof" info. The cli_wallet includes functionality for sending blind transfers * in which the values of the input and outputs amounts are “blinded.” - * In the case where a transaction produces two or more outputs, (e.g. an amount to the intended - * recipient plus “change” back to the sender), + * In the case where a transaction produces two or more outputs, (e.g. an amount to the intended + * recipient plus “change” back to the sender), * a "range proof" must be supplied to prove that none of the outputs commit to a negative value. * @param proof List of proof's characters * @return A range proof info structure with exponent, mantissa, min and max values - */ + */ range_proof_info range_get_info( const std::vector& proof ); }; /** - * @brief + * @brief The asset_api class allows query of info about asset holders. */ class asset_api { @@ -477,7 +486,8 @@ namespace graphene { namespace app { class orders_api { public: - orders_api(application& app):_app(app), database_api( std::ref(*app.chain_database()), &(app.get_options()) ){} + orders_api(application& app) + :_app(app), database_api( std::ref(*app.chain_database()), &(app.get_options()) ){} //virtual ~orders_api() {} /** @@ -535,8 +545,8 @@ namespace graphene { namespace app { * @param password Password to login with * @return True if logged in successfully; false otherwise * - * @note This must be called prior to requesting other APIs. Other APIs may not be accessible until the client - * has sucessfully authenticated. + * @note This must be called prior to requesting other APIs. + * Other APIs may not be accessible until the client has sucessfully authenticated. */ bool login(const string& user, const string& password); /// @brief Retrieve the network block API From 9dfd1cd584ffcd2f3d2e1c0e742e8b52b51b56e1 Mon Sep 17 00:00:00 2001 From: abitmore Date: Tue, 23 Jul 2019 22:22:03 -0400 Subject: [PATCH 030/111] Update CLI wallet docs --- .../wallet/include/graphene/wallet/wallet.hpp | 2 +- libraries/wallet/wallet.cpp | 14 ++++++-------- programs/cli_wallet/main.cpp | 4 +++- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index ad19558ddb..cc10e7c50c 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -797,7 +797,7 @@ class wallet_api */ bool load_wallet_file(string wallet_filename = ""); - /** Quitting from the wallet. + /** Quit from the wallet. * * The current wallet will be closed and saved. */ diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index 8ae31ab48d..fdec9afed0 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -4172,6 +4172,10 @@ string wallet_api::gethelp(const string& method)const std::stringstream ss; ss << "\n"; + std::string doxygenHelpString = my->method_documentation.get_detailed_description(method); + if (!doxygenHelpString.empty()) + ss << doxygenHelpString << "\n"; + if( method == "import_key" ) { ss << "usage: import_key ACCOUNT_NAME_OR_ID WIF_PRIVATE_KEY\n\n"; @@ -4219,14 +4223,8 @@ string wallet_api::gethelp(const string& method)const ss << fc::json::to_pretty_string( graphene::chain::bitasset_options() ); ss << "\nBITASSET_OPTIONS may be null\n"; } - else - { - std::string doxygenHelpString = my->method_documentation.get_detailed_description(method); - if (!doxygenHelpString.empty()) - ss << doxygenHelpString; - else - ss << "No help defined for method " << method << "\n"; - } + else if (doxygenHelpString.empty()) + ss << "No help defined for method " << method << "\n"; return ss.str(); } diff --git a/programs/cli_wallet/main.cpp b/programs/cli_wallet/main.cpp index 630256615a..e33c1c28fe 100644 --- a/programs/cli_wallet/main.cpp +++ b/programs/cli_wallet/main.cpp @@ -309,9 +309,11 @@ int main( int argc, char** argv ) for( auto& name_formatter : wapiptr->get_result_formatters() ) wallet_cli->format_result( name_formatter.first, name_formatter.second ); + std::cout << "\nType \"help\" for a list of available commands.\n"; + std::cout << "Type \"gethelp \" for info about individual commands.\n\n"; if( wapiptr->is_new() ) { - std::cout << "Please use the set_password method to initialize a new wallet before continuing\n"; + std::cout << "Please use the \"set_password\" method to initialize a new wallet before continuing\n"; wallet_cli->set_prompt( "new >>> " ); } else From 97b240282dbc98f75d36f90eb5cd12a1aef783ec Mon Sep 17 00:00:00 2001 From: abitmore Date: Wed, 24 Jul 2019 05:20:03 -0400 Subject: [PATCH 031/111] Update database API docs --- libraries/app/include/graphene/app/database_api.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/app/include/graphene/app/database_api.hpp b/libraries/app/include/graphene/app/database_api.hpp index 28424f0d65..0842bdf4d1 100644 --- a/libraries/app/include/graphene/app/database_api.hpp +++ b/libraries/app/include/graphene/app/database_api.hpp @@ -308,9 +308,9 @@ class database_api account_id_type get_account_id_from_string(const std::string& name_or_id) const; /** - * @brief Get a list of accounts by IDs or names + * @brief Get a list of accounts by names or IDs * @param account_names_or_ids names or IDs of the accounts to retrieve - * @return The accounts corresponding to the provided IDs or names + * @return The accounts corresponding to the provided names or IDs * * This function has semantics identical to @ref get_objects */ From be417d36d009f258a6e118842f627b587afb8860 Mon Sep 17 00:00:00 2001 From: John Jones Date: Fri, 26 Jul 2019 10:48:36 -0500 Subject: [PATCH 032/111] modified CMakeLists.txt for static linking of libcurl --- libraries/plugins/elasticsearch/CMakeLists.txt | 11 ++++++++++- libraries/plugins/es_objects/CMakeLists.txt | 12 +++++++++++- libraries/utilities/CMakeLists.txt | 12 +++++++++++- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/libraries/plugins/elasticsearch/CMakeLists.txt b/libraries/plugins/elasticsearch/CMakeLists.txt index ce9c7c1d1d..06eb6384ef 100644 --- a/libraries/plugins/elasticsearch/CMakeLists.txt +++ b/libraries/plugins/elasticsearch/CMakeLists.txt @@ -3,7 +3,16 @@ file(GLOB HEADERS "include/graphene/elasticsearch/*.hpp") add_library( graphene_elasticsearch elasticsearch_plugin.cpp ) -find_package(CURL REQUIRED) +if (NOT WIN32 AND NOT APPLE AND CURL_STATICLIB) + set (OLD_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) + set (CMAKE_FIND_LIBRARY_SUFFIXES .a) + find_package(CURL REQUIRED) + list(APPEND CURL_LIBRARIES ssl crypto) + set (CMAKE_FIND_LIBRARY_SUFFIXES ${OLD_SUFFIXES}) +else (NOT WIN32 AND NOT APPLE AND CURL_STATICLIB) + find_package(CURL REQUIRED) +endif (NOT WIN32 AND NOT APPLE AND CURL_STATICLIB) + include_directories(${CURL_INCLUDE_DIRS}) if(MSVC) set_source_files_properties(elasticsearch_plugin.cpp PROPERTIES COMPILE_FLAGS "/bigobj" ) diff --git a/libraries/plugins/es_objects/CMakeLists.txt b/libraries/plugins/es_objects/CMakeLists.txt index 42d18a6580..60971c8e35 100644 --- a/libraries/plugins/es_objects/CMakeLists.txt +++ b/libraries/plugins/es_objects/CMakeLists.txt @@ -3,7 +3,17 @@ file(GLOB HEADERS "include/graphene/es_objects/*.hpp") add_library( graphene_es_objects es_objects.cpp ) -find_package(CURL REQUIRED) + +if (NOT WIN32 AND NOT APPLE AND CURL_STATICLIB) + set (OLD_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) + set (CMAKE_FIND_LIBRARY_SUFFIXES .a) + find_package(CURL REQUIRED) + list(APPEND CURL_LIBRARIES ssl crypto) + set (CMAKE_FIND_LIBRARY_SUFFIXES ${OLD_SUFFIXES}) +else (NOT WIN32 AND NOT APPLE AND CURL_STATICLIB) + find_package(CURL REQUIRED) +endif (NOT WIN32 AND NOT APPLE AND CURL_STATICLIB) + include_directories(${CURL_INCLUDE_DIRS}) if(CURL_STATICLIB) SET_TARGET_PROPERTIES(graphene_es_objects PROPERTIES diff --git a/libraries/utilities/CMakeLists.txt b/libraries/utilities/CMakeLists.txt index 4311ef46cb..4f166e18c4 100644 --- a/libraries/utilities/CMakeLists.txt +++ b/libraries/utilities/CMakeLists.txt @@ -19,7 +19,17 @@ set(sources configure_file("${CMAKE_CURRENT_SOURCE_DIR}/git_revision.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/git_revision.cpp" @ONLY) list(APPEND sources "${CMAKE_CURRENT_BINARY_DIR}/git_revision.cpp") -find_package(CURL REQUIRED) + +if (NOT WIN32 AND NOT APPLE AND CURL_STATICLIB) + set (OLD_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) + set (CMAKE_FIND_LIBRARY_SUFFIXES .a) + find_package(CURL REQUIRED) + list(APPEND CURL_LIBRARIES ssl crypto) + set (CMAKE_FIND_LIBRARY_SUFFIXES ${OLD_SUFFIXES}) +else (NOT WIN32 AND NOT APPLE AND CURL_STATICLIB) + find_package(CURL REQUIRED) +endif (NOT WIN32 AND NOT APPLE AND CURL_STATICLIB) + include_directories(${CURL_INCLUDE_DIRS}) add_library( graphene_utilities ${sources} From 94e1da6b5ebd39d86b745d7b42aac575ffc20c24 Mon Sep 17 00:00:00 2001 From: abitmore Date: Fri, 26 Jul 2019 20:09:47 -0400 Subject: [PATCH 033/111] Reduce log level of dupe_trx and fill_or_kill --- libraries/chain/db_block.cpp | 7 ++++++- libraries/chain/exceptions.cpp | 8 +++++++- .../chain/include/graphene/chain/exceptions.hpp | 7 ++++++- libraries/chain/market_evaluator.cpp | 5 ++++- libraries/net/node.cpp | 15 ++++++++++++++- 5 files changed, 37 insertions(+), 5 deletions(-) diff --git a/libraries/chain/db_block.cpp b/libraries/chain/db_block.cpp index ace071ec0d..7eb518d181 100644 --- a/libraries/chain/db_block.cpp +++ b/libraries/chain/db_block.cpp @@ -636,7 +636,12 @@ processed_transaction database::_apply_transaction(const signed_transaction& trx auto& trx_idx = get_mutable_index_type(); const chain_id_type& chain_id = get_chain_id(); if( !(skip & skip_transaction_dupe_check) ) - FC_ASSERT( trx_idx.indices().get().find(trx.id()) == trx_idx.indices().get().end() ); + { + GRAPHENE_ASSERT( trx_idx.indices().get().find(trx.id()) == trx_idx.indices().get().end(), + duplicate_transaction, + "Transaction '${txid}' is already in the database", + ("txid",trx.id()) ); + } transaction_evaluation_state eval_state(this); const chain_parameters& chain_parameters = get_global_properties().parameters; eval_state._trx = &trx; diff --git a/libraries/chain/exceptions.cpp b/libraries/chain/exceptions.cpp index 68606a91f6..2d3093d818 100644 --- a/libraries/chain/exceptions.cpp +++ b/libraries/chain/exceptions.cpp @@ -41,6 +41,7 @@ namespace graphene { namespace chain { FC_IMPLEMENT_DERIVED_EXCEPTION( database_query_exception, chain_exception, 3010000, "database query exception" ) FC_IMPLEMENT_DERIVED_EXCEPTION( block_validate_exception, chain_exception, 3020000, "block validation exception" ) + FC_IMPLEMENT_DERIVED_EXCEPTION( transaction_process_exception,chain_exception, 3030000, "transaction processing exception" ) FC_IMPLEMENT_DERIVED_EXCEPTION( operation_validate_exception, chain_exception, 3040000, "operation validation exception" ) FC_IMPLEMENT_DERIVED_EXCEPTION( operation_evaluate_exception, chain_exception, 3050000, "operation evaluation exception" ) FC_IMPLEMENT_DERIVED_EXCEPTION( utility_exception, chain_exception, 3060000, "utility method exception" ) @@ -51,6 +52,8 @@ namespace graphene { namespace chain { FC_IMPLEMENT_DERIVED_EXCEPTION( insufficient_feeds, chain_exception, 37006, "insufficient feeds" ) + FC_IMPLEMENT_DERIVED_EXCEPTION( duplicate_transaction, transaction_process_exception, 3030001, "duplicate transaction" ) + FC_IMPLEMENT_DERIVED_EXCEPTION( pop_empty_chain, undo_database_exception, 3070001, "there are no blocks to pop" ) GRAPHENE_IMPLEMENT_OP_BASE_EXCEPTIONS( transfer ); @@ -58,7 +61,10 @@ namespace graphene { namespace chain { GRAPHENE_IMPLEMENT_OP_EVALUATE_EXCEPTION( to_account_not_whitelisted, transfer, 2, "owner mismatch" ) GRAPHENE_IMPLEMENT_OP_EVALUATE_EXCEPTION( restricted_transfer_asset, transfer, 3, "restricted transfer asset" ) - //GRAPHENE_IMPLEMENT_OP_BASE_EXCEPTIONS( limit_order_create ); + GRAPHENE_IMPLEMENT_OP_BASE_EXCEPTIONS( limit_order_create ); + GRAPHENE_IMPLEMENT_OP_EVALUATE_EXCEPTION( kill_unfilled, limit_order_create, 1, + "Killing limit order due to unable to fill" ) + //GRAPHENE_IMPLEMENT_OP_BASE_EXCEPTIONS( limit_order_cancel ); GRAPHENE_IMPLEMENT_OP_BASE_EXCEPTIONS( call_order_update ); GRAPHENE_IMPLEMENT_OP_EVALUATE_EXCEPTION( unfilled_margin_call, call_order_update, 1, "Updating call order would trigger a margin call that cannot be fully filled" ) diff --git a/libraries/chain/include/graphene/chain/exceptions.hpp b/libraries/chain/include/graphene/chain/exceptions.hpp index 0aa9b3db4a..9d85318c4d 100644 --- a/libraries/chain/include/graphene/chain/exceptions.hpp +++ b/libraries/chain/include/graphene/chain/exceptions.hpp @@ -110,6 +110,7 @@ namespace graphene { namespace chain { FC_DECLARE_DERIVED_EXCEPTION( database_query_exception, chain_exception, 3010000 ) FC_DECLARE_DERIVED_EXCEPTION( block_validate_exception, chain_exception, 3020000 ) + FC_DECLARE_DERIVED_EXCEPTION( transaction_process_exception,chain_exception, 3030000 ) FC_DECLARE_DERIVED_EXCEPTION( operation_validate_exception, chain_exception, 3040000 ) FC_DECLARE_DERIVED_EXCEPTION( operation_evaluate_exception, chain_exception, 3050000 ) FC_DECLARE_DERIVED_EXCEPTION( utility_exception, chain_exception, 3060000 ) @@ -120,6 +121,8 @@ namespace graphene { namespace chain { FC_DECLARE_DERIVED_EXCEPTION( insufficient_feeds, chain_exception, 37006 ) + FC_DECLARE_DERIVED_EXCEPTION( duplicate_transaction, transaction_process_exception, 3030001 ) + FC_DECLARE_DERIVED_EXCEPTION( pop_empty_chain, undo_database_exception, 3070001 ) GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( transfer ); @@ -127,7 +130,9 @@ namespace graphene { namespace chain { GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( to_account_not_whitelisted, transfer, 2, "owner mismatch" ) GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( restricted_transfer_asset, transfer, 3, "restricted transfer asset" ) - //GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( limit_order_create ); + GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( limit_order_create ); + GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( kill_unfilled, limit_order_create, 1, ) + //GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( limit_order_cancel ); GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( call_order_update ); GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( unfilled_margin_call, call_order_update, 1, "Updating call order would trigger a margin call that cannot be fully filled" ) diff --git a/libraries/chain/market_evaluator.cpp b/libraries/chain/market_evaluator.cpp index 18ebbe0180..f9b894d998 100644 --- a/libraries/chain/market_evaluator.cpp +++ b/libraries/chain/market_evaluator.cpp @@ -119,7 +119,10 @@ object_id_type limit_order_create_evaluator::do_apply(const limit_order_create_o else filled = db().apply_order( new_order_object ); - FC_ASSERT( !op.fill_or_kill || filled ); + GRAPHENE_ASSERT( !op.fill_or_kill || filled, + limit_order_create_kill_unfilled, + "Killing limit order ${op} due to unable to fill", + ("op",op) ); return order_id; } FC_CAPTURE_AND_RETHROW( (op) ) } diff --git a/libraries/net/node.cpp b/libraries/net/node.cpp index f570dac5bf..0224f4444f 100644 --- a/libraries/net/node.cpp +++ b/libraries/net/node.cpp @@ -3400,7 +3400,20 @@ namespace graphene { namespace net { namespace detail { } catch ( const fc::exception& e ) { - wlog( "client rejected message sent by peer ${peer}, ${e}", ("peer", originating_peer->get_remote_endpoint() )("e", e) ); + switch( e.code() ) + { + // log common exceptions in debug level + case 3030001: // duplicate_transaction + case 3050101: // limit_order_create_kill_unfilled + dlog( "client rejected message sent by peer ${peer}, ${e}", + ("peer", originating_peer->get_remote_endpoint() )("e", e) ); + break; + // log rarer exceptions in warn level + default: + wlog( "client rejected message sent by peer ${peer}, ${e}", + ("peer", originating_peer->get_remote_endpoint() )("e", e) ); + break; + } // record it so we don't try to fetch this item again _recently_failed_items.insert(peer_connection::timestamped_item_id(item_id(message_to_process.msg_type.value(), message_hash ), fc::time_point::now())); return; From c52eb625994c4be0dbb782944f8ada40d12fd6c6 Mon Sep 17 00:00:00 2001 From: abitmore Date: Sat, 27 Jul 2019 04:36:57 -0400 Subject: [PATCH 034/111] Wrap long lines --- libraries/net/node.cpp | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/libraries/net/node.cpp b/libraries/net/node.cpp index 0224f4444f..ad8bbec4f2 100644 --- a/libraries/net/node.cpp +++ b/libraries/net/node.cpp @@ -3346,7 +3346,7 @@ namespace graphene { namespace net { namespace detail { } void node_impl::on_get_current_connections_reply_message(peer_connection* originating_peer, - const get_current_connections_reply_message& get_current_connections_reply_message_received) + const get_current_connections_reply_message& get_current_connections_reply_message_received) { VERIFY_CORRECT_THREAD(); } @@ -3358,19 +3358,22 @@ namespace graphene { namespace net { namespace detail { // this just passes the message to the client, and does the bookkeeping // related to requesting and rebroadcasting the message. void node_impl::process_ordinary_message( peer_connection* originating_peer, - const message& message_to_process, const message_hash_type& message_hash ) + const message& message_to_process, + const message_hash_type& message_hash ) { VERIFY_CORRECT_THREAD(); fc::time_point message_receive_time = fc::time_point::now(); // only process it if we asked for it - auto iter = originating_peer->items_requested_from_peer.find( item_id(message_to_process.msg_type.value(), message_hash) ); + auto iter = originating_peer->items_requested_from_peer.find( + item_id(message_to_process.msg_type.value(), message_hash) ); if( iter == originating_peer->items_requested_from_peer.end() ) { wlog( "received a message I didn't ask for from peer ${endpoint}, disconnecting from peer", ( "endpoint", originating_peer->get_remote_endpoint() ) ); - fc::exception detailed_error( FC_LOG_MESSAGE(error, "You sent me a message that I didn't ask for, message_hash: ${message_hash}", - ( "message_hash", message_hash ) ) ); + fc::exception detailed_error( FC_LOG_MESSAGE(error, + "You sent me a message that I didn't ask for, message_hash: ${message_hash}", + ( "message_hash", message_hash ) ) ); disconnect_from_peer( originating_peer, "You sent me a message that I didn't request", true, detailed_error ); return; } @@ -3387,7 +3390,8 @@ namespace graphene { namespace net { namespace detail { if (message_to_process.msg_type.value() == trx_message_type) { trx_message transaction_message_to_process = message_to_process.as(); - dlog("passing message containing transaction ${trx} to client", ("trx", transaction_message_to_process.trx.id())); + dlog( "passing message containing transaction ${trx} to client", + ("trx", transaction_message_to_process.trx.id()) ); _delegate->handle_transaction(transaction_message_to_process); } else @@ -3415,12 +3419,14 @@ namespace graphene { namespace net { namespace detail { break; } // record it so we don't try to fetch this item again - _recently_failed_items.insert(peer_connection::timestamped_item_id(item_id(message_to_process.msg_type.value(), message_hash ), fc::time_point::now())); + _recently_failed_items.insert( peer_connection::timestamped_item_id( + item_id( message_to_process.msg_type.value(), message_hash ), fc::time_point::now() ) ); return; } // finally, if the delegate validated the message, broadcast it to our other peers - message_propagation_data propagation_data{message_receive_time, message_validated_time, originating_peer->node_id}; + message_propagation_data propagation_data { message_receive_time, message_validated_time, + originating_peer->node_id }; broadcast( message_to_process, propagation_data ); } } From eea889ddeca477b92a0c641f8a1debe377dd79c7 Mon Sep 17 00:00:00 2001 From: abitmore Date: Sat, 27 Jul 2019 12:30:12 -0400 Subject: [PATCH 035/111] Reduce log level of exceptions in order_cancel_op Some bots place limit orders then try to cancel some of them before a new block arrives. However, the order's id (in pending state) may be different in individual nodes, thus caused the exceptions. A potential solution to the order_id inconsistent issue: https://github.com/bitshares/bitshares-core/issues/556 --- libraries/chain/exceptions.cpp | 5 ++++- .../chain/include/graphene/chain/exceptions.hpp | 5 ++++- libraries/chain/market_evaluator.cpp | 13 +++++++++++-- libraries/net/node.cpp | 2 ++ 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/libraries/chain/exceptions.cpp b/libraries/chain/exceptions.cpp index 2d3093d818..7a27b07b4a 100644 --- a/libraries/chain/exceptions.cpp +++ b/libraries/chain/exceptions.cpp @@ -65,7 +65,10 @@ namespace graphene { namespace chain { GRAPHENE_IMPLEMENT_OP_EVALUATE_EXCEPTION( kill_unfilled, limit_order_create, 1, "Killing limit order due to unable to fill" ) - //GRAPHENE_IMPLEMENT_OP_BASE_EXCEPTIONS( limit_order_cancel ); + GRAPHENE_IMPLEMENT_OP_BASE_EXCEPTIONS( limit_order_cancel ); + GRAPHENE_IMPLEMENT_OP_EVALUATE_EXCEPTION( nonexist_order, limit_order_cancel, 1, "Order does not exist" ) + GRAPHENE_IMPLEMENT_OP_EVALUATE_EXCEPTION( owner_mismatch, limit_order_cancel, 2, "Order owned by someone else" ) + GRAPHENE_IMPLEMENT_OP_BASE_EXCEPTIONS( call_order_update ); GRAPHENE_IMPLEMENT_OP_EVALUATE_EXCEPTION( unfilled_margin_call, call_order_update, 1, "Updating call order would trigger a margin call that cannot be fully filled" ) diff --git a/libraries/chain/include/graphene/chain/exceptions.hpp b/libraries/chain/include/graphene/chain/exceptions.hpp index 9d85318c4d..9104115563 100644 --- a/libraries/chain/include/graphene/chain/exceptions.hpp +++ b/libraries/chain/include/graphene/chain/exceptions.hpp @@ -133,7 +133,10 @@ namespace graphene { namespace chain { GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( limit_order_create ); GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( kill_unfilled, limit_order_create, 1, ) - //GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( limit_order_cancel ); + GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( limit_order_cancel ); + GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( nonexist_order, limit_order_cancel, 1, ) + GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( owner_mismatch, limit_order_cancel, 2, ) + GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( call_order_update ); GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( unfilled_margin_call, call_order_update, 1, "Updating call order would trigger a margin call that cannot be fully filled" ) diff --git a/libraries/chain/market_evaluator.cpp b/libraries/chain/market_evaluator.cpp index f9b894d998..a1a8623b66 100644 --- a/libraries/chain/market_evaluator.cpp +++ b/libraries/chain/market_evaluator.cpp @@ -131,8 +131,17 @@ void_result limit_order_cancel_evaluator::do_evaluate(const limit_order_cancel_o { try { database& d = db(); - _order = &o.order(d); - FC_ASSERT( _order->seller == o.fee_paying_account ); + _order = d.find( o.order ); + + GRAPHENE_ASSERT( _order != nullptr, + limit_order_cancel_nonexist_order, + "Limit order ${oid} does not exist", + ("oid", o.order) ); + + GRAPHENE_ASSERT( _order->seller == o.fee_paying_account, + limit_order_cancel_owner_mismatch, + "Limit order ${oid} is owned by someone else", + ("oid", o.order) ); return void_result(); } FC_CAPTURE_AND_RETHROW( (o) ) } diff --git a/libraries/net/node.cpp b/libraries/net/node.cpp index ad8bbec4f2..721def0b87 100644 --- a/libraries/net/node.cpp +++ b/libraries/net/node.cpp @@ -3409,6 +3409,8 @@ namespace graphene { namespace net { namespace detail { // log common exceptions in debug level case 3030001: // duplicate_transaction case 3050101: // limit_order_create_kill_unfilled + case 3050201: // limit_order_cancel_nonexist_order + case 3050202: // limit_order_cancel_owner_mismatch dlog( "client rejected message sent by peer ${peer}, ${e}", ("peer", originating_peer->get_remote_endpoint() )("e", e) ); break; From 58d140791b38444387c70b199e0d42a900086cf1 Mon Sep 17 00:00:00 2001 From: abitmore Date: Sun, 28 Jul 2019 16:21:11 -0400 Subject: [PATCH 036/111] Wrap long lines --- libraries/net/node.cpp | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/libraries/net/node.cpp b/libraries/net/node.cpp index 721def0b87..625b48c071 100644 --- a/libraries/net/node.cpp +++ b/libraries/net/node.cpp @@ -2417,7 +2417,8 @@ namespace graphene { namespace net { namespace detail { } - void node_impl::on_closing_connection_message( peer_connection* originating_peer, const closing_connection_message& closing_connection_message_received ) + void node_impl::on_closing_connection_message( peer_connection* originating_peer, + const closing_connection_message& closing_connection_message_received ) { VERIFY_CORRECT_THREAD(); originating_peer->they_have_requested_close = true; @@ -2429,12 +2430,14 @@ namespace graphene { namespace net { namespace detail { ( "msg", closing_connection_message_received.reason_for_closing ) ( "error", closing_connection_message_received.error ) ); std::ostringstream message; - message << "Peer " << fc::variant( originating_peer->get_remote_endpoint(), GRAPHENE_NET_MAX_NESTED_OBJECTS ).as_string() << + message << "Peer " << fc::variant( originating_peer->get_remote_endpoint(), + GRAPHENE_NET_MAX_NESTED_OBJECTS ).as_string() << " disconnected us: " << closing_connection_message_received.reason_for_closing; - fc::exception detailed_error(FC_LOG_MESSAGE(warn, "Peer ${peer} is disconnecting us because of an error: ${msg}, exception: ${error}", - ( "peer", originating_peer->get_remote_endpoint() ) - ( "msg", closing_connection_message_received.reason_for_closing ) - ( "error", closing_connection_message_received.error ) )); + fc::exception detailed_error(FC_LOG_MESSAGE(warn, + "Peer ${peer} is disconnecting us because of an error: ${msg}, exception: ${error}", + ( "peer", originating_peer->get_remote_endpoint() ) + ( "msg", closing_connection_message_received.reason_for_closing ) + ( "error", closing_connection_message_received.error ) )); _delegate->error_encountered( message.str(), detailed_error ); } @@ -2667,7 +2670,8 @@ namespace graphene { namespace net { namespace detail { { ASSERT_TASK_NOT_PREEMPTED(); // don't yield while iterating over _active_connections - if (peer->ids_of_items_being_processed.find(block_message_to_send.block_id) != peer->ids_of_items_being_processed.end()) + if (peer->ids_of_items_being_processed.find(block_message_to_send.block_id) + != peer->ids_of_items_being_processed.end()) { if (discontinue_fetching_blocks_from_peer) { @@ -2676,7 +2680,9 @@ namespace graphene { namespace net { namespace detail { peer->inhibit_fetching_sync_blocks = true; } else - peers_to_disconnect[peer] = std::make_pair(std::string("You offered us a block that we reject as invalid"), fc::oexception(handle_message_exception)); + peers_to_disconnect[peer] = std::make_pair( + std::string("You offered us a block that we reject as invalid"), + fc::oexception(handle_message_exception)); } } } From 98bd37e6b325b3106c25294502063ac42f28c67e Mon Sep 17 00:00:00 2001 From: John Jones Date: Mon, 29 Jul 2019 13:07:51 -0500 Subject: [PATCH 037/111] move logic to main CMakeLists.txt --- CMakeLists.txt | 13 +++++++++++++ libraries/plugins/elasticsearch/CMakeLists.txt | 11 ++--------- libraries/plugins/es_objects/CMakeLists.txt | 10 +--------- libraries/utilities/CMakeLists.txt | 10 +--------- 4 files changed, 17 insertions(+), 27 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 91f4dd95d0..4540350f8e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,6 +29,19 @@ list( APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules" ) include(CheckCCompilerFlag) include(Utils) +# function to help with cUrl +macro(FIND_CURL) + if (NOT WIN32 AND NOT APPLE AND CURL_STATICLIB) + set (OLD_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) + set (CMAKE_FIND_LIBRARY_SUFFIXES .a) + find_package(CURL REQUIRED) + list(APPEND CURL_LIBRARIES ssl crypto) + set (CMAKE_FIND_LIBRARY_SUFFIXES ${OLD_SUFFIXES}) + else (NOT WIN32 AND NOT APPLE AND CURL_STATICLIB) + find_package(CURL REQUIRED) + endif (NOT WIN32 AND NOT APPLE AND CURL_STATICLIB) +endmacro() + # Fortify source if (CMAKE_COMPILER_IS_GNUCXX) if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") diff --git a/libraries/plugins/elasticsearch/CMakeLists.txt b/libraries/plugins/elasticsearch/CMakeLists.txt index 06eb6384ef..c7810f4eb3 100644 --- a/libraries/plugins/elasticsearch/CMakeLists.txt +++ b/libraries/plugins/elasticsearch/CMakeLists.txt @@ -3,15 +3,8 @@ file(GLOB HEADERS "include/graphene/elasticsearch/*.hpp") add_library( graphene_elasticsearch elasticsearch_plugin.cpp ) -if (NOT WIN32 AND NOT APPLE AND CURL_STATICLIB) - set (OLD_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) - set (CMAKE_FIND_LIBRARY_SUFFIXES .a) - find_package(CURL REQUIRED) - list(APPEND CURL_LIBRARIES ssl crypto) - set (CMAKE_FIND_LIBRARY_SUFFIXES ${OLD_SUFFIXES}) -else (NOT WIN32 AND NOT APPLE AND CURL_STATICLIB) - find_package(CURL REQUIRED) -endif (NOT WIN32 AND NOT APPLE AND CURL_STATICLIB) + +find_curl() include_directories(${CURL_INCLUDE_DIRS}) if(MSVC) diff --git a/libraries/plugins/es_objects/CMakeLists.txt b/libraries/plugins/es_objects/CMakeLists.txt index 60971c8e35..2cae2ffde4 100644 --- a/libraries/plugins/es_objects/CMakeLists.txt +++ b/libraries/plugins/es_objects/CMakeLists.txt @@ -4,15 +4,7 @@ add_library( graphene_es_objects es_objects.cpp ) -if (NOT WIN32 AND NOT APPLE AND CURL_STATICLIB) - set (OLD_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) - set (CMAKE_FIND_LIBRARY_SUFFIXES .a) - find_package(CURL REQUIRED) - list(APPEND CURL_LIBRARIES ssl crypto) - set (CMAKE_FIND_LIBRARY_SUFFIXES ${OLD_SUFFIXES}) -else (NOT WIN32 AND NOT APPLE AND CURL_STATICLIB) - find_package(CURL REQUIRED) -endif (NOT WIN32 AND NOT APPLE AND CURL_STATICLIB) +find_curl() include_directories(${CURL_INCLUDE_DIRS}) if(CURL_STATICLIB) diff --git a/libraries/utilities/CMakeLists.txt b/libraries/utilities/CMakeLists.txt index 4f166e18c4..c4c01cd212 100644 --- a/libraries/utilities/CMakeLists.txt +++ b/libraries/utilities/CMakeLists.txt @@ -20,15 +20,7 @@ set(sources configure_file("${CMAKE_CURRENT_SOURCE_DIR}/git_revision.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/git_revision.cpp" @ONLY) list(APPEND sources "${CMAKE_CURRENT_BINARY_DIR}/git_revision.cpp") -if (NOT WIN32 AND NOT APPLE AND CURL_STATICLIB) - set (OLD_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) - set (CMAKE_FIND_LIBRARY_SUFFIXES .a) - find_package(CURL REQUIRED) - list(APPEND CURL_LIBRARIES ssl crypto) - set (CMAKE_FIND_LIBRARY_SUFFIXES ${OLD_SUFFIXES}) -else (NOT WIN32 AND NOT APPLE AND CURL_STATICLIB) - find_package(CURL REQUIRED) -endif (NOT WIN32 AND NOT APPLE AND CURL_STATICLIB) +find_curl() include_directories(${CURL_INCLUDE_DIRS}) add_library( graphene_utilities From 8bbd21710d6a59112b87ce9099643a7f19323c7c Mon Sep 17 00:00:00 2001 From: abitmore Date: Mon, 29 Jul 2019 15:57:11 -0400 Subject: [PATCH 038/111] Reduce log level of exceptions in order_create_op Some misconfigured bots were trying to place limit orders in unauthorized markets, or place orders when don't have sufficient balance (this could also be caused by inconsistent pending state). --- libraries/chain/exceptions.cpp | 10 ++++++ .../include/graphene/chain/exceptions.hpp | 5 +++ libraries/chain/market_evaluator.cpp | 33 +++++++++++++------ libraries/net/node.cpp | 5 +++ 4 files changed, 43 insertions(+), 10 deletions(-) diff --git a/libraries/chain/exceptions.cpp b/libraries/chain/exceptions.cpp index 7a27b07b4a..5c7feffcde 100644 --- a/libraries/chain/exceptions.cpp +++ b/libraries/chain/exceptions.cpp @@ -64,6 +64,16 @@ namespace graphene { namespace chain { GRAPHENE_IMPLEMENT_OP_BASE_EXCEPTIONS( limit_order_create ); GRAPHENE_IMPLEMENT_OP_EVALUATE_EXCEPTION( kill_unfilled, limit_order_create, 1, "Killing limit order due to unable to fill" ) + GRAPHENE_IMPLEMENT_OP_EVALUATE_EXCEPTION( market_not_whitelisted, limit_order_create, 2, + "The market has not been whitelisted by the selling asset" ) + GRAPHENE_IMPLEMENT_OP_EVALUATE_EXCEPTION( market_blacklisted, limit_order_create, 3, + "The market has been blacklisted by the selling asset" ) + GRAPHENE_IMPLEMENT_OP_EVALUATE_EXCEPTION( selling_asset_unauthorized, limit_order_create, 4, + "The account is not allowed to transact the selling asset" ) + GRAPHENE_IMPLEMENT_OP_EVALUATE_EXCEPTION( receiving_asset_unauthorized, limit_order_create, 5, + "The account is not allowed to transact the receiving asset" ) + GRAPHENE_IMPLEMENT_OP_EVALUATE_EXCEPTION( insufficient_balance, limit_order_create, 6, + "Insufficient balance" ) GRAPHENE_IMPLEMENT_OP_BASE_EXCEPTIONS( limit_order_cancel ); GRAPHENE_IMPLEMENT_OP_EVALUATE_EXCEPTION( nonexist_order, limit_order_cancel, 1, "Order does not exist" ) diff --git a/libraries/chain/include/graphene/chain/exceptions.hpp b/libraries/chain/include/graphene/chain/exceptions.hpp index 9104115563..ed61381a59 100644 --- a/libraries/chain/include/graphene/chain/exceptions.hpp +++ b/libraries/chain/include/graphene/chain/exceptions.hpp @@ -132,6 +132,11 @@ namespace graphene { namespace chain { GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( limit_order_create ); GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( kill_unfilled, limit_order_create, 1, ) + GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( market_not_whitelisted, limit_order_create, 2, ) + GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( market_blacklisted, limit_order_create, 3, ) + GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( selling_asset_unauthorized, limit_order_create, 4, ) + GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( receiving_asset_unauthorized, limit_order_create, 5, ) + GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( insufficient_balance, limit_order_create, 6, ) GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( limit_order_cancel ); GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( nonexist_order, limit_order_cancel, 1, ) diff --git a/libraries/chain/market_evaluator.cpp b/libraries/chain/market_evaluator.cpp index a1a8623b66..4b6d9af928 100644 --- a/libraries/chain/market_evaluator.cpp +++ b/libraries/chain/market_evaluator.cpp @@ -48,19 +48,32 @@ void_result limit_order_create_evaluator::do_evaluate(const limit_order_create_o _receive_asset = &op.min_to_receive.asset_id(d); if( _sell_asset->options.whitelist_markets.size() ) - FC_ASSERT( _sell_asset->options.whitelist_markets.find(_receive_asset->id) - != _sell_asset->options.whitelist_markets.end(), - "This market has not been whitelisted." ); + { + GRAPHENE_ASSERT( _sell_asset->options.whitelist_markets.find(_receive_asset->id) + != _sell_asset->options.whitelist_markets.end(), + limit_order_create_market_not_whitelisted, + "This market has not been whitelisted by the selling asset", ); + } if( _sell_asset->options.blacklist_markets.size() ) - FC_ASSERT( _sell_asset->options.blacklist_markets.find(_receive_asset->id) - == _sell_asset->options.blacklist_markets.end(), - "This market has been blacklisted." ); + { + GRAPHENE_ASSERT( _sell_asset->options.blacklist_markets.find(_receive_asset->id) + == _sell_asset->options.blacklist_markets.end(), + limit_order_create_market_blacklisted, + "This market has been blacklisted by the selling asset", ); + } + + GRAPHENE_ASSERT( is_authorized_asset( d, *_seller, *_sell_asset ), + limit_order_create_selling_asset_unauthorized, + "The account is not allowed to transact the selling asset", ); - FC_ASSERT( is_authorized_asset( d, *_seller, *_sell_asset ) ); - FC_ASSERT( is_authorized_asset( d, *_seller, *_receive_asset ) ); + GRAPHENE_ASSERT( is_authorized_asset( d, *_seller, *_receive_asset ), + limit_order_create_receiving_asset_unauthorized, + "The account is not allowed to transact the receiving asset", ); - FC_ASSERT( d.get_balance( *_seller, *_sell_asset ) >= op.amount_to_sell, "insufficient balance", - ("balance",d.get_balance(*_seller,*_sell_asset))("amount_to_sell",op.amount_to_sell) ); + GRAPHENE_ASSERT( d.get_balance( *_seller, *_sell_asset ) >= op.amount_to_sell, + limit_order_create_insufficient_balance, + "insufficient balance", + ("balance",d.get_balance(*_seller,*_sell_asset))("amount_to_sell",op.amount_to_sell) ); return void_result(); } FC_CAPTURE_AND_RETHROW( (op) ) } diff --git a/libraries/net/node.cpp b/libraries/net/node.cpp index 625b48c071..8d9306c936 100644 --- a/libraries/net/node.cpp +++ b/libraries/net/node.cpp @@ -3415,6 +3415,11 @@ namespace graphene { namespace net { namespace detail { // log common exceptions in debug level case 3030001: // duplicate_transaction case 3050101: // limit_order_create_kill_unfilled + case 3050102: // limit_order_create_market_not_whitelisted + case 3050103: // limit_order_create_market_blacklisted + case 3050104: // limit_order_create_selling_asset_unauthorized + case 3050105: // limit_order_create_receiving_asset_unauthorized + case 3050106: // limit_order_create_insufficient_balance case 3050201: // limit_order_cancel_nonexist_order case 3050202: // limit_order_cancel_owner_mismatch dlog( "client rejected message sent by peer ${peer}, ${e}", From c213f3b0a85476f0e5b5a73bf53f8dd8ee87009a Mon Sep 17 00:00:00 2001 From: abitmore Date: Tue, 30 Jul 2019 15:45:32 -0400 Subject: [PATCH 039/111] Replace magic numbers in node.cpp with enum names --- libraries/net/node.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/libraries/net/node.cpp b/libraries/net/node.cpp index 8d9306c936..e3949852c7 100644 --- a/libraries/net/node.cpp +++ b/libraries/net/node.cpp @@ -79,6 +79,7 @@ #include #include +#include // Nasty hack: A circular dependency around fee_schedule is resolved by fwd-declaring it and using a shared_ptr // to it in chain_parameters, which is used in an operation and thus must be serialized by the net library. // Resolving that forward declaration doesn't happen until now: @@ -3413,15 +3414,15 @@ namespace graphene { namespace net { namespace detail { switch( e.code() ) { // log common exceptions in debug level - case 3030001: // duplicate_transaction - case 3050101: // limit_order_create_kill_unfilled - case 3050102: // limit_order_create_market_not_whitelisted - case 3050103: // limit_order_create_market_blacklisted - case 3050104: // limit_order_create_selling_asset_unauthorized - case 3050105: // limit_order_create_receiving_asset_unauthorized - case 3050106: // limit_order_create_insufficient_balance - case 3050201: // limit_order_cancel_nonexist_order - case 3050202: // limit_order_cancel_owner_mismatch + case graphene::chain::duplicate_transaction::code_enum::code_value : + case graphene::chain::limit_order_create_kill_unfilled::code_enum::code_value : + case graphene::chain::limit_order_create_market_not_whitelisted::code_enum::code_value : + case graphene::chain::limit_order_create_market_blacklisted::code_enum::code_value : + case graphene::chain::limit_order_create_selling_asset_unauthorized::code_enum::code_value : + case graphene::chain::limit_order_create_receiving_asset_unauthorized::code_enum::code_value : + case graphene::chain::limit_order_create_insufficient_balance::code_enum::code_value : + case graphene::chain::limit_order_cancel_nonexist_order::code_enum::code_value : + case graphene::chain::limit_order_cancel_owner_mismatch::code_enum::code_value : dlog( "client rejected message sent by peer ${peer}, ${e}", ("peer", originating_peer->get_remote_endpoint() )("e", e) ); break; From a71694905cb43ad3d36779f414efe1b66139a79d Mon Sep 17 00:00:00 2001 From: abitmore Date: Tue, 30 Jul 2019 16:27:43 -0400 Subject: [PATCH 040/111] Send shorter disconn-msg when got a future block --- libraries/app/application.cpp | 4 ++- libraries/net/exceptions.cpp | 2 ++ .../net/include/graphene/net/exceptions.hpp | 1 + libraries/net/node.cpp | 31 +++++++++++++++---- 4 files changed, 31 insertions(+), 7 deletions(-) diff --git a/libraries/app/application.cpp b/libraries/app/application.cpp index a7f8b76b3b..4f835ff10d 100644 --- a/libraries/app/application.cpp +++ b/libraries/app/application.cpp @@ -568,7 +568,9 @@ bool application_impl::handle_block(const graphene::net::block_message& blk_msg, ("w",witness_account.name) ("i",last_irr)("d",blk_msg.block.block_num()-last_irr) ); } - FC_ASSERT( (latency.count()/1000) > -5000, "Rejecting block with timestamp in the future" ); + GRAPHENE_ASSERT( latency.count()/1000 > -5000, + graphene::net::block_timestamp_in_future_exception, + "Rejecting block with timestamp in the future", ); try { const uint32_t skip = (_is_block_producer | _force_validate) ? diff --git a/libraries/net/exceptions.cpp b/libraries/net/exceptions.cpp index 7b6e23dc5d..5900eec66f 100644 --- a/libraries/net/exceptions.cpp +++ b/libraries/net/exceptions.cpp @@ -37,5 +37,7 @@ namespace graphene { namespace net { FC_IMPLEMENT_DERIVED_EXCEPTION( peer_is_on_an_unreachable_fork, net_exception, 90005, "peer is on another fork" ) FC_IMPLEMENT_DERIVED_EXCEPTION( unlinkable_block_exception, net_exception, 90006, "unlinkable block" ) + FC_IMPLEMENT_DERIVED_EXCEPTION( block_timestamp_in_future_exception, net_exception, 90007, + "block timestamp in the future" ) } } diff --git a/libraries/net/include/graphene/net/exceptions.hpp b/libraries/net/include/graphene/net/exceptions.hpp index e95eea8759..2a47d333eb 100644 --- a/libraries/net/include/graphene/net/exceptions.hpp +++ b/libraries/net/include/graphene/net/exceptions.hpp @@ -34,5 +34,6 @@ namespace graphene { namespace net { FC_DECLARE_DERIVED_EXCEPTION( block_older_than_undo_history, net_exception, 90004 ) FC_DECLARE_DERIVED_EXCEPTION( peer_is_on_an_unreachable_fork, net_exception, 90005 ) FC_DECLARE_DERIVED_EXCEPTION( unlinkable_block_exception, net_exception, 90006 ) + FC_DECLARE_DERIVED_EXCEPTION( block_timestamp_in_future_exception, net_exception, 90007 ) } } diff --git a/libraries/net/node.cpp b/libraries/net/node.cpp index e3949852c7..fc2a086ee2 100644 --- a/libraries/net/node.cpp +++ b/libraries/net/node.cpp @@ -2575,11 +2575,20 @@ namespace graphene { namespace net { namespace detail { } catch (const fc::exception& e) { + auto block_num = block_message_to_send.block.block_num(); wlog("Failed to push sync block ${num} (id:${id}): client rejected sync block sent by peer: ${e}", - ("num", block_message_to_send.block.block_num()) + ("num", block_num) ("id", block_message_to_send.block_id) ("e", e)); - handle_message_exception = e; + if( e.code() == block_timestamp_in_future_exception::code_enum::code_value ) + { + handle_message_exception = block_timestamp_in_future_exception( FC_LOG_MESSAGE( warn, "", + ("block_header", static_cast(block_message_to_send.block)) + ("block_num", block_num) + ("block_id", block_message_to_send.block_id) ) ); + } + else + handle_message_exception = e; } // build up lists for any potentially-blocking operations we need to do, then do them @@ -2992,11 +3001,21 @@ namespace graphene { namespace net { namespace detail { catch (const fc::exception& e) { // client rejected the block. Disconnect the client and any other clients that offered us this block - wlog("Failed to push block ${num} (id:${id}), client rejected block sent by peer", - ("num", block_message_to_process.block.block_num()) - ("id", block_message_to_process.block_id)); + auto block_num = block_message_to_process.block.block_num(); + wlog("Failed to push block ${num} (id:${id}), client rejected block sent by peer: ${e}", + ("num", block_num) + ("id", block_message_to_process.block_id) + ("e",e)); - disconnect_exception = e; + if( e.code() == block_timestamp_in_future_exception::code_enum::code_value ) + { + disconnect_exception = block_timestamp_in_future_exception( FC_LOG_MESSAGE( warn, "", + ("block_header", static_cast(block_message_to_process.block)) + ("block_num", block_num) + ("block_id", block_message_to_process.block_id) ) ); + } + else + disconnect_exception = e; disconnect_reason = "You offered me a block that I have deemed to be invalid"; peers_to_disconnect.insert( originating_peer->shared_from_this() ); From 35c1b8726f98c91c6b39194688877f5eba176c52 Mon Sep 17 00:00:00 2001 From: abitmore Date: Tue, 30 Jul 2019 17:17:51 -0400 Subject: [PATCH 041/111] Wrap long lines --- libraries/chain/exceptions.cpp | 44 ++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/libraries/chain/exceptions.cpp b/libraries/chain/exceptions.cpp index 5c7feffcde..37f72607dd 100644 --- a/libraries/chain/exceptions.cpp +++ b/libraries/chain/exceptions.cpp @@ -29,7 +29,7 @@ namespace graphene { namespace chain { // Internal exceptions - FC_IMPLEMENT_DERIVED_EXCEPTION( internal_exception, graphene::chain::chain_exception, 3990000, "internal exception" ) + FC_IMPLEMENT_DERIVED_EXCEPTION( internal_exception, chain_exception, 3990000, "internal exception" ) GRAPHENE_IMPLEMENT_INTERNAL_EXCEPTION( verify_auth_max_auth_exceeded, 1, "Exceeds max authority fan-out" ) GRAPHENE_IMPLEMENT_INTERNAL_EXCEPTION( verify_auth_account_not_found, 2, "Auth account not found" ) @@ -39,22 +39,31 @@ namespace graphene { namespace chain { FC_IMPLEMENT_EXCEPTION( chain_exception, 3000000, "blockchain exception" ) - FC_IMPLEMENT_DERIVED_EXCEPTION( database_query_exception, chain_exception, 3010000, "database query exception" ) - FC_IMPLEMENT_DERIVED_EXCEPTION( block_validate_exception, chain_exception, 3020000, "block validation exception" ) - FC_IMPLEMENT_DERIVED_EXCEPTION( transaction_process_exception,chain_exception, 3030000, "transaction processing exception" ) - FC_IMPLEMENT_DERIVED_EXCEPTION( operation_validate_exception, chain_exception, 3040000, "operation validation exception" ) - FC_IMPLEMENT_DERIVED_EXCEPTION( operation_evaluate_exception, chain_exception, 3050000, "operation evaluation exception" ) - FC_IMPLEMENT_DERIVED_EXCEPTION( utility_exception, chain_exception, 3060000, "utility method exception" ) - FC_IMPLEMENT_DERIVED_EXCEPTION( undo_database_exception, chain_exception, 3070000, "undo database exception" ) + FC_IMPLEMENT_DERIVED_EXCEPTION( database_query_exception, chain_exception, 3010000, + "database query exception" ) + FC_IMPLEMENT_DERIVED_EXCEPTION( block_validate_exception, chain_exception, 3020000, + "block validation exception" ) + FC_IMPLEMENT_DERIVED_EXCEPTION( transaction_process_exception,chain_exception, 3030000, + "transaction processing exception" ) + FC_IMPLEMENT_DERIVED_EXCEPTION( operation_validate_exception, chain_exception, 3040000, + "operation validation exception" ) + FC_IMPLEMENT_DERIVED_EXCEPTION( operation_evaluate_exception, chain_exception, 3050000, + "operation evaluation exception" ) + FC_IMPLEMENT_DERIVED_EXCEPTION( utility_exception, chain_exception, 3060000, + "utility method exception" ) + FC_IMPLEMENT_DERIVED_EXCEPTION( undo_database_exception, chain_exception, 3070000, + "undo database exception" ) FC_IMPLEMENT_DERIVED_EXCEPTION( unlinkable_block_exception, chain_exception, 3080000, "unlinkable block" ) FC_IMPLEMENT_DERIVED_EXCEPTION( black_swan_exception, chain_exception, 3090000, "black swan" ) FC_IMPLEMENT_DERIVED_EXCEPTION( plugin_exception, chain_exception, 3100000, "plugin exception" ) FC_IMPLEMENT_DERIVED_EXCEPTION( insufficient_feeds, chain_exception, 37006, "insufficient feeds" ) - FC_IMPLEMENT_DERIVED_EXCEPTION( duplicate_transaction, transaction_process_exception, 3030001, "duplicate transaction" ) + FC_IMPLEMENT_DERIVED_EXCEPTION( duplicate_transaction, transaction_process_exception, 3030001, + "duplicate transaction" ) - FC_IMPLEMENT_DERIVED_EXCEPTION( pop_empty_chain, undo_database_exception, 3070001, "there are no blocks to pop" ) + FC_IMPLEMENT_DERIVED_EXCEPTION( pop_empty_chain, undo_database_exception, 3070001, + "there are no blocks to pop" ) GRAPHENE_IMPLEMENT_OP_BASE_EXCEPTIONS( transfer ); GRAPHENE_IMPLEMENT_OP_EVALUATE_EXCEPTION( from_account_not_whitelisted, transfer, 1, "owner mismatch" ) @@ -80,13 +89,16 @@ namespace graphene { namespace chain { GRAPHENE_IMPLEMENT_OP_EVALUATE_EXCEPTION( owner_mismatch, limit_order_cancel, 2, "Order owned by someone else" ) GRAPHENE_IMPLEMENT_OP_BASE_EXCEPTIONS( call_order_update ); - GRAPHENE_IMPLEMENT_OP_EVALUATE_EXCEPTION( unfilled_margin_call, call_order_update, 1, "Updating call order would trigger a margin call that cannot be fully filled" ) + GRAPHENE_IMPLEMENT_OP_EVALUATE_EXCEPTION( unfilled_margin_call, call_order_update, 1, + "Updating call order would trigger a margin call that cannot be fully filled" ) GRAPHENE_IMPLEMENT_OP_BASE_EXCEPTIONS( account_create ); GRAPHENE_IMPLEMENT_OP_EVALUATE_EXCEPTION( max_auth_exceeded, account_create, 1, "Exceeds max authority fan-out" ) GRAPHENE_IMPLEMENT_OP_EVALUATE_EXCEPTION( auth_account_not_found, account_create, 2, "Auth account not found" ) - GRAPHENE_IMPLEMENT_OP_EVALUATE_EXCEPTION( buyback_incorrect_issuer, account_create, 3, "Incorrect issuer specified for account" ) - GRAPHENE_IMPLEMENT_OP_EVALUATE_EXCEPTION( buyback_already_exists, account_create, 4, "Cannot create buyback for asset which already has buyback" ) + GRAPHENE_IMPLEMENT_OP_EVALUATE_EXCEPTION( buyback_incorrect_issuer, account_create, 3, + "Incorrect issuer specified for account" ) + GRAPHENE_IMPLEMENT_OP_EVALUATE_EXCEPTION( buyback_already_exists, account_create, 4, + "Cannot create buyback for asset which already has buyback" ) GRAPHENE_IMPLEMENT_OP_EVALUATE_EXCEPTION( buyback_too_many_markets, account_create, 5, "Too many buyback markets" ) GRAPHENE_IMPLEMENT_OP_BASE_EXCEPTIONS( account_update ); @@ -114,7 +126,8 @@ namespace graphene { namespace chain { GRAPHENE_IMPLEMENT_OP_BASE_EXCEPTIONS( proposal_create ); GRAPHENE_IMPLEMENT_OP_EVALUATE_EXCEPTION( review_period_required, proposal_create, 1, "review_period required" ) - GRAPHENE_IMPLEMENT_OP_EVALUATE_EXCEPTION( review_period_insufficient, proposal_create, 2, "review_period insufficient" ) + GRAPHENE_IMPLEMENT_OP_EVALUATE_EXCEPTION( review_period_insufficient, proposal_create, 2, + "review_period insufficient" ) //GRAPHENE_IMPLEMENT_OP_BASE_EXCEPTIONS( proposal_update ); //GRAPHENE_IMPLEMENT_OP_BASE_EXCEPTIONS( proposal_delete ); @@ -139,7 +152,8 @@ namespace graphene { namespace chain { GRAPHENE_IMPLEMENT_OP_EVALUATE_EXCEPTION( not_permitted, override_transfer, 1, "not permitted" ) GRAPHENE_IMPLEMENT_OP_BASE_EXCEPTIONS( blind_transfer ); - GRAPHENE_IMPLEMENT_OP_EVALUATE_EXCEPTION( unknown_commitment, blind_transfer, 1, "Attempting to claim an unknown prior commitment" ); + GRAPHENE_IMPLEMENT_OP_EVALUATE_EXCEPTION( unknown_commitment, blind_transfer, 1, + "Attempting to claim an unknown prior commitment" ); //GRAPHENE_IMPLEMENT_OP_BASE_EXCEPTIONS( transfer_from_blind_operation ) //GRAPHENE_IMPLEMENT_OP_BASE_EXCEPTIONS( asset_claim_fees_operation ) From d04c62a66bc78fac5e4a2b92019fc9b4675e778c Mon Sep 17 00:00:00 2001 From: abitmore Date: Tue, 30 Jul 2019 17:22:07 -0400 Subject: [PATCH 042/111] Remove unused macro parameter --- .../include/graphene/chain/exceptions.hpp | 58 +++++++++---------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/libraries/chain/include/graphene/chain/exceptions.hpp b/libraries/chain/include/graphene/chain/exceptions.hpp index ed61381a59..e2100bdfe8 100644 --- a/libraries/chain/include/graphene/chain/exceptions.hpp +++ b/libraries/chain/include/graphene/chain/exceptions.hpp @@ -55,7 +55,7 @@ #op_name "_operation evaluation exception" \ ) -#define GRAPHENE_DECLARE_OP_VALIDATE_EXCEPTION( exc_name, op_name, seqnum, msg ) \ +#define GRAPHENE_DECLARE_OP_VALIDATE_EXCEPTION( exc_name, op_name, seqnum ) \ FC_DECLARE_DERIVED_EXCEPTION( \ op_name ## _ ## exc_name, \ graphene::chain::op_name ## _validate_exception, \ @@ -72,7 +72,7 @@ msg \ ) -#define GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( exc_name, op_name, seqnum, msg ) \ +#define GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( exc_name, op_name, seqnum ) \ FC_DECLARE_DERIVED_EXCEPTION( \ op_name ## _ ## exc_name, \ graphene::chain::op_name ## _evaluate_exception, \ @@ -126,35 +126,35 @@ namespace graphene { namespace chain { FC_DECLARE_DERIVED_EXCEPTION( pop_empty_chain, undo_database_exception, 3070001 ) GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( transfer ); - GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( from_account_not_whitelisted, transfer, 1, "owner mismatch" ) - GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( to_account_not_whitelisted, transfer, 2, "owner mismatch" ) - GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( restricted_transfer_asset, transfer, 3, "restricted transfer asset" ) + GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( from_account_not_whitelisted, transfer, 1 ) + GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( to_account_not_whitelisted, transfer, 2 ) + GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( restricted_transfer_asset, transfer, 3 ) GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( limit_order_create ); - GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( kill_unfilled, limit_order_create, 1, ) - GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( market_not_whitelisted, limit_order_create, 2, ) - GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( market_blacklisted, limit_order_create, 3, ) - GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( selling_asset_unauthorized, limit_order_create, 4, ) - GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( receiving_asset_unauthorized, limit_order_create, 5, ) - GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( insufficient_balance, limit_order_create, 6, ) + GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( kill_unfilled, limit_order_create, 1 ) + GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( market_not_whitelisted, limit_order_create, 2 ) + GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( market_blacklisted, limit_order_create, 3 ) + GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( selling_asset_unauthorized, limit_order_create, 4 ) + GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( receiving_asset_unauthorized, limit_order_create, 5 ) + GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( insufficient_balance, limit_order_create, 6 ) GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( limit_order_cancel ); - GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( nonexist_order, limit_order_cancel, 1, ) - GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( owner_mismatch, limit_order_cancel, 2, ) + GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( nonexist_order, limit_order_cancel, 1 ) + GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( owner_mismatch, limit_order_cancel, 2 ) GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( call_order_update ); - GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( unfilled_margin_call, call_order_update, 1, "Updating call order would trigger a margin call that cannot be fully filled" ) + GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( unfilled_margin_call, call_order_update, 1 ) GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( account_create ); - GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( max_auth_exceeded, account_create, 1, "Exceeds max authority fan-out" ) - GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( auth_account_not_found, account_create, 2, "Auth account not found" ) - GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( buyback_incorrect_issuer, account_create, 3, "Incorrect issuer specified for account" ) - GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( buyback_already_exists, account_create, 4, "Cannot create buyback for asset which already has buyback" ) - GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( buyback_too_many_markets, account_create, 5, "Too many buyback markets" ) + GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( max_auth_exceeded, account_create, 1 ) + GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( auth_account_not_found, account_create, 2 ) + GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( buyback_incorrect_issuer, account_create, 3 ) + GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( buyback_already_exists, account_create, 4 ) + GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( buyback_too_many_markets, account_create, 5 ) GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( account_update ); - GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( max_auth_exceeded, account_update, 1, "Exceeds max authority fan-out" ) - GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( auth_account_not_found, account_update, 2, "Auth account not found" ) + GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( max_auth_exceeded, account_update, 1 ) + GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( auth_account_not_found, account_update, 2 ) //GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( account_whitelist ); //GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( account_upgrade ); @@ -166,7 +166,7 @@ namespace graphene { namespace chain { //GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( asset_issue ); GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( asset_reserve ); - GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( invalid_on_mia, asset_reserve, 1, "invalid on mia" ) + GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( invalid_on_mia, asset_reserve, 1 ) //GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( asset_fund_fee_pool ); //GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( asset_settle ); @@ -176,8 +176,8 @@ namespace graphene { namespace chain { //GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( witness_create ); GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( proposal_create ); - GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( review_period_required, proposal_create, 1, "review_period required" ) - GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( review_period_insufficient, proposal_create, 2, "review_period insufficient" ) + GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( review_period_required, proposal_create, 1 ) + GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( review_period_insufficient, proposal_create, 2 ) //GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( proposal_update ); //GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( proposal_delete ); @@ -194,15 +194,15 @@ namespace graphene { namespace chain { //GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( assert ); GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( balance_claim ); - GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( claimed_too_often, balance_claim, 1, "balance claimed too often" ) - GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( invalid_claim_amount, balance_claim, 2, "invalid claim amount" ) - GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( owner_mismatch, balance_claim, 3, "owner mismatch" ) + GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( claimed_too_often, balance_claim, 1 ) + GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( invalid_claim_amount, balance_claim, 2 ) + GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( owner_mismatch, balance_claim, 3 ) GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( override_transfer ); - GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( not_permitted, override_transfer, 1, "not permitted" ) + GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( not_permitted, override_transfer, 1 ) GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( blind_transfer ); - GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( unknown_commitment, blind_transfer, 1, "Attempting to claim an unknown prior commitment" ); + GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( unknown_commitment, blind_transfer, 1 ) //GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( transfer_from_blind_operation ) //GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( asset_claim_fees_operation ) From 26e9f16b3f5f88cd186ec3c853aa7278d73c7419 Mon Sep 17 00:00:00 2001 From: Alfredo Date: Wed, 31 Jul 2019 10:16:36 -0300 Subject: [PATCH 043/111] simplify conditional --- libraries/app/application.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libraries/app/application.cpp b/libraries/app/application.cpp index 909bfd87e1..47e4cbc350 100644 --- a/libraries/app/application.cpp +++ b/libraries/app/application.cpp @@ -1075,9 +1075,7 @@ std::shared_ptr application::get_plugin(const string& name) con bool application::is_plugin_enabled(const string& name) const { - if(my->_active_plugins.find(name) == my->_active_plugins.end()) - return false; - return true; + return !(my->_active_plugins.find(name) == my->_active_plugins.end()); } net::node_ptr application::p2p_node() From 4fac171544b4a8f7859fc0ed56c06eddb3e6ff92 Mon Sep 17 00:00:00 2001 From: Alfredo Date: Wed, 31 Jul 2019 10:42:18 -0300 Subject: [PATCH 044/111] capture only what is necessary in lambda --- libraries/plugins/elasticsearch/elasticsearch_plugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp b/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp index c68454a153..1069b34269 100644 --- a/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp +++ b/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp @@ -482,7 +482,7 @@ void elasticsearch_plugin::plugin_initialize(const boost::program_options::varia if (my->_elasticsearch_mode == "all") my->_elasticsearch_operation_string = true; - database().applied_block.connect([&](const signed_block &b) { + database().applied_block.connect([this](const signed_block &b) { if (!my->update_account_histories(b)) FC_THROW_EXCEPTION(graphene::chain::plugin_exception, "Error populating ES database, we are going to keep trying."); }); From 29bf9758f18236ff42d9dfda4df546c96c14e9fd Mon Sep 17 00:00:00 2001 From: Alfredo Date: Wed, 31 Jul 2019 10:54:34 -0300 Subject: [PATCH 045/111] wrap command line option long lines --- .../elasticsearch/elasticsearch_plugin.cpp | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp b/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp index 1069b34269..98fc06d997 100644 --- a/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp +++ b/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp @@ -428,16 +428,26 @@ void elasticsearch_plugin::plugin_set_program_options( ) { cli.add_options() - ("elasticsearch-node-url", boost::program_options::value(), "Elastic Search database node url(http://localhost:9200/)") - ("elasticsearch-bulk-replay", boost::program_options::value(), "Number of bulk documents to index on replay(10000)") - ("elasticsearch-bulk-sync", boost::program_options::value(), "Number of bulk documents to index on a syncronied chain(100)") - ("elasticsearch-visitor", boost::program_options::value(), "Use visitor to index additional data(slows down the replay(false))") - ("elasticsearch-basic-auth", boost::program_options::value(), "Pass basic auth to elasticsearch database('')") - ("elasticsearch-index-prefix", boost::program_options::value(), "Add a prefix to the index(bitshares-)") - ("elasticsearch-operation-object", boost::program_options::value(), "Save operation as object(false)") - ("elasticsearch-start-es-after-block", boost::program_options::value(), "Start doing ES job after block(0)") - ("elasticsearch-operation-string", boost::program_options::value(), "Save operation as string. Needed to serve history api calls(true)") - ("elasticsearch-mode", boost::program_options::value(), "Mode of operation: only_save, only_query, all(only_save)") + ("elasticsearch-node-url", boost::program_options::value(), + "Elastic Search database node url(http://localhost:9200/)") + ("elasticsearch-bulk-replay", boost::program_options::value(), + "Number of bulk documents to index on replay(10000)") + ("elasticsearch-bulk-sync", boost::program_options::value(), + "Number of bulk documents to index on a syncronied chain(100)") + ("elasticsearch-visitor", boost::program_options::value(), + "Use visitor to index additional data(slows down the replay(false))") + ("elasticsearch-basic-auth", boost::program_options::value(), + "Pass basic auth to elasticsearch database('')") + ("elasticsearch-index-prefix", boost::program_options::value(), + "Add a prefix to the index(bitshares-)") + ("elasticsearch-operation-object", boost::program_options::value(), + "Save operation as object(false)") + ("elasticsearch-start-es-after-block", boost::program_options::value(), + "Start doing ES job after block(0)") + ("elasticsearch-operation-string", boost::program_options::value(), + "Save operation as string. Needed to serve history api calls(true)") + ("elasticsearch-mode", boost::program_options::value(), + "Mode of operation: only_save, only_query, all(only_save)") ; cfg.add(cli); } From 1e8211995da89d7c03c130500148763fdbb8407d Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Wed, 31 Jul 2019 16:00:39 -0300 Subject: [PATCH 046/111] libs doc separate protocol from chain --- libraries/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/README.md b/libraries/README.md index 256d15029b..06f7fc9b8a 100644 --- a/libraries/README.md +++ b/libraries/README.md @@ -10,11 +10,12 @@ Code in libraries is the most important part of **bitshares-core** project and i Folder | Name | Description | Status ---|---|---|--- [app](app) | Application | Bundles component libraries (chain, network, plugins) into a useful application. Also provides API access. | Active -[chain](chain) | Blockchain | Defines all objects, operations and types. This include the consensus protocol, defines the whole blockchain behaviour. | Active +[chain](chain) | Blockchain | Blockchain implementation and business logic. Database structure in the form of objects and updates to the blockchain in the form of evaluators are implemented here. | Active [db](db) | Database | Defines the internal database graphene uses. | Active [egenesis](egenesis) | Genesis | Hardcodes the `genesis.json` file into the `witness_node` executable.| Active [fc](fc) | Fast-compiling C++ library | https://github.com/bitshares/bitshares-fc | Active [net](net) | Network | The graphene p2p layer. | Active [plugins](plugins) | Plugins | Collection of singleton designed modules used for extending the bitshares-core. | Active +[protocol](protocol) | Protocol | Fundamental structure of the data that will be transmitted on the wire. Operations are defined and basic data integrity checks are done for each. | Active [utilities](utilities) | Utilities | Common utility calls used in applications or other libraries. | Active [wallet](wallet) | Wallet | Wallet definition for the `cli_wallet` software. | Active From de76301d536539675b90357720a758d849af3768 Mon Sep 17 00:00:00 2001 From: Alfredo Date: Wed, 31 Jul 2019 16:02:58 -0300 Subject: [PATCH 047/111] make mode an enum for comparison performance --- .../elasticsearch/elasticsearch_plugin.cpp | 15 +++++++++------ .../elasticsearch/elasticsearch_plugin.hpp | 3 +++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp b/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp index 98fc06d997..cbdec6fa93 100644 --- a/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp +++ b/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp @@ -59,7 +59,7 @@ class elasticsearch_plugin_impl bool _elasticsearch_operation_object = false; uint32_t _elasticsearch_start_es_after_block = 0; bool _elasticsearch_operation_string = true; - std::string _elasticsearch_mode = "only_save"; + mode _elasticsearch_mode = mode::only_save; CURL *curl; // curl handler vector bulk_lines; // vector of op lines vector prepare; @@ -446,8 +446,8 @@ void elasticsearch_plugin::plugin_set_program_options( "Start doing ES job after block(0)") ("elasticsearch-operation-string", boost::program_options::value(), "Save operation as string. Needed to serve history api calls(true)") - ("elasticsearch-mode", boost::program_options::value(), - "Mode of operation: only_save, only_query, all(only_save)") + ("elasticsearch-mode", boost::program_options::value(), + "Mode of operation: only_save(0), only_query(1), all(2) - Default: 0") ; cfg.add(cli); } @@ -485,11 +485,14 @@ void elasticsearch_plugin::plugin_initialize(const boost::program_options::varia my->_elasticsearch_operation_string = options["elasticsearch-operation-string"].as(); } if (options.count("elasticsearch-mode")) { - my->_elasticsearch_mode = options["elasticsearch-mode"].as(); + const auto option_number = options["elasticsearch-mode"].as(); + if(option_number > mode::all) + FC_THROW_EXCEPTION(fc::exception, "Elasticsearch mode not valid"); + my->_elasticsearch_mode = static_cast(options["elasticsearch-mode"].as()); } - if(my->_elasticsearch_mode != "only_query") { - if (my->_elasticsearch_mode == "all") + if(my->_elasticsearch_mode != mode::only_query) { + if (my->_elasticsearch_mode == mode::all) my->_elasticsearch_operation_string = true; database().applied_block.connect([this](const signed_block &b) { diff --git a/libraries/plugins/elasticsearch/include/graphene/elasticsearch/elasticsearch_plugin.hpp b/libraries/plugins/elasticsearch/include/graphene/elasticsearch/elasticsearch_plugin.hpp index 7cff0b73b8..eefbdf05f1 100644 --- a/libraries/plugins/elasticsearch/include/graphene/elasticsearch/elasticsearch_plugin.hpp +++ b/libraries/plugins/elasticsearch/include/graphene/elasticsearch/elasticsearch_plugin.hpp @@ -76,6 +76,8 @@ class elasticsearch_plugin : public graphene::app::plugin graphene::utilities::ES prepareHistoryQuery(string query); }; +enum mode { only_save = 0 , only_query = 1, all = 2 }; + struct operation_visitor { typedef void result_type; @@ -302,6 +304,7 @@ struct adaptor_struct { } } //graphene::elasticsearch +FC_REFLECT_ENUM( graphene::elasticsearch::mode, (only_save)(only_query)(all) ) FC_REFLECT( graphene::elasticsearch::operation_history_struct, (trx_in_block)(op_in_trx)(operation_result)(virtual_op)(op)(op_object) ) FC_REFLECT( graphene::elasticsearch::block_struct, (block_num)(block_time)(trx_id) ) FC_REFLECT( graphene::elasticsearch::fee_struct, (asset)(asset_name)(amount)(amount_units) ) From 5838a38fbc93b2673e7c96640abe15a5caa4533e Mon Sep 17 00:00:00 2001 From: Alfredo Date: Wed, 31 Jul 2019 16:59:50 -0300 Subject: [PATCH 048/111] throw when mode::all if elasticsearch-operation-string is false --- .../plugins/elasticsearch/elasticsearch_plugin.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp b/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp index cbdec6fa93..3463b91ae4 100644 --- a/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp +++ b/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp @@ -487,17 +487,19 @@ void elasticsearch_plugin::plugin_initialize(const boost::program_options::varia if (options.count("elasticsearch-mode")) { const auto option_number = options["elasticsearch-mode"].as(); if(option_number > mode::all) - FC_THROW_EXCEPTION(fc::exception, "Elasticsearch mode not valid"); + FC_THROW_EXCEPTION(graphene::chain::plugin_exception, "Elasticsearch mode not valid"); my->_elasticsearch_mode = static_cast(options["elasticsearch-mode"].as()); } if(my->_elasticsearch_mode != mode::only_query) { - if (my->_elasticsearch_mode == mode::all) - my->_elasticsearch_operation_string = true; + if (my->_elasticsearch_mode == mode::all && !my->_elasticsearch_operation_string) + FC_THROW_EXCEPTION(graphene::chain::plugin_exception, + "If elasticsearch-mode is set to all then elasticsearch-operation-string need to be true"); database().applied_block.connect([this](const signed_block &b) { if (!my->update_account_histories(b)) - FC_THROW_EXCEPTION(graphene::chain::plugin_exception, "Error populating ES database, we are going to keep trying."); + FC_THROW_EXCEPTION(graphene::chain::plugin_exception, + "Error populating ES database, we are going to keep trying."); }); } } From 1f6ac147d5b298fecf17e7bc281676160192ea70 Mon Sep 17 00:00:00 2001 From: Alfredo Date: Wed, 31 Jul 2019 17:33:37 -0300 Subject: [PATCH 049/111] change ES query --- .../elasticsearch/elasticsearch_plugin.cpp | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp b/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp index 3463b91ae4..f48d2e6f82 100644 --- a/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp +++ b/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp @@ -523,22 +523,9 @@ operation_history_object elasticsearch_plugin::get_operation_by_id(operation_his const string query = R"( { "query": { - "bool": { - "must": [ - { - "query_string": { - "query": "account_history.operation_id: )" + operation_id_string + R"(" - } - }, - { - "range": { - "block_data.block_time": { - "gte": "now-20y", - "lte": "now" - } - } - } - ] + "match": + { + "account_history.operation_id": )" + operation_id_string + R"(" } } } From 63f7affc81b0ca8cb274c97f2124d2d0d8d7ec05 Mon Sep 17 00:00:00 2001 From: Alfredo Date: Wed, 31 Jul 2019 18:25:42 -0300 Subject: [PATCH 050/111] remove range from second ES query --- libraries/plugins/elasticsearch/elasticsearch_plugin.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp b/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp index f48d2e6f82..fa82b9ba6f 100644 --- a/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp +++ b/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp @@ -566,14 +566,6 @@ vector elasticsearch_plugin::get_account_history( "query_string": { "query": "account_history.account: )" + account_id_string + range + R"(" } - }, - { - "range": { - "block_data.block_time": { - "gte": "now-20y", - "lte": "now" - } - } } ] } From a7fc6b0e9a4bfb379d2a04bbf0e6c4ed026325e6 Mon Sep 17 00:00:00 2001 From: Alfredo Date: Wed, 31 Jul 2019 19:43:01 -0300 Subject: [PATCH 051/111] add get_running_mode() to plugin and use it in api, fix capture --- libraries/app/api.cpp | 9 ++++++--- libraries/plugins/elasticsearch/elasticsearch_plugin.cpp | 6 ++++++ .../graphene/elasticsearch/elasticsearch_plugin.hpp | 4 +++- tests/common/database_fixture.cpp | 1 + 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/libraries/app/api.cpp b/libraries/app/api.cpp index 7b3d36a02f..68400016dd 100644 --- a/libraries/app/api.cpp +++ b/libraries/app/api.cpp @@ -330,9 +330,12 @@ namespace graphene { namespace app { if(_app.is_plugin_enabled("elasticsearch")) { auto es = _app.get_plugin("elasticsearch"); - auto _thread = std::make_shared("elasticsearch"); - return _thread->async([&](){ return es->get_account_history(account, stop, limit, start); }, - "thread invoke for method " BOOST_PP_STRINGIZE(method_name)).wait(); + if(es.get()->get_running_mode() != elasticsearch::mode::only_save) { + auto _thread = std::make_shared("elasticsearch"); + return _thread->async([&es, &account, &stop, &limit, &start]() { + return es->get_account_history(account, stop, limit, start); + }, "thread invoke for method " BOOST_PP_STRINGIZE(method_name)).wait(); + } } const auto& hist_idx = db.get_index_type(); diff --git a/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp b/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp index fa82b9ba6f..5729035ee6 100644 --- a/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp +++ b/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp @@ -630,4 +630,10 @@ graphene::utilities::ES elasticsearch_plugin::prepareHistoryQuery(string query) return es; } +mode elasticsearch_plugin::get_running_mode() +{ + return my->_elasticsearch_mode; +} + + } } diff --git a/libraries/plugins/elasticsearch/include/graphene/elasticsearch/elasticsearch_plugin.hpp b/libraries/plugins/elasticsearch/include/graphene/elasticsearch/elasticsearch_plugin.hpp index eefbdf05f1..7b08e1d73f 100644 --- a/libraries/plugins/elasticsearch/include/graphene/elasticsearch/elasticsearch_plugin.hpp +++ b/libraries/plugins/elasticsearch/include/graphene/elasticsearch/elasticsearch_plugin.hpp @@ -50,6 +50,8 @@ namespace detail class elasticsearch_plugin_impl; } +enum mode { only_save = 0 , only_query = 1, all = 2 }; + class elasticsearch_plugin : public graphene::app::plugin { public: @@ -67,6 +69,7 @@ class elasticsearch_plugin : public graphene::app::plugin operation_history_object get_operation_by_id(operation_history_id_type id); vector get_account_history(const account_id_type account_id, operation_history_id_type stop, unsigned limit, operation_history_id_type start); + mode get_running_mode(); friend class detail::elasticsearch_plugin_impl; std::unique_ptr my; @@ -76,7 +79,6 @@ class elasticsearch_plugin : public graphene::app::plugin graphene::utilities::ES prepareHistoryQuery(string query); }; -enum mode { only_save = 0 , only_query = 1, all = 2 }; struct operation_visitor { diff --git a/tests/common/database_fixture.cpp b/tests/common/database_fixture.cpp index 9bb5691540..cd563828df 100644 --- a/tests/common/database_fixture.cpp +++ b/tests/common/database_fixture.cpp @@ -198,6 +198,7 @@ database_fixture::database_fixture(const fc::time_point_sec &initial_timestamp) options.insert(std::make_pair("elasticsearch-visitor", boost::program_options::variable_value(false, false))); options.insert(std::make_pair("elasticsearch-operation-object", boost::program_options::variable_value(true, false))); options.insert(std::make_pair("elasticsearch-operation-string", boost::program_options::variable_value(true, false))); + options.insert(std::make_pair("elasticsearch-mode", boost::program_options::variable_value(uint16_t(2), false))); esplugin->plugin_initialize(options); esplugin->plugin_startup(); From f257cbaffb5b9e37814983f649b0eb5bcd954413 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Wed, 31 Jul 2019 18:03:28 +0200 Subject: [PATCH 052/111] BSIP-compatible initial version, non-working --- .../wallet/include/graphene/wallet/wallet.hpp | 24 ++++++++ libraries/wallet/wallet.cpp | 60 +++++++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index ec8d961994..6221a71f47 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -267,6 +267,11 @@ struct vesting_balance_object_with_info : public vesting_balance_object fc::time_point_sec allowed_withdraw_time; }; +struct signed_message { + fc::variants payload; + fc::ecc::compact_signature signature; +}; + namespace detail { class wallet_api_impl; } @@ -1055,6 +1060,21 @@ class wallet_api string read_memo(const memo_data& memo); + /** Sign a message using an account's memo key. + * + * @param signer the name or id of signing account + * @param message text to sign + * @return the signed message in the format used in https://github.com/xeroc/python-graphenelib/blob/d9634d74273ebacc92555499eca7c444217ecba0/graphenecommon/message.py#L64 + */ + signed_message sign_message(string signer, string message); + + /** Verify a message signed with sign_message + * + * @param message JSON-encoded signed message in the format used in https://github.com/xeroc/python-graphenelib/blob/d9634d74273ebacc92555499eca7c444217ecba0/graphenecommon/message.py#L64 + * @return true if signature matches + */ + bool verify_message(signed_message message); + /** These methods are used for stealth transfers */ ///@{ /** @@ -2034,6 +2054,8 @@ FC_REFLECT(graphene::wallet::operation_detail_ex, FC_REFLECT( graphene::wallet::account_history_operation_detail, (total_count)(result_count)(details)) +FC_REFLECT( graphene::wallet::signed_message, (payload)(signature) ) + FC_API( graphene::wallet::wallet_api, (help) (gethelp) @@ -2151,6 +2173,8 @@ FC_API( graphene::wallet::wallet_api, (network_get_connected_peers) (sign_memo) (read_memo) + (sign_message) + (verify_message) (set_key_label) (get_key_label) (get_public_key) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index 8441bf0492..eb303805f0 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -2244,6 +2244,55 @@ class wallet_api_impl return clear_text; } + signed_message sign_message(string signer, string message) + { + FC_ASSERT( !self.is_locked() ); + + const account_object from_account = get_account(signer); + + signed_message result; + result.payload.emplace_back( std::string("from") ); + result.payload.emplace_back( from_account.name ); + result.payload.emplace_back( std::string("key") ); + result.payload.emplace_back( std::string( from_account.options.memo_key ) ); + result.payload.emplace_back( std::string("time") ); + result.payload.emplace_back( time(nullptr) ); + result.payload.emplace_back( std::string("text") ); + result.payload.emplace_back( std::move(message) ); + + digest_type::encoder enc; + fc::raw::pack( enc, _chain_id ); + fc::raw::pack( enc, result.payload ); + result.signature = get_private_key( from_account.options.memo_key ).sign_compact( enc.result() ); + + return result; + } + + bool verify_message( signed_message message ) + { + FC_ASSERT( message.payload.size() == 8 ); + FC_ASSERT( message.payload[0].is_string() && message.payload[0].as_string() == "from" ); + FC_ASSERT( message.payload[1].is_string() ); + FC_ASSERT( message.payload[2].is_string() && message.payload[2].as_string() == "key" ); + FC_ASSERT( message.payload[3].is_string() ); + FC_ASSERT( message.payload[4].is_string() && message.payload[4].as_string() == "time" ); + FC_ASSERT( message.payload[5].is_numeric() ); + FC_ASSERT( message.payload[6].is_string() && message.payload[6].as_string() == "text" ); + FC_ASSERT( message.payload[7].is_string() ); + + const account_object from_account = get_account( message.payload[1].as_string() ); + const public_key_type key( message.payload[3].as_string() ); + + digest_type::encoder enc; + fc::raw::pack( enc, _chain_id ); + fc::raw::pack( enc, message.payload ); + const public_key signer( message.signature, enc.result() ); + FC_ASSERT( signer == key.key_data, "Message wasn't signed by contained key!" ); + FC_ASSERT( signer == from_account.options.memo_key.key_data, + "Message was signed by contained key, but it doesn't belong to the contained account!" ); + return true; + } + signed_transaction sell_asset(string seller_account, string amount_to_sell, string symbol_to_sell, @@ -4480,6 +4529,17 @@ string wallet_api::read_memo(const memo_data& memo) return my->read_memo(memo); } +signed_message wallet_api::sign_message(string signer, string message) +{ + FC_ASSERT(!is_locked()); + return my->sign_message(signer, message); +} + +bool wallet_api::verify_message(signed_message message) +{ + return my->verify_message(message); +} + string wallet_api::get_key_label( public_key_type key )const { auto key_itr = my->_wallet.labeled_keys.get().find(key); From d218bcaadb694975ff1455df8d217470e9a9b7f1 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Thu, 1 Aug 2019 17:42:20 +0200 Subject: [PATCH 053/111] Rewrite/refactor sign_message for compatibility with python-bitshares --- .../wallet/include/graphene/wallet/wallet.hpp | 29 +++++--- libraries/wallet/wallet.cpp | 68 +++++++++++++------ 2 files changed, 69 insertions(+), 28 deletions(-) diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index 6221a71f47..761434d4b8 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -267,9 +267,20 @@ struct vesting_balance_object_with_info : public vesting_balance_object fc::time_point_sec allowed_withdraw_time; }; -struct signed_message { - fc::variants payload; - fc::ecc::compact_signature signature; +struct signed_message_meta { + string account; + public_key_type memo_key; + uint32_t block; + int64_t time; +}; + +class signed_message { +public: + string message; + signed_message_meta meta; + fc::optional signature; + + fc::sha256 digest()const; }; namespace detail { @@ -1060,20 +1071,21 @@ class wallet_api string read_memo(const memo_data& memo); - /** Sign a message using an account's memo key. + /** Sign a message using an account's memo key. The signature is generated as in + * in https://github.com/xeroc/python-graphenelib/blob/d9634d74273ebacc92555499eca7c444217ecba0/graphenecommon/message.py#L64 . * * @param signer the name or id of signing account * @param message text to sign - * @return the signed message in the format used in https://github.com/xeroc/python-graphenelib/blob/d9634d74273ebacc92555499eca7c444217ecba0/graphenecommon/message.py#L64 + * @return the signed message in an abstract format */ signed_message sign_message(string signer, string message); /** Verify a message signed with sign_message * - * @param message JSON-encoded signed message in the format used in https://github.com/xeroc/python-graphenelib/blob/d9634d74273ebacc92555499eca7c444217ecba0/graphenecommon/message.py#L64 + * @param message either a JSON-encoded signed_message structure, or a signed message in encapsulated format * @return true if signature matches */ - bool verify_message(signed_message message); + bool verify_message(string message); /** These methods are used for stealth transfers */ ///@{ @@ -2054,7 +2066,8 @@ FC_REFLECT(graphene::wallet::operation_detail_ex, FC_REFLECT( graphene::wallet::account_history_operation_detail, (total_count)(result_count)(details)) -FC_REFLECT( graphene::wallet::signed_message, (payload)(signature) ) +FC_REFLECT( graphene::wallet::signed_message_meta, (account)(memo_key)(block)(time) ) +FC_REFLECT( graphene::wallet::signed_message, (message)(meta)(signature) ) FC_API( graphene::wallet::wallet_api, (help) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index eb303805f0..c51ce8acda 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -107,6 +107,11 @@ using std::endl; namespace detail { +static const string ENC_HEADER( "-----BEGIN BITSHARES SIGNED MESSAGE-----\n" ); +static const string ENC_META( "-----BEGIN META-----\n" ); +static const string ENC_SIG( "-----BEGIN SIGNATURE-----\n" ); +static const string ENC_FOOTER( "-----END BITSHARES SIGNED MESSAGE-----" ); + struct operation_result_printer { public: @@ -2250,27 +2255,19 @@ class wallet_api_impl const account_object from_account = get_account(signer); - signed_message result; - result.payload.emplace_back( std::string("from") ); - result.payload.emplace_back( from_account.name ); - result.payload.emplace_back( std::string("key") ); - result.payload.emplace_back( std::string( from_account.options.memo_key ) ); - result.payload.emplace_back( std::string("time") ); - result.payload.emplace_back( time(nullptr) ); - result.payload.emplace_back( std::string("text") ); - result.payload.emplace_back( std::move(message) ); - - digest_type::encoder enc; - fc::raw::pack( enc, _chain_id ); - fc::raw::pack( enc, result.payload ); - result.signature = get_private_key( from_account.options.memo_key ).sign_compact( enc.result() ); - - return result; + signed_message msg; + msg.message = message; + msg.meta.account = from_account.name; + msg.meta.memo_key = from_account.options.memo_key; + msg.meta.block = 0; + msg.meta.time = 0; + msg.signature = get_private_key( from_account.options.memo_key ).sign_compact( msg.digest() ); + return msg; } - bool verify_message( signed_message message ) + bool verify_message( string message ) { - FC_ASSERT( message.payload.size() == 8 ); + /*FC_ASSERT( message.payload.size() == 8 ); FC_ASSERT( message.payload[0].is_string() && message.payload[0].as_string() == "from" ); FC_ASSERT( message.payload[1].is_string() ); FC_ASSERT( message.payload[2].is_string() && message.payload[2].as_string() == "key" ); @@ -2289,7 +2286,8 @@ class wallet_api_impl const public_key signer( message.signature, enc.result() ); FC_ASSERT( signer == key.key_data, "Message wasn't signed by contained key!" ); FC_ASSERT( signer == from_account.options.memo_key.key_data, - "Message was signed by contained key, but it doesn't belong to the contained account!" ); + "Message was signed by contained key, but it doesn't belong to the contained account!" );*/ + FC_ASSERT( !"Not implemented!" ); return true; } @@ -2686,6 +2684,25 @@ class wallet_api_impl return ss.str(); }; + m["sign_message"] = [this](variant result, const fc::variants& a) + { + auto r = result.as( GRAPHENE_MAX_NESTED_OBJECTS ); + + fc::stringstream encapsulated; + encapsulated << ENC_HEADER; + encapsulated << r.message << '\n'; + encapsulated << ENC_META; + encapsulated << "account=" << r.meta.account << '\n'; + encapsulated << "memokey=" << std::string( r.meta.memo_key ) << '\n'; + encapsulated << "block=" << r.meta.block << '\n'; + encapsulated << "timestamp=" << r.meta.time << '\n'; + encapsulated << ENC_SIG; + encapsulated << fc::to_hex( (const char*)r.signature->data, r.signature->size() ) << '\n'; + encapsulated << ENC_FOOTER; + + return encapsulated.str(); + }; + return m; } @@ -3185,6 +3202,17 @@ std::string operation_result_printer::operator()(const asset& a) }}} namespace graphene { namespace wallet { + fc::sha256 signed_message::digest()const + { + fc::stringstream to_sign; + to_sign << message << '\n'; + to_sign << "account=" << meta.account << '\n'; + to_sign << "memokey=" << std::string( meta.memo_key ) << '\n'; + to_sign << "block=" << meta.block << '\n'; + to_sign << "timestamp=" << meta.time; + + return fc::sha256::hash( to_sign.str() ); + } vector utility::derive_owner_keys_from_brain_key(string brain_key, int number_of_desired_keys) { // Safety-check @@ -4535,7 +4563,7 @@ signed_message wallet_api::sign_message(string signer, string message) return my->sign_message(signer, message); } -bool wallet_api::verify_message(signed_message message) +bool wallet_api::verify_message(string message) { return my->verify_message(message); } From 07de45e51e2f0ebf35fe24cdcd734a4e54d33500 Mon Sep 17 00:00:00 2001 From: Alfredo Date: Thu, 1 Aug 2019 14:49:57 -0300 Subject: [PATCH 054/111] create only 1 thread to serve ES queries --- libraries/app/api.cpp | 6 ++++-- libraries/app/include/graphene/app/application.hpp | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/libraries/app/api.cpp b/libraries/app/api.cpp index 68400016dd..753b98f413 100644 --- a/libraries/app/api.cpp +++ b/libraries/app/api.cpp @@ -331,8 +331,10 @@ namespace graphene { namespace app { if(_app.is_plugin_enabled("elasticsearch")) { auto es = _app.get_plugin("elasticsearch"); if(es.get()->get_running_mode() != elasticsearch::mode::only_save) { - auto _thread = std::make_shared("elasticsearch"); - return _thread->async([&es, &account, &stop, &limit, &start]() { + if(!_app.elasticsearch_thread) + _app.elasticsearch_thread= std::make_shared("elasticsearch"); + + return _app.elasticsearch_thread->async([&es, &account, &stop, &limit, &start]() { return es->get_account_history(account, stop, limit, start); }, "thread invoke for method " BOOST_PP_STRINGIZE(method_name)).wait(); } diff --git a/libraries/app/include/graphene/app/application.hpp b/libraries/app/include/graphene/app/application.hpp index c1feb73422..2f2a5d4393 100644 --- a/libraries/app/include/graphene/app/application.hpp +++ b/libraries/app/include/graphene/app/application.hpp @@ -119,6 +119,7 @@ namespace graphene { namespace app { bool is_plugin_enabled(const string& name) const; + std::shared_ptr elasticsearch_thread; private: void add_available_plugin( std::shared_ptr p ); From 7d177bf59db4733131f501a68d4d9f61e32f182d Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Thu, 1 Aug 2019 21:29:02 +0200 Subject: [PATCH 055/111] Fixed verify_message --- libraries/wallet/wallet.cpp | 73 ++++++++++++++++++++++++++----------- 1 file changed, 52 insertions(+), 21 deletions(-) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index c51ce8acda..8f47a2c19e 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -302,6 +302,26 @@ class htlc_hash_to_string_visitor } }; +/* meta contains lines of the form "key=value". + * Returns the value for the corresponding key, throws if key is not present. */ +static string meta_extract( const string& meta, const string& key ) +{ + FC_ASSERT( meta.size() > key.size(), "Key '${k}' not found!", ("k",key) ); + size_t start; + if( meta.substr( 0, key.size() ) == key && meta[key.size()] == '=' ) + start = 0; + else + { + start = meta.find( "\n" + key + "=" ); + FC_ASSERT( start != string::npos, "Key '${k}' not found!", ("k",key) ); + ++start; + } + start += key.size() + 1; + size_t lf = meta.find( "\n", start ); + if( lf == string::npos ) lf = meta.size(); + return meta.substr( start, lf - start ); +} + class wallet_api_impl { public: @@ -2267,27 +2287,38 @@ class wallet_api_impl bool verify_message( string message ) { - /*FC_ASSERT( message.payload.size() == 8 ); - FC_ASSERT( message.payload[0].is_string() && message.payload[0].as_string() == "from" ); - FC_ASSERT( message.payload[1].is_string() ); - FC_ASSERT( message.payload[2].is_string() && message.payload[2].as_string() == "key" ); - FC_ASSERT( message.payload[3].is_string() ); - FC_ASSERT( message.payload[4].is_string() && message.payload[4].as_string() == "time" ); - FC_ASSERT( message.payload[5].is_numeric() ); - FC_ASSERT( message.payload[6].is_string() && message.payload[6].as_string() == "text" ); - FC_ASSERT( message.payload[7].is_string() ); - - const account_object from_account = get_account( message.payload[1].as_string() ); - const public_key_type key( message.payload[3].as_string() ); - - digest_type::encoder enc; - fc::raw::pack( enc, _chain_id ); - fc::raw::pack( enc, message.payload ); - const public_key signer( message.signature, enc.result() ); - FC_ASSERT( signer == key.key_data, "Message wasn't signed by contained key!" ); - FC_ASSERT( signer == from_account.options.memo_key.key_data, - "Message was signed by contained key, but it doesn't belong to the contained account!" );*/ - FC_ASSERT( !"Not implemented!" ); + signed_message msg; + try { + variant json = fc::json::from_string( message ); + msg = json.as( 5 ); + } catch( const fc::parse_error_exception& e ) { + size_t begin_p = message.find( ENC_HEADER ); + if( begin_p == string::npos ) throw; + size_t meta_p = message.find( ENC_META, begin_p ); + if( meta_p == string::npos || meta_p < begin_p + ENC_HEADER.size() + 1 ) throw; + size_t sig_p = message.find( ENC_SIG, meta_p ); + if( sig_p == string::npos || sig_p < meta_p + ENC_META.size() ) throw; + size_t end_p = message.find( ENC_FOOTER, meta_p ); + if( end_p == string::npos || end_p < sig_p + ENC_SIG.size() + 1 ) throw; + msg.message = message.substr( begin_p + ENC_HEADER.size(), meta_p - begin_p - ENC_HEADER.size() - 1 ); + const string meta = message.substr( meta_p + ENC_META.size(), sig_p - meta_p - ENC_META.size() ); + const string sig = message.substr( sig_p + ENC_SIG.size(), end_p - sig_p - ENC_SIG.size() - 1 ); + msg.meta.account = meta_extract( meta, "account" ); + msg.meta.memo_key = public_key_type( meta_extract( meta, "memokey" ) ); + msg.meta.block = boost::lexical_cast( meta_extract( meta, "block" ) ); + msg.meta.time = boost::lexical_cast( meta_extract( meta, "timestamp" ) ); + msg.signature = variant(sig).as< fc::ecc::compact_signature >( 5 ); + } + + if( !msg.signature.valid() ) return false; + + const account_object from_account = get_account( msg.meta.account ); + + const public_key signer( *msg.signature, msg.digest() ); + if( !( msg.meta.memo_key == signer ) ) return false; + FC_ASSERT( from_account.options.memo_key == signer, + "Message was signed by contained key, but it doesn't belong to the contained account!" ); + return true; } From 7544f7fb19763918fddb543d4545296a60815abe Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Thu, 1 Aug 2019 22:11:37 +0200 Subject: [PATCH 056/111] Refactored verify_message into distinct methods --- .../wallet/include/graphene/wallet/wallet.hpp | 24 ++++- libraries/wallet/wallet.cpp | 102 +++++++++++++----- 2 files changed, 96 insertions(+), 30 deletions(-) diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index 761434d4b8..fbfdee0714 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -1080,12 +1080,30 @@ class wallet_api */ signed_message sign_message(string signer, string message); + /** Verify a message signed with sign_message using the given account's memo key. + * + * @param message the message text + * @param account the account name of the message + * @param block the block number of the message + * @param time the timestamp of the message + * @param sig the message signature + * @return true if signature matches + */ + bool verify_message( string message, string account, int block, int time, compact_signature sig ); + /** Verify a message signed with sign_message * - * @param message either a JSON-encoded signed_message structure, or a signed message in encapsulated format + * @param message the signed_message structure containing message, meta data and signature + * @return true if signature matches + */ + bool verify_signed_message( signed_message message ); + + /** Verify a message signed with sign_message, in its encapsulated form. + * + * @param message the complete encapsulated message string including separators and line feeds * @return true if signature matches */ - bool verify_message(string message); + bool verify_encapsulated_message( string message ); /** These methods are used for stealth transfers */ ///@{ @@ -2188,6 +2206,8 @@ FC_API( graphene::wallet::wallet_api, (read_memo) (sign_message) (verify_message) + (verify_signed_message) + (verify_encapsulated_message) (set_key_label) (get_key_label) (get_public_key) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index 8f47a2c19e..a6d30047b7 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -2285,43 +2285,68 @@ class wallet_api_impl return msg; } - bool verify_message( string message ) + bool verify_message( const string& message, const string& account, int block, int time, const compact_signature& sig ) { + const account_object from_account = get_account( account ); + signed_message msg; - try { - variant json = fc::json::from_string( message ); - msg = json.as( 5 ); - } catch( const fc::parse_error_exception& e ) { - size_t begin_p = message.find( ENC_HEADER ); - if( begin_p == string::npos ) throw; - size_t meta_p = message.find( ENC_META, begin_p ); - if( meta_p == string::npos || meta_p < begin_p + ENC_HEADER.size() + 1 ) throw; - size_t sig_p = message.find( ENC_SIG, meta_p ); - if( sig_p == string::npos || sig_p < meta_p + ENC_META.size() ) throw; - size_t end_p = message.find( ENC_FOOTER, meta_p ); - if( end_p == string::npos || end_p < sig_p + ENC_SIG.size() + 1 ) throw; - msg.message = message.substr( begin_p + ENC_HEADER.size(), meta_p - begin_p - ENC_HEADER.size() - 1 ); - const string meta = message.substr( meta_p + ENC_META.size(), sig_p - meta_p - ENC_META.size() ); - const string sig = message.substr( sig_p + ENC_SIG.size(), end_p - sig_p - ENC_SIG.size() - 1 ); - msg.meta.account = meta_extract( meta, "account" ); - msg.meta.memo_key = public_key_type( meta_extract( meta, "memokey" ) ); - msg.meta.block = boost::lexical_cast( meta_extract( meta, "block" ) ); - msg.meta.time = boost::lexical_cast( meta_extract( meta, "timestamp" ) ); - msg.signature = variant(sig).as< fc::ecc::compact_signature >( 5 ); - } + msg.message = message; + msg.meta.account = from_account.name; + msg.meta.memo_key = from_account.options.memo_key; + msg.meta.block = block; + msg.meta.time = time; + msg.signature = sig; - if( !msg.signature.valid() ) return false; + return verify_signed_message( msg ); + } - const account_object from_account = get_account( msg.meta.account ); + bool verify_signed_message( const signed_message& message ) + { + if( !message.signature.valid() ) return false; + + const account_object from_account = get_account( message.meta.account ); - const public_key signer( *msg.signature, msg.digest() ); - if( !( msg.meta.memo_key == signer ) ) return false; + const public_key signer( *message.signature, message.digest() ); + if( !( message.meta.memo_key == signer ) ) return false; FC_ASSERT( from_account.options.memo_key == signer, "Message was signed by contained key, but it doesn't belong to the contained account!" ); return true; } + /** Verify a message signed with sign_message, in its encapsulated form. + * + * @param message the complete encapsulated message string including separators and line feeds + * @return true if signature matches + */ + bool verify_encapsulated_message( const string& message ) + { + signed_message msg; + size_t begin_p = message.find( ENC_HEADER ); + FC_ASSERT( begin_p != string::npos, "BEGIN MESSAGE line not found!" ); + size_t meta_p = message.find( ENC_META, begin_p ); + FC_ASSERT( meta_p != string::npos, "BEGIN META line not found!" ); + FC_ASSERT( meta_p >= begin_p + ENC_HEADER.size() + 1, "Missing message!?" ); + size_t sig_p = message.find( ENC_SIG, meta_p ); + FC_ASSERT( sig_p != string::npos, "BEGIN SIGNATURE line not found!" ); + FC_ASSERT( sig_p >= meta_p + ENC_META.size(), "Missing metadata?!" ); + size_t end_p = message.find( ENC_FOOTER, meta_p ); + FC_ASSERT( end_p != string::npos, "END MESSAGE line not found!" ); + FC_ASSERT( end_p >= sig_p + ENC_SIG.size() + 1, "Missing signature?!" ); + + msg.message = message.substr( begin_p + ENC_HEADER.size(), meta_p - begin_p - ENC_HEADER.size() - 1 ); + const string meta = message.substr( meta_p + ENC_META.size(), sig_p - meta_p - ENC_META.size() ); + const string sig = message.substr( sig_p + ENC_SIG.size(), end_p - sig_p - ENC_SIG.size() - 1 ); + + msg.meta.account = meta_extract( meta, "account" ); + msg.meta.memo_key = public_key_type( meta_extract( meta, "memokey" ) ); + msg.meta.block = boost::lexical_cast( meta_extract( meta, "block" ) ); + msg.meta.time = boost::lexical_cast( meta_extract( meta, "timestamp" ) ); + msg.signature = variant(sig).as< fc::ecc::compact_signature >( 5 ); + + return verify_signed_message( msg ); + } + signed_transaction sell_asset(string seller_account, string amount_to_sell, string symbol_to_sell, @@ -4594,11 +4619,32 @@ signed_message wallet_api::sign_message(string signer, string message) return my->sign_message(signer, message); } -bool wallet_api::verify_message(string message) +bool wallet_api::verify_message( string message, string account, int block, int time, compact_signature sig ) +{ + return my->verify_message( message, account, block, time, sig ); +} + +/** Verify a message signed with sign_message + * + * @param message the signed_message structure containing message, meta data and signature + * @return true if signature matches + */ +bool wallet_api::verify_signed_message( signed_message message ) +{ + return my->verify_signed_message( message ); +} + +/** Verify a message signed with sign_message, in its encapsulated form. + * + * @param message the complete encapsulated message string including separators and line feeds + * @return true if signature matches + */ +bool wallet_api::verify_encapsulated_message( string message ) { - return my->verify_message(message); + return my->verify_encapsulated_message( message ); } + string wallet_api::get_key_label( public_key_type key )const { auto key_itr = my->_wallet.labeled_keys.get().find(key); From 2c672fff3a2fb1bd2a3ed57e2cbea7bb3cb10c1b Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Fri, 2 Aug 2019 15:17:33 +0200 Subject: [PATCH 057/111] Added unit test --- tests/cli/main.cpp | 98 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/tests/cli/main.cpp b/tests/cli/main.cpp index ccff75736a..a22316bc3d 100644 --- a/tests/cli/main.cpp +++ b/tests/cli/main.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -37,6 +38,7 @@ #include #include #include +#include #include @@ -1084,3 +1086,99 @@ BOOST_AUTO_TEST_CASE( cli_create_htlc ) } app1->shutdown(); } + +static string encapsulate( const graphene::wallet::signed_message& msg ) +{ + fc::stringstream encapsulated; + encapsulated << "-----BEGIN BITSHARES SIGNED MESSAGE-----\n" + << msg.message << '\n' + << "-----BEGIN META-----\n" + << "account=" << msg.meta.account << '\n' + << "memokey=" << std::string( msg.meta.memo_key ) << '\n' + << "block=" << msg.meta.block << '\n' + << "timestamp=" << msg.meta.time << '\n' + << "-----BEGIN SIGNATURE-----\n" + << fc::to_hex( (const char*)msg.signature->data, msg.signature->size() ) << '\n' + << "-----END BITSHARES SIGNED MESSAGE-----"; + return encapsulated.str(); +} + +/****** + * Check signing/verifying a message with a memo key + */ +BOOST_FIXTURE_TEST_CASE( cli_sign_message, cli_fixture ) +{ try { + const auto nathan_priv = *wif_to_key( nathan_keys[0] ); + const public_key_type nathan_pub( nathan_priv.get_public_key() ); + + // account does not exist + BOOST_REQUIRE_THROW( con.wallet_api_ptr->sign_message( "dan", "123" ), fc::assert_exception ); + + // success + graphene::wallet::signed_message msg = con.wallet_api_ptr->sign_message( "nathan", "123" ); + BOOST_CHECK_EQUAL( "123", msg.message ); + BOOST_CHECK_EQUAL( "nathan", msg.meta.account ); + BOOST_CHECK_EQUAL( std::string( nathan_pub ), std::string( msg.meta.memo_key ) ); + BOOST_CHECK( msg.signature.valid() ); + + // change message, verify failure + msg.message = "124"; + BOOST_CHECK( !con.wallet_api_ptr->verify_message( msg.message, msg.meta.account, msg.meta.block, msg.meta.time, + *msg.signature ) ); + BOOST_CHECK( !con.wallet_api_ptr->verify_signed_message( msg ) ); + BOOST_CHECK( !con.wallet_api_ptr->verify_encapsulated_message( encapsulate( msg ) ) ); + msg.message = "123"; + + // change account, verify failure + msg.meta.account = "dan"; + BOOST_REQUIRE_THROW( !con.wallet_api_ptr->verify_message( msg.message, msg.meta.account, msg.meta.block, + msg.meta.time, *msg.signature ), fc::assert_exception ); + BOOST_REQUIRE_THROW( !con.wallet_api_ptr->verify_signed_message( msg ), fc::assert_exception ); + BOOST_REQUIRE_THROW( !con.wallet_api_ptr->verify_encapsulated_message( encapsulate( msg ) ), fc::assert_exception); + msg.meta.account = "nathan"; + + // change key, verify failure + ++msg.meta.memo_key.key_data.data[1]; + //BOOST_CHECK( !con.wallet_api_ptr->verify_message( msg.message, msg.meta.account, msg.meta.block, msg.meta.time, + // *msg.signature ) ); + BOOST_CHECK( !con.wallet_api_ptr->verify_signed_message( msg ) ); + BOOST_CHECK( !con.wallet_api_ptr->verify_encapsulated_message( encapsulate( msg ) ) ); + --msg.meta.memo_key.key_data.data[1]; + + // change block, verify failure + ++msg.meta.block; + BOOST_CHECK( !con.wallet_api_ptr->verify_message( msg.message, msg.meta.account, msg.meta.block, msg.meta.time, + *msg.signature ) ); + BOOST_CHECK( !con.wallet_api_ptr->verify_signed_message( msg ) ); + BOOST_CHECK( !con.wallet_api_ptr->verify_encapsulated_message( encapsulate( msg ) ) ); + --msg.meta.block; + + // change time, verify failure + ++msg.meta.time; + BOOST_CHECK( !con.wallet_api_ptr->verify_message( msg.message, msg.meta.account, msg.meta.block, msg.meta.time, + *msg.signature ) ); + BOOST_CHECK( !con.wallet_api_ptr->verify_signed_message( msg ) ); + BOOST_CHECK( !con.wallet_api_ptr->verify_encapsulated_message( encapsulate( msg ) ) ); + --msg.meta.time; + + // change signature, verify failure + ++msg.signature->data[1]; + try { + BOOST_CHECK( !con.wallet_api_ptr->verify_message( msg.message, msg.meta.account, msg.meta.block, msg.meta.time, + *msg.signature ) ); + } catch( const fc::assert_exception& ) {} // failure to reconstruct key from signature is ok as well + try { + BOOST_CHECK( !con.wallet_api_ptr->verify_signed_message( msg ) ); + } catch( const fc::assert_exception& ) {} // failure to reconstruct key from signature is ok as well + try { + BOOST_CHECK( !con.wallet_api_ptr->verify_encapsulated_message( encapsulate( msg ) ) ); + } catch( const fc::assert_exception& ) {} // failure to reconstruct key from signature is ok as well + --msg.signature->data[1]; + + // verify success + BOOST_CHECK( con.wallet_api_ptr->verify_message( msg.message, msg.meta.account, msg.meta.block, msg.meta.time, + *msg.signature ) ); + BOOST_CHECK( con.wallet_api_ptr->verify_signed_message( msg ) ); + BOOST_CHECK( con.wallet_api_ptr->verify_encapsulated_message( encapsulate( msg ) ) ); + +} FC_LOG_AND_RETHROW() } From 1d1a22939bc9f0388d408a228596834684989243 Mon Sep 17 00:00:00 2001 From: Fabian Schuh Date: Mon, 5 Aug 2019 13:04:14 +0200 Subject: [PATCH 058/111] Remove seed node with missing DNS record --- libraries/egenesis/seed-nodes.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/egenesis/seed-nodes.txt b/libraries/egenesis/seed-nodes.txt index a372b79e43..227110cdcb 100644 --- a/libraries/egenesis/seed-nodes.txt +++ b/libraries/egenesis/seed-nodes.txt @@ -5,7 +5,6 @@ "bts.lafona.net:1776", // lafona (France) "bts-seed1.abit-more.com:62015", // abit (China) "node.blckchnd.com:4243", // blckchnd (Germany) -"seed.bitsharesdex.com:50696", // iHashFury (Europe) "seed.roelandp.nl:1776", // roelandp (Canada) "seed04.bts-nodes.net:1776", // Thom (Australia) "seed05.bts-nodes.net:1776", // Thom (USA) From d7353240b07f3f405041d2589af6a9f99a92cd75 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Mon, 5 Aug 2019 15:17:40 +0200 Subject: [PATCH 059/111] Switched time to string format --- libraries/wallet/include/graphene/wallet/wallet.hpp | 4 ++-- libraries/wallet/wallet.cpp | 9 +++++---- tests/cli/main.cpp | 4 ++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index fbfdee0714..c3624419bf 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -271,7 +271,7 @@ struct signed_message_meta { string account; public_key_type memo_key; uint32_t block; - int64_t time; + string time; }; class signed_message { @@ -1089,7 +1089,7 @@ class wallet_api * @param sig the message signature * @return true if signature matches */ - bool verify_message( string message, string account, int block, int time, compact_signature sig ); + bool verify_message( string message, string account, int block, const string& time, compact_signature sig ); /** Verify a message signed with sign_message * diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index a6d30047b7..db62284210 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -2280,12 +2280,13 @@ class wallet_api_impl msg.meta.account = from_account.name; msg.meta.memo_key = from_account.options.memo_key; msg.meta.block = 0; - msg.meta.time = 0; + msg.meta.time = "1970-01-01T00:00:00Z"; msg.signature = get_private_key( from_account.options.memo_key ).sign_compact( msg.digest() ); return msg; } - bool verify_message( const string& message, const string& account, int block, int time, const compact_signature& sig ) + bool verify_message( const string& message, const string& account, int block, const string& time, + const compact_signature& sig ) { const account_object from_account = get_account( account ); @@ -2341,7 +2342,7 @@ class wallet_api_impl msg.meta.account = meta_extract( meta, "account" ); msg.meta.memo_key = public_key_type( meta_extract( meta, "memokey" ) ); msg.meta.block = boost::lexical_cast( meta_extract( meta, "block" ) ); - msg.meta.time = boost::lexical_cast( meta_extract( meta, "timestamp" ) ); + msg.meta.time = meta_extract( meta, "timestamp" ); msg.signature = variant(sig).as< fc::ecc::compact_signature >( 5 ); return verify_signed_message( msg ); @@ -4619,7 +4620,7 @@ signed_message wallet_api::sign_message(string signer, string message) return my->sign_message(signer, message); } -bool wallet_api::verify_message( string message, string account, int block, int time, compact_signature sig ) +bool wallet_api::verify_message( string message, string account, int block, const string& time, compact_signature sig ) { return my->verify_message( message, account, block, time, sig ); } diff --git a/tests/cli/main.cpp b/tests/cli/main.cpp index a22316bc3d..13510a4c8d 100644 --- a/tests/cli/main.cpp +++ b/tests/cli/main.cpp @@ -1154,12 +1154,12 @@ BOOST_FIXTURE_TEST_CASE( cli_sign_message, cli_fixture ) --msg.meta.block; // change time, verify failure - ++msg.meta.time; + ++msg.meta.time[0]; BOOST_CHECK( !con.wallet_api_ptr->verify_message( msg.message, msg.meta.account, msg.meta.block, msg.meta.time, *msg.signature ) ); BOOST_CHECK( !con.wallet_api_ptr->verify_signed_message( msg ) ); BOOST_CHECK( !con.wallet_api_ptr->verify_encapsulated_message( encapsulate( msg ) ) ); - --msg.meta.time; + --msg.meta.time[0]; // change signature, verify failure ++msg.signature->data[1]; From b2a519d50ff72469334e3b43cedb2e1ff698a836 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Mon, 5 Aug 2019 15:25:55 +0200 Subject: [PATCH 060/111] Use head block num + time instead of dummy values --- libraries/wallet/wallet.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index db62284210..dcd1a5b80e 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -2274,13 +2274,14 @@ class wallet_api_impl FC_ASSERT( !self.is_locked() ); const account_object from_account = get_account(signer); + auto dynamic_props = get_dynamic_global_properties(); signed_message msg; msg.message = message; msg.meta.account = from_account.name; msg.meta.memo_key = from_account.options.memo_key; - msg.meta.block = 0; - msg.meta.time = "1970-01-01T00:00:00Z"; + msg.meta.block = dynamic_props.head_block_number; + msg.meta.time = dynamic_props.time.to_iso_string() + "Z"; msg.signature = get_private_key( from_account.options.memo_key ).sign_compact( msg.digest() ); return msg; } From 098b02c1bf1e12ee12216fc7bd6247aa7b8ef06f Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Mon, 5 Aug 2019 15:26:12 +0200 Subject: [PATCH 061/111] Removed duplicate comment --- libraries/wallet/wallet.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index dcd1a5b80e..7c19bb94fe 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -2316,11 +2316,6 @@ class wallet_api_impl return true; } - /** Verify a message signed with sign_message, in its encapsulated form. - * - * @param message the complete encapsulated message string including separators and line feeds - * @return true if signature matches - */ bool verify_encapsulated_message( const string& message ) { signed_message msg; From 89e4e4ea7a2aa082ee61d0dc05cefa4ac1909286 Mon Sep 17 00:00:00 2001 From: crypto-ape <43807588+crypto-ape@users.noreply.github.com> Date: Mon, 5 Aug 2019 17:11:17 +0200 Subject: [PATCH 062/111] witness_node can accept private keys from files --- .../include/graphene/witness/witness.hpp | 1 + libraries/plugins/witness/witness.cpp | 68 +++++++++++++++---- 2 files changed, 55 insertions(+), 14 deletions(-) diff --git a/libraries/plugins/witness/include/graphene/witness/witness.hpp b/libraries/plugins/witness/include/graphene/witness/witness.hpp index 0d2eab27ac..8ca09a5b27 100644 --- a/libraries/plugins/witness/include/graphene/witness/witness.hpp +++ b/libraries/plugins/witness/include/graphene/witness/witness.hpp @@ -71,6 +71,7 @@ class witness_plugin : public graphene::app::plugin { void schedule_production_loop(); block_production_condition::block_production_condition_enum block_production_loop(); block_production_condition::block_production_condition_enum maybe_produce_block( fc::limited_mutable_variant_object& capture ); + void add_private_key(const std::string& key_id_to_wif_pair_string); /// Fetch signing keys of all witnesses in the cache from object database and update the cache accordingly void refresh_witness_key_cache(); diff --git a/libraries/plugins/witness/witness.cpp b/libraries/plugins/witness/witness.cpp index eda18b1ce8..05bbb9564d 100644 --- a/libraries/plugins/witness/witness.cpp +++ b/libraries/plugins/witness/witness.cpp @@ -29,6 +29,9 @@ #include #include +#include + +#include #include @@ -74,6 +77,10 @@ void witness_plugin::plugin_set_program_options( 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)") + ("private-key-file", bpo::value>()->composing()->multitoken(), + "Path to a file containing tuples of [PublicKey, WIF private key]." + " The file has to contain exactly one tuple (i.e. private - public key pair) per line." + " This option may be specified multiple times, thus multiple files can be provided.") ; config_file_options.add(command_line_options); } @@ -83,6 +90,32 @@ std::string witness_plugin::plugin_name()const return "witness"; } +void witness_plugin::add_private_key(const std::string& key_id_to_wif_pair_string) +{ + auto key_id_to_wif_pair = graphene::app::dejsonify> + (key_id_to_wif_pair_string, 5); + 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, 2).as(1); + } + catch (const fc::exception&) + { + FC_THROW("Invalid WIF-format private key ${key_string}", ("key_string", key_id_to_wif_pair.second)); + } + } + + if (_private_keys.find(key_id_to_wif_pair.first) == _private_keys.end()) + { + ilog("Public Key: ${public}", ("public", key_id_to_wif_pair.first)); + _private_keys[key_id_to_wif_pair.first] = *private_key; + } +} + void witness_plugin::plugin_initialize(const boost::program_options::variables_map& options) { try { ilog("witness plugin: plugin_initialize() begin"); @@ -94,24 +127,31 @@ void witness_plugin::plugin_initialize(const boost::program_options::variables_m 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, 5); - ilog("Public Key: ${public}", ("public", key_id_to_wif_pair.first)); - fc::optional private_key = graphene::utilities::wif_to_key(key_id_to_wif_pair.second); - if (!private_key) + add_private_key(key_id_to_wif_pair_string); + } + } + if (options.count("private-key-file")) + { + const std::vector key_id_to_wif_pair_files = + options["private-key-file"].as>(); + for (const boost::filesystem::path& key_id_to_wif_pair_file : key_id_to_wif_pair_files) + { + if (fc::exists(key_id_to_wif_pair_file)) { - // 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, 2).as(1); - } - catch (const fc::exception&) + std::string file_content; + fc::read_file_contents(key_id_to_wif_pair_file, file_content); + std::istringstream file_content_as_stream(file_content); + + std::string line; // key_id_to_wif_pair_string + while (std::getline(file_content_as_stream, line)) { - FC_THROW("Invalid WIF-format private key ${key_string}", ("key_string", key_id_to_wif_pair.second)); + add_private_key(line); } } - _private_keys[key_id_to_wif_pair.first] = *private_key; + else + { + FC_THROW("Failed to load private key file from ${path}", ("path", key_id_to_wif_pair_file.string())); + } } } if(options.count("required-participation")) From f65f5b69ef860eb3450299af758268f3c7bcafdb Mon Sep 17 00:00:00 2001 From: abitmore Date: Tue, 6 Aug 2019 12:26:10 -0400 Subject: [PATCH 063/111] Add test case for ticker volume underflow issue Reproduces https://github.com/bitshares/bitshares-core/issues/1883. --- tests/tests/settle_tests.cpp | 118 +++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) diff --git a/tests/tests/settle_tests.cpp b/tests/tests/settle_tests.cpp index f64719e613..6310493ae5 100644 --- a/tests/tests/settle_tests.cpp +++ b/tests/tests/settle_tests.cpp @@ -1501,4 +1501,122 @@ BOOST_AUTO_TEST_CASE( global_settle_rounding_test_after_hf_184 ) } FC_LOG_AND_RETHROW() } +/** + * Test case to reproduce https://github.com/bitshares/bitshares-core/issues/1883. + * When there is only one fill_order object in the ticker rolling buffer, it should only be rolled out once. + */ +BOOST_AUTO_TEST_CASE( global_settle_ticker_test ) +{ + try { + generate_block(); + + const auto& meta_idx = db.get_index_type>(); + const auto& ticker_idx = db.get_index_type().indices(); + const auto& history_idx = db.get_index_type().indices(); + + BOOST_CHECK_EQUAL( meta_idx.size(), 0 ); + BOOST_CHECK_EQUAL( ticker_idx.size(), 0 ); + BOOST_CHECK_EQUAL( history_idx.size(), 0 ); + + ACTORS((judge)(alice)); + + const auto& pmark = create_prediction_market("PMARK", judge_id); + const auto& core = asset_id_type()(db); + + int64_t init_balance(1000000); + transfer(committee_account, judge_id, asset(init_balance)); + transfer(committee_account, alice_id, asset(init_balance)); + + BOOST_TEST_MESSAGE( "Open position with equal collateral" ); + borrow( alice, pmark.amount(1000), asset(1000) ); + + BOOST_TEST_MESSAGE( "Globally settling" ); + force_global_settle( pmark, pmark.amount(1) / core.amount(1) ); + + generate_block(); + fc::usleep(fc::milliseconds(200)); // sleep a while to execute callback in another thread + + { + BOOST_CHECK_EQUAL( meta_idx.size(), 1 ); + BOOST_CHECK_EQUAL( ticker_idx.size(), 1 ); + BOOST_CHECK_EQUAL( history_idx.size(), 1 ); + + const auto& meta = *meta_idx.begin(); + const auto& tick = *ticker_idx.begin(); + const auto& hist = *history_idx.begin(); + + BOOST_CHECK( meta.rolling_min_order_his_id == hist.id ); + BOOST_CHECK( meta.skip_min_order_his_id == false ); + + BOOST_CHECK( tick.base_volume == 1000 ); + BOOST_CHECK( tick.quote_volume == 1000 ); + } + + generate_blocks( db.head_block_time() + 86000 ); // less than a day + fc::usleep(fc::milliseconds(200)); // sleep a while to execute callback in another thread + + // nothing changes + { + BOOST_CHECK_EQUAL( meta_idx.size(), 1 ); + BOOST_CHECK_EQUAL( ticker_idx.size(), 1 ); + BOOST_CHECK_EQUAL( history_idx.size(), 1 ); + + const auto& meta = *meta_idx.begin(); + const auto& tick = *ticker_idx.begin(); + const auto& hist = *history_idx.begin(); + + BOOST_CHECK( meta.rolling_min_order_his_id == hist.id ); + BOOST_CHECK( meta.skip_min_order_his_id == false ); + + BOOST_CHECK( tick.base_volume == 1000 ); + BOOST_CHECK( tick.quote_volume == 1000 ); + } + + generate_blocks( db.head_block_time() + 4000 ); // now more than 24 hours + fc::usleep(fc::milliseconds(200)); // sleep a while to execute callback in another thread + + // the history is rolled out, new 24h volume should be 0 + { + BOOST_CHECK_EQUAL( meta_idx.size(), 1 ); + BOOST_CHECK_EQUAL( ticker_idx.size(), 1 ); + BOOST_CHECK_EQUAL( history_idx.size(), 1 ); + + const auto& meta = *meta_idx.begin(); + const auto& tick = *ticker_idx.begin(); + const auto& hist = *history_idx.begin(); + + BOOST_CHECK( meta.rolling_min_order_his_id == hist.id ); + BOOST_CHECK( meta.skip_min_order_his_id == true ); // the order should be skipped on next roll + + BOOST_CHECK( tick.base_volume == 0 ); + BOOST_CHECK( tick.quote_volume == 0 ); + } + + generate_block(); + fc::usleep(fc::milliseconds(200)); // sleep a while to execute callback in another thread + + // nothing changes + { + BOOST_CHECK_EQUAL( meta_idx.size(), 1 ); + BOOST_CHECK_EQUAL( ticker_idx.size(), 1 ); + BOOST_CHECK_EQUAL( history_idx.size(), 1 ); + + const auto& meta = *meta_idx.begin(); + const auto& tick = *ticker_idx.begin(); + const auto& hist = *history_idx.begin(); + + BOOST_CHECK( meta.rolling_min_order_his_id == hist.id ); + BOOST_CHECK( meta.skip_min_order_his_id == true ); + + BOOST_CHECK( tick.base_volume == 0 ); + BOOST_CHECK( tick.quote_volume == 0 ); + } + + + } catch( const fc::exception& e) { + edump((e.to_detail_string())); + throw; + } +} + BOOST_AUTO_TEST_SUITE_END() From e98f178569b5100f3d566ef8411675c5402d312f Mon Sep 17 00:00:00 2001 From: abitmore Date: Tue, 6 Aug 2019 12:33:13 -0400 Subject: [PATCH 064/111] Fix market ticker volume underflow issue Ref: https://github.com/bitshares/bitshares-core/issues/1883 --- libraries/plugins/market_history/market_history_plugin.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/plugins/market_history/market_history_plugin.cpp b/libraries/plugins/market_history/market_history_plugin.cpp index 9c01ea2149..6b4a3558c4 100644 --- a/libraries/plugins/market_history/market_history_plugin.cpp +++ b/libraries/plugins/market_history/market_history_plugin.cpp @@ -371,7 +371,8 @@ void market_history_plugin_impl::update_market_histories( const signed_block& b } else // if all data are rolled out { - if( last_min_his_id != _meta->rolling_min_order_his_id ) // if rolled out some + if( !_meta->skip_min_order_his_id + || last_min_his_id != _meta->rolling_min_order_his_id ) // if rolled out some { db.modify( *_meta, [&]( market_ticker_meta_object& mtm ) { mtm.rolling_min_order_his_id = last_min_his_id; From adae71b1e3fb8fb5521321ea1204793fce5d5000 Mon Sep 17 00:00:00 2001 From: abitmore Date: Thu, 8 Aug 2019 12:56:33 +0000 Subject: [PATCH 065/111] Improve help message of get_dev_key --- programs/genesis_util/CMakeLists.txt | 2 +- programs/genesis_util/get_dev_key.cpp | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/programs/genesis_util/CMakeLists.txt b/programs/genesis_util/CMakeLists.txt index 9c3b278d23..31df5e5968 100644 --- a/programs/genesis_util/CMakeLists.txt +++ b/programs/genesis_util/CMakeLists.txt @@ -18,7 +18,7 @@ install( TARGETS add_executable( get_dev_key get_dev_key.cpp ) target_link_libraries( get_dev_key - PRIVATE graphene_app graphene_chain graphene_egenesis_none graphene_utilities fc ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} ) + PRIVATE graphene_utilities graphene_protocol fc ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} ) install( TARGETS get_dev_key diff --git a/programs/genesis_util/get_dev_key.cpp b/programs/genesis_util/get_dev_key.cpp index 4fc6a42f2c..52fa986e15 100644 --- a/programs/genesis_util/get_dev_key.cpp +++ b/programs/genesis_util/get_dev_key.cpp @@ -44,7 +44,7 @@ int main( int argc, char** argv ) { std::string dev_key_prefix; bool need_help = false; - if( argc < 2 ) + if( argc < 3 ) // requires at least a prefix and a suffix need_help = true; else { @@ -57,13 +57,13 @@ int main( int argc, char** argv ) if( need_help ) { - std::cerr << argc << " " << argv[1] << "\n"; - std::cerr << "get-dev-key ...\n" - "\n" - "example:\n" - "\n" - "get-dev-key wxyz- owner-5 active-7 balance-9 wit-block-signing-3 wit-owner-5 wit-active-33\n" - "get-dev-key wxyz- wit-block-signing-0:101\n" + std::cerr << "\nThis program generates keys with specified prefix and suffix(es) as seed(s).\n\n" + "Syntax:\n\n" + " get_dev_key ...\n\n" + "Examples:\n\n" + " get_dev_key nath an\n" + " get_dev_key wxyz- owner-5 active-7 balance-9 wit-block-signing-3 wit-owner-5 wit-active-33\n" + " get_dev_key wxyz- wit-block-signing-0:101\n" "\n"; return 1; } @@ -121,7 +121,7 @@ int main( int argc, char** argv ) } catch ( const fc::exception& e ) { - std::cout << e.to_detail_string() << "\n"; + std::cerr << e.to_detail_string() << "\n"; return 1; } return 0; From cc565a3443032b5df74b3e658b22afd8eecac019 Mon Sep 17 00:00:00 2001 From: abitmore Date: Wed, 24 Jul 2019 07:50:03 -0400 Subject: [PATCH 066/111] Add optional subscribe param to some database APIs These APIs are updated: - get_objects - get_assets - get_accounts - get_full_accounts - lookup_accounts - get_htlc --- libraries/app/database_api.cpp | 120 +++++++++++------- .../app/include/graphene/app/database_api.hpp | 51 ++++++-- libraries/wallet/wallet.cpp | 16 +-- 3 files changed, 120 insertions(+), 67 deletions(-) diff --git a/libraries/app/database_api.cpp b/libraries/app/database_api.cpp index ab6889c7b3..9e57c59858 100644 --- a/libraries/app/database_api.cpp +++ b/libraries/app/database_api.cpp @@ -59,7 +59,7 @@ class database_api_impl : public std::enable_shared_from_this // Objects - fc::variants get_objects(const vector& ids)const; + fc::variants get_objects( const vector& ids, optional subscribe )const; // Subscriptions void set_subscribe_callback( std::function cb, bool notify_remove_create ); @@ -87,12 +87,15 @@ class database_api_impl : public std::enable_shared_from_this // Accounts account_id_type get_account_id_from_string(const std::string& name_or_id)const; - vector> get_accounts(const vector& account_names_or_ids)const; - std::map get_full_accounts( const vector& names_or_ids, bool subscribe ); + vector> get_accounts( const vector& account_names_or_ids, + optional subscribe )const; + std::map get_full_accounts( const vector& names_or_ids, optional subscribe ); optional get_account_by_name( string name )const; vector get_account_references( const std::string account_id_or_name )const; vector> lookup_account_names(const vector& account_names)const; - map lookup_accounts(const string& lower_bound_name, uint32_t limit)const; + map lookup_accounts( const string& lower_bound_name, + uint32_t limit, + optional subscribe )const; uint64_t get_account_count()const; // Balances @@ -105,7 +108,8 @@ class database_api_impl : public std::enable_shared_from_this // Assets uint64_t get_asset_count()const; asset_id_type get_asset_id_from_string(const std::string& symbol_or_id)const; - vector> get_assets(const vector& asset_symbols_or_ids)const; + vector> get_assets( const vector& asset_symbols_or_ids, + optional subscribe )const; vector list_assets(const string& lower_bound_symbol, uint32_t limit)const; vector> lookup_asset_symbols(const vector& symbols_or_ids)const; vector get_assets_by_issuer(const std::string& issuer_name_or_id, @@ -180,7 +184,7 @@ class database_api_impl : public std::enable_shared_from_this vector get_withdraw_permissions_by_recipient(const std::string account_id_or_name, withdraw_permission_id_type start, uint32_t limit)const; // HTLC - optional get_htlc(htlc_id_type id) const; + optional get_htlc( htlc_id_type id, optional subscribe ) const; vector get_htlc_by_from(const std::string account_id_or_name, htlc_id_type start, uint32_t limit) const; vector get_htlc_by_to(const std::string account_id_or_name, htlc_id_type start, uint32_t limit) const; vector list_htlcs(const htlc_id_type lower_bound_id, uint32_t limit) const; @@ -188,6 +192,16 @@ class database_api_impl : public std::enable_shared_from_this //private: static string price_to_string( const price& _price, const asset_object& _base, const asset_object& _quote ); + // Decides whether to subscribe using member variables and given parameter + bool get_whether_to_subscribe( optional subscribe )const + { + if( !_subscribe_callback ) + return false; + if( subscribe.valid() ) + return *subscribe; + return _enabled_auto_subscription; + } + // Note: // Different type of object_id objects could become identical after packed. // For example, both `account_id_type a=1.2.0` and `asset_id_type b=1.3.0` will become `0` after packed. @@ -295,14 +309,16 @@ class database_api_impl : public std::enable_shared_from_this FC_ASSERT( asset, "no such asset" ); return asset; } - vector> get_assets(const vector& asset_ids)const + vector> get_assets( const vector& asset_ids, + optional subscribe = optional() )const { + bool to_subscribe = get_whether_to_subscribe( subscribe ); vector> result; result.reserve(asset_ids.size()); std::transform(asset_ids.begin(), asset_ids.end(), std::back_inserter(result), - [this](asset_id_type id) -> optional { + [this,to_subscribe](asset_id_type id) -> optional { if(auto o = _db.find(id)) { - if( _enabled_auto_subscription ) + if( to_subscribe ) subscribe_to_item( id ); return extend_asset( *o ); } @@ -509,30 +525,26 @@ market_ticker::market_ticker(const fc::time_point_sec& now, // // ////////////////////////////////////////////////////////////////////// -fc::variants database_api::get_objects(const vector& ids)const +fc::variants database_api::get_objects( const vector& ids, optional subscribe )const { - return my->get_objects( ids ); + return my->get_objects( ids, subscribe ); } -fc::variants database_api_impl::get_objects(const vector& ids)const +fc::variants database_api_impl::get_objects( const vector& ids, optional subscribe )const { - if( _subscribe_callback && _enabled_auto_subscription ) - { - for( auto id : ids ) - { - if( id.type() == operation_history_object_type && id.space() == protocol_ids ) continue; - if( id.type() == impl_account_transaction_history_object_type && id.space() == implementation_ids ) continue; - this->subscribe_to_item( id ); - } - } + bool to_subscribe = get_whether_to_subscribe( subscribe ); fc::variants result; result.reserve(ids.size()); std::transform(ids.begin(), ids.end(), std::back_inserter(result), - [this](object_id_type id) -> fc::variant { + [this,to_subscribe](object_id_type id) -> fc::variant { if(auto obj = _db.find_object(id)) + { + if( to_subscribe && !id.is() && !id.is() ) + this->subscribe_to_item( id ); return obj->to_variant(); + } return {}; }); @@ -834,21 +846,24 @@ account_id_type database_api::get_account_id_from_string(const std::string& name return my->get_account_from_string( name_or_id )->id; } -vector> database_api::get_accounts(const vector& account_names_or_ids)const +vector> database_api::get_accounts( const vector& account_names_or_ids, + optional subscribe )const { - return my->get_accounts( account_names_or_ids ); + return my->get_accounts( account_names_or_ids, subscribe ); } -vector> database_api_impl::get_accounts(const vector& account_names_or_ids)const +vector> database_api_impl::get_accounts( const vector& account_names_or_ids, + optional subscribe )const { + bool to_subscribe = get_whether_to_subscribe( subscribe ); vector> result; result.reserve(account_names_or_ids.size()); std::transform(account_names_or_ids.begin(), account_names_or_ids.end(), std::back_inserter(result), - [this](std::string id_or_name) -> optional { + [this,to_subscribe](std::string id_or_name) -> optional { const account_object *account = get_account_from_string(id_or_name, false); if(account == nullptr) return {}; - if( _enabled_auto_subscription ) + if( to_subscribe ) subscribe_to_item( account->id ); return *account; }); @@ -924,7 +939,7 @@ vector database_api_impl::get_account_limit_orders( const st } } else - { + { // if reach here start_price must be valid lower_itr = index_by_account.lower_bound(std::make_tuple(account->id, *ostart_price)); } @@ -941,18 +956,22 @@ vector database_api_impl::get_account_limit_orders( const st return results; } -std::map database_api::get_full_accounts( const vector& names_or_ids, bool subscribe ) +std::map database_api::get_full_accounts( const vector& names_or_ids, + optional subscribe ) { return my->get_full_accounts( names_or_ids, subscribe ); } -std::map database_api_impl::get_full_accounts( const vector& names_or_ids, bool subscribe) +std::map database_api_impl::get_full_accounts( const vector& names_or_ids, + optional subscribe ) { FC_ASSERT( names_or_ids.size() <= _app_options->api_limit_get_full_accounts ); const auto& proposal_idx = _db.get_index_type< primary_index< proposal_index > >(); const auto& proposals_by_account = proposal_idx.get_secondary_index(); + bool to_subscribe = get_whether_to_subscribe( subscribe ); + std::map results; for (const std::string& account_name_or_id : names_or_ids) @@ -961,7 +980,7 @@ std::map database_api_impl::get_full_accounts( const if (account == nullptr) continue; - if( subscribe ) + if( to_subscribe ) { if(_subscribed_accounts.size() < 100) { _subscribed_accounts.insert( account->get_id() ); @@ -1162,12 +1181,16 @@ vector> database_api_impl::lookup_account_names(const v return result; } -map database_api::lookup_accounts(const string& lower_bound_name, uint32_t limit)const +map database_api::lookup_accounts( const string& lower_bound_name, + uint32_t limit, + optional subscribe )const { - return my->lookup_accounts( lower_bound_name, limit ); + return my->lookup_accounts( lower_bound_name, limit, subscribe ); } -map database_api_impl::lookup_accounts(const string& lower_bound_name, uint32_t limit)const +map database_api_impl::lookup_accounts( const string& lower_bound_name, + uint32_t limit, + optional subscribe )const { FC_ASSERT( limit <= 1000 ); const auto& accounts_by_name = _db.get_index_type().indices().get(); @@ -1175,8 +1198,8 @@ map database_api_impl::lookup_accounts(const string& low if( limit == 0 ) // shortcut to save a database query return result; - - bool to_subscribe = (limit == 1 && _enabled_auto_subscription); // auto-subscribe if only look for one account + // auto-subscribe if only look for one account + bool to_subscribe = (limit == 1 && get_whether_to_subscribe( subscribe )); for( auto itr = accounts_by_name.lower_bound(lower_bound_name); limit-- && itr != accounts_by_name.end(); ++itr ) @@ -1317,21 +1340,24 @@ asset_id_type database_api::get_asset_id_from_string(const std::string& symbol_o return my->get_asset_from_string( symbol_or_id )->id; } -vector> database_api::get_assets(const vector& asset_symbols_or_ids)const +vector> database_api::get_assets( const vector& asset_symbols_or_ids, + optional subscribe )const { - return my->get_assets( asset_symbols_or_ids ); + return my->get_assets( asset_symbols_or_ids, subscribe ); } -vector> database_api_impl::get_assets(const vector& asset_symbols_or_ids)const +vector> database_api_impl::get_assets(const vector& asset_symbols_or_ids, + optional subscribe )const { + bool to_subscribe = get_whether_to_subscribe( subscribe ); vector> result; result.reserve(asset_symbols_or_ids.size()); std::transform(asset_symbols_or_ids.begin(), asset_symbols_or_ids.end(), std::back_inserter(result), - [this](std::string id_or_name) -> optional { + [this,to_subscribe](std::string id_or_name) -> optional { const asset_object* asset_obj = get_asset_from_string( id_or_name, false ); if( asset_obj == nullptr ) return {}; - if( _enabled_auto_subscription ) + if( to_subscribe ) subscribe_to_item( asset_obj->id ); return extend_asset( *asset_obj ); }); @@ -2377,7 +2403,7 @@ bool database_api::verify_account_authority( const string& account_name_or_id, c return my->verify_account_authority( account_name_or_id, signers ); } -bool database_api_impl::verify_account_authority( const string& account_name_or_id, +bool database_api_impl::verify_account_authority( const string& account_name_or_id, const flat_set& keys )const { // create a dummy transfer @@ -2392,7 +2418,7 @@ bool database_api_impl::verify_account_authority( const string& account_name_or_ [this]( account_id_type id ){ return &id(_db).active; }, [this]( account_id_type id ){ return &id(_db).owner; }, true ); - } + } catch (fc::exception& ex) { return false; @@ -2606,14 +2632,14 @@ vector database_api_impl::get_withdraw_permissions_b // // ////////////////////////////////////////////////////////////////////// -optional database_api::get_htlc(htlc_id_type id)const +optional database_api::get_htlc( htlc_id_type id, optional subscribe )const { - return my->get_htlc(id); + return my->get_htlc( id, subscribe ); } -fc::optional database_api_impl::get_htlc(htlc_id_type id) const +fc::optional database_api_impl::get_htlc( htlc_id_type id, optional subscribe )const { - auto obj = get_objects( { id }).front(); + auto obj = get_objects( { id }, subscribe ).front(); if ( !obj.is_null() ) { return fc::optional(obj.template as(GRAPHENE_MAX_NESTED_OBJECTS)); diff --git a/libraries/app/include/graphene/app/database_api.hpp b/libraries/app/include/graphene/app/database_api.hpp index af48fe2de9..be126e5348 100644 --- a/libraries/app/include/graphene/app/database_api.hpp +++ b/libraries/app/include/graphene/app/database_api.hpp @@ -156,11 +156,14 @@ class database_api /** * @brief Get the objects corresponding to the provided IDs * @param ids IDs of the objects to retrieve + * @param subscribe @a true to subscribe to the queried objects; @a false to not subscribe; + * @a null to subscribe or not subscribe according to current auto-subscription setting + * (see @ref set_auto_subscription) * @return The objects retrieved, in the order they are mentioned in ids * * If any of the provided IDs does not map to an object, a null variant is returned in its position. */ - fc::variants get_objects(const vector& ids)const; + fc::variants get_objects( const vector& ids, optional subscribe = optional() )const; /////////////////// // Subscriptions // @@ -187,9 +190,12 @@ class database_api * - get_assets * - get_objects * - lookup_accounts - * - * Does not impact this API: * - get_full_accounts + * - get_htlc + * + * Note: auto-subscription is enabled by default + * + * @see @ref set_subscribe_callback */ void set_auto_subscription( bool enable ); /** @@ -321,16 +327,22 @@ class database_api /** * @brief Get a list of accounts by names or IDs * @param account_names_or_ids names or IDs of the accounts to retrieve + * @param subscribe @a true to subscribe to the queried account objects; @a false to not subscribe; + * @a null to subscribe or not subscribe according to current auto-subscription setting + * (see @ref set_auto_subscription) * @return The accounts corresponding to the provided names or IDs * * This function has semantics identical to @ref get_objects */ - vector> get_accounts(const vector& account_names_or_ids)const; + vector> get_accounts( const vector& account_names_or_ids, + optional subscribe = optional() )const; /** * @brief Fetch all objects relevant to the specified accounts and optionally subscribe to updates * @param names_or_ids Each item must be the name or ID of an account to retrieve - * @param subscribe whether subscribe to updates + * @param subscribe @a true to subscribe to the queried full account objects; @a false to not subscribe; + * @a null to subscribe or not subscribe according to current auto-subscription setting + * (see @ref set_auto_subscription) * @return Map of string from @p names_or_ids to the corresponding account * * This function fetches all relevant objects for the given accounts, and subscribes to updates to the given @@ -338,7 +350,8 @@ class database_api * ignored. All other accounts will be retrieved and subscribed. * */ - std::map get_full_accounts( const vector& names_or_ids, bool subscribe ); + std::map get_full_accounts( const vector& names_or_ids, + optional subscribe = optional() ); /** * @brief Get info of an account by name @@ -359,7 +372,7 @@ class database_api * @param account_names Names of the accounts to retrieve * @return The accounts holding the provided names * - * This function has semantics identical to @ref get_objects + * This function has semantics identical to @ref get_objects, but doesn't subscribe. */ vector> lookup_account_names(const vector& account_names)const; @@ -367,9 +380,16 @@ class database_api * @brief Get names and IDs for registered accounts * @param lower_bound_name Lower bound of the first name to return * @param limit Maximum number of results to return -- must not exceed 1000 + * @param subscribe @a true to subscribe to the queried account objects; @a false to not subscribe; + * @a null to subscribe or not subscribe according to current auto-subscription setting + * (see @ref set_auto_subscription) * @return Map of account names to corresponding IDs + * + * Note: this API will subscribe to the queried account only if @p limit is 1. */ - map lookup_accounts(const string& lower_bound_name, uint32_t limit)const; + map lookup_accounts( const string& lower_bound_name, + uint32_t limit, + optional subscribe = optional() )const; ////////////// // Balances // @@ -428,11 +448,15 @@ class database_api /** * @brief Get a list of assets by symbol names or IDs * @param asset_symbols_or_ids symbol names or IDs of the assets to retrieve + * @param subscribe @a true to subscribe to the queried asset objects; @a false to not subscribe; + * @a null to subscribe or not subscribe according to current auto-subscription setting + * (see @ref set_auto_subscription) * @return The assets corresponding to the provided symbol names or IDs * * This function has semantics identical to @ref get_objects */ - vector> get_assets(const vector& asset_symbols_or_ids)const; + vector> get_assets( const vector& asset_symbols_or_ids, + optional subscribe = optional() )const; /** * @brief Get assets alphabetically by symbol name @@ -658,7 +682,7 @@ class database_api * @param witness_ids IDs of the witnesses to retrieve * @return The witnesses corresponding to the provided IDs * - * This function has semantics identical to @ref get_objects + * This function has semantics identical to @ref get_objects, but doesn't subscribe */ vector> get_witnesses(const vector& witness_ids)const; @@ -691,7 +715,7 @@ class database_api * @param committee_member_ids IDs of the committee_members to retrieve * @return The committee_members corresponding to the provided IDs * - * This function has semantics identical to @ref get_objects + * This function has semantics identical to @ref get_objects, but doesn't subscribe */ vector> get_committee_members( const vector& committee_member_ids)const; @@ -898,9 +922,12 @@ class database_api /** * @brief Get HTLC object * @param id HTLC contract id + * @param subscribe @a true to subscribe to the queried HTLC objects; @a false to not subscribe; + * @a null to subscribe or not subscribe according to current auto-subscription setting + * (see @ref set_auto_subscription) * @return HTLC object for the id */ - optional get_htlc(htlc_id_type id) const; + optional get_htlc( htlc_id_type id, optional subscribe = optional() ) const; /** * @brief Get non expired HTLC objects using the sender account diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index 7c19bb94fe..b97cb67d5b 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -588,7 +588,7 @@ class wallet_api_impl template graphene::db::object_downcast_t get_object(ID id)const { - auto ob = _remote_db->get_objects({id}).front(); + auto ob = _remote_db->get_objects({id}, {}).front(); return ob.template as>( GRAPHENE_MAX_NESTED_OBJECTS ); } @@ -680,7 +680,7 @@ class wallet_api_impl { std::string account_id = account_id_to_string(id); - auto rec = _remote_db->get_accounts({account_id}).front(); + auto rec = _remote_db->get_accounts({account_id}, {}).front(); FC_ASSERT(rec); return *rec; } @@ -711,7 +711,7 @@ class wallet_api_impl } optional find_asset(asset_id_type id)const { - auto rec = _remote_db->get_assets({asset_id_to_string(id)}).front(); + auto rec = _remote_db->get_assets({asset_id_to_string(id)}, {}).front(); return rec; } optional find_asset(string asset_symbol_or_id)const @@ -750,7 +750,7 @@ class wallet_api_impl { htlc_id_type id; fc::from_variant(htlc_id, id); - auto obj = _remote_db->get_objects( { id }).front(); + auto obj = _remote_db->get_objects( { id }, {}).front(); if ( !obj.is_null() ) { return fc::optional(obj.template as(GRAPHENE_MAX_NESTED_OBJECTS)); @@ -862,7 +862,7 @@ class wallet_api_impl account_ids_to_send.push_back( account_id ); ++it; } - std::vector< optional< account_object > > accounts = _remote_db->get_accounts(account_ids_to_send); + std::vector< optional< account_object > > accounts = _remote_db->get_accounts(account_ids_to_send, {}); // server response should be same length as request FC_ASSERT( accounts.size() == account_ids_to_send.size() ); size_t i = 0; @@ -1842,7 +1842,7 @@ class wallet_api_impl flat_set new_votes( acct.options.votes ); - fc::variants objects = _remote_db->get_objects( query_ids ); + fc::variants objects = _remote_db->get_objects( query_ids, {} ); for( const variant& obj : objects ) { worker_object wo; @@ -3352,7 +3352,7 @@ vector wallet_api::list_my_accounts() map wallet_api::list_accounts(const string& lowerbound, uint32_t limit) { - return my->_remote_db->lookup_accounts(lowerbound, limit); + return my->_remote_db->lookup_accounts(lowerbound, limit, {}); } vector wallet_api::list_account_balances(const string& id) @@ -3653,7 +3653,7 @@ string wallet_api::serialize_transaction( signed_transaction tx )const variant wallet_api::get_object( object_id_type id ) const { - return my->_remote_db->get_objects({id}); + return my->_remote_db->get_objects({id}, {}); } string wallet_api::get_wallet_filename() const From 202eb0b4e9699bc125bb9ee3f00b55d894068263 Mon Sep 17 00:00:00 2001 From: abitmore Date: Thu, 8 Aug 2019 17:52:52 -0400 Subject: [PATCH 067/111] Add test case for optional subscription --- tests/tests/database_api_tests.cpp | 80 ++++++++++++++++++++++++++---- 1 file changed, 70 insertions(+), 10 deletions(-) diff --git a/tests/tests/database_api_tests.cpp b/tests/tests/database_api_tests.cpp index 4b1d2b6b32..a3ddeb16fa 100644 --- a/tests/tests/database_api_tests.cpp +++ b/tests/tests/database_api_tests.cpp @@ -791,8 +791,13 @@ BOOST_AUTO_TEST_CASE( subscription_notification_test ) create_user_issued_asset( "UIATEST" ); -#define SUB_NOTIF_TEST_NUM_CALLBACKS_PLUS_ONE 8 +// declare db_api1 ~ db_api60 +#define SUB_NOTIF_TEST_NUM_CALLBACKS_PLUS_ONE 61 +// db_api1 ~ db_api30 auto-subscribe in the beginning, +// db_api31 ~ db_api60 don't auto-subscribe +#define SUB_NOTIF_TEST_START_ID_DISABLE_AUTO_SUB 31 +// create callback functions #define SUB_NOTIF_TEST_INIT_CALLBACKS(z, i, data) \ uint32_t objects_changed ## i = 0; \ auto callback ## i = [&]( const variant& v ) \ @@ -802,6 +807,7 @@ BOOST_AUTO_TEST_CASE( subscription_notification_test ) }; \ uint32_t expected_objects_changed ## i = 0; +// create function to check results #define SUB_NOTIF_TEST_CHECK(z, i, data) \ if( expected_objects_changed ## i > 0 ) { \ BOOST_CHECK_LE( expected_objects_changed ## i, objects_changed ## i ); \ @@ -834,6 +840,7 @@ BOOST_AUTO_TEST_CASE( subscription_notification_test ) graphene::app::database_api db_api2( db, &opt ); db_api2.set_subscribe_callback( callback2, true ); // subscribing to all should succeed +// declare the rest of API callers and initialize callbacks #define SUB_NOTIF_TEST_INIT_APIS(z, i, data) \ graphene::app::database_api db_api ## i( db, &opt ); \ db_api ## i.set_subscribe_callback( callback ## i, false ); @@ -841,32 +848,75 @@ BOOST_AUTO_TEST_CASE( subscription_notification_test ) BOOST_PP_REPEAT_FROM_TO( 3, SUB_NOTIF_TEST_NUM_CALLBACKS_PLUS_ONE, SUB_NOTIF_TEST_INIT_APIS, unused ); #undef SUB_NOTIF_TEST_INIT_APIS + +// disable auto-subscription for some API callers +#define SUB_NOTIF_TEST_DISABLE_AUTO_SUB(z, i, data) \ + db_api ## i.set_auto_subscription( false ); + + BOOST_PP_REPEAT_FROM_TO( SUB_NOTIF_TEST_START_ID_DISABLE_AUTO_SUB, SUB_NOTIF_TEST_NUM_CALLBACKS_PLUS_ONE, + SUB_NOTIF_TEST_DISABLE_AUTO_SUB, unused ); + +#undef SUB_NOTIF_TEST_DISABLE_AUTO_SUB #undef SUB_NOTIF_TEST_NUM_CALLBACKS_PLUS_ONE +#undef SUB_NOTIF_TEST_START_ID_DISABLE_AUTO_SUB vector account_ids; account_ids.push_back( alice_id ); - db_api1.get_objects( account_ids ); // db_api1 subscribe to Alice + db_api1.get_objects( account_ids ); // db_api1 subscribe to Alice + db_api11.get_objects( account_ids, true ); // db_api11 subscribe to Alice + db_api21.get_objects( account_ids, false ); // db_api21 doesn't subscribe to Alice + db_api31.get_objects( account_ids ); // db_api31 doesn't subscribe to Alice + db_api41.get_objects( account_ids, true ); // db_api41 subscribe to Alice + db_api51.get_objects( account_ids, false ); // db_api51 doesn't subscribe to Alice vector account_names; account_names.push_back( "alice" ); - db_api4.get_accounts( account_names ); // db_api4 subscribe to Alice - - db_api5.lookup_accounts( "ali", 1 ); // db_api5 subscribe to Alice - - db_api6.lookup_accounts( "alice", 3 ); // db_api6 does not subscribe to Alice + db_api4.get_accounts( account_names ); // db_api4 subscribe to Alice + db_api14.get_accounts( account_names, true ); // db_api14 subscribe to Alice + db_api24.get_accounts( account_names, false ); // db_api24 doesn't subscribe to Alice + db_api34.get_accounts( account_names ); // db_api34 doesn't subscribe to Alice + db_api44.get_accounts( account_names, true ); // db_api44 subscribe to Alice + db_api54.get_accounts( account_names, false ); // db_api54 doesn't subscribe to Alice + + db_api5.lookup_accounts( "ali", 1 ); // db_api5 subscribe to Alice + db_api15.lookup_accounts( "ali", 1, true ); // db_api15 subscribe to Alice + db_api25.lookup_accounts( "ali", 1, false ); // db_api25 doesn't subscribe to Alice + db_api35.lookup_accounts( "ali", 1 ); // db_api35 doesn't subscribe to Alice + db_api45.lookup_accounts( "ali", 1, true ); // db_api45 subscribe to Alice + db_api55.lookup_accounts( "ali", 1, false ); // db_api55 doesn't subscribe to Alice + + db_api6.lookup_accounts( "alice", 3 ); // db_api6 does not subscribe to Alice + db_api16.lookup_accounts( "alice", 3, true ); // db_api16 does not subscribe to Alice + db_api26.lookup_accounts( "alice", 3, false ); // db_api26 does not subscribe to Alice + db_api36.lookup_accounts( "alice", 3 ); // db_api36 does not subscribe to Alice + db_api46.lookup_accounts( "alice", 3, true ); // db_api46 does not subscribe to Alice + db_api56.lookup_accounts( "alice", 3, false ); // db_api56 does not subscribe to Alice vector asset_names; asset_names.push_back( "UIATEST" ); - db_api7.get_assets( asset_names ); // db_api7 subscribe to UIA + db_api7.get_assets( asset_names ); // db_api7 subscribe to UIA + db_api17.get_assets( asset_names, true ); // db_api17 subscribe to UIA + db_api27.get_assets( asset_names, false ); // db_api27 doesn't subscribe to UIA + db_api37.get_assets( asset_names ); // db_api37 doesn't subscribe to UIA + db_api47.get_assets( asset_names, true ); // db_api47 subscribe to UIA + db_api57.get_assets( asset_names, false ); // db_api57 doesn't subscribe to UIA generate_block(); ++expected_objects_changed1; // db_api1 subscribed to Alice, notify Alice account creation + ++expected_objects_changed11; // db_api11 subscribed to Alice, notify Alice account creation + ++expected_objects_changed41; // db_api41 subscribed to Alice, notify Alice account creation ++expected_objects_changed2; // db_api2 subscribed to all, notify new objects // db_api3 didn't subscribe to anything, nothing would be notified ++expected_objects_changed4; // db_api4 subscribed to Alice, notify Alice account creation + ++expected_objects_changed14; // db_api14 subscribed to Alice, notify Alice account creation + ++expected_objects_changed44; // db_api44 subscribed to Alice, notify Alice account creation ++expected_objects_changed5; // db_api5 subscribed to Alice, notify Alice account creation - // db_api6 didn't subscribe to anything, nothing would be notified + ++expected_objects_changed15; // db_api15 subscribed to Alice, notify Alice account creation + ++expected_objects_changed45; // db_api45 subscribed to Alice, notify Alice account creation + // db_api*6 didn't subscribe to anything, nothing would be notified ++expected_objects_changed7; // db_api7 subscribed to UIA, notify asset creation + ++expected_objects_changed17; // db_api17 subscribed to UIA, notify asset creation + ++expected_objects_changed47; // db_api47 subscribed to UIA, notify asset creation fc::usleep(fc::milliseconds(200)); // sleep a while to execute callback in another thread check_results(); @@ -889,7 +939,13 @@ BOOST_AUTO_TEST_CASE( subscription_notification_test ) obj_ids.push_back( db.get_dynamic_global_properties().id ); db_api3.get_objects( obj_ids ); // db_api3 subscribe to dynamic global properties - db_api4.get_full_accounts( account_names, true ); // db_api4 subscribe to Alice with get_full_accounts + db_api4.get_full_accounts( account_names, true ); // db_api4 subscribe to Alice with get_full_accounts + db_api14.get_full_accounts( account_names, false ); // db_api14 doesn't subscribe + db_api24.get_full_accounts( account_names ); // db_api24 subscribe to Alice with get_full_accounts + db_api34.get_full_accounts( account_names, true ); // db_api34 subscribe to Alice with get_full_accounts + db_api44.get_full_accounts( account_names, false ); // db_api44 doesn't subscribe + db_api54.get_full_accounts( account_names ); // db_api54 doesn't subscribe + db_api5.get_full_accounts( account_names, false ); // db_api5 doesn't subscribe transfer( account_id_type(), alice_id, asset(1) ); @@ -899,6 +955,8 @@ BOOST_AUTO_TEST_CASE( subscription_notification_test ) ++expected_objects_changed2; // db_api2 subscribed to all, notify new history records and etc ++expected_objects_changed3; // db_api3 subscribed to dynamic global properties, would be notified ++expected_objects_changed4; // db_api4 subscribed to full account data of Alice, would be notified + ++expected_objects_changed24; // db_api24 subscribed to full account data of Alice, would be notified + ++expected_objects_changed34; // db_api34 subscribed to full account data of Alice, would be notified // db_api5 only subscribed to the account object of Alice, nothing notified // db_api6 didn't subscribe to anything, nothing would be notified // db_api7: no change on UIA, nothing would be notified @@ -969,6 +1027,8 @@ BOOST_AUTO_TEST_CASE( subscription_notification_test ) ++expected_objects_changed2; // db_api2 subscribed to all, notify new history records and etc ++expected_objects_changed3; // db_api3 subscribed to dynamic global properties, would be notified ++expected_objects_changed4; // db_api4 subscribed to full account data of Alice, would be notified + ++expected_objects_changed24; // db_api24 subscribed to full account data of Alice, would be notified + ++expected_objects_changed34; // db_api34 subscribed to full account data of Alice, would be notified // db_api5 subscribed to anything, nothing notified // db_api6 subscribed to anything, nothing notified // db_api7: no change on UIA, nothing would be notified From bf448629221ca4daa4cd01ab4de7b628030cde03 Mon Sep 17 00:00:00 2001 From: abitmore Date: Thu, 8 Aug 2019 18:48:55 -0400 Subject: [PATCH 068/111] Move some functions from htlc_tests to db_fixture --- tests/common/database_fixture.cpp | 77 +++++++++++++++++++++++++ tests/common/database_fixture.hpp | 20 +++++++ tests/tests/htlc_tests.cpp | 95 +------------------------------ 3 files changed, 99 insertions(+), 93 deletions(-) diff --git a/tests/common/database_fixture.cpp b/tests/common/database_fixture.cpp index 1b3a5fccbf..ae3e074f4a 100644 --- a/tests/common/database_fixture.cpp +++ b/tests/common/database_fixture.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include @@ -1346,6 +1347,82 @@ vector< graphene::market_history::order_history_object > database_fixture::get_m return result; } +flat_map< uint64_t, graphene::chain::fee_parameters > database_fixture::get_htlc_fee_parameters() +{ + flat_map ret_val; + + htlc_create_operation::fee_parameters_type create_param; + create_param.fee_per_day = 2 * GRAPHENE_BLOCKCHAIN_PRECISION; + create_param.fee = 2 * GRAPHENE_BLOCKCHAIN_PRECISION; + ret_val[((operation)htlc_create_operation()).which()] = create_param; + + htlc_redeem_operation::fee_parameters_type redeem_param; + redeem_param.fee = 2 * GRAPHENE_BLOCKCHAIN_PRECISION; + redeem_param.fee_per_kb = 2 * GRAPHENE_BLOCKCHAIN_PRECISION; + ret_val[((operation)htlc_redeem_operation()).which()] = redeem_param; + + htlc_extend_operation::fee_parameters_type extend_param; + extend_param.fee = 2 * GRAPHENE_BLOCKCHAIN_PRECISION; + extend_param.fee_per_day = 2 * GRAPHENE_BLOCKCHAIN_PRECISION; + ret_val[((operation)htlc_extend_operation()).which()] = extend_param; + + return ret_val; +} + +void database_fixture::set_htlc_committee_parameters() +{ + // htlc fees + // get existing fee_schedule + const chain_parameters& existing_params = db.get_global_properties().parameters; + const fee_schedule_type& existing_fee_schedule = *(existing_params.current_fees); + // create a new fee_shedule + std::shared_ptr new_fee_schedule = std::make_shared(); + new_fee_schedule->scale = GRAPHENE_100_PERCENT; + // replace the old with the new + flat_map params_map = get_htlc_fee_parameters(); + for(auto param : existing_fee_schedule.parameters) + { + auto itr = params_map.find(param.which()); + if (itr == params_map.end()) + new_fee_schedule->parameters.insert(param); + else + { + new_fee_schedule->parameters.insert( (*itr).second); + } + } + // htlc parameters + proposal_create_operation cop = proposal_create_operation::committee_proposal( + db.get_global_properties().parameters, db.head_block_time()); + cop.fee_paying_account = GRAPHENE_TEMP_ACCOUNT; + cop.expiration_time = db.head_block_time() + *cop.review_period_seconds + 10; + committee_member_update_global_parameters_operation uop; + graphene::chain::htlc_options new_params; + new_params.max_preimage_size = 19200; + new_params.max_timeout_secs = 60 * 60 * 24 * 28; + uop.new_parameters.extensions.value.updatable_htlc_options = new_params; + uop.new_parameters.current_fees = new_fee_schedule; + cop.proposed_ops.emplace_back(uop); + + trx.operations.push_back(cop); + graphene::chain::processed_transaction proc_trx = db.push_transaction(trx); + trx.clear(); + proposal_id_type good_proposal_id = proc_trx.operation_results[0].get(); + + proposal_update_operation puo; + puo.proposal = good_proposal_id; + puo.fee_paying_account = GRAPHENE_TEMP_ACCOUNT; + puo.key_approvals_to_add.emplace( init_account_priv_key.get_public_key() ); + trx.operations.push_back(puo); + sign( trx, init_account_priv_key ); + db.push_transaction(trx); + trx.clear(); + + generate_blocks( good_proposal_id( db ).expiration_time + 5 ); + generate_blocks( db.get_dynamic_global_properties().next_maintenance_time ); + generate_block(); // get the maintenance skip slots out of the way + +} + namespace test { void set_expiration( const database& db, transaction& tx ) diff --git a/tests/common/database_fixture.hpp b/tests/common/database_fixture.hpp index 5368ce018b..eeecdcb5a6 100644 --- a/tests/common/database_fixture.hpp +++ b/tests/common/database_fixture.hpp @@ -371,6 +371,26 @@ struct database_fixture { vector< operation_history_object > get_operation_history( account_id_type account_id )const; vector< graphene::market_history::order_history_object > get_market_order_history( asset_id_type a, asset_id_type b )const; + + /**** + * @brief return htlc fee parameters + */ + flat_map< uint64_t, graphene::chain::fee_parameters > get_htlc_fee_parameters(); + /**** + * @brief push through a proposal that sets htlc parameters and fees + */ + void set_htlc_committee_parameters(); + /**** + * Hash the preimage and put it in a vector + * @param preimage the preimage + * @returns a vector that cointains the sha256 hash of the preimage + */ + template + H hash_it(std::vector preimage) + { + return H::hash( (char*)preimage.data(), preimage.size() ); + } + }; namespace test { diff --git a/tests/tests/htlc_tests.cpp b/tests/tests/htlc_tests.cpp index 6ade964236..fefdc546cd 100644 --- a/tests/tests/htlc_tests.cpp +++ b/tests/tests/htlc_tests.cpp @@ -63,102 +63,11 @@ void generate_random_preimage(uint16_t key_size, std::vector& vec) return; } -/**** - * Hash the preimage and put it in a vector - * @param preimage the preimage - * @returns a vector that cointains the sha256 hash of the preimage - */ -template -H hash_it(std::vector preimage) -{ - return H::hash( (char*)preimage.data(), preimage.size() ); -} - -flat_map< uint64_t, graphene::chain::fee_parameters > get_htlc_fee_parameters() -{ - flat_map ret_val; - - htlc_create_operation::fee_parameters_type create_param; - create_param.fee_per_day = 2 * GRAPHENE_BLOCKCHAIN_PRECISION; - create_param.fee = 2 * GRAPHENE_BLOCKCHAIN_PRECISION; - ret_val[((operation)htlc_create_operation()).which()] = create_param; - - htlc_redeem_operation::fee_parameters_type redeem_param; - redeem_param.fee = 2 * GRAPHENE_BLOCKCHAIN_PRECISION; - redeem_param.fee_per_kb = 2 * GRAPHENE_BLOCKCHAIN_PRECISION; - ret_val[((operation)htlc_redeem_operation()).which()] = redeem_param; - - htlc_extend_operation::fee_parameters_type extend_param; - extend_param.fee = 2 * GRAPHENE_BLOCKCHAIN_PRECISION; - extend_param.fee_per_day = 2 * GRAPHENE_BLOCKCHAIN_PRECISION; - ret_val[((operation)htlc_extend_operation()).which()] = extend_param; - - return ret_val; -} - -/**** - * @brief push through a proposal that sets htlc parameters and fees - * @param db_fixture the database connection - */ -void set_committee_parameters(database_fixture* db_fixture) -{ - // htlc fees - // get existing fee_schedule - const chain_parameters& existing_params = db_fixture->db.get_global_properties().parameters; - const fee_schedule_type& existing_fee_schedule = *(existing_params.current_fees); - // create a new fee_shedule - std::shared_ptr new_fee_schedule = std::make_shared(); - new_fee_schedule->scale = GRAPHENE_100_PERCENT; - // replace the old with the new - flat_map params_map = get_htlc_fee_parameters(); - for(auto param : existing_fee_schedule.parameters) - { - auto itr = params_map.find(param.which()); - if (itr == params_map.end()) - new_fee_schedule->parameters.insert(param); - else - { - new_fee_schedule->parameters.insert( (*itr).second); - } - } - // htlc parameters - proposal_create_operation cop = proposal_create_operation::committee_proposal( - db_fixture->db.get_global_properties().parameters, db_fixture->db.head_block_time()); - cop.fee_paying_account = GRAPHENE_TEMP_ACCOUNT; - cop.expiration_time = db_fixture->db.head_block_time() + *cop.review_period_seconds + 10; - committee_member_update_global_parameters_operation uop; - graphene::chain::htlc_options new_params; - new_params.max_preimage_size = 19200; - new_params.max_timeout_secs = 60 * 60 * 24 * 28; - uop.new_parameters.extensions.value.updatable_htlc_options = new_params; - uop.new_parameters.current_fees = new_fee_schedule; - cop.proposed_ops.emplace_back(uop); - - db_fixture->trx.operations.push_back(cop); - graphene::chain::processed_transaction proc_trx =db_fixture->db.push_transaction(db_fixture->trx); - db_fixture->trx.clear(); - proposal_id_type good_proposal_id = proc_trx.operation_results[0].get(); - - proposal_update_operation puo; - puo.proposal = good_proposal_id; - puo.fee_paying_account = GRAPHENE_TEMP_ACCOUNT; - puo.key_approvals_to_add.emplace( db_fixture->init_account_priv_key.get_public_key() ); - db_fixture->trx.operations.push_back(puo); - db_fixture->sign( db_fixture->trx, db_fixture->init_account_priv_key ); - db_fixture->db.push_transaction(db_fixture->trx); - db_fixture->trx.clear(); - - db_fixture->generate_blocks( good_proposal_id( db_fixture->db ).expiration_time + 5 ); - db_fixture->generate_blocks( db_fixture->db.get_dynamic_global_properties().next_maintenance_time ); - db_fixture->generate_block(); // get the maintenance skip slots out of the way - -} - void advance_past_hardfork(database_fixture* db_fixture) { db_fixture->generate_blocks(HARDFORK_CORE_1468_TIME); set_expiration(db_fixture->db, db_fixture->trx); - set_committee_parameters(db_fixture); + db_fixture->set_htlc_committee_parameters(); set_expiration(db_fixture->db, db_fixture->trx); } @@ -844,7 +753,7 @@ try { generate_blocks(HARDFORK_CORE_1468_TIME); set_expiration( db, trx ); - set_committee_parameters(this); + set_htlc_committee_parameters(); uint16_t preimage_size = 256; std::vector pre_image(256); From 8d0e8607b8d79d54cf34680f051ce7b2627a0310 Mon Sep 17 00:00:00 2001 From: abitmore Date: Thu, 8 Aug 2019 18:53:55 -0400 Subject: [PATCH 069/111] Add test case for get_htlc optional subscription --- tests/tests/database_api_tests.cpp | 44 ++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/tests/tests/database_api_tests.cpp b/tests/tests/database_api_tests.cpp index a3ddeb16fa..9304fa4b09 100644 --- a/tests/tests/database_api_tests.cpp +++ b/tests/tests/database_api_tests.cpp @@ -787,10 +787,43 @@ BOOST_AUTO_TEST_CASE( subscription_key_collision_test ) BOOST_AUTO_TEST_CASE( subscription_notification_test ) { try { + + generate_blocks(HARDFORK_CORE_1468_TIME); + set_expiration( db, trx ); + set_htlc_committee_parameters(); + generate_block(); + set_expiration( db, trx ); + ACTORS( (alice)(bob) ); create_user_issued_asset( "UIATEST" ); + // prepare data for get_htlc + { + int64_t init_balance(100 * GRAPHENE_BLOCKCHAIN_PRECISION); + transfer( committee_account, alice_id, graphene::chain::asset(init_balance) ); + + uint16_t preimage_size = 256; + std::vector pre_image(256); + std::independent_bits_engine rbe; + std::generate(begin(pre_image), end(pre_image), std::ref(rbe)); + + // alice puts a htlc contract to bob + graphene::chain::htlc_create_operation create_operation; + BOOST_TEST_MESSAGE("Alice, who has 100 coins, is transferring 3 coins to Bob"); + create_operation.amount = graphene::chain::asset( 3 * GRAPHENE_BLOCKCHAIN_PRECISION ); + create_operation.to = bob_id; + create_operation.claim_period_seconds = 60; + create_operation.preimage_hash = hash_it( pre_image ); + create_operation.preimage_size = preimage_size; + create_operation.from = alice_id; + create_operation.fee = db.get_global_properties().parameters.current_fees->calculate_fee(create_operation); + trx.operations.push_back(create_operation); + sign(trx, alice_private_key); + PUSH_TX(db, trx, ~0); + trx.clear(); + } + // declare db_api1 ~ db_api60 #define SUB_NOTIF_TEST_NUM_CALLBACKS_PLUS_ONE 61 // db_api1 ~ db_api30 auto-subscribe in the beginning, @@ -901,6 +934,14 @@ BOOST_AUTO_TEST_CASE( subscription_notification_test ) db_api47.get_assets( asset_names, true ); // db_api47 subscribe to UIA db_api57.get_assets( asset_names, false ); // db_api57 doesn't subscribe to UIA + graphene::chain::htlc_id_type alice_htlc_id_bob; // assuming ID of the first htlc object is 0 + db_api8.get_htlc( alice_htlc_id_bob ); // db_api8 subscribe to the HTLC object + db_api18.get_htlc( alice_htlc_id_bob, true ); // db_api18 subscribe to the HTLC object + db_api28.get_htlc( alice_htlc_id_bob, false ); // db_api28 doesn't subscribe to the HTLC object + db_api38.get_htlc( alice_htlc_id_bob ); // db_api38 doesn't subscribe to the HTLC object + db_api48.get_htlc( alice_htlc_id_bob, true ); // db_api48 subscribe to the HTLC object + db_api58.get_htlc( alice_htlc_id_bob, false ); // db_api58 doesn't subscribe to the HTLC object + generate_block(); ++expected_objects_changed1; // db_api1 subscribed to Alice, notify Alice account creation ++expected_objects_changed11; // db_api11 subscribed to Alice, notify Alice account creation @@ -917,6 +958,9 @@ BOOST_AUTO_TEST_CASE( subscription_notification_test ) ++expected_objects_changed7; // db_api7 subscribed to UIA, notify asset creation ++expected_objects_changed17; // db_api17 subscribed to UIA, notify asset creation ++expected_objects_changed47; // db_api47 subscribed to UIA, notify asset creation + ++expected_objects_changed8; // db_api8 subscribed to HTLC object, notify object creation + ++expected_objects_changed18; // db_api18 subscribed to HTLC object, notify object creation + ++expected_objects_changed48; // db_api48 subscribed to HTLC object, notify object creation fc::usleep(fc::milliseconds(200)); // sleep a while to execute callback in another thread check_results(); From 5d3632522905dcd1254992d625ee61f830af451b Mon Sep 17 00:00:00 2001 From: Nathan Hourt Date: Thu, 8 Aug 2019 22:40:43 -0500 Subject: [PATCH 070/111] Make Travis use multi-stage build The multi-stage build makes builds more reliable by building only the protocol in the first stage, which reliably passes in time, caching those binaries, and then building the rest and running tests in the second stage, which uses the cache to complete in time as well. --- .travis.yml | 22 ++++++---------------- programs/build_helpers/build_and_test | 15 +++++++++++++++ programs/build_helpers/build_protocol | 10 ++++++++++ 3 files changed, 31 insertions(+), 16 deletions(-) create mode 100755 programs/build_helpers/build_and_test create mode 100755 programs/build_helpers/build_protocol diff --git a/.travis.yml b/.travis.yml index 77e0407a33..bff35d3e29 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,19 +24,9 @@ env: - CCACHE_MAXSIZE=1Gi - CCACHE_SLOPPINESS=include_file_ctime,include_file_mtime,time_macros -script: - - programs/build_helpers/buildstep -s 3500 - - ccache -s - - programs/build_helpers/buildstep Prepare 1 "sed -i '/tests/d' libraries/fc/CMakeLists.txt" - - programs/build_helpers/buildstep cmake 5 "cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_FLAGS=--coverage -DCMAKE_CXX_FLAGS=--coverage -DBoost_USE_STATIC_LIBS=OFF -DCMAKE_CXX_OUTPUT_EXTENSION_REPLACE=ON ." - - programs/build_helpers/buildstep make.cli_wallet 2200 "programs/build_helpers/make_with_sonar bw-output -j 2 cli_wallet witness_node js_operation_serializer get_dev_key network_mapper" - - programs/build_helpers/buildstep make.chain_test 1000 "make -j 2 chain_test" - - programs/build_helpers/buildstep make.cli_test 200 "make -j 2 cli_test" - - programs/build_helpers/buildstep make.perf_test 120 "make -j 2 performance_test" - - set -o pipefail - - programs/build_helpers/buildstep run.chain_test 240 "libraries/fc/tests/run-parallel-tests.sh tests/chain_test" - - programs/build_helpers/buildstep run.cli_test 60 "libraries/fc/tests/run-parallel-tests.sh tests/cli_test" - - 'programs/build_helpers/buildstep prepare.sonar 20 "find libraries/[acdenptuw]*/CMakeFiles/*.dir programs/[cdgjsw]*/CMakeFiles/*.dir -type d | while read d; do gcov -o \"\$d\" \"\${d/CMakeFiles*.dir//}\"/*.cpp; done >/dev/null; programs/build_helpers/set_sonar_branch sonar-project.properties" || true' - - 'programs/build_helpers/buildstep run.sonar 1200 "which sonar-scanner && sonar-scanner" || true' - - programs/build_helpers/buildstep end 0 - - ccache -s +jobs: + include: + - stage: build for cache + script: ./programs/build_helpers/build_protocol + - stage: build and test + script: ./programs/build_helpers/build_and_test diff --git a/programs/build_helpers/build_and_test b/programs/build_helpers/build_and_test new file mode 100755 index 0000000000..5c0d268cb9 --- /dev/null +++ b/programs/build_helpers/build_and_test @@ -0,0 +1,15 @@ +#!/bin/bash + +programs/build_helpers/buildstep -s 3500 +ccache -s +programs/build_helpers/buildstep Prepare 1 "sed -i '/tests/d' libraries/fc/CMakeLists.txt" +programs/build_helpers/buildstep cmake 5 "cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_FLAGS=--coverage -DCMAKE_CXX_FLAGS=--coverage -DBoost_USE_STATIC_LIBS=OFF -DCMAKE_CXX_OUTPUT_EXTENSION_REPLACE=ON ." +programs/build_helpers/buildstep make.everything 2400 "programs/build_helpers/make_with_sonar bw-output -j 2 witness_node chain_test cli_test" +set -o pipefail +programs/build_helpers/buildstep run.chain_test 240 "libraries/fc/tests/run-parallel-tests.sh tests/chain_test" +programs/build_helpers/buildstep run.cli_test 60 "libraries/fc/tests/run-parallel-tests.sh tests/cli_test" +'programs/build_helpers/buildstep prepare.sonar 20 "find libraries/[acdenptuw]*/CMakeFiles/*.dir programs/[cdgjsw]*/CMakeFiles/*.dir -type d -print | while read d; do gcov -o \"\$d\" \"\${d/CMakeFiles*.dir//}\"/*.cpp; done >/dev/null; programs/build_helpers/set_sonar_branch sonar-project.properties" || true' +'programs/build_helpers/buildstep run.sonar 1200 "which sonar-scanner && sonar-scanner" || true' +programs/build_helpers/buildstep end 0 +ccache -s + diff --git a/programs/build_helpers/build_protocol b/programs/build_helpers/build_protocol new file mode 100755 index 0000000000..6307400586 --- /dev/null +++ b/programs/build_helpers/build_protocol @@ -0,0 +1,10 @@ +#!/bin/bash + +programs/build_helpers/buildstep -s 3500 +ccache -s +programs/build_helpers/buildstep Prepare 1 "sed -i '/tests/d' libraries/fc/CMakeLists.txt" +programs/build_helpers/buildstep cmake 5 "cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_FLAGS=--coverage -DCMAKE_CXX_FLAGS=--coverage -DBoost_USE_STATIC_LIBS=OFF -DCMAKE_CXX_OUTPUT_EXTENSION_REPLACE=ON ." +programs/build_helpers/buildstep make.fc 200 "make -j 2 fc" +programs/build_helpers/buildstep make.custom_auths 1000 "make -j 2 graphene_protocol" +programs/build_helpers/buildstep end 0 +ccache -s From d706a6db4cdfd15df4bc8193a8039f8d258b26d3 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Sat, 10 Aug 2019 11:10:22 -0300 Subject: [PATCH 071/111] add api_helper_indexes plugin --- libraries/plugins/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/plugins/README.md b/libraries/plugins/README.md index 18037d6c6e..fe635fbbe4 100644 --- a/libraries/plugins/README.md +++ b/libraries/plugins/README.md @@ -11,6 +11,7 @@ Plugins are optional to run by node operator according to their needs. However, Folder | Name | Description | Category | Status | SpaceID -----------------------------------|--------------------------|-----------------------------------------------------------------------------|----------------|---------------|--------------| [account_history](account_history) | Account History | Save account history data | History | Stable | 4 +[api_helper_indexes](api_helper_indexes) | API Helper Indexes | Provides some helper indexes used by various API calls | History | Stable | [debug_witness](debug_witness) | Debug Witness | Run "what-if" tests | Debug | Stable | [delayed_node](delayed_node) | Delayed Node | Avoid forks by running a several times confirmed and delayed blockchain | Business | Stable | [elasticsearch](elasticsearch) | ElasticSearch Operations | Save account history data into elasticsearch database | History | Experimental | 6 From c04d7eec6641a7d7cdfb376f4c11e607185d025e Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Wed, 17 Jul 2019 17:24:17 -0300 Subject: [PATCH 072/111] improve Doxyfile --- Doxyfile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Doxyfile b/Doxyfile index ebf009e2ff..b0e5d65c97 100644 --- a/Doxyfile +++ b/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = "Bitshares-Core" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = "3.0.1" +PROJECT_NUMBER = "3.3.0" # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a @@ -758,7 +758,7 @@ WARN_LOGFILE = # spaces. # Note: If this tag is empty the current directory is searched. -INPUT = README.md doc/main.dox libraries/chain libraries/chain/db libraries/app libraries/wallet +INPUT = README.md doc/main.dox libraries/chain libraries/db libraries/app libraries/wallet libraries/protocol libraries/net libraries/plugins libraries/fc libraries/utilities libraries/egenesis # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses @@ -778,7 +778,7 @@ INPUT_ENCODING = UTF-8 # *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, # *.qsf, *.as and *.js. -FILE_PATTERNS = +FILE_PATTERNS = *.cpp *.hpp *.hxx # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. @@ -793,7 +793,7 @@ RECURSIVE = YES # Note that relative paths are relative to the directory from which doxygen is # run. -EXCLUDE = +EXCLUDE = libraries/fc/vendor/editline libraries/fc/vendor/secp256k1-zkp libraries/fc/vendor/websocketpp # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded @@ -820,7 +820,7 @@ EXCLUDE_PATTERNS = # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories use the pattern */test/* -EXCLUDE_SYMBOLS = +EXCLUDE_SYMBOLS = boost # The EXAMPLE_PATH tag can be used to specify one or more files or directories # that contain example code fragments that are included (see the \include From 234f64197e2988c55572ab4de2bff2ca5adc155b Mon Sep 17 00:00:00 2001 From: Nathan Hourt Date: Mon, 12 Aug 2019 16:13:00 -0500 Subject: [PATCH 073/111] Update build_and_test Add `set -e` so if any of the commands fail, the script fails --- programs/build_helpers/build_and_test | 1 + 1 file changed, 1 insertion(+) diff --git a/programs/build_helpers/build_and_test b/programs/build_helpers/build_and_test index 5c0d268cb9..7a6b0ebc33 100755 --- a/programs/build_helpers/build_and_test +++ b/programs/build_helpers/build_and_test @@ -1,4 +1,5 @@ #!/bin/bash +set -e programs/build_helpers/buildstep -s 3500 ccache -s From 007c0e888fce4583f7b032d2c5114ad396bac282 Mon Sep 17 00:00:00 2001 From: Nathan Hourt Date: Mon, 12 Aug 2019 16:14:18 -0500 Subject: [PATCH 074/111] Update build_protocol Add `set -e` so if any command fails, the script fails --- programs/build_helpers/build_protocol | 1 + 1 file changed, 1 insertion(+) diff --git a/programs/build_helpers/build_protocol b/programs/build_helpers/build_protocol index 6307400586..9eb783cf37 100755 --- a/programs/build_helpers/build_protocol +++ b/programs/build_helpers/build_protocol @@ -1,4 +1,5 @@ #!/bin/bash +set -e programs/build_helpers/buildstep -s 3500 ccache -s From 7cfdd62e70f93f0ad580a277f4076532867ec430 Mon Sep 17 00:00:00 2001 From: Nathan Hourt Date: Mon, 12 Aug 2019 17:07:51 -0500 Subject: [PATCH 075/111] Update build_and_test Remove quotes; they didn't break Travis, but they do break bash --- programs/build_helpers/build_and_test | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/programs/build_helpers/build_and_test b/programs/build_helpers/build_and_test index 7a6b0ebc33..062f4d1883 100755 --- a/programs/build_helpers/build_and_test +++ b/programs/build_helpers/build_and_test @@ -9,8 +9,8 @@ programs/build_helpers/buildstep make.everything 2400 "programs/build_helpers/ma set -o pipefail programs/build_helpers/buildstep run.chain_test 240 "libraries/fc/tests/run-parallel-tests.sh tests/chain_test" programs/build_helpers/buildstep run.cli_test 60 "libraries/fc/tests/run-parallel-tests.sh tests/cli_test" -'programs/build_helpers/buildstep prepare.sonar 20 "find libraries/[acdenptuw]*/CMakeFiles/*.dir programs/[cdgjsw]*/CMakeFiles/*.dir -type d -print | while read d; do gcov -o \"\$d\" \"\${d/CMakeFiles*.dir//}\"/*.cpp; done >/dev/null; programs/build_helpers/set_sonar_branch sonar-project.properties" || true' -'programs/build_helpers/buildstep run.sonar 1200 "which sonar-scanner && sonar-scanner" || true' +programs/build_helpers/buildstep prepare.sonar 20 "find libraries/[acdenptuw]*/CMakeFiles/*.dir programs/[cdgjsw]*/CMakeFiles/*.dir -type d -print | while read d; do gcov -o \"\$d\" \"\${d/CMakeFiles*.dir//}\"/*.cpp; done >/dev/null; programs/build_helpers/set_sonar_branch sonar-project.properties" || true +programs/build_helpers/buildstep run.sonar 1200 "which sonar-scanner && sonar-scanner" || true programs/build_helpers/buildstep end 0 ccache -s From ba65ab5db3cf23e3c02bdd9783a83a393b709172 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Tue, 13 Aug 2019 10:47:09 -0300 Subject: [PATCH 076/111] change category to helper --- libraries/plugins/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/plugins/README.md b/libraries/plugins/README.md index fe635fbbe4..c130f7219f 100644 --- a/libraries/plugins/README.md +++ b/libraries/plugins/README.md @@ -11,7 +11,7 @@ Plugins are optional to run by node operator according to their needs. However, Folder | Name | Description | Category | Status | SpaceID -----------------------------------|--------------------------|-----------------------------------------------------------------------------|----------------|---------------|--------------| [account_history](account_history) | Account History | Save account history data | History | Stable | 4 -[api_helper_indexes](api_helper_indexes) | API Helper Indexes | Provides some helper indexes used by various API calls | History | Stable | +[api_helper_indexes](api_helper_indexes) | API Helper Indexes | Provides some helper indexes used by various API calls | Helper | Stable | [debug_witness](debug_witness) | Debug Witness | Run "what-if" tests | Debug | Stable | [delayed_node](delayed_node) | Delayed Node | Avoid forks by running a several times confirmed and delayed blockchain | Business | Stable | [elasticsearch](elasticsearch) | ElasticSearch Operations | Save account history data into elasticsearch database | History | Experimental | 6 From aa76ec09bd4dc8e7af382e0a9689ece1402f70fb Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Sat, 27 Apr 2019 22:01:49 +0200 Subject: [PATCH 077/111] Adapted to fc promise changes --- libraries/app/api.cpp | 2 +- libraries/chain/db_block.cpp | 2 +- libraries/net/node.cpp | 8 ++++---- programs/cli_wallet/main.cpp | 2 +- programs/delayed_node/main.cpp | 2 +- programs/network_mapper/network_mapper.cpp | 2 +- programs/size_checker/main.cpp | 1 + programs/witness_node/main.cpp | 2 +- 8 files changed, 11 insertions(+), 10 deletions(-) diff --git a/libraries/app/api.cpp b/libraries/app/api.cpp index d661bf4735..5d99a18a82 100644 --- a/libraries/app/api.cpp +++ b/libraries/app/api.cpp @@ -180,7 +180,7 @@ namespace graphene { namespace app { fc::variant network_broadcast_api::broadcast_transaction_synchronous(const precomputable_transaction& trx) { - fc::promise::ptr prom( new fc::promise() ); + fc::promise::ptr prom = fc::promise::create(); broadcast_transaction_with_callback( [prom]( const fc::variant& v ){ prom->set_value(v); }, trx ); diff --git a/libraries/chain/db_block.cpp b/libraries/chain/db_block.cpp index 7eb518d181..dbcf94b3fa 100644 --- a/libraries/chain/db_block.cpp +++ b/libraries/chain/db_block.cpp @@ -809,7 +809,7 @@ fc::future database::precompute_parallel( const signed_block& block, const block.id(); if( workers.empty() ) - return fc::future< void >( fc::promise< void >::ptr( new fc::promise< void >( true ) ) ); + return fc::future< void >( fc::promise< void >::create( true ) ); auto first = workers.begin(); auto worker = first; diff --git a/libraries/net/node.cpp b/libraries/net/node.cpp index fc2a086ee2..6859f64998 100644 --- a/libraries/net/node.cpp +++ b/libraries/net/node.cpp @@ -442,7 +442,7 @@ namespace graphene { namespace net { namespace detail { #if 0 try { - _retrigger_connect_loop_promise = fc::promise::ptr( new fc::promise("graphene::net::retrigger_connect_loop") ); + _retrigger_connect_loop_promise = fc::promise::create("graphene::net::retrigger_connect_loop"); if( is_wanting_new_connections() || !_add_once_node_list.empty() ) { if( is_wanting_new_connections() ) @@ -572,7 +572,7 @@ namespace graphene { namespace net { namespace detail { if( !_sync_items_to_fetch_updated ) { dlog( "no sync items to fetch right now, going to sleep" ); - _retrigger_fetch_sync_items_loop_promise = fc::promise::ptr( new fc::promise("graphene::net::retrigger_fetch_sync_items_loop") ); + _retrigger_fetch_sync_items_loop_promise = fc::promise::create("graphene::net::retrigger_fetch_sync_items_loop"); _retrigger_fetch_sync_items_loop_promise->wait(); _retrigger_fetch_sync_items_loop_promise.reset(); } @@ -699,7 +699,7 @@ namespace graphene { namespace net { namespace detail { if (!_items_to_fetch_updated) { - _retrigger_fetch_item_loop_promise = fc::promise::ptr(new fc::promise("graphene::net::retrigger_fetch_item_loop")); + _retrigger_fetch_item_loop_promise = fc::promise::create("graphene::net::retrigger_fetch_item_loop"); fc::microseconds time_until_retrigger = fc::microseconds::maximum(); if (next_peer_unblocked_time != fc::time_point::maximum()) time_until_retrigger = next_peer_unblocked_time - fc::time_point::now(); @@ -791,7 +791,7 @@ namespace graphene { namespace net { namespace detail { if (_new_inventory.empty()) { - _retrigger_advertise_inventory_loop_promise = fc::promise::ptr(new fc::promise("graphene::net::retrigger_advertise_inventory_loop")); + _retrigger_advertise_inventory_loop_promise = fc::promise::create("graphene::net::retrigger_advertise_inventory_loop"); _retrigger_advertise_inventory_loop_promise->wait(); _retrigger_advertise_inventory_loop_promise.reset(); } diff --git a/programs/cli_wallet/main.cpp b/programs/cli_wallet/main.cpp index e33c1c28fe..1cca772e9a 100644 --- a/programs/cli_wallet/main.cpp +++ b/programs/cli_wallet/main.cpp @@ -360,7 +360,7 @@ int main( int argc, char** argv ) } else { - fc::promise::ptr exit_promise = new fc::promise("UNIX Signal Handler"); + fc::promise::ptr exit_promise = fc::promise::create("UNIX Signal Handler"); fc::set_signal_handler( [&exit_promise](int signal) { ilog( "Captured SIGINT in daemon mode, exiting" ); diff --git a/programs/delayed_node/main.cpp b/programs/delayed_node/main.cpp index 8379a7485b..b760113049 100644 --- a/programs/delayed_node/main.cpp +++ b/programs/delayed_node/main.cpp @@ -187,7 +187,7 @@ int main(int argc, char** argv) { node.startup_plugins(); - fc::promise::ptr exit_promise = new fc::promise("UNIX Signal Handler"); + fc::promise::ptr exit_promise = fc::promise::create("UNIX Signal Handler"); fc::set_signal_handler([&exit_promise](int signal) { exit_promise->set_value(signal); }, SIGINT); diff --git a/programs/network_mapper/network_mapper.cpp b/programs/network_mapper/network_mapper.cpp index b00439467a..68b5f526f2 100644 --- a/programs/network_mapper/network_mapper.cpp +++ b/programs/network_mapper/network_mapper.cpp @@ -33,7 +33,7 @@ class peer_probe : public graphene::net::peer_connection_delegate _connection(graphene::net::peer_connection::make_shared(this)), _connection_was_rejected(false), _done(false), - _probe_complete_promise(fc::promise::ptr(new fc::promise("probe_complete"))) + _probe_complete_promise(fc::promise::create("probe_complete")) {} void start(const fc::ip::endpoint& endpoint_to_probe, diff --git a/programs/size_checker/main.cpp b/programs/size_checker/main.cpp index f4fb956341..a7c09308fc 100644 --- a/programs/size_checker/main.cpp +++ b/programs/size_checker/main.cpp @@ -23,6 +23,7 @@ */ #include +#include #include #include diff --git a/programs/witness_node/main.cpp b/programs/witness_node/main.cpp index acbda6386c..bf7669ed8b 100644 --- a/programs/witness_node/main.cpp +++ b/programs/witness_node/main.cpp @@ -157,7 +157,7 @@ int main(int argc, char** argv) { node->startup(); node->startup_plugins(); - fc::promise::ptr exit_promise = new fc::promise("UNIX Signal Handler"); + fc::promise::ptr exit_promise = fc::promise::create("UNIX Signal Handler"); fc::set_signal_handler([&exit_promise](int signal) { elog( "Caught SIGINT attempting to exit cleanly" ); From 8f1eca14cfed362a2659fca3986faf03043c6156 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Tue, 7 May 2019 08:27:57 +0200 Subject: [PATCH 078/111] Replace fc::uint128 with boost::multiprecision::uint128_t --- libraries/app/api.cpp | 1 + libraries/app/database_api.cpp | 14 ++-- libraries/app/include/graphene/app/util.hpp | 22 ++---- libraries/app/util.cpp | 73 +++++++------------ libraries/chain/account_object.cpp | 4 +- libraries/chain/asset_object.cpp | 5 +- libraries/chain/db_init.cpp | 3 +- libraries/chain/db_maint.cpp | 14 ++-- libraries/chain/db_market.cpp | 10 ++- libraries/chain/db_update.cpp | 6 +- libraries/chain/db_witness_schedule.cpp | 4 +- libraries/chain/evaluator.cpp | 2 - libraries/chain/genesis_state.cpp | 2 + .../graphene/chain/global_property_object.hpp | 4 - .../graphene/chain/vesting_balance_object.hpp | 8 +- libraries/chain/market_evaluator.cpp | 2 - libraries/chain/vesting_balance_object.cpp | 5 +- .../db/include/graphene/db/generic_index.hpp | 13 +--- libraries/db/include/graphene/db/index.hpp | 1 - libraries/db/include/graphene/db/object.hpp | 14 ++-- .../db/include/graphene/db/simple_index.hpp | 7 -- libraries/db/object_database.cpp | 1 - libraries/fc | 2 +- .../market_history/market_history_plugin.hpp | 7 +- libraries/protocol/asset.cpp | 3 +- libraries/protocol/fee_schedule.cpp | 5 +- .../include/graphene/protocol/types.hpp | 1 - libraries/protocol/operations.cpp | 6 +- libraries/protocol/vote.cpp | 2 + libraries/wallet/wallet.cpp | 3 +- tests/tests/app_util_tests.cpp | 11 +-- tests/tests/basic_tests.cpp | 2 +- tests/tests/block_tests.cpp | 6 +- tests/tests/call_order_tests.cpp | 1 - tests/tests/fee_tests.cpp | 6 +- 35 files changed, 115 insertions(+), 155 deletions(-) diff --git a/libraries/app/api.cpp b/libraries/app/api.cpp index 5d99a18a82..627a31b692 100644 --- a/libraries/app/api.cpp +++ b/libraries/app/api.cpp @@ -36,6 +36,7 @@ #include #include +#include #include #include #include diff --git a/libraries/app/database_api.cpp b/libraries/app/database_api.cpp index ab6889c7b3..009d208d39 100644 --- a/libraries/app/database_api.cpp +++ b/libraries/app/database_api.cpp @@ -36,7 +36,6 @@ #include #include -#include #include @@ -456,8 +455,8 @@ market_ticker::market_ticker(const market_ticker_object& mto, lowest_ask = "0"; highest_bid = "0"; - fc::uint128 bv; - fc::uint128 qv; + fc::uint128_t bv; + fc::uint128_t qv; price latest_price = asset( mto.latest_base, mto.base ) / asset( mto.latest_quote, mto.quote ); if( mto.base != asset_base.id ) latest_price = ~latest_price; @@ -1698,7 +1697,6 @@ order_book database_api::get_order_book( const string& base, const string& quote order_book database_api_impl::get_order_book( const string& base, const string& quote, unsigned limit )const { - using boost::multiprecision::uint128_t; uint64_t api_limit_get_order_book=_app_options->api_limit_get_order_book; FC_ASSERT( limit <= api_limit_get_order_book ); @@ -1720,7 +1718,9 @@ order_book database_api_impl::get_order_book( const string& base, const string& { order ord; ord.price = price_to_string( o.sell_price, *assets[0], *assets[1] ); - ord.quote = assets[1]->amount_to_string( share_type( ( uint128_t( o.for_sale.value ) * o.sell_price.quote.amount.value ) / o.sell_price.base.amount.value ) ); + ord.quote = assets[1]->amount_to_string( share_type( fc::uint128_t( o.for_sale.value ) + * o.sell_price.quote.amount.value + / o.sell_price.base.amount.value ) ); ord.base = assets[0]->amount_to_string( o.for_sale ); result.bids.push_back( ord ); } @@ -1729,7 +1729,9 @@ order_book database_api_impl::get_order_book( const string& base, const string& order ord; ord.price = price_to_string( o.sell_price, *assets[0], *assets[1] ); ord.quote = assets[1]->amount_to_string( o.for_sale ); - ord.base = assets[0]->amount_to_string( share_type( ( uint128_t( o.for_sale.value ) * o.sell_price.quote.amount.value ) / o.sell_price.base.amount.value ) ); + ord.base = assets[0]->amount_to_string( share_type( fc::uint128_t( o.for_sale.value ) + * o.sell_price.quote.amount.value + / o.sell_price.base.amount.value ) ); result.asks.push_back( ord ); } } diff --git a/libraries/app/include/graphene/app/util.hpp b/libraries/app/include/graphene/app/util.hpp index 038771015c..1513be9d10 100644 --- a/libraries/app/include/graphene/app/util.hpp +++ b/libraries/app/include/graphene/app/util.hpp @@ -23,21 +23,15 @@ */ #pragma once -#include - #include -#include - -namespace graphene { namespace app { - using namespace graphene::protocol; - - typedef boost::multiprecision::uint256_t u256; - - u256 to256( const fc::uint128& t ); - fc::uint128 to_capped128( const u256& t ); - string uint128_amount_to_string( const fc::uint128& amount, const uint8_t precision ); - string price_to_string( const price& _price, const uint8_t base_precision, const uint8_t quote_precision); - string price_diff_percent_string( const price& old_price, const price& new_price ); +namespace graphene { +namespace protocol { + struct price; +} +namespace app { + std::string uint128_amount_to_string( const fc::uint128_t& amount, const uint8_t precision ); + std::string price_to_string( const graphene::protocol::price& _price, const uint8_t base_precision, const uint8_t quote_precision); + std::string price_diff_percent_string( const graphene::protocol::price& old_price, const graphene::protocol::price& new_price ); } } diff --git a/libraries/app/util.cpp b/libraries/app/util.cpp index a7c80b9ebe..fabfa26599 100644 --- a/libraries/app/util.cpp +++ b/libraries/app/util.cpp @@ -22,39 +22,26 @@ * THE SOFTWARE. */ -#include +#include +#include +#include namespace graphene { namespace app { -u256 to256( const fc::uint128& t ) -{ - u256 v(t.hi); - v <<= 64; - v += t.lo; - return v; -} +using boost::multiprecision::uint256_t; -fc::uint128 to_capped128( const u256& t ) +static fc::uint128_t to_capped_128( const uint256_t& t ) { - static u256 max128 = to256( fc::uint128::max_value() ); - if( t >= max128 ) - return fc::uint128::max_value(); - fc::uint128 result; - u256 hi(t); - hi >>= 64; - result.hi = static_cast< uint64_t >( hi ); - u256 lo(t); - hi <<= 64; - lo -= hi; - result.lo = static_cast< uint64_t >( lo ); - return result; + if( t >= std::numeric_limits::max() ) + return std::numeric_limits::max(); + return static_cast(t); } -string uint128_amount_to_string( const fc::uint128& amount, const uint8_t precision ) +std::string uint128_amount_to_string( const fc::uint128_t& amount, const uint8_t precision ) { try { - string s = string( amount ); - if( precision == 0 || amount == fc::uint128() ) + std::string s = amount.str(); + if( precision == 0 || amount == fc::uint128_t() ) return s; std::stringstream ss; @@ -77,7 +64,7 @@ string uint128_amount_to_string( const fc::uint128& amount, const uint8_t precis return ss.str(); } FC_CAPTURE_AND_RETHROW( (amount)(precision) ) } -string price_to_string( const price& _price, const uint8_t base_precision, const uint8_t quote_precision ) +std::string price_to_string( const graphene::protocol::price& _price, const uint8_t base_precision, const uint8_t quote_precision ) { try { if( _price.base.amount == 0 ) return "0"; @@ -85,7 +72,7 @@ string price_to_string( const price& _price, const uint8_t base_precision, const FC_ASSERT( _price.quote.amount >= 0 ); FC_ASSERT( base_precision <= 19 ); FC_ASSERT( quote_precision <= 19 ); - price new_price = _price; + graphene::protocol::price new_price = _price; if( new_price.quote.amount == 0 ) { new_price.base.amount = std::numeric_limits::max(); @@ -93,13 +80,14 @@ string price_to_string( const price& _price, const uint8_t base_precision, const } // times (10**19) so won't overflow but have good accuracy - fc::uint128 price128 = fc::uint128( new_price.base.amount.value ) * uint64_t(10000000000000000000ULL) + fc::uint128_t price128 = fc::uint128_t( new_price.base.amount.value ) * uint64_t(10000000000000000000ULL) / new_price.quote.amount.value; return uint128_amount_to_string( price128, 19 + base_precision - quote_precision ); } FC_CAPTURE_AND_RETHROW( (_price)(base_precision)(quote_precision) ) } -string price_diff_percent_string( const price& old_price, const price& new_price ) +std::string price_diff_percent_string( const graphene::protocol::price& old_price, + const graphene::protocol::price& new_price ) { try { FC_ASSERT( old_price.base.asset_id == new_price.base.asset_id ); FC_ASSERT( old_price.quote.asset_id == new_price.quote.asset_id ); @@ -107,7 +95,7 @@ string price_diff_percent_string( const price& old_price, const price& new_price FC_ASSERT( old_price.quote.amount >= 0 ); FC_ASSERT( new_price.base.amount >= 0 ); FC_ASSERT( new_price.quote.amount >= 0 ); - price old_price1 = old_price; + graphene::protocol::price old_price1 = old_price; if( old_price.base.amount == 0 ) { old_price1.base.amount = 1; @@ -118,7 +106,7 @@ string price_diff_percent_string( const price& old_price, const price& new_price old_price1.base.amount = std::numeric_limits::max(); old_price1.quote.amount = 1; } - price new_price1 = new_price; + graphene::protocol::price new_price1 = new_price; if( new_price.base.amount == 0 ) { new_price1.base.amount = 1; @@ -133,25 +121,16 @@ string price_diff_percent_string( const price& old_price, const price& new_price // change = new/old - 1 = (new_base/new_quote)/(old_base/old_quote) - 1 // = (new_base * old_quote) / (new_quote * old_base) - 1 // = (new_base * old_quote - new_quote * old_base) / (new_quote * old_base) - fc::uint128 new128 = fc::uint128( new_price1.base.amount.value ) * old_price1.quote.amount.value; - fc::uint128 old128 = fc::uint128( old_price1.base.amount.value ) * new_price1.quote.amount.value; - bool non_negative = (new128 >= old128); - fc::uint128 diff128; + uint256_t new256 = uint256_t( new_price1.base.amount.value ) * old_price1.quote.amount.value; + uint256_t old256 = uint256_t( old_price1.base.amount.value ) * new_price1.quote.amount.value; + bool non_negative = (new256 >= old256); + uint256_t diff256; if( non_negative ) - diff128 = new128 - old128; + diff256 = new256 - old256; else - diff128 = old128 - new128; - static fc::uint128 max = fc::uint128::max_value() / 10000; - if( diff128 <= max ) - diff128 = diff128 * 10000 / old128; - else - { - u256 diff256 = to256( diff128 ); - diff256 *= 10000; - diff256 /= to256( old128 ); - diff128 = to_capped128( diff256 ); - } - string diff_str = uint128_amount_to_string( diff128, 2 ); // at most 2 decimal digits + diff256 = old256 - new256; + diff256 = diff256 * 10000 / old256; + std::string diff_str = uint128_amount_to_string( to_capped_128(diff256), 2 ); // at most 2 decimal digits if( non_negative || diff_str == "0" ) return diff_str; else diff --git a/libraries/chain/account_object.cpp b/libraries/chain/account_object.cpp index 8ec70a6a4f..76df1c6929 100644 --- a/libraries/chain/account_object.cpp +++ b/libraries/chain/account_object.cpp @@ -36,10 +36,10 @@ share_type cut_fee(share_type a, uint16_t p) if( p == GRAPHENE_100_PERCENT ) return a; - fc::uint128 r(a.value); + fc::uint128_t r = a.value; r *= p; r /= GRAPHENE_100_PERCENT; - return r.to_uint64(); + return r.convert_to(); } void account_balance_object::adjust_balance(const asset& delta) diff --git a/libraries/chain/asset_object.cpp b/libraries/chain/asset_object.cpp index 2244043920..0232162781 100644 --- a/libraries/chain/asset_object.cpp +++ b/libraries/chain/asset_object.cpp @@ -37,10 +37,11 @@ share_type asset_bitasset_data_object::max_force_settlement_volume(share_type cu if( options.maximum_force_settlement_volume == GRAPHENE_100_PERCENT ) return current_supply + force_settled_volume; - fc::uint128 volume = current_supply.value + force_settled_volume.value; + fc::uint128_t volume = current_supply.value; + volume += force_settled_volume.value; volume *= options.maximum_force_settlement_volume; volume /= GRAPHENE_100_PERCENT; - return volume.to_uint64(); + return volume.convert_to(); } void graphene::chain::asset_bitasset_data_object::update_median_feeds( time_point_sec current_time, diff --git a/libraries/chain/db_init.cpp b/libraries/chain/db_init.cpp index 3d0aaf8c04..124cede1eb 100644 --- a/libraries/chain/db_init.cpp +++ b/libraries/chain/db_init.cpp @@ -64,7 +64,6 @@ #include #include -#include #include #include @@ -427,7 +426,7 @@ void database::init_genesis(const genesis_state_type& genesis_state) p.time = genesis_state.initial_timestamp; p.dynamic_flags = 0; p.witness_budget = 0; - p.recent_slots_filled = fc::uint128::max_value(); + p.recent_slots_filled = std::numeric_limits::max(); }); FC_ASSERT( (genesis_state.immutable_parameters.min_witness_count & 1) == 1, "min_witness_count must be odd" ); diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index 7bba8beff5..97d9a632ff 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -22,8 +22,6 @@ * THE SOFTWARE. */ -#include - #include #include @@ -184,10 +182,10 @@ void database::pay_workers( share_type& budget ) // Note: if there is a good chance that passed_time_count == day_count, // for better performance, can avoid the 128 bit calculation by adding a check. // Since it's not the case on BitShares mainnet, we're not using a check here. - fc::uint128 pay(requested_pay.value); + fc::uint128_t pay = requested_pay.value; pay *= passed_time_count; pay /= day_count; - requested_pay = pay.to_uint64(); + requested_pay = pay.convert_to(); share_type actual_pay = std::min(budget, requested_pay); //ilog(" ==> Paying ${a} to worker ${w}", ("w", active_worker.id)("a", actual_pay)); @@ -442,7 +440,7 @@ void database::initialize_budget_record( fc::time_point_sec now, budget_record& budget_u128 += ((uint64_t(1) << GRAPHENE_CORE_ASSET_CYCLE_RATE_BITS) - 1); budget_u128 >>= GRAPHENE_CORE_ASSET_CYCLE_RATE_BITS; if( budget_u128 < reserve.value ) - rec.total_budget = share_type(budget_u128.to_uint64()); + rec.total_budget = share_type(budget_u128.convert_to()); else rec.total_budget = reserve; @@ -497,7 +495,7 @@ void database::process_budget() if( worker_budget_u128 >= available_funds.value ) worker_budget = available_funds; else - worker_budget = worker_budget_u128.to_uint64(); + worker_budget = worker_budget_u128.convert_to(); rec.worker_budget = worker_budget; available_funds -= worker_budget; @@ -637,12 +635,12 @@ void split_fba_balance( fc::uint128_t buyback_amount_128 = fba.accumulated_fba_fees.value; buyback_amount_128 *= designated_asset_buyback_pct; buyback_amount_128 /= GRAPHENE_100_PERCENT; - share_type buyback_amount = buyback_amount_128.to_uint64(); + share_type buyback_amount = buyback_amount_128.convert_to(); fc::uint128_t issuer_amount_128 = fba.accumulated_fba_fees.value; issuer_amount_128 *= designated_asset_issuer_pct; issuer_amount_128 /= GRAPHENE_100_PERCENT; - share_type issuer_amount = issuer_amount_128.to_uint64(); + share_type issuer_amount = issuer_amount_128.convert_to(); // this assert should never fail FC_ASSERT( buyback_amount + issuer_amount <= fba.accumulated_fba_fees ); diff --git a/libraries/chain/db_market.cpp b/libraries/chain/db_market.cpp index c009d0b830..b717446bd7 100644 --- a/libraries/chain/db_market.cpp +++ b/libraries/chain/db_market.cpp @@ -30,13 +30,15 @@ #include #include -#include +#include -namespace graphene { namespace chain { namespace detail { +namespace graphene { namespace chain { + +namespace detail { share_type calculate_percent(const share_type& value, uint16_t percent) { - boost::multiprecision::uint128_t a(value.value); + fc::uint128_t a(value.value); a *= percent; a /= GRAPHENE_100_PERCENT; FC_ASSERT( a <= GRAPHENE_MAX_SHARE_SUPPLY, "overflow when calculating percent" ); @@ -256,7 +258,7 @@ void database::cancel_limit_order( const limit_order_object& order, bool create_ } else { - boost::multiprecision::uint128_t fee128( deferred_paid_fee.amount.value ); + fc::uint128_t fee128( deferred_paid_fee.amount.value ); fee128 *= core_cancel_fee.amount.value; // to round up fee128 += order.deferred_fee.value; diff --git a/libraries/chain/db_update.cpp b/libraries/chain/db_update.cpp index cf767b5d89..6b39c98822 100644 --- a/libraries/chain/db_update.cpp +++ b/libraries/chain/db_update.cpp @@ -37,8 +37,6 @@ #include -#include - namespace graphene { namespace chain { void database::update_global_dynamic_data( const signed_block& b, const uint32_t missed_blocks ) @@ -412,9 +410,9 @@ void database::clear_expired_orders() { auto& pays = order.balance; auto receives = (order.balance * mia.current_feed.settlement_price); - receives.amount = ( fc::uint128_t(receives.amount.value) * + receives.amount = static_cast( fc::uint128_t(receives.amount.value) * (GRAPHENE_100_PERCENT - mia.options.force_settlement_offset_percent) / - GRAPHENE_100_PERCENT ).to_uint64(); + GRAPHENE_100_PERCENT ); assert(receives <= order.balance * mia.current_feed.settlement_price); settlement_price = pays / receives; } diff --git a/libraries/chain/db_witness_schedule.cpp b/libraries/chain/db_witness_schedule.cpp index 5fd5cfc2a1..8f5db1ce82 100644 --- a/libraries/chain/db_witness_schedule.cpp +++ b/libraries/chain/db_witness_schedule.cpp @@ -27,6 +27,8 @@ #include #include +#include + namespace graphene { namespace chain { using boost::container::flat_set; @@ -96,7 +98,7 @@ uint32_t database::update_witness_missed_blocks( const signed_block& b ) uint32_t database::witness_participation_rate()const { const dynamic_global_property_object& dpo = get_dynamic_global_properties(); - return uint64_t(GRAPHENE_100_PERCENT) * dpo.recent_slots_filled.popcount() / 128; + return uint64_t(GRAPHENE_100_PERCENT) * fc::popcount(dpo.recent_slots_filled) / 128; } void database::update_witness_schedule() diff --git a/libraries/chain/evaluator.cpp b/libraries/chain/evaluator.cpp index 482d9a01e0..a793163fe5 100644 --- a/libraries/chain/evaluator.cpp +++ b/libraries/chain/evaluator.cpp @@ -35,8 +35,6 @@ #include #include -#include - namespace graphene { namespace chain { database& generic_evaluator::db()const { return trx_state->db(); } diff --git a/libraries/chain/genesis_state.cpp b/libraries/chain/genesis_state.cpp index 90df17af01..ae6b015990 100644 --- a/libraries/chain/genesis_state.cpp +++ b/libraries/chain/genesis_state.cpp @@ -25,6 +25,8 @@ #include #include +#include + namespace graphene { namespace chain { chain_id_type genesis_state_type::compute_chain_id() const diff --git a/libraries/chain/include/graphene/chain/global_property_object.hpp b/libraries/chain/include/graphene/chain/global_property_object.hpp index 9141118bd2..a0e8b705d3 100644 --- a/libraries/chain/include/graphene/chain/global_property_object.hpp +++ b/libraries/chain/include/graphene/chain/global_property_object.hpp @@ -27,8 +27,6 @@ #include #include -#include - namespace graphene { namespace chain { /** @@ -83,8 +81,6 @@ namespace graphene { namespace chain { * every time a block is found it decreases by * RECENTLY_MISSED_COUNT_DECREMENT. It is * never less than 0. - * - * If the recently_missed_count hits 2*UNDO_HISTORY then no new blocks may be pushed. */ uint32_t recently_missed_count = 0; diff --git a/libraries/chain/include/graphene/chain/vesting_balance_object.hpp b/libraries/chain/include/graphene/chain/vesting_balance_object.hpp index 480922fa90..eea6c681be 100644 --- a/libraries/chain/include/graphene/chain/vesting_balance_object.hpp +++ b/libraries/chain/include/graphene/chain/vesting_balance_object.hpp @@ -88,11 +88,11 @@ namespace graphene { namespace chain { */ struct cdd_vesting_policy { - uint32_t vesting_seconds = 0; - fc::uint128_t coin_seconds_earned; + uint32_t vesting_seconds = 0; + fc::uint128_t coin_seconds_earned; /** while coindays may accrue over time, none may be claimed before first_claim date */ - fc::time_point_sec start_claim; - fc::time_point_sec coin_seconds_earned_last_update; + fc::time_point_sec start_claim; + fc::time_point_sec coin_seconds_earned_last_update; /** * Compute coin_seconds_earned. Used to diff --git a/libraries/chain/market_evaluator.cpp b/libraries/chain/market_evaluator.cpp index 4b6d9af928..848075da4d 100644 --- a/libraries/chain/market_evaluator.cpp +++ b/libraries/chain/market_evaluator.cpp @@ -34,8 +34,6 @@ #include -#include - namespace graphene { namespace chain { void_result limit_order_create_evaluator::do_evaluate(const limit_order_create_operation& op) { try { diff --git a/libraries/chain/vesting_balance_object.cpp b/libraries/chain/vesting_balance_object.cpp index 2bc8e45a78..fd723a3e6b 100644 --- a/libraries/chain/vesting_balance_object.cpp +++ b/libraries/chain/vesting_balance_object.cpp @@ -50,7 +50,8 @@ asset linear_vesting_policy::get_allowed_withdraw( const vesting_policy_context& share_type total_vested = 0; if( elapsed_seconds < vesting_duration_seconds ) { - total_vested = (fc::uint128_t( begin_balance.value ) * elapsed_seconds / vesting_duration_seconds).to_uint64(); + total_vested = static_cast(fc::uint128_t( begin_balance.value ) * elapsed_seconds + / vesting_duration_seconds); } else { @@ -117,7 +118,7 @@ asset cdd_vesting_policy::get_allowed_withdraw(const vesting_policy_context& ctx fc::uint128_t cs_earned = compute_coin_seconds_earned(ctx); fc::uint128_t withdraw_available = cs_earned / std::max(vesting_seconds, 1u); assert(withdraw_available <= ctx.balance.amount.value); - return asset(withdraw_available.to_uint64(), ctx.balance.asset_id); + return asset(static_cast(withdraw_available), ctx.balance.asset_id); } void cdd_vesting_policy::on_deposit(const vesting_policy_context& ctx) diff --git a/libraries/db/include/graphene/db/generic_index.hpp b/libraries/db/include/graphene/db/generic_index.hpp index b19fdf0aa7..812a6587d1 100644 --- a/libraries/db/include/graphene/db/generic_index.hpp +++ b/libraries/db/include/graphene/db/generic_index.hpp @@ -33,7 +33,7 @@ namespace graphene { namespace db { using boost::multi_index_container; using namespace boost::multi_index; - struct by_id{}; + struct by_id; /** * Almost all objects can be tracked and managed via a boost::multi_index container that uses * an unordered_unique key on the object ID. This template class adapts the generic index interface @@ -112,18 +112,7 @@ namespace graphene { namespace db { const index_type& indices()const { return _indices; } - virtual fc::uint128 hash()const override { - fc::uint128 result; - for( const auto& ptr : _indices ) - { - result += ptr.hash(); - } - - return result; - } - private: - fc::uint128 _current_hash; index_type _indices; }; diff --git a/libraries/db/include/graphene/db/index.hpp b/libraries/db/include/graphene/db/index.hpp index 2ba0c76a3c..b54e7266c7 100644 --- a/libraries/db/include/graphene/db/index.hpp +++ b/libraries/db/include/graphene/db/index.hpp @@ -130,7 +130,6 @@ namespace graphene { namespace db { } virtual void inspect_all_objects(std::function inspector)const = 0; - 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, uint32_t max_depth )const = 0; diff --git a/libraries/db/include/graphene/db/object.hpp b/libraries/db/include/graphene/db/object.hpp index 6da932b029..b5a6724a2b 100644 --- a/libraries/db/include/graphene/db/object.hpp +++ b/libraries/db/include/graphene/db/object.hpp @@ -22,10 +22,10 @@ * THE SOFTWARE. */ #pragma once +#include #include #include #include -#include #define MAX_NESTING (200) @@ -77,7 +77,6 @@ namespace graphene { namespace db { virtual void move_from( object& obj ) = 0; virtual variant to_variant()const = 0; virtual vector pack()const = 0; - virtual fc::uint128 hash()const = 0; }; /** @@ -102,10 +101,6 @@ namespace graphene { namespace db { } virtual variant to_variant()const { return variant( static_cast(*this), MAX_NESTING ); } virtual vector pack()const { return fc::raw::pack( static_cast(*this) ); } - virtual fc::uint128 hash()const { - auto tmp = this->pack(); - return fc::city_hash_crc_128( tmp.data(), tmp.size() ); - } }; typedef flat_map annotation_map; @@ -139,6 +134,13 @@ namespace graphene { namespace db { } } // graphene::db +// Without this, pack(object_id) tries to match the template for +// pack(boost::multiprecision::uint128_t). No idea why. :-( +namespace boost { namespace multiprecision { namespace detail { +template +struct is_restricted_conversion : public mpl::true_ {}; +}}} + FC_REFLECT_TYPENAME( graphene::db::annotation_map ) FC_REFLECT( graphene::db::object, (id) ) FC_REFLECT_DERIVED_TEMPLATE( (typename Derived), graphene::db::annotated_object, (graphene::db::object), (annotations) ) diff --git a/libraries/db/include/graphene/db/simple_index.hpp b/libraries/db/include/graphene/db/simple_index.hpp index 0e807aef6c..51679be2ad 100644 --- a/libraries/db/include/graphene/db/simple_index.hpp +++ b/libraries/db/include/graphene/db/simple_index.hpp @@ -98,13 +98,6 @@ namespace graphene { namespace db { } } FC_CAPTURE_AND_RETHROW() } - virtual fc::uint128 hash()const override { - fc::uint128 result; - for( const auto& ptr : _objects ) - result += ptr->hash(); - - return result; - } class const_iterator { diff --git a/libraries/db/object_database.cpp b/libraries/db/object_database.cpp index 5b026c08cf..75b7090be4 100644 --- a/libraries/db/object_database.cpp +++ b/libraries/db/object_database.cpp @@ -26,7 +26,6 @@ #include #include #include -#include namespace graphene { namespace db { diff --git a/libraries/fc b/libraries/fc index 2c5c30848a..b3904ad1fc 160000 --- a/libraries/fc +++ b/libraries/fc @@ -1 +1 @@ -Subproject commit 2c5c30848a2d1cdd774ecaef2b051565f6f151f9 +Subproject commit b3904ad1fc9363628ca42855d57cc0c88ca83c71 diff --git a/libraries/plugins/market_history/include/graphene/market_history/market_history_plugin.hpp b/libraries/plugins/market_history/include/graphene/market_history/market_history_plugin.hpp index c1a40637e6..51eca0d857 100644 --- a/libraries/plugins/market_history/include/graphene/market_history/market_history_plugin.hpp +++ b/libraries/plugins/market_history/include/graphene/market_history/market_history_plugin.hpp @@ -146,8 +146,8 @@ struct market_ticker_object : public abstract_object share_type last_day_quote; share_type latest_base; share_type latest_quote; - fc::uint128 base_volume; - fc::uint128 quote_volume; + fc::uint128_t base_volume; + fc::uint128_t quote_volume; }; struct market_ticker_meta_object : public abstract_object @@ -199,7 +199,8 @@ typedef multi_index_container< market_ticker_object, indexed_by< ordered_unique< tag, member< object, object_id_type, &object::id > >, - ordered_non_unique< tag, member< market_ticker_object, fc::uint128, &market_ticker_object::base_volume > >, + ordered_non_unique< tag, + member< market_ticker_object, fc::uint128_t, &market_ticker_object::base_volume > >, ordered_unique< tag, composite_key< diff --git a/libraries/protocol/asset.cpp b/libraries/protocol/asset.cpp index 77f6dd7c12..4d670ecc97 100644 --- a/libraries/protocol/asset.cpp +++ b/libraries/protocol/asset.cpp @@ -26,9 +26,10 @@ #include #include +#include namespace graphene { namespace protocol { - typedef boost::multiprecision::uint128_t uint128_t; + typedef fc::uint128_t uint128_t; typedef boost::multiprecision::int128_t int128_t; bool operator == ( const price& a, const price& b ) diff --git a/libraries/protocol/fee_schedule.cpp b/libraries/protocol/fee_schedule.cpp index 336c52a202..220e7fe8d1 100644 --- a/libraries/protocol/fee_schedule.cpp +++ b/libraries/protocol/fee_schedule.cpp @@ -25,6 +25,7 @@ #include #include +#include #define MAX_FEE_STABILIZATION_ITERATION 4 @@ -122,11 +123,11 @@ namespace graphene { namespace protocol { uint64_t required_fee = op.visit( calc_fee_visitor( *this, op ) ); if( scale != GRAPHENE_100_PERCENT ) { - auto scaled = fc::uint128(required_fee) * scale; + auto scaled = fc::uint128_t(required_fee) * scale; scaled /= GRAPHENE_100_PERCENT; FC_ASSERT( scaled <= GRAPHENE_MAX_SHARE_SUPPLY, "Required fee after scaling would exceed maximum possible supply" ); - required_fee = scaled.to_uint64(); + required_fee = scaled.convert_to(); } return asset( required_fee ); } diff --git a/libraries/protocol/include/graphene/protocol/types.hpp b/libraries/protocol/include/graphene/protocol/types.hpp index 16c589133f..91684ea7f2 100644 --- a/libraries/protocol/include/graphene/protocol/types.hpp +++ b/libraries/protocol/include/graphene/protocol/types.hpp @@ -54,7 +54,6 @@ #include #include -#include #include #include diff --git a/libraries/protocol/operations.cpp b/libraries/protocol/operations.cpp index 8045ed3261..d24d43c4ae 100644 --- a/libraries/protocol/operations.cpp +++ b/libraries/protocol/operations.cpp @@ -21,18 +21,20 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + #include #include #include +#include namespace graphene { namespace protocol { uint64_t base_operation::calculate_data_fee( uint64_t bytes, uint64_t price_per_kbyte ) { - auto result = (fc::uint128(bytes) * price_per_kbyte) / 1024; + auto result = (fc::uint128_t(bytes) * price_per_kbyte) / 1024; FC_ASSERT( result <= GRAPHENE_MAX_SHARE_SUPPLY ); - return result.to_uint64(); + return result.convert_to(); } fc::optional< fc::future > base_operation::validate_parallel( uint32_t skip )const diff --git a/libraries/protocol/vote.cpp b/libraries/protocol/vote.cpp index 16bd163337..75d9e17550 100644 --- a/libraries/protocol/vote.cpp +++ b/libraries/protocol/vote.cpp @@ -24,6 +24,8 @@ #include +#include + namespace fc { diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index 7c19bb94fe..c7bbe40f1c 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -60,6 +60,7 @@ #include #include #include +#include #include #include @@ -613,7 +614,7 @@ class wallet_api_impl fc::get_approximate_relative_time_string(dynamic_props.next_maintenance_time); result["chain_id"] = chain_props.chain_id; stringstream participation; - participation << fixed << std::setprecision(2) << (100*dynamic_props.recent_slots_filled.popcount()) / 128.0; + participation << fixed << std::setprecision(2) << (100.0*fc::popcount(dynamic_props.recent_slots_filled)) / 128.0; result["participation"] = participation.str(); result["active_witnesses"] = fc::variant(global_props.active_witnesses, GRAPHENE_MAX_NESTED_OBJECTS); result["active_committee_members"] = diff --git a/tests/tests/app_util_tests.cpp b/tests/tests/app_util_tests.cpp index 7034673443..7f6ccbaa43 100644 --- a/tests/tests/app_util_tests.cpp +++ b/tests/tests/app_util_tests.cpp @@ -32,15 +32,16 @@ using namespace graphene::chain; using namespace graphene::chain::test; using namespace graphene::app; +using fc::uint128_t; + BOOST_AUTO_TEST_SUITE(app_util_tests) BOOST_AUTO_TEST_CASE(uint128_amount_to_string_test) { - fc::uint128 max_u64( std::numeric_limits::max() ); - fc::uint128 min_gt_u64 = max_u64 + 1; - fc::uint128 one_u128 = max_u64 * 10; - fc::uint128 max_u128 = fc::uint128::max_value(); - //idump( ( uint128_amount_to_string( fc::uint128::max_value(), 0) ) ); + fc::uint128_t max_u64( std::numeric_limits::max() ); + fc::uint128_t min_gt_u64 = max_u64 + 1; + fc::uint128_t one_u128 = max_u64 * 10; + fc::uint128_t max_u128 = std::numeric_limits::max(); BOOST_CHECK_EQUAL( uint128_amount_to_string( 0, 0), "0" ); BOOST_CHECK_EQUAL( uint128_amount_to_string( 1, 0), "1" ); diff --git a/tests/tests/basic_tests.cpp b/tests/tests/basic_tests.cpp index 97d03ed41b..8fe1e28e55 100644 --- a/tests/tests/basic_tests.cpp +++ b/tests/tests/basic_tests.cpp @@ -231,7 +231,7 @@ BOOST_AUTO_TEST_CASE( price_test ) more_than_min.base.amount = 11; BOOST_CHECK( more_than_min * ratio_type(1,7) == price(asset(1),asset(more_than_min.quote.amount*7/11,asset_id_type(1))) ); more_than_min.base.amount = 64823; - BOOST_CHECK( more_than_min * ratio_type(31672,102472047) == price(asset(1),asset((fc::uint128(more_than_min.quote.amount.value)*102472047/(64823*31672)).to_uint64(),asset_id_type(1))) ); + BOOST_CHECK( more_than_min * ratio_type(31672,102472047) == price(asset(1),asset(static_cast(fc::uint128_t(more_than_min.quote.amount.value)*102472047/(64823*31672)),asset_id_type(1))) ); more_than_min.base.amount = 13; BOOST_CHECK( more_than_min * ratio_type(202472059,3) == price(asset((int64_t(13)*202472059)>>1),asset((more_than_min.quote.amount.value*3)>>1,asset_id_type(1))) ); // after >>1, quote = max*1.5, but gcd = 3, so quote/=3 = max/2, less than max diff --git a/tests/tests/block_tests.cpp b/tests/tests/block_tests.cpp index d93d9820a2..150bd30569 100644 --- a/tests/tests/block_tests.cpp +++ b/tests/tests/block_tests.cpp @@ -1103,14 +1103,14 @@ BOOST_FIXTURE_TEST_CASE( rsf_missed_blocks, database_fixture ) { generate_block(); - auto rsf = [&]() -> string + auto rsf = [this]() -> string { - fc::uint128 rsf = db.get_dynamic_global_properties().recent_slots_filled; + fc::uint128_t rsf = db.get_dynamic_global_properties().recent_slots_filled; string result = ""; result.reserve(128); for( int i=0; i<128; i++ ) { - result += ((rsf.lo & 1) == 0) ? '0' : '1'; + result += rsf & 1 ? '1' : '0'; rsf >>= 1; } return result; diff --git a/tests/tests/call_order_tests.cpp b/tests/tests/call_order_tests.cpp index 4f700cda87..f78ad5e6ca 100644 --- a/tests/tests/call_order_tests.cpp +++ b/tests/tests/call_order_tests.cpp @@ -24,7 +24,6 @@ #include #include -#include #include #include diff --git a/tests/tests/fee_tests.cpp b/tests/tests/fee_tests.cpp index 04bc758eed..6051509424 100644 --- a/tests/tests/fee_tests.cpp +++ b/tests/tests/fee_tests.cpp @@ -32,12 +32,12 @@ #include #include +#include + #include #include "../common/database_fixture.hpp" -#include - using namespace graphene::chain; using namespace graphene::chain::test; @@ -347,7 +347,7 @@ uint64_t pct( uint64_t percentage, uint64_t val ) fc::uint128_t x = percentage; x *= val; x /= GRAPHENE_100_PERCENT; - return x.to_uint64(); + return static_cast(x); } uint64_t pct( uint64_t percentage0, uint64_t percentage1, uint64_t val ) From 3911b7e90fd88037db482e3900ea03e4c89ca413 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Wed, 29 May 2019 11:22:42 +0200 Subject: [PATCH 079/111] Replaced fc::array with std::array --- .../net/include/graphene/net/message.hpp | 1 - .../net/include/graphene/net/stcp_socket.hpp | 4 +++- libraries/net/node.cpp | 2 +- libraries/protocol/address.cpp | 17 +++++++------- .../include/graphene/protocol/address.hpp | 2 +- .../include/graphene/protocol/pts_address.hpp | 11 ++++++---- libraries/protocol/pts_address.cpp | 22 +++++++++---------- libraries/protocol/types.cpp | 4 ++-- programs/js_operation_serializer/main.cpp | 11 +++++----- 9 files changed, 40 insertions(+), 34 deletions(-) diff --git a/libraries/net/include/graphene/net/message.hpp b/libraries/net/include/graphene/net/message.hpp index 8ebfd8caa3..cfff380f9b 100644 --- a/libraries/net/include/graphene/net/message.hpp +++ b/libraries/net/include/graphene/net/message.hpp @@ -26,7 +26,6 @@ #include -#include #include #include #include diff --git a/libraries/net/include/graphene/net/stcp_socket.hpp b/libraries/net/include/graphene/net/stcp_socket.hpp index cca94d5745..e2a0038375 100644 --- a/libraries/net/include/graphene/net/stcp_socket.hpp +++ b/libraries/net/include/graphene/net/stcp_socket.hpp @@ -26,6 +26,8 @@ #include #include +#include + namespace graphene { namespace net { /** @@ -61,7 +63,7 @@ class stcp_socket : public virtual fc::iostream fc::sha512 _shared_secret; fc::ecc::private_key _priv_key; - fc::array _buf; + std::array _buf; //uint32_t _buf_len; fc::tcp_socket _sock; fc::aes_encoder _send_aes; diff --git a/libraries/net/node.cpp b/libraries/net/node.cpp index 6859f64998..9a9b98386b 100644 --- a/libraries/net/node.cpp +++ b/libraries/net/node.cpp @@ -321,7 +321,7 @@ namespace graphene { namespace net { namespace detail { _maximum_blocks_per_peer_during_syncing(GRAPHENE_NET_MAX_BLOCKS_PER_PEER_DURING_SYNCING) { _rate_limiter.set_actual_rate_time_constant(fc::seconds(2)); - fc::rand_bytes(&_node_id.data[0], (int)_node_id.size()); + fc::rand_bytes((char*) _node_id.data(), (int)_node_id.size()); } node_impl::~node_impl() diff --git a/libraries/protocol/address.cpp b/libraries/protocol/address.cpp index 9ab70220ba..d941c32bf5 100644 --- a/libraries/protocol/address.cpp +++ b/libraries/protocol/address.cpp @@ -69,7 +69,7 @@ namespace graphene { namespace protocol { address::address( const fc::ecc::public_key& pub ) { auto dat = pub.serialize(); - addr = fc::ripemd160::hash( fc::sha512::hash( dat.data, sizeof( dat ) ) ); + addr = fc::ripemd160::hash( fc::sha512::hash( (char*) dat.data(), dat.size() ) ); } address::address( const pts_address& ptsaddr ) @@ -79,21 +79,22 @@ namespace graphene { namespace protocol { address::address( const fc::ecc::public_key_data& pub ) { - addr = fc::ripemd160::hash( fc::sha512::hash( pub.data, sizeof( pub ) ) ); + addr = fc::ripemd160::hash( fc::sha512::hash( (char*) pub.data(), pub.size() ) ); } address::address( const graphene::protocol::public_key_type& pub ) { - addr = fc::ripemd160::hash( fc::sha512::hash( pub.key_data.data, sizeof( pub.key_data ) ) ); + addr = fc::ripemd160::hash( fc::sha512::hash( (char*) pub.key_data.data(), pub.key_data.size() ) ); } address::operator std::string()const { - fc::array bin_addr; - memcpy( (char*)&bin_addr, (char*)&addr, sizeof( addr ) ); - auto checksum = fc::ripemd160::hash( (char*)&addr, sizeof( addr ) ); - memcpy( ((char*)&bin_addr)+20, (char*)&checksum._hash[0], 4 ); - return GRAPHENE_ADDRESS_PREFIX + fc::to_base58( bin_addr.data, sizeof( bin_addr ) ); + std::array bin_addr; + static_assert( bin_addr.size() >= sizeof(addr) + 4 ); + memcpy( bin_addr.data(), addr.data(), sizeof(addr) ); + auto checksum = fc::ripemd160::hash( addr.data(), sizeof(addr) ); + memcpy( bin_addr.data() + 20, (char*)&checksum._hash[0], 4 ); + return GRAPHENE_ADDRESS_PREFIX + fc::to_base58( bin_addr.data(), bin_addr.size() ); } } } // namespace graphene::protocol diff --git a/libraries/protocol/include/graphene/protocol/address.hpp b/libraries/protocol/include/graphene/protocol/address.hpp index e118128b55..4f04461c82 100644 --- a/libraries/protocol/include/graphene/protocol/address.hpp +++ b/libraries/protocol/include/graphene/protocol/address.hpp @@ -25,8 +25,8 @@ #include +#include #include -#include namespace graphene { namespace protocol { struct pts_address; diff --git a/libraries/protocol/include/graphene/protocol/pts_address.hpp b/libraries/protocol/include/graphene/protocol/pts_address.hpp index 981440cd16..8a30a44bfa 100644 --- a/libraries/protocol/include/graphene/protocol/pts_address.hpp +++ b/libraries/protocol/include/graphene/protocol/pts_address.hpp @@ -23,10 +23,13 @@ */ #pragma once -#include +#include +#include +#include + #include #include -#include +#include namespace fc { namespace ecc { class public_key; } } @@ -46,7 +49,7 @@ namespace graphene { namespace protocol { operator std::string()const; ///< converts to base58 + checksum - fc::array addr; ///< binary representation of address + std::array addr; ///< binary representation of address }; inline bool operator == ( const pts_address& a, const pts_address& b ) { return a.addr == b.addr; } @@ -64,7 +67,7 @@ namespace std size_t operator()(const graphene::protocol::pts_address &a) const { size_t s; - memcpy( (char*)&s, &a.addr.data[sizeof(a)-sizeof(s)], sizeof(s) ); + std::memcpy( (char*)&s, a.addr.data() + a.addr.size() - sizeof(s), sizeof(s) ); return s; } }; diff --git a/libraries/protocol/pts_address.cpp b/libraries/protocol/pts_address.cpp index 74e6d2b97e..64d23fbc3f 100644 --- a/libraries/protocol/pts_address.cpp +++ b/libraries/protocol/pts_address.cpp @@ -33,14 +33,14 @@ namespace graphene { namespace protocol { pts_address::pts_address() { - memset( addr.data, 0, sizeof(addr.data) ); + memset( addr.data(), 0, addr.size() ); } pts_address::pts_address( const std::string& base58str ) { std::vector v = fc::from_base58( fc::string(base58str) ); if( v.size() ) - memcpy( addr.data, v.data(), std::min( v.size(), sizeof(addr) ) ); + memcpy( addr.data(), v.data(), std::min( v.size(), addr.size() ) ); FC_ASSERT(is_valid(), "invalid pts_address ${a}", ("a", base58str)); } @@ -51,19 +51,19 @@ namespace graphene { namespace protocol { if( compressed ) { auto dat = pub.serialize(); - sha2 = fc::sha256::hash(dat.data, sizeof(dat) ); + sha2 = fc::sha256::hash((char*) dat.data(), dat.size() ); } else { auto dat = pub.serialize_ecc_point(); - sha2 = fc::sha256::hash(dat.data, sizeof(dat) ); + sha2 = fc::sha256::hash((char*) dat.data(), dat.size() ); } auto rep = fc::ripemd160::hash((char*)&sha2,sizeof(sha2)); - addr.data[0] = version; - memcpy( addr.data+1, (char*)&rep, sizeof(rep) ); - auto check = fc::sha256::hash( addr.data, sizeof(rep)+1 ); + addr[0] = version; + memcpy( addr.data() + 1, (char*)&rep, sizeof(rep) ); + auto check = fc::sha256::hash( addr.data(), sizeof(rep)+1 ); check = fc::sha256::hash(check); - memcpy( addr.data+1+sizeof(rep), (char*)&check, 4 ); + memcpy( addr.data() + 1 + sizeof(rep), (char*)&check, 4 ); } /** @@ -72,14 +72,14 @@ namespace graphene { namespace protocol { */ bool pts_address::is_valid()const { - auto check = fc::sha256::hash( addr.data, sizeof(fc::ripemd160)+1 ); + auto check = fc::sha256::hash( addr.data(), sizeof(fc::ripemd160)+1 ); check = fc::sha256::hash(check); - return memcmp( addr.data+1+sizeof(fc::ripemd160), (char*)&check, 4 ) == 0; + return memcmp( addr.data() + 1 + sizeof(fc::ripemd160), (char*)&check, 4 ) == 0; } pts_address::operator std::string()const { - return fc::to_base58( addr.data, sizeof(addr) ); + return fc::to_base58( addr.data(), addr.size() ); } } } // namespace graphene diff --git a/libraries/protocol/types.cpp b/libraries/protocol/types.cpp index 641e4fe328..74a6cc5f32 100644 --- a/libraries/protocol/types.cpp +++ b/libraries/protocol/types.cpp @@ -51,7 +51,7 @@ namespace graphene { namespace protocol { auto bin = fc::from_base58( base58str.substr( prefix_len ) ); auto bin_key = fc::raw::unpack(bin); key_data = bin_key.data; - FC_ASSERT( fc::ripemd160::hash( key_data.data, key_data.size() )._hash[0].value() == bin_key.check ); + FC_ASSERT( fc::ripemd160::hash( (char*) key_data.data(), key_data.size() )._hash[0].value() == bin_key.check ); }; public_key_type::operator fc::ecc::public_key_data() const @@ -68,7 +68,7 @@ namespace graphene { namespace protocol { { binary_key k; k.data = key_data; - k.check = fc::ripemd160::hash( k.data.data, k.data.size() )._hash[0].value(); + k.check = fc::ripemd160::hash( (char*) k.data.data(), k.data.size() )._hash[0].value(); auto data = fc::raw::pack( k ); return GRAPHENE_ADDRESS_PREFIX + fc::to_base58( data.data(), data.size() ); } diff --git a/programs/js_operation_serializer/main.cpp b/programs/js_operation_serializer/main.cpp index 94e5057d7c..4effe0efa3 100644 --- a/programs/js_operation_serializer/main.cpp +++ b/programs/js_operation_serializer/main.cpp @@ -103,12 +103,13 @@ bool register_serializer( const string& name, std::function sr ) template struct js_name { static std::string name(){ return remove_namespace(fc::get_typename::name()); }; }; template -struct js_name> +struct js_name> { - static std::string name(){ return "fixed_array "+ fc::to_string(N) + ", " + remove_namespace(fc::get_typename::name()); }; + static std::string name(){ return "fixed_array "+ fc::to_string(N) + ", " + + remove_namespace(fc::get_typename::name()); }; }; -template struct js_name> { static std::string name(){ return "bytes("+ fc::to_string(N) + ")"; }; }; -template struct js_name> { static std::string name(){ return "bytes("+ fc::to_string(N) + ")"; }; }; +template struct js_name> { static std::string name(){ return "bytes("+ fc::to_string(N) + ")"; }; }; +template struct js_name>{ static std::string name(){ return "bytes("+ fc::to_string(N) + ")"; }; }; template struct js_name< fc::optional > { static std::string name(){ return "optional(" + js_name::name() + ")"; } }; template<> struct js_name< object_id_type > { static std::string name(){ return "object_id_type"; } }; template struct js_name< fc::flat_set > { static std::string name(){ return "set(" + js_name::name() + ")"; } }; @@ -226,7 +227,7 @@ struct serializer }; template -struct serializer,false> +struct serializer,false> { static void init() { serializer::init(); } static void generate() {} From b46c252f27cd80ffcae9e6813b6aaaaa4411fec1 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Mon, 3 Jun 2019 18:34:30 +0200 Subject: [PATCH 080/111] Replaced true_type, false_type, is_class, is_enum with std type_traits --- libraries/protocol/include/graphene/protocol/object_id.hpp | 3 +-- libraries/protocol/include/graphene/protocol/types.hpp | 3 +-- programs/build_helpers/member_enumerator.cpp | 4 ++-- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/libraries/protocol/include/graphene/protocol/object_id.hpp b/libraries/protocol/include/graphene/protocol/object_id.hpp index 4175a8ea75..f4f02ab914 100644 --- a/libraries/protocol/include/graphene/protocol/object_id.hpp +++ b/libraries/protocol/include/graphene/protocol/object_id.hpp @@ -168,8 +168,7 @@ template struct reflector > { typedef graphene::db::object_id type; - typedef fc::true_type is_defined; - typedef fc::false_type is_enum; + typedef std::true_type is_defined; enum member_count_enum { local_member_count = 1, total_member_count = 1 diff --git a/libraries/protocol/include/graphene/protocol/types.hpp b/libraries/protocol/include/graphene/protocol/types.hpp index 91684ea7f2..0927fa1d87 100644 --- a/libraries/protocol/include/graphene/protocol/types.hpp +++ b/libraries/protocol/include/graphene/protocol/types.hpp @@ -76,8 +76,7 @@ namespace raw { \ namespace fc { \ template<> struct reflector {\ typedef TYPE type; \ - typedef fc::true_type is_defined; \ - typedef fc::false_type is_enum; \ + typedef std::true_type is_defined; \ enum member_count_enum { \ local_member_count = 0 BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_MEMBER_COUNT, +, MEMBERS ),\ total_member_count = local_member_count BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_BASE_MEMBER_COUNT, +, INHERITS )\ diff --git a/programs/build_helpers/member_enumerator.cpp b/programs/build_helpers/member_enumerator.cpp index cce25a5f4a..6a292298ee 100644 --- a/programs/build_helpers/member_enumerator.cpp +++ b/programs/build_helpers/member_enumerator.cpp @@ -110,7 +110,7 @@ void class_processor::process_class( const static_variant< T... >* dummy ) } } -template +template struct if_reflected { template< typename T > @@ -122,7 +122,7 @@ struct if_reflected }; template<> -struct if_reflected +struct if_reflected { template< typename T > static void process_class( class_processor* proc, const T* dummy ) From 4d4f863611f28a4ac30220518e17f1c19ddf56a8 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Thu, 6 Jun 2019 14:43:07 +0200 Subject: [PATCH 081/111] Use fc::uint128_t instead of boost --- libraries/protocol/asset.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/protocol/asset.cpp b/libraries/protocol/asset.cpp index 4d670ecc97..0edd1c80d9 100644 --- a/libraries/protocol/asset.cpp +++ b/libraries/protocol/asset.cpp @@ -29,8 +29,8 @@ #include namespace graphene { namespace protocol { - typedef fc::uint128_t uint128_t; - typedef boost::multiprecision::int128_t int128_t; + using fc::uint128_t; + using fc::int128_t; bool operator == ( const price& a, const price& b ) { From 2288f2f79a3827ae007b58f8dcf70301deb2a06f Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Fri, 7 Jun 2019 22:31:02 +0200 Subject: [PATCH 082/111] Supplement native 128bit integers --- libraries/app/util.cpp | 2 +- libraries/chain/account_object.cpp | 2 +- libraries/chain/asset_object.cpp | 2 +- libraries/chain/db_maint.cpp | 10 +++++----- libraries/chain/db_market.cpp | 4 ++-- libraries/protocol/asset.cpp | 20 ++++++++++---------- libraries/protocol/fee_schedule.cpp | 2 +- libraries/protocol/operations.cpp | 2 +- 8 files changed, 22 insertions(+), 22 deletions(-) diff --git a/libraries/app/util.cpp b/libraries/app/util.cpp index fabfa26599..4d22dc8e3e 100644 --- a/libraries/app/util.cpp +++ b/libraries/app/util.cpp @@ -40,7 +40,7 @@ static fc::uint128_t to_capped_128( const uint256_t& t ) std::string uint128_amount_to_string( const fc::uint128_t& amount, const uint8_t precision ) { try { - std::string s = amount.str(); + std::string s = boost::lexical_cast(amount); if( precision == 0 || amount == fc::uint128_t() ) return s; diff --git a/libraries/chain/account_object.cpp b/libraries/chain/account_object.cpp index 76df1c6929..d72d29536a 100644 --- a/libraries/chain/account_object.cpp +++ b/libraries/chain/account_object.cpp @@ -39,7 +39,7 @@ share_type cut_fee(share_type a, uint16_t p) fc::uint128_t r = a.value; r *= p; r /= GRAPHENE_100_PERCENT; - return r.convert_to(); + return static_cast(r); } void account_balance_object::adjust_balance(const asset& delta) diff --git a/libraries/chain/asset_object.cpp b/libraries/chain/asset_object.cpp index 0232162781..50e874f858 100644 --- a/libraries/chain/asset_object.cpp +++ b/libraries/chain/asset_object.cpp @@ -41,7 +41,7 @@ share_type asset_bitasset_data_object::max_force_settlement_volume(share_type cu volume += force_settled_volume.value; volume *= options.maximum_force_settlement_volume; volume /= GRAPHENE_100_PERCENT; - return volume.convert_to(); + return static_cast(volume); } void graphene::chain::asset_bitasset_data_object::update_median_feeds( time_point_sec current_time, diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index 97d9a632ff..ea4dda3526 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -185,7 +185,7 @@ void database::pay_workers( share_type& budget ) fc::uint128_t pay = requested_pay.value; pay *= passed_time_count; pay /= day_count; - requested_pay = pay.convert_to(); + requested_pay = static_cast(pay); share_type actual_pay = std::min(budget, requested_pay); //ilog(" ==> Paying ${a} to worker ${w}", ("w", active_worker.id)("a", actual_pay)); @@ -440,7 +440,7 @@ void database::initialize_budget_record( fc::time_point_sec now, budget_record& budget_u128 += ((uint64_t(1) << GRAPHENE_CORE_ASSET_CYCLE_RATE_BITS) - 1); budget_u128 >>= GRAPHENE_CORE_ASSET_CYCLE_RATE_BITS; if( budget_u128 < reserve.value ) - rec.total_budget = share_type(budget_u128.convert_to()); + rec.total_budget = share_type(static_cast(budget_u128)); else rec.total_budget = reserve; @@ -495,7 +495,7 @@ void database::process_budget() if( worker_budget_u128 >= available_funds.value ) worker_budget = available_funds; else - worker_budget = worker_budget_u128.convert_to(); + worker_budget = static_cast(worker_budget_u128); rec.worker_budget = worker_budget; available_funds -= worker_budget; @@ -635,12 +635,12 @@ void split_fba_balance( fc::uint128_t buyback_amount_128 = fba.accumulated_fba_fees.value; buyback_amount_128 *= designated_asset_buyback_pct; buyback_amount_128 /= GRAPHENE_100_PERCENT; - share_type buyback_amount = buyback_amount_128.convert_to(); + share_type buyback_amount = static_cast(buyback_amount_128); fc::uint128_t issuer_amount_128 = fba.accumulated_fba_fees.value; issuer_amount_128 *= designated_asset_issuer_pct; issuer_amount_128 /= GRAPHENE_100_PERCENT; - share_type issuer_amount = issuer_amount_128.convert_to(); + share_type issuer_amount = static_cast(issuer_amount_128); // this assert should never fail FC_ASSERT( buyback_amount + issuer_amount <= fba.accumulated_fba_fees ); diff --git a/libraries/chain/db_market.cpp b/libraries/chain/db_market.cpp index b717446bd7..01579a87e3 100644 --- a/libraries/chain/db_market.cpp +++ b/libraries/chain/db_market.cpp @@ -42,7 +42,7 @@ namespace detail { a *= percent; a /= GRAPHENE_100_PERCENT; FC_ASSERT( a <= GRAPHENE_MAX_SHARE_SUPPLY, "overflow when calculating percent" ); - return a.convert_to(); + return static_cast(a); } } //detail @@ -264,7 +264,7 @@ void database::cancel_limit_order( const limit_order_object& order, bool create_ fee128 += order.deferred_fee.value; fee128 -= 1; fee128 /= order.deferred_fee.value; - share_type cancel_fee_amount = fee128.convert_to(); + share_type cancel_fee_amount = static_cast(fee128); // cancel_fee should be positive, pay it to asset's accumulated_fees fee_asset_dyn_data = &deferred_paid_fee.asset_id(*this).dynamic_asset_data_id(*this); modify( *fee_asset_dyn_data, [&](asset_dynamic_data_object& addo) { diff --git a/libraries/protocol/asset.cpp b/libraries/protocol/asset.cpp index 0edd1c80d9..71e7665563 100644 --- a/libraries/protocol/asset.cpp +++ b/libraries/protocol/asset.cpp @@ -63,14 +63,14 @@ namespace graphene { namespace protocol { FC_ASSERT( b.base.amount.value > 0 ); uint128_t result = (uint128_t(a.amount.value) * b.quote.amount.value)/b.base.amount.value; FC_ASSERT( result <= GRAPHENE_MAX_SHARE_SUPPLY ); - return asset( result.convert_to(), b.quote.asset_id ); + return asset( static_cast(result), b.quote.asset_id ); } else if( a.asset_id == b.quote.asset_id ) { FC_ASSERT( b.quote.amount.value > 0 ); uint128_t result = (uint128_t(a.amount.value) * b.base.amount.value)/b.quote.amount.value; FC_ASSERT( result <= GRAPHENE_MAX_SHARE_SUPPLY ); - return asset( result.convert_to(), b.base.asset_id ); + return asset( static_cast(result), b.base.asset_id ); } FC_THROW_EXCEPTION( fc::assert_exception, "invalid asset * price", ("asset",a)("price",b) ); } @@ -83,14 +83,14 @@ namespace graphene { namespace protocol { FC_ASSERT( b.base.amount.value > 0 ); uint128_t result = (uint128_t(a.amount.value) * b.quote.amount.value + b.base.amount.value - 1)/b.base.amount.value; FC_ASSERT( result <= GRAPHENE_MAX_SHARE_SUPPLY ); - return asset( result.convert_to(), b.quote.asset_id ); + return asset( static_cast(result), b.quote.asset_id ); } else if( a.asset_id == b.quote.asset_id ) { FC_ASSERT( b.quote.amount.value > 0 ); uint128_t result = (uint128_t(a.amount.value) * b.base.amount.value + b.quote.amount.value - 1)/b.quote.amount.value; FC_ASSERT( result <= GRAPHENE_MAX_SHARE_SUPPLY ); - return asset( result.convert_to(), b.base.asset_id ); + return asset( static_cast(result), b.base.asset_id ); } FC_THROW_EXCEPTION( fc::assert_exception, "invalid asset::multiply_and_round_up(price)", ("asset",a)("price",b) ); } @@ -171,8 +171,8 @@ namespace graphene { namespace protocol { } } - price np = asset( cp.numerator().convert_to(), p.base.asset_id ) - / asset( cp.denominator().convert_to(), p.quote.asset_id ); + price np = asset( static_cast(cp.numerator()), p.base.asset_id ) + / asset( static_cast(cp.denominator()), p.quote.asset_id ); if( shrinked || using_max ) { @@ -218,8 +218,8 @@ namespace graphene { namespace protocol { while( cp.numerator() > GRAPHENE_MAX_SHARE_SUPPLY || cp.denominator() > GRAPHENE_MAX_SHARE_SUPPLY ) cp = boost::rational( (cp.numerator() >> 1)+1, (cp.denominator() >> 1)+1 ); - return ( asset( cp.denominator().convert_to(), collateral.asset_id ) - / asset( cp.numerator().convert_to(), debt.asset_id ) ); + return ( asset( static_cast(cp.denominator()), collateral.asset_id ) + / asset( static_cast(cp.numerator()), debt.asset_id ) ); } FC_CAPTURE_AND_RETHROW( (debt)(collateral)(collateral_ratio) ) } bool price::is_null() const @@ -277,8 +277,8 @@ namespace graphene { namespace protocol { cp = boost::rational( (cp.numerator() >> 1)+(cp.numerator()&1), (cp.denominator() >> 1)+(cp.denominator()&1) ); - return ( asset( cp.numerator().convert_to(), settlement_price.base.asset_id ) - / asset( cp.denominator().convert_to(), settlement_price.quote.asset_id ) ); + return ( asset( static_cast(cp.numerator()), settlement_price.base.asset_id ) + / asset( static_cast(cp.denominator()), settlement_price.quote.asset_id ) ); } price price_feed::max_short_squeeze_price()const diff --git a/libraries/protocol/fee_schedule.cpp b/libraries/protocol/fee_schedule.cpp index 220e7fe8d1..0c7129dc4b 100644 --- a/libraries/protocol/fee_schedule.cpp +++ b/libraries/protocol/fee_schedule.cpp @@ -127,7 +127,7 @@ namespace graphene { namespace protocol { scaled /= GRAPHENE_100_PERCENT; FC_ASSERT( scaled <= GRAPHENE_MAX_SHARE_SUPPLY, "Required fee after scaling would exceed maximum possible supply" ); - required_fee = scaled.convert_to(); + required_fee = static_cast(scaled); } return asset( required_fee ); } diff --git a/libraries/protocol/operations.cpp b/libraries/protocol/operations.cpp index d24d43c4ae..d1b71232c6 100644 --- a/libraries/protocol/operations.cpp +++ b/libraries/protocol/operations.cpp @@ -34,7 +34,7 @@ uint64_t base_operation::calculate_data_fee( uint64_t bytes, uint64_t price_per_ { auto result = (fc::uint128_t(bytes) * price_per_kbyte) / 1024; FC_ASSERT( result <= GRAPHENE_MAX_SHARE_SUPPLY ); - return result.convert_to(); + return static_cast(result); } fc::optional< fc::future > base_operation::validate_parallel( uint32_t skip )const From 9c4a36e5880e2ed5c326738c270136f82b9ada71 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Sat, 8 Jun 2019 10:17:29 +0200 Subject: [PATCH 083/111] Removed obsolete unused header --- programs/cli_wallet/main.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/programs/cli_wallet/main.cpp b/programs/cli_wallet/main.cpp index 1cca772e9a..5a4f528c5b 100644 --- a/programs/cli_wallet/main.cpp +++ b/programs/cli_wallet/main.cpp @@ -31,7 +31,6 @@ #include #include #include -#include #include #include From b7bc8b8d609d2675a14723f041684cf72794aacc Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Sat, 8 Jun 2019 10:18:01 +0200 Subject: [PATCH 084/111] Enable native 128bit --- CMakeLists.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4540350f8e..696f36d8c7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,12 @@ set( INSTALLER_APP_ID "68ad7005-8eee-49c9-95ce-9eed97e5b347" ) set( CMAKE_CXX_STANDARD 14 ) set( CMAKE_CXX_STANDARD_REQUIRED ON ) -set( CMAKE_CXX_EXTENSIONS OFF ) + +if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" ) + set( CMAKE_CXX_EXTENSIONS ON ) # for __int128 support +else( GNU ) + set( CMAKE_CXX_EXTENSIONS OFF ) +endif( GNU ) # http://stackoverflow.com/a/18369825 if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") From 6be04cbedbc3de050995324c0d724146c345c0ac Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Wed, 19 Jun 2019 20:48:29 +0200 Subject: [PATCH 085/111] Fixed static_assert --- libraries/protocol/address.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/protocol/address.cpp b/libraries/protocol/address.cpp index d941c32bf5..a826289a1e 100644 --- a/libraries/protocol/address.cpp +++ b/libraries/protocol/address.cpp @@ -90,7 +90,7 @@ namespace graphene { namespace protocol { address::operator std::string()const { std::array bin_addr; - static_assert( bin_addr.size() >= sizeof(addr) + 4 ); + static_assert( bin_addr.size() >= sizeof(addr) + 4, "address size mismatch" ); memcpy( bin_addr.data(), addr.data(), sizeof(addr) ); auto checksum = fc::ripemd160::hash( addr.data(), sizeof(addr) ); memcpy( bin_addr.data() + 20, (char*)&checksum._hash[0], 4 ); From 5e71819c60deb384e131181bfaefa2f9883a16ce Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Fri, 2 Aug 2019 16:53:21 +0200 Subject: [PATCH 086/111] Removed unused _buf --- libraries/net/include/graphene/net/stcp_socket.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/net/include/graphene/net/stcp_socket.hpp b/libraries/net/include/graphene/net/stcp_socket.hpp index e2a0038375..fb4bfbc72b 100644 --- a/libraries/net/include/graphene/net/stcp_socket.hpp +++ b/libraries/net/include/graphene/net/stcp_socket.hpp @@ -63,8 +63,6 @@ class stcp_socket : public virtual fc::iostream fc::sha512 _shared_secret; fc::ecc::private_key _priv_key; - std::array _buf; - //uint32_t _buf_len; fc::tcp_socket _sock; fc::aes_encoder _send_aes; fc::aes_decoder _recv_aes; From 40414e5cd68c796b24910fe9e0ddfc55d395276c Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Thu, 8 Aug 2019 20:29:26 +0200 Subject: [PATCH 087/111] Use fc::variant for uint128->string conversion --- libraries/app/util.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/app/util.cpp b/libraries/app/util.cpp index 4d22dc8e3e..542e69f177 100644 --- a/libraries/app/util.cpp +++ b/libraries/app/util.cpp @@ -40,7 +40,7 @@ static fc::uint128_t to_capped_128( const uint256_t& t ) std::string uint128_amount_to_string( const fc::uint128_t& amount, const uint8_t precision ) { try { - std::string s = boost::lexical_cast(amount); + std::string s = fc::variant( amount, 2 ).as_string(); if( precision == 0 || amount == fc::uint128_t() ) return s; From f157218d6605463b4f85293b396631c9043181be Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Sun, 11 Aug 2019 12:16:13 +0200 Subject: [PATCH 088/111] Fix cmake warning --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 696f36d8c7..bd9db30bf5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,9 +14,9 @@ set( CMAKE_CXX_STANDARD_REQUIRED ON ) if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" ) set( CMAKE_CXX_EXTENSIONS ON ) # for __int128 support -else( GNU ) +else( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" ) set( CMAKE_CXX_EXTENSIONS OFF ) -endif( GNU ) +endif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" ) # http://stackoverflow.com/a/18369825 if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") From b9614a44846a45fc87ec6de4138b3046e24c54a6 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Tue, 13 Aug 2019 15:29:58 +0200 Subject: [PATCH 089/111] Bumped fc --- libraries/fc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/fc b/libraries/fc index b3904ad1fc..82af8b55bd 160000 --- a/libraries/fc +++ b/libraries/fc @@ -1 +1 @@ -Subproject commit b3904ad1fc9363628ca42855d57cc0c88ca83c71 +Subproject commit 82af8b55bdda6294fed6168350402cfab3f1af87 From 9014ba155929543f5e69e7742d644298e075d5b7 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Tue, 13 Aug 2019 17:38:28 +0200 Subject: [PATCH 090/111] Adapted signed_message for std:array --- libraries/wallet/wallet.cpp | 2 +- tests/cli/main.cpp | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index c7bbe40f1c..19844eb239 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -2751,7 +2751,7 @@ class wallet_api_impl encapsulated << "block=" << r.meta.block << '\n'; encapsulated << "timestamp=" << r.meta.time << '\n'; encapsulated << ENC_SIG; - encapsulated << fc::to_hex( (const char*)r.signature->data, r.signature->size() ) << '\n'; + encapsulated << fc::to_hex( (const char*)r.signature->data(), r.signature->size() ) << '\n'; encapsulated << ENC_FOOTER; return encapsulated.str(); diff --git a/tests/cli/main.cpp b/tests/cli/main.cpp index 13510a4c8d..c2c0278a43 100644 --- a/tests/cli/main.cpp +++ b/tests/cli/main.cpp @@ -1098,7 +1098,7 @@ static string encapsulate( const graphene::wallet::signed_message& msg ) << "block=" << msg.meta.block << '\n' << "timestamp=" << msg.meta.time << '\n' << "-----BEGIN SIGNATURE-----\n" - << fc::to_hex( (const char*)msg.signature->data, msg.signature->size() ) << '\n' + << fc::to_hex( (const char*)msg.signature->data(), msg.signature->size() ) << '\n' << "-----END BITSHARES SIGNED MESSAGE-----"; return encapsulated.str(); } @@ -1138,12 +1138,12 @@ BOOST_FIXTURE_TEST_CASE( cli_sign_message, cli_fixture ) msg.meta.account = "nathan"; // change key, verify failure - ++msg.meta.memo_key.key_data.data[1]; + ++msg.meta.memo_key.key_data.data()[1]; //BOOST_CHECK( !con.wallet_api_ptr->verify_message( msg.message, msg.meta.account, msg.meta.block, msg.meta.time, // *msg.signature ) ); BOOST_CHECK( !con.wallet_api_ptr->verify_signed_message( msg ) ); BOOST_CHECK( !con.wallet_api_ptr->verify_encapsulated_message( encapsulate( msg ) ) ); - --msg.meta.memo_key.key_data.data[1]; + --msg.meta.memo_key.key_data.data()[1]; // change block, verify failure ++msg.meta.block; @@ -1162,7 +1162,7 @@ BOOST_FIXTURE_TEST_CASE( cli_sign_message, cli_fixture ) --msg.meta.time[0]; // change signature, verify failure - ++msg.signature->data[1]; + ++msg.signature->data()[1]; try { BOOST_CHECK( !con.wallet_api_ptr->verify_message( msg.message, msg.meta.account, msg.meta.block, msg.meta.time, *msg.signature ) ); @@ -1173,7 +1173,7 @@ BOOST_FIXTURE_TEST_CASE( cli_sign_message, cli_fixture ) try { BOOST_CHECK( !con.wallet_api_ptr->verify_encapsulated_message( encapsulate( msg ) ) ); } catch( const fc::assert_exception& ) {} // failure to reconstruct key from signature is ok as well - --msg.signature->data[1]; + --msg.signature->data()[1]; // verify success BOOST_CHECK( con.wallet_api_ptr->verify_message( msg.message, msg.meta.account, msg.meta.block, msg.meta.time, From cd5e9e247953cf8687317b6d80a206c4bf48c9ba Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Tue, 13 Aug 2019 13:27:29 -0300 Subject: [PATCH 091/111] change category to Database API --- libraries/plugins/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/plugins/README.md b/libraries/plugins/README.md index c130f7219f..411bab9b13 100644 --- a/libraries/plugins/README.md +++ b/libraries/plugins/README.md @@ -11,7 +11,7 @@ Plugins are optional to run by node operator according to their needs. However, Folder | Name | Description | Category | Status | SpaceID -----------------------------------|--------------------------|-----------------------------------------------------------------------------|----------------|---------------|--------------| [account_history](account_history) | Account History | Save account history data | History | Stable | 4 -[api_helper_indexes](api_helper_indexes) | API Helper Indexes | Provides some helper indexes used by various API calls | Helper | Stable | +[api_helper_indexes](api_helper_indexes) | API Helper Indexes | Provides some helper indexes used by various API calls | Database API | Stable | [debug_witness](debug_witness) | Debug Witness | Run "what-if" tests | Debug | Stable | [delayed_node](delayed_node) | Delayed Node | Avoid forks by running a several times confirmed and delayed blockchain | Business | Stable | [elasticsearch](elasticsearch) | ElasticSearch Operations | Save account history data into elasticsearch database | History | Experimental | 6 From fa2248fdee366b48818899a3862744f6d800bbe2 Mon Sep 17 00:00:00 2001 From: abitmore Date: Tue, 13 Aug 2019 19:52:03 +0000 Subject: [PATCH 092/111] Requires api_helper_indexes plugin to start node or start with --ignore-api-helper-indexes-warning. Don't silently write warning messages to P2P log. --- libraries/app/database_api.cpp | 1 - programs/witness_node/main.cpp | 14 ++++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/libraries/app/database_api.cpp b/libraries/app/database_api.cpp index ab6889c7b3..0639cbaaa3 100644 --- a/libraries/app/database_api.cpp +++ b/libraries/app/database_api.cpp @@ -428,7 +428,6 @@ database_api_impl::database_api_impl( graphene::chain::database& db, const appli } catch( fc::assert_exception& e ) { - wlog( "amount_in_collateral_index not found - please enable api_helper_indexes plugin!" ); amount_in_collateral_index = nullptr; } } diff --git a/programs/witness_node/main.cpp b/programs/witness_node/main.cpp index acbda6386c..e961c2452a 100644 --- a/programs/witness_node/main.cpp +++ b/programs/witness_node/main.cpp @@ -71,7 +71,8 @@ int main(int argc, char** argv) { ("version,v", "Display version information") ("plugins", bpo::value() ->default_value("witness account_history market_history grouped_orders api_helper_indexes"), - "Space-separated list of plugins to activate"); + "Space-separated list of plugins to activate") + ("ignore-api-helper-indexes-warning", "Do not exit if api_helper_indexes plugin is not enabled."); bpo::variables_map options; @@ -82,7 +83,8 @@ int main(int argc, char** argv) { cfg_options.add_options() ("plugins", bpo::value() ->default_value("witness account_history market_history grouped_orders api_helper_indexes"), - "Space-separated list of plugins to activate"); + "Space-separated list of plugins to activate") + ("ignore-api-helper-indexes-warning", "Do not exit if api_helper_indexes plugin is not enabled."); auto witness_plug = node->register_plugin(); auto debug_witness_plug = node->register_plugin(); @@ -143,6 +145,14 @@ int main(int argc, char** argv) { return 1; } + if( !plugins.count("api_helper_indexes") && !options.count("ignore-api-helper-indexes-warning") ) + { + std::cerr << "\nIf this is an API node, please enable api_helper_indexes plugin." + "\nIf this is not an API node, please start with \"--ignore-api-helper-indexes-warning\"" + " or enable it in config.ini file.\n\n"; + return 1; + } + std::for_each(plugins.begin(), plugins.end(), [node](const std::string& plug) mutable { if (!plug.empty()) { node->enable_plugin(plug); From ebd5dbbdd17d80308d229873e347d8d8f7820781 Mon Sep 17 00:00:00 2001 From: abitmore Date: Tue, 13 Aug 2019 20:37:04 +0000 Subject: [PATCH 093/111] Update comments, wrap long lines --- libraries/app/database_api.cpp | 5 +++-- libraries/app/include/graphene/app/database_api.hpp | 8 ++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/libraries/app/database_api.cpp b/libraries/app/database_api.cpp index 9e57c59858..be1ba4cb2f 100644 --- a/libraries/app/database_api.cpp +++ b/libraries/app/database_api.cpp @@ -89,7 +89,8 @@ class database_api_impl : public std::enable_shared_from_this account_id_type get_account_id_from_string(const std::string& name_or_id)const; vector> get_accounts( const vector& account_names_or_ids, optional subscribe )const; - std::map get_full_accounts( const vector& names_or_ids, optional subscribe ); + std::map get_full_accounts( const vector& names_or_ids, + optional subscribe ); optional get_account_by_name( string name )const; vector get_account_references( const std::string account_id_or_name )const; vector> lookup_account_names(const vector& account_names)const; @@ -1198,7 +1199,7 @@ map database_api_impl::lookup_accounts( const string& lo if( limit == 0 ) // shortcut to save a database query return result; - // auto-subscribe if only look for one account + // In addition to the common auto-subscription rules, here we auto-subscribe if only look for one account bool to_subscribe = (limit == 1 && get_whether_to_subscribe( subscribe )); for( auto itr = accounts_by_name.lower_bound(lower_bound_name); limit-- && itr != accounts_by_name.end(); diff --git a/libraries/app/include/graphene/app/database_api.hpp b/libraries/app/include/graphene/app/database_api.hpp index be126e5348..519f641b5a 100644 --- a/libraries/app/include/graphene/app/database_api.hpp +++ b/libraries/app/include/graphene/app/database_api.hpp @@ -160,10 +160,13 @@ class database_api * @a null to subscribe or not subscribe according to current auto-subscription setting * (see @ref set_auto_subscription) * @return The objects retrieved, in the order they are mentioned in ids + * @note operation_history_object (1.11.x) and account_transaction_history_object (2.9.x) + * can not be subscribed. * * If any of the provided IDs does not map to an object, a null variant is returned in its position. */ - fc::variants get_objects( const vector& ids, optional subscribe = optional() )const; + fc::variants get_objects( const vector& ids, + optional subscribe = optional() )const; /////////////////// // Subscriptions // @@ -385,7 +388,8 @@ class database_api * (see @ref set_auto_subscription) * @return Map of account names to corresponding IDs * - * Note: this API will subscribe to the queried account only if @p limit is 1. + * @note In addition to the common auto-subscription rules, + * this API will subscribe to the returned account only if @p limit is 1. */ map lookup_accounts( const string& lower_bound_name, uint32_t limit, From 8a3fad7dbc43710f0559e784f38fea2e9a827d19 Mon Sep 17 00:00:00 2001 From: John Jones Date: Wed, 14 Aug 2019 07:43:43 -0500 Subject: [PATCH 094/111] bump FC for Boost 1.70 --- libraries/fc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/fc b/libraries/fc index 82af8b55bd..91d8772b7b 160000 --- a/libraries/fc +++ b/libraries/fc @@ -1 +1 @@ -Subproject commit 82af8b55bdda6294fed6168350402cfab3f1af87 +Subproject commit 91d8772b7b09819b59893d645d01fe181923693d From e7df677a5e963286d314f08f4f7fca5fcf5d7072 Mon Sep 17 00:00:00 2001 From: abitmore Date: Wed, 14 Aug 2019 15:27:51 +0000 Subject: [PATCH 095/111] Requires api_helper_indexes only if enabled RPC --- programs/witness_node/main.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/programs/witness_node/main.cpp b/programs/witness_node/main.cpp index e961c2452a..d3996e73c6 100644 --- a/programs/witness_node/main.cpp +++ b/programs/witness_node/main.cpp @@ -145,7 +145,8 @@ int main(int argc, char** argv) { return 1; } - if( !plugins.count("api_helper_indexes") && !options.count("ignore-api-helper-indexes-warning") ) + if( !plugins.count("api_helper_indexes") && !options.count("ignore-api-helper-indexes-warning") + && ( options.count("rpc-endpoint") || options.count("rpc-tls-endpoint") ) ) { std::cerr << "\nIf this is an API node, please enable api_helper_indexes plugin." "\nIf this is not an API node, please start with \"--ignore-api-helper-indexes-warning\"" From f721cdc6f616546722368ea8d0ba75cb4e273f98 Mon Sep 17 00:00:00 2001 From: abitmore Date: Fri, 9 Aug 2019 10:33:51 -0400 Subject: [PATCH 096/111] Rename full_account.hpp to api_objects.hpp --- .../include/graphene/app/{full_account.hpp => api_objects.hpp} | 0 libraries/app/include/graphene/app/database_api.hpp | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename libraries/app/include/graphene/app/{full_account.hpp => api_objects.hpp} (100%) diff --git a/libraries/app/include/graphene/app/full_account.hpp b/libraries/app/include/graphene/app/api_objects.hpp similarity index 100% rename from libraries/app/include/graphene/app/full_account.hpp rename to libraries/app/include/graphene/app/api_objects.hpp diff --git a/libraries/app/include/graphene/app/database_api.hpp b/libraries/app/include/graphene/app/database_api.hpp index 519f641b5a..ed8d771429 100644 --- a/libraries/app/include/graphene/app/database_api.hpp +++ b/libraries/app/include/graphene/app/database_api.hpp @@ -23,7 +23,7 @@ */ #pragma once -#include +#include #include From ba0dca6f642698fa412721dff69f00cea64d9e42 Mon Sep 17 00:00:00 2001 From: abitmore Date: Fri, 9 Aug 2019 10:46:02 -0400 Subject: [PATCH 097/111] Move definitions of API objects to api_objects.hpp --- libraries/app/database_api.cpp | 4 - .../app/include/graphene/app/api_objects.hpp | 86 +++++++++++++++++- .../app/include/graphene/app/database_api.hpp | 87 ------------------- 3 files changed, 85 insertions(+), 92 deletions(-) diff --git a/libraries/app/database_api.cpp b/libraries/app/database_api.cpp index fe879b731e..fd23d34372 100644 --- a/libraries/app/database_api.cpp +++ b/libraries/app/database_api.cpp @@ -26,19 +26,15 @@ #include #include #include -#include #include #include #include #include -#include #include -#include #include - #include #include diff --git a/libraries/app/include/graphene/app/api_objects.hpp b/libraries/app/include/graphene/app/api_objects.hpp index 4618ef84a1..af7a96e1ab 100644 --- a/libraries/app/include/graphene/app/api_objects.hpp +++ b/libraries/app/include/graphene/app/api_objects.hpp @@ -24,15 +24,21 @@ #pragma once #include +#include #include -#include #include #include #include #include +#include +#include + +#include + namespace graphene { namespace app { using namespace graphene::chain; + using namespace graphene::market_history; struct more_data { @@ -72,6 +78,74 @@ namespace graphene { namespace app { more_data more_data_available; }; + struct order + { + string price; + string quote; + string base; + }; + + struct order_book + { + string base; + string quote; + vector< order > bids; + vector< order > asks; + }; + + struct market_ticker + { + time_point_sec time; + string base; + string quote; + string latest; + string lowest_ask; + string highest_bid; + string percent_change; + string base_volume; + string quote_volume; + + market_ticker() {} + market_ticker(const market_ticker_object& mto, + const fc::time_point_sec& now, + const asset_object& asset_base, + const asset_object& asset_quote, + const order_book& orders); + market_ticker(const fc::time_point_sec& now, + const asset_object& asset_base, + const asset_object& asset_quote); + }; + + struct market_volume + { + time_point_sec time; + string base; + string quote; + string base_volume; + string quote_volume; + }; + + struct market_trade + { + int64_t sequence = 0; + fc::time_point_sec date; + string price; + string amount; + string value; + account_id_type side1_account_id = GRAPHENE_NULL_ACCOUNT; + account_id_type side2_account_id = GRAPHENE_NULL_ACCOUNT; + }; + + struct extended_asset_object : asset_object + { + extended_asset_object() {} + explicit extended_asset_object( const asset_object& a ) : asset_object( a ) {} + explicit extended_asset_object( asset_object&& a ) : asset_object( std::move(a) ) {} + + optional total_in_collateral; + optional total_backing_collateral; + }; + } } FC_REFLECT( graphene::app::more_data, @@ -100,3 +174,13 @@ FC_REFLECT( graphene::app::full_account, (htlcs_to) (more_data_available) ) + +FC_REFLECT( graphene::app::order, (price)(quote)(base) ); +FC_REFLECT( graphene::app::order_book, (base)(quote)(bids)(asks) ); +FC_REFLECT( graphene::app::market_ticker, + (time)(base)(quote)(latest)(lowest_ask)(highest_bid)(percent_change)(base_volume)(quote_volume) ); +FC_REFLECT( graphene::app::market_volume, (time)(base)(quote)(base_volume)(quote_volume) ); +FC_REFLECT( graphene::app::market_trade, (sequence)(date)(price)(amount)(value)(side1_account_id)(side2_account_id) ); + +FC_REFLECT_DERIVED( graphene::app::extended_asset_object, (graphene::chain::asset_object), + (total_in_collateral)(total_backing_collateral) ); diff --git a/libraries/app/include/graphene/app/database_api.hpp b/libraries/app/include/graphene/app/database_api.hpp index ed8d771429..1960e64824 100644 --- a/libraries/app/include/graphene/app/database_api.hpp +++ b/libraries/app/include/graphene/app/database_api.hpp @@ -29,24 +29,15 @@ #include -#include -#include #include #include #include #include -#include #include -#include #include #include -#include - -#include -#include #include -#include #include #include @@ -68,74 +59,6 @@ using std::map; class database_api_impl; -struct order -{ - string price; - string quote; - string base; -}; - -struct order_book -{ - string base; - string quote; - vector< order > bids; - vector< order > asks; -}; - -struct market_ticker -{ - time_point_sec time; - string base; - string quote; - string latest; - string lowest_ask; - string highest_bid; - string percent_change; - string base_volume; - string quote_volume; - - market_ticker() {} - market_ticker(const market_ticker_object& mto, - const fc::time_point_sec& now, - const asset_object& asset_base, - const asset_object& asset_quote, - const order_book& orders); - market_ticker(const fc::time_point_sec& now, - const asset_object& asset_base, - const asset_object& asset_quote); -}; - -struct market_volume -{ - time_point_sec time; - string base; - string quote; - string base_volume; - string quote_volume; -}; - -struct market_trade -{ - int64_t sequence = 0; - fc::time_point_sec date; - string price; - string amount; - string value; - account_id_type side1_account_id = GRAPHENE_NULL_ACCOUNT; - account_id_type side2_account_id = GRAPHENE_NULL_ACCOUNT; -}; - -struct extended_asset_object : asset_object -{ - extended_asset_object() {} - explicit extended_asset_object( const asset_object& a ) : asset_object( a ) {} - explicit extended_asset_object( asset_object&& a ) : asset_object( std::move(a) ) {} - - optional total_in_collateral; - optional total_backing_collateral; -}; - /** * @brief The database_api class implements the RPC API for the chain database. * @@ -972,16 +895,6 @@ class database_api extern template class fc::api; -FC_REFLECT( graphene::app::order, (price)(quote)(base) ); -FC_REFLECT( graphene::app::order_book, (base)(quote)(bids)(asks) ); -FC_REFLECT( graphene::app::market_ticker, - (time)(base)(quote)(latest)(lowest_ask)(highest_bid)(percent_change)(base_volume)(quote_volume) ); -FC_REFLECT( graphene::app::market_volume, (time)(base)(quote)(base_volume)(quote_volume) ); -FC_REFLECT( graphene::app::market_trade, (sequence)(date)(price)(amount)(value)(side1_account_id)(side2_account_id) ); - -FC_REFLECT_DERIVED( graphene::app::extended_asset_object, (graphene::chain::asset_object), - (total_in_collateral)(total_backing_collateral) ); - FC_API(graphene::app::database_api, // Objects (get_objects) From 2796149c6a37eb686952f6f7c124f321802316d8 Mon Sep 17 00:00:00 2001 From: abitmore Date: Fri, 9 Aug 2019 11:40:26 -0400 Subject: [PATCH 098/111] Move some code from database_api.cpp to others Move market_ticket constrctors to api_objects.cpp; move price_to_string(...) to util.hpp and util.cpp. --- libraries/app/CMakeLists.txt | 1 + libraries/app/api_objects.cpp | 91 +++++++++++++++++++++ libraries/app/database_api.cpp | 76 ----------------- libraries/app/include/graphene/app/util.hpp | 13 ++- libraries/app/util.cpp | 17 +++- 5 files changed, 119 insertions(+), 79 deletions(-) create mode 100644 libraries/app/api_objects.cpp diff --git a/libraries/app/CMakeLists.txt b/libraries/app/CMakeLists.txt index e8dd9cad09..71762b1d90 100644 --- a/libraries/app/CMakeLists.txt +++ b/libraries/app/CMakeLists.txt @@ -3,6 +3,7 @@ file(GLOB EGENESIS_HEADERS "../egenesis/include/graphene/app/*.hpp") add_library( graphene_app api.cpp + api_objects.cpp application.cpp util.cpp database_api.cpp diff --git a/libraries/app/api_objects.cpp b/libraries/app/api_objects.cpp new file mode 100644 index 0000000000..e002f061ae --- /dev/null +++ b/libraries/app/api_objects.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2017 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 + +namespace graphene { namespace app { + +market_ticker::market_ticker(const market_ticker_object& mto, + const fc::time_point_sec& now, + const asset_object& asset_base, + const asset_object& asset_quote, + const order_book& orders) +{ + time = now; + base = asset_base.symbol; + quote = asset_quote.symbol; + percent_change = "0"; + lowest_ask = "0"; + highest_bid = "0"; + + fc::uint128_t bv; + fc::uint128_t qv; + price latest_price = asset( mto.latest_base, mto.base ) / asset( mto.latest_quote, mto.quote ); + if( mto.base != asset_base.id ) + latest_price = ~latest_price; + latest = price_to_string( latest_price, asset_base, asset_quote ); + if( mto.last_day_base != 0 && mto.last_day_quote != 0 // has trade data before 24 hours + && ( mto.last_day_base != mto.latest_base || mto.last_day_quote != mto.latest_quote ) ) // price changed + { + price last_day_price = asset( mto.last_day_base, mto.base ) / asset( mto.last_day_quote, mto.quote ); + if( mto.base != asset_base.id ) + last_day_price = ~last_day_price; + percent_change = price_diff_percent_string( last_day_price, latest_price ); + } + if( asset_base.id == mto.base ) + { + bv = mto.base_volume; + qv = mto.quote_volume; + } + else + { + bv = mto.quote_volume; + qv = mto.base_volume; + } + base_volume = uint128_amount_to_string( bv, asset_base.precision ); + quote_volume = uint128_amount_to_string( qv, asset_quote.precision ); + + if(!orders.asks.empty()) + lowest_ask = orders.asks[0].price; + if(!orders.bids.empty()) + highest_bid = orders.bids[0].price; +} + +market_ticker::market_ticker(const fc::time_point_sec& now, + const asset_object& asset_base, + const asset_object& asset_quote) +{ + time = now; + base = asset_base.symbol; + quote = asset_quote.symbol; + latest = "0"; + lowest_ask = "0"; + highest_bid = "0"; + percent_change = "0"; + base_volume = "0"; + quote_volume = "0"; +} + +} } // graphene::app diff --git a/libraries/app/database_api.cpp b/libraries/app/database_api.cpp index fd23d34372..48c8bc2ff3 100644 --- a/libraries/app/database_api.cpp +++ b/libraries/app/database_api.cpp @@ -186,7 +186,6 @@ class database_api_impl : public std::enable_shared_from_this vector list_htlcs(const htlc_id_type lower_bound_id, uint32_t limit) const; //private: - static string price_to_string( const price& _price, const asset_object& _base, const asset_object& _quote ); // Decides whether to subscribe using member variables and given parameter bool get_whether_to_subscribe( optional subscribe )const @@ -450,71 +449,6 @@ database_api_impl::~database_api_impl() dlog("freeing database api ${x}", ("x",int64_t(this)) ); } -////////////////////////////////////////////////////////////////////// -// // -// Market ticker constructor // -// // -////////////////////////////////////////////////////////////////////// -market_ticker::market_ticker(const market_ticker_object& mto, - const fc::time_point_sec& now, - const asset_object& asset_base, - const asset_object& asset_quote, - const order_book& orders) -{ - time = now; - base = asset_base.symbol; - quote = asset_quote.symbol; - percent_change = "0"; - lowest_ask = "0"; - highest_bid = "0"; - - fc::uint128_t bv; - fc::uint128_t qv; - price latest_price = asset( mto.latest_base, mto.base ) / asset( mto.latest_quote, mto.quote ); - if( mto.base != asset_base.id ) - latest_price = ~latest_price; - latest = database_api_impl::price_to_string( latest_price, asset_base, asset_quote ); - if( mto.last_day_base != 0 && mto.last_day_quote != 0 // has trade data before 24 hours - && ( mto.last_day_base != mto.latest_base || mto.last_day_quote != mto.latest_quote ) ) // price changed - { - price last_day_price = asset( mto.last_day_base, mto.base ) / asset( mto.last_day_quote, mto.quote ); - if( mto.base != asset_base.id ) - last_day_price = ~last_day_price; - percent_change = price_diff_percent_string( last_day_price, latest_price ); - } - if( asset_base.id == mto.base ) - { - bv = mto.base_volume; - qv = mto.quote_volume; - } - else - { - bv = mto.quote_volume; - qv = mto.base_volume; - } - base_volume = uint128_amount_to_string( bv, asset_base.precision ); - quote_volume = uint128_amount_to_string( qv, asset_quote.precision ); - - if(!orders.asks.empty()) - lowest_ask = orders.asks[0].price; - if(!orders.bids.empty()) - highest_bid = orders.bids[0].price; -} -market_ticker::market_ticker(const fc::time_point_sec& now, - const asset_object& asset_base, - const asset_object& asset_quote) -{ - time = now; - base = asset_base.symbol; - quote = asset_quote.symbol; - latest = "0"; - lowest_ask = "0"; - highest_bid = "0"; - percent_change = "0"; - base_volume = "0"; - quote_volume = "0"; -} - ////////////////////////////////////////////////////////////////////// // // // Objects // @@ -1650,16 +1584,6 @@ void database_api_impl::unsubscribe_from_market(const std::string& a, const std: _market_subscriptions.erase(std::make_pair(asset_a_id,asset_b_id)); } -string database_api_impl::price_to_string( const price& _price, const asset_object& _base, const asset_object& _quote ) -{ try { - if( _price.base.asset_id == _base.id && _price.quote.asset_id == _quote.id ) - return graphene::app::price_to_string( _price, _base.precision, _quote.precision ); - else if( _price.base.asset_id == _quote.id && _price.quote.asset_id == _base.id ) - return graphene::app::price_to_string( ~_price, _base.precision, _quote.precision ); - else - FC_ASSERT( !"bad parameters" ); -} FC_CAPTURE_AND_RETHROW( (_price)(_base)(_quote) ) } - market_ticker database_api::get_ticker( const string& base, const string& quote )const { return my->get_ticker( base, quote ); diff --git a/libraries/app/include/graphene/app/util.hpp b/libraries/app/include/graphene/app/util.hpp index 1513be9d10..a92b51588f 100644 --- a/libraries/app/include/graphene/app/util.hpp +++ b/libraries/app/include/graphene/app/util.hpp @@ -29,9 +29,18 @@ namespace graphene { namespace protocol { struct price; } +namespace chain { + struct asset_object; +} namespace app { std::string uint128_amount_to_string( const fc::uint128_t& amount, const uint8_t precision ); - std::string price_to_string( const graphene::protocol::price& _price, const uint8_t base_precision, const uint8_t quote_precision); - std::string price_diff_percent_string( const graphene::protocol::price& old_price, const graphene::protocol::price& new_price ); + std::string price_to_string( const graphene::protocol::price& _price, + const uint8_t base_precision, + const uint8_t quote_precision ); + std::string price_to_string( const graphene::protocol::price& _price, + const graphene::chain::asset_object& _base, + const graphene::chain::asset_object& _quote ); + std::string price_diff_percent_string( const graphene::protocol::price& old_price, + const graphene::protocol::price& new_price ); } } diff --git a/libraries/app/util.cpp b/libraries/app/util.cpp index 542e69f177..006bdab500 100644 --- a/libraries/app/util.cpp +++ b/libraries/app/util.cpp @@ -26,6 +26,7 @@ #include #include +#include namespace graphene { namespace app { @@ -64,7 +65,9 @@ std::string uint128_amount_to_string( const fc::uint128_t& amount, const uint8_t return ss.str(); } FC_CAPTURE_AND_RETHROW( (amount)(precision) ) } -std::string price_to_string( const graphene::protocol::price& _price, const uint8_t base_precision, const uint8_t quote_precision ) +std::string price_to_string( const graphene::protocol::price& _price, + const uint8_t base_precision, + const uint8_t quote_precision ) { try { if( _price.base.amount == 0 ) return "0"; @@ -86,6 +89,18 @@ std::string price_to_string( const graphene::protocol::price& _price, const uint return uint128_amount_to_string( price128, 19 + base_precision - quote_precision ); } FC_CAPTURE_AND_RETHROW( (_price)(base_precision)(quote_precision) ) } +std::string price_to_string( const graphene::protocol::price& _price, + const graphene::chain::asset_object& _base, + const graphene::chain::asset_object& _quote ) +{ try { + if( _price.base.asset_id == _base.id && _price.quote.asset_id == _quote.id ) + return price_to_string( _price, _base.precision, _quote.precision ); + else if( _price.base.asset_id == _quote.id && _price.quote.asset_id == _base.id ) + return price_to_string( ~_price, _base.precision, _quote.precision ); + else + FC_ASSERT( !"bad parameters" ); +} FC_CAPTURE_AND_RETHROW( (_price)(_base)(_quote) ) } + std::string price_diff_percent_string( const graphene::protocol::price& old_price, const graphene::protocol::price& new_price ) { try { From e5ae949e1c4bf54774964e25cc19a5a64a0fbafd Mon Sep 17 00:00:00 2001 From: abitmore Date: Fri, 9 Aug 2019 12:48:28 -0400 Subject: [PATCH 099/111] Create database_api_impl.hxx and move code into it --- libraries/app/database_api.cpp | 697 ++++++++++------------------ libraries/app/database_api_impl.hxx | 370 +++++++++++++++ 2 files changed, 628 insertions(+), 439 deletions(-) create mode 100644 libraries/app/database_api_impl.hxx diff --git a/libraries/app/database_api.cpp b/libraries/app/database_api.cpp index 48c8bc2ff3..e68c271892 100644 --- a/libraries/app/database_api.cpp +++ b/libraries/app/database_api.cpp @@ -22,15 +22,15 @@ * THE SOFTWARE. */ +#include "database_api_impl.hxx" + #include #include #include #include #include -#include #include -#include #include @@ -38,371 +38,10 @@ #include #include -#define GET_REQUIRED_FEES_MAX_RECURSION 4 - -typedef std::map< std::pair, std::vector > market_queue_type; - template class fc::api; namespace graphene { namespace app { -class database_api_impl : public std::enable_shared_from_this -{ - public: - explicit database_api_impl( graphene::chain::database& db, const application_options* app_options ); - ~database_api_impl(); - - - // Objects - fc::variants get_objects( const vector& ids, optional subscribe )const; - - // Subscriptions - void set_subscribe_callback( std::function cb, bool notify_remove_create ); - void set_auto_subscription( bool enable ); - void set_pending_transaction_callback( std::function cb ); - void set_block_applied_callback( std::function cb ); - void cancel_all_subscriptions(bool reset_callback, bool reset_market_subscriptions); - - // Blocks and transactions - optional get_block_header(uint32_t block_num)const; - map> get_block_header_batch(const vector block_nums)const; - optional get_block(uint32_t block_num)const; - processed_transaction get_transaction( uint32_t block_num, uint32_t trx_in_block )const; - - // Globals - chain_property_object get_chain_properties()const; - global_property_object get_global_properties()const; - fc::variant_object get_config()const; - chain_id_type get_chain_id()const; - dynamic_global_property_object get_dynamic_global_properties()const; - - // Keys - vector> get_key_references( vector key )const; - bool is_public_key_registered(string public_key) const; - - // Accounts - account_id_type get_account_id_from_string(const std::string& name_or_id)const; - vector> get_accounts( const vector& account_names_or_ids, - optional subscribe )const; - std::map get_full_accounts( const vector& names_or_ids, - optional subscribe ); - optional get_account_by_name( string name )const; - vector get_account_references( const std::string account_id_or_name )const; - vector> lookup_account_names(const vector& account_names)const; - map lookup_accounts( const string& lower_bound_name, - uint32_t limit, - optional subscribe )const; - uint64_t get_account_count()const; - - // Balances - vector get_account_balances(const std::string& account_name_or_id, const flat_set& assets)const; - vector get_named_account_balances(const std::string& name, const flat_set& assets)const; - vector get_balance_objects( const vector
& addrs )const; - vector get_vested_balances( const vector& objs )const; - vector get_vesting_balances( const std::string account_id_or_name )const; - - // Assets - uint64_t get_asset_count()const; - asset_id_type get_asset_id_from_string(const std::string& symbol_or_id)const; - vector> get_assets( const vector& asset_symbols_or_ids, - optional subscribe )const; - vector list_assets(const string& lower_bound_symbol, uint32_t limit)const; - vector> lookup_asset_symbols(const vector& symbols_or_ids)const; - vector get_assets_by_issuer(const std::string& issuer_name_or_id, - asset_id_type start, uint32_t limit)const; - - // Markets / feeds - vector get_limit_orders(const std::string& a, const std::string& b, uint32_t limit)const; - vector get_account_limit_orders( const string& account_name_or_id, - const string &base, - const string "e, uint32_t limit, - optional ostart_id, - optional ostart_price ); - vector get_call_orders(const std::string& a, uint32_t limit)const; - vector get_call_orders_by_account(const std::string& account_name_or_id, - asset_id_type start, uint32_t limit)const; - vector get_settle_orders(const std::string& a, uint32_t limit)const; - vector get_settle_orders_by_account(const std::string& account_name_or_id, - force_settlement_id_type start, uint32_t limit)const; - vector get_margin_positions( const std::string account_id_or_name )const; - vector get_collateral_bids(const std::string& asset, uint32_t limit, uint32_t start)const; - - void subscribe_to_market(std::function callback, const std::string& a, const std::string& b); - void unsubscribe_from_market(const std::string& a, const std::string& b); - - market_ticker get_ticker( const string& base, const string& quote, bool skip_order_book = false )const; - market_volume get_24_volume( const string& base, const string& quote )const; - order_book get_order_book( const string& base, const string& quote, unsigned limit = 50 )const; - vector get_top_markets( uint32_t limit )const; - vector get_trade_history( const string& base, const string& quote, fc::time_point_sec start, fc::time_point_sec stop, unsigned limit = 100 )const; - vector get_trade_history_by_sequence( const string& base, const string& quote, int64_t start, fc::time_point_sec stop, unsigned limit = 100 )const; - - // Witnesses - vector> get_witnesses(const vector& witness_ids)const; - fc::optional get_witness_by_account(const std::string account_id_or_name)const; - map lookup_witness_accounts(const string& lower_bound_name, uint32_t limit)const; - uint64_t get_witness_count()const; - - // Committee members - vector> get_committee_members(const vector& committee_member_ids)const; - fc::optional get_committee_member_by_account(const std::string account_id_or_name)const; - map lookup_committee_member_accounts(const string& lower_bound_name, uint32_t limit)const; - uint64_t get_committee_count()const; - - // Workers - vector get_all_workers()const; - vector> get_workers_by_account(const std::string account_id_or_name)const; - uint64_t get_worker_count()const; - - // Votes - vector lookup_vote_ids( const vector& votes )const; - - // Authority / validation - std::string get_transaction_hex(const signed_transaction& trx)const; - std::string get_transaction_hex_without_sig(const signed_transaction& trx)const; - - set get_required_signatures( const signed_transaction& trx, const flat_set& available_keys )const; - set get_potential_signatures( const signed_transaction& trx )const; - set
get_potential_address_signatures( const signed_transaction& trx )const; - bool verify_authority( const signed_transaction& trx )const; - bool verify_account_authority( const string& account_name_or_id, const flat_set& signers )const; - processed_transaction validate_transaction( const signed_transaction& trx )const; - vector< fc::variant > get_required_fees( const vector& ops, const std::string& asset_id_or_symbol )const; - - // Proposed transactions - vector get_proposed_transactions( const std::string account_id_or_name )const; - - // Blinded balances - vector get_blinded_balances( const flat_set& commitments )const; - - // Withdrawals - vector get_withdraw_permissions_by_giver(const std::string account_id_or_name, withdraw_permission_id_type start, uint32_t limit)const; - vector get_withdraw_permissions_by_recipient(const std::string account_id_or_name, withdraw_permission_id_type start, uint32_t limit)const; - - // HTLC - optional get_htlc( htlc_id_type id, optional subscribe ) const; - vector get_htlc_by_from(const std::string account_id_or_name, htlc_id_type start, uint32_t limit) const; - vector get_htlc_by_to(const std::string account_id_or_name, htlc_id_type start, uint32_t limit) const; - vector list_htlcs(const htlc_id_type lower_bound_id, uint32_t limit) const; - - //private: - - // Decides whether to subscribe using member variables and given parameter - bool get_whether_to_subscribe( optional subscribe )const - { - if( !_subscribe_callback ) - return false; - if( subscribe.valid() ) - return *subscribe; - return _enabled_auto_subscription; - } - - // Note: - // Different type of object_id objects could become identical after packed. - // For example, both `account_id_type a=1.2.0` and `asset_id_type b=1.3.0` will become `0` after packed. - // In order to avoid collision, we don't use a template function here, instead, we implicitly convert all - // object IDs to `object_id_type` when subscribing. - // - // If need to subscribe to other data types, override this function with the types as parameter. - // For example, we had a `get_subscription_key( const public_key_type& item )` function here, which was - // removed lately since we no longer subscribe to public keys. - vector get_subscription_key( const object_id_type& item )const - { - return fc::raw::pack(item); - } - - template - void subscribe_to_item( const T& item )const - { - if( !_subscribe_callback ) - return; - - vector key = get_subscription_key( item ); - if( !_subscribe_filter.contains( key.data(), key.size() ) ) - { - _subscribe_filter.insert( key.data(), key.size() ); - } - } - - template - bool is_subscribed_to_item( const T& item )const - { - if( !_subscribe_callback ) - return false; - - vector key = get_subscription_key( item ); - return _subscribe_filter.contains( key.data(), key.size() ); - } - - bool is_impacted_account( const flat_set& accounts) - { - if( !_subscribed_accounts.size() || !accounts.size() ) - return false; - - return std::any_of(accounts.begin(), accounts.end(), [this](const account_id_type& account) { - return _subscribed_accounts.find(account) != _subscribed_accounts.end(); - }); - } - - const std::pair get_order_market( const force_settlement_object& order ) - { - // TODO cache the result to avoid repeatly fetching from db - asset_id_type backing_id = order.balance.asset_id( _db ).bitasset_data( _db ).options.short_backing_asset; - auto tmp = std::make_pair( order.balance.asset_id, backing_id ); - if( tmp.first > tmp.second ) std::swap( tmp.first, tmp.second ); - return tmp; - } - - const account_object* get_account_from_string( const std::string& name_or_id, bool throw_if_not_found = true ) const - { - // TODO cache the result to avoid repeatly fetching from db - FC_ASSERT( name_or_id.size() > 0); - const account_object* account = nullptr; - if (std::isdigit(name_or_id[0])) - account = _db.find(fc::variant(name_or_id, 1).as(1)); - else - { - const auto& idx = _db.get_index_type().indices().get(); - auto itr = idx.find(name_or_id); - if (itr != idx.end()) - account = &*itr; - } - if(throw_if_not_found) - FC_ASSERT( account, "no such account" ); - return account; - } - - template - extended_asset_object extend_asset( ASSET&& a )const - { - asset_id_type id = a.id; - extended_asset_object result = extended_asset_object( std::forward( a ) ); - if( amount_in_collateral_index ) - { - result.total_in_collateral = amount_in_collateral_index->get_amount_in_collateral( id ); - if( result.bitasset_data_id.valid() ) - result.total_backing_collateral = amount_in_collateral_index->get_backing_collateral( id ); - } - return result; - } - - const asset_object* get_asset_from_string( const std::string& symbol_or_id, bool throw_if_not_found = true ) const - { - // TODO cache the result to avoid repeatly fetching from db - FC_ASSERT( symbol_or_id.size() > 0); - const asset_object* asset = nullptr; - if (std::isdigit(symbol_or_id[0])) - asset = _db.find(fc::variant(symbol_or_id, 1).as(1)); - else - { - const auto& idx = _db.get_index_type().indices().get(); - auto itr = idx.find(symbol_or_id); - if (itr != idx.end()) - asset = &*itr; - } - if(throw_if_not_found) - FC_ASSERT( asset, "no such asset" ); - return asset; - } - vector> get_assets( const vector& asset_ids, - optional subscribe = optional() )const - { - bool to_subscribe = get_whether_to_subscribe( subscribe ); - vector> result; result.reserve(asset_ids.size()); - std::transform(asset_ids.begin(), asset_ids.end(), std::back_inserter(result), - [this,to_subscribe](asset_id_type id) -> optional { - if(auto o = _db.find(id)) - { - if( to_subscribe ) - subscribe_to_item( id ); - return extend_asset( *o ); - } - return {}; - }); - return result; - } - vector get_limit_orders(const asset_id_type a, const asset_id_type b, const uint32_t limit)const - { - uint64_t api_limit_get_limit_orders=_app_options->api_limit_get_limit_orders; - FC_ASSERT( limit <= api_limit_get_limit_orders ); - - const auto& limit_order_idx = _db.get_index_type(); - const auto& limit_price_idx = limit_order_idx.indices().get(); - - vector result; - result.reserve(limit*2); - - uint32_t count = 0; - auto limit_itr = limit_price_idx.lower_bound(price::max(a,b)); - auto limit_end = limit_price_idx.upper_bound(price::min(a,b)); - while(limit_itr != limit_end && count < limit) - { - result.push_back(*limit_itr); - ++limit_itr; - ++count; - } - count = 0; - limit_itr = limit_price_idx.lower_bound(price::max(b,a)); - limit_end = limit_price_idx.upper_bound(price::min(b,a)); - while(limit_itr != limit_end && count < limit) - { - result.push_back(*limit_itr); - ++limit_itr; - ++count; - } - - return result; - } - - template - const std::pair get_order_market( const T& order ) - { - return order.get_market(); - } - - template - void enqueue_if_subscribed_to_market(const object* obj, market_queue_type& queue, bool full_object=true) - { - const T* order = dynamic_cast(obj); - FC_ASSERT( order != nullptr); - - const auto& market = get_order_market( *order ); - - auto sub = _market_subscriptions.find( market ); - if( sub != _market_subscriptions.end() ) { - queue[market].emplace_back( full_object ? obj->to_variant() : fc::variant(obj->id, 1) ); - } - } - - void broadcast_updates( const vector& updates ); - void broadcast_market_updates( const market_queue_type& queue); - void handle_object_changed(bool force_notify, bool full_object, const vector& ids, const flat_set& impacted_accounts, std::function find_object); - - /** called every time a block is applied to report the objects that were changed */ - void on_objects_new(const vector& ids, const flat_set& impacted_accounts); - void on_objects_changed(const vector& ids, const flat_set& impacted_accounts); - void on_objects_removed(const vector& ids, const vector& objs, const flat_set& impacted_accounts); - void on_applied_block(); - - bool _notify_remove_create = false; - mutable fc::bloom_filter _subscribe_filter; - std::set _subscribed_accounts; - std::function _subscribe_callback; - std::function _pending_trx_callback; - std::function _block_applied_callback; - bool _enabled_auto_subscription = true; - - boost::signals2::scoped_connection _new_connection; - boost::signals2::scoped_connection _change_connection; - boost::signals2::scoped_connection _removed_connection; - boost::signals2::scoped_connection _applied_block_connection; - boost::signals2::scoped_connection _pending_trx_connection; - map< pair, std::function > _market_subscriptions; - graphene::chain::database& _db; - const application_options* _app_options = nullptr; - const graphene::api_helper_indexes::amount_in_collateral_index* amount_in_collateral_index; -}; - ////////////////////////////////////////////////////////////////////// // // // Constructors // @@ -418,24 +57,29 @@ database_api_impl::database_api_impl( graphene::chain::database& db, const appli :_db(db), _app_options(app_options) { dlog("creating database api ${x}", ("x",int64_t(this)) ); - _new_connection = _db.new_objects.connect([this](const vector& ids, const flat_set& impacted_accounts) { + _new_connection = _db.new_objects.connect([this](const vector& ids, + const flat_set& impacted_accounts) { on_objects_new(ids, impacted_accounts); }); - _change_connection = _db.changed_objects.connect([this](const vector& ids, const flat_set& impacted_accounts) { + _change_connection = _db.changed_objects.connect([this](const vector& ids, + const flat_set& impacted_accounts) { on_objects_changed(ids, impacted_accounts); }); - _removed_connection = _db.removed_objects.connect([this](const vector& ids, const vector& objs, const flat_set& impacted_accounts) { + _removed_connection = _db.removed_objects.connect([this](const vector& ids, + const vector& objs, + const flat_set& impacted_accounts) { on_objects_removed(ids, objs, impacted_accounts); }); _applied_block_connection = _db.applied_block.connect([this](const signed_block&){ on_applied_block(); }); _pending_trx_connection = _db.on_pending_transaction.connect([this](const signed_transaction& trx ){ - if( _pending_trx_callback ) _pending_trx_callback( fc::variant(trx, GRAPHENE_MAX_NESTED_OBJECTS) ); + if( _pending_trx_callback ) + _pending_trx_callback( fc::variant(trx, GRAPHENE_MAX_NESTED_OBJECTS) ); }); try { amount_in_collateral_index = &_db.get_index_type< primary_index< call_order_index > >() - .get_secondary_index(); + .get_secondary_index(); } catch( fc::assert_exception& e ) { @@ -578,7 +222,8 @@ map> database_api::get_block_header_batch(const return my->get_block_header_batch( block_nums ); } -map> database_api_impl::get_block_header_batch(const vector block_nums) const +map> database_api_impl::get_block_header_batch( + const vector block_nums) const { map> results; for (const uint32_t block_num : block_nums) @@ -800,14 +445,16 @@ vector> database_api_impl::get_accounts( const vector database_api::get_account_limit_orders( const string& account_name_or_id, const string &base, - const string "e, uint32_t limit, optional ostart_id, optional ostart_price) +vector database_api::get_account_limit_orders( + const string& account_name_or_id, const string &base, const string "e, + uint32_t limit, optional ostart_id, optional ostart_price ) { return my->get_account_limit_orders( account_name_or_id, base, quote, limit, ostart_id, ostart_price ); } -vector database_api_impl::get_account_limit_orders( const string& account_name_or_id, const string &base, - const string "e, uint32_t limit, optional ostart_id, optional ostart_price) +vector database_api_impl::get_account_limit_orders( + const string& account_name_or_id, const string &base, const string "e, + uint32_t limit, optional ostart_id, optional ostart_price ) { FC_ASSERT( limit <= 101 ); @@ -924,20 +571,23 @@ std::map database_api_impl::get_full_accounts( const acnt.registrar_name = account->registrar(_db).name; acnt.referrer_name = account->referrer(_db).name; acnt.lifetime_referrer_name = account->lifetime_referrer(_db).name; - acnt.votes = lookup_vote_ids( vector(account->options.votes.begin(),account->options.votes.end()) ); + acnt.votes = lookup_vote_ids( vector( account->options.votes.begin(), + account->options.votes.end() ) ); if (account->cashback_vb) { acnt.cashback_balance = account->cashback_balance(_db); } - size_t api_limit_get_full_accounts_lists = static_cast(_app_options->api_limit_get_full_accounts_lists); + size_t api_limit_get_full_accounts_lists = static_cast( + _app_options->api_limit_get_full_accounts_lists ); // Add the account's proposals auto required_approvals_itr = proposals_by_account._account_to_proposals.find( account->id ); if( required_approvals_itr != proposals_by_account._account_to_proposals.end() ) { - acnt.proposals.reserve( std::min(required_approvals_itr->second.size(), api_limit_get_full_accounts_lists) ); + acnt.proposals.reserve( std::min(required_approvals_itr->second.size(), + api_limit_get_full_accounts_lists) ); for( auto proposal_id : required_approvals_itr->second ) { if(acnt.proposals.size() >= api_limit_get_full_accounts_lists) { @@ -961,7 +611,8 @@ std::map database_api_impl::get_full_accounts( const } // Add the account's vesting balances - auto vesting_range = _db.get_index_type().indices().get().equal_range(account->id); + auto vesting_range = _db.get_index_type().indices().get() + .equal_range(account->id); for(auto itr = vesting_range.first; itr != vesting_range.second; ++itr) { if(acnt.vesting_balances.size() >= api_limit_get_full_accounts_lists) { @@ -972,7 +623,8 @@ std::map database_api_impl::get_full_accounts( const } // Add the account's orders - auto order_range = _db.get_index_type().indices().get().equal_range(account->id); + auto order_range = _db.get_index_type().indices().get() + .equal_range(account->id); for(auto itr = order_range.first; itr != order_range.second; ++itr) { if(acnt.limit_orders.size() >= api_limit_get_full_accounts_lists) { @@ -990,7 +642,8 @@ std::map database_api_impl::get_full_accounts( const } acnt.call_orders.emplace_back(*itr); } - auto settle_range = _db.get_index_type().indices().get().equal_range(account->id); + auto settle_range = _db.get_index_type().indices().get() + .equal_range(account->id); for(auto itr = settle_range.first; itr != settle_range.second; ++itr) { if(acnt.settle_orders.size() >= api_limit_get_full_accounts_lists) { @@ -1158,12 +811,14 @@ uint64_t database_api_impl::get_account_count()const // // ////////////////////////////////////////////////////////////////////// -vector database_api::get_account_balances(const std::string& account_name_or_id, const flat_set& assets)const +vector database_api::get_account_balances( const std::string& account_name_or_id, + const flat_set& assets )const { return my->get_account_balances( account_name_or_id, assets ); } -vector database_api_impl::get_account_balances(const std::string& account_name_or_id, const flat_set& assets)const +vector database_api_impl::get_account_balances( const std::string& account_name_or_id, + const flat_set& assets )const { const account_object* account = get_account_from_string(account_name_or_id); account_id_type acnt = account->id; @@ -1172,7 +827,8 @@ vector database_api_impl::get_account_balances(const std::string& account { // if the caller passes in an empty list of assets, return balances for all assets the account owns const auto& balance_index = _db.get_index_type< primary_index< account_balance_index > >(); - const auto& balances = balance_index.get_secondary_index< balances_by_account_index >().get_account_balances( acnt ); + const auto& balances = balance_index.get_secondary_index< balances_by_account_index >() + .get_account_balances( acnt ); for( const auto balance : balances ) result.push_back( balance.second->get_balance() ); } @@ -1187,7 +843,8 @@ vector database_api_impl::get_account_balances(const std::string& account return result; } -vector database_api::get_named_account_balances(const std::string& name, const flat_set& assets)const +vector database_api::get_named_account_balances( const std::string& name, + const flat_set& assets )const { return my->get_account_balances( name, assets ); } @@ -1249,7 +906,8 @@ vector database_api_impl::get_vesting_balances( const st { const account_id_type account_id = get_account_from_string(account_id_or_name)->id; vector result; - auto vesting_range = _db.get_index_type().indices().get().equal_range(account_id); + auto vesting_range = _db.get_index_type().indices().get() + .equal_range(account_id); std::for_each(vesting_range.first, vesting_range.second, [&result](const vesting_balance_object& balance) { result.emplace_back(balance); @@ -1270,14 +928,16 @@ asset_id_type database_api::get_asset_id_from_string(const std::string& symbol_o return my->get_asset_from_string( symbol_or_id )->id; } -vector> database_api::get_assets( const vector& asset_symbols_or_ids, - optional subscribe )const +vector> database_api::get_assets( + const vector& asset_symbols_or_ids, + optional subscribe )const { return my->get_assets( asset_symbols_or_ids, subscribe ); } -vector> database_api_impl::get_assets(const vector& asset_symbols_or_ids, - optional subscribe )const +vector> database_api_impl::get_assets( + const vector& asset_symbols_or_ids, + optional subscribe )const { bool to_subscribe = get_whether_to_subscribe( subscribe ); vector> result; result.reserve(asset_symbols_or_ids.size()); @@ -1354,12 +1014,14 @@ vector database_api_impl::get_assets_by_issuer(const std: return result; } -vector> database_api::lookup_asset_symbols(const vector& symbols_or_ids)const +vector> database_api::lookup_asset_symbols( + const vector& symbols_or_ids )const { return my->lookup_asset_symbols( symbols_or_ids ); } -vector> database_api_impl::lookup_asset_symbols(const vector& symbols_or_ids)const +vector> database_api_impl::lookup_asset_symbols( + const vector& symbols_or_ids )const { const auto& assets_by_symbol = _db.get_index_type().indices().get(); vector > result; @@ -1388,10 +1050,8 @@ vector database_api::get_limit_orders(std::string a, std::st return my->get_limit_orders( a, b, limit ); } -/** - * @return the limit orders for both sides of the book for the two assets specified up to limit number on each side. - */ -vector database_api_impl::get_limit_orders(const std::string& a, const std::string& b, uint32_t limit)const +vector database_api_impl::get_limit_orders( const std::string& a, const std::string& b, + uint32_t limit )const { uint64_t api_limit_get_limit_orders=_app_options->api_limit_get_limit_orders; FC_ASSERT( limit <= api_limit_get_limit_orders ); @@ -1477,14 +1137,18 @@ vector database_api_impl::get_settle_orders(const std:: return result; } -vector database_api::get_settle_orders_by_account(const std::string& account_name_or_id, - force_settlement_id_type start, uint32_t limit)const +vector database_api::get_settle_orders_by_account( + const std::string& account_name_or_id, + force_settlement_id_type start, + uint32_t limit )const { return my->get_settle_orders_by_account( account_name_or_id, start, limit); } -vector database_api_impl::get_settle_orders_by_account(const std::string& account_name_or_id, - force_settlement_id_type start, uint32_t limit)const +vector database_api_impl::get_settle_orders_by_account( + const std::string& account_name_or_id, + force_settlement_id_type start, + uint32_t limit )const { uint64_t api_limit_get_settle_orders = _app_options->api_limit_get_settle_orders; FC_ASSERT( limit <= api_limit_get_settle_orders ); @@ -1527,12 +1191,14 @@ vector database_api_impl::get_margin_positions( const std::st } FC_CAPTURE_AND_RETHROW( (account_id_or_name) ) } -vector database_api::get_collateral_bids(const std::string& asset, uint32_t limit, uint32_t start)const +vector database_api::get_collateral_bids( const std::string& asset, + uint32_t limit, uint32_t start )const { return my->get_collateral_bids( asset, limit, start ); } -vector database_api_impl::get_collateral_bids(const std::string& asset, uint32_t limit, uint32_t skip)const +vector database_api_impl::get_collateral_bids( const std::string& asset, + uint32_t limit, uint32_t skip )const { try { FC_ASSERT( limit <= 100 ); const asset_id_type asset_id = get_asset_from_string(asset)->id; @@ -1542,8 +1208,12 @@ vector database_api_impl::get_collateral_bids(const std:: const asset_object& back = bad.options.short_backing_asset(_db); const auto& idx = _db.get_index_type(); const auto& aidx = idx.indices().get(); - auto start = aidx.lower_bound( boost::make_tuple( asset_id, price::max(back.id, asset_id), collateral_bid_id_type() ) ); - auto end = aidx.lower_bound( boost::make_tuple( asset_id, price::min(back.id, asset_id), collateral_bid_id_type(GRAPHENE_DB_MAX_INSTANCE_ID) ) ); + auto start = aidx.lower_bound( boost::make_tuple( asset_id, + price::max(back.id, asset_id), + collateral_bid_id_type() ) ); + auto end = aidx.lower_bound( boost::make_tuple( asset_id, + price::min(back.id, asset_id), + collateral_bid_id_type(GRAPHENE_DB_MAX_INSTANCE_ID) ) ); vector result; while( skip-- > 0 && start != end ) { ++start; } while( start != end && limit-- > 0) @@ -1554,12 +1224,14 @@ vector database_api_impl::get_collateral_bids(const std:: return result; } FC_CAPTURE_AND_RETHROW( (asset)(limit)(skip) ) } -void database_api::subscribe_to_market(std::function callback, const std::string& a, const std::string& b) +void database_api::subscribe_to_market( std::function callback, + const std::string& a, const std::string& b ) { my->subscribe_to_market( callback, a, b ); } -void database_api_impl::subscribe_to_market(std::function callback, const std::string& a, const std::string& b) +void database_api_impl::subscribe_to_market( std::function callback, + const std::string& a, const std::string& b ) { auto asset_a_id = get_asset_from_string(a)->id; auto asset_b_id = get_asset_from_string(b)->id; @@ -1601,7 +1273,7 @@ market_ticker database_api_impl::get_ticker( const string& base, const string& q auto base_id = assets[0]->id; auto quote_id = assets[1]->id; if( base_id > quote_id ) std::swap( base_id, quote_id ); - const auto& ticker_idx = _db.get_index_type().indices().get(); + const auto& ticker_idx = _db.get_index_type().indices().get(); auto itr = ticker_idx.find( std::make_tuple( base_id, quote_id ) ); const fc::time_point_sec now = _db.head_block_time(); if( itr != ticker_idx.end() ) @@ -1697,7 +1369,7 @@ vector database_api_impl::get_top_markets(uint32_t limit)const FC_ASSERT( limit <= 100 ); - const auto& volume_idx = _db.get_index_type().indices().get(); + const auto& volume_idx = _db.get_index_type().indices().get(); auto itr = volume_idx.rbegin(); vector result; result.reserve(limit); @@ -1748,11 +1420,12 @@ vector database_api_impl::get_trade_history( const string& base, start = fc::time_point_sec( fc::time_point::now() ); uint32_t count = 0; - const auto& history_idx = _db.get_index_type().indices().get(); + const auto& history_idx = _db.get_index_type().indices().get(); auto itr = history_idx.lower_bound( std::make_tuple( base_id, quote_id, start ) ); vector result; - while( itr != history_idx.end() && count < limit && !( itr->key.base != base_id || itr->key.quote != quote_id || itr->time < stop ) ) + while( itr != history_idx.end() && count < limit + && !( itr->key.base != base_id || itr->key.quote != quote_id || itr->time < stop ) ) { { market_trade trade; @@ -1846,7 +1519,8 @@ vector database_api_impl::get_trade_history_by_sequence( auto itr = history_idx.lower_bound( hkey ); vector result; - while( itr != history_idx.end() && count < limit && !( itr->key.base != base_id || itr->key.quote != quote_id || itr->time < stop ) ) + while( itr != history_idx.end() && count < limit + && !( itr->key.base != base_id || itr->key.quote != quote_id || itr->time < stop ) ) { if( itr->key.sequence == start_seq ) // found the key, should skip this and the other direction if found { @@ -1948,12 +1622,14 @@ fc::optional database_api_impl::get_witness_by_account(const std return {}; } -map database_api::lookup_witness_accounts(const string& lower_bound_name, uint32_t limit)const +map database_api::lookup_witness_accounts( const string& lower_bound_name, + uint32_t limit )const { return my->lookup_witness_accounts( lower_bound_name, limit ); } -map database_api_impl::lookup_witness_accounts(const string& lower_bound_name, uint32_t limit)const +map database_api_impl::lookup_witness_accounts( const string& lower_bound_name, + uint32_t limit )const { FC_ASSERT( limit <= 1000 ); const auto& witnesses_by_id = _db.get_index_type().indices().get(); @@ -1992,12 +1668,14 @@ uint64_t database_api_impl::get_witness_count()const // // ////////////////////////////////////////////////////////////////////// -vector> database_api::get_committee_members(const vector& committee_member_ids)const +vector> database_api::get_committee_members( + const vector& committee_member_ids )const { return my->get_committee_members( committee_member_ids ); } -vector> database_api_impl::get_committee_members(const vector& committee_member_ids)const +vector> database_api_impl::get_committee_members( + const vector& committee_member_ids )const { vector> result; result.reserve(committee_member_ids.size()); std::transform(committee_member_ids.begin(), committee_member_ids.end(), std::back_inserter(result), @@ -2009,12 +1687,14 @@ vector> database_api_impl::get_committee_membe return result; } -fc::optional database_api::get_committee_member_by_account(const std::string account_id_or_name)const +fc::optional database_api::get_committee_member_by_account( + const std::string account_id_or_name )const { return my->get_committee_member_by_account( account_id_or_name ); } -fc::optional database_api_impl::get_committee_member_by_account(const std::string account_id_or_name) const +fc::optional database_api_impl::get_committee_member_by_account( + const std::string account_id_or_name )const { const auto& idx = _db.get_index_type().indices().get(); const account_id_type account = get_account_from_string(account_id_or_name)->id; @@ -2024,12 +1704,14 @@ fc::optional database_api_impl::get_committee_member_by return {}; } -map database_api::lookup_committee_member_accounts(const string& lower_bound_name, uint32_t limit)const +map database_api::lookup_committee_member_accounts( + const string& lower_bound_name, uint32_t limit )const { return my->lookup_committee_member_accounts( lower_bound_name, limit ); } -map database_api_impl::lookup_committee_member_accounts(const string& lower_bound_name, uint32_t limit)const +map database_api_impl::lookup_committee_member_accounts( + const string& lower_bound_name, uint32_t limit )const { FC_ASSERT( limit <= 1000 ); const auto& committee_members_by_id = _db.get_index_type().indices().get(); @@ -2146,7 +1828,7 @@ vector database_api_impl::lookup_vote_ids( const vector& { auto itr = committee_idx.find( id ); if( itr != committee_idx.end() ) - result.emplace_back( variant( *itr, 2 ) ); // Depth of committee_member_object is 1, add 1 here to be safe + result.emplace_back( variant( *itr, 2 ) ); // Depth of committee_member_object is 1, add 1 to be safe else result.emplace_back( variant() ); break; @@ -2217,12 +1899,14 @@ std::string database_api_impl::get_transaction_hex_without_sig( return fc::to_hex(fc::raw::pack(static_cast(trx))); } -set database_api::get_required_signatures( const signed_transaction& trx, const flat_set& available_keys )const +set database_api::get_required_signatures( const signed_transaction& trx, + const flat_set& available_keys )const { return my->get_required_signatures( trx, available_keys ); } -set database_api_impl::get_required_signatures( const signed_transaction& trx, const flat_set& available_keys )const +set database_api_impl::get_required_signatures( const signed_transaction& trx, + const flat_set& available_keys )const { bool allow_non_immediate_owner = ( _db.head_block_time() >= HARDFORK_CORE_584_TIME ); auto result = trx.get_required_signatures( _db.get_chain_id(), @@ -2321,7 +2005,8 @@ bool database_api_impl::verify_authority( const signed_transaction& trx )const return true; } -bool database_api::verify_account_authority( const string& account_name_or_id, const flat_set& signers )const +bool database_api::verify_account_authority( const string& account_name_or_id, + const flat_set& signers )const { return my->verify_account_authority( account_name_or_id, signers ); } @@ -2360,7 +2045,8 @@ processed_transaction database_api_impl::validate_transaction( const signed_tran return _db.validate_transaction(trx); } -vector< fc::variant > database_api::get_required_fees( const vector& ops, const std::string& asset_id_or_symbol )const +vector< fc::variant > database_api::get_required_fees( const vector& ops, + const std::string& asset_id_or_symbol )const { return my->get_required_fees( ops, asset_id_or_symbol ); } @@ -2421,7 +2107,8 @@ struct get_required_fees_helper uint32_t current_recursion = 0; }; -vector< fc::variant > database_api_impl::get_required_fees( const vector& ops, const std::string& asset_id_or_symbol )const +vector< fc::variant > database_api_impl::get_required_fees( const vector& ops, + const std::string& asset_id_or_symbol )const { vector< operation > _ops = ops; // @@ -2480,12 +2167,14 @@ vector database_api_impl::get_proposed_transactions( const std: // // ////////////////////////////////////////////////////////////////////// -vector database_api::get_blinded_balances( const flat_set& commitments )const +vector database_api::get_blinded_balances( + const flat_set& commitments )const { return my->get_blinded_balances( commitments ); } -vector database_api_impl::get_blinded_balances( const flat_set& commitments )const +vector database_api_impl::get_blinded_balances( + const flat_set& commitments )const { vector result; result.reserve(commitments.size()); const auto& bal_idx = _db.get_index_type(); @@ -2505,12 +2194,18 @@ vector database_api_impl::get_blinded_balances( const fl // // ////////////////////////////////////////////////////////////////////// -vector database_api::get_withdraw_permissions_by_giver(const std::string account_id_or_name, withdraw_permission_id_type start, uint32_t limit)const +vector database_api::get_withdraw_permissions_by_giver( + const std::string account_id_or_name, + withdraw_permission_id_type start, + uint32_t limit)const { return my->get_withdraw_permissions_by_giver( account_id_or_name, start, limit ); } -vector database_api_impl::get_withdraw_permissions_by_giver(const std::string account_id_or_name, withdraw_permission_id_type start, uint32_t limit)const +vector database_api_impl::get_withdraw_permissions_by_giver( + const std::string account_id_or_name, + withdraw_permission_id_type start, + uint32_t limit)const { FC_ASSERT( limit <= 101 ); vector result; @@ -2519,7 +2214,8 @@ vector database_api_impl::get_withdraw_permissions_b auto withdraw_index_end = withdraw_idx.end(); const account_id_type account = get_account_from_string(account_id_or_name)->id; auto withdraw_itr = withdraw_idx.lower_bound(boost::make_tuple(account, start)); - while(withdraw_itr != withdraw_index_end && withdraw_itr->withdraw_from_account == account && result.size() < limit) + while( withdraw_itr != withdraw_index_end && withdraw_itr->withdraw_from_account == account + && result.size() < limit ) { result.push_back(*withdraw_itr); ++withdraw_itr; @@ -2527,12 +2223,18 @@ vector database_api_impl::get_withdraw_permissions_b return result; } -vector database_api::get_withdraw_permissions_by_recipient(const std::string account_id_or_name, withdraw_permission_id_type start, uint32_t limit)const +vector database_api::get_withdraw_permissions_by_recipient( + const std::string account_id_or_name, + withdraw_permission_id_type start, + uint32_t limit)const { return my->get_withdraw_permissions_by_recipient( account_id_or_name, start, limit ); } -vector database_api_impl::get_withdraw_permissions_by_recipient(const std::string account_id_or_name, withdraw_permission_id_type start, uint32_t limit)const +vector database_api_impl::get_withdraw_permissions_by_recipient( + const std::string account_id_or_name, + withdraw_permission_id_type start, + uint32_t limit)const { FC_ASSERT( limit <= 101 ); vector result; @@ -2570,12 +2272,14 @@ fc::optional database_api_impl::get_htlc( htlc_id_type id, optional return fc::optional(); } -vector database_api::get_htlc_by_from(const std::string account_id_or_name, htlc_id_type start, uint32_t limit)const +vector database_api::get_htlc_by_from( const std::string account_id_or_name, + htlc_id_type start, uint32_t limit )const { return my->get_htlc_by_from(account_id_or_name, start, limit); } -vector database_api_impl::get_htlc_by_from(const std::string account_id_or_name, htlc_id_type start, uint32_t limit) const +vector database_api_impl::get_htlc_by_from( const std::string account_id_or_name, + htlc_id_type start, uint32_t limit ) const { FC_ASSERT( limit <= _app_options->api_limit_get_htlc_by ); vector result; @@ -2593,12 +2297,14 @@ vector database_api_impl::get_htlc_by_from(const std::string accoun return result; } -vector database_api::get_htlc_by_to(const std::string account_id_or_name, htlc_id_type start, uint32_t limit)const +vector database_api::get_htlc_by_to( const std::string account_id_or_name, + htlc_id_type start, uint32_t limit )const { return my->get_htlc_by_to(account_id_or_name, start, limit); } -vector database_api_impl::get_htlc_by_to(const std::string account_id_or_name, htlc_id_type start, uint32_t limit) const +vector database_api_impl::get_htlc_by_to( const std::string account_id_or_name, + htlc_id_type start, uint32_t limit ) const { FC_ASSERT( limit <= _app_options->api_limit_get_htlc_by ); @@ -2643,6 +2349,110 @@ vector database_api_impl::list_htlcs(const htlc_id_type start, uint // // ////////////////////////////////////////////////////////////////////// +const account_object* database_api_impl::get_account_from_string( const std::string& name_or_id, + bool throw_if_not_found ) const +{ + // TODO cache the result to avoid repeatly fetching from db + FC_ASSERT( name_or_id.size() > 0); + const account_object* account = nullptr; + if (std::isdigit(name_or_id[0])) + account = _db.find(fc::variant(name_or_id, 1).as(1)); + else + { + const auto& idx = _db.get_index_type().indices().get(); + auto itr = idx.find(name_or_id); + if (itr != idx.end()) + account = &*itr; + } + if(throw_if_not_found) + FC_ASSERT( account, "no such account" ); + return account; +} + +const asset_object* database_api_impl::get_asset_from_string( const std::string& symbol_or_id, + bool throw_if_not_found ) const +{ + // TODO cache the result to avoid repeatly fetching from db + FC_ASSERT( symbol_or_id.size() > 0); + const asset_object* asset = nullptr; + if (std::isdigit(symbol_or_id[0])) + asset = _db.find(fc::variant(symbol_or_id, 1).as(1)); + else + { + const auto& idx = _db.get_index_type().indices().get(); + auto itr = idx.find(symbol_or_id); + if (itr != idx.end()) + asset = &*itr; + } + if(throw_if_not_found) + FC_ASSERT( asset, "no such asset" ); + return asset; +} + +// helper function +vector> database_api_impl::get_assets( const vector& asset_ids, + optional subscribe )const +{ + bool to_subscribe = get_whether_to_subscribe( subscribe ); + vector> result; result.reserve(asset_ids.size()); + std::transform(asset_ids.begin(), asset_ids.end(), std::back_inserter(result), + [this,to_subscribe](asset_id_type id) -> optional { + if(auto o = _db.find(id)) + { + if( to_subscribe ) + subscribe_to_item( id ); + return extend_asset( *o ); + } + return {}; + }); + return result; +} + +// helper function +vector database_api_impl::get_limit_orders( const asset_id_type a, const asset_id_type b, + const uint32_t limit )const +{ + uint64_t api_limit_get_limit_orders=_app_options->api_limit_get_limit_orders; + FC_ASSERT( limit <= api_limit_get_limit_orders ); + + const auto& limit_order_idx = _db.get_index_type(); + const auto& limit_price_idx = limit_order_idx.indices().get(); + + vector result; + result.reserve(limit*2); + + uint32_t count = 0; + auto limit_itr = limit_price_idx.lower_bound(price::max(a,b)); + auto limit_end = limit_price_idx.upper_bound(price::min(a,b)); + while(limit_itr != limit_end && count < limit) + { + result.push_back(*limit_itr); + ++limit_itr; + ++count; + } + count = 0; + limit_itr = limit_price_idx.lower_bound(price::max(b,a)); + limit_end = limit_price_idx.upper_bound(price::min(b,a)); + while(limit_itr != limit_end && count < limit) + { + result.push_back(*limit_itr); + ++limit_itr; + ++count; + } + + return result; +} + +bool database_api_impl::is_impacted_account( const flat_set& accounts) +{ + if( !_subscribed_accounts.size() || !accounts.size() ) + return false; + + return std::any_of(accounts.begin(), accounts.end(), [this](const account_id_type& account) { + return _subscribed_accounts.find(account) != _subscribed_accounts.end(); + }); +} + void database_api_impl::broadcast_updates( const vector& updates ) { if( updates.size() && _subscribe_callback ) { @@ -2670,7 +2480,9 @@ void database_api_impl::broadcast_market_updates( const market_queue_type& queue } } -void database_api_impl::on_objects_removed( const vector& ids, const vector& objs, const flat_set& impacted_accounts) +void database_api_impl::on_objects_removed( const vector& ids, + const vector& objs, + const flat_set& impacted_accounts ) { handle_object_changed(_notify_remove_create, false, ids, impacted_accounts, [objs](object_id_type id) -> const object* { @@ -2686,21 +2498,27 @@ void database_api_impl::on_objects_removed( const vector& ids, c ); } -void database_api_impl::on_objects_new(const vector& ids, const flat_set& impacted_accounts) +void database_api_impl::on_objects_new( const vector& ids, + const flat_set& impacted_accounts ) { handle_object_changed(_notify_remove_create, true, ids, impacted_accounts, std::bind(&object_database::find_object, &_db, std::placeholders::_1) ); } -void database_api_impl::on_objects_changed(const vector& ids, const flat_set& impacted_accounts) +void database_api_impl::on_objects_changed( const vector& ids, + const flat_set& impacted_accounts ) { handle_object_changed(false, true, ids, impacted_accounts, std::bind(&object_database::find_object, &_db, std::placeholders::_1) ); } -void database_api_impl::handle_object_changed(bool force_notify, bool full_object, const vector& ids, const flat_set& impacted_accounts, std::function find_object) +void database_api_impl::handle_object_changed( bool force_notify, + bool full_object, + const vector& ids, + const flat_set& impacted_accounts, + std::function find_object ) { if( _subscribe_callback ) { @@ -2745,7 +2563,8 @@ void database_api_impl::handle_object_changed(bool force_notify, bool full_objec } else if( id.is() ) { - enqueue_if_subscribed_to_market( find_object(id), broadcast_queue, full_object ); + enqueue_if_subscribed_to_market( find_object(id), broadcast_queue, + full_object ); } } diff --git a/libraries/app/database_api_impl.hxx b/libraries/app/database_api_impl.hxx new file mode 100644 index 0000000000..1d97f290d6 --- /dev/null +++ b/libraries/app/database_api_impl.hxx @@ -0,0 +1,370 @@ +/* + * Copyright (c) 2017 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 + +#define GET_REQUIRED_FEES_MAX_RECURSION 4 + +namespace graphene { namespace app { + +typedef std::map< std::pair, + std::vector > market_queue_type; + +class database_api_impl : public std::enable_shared_from_this +{ + public: + explicit database_api_impl( graphene::chain::database& db, const application_options* app_options ); + virtual ~database_api_impl(); + + // Objects + fc::variants get_objects( const vector& ids, optional subscribe )const; + + // Subscriptions + void set_subscribe_callback( std::function cb, bool notify_remove_create ); + void set_auto_subscription( bool enable ); + void set_pending_transaction_callback( std::function cb ); + void set_block_applied_callback( std::function cb ); + void cancel_all_subscriptions(bool reset_callback, bool reset_market_subscriptions); + + // Blocks and transactions + optional get_block_header(uint32_t block_num)const; + map> get_block_header_batch(const vector block_nums)const; + optional get_block(uint32_t block_num)const; + processed_transaction get_transaction( uint32_t block_num, uint32_t trx_in_block )const; + + // Globals + chain_property_object get_chain_properties()const; + global_property_object get_global_properties()const; + fc::variant_object get_config()const; + chain_id_type get_chain_id()const; + dynamic_global_property_object get_dynamic_global_properties()const; + + // Keys + vector> get_key_references( vector key )const; + bool is_public_key_registered(string public_key) const; + + // Accounts + account_id_type get_account_id_from_string(const std::string& name_or_id)const; + vector> get_accounts( const vector& account_names_or_ids, + optional subscribe )const; + std::map get_full_accounts( const vector& names_or_ids, + optional subscribe ); + optional get_account_by_name( string name )const; + vector get_account_references( const std::string account_id_or_name )const; + vector> lookup_account_names(const vector& account_names)const; + map lookup_accounts( const string& lower_bound_name, + uint32_t limit, + optional subscribe )const; + uint64_t get_account_count()const; + + // Balances + vector get_account_balances( const std::string& account_name_or_id, + const flat_set& assets )const; + vector get_named_account_balances(const std::string& name, const flat_set& assets)const; + vector get_balance_objects( const vector
& addrs )const; + vector get_vested_balances( const vector& objs )const; + vector get_vesting_balances( const std::string account_id_or_name )const; + + // Assets + uint64_t get_asset_count()const; + asset_id_type get_asset_id_from_string(const std::string& symbol_or_id)const; + vector> get_assets( const vector& asset_symbols_or_ids, + optional subscribe )const; + vector list_assets(const string& lower_bound_symbol, uint32_t limit)const; + vector> lookup_asset_symbols(const vector& symbols_or_ids)const; + vector get_assets_by_issuer(const std::string& issuer_name_or_id, + asset_id_type start, uint32_t limit)const; + + // Markets / feeds + vector get_limit_orders( const std::string& a, const std::string& b, + uint32_t limit)const; + vector get_account_limit_orders( const string& account_name_or_id, + const string &base, + const string "e, uint32_t limit, + optional ostart_id, + optional ostart_price ); + vector get_call_orders(const std::string& a, uint32_t limit)const; + vector get_call_orders_by_account(const std::string& account_name_or_id, + asset_id_type start, uint32_t limit)const; + vector get_settle_orders(const std::string& a, uint32_t limit)const; + vector get_settle_orders_by_account(const std::string& account_name_or_id, + force_settlement_id_type start, + uint32_t limit)const; + vector get_margin_positions( const std::string account_id_or_name )const; + vector get_collateral_bids( const std::string& asset, + uint32_t limit, uint32_t start)const; + + void subscribe_to_market( std::function callback, + const std::string& a, const std::string& b ); + void unsubscribe_from_market(const std::string& a, const std::string& b); + + market_ticker get_ticker( const string& base, const string& quote, + bool skip_order_book = false )const; + market_volume get_24_volume( const string& base, const string& quote )const; + order_book get_order_book( const string& base, const string& quote, + unsigned limit = 50 )const; + vector get_top_markets( uint32_t limit )const; + vector get_trade_history( const string& base, const string& quote, + fc::time_point_sec start, fc::time_point_sec stop, + unsigned limit = 100 )const; + vector get_trade_history_by_sequence( const string& base, const string& quote, + int64_t start, fc::time_point_sec stop, + unsigned limit = 100 )const; + + // Witnesses + vector> get_witnesses(const vector& witness_ids)const; + fc::optional get_witness_by_account(const std::string account_id_or_name)const; + map lookup_witness_accounts(const string& lower_bound_name, uint32_t limit)const; + uint64_t get_witness_count()const; + + // Committee members + vector> get_committee_members( + const vector& committee_member_ids )const; + fc::optional get_committee_member_by_account( + const std::string account_id_or_name )const; + map lookup_committee_member_accounts( + const string& lower_bound_name, uint32_t limit )const; + uint64_t get_committee_count()const; + + // Workers + vector get_all_workers()const; + vector> get_workers_by_account(const std::string account_id_or_name)const; + uint64_t get_worker_count()const; + + // Votes + vector lookup_vote_ids( const vector& votes )const; + + // Authority / validation + std::string get_transaction_hex(const signed_transaction& trx)const; + std::string get_transaction_hex_without_sig(const signed_transaction& trx)const; + + set get_required_signatures( const signed_transaction& trx, + const flat_set& available_keys )const; + set get_potential_signatures( const signed_transaction& trx )const; + set
get_potential_address_signatures( const signed_transaction& trx )const; + bool verify_authority( const signed_transaction& trx )const; + bool verify_account_authority( const string& account_name_or_id, + const flat_set& signers )const; + processed_transaction validate_transaction( const signed_transaction& trx )const; + vector< fc::variant > get_required_fees( const vector& ops, + const std::string& asset_id_or_symbol )const; + + // Proposed transactions + vector get_proposed_transactions( const std::string account_id_or_name )const; + + // Blinded balances + vector get_blinded_balances( const flat_set& commitments )const; + + // Withdrawals + vector get_withdraw_permissions_by_giver( const std::string account_id_or_name, + withdraw_permission_id_type start, + uint32_t limit )const; + vector get_withdraw_permissions_by_recipient( const std::string account_id_or_name, + withdraw_permission_id_type start, + uint32_t limit )const; + + // HTLC + optional get_htlc( htlc_id_type id, optional subscribe ) const; + vector get_htlc_by_from( const std::string account_id_or_name, + htlc_id_type start, uint32_t limit ) const; + vector get_htlc_by_to( const std::string account_id_or_name, + htlc_id_type start, uint32_t limit) const; + vector list_htlcs(const htlc_id_type lower_bound_id, uint32_t limit) const; + + //private: + + //////////////////////////////////////////////// + // Accounts + //////////////////////////////////////////////// + + const account_object* get_account_from_string( const std::string& name_or_id, + bool throw_if_not_found = true ) const; + + //////////////////////////////////////////////// + // Assets + //////////////////////////////////////////////// + + template + extended_asset_object extend_asset( ASSET&& a )const + { + asset_id_type id = a.id; + extended_asset_object result = extended_asset_object( std::forward( a ) ); + if( amount_in_collateral_index ) + { + result.total_in_collateral = amount_in_collateral_index->get_amount_in_collateral( id ); + if( result.bitasset_data_id.valid() ) + result.total_backing_collateral = amount_in_collateral_index->get_backing_collateral( id ); + } + return result; + } + + const asset_object* get_asset_from_string( const std::string& symbol_or_id, + bool throw_if_not_found = true ) const; + // helper function + vector> get_assets( const vector& asset_ids, + optional subscribe = optional() )const; + + //////////////////////////////////////////////// + // Markets + //////////////////////////////////////////////// + + // helper function + vector get_limit_orders( const asset_id_type a, const asset_id_type b, + const uint32_t limit )const; + + //////////////////////////////////////////////// + // Subscription + //////////////////////////////////////////////// + + // Decides whether to subscribe using member variables and given parameter + bool get_whether_to_subscribe( optional subscribe )const + { + if( !_subscribe_callback ) + return false; + if( subscribe.valid() ) + return *subscribe; + return _enabled_auto_subscription; + } + + // Note: + // Different type of object_id objects could become identical after packed. + // For example, both `account_id_type a=1.2.0` and `asset_id_type b=1.3.0` will become `0` after packed. + // In order to avoid collision, we don't use a template function here, instead, we implicitly convert all + // object IDs to `object_id_type` when subscribing. + // + // If need to subscribe to other data types, override this function with the types as parameter. + // For example, we had a `get_subscription_key( const public_key_type& item )` function here, which was + // removed lately since we no longer subscribe to public keys. + vector get_subscription_key( const object_id_type& item )const + { + return fc::raw::pack(item); + } + + template + void subscribe_to_item( const T& item )const + { + if( !_subscribe_callback ) + return; + + vector key = get_subscription_key( item ); + if( !_subscribe_filter.contains( key.data(), key.size() ) ) + { + _subscribe_filter.insert( key.data(), key.size() ); + } + } + + template + bool is_subscribed_to_item( const T& item )const + { + if( !_subscribe_callback ) + return false; + + vector key = get_subscription_key( item ); + return _subscribe_filter.contains( key.data(), key.size() ); + } + + // for full-account subscription + bool is_impacted_account( const flat_set& accounts ); + + // for market subscription + template + const std::pair get_order_market( const T& order ) + { + return order.get_market(); + } + + // for market subscription + const std::pair get_order_market( const force_settlement_object& order ) + { + // TODO cache the result to avoid repeatly fetching from db + asset_id_type backing_id = order.balance.asset_id( _db ).bitasset_data( _db ).options.short_backing_asset; + auto tmp = std::make_pair( order.balance.asset_id, backing_id ); + if( tmp.first > tmp.second ) std::swap( tmp.first, tmp.second ); + return tmp; + } + + template + void enqueue_if_subscribed_to_market(const object* obj, market_queue_type& queue, bool full_object=true) + { + const T* order = dynamic_cast(obj); + FC_ASSERT( order != nullptr); + + const auto& market = get_order_market( *order ); + + auto sub = _market_subscriptions.find( market ); + if( sub != _market_subscriptions.end() ) { + queue[market].emplace_back( full_object ? obj->to_variant() : fc::variant(obj->id, 1) ); + } + } + + void broadcast_updates( const vector& updates ); + void broadcast_market_updates( const market_queue_type& queue); + void handle_object_changed( bool force_notify, + bool full_object, + const vector& ids, + const flat_set& impacted_accounts, + std::function find_object ); + + /** called every time a block is applied to report the objects that were changed */ + void on_objects_new(const vector& ids, const flat_set& impacted_accounts); + void on_objects_changed(const vector& ids, const flat_set& impacted_accounts); + void on_objects_removed(const vector& ids, const vector& objs, + const flat_set& impacted_accounts); + void on_applied_block(); + + //////////////////////////////////////////////// + // Member variables + //////////////////////////////////////////////// + + bool _notify_remove_create = false; + bool _enabled_auto_subscription = true; + + mutable fc::bloom_filter _subscribe_filter; + std::set _subscribed_accounts; + + std::function _subscribe_callback; + std::function _pending_trx_callback; + std::function _block_applied_callback; + + boost::signals2::scoped_connection _new_connection; + boost::signals2::scoped_connection _change_connection; + boost::signals2::scoped_connection _removed_connection; + boost::signals2::scoped_connection _applied_block_connection; + boost::signals2::scoped_connection _pending_trx_connection; + + map< pair, std::function > _market_subscriptions; + + graphene::chain::database& _db; + const application_options* _app_options = nullptr; + + const graphene::api_helper_indexes::amount_in_collateral_index* amount_in_collateral_index; +}; + +} } // graphene::app From 3a6fbc44414eceed96523cab92a248749d21796d Mon Sep 17 00:00:00 2001 From: abitmore Date: Fri, 9 Aug 2019 13:01:13 -0400 Subject: [PATCH 100/111] Move get_account_limit_orders code to market group --- libraries/app/database_api.cpp | 176 ++++++++++++++++----------------- 1 file changed, 88 insertions(+), 88 deletions(-) diff --git a/libraries/app/database_api.cpp b/libraries/app/database_api.cpp index e68c271892..c5aa195f6b 100644 --- a/libraries/app/database_api.cpp +++ b/libraries/app/database_api.cpp @@ -445,94 +445,6 @@ vector> database_api_impl::get_accounts( const vector database_api::get_account_limit_orders( - const string& account_name_or_id, const string &base, const string "e, - uint32_t limit, optional ostart_id, optional ostart_price ) -{ - return my->get_account_limit_orders( account_name_or_id, base, quote, limit, ostart_id, ostart_price ); -} - -vector database_api_impl::get_account_limit_orders( - const string& account_name_or_id, const string &base, const string "e, - uint32_t limit, optional ostart_id, optional ostart_price ) -{ - FC_ASSERT( limit <= 101 ); - - vector results; - uint32_t count = 0; - - const account_object* account = get_account_from_string(account_name_or_id); - if (account == nullptr) - return results; - - auto assets = lookup_asset_symbols( {base, quote} ); - FC_ASSERT( assets[0], "Invalid base asset symbol: ${s}", ("s",base) ); - FC_ASSERT( assets[1], "Invalid quote asset symbol: ${s}", ("s",quote) ); - - auto base_id = assets[0]->id; - auto quote_id = assets[1]->id; - - if (ostart_price.valid()) { - FC_ASSERT(ostart_price->base.asset_id == base_id, "Base asset inconsistent with start price"); - FC_ASSERT(ostart_price->quote.asset_id == quote_id, "Quote asset inconsistent with start price"); - } - - const auto& index_by_account = _db.get_index_type().indices().get(); - limit_order_multi_index_type::index::type::const_iterator lower_itr; - limit_order_multi_index_type::index::type::const_iterator upper_itr; - - // if both order_id and price are invalid, query the first page - if ( !ostart_id.valid() && !ostart_price.valid() ) - { - lower_itr = index_by_account.lower_bound(std::make_tuple(account->id, price::max(base_id, quote_id))); - } - else if ( ostart_id.valid() ) - { - // in case of the order been deleted during page querying - const limit_order_object *p_loo = _db.find(*ostart_id); - - if ( !p_loo ) - { - if ( ostart_price.valid() ) - { - lower_itr = index_by_account.lower_bound(std::make_tuple(account->id, *ostart_price, *ostart_id)); - } - else - { - // start order id been deleted, yet not provided price either - FC_THROW("Order id invalid (maybe just been canceled?), and start price not provided"); - } - } - else - { - const limit_order_object &loo = *p_loo; - - // in case of the order not belongs to specified account or market - FC_ASSERT(loo.sell_price.base.asset_id == base_id, "Order base asset inconsistent"); - FC_ASSERT(loo.sell_price.quote.asset_id == quote_id, "Order quote asset inconsistent with order"); - FC_ASSERT(loo.seller == account->get_id(), "Order not owned by specified account"); - - lower_itr = index_by_account.lower_bound(std::make_tuple(account->id, loo.sell_price, *ostart_id)); - } - } - else - { - // if reach here start_price must be valid - lower_itr = index_by_account.lower_bound(std::make_tuple(account->id, *ostart_price)); - } - - upper_itr = index_by_account.upper_bound(std::make_tuple(account->id, price::min(base_id, quote_id))); - - // Add the account's orders - for ( ; lower_itr != upper_itr && count < limit; ++lower_itr, ++count) - { - const limit_order_object &order = *lower_itr; - results.emplace_back(order); - } - - return results; -} - std::map database_api::get_full_accounts( const vector& names_or_ids, optional subscribe ) { @@ -1062,6 +974,94 @@ vector database_api_impl::get_limit_orders( const std::strin return get_limit_orders(asset_a_id, asset_b_id, limit); } +vector database_api::get_account_limit_orders( + const string& account_name_or_id, const string &base, const string "e, + uint32_t limit, optional ostart_id, optional ostart_price ) +{ + return my->get_account_limit_orders( account_name_or_id, base, quote, limit, ostart_id, ostart_price ); +} + +vector database_api_impl::get_account_limit_orders( + const string& account_name_or_id, const string &base, const string "e, + uint32_t limit, optional ostart_id, optional ostart_price ) +{ + FC_ASSERT( limit <= 101 ); + + vector results; + uint32_t count = 0; + + const account_object* account = get_account_from_string(account_name_or_id); + if (account == nullptr) + return results; + + auto assets = lookup_asset_symbols( {base, quote} ); + FC_ASSERT( assets[0], "Invalid base asset symbol: ${s}", ("s",base) ); + FC_ASSERT( assets[1], "Invalid quote asset symbol: ${s}", ("s",quote) ); + + auto base_id = assets[0]->id; + auto quote_id = assets[1]->id; + + if (ostart_price.valid()) { + FC_ASSERT(ostart_price->base.asset_id == base_id, "Base asset inconsistent with start price"); + FC_ASSERT(ostart_price->quote.asset_id == quote_id, "Quote asset inconsistent with start price"); + } + + const auto& index_by_account = _db.get_index_type().indices().get(); + limit_order_multi_index_type::index::type::const_iterator lower_itr; + limit_order_multi_index_type::index::type::const_iterator upper_itr; + + // if both order_id and price are invalid, query the first page + if ( !ostart_id.valid() && !ostart_price.valid() ) + { + lower_itr = index_by_account.lower_bound(std::make_tuple(account->id, price::max(base_id, quote_id))); + } + else if ( ostart_id.valid() ) + { + // in case of the order been deleted during page querying + const limit_order_object *p_loo = _db.find(*ostart_id); + + if ( !p_loo ) + { + if ( ostart_price.valid() ) + { + lower_itr = index_by_account.lower_bound(std::make_tuple(account->id, *ostart_price, *ostart_id)); + } + else + { + // start order id been deleted, yet not provided price either + FC_THROW("Order id invalid (maybe just been canceled?), and start price not provided"); + } + } + else + { + const limit_order_object &loo = *p_loo; + + // in case of the order not belongs to specified account or market + FC_ASSERT(loo.sell_price.base.asset_id == base_id, "Order base asset inconsistent"); + FC_ASSERT(loo.sell_price.quote.asset_id == quote_id, "Order quote asset inconsistent with order"); + FC_ASSERT(loo.seller == account->get_id(), "Order not owned by specified account"); + + lower_itr = index_by_account.lower_bound(std::make_tuple(account->id, loo.sell_price, *ostart_id)); + } + } + else + { + // if reach here start_price must be valid + lower_itr = index_by_account.lower_bound(std::make_tuple(account->id, *ostart_price)); + } + + upper_itr = index_by_account.upper_bound(std::make_tuple(account->id, price::min(base_id, quote_id))); + + // Add the account's orders + for ( ; lower_itr != upper_itr && count < limit; ++lower_itr, ++count) + { + const limit_order_object &order = *lower_itr; + results.emplace_back(order); + } + + return results; +} + vector database_api::get_call_orders(const std::string& a, uint32_t limit)const { return my->get_call_orders( a, limit ); From a0aa6b407a89abaca884dd246df088baff0b7a59 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Thu, 15 Aug 2019 15:22:44 +0200 Subject: [PATCH 101/111] Fix broken build by adding missing include --- tests/tests/database_api_tests.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/tests/database_api_tests.cpp b/tests/tests/database_api_tests.cpp index 9304fa4b09..00f7ef4ca9 100644 --- a/tests/tests/database_api_tests.cpp +++ b/tests/tests/database_api_tests.cpp @@ -28,10 +28,12 @@ #include #include - #include + #include "../common/database_fixture.hpp" +#include + using namespace graphene::chain; using namespace graphene::chain::test; From 62fc6225656e3c299d95f056f5e1a8e1b2b49ef9 Mon Sep 17 00:00:00 2001 From: abitmore Date: Thu, 15 Aug 2019 08:32:47 -0400 Subject: [PATCH 102/111] Update includes --- libraries/app/database_api.cpp | 4 +--- libraries/app/database_api_impl.hxx | 4 ---- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/libraries/app/database_api.cpp b/libraries/app/database_api.cpp index c5aa195f6b..981a2eac84 100644 --- a/libraries/app/database_api.cpp +++ b/libraries/app/database_api.cpp @@ -24,19 +24,17 @@ #include "database_api_impl.hxx" -#include #include #include #include #include #include +#include #include #include -#include -#include template class fc::api; diff --git a/libraries/app/database_api_impl.hxx b/libraries/app/database_api_impl.hxx index 1d97f290d6..e2e7c376a4 100644 --- a/libraries/app/database_api_impl.hxx +++ b/libraries/app/database_api_impl.hxx @@ -25,10 +25,6 @@ #include #include -#include - -#include -#include #define GET_REQUIRED_FEES_MAX_RECURSION 4 From 6f313050cdc428427480f2eebd0db4374830786b Mon Sep 17 00:00:00 2001 From: Abit Date: Thu, 15 Aug 2019 22:46:08 +0200 Subject: [PATCH 103/111] Fix Windows linker error --- libraries/app/include/graphene/app/util.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/app/include/graphene/app/util.hpp b/libraries/app/include/graphene/app/util.hpp index a92b51588f..734ea7de04 100644 --- a/libraries/app/include/graphene/app/util.hpp +++ b/libraries/app/include/graphene/app/util.hpp @@ -30,7 +30,7 @@ namespace protocol { struct price; } namespace chain { - struct asset_object; + class asset_object; } namespace app { From 02819c31e3f0b86594068bab8d2c674bfad15c34 Mon Sep 17 00:00:00 2001 From: jmjatlanta Date: Fri, 16 Aug 2019 09:47:30 -0500 Subject: [PATCH 104/111] pthread fix for mac --- CMakeLists.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index bd9db30bf5..1e3d8e0eb1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -148,6 +148,14 @@ IF( WIN32 ) SET(BOOST_ROOT $ENV{BOOST_ROOT}) set(Boost_USE_MULTITHREADED ON) set(BOOST_ALL_DYN_LINK OFF) # force dynamic linking for all libraries +ELSE( WIN32 ) + IF( APPLE ) + set( CMAKE_THREAD_LIBS_INIT "-lpthread" ) + set( CMAKE_HAVE_THREADS_LIBRARY 1 ) + set( CMAKE_USE_WIN32_THREADS_INIT 0 ) + set( CMAKE_USE_PTHREADS_INIT 1 ) + set( THREADS_PREFER_PTHREAD_FLAG ON ) + ENDIF( APPLE ) ENDIF(WIN32) FIND_PACKAGE(Boost 1.57 REQUIRED COMPONENTS ${BOOST_COMPONENTS}) From 4c9a1cf58403e87773a298001b4e9653c7e2b85e Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Fri, 16 Aug 2019 16:03:32 -0300 Subject: [PATCH 105/111] fix hf_935_test in testnet --- tests/common/database_fixture.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tests/common/database_fixture.cpp b/tests/common/database_fixture.cpp index e25b4f76e0..8452644381 100644 --- a/tests/common/database_fixture.cpp +++ b/tests/common/database_fixture.cpp @@ -88,13 +88,14 @@ database_fixture::database_fixture(const fc::time_point_sec &initial_timestamp) genesis_state.initial_timestamp = initial_timestamp; - if(boost::unit_test::framework::current_test_case().p_name.value == "hf_935_test") + if(boost::unit_test::framework::current_test_case().p_name.value == "hf_935_test") { genesis_state.initial_active_witnesses = 20; - else + } + else { genesis_state.initial_active_witnesses = 10; - - genesis_state.immutable_parameters.min_committee_member_count = INITIAL_COMMITTEE_MEMBER_COUNT; - genesis_state.immutable_parameters.min_witness_count = INITIAL_WITNESS_COUNT; + genesis_state.immutable_parameters.min_committee_member_count = INITIAL_COMMITTEE_MEMBER_COUNT; + genesis_state.immutable_parameters.min_witness_count = INITIAL_WITNESS_COUNT; + } for( unsigned int i = 0; i < genesis_state.initial_active_witnesses; ++i ) { From 2e0ceb0bafea809d1ff5b3740fc0aad9f43da950 Mon Sep 17 00:00:00 2001 From: Abit Date: Sun, 18 Aug 2019 02:34:19 +0200 Subject: [PATCH 106/111] Bump DB_VERSION Due to https://github.com/bitshares/bitshares-core/pull/1885, need to force a replay. --- libraries/chain/include/graphene/chain/config.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/chain/include/graphene/chain/config.hpp b/libraries/chain/include/graphene/chain/config.hpp index 46a8feb54e..e508eb16b2 100644 --- a/libraries/chain/include/graphene/chain/config.hpp +++ b/libraries/chain/include/graphene/chain/config.hpp @@ -30,7 +30,7 @@ #define GRAPHENE_MAX_NESTED_OBJECTS (200) -#define GRAPHENE_CURRENT_DB_VERSION "20190503" +#define GRAPHENE_CURRENT_DB_VERSION "20190818" #define GRAPHENE_RECENTLY_MISSED_COUNT_INCREMENT 4 #define GRAPHENE_RECENTLY_MISSED_COUNT_DECREMENT 3 From f9cd6763ec099922756e2cd4e993f8a56bd1c96e Mon Sep 17 00:00:00 2001 From: Nathan Hourt Date: Tue, 20 Aug 2019 10:04:54 -0500 Subject: [PATCH 107/111] Fix build (Linux/Clang) --- CMakeLists.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bd9db30bf5..ba51edc031 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,11 +12,12 @@ set( INSTALLER_APP_ID "68ad7005-8eee-49c9-95ce-9eed97e5b347" ) set( CMAKE_CXX_STANDARD 14 ) set( CMAKE_CXX_STANDARD_REQUIRED ON ) -if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" ) +if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR + "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) set( CMAKE_CXX_EXTENSIONS ON ) # for __int128 support -else( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" ) +else() set( CMAKE_CXX_EXTENSIONS OFF ) -endif( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" ) +endif() # http://stackoverflow.com/a/18369825 if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") From 34372a78cc070bd292506e45f98caaf00cde45f6 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Wed, 21 Aug 2019 14:12:40 +0200 Subject: [PATCH 108/111] Bump fc to fix #1948 --- libraries/fc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/fc b/libraries/fc index 91d8772b7b..ea85954e17 160000 --- a/libraries/fc +++ b/libraries/fc @@ -1 +1 @@ -Subproject commit 91d8772b7b09819b59893d645d01fe181923693d +Subproject commit ea85954e1735c2cdc7287dbe13568a4290789f6e From a67260210fddd5412c5f22e6973726bef6d95af4 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Fri, 30 Aug 2019 21:00:32 +0200 Subject: [PATCH 109/111] Bump fc again for #1952 --- libraries/fc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/fc b/libraries/fc index ea85954e17..7a4758671f 160000 --- a/libraries/fc +++ b/libraries/fc @@ -1 +1 @@ -Subproject commit ea85954e1735c2cdc7287dbe13568a4290789f6e +Subproject commit 7a4758671ff3635a6493ea5a6206b570beda976a From eb65c2b9c6d9ceba2fe39447935f7360f5c7fa31 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Sun, 1 Sep 2019 09:50:09 +0200 Subject: [PATCH 110/111] Fix #1965 --- CMakeLists.txt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b1471a5c30..c9bb94a7cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -114,10 +114,8 @@ endif() add_definitions (-fPIC) set(CMAKE_EXPORT_COMPILE_COMMANDS "ON") -set(GRAPHENE_EGENESIS_JSON "${CMAKE_CURRENT_SOURCE_DIR}/libraries/egenesis/genesis.json" ) - -#set (ENABLE_INSTALLER 1) -#set (USE_PCH 1) +set( GRAPHENE_EGENESIS_JSON "${CMAKE_CURRENT_SOURCE_DIR}/libraries/egenesis/genesis.json" + CACHE STRING "Path to embedded genesis file" ) if (USE_PCH) include (cotire) From 600598790c6a0d4c500d6112d7d5d85d26946969 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Sun, 1 Sep 2019 15:50:25 +0200 Subject: [PATCH 111/111] Removed confusing key output --- programs/cli_wallet/main.cpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/programs/cli_wallet/main.cpp b/programs/cli_wallet/main.cpp index 5a4f528c5b..39d24dd91f 100644 --- a/programs/cli_wallet/main.cpp +++ b/programs/cli_wallet/main.cpp @@ -182,17 +182,6 @@ int main( int argc, char** argv ) setup_logging(options.at("logs-rpc-console-level").as(),options.at("logs-rpc-file").as(), options.at("logs-rpc-file-level").as(), options.at("logs-rpc-file-name").as()); - // key generation - fc::ecc::private_key committee_private_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("null_key"))); - - idump( (key_to_wif( committee_private_key ) ) ); - - fc::ecc::private_key nathan_private_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("nathan"))); - public_key_type nathan_pub_key = nathan_private_key.get_public_key(); - idump( (nathan_pub_key) ); - idump( (key_to_wif( nathan_private_key ) ) ); - - // // TODO: We read wallet_data twice, once in main() to grab the // socket info, again in wallet_api when we do // load_wallet_file(). Seems like this could be better