diff options
34 files changed, 446 insertions, 799 deletions
@@ -84,6 +84,10 @@ See [LICENSE](LICENSE). If you want to help out, see [CONTRIBUTING](CONTRIBUTING.md) for a set of guidelines. +## Vulnerability Response Process + +See [Vulnerability Response Process](VULNERABILITY_RESPONSE_PROCESS.md). + ## Monero software updates and consensus protocol changes (hard fork schedule) Monero uses a fixed-schedule hard fork mechanism to implement new features. This means that users of Monero (end users and service providers) need to run current versions and update their software on a regular schedule. Here is the current schedule, versions, and compatibility. @@ -360,7 +364,7 @@ monero-wallet-cli, and possibly monerod, if you get crashes refreshing. ## Internationalization -See README.i18n +See [README.i18n](README.i18n). ## Using Tor diff --git a/VULNERABILITY_RESPONSE_PROCESS.md b/VULNERABILITY_RESPONSE_PROCESS.md new file mode 100644 index 000000000..eea3a06e7 --- /dev/null +++ b/VULNERABILITY_RESPONSE_PROCESS.md @@ -0,0 +1,143 @@ +# Monero Vulnerability Response Process + +## Preamble + +Researchers/Hackers: while you research/hack, we ask that you please refrain from committing the following: +- Denial of Service / Active exploiting against the network +- Social Engineering of Monero staff or contractors +- Any physical or electronic attempts against Monero community property and/or data centers + +## I. Point of Contacts for Security Issues + +``` +ric@getmonero.org +BDA6 BD70 42B7 21C4 67A9 759D 7455 C5E3 C0CD CEB9 + +luigi1111@getmonero.org +8777 AB8F 778E E894 87A2 F8E7 F4AC A018 3641 E010 + +moneromooo.monero@gmail.com +48B0 8161 FBDA DFE3 93AD FC3E 686F 0745 4D6C EFC3 +``` + +## II. Security Response Team + +- fluffypony +- luigi1111 +- moneromooo + +## III. Incident Response + +1. Researcher submits report via one or both of two methods: + - a. Email + - b. [HackerOne](https://hackerone.com/monero) + +2. Response Team designates a Response Manager who is in charge of the particular report based on availability and/or knowledge-set + +3. In no more than 3 working days, Response Team should gratefully respond to researcher using only encrypted, secure channels + +4. Response Manager makes inquiries to satisfy any needed information to confirm if submission is indeed a vulnerability + - a. If submission proves to be vulnerable, proceed to next step + - b. If not vulnerable: + - i. Response Manager responds with reasons why submission is not a vulnerability + - ii. Response Manager moves discussion to a new or existing ticket on GitHub if necessary + +5. If over email, Response Manager opens a HackerOne issue for new submission + +6. Establish severity of vulnerability: + - a. HIGH: impacts network as a whole, has potential to break entire network, results in the loss of monero, or is on a scale of great catastrophe + - b. MEDIUM: impacts individual nodes, wallets, or must be carefully exploited + - c. LOW: is not easily exploitable + +7. Respond according to the severity of the vulnerability: + - a. HIGH severities must be notified on website and reddit /r/Monero within 3 working days of classification + - i. The notification should list appropriate steps for users to take, if any + - ii. The notification must not include any details that could suggest an exploitation path + - iii. The latter takes precedence over the former + - b. MEDIUM and HIGH severities will require a Point Release + - c. LOW severities will be addressed in the next Regular Release + +8. Response Team applies appropriate patch(es) + - a. Response Manager designates a PRIVATE git "hotfix branch" to work in + - b. Patches are reviewed with the researcher + - c. Any messages associated with PUBLIC commits during the time of review should not make reference to the security nature of the PRIVATE branch or its commits + - d. Vulnerability announcement is drafted + - i. Include the severity of the vulnerability + - ii. Include all vulnerable systems/apps/code + - iii. Include solutions (if any) if patch cannot be applied + - e. Release date is discussed + +9. At release date, Response Team coordinates with developers to finalize update: + - a. Response Manager propagates the "hotfix branch" to trunk + - b. Response Manager includes vulnerability announcement draft in release notes + - c. Proceed with the Point or Regular Release + +## IV. Post-release Disclosure Process + +1. Response Team has 90 days to fulfill all points within section III + +2. If the Incident Response process in section III is successfully completed: + - a. Response Manager contacts researcher and asks if researcher wishes for credit + - b. Finalize vulnerability announcement draft and include the following: + - i. Project name and URL + - ii. Versions known to be affected + - iii. Versions known to be not affected (for example, the vulnerable code was introduced in a recent version, and older versions are therefore unaffected) + - iv. Versions not checked + - v. Type of vulnerability and its impact + - vi. If already obtained or applicable, a CVE-ID + - vii. The planned, coordinated release date + - viii. Mitigating factors (for example, the vulnerability is only exposed in uncommon, non-default configurations) + - ix. Workarounds (configuration changes users can make to reduce their exposure to the vulnerability) + - x. If applicable, credits to the original reporter + - c. Release finalized vulnerability announcement on website and reddit /r/Monero + - d. For HIGH severities, release finalized vulnerability announcement on well-known mailing lists: + - i. oss-security@lists.openwall.com + - ii. bugtraq@securityfocus.com + - e. If applicable, developers request a CVE-ID + - i. The commit that applied the fix is made reference too in a future commit and includes a CVE-ID + +3. If the Incident Response process in section III is *not* successfully completed: + - a. Response Team and developers organize an IRC meeting to discuss why/what points in section III were not resolved and how the team can resolve them in the future + - b. Any developer meetings immediately following the incident should include points made in section V + - c. If disputes arise about whether or when to disclose information about a vulnerability, the Response Team will publicly discuss the issue via IRC and attempt to reach consensus + - d. If consensus on a timely disclosure is not met (no later than 90 days), the researcher (after 90 days) has every right to expose the vulnerability to the public + +## V. Incident Analysis + +1. Isolate codebase + - a. Response Team and developers should coordinate to work on the following: + - i. Problematic implementation of classes/libraries/functions, etc. + - ii. Focus on apps/distro packaging, etc. + - iii. Operator/config error, etc. + +2. Auditing + - a. Response Team and developers should coordinate to work on the following: + - i. Auditing of problem area(s) as discussed in point 1 + - ii. Generate internal reports and store for future reference + - iii. If results are not sensitive, share with the public via IRC or GitHub + +3. Response Team has 45 days following completion of section III to ensure completion of section V + +## VI. Resolutions + +Any further questions or resolutions regarding the incident(s) between the researcher and response + development team after public disclosure can be addressed via the following: + +- [GitHub](https://github.com/monero-project/monero/issues/) +- [HackerOne](https://hackerone.com/monero) +- [Reddit /r/Monero](https://reddit.com/r/Monero/) +- IRC +- Email + +## VII. Continuous Improvement + +1. Response Team and developers should hold annual meetings to review the previous year's incidents + +2. Response Team or designated person(s) should give a brief presentation, including: + - a. Areas of Monero affected by the incidents + - b. Any network downtime or monetary cost (if any) of the incidents + - c. Ways in which the incidents could have been avoided (if any) + - d. How effective this process was in dealing with the incidents + +3. After the presentation, Response Team and developers should discuss: + - a. Potential changes to development processes to reduce future incidents + - b. Potential changes to this process to improve future responses diff --git a/contrib/epee/include/file_io_utils.h b/contrib/epee/include/file_io_utils.h index 7e8521838..c387743a6 100644 --- a/contrib/epee/include/file_io_utils.h +++ b/contrib/epee/include/file_io_utils.h @@ -28,197 +28,13 @@ #ifndef _FILE_IO_UTILS_H_ #define _FILE_IO_UTILS_H_ - -//#include <sys/types.h> -//#include <sys/stat.h> - #include <iostream> #include <boost/filesystem.hpp> - -#ifndef MAKE64 - #define MAKE64(low,high) ((__int64)(((DWORD)(low)) | ((__int64)((DWORD)(high))) << 32)) -#endif - -#ifdef WINDOWS_PLATFORM -#include <psapi.h> -#include <strsafe.h> -#include <string.h> -#include <mbstring.h> - -#endif - - - namespace epee { namespace file_io_utils { -#ifdef WINDOWS_PLATFORM - - inline - std::string get_temp_file_name_a() - { - std::string str_result; - char sz_temp[MAX_PATH*2] = {0}; - if(!::GetTempPathA( sizeof( sz_temp ), sz_temp )) - return str_result; - - char sz_temp_file[MAX_PATH*2] = {0}; - if(!::GetTempFileNameA( sz_temp, "mail", 0, sz_temp_file)) - return str_result; - sz_temp_file[sizeof(sz_temp_file)-1] = 0; //be happy! - str_result = sz_temp_file; - return str_result; - } - - -#ifdef BOOST_LEXICAL_CAST_INCLUDED - inline - bool get_not_used_filename(const std::string& folder, OUT std::string& result_name) - { - DWORD folder_attr = ::GetFileAttributesA(folder.c_str()); - if(folder_attr == INVALID_FILE_ATTRIBUTES) - return false; - if(!(folder_attr&FILE_ATTRIBUTE_DIRECTORY)) - return false; - - - std::string base_name = folder + "\\tmp"; - std::string tmp_name; - bool name_found = false; - int current_index = 0; - tmp_name = base_name + boost::lexical_cast<std::string>(current_index) + ".tmp"; - while(!name_found) - { - if(INVALID_FILE_ATTRIBUTES == ::GetFileAttributesA(tmp_name.c_str())) - name_found = true; - else - { - current_index++; - tmp_name = base_name + boost::lexical_cast<std::string>(current_index) + ".tmp"; - } - } - result_name = tmp_name; - return true; - } -#endif - - inline - std::string get_temp_folder_a() - { - std::string str_result; - char sz_temp[MAX_PATH*2] = {0}; - if(!::GetTempPathA( sizeof( sz_temp ), sz_temp )) - return str_result; - sz_temp[(sizeof(sz_temp)/sizeof(sz_temp[0])) -1] = 0; - str_result = sz_temp; - return str_result; - } - - std::string convert_from_device_path_to_standart(const std::string& path) - { - - - STRSAFE_LPSTR pszFilename = (STRSAFE_LPSTR)path.c_str(); - - // Translate path with device name to drive letters. - char szTemp[4000] = {0}; - - if (::GetLogicalDriveStringsA(sizeof(szTemp)-1, szTemp)) - { - char szName[MAX_PATH]; - char szDrive[3] = " :"; - BOOL bFound = FALSE; - char* p = szTemp; - - do - { - // Copy the drive letter to the template string - *szDrive = *p; - - // Look up each device name - if (::QueryDosDeviceA(szDrive, szName, sizeof(szName))) - { - UINT uNameLen = strlen(szName); - - if (uNameLen < MAX_PATH) - { - bFound = _mbsnbicmp((const unsigned char*)pszFilename, (const unsigned char*)szName, - uNameLen) == 0; - - if (bFound) - { - // Reconstruct pszFilename using szTempFile - // Replace device path with DOS path - char szTempFile[MAX_PATH] = {0}; - StringCchPrintfA(szTempFile, - MAX_PATH, - "%s%s", - szDrive, - pszFilename+uNameLen); - return szTempFile; - //::StringCchCopyNA(pszFilename, MAX_PATH+1, szTempFile, strlen(szTempFile)); - } - } - } - - // Go to the next NULL character. - while (*p++); - } while (!bFound && *p); // end of string - } - - return ""; - } - - inline - std::string get_process_path_by_pid(DWORD pid) - { - std::string res; - - HANDLE hprocess = 0; - if( hprocess = ::OpenProcess( PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, FALSE, pid) ) - { - char buff[MAX_PATH]= {0}; - if(!::GetModuleFileNameExA( hprocess, 0, buff, MAX_PATH - 1 )) - res = "Unknown_b"; - else - { - buff[MAX_PATH - 1]=0; //be happy! - res = buff; - std::string::size_type a = res.rfind( '\\' ); - if ( a != std::string::npos ) - res.erase( 0, a+1); - - } - ::CloseHandle( hprocess ); - }else - res = "Unknown_a"; - - return res; - } - - - - - - inline - std::wstring get_temp_file_name_w() - { - std::wstring str_result; - wchar_t sz_temp[MAX_PATH*2] = {0}; - if(!::GetTempPathW( sizeof(sz_temp)/sizeof(sz_temp[0]), sz_temp )) - return str_result; - - wchar_t sz_temp_file[MAX_PATH+1] = {0}; - if(!::GetTempFileNameW( sz_temp, L"mail", 0, sz_temp_file)) - return str_result; - - sz_temp_file[(sizeof(sz_temp_file)/sizeof(sz_temp_file[0]))-1] = 0; //be happy! - str_result = sz_temp_file; - return str_result; - } -#endif inline bool is_file_exist(const std::string& path) { @@ -226,35 +42,6 @@ namespace file_io_utils return boost::filesystem::exists(p); } - /* - inline - bool save_string_to_handle(HANDLE hfile, const std::string& str) - { - - - - if( INVALID_HANDLE_VALUE != hfile ) - { - DWORD dw; - if( !::WriteFile( hfile, str.data(), (DWORD) str.size(), &dw, NULL) ) - { - int err_code = GetLastError(); - //LOG_PRINT("Failed to write to file handle: " << hfile<< " Last error code:" << err_code << " : " << log_space::get_win32_err_descr(err_code), LOG_LEVEL_2); - return false; - } - ::CloseHandle(hfile); - return true; - }else - { - //LOG_WIN32_ERROR(::GetLastError()); - return false; - } - - return false; - }*/ - - - inline bool save_string_to_file(const std::string& path_to_file, const std::string& str) { @@ -275,32 +62,6 @@ namespace file_io_utils } } - /* - inline - bool load_form_handle(HANDLE hfile, std::string& str) - { - if( INVALID_HANDLE_VALUE != hfile ) - { - bool res = true; - DWORD dw = 0; - DWORD fsize = ::GetFileSize(hfile, &dw); - if(fsize > 300000000) - { - ::CloseHandle(hfile); - return false; - } - if(fsize) - { - str.resize(fsize); - if(!::ReadFile( hfile, (LPVOID)str.data(), (DWORD)str.size(), &dw, NULL)) - res = false; - } - ::CloseHandle(hfile); - return res; - } - return false; - } - */ inline bool get_file_time(const std::string& path_to_file, OUT time_t& ft) { @@ -371,84 +132,6 @@ namespace file_io_utils return false; } } - - /* - bool remove_dir_and_subirs(const char* path_to_dir); - - inline - bool clean_dir(const char* path_to_dir) - { - if(!path_to_dir) - return false; - - std::string folder = path_to_dir; - WIN32_FIND_DATAA find_data = {0}; - HANDLE hfind = ::FindFirstFileA((folder + "\\*.*").c_str(), &find_data); - if(INVALID_HANDLE_VALUE == hfind) - return false; - do{ - if(!strcmp("..", find_data.cFileName) || (!strcmp(".", find_data.cFileName))) - continue; - - if(find_data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) - { - if(!remove_dir_and_subirs((folder + "\\" + find_data.cFileName).c_str())) - return false; - }else - { - if(!::DeleteFileA((folder + "\\" + find_data.cFileName).c_str())) - return false; - } - - - }while(::FindNextFileA(hfind, &find_data)); - ::FindClose(hfind); - - return true; - } - */ -#ifdef WINDOWS_PLATFORM - inline bool get_folder_content(const std::string& path, std::list<WIN32_FIND_DATAA>& OUT target_list) - { - WIN32_FIND_DATAA find_data = {0}; - HANDLE hfind = ::FindFirstFileA((path + "\\*.*").c_str(), &find_data); - if(INVALID_HANDLE_VALUE == hfind) - return false; - do{ - if(!strcmp("..", find_data.cFileName) || (!strcmp(".", find_data.cFileName))) - continue; - - target_list.push_back(find_data); - - }while(::FindNextFileA(hfind, &find_data)); - ::FindClose(hfind); - - return true; - } -#endif - inline bool get_folder_content(const std::string& path, std::list<std::string>& OUT target_list, bool only_files = false) - { - try - { - - boost::filesystem::directory_iterator end_itr; // default construction yields past-the-end - for ( boost::filesystem::directory_iterator itr( path ); itr != end_itr; ++itr ) - { - if ( only_files && boost::filesystem::is_directory(itr->status()) ) - { - continue; - } - target_list.push_back(itr->path().filename().string()); - } - - } - - catch(...) - { - return false; - } - return true; - } } } diff --git a/contrib/epee/include/string_coding.h b/contrib/epee/include/string_coding.h index a2e3d6eb2..82050ef96 100644 --- a/contrib/epee/include/string_coding.h +++ b/contrib/epee/include/string_coding.h @@ -29,7 +29,7 @@ #define _STRING_CODING_H_ #include <string> -//#include "md5_l.h" + namespace epee { namespace string_encoding @@ -62,23 +62,6 @@ namespace string_encoding (char*)str_trgt.data(), (int)str_trgt.size(), 0, 0); return str_trgt;*/ } -#ifdef WINDOWS_PLATFORM_EX - inline std::string convert_to_ansii_win(const std::wstring& str_from) - { - - int code_page = CP_ACP; - std::string str_trgt; - if(!str_from.size()) - return str_trgt; - int cb = ::WideCharToMultiByte( code_page, 0, str_from.data(), (__int32)str_from.size(), 0, 0, 0, 0 ); - if(!cb) - return str_trgt; - str_trgt.resize(cb); - ::WideCharToMultiByte( code_page, 0, str_from.data(), (int)str_from.size(), - (char*)str_trgt.data(), (int)str_trgt.size(), 0, 0); - return str_trgt; - } -#endif inline std::string convert_to_ansii(const std::string& str_from) { @@ -254,41 +237,6 @@ namespace string_encoding return ret; } - //md5 -#ifdef MD5_H - inline - std::string get_buf_as_hex_string(const void* pbuf, size_t len) - { - std::ostringstream result; - - const unsigned char* p_buff = (const unsigned char*)pbuf; - - for(unsigned int i=0;i<len;i++) - { // convert md to hex-represented string (hex-letters in upper case!) - result << std::setw(2) << std::setfill('0') - << std::setbase(16) << std::nouppercase - << (int)*p_buff++; - } - - return result.str(); - } - - inline - std::string get_md5_as_hexstring(const void* pbuff, size_t len) - { - unsigned char output[16] = {0}; - md5::md5((unsigned char*)pbuff, static_cast<unsigned int>(len), output); - return get_buf_as_hex_string(output, sizeof(output)); - } - - inline - std::string get_md5_as_hexstring(const std::string& src) - { - return get_md5_as_hexstring(src.data(), src.size()); - } -#endif - - } } diff --git a/contrib/epee/include/string_tools.h b/contrib/epee/include/string_tools.h index 67984b9e4..16e60e99a 100644 --- a/contrib/epee/include/string_tools.h +++ b/contrib/epee/include/string_tools.h @@ -35,11 +35,9 @@ # include <windows.h> #endif -//#include <objbase.h> #include <locale> #include <cstdlib> -#include <iomanip> -#include <map> +#include <string> #include <type_traits> #include <boost/uuid/uuid.hpp> #include <boost/uuid/uuid_io.hpp> @@ -62,38 +60,12 @@ namespace epee { namespace string_tools { - inline std::wstring get_str_from_guid(const boost::uuids::uuid& rid) - { - return boost::lexical_cast<std::wstring>(rid); - } //---------------------------------------------------------------------------- inline std::string get_str_from_guid_a(const boost::uuids::uuid& rid) { return boost::lexical_cast<std::string>(rid); } //---------------------------------------------------------------------------- - inline bool get_guid_from_string( boost::uuids::uuid& inetifer, std::wstring str_id) - { - if(str_id.size() < 36) - return false; - - if('{' == *str_id.begin()) - str_id.erase(0, 1); - - if('}' == *(--str_id.end())) - str_id.erase(--str_id.end()); - - try - { - inetifer = boost::lexical_cast<boost::uuids::uuid>(str_id); - return true; - } - catch(...) - { - return false; - } - } - //---------------------------------------------------------------------------- inline bool get_guid_from_string(OUT boost::uuids::uuid& inetifer, const std::string& str_id) { std::string local_str_id = str_id; @@ -201,22 +173,6 @@ DISABLE_GCC_WARNING(maybe-uninitialized) return true; } POP_WARNINGS - //--------------------------------------------------- - template<typename int_t> - bool get_xnum_from_hex_string(const std::string str, int_t& res ) - { - try - { - std::stringstream ss; - ss << std::hex << str; - ss >> res; - return true; - } - catch(...) - { - return false; - } - } //---------------------------------------------------------------------------- template<class XType> inline bool xtype_to_string(const XType& val, std::string& str) @@ -232,83 +188,6 @@ POP_WARNINGS return true; } - - typedef std::map<std::string, std::string> command_line_params_a; - typedef std::map<std::wstring, std::wstring> command_line_params_w; - - template<class t_string> - bool parse_commandline(std::map<t_string, t_string>& res, int argc, char** argv) - { - t_string key; - for(int i = 1; i < argc; i++) - { - if(!argv[i]) - break; - t_string s = argv[i]; - std::string::size_type p = s.find('='); - if(std::string::npos == p) - { - res[s] = ""; - }else - { - std::string ss; - t_string nm = s.substr(0, p); - t_string vl = s.substr(p+1, s.size()); - res[nm] = vl; - } - } - return true; - } - -/* template<typename t_type> - bool get_xparam_from_command_line(const std::map<std::string, std::string>& res, const std::basic_string<typename t_string::value_type> & key, t_type& val) - { - - } - */ - - template<class t_string, typename t_type> - bool get_xparam_from_command_line(const std::map<t_string, t_string>& res, const t_string & key, t_type& val) - { - typename std::map<t_string, t_string>::const_iterator it = res.find(key); - if(it == res.end()) - return false; - - if(it->second.size()) - { - return get_xtype_from_string(val, it->second); - } - - return true; - } - - template<class t_string, typename t_type> - t_type get_xparam_from_command_line(const std::map<t_string, t_string>& res, const t_string & key, const t_type& default_value) - { - typename std::map<t_string, t_string>::const_iterator it = res.find(key); - if(it == res.end()) - return default_value; - - if(it->second.size()) - { - t_type s; - get_xtype_from_string(s, it->second); - return s; - } - - return default_value; - } - - template<class t_string> - bool have_in_command_line(const std::map<t_string, t_string>& res, const std::basic_string<typename t_string::value_type>& key) - { - typename std::map<t_string, t_string>::const_iterator it = res.find(key); - if(it == res.end()) - return false; - - return true; - } - //---------------------------------------------------------------------------- std::string get_ip_string_from_int32(uint32_t ip); //---------------------------------------------------------------------------- @@ -342,16 +221,6 @@ POP_WARNINGS return true; } - //---------------------------------------------------------------------------- - template<typename t> - inline std::string get_t_as_hex_nwidth(const t& v, std::streamsize w = 8) - { - std::stringstream ss; - ss << std::setfill ('0') << std::setw (w) << std::hex << std::noshowbase; - ss << v; - return ss.str(); - } - inline std::string num_to_string_fast(int64_t val) { /* @@ -361,68 +230,6 @@ POP_WARNINGS return boost::lexical_cast<std::string>(val); } //---------------------------------------------------------------------------- - inline bool string_to_num_fast(const std::string& buff, int64_t& val) - { - //return get_xtype_from_string(val, buff); -#if (defined _MSC_VER) - val = _atoi64(buff.c_str()); -#else - val = atoll(buff.c_str()); -#endif - /* - * val = atoi64(buff.c_str()); - */ - if(buff != "0" && val == 0) - return false; - return true; - } - //---------------------------------------------------------------------------- - inline bool string_to_num_fast(const std::string& buff, int& val) - { - val = atoi(buff.c_str()); - if(buff != "0" && val == 0) - return false; - - return true; - } - //---------------------------------------------------------------------------- -#ifdef WINDOWS_PLATFORM - inline std::string system_time_to_string(const SYSTEMTIME& st) - { - - /* - TIME_ZONE_INFORMATION tzi; - GetTimeZoneInformation(&tzi); - SystemTimeToTzSpecificLocalTime(&tzi, &stUTC, &stLocal); - */ - - char szTime[25], szDate[25]; - ::GetTimeFormatA( - LOCALE_USER_DEFAULT, // locale - TIME_FORCE24HOURFORMAT, // options - &st, // time - NULL, // time format string - szTime, // formatted string buffer - 25 // size of string buffer - ); - - ::GetDateFormatA( - LOCALE_USER_DEFAULT, // locale - NULL, // options - &st, // date - NULL, // date format - szDate, // formatted string buffer - 25 // size of buffer - ); - szTime[24] = szDate[24] = 0; //be happy :) - - std::string res = szDate; - (res += " " )+= szTime; - return res; - - } -#endif - //---------------------------------------------------------------------------- inline bool compare_no_case(const std::string& str1, const std::string& str2) { @@ -430,33 +237,6 @@ POP_WARNINGS return !boost::iequals(str1, str2); } //---------------------------------------------------------------------------- - inline bool compare_no_case(const std::wstring& str1, const std::wstring& str2) - { - return !boost::iequals(str1, str2); - } - //---------------------------------------------------------------------------- - inline bool is_match_prefix(const std::wstring& str1, const std::wstring& prefix) - { - if(prefix.size()>str1.size()) - return false; - - if(!compare_no_case(str1.substr(0, prefix.size()), prefix)) - return true; - else - return false; - } - //---------------------------------------------------------------------------- - inline bool is_match_prefix(const std::string& str1, const std::string& prefix) - { - if(prefix.size()>str1.size()) - return false; - - if(!compare_no_case(str1.substr(0, prefix.size()), prefix)) - return true; - else - return false; - } - //---------------------------------------------------------------------------- inline std::string& get_current_module_name() { static std::string module_name; @@ -569,20 +349,6 @@ POP_WARNINGS return res; } //---------------------------------------------------------------------------- - inline std::string get_filename_from_path(const std::string& str) - { - std::string res; - std::string::size_type pos = str.rfind('\\'); - if(std::string::npos == pos) - return str; - - res = str.substr(pos+1, str.size()-pos); - return res; - } - //---------------------------------------------------------------------------- - - - inline std::string cut_off_extension(const std::string& str) { std::string res; @@ -593,127 +359,6 @@ POP_WARNINGS res = str.substr(0, pos); return res; } - - //---------------------------------------------------------------------------- -#ifdef _WININET_ - inline std::string get_string_from_systemtime(const SYSTEMTIME& sys_time) - { - std::string result_string; - - char buff[100] = {0}; - BOOL res = ::InternetTimeFromSystemTimeA(&sys_time, INTERNET_RFC1123_FORMAT, buff, 99); - if(!res) - { - LOG_ERROR("Failed to load SytemTime to string"); - } - - result_string = buff; - return result_string; - - } - //------------------------------------------------------------------------------------- - inline SYSTEMTIME get_systemtime_from_string(const std::string& buff) - { - SYSTEMTIME result_time = {0}; - - BOOL res = ::InternetTimeToSystemTimeA(buff.c_str(), &result_time, NULL); - if(!res) - { - LOG_ERROR("Failed to load SytemTime from string " << buff << "interval set to 15 minutes"); - } - - return result_time; - } -#endif - -#ifdef WINDOWS_PLATFORM - static const DWORD INFO_BUFFER_SIZE = 10000; - - static const wchar_t* get_pc_name() - { - static wchar_t info[INFO_BUFFER_SIZE]; - static DWORD bufCharCount = INFO_BUFFER_SIZE; - static bool init = false; - - if (!init) { - if (!GetComputerNameW( info, &bufCharCount )) - info[0] = 0; - else - init = true; - } - - return info; - } - - static const wchar_t* get_user_name() - { - static wchar_t info[INFO_BUFFER_SIZE]; - static DWORD bufCharCount = INFO_BUFFER_SIZE; - static bool init = false; - - if (!init) { - if (!GetUserNameW( info, &bufCharCount )) - info[0] = 0; - else - init = true; - } - - return info; - } -#endif - -#ifdef _LM_ - static const wchar_t* get_domain_name() - { - static wchar_t info[INFO_BUFFER_SIZE]; - static DWORD bufCharCount = 0; - static bool init = false; - - if (!init) { - LPWSTR domain( NULL ); - NETSETUP_JOIN_STATUS status; - info[0] = 0; - - if (NET_API_STATUS result = NetGetJoinInformation( NULL, &domain, &status )) - { - LOG_ERROR("get_domain_name error: " << log_space::get_win32_err_descr(result)); - } else - { - StringCchCopyW( info, sizeof(info)/sizeof( info[0] ), domain ); - NetApiBufferFree((void*)domain); - init = true; - } - } - - return info; - } -#endif -#ifdef WINDOWS_PLATFORM - inline - std::string load_resource_string_a(int id, const char* pmodule_name = NULL) - { - //slow realization - HMODULE h = ::GetModuleHandleA( pmodule_name ); - - char buff[2000] = {0}; - - ::LoadStringA( h, id, buff, sizeof(buff)); - buff[sizeof(buff)-1] = 0; //be happy :) - return buff; - } - inline - std::wstring load_resource_string_w(int id, const char* pmodule_name = NULL) - { - //slow realization - HMODULE h = ::GetModuleHandleA( pmodule_name ); - - wchar_t buff[2000] = {0}; - - ::LoadStringW( h, id, buff, sizeof(buff) / sizeof( buff[0] ) ); - buff[(sizeof(buff)/sizeof(buff[0]))-1] = 0; //be happy :) - return buff; - } -#endif } } #endif //_STRING_TOOLS_H_ diff --git a/external/easylogging++/easylogging++.cc b/external/easylogging++/easylogging++.cc index 4fbb94b25..efa876664 100644 --- a/external/easylogging++/easylogging++.cc +++ b/external/easylogging++/easylogging++.cc @@ -2095,6 +2095,7 @@ Storage::Storage(const LogBuilderPtr& defaultLogBuilder) : sysLogLogger->reconfigure(); #endif // defined(ELPP_SYSLOG) addFlag(LoggingFlag::AllowVerboseIfModuleNotSpecified); + addFlag(LoggingFlag::CreateLoggerAutomatically); #if ELPP_ASYNC_LOGGING installLogDispatchCallback<base::AsyncLogDispatchCallback>(std::string("AsyncLogDispatchCallback")); #else diff --git a/external/easylogging++/easylogging++.h b/external/easylogging++/easylogging++.h index 195df7e5c..8f592899e 100644 --- a/external/easylogging++/easylogging++.h +++ b/external/easylogging++/easylogging++.h @@ -290,7 +290,11 @@ ELPP_INTERNAL_DEBUGGING_OUT_INFO << ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStre #define ELPP_VARIADIC_TEMPLATES_SUPPORTED \ (ELPP_COMPILER_GCC || ELPP_COMPILER_CLANG || ELPP_COMPILER_INTEL || (ELPP_COMPILER_MSVC && _MSC_VER >= 1800)) // Logging Enable/Disable macros -#define ELPP_LOGGING_ENABLED (!defined(ELPP_DISABLE_LOGS)) +#ifdef ELPP_DISABLE_LOGS +# define ELPP_LOGGING_ENABLED 0 +#else +# define ELPP_LOGGING_ENABLED 1 +#endif #if (!defined(ELPP_DISABLE_DEBUG_LOGS) && (ELPP_LOGGING_ENABLED)) # define ELPP_DEBUG_LOG 1 #else diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h index abfa665ff..8dbf1b53b 100644 --- a/src/cryptonote_config.h +++ b/src/cryptonote_config.h @@ -109,6 +109,7 @@ #define P2P_DEFAULT_INVOKE_TIMEOUT 60*2*1000 //2 minutes #define P2P_DEFAULT_HANDSHAKE_INVOKE_TIMEOUT 5000 //5 seconds #define P2P_DEFAULT_WHITELIST_CONNECTIONS_PERCENT 70 +#define P2P_DEFAULT_ANCHOR_CONNECTIONS_COUNT 2 #define P2P_FAILED_ADDR_FORGET_SECONDS (60*60) //1 hour #define P2P_IP_BLOCKTIME (60*60*24) //24 hour diff --git a/src/mnemonics/CMakeLists.txt b/src/mnemonics/CMakeLists.txt index 4db19d195..c521a0932 100644 --- a/src/mnemonics/CMakeLists.txt +++ b/src/mnemonics/CMakeLists.txt @@ -41,7 +41,7 @@ set(mnemonics_private_headers italian.h japanese.h language_base.h - old_english.h + english_old.h portuguese.h russian.h singleton.h diff --git a/src/mnemonics/chinese_simplified.h b/src/mnemonics/chinese_simplified.h index 413186733..a85bbe963 100644 --- a/src/mnemonics/chinese_simplified.h +++ b/src/mnemonics/chinese_simplified.h @@ -72,7 +72,7 @@ namespace Language class Chinese_Simplified: public Base
{
public:
- Chinese_Simplified(): Base("Chinese (Simplified)", std::vector<std::string>({
+ Chinese_Simplified(): Base("简体中文 (中国)", std::vector<std::string>({
"的",
"一",
"是",
diff --git a/src/mnemonics/dutch.h b/src/mnemonics/dutch.h index 0d7a637e6..1cf9b606e 100644 --- a/src/mnemonics/dutch.h +++ b/src/mnemonics/dutch.h @@ -49,7 +49,7 @@ namespace Language class Dutch: public Base
{
public:
- Dutch(): Base("Dutch", std::vector<std::string>({
+ Dutch(): Base("Nederlands", std::vector<std::string>({
"aalglad",
"aalscholver",
"aambeeld",
diff --git a/src/mnemonics/electrum-words.cpp b/src/mnemonics/electrum-words.cpp index 501495f0b..ef1100a10 100644 --- a/src/mnemonics/electrum-words.cpp +++ b/src/mnemonics/electrum-words.cpp @@ -61,7 +61,7 @@ #include "portuguese.h" #include "japanese.h" #include "russian.h" -#include "old_english.h" +#include "english_old.h" #include "language_base.h" #include "singleton.h" @@ -95,7 +95,7 @@ namespace Language::Singleton<Language::Portuguese>::instance(), Language::Singleton<Language::Japanese>::instance(), Language::Singleton<Language::Russian>::instance(), - Language::Singleton<Language::OldEnglish>::instance() + Language::Singleton<Language::EnglishOld>::instance() }); Language::Base *fallback = NULL; @@ -318,39 +318,39 @@ namespace crypto { language = Language::Singleton<Language::English>::instance(); } - else if (language_name == "Dutch") + else if (language_name == "Nederlands") { language = Language::Singleton<Language::Dutch>::instance(); } - else if (language_name == "French") + else if (language_name == "Français") { language = Language::Singleton<Language::French>::instance(); } - else if (language_name == "Spanish") + else if (language_name == "Español") { language = Language::Singleton<Language::Spanish>::instance(); } - else if (language_name == "Portuguese") + else if (language_name == "Português") { language = Language::Singleton<Language::Portuguese>::instance(); } - else if (language_name == "Japanese") + else if (language_name == "日本語") { language = Language::Singleton<Language::Japanese>::instance(); } - else if (language_name == "Italian") + else if (language_name == "Italiano") { language = Language::Singleton<Language::Italian>::instance(); } - else if (language_name == "German") + else if (language_name == "Deutsch") { language = Language::Singleton<Language::German>::instance(); } - else if (language_name == "Russian") + else if (language_name == "русский язык") { language = Language::Singleton<Language::Russian>::instance(); } - else if (language_name == "Chinese (Simplified)") + else if (language_name == "简体中文 (中国)") { language = Language::Singleton<Language::Chinese_Simplified>::instance(); } @@ -399,16 +399,16 @@ namespace crypto void get_language_list(std::vector<std::string> &languages) { std::vector<Language::Base*> language_instances({ - Language::Singleton<Language::Chinese_Simplified>::instance(), + Language::Singleton<Language::German>::instance(), Language::Singleton<Language::English>::instance(), - Language::Singleton<Language::Dutch>::instance(), - Language::Singleton<Language::French>::instance(), Language::Singleton<Language::Spanish>::instance(), - Language::Singleton<Language::German>::instance(), + Language::Singleton<Language::French>::instance(), Language::Singleton<Language::Italian>::instance(), + Language::Singleton<Language::Dutch>::instance(), Language::Singleton<Language::Portuguese>::instance(), Language::Singleton<Language::Russian>::instance(), - Language::Singleton<Language::Japanese>::instance() + Language::Singleton<Language::Japanese>::instance(), + Language::Singleton<Language::Chinese_Simplified>::instance() }); for (std::vector<Language::Base*>::iterator it = language_instances.begin(); it != language_instances.end(); it++) diff --git a/src/mnemonics/electrum-words.h b/src/mnemonics/electrum-words.h index d1aa65939..3655dd201 100644 --- a/src/mnemonics/electrum-words.h +++ b/src/mnemonics/electrum-words.h @@ -60,7 +60,7 @@ namespace crypto { const int seed_length = 24; - const std::string old_language_name = "OldEnglish"; + const std::string old_language_name = "EnglishOld"; /*! * \brief Converts seed words to bytes (secret key). * \param words String containing the words separated by spaces. diff --git a/src/mnemonics/old_english.h b/src/mnemonics/english_old.h index 21ac95de3..9fa5e81e1 100644 --- a/src/mnemonics/old_english.h +++ b/src/mnemonics/english_old.h @@ -29,13 +29,13 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*!
- * \file old_english.h
+ * \file english_old.h
*
- * \brief Old English word list and map.
+ * \brief Older version of English word list and map.
*/
-#ifndef OLD_ENGLISH_H
-#define OLD_ENGLISH_H
+#ifndef ENGLISH_OLD_H
+#define ENGLISH_OLD_H
#include <vector>
#include <unordered_map>
@@ -48,10 +48,10 @@ */
namespace Language
{
- class OldEnglish: public Base
+ class EnglishOld: public Base
{
public:
- OldEnglish(): Base("OldEnglish", std::vector<std::string>({
+ EnglishOld(): Base("EnglishOld", std::vector<std::string>({
"like",
"just",
"love",
diff --git a/src/mnemonics/french.h b/src/mnemonics/french.h index 6cf44a197..ef951b2cc 100644 --- a/src/mnemonics/french.h +++ b/src/mnemonics/french.h @@ -49,7 +49,7 @@ namespace Language class French: public Base { public: - French(): Base("French", std::vector<std::string>({ + French(): Base("Français", std::vector<std::string>({ "abandon", "abattre", "aboi", diff --git a/src/mnemonics/german.h b/src/mnemonics/german.h index 1a1e6b467..46a8cf1fe 100644 --- a/src/mnemonics/german.h +++ b/src/mnemonics/german.h @@ -51,7 +51,7 @@ namespace Language class German: public Base
{
public:
- German(): Base("German", std::vector<std::string>({
+ German(): Base("Deutsch", std::vector<std::string>({
"Abakus",
"Abart",
"abbilden",
@@ -1678,11 +1678,11 @@ namespace Language "Zündung",
"Zweck",
"Zyklop"
- }), 4) - { + }), 4)
+ {
populate_maps();
}
};
}
-#endif +#endif
diff --git a/src/mnemonics/italian.h b/src/mnemonics/italian.h index 28cee9d9a..da0e1363c 100644 --- a/src/mnemonics/italian.h +++ b/src/mnemonics/italian.h @@ -51,7 +51,7 @@ namespace Language class Italian: public Base
{
public:
- Italian(): Base("Italian", std::vector<std::string>({
+ Italian(): Base("Italiano", std::vector<std::string>({
"abbinare",
"abbonato",
"abisso",
@@ -1678,11 +1678,11 @@ namespace Language "zolfo",
"zombie",
"zucchero"
- }), 4) - { + }), 4)
+ {
populate_maps();
}
};
}
-#endif +#endif
diff --git a/src/mnemonics/japanese.h b/src/mnemonics/japanese.h index d5ab4bc84..fd5425fb1 100644 --- a/src/mnemonics/japanese.h +++ b/src/mnemonics/japanese.h @@ -71,7 +71,7 @@ namespace Language class Japanese: public Base
{
public:
- Japanese(): Base("Japanese", std::vector<std::string>({
+ Japanese(): Base("日本語", std::vector<std::string>({
"あいこくしん",
"あいさつ",
"あいだ",
diff --git a/src/mnemonics/portuguese.h b/src/mnemonics/portuguese.h index f9d66afc4..bb1fe8ee5 100644 --- a/src/mnemonics/portuguese.h +++ b/src/mnemonics/portuguese.h @@ -72,7 +72,7 @@ namespace Language class Portuguese: public Base
{
public:
- Portuguese(): Base("Portuguese", std::vector<std::string>({
+ Portuguese(): Base("Português", std::vector<std::string>({
"abaular",
"abdominal",
"abeto",
diff --git a/src/mnemonics/russian.h b/src/mnemonics/russian.h index b3db4aa4c..bfe970b9d 100644 --- a/src/mnemonics/russian.h +++ b/src/mnemonics/russian.h @@ -51,7 +51,7 @@ namespace Language class Russian: public Base
{
public:
- Russian(): Base("Russian", std::vector<std::string>({
+ Russian(): Base("русский язык", std::vector<std::string>({
"абажур",
"абзац",
"абонент",
@@ -1678,11 +1678,11 @@ namespace Language "яхта",
"ячейка",
"ящик"
- }), 4) - { + }), 4)
+ {
populate_maps();
}
};
}
-#endif +#endif
diff --git a/src/mnemonics/spanish.h b/src/mnemonics/spanish.h index 117890ada..9db2a03f3 100644 --- a/src/mnemonics/spanish.h +++ b/src/mnemonics/spanish.h @@ -72,7 +72,7 @@ namespace Language class Spanish: public Base
{
public:
- Spanish(): Base("Spanish", std::vector<std::string>({
+ Spanish(): Base("Español", std::vector<std::string>({
"ábaco",
"abdomen",
"abeja",
diff --git a/src/p2p/net_node.h b/src/p2p/net_node.h index 4582a3236..13cd3f5b0 100644 --- a/src/p2p/net_node.h +++ b/src/p2p/net_node.h @@ -155,6 +155,8 @@ namespace nodetool CHAIN_INVOKE_MAP_TO_OBJ_FORCE_CONTEXT(m_payload_handler, typename t_payload_net_handler::connection_context&) END_INVOKE_MAP2() + enum PeerType { anchor = 0, white, gray }; + //----------------- commands handlers ---------------------------------------------- int handle_handshake(int command, typename COMMAND_HANDSHAKE::request& arg, typename COMMAND_HANDSHAKE::response& rsp, p2p_connection_context& context); int handle_timed_sync(int command, typename COMMAND_TIMED_SYNC::request& arg, typename COMMAND_TIMED_SYNC::response& rsp, p2p_connection_context& context); @@ -205,15 +207,17 @@ namespace nodetool bool do_handshake_with_peer(peerid_type& pi, p2p_connection_context& context, bool just_take_peerlist = false); bool do_peer_timed_sync(const epee::net_utils::connection_context_base& context, peerid_type peer_id); + bool make_new_connection_from_anchor_peerlist(const std::vector<anchor_peerlist_entry>& anchor_peerlist); 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); + bool try_to_connect_and_handshake_with_new_peer(const net_address& na, bool just_take_peerlist = false, uint64_t last_seen_stamp = 0, PeerType peer_type = white, uint64_t first_seen_stamp = 0); size_t get_random_index_with_fixed_probability(size_t max_index); bool is_peer_used(const peerlist_entry& peer); + bool is_peer_used(const anchor_peerlist_entry& peer); bool is_addr_connected(const net_address& peer); template<class t_callback> bool try_ping(basic_node_data& node_data, p2p_connection_context& context, t_callback cb); bool try_get_support_flags(const p2p_connection_context& context, std::function<void(p2p_connection_context&, const uint32_t&)> f); - bool make_expected_connections_count(bool white_list, size_t expected_connections); + bool make_expected_connections_count(PeerType peer_type, size_t expected_connections); void cache_connect_fail_info(const net_address& addr); bool is_addr_recently_failed(const net_address& addr); bool is_priority_node(const net_address& na); diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 2e2dffab8..5c903b1f5 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -874,6 +874,30 @@ namespace nodetool } //----------------------------------------------------------------------------------- template<class t_payload_net_handler> + bool node_server<t_payload_net_handler>::is_peer_used(const anchor_peerlist_entry& peer) + { + if(m_config.m_peer_id == peer.id) { + return true;//dont make connections to ourself + } + + bool used = false; + + m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt) + { + if(cntxt.peer_id == peer.id || (!cntxt.m_is_income && peer.adr.ip == cntxt.m_remote_ip && peer.adr.port == cntxt.m_remote_port)) + { + used = true; + + return false;//stop enumerating + } + + return true; + }); + + return used; + } + //----------------------------------------------------------------------------------- + template<class t_payload_net_handler> bool node_server<t_payload_net_handler>::is_addr_connected(const net_address& peer) { bool connected = false; @@ -900,7 +924,7 @@ namespace nodetool } while(0) template<class t_payload_net_handler> - bool node_server<t_payload_net_handler>::try_to_connect_and_handshake_with_new_peer(const net_address& na, bool just_take_peerlist, uint64_t last_seen_stamp, bool white) + bool node_server<t_payload_net_handler>::try_to_connect_and_handshake_with_new_peer(const net_address& na, bool just_take_peerlist, uint64_t last_seen_stamp, PeerType peer_type, uint64_t first_seen_stamp) { if (m_current_number_of_out_peers == m_config.m_net_config.connections_count) // out peers limit { @@ -913,7 +937,7 @@ namespace nodetool return false; } MDEBUG("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: " + << epee::string_tools::num_to_string_fast(na.port) << "(peer_type=" << peer_type << ", last_seen: " << (last_seen_stamp ? epee::misc_utils::get_time_interval_string(time(NULL) - last_seen_stamp):"never") << ")..."); @@ -963,6 +987,13 @@ namespace nodetool m_peerlist.append_with_peer_white(pe_local); //update last seen and push it to peerlist manager + anchor_peerlist_entry ape = AUTO_VAL_INIT(ape); + ape.adr = na; + ape.id = pi; + ape.first_seen = first_seen_stamp ? first_seen_stamp : time(nullptr); + + m_peerlist.append_with_peer_anchor(ape); + LOG_DEBUG_CC(con, "CONNECTION HANDSHAKED OK."); return true; } @@ -1029,6 +1060,41 @@ namespace nodetool } //----------------------------------------------------------------------------------- template<class t_payload_net_handler> + bool node_server<t_payload_net_handler>::make_new_connection_from_anchor_peerlist(const std::vector<anchor_peerlist_entry>& anchor_peerlist) + { + for (const auto& pe: anchor_peerlist) { + _note("Considering connecting (out) to peer: " << pe.id << " " << epee::string_tools::get_ip_string_from_int32(pe.adr.ip) << ":" << boost::lexical_cast<std::string>(pe.adr.port)); + + if(is_peer_used(pe)) { + _note("Peer is used"); + continue; + } + + if(!is_remote_ip_allowed(pe.adr.ip)) { + continue; + } + + if(is_addr_recently_failed(pe.adr)) { + continue; + } + + MDEBUG("Selected peer: " << pe.id << " " << epee::string_tools::get_ip_string_from_int32(pe.adr.ip) + << ":" << boost::lexical_cast<std::string>(pe.adr.port) + << "[peer_type=" << anchor + << "] first_seen: " << epee::misc_utils::get_time_interval_string(time(NULL) - pe.first_seen)); + + if(!try_to_connect_and_handshake_with_new_peer(pe.adr, false, 0, anchor, pe.first_seen)) { + _note("Handshake failed"); + continue; + } + + return true; + } + + return false; + } + //----------------------------------------------------------------------------------- + template<class t_payload_net_handler> bool node_server<t_payload_net_handler>::make_new_connection_from_peerlist(bool use_white_list) { size_t local_peers_count = use_white_list ? m_peerlist.get_white_peers_count():m_peerlist.get_gray_peers_count(); @@ -1079,10 +1145,10 @@ namespace nodetool MDEBUG("Selected peer: " << pe.id << " " << epee::string_tools::get_ip_string_from_int32(pe.adr.ip) << ":" << boost::lexical_cast<std::string>(pe.adr.port) - << "[white=" << use_white_list + << "[peer_list=" << (use_white_list ? white : gray) << "] 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)) { + if(!try_to_connect_and_handshake_with_new_peer(pe.adr, false, pe.last_seen, use_white_list ? white : gray)) { _note("Handshake failed"); continue; } @@ -1144,19 +1210,22 @@ namespace nodetool { if(conn_count < expected_white_connections) { - //start from white list - if(!make_expected_connections_count(true, expected_white_connections)) + //start from anchor list + if(!make_expected_connections_count(anchor, P2P_DEFAULT_ANCHOR_CONNECTIONS_COUNT)) return false; - //and then do grey list - if(!make_expected_connections_count(false, m_config.m_net_config.connections_count)) + //then do white list + if(!make_expected_connections_count(white, expected_white_connections)) + return false; + //then do grey list + if(!make_expected_connections_count(gray, m_config.m_net_config.connections_count)) return false; }else { //start from grey list - if(!make_expected_connections_count(false, m_config.m_net_config.connections_count)) + if(!make_expected_connections_count(gray, m_config.m_net_config.connections_count)) return false; //and then do white list - if(!make_expected_connections_count(true, m_config.m_net_config.connections_count)) + if(!make_expected_connections_count(white, m_config.m_net_config.connections_count)) return false; } } @@ -1165,11 +1234,17 @@ namespace nodetool } //----------------------------------------------------------------------------------- template<class t_payload_net_handler> - bool node_server<t_payload_net_handler>::make_expected_connections_count(bool white_list, size_t expected_connections) + bool node_server<t_payload_net_handler>::make_expected_connections_count(PeerType peer_type, size_t expected_connections) { if (m_offline) return true; + std::vector<anchor_peerlist_entry> apl; + + if (peer_type == anchor) { + m_peerlist.get_and_empty_anchor_peerlist(apl); + } + size_t conn_count = get_outgoing_connections_count(); //add new connections from white peers while(conn_count < expected_connections) @@ -1177,8 +1252,18 @@ namespace nodetool if(m_net_server.is_stop_signal_sent()) return false; - if(!make_new_connection_from_peerlist(white_list)) + if (peer_type == anchor && !make_new_connection_from_anchor_peerlist(apl)) { + break; + } + + if (peer_type == white && !make_new_connection_from_peerlist(true)) { + break; + } + + if (peer_type == gray && !make_new_connection_from_peerlist(false)) { break; + } + conn_count = get_outgoing_connections_count(); } return true; @@ -1660,6 +1745,14 @@ namespace nodetool template<class t_payload_net_handler> void node_server<t_payload_net_handler>::on_connection_close(p2p_connection_context& context) { + if (!m_net_server.is_stop_signal_sent() && !context.m_is_income) { + nodetool::net_address na = AUTO_VAL_INIT(na); + na.ip = context.m_remote_ip; + na.port = context.m_remote_port; + + m_peerlist.remove_from_peer_anchor(na); + } + MINFO("["<< epee::net_utils::print_connection_context(context) << "] CLOSE CONNECTION"); } diff --git a/src/p2p/net_peerlist.h b/src/p2p/net_peerlist.h index 11d995995..de0f51cc3 100644 --- a/src/p2p/net_peerlist.h +++ b/src/p2p/net_peerlist.h @@ -54,7 +54,7 @@ #include "net_peerlist_boost_serialization.h" -#define CURRENT_PEERLIST_STORAGE_ARCHIVE_VER 4 +#define CURRENT_PEERLIST_STORAGE_ARCHIVE_VER 5 namespace nodetool { @@ -77,13 +77,15 @@ namespace nodetool bool get_gray_peer_by_index(peerlist_entry& p, size_t i); bool append_with_peer_white(const peerlist_entry& pr); bool append_with_peer_gray(const peerlist_entry& pr); + bool append_with_peer_anchor(const anchor_peerlist_entry& ple); bool set_peer_just_seen(peerid_type peer, uint32_t ip, uint32_t port); bool set_peer_just_seen(peerid_type peer, const net_address& addr); bool set_peer_unreachable(const peerlist_entry& pr); bool is_ip_allowed(uint32_t ip); bool get_random_gray_peer(peerlist_entry& pe); bool remove_from_peer_gray(const peerlist_entry& pe); - + bool get_and_empty_anchor_peerlist(std::vector<anchor_peerlist_entry>& apl); + bool remove_from_peer_anchor(const net_address& addr); private: struct by_time{}; @@ -145,6 +147,16 @@ namespace nodetool boost::multi_index::ordered_non_unique<boost::multi_index::tag<by_time>, boost::multi_index::member<peerlist_entry,int64_t,&peerlist_entry::last_seen> > > > peers_indexed_old; + + typedef boost::multi_index_container< + anchor_peerlist_entry, + boost::multi_index::indexed_by< + // access by anchor_peerlist_entry::net_adress + boost::multi_index::ordered_unique<boost::multi_index::tag<by_addr>, boost::multi_index::member<anchor_peerlist_entry,net_address,&anchor_peerlist_entry::adr> >, + // sort by anchor_peerlist_entry::first_seen + boost::multi_index::ordered_non_unique<boost::multi_index::tag<by_time>, boost::multi_index::member<anchor_peerlist_entry,int64_t,&anchor_peerlist_entry::first_seen> > + > + > anchor_peers_indexed; public: template <class Archive, class t_version_type> @@ -161,8 +173,15 @@ namespace nodetool peers_indexed_from_old(pio, m_peers_white); return; } + a & m_peers_white; a & m_peers_gray; + + if(ver < 5) { + return; + } + + a & m_peers_anchor; } private: @@ -178,6 +197,7 @@ namespace nodetool peers_indexed m_peers_gray; peers_indexed m_peers_white; + anchor_peers_indexed m_peers_anchor; }; //-------------------------------------------------------------------------------------------------- inline @@ -398,6 +418,24 @@ namespace nodetool } //-------------------------------------------------------------------------------------------------- inline + bool peerlist_manager::append_with_peer_anchor(const anchor_peerlist_entry& ple) + { + TRY_ENTRY(); + + CRITICAL_REGION_LOCAL(m_peerlist_lock); + + auto by_addr_it_anchor = m_peers_anchor.get<by_addr>().find(ple.adr); + + if(by_addr_it_anchor == m_peers_anchor.get<by_addr>().end()) { + m_peers_anchor.insert(ple); + } + + return true; + + CATCH_ENTRY_L0("peerlist_manager::append_with_peer_anchor()", false); + } + //-------------------------------------------------------------------------------------------------- + inline bool peerlist_manager::get_random_gray_peer(peerlist_entry& pe) { TRY_ENTRY(); @@ -435,7 +473,46 @@ namespace nodetool CATCH_ENTRY_L0("peerlist_manager::remove_from_peer_gray()", false); } - //-------------------------------------------------------------------------------------------------- + //-------------------------------------------------------------------------------------------------- + inline + bool peerlist_manager::get_and_empty_anchor_peerlist(std::vector<anchor_peerlist_entry>& apl) + { + TRY_ENTRY(); + + CRITICAL_REGION_LOCAL(m_peerlist_lock); + + auto begin = m_peers_anchor.get<by_time>().begin(); + auto end = m_peers_anchor.get<by_time>().end(); + + std::for_each(begin, end, [&apl](const anchor_peerlist_entry &a) { + apl.push_back(a); + }); + + m_peers_anchor.get<by_time>().clear(); + + return true; + + CATCH_ENTRY_L0("peerlist_manager::get_and_empty_anchor_peerlist()", false); + } + //-------------------------------------------------------------------------------------------------- + inline + bool peerlist_manager::remove_from_peer_anchor(const net_address& addr) + { + TRY_ENTRY(); + + CRITICAL_REGION_LOCAL(m_peerlist_lock); + + anchor_peers_indexed::index_iterator<by_addr>::type iterator = m_peers_anchor.get<by_addr>().find(addr); + + if (iterator != m_peers_anchor.get<by_addr>().end()) { + m_peers_anchor.erase(iterator); + } + + return true; + + CATCH_ENTRY_L0("peerlist_manager::remove_from_peer_anchor()", false); + } + //-------------------------------------------------------------------------------------------------- } BOOST_CLASS_VERSION(nodetool::peerlist_manager, CURRENT_PEERLIST_STORAGE_ARCHIVE_VER) diff --git a/src/p2p/net_peerlist_boost_serialization.h b/src/p2p/net_peerlist_boost_serialization.h index 260f16919..6891ac80c 100644 --- a/src/p2p/net_peerlist_boost_serialization.h +++ b/src/p2p/net_peerlist_boost_serialization.h @@ -49,6 +49,14 @@ namespace boost a & pl.adr; a & pl.id; a & pl.last_seen; - } + } + + template <class Archive, class ver_type> + inline void serialize(Archive &a, nodetool::anchor_peerlist_entry& pl, const ver_type ver) + { + a & pl.adr; + a & pl.id; + a & pl.first_seen; + } } } diff --git a/src/p2p/p2p_protocol_defs.h b/src/p2p/p2p_protocol_defs.h index 97e75f5ca..5ec012714 100644 --- a/src/p2p/p2p_protocol_defs.h +++ b/src/p2p/p2p_protocol_defs.h @@ -56,6 +56,13 @@ namespace nodetool int64_t last_seen; }; + struct anchor_peerlist_entry + { + net_address adr; + peerid_type id; + int64_t first_seen; + }; + struct connection_entry { net_address adr; diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index b755ef12f..6c2df4b22 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -684,6 +684,7 @@ simple_wallet::simple_wallet() m_cmd_binder.set_handler("locked_transfer", boost::bind(&simple_wallet::locked_transfer, this, _1), tr("locked_transfer [<mixin_count>] <addr> <amount> <lockblocks>(Number of blocks to lock the transaction for, max 1000000) [<payment_id>]")); m_cmd_binder.set_handler("sweep_unmixable", boost::bind(&simple_wallet::sweep_unmixable, this, _1), tr("Send all unmixable outputs to yourself with mixin 0")); m_cmd_binder.set_handler("sweep_all", boost::bind(&simple_wallet::sweep_all, this, _1), tr("sweep_all [mixin] address [payment_id] - Send all unlocked balance to an address")); + m_cmd_binder.set_handler("sweep_below", boost::bind(&simple_wallet::sweep_below, this, _1), tr("sweep_below <amount_threshold> [mixin] address [payment_id] - Send all unlocked outputs below the threshold to an address")); m_cmd_binder.set_handler("donate", boost::bind(&simple_wallet::donate, this, _1), tr("donate [<mixin_count>] <amount> [payment_id] - Donate <amount> to the development team (donate.getmonero.org)")); m_cmd_binder.set_handler("sign_transfer", boost::bind(&simple_wallet::sign_transfer, this, _1), tr("Sign a transaction from a file")); m_cmd_binder.set_handler("submit_transfer", boost::bind(&simple_wallet::submit_transfer, this, _1), tr("Submit a signed transaction from a file")); @@ -2600,7 +2601,7 @@ bool simple_wallet::sweep_unmixable(const std::vector<std::string> &args_) return true; } //---------------------------------------------------------------------------------------------------- -bool simple_wallet::sweep_all(const std::vector<std::string> &args_) +bool simple_wallet::sweep_main(uint64_t below, const std::vector<std::string> &args_) { if (m_wallet->ask_password() && !get_and_verify_password()) { return true; } if (!try_connect_to_daemon()) @@ -2708,7 +2709,7 @@ bool simple_wallet::sweep_all(const std::vector<std::string> &args_) try { // figure out what tx will be necessary - auto ptx_vector = m_wallet->create_transactions_all(address, fake_outs_count, 0 /* unlock_time */, 0 /* unused fee arg*/, extra, m_trusted_daemon); + auto ptx_vector = m_wallet->create_transactions_all(below, address, fake_outs_count, 0 /* unlock_time */, 0 /* unused fee arg*/, extra, m_trusted_daemon); if (ptx_vector.empty()) { @@ -2861,6 +2862,27 @@ bool simple_wallet::sweep_all(const std::vector<std::string> &args_) return true; } //---------------------------------------------------------------------------------------------------- +bool simple_wallet::sweep_all(const std::vector<std::string> &args_) +{ + return sweep_main(0, args_); +} +//---------------------------------------------------------------------------------------------------- +bool simple_wallet::sweep_below(const std::vector<std::string> &args_) +{ + uint64_t below = 0; + if (args_.size() < 1) + { + fail_msg_writer() << tr("missing amount threshold"); + return true; + } + if (!cryptonote::parse_amount(below, args_[0])) + { + fail_msg_writer() << tr("invalid amount threshold"); + return true; + } + return sweep_main(below, std::vector<std::string>(++args_.begin(), args_.end())); +} +//---------------------------------------------------------------------------------------------------- bool simple_wallet::donate(const std::vector<std::string> &args_) { std::vector<std::string> local_args = args_; diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h index 14722e942..1b58ff32a 100644 --- a/src/simplewallet/simplewallet.h +++ b/src/simplewallet/simplewallet.h @@ -134,7 +134,9 @@ namespace cryptonote bool transfer(const std::vector<std::string> &args); bool transfer_new(const std::vector<std::string> &args); bool locked_transfer(const std::vector<std::string> &args); + bool sweep_main(uint64_t below, const std::vector<std::string> &args); bool sweep_all(const std::vector<std::string> &args); + bool sweep_below(const std::vector<std::string> &args); bool sweep_unmixable(const std::vector<std::string> &args); bool donate(const std::vector<std::string> &args); bool sign_transfer(const std::vector<std::string> &args); diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index fc2d6e755..21760ac49 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -952,7 +952,7 @@ PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, const static_cast<uint32_t>(priority), extra, m_trustedDaemon); } else { - transaction->m_pending_tx = m_wallet->create_transactions_all(addr, fake_outs_count, 0 /* unlock_time */, + transaction->m_pending_tx = m_wallet->create_transactions_all(0, addr, fake_outs_count, 0 /* unlock_time */, static_cast<uint32_t>(priority), extra, m_trustedDaemon); } diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 4adec0719..9069789ca 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -4581,7 +4581,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp return ptx_vector; } -std::vector<wallet2::pending_tx> wallet2::create_transactions_all(const cryptonote::account_public_address &address, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t> extra, bool trusted_daemon) +std::vector<wallet2::pending_tx> wallet2::create_transactions_all(uint64_t below, const cryptonote::account_public_address &address, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t> extra, bool trusted_daemon) { std::vector<size_t> unused_transfers_indices; std::vector<size_t> unused_dust_indices; @@ -4593,10 +4593,13 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_all(const cryptono const transfer_details& td = m_transfers[i]; if (!td.m_spent && (use_rct ? true : !td.is_rct()) && is_transfer_unlocked(td)) { - if (td.is_rct() || is_valid_decomposed_amount(td.amount())) - unused_transfers_indices.push_back(i); - else - unused_dust_indices.push_back(i); + if (below == 0 || td.amount() < below) + { + if (td.is_rct() || is_valid_decomposed_amount(td.amount())) + unused_transfers_indices.push_back(i); + else + unused_dust_indices.push_back(i); + } } } diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index e228dac4f..03c6a431b 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -414,7 +414,7 @@ namespace tools bool load_tx(const std::string &signed_filename, std::vector<tools::wallet2::pending_tx> &ptx, std::function<bool(const signed_tx_set&)> accept_func = NULL); std::vector<pending_tx> create_transactions(std::vector<cryptonote::tx_destination_entry> dsts, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t> extra, bool trusted_daemon); std::vector<wallet2::pending_tx> create_transactions_2(std::vector<cryptonote::tx_destination_entry> dsts, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t> extra, bool trusted_daemon); - std::vector<wallet2::pending_tx> create_transactions_all(const cryptonote::account_public_address &address, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t> extra, bool trusted_daemon); + std::vector<wallet2::pending_tx> create_transactions_all(uint64_t below, const cryptonote::account_public_address &address, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t> extra, bool trusted_daemon); std::vector<wallet2::pending_tx> create_transactions_from(const cryptonote::account_public_address &address, std::vector<size_t> unused_transfers_indices, std::vector<size_t> unused_dust_indices, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t> extra, bool trusted_daemon); std::vector<pending_tx> create_unmixable_sweep_transactions(bool trusted_daemon); bool check_connection(uint32_t *version = NULL, uint32_t timeout = 200000); diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index 5a7325a06..f2b3dcaf5 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -631,7 +631,7 @@ namespace tools try { - std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_all(dsts[0].addr, req.mixin, req.unlock_time, req.priority, extra, m_trusted_daemon); + std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_all(req.below_amount, dsts[0].addr, req.mixin, req.unlock_time, req.priority, extra, m_trusted_daemon); m_wallet->commit_tx(ptx_vector); diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h index 51fcf02b5..3c10dc41f 100644 --- a/src/wallet/wallet_rpc_server_commands_defs.h +++ b/src/wallet/wallet_rpc_server_commands_defs.h @@ -234,6 +234,7 @@ namespace wallet_rpc uint64_t unlock_time; std::string payment_id; bool get_tx_keys; + uint64_t below_amount; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(address) @@ -242,6 +243,7 @@ namespace wallet_rpc KV_SERIALIZE(unlock_time) KV_SERIALIZE(payment_id) KV_SERIALIZE(get_tx_keys) + KV_SERIALIZE(below_amount) END_KV_SERIALIZE_MAP() }; diff --git a/tests/unit_tests/mnemonics.cpp b/tests/unit_tests/mnemonics.cpp index e00b87e30..956c5e1b2 100644 --- a/tests/unit_tests/mnemonics.cpp +++ b/tests/unit_tests/mnemonics.cpp @@ -44,7 +44,7 @@ #include "mnemonics/russian.h" #include "mnemonics/french.h" #include "mnemonics/dutch.h" -#include "mnemonics/old_english.h" +#include "mnemonics/english_old.h" #include "mnemonics/language_base.h" #include "mnemonics/singleton.h" |