forked from such-gitea/wownero
Compare commits
60 Commits
v0.2.1.0
...
release-v0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d4ee3c3251 | ||
|
|
b48234e81b | ||
|
|
0cae683a75 | ||
|
|
cb1174cbe7 | ||
|
|
a53251ceb8 | ||
|
|
c074baee61 | ||
|
|
6fa2c65993 | ||
|
|
5b7063c15a | ||
|
|
db77273f3f | ||
|
|
13e9035505 | ||
|
|
e2a3f71870 | ||
|
|
668489a322 | ||
|
|
fa3ae1a16d | ||
|
|
a28b9e2e44 | ||
|
|
39ff8c91c7 | ||
|
|
f2b1dca6aa | ||
|
|
a896603556 | ||
|
|
e492718cd0 | ||
|
|
4cb1fa3243 | ||
|
|
a2d3bc992d | ||
|
|
6b05e7f45d | ||
|
|
0f4ed31a61 | ||
|
|
68505da66f | ||
|
|
6eaa228b16 | ||
|
|
05b49cc1bb | ||
|
|
90a4ba36a6 | ||
|
|
0bd04bdfad | ||
|
|
5cdbfe4e8b | ||
|
|
2c9c795f0c | ||
|
|
7ba35598be | ||
|
|
65f483ca5b | ||
|
|
6463a6da6f | ||
|
|
86e6008036 | ||
|
|
4bd2b033f6 | ||
|
|
f4fa62e1db | ||
|
|
dc4b05bfd4 | ||
|
|
b27b34d90a | ||
|
|
fea950a61b | ||
|
|
7f3f923021 | ||
|
|
8345f0aabc | ||
|
|
edf18e227d | ||
|
|
2b863521ba | ||
|
|
6270a903c8 | ||
|
|
9d366226cb | ||
|
|
9a2fa460b0 | ||
|
|
6489ad8a1a | ||
|
|
7df1321b30 | ||
|
|
8212762312 | ||
|
|
6f2886e135 | ||
|
|
1f3521f958 | ||
|
|
bb49011991 | ||
|
|
2e3340df7a | ||
|
|
d552924515 | ||
|
|
ee07408ce1 | ||
|
|
d0d1a14a05 | ||
|
|
2da1edf924 | ||
|
|
28b65ea422 | ||
|
|
2d4c0edd66 | ||
|
|
a0b47c970c | ||
|
|
7973af3a3c |
@@ -33,6 +33,7 @@
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#include "string_tools.h"
|
||||
#endif
|
||||
|
||||
// On Windows there is a problem with non-ASCII characters in path and file names
|
||||
@@ -72,11 +73,9 @@ namespace file_io_utils
|
||||
bool save_string_to_file(const std::string& path_to_file, const std::string& str)
|
||||
{
|
||||
#ifdef WIN32
|
||||
WCHAR wide_path[1000];
|
||||
int chars = MultiByteToWideChar(CP_UTF8, 0, path_to_file.c_str(), path_to_file.size() + 1, wide_path, 1000);
|
||||
if (chars == 0)
|
||||
return false;
|
||||
HANDLE file_handle = CreateFileW(wide_path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
std::wstring wide_path;
|
||||
try { wide_path = string_tools::utf8_to_utf16(path_to_file); } catch (...) { return false; }
|
||||
HANDLE file_handle = CreateFileW(wide_path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (file_handle == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
DWORD bytes_written;
|
||||
@@ -128,18 +127,16 @@ namespace file_io_utils
|
||||
|
||||
|
||||
inline
|
||||
bool load_file_to_string(const std::string& path_to_file, std::string& target_str)
|
||||
bool load_file_to_string(const std::string& path_to_file, std::string& target_str, size_t max_size = 1000000000)
|
||||
{
|
||||
#ifdef WIN32
|
||||
WCHAR wide_path[1000];
|
||||
int chars = MultiByteToWideChar(CP_UTF8, 0, path_to_file.c_str(), path_to_file.size() + 1, wide_path, 1000);
|
||||
if (chars == 0)
|
||||
return false;
|
||||
HANDLE file_handle = CreateFileW(wide_path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
std::wstring wide_path;
|
||||
try { wide_path = string_tools::utf8_to_utf16(path_to_file); } catch (...) { return false; }
|
||||
HANDLE file_handle = CreateFileW(wide_path.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (file_handle == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
DWORD file_size = GetFileSize(file_handle, NULL);
|
||||
if ((file_size == INVALID_FILE_SIZE) || (file_size > 1000000000)) {
|
||||
if ((file_size == INVALID_FILE_SIZE) || (uint64_t)file_size > (uint64_t)max_size) {
|
||||
CloseHandle(file_handle);
|
||||
return false;
|
||||
}
|
||||
@@ -159,7 +156,7 @@ namespace file_io_utils
|
||||
|
||||
std::ifstream::pos_type file_size = fstream.tellg();
|
||||
|
||||
if(file_size > 1000000000)
|
||||
if((uint64_t)file_size > (uint64_t)max_size) // ensure a large domain for comparison, and negative -> too large
|
||||
return false;//don't go crazy
|
||||
size_t file_size_t = static_cast<size_t>(file_size);
|
||||
|
||||
@@ -202,11 +199,9 @@ namespace file_io_utils
|
||||
bool get_file_size(const std::string& path_to_file, uint64_t &size)
|
||||
{
|
||||
#ifdef WIN32
|
||||
WCHAR wide_path[1000];
|
||||
int chars = MultiByteToWideChar(CP_UTF8, 0, path_to_file.c_str(), path_to_file.size() + 1, wide_path, 1000);
|
||||
if (chars == 0)
|
||||
return false;
|
||||
HANDLE file_handle = CreateFileW(wide_path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
std::wstring wide_path;
|
||||
try { wide_path = string_tools::utf8_to_utf16(path_to_file); } catch (...) { return false; }
|
||||
HANDLE file_handle = CreateFileW(wide_path.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (file_handle == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
LARGE_INTEGER file_size;
|
||||
|
||||
@@ -652,13 +652,13 @@ PRAGMA_WARNING_DISABLE_VS(4355)
|
||||
m_timer.cancel();
|
||||
boost::system::error_code ignored_ec;
|
||||
socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec);
|
||||
m_was_shutdown = true;
|
||||
m_protocol_handler.release_protocol();
|
||||
if (!m_host.empty())
|
||||
{
|
||||
host_count(m_host, -1);
|
||||
m_host = "";
|
||||
}
|
||||
m_was_shutdown = true;
|
||||
m_protocol_handler.release_protocol();
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
@@ -1029,7 +1029,8 @@ POP_WARNINGS
|
||||
void boosted_tcp_server<t_protocol_handler>::handle_accept(const boost::system::error_code& e)
|
||||
{
|
||||
MDEBUG("handle_accept");
|
||||
TRY_ENTRY();
|
||||
try
|
||||
{
|
||||
if (!e)
|
||||
{
|
||||
if (m_connection_type == e_connection_type_RPC) {
|
||||
@@ -1047,11 +1048,25 @@ POP_WARNINGS
|
||||
|
||||
conn->start(true, 1 < m_threads_count);
|
||||
conn->save_dbg_log();
|
||||
}else
|
||||
{
|
||||
_erro("Some problems at accept: " << e.message() << ", connections_count = " << m_sock_count);
|
||||
return;
|
||||
}
|
||||
CATCH_ENTRY_L0("boosted_tcp_server<t_protocol_handler>::handle_accept", void());
|
||||
else
|
||||
{
|
||||
MERROR("Error in boosted_tcp_server<t_protocol_handler>::handle_accept: " << e);
|
||||
}
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
MERROR("Exception in boosted_tcp_server<t_protocol_handler>::handle_accept: " << e.what());
|
||||
}
|
||||
|
||||
// error path, if e or exception
|
||||
_erro("Some problems at accept: " << e.message() << ", connections_count = " << m_sock_count);
|
||||
misc_utils::sleep_no_w(100);
|
||||
new_connection_.reset(new connection<t_protocol_handler>(io_service_, m_config, m_sock_count, m_sock_number, m_pfilter, m_connection_type));
|
||||
acceptor_.async_accept(new_connection_->socket(),
|
||||
boost::bind(&boosted_tcp_server<t_protocol_handler>::handle_accept, this,
|
||||
boost::asio::placeholders::error));
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
template<class t_protocol_handler>
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace epee
|
||||
|
||||
if( (ip | 0xffffff00) == 0xffffffac)
|
||||
{
|
||||
uint32_t second_num = (ip << 8) & 0xff000000;
|
||||
uint32_t second_num = (ip >> 8) & 0xff;
|
||||
if(second_num >= 16 && second_num <= 31 )
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -381,6 +381,41 @@ POP_WARNINGS
|
||||
res = str.substr(0, pos);
|
||||
return res;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
#ifdef _WIN32
|
||||
inline std::wstring utf8_to_utf16(const std::string& str)
|
||||
{
|
||||
if (str.empty())
|
||||
return {};
|
||||
int wstr_size = MultiByteToWideChar(CP_UTF8, 0, &str[0], str.size(), NULL, 0);
|
||||
if (wstr_size == 0)
|
||||
{
|
||||
throw std::runtime_error(std::error_code(GetLastError(), std::system_category()).message());
|
||||
}
|
||||
std::wstring wstr(wstr_size, wchar_t{});
|
||||
if (!MultiByteToWideChar(CP_UTF8, 0, &str[0], str.size(), &wstr[0], wstr_size))
|
||||
{
|
||||
throw std::runtime_error(std::error_code(GetLastError(), std::system_category()).message());
|
||||
}
|
||||
return wstr;
|
||||
}
|
||||
inline std::string utf16_to_utf8(const std::wstring& wstr)
|
||||
{
|
||||
if (wstr.empty())
|
||||
return {};
|
||||
int str_size = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], wstr.size(), NULL, 0, NULL, NULL);
|
||||
if (str_size == 0)
|
||||
{
|
||||
throw std::runtime_error(std::error_code(GetLastError(), std::system_category()).message());
|
||||
}
|
||||
std::string str(str_size, char{});
|
||||
if (!WideCharToMultiByte(CP_UTF8, 0, &wstr[0], wstr.size(), &str[0], str_size, NULL, NULL))
|
||||
{
|
||||
throw std::runtime_error(std::error_code(GetLastError(), std::system_category()).message());
|
||||
}
|
||||
return str;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif //_STRING_TOOLS_H_
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
|
||||
void *memwipe(void *ptr, size_t n)
|
||||
{
|
||||
if (memset_s(ptr, n, 0, n))
|
||||
if (n > 0 && memset_s(ptr, n, 0, n))
|
||||
{
|
||||
#ifdef NDEBUG
|
||||
fprintf(stderr, "Error: memset_s failed\n");
|
||||
@@ -67,7 +67,8 @@ void *memwipe(void *ptr, size_t n)
|
||||
|
||||
void *memwipe(void *ptr, size_t n)
|
||||
{
|
||||
explicit_bzero(ptr, n);
|
||||
if (n > 0)
|
||||
explicit_bzero(ptr, n);
|
||||
SCARECROW
|
||||
return ptr;
|
||||
}
|
||||
@@ -105,7 +106,8 @@ static void memory_cleanse(void *ptr, size_t len)
|
||||
|
||||
void *memwipe(void *ptr, size_t n)
|
||||
{
|
||||
memory_cleanse(ptr, n);
|
||||
if (n > 0)
|
||||
memory_cleanse(ptr, n);
|
||||
SCARECROW
|
||||
return ptr;
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ using namespace epee;
|
||||
static std::string generate_log_filename(const char *base)
|
||||
{
|
||||
std::string filename(base);
|
||||
static unsigned int fallback_counter = 0;
|
||||
char tmp[200];
|
||||
struct tm tm;
|
||||
time_t now = time(NULL);
|
||||
@@ -56,7 +57,7 @@ static std::string generate_log_filename(const char *base)
|
||||
#else
|
||||
(!gmtime_r(&now, &tm))
|
||||
#endif
|
||||
strcpy(tmp, "unknown");
|
||||
snprintf(tmp, sizeof(tmp), "part-%u", ++fallback_counter);
|
||||
else
|
||||
strftime(tmp, sizeof(tmp), "%Y-%m-%d-%H-%M-%S", &tm);
|
||||
tmp[sizeof(tmp) - 1] = 0;
|
||||
|
||||
@@ -148,6 +148,7 @@ struct txpool_tx_meta_t
|
||||
uint8_t relayed;
|
||||
uint8_t do_not_relay;
|
||||
uint8_t double_spend_seen: 1;
|
||||
uint8_t bf_padding: 7;
|
||||
|
||||
uint8_t padding[76]; // till 192 bytes
|
||||
};
|
||||
@@ -1505,6 +1506,13 @@ public:
|
||||
*/
|
||||
virtual bool is_read_only() const = 0;
|
||||
|
||||
/**
|
||||
* @brief get disk space requirements
|
||||
*
|
||||
* @return the size required
|
||||
*/
|
||||
virtual uint64_t get_database_size() const = 0;
|
||||
|
||||
// TODO: this should perhaps be (or call) a series of functions which
|
||||
// progressively update through version updates
|
||||
/**
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <random>
|
||||
|
||||
#include "string_tools.h"
|
||||
#include "file_io_utils.h"
|
||||
#include "common/util.h"
|
||||
#include "cryptonote_basic/cryptonote_format_utils.h"
|
||||
#include "crypto/crypto.h"
|
||||
@@ -1336,6 +1337,9 @@ void BlockchainLMDB::sync()
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
|
||||
if (is_read_only())
|
||||
return;
|
||||
|
||||
// Does nothing unless LMDB environment was opened with MDB_NOSYNC or in part
|
||||
// MDB_NOMETASYNC. Force flush to be synchronous.
|
||||
if (auto result = mdb_env_sync(m_env, true))
|
||||
@@ -3293,6 +3297,16 @@ bool BlockchainLMDB::is_read_only() const
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t BlockchainLMDB::get_database_size() const
|
||||
{
|
||||
uint64_t size = 0;
|
||||
boost::filesystem::path datafile(m_folder);
|
||||
datafile /= CRYPTONOTE_BLOCKCHAINDATA_FILENAME;
|
||||
if (!epee::file_io_utils::get_file_size(datafile.string(), size))
|
||||
size = 0;
|
||||
return size;
|
||||
}
|
||||
|
||||
void BlockchainLMDB::fixup()
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
|
||||
@@ -157,7 +157,7 @@ struct mdb_txn_safe
|
||||
class BlockchainLMDB : public BlockchainDB
|
||||
{
|
||||
public:
|
||||
BlockchainLMDB(bool batch_transactions=false);
|
||||
BlockchainLMDB(bool batch_transactions=true);
|
||||
~BlockchainLMDB();
|
||||
|
||||
virtual void open(const std::string& filename, const int mdb_flags=0);
|
||||
@@ -364,6 +364,8 @@ private:
|
||||
|
||||
virtual bool is_read_only() const;
|
||||
|
||||
virtual uint64_t get_database_size() const;
|
||||
|
||||
// fix up anything that may be wrong due to past bugs
|
||||
virtual void fixup();
|
||||
|
||||
|
||||
Binary file not shown.
@@ -78,7 +78,6 @@ monero_add_library(common
|
||||
DEPENDS generate_translations_header)
|
||||
target_link_libraries(common
|
||||
PUBLIC
|
||||
epee
|
||||
cncrypto
|
||||
${UNBOUND_LIBRARY}
|
||||
${LIBUNWIND_LIBRARIES}
|
||||
|
||||
@@ -440,10 +440,15 @@ std::string get_nix_version_display_string()
|
||||
|
||||
if (SHGetSpecialFolderPathW(NULL, psz_path, nfolder, iscreate))
|
||||
{
|
||||
int size_needed = WideCharToMultiByte(CP_UTF8, 0, psz_path, wcslen(psz_path), NULL, 0, NULL, NULL);
|
||||
std::string folder_name(size_needed, 0);
|
||||
WideCharToMultiByte(CP_UTF8, 0, psz_path, wcslen(psz_path), &folder_name[0], size_needed, NULL, NULL);
|
||||
return folder_name;
|
||||
try
|
||||
{
|
||||
return string_tools::utf16_to_utf8(psz_path);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
MERROR("utf16_to_utf8 failed: " << e.what());
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
LOG_ERROR("SHGetSpecialFolderPathW() failed, could not obtain requested path.");
|
||||
@@ -504,18 +509,20 @@ std::string get_nix_version_display_string()
|
||||
int code;
|
||||
#if defined(WIN32)
|
||||
// Maximizing chances for success
|
||||
WCHAR wide_replacement_name[1000];
|
||||
MultiByteToWideChar(CP_UTF8, 0, replacement_name.c_str(), replacement_name.size() + 1, wide_replacement_name, 1000);
|
||||
WCHAR wide_replaced_name[1000];
|
||||
MultiByteToWideChar(CP_UTF8, 0, replaced_name.c_str(), replaced_name.size() + 1, wide_replaced_name, 1000);
|
||||
std::wstring wide_replacement_name;
|
||||
try { wide_replacement_name = string_tools::utf8_to_utf16(replacement_name); }
|
||||
catch (...) { return std::error_code(GetLastError(), std::system_category()); }
|
||||
std::wstring wide_replaced_name;
|
||||
try { wide_replaced_name = string_tools::utf8_to_utf16(replaced_name); }
|
||||
catch (...) { return std::error_code(GetLastError(), std::system_category()); }
|
||||
|
||||
DWORD attributes = ::GetFileAttributesW(wide_replaced_name);
|
||||
DWORD attributes = ::GetFileAttributesW(wide_replaced_name.c_str());
|
||||
if (INVALID_FILE_ATTRIBUTES != attributes)
|
||||
{
|
||||
::SetFileAttributesW(wide_replaced_name, attributes & (~FILE_ATTRIBUTE_READONLY));
|
||||
::SetFileAttributesW(wide_replaced_name.c_str(), attributes & (~FILE_ATTRIBUTE_READONLY));
|
||||
}
|
||||
|
||||
bool ok = 0 != ::MoveFileExW(wide_replacement_name, wide_replaced_name, MOVEFILE_REPLACE_EXISTING);
|
||||
bool ok = 0 != ::MoveFileExW(wide_replacement_name.c_str(), wide_replaced_name.c_str(), MOVEFILE_REPLACE_EXISTING);
|
||||
code = ok ? 0 : static_cast<int>(::GetLastError());
|
||||
#else
|
||||
bool ok = 0 == std::rename(replacement_name.c_str(), replaced_name.c_str());
|
||||
@@ -657,6 +664,13 @@ std::string get_nix_version_display_string()
|
||||
|
||||
bool is_local_address(const std::string &address)
|
||||
{
|
||||
// always assume Tor/I2P addresses to be untrusted by default
|
||||
if (boost::ends_with(address, ".onion") || boost::ends_with(address, ".i2p"))
|
||||
{
|
||||
MDEBUG("Address '" << address << "' is Tor/I2P, non local");
|
||||
return false;
|
||||
}
|
||||
|
||||
// extract host
|
||||
epee::net_utils::http::url_content u_c;
|
||||
if (!epee::net_utils::parse_url(address, u_c))
|
||||
@@ -750,4 +764,22 @@ std::string get_nix_version_display_string()
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
boost::optional<std::pair<uint32_t, uint32_t>> parse_subaddress_lookahead(const std::string& str)
|
||||
{
|
||||
auto pos = str.find(":");
|
||||
bool r = pos != std::string::npos;
|
||||
uint32_t major;
|
||||
r = r && epee::string_tools::get_xtype_from_string(major, str.substr(0, pos));
|
||||
uint32_t minor;
|
||||
r = r && epee::string_tools::get_xtype_from_string(minor, str.substr(pos + 1));
|
||||
if (r)
|
||||
{
|
||||
return std::make_pair(major, minor);
|
||||
}
|
||||
else
|
||||
{
|
||||
return {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
#include <boost/thread/locks.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <system_error>
|
||||
#include <csignal>
|
||||
#include <cstdio>
|
||||
@@ -212,4 +213,6 @@ namespace tools
|
||||
|
||||
bool sha256sum(const uint8_t *data, size_t len, crypto::hash &hash);
|
||||
bool sha256sum(const std::string &filename, crypto::hash &hash);
|
||||
|
||||
boost::optional<std::pair<uint32_t, uint32_t>> parse_subaddress_lookahead(const std::string& str);
|
||||
}
|
||||
|
||||
@@ -905,10 +905,35 @@ STATIC INLINE void aes_pseudo_round_xor(const uint8_t *in, uint8_t *out, const u
|
||||
}
|
||||
}
|
||||
|
||||
STATIC INLINE void* aligned_malloc(size_t size, size_t align)
|
||||
{
|
||||
void *result;
|
||||
#ifdef _MSC_VER
|
||||
result = _aligned_malloc(size, align);
|
||||
#else
|
||||
if (posix_memalign(&result, align, size)) result = NULL;
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
STATIC INLINE void aligned_free(void *ptr)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
_aligned_free(ptr);
|
||||
#else
|
||||
free(ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int prehashed)
|
||||
{
|
||||
RDATA_ALIGN16 uint8_t expandedKey[240];
|
||||
|
||||
#ifndef FORCE_USE_HEAP
|
||||
RDATA_ALIGN16 uint8_t hp_state[MEMORY];
|
||||
#else
|
||||
uint8_t *hp_state = (uint8_t *)aligned_malloc(MEMORY,16);
|
||||
#endif
|
||||
|
||||
uint8_t text[INIT_SIZE_BYTE];
|
||||
RDATA_ALIGN16 uint64_t a[2];
|
||||
@@ -993,6 +1018,10 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||
memcpy(state.init, text, INIT_SIZE_BYTE);
|
||||
hash_permutation(&state.hs);
|
||||
extra_hashes[state.hs.b[0] & 3](&state, 200, hash);
|
||||
|
||||
#ifdef FORCE_USE_HEAP
|
||||
aligned_free(hp_state);
|
||||
#endif
|
||||
}
|
||||
#else /* aarch64 && crypto */
|
||||
|
||||
@@ -1127,8 +1156,7 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||
#ifndef FORCE_USE_HEAP
|
||||
uint8_t long_state[MEMORY];
|
||||
#else
|
||||
uint8_t *long_state = NULL;
|
||||
long_state = (uint8_t *)malloc(MEMORY);
|
||||
uint8_t *long_state = (uint8_t *)malloc(MEMORY);
|
||||
#endif
|
||||
|
||||
if (prehashed) {
|
||||
@@ -1294,7 +1322,12 @@ union cn_slow_hash_state {
|
||||
#pragma pack(pop)
|
||||
|
||||
void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int prehashed) {
|
||||
#ifndef FORCE_USE_HEAP
|
||||
uint8_t long_state[MEMORY];
|
||||
#else
|
||||
uint8_t *long_state = (uint8_t *)malloc(MEMORY);
|
||||
#endif
|
||||
|
||||
union cn_slow_hash_state state;
|
||||
uint8_t text[INIT_SIZE_BYTE];
|
||||
uint8_t a[AES_BLOCK_SIZE];
|
||||
@@ -1370,6 +1403,10 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||
/*memcpy(hash, &state, 32);*/
|
||||
extra_hashes[state.hs.b[0] & 3](&state, 200, hash);
|
||||
oaes_free((OAES_CTX **) &aes_ctx);
|
||||
|
||||
#ifdef FORCE_USE_HEAP
|
||||
free(long_state);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -157,7 +157,7 @@ DISABLE_VS_WARNINGS(4244 4345)
|
||||
void account_base::create_from_viewkey(const cryptonote::account_public_address& address, const crypto::secret_key& viewkey)
|
||||
{
|
||||
crypto::secret_key fake;
|
||||
memset(&fake, 0, sizeof(fake));
|
||||
memset(&unwrap(fake), 0, sizeof(fake));
|
||||
create_from_keys(address, fake, viewkey);
|
||||
}
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
@@ -243,33 +243,35 @@ namespace cryptonote {
|
||||
|
||||
// LWMA-2 difficulty algorithm
|
||||
// Copyright (c) 2017-2018 Zawy, MIT License
|
||||
// See commented version in https://github.com/zawy12/difficulty-algorithms/issues/3
|
||||
// for required config file changes.
|
||||
// https://github.com/zawy12/difficulty-algorithms/issues/3
|
||||
// See commented version for required config file changes.
|
||||
|
||||
difficulty_type next_difficulty_v3(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties) {
|
||||
difficulty_type next_difficulty_v3(std::vector<uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties) {
|
||||
|
||||
int64_t T = DIFFICULTY_TARGET_V2;
|
||||
int64_t N = DIFFICULTY_WINDOW_V2;
|
||||
int64_t FTL = CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT_V3;
|
||||
int64_t L(0), ST, sum_3_ST(0), next_D, prev_D;
|
||||
|
||||
assert(timestamps.size() == cumulative_difficulties.size() && timestamps.size() <= static_cast<uint64_t>(N+1) );
|
||||
|
||||
// TODO: change initial_difficulty_guess before v9 mainnet hard fork
|
||||
// if ( height >= fork_height && height <= fork_height+N ) { return difficulty_guess; }
|
||||
uint64_t initial_difficulty_guess = 100;
|
||||
if (timestamps.size() <= static_cast<uint64_t>(N)) {
|
||||
return initial_difficulty_guess;
|
||||
}
|
||||
uint64_t difficulty_guess = 100;
|
||||
if (timestamps.size() <= 10 ) { return difficulty_guess; }
|
||||
if ( timestamps.size() < static_cast<uint64_t>(N +1) ) { N = timestamps.size()-1; }
|
||||
|
||||
for ( int64_t i = 1; i <= N; i++) {
|
||||
ST = std::max(-FTL, std::min( (int64_t)(timestamps[i]) - (int64_t)(timestamps[i-1]), 6*T));
|
||||
L += ST * i ;
|
||||
ST = std::max(-FTL, std::min( static_cast<int64_t>(timestamps[i]) - static_cast<int64_t>(timestamps[i-1]), 6*T));
|
||||
L += ST * i ;
|
||||
if ( i > N-3 ) { sum_3_ST += ST; }
|
||||
}
|
||||
|
||||
next_D = ((cumulative_difficulties[N] - cumulative_difficulties[0])*T*(N+1)*99)/(100*2*L);
|
||||
next_D = (static_cast<int64_t>(cumulative_difficulties[N] - cumulative_difficulties[0])*T*(N+1)*99)/(100*2*L);
|
||||
|
||||
prev_D = cumulative_difficulties[N] - cumulative_difficulties[N-1];
|
||||
if ( sum_3_ST < (8*T)/10) { next_D = (prev_D*110)/100; }
|
||||
next_D = std::max((prev_D*67)/100, std::min( next_D, (prev_D*150)/100));
|
||||
if ( sum_3_ST < (8*T)/10) { next_D = std::max(next_D,(prev_D*110)/100); }
|
||||
|
||||
return static_cast<uint64_t>(next_D);
|
||||
}
|
||||
|
||||
@@ -485,7 +485,7 @@ namespace cryptonote
|
||||
{
|
||||
//we lucky!
|
||||
++m_config.current_extra_message_index;
|
||||
MGINFO_GREEN("Found block for difficulty: " << local_diff);
|
||||
MGINFO_GREEN("Found block " << get_block_hash(b) << " at height " << height << " for difficulty: " << local_diff);
|
||||
if(!m_phandler->handle_block_found(b))
|
||||
{
|
||||
--m_config.current_extra_message_index;
|
||||
|
||||
@@ -116,16 +116,8 @@ static const struct {
|
||||
uint8_t threshold;
|
||||
time_t time;
|
||||
} stagenet_hard_forks[] = {
|
||||
// version 1 from the start of the blockchain
|
||||
{ 1, 1, 0, 1341378000 },
|
||||
|
||||
// versions 2-7 in rapid succession from March 13th, 2018
|
||||
{ 2, 32000, 0, 1521000000 },
|
||||
{ 3, 33000, 0, 1521120000 },
|
||||
{ 4, 34000, 0, 1521240000 },
|
||||
{ 5, 35000, 0, 1521360000 },
|
||||
{ 6, 36000, 0, 1521480000 },
|
||||
{ 7, 37000, 0, 1521600000 },
|
||||
{ 7, 1, 0, 1519605000 },
|
||||
{ 8, 10, 0, 1530621606 },
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------
|
||||
@@ -417,7 +409,7 @@ bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline
|
||||
m_db->block_txn_stop();
|
||||
|
||||
uint64_t num_popped_blocks = 0;
|
||||
while (true)
|
||||
while (!m_db->is_read_only())
|
||||
{
|
||||
const uint64_t top_height = m_db->height() - 1;
|
||||
const crypto::hash top_id = m_db->top_block_hash();
|
||||
@@ -1950,14 +1942,21 @@ bool Blockchain::get_outs(const COMMAND_RPC_GET_OUTPUTS_BIN::request& req, COMMA
|
||||
|
||||
res.outs.clear();
|
||||
res.outs.reserve(req.outputs.size());
|
||||
for (const auto &i: req.outputs)
|
||||
try
|
||||
{
|
||||
// get tx_hash, tx_out_index from DB
|
||||
const output_data_t od = m_db->get_output_key(i.amount, i.index);
|
||||
tx_out_index toi = m_db->get_output_tx_and_index(i.amount, i.index);
|
||||
bool unlocked = is_tx_spendtime_unlocked(m_db->get_tx_unlock_time(toi.first));
|
||||
for (const auto &i: req.outputs)
|
||||
{
|
||||
// get tx_hash, tx_out_index from DB
|
||||
const output_data_t od = m_db->get_output_key(i.amount, i.index);
|
||||
tx_out_index toi = m_db->get_output_tx_and_index(i.amount, i.index);
|
||||
bool unlocked = is_tx_spendtime_unlocked(m_db->get_tx_unlock_time(toi.first));
|
||||
|
||||
res.outs.push_back({od.pubkey, od.commitment, unlocked, od.height, toi.first});
|
||||
res.outs.push_back({od.pubkey, od.commitment, unlocked, od.height, toi.first});
|
||||
}
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -3299,6 +3298,7 @@ bool Blockchain::handle_block_to_main_chain(const block& bl, const crypto::hash&
|
||||
if(bl.prev_id != get_tail_id())
|
||||
{
|
||||
MERROR_VER("Block with id: " << id << std::endl << "has wrong prev_id: " << bl.prev_id << std::endl << "expected: " << get_tail_id());
|
||||
bvc.m_verifivation_failed = true;
|
||||
leave:
|
||||
m_db->block_txn_stop();
|
||||
return false;
|
||||
@@ -3599,6 +3599,7 @@ leave:
|
||||
{
|
||||
//TODO: figure out the best way to deal with this failure
|
||||
LOG_ERROR("Error adding block with hash: " << id << " to blockchain, what = " << e.what());
|
||||
bvc.m_verifivation_failed = true;
|
||||
return_tx_to_pool(txs);
|
||||
return false;
|
||||
}
|
||||
@@ -3628,6 +3629,7 @@ leave:
|
||||
|
||||
// appears to be a NOP *and* is called elsewhere. wat?
|
||||
m_tx_pool.on_blockchain_inc(new_height, id);
|
||||
get_difficulty_for_next_block(); // just to cache it
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -4397,9 +4399,9 @@ std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>> Blockchain:: get_ou
|
||||
return m_db->get_output_histogram(amounts, unlocked, recent_cutoff, min_count);
|
||||
}
|
||||
|
||||
std::list<std::pair<Blockchain::block_extended_info,uint64_t>> Blockchain::get_alternative_chains() const
|
||||
std::list<std::pair<Blockchain::block_extended_info,std::vector<crypto::hash>>> Blockchain::get_alternative_chains() const
|
||||
{
|
||||
std::list<std::pair<Blockchain::block_extended_info,uint64_t>> chains;
|
||||
std::list<std::pair<Blockchain::block_extended_info,std::vector<crypto::hash>>> chains;
|
||||
|
||||
for (const auto &i: m_alternative_chains)
|
||||
{
|
||||
@@ -4415,15 +4417,16 @@ std::list<std::pair<Blockchain::block_extended_info,uint64_t>> Blockchain::get_a
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
uint64_t length = 1;
|
||||
std::vector<crypto::hash> chain;
|
||||
auto h = i.second.bl.prev_id;
|
||||
chain.push_back(top);
|
||||
blocks_ext_by_hash::const_iterator prev;
|
||||
while ((prev = m_alternative_chains.find(h)) != m_alternative_chains.end())
|
||||
{
|
||||
chain.push_back(h);
|
||||
h = prev->second.bl.prev_id;
|
||||
++length;
|
||||
}
|
||||
chains.push_back(std::make_pair(i.second, length));
|
||||
chains.push_back(std::make_pair(i.second, chain));
|
||||
}
|
||||
}
|
||||
return chains;
|
||||
@@ -4435,7 +4438,7 @@ void Blockchain::cancel()
|
||||
}
|
||||
|
||||
#if defined(PER_BLOCK_CHECKPOINT)
|
||||
static const char expected_block_hashes_hash[] = "b81e87c72cf3d1c0567077bb0eac6152a4bba8eeb2b4a7e1b69d1e866d341a3e";
|
||||
static const char expected_block_hashes_hash[] = "1ed4338c8e3f8eb877caae719bda776252b3a731be1613e0c4130fc67ea5280a";
|
||||
void Blockchain::load_compiled_in_block_hashes()
|
||||
{
|
||||
const bool testnet = m_nettype == TESTNET;
|
||||
|
||||
@@ -929,7 +929,7 @@ namespace cryptonote
|
||||
*
|
||||
* @return a list of chains
|
||||
*/
|
||||
std::list<std::pair<block_extended_info,uint64_t>> get_alternative_chains() const;
|
||||
std::list<std::pair<block_extended_info,std::vector<crypto::hash>>> get_alternative_chains() const;
|
||||
|
||||
void add_txpool_tx(transaction &tx, const txpool_tx_meta_t &meta);
|
||||
void update_txpool_tx(const crypto::hash &txid, const txpool_tx_meta_t &meta);
|
||||
|
||||
@@ -676,6 +676,7 @@ namespace cryptonote
|
||||
bool core::handle_incoming_txs(const std::list<blobdata>& tx_blobs, std::vector<tx_verification_context>& tvc, bool keeped_by_block, bool relayed, bool do_not_relay)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
CRITICAL_REGION_LOCAL(m_incoming_tx_lock);
|
||||
|
||||
struct result { bool res; cryptonote::transaction tx; crypto::hash hash; crypto::hash prefix_hash; bool in_txpool; bool in_blockchain; };
|
||||
std::vector<result> results(tx_blobs.size());
|
||||
@@ -1359,6 +1360,9 @@ namespace cryptonote
|
||||
MGINFO_YELLOW(ENDL << "**********************************************************************" << ENDL
|
||||
<< main_message << ENDL
|
||||
<< ENDL
|
||||
<< "Caution: Wownero is highly experimental software compiled by a ragtag team of stoners with as much" << ENDL
|
||||
<< "skill as Verge developers. Storing your life savings in WOW is probably not a good idea." << ENDL
|
||||
<< ENDL
|
||||
<< "You can set the level of process detailization through \"set_log <level|categories>\" command," << ENDL
|
||||
<< "where <level> is between 0 (no details) and 4 (very verbose), or custom category based levels (eg, *:WARNING)." << ENDL
|
||||
<< ENDL
|
||||
|
||||
@@ -239,6 +239,7 @@ namespace cryptonote
|
||||
meta.relayed = relayed;
|
||||
meta.do_not_relay = do_not_relay;
|
||||
meta.double_spend_seen = have_tx_keyimges_as_spent(tx);
|
||||
meta.bf_padding = 0;
|
||||
memset(meta.padding, 0, sizeof(meta.padding));
|
||||
try
|
||||
{
|
||||
@@ -278,6 +279,7 @@ namespace cryptonote
|
||||
meta.relayed = relayed;
|
||||
meta.do_not_relay = do_not_relay;
|
||||
meta.double_spend_seen = false;
|
||||
meta.bf_padding = 0;
|
||||
memset(meta.padding, 0, sizeof(meta.padding));
|
||||
|
||||
try
|
||||
|
||||
@@ -92,7 +92,6 @@ target_link_libraries(daemon
|
||||
daemonizer
|
||||
serialization
|
||||
daemon_rpc_server
|
||||
epee
|
||||
${EPEE_READLINE}
|
||||
version
|
||||
${Boost_CHRONO_LIBRARY}
|
||||
|
||||
@@ -599,13 +599,13 @@ bool t_command_parser_executor::print_coinbase_tx_sum(const std::vector<std::str
|
||||
|
||||
bool t_command_parser_executor::alt_chain_info(const std::vector<std::string>& args)
|
||||
{
|
||||
if(args.size())
|
||||
if(args.size() > 1)
|
||||
{
|
||||
std::cout << "No parameters allowed" << std::endl;
|
||||
std::cout << "usage: alt_chain_info [block_hash]" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_executor.alt_chain_info();
|
||||
return m_executor.alt_chain_info(args.size() == 1 ? args[0] : "");
|
||||
}
|
||||
|
||||
bool t_command_parser_executor::print_blockchain_dynamic_stats(const std::vector<std::string>& args)
|
||||
|
||||
@@ -255,6 +255,7 @@ t_command_server::t_command_server(
|
||||
m_command_lookup.set_handler(
|
||||
"alt_chain_info"
|
||||
, std::bind(&t_command_parser_executor::alt_chain_info, &m_parser, p::_1)
|
||||
, "alt_chain_info [blockhash]"
|
||||
, "Print the information about alternative chains."
|
||||
);
|
||||
m_command_lookup.set_handler(
|
||||
|
||||
@@ -262,6 +262,9 @@ int main(int argc, char const * argv[])
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef HAVE_READLINE
|
||||
rdln::suspend_readline pause_readline;
|
||||
#endif
|
||||
std::cerr << "Unknown command: " << command.front() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -973,7 +973,7 @@ bool t_rpc_command_executor::print_transaction_pool_stats() {
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(&res.pool_stats, 0, sizeof(res.pool_stats));
|
||||
res.pool_stats = {};
|
||||
if (!m_rpc_server->on_get_transaction_pool_stats(req, res, false) || res.status != CORE_RPC_STATUS_OK)
|
||||
{
|
||||
tools::fail_msg_writer() << make_error(fail_message, res.status);
|
||||
@@ -1625,7 +1625,7 @@ bool t_rpc_command_executor::print_coinbase_tx_sum(uint64_t height, uint64_t cou
|
||||
return true;
|
||||
}
|
||||
|
||||
bool t_rpc_command_executor::alt_chain_info()
|
||||
bool t_rpc_command_executor::alt_chain_info(const std::string &tip)
|
||||
{
|
||||
cryptonote::COMMAND_RPC_GET_INFO::request ireq;
|
||||
cryptonote::COMMAND_RPC_GET_INFO::response ires;
|
||||
@@ -1660,12 +1660,32 @@ bool t_rpc_command_executor::alt_chain_info()
|
||||
}
|
||||
}
|
||||
|
||||
tools::msg_writer() << boost::lexical_cast<std::string>(res.chains.size()) << " alternate chains found:";
|
||||
for (const auto &chain: res.chains)
|
||||
if (tip.empty())
|
||||
{
|
||||
uint64_t start_height = (chain.height - chain.length + 1);
|
||||
tools::msg_writer() << chain.length << " blocks long, from height " << start_height << " (" << (ires.height - start_height - 1)
|
||||
<< " deep), diff " << chain.difficulty << ": " << chain.block_hash;
|
||||
tools::msg_writer() << boost::lexical_cast<std::string>(res.chains.size()) << " alternate chains found:";
|
||||
for (const auto &chain: res.chains)
|
||||
{
|
||||
uint64_t start_height = (chain.height - chain.length + 1);
|
||||
tools::msg_writer() << chain.length << " blocks long, from height " << start_height << " (" << (ires.height - start_height - 1)
|
||||
<< " deep), diff " << chain.difficulty << ": " << chain.block_hash;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto i = std::find_if(res.chains.begin(), res.chains.end(), [&tip](cryptonote::COMMAND_RPC_GET_ALTERNATE_CHAINS::chain_info &info){ return info.block_hash == tip; });
|
||||
if (i != res.chains.end())
|
||||
{
|
||||
const auto &chain = *i;
|
||||
tools::success_msg_writer() << "Found alternate chain with tip " << tip;
|
||||
uint64_t start_height = (chain.height - chain.length + 1);
|
||||
tools::msg_writer() << chain.length << " blocks long, from height " << start_height << " (" << (ires.height - start_height - 1)
|
||||
<< " deep), diff " << chain.difficulty << ":";
|
||||
for (const std::string &block_id: chain.block_hashes)
|
||||
tools::msg_writer() << " " << block_id;
|
||||
tools::msg_writer() << "Chain parent on main chain: " << chain.main_chain_parent_block;
|
||||
}
|
||||
else
|
||||
tools::fail_msg_writer() << "Block hash " << tip << " is not the tip of any known alternate chain";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@ public:
|
||||
|
||||
bool print_coinbase_tx_sum(uint64_t height, uint64_t count);
|
||||
|
||||
bool alt_chain_info();
|
||||
bool alt_chain_info(const std::string &tip);
|
||||
|
||||
bool print_blockchain_dynamic_stats(uint64_t nblocks);
|
||||
|
||||
|
||||
@@ -38,7 +38,6 @@ source_group(p2p FILES ${P2P})
|
||||
monero_add_library(p2p ${P2P})
|
||||
target_link_libraries(p2p
|
||||
PUBLIC
|
||||
epee
|
||||
version
|
||||
cryptonote_core
|
||||
${UPNP_LIBRARIES}
|
||||
|
||||
@@ -372,13 +372,20 @@ namespace nodetool
|
||||
if (nettype == cryptonote::TESTNET) {
|
||||
full_addrs.insert("206.189.166.14:11180");
|
||||
full_addrs.insert("104.236.48.55:11180");
|
||||
} else {
|
||||
}
|
||||
else if (nettype == cryptonote::STAGENET)
|
||||
{
|
||||
full_addrs.insert("206.189.166.14:38080");
|
||||
full_addrs.insert("104.236.48.55:38080");
|
||||
}
|
||||
else
|
||||
{
|
||||
full_addrs.insert("66.70.218.230:34567");
|
||||
full_addrs.insert("34.209.48.213:34567");
|
||||
full_addrs.insert("159.65.91.59:34567");
|
||||
full_addrs.insert("138.197.31.246:34567");
|
||||
|
||||
}
|
||||
|
||||
return full_addrs;
|
||||
}
|
||||
|
||||
|
||||
@@ -111,7 +111,6 @@ target_link_libraries(rpc
|
||||
common
|
||||
cryptonote_core
|
||||
cryptonote_protocol
|
||||
epee
|
||||
${Boost_REGEX_LIBRARY}
|
||||
${Boost_THREAD_LIBRARY}
|
||||
PRIVATE
|
||||
|
||||
@@ -207,6 +207,7 @@ namespace cryptonote
|
||||
boost::shared_lock<boost::shared_mutex> lock(m_bootstrap_daemon_mutex);
|
||||
res.was_bootstrap_ever_used = m_was_bootstrap_ever_used;
|
||||
}
|
||||
res.database_size = m_core.get_blockchain_storage().get_db().get_database_size();
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -1591,6 +1592,7 @@ namespace cryptonote
|
||||
boost::shared_lock<boost::shared_mutex> lock(m_bootstrap_daemon_mutex);
|
||||
res.was_bootstrap_ever_used = m_was_bootstrap_ever_used;
|
||||
}
|
||||
res.database_size = m_core.get_blockchain_storage().get_db().get_database_size();
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -1788,10 +1790,22 @@ namespace cryptonote
|
||||
PERF_TIMER(on_get_alternate_chains);
|
||||
try
|
||||
{
|
||||
std::list<std::pair<Blockchain::block_extended_info, uint64_t>> chains = m_core.get_blockchain_storage().get_alternative_chains();
|
||||
std::list<std::pair<Blockchain::block_extended_info, std::vector<crypto::hash>>> chains = m_core.get_blockchain_storage().get_alternative_chains();
|
||||
for (const auto &i: chains)
|
||||
{
|
||||
res.chains.push_back(COMMAND_RPC_GET_ALTERNATE_CHAINS::chain_info{epee::string_tools::pod_to_hex(get_block_hash(i.first.bl)), i.first.height, i.second, i.first.cumulative_difficulty});
|
||||
res.chains.push_back(COMMAND_RPC_GET_ALTERNATE_CHAINS::chain_info{epee::string_tools::pod_to_hex(get_block_hash(i.first.bl)), i.first.height, i.second.size(), i.first.cumulative_difficulty, {}, std::string()});
|
||||
res.chains.back().block_hashes.reserve(i.second.size());
|
||||
for (const crypto::hash &block_id: i.second)
|
||||
res.chains.back().block_hashes.push_back(epee::string_tools::pod_to_hex(block_id));
|
||||
if (i.first.height < i.second.size())
|
||||
{
|
||||
res.status = "Error finding alternate chain attachment point";
|
||||
return true;
|
||||
}
|
||||
cryptonote::block main_chain_parent_block;
|
||||
try { main_chain_parent_block = m_core.get_blockchain_storage().get_db().get_block_from_height(i.first.height - i.second.size()); }
|
||||
catch (const std::exception &e) { res.status = "Error finding alternate chain attachment point"; return true; }
|
||||
res.chains.back().main_chain_parent_block = epee::string_tools::pod_to_hex(get_block_hash(main_chain_parent_block));
|
||||
}
|
||||
res.status = CORE_RPC_STATUS_OK;
|
||||
}
|
||||
|
||||
@@ -964,6 +964,7 @@ namespace cryptonote
|
||||
std::string bootstrap_daemon_address;
|
||||
uint64_t height_without_bootstrap;
|
||||
bool was_bootstrap_ever_used;
|
||||
uint64_t database_size;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(status)
|
||||
@@ -993,6 +994,7 @@ namespace cryptonote
|
||||
KV_SERIALIZE(bootstrap_daemon_address)
|
||||
KV_SERIALIZE(height_without_bootstrap)
|
||||
KV_SERIALIZE(was_bootstrap_ever_used)
|
||||
KV_SERIALIZE(database_size)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
@@ -1554,6 +1556,8 @@ namespace cryptonote
|
||||
std::vector<txpool_histo> histo;
|
||||
uint32_t num_double_spends;
|
||||
|
||||
txpool_stats(): bytes_total(0), bytes_min(0), bytes_max(0), bytes_med(0), fee_total(0), oldest(0), txs_total(0), num_failing(0), num_10m(0), num_not_relayed(0), histo_98pc(0), num_double_spends(0) {}
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(bytes_total)
|
||||
KV_SERIALIZE(bytes_min)
|
||||
@@ -2073,12 +2077,16 @@ namespace cryptonote
|
||||
uint64_t height;
|
||||
uint64_t length;
|
||||
uint64_t difficulty;
|
||||
std::vector<std::string> block_hashes;
|
||||
std::string main_chain_parent_block;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(block_hash)
|
||||
KV_SERIALIZE(height)
|
||||
KV_SERIALIZE(length)
|
||||
KV_SERIALIZE(difficulty)
|
||||
KV_SERIALIZE(block_hashes)
|
||||
KV_SERIALIZE(main_chain_parent_block)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
||||
@@ -104,6 +104,10 @@ bool ZmqServer::addTCPSocket(std::string address, std::string port)
|
||||
|
||||
rep_socket->setsockopt(ZMQ_RCVTIMEO, &DEFAULT_RPC_RECV_TIMEOUT_MS, sizeof(DEFAULT_RPC_RECV_TIMEOUT_MS));
|
||||
|
||||
if (address.empty())
|
||||
address = "*";
|
||||
if (port.empty())
|
||||
port = "*";
|
||||
std::string bind_address = addr_prefix + address + std::string(":") + port;
|
||||
rep_socket->bind(bind_address.c_str());
|
||||
}
|
||||
|
||||
@@ -48,7 +48,6 @@ target_link_libraries(simplewallet
|
||||
cncrypto
|
||||
common
|
||||
mnemonics
|
||||
epee
|
||||
${EPEE_READLINE}
|
||||
version
|
||||
${Boost_CHRONO_LIBRARY}
|
||||
|
||||
@@ -127,6 +127,7 @@ namespace
|
||||
const command_line::arg_descriptor<bool> arg_restore_multisig_wallet = {"restore-multisig-wallet", sw::tr("Recover multisig wallet using Electrum-style mnemonic seed"), false};
|
||||
const command_line::arg_descriptor<bool> arg_non_deterministic = {"non-deterministic", sw::tr("Generate non-deterministic view and spend keys"), false};
|
||||
const command_line::arg_descriptor<bool> arg_trusted_daemon = {"trusted-daemon", sw::tr("Enable commands which rely on a trusted daemon"), false};
|
||||
const command_line::arg_descriptor<bool> arg_untrusted_daemon = {"untrusted-daemon", sw::tr("Disable commands which rely on a trusted daemon"), false};
|
||||
const command_line::arg_descriptor<bool> arg_allow_mismatched_daemon_version = {"allow-mismatched-daemon-version", sw::tr("Allow communicating with a daemon that uses a different RPC version"), false};
|
||||
const command_line::arg_descriptor<uint64_t> arg_restore_height = {"restore-height", sw::tr("Restore from specific blockchain height"), 0};
|
||||
const command_line::arg_descriptor<bool> arg_do_not_relay = {"do-not-relay", sw::tr("The newly created transaction will not be relayed to the wownero network"), false};
|
||||
@@ -376,21 +377,10 @@ namespace
|
||||
|
||||
boost::optional<std::pair<uint32_t, uint32_t>> parse_subaddress_lookahead(const std::string& str)
|
||||
{
|
||||
auto pos = str.find(":");
|
||||
bool r = pos != std::string::npos;
|
||||
uint32_t major;
|
||||
r = r && epee::string_tools::get_xtype_from_string(major, str.substr(0, pos));
|
||||
uint32_t minor;
|
||||
r = r && epee::string_tools::get_xtype_from_string(minor, str.substr(pos + 1));
|
||||
if (r)
|
||||
{
|
||||
return std::make_pair(major, minor);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto r = tools::parse_subaddress_lookahead(str);
|
||||
if (!r)
|
||||
fail_msg_writer() << tr("invalid format for subaddress lookahead; must be <major>:<minor>");
|
||||
return {};
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void handle_transfer_exception(const std::exception_ptr &e, bool trusted_daemon)
|
||||
@@ -1060,7 +1050,7 @@ bool simple_wallet::import_multisig(const std::vector<std::string> &args)
|
||||
fail_msg_writer() << tr("Failed to import multisig info: ") << e.what();
|
||||
return true;
|
||||
}
|
||||
if (m_trusted_daemon)
|
||||
if (is_daemon_trusted())
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -1212,7 +1202,7 @@ bool simple_wallet::submit_multisig(const std::vector<std::string> &args)
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
handle_transfer_exception(std::current_exception(), m_trusted_daemon);
|
||||
handle_transfer_exception(std::current_exception(), is_daemon_trusted());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
@@ -1989,7 +1979,7 @@ simple_wallet::simple_wallet()
|
||||
tr("Stop mining in the daemon."));
|
||||
m_cmd_binder.set_handler("set_daemon",
|
||||
boost::bind(&simple_wallet::set_daemon, this, _1),
|
||||
tr("set_daemon <host>[:<port>]"),
|
||||
tr("set_daemon <host>[:<port>] [trusted|untrusted]"),
|
||||
tr("Set another daemon to connect to."));
|
||||
m_cmd_binder.set_handler("save_bc",
|
||||
boost::bind(&simple_wallet::save_bc, this, _1),
|
||||
@@ -3078,18 +3068,22 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
|
||||
return false;
|
||||
}
|
||||
|
||||
// set --trusted-daemon if local
|
||||
try
|
||||
{
|
||||
if (tools::is_local_address(m_wallet->get_daemon_address()))
|
||||
{
|
||||
MINFO(tr("Daemon is local, assuming trusted"));
|
||||
m_trusted_daemon = true;
|
||||
}
|
||||
}
|
||||
catch (const std::exception &e) { }
|
||||
|
||||
// set --trusted-daemon if local and not overridden
|
||||
if (!m_trusted_daemon)
|
||||
{
|
||||
try
|
||||
{
|
||||
m_trusted_daemon = false;
|
||||
if (tools::is_local_address(m_wallet->get_daemon_address()))
|
||||
{
|
||||
MINFO(tr("Daemon is local, assuming trusted"));
|
||||
m_trusted_daemon = true;
|
||||
}
|
||||
}
|
||||
catch (const std::exception &e) { }
|
||||
}
|
||||
|
||||
if (!is_daemon_trusted())
|
||||
message_writer() << (boost::format(tr("Warning: using an untrusted daemon at %s, privacy will be lessened")) % m_wallet->get_daemon_address()).str();
|
||||
|
||||
if (m_wallet->get_ring_database().empty())
|
||||
@@ -3123,7 +3117,10 @@ bool simple_wallet::handle_command_line(const boost::program_options::variables_
|
||||
m_restore_deterministic_wallet = command_line::get_arg(vm, arg_restore_deterministic_wallet);
|
||||
m_restore_multisig_wallet = command_line::get_arg(vm, arg_restore_multisig_wallet);
|
||||
m_non_deterministic = command_line::get_arg(vm, arg_non_deterministic);
|
||||
m_trusted_daemon = command_line::get_arg(vm, arg_trusted_daemon);
|
||||
if (!command_line::is_arg_defaulted(vm, arg_trusted_daemon) || !command_line::is_arg_defaulted(vm, arg_untrusted_daemon))
|
||||
m_trusted_daemon = command_line::get_arg(vm, arg_trusted_daemon) && !command_line::get_arg(vm, arg_untrusted_daemon);
|
||||
if (!command_line::is_arg_defaulted(vm, arg_trusted_daemon) && !command_line::is_arg_defaulted(vm, arg_untrusted_daemon))
|
||||
message_writer() << tr("--trusted-daemon and --untrusted-daemon are both seen, assuming untrusted");
|
||||
m_allow_mismatched_daemon_version = command_line::get_arg(vm, arg_allow_mismatched_daemon_version);
|
||||
m_restore_height = command_line::get_arg(vm, arg_restore_height);
|
||||
m_do_not_relay = command_line::get_arg(vm, arg_do_not_relay);
|
||||
@@ -3612,7 +3609,7 @@ bool simple_wallet::save_watch_only(const std::vector<std::string> &args/* = std
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::start_mining(const std::vector<std::string>& args)
|
||||
{
|
||||
if (!m_trusted_daemon)
|
||||
if (!is_daemon_trusted())
|
||||
{
|
||||
fail_msg_writer() << tr("this command requires a trusted daemon. Enable with --trusted-daemon");
|
||||
return true;
|
||||
@@ -3723,6 +3720,33 @@ bool simple_wallet::set_daemon(const std::vector<std::string>& args)
|
||||
}
|
||||
LOCK_IDLE_SCOPE();
|
||||
m_wallet->init(daemon_url);
|
||||
|
||||
if (args.size() == 2)
|
||||
{
|
||||
if (args[1] == "trusted")
|
||||
m_trusted_daemon = true;
|
||||
else if (args[1] == "untrusted")
|
||||
m_trusted_daemon = false;
|
||||
else
|
||||
{
|
||||
fail_msg_writer() << tr("Expected trusted or untrusted, got ") << args[1] << ": assuming untrusted";
|
||||
m_trusted_daemon = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_trusted_daemon = false;
|
||||
try
|
||||
{
|
||||
if (tools::is_local_address(m_wallet->get_daemon_address()))
|
||||
{
|
||||
MINFO(tr("Daemon is local, assuming trusted"));
|
||||
m_trusted_daemon = true;
|
||||
}
|
||||
}
|
||||
catch (const std::exception &e) { }
|
||||
}
|
||||
success_msg_writer() << boost::format("Daemon set to %s, %s") % daemon_url % (*m_trusted_daemon ? tr("trusted") : tr("untrusted"));
|
||||
} else {
|
||||
fail_msg_writer() << tr("This does not seem to be a valid daemon URL.");
|
||||
}
|
||||
@@ -4084,12 +4108,7 @@ uint64_t simple_wallet::get_daemon_blockchain_height(std::string& err)
|
||||
{
|
||||
throw std::runtime_error("simple_wallet null wallet");
|
||||
}
|
||||
|
||||
COMMAND_RPC_GET_HEIGHT::request req;
|
||||
COMMAND_RPC_GET_HEIGHT::response res = boost::value_initialized<COMMAND_RPC_GET_HEIGHT::response>();
|
||||
bool r = m_wallet->invoke_http_json("/getheight", req, res);
|
||||
err = interpret_rpc_response(r, res.status);
|
||||
return res.height;
|
||||
return m_wallet->get_daemon_blockchain_height(err);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::show_blockchain_height(const std::vector<std::string>& args)
|
||||
@@ -4108,7 +4127,7 @@ bool simple_wallet::show_blockchain_height(const std::vector<std::string>& args)
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::rescan_spent(const std::vector<std::string> &args)
|
||||
{
|
||||
if (!m_trusted_daemon)
|
||||
if (!is_daemon_trusted())
|
||||
{
|
||||
fail_msg_writer() << tr("this command requires a trusted daemon. Enable with --trusted-daemon");
|
||||
return true;
|
||||
@@ -4439,16 +4458,16 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
|
||||
return true;
|
||||
}
|
||||
unlock_block = bc_height + locked_blocks;
|
||||
ptx_vector = m_wallet->create_transactions_2(dsts, fake_outs_count, unlock_block /* unlock_time */, priority, extra, m_current_subaddress_account, subaddr_indices, m_trusted_daemon);
|
||||
ptx_vector = m_wallet->create_transactions_2(dsts, fake_outs_count, unlock_block /* unlock_time */, priority, extra, m_current_subaddress_account, subaddr_indices, is_daemon_trusted());
|
||||
break;
|
||||
case TransferNew:
|
||||
ptx_vector = m_wallet->create_transactions_2(dsts, fake_outs_count, 0 /* unlock_time */, priority, extra, m_current_subaddress_account, subaddr_indices, m_trusted_daemon);
|
||||
ptx_vector = m_wallet->create_transactions_2(dsts, fake_outs_count, 0 /* unlock_time */, priority, extra, m_current_subaddress_account, subaddr_indices, is_daemon_trusted());
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Unknown transfer method, using original");
|
||||
/* FALLTHRU */
|
||||
case TransferOriginal:
|
||||
ptx_vector = m_wallet->create_transactions(dsts, fake_outs_count, 0 /* unlock_time */, priority, extra, m_trusted_daemon);
|
||||
ptx_vector = m_wallet->create_transactions(dsts, fake_outs_count, 0 /* unlock_time */, priority, extra, is_daemon_trusted());
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -4607,7 +4626,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
handle_transfer_exception(std::current_exception(), m_trusted_daemon);
|
||||
handle_transfer_exception(std::current_exception(), is_daemon_trusted());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
@@ -4644,7 +4663,7 @@ bool simple_wallet::sweep_unmixable(const std::vector<std::string> &args_)
|
||||
try
|
||||
{
|
||||
// figure out what tx will be necessary
|
||||
auto ptx_vector = m_wallet->create_unmixable_sweep_transactions(m_trusted_daemon);
|
||||
auto ptx_vector = m_wallet->create_unmixable_sweep_transactions(is_daemon_trusted());
|
||||
|
||||
if (ptx_vector.empty())
|
||||
{
|
||||
@@ -4713,9 +4732,23 @@ bool simple_wallet::sweep_unmixable(const std::vector<std::string> &args_)
|
||||
commit_or_save(ptx_vector, m_do_not_relay);
|
||||
}
|
||||
}
|
||||
catch (const tools::error::not_enough_unlocked_money& e)
|
||||
{
|
||||
fail_msg_writer() << tr("Not enough money in unlocked balance");
|
||||
std::string accepted = input_line((boost::format(tr("Discarding %s of unmixable outputs that cannot be spent, which can be undone by \"rescan_spent\". Is this okay? (Y/Yes/N/No): ")) % print_money(e.available())).str());
|
||||
if (std::cin.eof())
|
||||
return true;
|
||||
if (command_line::is_yes(accepted))
|
||||
{
|
||||
try
|
||||
{
|
||||
m_wallet->discard_unmixable_outputs(is_daemon_trusted());
|
||||
} catch (...) {}
|
||||
}
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
handle_transfer_exception(std::current_exception(), m_trusted_daemon);
|
||||
handle_transfer_exception(std::current_exception(), is_daemon_trusted());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
@@ -4846,7 +4879,7 @@ bool simple_wallet::sweep_main(uint64_t below, const std::vector<std::string> &a
|
||||
try
|
||||
{
|
||||
// figure out what tx will be necessary
|
||||
auto ptx_vector = m_wallet->create_transactions_all(below, info.address, info.is_subaddress, fake_outs_count, 0 /* unlock_time */, priority, extra, m_current_subaddress_account, subaddr_indices, m_trusted_daemon);
|
||||
auto ptx_vector = m_wallet->create_transactions_all(below, info.address, info.is_subaddress, fake_outs_count, 0 /* unlock_time */, priority, extra, m_current_subaddress_account, subaddr_indices, is_daemon_trusted());
|
||||
|
||||
if (ptx_vector.empty())
|
||||
{
|
||||
@@ -4930,7 +4963,7 @@ bool simple_wallet::sweep_main(uint64_t below, const std::vector<std::string> &a
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
handle_transfer_exception(std::current_exception(), m_trusted_daemon);
|
||||
handle_transfer_exception(std::current_exception(), is_daemon_trusted());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
@@ -5045,7 +5078,7 @@ bool simple_wallet::sweep_single(const std::vector<std::string> &args_)
|
||||
try
|
||||
{
|
||||
// figure out what tx will be necessary
|
||||
auto ptx_vector = m_wallet->create_transactions_single(ki, info.address, info.is_subaddress, fake_outs_count, 0 /* unlock_time */, priority, extra, m_trusted_daemon);
|
||||
auto ptx_vector = m_wallet->create_transactions_single(ki, info.address, info.is_subaddress, fake_outs_count, 0 /* unlock_time */, priority, extra, is_daemon_trusted());
|
||||
|
||||
if (ptx_vector.empty())
|
||||
{
|
||||
@@ -5115,7 +5148,7 @@ bool simple_wallet::sweep_single(const std::vector<std::string> &args_)
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
handle_transfer_exception(std::current_exception(), m_trusted_daemon);
|
||||
handle_transfer_exception(std::current_exception(), is_daemon_trusted());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
@@ -5420,7 +5453,7 @@ bool simple_wallet::submit_transfer(const std::vector<std::string> &args_)
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
handle_transfer_exception(std::current_exception(), m_trusted_daemon);
|
||||
handle_transfer_exception(std::current_exception(), is_daemon_trusted());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
@@ -7008,7 +7041,7 @@ bool simple_wallet::import_key_images(const std::vector<std::string> &args)
|
||||
fail_msg_writer() << tr("command not supported by HW wallet");
|
||||
return true;
|
||||
}
|
||||
if (!m_trusted_daemon)
|
||||
if (!is_daemon_trusted())
|
||||
{
|
||||
fail_msg_writer() << tr("this command requires a trusted daemon. Enable with --trusted-daemon");
|
||||
return true;
|
||||
@@ -7394,6 +7427,7 @@ int main(int argc, char* argv[])
|
||||
command_line::add_arg(desc_params, arg_non_deterministic );
|
||||
command_line::add_arg(desc_params, arg_electrum_seed );
|
||||
command_line::add_arg(desc_params, arg_trusted_daemon);
|
||||
command_line::add_arg(desc_params, arg_untrusted_daemon);
|
||||
command_line::add_arg(desc_params, arg_allow_mismatched_daemon_version);
|
||||
command_line::add_arg(desc_params, arg_restore_height);
|
||||
command_line::add_arg(desc_params, arg_do_not_relay);
|
||||
|
||||
@@ -228,6 +228,7 @@ namespace cryptonote
|
||||
bool print_ring_members(const std::vector<tools::wallet2::pending_tx>& ptx_vector, std::ostream& ostr);
|
||||
std::string get_prompt() const;
|
||||
bool print_seed(bool encrypted);
|
||||
bool is_daemon_trusted() const { return *m_trusted_daemon; }
|
||||
|
||||
/*!
|
||||
* \brief Prints the seed with a nice message
|
||||
@@ -330,7 +331,7 @@ namespace cryptonote
|
||||
bool m_restore_deterministic_wallet; // recover flag
|
||||
bool m_restore_multisig_wallet; // recover flag
|
||||
bool m_non_deterministic; // old 2-random generation
|
||||
bool m_trusted_daemon;
|
||||
boost::optional<bool> m_trusted_daemon;
|
||||
bool m_allow_mismatched_daemon_version;
|
||||
bool m_restoring; // are we restoring, by whatever method?
|
||||
uint64_t m_restore_height; // optional
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#define DEF_MONERO_VERSION_TAG "@VERSIONTAG@"
|
||||
#define DEF_MONERO_VERSION "0.2.1.0-master"
|
||||
#define DEF_MONERO_VERSION "0.2.2.0-master"
|
||||
#define DEF_MONERO_RELEASE_NAME "Busty Brazzers"
|
||||
#define DEF_MONERO_VERSION_FULL DEF_MONERO_VERSION "-" DEF_MONERO_VERSION_TAG
|
||||
|
||||
|
||||
@@ -85,7 +85,6 @@ monero_add_executable(wallet_rpc_server
|
||||
target_link_libraries(wallet_rpc_server
|
||||
PRIVATE
|
||||
wallet
|
||||
epee
|
||||
rpc_base
|
||||
cryptonote_core
|
||||
cncrypto
|
||||
|
||||
@@ -60,7 +60,6 @@ namespace Monero {
|
||||
|
||||
namespace {
|
||||
// copy-pasted from simplewallet
|
||||
static const size_t DEFAULT_MIXIN = 9;
|
||||
static const int DEFAULT_REFRESH_INTERVAL_MILLIS = 1000 * 10;
|
||||
// limit maximum refresh interval as one minute
|
||||
static const int MAX_REFRESH_INTERVAL_MILLIS = 1000 * 60 * 1;
|
||||
@@ -1406,15 +1405,6 @@ void WalletImpl::setListener(WalletListener *l)
|
||||
m_wallet2Callback->setListener(l);
|
||||
}
|
||||
|
||||
uint32_t WalletImpl::defaultMixin() const
|
||||
{
|
||||
return m_wallet->default_mixin();
|
||||
}
|
||||
|
||||
void WalletImpl::setDefaultMixin(uint32_t arg)
|
||||
{
|
||||
m_wallet->default_mixin(arg);
|
||||
}
|
||||
|
||||
bool WalletImpl::setUserNote(const std::string &txid, const std::string ¬e)
|
||||
{
|
||||
@@ -1750,7 +1740,7 @@ void WalletImpl::refreshThreadFunc()
|
||||
// if auto refresh enabled, we wait for the "m_refreshIntervalSeconds" interval.
|
||||
// if not - we wait forever
|
||||
if (m_refreshIntervalMillis > 0) {
|
||||
boost::posix_time::milliseconds wait_for_ms(m_refreshIntervalMillis);
|
||||
boost::posix_time::milliseconds wait_for_ms(m_refreshIntervalMillis.load());
|
||||
m_refreshCV.timed_wait(lock, wait_for_ms);
|
||||
} else {
|
||||
m_refreshCV.wait(lock);
|
||||
|
||||
@@ -143,8 +143,6 @@ public:
|
||||
virtual Subaddress * subaddress();
|
||||
virtual SubaddressAccount * subaddressAccount();
|
||||
virtual void setListener(WalletListener * l);
|
||||
virtual uint32_t defaultMixin() const;
|
||||
virtual void setDefaultMixin(uint32_t arg);
|
||||
virtual bool setUserNote(const std::string &txid, const std::string ¬e);
|
||||
virtual std::string getUserNote(const std::string &txid) const;
|
||||
virtual std::string getTxKey(const std::string &txid) const;
|
||||
|
||||
@@ -696,16 +696,6 @@ struct Wallet
|
||||
virtual Subaddress * subaddress() = 0;
|
||||
virtual SubaddressAccount * subaddressAccount() = 0;
|
||||
virtual void setListener(WalletListener *) = 0;
|
||||
/*!
|
||||
* \brief defaultMixin - returns number of mixins used in transactions
|
||||
* \return
|
||||
*/
|
||||
virtual uint32_t defaultMixin() const = 0;
|
||||
/*!
|
||||
* \brief setDefaultMixin - setum number of mixins to be used for new transactions
|
||||
* \param arg
|
||||
*/
|
||||
virtual void setDefaultMixin(uint32_t arg) = 0;
|
||||
|
||||
/*!
|
||||
* \brief setUserNote - attach an arbitrary string note to a txid
|
||||
|
||||
@@ -41,21 +41,13 @@ static const std::chrono::seconds rpc_timeout = std::chrono::minutes(3) + std::c
|
||||
NodeRPCProxy::NodeRPCProxy(epee::net_utils::http::http_simple_client &http_client, boost::mutex &mutex)
|
||||
: m_http_client(http_client)
|
||||
, m_daemon_rpc_mutex(mutex)
|
||||
, m_height(0)
|
||||
, m_height_time(0)
|
||||
, m_earliest_height()
|
||||
, m_dynamic_per_kb_fee_estimate(0)
|
||||
, m_dynamic_per_kb_fee_estimate_cached_height(0)
|
||||
, m_dynamic_per_kb_fee_estimate_grace_blocks(0)
|
||||
, m_rpc_version(0)
|
||||
, m_target_height(0)
|
||||
, m_target_height_time(0)
|
||||
{}
|
||||
{
|
||||
invalidate();
|
||||
}
|
||||
|
||||
void NodeRPCProxy::invalidate()
|
||||
{
|
||||
m_height = 0;
|
||||
m_height_time = 0;
|
||||
for (size_t n = 0; n < 256; ++n)
|
||||
m_earliest_height[n] = 0;
|
||||
m_dynamic_per_kb_fee_estimate = 0;
|
||||
@@ -63,7 +55,8 @@ void NodeRPCProxy::invalidate()
|
||||
m_dynamic_per_kb_fee_estimate_grace_blocks = 0;
|
||||
m_rpc_version = 0;
|
||||
m_target_height = 0;
|
||||
m_target_height_time = 0;
|
||||
m_block_size_limit = 0;
|
||||
m_get_info_time = 0;
|
||||
}
|
||||
|
||||
boost::optional<std::string> NodeRPCProxy::get_rpc_version(uint32_t &rpc_version) const
|
||||
@@ -84,36 +77,15 @@ boost::optional<std::string> NodeRPCProxy::get_rpc_version(uint32_t &rpc_version
|
||||
return boost::optional<std::string>();
|
||||
}
|
||||
|
||||
boost::optional<std::string> NodeRPCProxy::get_height(uint64_t &height) const
|
||||
{
|
||||
const time_t now = time(NULL);
|
||||
if (m_height == 0 || now >= m_height_time + 30) // re-cache every 30 seconds
|
||||
{
|
||||
cryptonote::COMMAND_RPC_GET_HEIGHT::request req = AUTO_VAL_INIT(req);
|
||||
cryptonote::COMMAND_RPC_GET_HEIGHT::response res = AUTO_VAL_INIT(res);
|
||||
|
||||
m_daemon_rpc_mutex.lock();
|
||||
bool r = net_utils::invoke_http_json("/getheight", req, res, m_http_client, rpc_timeout);
|
||||
m_daemon_rpc_mutex.unlock();
|
||||
CHECK_AND_ASSERT_MES(r, std::string(), "Failed to connect to daemon");
|
||||
CHECK_AND_ASSERT_MES(res.status != CORE_RPC_STATUS_BUSY, res.status, "Failed to connect to daemon");
|
||||
CHECK_AND_ASSERT_MES(res.status == CORE_RPC_STATUS_OK, res.status, "Failed to get current blockchain height");
|
||||
m_height = res.height;
|
||||
m_height_time = now;
|
||||
}
|
||||
height = m_height;
|
||||
return boost::optional<std::string>();
|
||||
}
|
||||
|
||||
void NodeRPCProxy::set_height(uint64_t h)
|
||||
{
|
||||
m_height = h;
|
||||
}
|
||||
|
||||
boost::optional<std::string> NodeRPCProxy::get_target_height(uint64_t &height) const
|
||||
boost::optional<std::string> NodeRPCProxy::get_info() const
|
||||
{
|
||||
const time_t now = time(NULL);
|
||||
if (m_target_height == 0 || now >= m_target_height_time + 30) // re-cache every 30 seconds
|
||||
if (now >= m_get_info_time + 30) // re-cache every 30 seconds
|
||||
{
|
||||
cryptonote::COMMAND_RPC_GET_INFO::request req_t = AUTO_VAL_INIT(req_t);
|
||||
cryptonote::COMMAND_RPC_GET_INFO::response resp_t = AUTO_VAL_INIT(resp_t);
|
||||
@@ -125,13 +97,41 @@ boost::optional<std::string> NodeRPCProxy::get_target_height(uint64_t &height) c
|
||||
CHECK_AND_ASSERT_MES(r, std::string(), "Failed to connect to daemon");
|
||||
CHECK_AND_ASSERT_MES(resp_t.status != CORE_RPC_STATUS_BUSY, resp_t.status, "Failed to connect to daemon");
|
||||
CHECK_AND_ASSERT_MES(resp_t.status == CORE_RPC_STATUS_OK, resp_t.status, "Failed to get target blockchain height");
|
||||
m_height = resp_t.height;
|
||||
m_target_height = resp_t.target_height;
|
||||
m_target_height_time = now;
|
||||
m_block_size_limit = resp_t.block_size_limit;
|
||||
m_get_info_time = now;
|
||||
}
|
||||
return boost::optional<std::string>();
|
||||
}
|
||||
|
||||
boost::optional<std::string> NodeRPCProxy::get_height(uint64_t &height) const
|
||||
{
|
||||
auto res = get_info();
|
||||
if (res)
|
||||
return res;
|
||||
height = m_height;
|
||||
return boost::optional<std::string>();
|
||||
}
|
||||
|
||||
boost::optional<std::string> NodeRPCProxy::get_target_height(uint64_t &height) const
|
||||
{
|
||||
auto res = get_info();
|
||||
if (res)
|
||||
return res;
|
||||
height = m_target_height;
|
||||
return boost::optional<std::string>();
|
||||
}
|
||||
|
||||
boost::optional<std::string> NodeRPCProxy::get_block_size_limit(uint64_t &block_size_limit) const
|
||||
{
|
||||
auto res = get_info();
|
||||
if (res)
|
||||
return res;
|
||||
block_size_limit = m_block_size_limit;
|
||||
return boost::optional<std::string>();
|
||||
}
|
||||
|
||||
boost::optional<std::string> NodeRPCProxy::get_earliest_height(uint8_t version, uint64_t &earliest_height) const
|
||||
{
|
||||
if (m_earliest_height[version] == 0)
|
||||
|
||||
@@ -47,22 +47,25 @@ public:
|
||||
boost::optional<std::string> get_height(uint64_t &height) const;
|
||||
void set_height(uint64_t h);
|
||||
boost::optional<std::string> get_target_height(uint64_t &height) const;
|
||||
boost::optional<std::string> get_block_size_limit(uint64_t &block_size_limit) const;
|
||||
boost::optional<std::string> get_earliest_height(uint8_t version, uint64_t &earliest_height) const;
|
||||
boost::optional<std::string> get_dynamic_per_kb_fee_estimate(uint64_t grace_blocks, uint64_t &fee) const;
|
||||
|
||||
private:
|
||||
boost::optional<std::string> get_info() const;
|
||||
|
||||
epee::net_utils::http::http_simple_client &m_http_client;
|
||||
boost::mutex &m_daemon_rpc_mutex;
|
||||
|
||||
mutable uint64_t m_height;
|
||||
mutable time_t m_height_time;
|
||||
mutable uint64_t m_earliest_height[256];
|
||||
mutable uint64_t m_dynamic_per_kb_fee_estimate;
|
||||
mutable uint64_t m_dynamic_per_kb_fee_estimate_cached_height;
|
||||
mutable uint64_t m_dynamic_per_kb_fee_estimate_grace_blocks;
|
||||
mutable uint32_t m_rpc_version;
|
||||
mutable uint64_t m_target_height;
|
||||
mutable time_t m_target_height_time;
|
||||
mutable uint64_t m_block_size_limit;
|
||||
mutable time_t m_get_info_time;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -938,6 +938,7 @@ void wallet2::expand_subaddresses(const cryptonote::subaddress_index& index)
|
||||
}
|
||||
m_subaddress_labels.resize(index.major + 1, {"Untitled account"});
|
||||
m_subaddress_labels[index.major].resize(index.minor + 1);
|
||||
get_account_tags();
|
||||
}
|
||||
else if (m_subaddress_labels[index.major].size() <= index.minor)
|
||||
{
|
||||
@@ -1027,6 +1028,16 @@ void wallet2::check_acc_out_precomp(const tx_out &o, const crypto::key_derivatio
|
||||
tx_scan_info.error = false;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::check_acc_out_precomp_once(const tx_out &o, const crypto::key_derivation &derivation, const std::vector<crypto::key_derivation> &additional_derivations, size_t i, tx_scan_info_t &tx_scan_info, bool &already_seen) const
|
||||
{
|
||||
tx_scan_info.received = boost::none;
|
||||
if (already_seen)
|
||||
return;
|
||||
check_acc_out_precomp(o, derivation, additional_derivations, i, tx_scan_info);
|
||||
if (tx_scan_info.received)
|
||||
already_seen = true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
static uint64_t decodeRct(const rct::rctSig & rv, const crypto::key_derivation &derivation, unsigned int i, rct::key & mask, hw::device &hwdev)
|
||||
{
|
||||
crypto::secret_key scalar1;
|
||||
@@ -1107,7 +1118,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
|
||||
// Don't try to extract tx public key if tx has no ouputs
|
||||
size_t pk_index = 0;
|
||||
std::vector<tx_scan_info_t> tx_scan_info(tx.vout.size());
|
||||
std::unordered_set<crypto::public_key> public_keys_seen;
|
||||
std::deque<bool> output_found(tx.vout.size(), false);
|
||||
while (!tx.vout.empty())
|
||||
{
|
||||
// if tx.vout is not empty, we loop through all tx pubkeys
|
||||
@@ -1123,13 +1134,6 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
|
||||
break;
|
||||
}
|
||||
|
||||
if (public_keys_seen.find(pub_key_field.pub_key) != public_keys_seen.end())
|
||||
{
|
||||
MWARNING("The same transaction pubkey is present more than once, ignoring extra instance");
|
||||
continue;
|
||||
}
|
||||
public_keys_seen.insert(pub_key_field.pub_key);
|
||||
|
||||
int num_vouts_received = 0;
|
||||
tx_pub_key = pub_key_field.pub_key;
|
||||
tools::threadpool& tpool = tools::threadpool::getInstance();
|
||||
@@ -1169,7 +1173,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
|
||||
}
|
||||
else if (miner_tx && m_refresh_type == RefreshOptimizeCoinbase)
|
||||
{
|
||||
check_acc_out_precomp(tx.vout[0], derivation, additional_derivations, 0, tx_scan_info[0]);
|
||||
check_acc_out_precomp_once(tx.vout[0], derivation, additional_derivations, 0, tx_scan_info[0], output_found[0]);
|
||||
THROW_WALLET_EXCEPTION_IF(tx_scan_info[0].error, error::acc_outs_lookup_error, tx, tx_pub_key, m_account.get_keys());
|
||||
|
||||
// this assumes that the miner tx pays a single address
|
||||
@@ -1179,8 +1183,8 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
|
||||
// the first one was already checked
|
||||
for (size_t i = 1; i < tx.vout.size(); ++i)
|
||||
{
|
||||
tpool.submit(&waiter, boost::bind(&wallet2::check_acc_out_precomp, this, std::cref(tx.vout[i]), std::cref(derivation), std::cref(additional_derivations), i,
|
||||
std::ref(tx_scan_info[i])));
|
||||
tpool.submit(&waiter, boost::bind(&wallet2::check_acc_out_precomp_once, this, std::cref(tx.vout[i]), std::cref(derivation), std::cref(additional_derivations), i,
|
||||
std::ref(tx_scan_info[i]), std::ref(output_found[i])));
|
||||
}
|
||||
waiter.wait();
|
||||
// then scan all outputs from 0
|
||||
@@ -1202,8 +1206,8 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
|
||||
{
|
||||
for (size_t i = 0; i < tx.vout.size(); ++i)
|
||||
{
|
||||
tpool.submit(&waiter, boost::bind(&wallet2::check_acc_out_precomp, this, std::cref(tx.vout[i]), std::cref(derivation), std::cref(additional_derivations), i,
|
||||
std::ref(tx_scan_info[i])));
|
||||
tpool.submit(&waiter, boost::bind(&wallet2::check_acc_out_precomp_once, this, std::cref(tx.vout[i]), std::cref(derivation), std::cref(additional_derivations), i,
|
||||
std::ref(tx_scan_info[i]), std::ref(output_found[i])));
|
||||
}
|
||||
waiter.wait();
|
||||
|
||||
@@ -1224,7 +1228,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
|
||||
{
|
||||
for (size_t i = 0; i < tx.vout.size(); ++i)
|
||||
{
|
||||
check_acc_out_precomp(tx.vout[i], derivation, additional_derivations, i, tx_scan_info[i]);
|
||||
check_acc_out_precomp_once(tx.vout[i], derivation, additional_derivations, i, tx_scan_info[i], output_found[i]);
|
||||
THROW_WALLET_EXCEPTION_IF(tx_scan_info[i].error, error::acc_outs_lookup_error, tx, tx_pub_key, m_account.get_keys());
|
||||
if (tx_scan_info[i].received)
|
||||
{
|
||||
@@ -1308,20 +1312,20 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
|
||||
m_callback->on_money_received(height, txid, tx, td.m_amount, td.m_subaddr_index);
|
||||
}
|
||||
}
|
||||
else if (m_transfers[kit->second].m_spent || m_transfers[kit->second].amount() >= tx.vout[o].amount)
|
||||
else if (m_transfers[kit->second].m_spent || m_transfers[kit->second].amount() >= tx_scan_info[o].amount)
|
||||
{
|
||||
LOG_ERROR("Public key " << epee::string_tools::pod_to_hex(kit->first)
|
||||
<< " from received " << print_money(tx.vout[o].amount) << " output already exists with "
|
||||
<< " from received " << print_money(tx_scan_info[o].amount) << " output already exists with "
|
||||
<< (m_transfers[kit->second].m_spent ? "spent" : "unspent") << " "
|
||||
<< print_money(m_transfers[kit->second].amount()) << ", received output ignored");
|
||||
<< print_money(m_transfers[kit->second].amount()) << " in tx " << m_transfers[kit->second].m_txid << ", received output ignored");
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR("Public key " << epee::string_tools::pod_to_hex(kit->first)
|
||||
<< " from received " << print_money(tx.vout[o].amount) << " output already exists with "
|
||||
<< " from received " << print_money(tx_scan_info[o].amount) << " output already exists with "
|
||||
<< print_money(m_transfers[kit->second].amount()) << ", replacing with new output");
|
||||
// The new larger output replaced a previous smaller one
|
||||
tx_money_got_in_outs[tx_scan_info[o].received->index] -= tx.vout[o].amount;
|
||||
tx_money_got_in_outs[tx_scan_info[o].received->index] -= tx_scan_info[o].amount;
|
||||
|
||||
if (!pool)
|
||||
{
|
||||
@@ -3257,6 +3261,12 @@ void wallet2::restore(const std::string& wallet_, const epee::wipeable_string& p
|
||||
cryptonote::block b;
|
||||
generate_genesis(b);
|
||||
m_blockchain.push_back(get_block_hash(b));
|
||||
if (m_subaddress_lookahead_major == SUBADDRESS_LOOKAHEAD_MAJOR && m_subaddress_lookahead_minor == SUBADDRESS_LOOKAHEAD_MINOR)
|
||||
{
|
||||
// the default lookahead setting (50:200) is clearly too much for hardware wallet
|
||||
m_subaddress_lookahead_major = 5;
|
||||
m_subaddress_lookahead_minor = 20;
|
||||
}
|
||||
add_subaddress_account(tr("Primary account"));
|
||||
if (!wallet_.empty()) {
|
||||
store();
|
||||
@@ -3769,7 +3779,7 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
|
||||
{
|
||||
wallet2::cache_file_data cache_file_data;
|
||||
std::string buf;
|
||||
bool r = epee::file_io_utils::load_file_to_string(m_wallet_file, buf);
|
||||
bool r = epee::file_io_utils::load_file_to_string(m_wallet_file, buf, std::numeric_limits<size_t>::max());
|
||||
THROW_WALLET_EXCEPTION_IF(!r, error::file_read_error, m_wallet_file);
|
||||
|
||||
// try to read it as an encrypted cache
|
||||
@@ -5346,15 +5356,10 @@ uint32_t wallet2::adjust_priority(uint32_t priority)
|
||||
}
|
||||
|
||||
// get the current full reward zone
|
||||
cryptonote::COMMAND_RPC_GET_INFO::request getinfo_req = AUTO_VAL_INIT(getinfo_req);
|
||||
cryptonote::COMMAND_RPC_GET_INFO::response getinfo_res = AUTO_VAL_INIT(getinfo_res);
|
||||
m_daemon_rpc_mutex.lock();
|
||||
bool r = net_utils::invoke_http_json_rpc("/json_rpc", "get_info", getinfo_req, getinfo_res, m_http_client);
|
||||
m_daemon_rpc_mutex.unlock();
|
||||
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "get_info");
|
||||
THROW_WALLET_EXCEPTION_IF(getinfo_res.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "get_info");
|
||||
THROW_WALLET_EXCEPTION_IF(getinfo_res.status != CORE_RPC_STATUS_OK, error::get_tx_pool_error);
|
||||
const uint64_t full_reward_zone = getinfo_res.block_size_limit / 2;
|
||||
uint64_t block_size_limit = 0;
|
||||
const auto result = m_node_rpc_proxy.get_block_size_limit(block_size_limit);
|
||||
throw_on_rpc_response_error(result, "get_info");
|
||||
const uint64_t full_reward_zone = block_size_limit / 2;
|
||||
|
||||
// get the last N block headers and sum the block sizes
|
||||
const size_t N = 10;
|
||||
@@ -5368,7 +5373,7 @@ uint32_t wallet2::adjust_priority(uint32_t priority)
|
||||
m_daemon_rpc_mutex.lock();
|
||||
getbh_req.start_height = m_blockchain.size() - N;
|
||||
getbh_req.end_height = m_blockchain.size() - 1;
|
||||
r = net_utils::invoke_http_json_rpc("/json_rpc", "getblockheadersrange", getbh_req, getbh_res, m_http_client, rpc_timeout);
|
||||
bool r = net_utils::invoke_http_json_rpc("/json_rpc", "getblockheadersrange", getbh_req, getbh_res, m_http_client, rpc_timeout);
|
||||
m_daemon_rpc_mutex.unlock();
|
||||
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "getblockheadersrange");
|
||||
THROW_WALLET_EXCEPTION_IF(getbh_res.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "getblockheadersrange");
|
||||
@@ -8238,6 +8243,16 @@ std::vector<wallet2::pending_tx> wallet2::create_unmixable_sweep_transactions(bo
|
||||
|
||||
return create_transactions_from(m_account_public_address, false, unmixable_transfer_outputs, unmixable_dust_outputs, 0 /*fake_outs_count */, 0 /* unlock_time */, 1 /*priority */, std::vector<uint8_t>(), trusted_daemon);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::discard_unmixable_outputs(bool trusted_daemon)
|
||||
{
|
||||
// may throw
|
||||
std::vector<size_t> unmixable_outputs = select_available_unmixable_outputs(trusted_daemon);
|
||||
for (size_t idx : unmixable_outputs)
|
||||
{
|
||||
m_transfers[idx].m_spent = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool wallet2::get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys) const
|
||||
{
|
||||
@@ -9112,39 +9127,23 @@ uint64_t wallet2::get_daemon_blockchain_height(string &err) const
|
||||
|
||||
uint64_t wallet2::get_daemon_blockchain_target_height(string &err)
|
||||
{
|
||||
cryptonote::COMMAND_RPC_GET_INFO::request req_t = AUTO_VAL_INIT(req_t);
|
||||
cryptonote::COMMAND_RPC_GET_INFO::response resp_t = AUTO_VAL_INIT(resp_t);
|
||||
m_daemon_rpc_mutex.lock();
|
||||
bool ok = net_utils::invoke_http_json_rpc("/json_rpc", "get_info", req_t, resp_t, m_http_client);
|
||||
m_daemon_rpc_mutex.unlock();
|
||||
if (ok)
|
||||
err = "";
|
||||
uint64_t target_height = 0;
|
||||
const auto result = m_node_rpc_proxy.get_target_height(target_height);
|
||||
if (result && *result != CORE_RPC_STATUS_OK)
|
||||
{
|
||||
if (resp_t.status == CORE_RPC_STATUS_BUSY)
|
||||
{
|
||||
err = "daemon is busy. Please try again later.";
|
||||
}
|
||||
else if (resp_t.status != CORE_RPC_STATUS_OK)
|
||||
{
|
||||
err = resp_t.status;
|
||||
}
|
||||
else // success, cleaning up error message
|
||||
{
|
||||
err = "";
|
||||
}
|
||||
err= *result;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
err = "possibly lost connection to daemon";
|
||||
}
|
||||
return resp_t.target_height;
|
||||
return target_height;
|
||||
}
|
||||
|
||||
uint64_t wallet2::get_approximate_blockchain_height() const
|
||||
{
|
||||
// time of v8 fork
|
||||
const time_t fork_time = m_nettype == TESTNET ? 1529020649 : 1524622167;
|
||||
const time_t fork_time = m_nettype == TESTNET ? 1532756009 : m_nettype == STAGENET ? 1530635153 : 1524622167;
|
||||
// v8 fork block
|
||||
const uint64_t fork_block = m_nettype == TESTNET ? 10 : 6969;
|
||||
const uint64_t fork_block = m_nettype == TESTNET ? 10 : m_nettype == STAGENET ? 10 : 6969;
|
||||
// avg seconds per block
|
||||
const int seconds_per_block = DIFFICULTY_TARGET_V2;
|
||||
// Calculated blockchain height
|
||||
@@ -9516,7 +9515,7 @@ uint64_t wallet2::import_key_images(const std::vector<std::pair<crypto::key_imag
|
||||
std::unordered_set<crypto::hash> spent_txids; // For each spent key image, search for a tx in m_transfers that uses it as input.
|
||||
std::vector<size_t> swept_transfers; // If such a spending tx wasn't found in m_transfers, this means the spending tx
|
||||
// was created by sweep_all, so we can't know the spent height and other detailed info.
|
||||
for(size_t i = 0; i < m_transfers.size(); ++i)
|
||||
for(size_t i = 0; i < signed_key_images.size(); ++i)
|
||||
{
|
||||
transfer_details &td = m_transfers[i];
|
||||
uint64_t amount = td.amount();
|
||||
@@ -10378,15 +10377,10 @@ std::vector<std::pair<uint64_t, uint64_t>> wallet2::estimate_backlog(const std::
|
||||
THROW_WALLET_EXCEPTION_IF(res.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "get_txpool_backlog");
|
||||
THROW_WALLET_EXCEPTION_IF(res.status != CORE_RPC_STATUS_OK, error::get_tx_pool_error);
|
||||
|
||||
cryptonote::COMMAND_RPC_GET_INFO::request req_t = AUTO_VAL_INIT(req_t);
|
||||
cryptonote::COMMAND_RPC_GET_INFO::response resp_t = AUTO_VAL_INIT(resp_t);
|
||||
m_daemon_rpc_mutex.lock();
|
||||
r = net_utils::invoke_http_json_rpc("/json_rpc", "get_info", req_t, resp_t, m_http_client);
|
||||
m_daemon_rpc_mutex.unlock();
|
||||
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "get_info");
|
||||
THROW_WALLET_EXCEPTION_IF(resp_t.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "get_info");
|
||||
THROW_WALLET_EXCEPTION_IF(resp_t.status != CORE_RPC_STATUS_OK, error::get_tx_pool_error);
|
||||
uint64_t full_reward_zone = resp_t.block_size_limit / 2;
|
||||
uint64_t block_size_limit = 0;
|
||||
const auto result = m_node_rpc_proxy.get_block_size_limit(block_size_limit);
|
||||
throw_on_rpc_response_error(result, "get_info");
|
||||
uint64_t full_reward_zone = block_size_limit / 2;
|
||||
|
||||
std::vector<std::pair<uint64_t, uint64_t>> blocks;
|
||||
for (const auto &fee_level: fee_levels)
|
||||
|
||||
@@ -706,6 +706,7 @@ namespace tools
|
||||
bool sign_multisig_tx(multisig_tx_set &exported_txs, std::vector<crypto::hash> &txids);
|
||||
bool sign_multisig_tx_to_file(multisig_tx_set &exported_txs, const std::string &filename, std::vector<crypto::hash> &txids);
|
||||
std::vector<pending_tx> create_unmixable_sweep_transactions(bool trusted_daemon);
|
||||
void discard_unmixable_outputs(bool trusted_daemon);
|
||||
bool check_connection(uint32_t *version = NULL, uint32_t timeout = 200000);
|
||||
void get_transfers(wallet2::transfer_container& incoming_transfers) const;
|
||||
void get_payments(const crypto::hash& payment_id, std::list<wallet2::payment_details>& payments, uint64_t min_height = 0, const boost::optional<uint32_t>& subaddr_account = boost::none, const std::set<uint32_t>& subaddr_indices = {}) const;
|
||||
@@ -1109,6 +1110,7 @@ namespace tools
|
||||
bool generate_chacha_key_from_secret_keys(crypto::chacha_key &key) const;
|
||||
crypto::hash get_payment_id(const pending_tx &ptx) const;
|
||||
void check_acc_out_precomp(const cryptonote::tx_out &o, const crypto::key_derivation &derivation, const std::vector<crypto::key_derivation> &additional_derivations, size_t i, tx_scan_info_t &tx_scan_info) const;
|
||||
void check_acc_out_precomp_once(const cryptonote::tx_out &o, const crypto::key_derivation &derivation, const std::vector<crypto::key_derivation> &additional_derivations, size_t i, tx_scan_info_t &tx_scan_info, bool &already_seen) const;
|
||||
void parse_block_round(const cryptonote::blobdata &blob, cryptonote::block &bl, crypto::hash &bl_id, bool &error) const;
|
||||
uint64_t get_upper_transaction_size_limit() const;
|
||||
std::vector<uint64_t> get_unspent_amounts_vector() const;
|
||||
|
||||
@@ -179,6 +179,10 @@ namespace wallet_args
|
||||
{
|
||||
mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str());
|
||||
}
|
||||
else if (!log_to_console)
|
||||
{
|
||||
mlog_set_categories("");
|
||||
}
|
||||
|
||||
if (notice)
|
||||
Print(print) << notice << ENDL;
|
||||
|
||||
@@ -362,6 +362,7 @@ namespace tools
|
||||
if (!m_wallet) return not_open(er);
|
||||
try
|
||||
{
|
||||
THROW_WALLET_EXCEPTION_IF(req.account_index >= m_wallet->get_num_subaddress_accounts(), error::account_index_outofbound);
|
||||
res.addresses.clear();
|
||||
std::vector<uint32_t> req_address_index;
|
||||
if (req.address_index.empty())
|
||||
@@ -377,6 +378,7 @@ namespace tools
|
||||
m_wallet->get_transfers(transfers);
|
||||
for (uint32_t i : req_address_index)
|
||||
{
|
||||
THROW_WALLET_EXCEPTION_IF(i >= m_wallet->get_num_subaddresses(req.account_index), error::address_index_outofbound);
|
||||
res.addresses.resize(res.addresses.size() + 1);
|
||||
auto& info = res.addresses.back();
|
||||
const cryptonote::subaddress_index index = {req.account_index, i};
|
||||
@@ -500,6 +502,7 @@ namespace tools
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_get_account_tags(const wallet_rpc::COMMAND_RPC_GET_ACCOUNT_TAGS::request& req, wallet_rpc::COMMAND_RPC_GET_ACCOUNT_TAGS::response& res, epee::json_rpc::error& er)
|
||||
{
|
||||
if (!m_wallet) return not_open(er);
|
||||
const std::pair<std::map<std::string, std::string>, std::vector<std::string>> account_tags = m_wallet->get_account_tags();
|
||||
for (const std::pair<std::string, std::string>& p : account_tags.first)
|
||||
{
|
||||
@@ -518,6 +521,7 @@ namespace tools
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_tag_accounts(const wallet_rpc::COMMAND_RPC_TAG_ACCOUNTS::request& req, wallet_rpc::COMMAND_RPC_TAG_ACCOUNTS::response& res, epee::json_rpc::error& er)
|
||||
{
|
||||
if (!m_wallet) return not_open(er);
|
||||
try
|
||||
{
|
||||
m_wallet->set_account_tag(req.accounts, req.tag);
|
||||
@@ -532,6 +536,7 @@ namespace tools
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_untag_accounts(const wallet_rpc::COMMAND_RPC_UNTAG_ACCOUNTS::request& req, wallet_rpc::COMMAND_RPC_UNTAG_ACCOUNTS::response& res, epee::json_rpc::error& er)
|
||||
{
|
||||
if (!m_wallet) return not_open(er);
|
||||
try
|
||||
{
|
||||
m_wallet->set_account_tag(req.accounts, "");
|
||||
@@ -546,6 +551,7 @@ namespace tools
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_set_account_tag_description(const wallet_rpc::COMMAND_RPC_SET_ACCOUNT_TAG_DESCRIPTION::request& req, wallet_rpc::COMMAND_RPC_SET_ACCOUNT_TAG_DESCRIPTION::response& res, epee::json_rpc::error& er)
|
||||
{
|
||||
if (!m_wallet) return not_open(er);
|
||||
try
|
||||
{
|
||||
m_wallet->set_account_tag_description(req.tag, req.description);
|
||||
@@ -2054,6 +2060,7 @@ namespace tools
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_make_uri(const wallet_rpc::COMMAND_RPC_MAKE_URI::request& req, wallet_rpc::COMMAND_RPC_MAKE_URI::response& res, epee::json_rpc::error& er)
|
||||
{
|
||||
if (!m_wallet) return not_open(er);
|
||||
std::string error;
|
||||
std::string uri = m_wallet->make_uri(req.address, req.payment_id, req.amount, req.tx_description, req.recipient_name, error);
|
||||
if (uri.empty())
|
||||
@@ -2267,6 +2274,7 @@ namespace tools
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_stop_mining(const wallet_rpc::COMMAND_RPC_STOP_MINING::request& req, wallet_rpc::COMMAND_RPC_STOP_MINING::response& res, epee::json_rpc::error& er)
|
||||
{
|
||||
if (!m_wallet) return not_open(er);
|
||||
cryptonote::COMMAND_RPC_STOP_MINING::request daemon_req;
|
||||
cryptonote::COMMAND_RPC_STOP_MINING::response daemon_res;
|
||||
bool r = m_wallet->invoke_http_json("/stop_mining", daemon_req, daemon_res);
|
||||
|
||||
@@ -86,7 +86,6 @@ target_link_libraries(unit_tests
|
||||
wallet
|
||||
p2p
|
||||
version
|
||||
epee
|
||||
${Boost_CHRONO_LIBRARY}
|
||||
${Boost_THREAD_LIBRARY}
|
||||
${GTEST_LIBRARIES}
|
||||
|
||||
@@ -122,6 +122,7 @@ public:
|
||||
virtual void remove_txpool_tx(const crypto::hash& txid) {}
|
||||
virtual bool get_txpool_tx_meta(const crypto::hash& txid, txpool_tx_meta_t &meta) const { return false; }
|
||||
virtual bool get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata &bd) const { return false; }
|
||||
virtual uint64_t get_database_size() const { return 0; }
|
||||
virtual cryptonote::blobdata get_txpool_tx_blob(const crypto::hash& txid) const { return ""; }
|
||||
virtual bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata*)>, bool include_blob = false, bool include_unrelayed_txes = false) const { return false; }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user