Merge pull request #70 from wowario/upstream

Upstream
This commit is contained in:
jw 2018-07-07 11:28:18 -07:00 committed by GitHub
commit 6b05e7f45d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 309 additions and 101 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

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

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

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

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

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

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

View File

@ -1554,6 +1554,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)

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

@ -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.");
}
@ -4108,7 +4132,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 +4463,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 +4631,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 +4668,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 +4737,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 +4884,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 +4968,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 +5083,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 +5153,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 +5458,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 +7046,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 +7432,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

@ -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)
{
@ -1308,20 +1309,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 +3258,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 +3776,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
@ -8238,6 +8245,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
{
@ -9516,7 +9533,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();

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;

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