diff --git a/.gitignore b/.gitignore index 03917111..4ae0dfcb 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ CMakeCache.txt CMakeFiles Makefile +CMakeDoxyfile.in compile_commands.json moc_* *.moc diff --git a/CMakeLists.txt b/CMakeLists.txt index 8ebf9319..3f725ced 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,11 +1,11 @@ # Defines LocalCoin library target. -project( BitShares ) +project( LocalCoin ) cmake_minimum_required( VERSION 2.8.12 ) -set( BLOCKCHAIN_NAME "BitShares" ) +set( BLOCKCHAIN_NAME "LocalCoin" ) set( CLI_CLIENT_EXECUTABLE_NAME graphene_client ) -set( GUI_CLIENT_EXECUTABLE_NAME BitShares ) +set( GUI_CLIENT_EXECUTABLE_NAME LocalCoin ) set( CUSTOM_URL_SCHEME "gcs" ) set( INSTALLER_APP_ID "68ad7005-8eee-49c9-95ce-9eed97e5b347" ) @@ -102,6 +102,11 @@ if( WIN32 ) SET(TCL_LIBS "${TCL_LIBS}${TCL_LIB_PATH}/${TCL_LIB_NAME}g${TCL_LIB_EXT}") SET(TCL_LIBRARY ${TCL_LIBS}) + find_package( CURL ) + set(CURL_STATICLIB ON) + include_directories( ${CURL_INCLUDE_DIRS} ) + link_directories( ${CURL_LIBRARIES} ) + else( WIN32 ) # Apple AND Linux if( APPLE ) @@ -177,15 +182,15 @@ set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSIO set(CPACK_PACKAGE_DESCRIPTION "A client for the LocalCoin network") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "A client for the LocalCoin network") set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.md") -set(CPACK_PACKAGE_INSTALL_DIRECTORY "BitShares ${CPACK_PACKAGE_VERSION}") +set(CPACK_PACKAGE_INSTALL_DIRECTORY "LocalCoin ${CPACK_PACKAGE_VERSION}") if(WIN32) SET(CPACK_GENERATOR "ZIP;NSIS") - set(CPACK_PACKAGE_NAME "BitShares") # override above + set(CPACK_PACKAGE_NAME "LocalCoin") # override above set(CPACK_NSIS_EXECUTABLES_DIRECTORY .) - set(CPACK_NSIS_PACKAGE_NAME "BitShares v${CPACK_PACKAGE_VERSION}") + set(CPACK_NSIS_PACKAGE_NAME "LocalCoin v${CPACK_PACKAGE_VERSION}") set(CPACK_NSIS_DISPLAY_NAME "${CPACK_NSIS_PACKAGE_NAME}") - set(CPACK_NSIS_DEFINES " !define MUI_STARTMENUPAGE_DEFAULTFOLDER \\\"BitShares\\\"") + set(CPACK_NSIS_DEFINES " !define MUI_STARTMENUPAGE_DEFAULTFOLDER \\\"LocalCoin\\\"") # it seems like windows zip files usually don't have a single directory inside them, unix tgz frequently do SET(CPACK_INCLUDE_TOPLEVEL_DIRECTORY 0) diff --git a/README.md b/README.md index 5d1e76b4..2e813d90 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,6 @@ -LocalCoin Core +LocalCoin Core - MasterNodes ============== -[Build Status](https://travis-ci.org/LocalCoinIS/LocalCoin-core/branches): - -`master` | `develop` | `hardfork` | `testnet` | `localcoin-fc` - --- | --- | --- | --- | --- - [![](https://travis-ci.org/LocalCoinIS/LocalCoin-core.svg?branch=master)](https://travis-ci.org/LocalCoinIS/LocalCoin-core) | [![](https://travis-ci.org/LocalCoinIS/LocalCoin-core.svg?branch=develop)](https://travis-ci.org/LocalCoinIS/LocalCoin-core) | [![](https://travis-ci.org/LocalCoinIS/LocalCoin-core.svg?branch=hardfork)](https://travis-ci.org/LocalCoinIS/LocalCoin-core) | [![](https://travis-ci.org/LocalCoinIS/LocalCoin-core.svg?branch=testnet)](https://travis-ci.org/LocalCoinIS/LocalCoin-core) | [![](https://travis-ci.org/LocalCoinIS/LocalCoin-fc.svg?branch=master)](https://travis-ci.org/LocalCoinIS/LocalCoin-fc) - - * [Getting Started](#getting-started) * [Support](#support) * [Using the API](#using-the-api) @@ -18,7 +11,7 @@ LocalCoin Core LocalCoin Core is the LocalCoin blockchain implementation and command-line interface. The web wallet is [LocalCoin UI](https://github.com/LocalCoinIS/LocalCoin-ui). -Visit [localcoin.org](https://localcoin.org/) to learn about LocalCoin and join the community at [localcoinTalk.org](https://localcointalk.org/). +Visit [localcoin.is](https://localcoin.is/) to learn about LocalCoin. **NOTE:** The official LocalCoin git repository location, default branch, and submodule remotes were recently changed. Existing repositories can be updated with the following steps: @@ -33,7 +26,7 @@ repositories can be updated with the following steps: Getting Started --------------- Build instructions and additional documentation are available in the -[wiki](https://github.com/LocalCoinIS/LocalCoin-core/wiki). +[wiki](https://dev.localcoin.is). We recommend building on Ubuntu 16.04 LTS, and the build dependencies may be installed with: @@ -88,14 +81,10 @@ Use `help` to see all available wallet commands. Source definition and listing o Support ------- -Technical support is available in the [localcoinTalk technical support subforum](https://localcointalk.org/index.php?board=45.0). - LocalCoin Core bugs can be reported directly to the [issue tracker](https://github.com/LocalCoinIS/LocalCoin-core/issues). LocalCoin UI bugs should be reported to the [UI issue tracker](https://github.com/LocalCoinIS/LocalCoin-ui/issues) -Up to date online Doxygen documentation can be found at [Doxygen](https://localcoin.org/doxygen/hierarchy.html) - Using the API ------------- @@ -160,13 +149,6 @@ With the above configuration, here is an example of how to call `add_node` from Note, the call to `network_node` is necessary to obtain the correct API identifier for the network API. It is not guaranteed that the network API identifier will always be `2`. -Since the `network_node` API requires login, it is only accessible over the websocket RPC. Our `doxygen` documentation contains the most up-to-date information -about API's for the [witness node](https://localcoin.github.io/doxygen/namespacegraphene_1_1app.html) and the -[wallet](https://localcoin.github.io/doxygen/classgraphene_1_1wallet_1_1wallet__api.html). -If you want information which is not available from an API, it might be available -from the [database](https://localcoin.github.io/doxygen/classgraphene_1_1chain_1_1database.html); -it is fairly simple to write API methods to expose database methods. - FAQ --- @@ -207,7 +189,7 @@ FAQ The second number specifies the *type*. The type of the object determines what fields it has. For a complete list of type ID's, see `enum object_type` and `enum impl_object_type` in - [types.hpp](https://github.com/LocalCoinIS/LocalCoin-2/blob/localcoin/libraries/chain/include/graphene/chain/protocol/types.hpp). + [types.hpp](https://github.com/LocalCoinIS/LocalCoin-core/blob/master/libraries/chain/include/graphene/chain/protocol/types.hpp). The third number specifies the *instance*. The instance of the object is different for each individual object. diff --git a/check_unique_assets.php b/check_unique_assets.php deleted file mode 100644 index 75c80789..00000000 --- a/check_unique_assets.php +++ /dev/null @@ -1,17 +0,0 @@ - "2.0", - "method" => "create_account_with_brain_key", - "params" => [ - BRAIN_KEY, - $account, - LOCALCOIN_ACCOUNT, - REFFER_ACCOUNT, - true - ], - "id" => 1 - ]); - $ch = curl_init(HOST); - curl_setopt($ch, CURLOPT_POST, 1); - curl_setopt($ch, CURLOPT_POSTFIELDS, $json); - curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json')); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); - $result = curl_exec($ch); - - echo $account . "\n"; -} \ No newline at end of file diff --git a/docs b/docs index bd792d02..008cd676 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit bd792d02c70e7686da2b27197eba4fd6df30477c +Subproject commit 008cd676579efd28083e35eaff49b1b6437144d9 diff --git a/genesis.json b/genesis.json index 885941e1..edee7b20 100644 --- a/genesis.json +++ b/genesis.json @@ -245,6 +245,16 @@ ], [ 46, {} + ], + [ + 47, { + "fee": 1000000 + } + ], + [ + 48, { + "fee" : 100000 + } ] ], "scale": 10000 @@ -269,6 +279,7 @@ "cashback_vesting_threshold": 10000000, "count_non_member_votes": true, "allow_non_member_whitelists": false, + "activenode_pay_per_block": 6500, "witness_pay_per_block": 65000, "worker_budget_per_day": "30000000000", "max_predicate_opcode": 1, diff --git a/import_balances.php b/import_balances.php deleted file mode 100644 index d880b0e6..00000000 --- a/import_balances.php +++ /dev/null @@ -1,22 +0,0 @@ - $item) { - $json = json_encode([ - "jsonrpc" => "2.0", - "method" => "issue_asset", - "params" => [ - ACCOUNT, - AMOUNT, - $item["symbol"], - "init ".AMOUNT." coins", - true - ], - "id" => 1 - ]); - $ch = curl_init(HOST); - curl_setopt($ch, CURLOPT_POST, 1); - curl_setopt($ch, CURLOPT_POSTFIELDS, $json); - curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json')); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); - $result = curl_exec($ch); - - echo count($genesis["initial_assets"]) - $id - 1; - echo "\n"; -} \ No newline at end of file diff --git a/issue_assets_for_test.php b/issue_assets_for_test.php deleted file mode 100644 index ffcf107d..00000000 --- a/issue_assets_for_test.php +++ /dev/null @@ -1,47 +0,0 @@ - $item) $assets[] = $item["symbol"]; -$countAccounts = ceil(count($assets) / PART_SIZE); - -for($accountId = 1; $accountId <= $countAccounts; $accountId++) { - $account = ACCOUNT_BASE_NAME . $accountId; - $list[$account] = []; - - for($i=(($accountId-1) * PART_SIZE); $i <= $accountId * PART_SIZE; $i++) { - if(!empty($assets[$i])) { - $list[$account][] = $assets[$i]; - } - } -} - -foreach($list as $account => $assetsForAccounts) { - foreach($assetsForAccounts as $asset) { - $json = json_encode([ - "jsonrpc" => "2.0", - "method" => "issue_asset", - "params" => [ - $account, - AMOUNT, - $asset, - "init ".AMOUNT." coins", - true - ], - "id" => 1 - ]); - $ch = curl_init(HOST); - curl_setopt($ch, CURLOPT_POST, 1); - curl_setopt($ch, CURLOPT_POSTFIELDS, $json); - curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json')); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); - $result = curl_exec($ch); - - echo $account . " - " . $asset . "\n"; - } -} \ No newline at end of file diff --git a/libraries/app/application.cpp b/libraries/app/application.cpp index 67530898..d8ff8363 100644 --- a/libraries/app/application.cpp +++ b/libraries/app/application.cpp @@ -117,7 +117,7 @@ namespace graphene { namespace app { namespace detail { void application_impl::reset_p2p_node(const fc::path& data_dir) { try { - _p2p_network = std::make_shared("BitShares Reference Implementation"); + _p2p_network = std::make_shared("LocalCoin Reference Implementation"); _p2p_network->load_configuration(data_dir / "p2p"); _p2p_network->set_node_delegate(this); @@ -164,8 +164,11 @@ void application_impl::reset_p2p_node(const fc::path& data_dir) else { // https://bitsharestalk.org/index.php/topic,23715.0.html - vector seeds = { - }; + vector seeds = { + "moscow.localcoin.is:11010" // Moscow (Russia) + "ru.localcoin.is:11010" // Russia + "helsinki.localcoin.is:11010" // Helsinki (Finland) + }; for( const string& endpoint_string : seeds ) { try { @@ -500,6 +503,9 @@ bool application_impl::handle_block(const graphene::net::block_message& blk_msg, // the block was accepted, so we now know all of the transactions contained in the block if (!sync_mode) { + _chain_db->notify_new_block_applied( blk_msg.block ); //emit + + // if we're not in sync mode, there's a chance we will be seeing some transactions // included in blocks before we see the free-floating transaction itself. If that // happens, there's no reason to fetch the transactions, so construct a list of the @@ -542,7 +548,6 @@ void application_impl::handle_transaction(const graphene::net::trx_message& tran last_call = now; trx_count = 0; } - _chain_db->push_transaction( transaction_message.trx ); } FC_CAPTURE_AND_RETHROW( (transaction_message) ) } @@ -976,6 +981,7 @@ void application::initialize(const fc::path& data_dir, const boost::program_opti else { wanted.push_back("witness"); + wanted.push_back("activenode"); wanted.push_back("account_history"); wanted.push_back("market_history"); wanted.push_back("grouped_orders"); diff --git a/libraries/app/database_api.cpp b/libraries/app/database_api.cpp index 8b979690..f129cf8a 100644 --- a/libraries/app/database_api.cpp +++ b/libraries/app/database_api.cpp @@ -122,6 +122,12 @@ class database_api_impl : public std::enable_shared_from_this map lookup_witness_accounts(const string& lower_bound_name, uint32_t limit)const; uint64_t get_witness_count()const; + // Activenodes + fc::optional get_activenode_by_account(account_id_type account)const; + vector> get_activenodes(const vector& activenode_ids)const; + map lookup_activenode_accounts(const string& lower_bound_name, uint32_t limit)const; + uint64_t get_activenode_count()const; + // Committee members vector> get_committee_members(const vector& committee_member_ids)const; fc::optional get_committee_member_by_account(account_id_type account)const; @@ -1610,6 +1616,80 @@ uint64_t database_api_impl::get_witness_count()const return _db.get_index_type().indices().size(); } +////////////////////////////////////////////////////////////////////// +// // +// Activenodes // +// // +////////////////////////////////////////////////////////////////////// + +vector> database_api::get_activenodes(const vector& activenode_ids)const +{ + return my->get_activenodes( activenode_ids ); +} + +vector> database_api_impl::get_activenodes(const vector& activenode_ids)const +{ + vector> result; result.reserve(activenode_ids.size()); + std::transform(activenode_ids.begin(), activenode_ids.end(), std::back_inserter(result), + [this](activenode_id_type id) -> optional { + if(auto o = _db.find(id)) + return *o; + return {}; + }); + return result; +} + +map database_api::lookup_activenode_accounts(const string& lower_bound_name, uint32_t limit)const +{ + return my->lookup_activenode_accounts( lower_bound_name, limit ); +} + +map database_api_impl::lookup_activenode_accounts(const string& lower_bound_name, uint32_t limit)const +{ + FC_ASSERT( limit <= 1000 ); + const auto& activenodes_by_id = _db.get_index_type().indices().get(); + + // we want to order activenodes by account name, but that name is in the account object + // so the activenode_index doesn't have a quick way to access it. + // get all the names and look them all up, sort them, then figure out what + // records to return. This could be optimized, but we expect the + // number of activenodes to be few and the frequency of calls to be rare + std::map activenodes_by_account_name; + for (const activenode_object& activenode : activenodes_by_id) + if (auto account_iter = _db.find(activenode.activenode_account)) + if (account_iter->name >= lower_bound_name) // we can ignore anything below lower_bound_name + activenodes_by_account_name.insert(std::make_pair(account_iter->name, activenode.id)); + + auto end_iter = activenodes_by_account_name.begin(); + while (end_iter != activenodes_by_account_name.end() && limit--) + ++end_iter; + activenodes_by_account_name.erase(end_iter, activenodes_by_account_name.end()); + return activenodes_by_account_name; +} + +uint64_t database_api::get_activenode_count()const +{ + return my->get_activenode_count(); +} + +uint64_t database_api_impl::get_activenode_count()const +{ + return _db.get_index_type().indices().size(); +} + +fc::optional database_api::get_activenode_by_account(account_id_type account)const +{ + return my->get_activenode_by_account( account ); +} + +fc::optional database_api_impl::get_activenode_by_account(account_id_type account) const +{ + const auto& idx = _db.get_index_type().indices().get(); + auto itr = idx.find(account); + if( itr != idx.end() ) + return *itr; + return {}; +} ////////////////////////////////////////////////////////////////////// // // // Committee members // diff --git a/libraries/app/impacted.cpp b/libraries/app/impacted.cpp index 5f2d4fdb..3e3a97ec 100644 --- a/libraries/app/impacted.cpp +++ b/libraries/app/impacted.cpp @@ -211,6 +211,15 @@ struct get_impacted_account_visitor _impacted.insert( op.account_id ); } + void operator()( const activenode_create_operation& op ) + { + _impacted.insert( op.activenode_account ); + } + + void operator()( const activenode_send_activity_operation& op ) + { + _impacted.insert( op.activenode_account ); + } }; void operation_get_impacted_accounts( const operation& op, flat_set& result ) diff --git a/libraries/app/include/graphene/app/database_api.hpp b/libraries/app/include/graphene/app/database_api.hpp index d7bbb9ee..b92847a9 100644 --- a/libraries/app/include/graphene/app/database_api.hpp +++ b/libraries/app/include/graphene/app/database_api.hpp @@ -40,6 +40,7 @@ #include #include #include +#include #include @@ -516,6 +517,27 @@ class database_api */ uint64_t get_witness_count()const; + + ///////////////// + // Activenodes // + ///////////////// + + vector> get_activenodes(const vector& witness_ids)const; + + + map lookup_activenode_accounts(const string& lower_bound_name, uint32_t limit)const; + + + /** + * @brief Get the activenode owned by a given account + * @param account The ID of the account whose activenode should be retrieved + * @return The activenode object, or null if the account does not have a activenode + */ + fc::optional get_activenode_by_account(account_id_type account)const; + + + uint64_t get_activenode_count()const; + /////////////////////// // Committee members // /////////////////////// @@ -754,6 +776,13 @@ FC_API(graphene::app::database_api, (lookup_witness_accounts) (get_witness_count) + // Activenodes + (get_activenodes) + (get_activenode_by_account) + (lookup_activenode_accounts) + (get_activenode_count) + + // Committee members (get_committee_members) (get_committee_member_by_account) diff --git a/libraries/chain/CMakeLists.txt b/libraries/chain/CMakeLists.txt index 8443841e..992ae7f7 100644 --- a/libraries/chain/CMakeLists.txt +++ b/libraries/chain/CMakeLists.txt @@ -20,6 +20,7 @@ if( GRAPHENE_DISABLE_UNITY_BUILD ) db_market.cpp db_update.cpp db_witness_schedule.cpp + db_activenode_schedule.cpp db_notify.cpp ) message( STATUS "Graphene database unity build disabled" ) @@ -45,6 +46,7 @@ add_library( graphene_chain protocol/transfer.cpp protocol/committee_member.cpp protocol/witness.cpp + protocol/activenode.cpp protocol/market.cpp protocol/proposal.cpp protocol/withdraw_permission.cpp @@ -69,6 +71,7 @@ add_library( graphene_chain account_evaluator.cpp assert_evaluator.cpp witness_evaluator.cpp + activenode_evaluator.cpp committee_member_evaluator.cpp asset_evaluator.cpp transfer_evaluator.cpp diff --git a/libraries/chain/account_evaluator.cpp b/libraries/chain/account_evaluator.cpp index 84334339..2bab2ef1 100644 --- a/libraries/chain/account_evaluator.cpp +++ b/libraries/chain/account_evaluator.cpp @@ -35,6 +35,8 @@ #include #include #include +#include + #include #include diff --git a/libraries/chain/account_object.cpp b/libraries/chain/account_object.cpp index 90d97692..b1ec4746 100644 --- a/libraries/chain/account_object.cpp +++ b/libraries/chain/account_object.cpp @@ -102,8 +102,11 @@ void account_statistics_object::process_fees(const account_object& a, database& } } -void account_statistics_object::pay_fee( share_type core_fee, share_type cashback_vesting_threshold ) +void account_statistics_object::pay_fee( share_type core_fee, share_type cashback_vesting_threshold, database& d) { + if (owner(d).is_system_account) { + return; + } if( core_fee > cashback_vesting_threshold ) pending_fees += core_fee; else diff --git a/libraries/chain/activenode_evaluator.cpp b/libraries/chain/activenode_evaluator.cpp new file mode 100644 index 00000000..4e49ff78 --- /dev/null +++ b/libraries/chain/activenode_evaluator.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2015 Cryptonomex, Inc., and contributors. + * + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace graphene { namespace chain { + +void_result activenode_create_evaluator::do_evaluate( const activenode_create_operation& op ) +{ try { + + database& d = db(); + auto& account_obj = d.get(op.activenode_account); + FC_ASSERT(d.get(op.activenode_account).is_lifetime_member()); + + share_type total_balance = d.get_total_account_balance(account_obj); + FC_ASSERT(total_balance >= LLC_ACTIVENODE_MINIMAL_BALANCE_CREATE, "Insufficient Balance: ${a}'s balance of ${b} is less than minimal activenode balance required ${r}", + ("a",account_obj.name) + ("b",d.to_pretty_string(asset(total_balance))) + ("r",d.to_pretty_string(asset(LLC_ACTIVENODE_MINIMAL_BALANCE_CREATE)))); + + return void_result(); +} FC_CAPTURE_AND_RETHROW( (op) ) } + +object_id_type activenode_create_evaluator::do_apply( const activenode_create_operation& op ) +{ try { + const auto& new_activenode_object = db().create( [&]( activenode_object& obj ){ + obj.activenode_account = op.activenode_account; + }); + return new_activenode_object.id; +} FC_CAPTURE_AND_RETHROW( (op) ) } + + +void_result activenode_activity_evaluator::do_evaluate( const activenode_send_activity_operation& op ) +{ try { + FC_ASSERT(db().get(op.activenode_account).is_lifetime_member()); + // here we validate that action is possible + const auto& anode_idx = db().get_index_type().indices().get(); + FC_ASSERT(anode_idx.find(op.activenode_account) != anode_idx.end(), "Account ${acc} is not a registered activenode", ("acc", op.activenode_account)); + FC_ASSERT(db().get(op.activenode).activenode_account == op.activenode_account); + + return void_result(); +} FC_CAPTURE_AND_RETHROW( (op) ) } + +void_result activenode_activity_evaluator::do_apply( const activenode_send_activity_operation& op ) +{ try { + database& _db = db(); + _db.modify( + _db.get(op.activenode), + [&]( activenode_object& activenode_object ) + { + activenode_object.last_activity = db().head_block_time(); + activenode_object.endpoint = op.endpoint; + }); + return void_result(); +} FC_CAPTURE_AND_RETHROW( (op) ) } +} } // graphene::chain diff --git a/libraries/chain/database.cpp b/libraries/chain/database.cpp index 2d02b184..e163515c 100644 --- a/libraries/chain/database.cpp +++ b/libraries/chain/database.cpp @@ -32,4 +32,5 @@ #include "db_market.cpp" #include "db_update.cpp" #include "db_witness_schedule.cpp" +#include "db_activenode_schedule.cpp" #include "db_notify.cpp" \ No newline at end of file diff --git a/libraries/chain/db_activenode_schedule.cpp b/libraries/chain/db_activenode_schedule.cpp new file mode 100644 index 00000000..0ccb5b4e --- /dev/null +++ b/libraries/chain/db_activenode_schedule.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2015 Cryptonomex, Inc., and contributors. + * + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include +#include + +namespace graphene { namespace chain { + +using boost::container::flat_set; + + +fc::optional database::get_scheduled_activenode(uint32_t block_num)const +{ + fc::optional scheduled_node(); + const global_property_object& gpo = get_global_properties(); + const dynamic_global_property_object& dpo = get_dynamic_global_properties(); + const activenode_schedule_object& aso = activenode_schedule_id_type()(*this); + if (head_block_num() == 0) { //GENESIS + return fc::optional(); + } + if (aso.current_shuffled_activenodes.size() == 0) + return fc::optional(); + + FC_ASSERT(block_num == head_block_num() || block_num == head_block_num() - 1); + return aso.current_shuffled_activenodes[block_num - dpo.current_scheduling_block_num]; +} + +void database::update_activenode_schedule() +{ + const activenode_schedule_object& aso = activenode_schedule_id_type()(*this); + const global_property_object& gpo = get_global_properties(); + const dynamic_global_property_object& dpo = get_dynamic_global_properties(); + + if ( dpo.dynamic_flags & dynamic_global_property_object::maintenance_flag || + (gpo.current_activenodes.size() != 0 && head_block_num() % gpo.current_activenodes.size() == 0) ) + { + modify( aso, [&]( activenode_schedule_object& _aso ) + { + _aso.current_shuffled_activenodes.clear(); + _aso.current_shuffled_activenodes.reserve( gpo.current_activenodes.size() ); + + for( const activenode_id_type& w : gpo.current_activenodes ) + _aso.current_shuffled_activenodes.push_back( w ); + + auto now_hi = uint64_t(head_block_time().sec_since_epoch()) << 32; + for( uint32_t i = 0; i < _aso.current_shuffled_activenodes.size(); ++i ) + { + /// High performance random generator + /// http://xorshift.di.unimi.it/ + uint64_t k = now_hi + uint64_t(i)*2685821657736338717ULL; + k ^= (k >> 12); + k ^= (k << 25); + k ^= (k >> 27); + k *= 2685821657736338717ULL; + + uint32_t jmax = _aso.current_shuffled_activenodes.size() - i; + uint32_t j = i + k%jmax; + std::swap( _aso.current_shuffled_activenodes[i], + _aso.current_shuffled_activenodes[j] ); + } + }); + modify( dpo, [&]( dynamic_global_property_object& _dpo ) + { + _dpo.current_scheduling_block_num = head_block_num(); + } ); + } +} + +} } + + diff --git a/libraries/chain/db_balance.cpp b/libraries/chain/db_balance.cpp index a70f077b..34493cd6 100644 --- a/libraries/chain/db_balance.cpp +++ b/libraries/chain/db_balance.cpp @@ -28,6 +28,8 @@ #include #include #include +#include + namespace graphene { namespace chain { @@ -186,4 +188,27 @@ void database::deposit_witness_pay(const witness_object& wit, share_type amount) return; } +void database::deposit_activenode_pay(const activenode_object& ano, share_type amount) +{ + if( amount == 0 ) + return; + + optional< vesting_balance_id_type > new_vbid = deposit_lazy_vesting( + ano.pay_vb, + amount, + get_global_properties().parameters.activenode_pay_vesting_seconds, + ano.activenode_account, + true ); + + if( new_vbid.valid() ) + { + modify( ano, [&]( activenode_object& _ano ) + { + _ano.pay_vb = *new_vbid; + } ); + } + + return; +} + } } diff --git a/libraries/chain/db_block.cpp b/libraries/chain/db_block.cpp index b571f887..0a1fadce 100644 --- a/libraries/chain/db_block.cpp +++ b/libraries/chain/db_block.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -230,6 +231,7 @@ processed_transaction database::_push_transaction( const signed_transaction& trx { // If this is the first transaction pushed after applying a block, start a new undo session. // This allows us to quickly rewind to the clean state of the head block, in case a new block arrives. + if( !_pending_tx_session.valid() ) _pending_tx_session = _undo_db.start_undo_session(); @@ -513,6 +515,9 @@ void database::_apply_block( const signed_block& next_block ) } update_global_dynamic_data(next_block); + + reward_activenode(next_block); + update_signing_witness(signing_witness, next_block); update_last_irreversible_block(); @@ -534,6 +539,9 @@ void database::_apply_block( const signed_block& next_block ) // to be called for header validation? update_maintenance_flag( maint_needed ); update_witness_schedule(); + update_activenode_schedule(); + clean_poor_activenodes(); + if( !_node_property_object.debug_updates.empty() ) apply_debug_updates(); diff --git a/libraries/chain/db_debug.cpp b/libraries/chain/db_debug.cpp index 61376c22..29cd4523 100644 --- a/libraries/chain/db_debug.cpp +++ b/libraries/chain/db_debug.cpp @@ -29,6 +29,7 @@ #include #include #include +#include namespace graphene { namespace chain { diff --git a/libraries/chain/db_init.cpp b/libraries/chain/db_init.cpp index 85203e31..430f3cd0 100644 --- a/libraries/chain/db_init.cpp +++ b/libraries/chain/db_init.cpp @@ -44,6 +44,8 @@ #include #include #include +#include + #include #include @@ -61,8 +63,10 @@ #include #include #include +#include #include +#include #include #include @@ -172,6 +176,9 @@ void database::initialize_evaluators() register_evaluator(); register_evaluator(); register_evaluator(); + register_evaluator(); + register_evaluator(); + } void database::initialize_indexes() @@ -189,6 +196,8 @@ void database::initialize_indexes() add_index< primary_index >(); add_index< primary_index >(); + add_index< primary_index >(); + add_index< primary_index >(); add_index< primary_index >(); @@ -218,6 +227,7 @@ void database::initialize_indexes() add_index< primary_index >(); add_index< primary_index< simple_index< fba_accumulator_object > > >(); + add_index< primary_index > >(); } void database::init_genesis(const genesis_state_type& genesis_state) @@ -425,6 +435,12 @@ void database::init_genesis(const genesis_state_type& genesis_state) } account_id_type account_id(apply_operation(genesis_eval_state, cop).get()); + if( account.is_system_account ) + { + modify( account_id(*this), [&]( account_object& a ) { + a.is_system_account = true; + }); + } if( account.is_lifetime_member ) { account_upgrade_operation op; @@ -615,6 +631,7 @@ void database::init_genesis(const genesis_state_type& genesis_state) std::for_each(genesis_state.initial_witness_candidates.begin(), genesis_state.initial_witness_candidates.end(), [&](const genesis_state_type::initial_witness_type& witness) { witness_create_operation op; + op.initial = true; op.witness_account = get_account_id(witness.owner_name); op.block_signing_key = witness.block_signing_key; apply_operation(genesis_eval_state, op); @@ -663,6 +680,14 @@ void database::init_genesis(const genesis_state_type& genesis_state) wso.current_shuffled_witnesses.push_back( wid ); }); + // Create activenode scheduler + create([&]( activenode_schedule_object& aso ) + { + // TODO: should I + // for( const activenode_id_type& aid : get_global_properties().active_nodes ) + // aso.current_shuffled_activenodes.push_back( aid ); + }); + // Create FBA counters create([&]( fba_accumulator_object& acc ) { diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index 0c461447..ed7f34c7 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #include namespace graphene { namespace chain { @@ -74,9 +75,6 @@ vector> database::sort bool database::witness_can_be_active(const witness_object& witness) const { - const account_balance_index& balance_index = get_index_type(); - auto range = balance_index.indices().get().equal_range(boost::make_tuple(witness.witness_account)); - auto& account = witness.witness_account(*this); const auto& stats = account.statistics(*this); share_type total_balance = stats.total_core_in_orders.value @@ -196,7 +194,6 @@ void database::pay_workers( share_type& budget ) } share_type actual_pay = std::min(budget, requested_pay); - //ilog(" ==> Paying ${a} to worker ${w}", ("w", active_worker.id)("a", actual_pay)); modify(active_worker, [&](worker_object& w) { w.worker.visit(worker_pay_visitor(actual_pay, *this)); }); @@ -205,6 +202,115 @@ void database::pay_workers( share_type& budget ) } } +void database::burn_account_coins(account_id_type account, asset amount) { + + const asset_dynamic_data_object& core = + asset_id_type(0)(*this).dynamic_asset_data_id(*this); + + modify(core, [&]( asset_dynamic_data_object& _core ) + { + _core.current_supply = _core.current_supply - amount.amount; + }); + + adjust_balance( account, -amount ); +} + +void database::update_current_activenodes() +{ try { + const global_property_object& gpo = get_global_properties(); + const dynamic_global_property_object& dpo = get_dynamic_global_properties(); + + const auto& anodes = get_index_type().indices(); + + uint32_t blocks_since_maintenance = head_block_num() - dpo.previous_maintenance_block_num; + uint32_t min_blocks_per_node = 0; + if (gpo.current_activenodes.size()) + min_blocks_per_node = blocks_since_maintenance / gpo.current_activenodes.size() / 2; + + if (gpo.current_activenodes.size() > blocks_since_maintenance /2) { + wlog("Not every node will get reward - there is more than blocks_since_maintenance/2 activenodes (${nodes}/${blocks}", ("nodes", gpo.current_activenodes.size())("blocks", blocks_since_maintenance /2)); + } + + std::vector new_activenodes; + + for( const activenode_object& anode : anodes ) { + // node is still having penalty + if (anode.penalty_left > 0) { + + modify(anode, [&]( activenode_object& anode_obj ){ + anode_obj.penalty_left--; + }); + + if (anode.penalty_left != 0) { + continue; + } + share_type account_balance = get_balance(anode.activenode_account, asset_id_type()).amount.value; + chain::activenode_create_operation create_op; + + asset create_anode_fee = current_fee_schedule().calculate_fee( create_op ); + if (account_balance < LLC_ACTIVENODE_MINIMAL_BALANCE_AFTER_SEND + create_anode_fee.amount) { + // если balance < min_balance + create_anode.fee, то не возвращаем к жизни, т.к. сразу удалим + continue; + } + burn_account_coins(anode.activenode_account, create_anode_fee); + new_activenodes.push_back(anode.id); + } + else { + uint32_t activities_num = anode.activities_sent; + if (anode.activities_sent >= min_blocks_per_node) { + new_activenodes.push_back(anode.id); + modify(anode, [&]( activenode_object& anode_obj ){ + anode_obj.activities_sent = 0; + //for cases when min_blocks_per_node = 0 (can happen because of integer division) + if (anode.is_new) { + anode_obj.is_new = false; + } + }); + continue; + } + + // if node didn't exist and it is here - we should add it + if (anode.is_new) { + new_activenodes.push_back(anode.id); + modify(anode, [&]( activenode_object& anode_obj ){ + anode_obj.is_new = false; + anode_obj.activities_sent = 0; + }); + continue; + } + + modify(anode, [&]( activenode_object& anode_obj ){ + anode_obj.activities_sent = 0; + }); + + if (anode.max_penalty == LLC_ACTIVENODE_MAX_MISS_PENALTY) { + remove(anode); + continue; + } + modify(anode, [&]( activenode_object& anode_obj ){ + if (!anode_obj.max_penalty) { + anode_obj.max_penalty = 1; + } + else + anode_obj.max_penalty *= 2; + anode_obj.penalty_left = anode_obj.max_penalty; + }); + } + } + + modify(gpo, [&]( global_property_object& gp ){ + + gp.current_activenodes.clear(); + gp.current_activenodes.reserve(new_activenodes.size()); + + std::transform(new_activenodes.begin(), new_activenodes.end(), + std::inserter(gp.current_activenodes, gp.current_activenodes.end()), + [](const activenode_id_type& anode_id) { + return anode_id; + }); + }); +} FC_CAPTURE_AND_RETHROW() } + void database::update_active_witnesses() { try { assert( _witness_count_histogram_buffer.size() > 0 ); @@ -820,7 +926,9 @@ void database::process_bids( const asset_bitasset_data_object& bad ) void database::perform_chain_maintenance(const signed_block& next_block, const global_property_object& global_props) { + dlog("chain_maintenance"); const auto& gpo = get_global_properties(); + const auto& dpo = get_dynamic_global_properties(); distribute_fba_balances(*this); create_buyback_orders(*this); @@ -918,6 +1026,13 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g update_top_n_authorities(*this); update_active_witnesses(); + //here we need to calc how many blocks each activenode has missed and throw them away if < 50% + // but if there more than blocks_in_interval/2 activenodes, then not every node will be granted with at least 2 blocks + update_current_activenodes(); + modify( dpo, [&]( dynamic_global_property_object& _dpo ) + { + _dpo.previous_maintenance_block_num = head_block_num(); + } ); update_active_committee_members(); update_worker_votes(); diff --git a/libraries/chain/db_market.cpp b/libraries/chain/db_market.cpp index ef811c03..8d2b1acd 100644 --- a/libraries/chain/db_market.cpp +++ b/libraries/chain/db_market.cpp @@ -402,7 +402,7 @@ bool database::fill_order( const limit_order_object& order, const asset& pays, c { modify( seller.statistics(*this), [&]( account_statistics_object& statistics ) { - statistics.pay_fee( order.deferred_fee, get_global_properties().parameters.cashback_vesting_threshold ); + statistics.pay_fee( order.deferred_fee, get_global_properties().parameters.cashback_vesting_threshold, *this); } ); } diff --git a/libraries/chain/db_notify.cpp b/libraries/chain/db_notify.cpp index 32f30481..c022ae33 100644 --- a/libraries/chain/db_notify.cpp +++ b/libraries/chain/db_notify.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -199,6 +200,16 @@ struct get_impacted_account_visitor _impacted.insert( op.account_id ); } + void operator()( const activenode_create_operation& op ) + { + _impacted.insert( op.activenode_account ); + } + + void operator()( const activenode_send_activity_operation& op ) + { + _impacted.insert( op.activenode_account ); + } + }; static void operation_get_impacted_accounts( const operation& op, flat_set& result ) @@ -287,6 +298,11 @@ static void get_relevant_accounts( const object* obj, flat_set& } case balance_object_type:{ /** these are free from any accounts */ break; + } case activenode_object_type: { + const auto& aobj = dynamic_cast(obj); + FC_ASSERT( aobj != nullptr ); + accounts.insert( aobj->activenode_account ); + break; } } } @@ -350,6 +366,8 @@ static void get_relevant_accounts( const object* obj, flat_set& accounts.insert( aobj->bidder ); break; } + case impl_activenode_schedule_object_type: + break; } } } // end get_relevant_accounts( const object* obj, flat_set& accounts ) @@ -361,6 +379,11 @@ void database::notify_applied_block( const signed_block& block ) GRAPHENE_TRY_NOTIFY( applied_block, block ) } +void database::notify_new_block_applied( const signed_block& block ) +{ + GRAPHENE_TRY_NOTIFY( new_block_applied, block ) +} + void database::notify_on_pending_transaction( const signed_transaction& tx ) { GRAPHENE_TRY_NOTIFY( on_pending_transaction, tx ) diff --git a/libraries/chain/db_update.cpp b/libraries/chain/db_update.cpp index 5ffe89c1..d2d3db6f 100644 --- a/libraries/chain/db_update.cpp +++ b/libraries/chain/db_update.cpp @@ -33,10 +33,12 @@ #include #include #include +#include #include #include +#include namespace graphene { namespace chain { @@ -44,7 +46,8 @@ void database::update_global_dynamic_data( const signed_block& b ) { const dynamic_global_property_object& _dgp = dynamic_global_property_id_type(0)(*this); - + + // activenodes missed can be implemented in the same way uint32_t missed_blocks = get_slot_at_time( b.timestamp ); assert( missed_blocks != 0 ); missed_blocks--; @@ -105,14 +108,24 @@ void database::update_signing_witness(const witness_object& signing_witness, con const dynamic_global_property_object& dpo = get_dynamic_global_properties(); uint64_t new_block_aslot = dpo.current_aslot + get_slot_at_time( new_block.timestamp ); - share_type witness_pay = std::min( gpo.parameters.witness_pay_per_block, dpo.witness_budget ); + auto& account = signing_witness.witness_account(*this); + const auto& stats = account.statistics(*this); + share_type total_balance = stats.total_core_in_orders.value + + (account.cashback_vb.valid() ? (*account.cashback_vb)(*this).balance.amount.value: 0) + + get_balance(account.get_id(), asset_id_type()).amount.value; + + bool enough_balance = (total_balance >= LLC_WITNESS_MINIMAL_BALANCE); - modify( dpo, [&]( dynamic_global_property_object& _dpo ) - { - _dpo.witness_budget -= witness_pay; - } ); + if (enough_balance) { + share_type witness_pay = std::min( gpo.parameters.witness_pay_per_block, dpo.witness_budget ); + + modify( dpo, [&]( dynamic_global_property_object& _dpo ) + { + _dpo.witness_budget -= witness_pay; + } ); - deposit_witness_pay( signing_witness, witness_pay ); + deposit_witness_pay( signing_witness, witness_pay ); + } modify( signing_witness, [&]( witness_object& _wit ) { @@ -121,6 +134,66 @@ void database::update_signing_witness(const witness_object& signing_witness, con } ); } +share_type database::get_total_account_balance(const account_object& account) { + const auto& stats = account.statistics(*this); + share_type total_balance = stats.total_core_in_orders.value + + (account.cashback_vb.valid() ? (*account.cashback_vb)(*this).balance.amount.value: 0) + + get_balance(account.get_id(), asset_id_type()).amount.value; + return total_balance; +} + +//we can also disable instead +void database::clean_poor_activenodes() { + const auto& idx = get_index_type().indices(); + std::vector list_for_removal; + + for( const activenode_object& act_object : idx ) { + //removing activenodes that doesn't have money + share_type total_balance = get_total_account_balance(act_object.activenode_account(*this)); + if (total_balance < LLC_ACTIVENODE_MINIMAL_BALANCE_AFTER_SEND) { + remove(act_object); + } + } +} + + +void database::reward_activenode(const signed_block& new_block) { + const global_property_object& gpo = get_global_properties(); + const auto& anodes = get_index_type().indices(); + + // check scheduled + if (anodes.size() == 0) return; + if (head_block_num() == 0 || head_block_num() == 1) return; //GENESIS + + const activenode_schedule_object& aso = activenode_schedule_id_type()(*this); + if (aso.current_shuffled_activenodes.size() == 0) { + return; + } + fc::optional scheduled_activenode = get_scheduled_activenode(head_block_num() - 1); + if (!scheduled_activenode) + return; + + if (find(*scheduled_activenode) == nullptr ) { + // was deleted + return; + } + auto& activenode = (*scheduled_activenode)(*this); + signed_block prev_block = *fetch_block_by_number(new_block.block_num() - 1); + fc::time_point_sec prev_block_time = prev_block.timestamp; + if (activenode.last_activity == prev_block_time) { + modify( activenode, [&]( activenode_object& _ano ) + { + _ano.activities_sent++; + } ); + + chain::activenode_send_activity_operation send_activity_operation; + + share_type fee = current_fee_schedule().calculate_fee( send_activity_operation ).amount; + share_type to_deposit = fee.value * 0.2 + gpo.parameters.activenode_pay_per_block; + deposit_activenode_pay( activenode, to_deposit ); + } +} + void database::update_last_irreversible_block() { const global_property_object& gpo = get_global_properties(); diff --git a/libraries/chain/db_witness_schedule.cpp b/libraries/chain/db_witness_schedule.cpp index 66db87ee..b95392b2 100644 --- a/libraries/chain/db_witness_schedule.cpp +++ b/libraries/chain/db_witness_schedule.cpp @@ -39,6 +39,7 @@ witness_id_type database::get_scheduled_witness( uint32_t slot_num )const return wso.current_shuffled_witnesses[ current_aslot % wso.current_shuffled_witnesses.size() ]; } +// returns the time of the next witness producal fc::time_point_sec database::get_slot_time(uint32_t slot_num)const { if( slot_num == 0 ) @@ -59,6 +60,7 @@ fc::time_point_sec database::get_slot_time(uint32_t slot_num)const const global_property_object& gpo = get_global_properties(); + // if maitenance - add several blocks (that are missed) if( dpo.dynamic_flags & dynamic_global_property_object::maintenance_flag ) slot_num += gpo.parameters.maintenance_skip_slots; @@ -66,12 +68,14 @@ fc::time_point_sec database::get_slot_time(uint32_t slot_num)const // "slot 1" is head_slot_time, // plus maint interval if head block is a maint block // plus block interval if head block is not a maint block + return head_slot_time + (slot_num * interval); } uint32_t database::get_slot_at_time(fc::time_point_sec when)const { fc::time_point_sec first_slot_time = get_slot_time( 1 ); + if( when < first_slot_time ) return 0; return (when - first_slot_time).to_seconds() / block_interval() + 1; diff --git a/libraries/chain/evaluator.cpp b/libraries/chain/evaluator.cpp index a4127c25..efa42ab0 100644 --- a/libraries/chain/evaluator.cpp +++ b/libraries/chain/evaluator.cpp @@ -99,7 +99,7 @@ database& generic_evaluator::db()const { return trx_state->db(); } /// TODO: db().pay_fee( account_id, core_fee ); d.modify(*fee_paying_account_statistics, [&](account_statistics_object& s) { - s.pay_fee( core_fee_paid, d.get_global_properties().parameters.cashback_vesting_threshold ); + s.pay_fee( core_fee_paid, d.get_global_properties().parameters.cashback_vesting_threshold, db()); }); } } FC_CAPTURE_AND_RETHROW() } diff --git a/libraries/chain/hardfork.d/700.hf b/libraries/chain/hardfork.d/700.hf new file mode 100644 index 00000000..c12cc6ce --- /dev/null +++ b/libraries/chain/hardfork.d/700.hf @@ -0,0 +1,4 @@ +// #700 Masternode update +#ifndef HARDFORK_700_TIME +#define HARDFORK_700_TIME (fc::time_point_sec( 1543253000 )) +#endif diff --git a/libraries/chain/include/graphene/chain/account_object.hpp b/libraries/chain/include/graphene/chain/account_object.hpp index 522cb7bc..e3ac5f97 100644 --- a/libraries/chain/include/graphene/chain/account_object.hpp +++ b/libraries/chain/include/graphene/chain/account_object.hpp @@ -88,7 +88,7 @@ namespace graphene { namespace chain { /** * Core fees are paid into the account_statistics_object by this method */ - void pay_fee( share_type core_fee, share_type cashback_vesting_threshold ); + void pay_fee( share_type core_fee, share_type cashback_vesting_threshold, database& d ); }; /** @@ -144,6 +144,8 @@ namespace graphene { namespace chain { /// The lifetime member at the top of the referral tree. Receives a percentage of referral rewards. account_id_type lifetime_referrer; + bool is_system_account = false; + /// Percentage of fee which should go to network. uint16_t network_fee_percentage = GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE; /// Percentage of fee which should go to lifetime referrer. @@ -379,6 +381,7 @@ FC_REFLECT_DERIVED( graphene::chain::account_object, (owner_special_authority)(active_special_authority) (top_n_control_flags) (allowed_assets) + (is_system_account) ) FC_REFLECT_DERIVED( graphene::chain::account_balance_object, diff --git a/libraries/chain/include/graphene/chain/activenode_evaluator.hpp b/libraries/chain/include/graphene/chain/activenode_evaluator.hpp new file mode 100644 index 00000000..4ee2c3f8 --- /dev/null +++ b/libraries/chain/include/graphene/chain/activenode_evaluator.hpp @@ -0,0 +1,24 @@ +#pragma once +#include +#include +#include +namespace graphene { namespace chain { + + class activenode_create_evaluator : public evaluator + { + public: + typedef activenode_create_operation operation_type; + + void_result do_evaluate( const activenode_create_operation& o ); + object_id_type do_apply( const activenode_create_operation& o ); + }; + + class activenode_activity_evaluator : public evaluator + { + public: + typedef activenode_send_activity_operation operation_type; + + void_result do_evaluate( const activenode_send_activity_operation& o ); + void_result do_apply( const activenode_send_activity_operation& o ); + }; +} } // graphene::chain diff --git a/libraries/chain/include/graphene/chain/activenode_object.hpp b/libraries/chain/include/graphene/chain/activenode_object.hpp new file mode 100644 index 00000000..ea4120da --- /dev/null +++ b/libraries/chain/include/graphene/chain/activenode_object.hpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2015 Cryptonomex, Inc., and contributors. + * + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#pragma once +#include +#include +#include +#include + + +namespace graphene { namespace chain { + using namespace graphene::db; + class activenode_object; + + class activenode_object : public abstract_object + { + public: + static const uint8_t space_id = protocol_ids; + static const uint8_t type_id = activenode_object_type; + + account_id_type activenode_account; + fc::time_point_sec last_activity; + + uint32_t activities_sent = 0; // amount of activities sent in this interval + uint8_t penalty_left = 0; // how many maintenance intervals do we need to wait before we'll become active + uint8_t max_penalty = 0; // max penalty that we've got + + bool is_new = true; // have the activenode already participated in scheduling + + fc::ip::endpoint endpoint; + optional< vesting_balance_id_type > pay_vb; + activenode_object() {} + }; + + struct by_account; + using activenode_multi_index_type = multi_index_container< + activenode_object, + indexed_by< + ordered_unique< tag, + member + >, + ordered_unique< tag, + member + > + > + >; + using activenode_index = generic_index; +} } // graphene::chain + +FC_REFLECT_DERIVED( graphene::chain::activenode_object, (graphene::db::object), + (activenode_account) + (last_activity) + (endpoint) + (pay_vb) + (activities_sent) + (penalty_left) + (max_penalty) + (is_new) + ) \ No newline at end of file diff --git a/libraries/chain/include/graphene/chain/activenode_schedule_object.hpp b/libraries/chain/include/graphene/chain/activenode_schedule_object.hpp new file mode 100644 index 00000000..33e6d7c5 --- /dev/null +++ b/libraries/chain/include/graphene/chain/activenode_schedule_object.hpp @@ -0,0 +1,25 @@ +#pragma once +#include +#include +#include + +namespace graphene { namespace chain { + +class activenode_schedule_object; + +class activenode_schedule_object : public graphene::db::abstract_object +{ + public: + static const uint8_t space_id = implementation_ids; + static const uint8_t type_id = impl_activenode_schedule_object_type; + + vector< activenode_id_type > current_shuffled_activenodes; +}; + +} } + +FC_REFLECT_DERIVED( + graphene::chain::activenode_schedule_object, + (graphene::db::object), + (current_shuffled_activenodes) +) diff --git a/libraries/chain/include/graphene/chain/config.hpp b/libraries/chain/include/graphene/chain/config.hpp index aeac99a6..52211ed2 100644 --- a/libraries/chain/include/graphene/chain/config.hpp +++ b/libraries/chain/include/graphene/chain/config.hpp @@ -47,7 +47,7 @@ #define GRAPHENE_DEFAULT_MAX_TRANSACTION_SIZE 2048 #define GRAPHENE_DEFAULT_MAX_BLOCK_SIZE (2*1000*1000) /* < 2 MiB (less than MAX_MESSAGE_SIZE in graphene/net/config.hpp) */ #define GRAPHENE_DEFAULT_MAX_TIME_UNTIL_EXPIRATION (60*60*24) // seconds, aka: 1 day -#define GRAPHENE_DEFAULT_MAINTENANCE_INTERVAL (60*60*24) // seconds, aka: 1 day +#define GRAPHENE_DEFAULT_MAINTENANCE_INTERVAL (60*60*24) // seconds, aka: 1 day #define GRAPHENE_DEFAULT_MAINTENANCE_SKIP_SLOTS 3 // number of slots to skip for maintenance interval #define GRAPHENE_MIN_UNDO_HISTORY 10 @@ -135,8 +135,12 @@ #define GRAPHENE_DEFAULT_WITNESS_PAY_PER_BLOCK (GRAPHENE_BLOCKCHAIN_PRECISION * int64_t( 10) ) #define GRAPHENE_DEFAULT_WITNESS_PAY_VESTING_SECONDS (60*60*24) +#define GRAPHENE_DEFAULT_ACTIVENODE_PAY_VESTING_SECONDS (60*60*24) + #define GRAPHENE_DEFAULT_WORKER_BUDGET_PER_DAY (GRAPHENE_BLOCKCHAIN_PRECISION * int64_t(500) * 1000 ) +#define GRAPHENE_DEFAULT_ACTIVENODE_PAY_PER_BLOCK int64_t(GRAPHENE_BLOCKCHAIN_PRECISION * double( 1.1) ) + #define GRAPHENE_DEFAULT_MINIMUM_FEEDS 7 #define GRAPHENE_MAX_INTEREST_APR uint16_t( 10000 ) @@ -168,7 +172,12 @@ #define GRAPHENE_NULL_WITNESS (graphene::chain::witness_id_type(0)) ///@} + #define GRAPHENE_FBA_STEALTH_DESIGNATED_ASSET (asset_id_type(743)) #define GRAPHENE_MAX_NESTED_OBJECTS (200) #define LLC_WITNESS_MINIMAL_BALANCE (100000 * GRAPHENE_BLOCKCHAIN_PRECISION) + +#define LLC_ACTIVENODE_MINIMAL_BALANCE_AFTER_SEND (500 * GRAPHENE_BLOCKCHAIN_PRECISION) +#define LLC_ACTIVENODE_MINIMAL_BALANCE_CREATE (511 * GRAPHENE_BLOCKCHAIN_PRECISION) +#define LLC_ACTIVENODE_MAX_MISS_PENALTY (8) \ No newline at end of file diff --git a/libraries/chain/include/graphene/chain/database.hpp b/libraries/chain/include/graphene/chain/database.hpp index 33c27f63..48045895 100644 --- a/libraries/chain/include/graphene/chain/database.hpp +++ b/libraries/chain/include/graphene/chain/database.hpp @@ -185,6 +185,10 @@ namespace graphene { namespace chain { */ fc::signal applied_block; + /** + */ + fc::signal new_block_applied; + /** * This signal is emitted any time a new transaction is added to the pending * block state. @@ -248,6 +252,11 @@ namespace graphene { namespace chain { void update_witness_schedule(); + //////////////////// db_activenode_schedule.cpp //////////////////// + fc::optional get_scheduled_activenode(uint32_t block_num)const; + + void update_activenode_schedule(); + //////////////////// db_getter.cpp //////////////////// const chain_id_type& get_chain_id()const; @@ -326,6 +335,9 @@ namespace graphene { namespace chain { void deposit_cashback(const account_object& acct, share_type amount, bool require_vesting = true); // helper to handle witness pay void deposit_witness_pay(const witness_object& wit, share_type amount); + // helper to handle witness pay + void deposit_activenode_pay(const activenode_object& ano, share_type amount); + //////////////////// db_debug.cpp //////////////////// @@ -406,6 +418,8 @@ namespace graphene { namespace chain { * can be reapplied at the proper time */ std::deque< signed_transaction > _popped_tx; + void notify_new_block_applied( const signed_block& block ); + /** * @} */ @@ -433,6 +447,8 @@ namespace graphene { namespace chain { void apply_block( const signed_block& next_block, uint32_t skip = skip_nothing ); processed_transaction apply_transaction( const signed_transaction& trx, uint32_t skip = skip_nothing ); operation_result apply_operation( transaction_evaluation_state& eval_state, const operation& op ); + share_type get_total_account_balance(const account_object& account); + private: void _apply_block( const signed_block& next_block ); processed_transaction _apply_transaction( const signed_transaction& trx ); @@ -448,6 +464,8 @@ namespace graphene { namespace chain { //////////////////// db_update.cpp //////////////////// void update_global_dynamic_data( const signed_block& b ); void update_signing_witness(const witness_object& signing_witness, const signed_block& new_block); + void clean_poor_activenodes(); + void reward_activenode(const signed_block& new_block); void update_last_irreversible_block(); void clear_expired_transactions(); void clear_expired_proposals(); @@ -467,12 +485,16 @@ namespace graphene { namespace chain { void pay_workers( share_type& budget ); void perform_chain_maintenance(const signed_block& next_block, const global_property_object& global_props); void update_active_witnesses(); + void update_current_activenodes(); void update_active_committee_members(); void update_worker_votes(); void process_bids( const asset_bitasset_data_object& bad ); template void perform_account_maintenance(std::tuple helpers); + + void burn_account_coins(account_id_type account, asset amount); + ///@} ///@} diff --git a/libraries/chain/include/graphene/chain/evaluator.hpp b/libraries/chain/include/graphene/chain/evaluator.hpp index af90517e..46c3cd23 100644 --- a/libraries/chain/include/graphene/chain/evaluator.hpp +++ b/libraries/chain/include/graphene/chain/evaluator.hpp @@ -168,8 +168,8 @@ namespace graphene { namespace chain { pay_fee(); auto result = eval->do_apply(op); - - db_adjust_balance(op.fee_payer(), -fee_from_account); + if (!op.fee_payer()(db()).is_system_account) + db_adjust_balance(op.fee_payer(), -fee_from_account); return result; } diff --git a/libraries/chain/include/graphene/chain/genesis_state.hpp b/libraries/chain/include/graphene/chain/genesis_state.hpp index df87d179..0e52dbd9 100644 --- a/libraries/chain/include/graphene/chain/genesis_state.hpp +++ b/libraries/chain/include/graphene/chain/genesis_state.hpp @@ -51,6 +51,7 @@ struct genesis_state_type { public_key_type owner_key; public_key_type active_key; bool is_lifetime_member = false; + bool is_system_account = false; }; struct initial_asset_type { struct initial_collateral_position { @@ -127,7 +128,7 @@ struct genesis_state_type { } } // namespace graphene::chain -FC_REFLECT(graphene::chain::genesis_state_type::initial_account_type, (name)(owner_key)(active_key)(is_lifetime_member)) +FC_REFLECT(graphene::chain::genesis_state_type::initial_account_type, (name)(owner_key)(active_key)(is_lifetime_member)(is_system_account)) FC_REFLECT(graphene::chain::genesis_state_type::initial_asset_type, (symbol)(issuer_name)(description)(precision)(max_supply)(accumulated_fees)(is_bitasset)(collateral_records)) diff --git a/libraries/chain/include/graphene/chain/global_property_object.hpp b/libraries/chain/include/graphene/chain/global_property_object.hpp index 2c5a1f12..4ad27e85 100644 --- a/libraries/chain/include/graphene/chain/global_property_object.hpp +++ b/libraries/chain/include/graphene/chain/global_property_object.hpp @@ -51,6 +51,8 @@ namespace graphene { namespace chain { uint32_t next_available_vote_id = 0; vector active_committee_members; // updated once per maintenance interval flat_set active_witnesses; // updated once per maintenance interval + flat_set current_activenodes; // updated once per maintenance interval + // n.b. witness scheduling is done by witness_schedule object }; @@ -108,6 +110,9 @@ namespace graphene { namespace chain { uint32_t last_irreversible_block_num = 0; + uint32_t current_scheduling_block_num = 0; + uint32_t previous_maintenance_block_num = 0; + enum dynamic_flag_bits { /** @@ -138,6 +143,8 @@ FC_REFLECT_DERIVED( graphene::chain::dynamic_global_property_object, (graphene:: (recent_slots_filled) (dynamic_flags) (last_irreversible_block_num) + (current_scheduling_block_num) + (previous_maintenance_block_num) ) FC_REFLECT_DERIVED( graphene::chain::global_property_object, (graphene::db::object), @@ -146,4 +153,5 @@ FC_REFLECT_DERIVED( graphene::chain::global_property_object, (graphene::db::obje (next_available_vote_id) (active_committee_members) (active_witnesses) + (current_activenodes) ) diff --git a/libraries/chain/include/graphene/chain/protocol/activenode.hpp b/libraries/chain/include/graphene/chain/protocol/activenode.hpp new file mode 100644 index 00000000..d1d19057 --- /dev/null +++ b/libraries/chain/include/graphene/chain/protocol/activenode.hpp @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2015 Cryptonomex, Inc., and contributors. + * + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#pragma once +#include +#include + +namespace graphene { namespace chain { + + /** + * @brief Create an activenode object, as a bid to hold a witness position on the network. + * @ingroup operations + * + * Accounts which wish to become witnesses may use this operation to create a witness object which stakeholders may + * vote on to approve its position as a witness. + */ + struct activenode_create_operation : public base_operation + { + struct fee_parameters_type { uint64_t fee = 10 * GRAPHENE_BLOCKCHAIN_PRECISION; }; + + asset fee; + /// The account which owns the activenode. This account pays the fee for this operation. + account_id_type activenode_account; + + account_id_type fee_payer()const { return activenode_account; } + void validate()const; + }; + + + /** + * @brief Sending activity operation (I'm active) + * @ingroup operations + * + */ + struct activenode_send_activity_operation : public base_operation + { + struct fee_parameters_type { uint64_t fee = 10 * GRAPHENE_BLOCKCHAIN_PRECISION; }; + + asset fee; + /// The account which owns the activenode. This account pays the fee for this operation. + account_id_type activenode_account; + activenode_id_type activenode; + fc::time_point_sec timepoint; + fc::ip::endpoint endpoint; + + account_id_type fee_payer()const { return activenode_account; } + void validate()const; + }; + +} } // graphene::chain + +FC_REFLECT( graphene::chain::activenode_create_operation::fee_parameters_type, (fee) ) +FC_REFLECT( graphene::chain::activenode_create_operation, (fee)(activenode_account) ) + + +FC_REFLECT( graphene::chain::activenode_send_activity_operation::fee_parameters_type, (fee) ) +FC_REFLECT( graphene::chain::activenode_send_activity_operation, (fee)(activenode_account)(activenode)(timepoint)(endpoint) ) diff --git a/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp b/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp index 695d9541..87bda97a 100644 --- a/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp +++ b/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp @@ -56,7 +56,12 @@ namespace graphene { namespace chain { bool count_non_member_votes = true; ///< set to false to restrict voting privlegages to member accounts bool allow_non_member_whitelists = false; ///< true if non-member accounts may set whitelists and blacklists; false otherwise share_type witness_pay_per_block = GRAPHENE_DEFAULT_WITNESS_PAY_PER_BLOCK; ///< CORE to be allocated to witnesses (per block) + + share_type activenode_pay_per_block = GRAPHENE_DEFAULT_ACTIVENODE_PAY_PER_BLOCK; ///< CORE to be allocated to witnesses (per block) + uint32_t witness_pay_vesting_seconds = GRAPHENE_DEFAULT_WITNESS_PAY_VESTING_SECONDS; ///< vesting_seconds parameter for witness VBO's + uint32_t activenode_pay_vesting_seconds = GRAPHENE_DEFAULT_ACTIVENODE_PAY_VESTING_SECONDS; ///< vesting_seconds parameter for witness VBO's + share_type worker_budget_per_day = GRAPHENE_DEFAULT_WORKER_BUDGET_PER_DAY; ///< CORE to be allocated to workers (per day) uint16_t max_predicate_opcode = GRAPHENE_DEFAULT_MAX_ASSERT_OPCODE; ///< predicate_opcode must be less than this number share_type fee_liquidation_threshold = GRAPHENE_DEFAULT_FEE_LIQUIDATION_THRESHOLD; ///< value in CORE at which accumulated fees in blockchain-issued market assets should be liquidated @@ -94,6 +99,7 @@ FC_REFLECT( graphene::chain::chain_parameters, (count_non_member_votes) (allow_non_member_whitelists) (witness_pay_per_block) + (activenode_pay_per_block) (worker_budget_per_day) (max_predicate_opcode) (fee_liquidation_threshold) diff --git a/libraries/chain/include/graphene/chain/protocol/operations.hpp b/libraries/chain/include/graphene/chain/protocol/operations.hpp index 3377a2f9..662bfb91 100644 --- a/libraries/chain/include/graphene/chain/protocol/operations.hpp +++ b/libraries/chain/include/graphene/chain/protocol/operations.hpp @@ -37,6 +37,7 @@ #include #include #include +#include #include namespace graphene { namespace chain { @@ -93,7 +94,9 @@ namespace graphene { namespace chain { asset_claim_fees_operation, fba_distribute_operation, // VIRTUAL bid_collateral_operation, - execute_bid_operation // VIRTUAL + execute_bid_operation, // VIRTUAL + activenode_create_operation, + activenode_send_activity_operation > operation; /// @} // operations group diff --git a/libraries/chain/include/graphene/chain/protocol/types.hpp b/libraries/chain/include/graphene/chain/protocol/types.hpp index 5e0c4a02..372713cc 100644 --- a/libraries/chain/include/graphene/chain/protocol/types.hpp +++ b/libraries/chain/include/graphene/chain/protocol/types.hpp @@ -141,6 +141,7 @@ namespace graphene { namespace chain { vesting_balance_object_type, worker_object_type, balance_object_type, + activenode_object_type, OBJECT_TYPE_COUNT ///< Sentry value which contains the number of different object types }; @@ -163,7 +164,8 @@ namespace graphene { namespace chain { impl_special_authority_object_type, impl_buyback_object_type, impl_fba_accumulator_object_type, - impl_collateral_bid_object_type + impl_collateral_bid_object_type, + impl_activenode_schedule_object_type }; //typedef fc::unsigned_int object_id_type; @@ -183,6 +185,7 @@ namespace graphene { namespace chain { class worker_object; class balance_object; class blinded_balance_object; + class activenode_object; typedef object_id< protocol_ids, account_object_type, account_object> account_id_type; typedef object_id< protocol_ids, asset_object_type, asset_object> asset_id_type; @@ -198,6 +201,7 @@ namespace graphene { namespace chain { typedef object_id< protocol_ids, vesting_balance_object_type, vesting_balance_object> vesting_balance_id_type; typedef object_id< protocol_ids, worker_object_type, worker_object> worker_id_type; typedef object_id< protocol_ids, balance_object_type, balance_object> balance_id_type; + typedef object_id< protocol_ids, activenode_object_type, activenode_object> activenode_id_type; // implementation types class global_property_object; @@ -216,6 +220,7 @@ namespace graphene { namespace chain { class buyback_object; class fba_accumulator_object; class collateral_bid_object; + class activenode_schedule_object; typedef object_id< implementation_ids, impl_global_property_object_type, global_property_object> global_property_id_type; typedef object_id< implementation_ids, impl_dynamic_global_property_object_type, dynamic_global_property_object> dynamic_global_property_id_type; @@ -237,6 +242,7 @@ namespace graphene { namespace chain { typedef object_id< implementation_ids, impl_buyback_object_type, buyback_object > buyback_id_type; typedef object_id< implementation_ids, impl_fba_accumulator_object_type, fba_accumulator_object > fba_accumulator_id_type; typedef object_id< implementation_ids, impl_collateral_bid_object_type, collateral_bid_object > collateral_bid_id_type; + typedef object_id< implementation_ids, impl_activenode_schedule_object_type, activenode_schedule_object> activenode_schedule_id_type; typedef fc::array symbol_type; typedef fc::ripemd160 block_id_type; @@ -347,6 +353,7 @@ FC_REFLECT_ENUM( graphene::chain::object_type, (vesting_balance_object_type) (worker_object_type) (balance_object_type) + (activenode_object_type) (OBJECT_TYPE_COUNT) ) FC_REFLECT_ENUM( graphene::chain::impl_object_type, @@ -368,6 +375,7 @@ FC_REFLECT_ENUM( graphene::chain::impl_object_type, (impl_buyback_object_type) (impl_fba_accumulator_object_type) (impl_collateral_bid_object_type) + (impl_activenode_schedule_object_type) ) FC_REFLECT_TYPENAME( graphene::chain::share_type ) diff --git a/libraries/chain/include/graphene/chain/protocol/witness.hpp b/libraries/chain/include/graphene/chain/protocol/witness.hpp index 5eb75f9b..8b61a7ff 100644 --- a/libraries/chain/include/graphene/chain/protocol/witness.hpp +++ b/libraries/chain/include/graphene/chain/protocol/witness.hpp @@ -42,6 +42,7 @@ namespace graphene { namespace chain { account_id_type witness_account; string url; public_key_type block_signing_key; + bool initial = false; account_id_type fee_payer()const { return witness_account; } void validate()const; diff --git a/libraries/chain/protocol/activenode.cpp b/libraries/chain/protocol/activenode.cpp new file mode 100644 index 00000000..1d93a753 --- /dev/null +++ b/libraries/chain/protocol/activenode.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2015 Cryptonomex, Inc., and contributors. + * + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include + +namespace graphene { namespace chain { + +void activenode_create_operation::validate() const +{ + FC_ASSERT(fee.amount >= 0); +} +void activenode_send_activity_operation::validate() const +{ + FC_ASSERT(fee.amount >= 0); +} + +} } // graphene::chain diff --git a/libraries/chain/witness_evaluator.cpp b/libraries/chain/witness_evaluator.cpp index 93785bdc..0ed3af82 100644 --- a/libraries/chain/witness_evaluator.cpp +++ b/libraries/chain/witness_evaluator.cpp @@ -27,12 +27,23 @@ #include #include #include +#include + namespace graphene { namespace chain { void_result witness_create_evaluator::do_evaluate( const witness_create_operation& op ) { try { FC_ASSERT(db().get(op.witness_account).is_lifetime_member()); + if (!op.initial) { + auto& account = op.witness_account(db()); + const auto& stats = account.statistics(db()); + share_type total_balance = stats.total_core_in_orders.value + + (account.cashback_vb.valid() ? ((*account.cashback_vb)(db())).balance.amount.value: 0) + + db().get_balance(account.get_id(), asset_id_type()).amount.value; + + FC_ASSERT(total_balance >= LLC_WITNESS_MINIMAL_BALANCE); + } return void_result(); } FC_CAPTURE_AND_RETHROW( (op) ) } diff --git a/libraries/net/stcp_socket.cpp b/libraries/net/stcp_socket.cpp index 7a483f08..a7c6bf20 100644 --- a/libraries/net/stcp_socket.cpp +++ b/libraries/net/stcp_socket.cpp @@ -61,7 +61,6 @@ void stcp_socket::do_key_exchange() memcpy((char*)&rpub, serialized_key_buffer.get(), sizeof(fc::ecc::public_key_data)); _shared_secret = _priv_key.get_shared_secret( rpub ); -// ilog("shared secret ${s}", ("s", shared_secret) ); _send_aes.init( fc::sha256::hash( (char*)&_shared_secret, sizeof(_shared_secret) ), fc::city_hash_crc_128((char*)&_shared_secret,sizeof(_shared_secret) ) ); _recv_aes.init( fc::sha256::hash( (char*)&_shared_secret, sizeof(_shared_secret) ), diff --git a/libraries/plugins/CMakeLists.txt b/libraries/plugins/CMakeLists.txt index caacb8bd..4d460a20 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( activenode ) \ No newline at end of file diff --git a/libraries/plugins/activenode/CMakeLists.txt b/libraries/plugins/activenode/CMakeLists.txt new file mode 100644 index 00000000..8e1de7d0 --- /dev/null +++ b/libraries/plugins/activenode/CMakeLists.txt @@ -0,0 +1,17 @@ +file(GLOB HEADERS "include/graphene/activenode/*.hpp") + +add_library( graphene_activenode + activenode.cpp + ) + +target_link_libraries( graphene_activenode graphene_chain graphene_app ) +target_include_directories( graphene_activenode + PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" ) + +install( TARGETS + graphene_activenode + + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib +) diff --git a/libraries/plugins/activenode/activenode.cpp b/libraries/plugins/activenode/activenode.cpp new file mode 100644 index 00000000..5923dec2 --- /dev/null +++ b/libraries/plugins/activenode/activenode.cpp @@ -0,0 +1,258 @@ +/* + * Copyright (c) 2015 Cryptonomex, Inc., and contributors. + * + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include + +#include +#include + +using namespace graphene::activenode_plugin; +using std::string; +using std::vector; + +namespace bpo = boost::program_options; + +void activenode_plugin::plugin_set_program_options( + boost::program_options::options_description& command_line_options, + boost::program_options::options_description& config_file_options) +{ + auto default_priv_key = fc::ecc::private_key::regenerate(fc::sha256::hash(std::string("nathan"))); + command_line_options.add_options() + ("activenode-account", bpo::value()->composing()->multitoken(), + "Name of account that is an activenode") + ("activenode-private-key", bpo::value>()->composing()->multitoken()-> + DEFAULT_VALUE_VECTOR(std::make_pair(chain::public_key_type(default_priv_key.get_public_key()), graphene::utilities::key_to_wif(default_priv_key))), + "Tuple of [PublicKey, WIF private key] (for account that will get rewards for being an activenode)") + ; + config_file_options.add(command_line_options); +} + +std::string activenode_plugin::plugin_name()const +{ + return "activenode"; +} + +void activenode_plugin::plugin_initialize(const boost::program_options::variables_map& options) +{ try { + ilog("activenode plugin: plugin_initialize() begin"); + _options = &options; + if (options.count("activenode-account")) { + _activenode_account_name = options["activenode-account"].as(); + } else { + elog("activenode-account field is empty! Please add activenode account to configuration"); + } + if( options.count("activenode-private-key") ) + { + const std::vector key_id_to_wif_pair_strings = options["activenode-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, GRAPHENE_MAX_NESTED_OBJECTS); + idump((key_id_to_wif_pair)); + fc::optional private_key = graphene::utilities::wif_to_key(key_id_to_wif_pair.second); + if (!private_key) + { + // the key isn't in WIF format; see if they are still passing the old native private key format. This is + // just here to ease the transition, can be removed soon + try + { + private_key = fc::variant( key_id_to_wif_pair.second, GRAPHENE_MAX_NESTED_OBJECTS ).as( GRAPHENE_MAX_NESTED_OBJECTS ); + } + catch (const fc::exception&) + { + FC_THROW("Invalid WIF-format private key ${key_string}", ("key_string", key_id_to_wif_pair.second)); + } + } + _private_key = std::make_pair(key_id_to_wif_pair.first, *private_key); + } + } else { + elog("activenode-private-key field is empty! Please add activenode private key to configuration"); + } + ilog("activenode plugin: plugin_initialize() end"); +} FC_LOG_AND_RETHROW() } + +void activenode_plugin::plugin_startup() +{ try { + ilog("activenode plugin: plugin_startup() begin"); + if (_activenode_account_name.size()) { + chain::database& db = database(); + const auto& account_idx = db.get_index_type().indices().get(); + const auto anode_account_itr = account_idx.find(_activenode_account_name); + if (anode_account_itr != account_idx.end()) { + _activenode_account_id = anode_account_itr->id; + db.new_block_applied.connect( [&]( const signed_block& b){ on_new_block_applied(b); } ); + } + else { + elog("activenode plugin: invalid activenode-account provided - no activenode associated with account with name ${activenode_account}", ("activenode_account", _activenode_account_name)); + } + } + ilog("activenode plugin: plugin_startup() end"); +} FC_CAPTURE_AND_RETHROW() } + +void activenode_plugin::plugin_shutdown() +{ + // nothing to do +} + +void activenode_plugin::on_new_block_applied(const signed_block& new_block) +{ + chain::database& db = database(); + + // check if still exists + if (_activenode){ + if ( db.find(*_activenode) == nullptr ) { + ilog("RESET DELETED ACTIVENODE"); + _activenode.reset(); + } + } + + if (!_activenode) { + // get activenode from account + const auto& anode_idx = db.get_index_type().indices().get(); + const auto& anode_itr = anode_idx.find(_activenode_account_id); + if (anode_itr != anode_idx.end()) { + _activenode = anode_itr->id; + } + else { + // didn't find any node for account + return; + } + } + + // if we are scheduled - send activity + + fc::optional scheduled_activenode = db.get_scheduled_activenode(db.head_block_num()); + fc::limited_mutable_variant_object capture( GRAPHENE_MAX_NESTED_OBJECTS ); + activenode_condition::activenode_condition_enum result; + + if (_activenode != scheduled_activenode) + return; + if ((*_activenode)(db).last_activity == fc::time_point::now()) + //double block appied + return; + try + { + result = send_activity(capture); + } + catch( const fc::canceled_exception& ) + { + //We're trying to exit. Go ahead and let this one out. + throw; + } + catch( const fc::exception& e ) + { + elog("Got exception while sending activity:\n${e}", ("e", e.to_detail_string())); + result = activenode_condition::exception_perform_activity; + } + switch( result ) + { + case activenode_condition::performed_activity: + ilog("Sent activity from anode ${activenode}, endpoint ${endpoint} with timestamp ${timestamp}", (capture)); + break; + case activenode_condition::not_synced: + ilog("Not sending activity because activity is disabled until we receive a recent block (see: --enable-stale-activity)"); + break; + case activenode_condition::not_my_turn: + break; + case activenode_condition::deleted: + return; + case activenode_condition::not_time_yet: + break; + case activenode_condition::no_private_key: + ilog("Not sending activity because I don't have the private key for ${scheduled_key}", (capture) ); + break; + case activenode_condition::lag: + elog("Not sending activity because node didn't wake up within 500ms of the slot time. scheduled=${scheduled_time} now=${now}", (capture)); + break; + case activenode_condition::no_scheduled_activenodes: + dlog("No scheduled activenodes"); + break; + case activenode_condition::not_sending: + break; + case activenode_condition::exception_perform_activity: + elog( "exception sending activity" ); + break; + } +} + +activenode_condition::activenode_condition_enum +activenode_plugin::send_activity( fc::limited_mutable_variant_object& capture ) +{ + chain::database& db = database(); + + const dynamic_global_property_object& dpo = db.get_dynamic_global_properties(); + + fc::variant_object network_info = app().p2p_node()->network_get_info(); + + fc::ip::endpoint endpoint = fc::ip::endpoint::from_string(network_info["listening_on"].as_string()); + graphene::net::firewalled_state node_firewalled_state; + fc::from_variant(network_info["firewalled"], node_firewalled_state, 1); + + if (!endpoint.get_address().is_public_address() || endpoint.get_address() == fc::ip::address("127.0.0.1")) { + elog("ERROR: node's ip is local ${endpoint}", ("endpoint", endpoint.get_address())); + return activenode_condition::not_sending; + } + + if (node_firewalled_state == graphene::net::firewalled_state::firewalled) { + elog("ERROR: node is firewalled ${endpoint}", ("endpoint", endpoint.get_address())); + return activenode_condition::not_sending; + } + + chain::activenode_send_activity_operation send_activity_operation; + fc::time_point_sec now = db.head_block_time(); + send_activity_operation.timepoint = now; + send_activity_operation.endpoint = endpoint; + send_activity_operation.activenode = *_activenode; + send_activity_operation.activenode_account = (*_activenode)(db).activenode_account; + + graphene::chain::signed_transaction tx; + tx.operations.push_back( send_activity_operation ); + + const graphene::chain::fee_schedule& fee_shed = db.current_fee_schedule(); + for( auto& op : tx.operations ) + fee_shed.set_fee(op); + + tx.validate(); + auto dyn_props = db.get_dynamic_global_properties(); + tx.set_reference_block( dyn_props.head_block_id ); + tx.set_expiration( dyn_props.time + fc::seconds(30) ); + + tx.sign( _private_key.second, db.get_chain_id() ); + app().chain_database()->push_transaction(tx); + if( app().p2p_node() != nullptr ) + app().p2p_node()->broadcast_transaction(tx); + + capture("timestamp", now)("endpoint", endpoint)("activenode", *_activenode); + + return activenode_condition::performed_activity; +} \ No newline at end of file diff --git a/libraries/plugins/activenode/include/graphene/activenode/activenode.hpp b/libraries/plugins/activenode/include/graphene/activenode/activenode.hpp new file mode 100644 index 00000000..77355e54 --- /dev/null +++ b/libraries/plugins/activenode/include/graphene/activenode/activenode.hpp @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2015 Cryptonomex, Inc., and contributors. + * + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#pragma once + +#include +#include + +#include +#include + +namespace graphene { namespace activenode_plugin { +using namespace fc; +using namespace chain; +namespace activenode_condition +{ + enum activenode_condition_enum + { + performed_activity = 0, + not_synced = 1, + not_my_turn = 2, + not_time_yet = 3, + no_private_key = 4, + lag = 5, + no_scheduled_activenodes = 6, + deleted = 7, + not_sending = 8, + exception_perform_activity = 9 + }; +} + +class activenode_plugin : public graphene::app::plugin { +public: + ~activenode_plugin() { + try { + if( _activity_task.valid() ) + _activity_task.cancel_and_wait(__FUNCTION__); + } catch(fc::canceled_exception&) { + //Expected exception. Move along. + } catch(fc::exception& e) { + edump((e.to_detail_string())); + } + } + + std::string plugin_name()const override; + + virtual void plugin_set_program_options( + boost::program_options::options_description &command_line_options, + boost::program_options::options_description &config_file_options + ) override; + + void set_activenode_plugin_enabled(bool allow) { _activenode_plugin_enabled = allow; } + + virtual void plugin_initialize( const boost::program_options::variables_map& options ) override; + virtual void plugin_startup() override; + virtual void plugin_shutdown() override; + +private: + void schedule_activity_loop(); + void on_new_block_applied(const signed_block& new_block); + + activenode_condition::activenode_condition_enum activity_loop(); + activenode_condition::activenode_condition_enum maybe_send_activity( fc::limited_mutable_variant_object& capture ); + + activenode_condition::activenode_condition_enum send_activity( fc::limited_mutable_variant_object& capture ); + + boost::program_options::variables_map _options; + bool _activenode_plugin_enabled = true; + + std::pair _private_key; + optional _activenode = optional(); + std::string _activenode_account_name; + chain::account_id_type _activenode_account_id; + fc::future _activity_task; +}; + +} } //graphene::activenode_plugin diff --git a/libraries/plugins/debug_witness/debug_api.cpp b/libraries/plugins/debug_witness/debug_api.cpp index 823755f5..65d6d669 100644 --- a/libraries/plugins/debug_witness/debug_api.cpp +++ b/libraries/plugins/debug_witness/debug_api.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include diff --git a/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp b/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp index 2398fc7b..98cba0e6 100644 --- a/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp +++ b/libraries/plugins/elasticsearch/elasticsearch_plugin.cpp @@ -317,7 +317,6 @@ void elasticsearch_plugin_impl::sendBulk(std::string _elasticsearch_node_url, bo curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *) &readBuffer_logs); curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcrp/0.1"); //curl_easy_setopt(curl, CURLOPT_VERBOSE, true); - //ilog("log here curl: ${output}", ("output", readBuffer_logs)); curl_easy_perform(curl); http_code = 0; diff --git a/libraries/plugins/es_objects/es_objects.cpp b/libraries/plugins/es_objects/es_objects.cpp index 586cb1e2..6de81eb5 100644 --- a/libraries/plugins/es_objects/es_objects.cpp +++ b/libraries/plugins/es_objects/es_objects.cpp @@ -347,9 +347,7 @@ void es_objects_plugin::plugin_set_program_options( ("es-objects-assets", boost::program_options::value(), "Store asset objects") ("es-objects-balances", boost::program_options::value(), "Store balances objects") ("es-objects-limit-orders", boost::program_options::value(), "Store limit order objects") - ("es-objects-asset-bitasset", boost::program_options::value(), "Store feed data") - - ; + ("es-objects-asset-bitasset", boost::program_options::value(), "Store feed data"); cfg.add(cli); } diff --git a/libraries/plugins/market_history/market_history_plugin.cpp b/libraries/plugins/market_history/market_history_plugin.cpp index 3f3277e4..71248492 100644 --- a/libraries/plugins/market_history/market_history_plugin.cpp +++ b/libraries/plugins/market_history/market_history_plugin.cpp @@ -83,7 +83,6 @@ struct operation_process_fill_order void operator()( const fill_order_operation& o )const { - //ilog( "processing ${o}", ("o",o) ); auto& db = _plugin.database(); const auto& order_his_idx = db.get_index_type().indices(); const auto& history_idx = order_his_idx.get(); diff --git a/libraries/plugins/witness/witness.cpp b/libraries/plugins/witness/witness.cpp index 754e3461..f56b7f35 100644 --- a/libraries/plugins/witness/witness.cpp +++ b/libraries/plugins/witness/witness.cpp @@ -146,7 +146,10 @@ void witness_plugin::schedule_production_loop() //Schedule for the next second's tick regardless of chain state // If we would wait less than 50ms, wait for the whole second. fc::time_point now = fc::time_point::now(); + + //in microseconds int64_t time_to_next_second = 1000000 - (now.time_since_epoch().count() % 1000000); + // next second in less than 50ms, we'll wait for the next one if( time_to_next_second < 50000 ) // we must sleep for at least 50ms time_to_next_second += 1000000; @@ -212,7 +215,7 @@ block_production_condition::block_production_condition_enum witness_plugin::mayb { chain::database& db = database(); fc::time_point now_fine = fc::time_point::now(); - fc::time_point_sec now = now_fine + fc::microseconds( 500000 ); + fc::time_point_sec now = now_fine; // If the next block production opportunity is in the present or future, we're synced. if( !_production_enabled ) @@ -225,6 +228,7 @@ block_production_condition::block_production_condition_enum witness_plugin::mayb // is anyone scheduled to produce now or one second in the future? uint32_t slot = db.get_slot_at_time( now ); + if( slot == 0 ) { capture("next_time", db.get_slot_time(1)); @@ -279,7 +283,11 @@ block_production_condition::block_production_condition_enum witness_plugin::mayb _production_skip_flags ); capture("n", block.block_num())("t", block.timestamp)("c", now); - fc::async( [this,block](){ p2p_node().broadcast(net::block_message(block)); } ); + fc::async( [this,block](){ + p2p_node().broadcast(net::block_message(block)); + database().notify_new_block_applied( block ); //emit + + } ); return block_production_condition::produced; } diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index 8ffb499d..d48601a7 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -1259,6 +1259,8 @@ class wallet_api */ map list_witnesses(const string& lowerbound, uint32_t limit); + map list_activenodes(const string& lowerbound, uint32_t limit); + /** Lists all committee_members registered in the blockchain. * This returns a list of all account names that own committee_members, and the associated committee_member id, * sorted by name. This lists committee_members whether they are currently voted in or not. @@ -1280,6 +1282,9 @@ class wallet_api */ witness_object get_witness(string owner_account); + activenode_object get_activenode(string owner_account); + + /** Returns information about the given committee_member. * @param owner_account the name or id of the committee_member account owner, or the id of the committee_member * @returns the information about the committee_member stored in the block chain @@ -1300,6 +1305,9 @@ class wallet_api string url, bool broadcast = false); + signed_transaction create_activenode(string owner_account, + bool broadcast /* = false */); + /** * Update a witness object owned by the given account. * @@ -1690,10 +1698,13 @@ FC_API( graphene::wallet::wallet_api, (whitelist_account) (create_committee_member) (get_witness) + (get_activenode) (get_committee_member) (list_witnesses) + (list_activenodes) (list_committee_members) (create_witness) + (create_activenode) (update_witness) (create_worker) (update_worker_votes) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index b53f9741..ba3aeaf9 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -1123,7 +1123,6 @@ class wallet_api_impl return create_account_with_private_key(owner_privkey, account_name, registrar_account, referrer_account, broadcast, save_wallet); } FC_CAPTURE_AND_RETHROW( (account_name)(registrar_account)(referrer_account) ) } - signed_transaction create_asset(string issuer, string symbol, uint8_t precision, @@ -1427,6 +1426,41 @@ class wallet_api_impl FC_CAPTURE_AND_RETHROW( (owner_account) ) } + activenode_object get_activenode(string owner_account) + { + try + { + fc::optional activenode_id = maybe_id(owner_account); + if (activenode_id) + { + std::vector ids_to_get; + ids_to_get.push_back(*activenode_id); + std::vector> activenode_objects = _remote_db->get_activenodes(ids_to_get); + if (activenode_objects.front()) + return *activenode_objects.front(); + FC_THROW("No activenode is registered for id ${id}", ("id", owner_account)); + } + else + { + // then maybe it's the owner account + try + { + account_id_type owner_account_id = get_account_id(owner_account); + fc::optional activenode = _remote_db->get_activenode_by_account(owner_account_id); + if (activenode) + return *activenode; + else + FC_THROW("No activenode is registered for account ${account}", ("account", owner_account)); + } + catch (const fc::exception&) + { + FC_THROW("No account or activenode named ${account}", ("account", owner_account)); + } + } + } + FC_CAPTURE_AND_RETHROW( (owner_account) ) + } + committee_member_object get_committee_member(string owner_account) { try @@ -1490,6 +1524,25 @@ class wallet_api_impl return sign_transaction( tx, broadcast ); } FC_CAPTURE_AND_RETHROW( (owner_account)(broadcast) ) } + signed_transaction create_activenode(string owner_account, + bool broadcast /* = false */) + { try { + account_object activenode_account = get_account(owner_account); + + activenode_create_operation activenode_create_op; + activenode_create_op.activenode_account = activenode_account.id; + + if (_remote_db->get_activenode_by_account(activenode_create_op.activenode_account)) + FC_THROW("Account ${owner_account} is already an activenode", ("owner_account", owner_account)); + + signed_transaction tx; + tx.operations.push_back( activenode_create_op ); + set_operation_fees( tx, _remote_db->get_global_properties().parameters.current_fees); + tx.validate(); + + return sign_transaction( tx, broadcast ); + } FC_CAPTURE_AND_RETHROW( (owner_account)(broadcast) ) } + signed_transaction update_witness(string witness_name, string url, string block_signing_key, @@ -3386,6 +3439,17 @@ map wallet_api::list_witnesses(const string& lowerbound, return my->_remote_db->lookup_witness_accounts(lowerbound, limit); } +map wallet_api::list_activenodes(const string& lowerbound, uint32_t limit) +{ + return my->_remote_db->lookup_activenode_accounts(lowerbound, limit); +} + +signed_transaction wallet_api::create_activenode(string owner_account, + bool broadcast /* = false */) +{ + return my->create_activenode(owner_account, broadcast); +} + map wallet_api::list_committee_members(const string& lowerbound, uint32_t limit) { return my->_remote_db->lookup_committee_member_accounts(lowerbound, limit); @@ -3396,6 +3460,11 @@ witness_object wallet_api::get_witness(string owner_account) return my->get_witness(owner_account); } +activenode_object wallet_api::get_activenode(string owner_account) +{ + return my->get_activenode(owner_account); +} + committee_member_object wallet_api::get_committee_member(string owner_account) { return my->get_committee_member(owner_account); diff --git a/prod_conf.ini b/prod_conf.ini deleted file mode 100644 index a74734ce..00000000 --- a/prod_conf.ini +++ /dev/null @@ -1,172 +0,0 @@ -# Endpoint for P2P node to listen on -p2p-endpoint = 0.0.0.0:11010 - -# P2P nodes to connect to on startup (may specify multiple times) -seed-node = localcoin.airdroptelegramknights.io:11010 -seed-node = helsinki.localcoin.is:11010 -seed-node = ua-dnepro.localcoin.is:11010 -seed-node = moscow.localcoin.is:11010 - -# JSON array of P2P nodes to connect to on startup -# seed-nodes = ["moscow.localcoin.is:11010","localcoin.airdroptelegramknights.io:11010"] - -# Pairs of [BLOCK_NUM,BLOCK_ID] that should be enforced as checkpoints. -# checkpoint = - -# Endpoint for websocket RPC to listen on -rpc-endpoint = 0.0.0.0:8090 - -# Endpoint for TLS websocket RPC to listen on -# rpc-tls-endpoint = - -# The TLS certificate file for this server -# server-pem = - -# Password for this certificate -# server-pem-password = - -# File to read Genesis State from -genesis-json = genesis.json - -# Block signing key to use for init witnesses, overrides genesis file -# dbg-init-key = - -# JSON file specifying API permissions -# api-access = - -# Space-separated list of plugins to activate -# plugins = - -# Enable block production, even if the chain is stale. -enable-stale-production = true - -# Percent of witnesses (0-99) that must be participating in order to produce blocks -required-participation = false - -# ID of witness controlled by this node (e.g. "1.6.5", quotes are required, may specify multiple times) -witness-id = "1.6.1" -witness-id = "1.6.2" -witness-id = "1.6.3" -witness-id = "1.6.4" -witness-id = "1.6.5" -witness-id = "1.6.6" -witness-id = "1.6.7" -witness-id = "1.6.8" - -# Tuple of [PublicKey, WIF private key] (may specify multiple times) -private-key = ["LLC78dAhdTGLacNRTJzfXUnF5qdJiWBNkWukzYHqauirGftjuBD4d","5KCNzYJAi6oDwq18EXzwJYn65xRzFVz5JYr3EYh9QevgxwuX1Ad"] -private-key = ["LLC5xhgVsG4hgXDQ4bwSBiwqD78jczBv5VxHpGzShQRgBiStPivzN","5KKinpDPHAe519pZ1joHbZNpQrNskjgpAA9dr8Myj1LyXvmqwnb"] -private-key = ["LLC5gVwdbDbTpRioxqBaDreLF33pptE7QSqNZ1scQBsnvPFCXQYjn","5JuZjge7gZhkm32kuWuY5rFs6sU5YZJa9dRhbbmyyZkgqWcHbRi"] -private-key = ["LLC5E1EEvKb2jtqR8smjkWHMubbQcih1VqTPG2TP5RwrzeUjkGHyY","5JLYsHKwujWcjshtkfaR1AcLshgf1Xo6tgehcZtsXzRjrrLXDqd"] -private-key = ["LLC6crqygKbdqTNiU3Vai8RtweM7w5RnWwtDqdKy7277UytxffhCK","5JoSGd8QVoSy2bayYf1xVKK4y8bfjpyd4mLEXeJM3dZ79LiYx7s"] -private-key = ["LLC7ZVK91ku6a5jYUYR8FfnFeipbBBUcuBGjimeaCnhjpwsp4PDLG","5KJgab4NcbBXqAo6eFktvDaJfMQBmwD6LGeVJ26R2XB584zShhZ"] -private-key = ["LLC5NGpou9nB1LS2X9sSRyawVtZZNaGZpf22EvbgDLs1LYoswNy6H","5Hz2oKGJKbmDC5Bp7ARFHdS8tFL2o4wm8DybFtmr3w97pAX4KM7"] -private-key = ["LLC7xfPUpkr5jfyYaMkhHEZurSEn87jqZNgcxsqEgApkXSzUrek23","5JjKPDzqw9DWPPhatkM7jo3PBoAMYDnUrCcLJQXYdw9eHRLad6k"] - -# Tuple of [PublicKey, WIF private key] (may specify multiple times) -debug-private-key = ["LLC6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV","5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3"] - -# Account ID to track history for (may specify multiple times) -# track-account = - -# Keep only those operations in memory that are related to account history tracking -partial-operations = 1 - -# Maximum number of operations per account will be kept in memory -max-ops-per-account = 1000 - -# Elastic Search database node url -# elasticsearch-node-url = - -# Number of bulk documents to index on replay(5000) -# elasticsearch-bulk-replay = - -# Number of bulk documents to index on a syncronied chain(10) -# elasticsearch-bulk-sync = - -# Log bulk events to database -# elasticsearch-logs = - -# Use visitor to index additional data(slows down the replay) -# elasticsearch-visitor = - -# Track market history by grouping orders into buckets of equal size measured in seconds specified as a JSON array of numbers -bucket-size = [60,300,900,1800,3600,14400,86400] - -# How far back in time to track history for each bucket size, measured in the number of buckets (default: 1000) -history-per-size = 1000 - -# Will only store this amount of matched orders for each market in order history for querying, or those meet the other option, which has more data (default: 1000) -max-order-his-records-per-market = 1000 - -# Will only store matched orders in last X seconds for each market in order history for querying, or those meet the other option, which has more data (default: 259200 (3 days)) -max-order-his-seconds-per-market = 259200 - -# RPC endpoint of a trusted validating node (required) -# trusted-node = - -# Block number after which to do a snapshot -# snapshot-at-block = - -# Block time (ISO format) after which to do a snapshot -# snapshot-at-time = - -# Pathname of JSON file where to store the snapshot -# snapshot-to = - -# Elasticsearch node url -# es-objects-elasticsearch-url = - -# Log bulk events to database -# es-objects-logs = - -# Number of bulk documents to index on replay(5000) -# es-objects-bulk-replay = - -# Number of bulk documents to index on a syncronied chain(10) -# es-objects-bulk-sync = - -# Store proposal objects -# es-objects-proposals = - -# Store account objects -# es-objects-accounts = - -# Store asset objects -# es-objects-assets = - -# Store balances objects -# es-objects-balances = - -# Store limit order objects -# es-objects-limit-orders = - -# Store feed data -# es-objects-asset-bitasset = - -# Group orders by percentage increase on price. Specify a JSON array of numbers here, each number is a group, number 1 means 0.01%. -tracked-groups = [10,100] - -# declare an appender named "stderr" that writes messages to the console -[log.console_appender.stderr] -stream=std_error - -# declare an appender named "p2p" that writes messages to p2p.log -[log.file_appender.p2p] -# filename can be absolute or relative to this config file -filename=logs/p2p/p2p.log -# Rotate log every ? minutes, if leave out default to 60 -rotation_interval=60 -# how long will logs be kept (in days), if leave out default to 7 -rotation_limit=7 - -# route any messages logged to the default logger to the "stderr" logger we -# declared above, if they are info level are higher -[logger.default] -level=info -appenders=stderr - -# route messages sent to the "p2p" logger to the p2p appender declared above -[logger.p2p] -level=info -appenders=p2p diff --git a/programs/build_helpers/member_enumerator.cpp b/programs/build_helpers/member_enumerator.cpp index 4204a251..18d1bbb6 100644 --- a/programs/build_helpers/member_enumerator.cpp +++ b/programs/build_helpers/member_enumerator.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include diff --git a/programs/js_operation_serializer/main.cpp b/programs/js_operation_serializer/main.cpp index 61c1873e..a644f48d 100644 --- a/programs/js_operation_serializer/main.cpp +++ b/programs/js_operation_serializer/main.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include diff --git a/programs/witness_node/CMakeLists.txt b/programs/witness_node/CMakeLists.txt index 4815879a..b1864be2 100644 --- a/programs/witness_node/CMakeLists.txt +++ b/programs/witness_node/CMakeLists.txt @@ -12,7 +12,7 @@ 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_activenode graphene_chain graphene_debug_witness graphene_egenesis_full graphene_snapshot graphene_es_objects 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 f5a2dc40..f6fc2d32 100644 --- a/programs/witness_node/main.cpp +++ b/programs/witness_node/main.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -192,6 +193,8 @@ int main(int argc, char** argv) { bpo::variables_map options; auto witness_plug = node->register_plugin(); + auto activenode_plug = node->register_plugin(); + auto debug_witness_plug = node->register_plugin(); auto history_plug = node->register_plugin(); auto elasticsearch_plug = node->register_plugin(); diff --git a/reserve_asset.php b/reserve_asset.php deleted file mode 100644 index a7827ba8..00000000 --- a/reserve_asset.php +++ /dev/null @@ -1,28 +0,0 @@ - $item) { - $json = json_encode([ - "jsonrpc" => "2.0", - "method" => "reserve_asset", - "params" => [ - ACCOUNT, - AMOUNT, - $item["symbol"], - true - ], - "id" => 1 - ]); - $ch = curl_init(HOST); - curl_setopt($ch, CURLOPT_POST, 1); - curl_setopt($ch, CURLOPT_POSTFIELDS, $json); - curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json')); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); - $result = curl_exec($ch); - - echo count($genesis["initial_assets"]) - $id - 1; - echo "\n"; -} \ No newline at end of file diff --git a/startup_cli_wallet_testnet.txt b/startup_cli_wallet_testnet.txt deleted file mode 100644 index 4c17265d..00000000 --- a/startup_cli_wallet_testnet.txt +++ /dev/null @@ -1,29 +0,0 @@ -set_password testpass -unlock testpass - -import_key notteler "5KCNzYJAi6oDwq18EXzwJYn65xRzFVz5JYr3EYh9QevgxwuX1Ad" true -import_balance notteler ["5KCNzYJAi6oDwq18EXzwJYn65xRzFVz5JYr3EYh9QevgxwuX1Ad"] true true - -import_key germut "5KKinpDPHAe519pZ1joHbZNpQrNskjgpAA9dr8Myj1LyXvmqwnb" true -import_balance germut ["5KKinpDPHAe519pZ1joHbZNpQrNskjgpAA9dr8Myj1LyXvmqwnb"] true true - -import_key localcoin-ico "5JuZjge7gZhkm32kuWuY5rFs6sU5YZJa9dRhbbmyyZkgqWcHbRi" true -import_balance localcoin-ico ["5JuZjge7gZhkm32kuWuY5rFs6sU5YZJa9dRhbbmyyZkgqWcHbRi"] true true - -import_key localcoin "5JLYsHKwujWcjshtkfaR1AcLshgf1Xo6tgehcZtsXzRjrrLXDqd" true -import_balance localcoin ["5JLYsHKwujWcjshtkfaR1AcLshgf1Xo6tgehcZtsXzRjrrLXDqd"] true true - -import_key localcoin-wallet "5JoSGd8QVoSy2bayYf1xVKK4y8bfjpyd4mLEXeJM3dZ79LiYx7s" true -import_balance localcoin-wallet ["5JoSGd8QVoSy2bayYf1xVKK4y8bfjpyd4mLEXeJM3dZ79LiYx7s"] true true - -import_key localcoin-fiat "5KJgab4NcbBXqAo6eFktvDaJfMQBmwD6LGeVJ26R2XB584zShhZ" true -import_balance localcoin-fiat ["5KJgab4NcbBXqAo6eFktvDaJfMQBmwD6LGeVJ26R2XB584zShhZ"] true true - -import_key localcoin-otc "5Hz2oKGJKbmDC5Bp7ARFHdS8tFL2o4wm8DybFtmr3w97pAX4KM7" true -import_balance localcoin-otc ["5Hz2oKGJKbmDC5Bp7ARFHdS8tFL2o4wm8DybFtmr3w97pAX4KM7"] true true - -import_key localcoin-feed "5JjKPDzqw9DWPPhatkM7jo3PBoAMYDnUrCcLJQXYdw9eHRLad6k" true -import_balance localcoin-feed ["5JjKPDzqw9DWPPhatkM7jo3PBoAMYDnUrCcLJQXYdw9eHRLad6k"] true true - -import_key llc-igorbiliba "5KAPZxRBf3pQTHSNVEQUyH4gncUu82TMT3mFXTr9G3wpFNAu8Zn" true -import_balance llc-igorbiliba ["5KAPZxRBf3pQTHSNVEQUyH4gncUu82TMT3mFXTr9G3wpFNAu8Zn"] true true \ No newline at end of file diff --git a/test-config.ini b/test-config.ini deleted file mode 100644 index 43874d67..00000000 --- a/test-config.ini +++ /dev/null @@ -1,165 +0,0 @@ -# Endpoint for P2P node to listen on -p2p-endpoint = 0.0.0.0:11010 - -# P2P nodes to connect to on startup (may specify multiple times) -seed-node = localcoin.airdroptelegramknights.io:11010 -seed-node = helsinki.localcoin.is:11010 -seed-node = ua-dnepro.localcoin.is:11010 -seed-node = moscow.localcoin.is:11010 - -# JSON array of P2P nodes to connect to on startup -# seed-nodes = ["moscow.localcoin.is:11010","localcoin.airdroptelegramknights.io:11010"] - -# Pairs of [BLOCK_NUM,BLOCK_ID] that should be enforced as checkpoints. -# checkpoint = - -# Endpoint for websocket RPC to listen on -rpc-endpoint = 0.0.0.0:8090 - -# Endpoint for TLS websocket RPC to listen on -# rpc-tls-endpoint = - -# The TLS certificate file for this server -# server-pem = - -# Password for this certificate -# server-pem-password = - -# File to read Genesis State from -genesis-json = genesis.json - -# Block signing key to use for init witnesses, overrides genesis file -# dbg-init-key = - -# JSON file specifying API permissions -# api-access = - -# Space-separated list of plugins to activate -# plugins = - -# Enable block production, even if the chain is stale. -enable-stale-production = true - -# Percent of witnesses (0-99) that must be participating in order to produce blocks -required-participation = false - -# ID of witness controlled by this node (e.g. "1.6.5", quotes are required, may specify multiple times) -witness-id = "1.6.1" -witness-id = "1.6.2" -witness-id = "1.6.3" -witness-id = "1.6.4" -witness-id = "1.6.5" -witness-id = "1.6.6" -witness-id = "1.6.7" -witness-id = "1.6.8" - -# Tuple of [PublicKey, WIF private key] (may specify multiple times) -private-key = ["LLC6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV","5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3"] - -# Tuple of [PublicKey, WIF private key] (may specify multiple times) -debug-private-key = ["LLC6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV","5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3"] - -# Account ID to track history for (may specify multiple times) -# track-account = - -# Keep only those operations in memory that are related to account history tracking -partial-operations = 1 - -# Maximum number of operations per account will be kept in memory -max-ops-per-account = 1000 - -# Elastic Search database node url -# elasticsearch-node-url = - -# Number of bulk documents to index on replay(5000) -# elasticsearch-bulk-replay = - -# Number of bulk documents to index on a syncronied chain(10) -# elasticsearch-bulk-sync = - -# Log bulk events to database -# elasticsearch-logs = - -# Use visitor to index additional data(slows down the replay) -# elasticsearch-visitor = - -# Track market history by grouping orders into buckets of equal size measured in seconds specified as a JSON array of numbers -bucket-size = [60,300,900,1800,3600,14400,86400] - -# How far back in time to track history for each bucket size, measured in the number of buckets (default: 1000) -history-per-size = 1000 - -# Will only store this amount of matched orders for each market in order history for querying, or those meet the other option, which has more data (default: 1000) -max-order-his-records-per-market = 1000 - -# Will only store matched orders in last X seconds for each market in order history for querying, or those meet the other option, which has more data (default: 259200 (3 days)) -max-order-his-seconds-per-market = 259200 - -# RPC endpoint of a trusted validating node (required) -# trusted-node = - -# Block number after which to do a snapshot -# snapshot-at-block = - -# Block time (ISO format) after which to do a snapshot -# snapshot-at-time = - -# Pathname of JSON file where to store the snapshot -# snapshot-to = - -# Elasticsearch node url -# es-objects-elasticsearch-url = - -# Log bulk events to database -# es-objects-logs = - -# Number of bulk documents to index on replay(5000) -# es-objects-bulk-replay = - -# Number of bulk documents to index on a syncronied chain(10) -# es-objects-bulk-sync = - -# Store proposal objects -# es-objects-proposals = - -# Store account objects -# es-objects-accounts = - -# Store asset objects -# es-objects-assets = - -# Store balances objects -# es-objects-balances = - -# Store limit order objects -# es-objects-limit-orders = - -# Store feed data -# es-objects-asset-bitasset = - -# Group orders by percentage increase on price. Specify a JSON array of numbers here, each number is a group, number 1 means 0.01%. -tracked-groups = [10,100] - -# declare an appender named "stderr" that writes messages to the console -[log.console_appender.stderr] -stream=std_error - -# declare an appender named "p2p" that writes messages to p2p.log -[log.file_appender.p2p] -# filename can be absolute or relative to this config file -filename=logs/p2p/p2p.log -# Rotate log every ? minutes, if leave out default to 60 -rotation_interval=60 -# how long will logs be kept (in days), if leave out default to 7 -rotation_limit=7 - -# route any messages logged to the default logger to the "stderr" logger we -# declared above, if they are info level are higher -[logger.default] -level=info -appenders=stderr - -# route messages sent to the "p2p" logger to the p2p appender declared above -[logger.p2p] -level=info -appenders=p2p diff --git a/test-genesis.json b/test-genesis.json deleted file mode 100644 index 1e5e3d21..00000000 --- a/test-genesis.json +++ /dev/null @@ -1,2013 +0,0 @@ -{ - "initial_timestamp": "2018-05-15T10:23:20", - "max_core_supply": "360000000000000", - "initial_parameters": { - "current_fees": { - "parameters": [ - [ - 0, { - "fee": 2000000, - "price_per_kbyte": 1000000 - } - ], - [ - 1, { - "fee": 500000 - } - ], - [ - 2, { - "fee": 0 - } - ], - [ - 3, { - "fee": 2000000 - } - ], - [ - 4, {} - ], - [ - 5, { - "basic_fee": 500000, - "premium_fee": 200000000, - "price_per_kbyte": 100000 - } - ], - [ - 6, { - "fee": 2000000, - "price_per_kbyte": 100000 - } - ], - [ - 7, { - "fee": 300000 - } - ], - [ - 8, { - "membership_annual_fee": 200000000, - "membership_lifetime_fee": 1000000000 - } - ], - [ - 9, { - "fee": 50000000 - } - ], - [ - 10, { - "symbol3": "50000000000", - "symbol4": "30000000000", - "long_symbol": 500000000, - "price_per_kbyte": 10 - } - ], - [ - 11, { - "fee": 50000000, - "price_per_kbyte": 10 - } - ], - [ - 12, { - "fee": 50000000 - } - ], - [ - 13, { - "fee": 50000000 - } - ], - [ - 14, { - "fee": 2000000, - "price_per_kbyte": 100000 - } - ], - [ - 15, { - "fee": 2000000 - } - ], - [ - 16, { - "fee": 100000 - } - ], - [ - 17, { - "fee": 10000000 - } - ], - [ - 18, { - "fee": 50000000 - } - ], - [ - 19, { - "fee": 100000 - } - ], - [ - 20, { - "fee": 500000000 - } - ], - [ - 21, { - "fee": 2000000 - } - ], - [ - 22, { - "fee": 2000000, - "price_per_kbyte": 10 - } - ], - [ - 23, { - "fee": 2000000, - "price_per_kbyte": 10 - } - ], - [ - 24, { - "fee": 100000 - } - ], - [ - 25, { - "fee": 100000 - } - ], - [ - 26, { - "fee": 100000 - } - ], - [ - 27, { - "fee": 2000000, - "price_per_kbyte": 10 - } - ], - [ - 28, { - "fee": 0 - } - ], - [ - 29, { - "fee": 500000000 - } - ], - [ - 30, { - "fee": 2000000 - } - ], - [ - 31, { - "fee": 100000 - } - ], - [ - 32, { - "fee": 100000 - } - ], - [ - 33, { - "fee": 2000000 - } - ], - [ - 34, { - "fee": 500000000 - } - ], - [ - 35, { - "fee": 100000, - "price_per_kbyte": 10 - } - ], - [ - 36, { - "fee": 100000 - } - ], - [ - 37, {} - ], - [ - 38, { - "fee": 2000000, - "price_per_kbyte": 10 - } - ], - [ - 39, { - "fee": 500000, - "price_per_output": 500000 - } - ], - [ - 40, { - "fee": 500000, - "price_per_output": 500000 - } - ], - [ - 41, { - "fee": 500000 - } - ], - [ - 42, {} - ], - [ - 43, { - "fee": 2000000 - } - ], - [ - 44, {} - ], - [ - 45, { - "fee": 2000000 - } - ], - [ - 46, {} - ] - ], - "scale": 10000 - }, - "block_interval": 3, - "maintenance_interval": 86400, - "maintenance_skip_slots": 3, - "committee_proposal_review_period": 1209600, - "maximum_transaction_size": 2048, - "maximum_block_size": 2000000, - "maximum_time_until_expiration": 86400, - "maximum_proposal_lifetime": 2419200, - "maximum_asset_whitelist_authorities": 10, - "maximum_asset_feed_publishers": 10, - "maximum_witness_count": 1001, - "maximum_committee_count": 1001, - "maximum_authority_membership": 10, - "reserve_percent_of_fee": 2000, - "network_percent_of_fee": 2000, - "lifetime_referrer_percent_of_fee": 3000, - "cashback_vesting_period_seconds": 31536000, - "cashback_vesting_threshold": 10000000, - "count_non_member_votes": true, - "allow_non_member_whitelists": false, - "witness_pay_per_block": 100000, - "worker_budget_per_day": "50000000000", - "max_predicate_opcode": 1, - "fee_liquidation_threshold": 10000000, - "accounts_per_fee_scale": 1000, - "account_fee_scale_bitshifts": 4, - "max_authority_depth": 2, - "extensions": [] - }, - "initial_accounts": [{ - "name": "notteler", - "owner_key": "LLC6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "LLC6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - }, { - "name": "germut", - "owner_key": "LLC6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "LLC6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - }, { - "name": "localcoin-ico", - "owner_key": "LLC6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "LLC6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - }, { - "name": "localcoin", - "owner_key": "LLC6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "LLC6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - }, { - "name": "localcoin-wallet", - "owner_key": "LLC6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "LLC6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - }, { - "name": "localcoin-fiat", - "owner_key": "LLC6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "LLC6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - }, { - "name": "localcoin-otc", - "owner_key": "LLC6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "LLC6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - }, { - "name": "localcoin-feed", - "owner_key": "LLC6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "LLC6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - }], - "initial_assets": [{ - "symbol": "USD", - "issuer_name": "localcoin-fiat", - "description": "US dollar", - "precision": 4 - }, { - "symbol": "EUR", - "issuer_name": "localcoin-fiat", - "description": "Euro", - "precision": 4 - }, { - "symbol": "GBP", - "issuer_name": "localcoin-fiat", - "description": "Pound sterling", - "precision": 4 - }, { - "symbol": "RUB", - "issuer_name": "localcoin-fiat", - "description": "Russian rouble", - "precision": 4 - }, { - "symbol": "CNY", - "issuer_name": "localcoin-fiat", - "description": "Chinese yuan renminbi", - "precision": 4 - }, - { - "description": "1 bitcoin", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "BTC" - }, - { - "description": "1 ethereum", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "ETH" - }, - - { - "description": "1 bitcoin cash", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "BCH" - }, - - { - "description": "1 litecoin", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "LTC" - }, - - - { - "description": "1 ripple", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "XRP" - }, - - { - "description": "1 qtum", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "QTUM" - }, - - { - "description": "1 huobi token", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "HT" - }, - - { - "description": "1 ethereum classic", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "ETC" - }, - - { - "description": "1 NEO", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "NEO" - }, - - - { - "description": "1 cardano", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "ADA" - }, - - { - "description": "1 zcash", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "ZEC" - }, - { - "description": "1 stellar", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "XLM" - }, - { - "description": "1 IOTA", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "MIOTA" - }, - - { - "description": "1 monero", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "XMR" - }, - { - "description": "1 dash", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "DASH" - }, - { - "description": "1 nem", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "XEM" - }, - - { - "description": "1 bytecoin", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "BCN" - }, - - - { - "description": "1 lisk", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "LSK" - }, - { - "description": "1 bitcoin gold", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "BTG" - }, - { - "description": "1 decred", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "DCR" - }, - { - "description": "1 verge", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "XVG" - }, - { - "description": "1 steem", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "STEEM" - }, - { - "description": "1 nano", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "NANO" - }, - { - "description": "1 bitshares", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "BTS" - }, - { - "description": "1 wanchain", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "WAN" - }, - { - "description": "1 hshare", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "HSR" - }, - { - "description": "1 Waves", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "WAVES" - }, - { - "description": "1 Achain", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "ACT" - }, - { - "description": "1 Groestlcoin", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "GRS" - }, - { - "description": "1 dogecoin", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "DOGE" - }, - { - "description": "1 waykichain", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "WICC" - }, - { - "description": "1 GXChain", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "GXS" - }, - { - "description": "1 cloakcoin", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "CLOAK" - }, - { - "description": "1 stratis", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "STRAT" - }, - { - "description": "1 neblio", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "NEBL" - }, - { - "description": "1 siacoin", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "SC" - }, - { - "description": "1 elastos", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "ELA" - }, - { - "description": "1 navcoin", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "NAV" - }, - { - "description": "1 asch", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "XAS" - }, - { - "description": "1 Metaverse ETP", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "ETP" - }, - { - "description": "1 digibyte", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "DGB" - }, - { - "description": "1 reddcoin", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "RDD" - }, - { - "description": "1 poa network", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "POA" - }, - { - "description": "1 nxt", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "NXT" - }, - { - "description": "1 syscoin", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "SYS" - }, - { - "description": "1 pivx", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "PIVX" - }, - { - "description": "1 Pura", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "PURA" - }, - { - "description": "1 DECENT", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "DCT" - }, - { - "description": "1 nexus", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "NXS" - }, - { - "description": "1 primecoin", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "XPM" - }, - { - "description": "1 komodo", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "KMD" - }, - { - "description": "1 DigitalNote", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "XDN" - }, - { - "description": "1 ZenCash", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "ZEN" - }, - { - "description": "1 Ardor", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "ARDR" - }, - { - "description": "1 vertcoin", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "VTC" - }, - { - "description": "1 bitcoin diamond", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "BCD" - }, - { - "description": "1 cryptonex", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "CNX" - }, - { - "description": "1 ZCoin", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "XZC" - }, - { - "description": "1 Steem Dollars", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "SBD" - }, - { - "description": "1 Factom", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "FCT" - }, - { - "description": "1 LinkEye", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "LET" - }, - { - "description": "1 Viacoin", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "VIA" - }, - { - "description": "1 Particl", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "PART" - }, - { - "description": "1 Emercoin", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "EMC" - }, - { - "description": "1 Ark", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "ARK" - }, - { - "description": "1 Experience points", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "XP" - }, - { - "description": "1 Skycoin", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "SKY" - }, - { - "description": "1 ZClassic", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "ZCL" - }, - { - "description": "1 MonaCoin", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "MONA" - }, - { - "description": "1 SelfSell", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "SSC" - }, - { - "description": "1 Ubiq", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "UBQ" - }, - { - "description": "1 BitCoin Private", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "BTCP" - }, - { - "description": "1 BitCore", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "BTX" - }, - { - "description": "1 Electroneum", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "ETN" - }, - { - "description": "1 Electra", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "ECA" - }, - { - "description": "1 Einsteinium", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "EMC2" - }, - { - "description": "1 Salus", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "SLS" - }, - { - "description": "1 TokenPay", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "TPAY" - }, - { - "description": "1 Ravencoin", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "RVN" - }, - { - "description": "1 GameCredits", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "GAME" - }, - { - "description": "1 ION", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "ION" - }, - { - "description": "1 Peercoin", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "PPC" - }, - { - "description": "1 BOSCoin", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "BOS" - }, - { - "description": "1 LBRY Credits", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "LBC" - }, - { - "description": "1 Litecoin Cash", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "LCC" - }, - { - "description": "1 Zoin", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "ZOI" - }, - { - "description": "1 WhiteCoin", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "XWC" - }, - { - "description": "1 BitCoin Dark", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "BTCD" - }, - { - "description": "1 Burst", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "BURST" - }, - { - "description": "1 Byteball Bytes", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "GBYTE" - }, - { - "description": "1 HTMLCOIN", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "HTML" - }, - { - "description": "1 BitBay", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "BAY" - }, - { - "description": "1 Counterparty", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "XCP" - }, - { - "description": "1 Namecoin", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "NMC" - }, - { - "description": "1 Blocknet", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "BLOCK" - }, - { - "description": "1 SmartCash", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "SMART" - }, - { - "description": "1 Feathercoin", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "FTC" - }, - { - "description": "1 Gulden", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "NLG" - }, - { - "description": "1 MinexCoin", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "MNX" - }, - - - - - { - "description": "1 Tether", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "USDT" - }, - { - "description": "1 EOS", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "EOS" - }, - { - "description": "1 TRON", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "TRX" - }, - { - "description": "1 True Chain", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "TRUE" - }, - { - "description": "1 0x", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "ZRX" - }, - { - "description": "1 Bibox Token", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "BIX" - }, - { - "description": "1 Ontology", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "ONT" - }, - { - "description": "1 CyberMiles", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "CMT" - }, - { - "description": "1 Zilliqa", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "ZIL" - }, - { - "description": "1 IOSToken", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "IOST" - }, - { - "description": "1 VeChain", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "VEN" - }, - { - "description": "1 Cortex", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "CTXC" - }, - { - "description": "1 Binance Coin", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "BNB" - }, - { - "description": "1 Bytom", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "BTM" - }, - { - "description": "1 aelf", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "ELF" - }, - { - "description": "1 OmiseGO", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "OMG" - }, - { - "description": "1 Nebulas", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "NAS" - }, - { - "description": "1 ICON", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "ICX" - }, - { - "description": "1 Status", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "SNT" - }, - { - "description": "1 Storm", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "STORM" - }, - { - "description": "1 Populous", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "PPT" - }, - { - "description": "1 Aeternity", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "AE" - }, - { - "description": "1 Loopring", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "LRC" - }, - { - "description": "1 Mithril", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "MITH" - }, - { - "description": "1 Nexo", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "NEXO" - }, - { - "description": "1 Monaco", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "MCO" - }, - { - "description": "1 Arcblock", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "ABT" - }, - { - "description": "1 Golem", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "GNT" - }, - { - "description": "1 Kyber Network", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "KNC" - }, - { - "description": "1 IHT Real Estate Protocol", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "IHT" - }, - { - "description": "1 All Sports", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "SOC" - }, - { - "description": "1 Time New Bank", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "TNB" - }, - { - "description": "1 Bancor", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "BNT" - }, - { - "description": "1 eosDAC", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "EOSDAC" - }, - { - "description": "1 Nucleus Vision", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "NCASH" - }, - { - "description": "1 Theta Token", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "THETA" - }, - { - "description": "1 Loom Network", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "LOOM" - }, - { - "description": "1 Civic", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "CVC" - }, - { - "description": "1 Gifto", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "GTO" - }, - { - "description": "1 Enigma", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "ENG" - }, - { - "description": "1 Game.com", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "GTC" - }, - { - "description": "1 Fusion", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "FSN" - }, - { - "description": "1 Basic Attention Token", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "BAT" - }, - { - "description": "1 Power Ledger", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "POWR" - }, - { - "description": "1 Waltonchain", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "WTC" - }, - { - "description": "1 FunFair", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "FUN" - }, - { - "description": "1 TenX", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "PAY" - }, - { - "description": "1 Storj", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "STORJ" - }, - { - "description": "1 Nuls", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "NULS" - }, - { - "description": "1 Polymath", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "POLY" - }, - { - "description": "1 Ethos", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "ETHOS" - }, - { - "description": "1 High Performance Blockchain", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "HPB" - }, - { - "description": "1 Augur", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "REP" - }, - { - "description": "1 Ink", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "INK" - }, - { - "description": "1 Ruff", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "RUFF" - }, - { - "description": "1 Gas", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "GAS" - }, - { - "description": "1 SALT", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "SALT" - }, - { - "description": "1 Substratum", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "SUB" - }, - { - "description": "1 Bluzelle", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "BLZ" - }, - { - "description": "1 Decentraland", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "MANA" - }, - { - "description": "1 Aion", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "AION" - }, - { - "description": "1 Bottos", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "BTO" - }, - { - "description": "1 Holo", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "HOT" - }, - { - "description": "1 Credits", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "CS" - }, - { - "description": "1 DeepBrain Chain", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "DBC" - }, - { - "description": "1 Quantstamp", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "QSP" - }, - { - "description": "1 BnkToTheFuture", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "BFT" - }, - { - "description": "1 Enjin Coin", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "ENJ" - }, - { - "description": "1 MaidSafeCoin", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "SAFE" - }, - { - "description": "1 WAX", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "WAX" - }, - { - "description": "1 iExec RLC", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "RLC" - }, - { - "description": "1 Dent", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "DENT" - }, - { - "description": "1 Dragonchain", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "DRGN" - }, - { - "description": "1 SmartMesh", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "SMT" - }, - { - "description": "1 Matrix AI Network", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "MAN" - }, - { - "description": "1 Delphy", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "DPY" - }, - { - "description": "1 Revain", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "R" - }, - { - "description": "1 DigixDAO", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "DGD" - }, - { - "description": "1 QASH", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "QASH" - }, - { - "description": "1 Crypterium", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "CRPT" - }, - { - "description": "1 SONM", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "SNM" - }, - { - "description": "1 Request Network", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "REQ" - }, - { - "description": "1 Ignis", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "IGNIS" - }, - { - "description": "1 Scry.info", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "DDD" - }, - { - "description": "1 ChainLink", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "LINK" - }, - { - "description": "1 Veritaseum", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "VERI" - }, - { - "description": "1 Maker", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "MKR" - }, - { - "description": "1 Kin", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "KIN" - }, - { - "description": "1 Cindicator", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "CND" - }, - { - "description": "1 MediBloc", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "MED" - }, - { - "description": "1 SophiaTX", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "SPHTX" - }, - { - "description": "1 Gnosis", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "GNO" - }, - { - "description": "1 RChain", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "RHOC" - }, - { - "description": "1 Iconomi", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "ICN" - }, - { - "description": "1 Mixin", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "XIN" - }, - { - "description": "1 Aragon", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "ANT" - }, - { - "description": "1 Dentacoin", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "DCN" - }, - { - "description": "1 Centrality", - "is_bitasset": true, - "issuer_name": "localcoin-wallet", - "max_supply": "1000000000000000", - "precision": 8, - "symbol": "CENNZ" - } - ], - - "initial_balances": [{ - "owner": "LLCJBqPxC8R6H4KdRPSxbs999XyobsZXTyPa", - "asset_symbol": "LLC", - "amount": "80000000000000" - }, - { - "owner": "LLCHnjug7KJG84jg8qoG5SVa9XDqfDm8cBkx", - "asset_symbol": "LLC", - "amount": "20000000000000" - }, - { - "owner": "LLC6f3FN251kWo8gQKrTwtSb1R8Tvt6w2B3H", - "asset_symbol": "LLC", - "amount": "10000000000000" - } - ], - "initial_vesting_balances": [], - "initial_active_witnesses": 8, - "initial_witness_candidates": [{ - "owner_name": "notteler", - "block_signing_key": "LLC6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - }, { - "owner_name": "germut", - "block_signing_key": "LLC6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - }, { - "owner_name": "localcoin-ico", - "block_signing_key": "LLC6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - }, { - "owner_name": "localcoin", - "block_signing_key": "LLC6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - }, { - "owner_name": "localcoin-wallet", - "block_signing_key": "LLC6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - }, { - "owner_name": "localcoin-fiat", - "block_signing_key": "LLC6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - }, { - "owner_name": "localcoin-otc", - "block_signing_key": "LLC6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - }, { - "owner_name": "localcoin-feed", - "block_signing_key": "LLC6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - }], - "initial_committee_candidates": [{ - "owner_name": "notteler" - }, { - "owner_name": "germut" - }, { - "owner_name": "localcoin-ico" - }, { - "owner_name": "localcoin" - }, { - "owner_name": "localcoin-wallet" - }, { - "owner_name": "localcoin-fiat" - }, { - "owner_name": "localcoin-otc" - }, { - "owner_name": "localcoin-feed" - }], - "initial_worker_candidates": [], - "initial_chain_id": "aa34045518f1469a28fa4578240d5f039afa9959c0b95ce3b39674efa691fb21", - "immutable_parameters": { - "min_committee_member_count": 7, - "min_witness_count": 7, - "num_special_accounts": 0, - "num_special_assets": 0 - } -} \ No newline at end of file diff --git a/testnet-shared-accounts.txt b/testnet-shared-accounts.txt deleted file mode 100644 index 99392365..00000000 --- a/testnet-shared-accounts.txt +++ /dev/null @@ -1,556 +0,0 @@ - "initial_accounts": [{ - "name": "init0", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init1", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init2", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init3", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init4", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init5", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init6", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init7", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init8", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init9", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init10", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init11", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init12", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init13", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init14", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init15", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init16", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init17", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init18", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init19", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init20", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init21", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init22", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init23", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init24", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init25", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init26", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init27", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init28", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init29", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init30", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init31", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init32", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init33", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init34", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init35", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init36", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init37", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init38", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init39", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init40", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init41", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init42", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init43", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init44", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init45", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init46", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init47", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init48", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init49", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init50", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init51", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init52", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init53", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init54", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init55", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init56", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init57", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init58", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init59", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init60", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init61", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init62", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init63", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init64", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init65", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init66", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init67", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init68", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init69", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init70", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init71", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init72", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init73", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init74", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init75", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init76", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init77", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init78", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init79", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init80", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init81", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init82", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init83", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init84", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init85", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init86", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init87", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init88", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init89", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init90", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init91", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init92", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init93", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init94", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init95", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init96", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init97", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init98", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init99", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "init100", - "owner_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "active_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", - "is_lifetime_member": true - },{ - "name": "dummy0", - "owner_key": "BTS6qkMe8pHmQ4zUetLV1bbVKoQJYTNb1fSUbkQzuzpscYhonWpgk", - "active_key": "BTS6qkMe8pHmQ4zUetLV1bbVKoQJYTNb1fSUbkQzuzpscYhonWpgk", - "is_lifetime_member": true - },{ - "name": "dummy1", - "owner_key": "BTS7wXsTzBBR2QEetjrgxcSmN7Kuzey3RAzQWNNHwbPQsKYxkP6fp", - "active_key": "BTS7wXsTzBBR2QEetjrgxcSmN7Kuzey3RAzQWNNHwbPQsKYxkP6fp", - "is_lifetime_member": true - },{ - "name": "dummy2", - "owner_key": "BTS7rzifzfJxS8RWhev9aU8HDYoJi1EGwJRHG9B2fJKxnZAiF2Rsh", - "active_key": "BTS7rzifzfJxS8RWhev9aU8HDYoJi1EGwJRHG9B2fJKxnZAiF2Rsh", - "is_lifetime_member": true - },{ - "name": "dummy3", - "owner_key": "BTS6QZdcwFEFMtHsfW27YBGTv9KLaLTvgx5wgGrPHeUxDTrYEQJ2d", - "active_key": "BTS6QZdcwFEFMtHsfW27YBGTv9KLaLTvgx5wgGrPHeUxDTrYEQJ2d", - "is_lifetime_member": true - },{ - "name": "dummy4", - "owner_key": "BTS7q5MqhSP2a6CRTWaJk77ZcGdpnv14JbT4cVzbXaoAsWJoCxFJG", - "active_key": "BTS7q5MqhSP2a6CRTWaJk77ZcGdpnv14JbT4cVzbXaoAsWJoCxFJG", - "is_lifetime_member": true - },{ - "name": "dummy5", - "owner_key": "BTS5sRXxgDCnteHLUS623xtxJM5WKKVygwDMzEso6LigwxvprJqBA", - "active_key": "BTS5sRXxgDCnteHLUS623xtxJM5WKKVygwDMzEso6LigwxvprJqBA", - "is_lifetime_member": true - },{ - "name": "dummy6", - "owner_key": "BTS5V4HEQJbVbMjUWASeknQ42NT3NP9bZaygt83XMuvy6v4QMJuSP", - "active_key": "BTS5V4HEQJbVbMjUWASeknQ42NT3NP9bZaygt83XMuvy6v4QMJuSP", - "is_lifetime_member": true - },{ - "name": "dummy7", - "owner_key": "BTS86ukuPAufzKouerZf1dCxjVSmxQPA5kLwvnYEjn9GRqi5qXBop", - "active_key": "BTS86ukuPAufzKouerZf1dCxjVSmxQPA5kLwvnYEjn9GRqi5qXBop", - "is_lifetime_member": true - },{ - "name": "dummy8", - "owner_key": "BTS7Sdg3kQuz2pPT8mA8Yr3mkBe7zr6293mnBmoR36z9xxtRdiMmJ", - "active_key": "BTS7Sdg3kQuz2pPT8mA8Yr3mkBe7zr6293mnBmoR36z9xxtRdiMmJ", - "is_lifetime_member": true - },{ - "name": "dummy9", - "owner_key": "BTS5WCj1mMiiqEE4QRs7xhaFfSaiFroejUp3GuZE9wvfue9nxhPPn", - "active_key": "BTS5WCj1mMiiqEE4QRs7xhaFfSaiFroejUp3GuZE9wvfue9nxhPPn", - "is_lifetime_member": true - },{ diff --git a/testnet-shared-balances.txt b/testnet-shared-balances.txt deleted file mode 100644 index dc9061fa..00000000 --- a/testnet-shared-balances.txt +++ /dev/null @@ -1,41 +0,0 @@ - "initial_balances": [{ - "owner": "BTSHYhQcrjVg5kBzCoeeD38eQdncCC5pBgee", - "asset_symbol": "CORE", - "amount": 100000000000 - },{ - "owner": "BTSPgQZg5929ht1NBdEvsGKqoQ7buRu3nKf4", - "asset_symbol": "CORE", - "amount": 100000000000 - },{ - "owner": "BTSC9zrLXSAPUQaVmQPk1S9dMqSzT7jPqYU7", - "asset_symbol": "CORE", - "amount": 100000000000 - },{ - "owner": "BTS93aQPtbbkXwaSjtHaREsNVcCvbfHo93aZ", - "asset_symbol": "CORE", - "amount": 100000000000 - },{ - "owner": "BTS6RM4UfsYFPDuhbmgkvDS9ip8Kvqundvyk", - "asset_symbol": "CORE", - "amount": 100000000000 - },{ - "owner": "BTSNVkZXdqWWSzqHVxvfetMe347is6kEkC4K", - "asset_symbol": "CORE", - "amount": 100000000000 - },{ - "owner": "BTS5GHzWZ64Luoajqsz6JGjTKVMgWYkGV9SQ", - "asset_symbol": "CORE", - "amount": 100000000000 - },{ - "owner": "BTSDCVRFez92bW9doRLjnFCKLJnpM58mgmMb", - "asset_symbol": "CORE", - "amount": 100000000000 - },{ - "owner": "BTS5CCdX3JYLBptYMuCjbsezqGYzN9vG9JCu", - "asset_symbol": "CORE", - "amount": 100000000000 - },{ - "owner": "BTSEQ3yQdr3EMDL2eRqGiceMCpoanaW16Puw", - "asset_symbol": "CORE", - "amount": 100000000000 - },{ diff --git a/testnet-shared-committee-members.txt b/testnet-shared-committee-members.txt deleted file mode 100644 index 7d7ae11b..00000000 --- a/testnet-shared-committee-members.txt +++ /dev/null @@ -1,204 +0,0 @@ - "initial_committee_candidates": [{ - "owner_name": "init0" - },{ - "owner_name": "init1" - },{ - "owner_name": "init2" - },{ - "owner_name": "init3" - },{ - "owner_name": "init4" - },{ - "owner_name": "init5" - },{ - "owner_name": "init6" - },{ - "owner_name": "init7" - },{ - "owner_name": "init8" - },{ - "owner_name": "init9" - },{ - "owner_name": "init10" - },{ - "owner_name": "init11" - },{ - "owner_name": "init12" - },{ - "owner_name": "init13" - },{ - "owner_name": "init14" - },{ - "owner_name": "init15" - },{ - "owner_name": "init16" - },{ - "owner_name": "init17" - },{ - "owner_name": "init18" - },{ - "owner_name": "init19" - },{ - "owner_name": "init20" - },{ - "owner_name": "init21" - },{ - "owner_name": "init22" - },{ - "owner_name": "init23" - },{ - "owner_name": "init24" - },{ - "owner_name": "init25" - },{ - "owner_name": "init26" - },{ - "owner_name": "init27" - },{ - "owner_name": "init28" - },{ - "owner_name": "init29" - },{ - "owner_name": "init30" - },{ - "owner_name": "init31" - },{ - "owner_name": "init32" - },{ - "owner_name": "init33" - },{ - "owner_name": "init34" - },{ - "owner_name": "init35" - },{ - "owner_name": "init36" - },{ - "owner_name": "init37" - },{ - "owner_name": "init38" - },{ - "owner_name": "init39" - },{ - "owner_name": "init40" - },{ - "owner_name": "init41" - },{ - "owner_name": "init42" - },{ - "owner_name": "init43" - },{ - "owner_name": "init44" - },{ - "owner_name": "init45" - },{ - "owner_name": "init46" - },{ - "owner_name": "init47" - },{ - "owner_name": "init48" - },{ - "owner_name": "init49" - },{ - "owner_name": "init50" - },{ - "owner_name": "init51" - },{ - "owner_name": "init52" - },{ - "owner_name": "init53" - },{ - "owner_name": "init54" - },{ - "owner_name": "init55" - },{ - "owner_name": "init56" - },{ - "owner_name": "init57" - },{ - "owner_name": "init58" - },{ - "owner_name": "init59" - },{ - "owner_name": "init60" - },{ - "owner_name": "init61" - },{ - "owner_name": "init62" - },{ - "owner_name": "init63" - },{ - "owner_name": "init64" - },{ - "owner_name": "init65" - },{ - "owner_name": "init66" - },{ - "owner_name": "init67" - },{ - "owner_name": "init68" - },{ - "owner_name": "init69" - },{ - "owner_name": "init70" - },{ - "owner_name": "init71" - },{ - "owner_name": "init72" - },{ - "owner_name": "init73" - },{ - "owner_name": "init74" - },{ - "owner_name": "init75" - },{ - "owner_name": "init76" - },{ - "owner_name": "init77" - },{ - "owner_name": "init78" - },{ - "owner_name": "init79" - },{ - "owner_name": "init80" - },{ - "owner_name": "init81" - },{ - "owner_name": "init82" - },{ - "owner_name": "init83" - },{ - "owner_name": "init84" - },{ - "owner_name": "init85" - },{ - "owner_name": "init86" - },{ - "owner_name": "init87" - },{ - "owner_name": "init88" - },{ - "owner_name": "init89" - },{ - "owner_name": "init90" - },{ - "owner_name": "init91" - },{ - "owner_name": "init92" - },{ - "owner_name": "init93" - },{ - "owner_name": "init94" - },{ - "owner_name": "init95" - },{ - "owner_name": "init96" - },{ - "owner_name": "init97" - },{ - "owner_name": "init98" - },{ - "owner_name": "init99" - },{ - "owner_name": "init100" - } - ], diff --git a/testnet-shared-private-keys.txt b/testnet-shared-private-keys.txt deleted file mode 100644 index e2a8d7dd..00000000 --- a/testnet-shared-private-keys.txt +++ /dev/null @@ -1,10 +0,0 @@ -5KCNDLVGqvX8p3GcMFun9sMe6XbMvycVTm4bGrkB5aZGWCbAAtr -5HvFQ1bcAWk8H1A2qXj1AqSNp93GUAb6b2w5TVfLb1jWL6yNF3f -5JSxv2kgaBSm9nGseRNhLhgEKTBmoKJ5CkgLbbk5RW4RBCNsLJC -5K5E2TQtrodDFzsqPq3oVFi9rVX15AN8sLE3iTHfVsX1b49y49J -5HxC3fwN7VDZXKVkbbX3SzCczh18Fetx8TXBfJ3z3ovDUSPKvVd -5KSr4w978PDanQDYtftarcfJVvGe4wedYb1sYbdH6HNpi15heRa -5Kan4si6qWvDVpZuqug4c6KQH4zkvDhwspaGQiFKYniJv6qji6t -5KcZri5DDsMcDp1DjNeMkZSijkWurPoAoR7gBKTnnetNQ9CpXoJ -5K5TRZyEhC6GPgi57t5FhiSMRGVTHEbwXngbBEtCA41gM8LPFhF -5KXVG4oP4Vj3RawRpta79UFAg7pWp17FGf4DnrKfkr69ELytDMv diff --git a/testnet-shared-vesting-balances.txt b/testnet-shared-vesting-balances.txt deleted file mode 100644 index 1dd00230..00000000 --- a/testnet-shared-vesting-balances.txt +++ /dev/null @@ -1,71 +0,0 @@ - "initial_vesting_balances": [{ - "owner": "BTSHYhQcrjVg5kBzCoeeD38eQdncCC5pBgee", - "asset_symbol": "BTS", - "amount": 50000000000, - "begin_timestamp": "2014-11-06T00:00:00", - "vesting_duration_seconds": 63072000, - "begin_balance": 50000000000 - },{ - "owner": "BTSPgQZg5929ht1NBdEvsGKqoQ7buRu3nKf4", - "asset_symbol": "BTS", - "amount": 50000000000, - "begin_timestamp": "2014-11-06T00:00:00", - "vesting_duration_seconds": 63072000, - "begin_balance": 50000000000 - },{ - "owner": "BTSC9zrLXSAPUQaVmQPk1S9dMqSzT7jPqYU7", - "asset_symbol": "BTS", - "amount": 50000000000, - "begin_timestamp": "2014-11-06T00:00:00", - "vesting_duration_seconds": 63072000, - "begin_balance": 50000000000 - },{ - "owner": "BTS93aQPtbbkXwaSjtHaREsNVcCvbfHo93aZ", - "asset_symbol": "BTS", - "amount": 50000000000, - "begin_timestamp": "2014-11-06T00:00:00", - "vesting_duration_seconds": 63072000, - "begin_balance": 50000000000 - },{ - "owner": "BTS6RM4UfsYFPDuhbmgkvDS9ip8Kvqundvyk", - "asset_symbol": "BTS", - "amount": 50000000000, - "begin_timestamp": "2014-11-06T00:00:00", - "vesting_duration_seconds": 63072000, - "begin_balance": 50000000000 - },{ - "owner": "BTSNVkZXdqWWSzqHVxvfetMe347is6kEkC4K", - "asset_symbol": "BTS", - "amount": 50000000000, - "begin_timestamp": "2014-11-06T00:00:00", - "vesting_duration_seconds": 63072000, - "begin_balance": 50000000000 - },{ - "owner": "BTS5GHzWZ64Luoajqsz6JGjTKVMgWYkGV9SQ", - "asset_symbol": "BTS", - "amount": 50000000000, - "begin_timestamp": "2014-11-06T00:00:00", - "vesting_duration_seconds": 63072000, - "begin_balance": 50000000000 - },{ - "owner": "BTSDCVRFez92bW9doRLjnFCKLJnpM58mgmMb", - "asset_symbol": "BTS", - "amount": 50000000000, - "begin_timestamp": "2014-11-06T00:00:00", - "vesting_duration_seconds": 63072000, - "begin_balance": 50000000000 - },{ - "owner": "BTS5CCdX3JYLBptYMuCjbsezqGYzN9vG9JCu", - "asset_symbol": "BTS", - "amount": 50000000000, - "begin_timestamp": "2014-11-06T00:00:00", - "vesting_duration_seconds": 63072000, - "begin_balance": 50000000000 - },{ - "owner": "BTSEQ3yQdr3EMDL2eRqGiceMCpoanaW16Puw", - "asset_symbol": "BTS", - "amount": 50000000000, - "begin_timestamp": "2014-11-06T00:00:00", - "vesting_duration_seconds": 63072000, - "begin_balance": 50000000000 - },{ diff --git a/testnet-shared-witnesses.txt b/testnet-shared-witnesses.txt deleted file mode 100644 index c09b1329..00000000 --- a/testnet-shared-witnesses.txt +++ /dev/null @@ -1,304 +0,0 @@ - "initial_witness_candidates": [{ - "owner_name": "init0", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init1", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init2", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init3", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init4", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init5", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init6", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init7", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init8", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init9", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init10", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init11", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init12", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init13", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init14", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init15", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init16", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init17", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init18", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init19", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init20", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init21", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init22", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init23", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init24", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init25", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init26", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init27", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init28", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init29", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init30", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init31", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init32", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init33", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init34", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init35", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init36", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init37", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init38", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init39", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init40", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init41", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init42", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init43", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init44", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init45", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init46", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init47", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init48", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init49", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init50", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init51", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init52", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init53", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init54", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init55", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init56", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init57", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init58", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init59", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init60", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init61", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init62", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init63", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init64", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init65", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init66", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init67", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init68", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init69", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init70", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init71", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init72", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init73", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init74", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init75", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init76", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init77", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init78", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init79", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init80", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init81", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init82", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init83", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init84", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init85", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init86", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init87", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init88", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init89", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init90", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init91", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init92", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init93", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init94", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init95", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init96", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init97", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init98", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init99", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ - "owner_name": "init100", - "block_signing_key": "GPH6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" - },{ diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 5b19d9d8..81aee8b7 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -23,10 +23,10 @@ target_link_libraries( chain_bench graphene_chain graphene_app graphene_account_ file(GLOB APP_SOURCES "app/*.cpp") add_executable( app_test ${APP_SOURCES} ) -target_link_libraries( app_test graphene_app graphene_account_history graphene_net graphene_witness graphene_chain graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} ) +target_link_libraries( app_test graphene_app graphene_account_history graphene_net graphene_witness graphene_activenode graphene_chain graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} ) file(GLOB CLI_SOURCES "cli/*.cpp") add_executable( cli_test ${CLI_SOURCES} ) -target_link_libraries( cli_test graphene_app graphene_wallet graphene_witness graphene_account_history graphene_net graphene_chain graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} ) +target_link_libraries( cli_test graphene_app graphene_wallet graphene_witness graphene_activenode graphene_account_history graphene_net graphene_chain graphene_egenesis_none fc ${PLATFORM_SPECIFIC_LIBS} ) add_subdirectory( generate_empty_blocks ) diff --git a/tests/common/database_fixture.cpp b/tests/common/database_fixture.cpp index bac16f18..1423c9c8 100644 --- a/tests/common/database_fixture.cpp +++ b/tests/common/database_fixture.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include diff --git a/tests/gateis_manual_tests/activenode.scenario b/tests/gateis_manual_tests/activenode.scenario new file mode 100644 index 00000000..1f232c70 --- /dev/null +++ b/tests/gateis_manual_tests/activenode.scenario @@ -0,0 +1,12 @@ +# we can become activenode + +# we can become activenode with only 511 LLC + +# we can't become activenode with 510 LLC + + +# we send send_activity operation and operation is included in block + + +# AN gets reward + + +# first we send activity, then we delete nodes and give out rewards + +# if AN doesn't have 500 LLC after sending activity - we delete account + + +# we can get AN info + \ No newline at end of file diff --git a/tests/tests/activenodes_tests.cpp b/tests/tests/activenodes_tests.cpp new file mode 100644 index 00000000..e69de29b