From 46906700318c5361f0e04a7639bfe2ba01b7564c Mon Sep 17 00:00:00 2001 From: Neozaru Date: Fri, 16 May 2014 00:21:43 +0200 Subject: Added 'save_bc' command in daemon for saving blockchain remotely --- src/simplewallet/simplewallet.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'src/simplewallet/simplewallet.cpp') diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 919782ab6..0f84b81de 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -181,6 +181,7 @@ simple_wallet::simple_wallet() { m_cmd_binder.set_handler("start_mining", boost::bind(&simple_wallet::start_mining, this, _1), "start_mining [] - Start mining in daemon"); m_cmd_binder.set_handler("stop_mining", boost::bind(&simple_wallet::stop_mining, this, _1), "Stop mining in daemon"); + m_cmd_binder.set_handler("save_bc", boost::bind(&simple_wallet::save_bc, this, _1), "Save current blockchain data"); m_cmd_binder.set_handler("refresh", boost::bind(&simple_wallet::refresh, this, _1), "Resynchronize transactions and balance"); m_cmd_binder.set_handler("balance", boost::bind(&simple_wallet::show_balance, this, _1), "Show current wallet balance"); m_cmd_binder.set_handler("incoming_transfers", boost::bind(&simple_wallet::show_incoming_transfers, this, _1), "incoming_transfers [available|unavailable] - Show incoming transfers - all of them or filter them by availability"); @@ -491,6 +492,22 @@ bool simple_wallet::stop_mining(const std::vector& args) return true; } //---------------------------------------------------------------------------------------------------- +bool simple_wallet::save_bc(const std::vector& args) +{ + if (!try_connect_to_daemon()) + return true; + + COMMAND_RPC_SAVE_BC::request req; + COMMAND_RPC_SAVE_BC::response res; + bool r = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/save_bc", req, res, m_http_client); + std::string err = interpret_rpc_response(r, res.status); + if (err.empty()) + success_msg_writer() << "Blockchain saved"; + else + fail_msg_writer() << "Blockchain can't be saved: " << err; + return true; +} +//---------------------------------------------------------------------------------------------------- void simple_wallet::on_new_block(uint64_t height, const cryptonote::block& block) { m_refresh_progress_reporter.update(height, false); -- cgit v1.2.3 From 3a3a8176782a4fa75b0607fba0393c9d4a1746be Mon Sep 17 00:00:00 2001 From: mydesktop Date: Sun, 25 May 2014 13:06:40 -0400 Subject: 0.8.8update --- .gitignore | 2 +- CMakeLists.txt | 6 +- ReleaseNotes.txt | 15 +- contrib/epee/include/console_handler.h | 17 -- contrib/epee/include/net/abstract_tcp_server2.inl | 4 +- contrib/epee/include/net/http_protocol_handler.h | 45 +++-- .../epee/include/net/http_server_handlers_map2.h | 99 +---------- contrib/epee/include/net/net_utils_base.h | 17 +- contrib/epee/include/profile_tools.h | 10 +- .../include/serialization/keyvalue_serialization.h | 6 +- contrib/epee/include/storages/portable_storage.h | 24 +-- .../storages/portable_storage_template_helper.h | 11 +- .../include/storages/portable_storage_to_json.h | 59 ++++--- contrib/epee/include/string_tools.h | 1 + src/crypto/oaes_lib.c | 1 - src/crypto/oaes_lib.h | 23 ++- src/cryptonote_config.h | 6 +- src/cryptonote_core/blockchain_storage.cpp | 139 +++++++++------ src/cryptonote_core/blockchain_storage.h | 12 +- src/cryptonote_core/checkpoints.cpp | 26 ++- src/cryptonote_core/checkpoints.h | 3 + src/cryptonote_core/checkpoints_create.h | 9 +- src/cryptonote_core/cryptonote_core.cpp | 2 +- src/cryptonote_core/cryptonote_core.h | 4 +- src/cryptonote_core/cryptonote_format_utils.cpp | 3 +- src/cryptonote_core/miner.h | 13 +- src/cryptonote_core/tx_extra.h | 1 - src/cryptonote_core/tx_pool.h | 2 - .../cryptonote_protocol_handler.h | 4 +- .../cryptonote_protocol_handler.inl | 25 +-- src/daemon/daemon_commands_handler.h | 49 +++++- src/p2p/net_node.h | 25 ++- src/p2p/net_node.inl | 194 +++++++++++++-------- src/rpc/core_rpc_server.cpp | 4 +- src/serialization/crypto.h | 2 + src/serialization/serialization.h | 6 +- src/simplewallet/simplewallet.cpp | 10 +- src/simplewallet/simplewallet.h | 2 +- src/version.h.in | 2 +- src/wallet/wallet2.cpp | 4 +- src/wallet/wallet2.h | 6 +- tests/core_tests/chaingen_main.cpp | 12 +- tests/performance_tests/main.cpp | 3 + 43 files changed, 502 insertions(+), 406 deletions(-) (limited to 'src/simplewallet/simplewallet.cpp') diff --git a/.gitignore b/.gitignore index 554267b09..20a3894a6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ .DS_Store /build -/tags \ No newline at end of file +/tags diff --git a/CMakeLists.txt b/CMakeLists.txt index e1c2586c5..28130e566 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,8 +81,8 @@ else() set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${DEBUG_FLAGS}") set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${RELEASE_FLAGS}") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${RELEASE_FLAGS}") - if(STATIC) - set_static_flags() + if(STATIC AND NOT APPLE) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++") endif() endif() @@ -90,7 +90,7 @@ if(STATIC) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_STATIC_RUNTIME ON) endif() -find_package(Boost 1.53 REQUIRED COMPONENTS system filesystem thread date_time chrono regex serialization atomic program_options) +find_package(Boost 1.53 REQUIRED COMPONENTS system filesystem thread date_time chrono regex serialization program_options) if((${Boost_MAJOR_VERSION} EQUAL 1) AND (${Boost_MINOR_VERSION} EQUAL 54)) message(SEND_ERROR "Boost version 1.54 is unsupported, more details are available here http://goo.gl/RrCFmA") endif() diff --git a/ReleaseNotes.txt b/ReleaseNotes.txt index 3aa32a238..2edc278a9 100644 --- a/ReleaseNotes.txt +++ b/ReleaseNotes.txt @@ -1,5 +1,18 @@ Bitmonero +Release notes 0.8.8 + +- JSON RPC v2.0 compatibility +- JSON RPC over TCP added- Further optimizations +- Fixed a bug with checkpoints behavior +- UI improvements for daemon +- Fixed COIN value (10^12) +- Raised minimum fee to (1/2) * (10^10) + +Release notes 0.8.7 + +- Slow hash optimizations + Release notes 0.8.6 - Simplwallet can set extra for transfers @@ -34,4 +47,4 @@ Release notes 0.8.2 Release notes 0.8.1 -Bytecoin project is moved to GitHub \ No newline at end of file +Bytecoin project is moved to GitHub diff --git a/contrib/epee/include/console_handler.h b/contrib/epee/include/console_handler.h index 5798d2def..fcab35aaa 100644 --- a/contrib/epee/include/console_handler.h +++ b/contrib/epee/include/console_handler.h @@ -267,23 +267,6 @@ namespace epee if(0 == command.compare("exit") || 0 == command.compare("q")) { continue_handle = false; - }else if (!command.compare(0, 7, "set_log")) - { - //parse set_log command - if(command.size() != 9) - { - std::cout << "wrong syntax: " << command << std::endl << "use set_log n" << std::endl; - continue; - } - uint16_t n = 0; - if(!string_tools::get_xtype_from_string(n, command.substr(8, 1))) - { - std::cout << "wrong syntax: " << command << std::endl << "use set_log n" << std::endl; - continue; - } - log_space::get_set_log_detalisation_level(true, n); - std::cout << "New log level set " << n; - LOG_PRINT_L2("New log level set " << n); }else if (command.empty()) { continue; diff --git a/contrib/epee/include/net/abstract_tcp_server2.inl b/contrib/epee/include/net/abstract_tcp_server2.inl index 2a4b10e48..403f5a3bd 100644 --- a/contrib/epee/include/net/abstract_tcp_server2.inl +++ b/contrib/epee/include/net/abstract_tcp_server2.inl @@ -52,11 +52,11 @@ PRAGMA_WARNING_DISABLE_VS(4355) typename t_protocol_handler::config_type& config, volatile uint32_t& sock_count, i_connection_filter* &pfilter) : strand_(io_service), socket_(io_service), - m_protocol_handler(this, config, context), m_want_close_connection(0), m_was_shutdown(0), m_ref_sockets_count(sock_count), - m_pfilter(pfilter) + m_pfilter(pfilter), + m_protocol_handler(this, config, context) { boost::interprocess::ipcdetail::atomic_inc32(&m_ref_sockets_count); } diff --git a/contrib/epee/include/net/http_protocol_handler.h b/contrib/epee/include/net/http_protocol_handler.h index 4bf48750e..aed909778 100644 --- a/contrib/epee/include/net/http_protocol_handler.h +++ b/contrib/epee/include/net/http_protocol_handler.h @@ -55,20 +55,20 @@ namespace net_utils /************************************************************************/ /* */ /************************************************************************/ - template + template class simple_http_connection_handler { public: - typedef t_connection_context connection_context;//t_connection_context net_utils::connection_context_base connection_context; + typedef t_connection_context connection_context;//t_connection_context net_utils::connection_context_base connection_context; typedef http_server_config config_type; simple_http_connection_handler(i_service_endpoint* psnd_hndlr, config_type& config); virtual ~simple_http_connection_handler(){} - bool release_protocol() - { - return true; - } + bool release_protocol() + { + return true; + } virtual bool thread_init() { @@ -85,10 +85,6 @@ namespace net_utils } virtual bool handle_recv(const void* ptr, size_t cb); virtual bool handle_request(const http::http_request_info& query_info, http_response_info& response); - - - //temporary here - //bool parse_uri(const std::string uri, uri_content& content); private: enum machine_state{ @@ -142,34 +138,37 @@ namespace net_utils i_service_endpoint* m_psnd_hndlr; }; - template + template struct i_http_server_handler { virtual ~i_http_server_handler(){} - virtual bool handle_http_request(const http_request_info& query_info, http_response_info& response, t_connection_context& m_conn_context)=0; - virtual bool init_server_thread(){return true;} + virtual bool handle_http_request(const http_request_info& query_info, + http_response_info& response, + t_connection_context& m_conn_context) = 0; + virtual bool init_server_thread(){return true;} virtual bool deinit_server_thread(){return true;} }; - template + template struct custum_handler_config: public http_server_config { i_http_server_handler* m_phandler; }; - /************************************************************************/ - /* */ - /************************************************************************/ + /************************************************************************/ + /* */ + /************************************************************************/ - template + template class http_custom_handler: public simple_http_connection_handler { public: typedef custum_handler_config config_type; - http_custom_handler(i_service_endpoint* psnd_hndlr, config_type& config, t_connection_context& conn_context):simple_http_connection_handler(psnd_hndlr, config), - m_config(config), - m_conn_context(conn_context) + http_custom_handler(i_service_endpoint* psnd_hndlr, config_type& config, t_connection_context& conn_context) + : simple_http_connection_handler(psnd_hndlr, config), + m_config(config), + m_conn_context(conn_context) {} inline bool handle_request(const http_request_info& query_info, http_response_info& response) { @@ -191,8 +190,8 @@ namespace net_utils { return m_config.m_phandler->deinit_server_thread(); } - void handle_qued_callback() - {} + void handle_qued_callback() + {} bool after_init_connection() { return true; diff --git a/contrib/epee/include/net/http_server_handlers_map2.h b/contrib/epee/include/net/http_server_handlers_map2.h index af4e035f8..201460130 100644 --- a/contrib/epee/include/net/http_server_handlers_map2.h +++ b/contrib/epee/include/net/http_server_handlers_map2.h @@ -26,9 +26,10 @@ #pragma once -#include "serialization/keyvalue_serialization.h" -#include "storages/portable_storage_template_helper.h" #include "http_base.h" +#include "jsonrpc_structs.h" +#include "storages/portable_storage.h" +#include "storages/portable_storage_template_helper.h" #define CHAIN_HTTP_TO_MAP2(context_type) bool handle_http_request(const epee::net_utils::http::http_request_info& query_info, \ @@ -109,98 +110,6 @@ #define END_URI_MAP2() return handled;} - - -namespace epee -{ - namespace json_rpc - { - template - struct request - { - std::string jsonrpc; - std::string method; - epee::serialization::storage_entry id; - t_param params; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(jsonrpc) - KV_SERIALIZE(id) - KV_SERIALIZE(method) - KV_SERIALIZE(params) - END_KV_SERIALIZE_MAP() - }; - - struct error - { - int64_t code; - std::string message; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(code) - KV_SERIALIZE(message) - END_KV_SERIALIZE_MAP() - }; - - struct dummy_error - { - BEGIN_KV_SERIALIZE_MAP() - END_KV_SERIALIZE_MAP() - }; - - struct dummy_result - { - BEGIN_KV_SERIALIZE_MAP() - END_KV_SERIALIZE_MAP() - }; - - template - struct response - { - std::string jsonrpc; - t_param result; - epee::serialization::storage_entry id; - t_error error; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(jsonrpc) - KV_SERIALIZE(id) - KV_SERIALIZE(result) - KV_SERIALIZE(error) - END_KV_SERIALIZE_MAP() - }; - - template - struct response - { - std::string jsonrpc; - t_param result; - epee::serialization::storage_entry id; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(jsonrpc) - KV_SERIALIZE(id) - KV_SERIALIZE(result) - END_KV_SERIALIZE_MAP() - }; - - template - struct response - { - std::string jsonrpc; - t_error error; - epee::serialization::storage_entry id; - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(jsonrpc) - KV_SERIALIZE(id) - KV_SERIALIZE(error) - END_KV_SERIALIZE_MAP() - }; - - typedef response error_response; - } -} - - - - #define BEGIN_JSON_RPC_MAP(uri) else if(query_info.m_URI == uri) \ { \ uint64_t ticks = epee::misc_utils::get_tick_count(); \ @@ -315,6 +224,6 @@ namespace epee rsp.error.message = "Method not found"; \ epee::serialization::store_t_to_json(static_cast(rsp), response_info.m_body); \ return true; \ - } +} diff --git a/contrib/epee/include/net/net_utils_base.h b/contrib/epee/include/net/net_utils_base.h index 793135b87..b5619bab3 100644 --- a/contrib/epee/include/net/net_utils_base.h +++ b/contrib/epee/include/net/net_utils_base.h @@ -47,8 +47,8 @@ namespace net_utils struct connection_context_base { const boost::uuids::uuid m_connection_id; - const uint32_t m_remote_ip; - const uint32_t m_remote_port; + const uint32_t m_remote_ip; + const uint32_t m_remote_port; const bool m_is_income; const time_t m_started; time_t m_last_recv; @@ -56,27 +56,30 @@ namespace net_utils uint64_t m_recv_cnt; uint64_t m_send_cnt; - connection_context_base(boost::uuids::uuid connection_id, long remote_ip, int remote_port, bool is_income, time_t last_recv = 0, time_t last_send = 0, uint64_t recv_cnt = 0, uint64_t send_cnt = 0): + connection_context_base(boost::uuids::uuid connection_id, + long remote_ip, int remote_port, bool is_income, + time_t last_recv = 0, time_t last_send = 0, + uint64_t recv_cnt = 0, uint64_t send_cnt = 0): m_connection_id(connection_id), m_remote_ip(remote_ip), m_remote_port(remote_port), m_is_income(is_income), + m_started(time(NULL)), m_last_recv(last_recv), m_last_send(last_send), m_recv_cnt(recv_cnt), - m_send_cnt(send_cnt), - m_started(time(NULL)) + m_send_cnt(send_cnt) {} connection_context_base(): m_connection_id(), m_remote_ip(0), m_remote_port(0), m_is_income(false), + m_started(time(NULL)), m_last_recv(0), m_last_send(0), m_recv_cnt(0), - m_send_cnt(0), - m_started(time(NULL)) + m_send_cnt(0) {} connection_context_base& operator=(const connection_context_base& a) diff --git a/contrib/epee/include/profile_tools.h b/contrib/epee/include/profile_tools.h index be45feafe..0e1646f60 100644 --- a/contrib/epee/include/profile_tools.h +++ b/contrib/epee/include/profile_tools.h @@ -51,13 +51,13 @@ namespace epee #define PROFILE_FUNC_THIRD(immortal_ptr_str) #endif -#define START_WAY_POINTS() uint64_t _____way_point_time = misc_utils::get_tick_count(); -#define WAY_POINT(name) {uint64_t delta = misc_utils::get_tick_count()-_____way_point_time; LOG_PRINT("Way point " << name << ": " << delta, LOG_LEVEL_2);_____way_point_time = misc_utils::get_tick_count();} -#define WAY_POINT2(name, avrg_obj) {uint64_t delta = misc_utils::get_tick_count()-_____way_point_time; avrg_obj.push(delta); LOG_PRINT("Way point " << name << ": " << delta, LOG_LEVEL_2);_____way_point_time = misc_utils::get_tick_count();} +#define START_WAY_POINTS() uint64_t _____way_point_time = epee::misc_utils::get_tick_count(); +#define WAY_POINT(name) {uint64_t delta = epee::misc_utils::get_tick_count()-_____way_point_time; LOG_PRINT("Way point " << name << ": " << delta, LOG_LEVEL_2);_____way_point_time = misc_utils::get_tick_count();} +#define WAY_POINT2(name, avrg_obj) {uint64_t delta = epee::misc_utils::get_tick_count()-_____way_point_time; avrg_obj.push(delta); LOG_PRINT("Way point " << name << ": " << delta, LOG_LEVEL_2);_____way_point_time = misc_utils::get_tick_count();} -#define TIME_MEASURE_START(var_name) uint64_t var_name = misc_utils::get_tick_count(); -#define TIME_MEASURE_FINISH(var_name) var_name = misc_utils::get_tick_count() - var_name; +#define TIME_MEASURE_START(var_name) uint64_t var_name = epee::misc_utils::get_tick_count(); +#define TIME_MEASURE_FINISH(var_name) var_name = epee::misc_utils::get_tick_count() - var_name; namespace profile_tools { diff --git a/contrib/epee/include/serialization/keyvalue_serialization.h b/contrib/epee/include/serialization/keyvalue_serialization.h index 27fb0f1e2..bf2c8dacd 100644 --- a/contrib/epee/include/serialization/keyvalue_serialization.h +++ b/contrib/epee/include/serialization/keyvalue_serialization.h @@ -31,6 +31,8 @@ #include "misc_log_ex.h" #include "enableable.h" #include "keyvalue_serialization_overloads.h" +#include "serialization/serialization.h" + namespace epee { /************************************************************************/ @@ -41,12 +43,12 @@ public: \ template \ bool store( t_storage& st, typename t_storage::hsection hparent_section = nullptr) const\ {\ - return serialize_map(*this, st, hparent_section);\ + return serialize_map(*this, st, hparent_section);\ }\ template \ bool _load( t_storage& stg, typename t_storage::hsection hparent_section = nullptr)\ {\ - return serialize_map(*this, stg, hparent_section);\ + return serialize_map(*this, stg, hparent_section);\ }\ template \ bool load( t_storage& stg, typename t_storage::hsection hparent_section = nullptr)\ diff --git a/contrib/epee/include/storages/portable_storage.h b/contrib/epee/include/storages/portable_storage.h index c244dac19..bbfe5f85c 100644 --- a/contrib/epee/include/storages/portable_storage.h +++ b/contrib/epee/include/storages/portable_storage.h @@ -83,7 +83,7 @@ namespace epee bool load_from_binary(const binarybuffer& target); template bool dump_as_xml(std::string& targetObj, const std::string& root_name = ""); - bool dump_as_json(std::string& targetObj, size_t indent = 0); + bool dump_as_json(std::string& targetObj, size_t indent = 0, bool insert_newlines = true); bool load_from_json(const std::string& source); private: @@ -106,17 +106,17 @@ namespace epee #pragma pack(pop) }; inline - bool portable_storage::dump_as_json(std::string& buff, size_t indent) + bool portable_storage::dump_as_json(std::string& buff, size_t indent, bool insert_newlines) { TRY_ENTRY(); std::stringstream ss; - epee::serialization::dump_as_json(ss, m_root, indent); + epee::serialization::dump_as_json(ss, m_root, indent, insert_newlines); buff = ss.str(); return true; CATCH_ENTRY("portable_storage::dump_as_json", false) } inline - bool portable_storage::load_from_json(const std::string& source) + bool portable_storage::load_from_json(const std::string& source) { TRY_ENTRY(); return json::load_from_json(source, *this); @@ -124,13 +124,13 @@ namespace epee } template - bool portable_storage::dump_as_xml(std::string& targetObj, const std::string& root_name) + bool portable_storage::dump_as_xml(std::string& targetObj, const std::string& root_name) { return false;//TODO: don't think i ever again will use xml - ambiguous and "overtagged" format } inline - bool portable_storage::store_to_binary(binarybuffer& target) + bool portable_storage::store_to_binary(binarybuffer& target) { TRY_ENTRY(); std::stringstream ss; @@ -145,7 +145,7 @@ namespace epee CATCH_ENTRY("portable_storage::store_to_binary", false) } inline - bool portable_storage::load_from_binary(const binarybuffer& source) + bool portable_storage::load_from_binary(const binarybuffer& source) { m_root.m_entries.clear(); if(source.size() < sizeof(storage_block_header)) @@ -174,7 +174,7 @@ namespace epee } //--------------------------------------------------------------------------------------------------------------- inline - hsection portable_storage::open_section(const std::string& section_name, hsection hparent_section, bool create_if_notexist) + hsection portable_storage::open_section(const std::string& section_name, hsection hparent_section, bool create_if_notexist) { TRY_ENTRY(); hparent_section = hparent_section ? hparent_section:&m_root; @@ -238,7 +238,7 @@ namespace epee } //--------------------------------------------------------------------------------------------------------------- template - bool portable_storage::set_value(const std::string& value_name, const t_value& v, hsection hparent_section) + bool portable_storage::set_value(const std::string& value_name, const t_value& v, hsection hparent_section) { BOOST_MPL_ASSERT(( boost::mpl::contains::type, t_value> )); TRY_ENTRY(); @@ -345,7 +345,7 @@ namespace epee template - bool portable_storage::get_next_value(harray hval_array, t_value& target) + bool portable_storage::get_next_value(harray hval_array, t_value& target) { BOOST_MPL_ASSERT(( boost::mpl::contains )); //TRY_ENTRY(); @@ -462,7 +462,7 @@ namespace epee } //--------------------------------------------------------------------------------------------------------------- inline - bool portable_storage::insert_next_section(harray hsec_array, hsection& hinserted_childsection) + bool portable_storage::insert_next_section(harray hsec_array, hsection& hinserted_childsection) { TRY_ENTRY(); CHECK_AND_ASSERT(hsec_array, false); @@ -476,4 +476,4 @@ namespace epee } //--------------------------------------------------------------------------------------------------------------- } -} \ No newline at end of file +} diff --git a/contrib/epee/include/storages/portable_storage_template_helper.h b/contrib/epee/include/storages/portable_storage_template_helper.h index 2163cb879..008f44321 100644 --- a/contrib/epee/include/storages/portable_storage_template_helper.h +++ b/contrib/epee/include/storages/portable_storage_template_helper.h @@ -25,6 +25,9 @@ // #pragma once + +#include + #include "parserse_base_utils.h" #include "portable_storage.h" #include "file_io_utils.h" @@ -56,19 +59,19 @@ namespace epee } //----------------------------------------------------------------------------------------------------------- template - bool store_t_to_json(t_struct& str_in, std::string& json_buff, size_t indent = 0) + bool store_t_to_json(t_struct& str_in, std::string& json_buff, size_t indent = 0, bool insert_newlines = true) { portable_storage ps; str_in.store(ps); - ps.dump_as_json(json_buff, indent); + ps.dump_as_json(json_buff, indent, insert_newlines); return true; } //----------------------------------------------------------------------------------------------------------- template - std::string store_t_to_json(t_struct& str_in, size_t indent = 0) + std::string store_t_to_json(t_struct& str_in, size_t indent = 0, bool insert_newlines = true) { std::string json_buff; - store_t_to_json(str_in, json_buff, indent); + store_t_to_json(str_in, json_buff, indent, insert_newlines); return std::move(json_buff); } //----------------------------------------------------------------------------------------------------------- diff --git a/contrib/epee/include/storages/portable_storage_to_json.h b/contrib/epee/include/storages/portable_storage_to_json.h index aff85b201..e3fdcec29 100644 --- a/contrib/epee/include/storages/portable_storage_to_json.h +++ b/contrib/epee/include/storages/portable_storage_to_json.h @@ -30,6 +30,7 @@ #include "misc_language.h" #include "portable_storage_base.h" +#include "parserse_base_utils.h" namespace epee { @@ -37,21 +38,21 @@ namespace epee { template - void dump_as_json(t_stream& strm, const array_entry& ae, size_t indent); + void dump_as_json(t_stream& strm, const array_entry& ae, size_t indent, bool insert_newlines); template - void dump_as_json(t_stream& strm, const storage_entry& se, size_t indent); + void dump_as_json(t_stream& strm, const storage_entry& se, size_t indent, bool insert_newlines); template - void dump_as_json(t_stream& strm, const std::string& v, size_t indent); + void dump_as_json(t_stream& strm, const std::string& v, size_t indent, bool insert_newlines); template - void dump_as_json(t_stream& strm, const int8_t& v, size_t indent); + void dump_as_json(t_stream& strm, const int8_t& v, size_t indent, bool insert_newlines); template - void dump_as_json(t_stream& strm, const uint8_t& v, size_t indent); + void dump_as_json(t_stream& strm, const uint8_t& v, size_t indent, bool insert_newlines); template - void dump_as_json(t_stream& strm, const bool& v, size_t indent); + void dump_as_json(t_stream& strm, const bool& v, size_t indent, bool insert_newlines); template - void dump_as_json(t_stream& strm, const t_type& v, size_t indent); + void dump_as_json(t_stream& strm, const t_type& v, size_t indent, bool insert_newlines); template - void dump_as_json(t_stream& strm, const section& sec, size_t indent); + void dump_as_json(t_stream& strm, const section& sec, size_t indent, bool insert_newlines); inline std::string make_indent(size_t indent) @@ -64,7 +65,11 @@ namespace epee { t_stream& m_strm; size_t m_indent; - array_entry_store_to_json_visitor(t_stream& strm, size_t indent):m_strm(strm), m_indent(indent){} + bool m_insert_newlines; + array_entry_store_to_json_visitor(t_stream& strm, size_t indent, + bool insert_newlines = true) + : m_strm(strm), m_indent(indent), m_insert_newlines(insert_newlines) + {} template void operator()(const array_entry_t& a) @@ -75,7 +80,7 @@ namespace epee auto last_it = --a.m_array.end(); for(auto it = a.m_array.begin(); it != a.m_array.end(); it++) { - dump_as_json(m_strm, *it, m_indent); + dump_as_json(m_strm, *it, m_indent, m_insert_newlines); if(it != last_it) m_strm << ","; } @@ -89,50 +94,53 @@ namespace epee { t_stream& m_strm; size_t m_indent; - storage_entry_store_to_json_visitor(t_stream& strm, size_t indent):m_strm(strm), m_indent(indent) + bool m_insert_newlines; + storage_entry_store_to_json_visitor(t_stream& strm, size_t indent, + bool insert_newlines = true) + : m_strm(strm), m_indent(indent), m_insert_newlines(insert_newlines) {} //section, array_entry template void operator()(const visited_type& v) { - dump_as_json(m_strm, v, m_indent); + dump_as_json(m_strm, v, m_indent, m_insert_newlines); } }; template - void dump_as_json(t_stream& strm, const array_entry& ae, size_t indent) + void dump_as_json(t_stream& strm, const array_entry& ae, size_t indent, bool insert_newlines) { - array_entry_store_to_json_visitor aesv(strm, indent); + array_entry_store_to_json_visitor aesv(strm, indent, insert_newlines); boost::apply_visitor(aesv, ae); } template - void dump_as_json(t_stream& strm, const storage_entry& se, size_t indent) + void dump_as_json(t_stream& strm, const storage_entry& se, size_t indent, bool insert_newlines) { - storage_entry_store_to_json_visitor sv(strm, indent); + storage_entry_store_to_json_visitor sv(strm, indent, insert_newlines); boost::apply_visitor(sv, se); } template - void dump_as_json(t_stream& strm, const std::string& v, size_t indent) + void dump_as_json(t_stream& strm, const std::string& v, size_t indent, bool insert_newlines) { strm << "\"" << misc_utils::parse::transform_to_escape_sequence(v) << "\""; } template - void dump_as_json(t_stream& strm, const int8_t& v, size_t indent) + void dump_as_json(t_stream& strm, const int8_t& v, size_t indent, bool insert_newlines) { strm << static_cast(v); } template - void dump_as_json(t_stream& strm, const uint8_t& v, size_t indent) + void dump_as_json(t_stream& strm, const uint8_t& v, size_t indent, bool insert_newlines) { strm << static_cast(v); } template - void dump_as_json(t_stream& strm, const bool& v, size_t indent) + void dump_as_json(t_stream& strm, const bool& v, size_t indent, bool insert_newlines) { if(v) strm << "true"; @@ -143,16 +151,17 @@ namespace epee template - void dump_as_json(t_stream& strm, const t_type& v, size_t indent) + void dump_as_json(t_stream& strm, const t_type& v, size_t indent, bool insert_newlines) { strm << v; } template - void dump_as_json(t_stream& strm, const section& sec, size_t indent) + void dump_as_json(t_stream& strm, const section& sec, size_t indent, bool insert_newlines) { size_t local_indent = indent + 1; - strm << "{\r\n"; + std::string newline = insert_newlines ? "\r\n" : ""; + strm << "{" << newline; std::string indent_str = make_indent(local_indent); if(sec.m_entries.size()) { @@ -160,10 +169,10 @@ namespace epee for(auto it = sec.m_entries.begin(); it!= sec.m_entries.end();it++) { strm << indent_str << "\"" << misc_utils::parse::transform_to_escape_sequence(it->first) << "\"" << ": "; - dump_as_json(strm, it->second, local_indent); + dump_as_json(strm, it->second, local_indent, insert_newlines); if(it_last != it) strm << ","; - strm << "\r\n"; + strm << newline; } } strm << make_indent(indent) << "}"; diff --git a/contrib/epee/include/string_tools.h b/contrib/epee/include/string_tools.h index 4cc88418c..8289ee0ba 100644 --- a/contrib/epee/include/string_tools.h +++ b/contrib/epee/include/string_tools.h @@ -32,6 +32,7 @@ //#include #include #include +#include //#include #include #include diff --git a/src/crypto/oaes_lib.c b/src/crypto/oaes_lib.c index 96f038600..f3f2aac8c 100644 --- a/src/crypto/oaes_lib.c +++ b/src/crypto/oaes_lib.c @@ -64,7 +64,6 @@ static const char _NR[] = { # define min(a,b) (((a)<(b)) ? (a) : (b)) #endif /* min */ - // "OAES<8-bit header version><8-bit type><16-bit options><8-bit flags><56-bit reserved>" static uint8_t oaes_header[OAES_BLOCK_SIZE] = { // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, diff --git a/src/crypto/oaes_lib.h b/src/crypto/oaes_lib.h index 16b914c7a..fd1942822 100644 --- a/src/crypto/oaes_lib.h +++ b/src/crypto/oaes_lib.h @@ -32,6 +32,7 @@ #define _OAES_LIB_H #include +#include #ifdef __cplusplus extern "C" { @@ -101,15 +102,14 @@ typedef int ( * oaes_step_cb ) ( typedef uint16_t OAES_OPTION; - typedef struct _oaes_key { - size_t data_len; - uint8_t *data; - size_t exp_data_len; - uint8_t *exp_data; - size_t num_keys; - size_t key_base; + size_t data_len; + uint8_t *data; + size_t exp_data_len; + uint8_t *exp_data; + size_t num_keys; + size_t key_base; } oaes_key; typedef struct _oaes_ctx @@ -119,14 +119,13 @@ typedef struct _oaes_ctx #endif // OAES_HAVE_ISAAC #ifdef OAES_DEBUG - oaes_step_cb step_cb; + oaes_step_cb step_cb; #endif // OAES_DEBUG - oaes_key * key; - OAES_OPTION options; - uint8_t iv[OAES_BLOCK_SIZE]; + oaes_key * key; + OAES_OPTION options; + uint8_t iv[OAES_BLOCK_SIZE]; } oaes_ctx; - /* * // usage: * diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h index 34d053aa8..a992a9db0 100644 --- a/src/cryptonote_config.h +++ b/src/cryptonote_config.h @@ -8,7 +8,7 @@ #define CRYPTONOTE_MAX_BLOCK_SIZE 500000000 // block header blob limit, never used! #define CRYPTONOTE_MAX_TX_SIZE 1000000000 #define CRYPTONOTE_PUBLIC_ADDRESS_TEXTBLOB_VER 0 -#define CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX 18 // addresses start with "2" +#define CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX 18 // addresses start with "4" #define CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW 60 #define CURRENT_TRANSACTION_VERSION 1 #define CURRENT_BLOCK_MAJOR_VERSION 1 @@ -26,8 +26,8 @@ #define CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE 600 #define CRYPTONOTE_DISPLAY_DECIMAL_POINT 12 // COIN - number of smallest units in one coin -#define COIN ((uint64_t)100000000) // pow(10, 8) -#define DEFAULT_FEE ((uint64_t)1000000) // pow(10, 6) +#define COIN ((uint64_t)1000000000000) // pow(10, 12) +#define DEFAULT_FEE ((uint64_t)5000000000) // 5 * pow(10, 9) #define ORPHANED_BLOCKS_MAX_COUNT 100 diff --git a/src/cryptonote_core/blockchain_storage.cpp b/src/cryptonote_core/blockchain_storage.cpp index 0e20b454b..7123b7521 100644 --- a/src/cryptonote_core/blockchain_storage.cpp +++ b/src/cryptonote_core/blockchain_storage.cpp @@ -372,7 +372,7 @@ bool blockchain_storage::rollback_blockchain_switching(std::list& origina return true; } //------------------------------------------------------------------ -bool blockchain_storage::switch_to_alternative_blockchain(std::list& alt_chain) +bool blockchain_storage::switch_to_alternative_blockchain(std::list& alt_chain, bool discard_disconnected_chain) { CRITICAL_REGION_LOCAL(m_blockchain_lock); CHECK_AND_ASSERT_MES(alt_chain.size(), false, "switch_to_alternative_blockchain: empty chain passed"); @@ -414,16 +414,19 @@ bool blockchain_storage::switch_to_alternative_blockchain(std::list(); - bool r = handle_alternative_block(old_ch_ent, get_block_hash(old_ch_ent), bvc); - if(!r) + //pushing old chain as alternative chain + BOOST_FOREACH(auto& old_ch_ent, disconnected_chain) { - LOG_ERROR("Failed to push ex-main chain blocks to alternative chain "); - rollback_blockchain_switching(disconnected_chain, split_height); - return false; + block_verification_context bvc = boost::value_initialized(); + bool r = handle_alternative_block(old_ch_ent, get_block_hash(old_ch_ent), bvc); + if(!r) + { + LOG_ERROR("Failed to push ex-main chain blocks to alternative chain "); + rollback_blockchain_switching(disconnected_chain, split_height); + return false; + } } } @@ -701,6 +704,22 @@ bool blockchain_storage::handle_alternative_block(const block& b, const crypto:: { CRITICAL_REGION_LOCAL(m_blockchain_lock); + uint64_t block_height = get_block_height(b); + if(0 == block_height) + { + LOG_ERROR("Block with id: " << string_tools::pod_to_hex(id) << " (as alternative) have wrong miner transaction"); + bvc.m_verifivation_failed = true; + return false; + } + if (!m_checkpoints.is_alternative_block_allowed(get_current_blockchain_height(), block_height)) + { + LOG_PRINT_RED_L0("Block with id: " << id + << ENDL << " can't be accepted for alternative chain, block height: " << block_height + << ENDL << " blockchain height: " << get_current_blockchain_height()); + bvc.m_verifivation_failed = true; + return false; + } + //block is not related with head of main chain //first of all - look in alternative chains container auto it_main_prev = m_blocks_index.find(b.prev_id); @@ -746,31 +765,28 @@ bool blockchain_storage::handle_alternative_block(const block& b, const crypto:: block_extended_info bei = boost::value_initialized(); bei.bl = b; bei.height = alt_chain.size() ? it_prev->second.height + 1 : it_main_prev->second + 1; + + bool is_a_checkpoint; + if(!m_checkpoints.check_block(bei.height, id, is_a_checkpoint)) + { + LOG_ERROR("CHECKPOINT VALIDATION FAILED"); + bvc.m_verifivation_failed = true; + return false; + } + + // Always check PoW for alternative blocks + m_is_in_checkpoint_zone = false; difficulty_type current_diff = get_next_difficulty_for_alternative_chain(alt_chain, bei); CHECK_AND_ASSERT_MES(current_diff, false, "!!!!!!! DIFFICULTY OVERHEAD !!!!!!!"); crypto::hash proof_of_work = null_hash; - if(!m_checkpoints.is_in_checkpoint_zone(bei.height)) + get_block_longhash(bei.bl, proof_of_work, bei.height); + if(!check_hash(proof_of_work, current_diff)) { - m_is_in_checkpoint_zone = false; - get_block_longhash(bei.bl, proof_of_work, bei.height); - - if(!check_hash(proof_of_work, current_diff)) - { - LOG_PRINT_RED_L0("Block with id: " << id - << ENDL << " for alternative chain, have not enough proof of work: " << proof_of_work - << ENDL << " expected difficulty: " << current_diff); - bvc.m_verifivation_failed = true; - return false; - } - }else - { - m_is_in_checkpoint_zone = true; - if(!m_checkpoints.check_block(bei.height, id)) - { - LOG_ERROR("CHECKPOINT VALIDATION FAILED"); - bvc.m_verifivation_failed = true; - return false; - } + LOG_PRINT_RED_L0("Block with id: " << id + << ENDL << " for alternative chain, have not enough proof of work: " << proof_of_work + << ENDL << " expected difficulty: " << current_diff); + bvc.m_verifivation_failed = true; + return false; } if(!prevalidate_miner_transaction(b, bei.height)) @@ -792,22 +808,33 @@ bool blockchain_storage::handle_alternative_block(const block& b, const crypto:: auto i_res = m_alternative_chains.insert(blocks_ext_by_hash::value_type(id, bei)); CHECK_AND_ASSERT_MES(i_res.second, false, "insertion of new alternative block returned as it already exist"); alt_chain.push_back(i_res.first); - //check if difficulty bigger then in main chain - if(m_blocks.back().cumulative_difficulty < bei.cumulative_difficulty) + + if(is_a_checkpoint) { //do reorganize! - LOG_PRINT_GREEN("###### REORGANIZE on height: " << alt_chain.front()->second.height << " of " << m_blocks.size() -1 << " with cum_difficulty " << m_blocks.back().cumulative_difficulty + LOG_PRINT_GREEN("###### REORGANIZE on height: " << alt_chain.front()->second.height << " of " << m_blocks.size() - 1 << + ", checkpoint is found in alternative chain on height " << bei.height, LOG_LEVEL_0); + bool r = switch_to_alternative_blockchain(alt_chain, true); + if(r) bvc.m_added_to_main_chain = true; + else bvc.m_verifivation_failed = true; + return r; + }else if(m_blocks.back().cumulative_difficulty < bei.cumulative_difficulty) //check if difficulty bigger then in main chain + { + //do reorganize! + LOG_PRINT_GREEN("###### REORGANIZE on height: " << alt_chain.front()->second.height << " of " << m_blocks.size() - 1 << " with cum_difficulty " << m_blocks.back().cumulative_difficulty << ENDL << " alternative blockchain size: " << alt_chain.size() << " with cum_difficulty " << bei.cumulative_difficulty, LOG_LEVEL_0); - bool r = switch_to_alternative_blockchain(alt_chain); + bool r = switch_to_alternative_blockchain(alt_chain, false); if(r) bvc.m_added_to_main_chain = true; else bvc.m_verifivation_failed = true; return r; + }else + { + LOG_PRINT_BLUE("----- BLOCK ADDED AS ALTERNATIVE ON HEIGHT " << bei.height + << ENDL << "id:\t" << id + << ENDL << "PoW:\t" << proof_of_work + << ENDL << "difficulty:\t" << current_diff, LOG_LEVEL_0); + return true; } - LOG_PRINT_BLUE("----- BLOCK ADDED AS ALTERNATIVE ON HEIGHT " << bei.height - << ENDL << "id:\t" << id - << ENDL << "PoW:\t" << proof_of_work - << ENDL << "difficulty:\t" << current_diff, LOG_LEVEL_0); - return true; }else { //block orphaned @@ -815,7 +842,6 @@ bool blockchain_storage::handle_alternative_block(const block& b, const crypto:: LOG_PRINT_RED_L0("Block recognized as orphaned and rejected, id = " << id); } - return true; } //------------------------------------------------------------------ @@ -1480,19 +1506,27 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt TIME_MEASURE_FINISH(target_calculating_time); TIME_MEASURE_START(longhash_calculating_time); crypto::hash proof_of_work = null_hash; - if(!m_checkpoints.is_in_checkpoint_zone(get_current_blockchain_height())) + + // Formerly the code below contained an if loop with the following condition + // !m_checkpoints.is_in_checkpoint_zone(get_current_blockchain_height()) + // however, this caused the daemon to not bother checking PoW for blocks + // before checkpoints, which is very dangerous behaviour. We moved the PoW + // validation out of the next chunk of code to make sure that we correctly + // check PoW now. + proof_of_work = get_block_longhash(bl, m_blocks.size()); + + if(!check_hash(proof_of_work, current_diffic)) { - proof_of_work = get_block_longhash(bl, m_blocks.size()); + LOG_PRINT_L0("Block with id: " << id << ENDL + << "have not enough proof of work: " << proof_of_work << ENDL + << "nexpected difficulty: " << current_diffic ); + bvc.m_verifivation_failed = true; + return false; + } - if(!check_hash(proof_of_work, current_diffic)) - { - LOG_PRINT_L0("Block with id: " << id << ENDL - << "have not enough proof of work: " << proof_of_work << ENDL - << "nexpected difficulty: " << current_diffic ); - bvc.m_verifivation_failed = true; - return false; - } - }else + // If we're at a checkpoint, ensure that our hardcoded checkpoint hash + // is correct. + if(!m_checkpoints.is_in_checkpoint_zone(get_current_blockchain_height())) { if(!m_checkpoints.check_block(get_current_blockchain_height(), id)) { @@ -1501,6 +1535,7 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt return false; } } + TIME_MEASURE_FINISH(longhash_calculating_time); if(!prevalidate_miner_transaction(bl, m_blocks.size())) @@ -1648,4 +1683,4 @@ bool blockchain_storage::add_new_block(const block& bl_, block_verification_cont } return handle_block_to_main_chain(bl, id, bvc); -} \ No newline at end of file +} diff --git a/src/cryptonote_core/blockchain_storage.h b/src/cryptonote_core/blockchain_storage.h index 1ea5e29ea..b1fb5df41 100644 --- a/src/cryptonote_core/blockchain_storage.h +++ b/src/cryptonote_core/blockchain_storage.h @@ -13,6 +13,8 @@ #include #include +#include "syncobj.h" +#include "string_tools.h" #include "tx_pool.h" #include "cryptonote_basic.h" #include "common/util.h" @@ -50,7 +52,7 @@ namespace cryptonote uint64_t already_generated_coins; }; - blockchain_storage(tx_memory_pool& tx_pool):m_tx_pool(tx_pool), m_current_block_cumul_sz_limit(0), m_is_in_checkpoint_zone(false) + blockchain_storage(tx_memory_pool& tx_pool):m_tx_pool(tx_pool), m_current_block_cumul_sz_limit(0), m_is_in_checkpoint_zone(false), m_is_blockchain_storing(false) {}; bool init() { return init(tools::get_default_data_dir()); } @@ -119,7 +121,7 @@ namespace cryptonote missed_bs.push_back(bl_id); else { - CHECK_AND_ASSERT_MES(it->second < m_blocks.size(), false, "Internal error: bl_id=" << string_tools::pod_to_hex(bl_id) + CHECK_AND_ASSERT_MES(it->second < m_blocks.size(), false, "Internal error: bl_id=" << epee::string_tools::pod_to_hex(bl_id) << " have index record with offset="<second<< ", bigger then m_blocks.size()=" << m_blocks.size()); blocks.push_back(m_blocks[it->second].bl); } @@ -163,7 +165,7 @@ namespace cryptonote typedef std::map>> outputs_container; //crypto::hash - tx hash, size_t - index of out in transaction tx_memory_pool& m_tx_pool; - critical_section m_blockchain_lock; // TODO: add here reader/writer lock + epee::critical_section m_blockchain_lock; // TODO: add here reader/writer lock // main chain blocks_container m_blocks; // height -> block_extended_info @@ -186,7 +188,7 @@ namespace cryptonote std::atomic m_is_in_checkpoint_zone; std::atomic m_is_blockchain_storing; - bool switch_to_alternative_blockchain(std::list& alt_chain); + bool switch_to_alternative_blockchain(std::list& alt_chain, bool discard_disconnected_chain); bool pop_block_from_blockchain(); bool purge_block_data_from_blockchain(const block& b, size_t processed_tx_count); bool purge_transaction_from_blockchain(const crypto::hash& tx_id); @@ -301,7 +303,7 @@ namespace cryptonote return false; } transactions_container::iterator tx_it = m_transactions.find(amount_outs_vec[i].first); - CHECK_AND_ASSERT_MES(tx_it != m_transactions.end(), false, "Wrong transaction id in output indexes: " <second.tx.vout.size(), false, "Wrong index in transaction outputs: " << amount_outs_vec[i].second << ", expected less then " << tx_it->second.tx.vout.size()); if(!vis.handle_output(tx_it->second.tx, tx_it->second.tx.vout[amount_outs_vec[i].second])) diff --git a/src/cryptonote_core/checkpoints.cpp b/src/cryptonote_core/checkpoints.cpp index 54c2f3a6d..33a2d2986 100644 --- a/src/cryptonote_core/checkpoints.cpp +++ b/src/cryptonote_core/checkpoints.cpp @@ -29,10 +29,11 @@ namespace cryptonote return !m_points.empty() && (height <= (--m_points.end())->first); } //--------------------------------------------------------------------------- - bool checkpoints::check_block(uint64_t height, const crypto::hash& h) const + bool checkpoints::check_block(uint64_t height, const crypto::hash& h, bool& is_a_checkpoint) const { auto it = m_points.find(height); - if(it == m_points.end()) + is_a_checkpoint = it != m_points.end(); + if(!is_a_checkpoint) return true; if(it->second == h) @@ -45,4 +46,25 @@ namespace cryptonote return false; } } + //--------------------------------------------------------------------------- + bool checkpoints::check_block(uint64_t height, const crypto::hash& h) const + { + bool ignored; + return check_block(height, h, ignored); + } + //--------------------------------------------------------------------------- + bool checkpoints::is_alternative_block_allowed(uint64_t blockchain_height, uint64_t block_height) const + { + if (0 == block_height) + return false; + + auto it = m_points.upper_bound(blockchain_height); + // Is blockchain_height before the first checkpoint? + if (it == m_points.begin()) + return true; + + --it; + uint64_t checkpoint_height = it->first; + return checkpoint_height < block_height; + } } diff --git a/src/cryptonote_core/checkpoints.h b/src/cryptonote_core/checkpoints.h index 20014b1c8..1bc055d91 100644 --- a/src/cryptonote_core/checkpoints.h +++ b/src/cryptonote_core/checkpoints.h @@ -16,6 +16,9 @@ namespace cryptonote bool add_checkpoint(uint64_t height, const std::string& hash_str); bool is_in_checkpoint_zone(uint64_t height) const; bool check_block(uint64_t height, const crypto::hash& h) const; + bool check_block(uint64_t height, const crypto::hash& h, bool& is_a_checkpoint) const; + bool is_alternative_block_allowed(uint64_t blockchain_height, uint64_t block_height) const; + private: std::map m_points; }; diff --git a/src/cryptonote_core/checkpoints_create.h b/src/cryptonote_core/checkpoints_create.h index 32d15831f..3ecbbf0b6 100644 --- a/src/cryptonote_core/checkpoints_create.h +++ b/src/cryptonote_core/checkpoints_create.h @@ -12,12 +12,9 @@ namespace cryptonote { inline bool create_checkpoints(cryptonote::checkpoints& checkpoints) { - // Checkpointing disabled until we can make the client not fast-sync - // without checking PoW at some point. Otherwise we may be exposed - // to blockchain corruption attacks. Need to investigate this further. - // 8-5-14 - // ADD_CHECKPOINT(22231, "7cb10e29d67e1c069e6e11b17d30b809724255fee2f6868dc14cfc6ed44dfb25"); - // ADD_CHECKPOINT(29556, "53c484a8ed91e4da621bb2fa88106dbde426fe90d7ef07b9c1e5127fb6f3a7f6"); + ADD_CHECKPOINT(22231, "7cb10e29d67e1c069e6e11b17d30b809724255fee2f6868dc14cfc6ed44dfb25"); + ADD_CHECKPOINT(29556, "53c484a8ed91e4da621bb2fa88106dbde426fe90d7ef07b9c1e5127fb6f3a7f6"); + ADD_CHECKPOINT(50000, "0fe8758ab06a8b9cb35b7328fd4f757af530a5d37759f9d3e421023231f7b31c"); return true; } } diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index a09f25d31..b6bfa09c8 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -502,7 +502,7 @@ namespace cryptonote LOG_PRINT_L0(ENDL << "**********************************************************************" << ENDL << "The daemon will start synchronizing with the network. It may take up to several hours." << ENDL << ENDL - << "You can set the level of process detailization by using command \"set_log \", where is either 0 (no details), 1 (current block height synchronized), or 2 (all details)." << ENDL + << "You can set the level of process detailization* through \"set_log \" command*, where is between 0 (no details) and 4 (very verbose)." << ENDL << ENDL << "Use \"help\" command to see the list of available commands." << ENDL << ENDL diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h index c298451e8..cde52d5a2 100644 --- a/src/cryptonote_core/cryptonote_core.h +++ b/src/cryptonote_core/cryptonote_core.h @@ -115,13 +115,13 @@ namespace cryptonote tx_memory_pool m_mempool; blockchain_storage m_blockchain_storage; i_cryptonote_protocol* m_pprotocol; - critical_section m_incoming_tx_lock; + epee::critical_section m_incoming_tx_lock; //m_miner and m_miner_addres are probably temporary here miner m_miner; account_public_address m_miner_address; std::string m_config_folder; cryptonote_protocol_stub m_protocol_stub; - math_helper::once_a_time_seconds<60*60*12, false> m_store_blockchain_interval; + epee::math_helper::once_a_time_seconds<60*60*12, false> m_store_blockchain_interval; friend class tx_validate_inputs; std::atomic m_starter_message_showed; }; diff --git a/src/cryptonote_core/cryptonote_format_utils.cpp b/src/cryptonote_core/cryptonote_format_utils.cpp index 2b38d001f..7b7f18844 100644 --- a/src/cryptonote_core/cryptonote_format_utils.cpp +++ b/src/cryptonote_core/cryptonote_format_utils.cpp @@ -239,8 +239,7 @@ namespace cryptonote crypto::public_key get_tx_pub_key_from_extra(const std::vector& tx_extra) { std::vector tx_extra_fields; - if (!parse_tx_extra(tx_extra, tx_extra_fields)) - return null_pkey; + parse_tx_extra(tx_extra, tx_extra_fields); tx_extra_pub_key pub_key_field; if(!find_tx_extra_field_by_type(tx_extra_fields, pub_key_field)) diff --git a/src/cryptonote_core/miner.h b/src/cryptonote_core/miner.h index da4578b06..61c063ddf 100644 --- a/src/cryptonote_core/miner.h +++ b/src/cryptonote_core/miner.h @@ -4,7 +4,6 @@ #pragma once -#include #include #include #include "cryptonote_basic.h" @@ -64,7 +63,7 @@ namespace cryptonote volatile uint32_t m_stop; - ::critical_section m_template_lock; + epee::critical_section m_template_lock; block m_template; std::atomic m_template_no; std::atomic m_starter_nonce; @@ -73,21 +72,21 @@ namespace cryptonote volatile uint32_t m_thread_index; volatile uint32_t m_threads_total; std::atomic m_pausers_count; - ::critical_section m_miners_count_lock; + epee::critical_section m_miners_count_lock; std::list m_threads; - ::critical_section m_threads_lock; + epee::critical_section m_threads_lock; i_miner_handler* m_phandler; account_public_address m_mine_address; - math_helper::once_a_time_seconds<5> m_update_block_template_interval; - math_helper::once_a_time_seconds<2> m_update_merge_hr_interval; + epee::math_helper::once_a_time_seconds<5> m_update_block_template_interval; + epee::math_helper::once_a_time_seconds<2> m_update_merge_hr_interval; std::vector m_extra_messages; miner_config m_config; std::string m_config_folder_path; std::atomic m_last_hr_merge_time; std::atomic m_hashes; std::atomic m_current_hash_rate; - critical_section m_last_hash_rates_lock; + epee::critical_section m_last_hash_rates_lock; std::list m_last_hash_rates; bool m_do_print_hashrate; bool m_do_mining; diff --git a/src/cryptonote_core/tx_extra.h b/src/cryptonote_core/tx_extra.h index 254a6a2ff..37a04a41e 100644 --- a/src/cryptonote_core/tx_extra.h +++ b/src/cryptonote_core/tx_extra.h @@ -135,7 +135,6 @@ namespace cryptonote // varint tag; // varint size; // varint data[]; - //typedef boost::variant tx_extra_field; typedef boost::variant tx_extra_field; } diff --git a/src/cryptonote_core/tx_pool.h b/src/cryptonote_core/tx_pool.h index 3978dfb96..26d273aa7 100644 --- a/src/cryptonote_core/tx_pool.h +++ b/src/cryptonote_core/tx_pool.h @@ -4,8 +4,6 @@ #pragma once #include "include_base_utils.h" -using namespace epee; - #include #include diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.h b/src/cryptonote_protocol/cryptonote_protocol_handler.h index 178ec2eb1..80538677c 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.h +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.h @@ -81,7 +81,7 @@ namespace cryptonote template bool post_notify(typename t_parametr::request& arg, cryptonote_connection_context& context) { - LOG_PRINT_L2("[" << net_utils::print_connection_context_short(context) << "] post " << typeid(t_parametr).name() << " -->"); + LOG_PRINT_L2("[" << epee::net_utils::print_connection_context_short(context) << "] post " << typeid(t_parametr).name() << " -->"); std::string blob; epee::serialization::store_t_to_binary(arg, blob); return m_p2p->invoke_notify_to_peer(t_parametr::ID, blob, context); @@ -90,7 +90,7 @@ namespace cryptonote template bool relay_post_notify(typename t_parametr::request& arg, cryptonote_connection_context& exlude_context) { - LOG_PRINT_L2("[" << net_utils::print_connection_context_short(exlude_context) << "] post relay " << typeid(t_parametr).name() << " -->"); + LOG_PRINT_L2("[" << epee::net_utils::print_connection_context_short(exlude_context) << "] post relay " << typeid(t_parametr).name() << " -->"); std::string arg_buff; epee::serialization::store_t_to_binary(arg, arg_buff); return m_p2p->relay_notify_to_all(t_parametr::ID, arg_buff, exlude_context); diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl index a0838e690..2584f1097 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl @@ -81,7 +81,7 @@ namespace cryptonote m_p2p->for_each_connection([&](const connection_context& cntxt, nodetool::peerid_type peer_id) { ss << std::setw(25) << std::left << std::string(cntxt.m_is_income ? " [INC]":"[OUT]") + - string_tools::get_ip_string_from_int32(cntxt.m_remote_ip) + ":" + std::to_string(cntxt.m_remote_port) + epee::string_tools::get_ip_string_from_int32(cntxt.m_remote_ip) + ":" + std::to_string(cntxt.m_remote_port) << std::setw(20) << std::hex << peer_id << std::setw(25) << std::to_string(cntxt.m_recv_cnt)+ "(" + std::to_string(time(NULL) - cntxt.m_last_recv) + ")" + "/" + std::to_string(cntxt.m_send_cnt) + "(" + std::to_string(time(NULL) - cntxt.m_last_send) + ")" << std::setw(25) << get_protocol_state_string(cntxt.m_state) @@ -108,9 +108,12 @@ namespace cryptonote return true; } - LOG_PRINT_CCONTEXT_YELLOW("Sync data returned unknown top block: " << m_core.get_current_blockchain_height() << "->" << hshd.current_height - << "[" << static_cast(hshd.current_height - m_core.get_current_blockchain_height()) << " blocks(" << (hshd.current_height - m_core.get_current_blockchain_height()) /1440 << " days) behind] " << ENDL - << "remote top: " << hshd.top_id << "[" << hshd.current_height << "]" << ", set SYNCHRONIZATION mode", (is_inital ? LOG_LEVEL_0:LOG_LEVEL_1)); + int64_t diff = static_cast(hshd.current_height) - static_cast(m_core.get_current_blockchain_height()); + LOG_PRINT_CCONTEXT_YELLOW("Sync data returned unknown top block: " << m_core.get_current_blockchain_height() << " -> " << hshd.current_height + << " [" << std::abs(diff) << " blocks (" << diff / (24 * 60 * 60 / DIFFICULTY_TARGET) << " days) " + << (0 <= diff ? std::string("behind") : std::string("ahead")) + << "] " << ENDL << "SYNCHRONIZATION started", (is_inital ? LOG_LEVEL_0:LOG_LEVEL_1)); + LOG_PRINT_L1("Remote top block height: " << hshd.current_height << ", id: " << hshd.top_id); context.m_state = cryptonote_connection_context::state_synchronizing; context.m_remote_blockchain_height = hshd.current_height; //let the socket to send response to handshake, but request callback, to let send request data after response @@ -254,7 +257,7 @@ namespace cryptonote if(!parse_and_validate_block_from_blob(block_entry.block, b)) { LOG_ERROR_CCONTEXT("sent wrong block: failed to parse and validate block: \r\n" - << string_tools::buff_to_hex_nodelimer(block_entry.block) << "\r\n dropping connection"); + << epee::string_tools::buff_to_hex_nodelimer(block_entry.block) << "\r\n dropping connection"); m_p2p->drop_connection(context); return 1; } @@ -274,14 +277,14 @@ namespace cryptonote auto req_it = context.m_requested_objects.find(get_block_hash(b)); if(req_it == context.m_requested_objects.end()) { - LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_GET_OBJECTS: block with id=" << string_tools::pod_to_hex(get_blob_hash(block_entry.block)) + LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_GET_OBJECTS: block with id=" << epee::string_tools::pod_to_hex(get_blob_hash(block_entry.block)) << " wasn't requested, dropping connection"); m_p2p->drop_connection(context); return 1; } if(b.tx_hashes.size() != block_entry.txs.size()) { - LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_GET_OBJECTS: block with id=" << string_tools::pod_to_hex(get_blob_hash(block_entry.block)) + LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_GET_OBJECTS: block with id=" << epee::string_tools::pod_to_hex(get_blob_hash(block_entry.block)) << ", tx_hashes.size()=" << b.tx_hashes.size() << " mismatch with block_complete_entry.m_txs.size()=" << block_entry.txs.size() << ", dropping connection"); m_p2p->drop_connection(context); return 1; @@ -300,7 +303,7 @@ namespace cryptonote { m_core.pause_mine(); - misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler( + epee::misc_utils::auto_scope_leave_caller scope_exit_handler = epee::misc_utils::create_scope_leave_handler( boost::bind(&t_core::resume_mine, &m_core)); BOOST_FOREACH(const block_complete_entry& block_entry, arg.blocks) @@ -314,7 +317,7 @@ namespace cryptonote if(tvc.m_verifivation_failed) { LOG_ERROR_CCONTEXT("transaction verification failed on NOTIFY_RESPONSE_GET_OBJECTS, \r\ntx_id = " - << string_tools::pod_to_hex(get_blob_hash(tx_blob)) << ", dropping connection"); + << epee::string_tools::pod_to_hex(get_blob_hash(tx_blob)) << ", dropping connection"); m_p2p->drop_connection(context); return 1; } @@ -408,7 +411,7 @@ namespace cryptonote << "\r\nm_remote_blockchain_height=" << context.m_remote_blockchain_height << "\r\nm_needed_objects.size()=" << context.m_needed_objects.size() << "\r\nm_requested_objects.size()=" << context.m_requested_objects.size() - << "\r\non connection [" << net_utils::print_connection_context_short(context)<< "]"); + << "\r\non connection [" << epee::net_utils::print_connection_context_short(context)<< "]"); context.m_state = cryptonote_connection_context::state_normal; LOG_PRINT_CCONTEXT_GREEN(" SYNCHRONIZED OK", LOG_LEVEL_0); @@ -464,7 +467,7 @@ namespace cryptonote if(!m_core.have_block(arg.m_block_ids.front())) { LOG_ERROR_CCONTEXT("sent m_block_ids starting from unknown id: " - << string_tools::pod_to_hex(arg.m_block_ids.front()) << " , dropping connection"); + << epee::string_tools::pod_to_hex(arg.m_block_ids.front()) << " , dropping connection"); m_p2p->drop_connection(context); return 1; } diff --git a/src/daemon/daemon_commands_handler.h b/src/daemon/daemon_commands_handler.h index 74b671e2a..135ec68f8 100644 --- a/src/daemon/daemon_commands_handler.h +++ b/src/daemon/daemon_commands_handler.h @@ -11,6 +11,7 @@ #include "cryptonote_protocol/cryptonote_protocol_handler.h" #include "common/util.h" #include "crypto/hash.h" +#include "version.h" class daemon_cmmands_handler @@ -34,6 +35,7 @@ public: m_cmd_binder.set_handler("show_hr", boost::bind(&daemon_cmmands_handler::show_hr, this, _1), "Start showing hash rate"); m_cmd_binder.set_handler("hide_hr", boost::bind(&daemon_cmmands_handler::hide_hr, this, _1), "Stop showing hash rate"); m_cmd_binder.set_handler("save", boost::bind(&daemon_cmmands_handler::save, this, _1), "Save blockchain"); + m_cmd_binder.set_handler("set_log", boost::bind(&daemon_cmmands_handler::set_log, this, _1), "set_log - Change current log detalization level, is a number 0-4"); m_cmd_binder.set_handler("diff", boost::bind(&daemon_cmmands_handler::diff, this, _1), "Show difficulty"); } @@ -55,6 +57,7 @@ private: std::string get_commands_str() { std::stringstream ss; + ss << CRYPTONOTE_NAME << " v" << PROJECT_VERSION_LONG << ENDL; ss << "Commands: " << ENDL; std::string usage = m_cmd_binder.get_usage(); boost::replace_all(usage, "\n", "\n "); @@ -135,19 +138,34 @@ private: return false; } uint64_t start_index = 0; + uint64_t end_index = 0; uint64_t end_block_parametr = m_srv.get_payload_object().get_core().get_current_blockchain_height(); if(!string_tools::get_xtype_from_string(start_index, args[0])) { std::cout << "wrong starter block index parameter" << ENDL; return false; } - if(args.size() >1 && !string_tools::get_xtype_from_string(end_block_parametr, args[1])) + if(args.size() >1 && !string_tools::get_xtype_from_string(end_index, args[1])) { std::cout << "wrong end block index parameter" << ENDL; return false; } + if (end_index == 0) + { + end_index = end_block_parametr; + } + if (end_index > end_block_parametr) + { + std::cout << "end block index parameter shouldn't be greater than " << end_block_parametr << ENDL; + return false; + } + if (end_index <= start_index) + { + std::cout << "end block index should be greater than starter block index" << ENDL; + return false; + } - m_srv.get_payload_object().get_core().print_blockchain(start_index, end_block_parametr); + m_srv.get_payload_object().get_core().print_blockchain(start_index, end_index); return true; } //-------------------------------------------------------------------------------- @@ -156,6 +174,33 @@ private: m_srv.get_payload_object().get_core().print_blockchain_index(); return true; } + + bool set_log(const std::vector& args) + { + if(args.size() != 1) + { + std::cout << "use: set_log " << ENDL; + return true; + } + + uint16_t l = 0; + if(!string_tools::get_xtype_from_string(l, args[0])) + { + std::cout << "wrong number format, use: set_log " << ENDL; + return true; + } + + if(LOG_LEVEL_4 < l) + { + std::cout << "wrong number range, use: set_log " << ENDL; + return true; + } + + log_space::log_singletone::get_set_log_detalisation_level(true, l); + + return true; + } + //-------------------------------------------------------------------------------- template static bool print_as_json(T& obj) diff --git a/src/p2p/net_node.h b/src/p2p/net_node.h index 794b97429..5a03b049f 100644 --- a/src/p2p/net_node.h +++ b/src/p2p/net_node.h @@ -24,8 +24,7 @@ #include "p2p_networks.h" #include "math_helper.h" #include "net_node_common.h" - -using namespace epee; +#include "common/command_line.h" PUSH_WARNINGS DISABLE_VS_WARNINGS(4355) @@ -39,7 +38,7 @@ namespace nodetool }; template - class node_server: public levin::levin_commands_handler >, + class node_server: public epee::levin::levin_commands_handler >, public i_p2p_endpoint { struct by_conn_id{}; @@ -126,7 +125,7 @@ namespace nodetool bool parse_peer_from_string(nodetool::net_address& pe, const std::string& node_addr); bool handle_command_line(const boost::program_options::variables_map& vm); bool idle_worker(); - bool handle_remote_peerlist(const std::list& peerlist, time_t local_time, const net_utils::connection_context_base& context); + bool handle_remote_peerlist(const std::list& peerlist, time_t local_time, const epee::net_utils::connection_context_base& context); bool get_local_node_data(basic_node_data& node_data); //bool get_local_handshake_data(handshake_data& hshd); @@ -136,7 +135,7 @@ namespace nodetool bool connections_maker(); bool peer_sync_idle_maker(); bool do_handshake_with_peer(peerid_type& pi, p2p_connection_context& context, bool just_take_peerlist = false); - bool do_peer_timed_sync(const net_utils::connection_context_base& context, peerid_type peer_id); + bool do_peer_timed_sync(const epee::net_utils::connection_context_base& context, peerid_type peer_id); bool make_new_connection_from_peerlist(bool use_white_list); bool try_to_connect_and_handshake_with_new_peer(const net_address& na, bool just_take_peerlist = false, uint64_t last_seen_stamp = 0, bool white = true); @@ -146,12 +145,19 @@ namespace nodetool template bool try_ping(basic_node_data& node_data, p2p_connection_context& context, t_callback cb); bool make_expected_connections_count(bool white_list, size_t expected_connections); + bool is_priority_node(const net_address& na); + + template + bool connect_to_peerlist(const Container& peers); + + template + bool parse_peers_and_add_to_container(const boost::program_options::variables_map& vm, const command_line::arg_descriptor > & arg, Container& container); //debug functions std::string print_connections_container(); - typedef net_utils::boosted_tcp_server > net_server; + typedef epee::net_utils::boosted_tcp_server > net_server; struct config { @@ -181,9 +187,9 @@ namespace nodetool t_payload_net_handler& m_payload_handler; peerlist_manager m_peerlist; - math_helper::once_a_time_seconds m_peer_handshake_idle_maker_interval; - math_helper::once_a_time_seconds<1> m_connections_maker_interval; - math_helper::once_a_time_seconds<60*30, false> m_peerlist_store_interval; + epee::math_helper::once_a_time_seconds m_peer_handshake_idle_maker_interval; + epee::math_helper::once_a_time_seconds<1> m_connections_maker_interval; + epee::math_helper::once_a_time_seconds<60*30, false> m_peerlist_store_interval; std::string m_bind_ip; std::string m_port; @@ -191,6 +197,7 @@ namespace nodetool uint64_t m_last_stat_request_time; #endif std::list m_priority_peers; + std::vector m_exclusive_peers; std::vector m_seed_nodes; std::list m_command_line_peers; uint64_t m_peer_livetime; diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 31d3e6597..e45e51b77 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -4,9 +4,10 @@ #pragma once +#include + #include "version.h" #include "string_tools.h" -#include "common/command_line.h" #include "common/util.h" #include "net/net_helper.h" #include "math_helper.h" @@ -31,8 +32,11 @@ namespace nodetool const command_line::arg_descriptor arg_p2p_allow_local_ip = {"allow-local-ip", "Allow local ip add to peer list, mostly in debug purposes"}; const command_line::arg_descriptor > arg_p2p_add_peer = {"add-peer", "Manually add peer to local peerlist"}; const command_line::arg_descriptor > arg_p2p_add_priority_node = {"add-priority-node", "Specify list of peers to connect to and attempt to keep the connection open"}; + const command_line::arg_descriptor > arg_p2p_add_exclusive_node = {"add-exclusive-node", "Specify list of peers to connect to only." + " If this option is given the options add-priority-node and seed-node are ignored"}; const command_line::arg_descriptor > arg_p2p_seed_node = {"seed-node", "Connect to a node to retrieve peer addresses, and disconnect"}; - const command_line::arg_descriptor arg_p2p_hide_my_port = {"hide-my-port", "Do not announce yourself as peerlist candidate", false, true}; } + const command_line::arg_descriptor arg_p2p_hide_my_port = {"hide-my-port", "Do not announce yourself as peerlist candidate", false, true}; + } //----------------------------------------------------------------------------------- template @@ -44,6 +48,7 @@ namespace nodetool command_line::add_arg(desc, arg_p2p_allow_local_ip); command_line::add_arg(desc, arg_p2p_add_peer); command_line::add_arg(desc, arg_p2p_add_priority_node); + command_line::add_arg(desc, arg_p2p_add_exclusive_node); command_line::add_arg(desc, arg_p2p_seed_node); command_line::add_arg(desc, arg_p2p_hide_my_port); } //----------------------------------------------------------------------------------- @@ -96,7 +101,7 @@ namespace nodetool template bool node_server::parse_peer_from_string(nodetool::net_address& pe, const std::string& node_addr) { - return string_tools::parse_peer_from_string(pe.ip, pe.port, node_addr); + return epee::string_tools::parse_peer_from_string(pe.ip, pe.port, node_addr); } //----------------------------------------------------------------------------------- template @@ -120,30 +125,26 @@ namespace nodetool } } - if (command_line::has_arg(vm, arg_p2p_add_priority_node)) - { - std::vector perrs = command_line::get_arg(vm, arg_p2p_add_priority_node); - for(const std::string& pr_str: perrs) - { - nodetool::net_address na = AUTO_VAL_INIT(na); - bool r = parse_peer_from_string(na, pr_str); - CHECK_AND_ASSERT_MES(r, false, "Failed to parse address from string: " << pr_str); - m_priority_peers.push_back(na); - } + if (command_line::has_arg(vm,arg_p2p_add_exclusive_node)) + { + if (!parse_peers_and_add_to_container(vm, arg_p2p_add_exclusive_node, m_exclusive_peers)) + return false; + } + else if (command_line::has_arg(vm, arg_p2p_add_priority_node)) + { + if (!parse_peers_and_add_to_container(vm, arg_p2p_add_priority_node, m_priority_peers)) + return false; } if (command_line::has_arg(vm, arg_p2p_seed_node)) { - std::vector seed_perrs = command_line::get_arg(vm, arg_p2p_seed_node); - for(const std::string& pr_str: seed_perrs) - { - nodetool::net_address na = AUTO_VAL_INIT(na); - bool r = parse_peer_from_string(na, pr_str); - CHECK_AND_ASSERT_MES(r, false, "Failed to parse seed address from string: " << pr_str); - m_seed_nodes.push_back(na); - } + if (!parse_peers_and_add_to_container(vm, arg_p2p_seed_node, m_seed_nodes)) + return false; } + if(command_line::has_arg(vm, arg_p2p_hide_my_port)) - m_hide_my_port = true; return true; + m_hide_my_port = true; + + return true; } //----------------------------------------------------------------------------------- namespace @@ -353,23 +354,23 @@ namespace nodetool get_local_node_data(arg.node_data); m_payload_handler.get_payload_sync_data(arg.payload_data); - simple_event ev; + epee::simple_event ev; std::atomic hsh_result(false); - bool r = net_utils::async_invoke_remote_command2(context_.m_connection_id, COMMAND_HANDSHAKE::ID, arg, m_net_server.get_config_object(), + bool r = epee::net_utils::async_invoke_remote_command2(context_.m_connection_id, COMMAND_HANDSHAKE::ID, arg, m_net_server.get_config_object(), [this, &pi, &ev, &hsh_result, &just_take_peerlist](int code, const typename COMMAND_HANDSHAKE::response& rsp, p2p_connection_context& context) { - misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler([&](){ev.raise();}); + epee::misc_utils::auto_scope_leave_caller scope_exit_handler = epee::misc_utils::create_scope_leave_handler([&](){ev.raise();}); if(code < 0) { - LOG_PRINT_CC_RED(context, "COMMAND_HANDSHAKE invoke failed. (" << code << ", " << levin::get_err_descr(code) << ")", LOG_LEVEL_1); + LOG_PRINT_CC_RED(context, "COMMAND_HANDSHAKE invoke failed. (" << code << ", " << epee::levin::get_err_descr(code) << ")", LOG_LEVEL_1); return; } if(rsp.node_data.network_id != BYTECOIN_NETWORK) { - LOG_ERROR_CCONTEXT("COMMAND_HANDSHAKE Failed, wrong network! (" << string_tools::get_str_from_guid_a(rsp.node_data.network_id) << "), closing connection."); + LOG_ERROR_CCONTEXT("COMMAND_HANDSHAKE Failed, wrong network! (" << epee::string_tools::get_str_from_guid_a(rsp.node_data.network_id) << "), closing connection."); return; } @@ -397,10 +398,10 @@ namespace nodetool hsh_result = false; return; } - LOG_PRINT_CCONTEXT_L0(" COMMAND_HANDSHAKE INVOKED OK"); + LOG_PRINT_CCONTEXT_L1(" COMMAND_HANDSHAKE INVOKED OK"); }else { - LOG_PRINT_CCONTEXT_L0(" COMMAND_HANDSHAKE(AND CLOSE) INVOKED OK"); + LOG_PRINT_CCONTEXT_L1(" COMMAND_HANDSHAKE(AND CLOSE) INVOKED OK"); } }, P2P_DEFAULT_HANDSHAKE_INVOKE_TIMEOUT); @@ -411,7 +412,7 @@ namespace nodetool if(!hsh_result) { - LOG_PRINT_CC_L0(context_, "COMMAND_HANDSHAKE Failed"); + LOG_PRINT_CC_L1(context_, "COMMAND_HANDSHAKE Failed"); m_net_server.get_config_object().close(context_.m_connection_id); } @@ -419,17 +420,17 @@ namespace nodetool } //----------------------------------------------------------------------------------- template - bool node_server::do_peer_timed_sync(const net_utils::connection_context_base& context_, peerid_type peer_id) + bool node_server::do_peer_timed_sync(const epee::net_utils::connection_context_base& context_, peerid_type peer_id) { typename COMMAND_TIMED_SYNC::request arg = AUTO_VAL_INIT(arg); m_payload_handler.get_payload_sync_data(arg.payload_data); - bool r = net_utils::async_invoke_remote_command2(context_.m_connection_id, COMMAND_TIMED_SYNC::ID, arg, m_net_server.get_config_object(), + bool r = epee::net_utils::async_invoke_remote_command2(context_.m_connection_id, COMMAND_TIMED_SYNC::ID, arg, m_net_server.get_config_object(), [this](int code, const typename COMMAND_TIMED_SYNC::response& rsp, p2p_connection_context& context) { if(code < 0) { - LOG_PRINT_CC_RED(context, "COMMAND_TIMED_SYNC invoke failed. (" << code << ", " << levin::get_err_descr(code) << ")", LOG_LEVEL_1); + LOG_PRINT_CC_RED(context, "COMMAND_TIMED_SYNC invoke failed. (" << code << ", " << epee::levin::get_err_descr(code) << ")", LOG_LEVEL_1); return; } @@ -502,36 +503,53 @@ namespace nodetool return connected; } - //----------------------------------------------------------------------------------- +#define LOG_PRINT_CC_PRIORITY_NODE(priority, con, msg) \ + do { \ + if (priority) {\ + LOG_PRINT_CC_L0(con, msg); \ + } else {\ + LOG_PRINT_CC_L1(con, msg); \ + } \ + } while(0) + template bool node_server::try_to_connect_and_handshake_with_new_peer(const net_address& na, bool just_take_peerlist, uint64_t last_seen_stamp, bool white) { - LOG_PRINT_L0("Connecting to " << string_tools::get_ip_string_from_int32(na.ip) << ":" << string_tools::num_to_string_fast(na.port) << "(white=" << white << ", last_seen: " << (last_seen_stamp?misc_utils::get_time_interval_string(time(NULL) - last_seen_stamp):"never" ) << ")..."); + LOG_PRINT_L1("Connecting to " << epee::string_tools::get_ip_string_from_int32(na.ip) << ":" + << epee::string_tools::num_to_string_fast(na.port) << "(white=" << white << ", last_seen: " + << (last_seen_stamp ? epee::misc_utils::get_time_interval_string(time(NULL) - last_seen_stamp):"never") + << ")..."); typename net_server::t_connection_context con = AUTO_VAL_INIT(con); - bool res = m_net_server.connect(string_tools::get_ip_string_from_int32(na.ip), - string_tools::num_to_string_fast(na.port), + bool res = m_net_server.connect(epee::string_tools::get_ip_string_from_int32(na.ip), + epee::string_tools::num_to_string_fast(na.port), m_config.m_net_config.connection_timeout, con); + if(!res) { - LOG_PRINT_L0("Connect failed to " - << string_tools::get_ip_string_from_int32(na.ip) - << ":" << string_tools::num_to_string_fast(na.port) + bool is_priority = is_priority_node(na); + LOG_PRINT_CC_PRIORITY_NODE(is_priority, con, "Connect failed to " + << epee::string_tools::get_ip_string_from_int32(na.ip) + << ":" << epee::string_tools::num_to_string_fast(na.port) /*<< ", try " << try_count*/); //m_peerlist.set_peer_unreachable(pe); return false; } + peerid_type pi = AUTO_VAL_INIT(pi); res = do_handshake_with_peer(pi, con, just_take_peerlist); + if(!res) { - LOG_PRINT_CC_L0(con, "Failed to HANDSHAKE with peer " - << string_tools::get_ip_string_from_int32(na.ip) - << ":" << string_tools::num_to_string_fast(na.port) + bool is_priority = is_priority_node(na); + LOG_PRINT_CC_PRIORITY_NODE(is_priority, con, "Failed to HANDSHAKE with peer " + << epee::string_tools::get_ip_string_from_int32(na.ip) + << ":" << epee::string_tools::num_to_string_fast(na.port) /*<< ", try " << try_count*/); return false; } + if(just_take_peerlist) { m_net_server.get_config_object().close(con.m_connection_id); @@ -549,6 +567,9 @@ namespace nodetool LOG_PRINT_CC_GREEN(con, "CONNECTION HANDSHAKED OK.", LOG_LEVEL_2); return true; } + +#undef LOG_PRINT_CC_PRIORITY_NODE + //----------------------------------------------------------------------------------- template bool node_server::make_new_connection_from_peerlist(bool use_white_list) @@ -582,7 +603,10 @@ namespace nodetool if(is_peer_used(pe)) continue; - LOG_PRINT_L1("Selected peer: " << pe.id << " " << string_tools::get_ip_string_from_int32(pe.adr.ip) << ":" << boost::lexical_cast(pe.adr.port) << "[white=" << use_white_list << "] last_seen: " << (pe.last_seen ? misc_utils::get_time_interval_string(time(NULL) - pe.last_seen) : "never")); + LOG_PRINT_L1("Selected peer: " << pe.id << " " << epee::string_tools::get_ip_string_from_int32(pe.adr.ip) + << ":" << boost::lexical_cast(pe.adr.port) + << "[white=" << use_white_list + << "] last_seen: " << (pe.last_seen ? epee::misc_utils::get_time_interval_string(time(NULL) - pe.last_seen) : "never")); if(!try_to_connect_and_handshake_with_new_peer(pe.adr, false, pe.last_seen, use_white_list)) continue; @@ -595,6 +619,10 @@ namespace nodetool template bool node_server::connections_maker() { + if (!connect_to_peerlist(m_exclusive_peers)) return false; + + if (!m_exclusive_peers.empty()) return true; + if(!m_peerlist.get_white_peers_count() && m_seed_nodes.size()) { size_t try_count = 0; @@ -616,15 +644,7 @@ namespace nodetool } } - for(const net_address& na: m_priority_peers) - { - if(m_net_server.is_stop_signal_sent()) - return false; - - if(is_addr_connected(na)) - continue; - try_to_connect_and_handshake_with_new_peer(na); - } + if (!connect_to_peerlist(m_priority_peers)) return false; size_t expected_white_connections = (m_config.m_net_config.connections_count*P2P_DEFAULT_WHITELIST_CONNECTIONS_PERCENT)/100; @@ -698,7 +718,7 @@ namespace nodetool bool node_server::peer_sync_idle_maker() { LOG_PRINT_L2("STARTED PEERLIST IDLE HANDSHAKE"); - typedef std::list > local_connects_type; + typedef std::list > local_connects_type; local_connects_type cncts; m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt) { @@ -725,7 +745,7 @@ namespace nodetool { if(be.last_seen > local_time) { - LOG_PRINT_RED_L0("FOUND FUTURE peerlist for entry " << string_tools::get_ip_string_from_int32(be.adr.ip) << ":" << be.adr.port << " last_seen: " << be.last_seen << ", local_time(on remote node):" << local_time); + LOG_PRINT_RED_L0("FOUND FUTURE peerlist for entry " << epee::string_tools::get_ip_string_from_int32(be.adr.ip) << ":" << be.adr.port << " last_seen: " << be.last_seen << ", local_time(on remote node):" << local_time); return false; } be.last_seen += delta; @@ -734,7 +754,7 @@ namespace nodetool } //----------------------------------------------------------------------------------- template - bool node_server::handle_remote_peerlist(const std::list& peerlist, time_t local_time, const net_utils::connection_context_base& context) + bool node_server::handle_remote_peerlist(const std::list& peerlist, time_t local_time, const epee::net_utils::connection_context_base& context) { int64_t delta = 0; std::list peerlist_ = peerlist; @@ -782,7 +802,7 @@ namespace nodetool return false; } crypto::public_key pk = AUTO_VAL_INIT(pk); - string_tools::hex_to_pod(P2P_STAT_TRUSTED_PUB_KEY, pk); + epee::string_tools::hex_to_pod(P2P_STAT_TRUSTED_PUB_KEY, pk); crypto::hash h = tools::get_proof_of_trust_hash(tr); if(!crypto::check_signature(h, pk, tr.sign)) { @@ -903,8 +923,8 @@ namespace nodetool uint32_t actual_ip = context.m_remote_ip; if(!m_peerlist.is_ip_allowed(actual_ip)) return false; - std::string ip = string_tools::get_ip_string_from_int32(actual_ip); - std::string port = string_tools::num_to_string_fast(node_data.my_port); + std::string ip = epee::string_tools::get_ip_string_from_int32(actual_ip); + std::string port = epee::string_tools::num_to_string_fast(node_data.my_port); peerid_type pr = node_data.peer_id; bool r = m_net_server.connect_async(ip, port, m_config.m_net_config.ping_connection_timeout, [cb, /*context,*/ ip, port, pr, this]( const typename net_server::t_connection_context& ping_context, @@ -922,12 +942,12 @@ namespace nodetool std::string port_=port; peerid_type pr_ = pr; auto cb_ = cb;*/ - bool inv_call_res = net_utils::async_invoke_remote_command2(ping_context.m_connection_id, COMMAND_PING::ID, req, m_net_server.get_config_object(), + bool inv_call_res = epee::net_utils::async_invoke_remote_command2(ping_context.m_connection_id, COMMAND_PING::ID, req, m_net_server.get_config_object(), [=](int code, const COMMAND_PING::response& rsp, p2p_connection_context& context) { if(code <= 0) { - LOG_PRINT_CC_L2(ping_context, "Failed to invoke COMMAND_PING to " << ip << ":" << port << "(" << code << ", " << levin::get_err_descr(code) << ")"); + LOG_PRINT_CC_L2(ping_context, "Failed to invoke COMMAND_PING to " << ip << ":" << port << "(" << code << ", " << epee::levin::get_err_descr(code) << ")"); return; } @@ -979,7 +999,7 @@ namespace nodetool if(arg.node_data.network_id != BYTECOIN_NETWORK) { - LOG_PRINT_CCONTEXT_L0("WRONG NETWORK AGENT CONNECTED! id=" << string_tools::get_str_from_guid_a(arg.node_data.network_id)); + LOG_PRINT_CCONTEXT_L0("WRONG NETWORK AGENT CONNECTED! id=" << epee::string_tools::get_str_from_guid_a(arg.node_data.network_id)); drop_connection(context); return 1; } @@ -1021,7 +1041,7 @@ namespace nodetool time(&pe.last_seen); pe.id = peer_id_l; this->m_peerlist.append_with_peer_white(pe); - LOG_PRINT_CCONTEXT_L2("PING SUCCESS " << string_tools::get_ip_string_from_int32(context.m_remote_ip) << ":" << port_l); + LOG_PRINT_CCONTEXT_L2("PING SUCCESS " << epee::string_tools::get_ip_string_from_int32(context.m_remote_ip) << ":" << port_l); }); } @@ -1066,9 +1086,9 @@ namespace nodetool std::stringstream ss; m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt) { - ss << string_tools::get_ip_string_from_int32(cntxt.m_remote_ip) << ":" << cntxt.m_remote_port + ss << epee::string_tools::get_ip_string_from_int32(cntxt.m_remote_ip) << ":" << cntxt.m_remote_port << " \t\tpeer_id " << cntxt.peer_id - << " \t\tconn_id " << string_tools::get_str_from_guid_a(cntxt.m_connection_id) << (cntxt.m_is_income ? " INC":" OUT") + << " \t\tconn_id " << epee::string_tools::get_str_from_guid_a(cntxt.m_connection_id) << (cntxt.m_is_income ? " INC":" OUT") << std::endl; return true; }); @@ -1079,13 +1099,51 @@ namespace nodetool template void node_server::on_connection_new(p2p_connection_context& context) { - LOG_PRINT_L2("["<< net_utils::print_connection_context(context) << "] NEW CONNECTION"); + LOG_PRINT_L2("["<< epee::net_utils::print_connection_context(context) << "] NEW CONNECTION"); } //----------------------------------------------------------------------------------- template void node_server::on_connection_close(p2p_connection_context& context) { - LOG_PRINT_L2("["<< net_utils::print_connection_context(context) << "] CLOSE CONNECTION"); + LOG_PRINT_L2("["<< epee::net_utils::print_connection_context(context) << "] CLOSE CONNECTION"); + } + + template + bool node_server::is_priority_node(const net_address& na) + { + return (std::find(m_priority_peers.begin(), m_priority_peers.end(), na) != m_priority_peers.end()) || (std::find(m_exclusive_peers.begin(), m_exclusive_peers.end(), na) != m_exclusive_peers.end()); + } + + template template + bool node_server::connect_to_peerlist(const Container& peers) + { + for(const net_address& na: peers) + { + if(m_net_server.is_stop_signal_sent()) + return false; + + if(is_addr_connected(na)) + continue; + + try_to_connect_and_handshake_with_new_peer(na); + } + + return true; + } + + template template + bool node_server::parse_peers_and_add_to_container(const boost::program_options::variables_map& vm, const command_line::arg_descriptor > & arg, Container& container) + { + std::vector perrs = command_line::get_arg(vm, arg); + + for(const std::string& pr_str: perrs) + { + nodetool::net_address na = AUTO_VAL_INIT(na); + bool r = parse_peer_from_string(na, pr_str); + CHECK_AND_ASSERT_MES(r, false, "Failed to parse address from string: " << pr_str); + container.push_back(na); + } + + return true; } - //----------------------------------------------------------------------------------- } diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 2c4e82085..8779f73d8 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -395,7 +395,7 @@ namespace cryptonote return false; } res.blocktemplate_blob = string_tools::buff_to_hex_nodelimer(block_blob); - + res.status = CORE_RPC_STATUS_OK; return true; } //------------------------------------------------------------------------------------------------------------------------------ @@ -423,7 +423,7 @@ namespace cryptonote error_resp.message = "Block not accepted"; return false; } - res.status = "OK"; + res.status = CORE_RPC_STATUS_OK; return true; } //------------------------------------------------------------------------------------------------------------------------------ diff --git a/src/serialization/crypto.h b/src/serialization/crypto.h index 89d3c9885..b7763ffeb 100644 --- a/src/serialization/crypto.h +++ b/src/serialization/crypto.h @@ -2,6 +2,8 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include + #include "serialization.h" #include "debug_archive.h" #include "crypto/chacha8.h" diff --git a/src/serialization/serialization.h b/src/serialization/serialization.h index 2e69ea0a3..7024fdc03 100644 --- a/src/serialization/serialization.h +++ b/src/serialization/serialization.h @@ -10,6 +10,7 @@ #include #include #include +#include template struct is_blob_type { typedef boost::false_type type; }; @@ -79,8 +80,10 @@ inline bool do_serialize(Archive &ar, T &v) if (!r || !ar.stream().good()) return false; \ } while(0); #define FIELDS(f) \ + do { \ bool r = ::do_serialize(ar, f); \ - if (!r || !ar.stream().good()) return false; + if (!r || !ar.stream().good()) return false; \ + } while(0); #define FIELD(f) \ do { \ ar.tag(#f); \ @@ -99,6 +102,7 @@ inline bool do_serialize(Archive &ar, T &v) ar.serialize_varint(f); \ if (!ar.stream().good()) return false; \ } while(0); + namespace serialization { namespace detail { diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 0f84b81de..b1fdd2688 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -202,7 +202,7 @@ bool simple_wallet::set_log(const std::vector &args) return true; } uint16_t l = 0; - if(!string_tools::get_xtype_from_string(l, args[0])) + if(!epee::string_tools::get_xtype_from_string(l, args[0])) { fail_msg_writer() << "wrong number format, use: set_log "; return true; @@ -229,8 +229,8 @@ bool simple_wallet::ask_wallet_create_if_needed() wallet_path = string_tools::trim(wallet_path); bool keys_file_exists; - bool wallet_file_exitst; - tools::wallet2::wallet_exists(wallet_path, keys_file_exists, wallet_file_exitst); + bool wallet_file_exists; + tools::wallet2::wallet_exists(wallet_path, keys_file_exists, wallet_file_exists); bool r; if(keys_file_exists) @@ -239,7 +239,7 @@ bool simple_wallet::ask_wallet_create_if_needed() r = true; }else { - if(!wallet_file_exitst) + if(!wallet_file_exists) { std::cout << "The wallet doesn't exist, generating new one" << std::endl; m_generate_new = wallet_path; @@ -749,7 +749,7 @@ bool simple_wallet::transfer(const std::vector &args_) } size_t fake_outs_count; - if(!string_tools::get_xtype_from_string(fake_outs_count, local_args[0])) + if(!epee::string_tools::get_xtype_from_string(fake_outs_count, local_args[0])) { fail_msg_writer() << "mixin_count should be non-negative integer, got " << local_args[0]; return true; diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h index 3aa0789ae..3dcaaeaa0 100644 --- a/src/simplewallet/simplewallet.h +++ b/src/simplewallet/simplewallet.h @@ -132,7 +132,7 @@ namespace cryptonote epee::console_handlers_binder m_cmd_binder; std::unique_ptr m_wallet; - net_utils::http::http_simple_client m_http_client; + epee::net_utils::http::http_simple_client m_http_client; refresh_progress_reporter_t m_refresh_progress_reporter; }; } diff --git a/src/version.h.in b/src/version.h.in index 01d2994f8..f171a8e6b 100644 --- a/src/version.h.in +++ b/src/version.h.in @@ -1,4 +1,4 @@ #define BUILD_COMMIT_ID "@VERSION@" -#define PROJECT_VERSION "0.8.8.2" +#define PROJECT_VERSION "0.8.8" #define PROJECT_VERSION_BUILD_NO "1" #define PROJECT_VERSION_LONG PROJECT_VERSION "." PROJECT_VERSION_BUILD_NO "(" BUILD_COMMIT_ID ")" diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index e8d67eec2..111b76117 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -455,14 +455,14 @@ void wallet2::generate(const std::string& wallet_, const std::string& password) store(); } //---------------------------------------------------------------------------------------------------- -void wallet2::wallet_exists(const std::string& file_path, bool& keys_file_exists, bool& wallet_file_exitst) +void wallet2::wallet_exists(const std::string& file_path, bool& keys_file_exists, bool& wallet_file_exists) { std::string keys_file, wallet_file; do_prepare_file_names(file_path, keys_file, wallet_file); boost::system::error_code ignore; keys_file_exists = boost::filesystem::exists(keys_file, ignore); - wallet_file_exitst = boost::filesystem::exists(wallet_file, ignore); + wallet_file_exists = boost::filesystem::exists(wallet_file, ignore); } //---------------------------------------------------------------------------------------------------- bool wallet2::prepare_file_names(const std::string& file_path) diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index edbf31f2d..d2016f696 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -144,7 +144,7 @@ namespace tools a & m_payments; } - static void wallet_exists(const std::string& file_path, bool& keys_file_exists, bool& wallet_file_exitst); + static void wallet_exists(const std::string& file_path, bool& keys_file_exists, bool& wallet_file_exists); private: bool store_keys(const std::string& keys_file_name, const std::string& password); @@ -326,7 +326,7 @@ namespace tools req.amounts.push_back(it->amount()); } - bool r = net_utils::invoke_http_bin_remote_command2(m_daemon_address + "/getrandom_outs.bin", req, daemon_resp, m_http_client, 200000); + bool r = epee::net_utils::invoke_http_bin_remote_command2(m_daemon_address + "/getrandom_outs.bin", req, daemon_resp, m_http_client, 200000); THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "getrandom_outs.bin"); THROW_WALLET_EXCEPTION_IF(daemon_resp.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "getrandom_outs.bin"); THROW_WALLET_EXCEPTION_IF(daemon_resp.status != CORE_RPC_STATUS_OK, error::get_random_outs_error, daemon_resp.status); @@ -421,7 +421,7 @@ namespace tools COMMAND_RPC_SEND_RAW_TX::request req; req.tx_as_hex = epee::string_tools::buff_to_hex_nodelimer(tx_to_blob(tx)); COMMAND_RPC_SEND_RAW_TX::response daemon_send_resp; - r = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/sendrawtransaction", req, daemon_send_resp, m_http_client, 200000); + r = epee::net_utils::invoke_http_json_remote_command2(m_daemon_address + "/sendrawtransaction", req, daemon_send_resp, m_http_client, 200000); THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "sendrawtransaction"); THROW_WALLET_EXCEPTION_IF(daemon_send_resp.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "sendrawtransaction"); THROW_WALLET_EXCEPTION_IF(daemon_send_resp.status != CORE_RPC_STATUS_OK, error::tx_rejected, tx, daemon_send_resp.status); diff --git a/tests/core_tests/chaingen_main.cpp b/tests/core_tests/chaingen_main.cpp index c575f9272..e6f287d74 100644 --- a/tests/core_tests/chaingen_main.cpp +++ b/tests/core_tests/chaingen_main.cpp @@ -21,15 +21,15 @@ namespace int main(int argc, char* argv[]) { TRY_ENTRY(); - string_tools::set_module_name_and_folder(argv[0]); + epee::string_tools::set_module_name_and_folder(argv[0]); //set up logging options - log_space::get_set_log_detalisation_level(true, LOG_LEVEL_3); - log_space::log_singletone::add_logger(LOGGER_CONSOLE, NULL, NULL, LOG_LEVEL_2); + epee::log_space::get_set_log_detalisation_level(true, LOG_LEVEL_3); + epee::log_space::log_singletone::add_logger(LOGGER_CONSOLE, NULL, NULL, LOG_LEVEL_2); - log_space::log_singletone::add_logger(LOGGER_FILE, - log_space::log_singletone::get_default_log_file().c_str(), - log_space::log_singletone::get_default_log_folder().c_str()); + epee::log_space::log_singletone::add_logger(LOGGER_FILE, + epee::log_space::log_singletone::get_default_log_file().c_str(), + epee::log_space::log_singletone::get_default_log_folder().c_str()); po::options_description desc_options("Allowed options"); command_line::add_arg(desc_options, command_line::arg_help); diff --git a/tests/performance_tests/main.cpp b/tests/performance_tests/main.cpp index 2ad503b83..72ee2ca6c 100644 --- a/tests/performance_tests/main.cpp +++ b/tests/performance_tests/main.cpp @@ -8,6 +8,7 @@ // tests #include "construct_tx.h" #include "check_ring_signature.h" +#include "cn_slow_hash.h" #include "derive_public_key.h" #include "derive_secret_key.h" #include "generate_key_derivation.h" @@ -56,6 +57,8 @@ int main(int argc, char** argv) TEST_PERFORMANCE0(test_derive_public_key); TEST_PERFORMANCE0(test_derive_secret_key); + TEST_PERFORMANCE0(test_cn_slow_hash); + std::cout << "Tests finished. Elapsed time: " << timer.elapsed_ms() / 1000 << " sec" << std::endl; return 0; -- cgit v1.2.3 From 785814cb1007f84da3a723c10d778206dbf2fb31 Mon Sep 17 00:00:00 2001 From: paybee Date: Mon, 26 May 2014 11:46:09 +0200 Subject: simplewallet exits when COMMAND is given as a command-line argument --- src/simplewallet/simplewallet.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'src/simplewallet/simplewallet.cpp') diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 0f84b81de..cc10de5cd 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -1054,14 +1054,20 @@ int main(int argc, char* argv[]) std::vector command = command_line::get_arg(vm, arg_command); if (!command.empty()) + { w.process_command(command); - - tools::signal_handler::install([&w] { w.stop(); - }); - w.run(); + w.deinit(); + } + else + { + tools::signal_handler::install([&w] { + w.stop(); + }); + w.run(); - w.deinit(); + w.deinit(); + } } return 1; //CATCH_ENTRY_L0("main", 1); -- cgit v1.2.3 From dfc092d3a973a184142fd9d86a2301f58b02396f Mon Sep 17 00:00:00 2001 From: Neozaru Date: Wed, 28 May 2014 21:58:38 +0200 Subject: Fixed return status for '--help'. Fixed wallet name (use macro instead of 'bytecoin wallet' --- src/simplewallet/simplewallet.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/simplewallet/simplewallet.cpp') diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 0f84b81de..158fa1d4f 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -944,7 +944,7 @@ int main(int argc, char* argv[]) if (command_line::get_arg(vm, command_line::arg_help)) { - success_msg_writer() << "bytecoin wallet v" << PROJECT_VERSION_LONG; + success_msg_writer() << CRYPTONOTE_NAME << " wallet v" << PROJECT_VERSION_LONG; success_msg_writer() << "Usage: simplewallet [--wallet-file=|--generate-new-wallet=] [--daemon-address=:] []"; success_msg_writer() << desc_all << '\n' << w.get_commands_str(); return false; @@ -961,7 +961,7 @@ int main(int argc, char* argv[]) return true; }); if (!r) - return 1; + return 0; //set up logging options log_space::get_set_log_detalisation_level(true, LOG_LEVEL_2); -- cgit v1.2.3 From d2f44503a7d3d9cbf37bc1b44686b0b6f076212b Mon Sep 17 00:00:00 2001 From: Neozaru Date: Wed, 28 May 2014 22:21:52 +0200 Subject: Added '--exit-after-cmd' option in simplewallet --- src/simplewallet/simplewallet.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src/simplewallet/simplewallet.cpp') diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 158fa1d4f..b5f4b7a6f 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -38,6 +38,7 @@ namespace const command_line::arg_descriptor arg_daemon_address = {"daemon-address", "Use daemon instance at :", ""}; const command_line::arg_descriptor arg_daemon_host = {"daemon-host", "Use daemon instance at host instead of localhost", ""}; const command_line::arg_descriptor arg_password = {"password", "Wallet password", "", true}; + const command_line::arg_descriptor arg_exit_after_cmd = {"exit-after-cmd", "Will not enter in the CLI console after command execution. Default: false", ""}; const command_line::arg_descriptor arg_daemon_port = {"daemon-port", "Use daemon instance at port instead of 8081", 0}; const command_line::arg_descriptor arg_log_level = {"set_log", "", 0, true}; @@ -928,6 +929,7 @@ int main(int argc, char* argv[]) command_line::add_arg(desc_params, arg_daemon_host); command_line::add_arg(desc_params, arg_daemon_port); command_line::add_arg(desc_params, arg_command); + command_line::add_arg(desc_params, arg_exit_after_cmd); command_line::add_arg(desc_params, arg_log_level); tools::wallet_rpc_server::init_options(desc_params); @@ -1059,7 +1061,13 @@ int main(int argc, char* argv[]) tools::signal_handler::install([&w] { w.stop(); }); - w.run(); + + const std::string& exit_after_command = command_line::get_arg(vm, arg_exit_after_cmd); + + /* Enters in CLI mode only if --exit-after-cmd is not set to true */ + if ( !boost::iequals(exit_after_command,"true") && !boost::iequals(exit_after_command,"yes") ) { + w.run(); + } w.deinit(); } -- cgit v1.2.3 From 506fd372ec78f3cb5c492fc981bbaac7936be8aa Mon Sep 17 00:00:00 2001 From: Neozaru Date: Wed, 28 May 2014 22:27:59 +0200 Subject: simplewallet returns 0 when no error --- src/simplewallet/simplewallet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/simplewallet/simplewallet.cpp') diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index b5f4b7a6f..7485f5cb1 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -1071,6 +1071,6 @@ int main(int argc, char* argv[]) w.deinit(); } - return 1; + return 0; //CATCH_ENTRY_L0("main", 1); } -- cgit v1.2.3 From 117393d562fc9782efed0e1b25f6470d9f8102b2 Mon Sep 17 00:00:00 2001 From: Neozaru Date: Mon, 2 Jun 2014 00:22:42 +0200 Subject: Added 'payment_id' optional argument to 'transfer' wallet RPC method --- src/simplewallet/simplewallet.cpp | 17 ++--------------- src/wallet/wallet2.cpp | 14 ++++++++++++++ src/wallet/wallet2.h | 2 ++ src/wallet/wallet_rpc_server.cpp | 29 ++++++++++++++++++++++++++++- src/wallet/wallet_rpc_server_commans_defs.h | 2 ++ 5 files changed, 48 insertions(+), 16 deletions(-) (limited to 'src/simplewallet/simplewallet.cpp') diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index dc45d9d74..4cab12c22 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -64,19 +64,6 @@ namespace return err; } - bool parse_payment_id(const std::string& payment_id_str, crypto::hash& payment_id) - { - blobdata payment_id_data; - if(!string_tools::parse_hexstr_to_binbuff(payment_id_str, payment_id_data)) - return false; - - if(sizeof(crypto::hash) != payment_id_data.size()) - return false; - - payment_id = *reinterpret_cast(payment_id_data.data()); - return true; - } - class message_writer { public: @@ -680,7 +667,7 @@ bool simple_wallet::show_payments(const std::vector &args) for(std::string arg : args) { crypto::hash payment_id; - if(parse_payment_id(arg, payment_id)) + if(tools::wallet2::parse_payment_id(arg, payment_id)) { std::list payments; m_wallet->get_payments(payment_id, payments); @@ -763,7 +750,7 @@ bool simple_wallet::transfer(const std::vector &args_) local_args.pop_back(); crypto::hash payment_id; - bool r = parse_payment_id(payment_id_str, payment_id); + bool r = tools::wallet2::parse_payment_id(payment_id_str, payment_id); if(r) { std::string extra_nonce; diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 111b76117..fb1e5575b 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -19,6 +19,7 @@ using namespace epee; #include "profile_tools.h" #include "crypto/crypto.h" #include "serialization/binary_utils.h" +#include "cryptonote_protocol/blobdatatype.h" using namespace cryptonote; @@ -465,6 +466,19 @@ void wallet2::wallet_exists(const std::string& file_path, bool& keys_file_exists wallet_file_exists = boost::filesystem::exists(wallet_file, ignore); } //---------------------------------------------------------------------------------------------------- +bool wallet2::parse_payment_id(const std::string& payment_id_str, crypto::hash& payment_id) +{ + cryptonote::blobdata payment_id_data; + if(!epee::string_tools::parse_hexstr_to_binbuff(payment_id_str, payment_id_data)) + return false; + + if(sizeof(crypto::hash) != payment_id_data.size()) + return false; + + payment_id = *reinterpret_cast(payment_id_data.data()); + return true; +} +//---------------------------------------------------------------------------------------------------- bool wallet2::prepare_file_names(const std::string& file_path) { do_prepare_file_names(file_path, m_keys_file, m_wallet_file); diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index f90fc4fac..9ca586425 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -151,6 +151,8 @@ namespace tools static void wallet_exists(const std::string& file_path, bool& keys_file_exists, bool& wallet_file_exists); + static bool parse_payment_id(const std::string& payment_id_str, crypto::hash& payment_id); + private: bool store_keys(const std::string& keys_file_name, const std::string& password); void load_keys(const std::string& keys_file_name, const std::string& password); diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index 55f81aacc..af195cfcc 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -102,10 +102,37 @@ namespace tools de.amount = it->amount; dsts.push_back(de); } + + std::vector extra; + if (!req.payment_id.empty()) { + + /* Just to clarify */ + const std::string& payment_id_str = req.payment_id; + + crypto::hash payment_id; + /* Parse payment ID */ + if (!wallet2::parse_payment_id(payment_id_str, payment_id)) { + er.code = WALLET_RPC_ERROR_CODE_WRONG_PAYMENT_ID; + er.message = "Payment id has invalid format: \"" + payment_id_str + "\", expected 64-character string"; + return false; + } + + std::string extra_nonce; + cryptonote::set_payment_id_to_tx_extra_nonce(extra_nonce, payment_id); + + /* Append Payment ID data into extra */ + if (!cryptonote::add_extra_nonce_to_tx_extra(extra, extra_nonce)) { + er.code = WALLET_RPC_ERROR_CODE_WRONG_PAYMENT_ID; + er.message = "Something went wront with payment_id. Please check its format: \"" + payment_id_str + "\", expected 64-character string"; + return false; + } + + } + try { cryptonote::transaction tx; - m_wallet.transfer(dsts, req.mixin, req.unlock_time, req.fee, std::vector(), tx); + m_wallet.transfer(dsts, req.mixin, req.unlock_time, req.fee, extra, tx); res.tx_hash = boost::lexical_cast(cryptonote::get_transaction_hash(tx)); return true; } diff --git a/src/wallet/wallet_rpc_server_commans_defs.h b/src/wallet/wallet_rpc_server_commans_defs.h index cc005b29c..df05b4e0a 100644 --- a/src/wallet/wallet_rpc_server_commans_defs.h +++ b/src/wallet/wallet_rpc_server_commans_defs.h @@ -70,12 +70,14 @@ namespace wallet_rpc uint64_t fee; uint64_t mixin; uint64_t unlock_time; + std::string payment_id; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(destinations) KV_SERIALIZE(fee) KV_SERIALIZE(mixin) KV_SERIALIZE(unlock_time) + KV_SERIALIZE(payment_id) END_KV_SERIALIZE_MAP() }; -- cgit v1.2.3 From 4f382b383005d09f6056371d0fecdc8b6ce37a08 Mon Sep 17 00:00:00 2001 From: Thomas Winget Date: Wed, 4 Jun 2014 18:59:47 -0400 Subject: most functions prototyped/modified for wallet recovery --- src/crypto/crypto.cpp | 6 + src/crypto/electrum-words.cpp | 29 + src/crypto/electrum-words.h | 3276 +++++++++++++++++++++++++++++++++++++ src/cryptonote_core/account.cpp | 2 +- src/cryptonote_core/account.h | 2 +- src/simplewallet/simplewallet.cpp | 35 +- src/simplewallet/simplewallet.h | 10 +- src/wallet/wallet2.cpp | 6 +- src/wallet/wallet2.h | 3 +- src/wallet/wallet_errors.h | 11 + 10 files changed, 3371 insertions(+), 9 deletions(-) create mode 100644 src/crypto/electrum-words.cpp create mode 100644 src/crypto/electrum-words.h (limited to 'src/simplewallet/simplewallet.cpp') diff --git a/src/crypto/crypto.cpp b/src/crypto/crypto.cpp index f5f525700..31fc31d5b 100644 --- a/src/crypto/crypto.cpp +++ b/src/crypto/crypto.cpp @@ -50,6 +50,7 @@ namespace crypto { return &reinterpret_cast(scalar); } + /* generate a random 32-byte (256-bit) integer and copy it to res */ static inline void random_scalar(ec_scalar &res) { unsigned char tmp[64]; generate_random_bytes(64, tmp); @@ -62,6 +63,11 @@ namespace crypto { sc_reduce32(&res); } + /* + * generate public and secret keys from a random 256-bit integer + * TODO: allow specifiying random value (for wallet recovery) + * + */ void crypto_ops::generate_keys(public_key &pub, secret_key &sec) { lock_guard lock(random_lock); ge_p3 point; diff --git a/src/crypto/electrum-words.cpp b/src/crypto/electrum-words.cpp new file mode 100644 index 000000000..cb01c9203 --- /dev/null +++ b/src/crypto/electrum-words.cpp @@ -0,0 +1,29 @@ +/* + * This file and its header file are for translating Electrum-style word lists + * into their equivalent byte representations for cross-compatibility with + * that method of "backing up" one's wallet keys. + */ + +#include +#include +#include "crypto/crypto.h" // for declaration of crypto::secret_key + +#include "crypto/electrum-words.h" + +namespace crypto +{ + namespace ElectrumWords + { + + bool words_to_bytes(const std::string& words, crypto::secret_key& dst) + { + return false; + } + bool bytes_to_words(const crypto::secret_key& src, std::string& words) + { + return false; + } + + } // namespace ElectrumWords + +} // namespace crypto diff --git a/src/crypto/electrum-words.h b/src/crypto/electrum-words.h new file mode 100644 index 000000000..6b8291047 --- /dev/null +++ b/src/crypto/electrum-words.h @@ -0,0 +1,3276 @@ +/* + * This file and its cpp file are for translating Electrum-style word lists + * into their equivalent byte representations for cross-compatibility with + * that method of "backing up" one's wallet keys. + */ + +#include +#include +#include "crypto/crypto.h" // for declaration of crypto::secret_key + +namespace crypto +{ + namespace ElectrumWords + { + bool words_to_bytes(const std::string& words, crypto::secret_key& dst); + bool bytes_to_words(const crypto::secret_key& src, std::string& words); + + const std::map wordsMap = { + {"like", 0}, + {"just", 1}, + {"love", 2}, + {"know", 3}, + {"never", 4}, + {"want", 5}, + {"time", 6}, + {"out", 7}, + {"there", 8}, + {"make", 9}, + {"look", 10}, + {"eye", 11}, + {"down", 12}, + {"only", 13}, + {"think", 14}, + {"heart", 15}, + {"back", 16}, + {"then", 17}, + {"into", 18}, + {"about", 19}, + {"more", 20}, + {"away", 21}, + {"still", 22}, + {"them", 23}, + {"take", 24}, + {"thing", 25}, + {"even", 26}, + {"through", 27}, + {"long", 28}, + {"always", 29}, + {"world", 30}, + {"too", 31}, + {"friend", 32}, + {"tell", 33}, + {"try", 34}, + {"hand", 35}, + {"thought", 36}, + {"over", 37}, + {"here", 38}, + {"other", 39}, + {"need", 40}, + {"smile", 41}, + {"again", 42}, + {"much", 43}, + {"cry", 44}, + {"been", 45}, + {"night", 46}, + {"ever", 47}, + {"little", 48}, + {"said", 49}, + {"end", 50}, + {"some", 51}, + {"those", 52}, + {"around", 53}, + {"mind", 54}, + {"people", 55}, + {"girl", 56}, + {"leave", 57}, + {"dream", 58}, + {"left", 59}, + {"turn", 60}, + {"myself", 61}, + {"give", 62}, + {"nothing", 63}, + {"really", 64}, + {"off", 65}, + {"before", 66}, + {"something", 67}, + {"find", 68}, + {"walk", 69}, + {"wish", 70}, + {"good", 71}, + {"once", 72}, + {"place", 73}, + {"ask", 74}, + {"stop", 75}, + {"keep", 76}, + {"watch", 77}, + {"seem", 78}, + {"everything", 79}, + {"wait", 80}, + {"got", 81}, + {"yet", 82}, + {"made", 83}, + {"remember", 84}, + {"start", 85}, + {"alone", 86}, + {"run", 87}, + {"hope", 88}, + {"maybe", 89}, + {"believe", 90}, + {"body", 91}, + {"hate", 92}, + {"after", 93}, + {"close", 94}, + {"talk", 95}, + {"stand", 96}, + {"own", 97}, + {"each", 98}, + {"hurt", 99}, + {"help", 100}, + {"home", 101}, + {"god", 102}, + {"soul", 103}, + {"new", 104}, + {"many", 105}, + {"two", 106}, + {"inside", 107}, + {"should", 108}, + {"true", 109}, + {"first", 110}, + {"fear", 111}, + {"mean", 112}, + {"better", 113}, + {"play", 114}, + {"another", 115}, + {"gone", 116}, + {"change", 117}, + {"use", 118}, + {"wonder", 119}, + {"someone", 120}, + {"hair", 121}, + {"cold", 122}, + {"open", 123}, + {"best", 124}, + {"any", 125}, + {"behind", 126}, + {"happen", 127}, + {"water", 128}, + {"dark", 129}, + {"laugh", 130}, + {"stay", 131}, + {"forever", 132}, + {"name", 133}, + {"work", 134}, + {"show", 135}, + {"sky", 136}, + {"break", 137}, + {"came", 138}, + {"deep", 139}, + {"door", 140}, + {"put", 141}, + {"black", 142}, + {"together", 143}, + {"upon", 144}, + {"happy", 145}, + {"such", 146}, + {"great", 147}, + {"white", 148}, + {"matter", 149}, + {"fill", 150}, + {"past", 151}, + {"please", 152}, + {"burn", 153}, + {"cause", 154}, + {"enough", 155}, + {"touch", 156}, + {"moment", 157}, + {"soon", 158}, + {"voice", 159}, + {"scream", 160}, + {"anything", 161}, + {"stare", 162}, + {"sound", 163}, + {"red", 164}, + {"everyone", 165}, + {"hide", 166}, + {"kiss", 167}, + {"truth", 168}, + {"death", 169}, + {"beautiful", 170}, + {"mine", 171}, + {"blood", 172}, + {"broken", 173}, + {"very", 174}, + {"pass", 175}, + {"next", 176}, + {"forget", 177}, + {"tree", 178}, + {"wrong", 179}, + {"air", 180}, + {"mother", 181}, + {"understand", 182}, + {"lip", 183}, + {"hit", 184}, + {"wall", 185}, + {"memory", 186}, + {"sleep", 187}, + {"free", 188}, + {"high", 189}, + {"realize", 190}, + {"school", 191}, + {"might", 192}, + {"skin", 193}, + {"sweet", 194}, + {"perfect", 195}, + {"blue", 196}, + {"kill", 197}, + {"breath", 198}, + {"dance", 199}, + {"against", 200}, + {"fly", 201}, + {"between", 202}, + {"grow", 203}, + {"strong", 204}, + {"under", 205}, + {"listen", 206}, + {"bring", 207}, + {"sometimes", 208}, + {"speak", 209}, + {"pull", 210}, + {"person", 211}, + {"become", 212}, + {"family", 213}, + {"begin", 214}, + {"ground", 215}, + {"real", 216}, + {"small", 217}, + {"father", 218}, + {"sure", 219}, + {"feet", 220}, + {"rest", 221}, + {"young", 222}, + {"finally", 223}, + {"land", 224}, + {"across", 225}, + {"today", 226}, + {"different", 227}, + {"guy", 228}, + {"line", 229}, + {"fire", 230}, + {"reason", 231}, + {"reach", 232}, + {"second", 233}, + {"slowly", 234}, + {"write", 235}, + {"eat", 236}, + {"smell", 237}, + {"mouth", 238}, + {"step", 239}, + {"learn", 240}, + {"three", 241}, + {"floor", 242}, + {"promise", 243}, + {"breathe", 244}, + {"darkness", 245}, + {"push", 246}, + {"earth", 247}, + {"guess", 248}, + {"save", 249}, + {"song", 250}, + {"above", 251}, + {"along", 252}, + {"both", 253}, + {"color", 254}, + {"house", 255}, + {"almost", 256}, + {"sorry", 257}, + {"anymore", 258}, + {"brother", 259}, + {"okay", 260}, + {"dear", 261}, + {"game", 262}, + {"fade", 263}, + {"already", 264}, + {"apart", 265}, + {"warm", 266}, + {"beauty", 267}, + {"heard", 268}, + {"notice", 269}, + {"question", 270}, + {"shine", 271}, + {"began", 272}, + {"piece", 273}, + {"whole", 274}, + {"shadow", 275}, + {"secret", 276}, + {"street", 277}, + {"within", 278}, + {"finger", 279}, + {"point", 280}, + {"morning", 281}, + {"whisper", 282}, + {"child", 283}, + {"moon", 284}, + {"green", 285}, + {"story", 286}, + {"glass", 287}, + {"kid", 288}, + {"silence", 289}, + {"since", 290}, + {"soft", 291}, + {"yourself", 292}, + {"empty", 293}, + {"shall", 294}, + {"angel", 295}, + {"answer", 296}, + {"baby", 297}, + {"bright", 298}, + {"dad", 299}, + {"path", 300}, + {"worry", 301}, + {"hour", 302}, + {"drop", 303}, + {"follow", 304}, + {"power", 305}, + {"war", 306}, + {"half", 307}, + {"flow", 308}, + {"heaven", 309}, + {"act", 310}, + {"chance", 311}, + {"fact", 312}, + {"least", 313}, + {"tired", 314}, + {"children", 315}, + {"near", 316}, + {"quite", 317}, + {"afraid", 318}, + {"rise", 319}, + {"sea", 320}, + {"taste", 321}, + {"window", 322}, + {"cover", 323}, + {"nice", 324}, + {"trust", 325}, + {"lot", 326}, + {"sad", 327}, + {"cool", 328}, + {"force", 329}, + {"peace", 330}, + {"return", 331}, + {"blind", 332}, + {"easy", 333}, + {"ready", 334}, + {"roll", 335}, + {"rose", 336}, + {"drive", 337}, + {"held", 338}, + {"music", 339}, + {"beneath", 340}, + {"hang", 341}, + {"mom", 342}, + {"paint", 343}, + {"emotion", 344}, + {"quiet", 345}, + {"clear", 346}, + {"cloud", 347}, + {"few", 348}, + {"pretty", 349}, + {"bird", 350}, + {"outside", 351}, + {"paper", 352}, + {"picture", 353}, + {"front", 354}, + {"rock", 355}, + {"simple", 356}, + {"anyone", 357}, + {"meant", 358}, + {"reality", 359}, + {"road", 360}, + {"sense", 361}, + {"waste", 362}, + {"bit", 363}, + {"leaf", 364}, + {"thank", 365}, + {"happiness", 366}, + {"meet", 367}, + {"men", 368}, + {"smoke", 369}, + {"truly", 370}, + {"decide", 371}, + {"self", 372}, + {"age", 373}, + {"book", 374}, + {"form", 375}, + {"alive", 376}, + {"carry", 377}, + {"escape", 378}, + {"damn", 379}, + {"instead", 380}, + {"able", 381}, + {"ice", 382}, + {"minute", 383}, + {"throw", 384}, + {"catch", 385}, + {"leg", 386}, + {"ring", 387}, + {"course", 388}, + {"goodbye", 389}, + {"lead", 390}, + {"poem", 391}, + {"sick", 392}, + {"corner", 393}, + {"desire", 394}, + {"known", 395}, + {"problem", 396}, + {"remind", 397}, + {"shoulder", 398}, + {"suppose", 399}, + {"toward", 400}, + {"wave", 401}, + {"drink", 402}, + {"jump", 403}, + {"woman", 404}, + {"pretend", 405}, + {"sister", 406}, + {"week", 407}, + {"human", 408}, + {"joy", 409}, + {"crack", 410}, + {"grey", 411}, + {"pray", 412}, + {"surprise", 413}, + {"dry", 414}, + {"knee", 415}, + {"less", 416}, + {"search", 417}, + {"bleed", 418}, + {"caught", 419}, + {"clean", 420}, + {"embrace", 421}, + {"future", 422}, + {"king", 423}, + {"son", 424}, + {"sorrow", 425}, + {"chest", 426}, + {"hug", 427}, + {"remain", 428}, + {"sat", 429}, + {"worth", 430}, + {"blow", 431}, + {"daddy", 432}, + {"final", 433}, + {"parent", 434}, + {"tight", 435}, + {"also", 436}, + {"create", 437}, + {"lonely", 438}, + {"safe", 439}, + {"cross", 440}, + {"dress", 441}, + {"evil", 442}, + {"silent", 443}, + {"bone", 444}, + {"fate", 445}, + {"perhaps", 446}, + {"anger", 447}, + {"class", 448}, + {"scar", 449}, + {"snow", 450}, + {"tiny", 451}, + {"tonight", 452}, + {"continue", 453}, + {"control", 454}, + {"dog", 455}, + {"edge", 456}, + {"mirror", 457}, + {"month", 458}, + {"suddenly", 459}, + {"comfort", 460}, + {"given", 461}, + {"loud", 462}, + {"quickly", 463}, + {"gaze", 464}, + {"plan", 465}, + {"rush", 466}, + {"stone", 467}, + {"town", 468}, + {"battle", 469}, + {"ignore", 470}, + {"spirit", 471}, + {"stood", 472}, + {"stupid", 473}, + {"yours", 474}, + {"brown", 475}, + {"build", 476}, + {"dust", 477}, + {"hey", 478}, + {"kept", 479}, + {"pay", 480}, + {"phone", 481}, + {"twist", 482}, + {"although", 483}, + {"ball", 484}, + {"beyond", 485}, + {"hidden", 486}, + {"nose", 487}, + {"taken", 488}, + {"fail", 489}, + {"float", 490}, + {"pure", 491}, + {"somehow", 492}, + {"wash", 493}, + {"wrap", 494}, + {"angry", 495}, + {"cheek", 496}, + {"creature", 497}, + {"forgotten", 498}, + {"heat", 499}, + {"rip", 500}, + {"single", 501}, + {"space", 502}, + {"special", 503}, + {"weak", 504}, + {"whatever", 505}, + {"yell", 506}, + {"anyway", 507}, + {"blame", 508}, + {"job", 509}, + {"choose", 510}, + {"country", 511}, + {"curse", 512}, + {"drift", 513}, + {"echo", 514}, + {"figure", 515}, + {"grew", 516}, + {"laughter", 517}, + {"neck", 518}, + {"suffer", 519}, + {"worse", 520}, + {"yeah", 521}, + {"disappear", 522}, + {"foot", 523}, + {"forward", 524}, + {"knife", 525}, + {"mess", 526}, + {"somewhere", 527}, + {"stomach", 528}, + {"storm", 529}, + {"beg", 530}, + {"idea", 531}, + {"lift", 532}, + {"offer", 533}, + {"breeze", 534}, + {"field", 535}, + {"five", 536}, + {"often", 537}, + {"simply", 538}, + {"stuck", 539}, + {"win", 540}, + {"allow", 541}, + {"confuse", 542}, + {"enjoy", 543}, + {"except", 544}, + {"flower", 545}, + {"seek", 546}, + {"strength", 547}, + {"calm", 548}, + {"grin", 549}, + {"gun", 550}, + {"heavy", 551}, + {"hill", 552}, + {"large", 553}, + {"ocean", 554}, + {"shoe", 555}, + {"sigh", 556}, + {"straight", 557}, + {"summer", 558}, + {"tongue", 559}, + {"accept", 560}, + {"crazy", 561}, + {"everyday", 562}, + {"exist", 563}, + {"grass", 564}, + {"mistake", 565}, + {"sent", 566}, + {"shut", 567}, + {"surround", 568}, + {"table", 569}, + {"ache", 570}, + {"brain", 571}, + {"destroy", 572}, + {"heal", 573}, + {"nature", 574}, + {"shout", 575}, + {"sign", 576}, + {"stain", 577}, + {"choice", 578}, + {"doubt", 579}, + {"glance", 580}, + {"glow", 581}, + {"mountain", 582}, + {"queen", 583}, + {"stranger", 584}, + {"throat", 585}, + {"tomorrow", 586}, + {"city", 587}, + {"either", 588}, + {"fish", 589}, + {"flame", 590}, + {"rather", 591}, + {"shape", 592}, + {"spin", 593}, + {"spread", 594}, + {"ash", 595}, + {"distance", 596}, + {"finish", 597}, + {"image", 598}, + {"imagine", 599}, + {"important", 600}, + {"nobody", 601}, + {"shatter", 602}, + {"warmth", 603}, + {"became", 604}, + {"feed", 605}, + {"flesh", 606}, + {"funny", 607}, + {"lust", 608}, + {"shirt", 609}, + {"trouble", 610}, + {"yellow", 611}, + {"attention", 612}, + {"bare", 613}, + {"bite", 614}, + {"money", 615}, + {"protect", 616}, + {"amaze", 617}, + {"appear", 618}, + {"born", 619}, + {"choke", 620}, + {"completely", 621}, + {"daughter", 622}, + {"fresh", 623}, + {"friendship", 624}, + {"gentle", 625}, + {"probably", 626}, + {"six", 627}, + {"deserve", 628}, + {"expect", 629}, + {"grab", 630}, + {"middle", 631}, + {"nightmare", 632}, + {"river", 633}, + {"thousand", 634}, + {"weight", 635}, + {"worst", 636}, + {"wound", 637}, + {"barely", 638}, + {"bottle", 639}, + {"cream", 640}, + {"regret", 641}, + {"relationship", 642}, + {"stick", 643}, + {"test", 644}, + {"crush", 645}, + {"endless", 646}, + {"fault", 647}, + {"itself", 648}, + {"rule", 649}, + {"spill", 650}, + {"art", 651}, + {"circle", 652}, + {"join", 653}, + {"kick", 654}, + {"mask", 655}, + {"master", 656}, + {"passion", 657}, + {"quick", 658}, + {"raise", 659}, + {"smooth", 660}, + {"unless", 661}, + {"wander", 662}, + {"actually", 663}, + {"broke", 664}, + {"chair", 665}, + {"deal", 666}, + {"favorite", 667}, + {"gift", 668}, + {"note", 669}, + {"number", 670}, + {"sweat", 671}, + {"box", 672}, + {"chill", 673}, + {"clothes", 674}, + {"lady", 675}, + {"mark", 676}, + {"park", 677}, + {"poor", 678}, + {"sadness", 679}, + {"tie", 680}, + {"animal", 681}, + {"belong", 682}, + {"brush", 683}, + {"consume", 684}, + {"dawn", 685}, + {"forest", 686}, + {"innocent", 687}, + {"pen", 688}, + {"pride", 689}, + {"stream", 690}, + {"thick", 691}, + {"clay", 692}, + {"complete", 693}, + {"count", 694}, + {"draw", 695}, + {"faith", 696}, + {"press", 697}, + {"silver", 698}, + {"struggle", 699}, + {"surface", 700}, + {"taught", 701}, + {"teach", 702}, + {"wet", 703}, + {"bless", 704}, + {"chase", 705}, + {"climb", 706}, + {"enter", 707}, + {"letter", 708}, + {"melt", 709}, + {"metal", 710}, + {"movie", 711}, + {"stretch", 712}, + {"swing", 713}, + {"vision", 714}, + {"wife", 715}, + {"beside", 716}, + {"crash", 717}, + {"forgot", 718}, + {"guide", 719}, + {"haunt", 720}, + {"joke", 721}, + {"knock", 722}, + {"plant", 723}, + {"pour", 724}, + {"prove", 725}, + {"reveal", 726}, + {"steal", 727}, + {"stuff", 728}, + {"trip", 729}, + {"wood", 730}, + {"wrist", 731}, + {"bother", 732}, + {"bottom", 733}, + {"crawl", 734}, + {"crowd", 735}, + {"fix", 736}, + {"forgive", 737}, + {"frown", 738}, + {"grace", 739}, + {"loose", 740}, + {"lucky", 741}, + {"party", 742}, + {"release", 743}, + {"surely", 744}, + {"survive", 745}, + {"teacher", 746}, + {"gently", 747}, + {"grip", 748}, + {"speed", 749}, + {"suicide", 750}, + {"travel", 751}, + {"treat", 752}, + {"vein", 753}, + {"written", 754}, + {"cage", 755}, + {"chain", 756}, + {"conversation", 757}, + {"date", 758}, + {"enemy", 759}, + {"however", 760}, + {"interest", 761}, + {"million", 762}, + {"page", 763}, + {"pink", 764}, + {"proud", 765}, + {"sway", 766}, + {"themselves", 767}, + {"winter", 768}, + {"church", 769}, + {"cruel", 770}, + {"cup", 771}, + {"demon", 772}, + {"experience", 773}, + {"freedom", 774}, + {"pair", 775}, + {"pop", 776}, + {"purpose", 777}, + {"respect", 778}, + {"shoot", 779}, + {"softly", 780}, + {"state", 781}, + {"strange", 782}, + {"bar", 783}, + {"birth", 784}, + {"curl", 785}, + {"dirt", 786}, + {"excuse", 787}, + {"lord", 788}, + {"lovely", 789}, + {"monster", 790}, + {"order", 791}, + {"pack", 792}, + {"pants", 793}, + {"pool", 794}, + {"scene", 795}, + {"seven", 796}, + {"shame", 797}, + {"slide", 798}, + {"ugly", 799}, + {"among", 800}, + {"blade", 801}, + {"blonde", 802}, + {"closet", 803}, + {"creek", 804}, + {"deny", 805}, + {"drug", 806}, + {"eternity", 807}, + {"gain", 808}, + {"grade", 809}, + {"handle", 810}, + {"key", 811}, + {"linger", 812}, + {"pale", 813}, + {"prepare", 814}, + {"swallow", 815}, + {"swim", 816}, + {"tremble", 817}, + {"wheel", 818}, + {"won", 819}, + {"cast", 820}, + {"cigarette", 821}, + {"claim", 822}, + {"college", 823}, + {"direction", 824}, + {"dirty", 825}, + {"gather", 826}, + {"ghost", 827}, + {"hundred", 828}, + {"loss", 829}, + {"lung", 830}, + {"orange", 831}, + {"present", 832}, + {"swear", 833}, + {"swirl", 834}, + {"twice", 835}, + {"wild", 836}, + {"bitter", 837}, + {"blanket", 838}, + {"doctor", 839}, + {"everywhere", 840}, + {"flash", 841}, + {"grown", 842}, + {"knowledge", 843}, + {"numb", 844}, + {"pressure", 845}, + {"radio", 846}, + {"repeat", 847}, + {"ruin", 848}, + {"spend", 849}, + {"unknown", 850}, + {"buy", 851}, + {"clock", 852}, + {"devil", 853}, + {"early", 854}, + {"false", 855}, + {"fantasy", 856}, + {"pound", 857}, + {"precious", 858}, + {"refuse", 859}, + {"sheet", 860}, + {"teeth", 861}, + {"welcome", 862}, + {"add", 863}, + {"ahead", 864}, + {"block", 865}, + {"bury", 866}, + {"caress", 867}, + {"content", 868}, + {"depth", 869}, + {"despite", 870}, + {"distant", 871}, + {"marry", 872}, + {"purple", 873}, + {"threw", 874}, + {"whenever", 875}, + {"bomb", 876}, + {"dull", 877}, + {"easily", 878}, + {"grasp", 879}, + {"hospital", 880}, + {"innocence", 881}, + {"normal", 882}, + {"receive", 883}, + {"reply", 884}, + {"rhyme", 885}, + {"shade", 886}, + {"someday", 887}, + {"sword", 888}, + {"toe", 889}, + {"visit", 890}, + {"asleep", 891}, + {"bought", 892}, + {"center", 893}, + {"consider", 894}, + {"flat", 895}, + {"hero", 896}, + {"history", 897}, + {"ink", 898}, + {"insane", 899}, + {"muscle", 900}, + {"mystery", 901}, + {"pocket", 902}, + {"reflection", 903}, + {"shove", 904}, + {"silently", 905}, + {"smart", 906}, + {"soldier", 907}, + {"spot", 908}, + {"stress", 909}, + {"train", 910}, + {"type", 911}, + {"view", 912}, + {"whether", 913}, + {"bus", 914}, + {"energy", 915}, + {"explain", 916}, + {"holy", 917}, + {"hunger", 918}, + {"inch", 919}, + {"magic", 920}, + {"mix", 921}, + {"noise", 922}, + {"nowhere", 923}, + {"prayer", 924}, + {"presence", 925}, + {"shock", 926}, + {"snap", 927}, + {"spider", 928}, + {"study", 929}, + {"thunder", 930}, + {"trail", 931}, + {"admit", 932}, + {"agree", 933}, + {"bag", 934}, + {"bang", 935}, + {"bound", 936}, + {"butterfly", 937}, + {"cute", 938}, + {"exactly", 939}, + {"explode", 940}, + {"familiar", 941}, + {"fold", 942}, + {"further", 943}, + {"pierce", 944}, + {"reflect", 945}, + {"scent", 946}, + {"selfish", 947}, + {"sharp", 948}, + {"sink", 949}, + {"spring", 950}, + {"stumble", 951}, + {"universe", 952}, + {"weep", 953}, + {"women", 954}, + {"wonderful", 955}, + {"action", 956}, + {"ancient", 957}, + {"attempt", 958}, + {"avoid", 959}, + {"birthday", 960}, + {"branch", 961}, + {"chocolate", 962}, + {"core", 963}, + {"depress", 964}, + {"drunk", 965}, + {"especially", 966}, + {"focus", 967}, + {"fruit", 968}, + {"honest", 969}, + {"match", 970}, + {"palm", 971}, + {"perfectly", 972}, + {"pillow", 973}, + {"pity", 974}, + {"poison", 975}, + {"roar", 976}, + {"shift", 977}, + {"slightly", 978}, + {"thump", 979}, + {"truck", 980}, + {"tune", 981}, + {"twenty", 982}, + {"unable", 983}, + {"wipe", 984}, + {"wrote", 985}, + {"coat", 986}, + {"constant", 987}, + {"dinner", 988}, + {"drove", 989}, + {"egg", 990}, + {"eternal", 991}, + {"flight", 992}, + {"flood", 993}, + {"frame", 994}, + {"freak", 995}, + {"gasp", 996}, + {"glad", 997}, + {"hollow", 998}, + {"motion", 999}, + {"peer", 1000}, + {"plastic", 1001}, + {"root", 1002}, + {"screen", 1003}, + {"season", 1004}, + {"sting", 1005}, + {"strike", 1006}, + {"team", 1007}, + {"unlike", 1008}, + {"victim", 1009}, + {"volume", 1010}, + {"warn", 1011}, + {"weird", 1012}, + {"attack", 1013}, + {"await", 1014}, + {"awake", 1015}, + {"built", 1016}, + {"charm", 1017}, + {"crave", 1018}, + {"despair", 1019}, + {"fought", 1020}, + {"grant", 1021}, + {"grief", 1022}, + {"horse", 1023}, + {"limit", 1024}, + {"message", 1025}, + {"ripple", 1026}, + {"sanity", 1027}, + {"scatter", 1028}, + {"serve", 1029}, + {"split", 1030}, + {"string", 1031}, + {"trick", 1032}, + {"annoy", 1033}, + {"blur", 1034}, + {"boat", 1035}, + {"brave", 1036}, + {"clearly", 1037}, + {"cling", 1038}, + {"connect", 1039}, + {"fist", 1040}, + {"forth", 1041}, + {"imagination", 1042}, + {"iron", 1043}, + {"jock", 1044}, + {"judge", 1045}, + {"lesson", 1046}, + {"milk", 1047}, + {"misery", 1048}, + {"nail", 1049}, + {"naked", 1050}, + {"ourselves", 1051}, + {"poet", 1052}, + {"possible", 1053}, + {"princess", 1054}, + {"sail", 1055}, + {"size", 1056}, + {"snake", 1057}, + {"society", 1058}, + {"stroke", 1059}, + {"torture", 1060}, + {"toss", 1061}, + {"trace", 1062}, + {"wise", 1063}, + {"bloom", 1064}, + {"bullet", 1065}, + {"cell", 1066}, + {"check", 1067}, + {"cost", 1068}, + {"darling", 1069}, + {"during", 1070}, + {"footstep", 1071}, + {"fragile", 1072}, + {"hallway", 1073}, + {"hardly", 1074}, + {"horizon", 1075}, + {"invisible", 1076}, + {"journey", 1077}, + {"midnight", 1078}, + {"mud", 1079}, + {"nod", 1080}, + {"pause", 1081}, + {"relax", 1082}, + {"shiver", 1083}, + {"sudden", 1084}, + {"value", 1085}, + {"youth", 1086}, + {"abuse", 1087}, + {"admire", 1088}, + {"blink", 1089}, + {"breast", 1090}, + {"bruise", 1091}, + {"constantly", 1092}, + {"couple", 1093}, + {"creep", 1094}, + {"curve", 1095}, + {"difference", 1096}, + {"dumb", 1097}, + {"emptiness", 1098}, + {"gotta", 1099}, + {"honor", 1100}, + {"plain", 1101}, + {"planet", 1102}, + {"recall", 1103}, + {"rub", 1104}, + {"ship", 1105}, + {"slam", 1106}, + {"soar", 1107}, + {"somebody", 1108}, + {"tightly", 1109}, + {"weather", 1110}, + {"adore", 1111}, + {"approach", 1112}, + {"bond", 1113}, + {"bread", 1114}, + {"burst", 1115}, + {"candle", 1116}, + {"coffee", 1117}, + {"cousin", 1118}, + {"crime", 1119}, + {"desert", 1120}, + {"flutter", 1121}, + {"frozen", 1122}, + {"grand", 1123}, + {"heel", 1124}, + {"hello", 1125}, + {"language", 1126}, + {"level", 1127}, + {"movement", 1128}, + {"pleasure", 1129}, + {"powerful", 1130}, + {"random", 1131}, + {"rhythm", 1132}, + {"settle", 1133}, + {"silly", 1134}, + {"slap", 1135}, + {"sort", 1136}, + {"spoken", 1137}, + {"steel", 1138}, + {"threaten", 1139}, + {"tumble", 1140}, + {"upset", 1141}, + {"aside", 1142}, + {"awkward", 1143}, + {"bee", 1144}, + {"blank", 1145}, + {"board", 1146}, + {"button", 1147}, + {"card", 1148}, + {"carefully", 1149}, + {"complain", 1150}, + {"crap", 1151}, + {"deeply", 1152}, + {"discover", 1153}, + {"drag", 1154}, + {"dread", 1155}, + {"effort", 1156}, + {"entire", 1157}, + {"fairy", 1158}, + {"giant", 1159}, + {"gotten", 1160}, + {"greet", 1161}, + {"illusion", 1162}, + {"jeans", 1163}, + {"leap", 1164}, + {"liquid", 1165}, + {"march", 1166}, + {"mend", 1167}, + {"nervous", 1168}, + {"nine", 1169}, + {"replace", 1170}, + {"rope", 1171}, + {"spine", 1172}, + {"stole", 1173}, + {"terror", 1174}, + {"accident", 1175}, + {"apple", 1176}, + {"balance", 1177}, + {"boom", 1178}, + {"childhood", 1179}, + {"collect", 1180}, + {"demand", 1181}, + {"depression", 1182}, + {"eventually", 1183}, + {"faint", 1184}, + {"glare", 1185}, + {"goal", 1186}, + {"group", 1187}, + {"honey", 1188}, + {"kitchen", 1189}, + {"laid", 1190}, + {"limb", 1191}, + {"machine", 1192}, + {"mere", 1193}, + {"mold", 1194}, + {"murder", 1195}, + {"nerve", 1196}, + {"painful", 1197}, + {"poetry", 1198}, + {"prince", 1199}, + {"rabbit", 1200}, + {"shelter", 1201}, + {"shore", 1202}, + {"shower", 1203}, + {"soothe", 1204}, + {"stair", 1205}, + {"steady", 1206}, + {"sunlight", 1207}, + {"tangle", 1208}, + {"tease", 1209}, + {"treasure", 1210}, + {"uncle", 1211}, + {"begun", 1212}, + {"bliss", 1213}, + {"canvas", 1214}, + {"cheer", 1215}, + {"claw", 1216}, + {"clutch", 1217}, + {"commit", 1218}, + {"crimson", 1219}, + {"crystal", 1220}, + {"delight", 1221}, + {"doll", 1222}, + {"existence", 1223}, + {"express", 1224}, + {"fog", 1225}, + {"football", 1226}, + {"gay", 1227}, + {"goose", 1228}, + {"guard", 1229}, + {"hatred", 1230}, + {"illuminate", 1231}, + {"mass", 1232}, + {"math", 1233}, + {"mourn", 1234}, + {"rich", 1235}, + {"rough", 1236}, + {"skip", 1237}, + {"stir", 1238}, + {"student", 1239}, + {"style", 1240}, + {"support", 1241}, + {"thorn", 1242}, + {"tough", 1243}, + {"yard", 1244}, + {"yearn", 1245}, + {"yesterday", 1246}, + {"advice", 1247}, + {"appreciate", 1248}, + {"autumn", 1249}, + {"bank", 1250}, + {"beam", 1251}, + {"bowl", 1252}, + {"capture", 1253}, + {"carve", 1254}, + {"collapse", 1255}, + {"confusion", 1256}, + {"creation", 1257}, + {"dove", 1258}, + {"feather", 1259}, + {"girlfriend", 1260}, + {"glory", 1261}, + {"government", 1262}, + {"harsh", 1263}, + {"hop", 1264}, + {"inner", 1265}, + {"loser", 1266}, + {"moonlight", 1267}, + {"neighbor", 1268}, + {"neither", 1269}, + {"peach", 1270}, + {"pig", 1271}, + {"praise", 1272}, + {"screw", 1273}, + {"shield", 1274}, + {"shimmer", 1275}, + {"sneak", 1276}, + {"stab", 1277}, + {"subject", 1278}, + {"throughout", 1279}, + {"thrown", 1280}, + {"tower", 1281}, + {"twirl", 1282}, + {"wow", 1283}, + {"army", 1284}, + {"arrive", 1285}, + {"bathroom", 1286}, + {"bump", 1287}, + {"cease", 1288}, + {"cookie", 1289}, + {"couch", 1290}, + {"courage", 1291}, + {"dim", 1292}, + {"guilt", 1293}, + {"howl", 1294}, + {"hum", 1295}, + {"husband", 1296}, + {"insult", 1297}, + {"led", 1298}, + {"lunch", 1299}, + {"mock", 1300}, + {"mostly", 1301}, + {"natural", 1302}, + {"nearly", 1303}, + {"needle", 1304}, + {"nerd", 1305}, + {"peaceful", 1306}, + {"perfection", 1307}, + {"pile", 1308}, + {"price", 1309}, + {"remove", 1310}, + {"roam", 1311}, + {"sanctuary", 1312}, + {"serious", 1313}, + {"shiny", 1314}, + {"shook", 1315}, + {"sob", 1316}, + {"stolen", 1317}, + {"tap", 1318}, + {"vain", 1319}, + {"void", 1320}, + {"warrior", 1321}, + {"wrinkle", 1322}, + {"affection", 1323}, + {"apologize", 1324}, + {"blossom", 1325}, + {"bounce", 1326}, + {"bridge", 1327}, + {"cheap", 1328}, + {"crumble", 1329}, + {"decision", 1330}, + {"descend", 1331}, + {"desperately", 1332}, + {"dig", 1333}, + {"dot", 1334}, + {"flip", 1335}, + {"frighten", 1336}, + {"heartbeat", 1337}, + {"huge", 1338}, + {"lazy", 1339}, + {"lick", 1340}, + {"odd", 1341}, + {"opinion", 1342}, + {"process", 1343}, + {"puzzle", 1344}, + {"quietly", 1345}, + {"retreat", 1346}, + {"score", 1347}, + {"sentence", 1348}, + {"separate", 1349}, + {"situation", 1350}, + {"skill", 1351}, + {"soak", 1352}, + {"square", 1353}, + {"stray", 1354}, + {"taint", 1355}, + {"task", 1356}, + {"tide", 1357}, + {"underneath", 1358}, + {"veil", 1359}, + {"whistle", 1360}, + {"anywhere", 1361}, + {"bedroom", 1362}, + {"bid", 1363}, + {"bloody", 1364}, + {"burden", 1365}, + {"careful", 1366}, + {"compare", 1367}, + {"concern", 1368}, + {"curtain", 1369}, + {"decay", 1370}, + {"defeat", 1371}, + {"describe", 1372}, + {"double", 1373}, + {"dreamer", 1374}, + {"driver", 1375}, + {"dwell", 1376}, + {"evening", 1377}, + {"flare", 1378}, + {"flicker", 1379}, + {"grandma", 1380}, + {"guitar", 1381}, + {"harm", 1382}, + {"horrible", 1383}, + {"hungry", 1384}, + {"indeed", 1385}, + {"lace", 1386}, + {"melody", 1387}, + {"monkey", 1388}, + {"nation", 1389}, + {"object", 1390}, + {"obviously", 1391}, + {"rainbow", 1392}, + {"salt", 1393}, + {"scratch", 1394}, + {"shown", 1395}, + {"shy", 1396}, + {"stage", 1397}, + {"stun", 1398}, + {"third", 1399}, + {"tickle", 1400}, + {"useless", 1401}, + {"weakness", 1402}, + {"worship", 1403}, + {"worthless", 1404}, + {"afternoon", 1405}, + {"beard", 1406}, + {"boyfriend", 1407}, + {"bubble", 1408}, + {"busy", 1409}, + {"certain", 1410}, + {"chin", 1411}, + {"concrete", 1412}, + {"desk", 1413}, + {"diamond", 1414}, + {"doom", 1415}, + {"drawn", 1416}, + {"due", 1417}, + {"felicity", 1418}, + {"freeze", 1419}, + {"frost", 1420}, + {"garden", 1421}, + {"glide", 1422}, + {"harmony", 1423}, + {"hopefully", 1424}, + {"hunt", 1425}, + {"jealous", 1426}, + {"lightning", 1427}, + {"mama", 1428}, + {"mercy", 1429}, + {"peel", 1430}, + {"physical", 1431}, + {"position", 1432}, + {"pulse", 1433}, + {"punch", 1434}, + {"quit", 1435}, + {"rant", 1436}, + {"respond", 1437}, + {"salty", 1438}, + {"sane", 1439}, + {"satisfy", 1440}, + {"savior", 1441}, + {"sheep", 1442}, + {"slept", 1443}, + {"social", 1444}, + {"sport", 1445}, + {"tuck", 1446}, + {"utter", 1447}, + {"valley", 1448}, + {"wolf", 1449}, + {"aim", 1450}, + {"alas", 1451}, + {"alter", 1452}, + {"arrow", 1453}, + {"awaken", 1454}, + {"beaten", 1455}, + {"belief", 1456}, + {"brand", 1457}, + {"ceiling", 1458}, + {"cheese", 1459}, + {"clue", 1460}, + {"confidence", 1461}, + {"connection", 1462}, + {"daily", 1463}, + {"disguise", 1464}, + {"eager", 1465}, + {"erase", 1466}, + {"essence", 1467}, + {"everytime", 1468}, + {"expression", 1469}, + {"fan", 1470}, + {"flag", 1471}, + {"flirt", 1472}, + {"foul", 1473}, + {"fur", 1474}, + {"giggle", 1475}, + {"glorious", 1476}, + {"ignorance", 1477}, + {"law", 1478}, + {"lifeless", 1479}, + {"measure", 1480}, + {"mighty", 1481}, + {"muse", 1482}, + {"north", 1483}, + {"opposite", 1484}, + {"paradise", 1485}, + {"patience", 1486}, + {"patient", 1487}, + {"pencil", 1488}, + {"petal", 1489}, + {"plate", 1490}, + {"ponder", 1491}, + {"possibly", 1492}, + {"practice", 1493}, + {"slice", 1494}, + {"spell", 1495}, + {"stock", 1496}, + {"strife", 1497}, + {"strip", 1498}, + {"suffocate", 1499}, + {"suit", 1500}, + {"tender", 1501}, + {"tool", 1502}, + {"trade", 1503}, + {"velvet", 1504}, + {"verse", 1505}, + {"waist", 1506}, + {"witch", 1507}, + {"aunt", 1508}, + {"bench", 1509}, + {"bold", 1510}, + {"cap", 1511}, + {"certainly", 1512}, + {"click", 1513}, + {"companion", 1514}, + {"creator", 1515}, + {"dart", 1516}, + {"delicate", 1517}, + {"determine", 1518}, + {"dish", 1519}, + {"dragon", 1520}, + {"drama", 1521}, + {"drum", 1522}, + {"dude", 1523}, + {"everybody", 1524}, + {"feast", 1525}, + {"forehead", 1526}, + {"former", 1527}, + {"fright", 1528}, + {"fully", 1529}, + {"gas", 1530}, + {"hook", 1531}, + {"hurl", 1532}, + {"invite", 1533}, + {"juice", 1534}, + {"manage", 1535}, + {"moral", 1536}, + {"possess", 1537}, + {"raw", 1538}, + {"rebel", 1539}, + {"royal", 1540}, + {"scale", 1541}, + {"scary", 1542}, + {"several", 1543}, + {"slight", 1544}, + {"stubborn", 1545}, + {"swell", 1546}, + {"talent", 1547}, + {"tea", 1548}, + {"terrible", 1549}, + {"thread", 1550}, + {"torment", 1551}, + {"trickle", 1552}, + {"usually", 1553}, + {"vast", 1554}, + {"violence", 1555}, + {"weave", 1556}, + {"acid", 1557}, + {"agony", 1558}, + {"ashamed", 1559}, + {"awe", 1560}, + {"belly", 1561}, + {"blend", 1562}, + {"blush", 1563}, + {"character", 1564}, + {"cheat", 1565}, + {"common", 1566}, + {"company", 1567}, + {"coward", 1568}, + {"creak", 1569}, + {"danger", 1570}, + {"deadly", 1571}, + {"defense", 1572}, + {"define", 1573}, + {"depend", 1574}, + {"desperate", 1575}, + {"destination", 1576}, + {"dew", 1577}, + {"duck", 1578}, + {"dusty", 1579}, + {"embarrass", 1580}, + {"engine", 1581}, + {"example", 1582}, + {"explore", 1583}, + {"foe", 1584}, + {"freely", 1585}, + {"frustrate", 1586}, + {"generation", 1587}, + {"glove", 1588}, + {"guilty", 1589}, + {"health", 1590}, + {"hurry", 1591}, + {"idiot", 1592}, + {"impossible", 1593}, + {"inhale", 1594}, + {"jaw", 1595}, + {"kingdom", 1596}, + {"mention", 1597}, + {"mist", 1598}, + {"moan", 1599}, + {"mumble", 1600}, + {"mutter", 1601}, + {"observe", 1602}, + {"ode", 1603}, + {"pathetic", 1604}, + {"pattern", 1605}, + {"pie", 1606}, + {"prefer", 1607}, + {"puff", 1608}, + {"rape", 1609}, + {"rare", 1610}, + {"revenge", 1611}, + {"rude", 1612}, + {"scrape", 1613}, + {"spiral", 1614}, + {"squeeze", 1615}, + {"strain", 1616}, + {"sunset", 1617}, + {"suspend", 1618}, + {"sympathy", 1619}, + {"thigh", 1620}, + {"throne", 1621}, + {"total", 1622}, + {"unseen", 1623}, + {"weapon", 1624}, + {"weary", 1625} + }; + + const std::string wordsArray[] = { + "like", + "just", + "love", + "know", + "never", + "want", + "time", + "out", + "there", + "make", + "look", + "eye", + "down", + "only", + "think", + "heart", + "back", + "then", + "into", + "about", + "more", + "away", + "still", + "them", + "take", + "thing", + "even", + "through", + "long", + "always", + "world", + "too", + "friend", + "tell", + "try", + "hand", + "thought", + "over", + "here", + "other", + "need", + "smile", + "again", + "much", + "cry", + "been", + "night", + "ever", + "little", + "said", + "end", + "some", + "those", + "around", + "mind", + "people", + "girl", + "leave", + "dream", + "left", + "turn", + "myself", + "give", + "nothing", + "really", + "off", + "before", + "something", + "find", + "walk", + "wish", + "good", + "once", + "place", + "ask", + "stop", + "keep", + "watch", + "seem", + "everything", + "wait", + "got", + "yet", + "made", + "remember", + "start", + "alone", + "run", + "hope", + "maybe", + "believe", + "body", + "hate", + "after", + "close", + "talk", + "stand", + "own", + "each", + "hurt", + "help", + "home", + "god", + "soul", + "new", + "many", + "two", + "inside", + "should", + "true", + "first", + "fear", + "mean", + "better", + "play", + "another", + "gone", + "change", + "use", + "wonder", + "someone", + "hair", + "cold", + "open", + "best", + "any", + "behind", + "happen", + "water", + "dark", + "laugh", + "stay", + "forever", + "name", + "work", + "show", + "sky", + "break", + "came", + "deep", + "door", + "put", + "black", + "together", + "upon", + "happy", + "such", + "great", + "white", + "matter", + "fill", + "past", + "please", + "burn", + "cause", + "enough", + "touch", + "moment", + "soon", + "voice", + "scream", + "anything", + "stare", + "sound", + "red", + "everyone", + "hide", + "kiss", + "truth", + "death", + "beautiful", + "mine", + "blood", + "broken", + "very", + "pass", + "next", + "forget", + "tree", + "wrong", + "air", + "mother", + "understand", + "lip", + "hit", + "wall", + "memory", + "sleep", + "free", + "high", + "realize", + "school", + "might", + "skin", + "sweet", + "perfect", + "blue", + "kill", + "breath", + "dance", + "against", + "fly", + "between", + "grow", + "strong", + "under", + "listen", + "bring", + "sometimes", + "speak", + "pull", + "person", + "become", + "family", + "begin", + "ground", + "real", + "small", + "father", + "sure", + "feet", + "rest", + "young", + "finally", + "land", + "across", + "today", + "different", + "guy", + "line", + "fire", + "reason", + "reach", + "second", + "slowly", + "write", + "eat", + "smell", + "mouth", + "step", + "learn", + "three", + "floor", + "promise", + "breathe", + "darkness", + "push", + "earth", + "guess", + "save", + "song", + "above", + "along", + "both", + "color", + "house", + "almost", + "sorry", + "anymore", + "brother", + "okay", + "dear", + "game", + "fade", + "already", + "apart", + "warm", + "beauty", + "heard", + "notice", + "question", + "shine", + "began", + "piece", + "whole", + "shadow", + "secret", + "street", + "within", + "finger", + "point", + "morning", + "whisper", + "child", + "moon", + "green", + "story", + "glass", + "kid", + "silence", + "since", + "soft", + "yourself", + "empty", + "shall", + "angel", + "answer", + "baby", + "bright", + "dad", + "path", + "worry", + "hour", + "drop", + "follow", + "power", + "war", + "half", + "flow", + "heaven", + "act", + "chance", + "fact", + "least", + "tired", + "children", + "near", + "quite", + "afraid", + "rise", + "sea", + "taste", + "window", + "cover", + "nice", + "trust", + "lot", + "sad", + "cool", + "force", + "peace", + "return", + "blind", + "easy", + "ready", + "roll", + "rose", + "drive", + "held", + "music", + "beneath", + "hang", + "mom", + "paint", + "emotion", + "quiet", + "clear", + "cloud", + "few", + "pretty", + "bird", + "outside", + "paper", + "picture", + "front", + "rock", + "simple", + "anyone", + "meant", + "reality", + "road", + "sense", + "waste", + "bit", + "leaf", + "thank", + "happiness", + "meet", + "men", + "smoke", + "truly", + "decide", + "self", + "age", + "book", + "form", + "alive", + "carry", + "escape", + "damn", + "instead", + "able", + "ice", + "minute", + "throw", + "catch", + "leg", + "ring", + "course", + "goodbye", + "lead", + "poem", + "sick", + "corner", + "desire", + "known", + "problem", + "remind", + "shoulder", + "suppose", + "toward", + "wave", + "drink", + "jump", + "woman", + "pretend", + "sister", + "week", + "human", + "joy", + "crack", + "grey", + "pray", + "surprise", + "dry", + "knee", + "less", + "search", + "bleed", + "caught", + "clean", + "embrace", + "future", + "king", + "son", + "sorrow", + "chest", + "hug", + "remain", + "sat", + "worth", + "blow", + "daddy", + "final", + "parent", + "tight", + "also", + "create", + "lonely", + "safe", + "cross", + "dress", + "evil", + "silent", + "bone", + "fate", + "perhaps", + "anger", + "class", + "scar", + "snow", + "tiny", + "tonight", + "continue", + "control", + "dog", + "edge", + "mirror", + "month", + "suddenly", + "comfort", + "given", + "loud", + "quickly", + "gaze", + "plan", + "rush", + "stone", + "town", + "battle", + "ignore", + "spirit", + "stood", + "stupid", + "yours", + "brown", + "build", + "dust", + "hey", + "kept", + "pay", + "phone", + "twist", + "although", + "ball", + "beyond", + "hidden", + "nose", + "taken", + "fail", + "float", + "pure", + "somehow", + "wash", + "wrap", + "angry", + "cheek", + "creature", + "forgotten", + "heat", + "rip", + "single", + "space", + "special", + "weak", + "whatever", + "yell", + "anyway", + "blame", + "job", + "choose", + "country", + "curse", + "drift", + "echo", + "figure", + "grew", + "laughter", + "neck", + "suffer", + "worse", + "yeah", + "disappear", + "foot", + "forward", + "knife", + "mess", + "somewhere", + "stomach", + "storm", + "beg", + "idea", + "lift", + "offer", + "breeze", + "field", + "five", + "often", + "simply", + "stuck", + "win", + "allow", + "confuse", + "enjoy", + "except", + "flower", + "seek", + "strength", + "calm", + "grin", + "gun", + "heavy", + "hill", + "large", + "ocean", + "shoe", + "sigh", + "straight", + "summer", + "tongue", + "accept", + "crazy", + "everyday", + "exist", + "grass", + "mistake", + "sent", + "shut", + "surround", + "table", + "ache", + "brain", + "destroy", + "heal", + "nature", + "shout", + "sign", + "stain", + "choice", + "doubt", + "glance", + "glow", + "mountain", + "queen", + "stranger", + "throat", + "tomorrow", + "city", + "either", + "fish", + "flame", + "rather", + "shape", + "spin", + "spread", + "ash", + "distance", + "finish", + "image", + "imagine", + "important", + "nobody", + "shatter", + "warmth", + "became", + "feed", + "flesh", + "funny", + "lust", + "shirt", + "trouble", + "yellow", + "attention", + "bare", + "bite", + "money", + "protect", + "amaze", + "appear", + "born", + "choke", + "completely", + "daughter", + "fresh", + "friendship", + "gentle", + "probably", + "six", + "deserve", + "expect", + "grab", + "middle", + "nightmare", + "river", + "thousand", + "weight", + "worst", + "wound", + "barely", + "bottle", + "cream", + "regret", + "relationship", + "stick", + "test", + "crush", + "endless", + "fault", + "itself", + "rule", + "spill", + "art", + "circle", + "join", + "kick", + "mask", + "master", + "passion", + "quick", + "raise", + "smooth", + "unless", + "wander", + "actually", + "broke", + "chair", + "deal", + "favorite", + "gift", + "note", + "number", + "sweat", + "box", + "chill", + "clothes", + "lady", + "mark", + "park", + "poor", + "sadness", + "tie", + "animal", + "belong", + "brush", + "consume", + "dawn", + "forest", + "innocent", + "pen", + "pride", + "stream", + "thick", + "clay", + "complete", + "count", + "draw", + "faith", + "press", + "silver", + "struggle", + "surface", + "taught", + "teach", + "wet", + "bless", + "chase", + "climb", + "enter", + "letter", + "melt", + "metal", + "movie", + "stretch", + "swing", + "vision", + "wife", + "beside", + "crash", + "forgot", + "guide", + "haunt", + "joke", + "knock", + "plant", + "pour", + "prove", + "reveal", + "steal", + "stuff", + "trip", + "wood", + "wrist", + "bother", + "bottom", + "crawl", + "crowd", + "fix", + "forgive", + "frown", + "grace", + "loose", + "lucky", + "party", + "release", + "surely", + "survive", + "teacher", + "gently", + "grip", + "speed", + "suicide", + "travel", + "treat", + "vein", + "written", + "cage", + "chain", + "conversation", + "date", + "enemy", + "however", + "interest", + "million", + "page", + "pink", + "proud", + "sway", + "themselves", + "winter", + "church", + "cruel", + "cup", + "demon", + "experience", + "freedom", + "pair", + "pop", + "purpose", + "respect", + "shoot", + "softly", + "state", + "strange", + "bar", + "birth", + "curl", + "dirt", + "excuse", + "lord", + "lovely", + "monster", + "order", + "pack", + "pants", + "pool", + "scene", + "seven", + "shame", + "slide", + "ugly", + "among", + "blade", + "blonde", + "closet", + "creek", + "deny", + "drug", + "eternity", + "gain", + "grade", + "handle", + "key", + "linger", + "pale", + "prepare", + "swallow", + "swim", + "tremble", + "wheel", + "won", + "cast", + "cigarette", + "claim", + "college", + "direction", + "dirty", + "gather", + "ghost", + "hundred", + "loss", + "lung", + "orange", + "present", + "swear", + "swirl", + "twice", + "wild", + "bitter", + "blanket", + "doctor", + "everywhere", + "flash", + "grown", + "knowledge", + "numb", + "pressure", + "radio", + "repeat", + "ruin", + "spend", + "unknown", + "buy", + "clock", + "devil", + "early", + "false", + "fantasy", + "pound", + "precious", + "refuse", + "sheet", + "teeth", + "welcome", + "add", + "ahead", + "block", + "bury", + "caress", + "content", + "depth", + "despite", + "distant", + "marry", + "purple", + "threw", + "whenever", + "bomb", + "dull", + "easily", + "grasp", + "hospital", + "innocence", + "normal", + "receive", + "reply", + "rhyme", + "shade", + "someday", + "sword", + "toe", + "visit", + "asleep", + "bought", + "center", + "consider", + "flat", + "hero", + "history", + "ink", + "insane", + "muscle", + "mystery", + "pocket", + "reflection", + "shove", + "silently", + "smart", + "soldier", + "spot", + "stress", + "train", + "type", + "view", + "whether", + "bus", + "energy", + "explain", + "holy", + "hunger", + "inch", + "magic", + "mix", + "noise", + "nowhere", + "prayer", + "presence", + "shock", + "snap", + "spider", + "study", + "thunder", + "trail", + "admit", + "agree", + "bag", + "bang", + "bound", + "butterfly", + "cute", + "exactly", + "explode", + "familiar", + "fold", + "further", + "pierce", + "reflect", + "scent", + "selfish", + "sharp", + "sink", + "spring", + "stumble", + "universe", + "weep", + "women", + "wonderful", + "action", + "ancient", + "attempt", + "avoid", + "birthday", + "branch", + "chocolate", + "core", + "depress", + "drunk", + "especially", + "focus", + "fruit", + "honest", + "match", + "palm", + "perfectly", + "pillow", + "pity", + "poison", + "roar", + "shift", + "slightly", + "thump", + "truck", + "tune", + "twenty", + "unable", + "wipe", + "wrote", + "coat", + "constant", + "dinner", + "drove", + "egg", + "eternal", + "flight", + "flood", + "frame", + "freak", + "gasp", + "glad", + "hollow", + "motion", + "peer", + "plastic", + "root", + "screen", + "season", + "sting", + "strike", + "team", + "unlike", + "victim", + "volume", + "warn", + "weird", + "attack", + "await", + "awake", + "built", + "charm", + "crave", + "despair", + "fought", + "grant", + "grief", + "horse", + "limit", + "message", + "ripple", + "sanity", + "scatter", + "serve", + "split", + "string", + "trick", + "annoy", + "blur", + "boat", + "brave", + "clearly", + "cling", + "connect", + "fist", + "forth", + "imagination", + "iron", + "jock", + "judge", + "lesson", + "milk", + "misery", + "nail", + "naked", + "ourselves", + "poet", + "possible", + "princess", + "sail", + "size", + "snake", + "society", + "stroke", + "torture", + "toss", + "trace", + "wise", + "bloom", + "bullet", + "cell", + "check", + "cost", + "darling", + "during", + "footstep", + "fragile", + "hallway", + "hardly", + "horizon", + "invisible", + "journey", + "midnight", + "mud", + "nod", + "pause", + "relax", + "shiver", + "sudden", + "value", + "youth", + "abuse", + "admire", + "blink", + "breast", + "bruise", + "constantly", + "couple", + "creep", + "curve", + "difference", + "dumb", + "emptiness", + "gotta", + "honor", + "plain", + "planet", + "recall", + "rub", + "ship", + "slam", + "soar", + "somebody", + "tightly", + "weather", + "adore", + "approach", + "bond", + "bread", + "burst", + "candle", + "coffee", + "cousin", + "crime", + "desert", + "flutter", + "frozen", + "grand", + "heel", + "hello", + "language", + "level", + "movement", + "pleasure", + "powerful", + "random", + "rhythm", + "settle", + "silly", + "slap", + "sort", + "spoken", + "steel", + "threaten", + "tumble", + "upset", + "aside", + "awkward", + "bee", + "blank", + "board", + "button", + "card", + "carefully", + "complain", + "crap", + "deeply", + "discover", + "drag", + "dread", + "effort", + "entire", + "fairy", + "giant", + "gotten", + "greet", + "illusion", + "jeans", + "leap", + "liquid", + "march", + "mend", + "nervous", + "nine", + "replace", + "rope", + "spine", + "stole", + "terror", + "accident", + "apple", + "balance", + "boom", + "childhood", + "collect", + "demand", + "depression", + "eventually", + "faint", + "glare", + "goal", + "group", + "honey", + "kitchen", + "laid", + "limb", + "machine", + "mere", + "mold", + "murder", + "nerve", + "painful", + "poetry", + "prince", + "rabbit", + "shelter", + "shore", + "shower", + "soothe", + "stair", + "steady", + "sunlight", + "tangle", + "tease", + "treasure", + "uncle", + "begun", + "bliss", + "canvas", + "cheer", + "claw", + "clutch", + "commit", + "crimson", + "crystal", + "delight", + "doll", + "existence", + "express", + "fog", + "football", + "gay", + "goose", + "guard", + "hatred", + "illuminate", + "mass", + "math", + "mourn", + "rich", + "rough", + "skip", + "stir", + "student", + "style", + "support", + "thorn", + "tough", + "yard", + "yearn", + "yesterday", + "advice", + "appreciate", + "autumn", + "bank", + "beam", + "bowl", + "capture", + "carve", + "collapse", + "confusion", + "creation", + "dove", + "feather", + "girlfriend", + "glory", + "government", + "harsh", + "hop", + "inner", + "loser", + "moonlight", + "neighbor", + "neither", + "peach", + "pig", + "praise", + "screw", + "shield", + "shimmer", + "sneak", + "stab", + "subject", + "throughout", + "thrown", + "tower", + "twirl", + "wow", + "army", + "arrive", + "bathroom", + "bump", + "cease", + "cookie", + "couch", + "courage", + "dim", + "guilt", + "howl", + "hum", + "husband", + "insult", + "led", + "lunch", + "mock", + "mostly", + "natural", + "nearly", + "needle", + "nerd", + "peaceful", + "perfection", + "pile", + "price", + "remove", + "roam", + "sanctuary", + "serious", + "shiny", + "shook", + "sob", + "stolen", + "tap", + "vain", + "void", + "warrior", + "wrinkle", + "affection", + "apologize", + "blossom", + "bounce", + "bridge", + "cheap", + "crumble", + "decision", + "descend", + "desperately", + "dig", + "dot", + "flip", + "frighten", + "heartbeat", + "huge", + "lazy", + "lick", + "odd", + "opinion", + "process", + "puzzle", + "quietly", + "retreat", + "score", + "sentence", + "separate", + "situation", + "skill", + "soak", + "square", + "stray", + "taint", + "task", + "tide", + "underneath", + "veil", + "whistle", + "anywhere", + "bedroom", + "bid", + "bloody", + "burden", + "careful", + "compare", + "concern", + "curtain", + "decay", + "defeat", + "describe", + "double", + "dreamer", + "driver", + "dwell", + "evening", + "flare", + "flicker", + "grandma", + "guitar", + "harm", + "horrible", + "hungry", + "indeed", + "lace", + "melody", + "monkey", + "nation", + "object", + "obviously", + "rainbow", + "salt", + "scratch", + "shown", + "shy", + "stage", + "stun", + "third", + "tickle", + "useless", + "weakness", + "worship", + "worthless", + "afternoon", + "beard", + "boyfriend", + "bubble", + "busy", + "certain", + "chin", + "concrete", + "desk", + "diamond", + "doom", + "drawn", + "due", + "felicity", + "freeze", + "frost", + "garden", + "glide", + "harmony", + "hopefully", + "hunt", + "jealous", + "lightning", + "mama", + "mercy", + "peel", + "physical", + "position", + "pulse", + "punch", + "quit", + "rant", + "respond", + "salty", + "sane", + "satisfy", + "savior", + "sheep", + "slept", + "social", + "sport", + "tuck", + "utter", + "valley", + "wolf", + "aim", + "alas", + "alter", + "arrow", + "awaken", + "beaten", + "belief", + "brand", + "ceiling", + "cheese", + "clue", + "confidence", + "connection", + "daily", + "disguise", + "eager", + "erase", + "essence", + "everytime", + "expression", + "fan", + "flag", + "flirt", + "foul", + "fur", + "giggle", + "glorious", + "ignorance", + "law", + "lifeless", + "measure", + "mighty", + "muse", + "north", + "opposite", + "paradise", + "patience", + "patient", + "pencil", + "petal", + "plate", + "ponder", + "possibly", + "practice", + "slice", + "spell", + "stock", + "strife", + "strip", + "suffocate", + "suit", + "tender", + "tool", + "trade", + "velvet", + "verse", + "waist", + "witch", + "aunt", + "bench", + "bold", + "cap", + "certainly", + "click", + "companion", + "creator", + "dart", + "delicate", + "determine", + "dish", + "dragon", + "drama", + "drum", + "dude", + "everybody", + "feast", + "forehead", + "former", + "fright", + "fully", + "gas", + "hook", + "hurl", + "invite", + "juice", + "manage", + "moral", + "possess", + "raw", + "rebel", + "royal", + "scale", + "scary", + "several", + "slight", + "stubborn", + "swell", + "talent", + "tea", + "terrible", + "thread", + "torment", + "trickle", + "usually", + "vast", + "violence", + "weave", + "acid", + "agony", + "ashamed", + "awe", + "belly", + "blend", + "blush", + "character", + "cheat", + "common", + "company", + "coward", + "creak", + "danger", + "deadly", + "defense", + "define", + "depend", + "desperate", + "destination", + "dew", + "duck", + "dusty", + "embarrass", + "engine", + "example", + "explore", + "foe", + "freely", + "frustrate", + "generation", + "glove", + "guilty", + "health", + "hurry", + "idiot", + "impossible", + "inhale", + "jaw", + "kingdom", + "mention", + "mist", + "moan", + "mumble", + "mutter", + "observe", + "ode", + "pathetic", + "pattern", + "pie", + "prefer", + "puff", + "rape", + "rare", + "revenge", + "rude", + "scrape", + "spiral", + "squeeze", + "strain", + "sunset", + "suspend", + "sympathy", + "thigh", + "throne", + "total", + "unseen", + "weapon", + "weary" + }; + } +} diff --git a/src/cryptonote_core/account.cpp b/src/cryptonote_core/account.cpp index ba39b9b77..9a96de2f0 100644 --- a/src/cryptonote_core/account.cpp +++ b/src/cryptonote_core/account.cpp @@ -29,7 +29,7 @@ DISABLE_VS_WARNINGS(4244 4345) m_keys = account_keys(); } //----------------------------------------------------------------- - void account_base::generate() + void account_base::generate(const crypto::secret_key& recovery_key, bool recover) { generate_keys(m_keys.m_account_address.m_spend_public_key, m_keys.m_spend_secret_key); generate_keys(m_keys.m_account_address.m_view_public_key, m_keys.m_view_secret_key); diff --git a/src/cryptonote_core/account.h b/src/cryptonote_core/account.h index 8b525da97..96125eb27 100644 --- a/src/cryptonote_core/account.h +++ b/src/cryptonote_core/account.h @@ -31,7 +31,7 @@ namespace cryptonote { public: account_base(); - void generate(); + void generate(const crypto::secret_key& recovery_key, bool recover); const account_keys& get_keys() const; std::string get_public_address_str(); diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 4cab12c22..3cea02bf1 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -17,6 +17,8 @@ #include "rpc/core_rpc_server_commands_defs.h" #include "wallet/wallet_rpc_server.h" #include "version.h" +#include "crypto/crypto.h" // for crypto::secret_key definition +#include "crypto/electrum-words.h" #if defined(WIN32) #include @@ -38,6 +40,8 @@ namespace const command_line::arg_descriptor arg_daemon_address = {"daemon-address", "Use daemon instance at :", ""}; const command_line::arg_descriptor arg_daemon_host = {"daemon-host", "Use daemon instance at host instead of localhost", ""}; const command_line::arg_descriptor arg_password = {"password", "Wallet password", "", true}; + const command_line::arg_descriptor arg_electrum_seed = {"electrum-seed", "Specify electrum seed for wallet recovery/creation", ""}; + const command_line::arg_descriptor arg_recover = {"recover", "Recover wallet using mnemonic generator (e.g. electrum word list)", false}; const command_line::arg_descriptor arg_daemon_port = {"daemon-port", "Use daemon instance at port instead of 8081", 0}; const command_line::arg_descriptor arg_log_level = {"set_log", "", 0, true}; @@ -284,7 +288,24 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm) if (!m_generate_new.empty()) { - bool r = new_wallet(m_generate_new, pwd_container.password()); + // check for recover flag. if present, require electrum word list (only recovery option for now). + if (m_recover) + { + if (m_electrum_seed.empty()) + { + fail_msg_writer() << "specify a recovery parameter (e.g. electrum word list) with the recover option"; + return false; + } + else // verify recovery param (electrum word list) and convert to byte representation + { + CHECK_AND_ASSERT_MES( + crypto::ElectrumWords::words_to_bytes(m_electrum_seed, m_recovery_key), + false, + "electrum-style word list failed verification" + ); + } + } + bool r = new_wallet(m_generate_new, pwd_container.password(), m_recovery_key, m_recover); CHECK_AND_ASSERT_MES(r, false, "account creation failed"); } else @@ -311,6 +332,8 @@ void simple_wallet::handle_command_line(const boost::program_options::variables_ m_daemon_address = command_line::get_arg(vm, arg_daemon_address); m_daemon_host = command_line::get_arg(vm, arg_daemon_host); m_daemon_port = command_line::get_arg(vm, arg_daemon_port); + m_electrum_seed = command_line::get_arg(vm, arg_electrum_seed); + m_recover = command_line::get_arg(vm, arg_recover); } //---------------------------------------------------------------------------------------------------- bool simple_wallet::try_connect_to_daemon() @@ -324,8 +347,14 @@ bool simple_wallet::try_connect_to_daemon() } return true; } + +bool simple_wallet::parse_electrum() +{ + return false; +} + //---------------------------------------------------------------------------------------------------- -bool simple_wallet::new_wallet(const string &wallet_file, const std::string& password) +bool simple_wallet::new_wallet(const string &wallet_file, const std::string& password, const crypto::secret_key& recovery_key, bool recover) { m_wallet_file = wallet_file; @@ -333,7 +362,7 @@ bool simple_wallet::new_wallet(const string &wallet_file, const std::string& pas m_wallet->callback(this); try { - m_wallet->generate(wallet_file, password); + m_wallet->generate(wallet_file, password, recovery_key, recover); message_writer(epee::log_space::console_color_white, true) << "Generated new wallet: " << m_wallet->get_account().get_public_address_str() << std::endl << "view key: " << string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_view_secret_key); } catch (const std::exception& e) diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h index 3dcaaeaa0..d1f9fe98b 100644 --- a/src/simplewallet/simplewallet.h +++ b/src/simplewallet/simplewallet.h @@ -13,6 +13,7 @@ #include "wallet/wallet2.h" #include "console_handler.h" #include "password_container.h" +#include "crypto/crypto.h" // for definition of crypto::secret_key namespace cryptonote @@ -39,7 +40,9 @@ namespace cryptonote bool run_console_handler(); - bool new_wallet(const std::string &wallet_file, const std::string& password); + bool parse_electrum(); + + bool new_wallet(const std::string &wallet_file, const std::string& password, const crypto::secret_key& recovery_key = crypto::secret_key(), bool recover = false); bool open_wallet(const std::string &wallet_file, const std::string& password); bool close_wallet(); @@ -125,6 +128,11 @@ namespace cryptonote std::string m_generate_new; std::string m_import_path; + std::string m_electrum_seed; // electrum-style seed parameter + + crypto::secret_key m_recovery_key; // recovery key (used as random for wallet gen) + bool m_recover; // recover flag + std::string m_daemon_address; std::string m_daemon_host; int m_daemon_port; diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index fb1e5575b..b0c341615 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -38,6 +38,7 @@ void do_prepare_file_names(const std::string& file_path, std::string& keys_file, keys_file += ".keys"; } } + } //namespace namespace tools @@ -435,7 +436,7 @@ void wallet2::load_keys(const std::string& keys_file_name, const std::string& pa THROW_WALLET_EXCEPTION_IF(!r, error::invalid_password); } //---------------------------------------------------------------------------------------------------- -void wallet2::generate(const std::string& wallet_, const std::string& password) +void wallet2::generate(const std::string& wallet_, const std::string& password, const crypto::secret_key& recovery_param, bool recover) { clear(); prepare_file_names(wallet_); @@ -444,7 +445,8 @@ void wallet2::generate(const std::string& wallet_, const std::string& password) THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_wallet_file, ignored_ec), error::file_exists, m_wallet_file); THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_keys_file, ignored_ec), error::file_exists, m_keys_file); - m_account.generate(); + m_account.generate(recovery_param, recover); + m_account_public_address = m_account.get_keys().m_account_address; bool r = store_keys(m_keys_file, password); diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 9ca586425..87e1dcbd4 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -97,7 +97,7 @@ namespace tools END_SERIALIZE() }; - void generate(const std::string& wallet, const std::string& password); + void generate(const std::string& wallet, const std::string& password, const crypto::secret_key& recovery_param, bool recover = false); void load(const std::string& wallet, const std::string& password); void store(); cryptonote::account_base& get_account(){return m_account;} @@ -227,6 +227,7 @@ namespace boost namespace tools { + namespace detail { //---------------------------------------------------------------------------------------------------- diff --git a/src/wallet/wallet_errors.h b/src/wallet/wallet_errors.h index 0d42dbaf4..71c946545 100644 --- a/src/wallet/wallet_errors.h +++ b/src/wallet/wallet_errors.h @@ -188,6 +188,17 @@ namespace tools std::string to_string() const { return wallet_logic_error::to_string(); } }; + + //---------------------------------------------------------------------------------------------------- + struct invalid_pregenerated_random : public wallet_logic_error + { + explicit invalid_pregenerated_random (std::string&& loc) + : wallet_logic_error(std::move(loc), "invalid pregenerated random for wallet creation/recovery") + { + } + + std::string to_string() const { return wallet_logic_error::to_string(); } + }; //---------------------------------------------------------------------------------------------------- struct refresh_error : public wallet_logic_error { -- cgit v1.2.3 From d22e458c6c680f4b5dcf56a58a37a5f79912e65c Mon Sep 17 00:00:00 2001 From: Thomas Winget Date: Fri, 6 Jun 2014 14:18:11 -0400 Subject: builds, but doesn't link. other than that, electrum-style recovery implemented (but not tested\!) --- src/common/pod-class.h | 6 ++++++ src/crypto/crypto.cpp | 19 +++++++++++++++++-- src/crypto/crypto.h | 8 ++++---- src/crypto/electrum-words.cpp | 10 +++++----- src/cryptonote_core/account.cpp | 13 ++++++++++--- src/cryptonote_core/account.h | 2 +- src/simplewallet/simplewallet.cpp | 10 +++++++++- src/wallet/wallet2.cpp | 5 +++-- src/wallet/wallet2.h | 2 +- 9 files changed, 56 insertions(+), 19 deletions(-) (limited to 'src/simplewallet/simplewallet.cpp') diff --git a/src/common/pod-class.h b/src/common/pod-class.h index c07edb208..10d680484 100644 --- a/src/common/pod-class.h +++ b/src/common/pod-class.h @@ -4,8 +4,14 @@ #pragma once +// FIXME: Why is this ifdef needed? Hopefully making it struct won't break things. + +/* #if defined(_MSC_VER) #define POD_CLASS struct #else #define POD_CLASS class #endif +*/ + +#define POD_CLASS struct diff --git a/src/crypto/crypto.cpp b/src/crypto/crypto.cpp index 31fc31d5b..98a17a3e4 100644 --- a/src/crypto/crypto.cpp +++ b/src/crypto/crypto.cpp @@ -68,12 +68,27 @@ namespace crypto { * TODO: allow specifiying random value (for wallet recovery) * */ - void crypto_ops::generate_keys(public_key &pub, secret_key &sec) { + secret_key crypto_ops::generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key, bool recover) { lock_guard lock(random_lock); ge_p3 point; - random_scalar(sec); + + secret_key rng; + + if (recover) + { + rng = recovery_key; + } + else + { + random_scalar(rng); + } + sec = rng; + sc_reduce32(&sec); // reduce in case second round of keys (sendkeys) + ge_scalarmult_base(&point, &sec); ge_p3_tobytes(&pub, &point); + + return rng; } bool crypto_ops::check_key(const public_key &key) { diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h index 61641fbcf..024713df1 100644 --- a/src/crypto/crypto.h +++ b/src/crypto/crypto.h @@ -62,8 +62,8 @@ namespace crypto { void operator=(const crypto_ops &); ~crypto_ops(); - static void generate_keys(public_key &, secret_key &); - friend void generate_keys(public_key &, secret_key &); + static secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key = secret_key(), bool recover = false); + friend secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key, bool recover); static bool check_key(const public_key &); friend bool check_key(const public_key &); static bool secret_key_to_public_key(const secret_key &, public_key &); @@ -102,8 +102,8 @@ namespace crypto { /* Generate a new key pair */ - inline void generate_keys(public_key &pub, secret_key &sec) { - crypto_ops::generate_keys(pub, sec); + inline secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key = secret_key(), bool recover = false) { + return crypto_ops::generate_keys(pub, sec, recovery_key, recover); } /* Check a public key. Returns true if it is valid, false otherwise. diff --git a/src/crypto/electrum-words.cpp b/src/crypto/electrum-words.cpp index b4580e01f..048aa403f 100644 --- a/src/crypto/electrum-words.cpp +++ b/src/crypto/electrum-words.cpp @@ -36,7 +36,7 @@ namespace crypto // error on non-compliant word list if (wlist.size() != 12 && wlist.size() != 24) return false; - for (int i=0; i < wlist.size() / 3; i++) + for (unsigned int i=0; i < wlist.size() / 3; i++) { uint32_t val; uint32_t w1, w2, w3; @@ -55,12 +55,12 @@ namespace crypto val = w1 + n * ((w2 - w1) % n) + n * n * ((w3 - w2) % n); - memcpy(dst.data + i * 4, val, 4); // copy 4 bytes to position + memcpy(&dst.data + i * 4, &val, 4); // copy 4 bytes to position } if (wlist.size() == 12) { - memcpy(dst.data, dst.data + 16, 16); // if electrum 12-word seed, duplicate + memcpy(&dst.data, &dst.data + 16, 16); // if electrum 12-word seed, duplicate } return true; @@ -78,13 +78,13 @@ namespace crypto if (sizeof(src.data) % 4 != 0) return false; // 8 bytes -> 3 words. 8 digits base 16 -> 3 digits base 1626 - for (int i=0; i < sizeof(src.data)/4; i++, words += ' ') + for (unsigned int i=0; i < sizeof(src.data)/4; i++, words += ' ') { uint32_t w1, w2, w3; uint32_t val; - memcpy(val, src, 4); + memcpy(&val, &src.data, 4); w1 = val % n; w2 = ((val / n) + w1) % n; diff --git a/src/cryptonote_core/account.cpp b/src/cryptonote_core/account.cpp index 9a96de2f0..bd47c8ba4 100644 --- a/src/cryptonote_core/account.cpp +++ b/src/cryptonote_core/account.cpp @@ -10,6 +10,7 @@ #include "account.h" #include "warnings.h" #include "crypto/crypto.h" +#include "crypto/blake256.h" #include "cryptonote_core/cryptonote_basic_impl.h" #include "cryptonote_core/cryptonote_format_utils.h" using namespace std; @@ -29,11 +30,17 @@ DISABLE_VS_WARNINGS(4244 4345) m_keys = account_keys(); } //----------------------------------------------------------------- - void account_base::generate(const crypto::secret_key& recovery_key, bool recover) + crypto::secret_key account_base::generate(const crypto::secret_key& recovery_key, bool recover) { - generate_keys(m_keys.m_account_address.m_spend_public_key, m_keys.m_spend_secret_key); - generate_keys(m_keys.m_account_address.m_view_public_key, m_keys.m_view_secret_key); + crypto::secret_key first = generate_keys(m_keys.m_account_address.m_spend_public_key, m_keys.m_spend_secret_key, recovery_key, recover); + + // rng for generating second set of keys is hash of first rng. means only one set of electrum-style words needed for recovery + crypto::secret_key second; + blake256_hash((uint8_t *)&second, (uint8_t *)&first, sizeof(crypto::secret_key)); + + generate_keys(m_keys.m_account_address.m_view_public_key, m_keys.m_view_secret_key, second, true); m_creation_timestamp = time(NULL); + return first; } //----------------------------------------------------------------- const account_keys& account_base::get_keys() const diff --git a/src/cryptonote_core/account.h b/src/cryptonote_core/account.h index 745da0897..f07d4dd79 100644 --- a/src/cryptonote_core/account.h +++ b/src/cryptonote_core/account.h @@ -31,7 +31,7 @@ namespace cryptonote { public: account_base(); - void generate(const crypto::secret_key& recovery_key = crypto::secret_key(), bool recover = false); + crypto::secret_key generate(const crypto::secret_key& recovery_key = crypto::secret_key(), bool recover = false); const account_keys& get_keys() const; std::string get_public_address_str(); diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 3cea02bf1..261c150e9 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -360,9 +360,11 @@ bool simple_wallet::new_wallet(const string &wallet_file, const std::string& pas m_wallet.reset(new tools::wallet2()); m_wallet->callback(this); + + crypto::secret_key recovery_val; try { - m_wallet->generate(wallet_file, password, recovery_key, recover); + recovery_val = m_wallet->generate(wallet_file, password, recovery_key, recover); message_writer(epee::log_space::console_color_white, true) << "Generated new wallet: " << m_wallet->get_account().get_public_address_str() << std::endl << "view key: " << string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_view_secret_key); } catch (const std::exception& e) @@ -373,6 +375,10 @@ bool simple_wallet::new_wallet(const string &wallet_file, const std::string& pas m_wallet->init(m_daemon_address); + // convert rng value to electrum-style word list + std::string electrum_words; + crypto::ElectrumWords::bytes_to_words(recovery_val, electrum_words); + success_msg_writer() << "**********************************************************************\n" << "Your wallet has been generated.\n" << @@ -381,6 +387,8 @@ bool simple_wallet::new_wallet(const string &wallet_file, const std::string& pas "Always use \"exit\" command when closing simplewallet to save\n" << "current session's state. Otherwise, you will possibly need to synchronize \n" << "your wallet again. Your wallet key is NOT under risk anyway.\n" << + "\nYour wallet can be recovered using the following electrum-style word list:\n" << + electrum_words << "\n" << "**********************************************************************"; return true; } diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index b0c341615..59e1b0fa4 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -436,7 +436,7 @@ void wallet2::load_keys(const std::string& keys_file_name, const std::string& pa THROW_WALLET_EXCEPTION_IF(!r, error::invalid_password); } //---------------------------------------------------------------------------------------------------- -void wallet2::generate(const std::string& wallet_, const std::string& password, const crypto::secret_key& recovery_param, bool recover) +crypto::secret_key wallet2::generate(const std::string& wallet_, const std::string& password, const crypto::secret_key& recovery_param, bool recover) { clear(); prepare_file_names(wallet_); @@ -445,7 +445,7 @@ void wallet2::generate(const std::string& wallet_, const std::string& password, THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_wallet_file, ignored_ec), error::file_exists, m_wallet_file); THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_keys_file, ignored_ec), error::file_exists, m_keys_file); - m_account.generate(recovery_param, recover); + crypto::secret_key retval = m_account.generate(recovery_param, recover); m_account_public_address = m_account.get_keys().m_account_address; @@ -456,6 +456,7 @@ void wallet2::generate(const std::string& wallet_, const std::string& password, if(!r) LOG_PRINT_RED_L0("String with address text not saved"); store(); + return retval; } //---------------------------------------------------------------------------------------------------- void wallet2::wallet_exists(const std::string& file_path, bool& keys_file_exists, bool& wallet_file_exists) diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 85ed344c3..f54045b3a 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -97,7 +97,7 @@ namespace tools END_SERIALIZE() }; - void generate(const std::string& wallet, const std::string& password, const crypto::secret_key& recovery_param = crypto::secret_key(), bool recover = false); + crypto::secret_key generate(const std::string& wallet, const std::string& password, const crypto::secret_key& recovery_param = crypto::secret_key(), bool recover = false); void load(const std::string& wallet, const std::string& password); void store(); cryptonote::account_base& get_account(){return m_account;} -- cgit v1.2.3 From 72c3f36ca44a4be4d237095fd14e1ff862af5864 Mon Sep 17 00:00:00 2001 From: Thomas Winget Date: Fri, 6 Jun 2014 15:45:21 -0400 Subject: fixed some pointer- and loop-based derps --- src/crypto/electrum-words.cpp | 2 +- src/cryptonote_core/account.cpp | 3 +++ src/simplewallet/simplewallet.cpp | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) (limited to 'src/simplewallet/simplewallet.cpp') diff --git a/src/crypto/electrum-words.cpp b/src/crypto/electrum-words.cpp index 048aa403f..5489d5034 100644 --- a/src/crypto/electrum-words.cpp +++ b/src/crypto/electrum-words.cpp @@ -84,7 +84,7 @@ namespace crypto uint32_t val; - memcpy(&val, &src.data, 4); + memcpy(&val, (src.data) + (i * 4), 4); w1 = val % n; w2 = ((val / n) + w1) % n; diff --git a/src/cryptonote_core/account.cpp b/src/cryptonote_core/account.cpp index bd47c8ba4..f4de36738 100644 --- a/src/cryptonote_core/account.cpp +++ b/src/cryptonote_core/account.cpp @@ -10,7 +10,10 @@ #include "account.h" #include "warnings.h" #include "crypto/crypto.h" +extern "C" +{ #include "crypto/blake256.h" +} #include "cryptonote_core/cryptonote_basic_impl.h" #include "cryptonote_core/cryptonote_format_utils.h" using namespace std; diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 261c150e9..ef96d7b96 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -953,6 +953,8 @@ int main(int argc, char* argv[]) command_line::add_arg(desc_params, arg_daemon_port); command_line::add_arg(desc_params, arg_command); command_line::add_arg(desc_params, arg_log_level); + command_line::add_arg(desc_params, arg_recover ); + command_line::add_arg(desc_params, arg_electrum_seed ); tools::wallet_rpc_server::init_options(desc_params); po::positional_options_description positional_options; -- cgit v1.2.3 From 8bc032ed092e65e944e9032bc6042ae118346fa9 Mon Sep 17 00:00:00 2001 From: Thomas Winget Date: Fri, 6 Jun 2014 16:31:04 -0400 Subject: more pointer-based derp --- src/crypto/electrum-words.cpp | 13 +++++++++++-- src/crypto/electrum-words.h | 3 ++- src/simplewallet/simplewallet.cpp | 15 ++++++++++----- 3 files changed, 23 insertions(+), 8 deletions(-) (limited to 'src/simplewallet/simplewallet.cpp') diff --git a/src/crypto/electrum-words.cpp b/src/crypto/electrum-words.cpp index 5489d5034..a11d287b2 100644 --- a/src/crypto/electrum-words.cpp +++ b/src/crypto/electrum-words.cpp @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -55,14 +56,22 @@ namespace crypto val = w1 + n * ((w2 - w1) % n) + n * n * ((w3 - w2) % n); - memcpy(&dst.data + i * 4, &val, 4); // copy 4 bytes to position + memcpy(dst.data + i * 4, &val, 4); // copy 4 bytes to position } + std::string wlist_copy = words; if (wlist.size() == 12) { - memcpy(&dst.data, &dst.data + 16, 16); // if electrum 12-word seed, duplicate + memcpy(dst.data, dst.data + 16, 16); // if electrum 12-word seed, duplicate + wlist_copy += ' '; + wlist_copy += words; } + std::string back_to_words; + bytes_to_words(dst, back_to_words); + + assert(wlist_copy == back_to_words); // sanity check + return true; } diff --git a/src/crypto/electrum-words.h b/src/crypto/electrum-words.h index f5f8d1d95..a533299bd 100644 --- a/src/crypto/electrum-words.h +++ b/src/crypto/electrum-words.h @@ -5,6 +5,7 @@ */ #include +#include #include #include "crypto/crypto.h" // for declaration of crypto::secret_key @@ -18,7 +19,7 @@ namespace crypto bool words_to_bytes(const std::string& words, crypto::secret_key& dst); bool bytes_to_words(const crypto::secret_key& src, std::string& words); - const std::map wordsMap = { + const std::map wordsMap = { {"like", 0}, {"just", 1}, {"love", 2}, diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index ef96d7b96..55099199d 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -255,10 +255,15 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm) return false; } - size_t c = 0; - if(!m_generate_new.empty()) ++c; - if(!m_wallet_file.empty()) ++c; - if (1 != c) + if(m_recover) + { + if (m_generate_new.empty()) + { + fail_msg_writer() << "You must specify a wallet file name to recover to using either --generate-new-wallet=\"name\""; + return false; + } + } + else if(!m_generate_new.empty() ^ !m_wallet_file.empty()) { if(!ask_wallet_create_if_needed()) return false; @@ -286,7 +291,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm) } } - if (!m_generate_new.empty()) + if (!m_generate_new.empty() || m_recover) { // check for recover flag. if present, require electrum word list (only recovery option for now). if (m_recover) -- cgit v1.2.3 From ce352392d53fd2679ba2671349543528207a923e Mon Sep 17 00:00:00 2001 From: Thomas Winget Date: Sun, 8 Jun 2014 18:12:38 -0400 Subject: DRY cin input_line (and test replacement of non-DRY usage) --- src/common/command_line.cpp | 12 ++++++++++++ src/common/command_line.h | 3 +++ src/simplewallet/simplewallet.cpp | 10 ++++------ 3 files changed, 19 insertions(+), 6 deletions(-) (limited to 'src/simplewallet/simplewallet.cpp') diff --git a/src/common/command_line.cpp b/src/common/command_line.cpp index 0b90345d9..d507f36a7 100644 --- a/src/common/command_line.cpp +++ b/src/common/command_line.cpp @@ -3,9 +3,21 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "command_line.h" +#include "string_tools.h" namespace command_line { + std::string input_line(const std::string& prompt) + { + std::cout << prompt; + + std::string buf; + std::getline(std::cin, buf); + + return epee::string_tools::trim(buf); + + } + const arg_descriptor arg_help = {"help", "Produce help message"}; const arg_descriptor arg_version = {"version", "Output version information"}; const arg_descriptor arg_data_dir = {"data-dir", "Specify data directory"}; diff --git a/src/common/command_line.h b/src/common/command_line.h index 860653772..a6f78569c 100644 --- a/src/common/command_line.h +++ b/src/common/command_line.h @@ -14,6 +14,9 @@ namespace command_line { + + std::string input_line(const std::string& prompt); + template struct arg_descriptor; diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 55099199d..24ecb4504 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -212,12 +212,10 @@ bool simple_wallet::ask_wallet_create_if_needed() { std::string wallet_path; - std::cout << "Specify wallet file name (e.g., wallet.bin). If the wallet doesn't exist, it will be created.\n"; - std::cout << "Wallet file name: "; - - std::getline(std::cin, wallet_path); - - wallet_path = string_tools::trim(wallet_path); + wallet_path = command_line::input_line( + "Specify wallet file name (e.g., wallet.bin). If the wallet doesn't exist, it will be created.\n" + "Wallet file name: " + ); bool keys_file_exists; bool wallet_file_exists; -- cgit v1.2.3 From b6a475119731d88aec017fa1d69128c20da6b303 Mon Sep 17 00:00:00 2001 From: Thomas Winget Date: Sun, 8 Jun 2014 18:59:02 -0400 Subject: reworked command line args for simplewallet. --generate-new-wallet and --wallet-file are now properly mutually-exclusive. --- src/simplewallet/simplewallet.cpp | 47 ++++++++++++++++++++++++--------------- src/simplewallet/simplewallet.h | 2 +- 2 files changed, 30 insertions(+), 19 deletions(-) (limited to 'src/simplewallet/simplewallet.cpp') diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 24ecb4504..4131638ac 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -41,7 +41,7 @@ namespace const command_line::arg_descriptor arg_daemon_host = {"daemon-host", "Use daemon instance at host instead of localhost", ""}; const command_line::arg_descriptor arg_password = {"password", "Wallet password", "", true}; const command_line::arg_descriptor arg_electrum_seed = {"electrum-seed", "Specify electrum seed for wallet recovery/creation", ""}; - const command_line::arg_descriptor arg_recover = {"recover", "Recover wallet using mnemonic generator (e.g. electrum word list)", false}; + const command_line::arg_descriptor arg_restore_deterministic_wallet = {"restore-deterministic-wallet", "Recover wallet using electrum-style mnemonic", false}; const command_line::arg_descriptor arg_daemon_port = {"daemon-port", "Use daemon instance at port instead of 8081", 0}; const command_line::arg_descriptor arg_log_level = {"set_log", "", 0, true}; @@ -253,18 +253,23 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm) return false; } - if(m_recover) + if(m_restore_deterministic_wallet) { if (m_generate_new.empty()) { - fail_msg_writer() << "You must specify a wallet file name to recover to using either --generate-new-wallet=\"name\""; + fail_msg_writer() << "You must specify a wallet file name to recover to using --wallet-file=\"name\""; return false; } } - else if(!m_generate_new.empty() ^ !m_wallet_file.empty()) + + if(!m_generate_new.empty() && !m_wallet_file.empty()) { - if(!ask_wallet_create_if_needed()) - return false; + fail_msg_writer() << "Specifying both --generate-new-wallet=\"wallet_name\" and --wallet-file=\"wallet_name\" doesn't make sense!"; + return false; + } + else if (m_generate_new.empty() && m_wallet_file.empty()) + { + if(!ask_wallet_create_if_needed()) return false; } if (m_daemon_host.empty()) @@ -289,26 +294,32 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm) } } - if (!m_generate_new.empty() || m_recover) + if (!m_generate_new.empty() || m_restore_deterministic_wallet) { + if (m_wallet_file.empty()) m_wallet_file = m_generate_new; // alias for simplicity later + // check for recover flag. if present, require electrum word list (only recovery option for now). - if (m_recover) + if (m_restore_deterministic_wallet) { if (m_electrum_seed.empty()) { - fail_msg_writer() << "specify a recovery parameter (e.g. electrum word list) with the recover option"; - return false; + m_electrum_seed = command_line::input_line("Specify electrum seed: "); + if (m_electrum_seed.empty()) + { + fail_msg_writer() << "specify a recovery parameter (e.g. electrum word list) with the --electrum-seed=\"words list here\""; + return false; + } } else // verify recovery param (electrum word list) and convert to byte representation { - CHECK_AND_ASSERT_MES( - crypto::ElectrumWords::words_to_bytes(m_electrum_seed, m_recovery_key), - false, - "electrum-style word list failed verification" - ); + if (!crypto::ElectrumWords::words_to_bytes(m_electrum_seed, m_recovery_key)) + { + fail_msg_writer() << "electrum-style word list failed verification"; + return false; + } } } - bool r = new_wallet(m_generate_new, pwd_container.password(), m_recovery_key, m_recover); + bool r = new_wallet(m_wallet_file, pwd_container.password(), m_recovery_key, m_restore_deterministic_wallet); CHECK_AND_ASSERT_MES(r, false, "account creation failed"); } else @@ -336,7 +347,7 @@ void simple_wallet::handle_command_line(const boost::program_options::variables_ m_daemon_host = command_line::get_arg(vm, arg_daemon_host); m_daemon_port = command_line::get_arg(vm, arg_daemon_port); m_electrum_seed = command_line::get_arg(vm, arg_electrum_seed); - m_recover = command_line::get_arg(vm, arg_recover); + m_restore_deterministic_wallet = command_line::get_arg(vm, arg_restore_deterministic_wallet); } //---------------------------------------------------------------------------------------------------- bool simple_wallet::try_connect_to_daemon() @@ -956,7 +967,7 @@ int main(int argc, char* argv[]) command_line::add_arg(desc_params, arg_daemon_port); command_line::add_arg(desc_params, arg_command); command_line::add_arg(desc_params, arg_log_level); - command_line::add_arg(desc_params, arg_recover ); + command_line::add_arg(desc_params, arg_restore_deterministic_wallet ); command_line::add_arg(desc_params, arg_electrum_seed ); tools::wallet_rpc_server::init_options(desc_params); diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h index d1f9fe98b..37ccfe895 100644 --- a/src/simplewallet/simplewallet.h +++ b/src/simplewallet/simplewallet.h @@ -131,7 +131,7 @@ namespace cryptonote std::string m_electrum_seed; // electrum-style seed parameter crypto::secret_key m_recovery_key; // recovery key (used as random for wallet gen) - bool m_recover; // recover flag + bool m_restore_deterministic_wallet; // recover flag std::string m_daemon_address; std::string m_daemon_host; -- cgit v1.2.3 From da37b6f15b6eb1f7b4ac9802a3350413d303a5c9 Mon Sep 17 00:00:00 2001 From: Thomas Winget Date: Sun, 8 Jun 2014 20:04:32 -0400 Subject: allow two-random-numbers wallet generation (but not as default) --- src/cryptonote_core/account.cpp | 4 +- src/cryptonote_core/account.h | 2 +- src/simplewallet/simplewallet.cpp | 77 ++++++++++++++++++++++----------------- src/simplewallet/simplewallet.h | 5 +-- src/wallet/wallet2.cpp | 4 +- src/wallet/wallet2.h | 2 +- 6 files changed, 52 insertions(+), 42 deletions(-) (limited to 'src/simplewallet/simplewallet.cpp') diff --git a/src/cryptonote_core/account.cpp b/src/cryptonote_core/account.cpp index f4de36738..7da1c6745 100644 --- a/src/cryptonote_core/account.cpp +++ b/src/cryptonote_core/account.cpp @@ -33,7 +33,7 @@ DISABLE_VS_WARNINGS(4244 4345) m_keys = account_keys(); } //----------------------------------------------------------------- - crypto::secret_key account_base::generate(const crypto::secret_key& recovery_key, bool recover) + crypto::secret_key account_base::generate(const crypto::secret_key& recovery_key, bool recover, bool two_random) { crypto::secret_key first = generate_keys(m_keys.m_account_address.m_spend_public_key, m_keys.m_spend_secret_key, recovery_key, recover); @@ -41,7 +41,7 @@ DISABLE_VS_WARNINGS(4244 4345) crypto::secret_key second; blake256_hash((uint8_t *)&second, (uint8_t *)&first, sizeof(crypto::secret_key)); - generate_keys(m_keys.m_account_address.m_view_public_key, m_keys.m_view_secret_key, second, true); + generate_keys(m_keys.m_account_address.m_view_public_key, m_keys.m_view_secret_key, second, two_random ? false : true); m_creation_timestamp = time(NULL); return first; } diff --git a/src/cryptonote_core/account.h b/src/cryptonote_core/account.h index f07d4dd79..cb77d7c4e 100644 --- a/src/cryptonote_core/account.h +++ b/src/cryptonote_core/account.h @@ -31,7 +31,7 @@ namespace cryptonote { public: account_base(); - crypto::secret_key generate(const crypto::secret_key& recovery_key = crypto::secret_key(), bool recover = false); + crypto::secret_key generate(const crypto::secret_key& recovery_key = crypto::secret_key(), bool recover = false, bool two_random = false); const account_keys& get_keys() const; std::string get_public_address_str(); diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 4131638ac..95d163f2e 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -42,6 +42,7 @@ namespace const command_line::arg_descriptor arg_password = {"password", "Wallet password", "", true}; const command_line::arg_descriptor arg_electrum_seed = {"electrum-seed", "Specify electrum seed for wallet recovery/creation", ""}; const command_line::arg_descriptor arg_restore_deterministic_wallet = {"restore-deterministic-wallet", "Recover wallet using electrum-style mnemonic", false}; + const command_line::arg_descriptor arg_non_deterministic = {"non-deterministic", "requires --generate-new-wallet, uses old generation method", false}; const command_line::arg_descriptor arg_daemon_port = {"daemon-port", "Use daemon instance at port instead of 8081", 0}; const command_line::arg_descriptor arg_log_level = {"set_log", "", 0, true}; @@ -221,6 +222,16 @@ bool simple_wallet::ask_wallet_create_if_needed() bool wallet_file_exists; tools::wallet2::wallet_exists(wallet_path, keys_file_exists, wallet_file_exists); + // add logic to error out if new wallet requested but named wallet file exists + if (keys_file_exists || wallet_file_exists) + { + if (!m_generate_new.empty() || m_restore_deterministic_wallet) + { + fail_msg_writer() << "Attempting to generate or restore wallet, but specified file(s) exist. Exiting to not risk overwriting."; + return false; + } + } + bool r; if(keys_file_exists) { @@ -253,15 +264,6 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm) return false; } - if(m_restore_deterministic_wallet) - { - if (m_generate_new.empty()) - { - fail_msg_writer() << "You must specify a wallet file name to recover to using --wallet-file=\"name\""; - return false; - } - } - if(!m_generate_new.empty() && !m_wallet_file.empty()) { fail_msg_writer() << "Specifying both --generate-new-wallet=\"wallet_name\" and --wallet-file=\"wallet_name\" doesn't make sense!"; @@ -301,25 +303,29 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm) // check for recover flag. if present, require electrum word list (only recovery option for now). if (m_restore_deterministic_wallet) { + if (m_non_deterministic) + { + fail_msg_writer() << "Cannot specify both --restore-deterministic-wallet and --non-deterministic"; + return false; + } + if (m_electrum_seed.empty()) { m_electrum_seed = command_line::input_line("Specify electrum seed: "); if (m_electrum_seed.empty()) { - fail_msg_writer() << "specify a recovery parameter (e.g. electrum word list) with the --electrum-seed=\"words list here\""; + fail_msg_writer() << "specify a recovery parameter with the --electrum-seed=\"words list here\""; return false; } } - else // verify recovery param (electrum word list) and convert to byte representation + + if (!crypto::ElectrumWords::words_to_bytes(m_electrum_seed, m_recovery_key)) { - if (!crypto::ElectrumWords::words_to_bytes(m_electrum_seed, m_recovery_key)) - { - fail_msg_writer() << "electrum-style word list failed verification"; - return false; - } + fail_msg_writer() << "electrum-style word list failed verification"; + return false; } } - bool r = new_wallet(m_wallet_file, pwd_container.password(), m_recovery_key, m_restore_deterministic_wallet); + bool r = new_wallet(m_wallet_file, pwd_container.password(), m_recovery_key, m_restore_deterministic_wallet, m_non_deterministic); CHECK_AND_ASSERT_MES(r, false, "account creation failed"); } else @@ -341,13 +347,14 @@ bool simple_wallet::deinit() //---------------------------------------------------------------------------------------------------- void simple_wallet::handle_command_line(const boost::program_options::variables_map& vm) { - m_wallet_file = command_line::get_arg(vm, arg_wallet_file); - m_generate_new = command_line::get_arg(vm, arg_generate_new_wallet); - m_daemon_address = command_line::get_arg(vm, arg_daemon_address); - m_daemon_host = command_line::get_arg(vm, arg_daemon_host); - m_daemon_port = command_line::get_arg(vm, arg_daemon_port); - m_electrum_seed = command_line::get_arg(vm, arg_electrum_seed); - m_restore_deterministic_wallet = command_line::get_arg(vm, arg_restore_deterministic_wallet); + m_wallet_file = command_line::get_arg(vm, arg_wallet_file); + m_generate_new = command_line::get_arg(vm, arg_generate_new_wallet); + m_daemon_address = command_line::get_arg(vm, arg_daemon_address); + m_daemon_host = command_line::get_arg(vm, arg_daemon_host); + m_daemon_port = command_line::get_arg(vm, arg_daemon_port); + m_electrum_seed = command_line::get_arg(vm, arg_electrum_seed); + m_restore_deterministic_wallet = command_line::get_arg(vm, arg_restore_deterministic_wallet); + m_non_deterministic = command_line::get_arg(vm, arg_non_deterministic); } //---------------------------------------------------------------------------------------------------- bool simple_wallet::try_connect_to_daemon() @@ -362,13 +369,8 @@ bool simple_wallet::try_connect_to_daemon() return true; } -bool simple_wallet::parse_electrum() -{ - return false; -} - //---------------------------------------------------------------------------------------------------- -bool simple_wallet::new_wallet(const string &wallet_file, const std::string& password, const crypto::secret_key& recovery_key, bool recover) +bool simple_wallet::new_wallet(const string &wallet_file, const std::string& password, const crypto::secret_key& recovery_key, bool recover, bool two_random) { m_wallet_file = wallet_file; @@ -378,7 +380,7 @@ bool simple_wallet::new_wallet(const string &wallet_file, const std::string& pas crypto::secret_key recovery_val; try { - recovery_val = m_wallet->generate(wallet_file, password, recovery_key, recover); + recovery_val = m_wallet->generate(wallet_file, password, recovery_key, recover, two_random); message_writer(epee::log_space::console_color_white, true) << "Generated new wallet: " << m_wallet->get_account().get_public_address_str() << std::endl << "view key: " << string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_view_secret_key); } catch (const std::exception& e) @@ -393,6 +395,15 @@ bool simple_wallet::new_wallet(const string &wallet_file, const std::string& pas std::string electrum_words; crypto::ElectrumWords::bytes_to_words(recovery_val, electrum_words); + std::string print_electrum = ""; + + if (!two_random) + { + print_electrum = "\nYour wallet can be recovered using the following electrum-style word list:\n"; + print_electrum += electrum_words; + print_electrum += "\n"; + } + success_msg_writer() << "**********************************************************************\n" << "Your wallet has been generated.\n" << @@ -401,8 +412,7 @@ bool simple_wallet::new_wallet(const string &wallet_file, const std::string& pas "Always use \"exit\" command when closing simplewallet to save\n" << "current session's state. Otherwise, you will possibly need to synchronize \n" << "your wallet again. Your wallet key is NOT under risk anyway.\n" << - "\nYour wallet can be recovered using the following electrum-style word list:\n" << - electrum_words << "\n" << + print_electrum << "**********************************************************************"; return true; } @@ -968,6 +978,7 @@ int main(int argc, char* argv[]) command_line::add_arg(desc_params, arg_command); command_line::add_arg(desc_params, arg_log_level); command_line::add_arg(desc_params, arg_restore_deterministic_wallet ); + command_line::add_arg(desc_params, arg_non_deterministic ); command_line::add_arg(desc_params, arg_electrum_seed ); tools::wallet_rpc_server::init_options(desc_params); diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h index 37ccfe895..006cdd08e 100644 --- a/src/simplewallet/simplewallet.h +++ b/src/simplewallet/simplewallet.h @@ -40,9 +40,7 @@ namespace cryptonote bool run_console_handler(); - bool parse_electrum(); - - bool new_wallet(const std::string &wallet_file, const std::string& password, const crypto::secret_key& recovery_key = crypto::secret_key(), bool recover = false); + bool new_wallet(const std::string &wallet_file, const std::string& password, const crypto::secret_key& recovery_key = crypto::secret_key(), bool recover = false, bool two_random = false); bool open_wallet(const std::string &wallet_file, const std::string& password); bool close_wallet(); @@ -132,6 +130,7 @@ namespace cryptonote crypto::secret_key m_recovery_key; // recovery key (used as random for wallet gen) bool m_restore_deterministic_wallet; // recover flag + bool m_non_deterministic; // old 2-random generation std::string m_daemon_address; std::string m_daemon_host; diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 59e1b0fa4..a63eb4be7 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -436,7 +436,7 @@ void wallet2::load_keys(const std::string& keys_file_name, const std::string& pa THROW_WALLET_EXCEPTION_IF(!r, error::invalid_password); } //---------------------------------------------------------------------------------------------------- -crypto::secret_key wallet2::generate(const std::string& wallet_, const std::string& password, const crypto::secret_key& recovery_param, bool recover) +crypto::secret_key wallet2::generate(const std::string& wallet_, const std::string& password, const crypto::secret_key& recovery_param, bool recover, bool two_random) { clear(); prepare_file_names(wallet_); @@ -445,7 +445,7 @@ crypto::secret_key wallet2::generate(const std::string& wallet_, const std::stri THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_wallet_file, ignored_ec), error::file_exists, m_wallet_file); THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_keys_file, ignored_ec), error::file_exists, m_keys_file); - crypto::secret_key retval = m_account.generate(recovery_param, recover); + crypto::secret_key retval = m_account.generate(recovery_param, recover, two_random); m_account_public_address = m_account.get_keys().m_account_address; diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index f54045b3a..534a0517b 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -97,7 +97,7 @@ namespace tools END_SERIALIZE() }; - crypto::secret_key generate(const std::string& wallet, const std::string& password, const crypto::secret_key& recovery_param = crypto::secret_key(), bool recover = false); + crypto::secret_key generate(const std::string& wallet, const std::string& password, const crypto::secret_key& recovery_param = crypto::secret_key(), bool recover = false, bool two_random = false); void load(const std::string& wallet, const std::string& password); void store(); cryptonote::account_base& get_account(){return m_account;} -- cgit v1.2.3 From 305def9493d9ba20246068b7676e50f384b6ae39 Mon Sep 17 00:00:00 2001 From: tom Date: Mon, 9 Jun 2014 18:28:08 -0400 Subject: changed some print messages --- src/simplewallet/simplewallet.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/simplewallet/simplewallet.cpp') diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 95d163f2e..e2b0cab13 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -42,7 +42,7 @@ namespace const command_line::arg_descriptor arg_password = {"password", "Wallet password", "", true}; const command_line::arg_descriptor arg_electrum_seed = {"electrum-seed", "Specify electrum seed for wallet recovery/creation", ""}; const command_line::arg_descriptor arg_restore_deterministic_wallet = {"restore-deterministic-wallet", "Recover wallet using electrum-style mnemonic", false}; - const command_line::arg_descriptor arg_non_deterministic = {"non-deterministic", "requires --generate-new-wallet, uses old generation method", false}; + const command_line::arg_descriptor arg_non_deterministic = {"non-deterministic", "created non-deterministic view and spend keys", false}; const command_line::arg_descriptor arg_daemon_port = {"daemon-port", "Use daemon instance at port instead of 8081", 0}; const command_line::arg_descriptor arg_log_level = {"set_log", "", 0, true}; @@ -399,7 +399,7 @@ bool simple_wallet::new_wallet(const string &wallet_file, const std::string& pas if (!two_random) { - print_electrum = "\nYour wallet can be recovered using the following electrum-style word list:\n"; + print_electrum = "\nPLEASE NOTE: the following 24 words can be used to recover access to your wallet. Please write them down and store them somewhere safe and secure. Please do not store them in your email or on file storage services outside of your immediate control. You will not be able to view these words again, so it is imperative to make note of them now.\n"; print_electrum += electrum_words; print_electrum += "\n"; } -- cgit v1.2.3 From 0c85229924f7e0d85cb16fedf1ffbf23f870770e Mon Sep 17 00:00:00 2001 From: tom Date: Mon, 9 Jun 2014 20:04:56 -0400 Subject: changed text a bit more --- src/simplewallet/simplewallet.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'src/simplewallet/simplewallet.cpp') diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index e2b0cab13..21f3a8688 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -42,7 +42,7 @@ namespace const command_line::arg_descriptor arg_password = {"password", "Wallet password", "", true}; const command_line::arg_descriptor arg_electrum_seed = {"electrum-seed", "Specify electrum seed for wallet recovery/creation", ""}; const command_line::arg_descriptor arg_restore_deterministic_wallet = {"restore-deterministic-wallet", "Recover wallet using electrum-style mnemonic", false}; - const command_line::arg_descriptor arg_non_deterministic = {"non-deterministic", "created non-deterministic view and spend keys", false}; + const command_line::arg_descriptor arg_non_deterministic = {"non-deterministic", "creates non-deterministic view and spend keys", false}; const command_line::arg_descriptor arg_daemon_port = {"daemon-port", "Use daemon instance at port instead of 8081", 0}; const command_line::arg_descriptor arg_log_level = {"set_log", "", 0, true}; @@ -397,12 +397,6 @@ bool simple_wallet::new_wallet(const string &wallet_file, const std::string& pas std::string print_electrum = ""; - if (!two_random) - { - print_electrum = "\nPLEASE NOTE: the following 24 words can be used to recover access to your wallet. Please write them down and store them somewhere safe and secure. Please do not store them in your email or on file storage services outside of your immediate control. You will not be able to view these words again, so it is imperative to make note of them now.\n"; - print_electrum += electrum_words; - print_electrum += "\n"; - } success_msg_writer() << "**********************************************************************\n" << @@ -411,9 +405,16 @@ bool simple_wallet::new_wallet(const string &wallet_file, const std::string& pas "Use \"help\" command to see the list of available commands.\n" << "Always use \"exit\" command when closing simplewallet to save\n" << "current session's state. Otherwise, you will possibly need to synchronize \n" << - "your wallet again. Your wallet key is NOT under risk anyway.\n" << - print_electrum << - "**********************************************************************"; + "your wallet again. Your wallet key is NOT under risk anyway.\n" + ; + + if (!two_random) + { + success_msg_writer(true) << "\nPLEASE NOTE: the following 24 words can be used to recover access to your wallet. Please write them down and store them somewhere safe and secure. Please do not store them in your email or on file storage services outside of your immediate control. You will not be able to view these words again, so it is imperative to make note of them now.\n"; + success_msg_writer() << electrum_words; + } + success_msg_writer() << "**********************************************************************"; + return true; } //---------------------------------------------------------------------------------------------------- -- cgit v1.2.3 From c49cb0461091495c023fb9aa56ca8298a556f0a5 Mon Sep 17 00:00:00 2001 From: Thomas Winget Date: Thu, 12 Jun 2014 19:34:24 -0400 Subject: changed wallet mnemonic to use cout so it doesn't print to log --- src/simplewallet/simplewallet.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/simplewallet/simplewallet.cpp') diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 21f3a8688..6af0de9f9 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -3,6 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include +#include #include #include #include @@ -411,7 +412,7 @@ bool simple_wallet::new_wallet(const string &wallet_file, const std::string& pas if (!two_random) { success_msg_writer(true) << "\nPLEASE NOTE: the following 24 words can be used to recover access to your wallet. Please write them down and store them somewhere safe and secure. Please do not store them in your email or on file storage services outside of your immediate control. You will not be able to view these words again, so it is imperative to make note of them now.\n"; - success_msg_writer() << electrum_words; + std::cout << electrum_words << std::endl; } success_msg_writer() << "**********************************************************************"; -- cgit v1.2.3