diff --git a/libraries/chain/include/eosio/chain/pbft.hpp b/libraries/chain/include/eosio/chain/pbft.hpp index ca8130a2381..dd275943451 100644 --- a/libraries/chain/include/eosio/chain/pbft.hpp +++ b/libraries/chain/include/eosio/chain/pbft.hpp @@ -56,15 +56,15 @@ namespace eosio { const vector &get_prepares_cache() const; - void set_prepares_cache(const vector &prepares_cache); + void set_prepares_cache(const vector &pcache); const vector &get_commits_cache() const; - void set_commits_cache(const vector &commits_cache); + void set_commits_cache(const vector &ccache); const vector &get_view_changes_cache() const; - void set_view_changes_cache(const vector &view_changes_cache); + void set_view_changes_cache(const vector &vc_cache); const uint32_t &get_current_view() const; @@ -72,29 +72,29 @@ namespace eosio { const vector &get_prepared_certificate() const; - void set_prepared_certificate(const vector &prepared_certificate); + void set_prepared_certificate(const vector &pcert); const vector> &get_committed_certificate() const; - void set_committed_certificate(const vector> &pbft_committed_certificate_vector); + void set_committed_certificate(const vector> &ccert); const vector &get_view_changed_certificate() const; - void set_view_changed_certificate(const vector &view_changed_certificate); + void set_view_changed_certificate(const vector &vc_cert); const uint32_t &get_target_view_retries() const; - void set_target_view_retries(const uint32_t &target_view_reties); + void set_target_view_retries(const uint32_t &tv_reties); const uint32_t &get_target_view() const; - void set_target_view(const uint32_t &target_view); + void set_target_view(const uint32_t &tv); const uint32_t &get_view_change_timer() const; - void set_view_change_timer(const uint32_t &view_change_timer); + void set_view_change_timer(const uint32_t &vc_timer); - void manually_set_current_view(const uint32_t ¤t_view); + void manually_set_current_view(const uint32_t &cv); protected: psm_cache cache; diff --git a/libraries/chain/pbft.cpp b/libraries/chain/pbft.cpp index 3d8b0ac2ff5..2236de50f5a 100644 --- a/libraries/chain/pbft.cpp +++ b/libraries/chain/pbft.cpp @@ -142,8 +142,8 @@ namespace eosio { current->on_new_view(this, e, pbft_db); } - void psm_machine::manually_set_current_view(const uint32_t ¤t_view) { - current->manually_set_view(this, current_view); + void psm_machine::manually_set_current_view(const uint32_t &cv) { + current->manually_set_view(this, cv); } /** @@ -575,24 +575,24 @@ namespace eosio { return this->cache.prepares_cache; } - void psm_machine::set_prepares_cache(const vector &prepares_cache) { - this->cache.prepares_cache = prepares_cache; + void psm_machine::set_prepares_cache(const vector &pcache) { + this->cache.prepares_cache = pcache; } const vector &psm_machine::get_commits_cache() const { return this->cache.commits_cache; } - void psm_machine::set_commits_cache(const vector &commits_cache) { - this->cache.commits_cache = commits_cache; + void psm_machine::set_commits_cache(const vector &ccache) { + this->cache.commits_cache = ccache; } const vector &psm_machine::get_view_changes_cache() const { return this->cache.view_changes_cache; } - void psm_machine::set_view_changes_cache(const vector &view_changes_cache) { - this->cache.view_changes_cache = view_changes_cache; + void psm_machine::set_view_changes_cache(const vector &vc_cache) { + this->cache.view_changes_cache = vc_cache; } const uint32_t &psm_machine::get_current_view() const { @@ -607,16 +607,16 @@ namespace eosio { return this->cache.prepared_certificate; } - void psm_machine::set_prepared_certificate(const vector &prepared_certificate) { - this->cache.prepared_certificate = prepared_certificate; + void psm_machine::set_prepared_certificate(const vector &pcert) { + this->cache.prepared_certificate = pcert; } const vector> &psm_machine::get_committed_certificate() const { return this->cache.committed_certificate; } - void psm_machine::set_committed_certificate(const vector> &pbft_committed_certificate_vector) { - this->cache.committed_certificate = pbft_committed_certificate_vector; + void psm_machine::set_committed_certificate(const vector> &ccert) { + this->cache.committed_certificate = ccert; } const vector &psm_machine::get_view_changed_certificate() const { @@ -624,32 +624,32 @@ namespace eosio { } void psm_machine::set_view_changed_certificate( - const vector &view_changed_certificate) { - this->cache.view_changed_certificate = view_changed_certificate; + const vector &vc_cert) { + this->cache.view_changed_certificate = vc_cert; } const uint32_t &psm_machine::get_target_view_retries() const { return this->target_view_retries; } - void psm_machine::set_target_view_retries(const uint32_t &target_view_reties) { - this->target_view_retries = target_view_reties; + void psm_machine::set_target_view_retries(const uint32_t &tv_reties) { + this->target_view_retries = tv_reties; } const uint32_t &psm_machine::get_target_view() const { return this->target_view; } - void psm_machine::set_target_view(const uint32_t &target_view) { - this->target_view = target_view; + void psm_machine::set_target_view(const uint32_t &tv) { + this->target_view = tv; } const uint32_t &psm_machine::get_view_change_timer() const { return this->view_change_timer; } - void psm_machine::set_view_change_timer(const uint32_t &view_change_timer) { - this->view_change_timer = view_change_timer; + void psm_machine::set_view_change_timer(const uint32_t &vc_timer) { + this->view_change_timer = vc_timer; } } } \ No newline at end of file diff --git a/libraries/chain/pbft_database.cpp b/libraries/chain/pbft_database.cpp index 3d7c736285e..5440aec0db2 100644 --- a/libraries/chain/pbft_database.cpp +++ b/libraries/chain/pbft_database.cpp @@ -667,9 +667,11 @@ namespace eosio { pcc.resize(ctrl.my_signature_providers().size()); const auto &by_commit_and_num_index = pbft_state_index.get(); auto itr = by_commit_and_num_index.begin(); + if (itr == by_commit_and_num_index.end()) return vector>{}; pbft_state_ptr psp = *itr; - if (itr == by_commit_and_num_index.end() || !psp->should_committed) return vector>{}; + + if (!psp->should_committed) return vector>{}; auto highest_committed_block_num = psp->block_num; @@ -1200,7 +1202,7 @@ namespace eosio { } if (!pending_checkpoint_block_num.empty()) { - std::sort(pending_checkpoint_block_num.begin(), pending_checkpoint_block_num.begin()); + std::sort(pending_checkpoint_block_num.begin(), pending_checkpoint_block_num.end()); for (auto h: pending_checkpoint_block_num) { for (auto const &my_sp : ctrl.my_signature_providers()) { auto uuid = boost::uuids::to_string(uuid_generator()); diff --git a/plugins/txn_test_gen_plugin/CMakeLists.txt b/plugins/txn_test_gen_plugin/CMakeLists.txt index e765f3478e6..286066d6149 100644 --- a/plugins/txn_test_gen_plugin/CMakeLists.txt +++ b/plugins/txn_test_gen_plugin/CMakeLists.txt @@ -5,6 +5,6 @@ add_library( txn_test_gen_plugin add_dependencies(txn_test_gen_plugin eosio.token) -target_link_libraries( txn_test_gen_plugin appbase fc http_plugin chain_plugin ) +target_link_libraries( txn_test_gen_plugin appbase fc http_plugin chain_plugin net_plugin) target_include_directories( txn_test_gen_plugin PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" ) target_include_directories( txn_test_gen_plugin PUBLIC ${CMAKE_BINARY_DIR}/contracts ) diff --git a/plugins/txn_test_gen_plugin/README.md b/plugins/txn_test_gen_plugin/README.md index 8d74e6a0412..313fdf83e5d 100644 --- a/plugins/txn_test_gen_plugin/README.md +++ b/plugins/txn_test_gen_plugin/README.md @@ -68,8 +68,28 @@ $ ./cleos set contract eosio ~/eos/build.release/contracts/eosio.bios/ ### Initialize the accounts txn_test_gen_plugin uses ```bash -$ curl --data-binary '["eosio", "5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3"]' http://127.0.0.1:8888/v1/txn_test_gen/create_test_accounts +$ curl --data-binary '[, , ]' http://127.0.0.1:8888/v1/txn_test_gen/create_test_accounts + +example: +$ curl --data-binary '["eosio", "5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3", "EOS"]' http://127.0.0.1:8888/v1/txn_test_gen/create_test_accounts ``` +> **make sure there are more than 4000,0000 ** in creator + + +This api does: +1. creates following accounts: +aaaaaaaaaaaa +bbbbbbbbbbbb +cccccccccccc + +1. delegate 1000,0000 cpu, 100 net, and 100 ram to above accounts using +1. deploy a token contract to account cccccccccccc and issue a large number of tokens to cccccccccccc, then transfer some tokens to aaaaaaaaaaaa and bbbbbbbbbbbb +1. subsequent trx will be generated using deployed token contract + 1. aaaaaaaaaaaa transfer to bbbbbbbbbbbb + 1. bbbbbbbbbbbb transfer to aaaaaaaaaaaa + + + ### Start transaction generation, this will submit 20 transactions evey 20ms (total of 1000TPS) ```bash diff --git a/plugins/txn_test_gen_plugin/txn_test_gen_plugin.cpp b/plugins/txn_test_gen_plugin/txn_test_gen_plugin.cpp index 3a2c4fed5fb..06b6f437cdb 100644 --- a/plugins/txn_test_gen_plugin/txn_test_gen_plugin.cpp +++ b/plugins/txn_test_gen_plugin/txn_test_gen_plugin.cpp @@ -4,6 +4,7 @@ */ #include #include +#include #include #include @@ -24,9 +25,11 @@ #include #include +#include +#include namespace eosio { namespace detail { - struct txn_test_gen_empty {}; +struct txn_test_gen_empty {}; }} FC_REFLECT(eosio::detail::txn_test_gen_empty, ); @@ -82,341 +85,414 @@ using namespace eosio::chain; }\ } -#define INVOKE_ASYNC_R_R(api_handle, call_name, in_param0, in_param1) \ +#define INVOKE_ASYNC_R_R(api_handle, call_name, in_param0, in_param1, in_param2) \ const auto& vs = fc::json::json::from_string(body).as(); \ - api_handle->call_name(vs.at(0).as(), vs.at(1).as(), result_handler); + api_handle->call_name(vs.at(0).as(), vs.at(1).as(), vs.at(2).as(), result_handler); struct txn_test_gen_plugin_impl { - uint64_t _total_us = 0; - uint64_t _txcount = 0; + uint64_t _total_us = 0; + uint64_t _txcount = 0; - int _remain = 0; + int _remain = 0; - void push_next_transaction(const std::shared_ptr>& trxs, size_t index, const std::function& next ) { + std::string cached_salt; + uint64_t cached_period; + uint64_t cached_batch_size; + + void push_next_transaction(const std::shared_ptr>& trxs, size_t index, const std::function& next ) { chain_plugin& cp = app().get_plugin(); const int overlap = 20; int end = std::min(index + overlap, trxs->size()); _remain = end - index; for (int i = index; i < end; ++i) { - cp.accept_transaction( packed_transaction(trxs->at(i)), [=](const fc::static_variant& result){ + cp.accept_transaction( packed_transaction(trxs->at(i)), [=](const fc::static_variant& result){ if (result.contains()) { - next(result.get()); + next(result.get()); } else { - if (result.contains() && result.get()->receipt) { - _total_us += result.get()->receipt->cpu_usage_us; - ++_txcount; - } - --_remain; - if (_remain == 0 ) { - if (end < trxs->size()) { - push_next_transaction(trxs, index + overlap, next); - } else { - next(nullptr); - } - } + if (result.contains() && result.get()->receipt) { + _total_us += result.get()->receipt->cpu_usage_us; + ++_txcount; + } + --_remain; + if (_remain == 0 ) { + if (end < trxs->size()) { + push_next_transaction(trxs, index + overlap, next); + } else { + next(nullptr); + } + } } - }); + }); } - } + } - void push_transactions( std::vector&& trxs, const std::function& next ) { + void push_transactions( std::vector&& trxs, const std::function& next ) { auto trxs_copy = std::make_shared>(std::move(trxs)); push_next_transaction(trxs_copy, 0, next); - } + } - void create_test_accounts(const std::string& init_name, const std::string& init_priv_key, const std::function& next) { + void create_test_accounts(const std::string& init_name, const std::string& init_priv_key, + const std::string& core_symbol, + const std::function& next) { std::vector trxs; trxs.reserve(2); try { - name newaccountA("txn.test.a"); - name newaccountB("txn.test.b"); - name newaccountC("txn.test.t"); - name creator(init_name); - - abi_def currency_abi_def = fc::json::from_string(eosio_token_abi).as(); - - controller& cc = app().get_plugin().chain(); - auto chainid = app().get_plugin().get_chain_id(); - auto abi_serializer_max_time = app().get_plugin().get_abi_serializer_max_time(); - - abi_serializer eosio_token_serializer{fc::json::from_string(eosio_token_abi).as(), abi_serializer_max_time}; - - fc::crypto::private_key txn_test_receiver_A_priv_key = fc::crypto::private_key::regenerate(fc::sha256(std::string(64, 'a'))); - fc::crypto::private_key txn_test_receiver_B_priv_key = fc::crypto::private_key::regenerate(fc::sha256(std::string(64, 'b'))); - fc::crypto::private_key txn_test_receiver_C_priv_key = fc::crypto::private_key::regenerate(fc::sha256(std::string(64, 'c'))); - fc::crypto::public_key txn_text_receiver_A_pub_key = txn_test_receiver_A_priv_key.get_public_key(); - fc::crypto::public_key txn_text_receiver_B_pub_key = txn_test_receiver_B_priv_key.get_public_key(); - fc::crypto::public_key txn_text_receiver_C_pub_key = txn_test_receiver_C_priv_key.get_public_key(); - fc::crypto::private_key creator_priv_key = fc::crypto::private_key(init_priv_key); - - //create some test accounts - { - signed_transaction trx; - - //create "A" account - { - auto owner_auth = eosio::chain::authority{1, {{txn_text_receiver_A_pub_key, 1}}, {}}; - auto active_auth = eosio::chain::authority{1, {{txn_text_receiver_A_pub_key, 1}}, {}}; - - trx.actions.emplace_back(vector{{creator,"active"}}, newaccount{creator, newaccountA, owner_auth, active_auth}); - } - //create "B" account - { - auto owner_auth = eosio::chain::authority{1, {{txn_text_receiver_B_pub_key, 1}}, {}}; - auto active_auth = eosio::chain::authority{1, {{txn_text_receiver_B_pub_key, 1}}, {}}; - - trx.actions.emplace_back(vector{{creator,"active"}}, newaccount{creator, newaccountB, owner_auth, active_auth}); - } - //create "txn.test.t" account - { - auto owner_auth = eosio::chain::authority{1, {{txn_text_receiver_C_pub_key, 1}}, {}}; - auto active_auth = eosio::chain::authority{1, {{txn_text_receiver_C_pub_key, 1}}, {}}; - - trx.actions.emplace_back(vector{{creator,"active"}}, newaccount{creator, newaccountC, owner_auth, active_auth}); - } - - trx.expiration = cc.head_block_time() + fc::seconds(30); - trx.set_reference_block(cc.head_block_id()); - trx.sign(creator_priv_key, chainid); - trxs.emplace_back(std::move(trx)); - } - - //set txn.test.t contract to eosio.token & initialize it - { - signed_transaction trx; - - vector wasm = wast_to_wasm(std::string(eosio_token_wast)); - - setcode handler; - handler.account = newaccountC; - handler.code.assign(wasm.begin(), wasm.end()); - - trx.actions.emplace_back( vector{{newaccountC,"active"}}, handler); - - { - setabi handler; - handler.account = newaccountC; - handler.abi = fc::raw::pack(json::from_string(eosio_token_abi).as()); - trx.actions.emplace_back( vector{{newaccountC,"active"}}, handler); - } - - { - action act; - act.account = N(txn.test.t); - act.name = N(create); - act.authorization = vector{{newaccountC,config::active_name}}; - act.data = eosio_token_serializer.variant_to_binary("create", fc::json::from_string("{\"issuer\":\"txn.test.t\",\"maximum_supply\":\"1000000000.0000 CUR\"}}"), abi_serializer_max_time); - trx.actions.push_back(act); - } - { - action act; - act.account = N(txn.test.t); - act.name = N(issue); - act.authorization = vector{{newaccountC,config::active_name}}; - act.data = eosio_token_serializer.variant_to_binary("issue", fc::json::from_string("{\"to\":\"txn.test.t\",\"quantity\":\"600.0000 CUR\",\"memo\":\"\"}"), abi_serializer_max_time); - trx.actions.push_back(act); - } - { - action act; - act.account = N(txn.test.t); - act.name = N(transfer); - act.authorization = vector{{newaccountC,config::active_name}}; - act.data = eosio_token_serializer.variant_to_binary("transfer", fc::json::from_string("{\"from\":\"txn.test.t\",\"to\":\"txn.test.a\",\"quantity\":\"200.0000 CUR\",\"memo\":\"\"}"), abi_serializer_max_time); - trx.actions.push_back(act); - } - { - action act; - act.account = N(txn.test.t); - act.name = N(transfer); - act.authorization = vector{{newaccountC,config::active_name}}; - act.data = eosio_token_serializer.variant_to_binary("transfer", fc::json::from_string("{\"from\":\"txn.test.t\",\"to\":\"txn.test.b\",\"quantity\":\"200.0000 CUR\",\"memo\":\"\"}"), abi_serializer_max_time); - trx.actions.push_back(act); - } - - trx.expiration = cc.head_block_time() + fc::seconds(30); - trx.set_reference_block(cc.head_block_id()); - trx.max_net_usage_words = 5000; - trx.sign(txn_test_receiver_C_priv_key, chainid); - trxs.emplace_back(std::move(trx)); - } + name newaccountA("aaaaaaaaaaaa"); + name newaccountB("bbbbbbbbbbbb"); + name newaccountC("cccccccccccc"); + name creator(init_name); + + abi_def currency_abi_def = fc::json::from_string(eosio_token_abi).as(); + + controller& cc = app().get_plugin().chain(); + auto chainid = app().get_plugin().get_chain_id(); + auto abi_serializer_max_time = app().get_plugin().get_abi_serializer_max_time(); + + abi_serializer eosio_token_serializer{fc::json::from_string(eosio_token_abi).as(), abi_serializer_max_time}; + + fc::crypto::private_key txn_test_receiver_A_priv_key = fc::crypto::private_key::regenerate(fc::sha256(std::string(64, 'a'))); + fc::crypto::private_key txn_test_receiver_B_priv_key = fc::crypto::private_key::regenerate(fc::sha256(std::string(64, 'b'))); + fc::crypto::private_key txn_test_receiver_C_priv_key = fc::crypto::private_key::regenerate(fc::sha256(std::string(64, 'c'))); + fc::crypto::public_key txn_text_receiver_A_pub_key = txn_test_receiver_A_priv_key.get_public_key(); + fc::crypto::public_key txn_text_receiver_B_pub_key = txn_test_receiver_B_priv_key.get_public_key(); + fc::crypto::public_key txn_text_receiver_C_pub_key = txn_test_receiver_C_priv_key.get_public_key(); + fc::crypto::private_key creator_priv_key = fc::crypto::private_key(init_priv_key); + + eosio::chain::asset net{1000000, symbol(4,core_symbol.c_str())}; + eosio::chain::asset cpu{10000000000, symbol(4,core_symbol.c_str())}; + eosio::chain::asset ram{1000000, symbol(4,core_symbol.c_str())}; + + //create some test accounts + { + signed_transaction trx; + + //create "A" account + { + auto owner_auth = eosio::chain::authority{1, {{txn_text_receiver_A_pub_key, 1}}, {}}; + auto active_auth = eosio::chain::authority{1, {{txn_text_receiver_A_pub_key, 1}}, {}}; + + trx.actions.emplace_back(vector{{creator,"active"}}, newaccount{creator, newaccountA, owner_auth, active_auth}); + + //delegate cpu net and buyram + auto act_delegatebw = create_action_delegatebw(creator, newaccountA,net,cpu,abi_serializer_max_time); + auto act_buyram = create_action_buyram(creator, newaccountA, ram, abi_serializer_max_time); + + trx.actions.emplace_back(act_delegatebw); + trx.actions.emplace_back(act_buyram); + + } + //create "B" account + { + auto owner_auth = eosio::chain::authority{1, {{txn_text_receiver_B_pub_key, 1}}, {}}; + auto active_auth = eosio::chain::authority{1, {{txn_text_receiver_B_pub_key, 1}}, {}}; + + trx.actions.emplace_back(vector{{creator,"active"}}, newaccount{creator, newaccountB, owner_auth, active_auth}); + + //delegate cpu net and buyram + auto act_delegatebw = create_action_delegatebw(creator, newaccountB,net,cpu,abi_serializer_max_time); + auto act_buyram = create_action_buyram(creator, newaccountB, ram, abi_serializer_max_time); + + trx.actions.emplace_back(act_delegatebw); + trx.actions.emplace_back(act_buyram); + } + //create "cccccccccccc" account + { + auto owner_auth = eosio::chain::authority{1, {{txn_text_receiver_C_pub_key, 1}}, {}}; + auto active_auth = eosio::chain::authority{1, {{txn_text_receiver_C_pub_key, 1}}, {}}; + + trx.actions.emplace_back(vector{{creator,"active"}}, newaccount{creator, newaccountC, owner_auth, active_auth}); + + //delegate cpu net and buyram + auto act_delegatebw = create_action_delegatebw(creator, newaccountC,net,cpu,abi_serializer_max_time); + auto act_buyram = create_action_buyram(creator, newaccountC, ram, abi_serializer_max_time); + + trx.actions.emplace_back(act_delegatebw); + trx.actions.emplace_back(act_buyram); + } + + trx.expiration = cc.head_block_time() + fc::seconds(30); + trx.set_reference_block(cc.head_block_id()); + trx.sign(creator_priv_key, chainid); + trxs.emplace_back(std::move(trx)); + } + + //set cccccccccccc contract to eosio.token & initialize it + { + signed_transaction trx; + + vector wasm = wast_to_wasm(std::string(eosio_token_wast)); + + setcode handler; + handler.account = newaccountC; + handler.code.assign(wasm.begin(), wasm.end()); + + trx.actions.emplace_back( vector{{newaccountC,"active"}}, handler); + + { + setabi handler; + handler.account = newaccountC; + handler.abi = fc::raw::pack(json::from_string(eosio_token_abi).as()); + trx.actions.emplace_back( vector{{newaccountC,"active"}}, handler); + } + + { + action act; + act.account = N(cccccccccccc); + act.name = N(create); + act.authorization = vector{{newaccountC,config::active_name}}; + act.data = eosio_token_serializer.variant_to_binary("create", fc::json::from_string("{\"issuer\":\"cccccccccccc\",\"maximum_supply\":\"1000000000.0000 CUR\"}}"), abi_serializer_max_time); + trx.actions.push_back(act); + } + { + action act; + act.account = N(cccccccccccc); + act.name = N(issue); + act.authorization = vector{{newaccountC,config::active_name}}; + act.data = eosio_token_serializer.variant_to_binary("issue", fc::json::from_string("{\"to\":\"cccccccccccc\",\"quantity\":\"1000000000.0000 CUR\",\"memo\":\"\"}"), abi_serializer_max_time); + trx.actions.push_back(act); + } + { + action act; + act.account = N(cccccccccccc); + act.name = N(transfer); + act.authorization = vector{{newaccountC,config::active_name}}; + act.data = eosio_token_serializer.variant_to_binary("transfer", fc::json::from_string("{\"from\":\"cccccccccccc\",\"to\":\"aaaaaaaaaaaa\",\"quantity\":\"500000000.0000 CUR\",\"memo\":\"\"}"), abi_serializer_max_time); + trx.actions.push_back(act); + } + { + action act; + act.account = N(cccccccccccc); + act.name = N(transfer); + act.authorization = vector{{newaccountC,config::active_name}}; + act.data = eosio_token_serializer.variant_to_binary("transfer", fc::json::from_string("{\"from\":\"cccccccccccc\",\"to\":\"bbbbbbbbbbbb\",\"quantity\":\"500000000.0000 CUR\",\"memo\":\"\"}"), abi_serializer_max_time); + trx.actions.push_back(act); + } + + trx.expiration = cc.head_block_time() + fc::seconds(30); + trx.set_reference_block(cc.head_block_id()); + trx.max_net_usage_words = 5000; + trx.sign(txn_test_receiver_C_priv_key, chainid); + trxs.emplace_back(std::move(trx)); + } } catch (const fc::exception& e) { - next(e.dynamic_copy_exception()); - return; + next(e.dynamic_copy_exception()); + return; } push_transactions(std::move(trxs), next); - } - - void start_generation(const std::string& salt, const uint64_t& period, const uint64_t& batch_size) { + } + + eosio::chain::action create_action_delegatebw(const name &from, const name &to, const asset &net, const asset &cpu, const fc::microseconds &abi_serializer_max_time){ + fc::variant variant_delegate = fc::mutable_variant_object() + ("from", from.to_string()) + ("receiver", to.to_string()) + ("stake_net_quantity", net.to_string()) + ("stake_cpu_quantity", cpu.to_string()) + ("transfer", true); + abi_serializer eosio_system_serializer{fc::json::from_string(eosio_system_abi).as(), abi_serializer_max_time}; + + auto payload_delegate = eosio_system_serializer.variant_to_binary( "delegatebw", variant_delegate, abi_serializer_max_time); + eosio::chain::action act_delegate{vector{{from,"active"}}, + config::system_account_name, N(delegatebw), payload_delegate}; + + return act_delegate; + } + + eosio::chain::action create_action_buyram(const name &from, const name &to, const asset &quant, const fc::microseconds &abi_serializer_max_time){ + fc::variant variant_buyram = fc::mutable_variant_object() + ("payer", from.to_string()) + ("receiver", to.to_string()) + ("quant", quant.to_string()); + abi_serializer eosio_system_serializer{fc::json::from_string(eosio_system_abi).as(), abi_serializer_max_time}; + + auto payload_buyram = eosio_system_serializer.variant_to_binary( "buyram", variant_buyram, abi_serializer_max_time); + eosio::chain::action act_buyram{vector{{from,"active"}}, + config::system_account_name, N(buyram), payload_buyram}; + + return act_buyram; + } + + void start_generation(const std::string& salt, const uint64_t& period, const uint64_t& batch_size) { if(running) - throw fc::exception(fc::invalid_operation_exception_code); + throw fc::exception(fc::invalid_operation_exception_code); if(period < 1 || period > 2500) - throw fc::exception(fc::invalid_operation_exception_code); + throw fc::exception(fc::invalid_operation_exception_code); if(batch_size < 1 || batch_size > 250) - throw fc::exception(fc::invalid_operation_exception_code); + throw fc::exception(fc::invalid_operation_exception_code); if(batch_size & 1) - throw fc::exception(fc::invalid_operation_exception_code); + throw fc::exception(fc::invalid_operation_exception_code); running = true; + cached_salt = salt; + cached_period = period; + cached_batch_size = batch_size; controller& cc = app().get_plugin().chain(); auto abi_serializer_max_time = app().get_plugin().get_abi_serializer_max_time(); abi_serializer eosio_token_serializer{fc::json::from_string(eosio_token_abi).as(), abi_serializer_max_time}; //create the actions here - act_a_to_b.account = N(txn.test.t); + act_a_to_b.account = N(cccccccccccc); act_a_to_b.name = N(transfer); - act_a_to_b.authorization = vector{{name("txn.test.a"),config::active_name}}; - act_a_to_b.data = eosio_token_serializer.variant_to_binary("transfer", - fc::json::from_string(fc::format_string("{\"from\":\"txn.test.a\",\"to\":\"txn.test.b\",\"quantity\":\"1.0000 CUR\",\"memo\":\"${l}\"}", - fc::mutable_variant_object()("l", salt))), - abi_serializer_max_time); + act_a_to_b.authorization = vector{{name("aaaaaaaaaaaa"),config::active_name}}; + act_a_to_b.data = eosio_token_serializer.variant_to_binary("transfer", + fc::json::from_string(fc::format_string("{\"from\":\"aaaaaaaaaaaa\",\"to\":\"bbbbbbbbbbbb\",\"quantity\":\"1.0000 CUR\",\"memo\":\"${l}\"}", + fc::mutable_variant_object()("l", salt))), + abi_serializer_max_time); - act_b_to_a.account = N(txn.test.t); + act_b_to_a.account = N(cccccccccccc); act_b_to_a.name = N(transfer); - act_b_to_a.authorization = vector{{name("txn.test.b"),config::active_name}}; - act_b_to_a.data = eosio_token_serializer.variant_to_binary("transfer", - fc::json::from_string(fc::format_string("{\"from\":\"txn.test.b\",\"to\":\"txn.test.a\",\"quantity\":\"1.0000 CUR\",\"memo\":\"${l}\"}", - fc::mutable_variant_object()("l", salt))), - abi_serializer_max_time); + act_b_to_a.authorization = vector{{name("bbbbbbbbbbbb"),config::active_name}}; + act_b_to_a.data = eosio_token_serializer.variant_to_binary("transfer", + fc::json::from_string(fc::format_string("{\"from\":\"bbbbbbbbbbbb\",\"to\":\"aaaaaaaaaaaa\",\"quantity\":\"1.0000 CUR\",\"memo\":\"${l}\"}", + fc::mutable_variant_object()("l", salt))), + abi_serializer_max_time); timer_timeout = period; batch = batch_size/2; ilog("Started transaction test plugin; performing ${p} transactions every ${m}ms", ("p", batch_size)("m", period)); + ilog("wait 3 seconds to spin up"); + arm_timer(boost::asio::high_resolution_timer::clock_type::now() + std::chrono::milliseconds(3000) ); + } - arm_timer(boost::asio::high_resolution_timer::clock_type::now()); - } - - void arm_timer(boost::asio::high_resolution_timer::time_point s) { + void arm_timer(boost::asio::high_resolution_timer::time_point s) { timer.expires_at(s + std::chrono::milliseconds(timer_timeout)); timer.async_wait([this](const boost::system::error_code& ec) { - if(!running || ec) + if(!running || ec) return; - send_transaction([this](const fc::exception_ptr& e){ - if (e) { - elog("pushing transaction failed: ${e}", ("e", e->to_detail_string())); - stop_generation(); - } else { - arm_timer(timer.expires_at()); - } - }); + send_transaction([this](const fc::exception_ptr& e){ + if (e) { + elog("pushing transaction failed: ${e}", ("e", e->to_detail_string())); + stop_generation(); + auto peers_conn = app().get_plugin().connections(); + for(const auto c : peers_conn){ + app().get_plugin().disconnect(c.peer); + } + for(const auto c : peers_conn){ + app().get_plugin().connect(c.peer); + } + start_generation(cached_salt,cached_period,cached_batch_size); + } else { + arm_timer(timer.expires_at()); + } + }); }); - } + } - void send_transaction(std::function next) { + void send_transaction(std::function next) { std::vector trxs; trxs.reserve(2*batch); try { - controller& cc = app().get_plugin().chain(); - auto chainid = app().get_plugin().get_chain_id(); - - static fc::crypto::private_key a_priv_key = fc::crypto::private_key::regenerate(fc::sha256(std::string(64, 'a'))); - static fc::crypto::private_key b_priv_key = fc::crypto::private_key::regenerate(fc::sha256(std::string(64, 'b'))); - - static uint64_t nonce = static_cast(fc::time_point::now().sec_since_epoch()) << 32; - - uint32_t reference_block_num = cc.last_irreversible_block_num(); - if (txn_reference_block_lag >= 0) { - reference_block_num = cc.head_block_num(); - if (reference_block_num <= (uint32_t)txn_reference_block_lag) { - reference_block_num = 0; - } else { - reference_block_num -= (uint32_t)txn_reference_block_lag; - } - } - - block_id_type reference_block_id = cc.get_block_id_for_num(reference_block_num); - - for(unsigned int i = 0; i < batch; ++i) { - { - signed_transaction trx; - trx.actions.push_back(act_a_to_b); - trx.context_free_actions.emplace_back(action({}, config::null_account_name, "nonce", fc::raw::pack(nonce++))); - trx.set_reference_block(reference_block_id); - trx.expiration = cc.head_block_time() + fc::seconds(30); - trx.max_net_usage_words = 100; - trx.sign(a_priv_key, chainid); - trxs.emplace_back(std::move(trx)); - } - - { - signed_transaction trx; - trx.actions.push_back(act_b_to_a); - trx.context_free_actions.emplace_back(action({}, config::null_account_name, "nonce", fc::raw::pack(nonce++))); - trx.set_reference_block(reference_block_id); - trx.expiration = cc.head_block_time() + fc::seconds(30); - trx.max_net_usage_words = 100; - trx.sign(b_priv_key, chainid); - trxs.emplace_back(std::move(trx)); - } - } + controller& cc = app().get_plugin().chain(); + auto chainid = app().get_plugin().get_chain_id(); + + static fc::crypto::private_key a_priv_key = fc::crypto::private_key::regenerate(fc::sha256(std::string(64, 'a'))); + static fc::crypto::private_key b_priv_key = fc::crypto::private_key::regenerate(fc::sha256(std::string(64, 'b'))); + + static uint64_t nonce = static_cast(fc::time_point::now().sec_since_epoch()) << 32; + + uint32_t reference_block_num = cc.last_irreversible_block_num(); + if (txn_reference_block_lag >= 0) { + reference_block_num = cc.head_block_num(); + if (reference_block_num <= (uint32_t)txn_reference_block_lag) { + reference_block_num = 0; + } else { + reference_block_num -= (uint32_t)txn_reference_block_lag; + } + } + + block_id_type reference_block_id = cc.get_block_id_for_num(reference_block_num); + + for(unsigned int i = 0; i < batch; ++i) { + { + signed_transaction trx; + trx.actions.push_back(act_a_to_b); + trx.context_free_actions.emplace_back(action({}, config::null_account_name, "nonce", fc::raw::pack(nonce++))); + trx.set_reference_block(reference_block_id); + trx.expiration = cc.head_block_time() + fc::seconds(30); + trx.max_net_usage_words = 100; + trx.sign(a_priv_key, chainid); + trxs.emplace_back(std::move(trx)); + } + + { + signed_transaction trx; + trx.actions.push_back(act_b_to_a); + trx.context_free_actions.emplace_back(action({}, config::null_account_name, "nonce", fc::raw::pack(nonce++))); + trx.set_reference_block(reference_block_id); + trx.expiration = cc.head_block_time() + fc::seconds(30); + trx.max_net_usage_words = 100; + trx.sign(b_priv_key, chainid); + trxs.emplace_back(std::move(trx)); + } + } } catch ( const fc::exception& e ) { - next(e.dynamic_copy_exception()); + next(e.dynamic_copy_exception()); } push_transactions(std::move(trxs), next); - } + } - void stop_generation() { + void stop_generation() { if(!running) - throw fc::exception(fc::invalid_operation_exception_code); + throw fc::exception(fc::invalid_operation_exception_code); timer.cancel(); running = false; ilog("Stopping transaction generation test"); if (_txcount) { - ilog("${d} transactions executed, ${t}us / transaction", ("d", _txcount)("t", _total_us / (double)_txcount)); - _txcount = _total_us = 0; + ilog("${d} transactions executed, ${t}us / transaction", ("d", _txcount)("t", _total_us / (double)_txcount)); + _txcount = _total_us = 0; } - } + } - boost::asio::high_resolution_timer timer{app().get_io_service()}; - bool running{false}; + boost::asio::high_resolution_timer timer{app().get_io_service()}; + bool running{false}; - unsigned timer_timeout; - unsigned batch; + unsigned timer_timeout; + unsigned batch; - action act_a_to_b; - action act_b_to_a; + action act_a_to_b; + action act_b_to_a; - int32_t txn_reference_block_lag; + int32_t txn_reference_block_lag; }; txn_test_gen_plugin::txn_test_gen_plugin() {} txn_test_gen_plugin::~txn_test_gen_plugin() {} void txn_test_gen_plugin::set_program_options(options_description&, options_description& cfg) { - cfg.add_options() - ("txn-reference-block-lag", bpo::value()->default_value(0), "Lag in number of blocks from the head block when selecting the reference block for transactions (-1 means Last Irreversible Block)") - ; + cfg.add_options() + ("txn-reference-block-lag", bpo::value()->default_value(0), "Lag in number of blocks from the head block when selecting the reference block for transactions (-1 means Last Irreversible Block)") + ; } void txn_test_gen_plugin::plugin_initialize(const variables_map& options) { - try { - my.reset( new txn_test_gen_plugin_impl ); - my->txn_reference_block_lag = options.at( "txn-reference-block-lag" ).as(); - } FC_LOG_AND_RETHROW() + try { + my.reset( new txn_test_gen_plugin_impl ); + my->txn_reference_block_lag = options.at( "txn-reference-block-lag" ).as(); + } FC_LOG_AND_RETHROW() } void txn_test_gen_plugin::plugin_startup() { - app().get_plugin().add_api({ - CALL_ASYNC(txn_test_gen, my, create_test_accounts, INVOKE_ASYNC_R_R(my, create_test_accounts, std::string, std::string), 200), - CALL(txn_test_gen, my, stop_generation, INVOKE_V_V(my, stop_generation), 200), - CALL(txn_test_gen, my, start_generation, INVOKE_V_R_R_R(my, start_generation, std::string, uint64_t, uint64_t), 200) - }); + app().get_plugin().add_api({ + CALL_ASYNC(txn_test_gen, my, create_test_accounts, INVOKE_ASYNC_R_R(my, create_test_accounts, std::string, std::string, std::string), 200), + CALL(txn_test_gen, my, stop_generation, INVOKE_V_V(my, stop_generation), 200), + CALL(txn_test_gen, my, start_generation, INVOKE_V_R_R_R(my, start_generation, std::string, uint64_t, uint64_t), 200) + }); } void txn_test_gen_plugin::plugin_shutdown() { - try { - my->stop_generation(); - } - catch(fc::exception e) { - } + try { + my->stop_generation(); + } + catch(fc::exception e) { + } } }