Compare commits

...

60 Commits

Author SHA1 Message Date
jw
d4ee3c3251 Merge pull request #75 from wowario/checkpoints
update checkpoints.dat for point release
2018-08-05 17:13:36 -07:00
jw
b48234e81b Merge pull request #74 from fuwa0529/fix-default-mixin-link-error
clean up defaultMixin for wallet api
2018-08-05 17:13:25 -07:00
wowario
0cae683a75 update checkpoints.dat for point release 2018-08-01 10:35:14 -05:00
fuwa
cb1174cbe7 clean up defaultMixin for wallet api 2018-08-01 03:13:09 +08:00
jw
a53251ceb8 Merge pull request #72 from wowario/lwma2
update lwma2
2018-07-28 07:12:37 -07:00
jw
c074baee61 Merge pull request #71 from wowario/upstream
Upstream
2018-07-28 07:12:27 -07:00
wowario
6fa2c65993 Reset testnet timestamp 2018-07-28 00:47:26 -05:00
stoffu
5b7063c15a db_lmdb: enable batch transactions by default 2018-07-27 16:00:32 -05:00
moneromooo-monero
db77273f3f node_rpc_proxy: factor a few RPC calls using get_info
Takes advantage of caching
2018-07-27 15:57:10 -05:00
moneromooo-monero
13e9035505 blockchain: cache next block difficulty after adding a block
It's not 100% certain it'll be needed, but it avoids getinfo
needing the blockchain lock and potentially blocking
2018-07-27 15:54:07 -05:00
moneromooo-monero
e2a3f71870 memwipe: don't call the workhorse for 0 bytes
Some of them don't like it
2018-07-27 15:52:54 -05:00
moneromooo-monero
668489a322 db_lmdb: don't sync a read only DB
This would only throw
2018-07-27 15:52:09 -05:00
moneromooo-monero
fa3ae1a16d alt_chain_info can now give more info about a particular alt chain 2018-07-27 09:33:24 -05:00
moneromooo-monero
a28b9e2e44 rpc: add blockchain disk size to getinfo
This should help new nodes predict how much disk space will be
needed for a full sync
2018-07-27 09:33:24 -05:00
stoffu
39ff8c91c7 miner: show id and height when a block is found 2018-07-27 09:33:24 -05:00
moneromooo-monero
f2b1dca6aa remove epee from link lines where it's redundant
For some reason, this confuses and kills ASAN on startup
as it thinks const uint8_t ipv4_network_address::ID is
defined multiple times.
2018-07-27 09:33:24 -05:00
moneromooo-monero
a896603556 blockchain: set the m_verifivation_failed flag in a couple more places
when a block being added to the main chain is invalid.

