aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md6
-rw-r--r--VULNERABILITY_RESPONSE_PROCESS.md143
-rw-r--r--contrib/epee/include/file_io_utils.h317
-rw-r--r--contrib/epee/include/string_coding.h54
-rw-r--r--contrib/epee/include/string_tools.h357
-rw-r--r--external/easylogging++/easylogging++.cc1
-rw-r--r--external/easylogging++/easylogging++.h6
-rw-r--r--src/cryptonote_config.h1
-rw-r--r--src/mnemonics/CMakeLists.txt2
-rw-r--r--src/mnemonics/chinese_simplified.h2
-rw-r--r--src/mnemonics/dutch.h2
-rw-r--r--src/mnemonics/electrum-words.cpp32
-rw-r--r--src/mnemonics/electrum-words.h2
-rw-r--r--src/mnemonics/english_old.h (renamed from src/mnemonics/old_english.h)12
-rw-r--r--src/mnemonics/french.h2
-rw-r--r--src/mnemonics/german.h8
-rw-r--r--src/mnemonics/italian.h8
-rw-r--r--src/mnemonics/japanese.h2
-rw-r--r--src/mnemonics/portuguese.h2
-rw-r--r--src/mnemonics/russian.h8
-rw-r--r--src/mnemonics/spanish.h2
-rw-r--r--src/p2p/net_node.h8
-rw-r--r--src/p2p/net_node.inl117
-rw-r--r--src/p2p/net_peerlist.h83
-rw-r--r--src/p2p/net_peerlist_boost_serialization.h10
-rw-r--r--src/p2p/p2p_protocol_defs.h7
-rw-r--r--src/simplewallet/simplewallet.cpp26
-rw-r--r--src/simplewallet/simplewallet.h2
-rw-r--r--src/wallet/api/wallet.cpp2
-rw-r--r--src/wallet/wallet2.cpp13
-rw-r--r--src/wallet/wallet2.h2
-rw-r--r--src/wallet/wallet_rpc_server.cpp2
-rw-r--r--src/wallet/wallet_rpc_server_commands_defs.h2
-rw-r--r--tests/unit_tests/mnemonics.cpp2
34 files changed, 446 insertions, 799 deletions
diff --git a/README.md b/README.md
index aa62fb003..4a29a5bc9 100644
--- a/README.md
+++ b/README.md
@@ -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"