This ensures the peer is banned after a number of these.
2018-07-27 04:06:12 -05:00
Teutone
e492718cd0 add .load() to make Boost 1.67 happy with its new is_integral check 2018-07-27 03:45:51 -05:00
moneromooo-monero
4cb1fa3243 wallet2: ensure outputs are processed only once
This should be proof against any way one might get to multiple
processing, such as generating the same derivation from the
same pubkey, etc
2018-07-27 03:45:51 -05:00
wowario
a2d3bc992d update lwma2 2018-07-23 20:57:33 -07:00
jw
6b05e7f45d Merge pull request #70 from wowario/upstream
Upstream
2018-07-07 11:28:18 -07:00
wowario
0f4ed31a61 bump version to 0.2.2.0 2018-07-07 13:32:51 +03:00
m2049r
68505da66f malloc scratchpad for all supported android archs 2018-07-07 13:25:11 +03:00
moneromooo-monero
6eaa228b16 abstract_tcp_server2: fix use after free 2018-07-07 13:22:01 +03:00
moneromooo-monero
05b49cc1bb simplewallet: init trusted daemon flag to false when autodetecting 2018-07-07 13:21:35 +03:00
moneromooo-monero
90a4ba36a6 wallet2: fix read buffer overflow in import_key_images 2018-07-07 13:21:13 +03:00
stoffu
0bd04bdfad wallet-rpc.getaddress: throw if index is out of bound 2018-07-07 13:20:52 +03:00
moneromooo-monero
5cdbfe4e8b zmq_server: fix bind call when address and/or port are empty 2018-07-07 13:20:34 +03:00
Howard Chu
2c9c795f0c Fix RPC crashes that didn't check for an open wallet 2018-07-07 13:19:37 +03:00
moneromooo-monero
7ba35598be wallet2: fix out of sync account tag cache
This would cause crashes when trying to tag an account that was
just created
2018-07-07 13:19:10 +03:00
moneromooo-monero
65f483ca5b abstract_tcp_server2: restart async accept on error 2018-07-07 13:18:45 +03:00
stoffu
6463a6da6f epee.string_tools: add conversion between UTF-8 and UTF-16 2018-07-07 13:18:26 +03:00
stoffu
86e6008036 Move parse_subaddress_lookahead() from simplewallet.cpp to util.cpp 2018-07-07 13:17:07 +03:00
stoffu
4bd2b033f6 wallet2: lower default for subaddress lookahead when restoring with hardware 2018-07-07 13:16:47 +03:00
stoffu
f4fa62e1db wallet: allow unspendable unmixable outputs to be discarded 2018-07-07 13:16:26 +03:00
stoffu
dc4b05bfd4 wallet2: use decoded amount when reporting repeated output key 2018-07-07 13:15:58 +03:00
moneromooo-monero
b27b34d90a epee: fallback to a counter if gmtime fails when rotating logs 2018-07-07 13:14:19 +03:00
moneromooo-monero
fea950a61b wallet: do not log by default if we're not asked to log to console
This means monero-wallet-rpc still does, but the user level program
does not.
2018-07-07 13:13:57 +03:00
moneromooo-monero
7f3f923021 tx_pool: initialize bitflags padding since it gets written to storage
Avoids valgrind reporting uninitialized data usage
2018-07-07 13:13:36 +03:00
moneromooo-monero
8345f0aabc util: consider Tor/I2P addresses to be non local 2018-07-07 13:13:14 +03:00
moneromooo-monero
edf18e227d simplewallet: add optional trusted/untrusted argument to set_daemon
Otherwise the previous daemon's trustedness would carry over.
If not specified, the local address check is performed again.
2018-07-07 13:12:54 +03:00
stoffu
2b863521ba blockchain: pop forked blocks only when DB is not read-only 2018-07-07 13:12:33 +03:00
moneromooo-monero
6270a903c8 blockchain: return error when requesting non existent output
avoids RPC thread dying, causing the wallet to timeout
2018-07-07 13:12:12 +03:00
moneromooo-monero
9d366226cb epee: fix detection of 172.16.0.0/172.31.255.255 local IP range 2018-07-07 13:11:51 +03:00
moneromooo-monero
9a2fa460b0 daemon: fix readline interfering with std::cerr usage
Once readline is initialized, std::cerr's operator<< will
output a 0xff byte for unknown reasons.
2018-07-07 13:11:30 +03:00
moneromooo-monero
6489ad8a1a disable file size sanity check when loading the wallet cache 2018-07-07 13:11:08 +03:00
moneromooo-monero
7df1321b30 fix build with GCC 8.1.0 2018-07-07 13:10:47 +03:00
moneromooo-monero
8212762312 core: lock incoming tx lock when checking the txpool and chain
This gets rid of an innocuous race trying to add the same tx
twice to the txpool
2018-07-07 13:10:25 +03:00
moneromooo-monero
6f2886e135 simplewallet: add --untrusted-daemon option 2018-07-07 13:10:04 +03:00
jw
1f3521f958 Merge pull request #68 from wownero/release-v0.2.1.0
Release v0.2.1.0
2018-07-06 17:31:24 -07:00
jw
bb49011991 Merge pull request #67 from wowario/lwma2-update
Update lwma2
2018-07-05 15:13:21 -07:00
jw
2e3340df7a Merge pull request #66 from wowario/testnet-stagenet
Add stagenet and reset testnet
2018-07-05 15:13:06 -07:00
wowario
d552924515 Update adapt get_approximate_blockchain_height 2018-07-04 20:56:58 +03:00
wowario
ee07408ce1 Add stagenet ips 2018-07-04 19:20:06 +03:00
wowario
d0d1a14a05 Add stagenet fork heights 2018-07-04 19:20:05 +03:00
wowario
2da1edf924 Update difficulty 2018-07-03 11:41:22 +03:00
jw
28b65ea422 Merge pull request #64 from wowario/release-v0.2.1.0
Captain obvious warning
2018-06-29 05:25:32 -07:00
wowario
2d4c0edd66 Captain obvious warning 2018-06-29 12:36:11 +03:00
jw
a0b47c970c Merge pull request #63 from fuwa0529/fix-default-mixin
remove unused default mixin from wallet.cpp
2018-06-28 12:27:39 -07:00
fuwa
7973af3a3c remove unused default mixin from wallet.cpp 2018-06-26 04:58:36 +08:00
49 changed files with 510 additions and 280 deletions

View File

@@ -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;

View File

@@ -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>

View File

@@ -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;
}

View File

@@ -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_

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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
/**

View File

@@ -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__);

View File

@@ -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.

View File

@@ -78,7 +78,6 @@ monero_add_library(common
DEPENDS generate_translations_header)
target_link_libraries(common
PUBLIC
epee
cncrypto
${UNBOUND_LIBRARY}
${LIBUNWIND_LIBRARIES}

View File

@@ -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 {};
}
}
}

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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);
}
//-----------------------------------------------------------------

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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

View File

@@ -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

View File

@@ -92,7 +92,6 @@ target_link_libraries(daemon
daemonizer
serialization
daemon_rpc_server
epee
${EPEE_READLINE}
version
${Boost_CHRONO_LIBRARY}

View File

@@ -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)

View File

@@ -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(

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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}

View File

@@ -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;
}

View File

@@ -111,7 +111,6 @@ target_link_libraries(rpc
common
cryptonote_core
cryptonote_protocol
epee
${Boost_REGEX_LIBRARY}
${Boost_THREAD_LIBRARY}
PRIVATE

View File

@@ -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;
}

View File

@@ -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()
};

View File

@@ -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());
}

View File

@@ -48,7 +48,6 @@ target_link_libraries(simplewallet
cncrypto
common
mnemonics
epee
${EPEE_READLINE}
version
${Boost_CHRONO_LIBRARY}

View File

@@ -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);

View File

@@ -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

View File

@@ -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

View File

@@ -85,7 +85,6 @@ monero_add_executable(wallet_rpc_server
target_link_libraries(wallet_rpc_server
PRIVATE
wallet
epee
rpc_base
cryptonote_core
cncrypto

View File

@@ -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 &note)
{
@@ -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);

View File

@@ -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 &note);
virtual std::string getUserNote(const std::string &txid) const;
virtual std::string getTxKey(const std::string &txid) const;

View File

@@ -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

View File

@@ -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)

View File

@@ -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;
};
}

View File

@@ -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)

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -86,7 +86,6 @@ target_link_libraries(unit_tests
wallet
p2p
version
epee
${Boost_CHRONO_LIBRARY}
${Boost_THREAD_LIBRARY}
${GTEST_LIBRARIES}

View File

@@ -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; }