aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml2
-rw-r--r--CMakeLists.txt10
-rw-r--r--Dockerfile1
-rw-r--r--README.md37
-rw-r--r--contrib/depends/toolchain.cmake.in2
-rw-r--r--contrib/epee/include/console_handler.h5
-rw-r--r--contrib/epee/include/misc_language.h3
-rw-r--r--contrib/epee/include/net/abstract_tcp_server2.h11
-rw-r--r--contrib/epee/include/net/abstract_tcp_server2.inl10
-rw-r--r--contrib/epee/include/net/connection_basic.hpp3
-rw-r--r--contrib/epee/include/net/http_protocol_handler.inl1
-rw-r--r--contrib/epee/include/net/levin_protocol_handler_async.h4
-rw-r--r--contrib/epee/src/connection_basic.cpp7
-rw-r--r--contrib/epee/src/mlog.cpp35
-rw-r--r--contrib/epee/src/network_throttle-detail.cpp1
-rw-r--r--src/blockchain_utilities/CMakeLists.txt2
-rw-r--r--src/blockchain_utilities/blockchain_blackball.cpp24
-rw-r--r--src/common/expect.h4
-rw-r--r--src/common/password.cpp15
-rw-r--r--src/common/spawn.cpp3
-rw-r--r--src/common/threadpool.cpp10
-rw-r--r--src/common/util.cpp22
-rw-r--r--src/common/util.h2
-rw-r--r--src/cryptonote_basic/cryptonote_format_utils.cpp10
-rw-r--r--src/cryptonote_basic/cryptonote_format_utils.h1
-rw-r--r--src/cryptonote_basic/miner.cpp2
-rw-r--r--src/cryptonote_core/blockchain.cpp7
-rw-r--r--src/cryptonote_core/cryptonote_core.cpp7
-rw-r--r--src/cryptonote_core/tx_pool.cpp51
-rw-r--r--src/cryptonote_core/tx_pool.h13
-rw-r--r--src/daemon/daemon.cpp14
-rw-r--r--src/daemonizer/windows_daemonizer.inl1
-rw-r--r--src/debug_utilities/object_sizes.cpp1
-rw-r--r--src/device/device_io_hid.cpp56
-rw-r--r--src/device/device_io_hid.hpp12
-rw-r--r--src/device/device_ledger.cpp2
-rw-r--r--src/p2p/net_node.cpp1
-rw-r--r--src/p2p/net_node.inl6
-rw-r--r--src/rpc/core_rpc_server.cpp18
-rw-r--r--src/rpc/daemon_messages.h2
-rw-r--r--src/serialization/serialization.h23
-rw-r--r--src/simplewallet/simplewallet.cpp38
-rw-r--r--src/wallet/api/wallet.cpp8
-rw-r--r--src/wallet/ringdb.cpp4
-rw-r--r--src/wallet/wallet2.cpp24
-rw-r--r--src/wallet/wallet_rpc_server.cpp3
-rw-r--r--src/wallet/wallet_rpc_server.h1
-rw-r--r--tests/crypto/main.cpp3
-rw-r--r--tests/functional_tests/CMakeLists.txt4
-rw-r--r--tests/fuzz/base58.cpp2
-rw-r--r--tests/fuzz/block.cpp2
-rw-r--r--tests/fuzz/bulletproof.cpp2
-rw-r--r--tests/fuzz/cold-outputs.cpp2
-rw-r--r--tests/fuzz/cold-transaction.cpp2
-rw-r--r--tests/fuzz/http-client.cpp2
-rw-r--r--tests/fuzz/levin.cpp2
-rw-r--r--tests/fuzz/load_from_binary.cpp2
-rw-r--r--tests/fuzz/load_from_json.cpp2
-rw-r--r--tests/fuzz/parse_url.cpp2
-rw-r--r--tests/fuzz/signature.cpp2
-rw-r--r--tests/fuzz/transaction.cpp2
-rw-r--r--tests/net_load_tests/clt.cpp3
-rw-r--r--tests/net_load_tests/srv.cpp3
-rw-r--r--tests/unit_tests/CMakeLists.txt7
-rw-r--r--tests/unit_tests/aligned.cpp21
-rw-r--r--tests/unit_tests/notify.cpp57
-rw-r--r--tests/unit_tests/ringdb.cpp10
-rw-r--r--tests/unit_tests/test_notifier.cpp54
68 files changed, 523 insertions, 182 deletions
diff --git a/.travis.yml b/.travis.yml
index ca3a24ae8..6a9b9b94b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -58,7 +58,7 @@ script:
- export TRAVIS_COMMIT_LOG=`git log --format=fuller -1`
- OUTDIR=$BASE_OUTDIR/$TRAVIS_PULL_REQUEST/$TRAVIS_JOB_NUMBER-$HOST
- if [ -z "$NO_DEPENDS" ]; then $DOCKER_EXEC ccache --max-size=$CCACHE_SIZE; fi
- - $DOCKER_EXEC bash -c "mkdir build && cd build && cmake -DCMAKE_TOOLCHAIN_FILE=$TRAVIS_BUILD_DIR/contrib/depends/$HOST/share/toolchain.cmake .. && make $MAKEJOBS"
+ - $DOCKER_EXEC bash -c "mkdir build && cd build && cmake -DCMAKE_TOOLCHAIN_FILE=$TRAVIS_BUILD_DIR/contrib/depends/$HOST/share/toolchain.cmake -DTRAVIS=true .. && make $MAKEJOBS"
- export LD_LIBRARY_PATH=$TRAVIS_BUILD_DIR/contrib/depends/$HOST/lib
after_script:
- echo $TRAVIS_COMMIT_RANGE
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1bffd29b6..8baac02e9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -40,6 +40,7 @@ if (IOS)
endif()
cmake_minimum_required(VERSION 2.8.7)
+message(STATUS "CMake version ${CMAKE_VERSION}")
project(monero)
@@ -139,7 +140,6 @@ if(ARCH_ID STREQUAL "ppc64le")
set(PPC64LE 1)
set(PPC64 0)
set(PPC 0)
-
endif()
if(ARCH_ID STREQUAL "powerpc64" OR ARCH_ID STREQUAL "ppc64")
@@ -517,10 +517,8 @@ if(MSVC)
include_directories(SYSTEM src/platform/msc)
else()
include(TestCXXAcceptsFlag)
- if (NOT ARM6)
- if(NOT DEPENDS OR DEPENDS AND NOT ARM)
- set(ARCH native CACHE STRING "CPU to build for: -march value or 'default' to not pass -march at all")
- endif()
+ if (NOT ARCH)
+ set(ARCH native CACHE STRING "CPU to build for: -march value or 'default' to not pass -march at all")
endif()
message(STATUS "Building on ${CMAKE_SYSTEM_PROCESSOR} for ${ARCH}")
if(ARCH STREQUAL "default")
@@ -882,7 +880,7 @@ endif()
include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
if(MINGW)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wa,-mbig-obj")
- set(EXTRA_LIBRARIES mswsock;ws2_32;iphlpapi;crypt32)
+ set(EXTRA_LIBRARIES mswsock;ws2_32;iphlpapi;crypt32;bcrypt)
if(DEPENDS)
set(ICU_LIBRARIES ${Boost_LOCALE_LIBRARY} sicuio sicuin sicuuc sicudt sicutu iconv)
else()
diff --git a/Dockerfile b/Dockerfile
index 40ba81d9c..cd3e7df70 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -115,6 +115,7 @@ COPY . .
ENV USE_SINGLE_BUILDDIR=1
ARG NPROC
RUN set -ex && \
+ git submodule init && git submodule update && \
rm -rf build && \
if [ -z "$NPROC" ] ; \
then make -j$(nproc) release-static ; \
diff --git a/README.md b/README.md
index 601cce544..6b6f0cac5 100644
--- a/README.md
+++ b/README.md
@@ -480,7 +480,7 @@ Then you can run make as usual.
# Get binaries
docker cp monero-android:/src/build/release/bin .
-### Building portable statically linked binaries (Cross Compiling)
+### Building portable statically linked binaries
By default, in either dynamically or statically linked builds, binaries target the specific host processor on which the build happens and are not portable to other processors. Portable binaries can be built using the following targets:
@@ -492,6 +492,25 @@ By default, in either dynamically or statically linked builds, binaries target t
* ```make release-static-win64``` builds binaries on 64-bit Windows portable across 64-bit Windows systems
* ```make release-static-win32``` builds binaries on 64-bit or 32-bit Windows portable across 32-bit Windows systems
+### Cross Compiling
+
+You can also cross-compile static binaries on Linux for Windows and macOS with the `depends` system. Go to `contrib/depends` and type:
+
+* ```make HOST=x86_64-linux-gnu``` for 64-bit linux binaries.
+* ```make HOST=x86_64-w64-mingw32``` for 64-bit windows binaries. Requires: python3 nsis g++-mingw-w64-x86-64 wine1.6 bc
+* ```make HOST=x86_64-apple-darwin11``` for darwin binaries. Requires: cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev
+* ```make HOST=i686-linux-gnu``` for 32-bit linux binaries. Requires: g++-multilib bc
+* ```make HOST=i686-w64-mingw32``` for 32-bit windows binaries. Requires: python3 nsis g++-mingw-w64-i686
+* ```make HOST=arm-linux-gnueabihf``` for armv6 binaries. Requires: g++-arm-linux-gnueabihf
+
+The required packages are the names for each toolchain on apt. Depending on your distro, they may have different names.
+Then go back to the source dir and type:
+
+* ```cmake -DCMAKE_TOOLCHAIN_FILE=`pwd`/contrib/depends/<chosen triplet>/share/toolchain.cmake```
+Where <chosen triplet> is one of the above mentioned targets.
+
+Using `depends` might also be easier to compile Monero on Windows than using MSys. Activate Windows Subsystem for Linux (WSL) with a distro (for example Ubuntu), install the apt build-essentials and follow the `depends` steps as depicted above.
+
## Installing Monero from a package
**DISCLAIMER: These packages are not part of this repository or maintained by this project's contributors, and as such, do not go through the same review process to ensure their trustworthiness and security.**
@@ -535,22 +554,6 @@ Installing a snap is very quick. Snaps are secure. They are isolated with all of
Packaging for your favorite distribution would be a welcome contribution!
-You can also cross-compile binaries on linux for windows and macos with the depends system. Go to contrib/depends and type:
-
-* ```make HOST=x86_64-linux-gnu``` for 64-bit linux binaries.
-* ```make HOST=x86_64-w64-mingw32``` for 64-bit windows binaries. Requires: python3 nsis g++-mingw-w64-x86-64 wine1.6 bc
-* ```make HOST=x86_64-apple-darwin11``` for darwin binaries. Requires: cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev
-* ```make HOST=i686-linux-gnu``` for 32-bit linux binaries. Requires: g++-multilib bc
-* ```make HOST=i686-w64-mingw32``` for 32-bit windows binaries. Requires: python3 nsis g++-mingw-w64-i686
-* ```make HOST=arm-linux-gnueabihf``` for armv6 binaries. Requires: g++-arm-linux-gnueabihf
-
-The required packages are the names for each toolchain on apt. Depending on your distro, they may have different names.
-Then go back to the source dir and type for example for windows 64bit:
-
-* ```cmake -DCMAKE_TOOLCHAIN_FILE=`pwd`/contrib/depends/x86_64-w64-mingw32```
-
-Using depends might also be easier to compile monero on windows than using msys. Activate windows subsystem for linux (for example ubuntu) install the apt build-essentials and follow the depends steps as depicted above.
-
## Running monerod
The build places the binary in `bin/` sub-directory within the build directory
diff --git a/contrib/depends/toolchain.cmake.in b/contrib/depends/toolchain.cmake.in
index f8548a724..66168facb 100644
--- a/contrib/depends/toolchain.cmake.in
+++ b/contrib/depends/toolchain.cmake.in
@@ -51,7 +51,9 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
SET(APPLE True)
SET(BUILD_TAG "mac-x64")
SET(BUILD_64 ON)
+ if(NOT TRAVIS)
SET(ARCH "x86_64")
+ endif()
SET(BREW OFF)
SET(PORT OFF)
SET(CMAKE_OSX_SYSROOT "@sdk@/MacOSX10.11.sdk/")
diff --git a/contrib/epee/include/console_handler.h b/contrib/epee/include/console_handler.h
index 2ccf5b095..6e7efd1d7 100644
--- a/contrib/epee/include/console_handler.h
+++ b/contrib/epee/include/console_handler.h
@@ -352,8 +352,11 @@ eof:
std::string command;
bool get_line_ret = m_stdin_reader.get_line(command);
- if (!m_running || m_stdin_reader.eos())
+ if (!m_running)
+ break;
+ if (m_stdin_reader.eos())
{
+ MGINFO("EOF on stdin, exiting");
break;
}
if (!get_line_ret)
diff --git a/contrib/epee/include/misc_language.h b/contrib/epee/include/misc_language.h
index d5157365c..7e4eb337d 100644
--- a/contrib/epee/include/misc_language.h
+++ b/contrib/epee/include/misc_language.h
@@ -147,7 +147,8 @@ namespace misc_utils
{}
~call_befor_die()
{
- m_func();
+ try { m_func(); }
+ catch (...) { /* ignore */ }
}
};
diff --git a/contrib/epee/include/net/abstract_tcp_server2.h b/contrib/epee/include/net/abstract_tcp_server2.h
index b2c05ebb0..3f726a352 100644
--- a/contrib/epee/include/net/abstract_tcp_server2.h
+++ b/contrib/epee/include/net/abstract_tcp_server2.h
@@ -246,7 +246,6 @@ namespace net_utils
m_timer(io_serice)
{}
boost::asio::deadline_timer m_timer;
- uint64_t m_period;
};
template <class t_handler>
@@ -262,25 +261,27 @@ namespace net_utils
{
return m_handler();
}
+ uint64_t m_period;
};
template<class t_handler>
bool add_idle_handler(t_handler t_callback, uint64_t timeout_ms)
{
- boost::shared_ptr<idle_callback_conext_base> ptr(new idle_callback_conext<t_handler>(io_service_, t_callback, timeout_ms));
+ boost::shared_ptr<idle_callback_conext<t_handler>> ptr(new idle_callback_conext<t_handler>(io_service_, t_callback, timeout_ms));
//needed call handler here ?...
ptr->m_timer.expires_from_now(boost::posix_time::milliseconds(ptr->m_period));
- ptr->m_timer.async_wait(boost::bind(&boosted_tcp_server<t_protocol_handler>::global_timer_handler, this, ptr));
+ ptr->m_timer.async_wait(boost::bind(&boosted_tcp_server<t_protocol_handler>::global_timer_handler<t_handler>, this, ptr));
return true;
}
- bool global_timer_handler(/*const boost::system::error_code& err, */boost::shared_ptr<idle_callback_conext_base> ptr)
+ template<class t_handler>
+ bool global_timer_handler(/*const boost::system::error_code& err, */boost::shared_ptr<idle_callback_conext<t_handler>> ptr)
{
//if handler return false - he don't want to be called anymore
if(!ptr->call_handler())
return true;
ptr->m_timer.expires_from_now(boost::posix_time::milliseconds(ptr->m_period));
- ptr->m_timer.async_wait(boost::bind(&boosted_tcp_server<t_protocol_handler>::global_timer_handler, this, ptr));
+ ptr->m_timer.async_wait(boost::bind(&boosted_tcp_server<t_protocol_handler>::global_timer_handler<t_handler>, this, ptr));
return true;
}
diff --git a/contrib/epee/include/net/abstract_tcp_server2.inl b/contrib/epee/include/net/abstract_tcp_server2.inl
index 3a5c83017..5dbb7a478 100644
--- a/contrib/epee/include/net/abstract_tcp_server2.inl
+++ b/contrib/epee/include/net/abstract_tcp_server2.inl
@@ -43,6 +43,8 @@
#include <boost/date_time/posix_time/posix_time.hpp> // TODO
#include <boost/thread/thread.hpp> // TODO
#include <boost/thread/condition_variable.hpp> // TODO
+#include "warnings.h"
+#include "string_tools.h"
#include "misc_language.h"
#include "net/local_ip.h"
#include "pragma_comp_defs.h"
@@ -51,8 +53,6 @@
#include <iomanip>
#include <algorithm>
-#include "../../../../src/cryptonote_core/cryptonote_core.h" // e.g. for the send_stop_signal()
-
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "net"
@@ -149,10 +149,8 @@ PRAGMA_WARNING_DISABLE_VS(4355)
const unsigned long ip_{boost::asio::detail::socket_ops::host_to_network_long(remote_ep.address().to_v4().to_ulong())};
m_local = epee::net_utils::is_ip_loopback(ip_) || epee::net_utils::is_ip_local(ip_);
- // create a random uuid
- boost::uuids::uuid random_uuid;
- // that stuff turns out to be included, even though it's from src... Taking advantage
- random_uuid = crypto::rand<boost::uuids::uuid>();
+ // create a random uuid, we don't need crypto strength here
+ const boost::uuids::uuid random_uuid = boost::uuids::random_generator()();
context.set_details(random_uuid, epee::net_utils::ipv4_network_address(ip_, remote_ep.port()), is_income);
_dbg3("[sock " << socket_.native_handle() << "] new connection from " << print_connection_context_short(context) <<
diff --git a/contrib/epee/include/net/connection_basic.hpp b/contrib/epee/include/net/connection_basic.hpp
index 095e747a5..7e8750047 100644
--- a/contrib/epee/include/net/connection_basic.hpp
+++ b/contrib/epee/include/net/connection_basic.hpp
@@ -92,7 +92,6 @@ class connection_basic { // not-templated base class for rapid developmet of som
critical_section m_send_que_lock;
std::list<std::string> m_send_que;
volatile bool m_is_multithreaded;
- double m_start_time;
/// Strand to ensure the connection's handlers are not called concurrently.
boost::asio::io_service::strand strand_;
/// Socket for the connection.
@@ -112,8 +111,6 @@ class connection_basic { // not-templated base class for rapid developmet of som
void logger_handle_net_write(size_t size); // network data written
void logger_handle_net_read(size_t size); // network data read
- void set_start_time();
-
// config for rate limit
static void set_rate_up_limit(uint64_t limit);
diff --git a/contrib/epee/include/net/http_protocol_handler.inl b/contrib/epee/include/net/http_protocol_handler.inl
index 76db5346f..b53bdc200 100644
--- a/contrib/epee/include/net/http_protocol_handler.inl
+++ b/contrib/epee/include/net/http_protocol_handler.inl
@@ -32,6 +32,7 @@
#include "string_tools.h"
#include "file_io_utils.h"
#include "net_parse_helpers.h"
+#include "time_helper.h"
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "net.http"
diff --git a/contrib/epee/include/net/levin_protocol_handler_async.h b/contrib/epee/include/net/levin_protocol_handler_async.h
index e9853ee26..08aa1d468 100644
--- a/contrib/epee/include/net/levin_protocol_handler_async.h
+++ b/contrib/epee/include/net/levin_protocol_handler_async.h
@@ -99,7 +99,7 @@ public:
size_t get_connections_count();
void set_handler(levin_commands_handler<t_connection_context>* handler, void (*destroy)(levin_commands_handler<t_connection_context>*) = NULL);
- async_protocol_handler_config():m_pcommands_handler(NULL), m_pcommands_handler_destroy(NULL), m_max_packet_size(LEVIN_DEFAULT_MAX_PACKET_SIZE)
+ async_protocol_handler_config():m_pcommands_handler(NULL), m_pcommands_handler_destroy(NULL), m_max_packet_size(LEVIN_DEFAULT_MAX_PACKET_SIZE), m_invoke_timeout(LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED)
{}
~async_protocol_handler_config() { set_handler(NULL, NULL); }
void del_out_connections(size_t count);
@@ -272,6 +272,8 @@ public:
m_wait_count = 0;
m_oponent_protocol_ver = 0;
m_connection_initialized = false;
+ m_invoke_buf_ready = 0;
+ m_invoke_result_code = LEVIN_ERROR_CONNECTION;
}
virtual ~async_protocol_handler()
{
diff --git a/contrib/epee/src/connection_basic.cpp b/contrib/epee/src/connection_basic.cpp
index dea1928a7..9ab485839 100644
--- a/contrib/epee/src/connection_basic.cpp
+++ b/contrib/epee/src/connection_basic.cpp
@@ -250,22 +250,15 @@ void connection_basic::sleep_before_packet(size_t packet_size, int phase, int q
}
}
-void connection_basic::set_start_time() {
- CRITICAL_REGION_LOCAL( network_throttle_manager::m_lock_get_global_throttle_out );
- m_start_time = network_throttle_manager::get_global_throttle_out().get_time_seconds();
-}
void connection_basic::do_send_handler_write(const void* ptr , size_t cb ) {
// No sleeping here; sleeping is done once and for all in connection<t_protocol_handler>::handle_write
MTRACE("handler_write (direct) - before ASIO write, for packet="<<cb<<" B (after sleep)");
- set_start_time();
}
void connection_basic::do_send_handler_write_from_queue( const boost::system::error_code& e, size_t cb, int q_len ) {
// No sleeping here; sleeping is done once and for all in connection<t_protocol_handler>::handle_write
MTRACE("handler_write (after write, from queue="<<q_len<<") - before ASIO write, for packet="<<cb<<" B (after sleep)");
-
- set_start_time();
}
void connection_basic::logger_handle_net_read(size_t size) { // network data read
diff --git a/contrib/epee/src/mlog.cpp b/contrib/epee/src/mlog.cpp
index 61d853ef4..638155b6b 100644
--- a/contrib/epee/src/mlog.cpp
+++ b/contrib/epee/src/mlog.cpp
@@ -28,6 +28,13 @@
#ifndef _MLOG_H_
#define _MLOG_H_
+#ifdef _WIN32
+#include <windows.h>
+#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
+#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
+#endif
+#endif
+
#include <time.h>
#include <atomic>
#include <boost/filesystem.hpp>
@@ -117,6 +124,31 @@ static const char *get_default_categories(int level)
return categories;
}
+#ifdef WIN32
+bool EnableVTMode()
+{
+ // Set output mode to handle virtual terminal sequences
+ HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
+ if (hOut == INVALID_HANDLE_VALUE)
+ {
+ return false;
+ }
+
+ DWORD dwMode = 0;
+ if (!GetConsoleMode(hOut, &dwMode))
+ {
+ return false;
+ }
+
+ dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
+ if (!SetConsoleMode(hOut, dwMode))
+ {
+ return false;
+ }
+ return true;
+}
+#endif
+
void mlog_configure(const std::string &filename_base, bool console, const std::size_t max_log_file_size, const std::size_t max_log_files)
{
el::Configurations c;
@@ -202,6 +234,9 @@ void mlog_configure(const std::string &filename_base, bool console, const std::s
monero_log = get_default_categories(0);
}
mlog_set_log(monero_log);
+#ifdef WIN32
+ EnableVTMode();
+#endif
}
void mlog_set_categories(const char *categories)
diff --git a/contrib/epee/src/network_throttle-detail.cpp b/contrib/epee/src/network_throttle-detail.cpp
index 7eeade3a1..28c85bb78 100644
--- a/contrib/epee/src/network_throttle-detail.cpp
+++ b/contrib/epee/src/network_throttle-detail.cpp
@@ -146,6 +146,7 @@ network_throttle::network_throttle(const std::string &nameshort, const std::stri
m_network_add_cost = 128;
m_network_minimal_segment = 256;
m_network_max_segment = 1024*1024;
+ m_start_time = 0;
m_any_packet_yet = false;
m_slot_size = 1.0; // hard coded in few places
m_target_speed = 16 * 1024; // other defaults are probably defined in the command-line parsing code when this class is used e.g. as main global throttle
diff --git a/src/blockchain_utilities/CMakeLists.txt b/src/blockchain_utilities/CMakeLists.txt
index ecd7b754c..24a750eb0 100644
--- a/src/blockchain_utilities/CMakeLists.txt
+++ b/src/blockchain_utilities/CMakeLists.txt
@@ -184,7 +184,7 @@ target_link_libraries(blockchain_blackball
set_property(TARGET blockchain_blackball
PROPERTY
- OUTPUT_NAME "monero-blockchain-blackball")
+ OUTPUT_NAME "monero-blockchain-mark-spent-outputs")
install(TARGETS blockchain_blackball DESTINATION bin)
diff --git a/src/blockchain_utilities/blockchain_blackball.cpp b/src/blockchain_utilities/blockchain_blackball.cpp
index 03ff3cdcd..d2ce5cf76 100644
--- a/src/blockchain_utilities/blockchain_blackball.cpp
+++ b/src/blockchain_utilities/blockchain_blackball.cpp
@@ -226,7 +226,7 @@ static void init(std::string cache_filename)
bool tx_active = false;
int dbr;
- MINFO("Creating blackball cache in " << cache_filename);
+ MINFO("Creating spent output cache in " << cache_filename);
tools::create_directories_if_necessary(cache_filename);
@@ -1019,7 +1019,7 @@ int main(int argc, char* argv[])
po::options_description desc_cmd_only("Command line options");
po::options_description desc_cmd_sett("Command line options and settings options");
const command_line::arg_descriptor<std::string> arg_blackball_db_dir = {
- "blackball-db-dir", "Specify blackball database directory",
+ "spent-output-db-dir", "Specify spent output database directory",
get_default_db_path(),
};
const command_line::arg_descriptor<std::string> arg_log_level = {"log-level", "0-4 or categories", ""};
@@ -1076,7 +1076,7 @@ int main(int argc, char* argv[])
return 1;
}
- mlog_configure(mlog_get_default_log_path("monero-blockchain-blackball.log"), true);
+ mlog_configure(mlog_get_default_log_path("monero-blockchain-find-spent-outputs.log"), true);
if (!command_line::is_arg_defaulted(vm, arg_log_level))
mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str());
else
@@ -1114,10 +1114,10 @@ int main(int argc, char* argv[])
return 1;
}
- const std::string cache_dir = (output_file_path / "blackball-cache").string();
+ const std::string cache_dir = (output_file_path / "spent-outputs-cache").string();
init(cache_dir);
- LOG_PRINT_L0("Scanning for blackballable outputs...");
+ LOG_PRINT_L0("Scanning for spent outputs...");
size_t done = 0;
@@ -1215,7 +1215,7 @@ int main(int argc, char* argv[])
const std::pair<uint64_t, uint64_t> output = std::make_pair(txin.amount, absolute[0]);
if (opt_verbose)
{
- MINFO("Blackballing output " << output.first << "/" << output.second << ", due to being used in a 1-ring");
+ MINFO("Marking output " << output.first << "/" << output.second << " as spent, due to being used in a 1-ring");
std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush;
}
blackballs.push_back(output);
@@ -1229,7 +1229,7 @@ int main(int argc, char* argv[])
const std::pair<uint64_t, uint64_t> output = std::make_pair(txin.amount, absolute[o]);
if (opt_verbose)
{
- MINFO("Blackballing output " << output.first << "/" << output.second << ", due to being used in " << new_ring.size() << " identical " << new_ring.size() << "-rings");
+ MINFO("Marking output " << output.first << "/" << output.second << " as spent, due to being used in " << new_ring.size() << " identical " << new_ring.size() << "-rings");
std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush;
}
blackballs.push_back(output);
@@ -1244,7 +1244,7 @@ int main(int argc, char* argv[])
const std::pair<uint64_t, uint64_t> output = std::make_pair(txin.amount, absolute[o]);
if (opt_verbose)
{
- MINFO("Blackballing output " << output.first << "/" << output.second << ", due to being used in " << new_ring.size() << " subsets of " << new_ring.size() << "-rings");
+ MINFO("Marking output " << output.first << "/" << output.second << " as spent, due to being used in " << new_ring.size() << " subsets of " << new_ring.size() << "-rings");
std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush;
}
blackballs.push_back(output);
@@ -1280,7 +1280,7 @@ int main(int argc, char* argv[])
const std::pair<uint64_t, uint64_t> output = std::make_pair(txin.amount, common[0]);
if (opt_verbose)
{
- MINFO("Blackballing output " << output.first << "/" << output.second << ", due to being used in rings with a single common element");
+ MINFO("Marking output " << output.first << "/" << output.second << " as spent, due to being used in rings with a single common element");
std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush;
}
blackballs.push_back(output);
@@ -1392,7 +1392,7 @@ int main(int argc, char* argv[])
const std::pair<uint64_t, uint64_t> output = std::make_pair(od.amount, last_unknown);
if (opt_verbose)
{
- MINFO("Blackballing output " << output.first << "/" << output.second << ", due to being used in a " <<
+ MINFO("Marking output " << output.first << "/" << output.second << " as spent, due to being used in a " <<
absolute.size() << "-ring where all other outputs are known to be spent");
}
blackballs.push_back(output);
@@ -1420,7 +1420,7 @@ int main(int argc, char* argv[])
skip_secondary_passes:
uint64_t diff = get_num_spent_outputs() - start_blackballed_outputs;
- LOG_PRINT_L0(std::to_string(diff) << " new outputs blackballed, " << get_num_spent_outputs() << " total outputs blackballed");
+ LOG_PRINT_L0(std::to_string(diff) << " new outputs marked as spent, " << get_num_spent_outputs() << " total outputs marked as spent");
MDB_txn *txn;
dbr = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn);
@@ -1460,7 +1460,7 @@ skip_secondary_passes:
mdb_txn_abort(txn);
}
- LOG_PRINT_L0("Blockchain blackball data exported OK");
+ LOG_PRINT_L0("Blockchain spent output data exported OK");
close_db(env0, txn0, cur0, dbi0);
close();
return 0;
diff --git a/src/common/expect.h b/src/common/expect.h
index 326242502..72e4060a7 100644
--- a/src/common/expect.h
+++ b/src/common/expect.h
@@ -350,7 +350,9 @@ public:
using error_type = std::error_code;
//! Create a successful object.
- expect() = default;
+ expect() noexcept
+ : code_()
+ {}
expect(std::error_code const& code) noexcept
: code_(code)
diff --git a/src/common/password.cpp b/src/common/password.cpp
index a8d5141dc..b3c51128f 100644
--- a/src/common/password.cpp
+++ b/src/common/password.cpp
@@ -60,7 +60,7 @@ namespace
DWORD mode_old;
::GetConsoleMode(h_cin, &mode_old);
- DWORD mode_new = mode_old & ~((hide_input ? ENABLE_ECHO_INPUT : 0) | ENABLE_LINE_INPUT);
+ DWORD mode_new = mode_old & ~(hide_input ? ENABLE_ECHO_INPUT : 0);
::SetConsoleMode(h_cin, mode_new);
bool r = true;
@@ -78,7 +78,11 @@ namespace
{
break;
}
- else if (ucs2_ch == L'\n' || ucs2_ch == L'\r')
+ else if (ucs2_ch == L'\r')
+ {
+ continue;
+ }
+ else if (ucs2_ch == L'\n')
{
std::cout << std::endl;
break;
@@ -158,6 +162,13 @@ namespace
if (!aPass.empty())
{
aPass.pop_back();
+ if (!hide_input)
+ std::cout << "\b\b\b \b\b\b" << std::flush;
+ }
+ else
+ {
+ if (!hide_input)
+ std::cout << "\b\b \b\b" << std::flush;
}
}
else
diff --git a/src/common/spawn.cpp b/src/common/spawn.cpp
index 59f11675c..0a2ce8387 100644
--- a/src/common/spawn.cpp
+++ b/src/common/spawn.cpp
@@ -38,6 +38,7 @@
#endif
#include "misc_log_ex.h"
+#include "util.h"
#include "spawn.h"
namespace tools
@@ -101,6 +102,8 @@ int spawn(const char *filename, const std::vector<std::string>& args, bool wait)
// child
if (pid == 0)
{
+ tools::closefrom(3);
+ close(0);
char *envp[] = {NULL};
execve(filename, argv, envp);
MERROR("Failed to execve: " << strerror(errno));
diff --git a/src/common/threadpool.cpp b/src/common/threadpool.cpp
index 5ea04a353..37825e31d 100644
--- a/src/common/threadpool.cpp
+++ b/src/common/threadpool.cpp
@@ -51,11 +51,19 @@ threadpool::threadpool(unsigned int max_threads) : running(true), active(0) {
}
threadpool::~threadpool() {
+ try
{
const boost::unique_lock<boost::mutex> lock(mutex);
running = false;
has_work.notify_all();
}
+ catch (...)
+ {
+ // if the lock throws, we're just do it without a lock and hope,
+ // since the alternative is terminate
+ running = false;
+ has_work.notify_all();
+ }
for (size_t i = 0; i<threads.size(); i++) {
try { threads[i].join(); }
catch (...) { /* ignore */ }
@@ -91,11 +99,13 @@ unsigned int threadpool::get_max_concurrency() const {
threadpool::waiter::~waiter()
{
+ try
{
boost::unique_lock<boost::mutex> lock(mt);
if (num)
MERROR("wait should have been called before waiter dtor - waiting now");
}
+ catch (...) { /* ignore */ }
try
{
wait(NULL);
diff --git a/src/common/util.cpp b/src/common/util.cpp
index 2a1d49af0..f91230528 100644
--- a/src/common/util.cpp
+++ b/src/common/util.cpp
@@ -28,6 +28,7 @@
//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
+#include <unistd.h>
#include <cstdio>
#ifdef __GLIBC__
@@ -233,7 +234,7 @@ namespace tools
MERROR("Failed to open " << filename << ": " << std::error_code(GetLastError(), std::system_category()));
}
#else
- m_fd = open(filename.c_str(), O_RDONLY | O_CREAT, 0666);
+ m_fd = open(filename.c_str(), O_RDONLY | O_CREAT | O_CLOEXEC, 0666);
if (m_fd != -1)
{
if (flock(m_fd, LOCK_EX | LOCK_NB) == -1)
@@ -967,4 +968,23 @@ std::string get_nix_version_display_string()
}
#endif
+ void closefrom(int fd)
+ {
+#if defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__ || defined __DragonFly__
+ ::closefrom(fd);
+#else
+#if defined __GLIBC__
+ const int sc_open_max = sysconf(_SC_OPEN_MAX);
+ const int MAX_FDS = std::min(65536, sc_open_max);
+#else
+ const int MAX_FDS = 65536;
+#endif
+ while (fd < MAX_FDS)
+ {
+ close(fd);
+ ++fd;
+ }
+#endif
+ }
+
}
diff --git a/src/common/util.h b/src/common/util.h
index ce773bd38..e793a42b5 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -238,4 +238,6 @@ namespace tools
#ifdef _WIN32
std::string input_line_win();
#endif
+
+ void closefrom(int fd);
}
diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp
index 5fcfa33f6..9e9c12605 100644
--- a/src/cryptonote_basic/cryptonote_format_utils.cpp
+++ b/src/cryptonote_basic/cryptonote_format_utils.cpp
@@ -199,6 +199,16 @@ namespace cryptonote
return true;
}
//---------------------------------------------------------------
+ bool parse_and_validate_tx_prefix_from_blob(const blobdata& tx_blob, transaction_prefix& tx)
+ {
+ std::stringstream ss;
+ ss << tx_blob;
+ binary_archive<false> ba(ss);
+ bool r = ::serialization::serialize_noeof(ba, tx);
+ CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction prefix from blob");
+ return true;
+ }
+ //---------------------------------------------------------------
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash)
{
std::stringstream ss;
diff --git a/src/cryptonote_basic/cryptonote_format_utils.h b/src/cryptonote_basic/cryptonote_format_utils.h
index bf71eb591..725c75f4e 100644
--- a/src/cryptonote_basic/cryptonote_format_utils.h
+++ b/src/cryptonote_basic/cryptonote_format_utils.h
@@ -48,6 +48,7 @@ namespace cryptonote
//---------------------------------------------------------------
void get_transaction_prefix_hash(const transaction_prefix& tx, crypto::hash& h);
crypto::hash get_transaction_prefix_hash(const transaction_prefix& tx);
+ bool parse_and_validate_tx_prefix_from_blob(const blobdata& tx_blob, transaction_prefix& tx);
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash);
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx);
bool parse_and_validate_tx_base_from_blob(const blobdata& tx_blob, transaction& tx);
diff --git a/src/cryptonote_basic/miner.cpp b/src/cryptonote_basic/miner.cpp
index 2bd43de94..d0b03593e 100644
--- a/src/cryptonote_basic/miner.cpp
+++ b/src/cryptonote_basic/miner.cpp
@@ -201,7 +201,7 @@ namespace cryptonote
float hr = static_cast<float>(total_hr)/static_cast<float>(m_last_hash_rates.size());
const auto flags = std::cout.flags();
const auto precision = std::cout.precision();
- std::cout << "hashrate: " << std::setprecision(4) << std::fixed << hr << flags << precision << ENDL;
+ std::cout << "hashrate: " << std::setprecision(4) << std::fixed << hr << std::setiosflags(flags) << std::setprecision(precision) << ENDL;
}
}
m_last_hr_merge_time = misc_utils::get_tick_count();
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp
index eb869b795..1ec2366e4 100644
--- a/src/cryptonote_core/blockchain.cpp
+++ b/src/cryptonote_core/blockchain.cpp
@@ -344,6 +344,9 @@ uint64_t Blockchain::get_current_blockchain_height() const
bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline, const cryptonote::test_options *test_options, difficulty_type fixed_difficulty)
{
LOG_PRINT_L3("Blockchain::" << __func__);
+
+ CHECK_AND_ASSERT_MES(nettype != FAKECHAIN || test_options, false, "fake chain network type used without options");
+
CRITICAL_REGION_LOCAL(m_tx_pool);
CRITICAL_REGION_LOCAL1(m_blockchain_lock);
@@ -2364,7 +2367,7 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context
const bool bulletproof = rct::is_rct_bulletproof(tx.rct_signatures.type);
if (bulletproof || !tx.rct_signatures.p.bulletproofs.empty())
{
- MERROR("Bulletproofs are not allowed before v8");
+ MERROR_VER("Bulletproofs are not allowed before v8");
tvc.m_invalid_output = true;
return false;
}
@@ -2377,7 +2380,7 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context
const bool borromean = rct::is_rct_borromean(tx.rct_signatures.type);
if (borromean)
{
- MERROR("Borromean range proofs are not allowed after v8");
+ MERROR_VER("Borromean range proofs are not allowed after v8");
tvc.m_invalid_output = true;
return false;
}
diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp
index 69e3c708b..2fec6b613 100644
--- a/src/cryptonote_core/cryptonote_core.cpp
+++ b/src/cryptonote_core/cryptonote_core.cpp
@@ -856,16 +856,19 @@ namespace cryptonote
}
waiter.wait(&tpool);
it = tx_blobs.begin();
+ std::vector<bool> already_have(tx_blobs.size(), false);
for (size_t i = 0; i < tx_blobs.size(); i++, ++it) {
if (!results[i].res)
continue;
if(m_mempool.have_tx(results[i].hash))
{
LOG_PRINT_L2("tx " << results[i].hash << "already have transaction in tx_pool");
+ already_have[i] = true;
}
else if(m_blockchain_storage.have_tx(results[i].hash))
{
LOG_PRINT_L2("tx " << results[i].hash << " already have transaction in blockchain");
+ already_have[i] = true;
}
else
{
@@ -887,7 +890,7 @@ namespace cryptonote
std::vector<tx_verification_batch_info> tx_info;
tx_info.reserve(tx_blobs.size());
for (size_t i = 0; i < tx_blobs.size(); i++) {
- if (!results[i].res)
+ if (!results[i].res || already_have[i])
continue;
tx_info.push_back({&results[i].tx, results[i].hash, tvc[i], results[i].res});
}
@@ -897,6 +900,8 @@ namespace cryptonote
bool ok = true;
it = tx_blobs.begin();
for (size_t i = 0; i < tx_blobs.size(); i++, ++it) {
+ if (already_have[i])
+ continue;
if (!results[i].res)
{
ok = false;
diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp
index c31a2073b..553a22298 100644
--- a/src/cryptonote_core/tx_pool.cpp
+++ b/src/cryptonote_core/tx_pool.cpp
@@ -250,7 +250,7 @@ namespace cryptonote
CRITICAL_REGION_LOCAL1(m_blockchain);
LockedTXN lock(m_blockchain);
m_blockchain.add_txpool_tx(tx, meta);
- if (!insert_key_images(tx, kept_by_block))
+ if (!insert_key_images(tx, id, kept_by_block))
return false;
m_txs_by_fee_and_receive_time.emplace(std::pair<double, std::time_t>(fee / (double)tx_weight, receive_time), id);
}
@@ -290,9 +290,10 @@ namespace cryptonote
{
CRITICAL_REGION_LOCAL1(m_blockchain);
LockedTXN lock(m_blockchain);
- m_blockchain.remove_txpool_tx(get_transaction_hash(tx));
+ const crypto::hash txid = get_transaction_hash(tx);
+ m_blockchain.remove_txpool_tx(txid);
m_blockchain.add_txpool_tx(tx, meta);
- if (!insert_key_images(tx, kept_by_block))
+ if (!insert_key_images(tx, txid, kept_by_block))
return false;
m_txs_by_fee_and_receive_time.emplace(std::pair<double, std::time_t>(fee / (double)tx_weight, receive_time), id);
}
@@ -371,8 +372,8 @@ namespace cryptonote
continue;
}
cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(txid);
- cryptonote::transaction tx;
- if (!parse_and_validate_tx_from_blob(txblob, tx))
+ cryptonote::transaction_prefix tx;
+ if (!parse_and_validate_tx_prefix_from_blob(txblob, tx))
{
MERROR("Failed to parse tx from txpool");
return;
@@ -381,7 +382,7 @@ namespace cryptonote
MINFO("Pruning tx " << txid << " from txpool: weight: " << it->first.second << ", fee/byte: " << it->first.first);
m_blockchain.remove_txpool_tx(txid);
m_txpool_weight -= it->first.second;
- remove_transaction_keyimages(tx);
+ remove_transaction_keyimages(tx, txid);
MINFO("Pruned tx " << txid << " from txpool: weight: " << it->first.second << ", fee/byte: " << it->first.first);
m_txs_by_fee_and_receive_time.erase(it--);
changed = true;
@@ -398,11 +399,10 @@ namespace cryptonote
MINFO("Pool weight after pruning is larger than limit: " << m_txpool_weight << "/" << bytes);
}
//---------------------------------------------------------------------------------
- bool tx_memory_pool::insert_key_images(const transaction &tx, bool kept_by_block)
+ bool tx_memory_pool::insert_key_images(const transaction_prefix &tx, const crypto::hash &id, bool kept_by_block)
{
for(const auto& in: tx.vin)
{
- const crypto::hash id = get_transaction_hash(tx);
CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, txin, false);
std::unordered_set<crypto::hash>& kei_image_set = m_spent_key_images[txin.k_image];
CHECK_AND_ASSERT_MES(kept_by_block || kei_image_set.size() == 0, false, "internal error: kept_by_block=" << kept_by_block
@@ -418,19 +418,17 @@ namespace cryptonote
//FIXME: Can return early before removal of all of the key images.
// At the least, need to make sure that a false return here
// is treated properly. Should probably not return early, however.
- bool tx_memory_pool::remove_transaction_keyimages(const transaction& tx)
+ bool tx_memory_pool::remove_transaction_keyimages(const transaction_prefix& tx, const crypto::hash &actual_hash)
{
CRITICAL_REGION_LOCAL(m_transactions_lock);
CRITICAL_REGION_LOCAL1(m_blockchain);
// ND: Speedup
- // 1. Move transaction hash calcuation outside of loop. ._.
- crypto::hash actual_hash = get_transaction_hash(tx);
for(const txin_v& vi: tx.vin)
{
CHECKED_GET_SPECIFIC_VARIANT(vi, const txin_to_key, txin, false);
auto it = m_spent_key_images.find(txin.k_image);
CHECK_AND_ASSERT_MES(it != m_spent_key_images.end(), false, "failed to find transaction input in key images. img=" << txin.k_image << ENDL
- << "transaction id = " << get_transaction_hash(tx));
+ << "transaction id = " << actual_hash);
std::unordered_set<crypto::hash>& key_image_set = it->second;
CHECK_AND_ASSERT_MES(key_image_set.size(), false, "empty key_image set, img=" << txin.k_image << ENDL
<< "transaction id = " << actual_hash);
@@ -483,7 +481,7 @@ namespace cryptonote
// remove first, in case this throws, so key images aren't removed
m_blockchain.remove_txpool_tx(id);
m_txpool_weight -= tx_weight;
- remove_transaction_keyimages(tx);
+ remove_transaction_keyimages(tx, id);
}
catch (const std::exception &e)
{
@@ -515,7 +513,7 @@ namespace cryptonote
{
CRITICAL_REGION_LOCAL(m_transactions_lock);
CRITICAL_REGION_LOCAL1(m_blockchain);
- std::unordered_set<crypto::hash> remove;
+ std::list<std::pair<crypto::hash, uint64_t>> remove;
m_blockchain.for_all_txpool_txes([this, &remove](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata*) {
uint64_t tx_age = time(nullptr) - meta.receive_time;
@@ -533,7 +531,7 @@ namespace cryptonote
m_txs_by_fee_and_receive_time.erase(sorted_it);
}
m_timed_out_transactions.insert(txid);
- remove.insert(txid);
+ remove.push_back(std::make_pair(txid, meta.weight));
}
return true;
}, false);
@@ -541,13 +539,14 @@ namespace cryptonote
if (!remove.empty())
{
LockedTXN lock(m_blockchain);
- for (const crypto::hash &txid: remove)
+ for (const std::pair<crypto::hash, uint64_t> &entry: remove)
{
+ const crypto::hash &txid = entry.first;
try
{
cryptonote::blobdata bd = m_blockchain.get_txpool_tx_blob(txid);
- cryptonote::transaction tx;
- if (!parse_and_validate_tx_from_blob(bd, tx))
+ cryptonote::transaction_prefix tx;
+ if (!parse_and_validate_tx_prefix_from_blob(bd, tx))
{
MERROR("Failed to parse tx from txpool");
// continue
@@ -556,8 +555,8 @@ namespace cryptonote
{
// remove first, so we only remove key images if the tx removal succeeds
m_blockchain.remove_txpool_tx(txid);
- m_txpool_weight -= get_transaction_weight(tx, bd.size());
- remove_transaction_keyimages(tx);
+ m_txpool_weight -= entry.second;
+ remove_transaction_keyimages(tx, txid);
}
}
catch (const std::exception &e)
@@ -1041,7 +1040,7 @@ namespace cryptonote
return true;
}
//---------------------------------------------------------------------------------
- bool tx_memory_pool::have_key_images(const std::unordered_set<crypto::key_image>& k_images, const transaction& tx)
+ bool tx_memory_pool::have_key_images(const std::unordered_set<crypto::key_image>& k_images, const transaction_prefix& tx)
{
for(size_t i = 0; i!= tx.vin.size(); i++)
{
@@ -1052,7 +1051,7 @@ namespace cryptonote
return false;
}
//---------------------------------------------------------------------------------
- bool tx_memory_pool::append_key_images(std::unordered_set<crypto::key_image>& k_images, const transaction& tx)
+ bool tx_memory_pool::append_key_images(std::unordered_set<crypto::key_image>& k_images, const transaction_prefix& tx)
{
for(size_t i = 0; i!= tx.vin.size(); i++)
{
@@ -1301,7 +1300,7 @@ namespace cryptonote
// remove tx from db first
m_blockchain.remove_txpool_tx(txid);
m_txpool_weight -= get_transaction_weight(tx, txblob.size());
- remove_transaction_keyimages(tx);
+ remove_transaction_keyimages(tx, txid);
auto sorted_it = find_tx_in_sorted_container(txid);
if (sorted_it == m_txs_by_fee_and_receive_time.end())
{
@@ -1344,14 +1343,14 @@ namespace cryptonote
bool r = m_blockchain.for_all_txpool_txes([this, &remove, kept](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd) {
if (!!kept != !!meta.kept_by_block)
return true;
- cryptonote::transaction tx;
- if (!parse_and_validate_tx_from_blob(*bd, tx))
+ cryptonote::transaction_prefix tx;
+ if (!parse_and_validate_tx_prefix_from_blob(*bd, tx))
{
MWARNING("Failed to parse tx from txpool, removing");
remove.push_back(txid);
return true;
}
- if (!insert_key_images(tx, meta.kept_by_block))
+ if (!insert_key_images(tx, txid, meta.kept_by_block))
{
MFATAL("Failed to insert key images from txpool tx");
return false;
diff --git a/src/cryptonote_core/tx_pool.h b/src/cryptonote_core/tx_pool.h
index 892cadc69..7a0cc23bf 100644
--- a/src/cryptonote_core/tx_pool.h
+++ b/src/cryptonote_core/tx_pool.h
@@ -434,7 +434,7 @@ namespace cryptonote
*
* @return true on success, false on error
*/
- bool insert_key_images(const transaction &tx, bool kept_by_block);
+ bool insert_key_images(const transaction_prefix &tx, const crypto::hash &txid, bool kept_by_block);
/**
* @brief remove old transactions from the pool
@@ -478,10 +478,11 @@ namespace cryptonote
* a transaction from the pool.
*
* @param tx the transaction
+ * @param txid the transaction's hash
*
* @return false if any key images to be removed cannot be found, otherwise true
*/
- bool remove_transaction_keyimages(const transaction& tx);
+ bool remove_transaction_keyimages(const transaction_prefix& tx, const crypto::hash &txid);
/**
* @brief check if any of a transaction's spent key images are present in a given set
@@ -491,7 +492,7 @@ namespace cryptonote
*
* @return true if any key images present in the set, otherwise false
*/
- static bool have_key_images(const std::unordered_set<crypto::key_image>& kic, const transaction& tx);
+ static bool have_key_images(const std::unordered_set<crypto::key_image>& kic, const transaction_prefix& tx);
/**
* @brief append the key images from a transaction to the given set
@@ -501,7 +502,7 @@ namespace cryptonote
*
* @return false if any append fails, otherwise true
*/
- static bool append_key_images(std::unordered_set<crypto::key_image>& kic, const transaction& tx);
+ static bool append_key_images(std::unordered_set<crypto::key_image>& kic, const transaction_prefix& tx);
/**
* @brief check if a transaction is a valid candidate for inclusion in a block
@@ -509,11 +510,11 @@ namespace cryptonote
* @param txd the transaction to check (and info about it)
* @param txid the txid of the transaction to check
* @param txblob the transaction blob to check
- * @param tx the parsed transaction, if successful
+ * @param tx the parsed transaction prefix, if successful
*
* @return true if the transaction is good to go, otherwise false
*/
- bool is_transaction_ready_to_go(txpool_tx_meta_t& txd, const crypto::hash &txid, const cryptonote::blobdata &txblob, transaction &tx) const;
+ bool is_transaction_ready_to_go(txpool_tx_meta_t& txd, const crypto::hash &txid, const cryptonote::blobdata &txblob, transaction&tx) const;
/**
* @brief mark all transactions double spending the one passed
diff --git a/src/daemon/daemon.cpp b/src/daemon/daemon.cpp
index ea24e32eb..49d6d49cf 100644
--- a/src/daemon/daemon.cpp
+++ b/src/daemon/daemon.cpp
@@ -136,7 +136,19 @@ bool t_daemon::run(bool interactive)
{
throw std::runtime_error{"Can't run stopped daemon"};
}
- tools::signal_handler::install(std::bind(&daemonize::t_daemon::stop_p2p, this));
+
+ std::atomic<bool> stop(false), shutdown(false);
+ boost::thread stop_thread = boost::thread([&stop, &shutdown, this] {
+ while (!stop)
+ epee::misc_utils::sleep_no_w(100);
+ if (shutdown)
+ this->stop_p2p();
+ });
+ epee::misc_utils::auto_scope_leave_caller scope_exit_handler = epee::misc_utils::create_scope_leave_handler([&](){
+ stop = true;
+ stop_thread.join();
+ });
+ tools::signal_handler::install([&stop, &shutdown](int){ stop = shutdown = true; });
try
{
diff --git a/src/daemonizer/windows_daemonizer.inl b/src/daemonizer/windows_daemonizer.inl
index 8077f29fb..7e61e3603 100644
--- a/src/daemonizer/windows_daemonizer.inl
+++ b/src/daemonizer/windows_daemonizer.inl
@@ -31,6 +31,7 @@
#include "common/util.h"
#include "daemonizer/windows_service.h"
#include "daemonizer/windows_service_runner.h"
+#include "cryptonote_core/cryptonote_core.h"
#include <shlobj.h>
#include <boost/filesystem/operations.hpp>
diff --git a/src/debug_utilities/object_sizes.cpp b/src/debug_utilities/object_sizes.cpp
index ab8839636..2281d0734 100644
--- a/src/debug_utilities/object_sizes.cpp
+++ b/src/debug_utilities/object_sizes.cpp
@@ -29,6 +29,7 @@
#include <map>
#include "cryptonote_basic/cryptonote_basic.h"
#include "cryptonote_basic/tx_extra.h"
+#include "cryptonote_core/cryptonote_core.h"
#include "cryptonote_core/blockchain.h"
#include "p2p/p2p_protocol_defs.h"
#include "net/connection_basic.hpp"
diff --git a/src/device/device_io_hid.cpp b/src/device/device_io_hid.cpp
index 562aca8b8..666255cb3 100644
--- a/src/device/device_io_hid.cpp
+++ b/src/device/device_io_hid.cpp
@@ -13,6 +13,7 @@
//
#if defined(HAVE_HIDAPI)
+#include <boost/scope_exit.hpp>
#include "log.hpp"
#include "device_io_hid.hpp"
@@ -69,11 +70,47 @@ namespace hw {
void device_io_hid::connect(void *params) {
hid_conn_params *p = (struct hid_conn_params*)params;
- this->connect(p->vid, p->pid, p->interface_number, p->usage_page, p->interface_OR_page);
+ this->connect(p->vid, p->pid, p->interface_number, p->usage_page);
}
- void device_io_hid::connect(unsigned int vid, unsigned int pid, unsigned int interface_number, unsigned int usage_page, bool interface_OR_page ) {
- hid_device_info *hwdev_info, *hwdev_info_list;
+ hid_device_info *device_io_hid::find_device(hid_device_info *devices_list, boost::optional<int> interface_number, boost::optional<unsigned short> usage_page) {
+ bool select_any = !interface_number && !usage_page;
+
+ MDEBUG( "Looking for " <<
+ (select_any ? "any HID Device" : "HID Device with") <<
+ (interface_number ? (" interface_number " + std::to_string(interface_number.value())) : "") <<
+ ((interface_number && usage_page) ? " or" : "") <<
+ (usage_page ? (" usage_page " + std::to_string(usage_page.value())) : ""));
+
+ hid_device_info *result = nullptr;
+ for (; devices_list != nullptr; devices_list = devices_list->next) {
+ BOOST_SCOPE_EXIT(&devices_list, &result) {
+ MDEBUG( (result == devices_list ? "SELECTED" : "SKIPPED ") <<
+ " HID Device" <<
+ " path " << safe_hid_path(devices_list) <<
+ " interface_number " << devices_list->interface_number <<
+ " usage_page " << devices_list->usage_page);
+ }
+ BOOST_SCOPE_EXIT_END
+
+ if (result != nullptr) {
+ continue;
+ }
+
+ if (select_any) {
+ result = devices_list;
+ } else if (interface_number && devices_list->interface_number == interface_number.value()) {
+ result = devices_list;
+ } else if (usage_page && devices_list->usage_page == usage_page.value()) {
+ result = devices_list;
+ }
+ }
+
+ return result;
+ }
+
+ void device_io_hid::connect(unsigned int vid, unsigned int pid, boost::optional<int> interface_number, boost::optional<unsigned short> usage_page) {
+ hid_device_info *hwdev_info_list;
hid_device *hwdev;
this->disconnect();
@@ -81,17 +118,8 @@ namespace hw {
hwdev_info_list = hid_enumerate(vid, pid);
ASSERT_X(hwdev_info_list, "Unable to enumerate device "+std::to_string(vid)+":"+std::to_string(vid)+ ": "+ safe_hid_error(this->usb_device));
hwdev = NULL;
- hwdev_info = hwdev_info_list;
- while (hwdev_info) {
- if ((interface_OR_page && ((usage_page == 0xffa0) || (interface_number == 0))) ||
- ((usage_page == 0xffa0) && (interface_number == 0)) ) {
- MDEBUG("HID Device found: " << safe_hid_path(hwdev_info));
- hwdev = hid_open_path(hwdev_info->path);
- break;
- } else {
- MDEBUG("HID Device discard: " << safe_hid_path(hwdev_info) << "("+std::to_string(hwdev_info->usage_page) << "," << std::to_string(hwdev_info->interface_number) << ")");
- }
- hwdev_info = hwdev_info->next;
+ if (hid_device_info *device = find_device(hwdev_info_list, interface_number, usage_page)) {
+ hwdev = hid_open_path(device->path);
}
hid_free_enumeration(hwdev_info_list);
ASSERT_X(hwdev, "Unable to open device "+std::to_string(pid)+":"+std::to_string(vid));
diff --git a/src/device/device_io_hid.hpp b/src/device/device_io_hid.hpp
index 6fd15a1d1..bb0f0a814 100644
--- a/src/device/device_io_hid.hpp
+++ b/src/device/device_io_hid.hpp
@@ -29,6 +29,7 @@
#if defined(HAVE_HIDAPI)
+#include <boost/optional/optional.hpp>
#include <hidapi/hidapi.h>
#include "device_io.hpp"
@@ -52,9 +53,8 @@ namespace hw {
struct hid_conn_params {
unsigned int vid;
unsigned int pid;
- unsigned int interface_number;
- unsigned int usage_page;
- bool interface_OR_page ;
+ int interface_number;
+ unsigned short usage_page;
};
@@ -82,13 +82,11 @@ namespace hw {
unsigned int wrapCommand(const unsigned char *command, size_t command_len, unsigned char *out, size_t out_len);
unsigned int unwrapReponse(const unsigned char *data, size_t data_len, unsigned char *out, size_t out_len);
+ hid_device_info *find_device(hid_device_info *devices_list, boost::optional<int> interface_number, boost::optional<unsigned short> usage_page);
public:
bool hid_verbose = false;
- static const unsigned int OR_SELECT = 1;
- static const unsigned int AND_SELECT = 2;
-
static const unsigned short DEFAULT_CHANNEL = 0x0001;
static const unsigned char DEFAULT_TAG = 0x01;
static const unsigned int DEFAULT_PACKET_SIZE = 64;
@@ -100,7 +98,7 @@ namespace hw {
void init();
void connect(void *params);
- void connect(unsigned int vid, unsigned int pid, unsigned int interface_number, unsigned int usage_page, bool interface_OR_page );
+ void connect(unsigned int vid, unsigned int pid, boost::optional<int> interface_number, boost::optional<unsigned short> usage_page);
bool connected() const;
int exchange(unsigned char *command, unsigned int cmd_len, unsigned char *response, unsigned int max_resp_len);
void disconnect();
diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp
index a17784960..d879ee95a 100644
--- a/src/device/device_ledger.cpp
+++ b/src/device/device_ledger.cpp
@@ -340,7 +340,7 @@ namespace hw {
bool device_ledger::connect(void) {
this->disconnect();
- hw_device.connect(0x2c97,0x0001, 0, 0xffa0, hw_device.OR_SELECT);
+ hw_device.connect(0x2c97, 0x0001, 0, 0xffa0);
this->reset();
#ifdef DEBUG_HWDEVICE
cryptonote::account_public_address pubkey;
diff --git a/src/p2p/net_node.cpp b/src/p2p/net_node.cpp
index c9ca63f43..e9d2061e8 100644
--- a/src/p2p/net_node.cpp
+++ b/src/p2p/net_node.cpp
@@ -29,6 +29,7 @@
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#include "common/command_line.h"
+#include "cryptonote_core/cryptonote_core.h"
#include "net_node.h"
namespace nodetool
diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl
index 74924e4f4..9390626a8 100644
--- a/src/p2p/net_node.inl
+++ b/src/p2p/net_node.inl
@@ -937,7 +937,7 @@ namespace nodetool
bool res = m_net_server.connect(epee::string_tools::get_ip_string_from_int32(ipv4.ip()),
epee::string_tools::num_to_string_fast(ipv4.port()),
m_config.m_net_config.connection_timeout,
- con, m_bind_ip.empty() ? "0.0.0.0" : m_bind_ip);
+ con);
if(!res)
{
@@ -1002,7 +1002,7 @@ namespace nodetool
bool res = m_net_server.connect(epee::string_tools::get_ip_string_from_int32(ipv4.ip()),
epee::string_tools::num_to_string_fast(ipv4.port()),
m_config.m_net_config.connection_timeout,
- con, m_bind_ip.empty() ? "0.0.0.0" : m_bind_ip);
+ con);
if (!res) {
bool is_priority = is_priority_node(na);
@@ -1617,7 +1617,7 @@ namespace nodetool
return false;
}
return true;
- }, m_bind_ip.empty() ? "0.0.0.0" : m_bind_ip);
+ });
if(!r)
{
LOG_WARNING_CC(context, "Failed to call connect_async, network error.");
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index be511a2d2..55ee66a79 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -924,6 +924,8 @@ namespace cryptonote
return r;
m_core.get_pool_transactions_and_spent_keys_info(res.transactions, res.spent_key_images, !request_has_rpc_origin || !m_restricted);
+ for (tx_info& txi : res.transactions)
+ txi.tx_blob = epee::string_tools::buff_to_hex_nodelimer(txi.tx_blob);
res.status = CORE_RPC_STATUS_OK;
return true;
}
@@ -1090,7 +1092,7 @@ namespace cryptonote
{
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
error_resp.message = "Internal error: failed to create block template";
- LOG_ERROR("Failed to tx pub key in coinbase extra");
+ LOG_ERROR("Failed to get tx pub key in coinbase extra");
return false;
}
res.reserved_offset = slow_memmem((void*)block_blob.data(), block_blob.size(), &tx_pub_key, sizeof(tx_pub_key));
@@ -2118,6 +2120,8 @@ namespace cryptonote
try
{
+ // 0 is placeholder for the whole chain
+ const uint64_t req_to_height = req.to_height ? req.to_height : (m_core.get_current_blockchain_height() - 1);
for (uint64_t amount: req.amounts)
{
static struct D
@@ -2130,7 +2134,7 @@ namespace cryptonote
} d;
boost::unique_lock<boost::mutex> lock(d.mutex);
- if (d.cached && amount == 0 && d.cached_from == req.from_height && d.cached_to == req.to_height)
+ if (d.cached && amount == 0 && d.cached_from == req.from_height && d.cached_to == req_to_height)
{
res.distributions.push_back({amount, d.cached_start_height, req.binary, d.cached_distribution, d.cached_base});
if (!req.cumulative)
@@ -2145,23 +2149,23 @@ namespace cryptonote
std::vector<uint64_t> distribution;
uint64_t start_height, base;
- if (!m_core.get_output_distribution(amount, req.from_height, req.to_height, start_height, distribution, base))
+ if (!m_core.get_output_distribution(amount, req.from_height, req_to_height, start_height, distribution, base))
{
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
error_resp.message = "Failed to get rct distribution";
return false;
}
- if (req.to_height > 0 && req.to_height >= req.from_height)
+ if (req_to_height > 0 && req_to_height >= req.from_height)
{
uint64_t offset = std::max(req.from_height, start_height);
- if (offset <= req.to_height && req.to_height - offset + 1 < distribution.size())
- distribution.resize(req.to_height - offset + 1);
+ if (offset <= req_to_height && req_to_height - offset + 1 < distribution.size())
+ distribution.resize(req_to_height - offset + 1);
}
if (amount == 0)
{
d.cached_from = req.from_height;
- d.cached_to = req.to_height;
+ d.cached_to = req_to_height;
d.cached_distribution = distribution;
d.cached_start_height = start_height;
d.cached_base = base;
diff --git a/src/rpc/daemon_messages.h b/src/rpc/daemon_messages.h
index 8fff369df..be3138e3b 100644
--- a/src/rpc/daemon_messages.h
+++ b/src/rpc/daemon_messages.h
@@ -67,7 +67,7 @@ class classname \
// NOTE: when using a type with multiple template parameters,
// replace any comma in the template specifier with the macro
// above, or the preprocessor will eat the comma in a bad way.
-#define RPC_MESSAGE_MEMBER(type, name) type name;
+#define RPC_MESSAGE_MEMBER(type, name) type name = type{}
namespace cryptonote
diff --git a/src/serialization/serialization.h b/src/serialization/serialization.h
index 5fc382a1e..2050e88e2 100644
--- a/src/serialization/serialization.h
+++ b/src/serialization/serialization.h
@@ -318,7 +318,7 @@ namespace serialization {
* \brief self explanatory
*/
template<class Stream>
- bool do_check_stream_state(Stream& s, boost::mpl::bool_<true>)
+ bool do_check_stream_state(Stream& s, boost::mpl::bool_<true>, bool noeof)
{
return s.good();
}
@@ -329,13 +329,13 @@ namespace serialization {
* \detailed Also checks to make sure that the stream is not at EOF
*/
template<class Stream>
- bool do_check_stream_state(Stream& s, boost::mpl::bool_<false>)
+ bool do_check_stream_state(Stream& s, boost::mpl::bool_<false>, bool noeof)
{
bool result = false;
if (s.good())
{
std::ios_base::iostate state = s.rdstate();
- result = EOF == s.peek();
+ result = noeof || EOF == s.peek();
s.clear(state);
}
return result;
@@ -347,9 +347,9 @@ namespace serialization {
* \brief calls detail::do_check_stream_state for ar
*/
template<class Archive>
- bool check_stream_state(Archive& ar)
+ bool check_stream_state(Archive& ar, bool noeof = false)
{
- return detail::do_check_stream_state(ar.stream(), typename Archive::is_saving());
+ return detail::do_check_stream_state(ar.stream(), typename Archive::is_saving(), noeof);
}
/*! \fn serialize
@@ -360,6 +360,17 @@ namespace serialization {
inline bool serialize(Archive &ar, T &v)
{
bool r = do_serialize(ar, v);
- return r && check_stream_state(ar);
+ return r && check_stream_state(ar, false);
+ }
+
+ /*! \fn serialize
+ *
+ * \brief serializes \a v into \a ar
+ */
+ template <class Archive, class T>
+ inline bool serialize_noeof(Archive &ar, T &v)
+ {
+ bool r = do_serialize(ar, v);
+ return r && check_stream_state(ar, true);
}
}
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index 4ec7e3eb4..18b596662 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -1640,7 +1640,7 @@ bool simple_wallet::blackball(const std::vector<std::string> &args)
uint64_t amount = std::numeric_limits<uint64_t>::max(), offset, num_offsets;
if (args.size() == 0)
{
- fail_msg_writer() << tr("usage: blackball <amount>/<offset> | <filename> [add]");
+ fail_msg_writer() << tr("usage: mark_output_spent <amount>/<offset> | <filename> [add]");
return true;
}
@@ -1718,7 +1718,7 @@ bool simple_wallet::blackball(const std::vector<std::string> &args)
}
catch (const std::exception &e)
{
- fail_msg_writer() << tr("Failed to blackball output: ") << e.what();
+ fail_msg_writer() << tr("Failed to mark output spent: ") << e.what();
}
return true;
@@ -1729,7 +1729,7 @@ bool simple_wallet::unblackball(const std::vector<std::string> &args)
std::pair<uint64_t, uint64_t> output;
if (args.size() != 1)
{
- fail_msg_writer() << tr("usage: unblackball <amount>/<offset>");
+ fail_msg_writer() << tr("usage: mark_output_unspent <amount>/<offset>");
return true;
}
@@ -1745,7 +1745,7 @@ bool simple_wallet::unblackball(const std::vector<std::string> &args)
}
catch (const std::exception &e)
{
- fail_msg_writer() << tr("Failed to unblackball output: ") << e.what();
+ fail_msg_writer() << tr("Failed to mark output unspent: ") << e.what();
}
return true;
@@ -1756,7 +1756,7 @@ bool simple_wallet::blackballed(const std::vector<std::string> &args)
std::pair<uint64_t, uint64_t> output;
if (args.size() != 1)
{
- fail_msg_writer() << tr("usage: blackballed <amount>/<offset>");
+ fail_msg_writer() << tr("usage: is_output_spent <amount>/<offset>");
return true;
}
@@ -1769,13 +1769,13 @@ bool simple_wallet::blackballed(const std::vector<std::string> &args)
try
{
if (m_wallet->is_output_blackballed(output))
- message_writer() << tr("Blackballed: ") << output.first << "/" << output.second;
+ message_writer() << tr("Spent: ") << output.first << "/" << output.second;
else
- message_writer() << tr("not blackballed: ") << output.first << "/" << output.second;
+ message_writer() << tr("Not spent: ") << output.first << "/" << output.second;
}
catch (const std::exception &e)
{
- fail_msg_writer() << tr("Failed to unblackball output: ") << e.what();
+ fail_msg_writer() << tr("Failed to check whether output is spent: ") << e.what();
}
return true;
@@ -2403,7 +2403,7 @@ simple_wallet::simple_wallet()
"store-tx-info <1|0>\n "
" Whether to store outgoing tx info (destination address, payment ID, tx secret key) for future reference.\n "
"default-ring-size <n>\n "
- " Set the default ring size (default and minimum is 5).\n "
+ " Set the default ring size (obsolete).\n "
"auto-refresh <1|0>\n "
" Whether to automatically synchronize new blocks from the daemon.\n "
"refresh-type <full|optimize-coinbase|no-coinbase|default>\n "
@@ -2599,18 +2599,18 @@ simple_wallet::simple_wallet()
boost::bind(&simple_wallet::save_known_rings, this, _1),
tr("save_known_rings"),
tr("Save known rings to the shared rings database"));
- m_cmd_binder.set_handler("blackball",
+ m_cmd_binder.set_handler("mark_output_spent",
boost::bind(&simple_wallet::blackball, this, _1),
- tr("blackball <amount>/<offset> | <filename> [add]"),
- tr("Blackball output(s) so they never get selected as fake outputs in a ring"));
- m_cmd_binder.set_handler("unblackball",
+ tr("mark_output_spent <amount>/<offset> | <filename> [add]"),
+ tr("Mark output(s) as spent so they never get selected as fake outputs in a ring"));
+ m_cmd_binder.set_handler("mark_output_unspent",
boost::bind(&simple_wallet::unblackball, this, _1),
- tr("unblackball <amount>/<offset>"),
- tr("Unblackballs an output so it may get selected as a fake output in a ring"));
- m_cmd_binder.set_handler("blackballed",
+ tr("mark_output_unspent <amount>/<offset>"),
+ tr("Marks an output as unspent so it may get selected as a fake output in a ring"));
+ m_cmd_binder.set_handler("is_output_spent",
boost::bind(&simple_wallet::blackballed, this, _1),
- tr("blackballed <amount>/<offset>"),
- tr("Checks whether an output is blackballed"));
+ tr("is_output_spent <amount>/<offset>"),
+ tr("Checks whether an output is marked as spent"));
m_cmd_binder.set_handler("version",
boost::bind(&simple_wallet::version, this, _1),
tr("version"),
@@ -3032,7 +3032,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
return false;
}
crypto::secret_key viewkey;
- if (viewkey_string.hex_to_pod(unwrap(unwrap(viewkey))))
+ if (!viewkey_string.hex_to_pod(unwrap(unwrap(viewkey))))
{
fail_msg_writer() << tr("failed to parse view key secret key");
return false;
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index de1bfdae1..1b4370c36 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -776,7 +776,7 @@ bool WalletImpl::setPassword(const std::string &password)
{
clearStatus();
try {
- m_wallet->rewrite(m_wallet->get_wallet_file(), password);
+ m_wallet->change_password(m_wallet->get_wallet_file(), m_password, password);
m_password = password;
} catch (const std::exception &e) {
setStatusError(e.what());
@@ -2161,7 +2161,7 @@ bool WalletImpl::blackballOutputs(const std::vector<std::string> &outputs, bool
bool ret = m_wallet->set_blackballed_outputs(raw_outputs, add);
if (!ret)
{
- setStatusError(tr("Failed to set blackballed outputs"));
+ setStatusError(tr("Failed to mark outputs as spent"));
return false;
}
return true;
@@ -2183,7 +2183,7 @@ bool WalletImpl::blackballOutput(const std::string &amount, const std::string &o
bool ret = m_wallet->blackball_output(std::make_pair(raw_amount, raw_offset));
if (!ret)
{
- setStatusError(tr("Failed to blackball output"));
+ setStatusError(tr("Failed to mark output as spent"));
return false;
}
return true;
@@ -2205,7 +2205,7 @@ bool WalletImpl::unblackballOutput(const std::string &amount, const std::string
bool ret = m_wallet->unblackball_output(std::make_pair(raw_amount, raw_offset));
if (!ret)
{
- setStatusError(tr("Failed to unblackball output"));
+ setStatusError(tr("Failed to mark output as unspent"));
return false;
}
return true;
diff --git a/src/wallet/ringdb.cpp b/src/wallet/ringdb.cpp
index e5995e7fb..f562d6c06 100644
--- a/src/wallet/ringdb.cpp
+++ b/src/wallet/ringdb.cpp
@@ -412,13 +412,13 @@ bool ringdb::blackball_worker(const std::vector<std::pair<uint64_t, uint64_t>> &
switch (op)
{
case BLACKBALL_BLACKBALL:
- MDEBUG("Blackballing output " << output.first << "/" << output.second);
+ MDEBUG("Marking output " << output.first << "/" << output.second << " as spent");
dbr = mdb_cursor_put(cursor, &key, &data, MDB_APPENDDUP);
if (dbr == MDB_KEYEXIST)
dbr = 0;
break;
case BLACKBALL_UNBLACKBALL:
- MDEBUG("Unblackballing output " << output.first << "/" << output.second);
+ MDEBUG("Marking output " << output.first << "/" << output.second << " as unspent");
dbr = mdb_cursor_get(cursor, &key, &data, MDB_GET_BOTH);
if (dbr == 0)
dbr = mdb_cursor_del(cursor, 0);
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index f87edf506..6b3a8533e 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -37,6 +37,8 @@
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/split.hpp>
+#include <boost/algorithm/string/join.hpp>
+#include <boost/range/adaptor/transformed.hpp>
#include "include_base_utils.h"
using namespace epee;
@@ -3611,6 +3613,7 @@ bool wallet2::query_device(hw::device::device_type& device_type, const std::stri
if (json.Parse(account_data.c_str()).HasParseError() || !json.IsObject())
crypto::chacha8(keys_file_data.account_data.data(), keys_file_data.account_data.size(), key, keys_file_data.iv, &account_data[0]);
+ device_type = hw::device::device_type::SOFTWARE;
// The contents should be JSON if the wallet follows the new format.
if (json.Parse(account_data.c_str()).HasParseError())
{
@@ -6965,6 +6968,8 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
LOG_PRINT_L1("Selecting real output: " << td.m_global_output_index << " for " << print_money(amount));
}
+ std::unordered_map<const char*, std::set<uint64_t>> picks;
+
// while we still need more mixins
uint64_t num_usable_outs = num_outs;
bool allow_blackballed = false;
@@ -6979,7 +6984,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
// outputs, we still need to reach the minimum ring size)
if (allow_blackballed)
break;
- MINFO("Not enough non blackballed outputs, we'll allow blackballed ones");
+ MINFO("Not enough output not marked as spent, we'll allow outputs marked as spent");
allow_blackballed = true;
num_usable_outs = num_outs;
}
@@ -7063,11 +7068,15 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
}
seen_indices.emplace(i);
- LOG_PRINT_L2("picking " << i << " as " << type);
+ picks[type].insert(i);
req.outputs.push_back({amount, i});
++num_found;
}
+ for (const auto &pick: picks)
+ MDEBUG("picking " << pick.first << " outputs: " <<
+ boost::join(pick.second | boost::adaptors::transformed([](uint64_t out){return std::to_string(out);}), " "));
+
// if we had enough unusable outputs, we might fall off here and still
// have too few outputs, so we stuff with one to keep counts good, and
// we'll error out later
@@ -7083,8 +7092,15 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
[](const get_outputs_out &a, const get_outputs_out &b) { return a.index < b.index; });
}
- for (auto i: req.outputs)
- LOG_PRINT_L1("asking for output " << i.index << " for " << print_money(i.amount));
+ if (ELPP->vRegistry()->allowed(el::Level::Debug, MONERO_DEFAULT_LOG_CATEGORY))
+ {
+ std::map<uint64_t, std::set<uint64_t>> outs;
+ for (const auto &i: req.outputs)
+ outs[i.amount].insert(i.index);
+ for (const auto &o: outs)
+ MDEBUG("asking for outputs with amount " << print_money(o.first) << ": " <<
+ boost::join(o.second | boost::adaptors::transformed([](uint64_t out){return std::to_string(out);}), " "));
+ }
// get the keys for those
m_daemon_rpc_mutex.lock();
diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index e0b631aaf..1b63d65b6 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -2822,8 +2822,7 @@ namespace tools
{
try
{
- m_wallet->rewrite(m_wallet->get_wallet_file(), req.new_password);
- m_wallet->store();
+ m_wallet->change_password(m_wallet->get_wallet_file(), req.old_password, req.new_password);
LOG_PRINT_L0("Wallet password changed.");
}
catch (const std::exception& e)
diff --git a/src/wallet/wallet_rpc_server.h b/src/wallet/wallet_rpc_server.h
index ab896aa3b..35ea11902 100644
--- a/src/wallet/wallet_rpc_server.h
+++ b/src/wallet/wallet_rpc_server.h
@@ -35,6 +35,7 @@
#include <string>
#include "common/util.h"
#include "net/http_server_impl_base.h"
+#include "math_helper.h"
#include "wallet_rpc_server_commands_defs.h"
#include "wallet2.h"
diff --git a/tests/crypto/main.cpp b/tests/crypto/main.cpp
index e5406f771..cc3b53b83 100644
--- a/tests/crypto/main.cpp
+++ b/tests/crypto/main.cpp
@@ -35,6 +35,7 @@
#include <vector>
#include "warnings.h"
+#include "misc_log_ex.h"
#include "crypto/crypto.h"
#include "crypto/hash.h"
#include "crypto-tests.h"
@@ -59,6 +60,7 @@ bool operator !=(const key_derivation &a, const key_derivation &b) {
DISABLE_GCC_WARNING(maybe-uninitialized)
int main(int argc, char *argv[]) {
+ TRY_ENTRY();
fstream input;
string cmd;
size_t test = 0;
@@ -266,4 +268,5 @@ error:
error = true;
}
return error ? 1 : 0;
+ CATCH_ENTRY_L0("main", 1);
}
diff --git a/tests/functional_tests/CMakeLists.txt b/tests/functional_tests/CMakeLists.txt
index 4b21b945c..7a2a7fbd1 100644
--- a/tests/functional_tests/CMakeLists.txt
+++ b/tests/functional_tests/CMakeLists.txt
@@ -26,10 +26,6 @@
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-if(WIN32)
- set(EXTRA_LIBRARIES "${EXTRA_LIBRARIES};bcrypt")
-endif()
-
set(functional_tests_sources
main.cpp
transactions_flow_test.cpp
diff --git a/tests/fuzz/base58.cpp b/tests/fuzz/base58.cpp
index 49516dd83..a4857bdd1 100644
--- a/tests/fuzz/base58.cpp
+++ b/tests/fuzz/base58.cpp
@@ -68,7 +68,9 @@ int Base58Fuzzer::run(const std::string &filename)
int main(int argc, const char **argv)
{
+ TRY_ENTRY();
Base58Fuzzer fuzzer;
return run_fuzzer(argc, argv, fuzzer);
+ CATCH_ENTRY_L0("main", 1);
}
diff --git a/tests/fuzz/block.cpp b/tests/fuzz/block.cpp
index 2df77b046..eed3b94b2 100644
--- a/tests/fuzz/block.cpp
+++ b/tests/fuzz/block.cpp
@@ -61,6 +61,8 @@ int BlockFuzzer::run(const std::string &filename)
int main(int argc, const char **argv)
{
+ TRY_ENTRY();
BlockFuzzer fuzzer;
return run_fuzzer(argc, argv, fuzzer);
+ CATCH_ENTRY_L0("main", 1);
}
diff --git a/tests/fuzz/bulletproof.cpp b/tests/fuzz/bulletproof.cpp
index 2f4dfd0ea..2f3a2f8d1 100644
--- a/tests/fuzz/bulletproof.cpp
+++ b/tests/fuzz/bulletproof.cpp
@@ -65,6 +65,8 @@ int BulletproofFuzzer::run(const std::string &filename)
int main(int argc, const char **argv)
{
+ TRY_ENTRY();
BulletproofFuzzer fuzzer;
return run_fuzzer(argc, argv, fuzzer);
+ CATCH_ENTRY_L0("main", 1);
}
diff --git a/tests/fuzz/cold-outputs.cpp b/tests/fuzz/cold-outputs.cpp
index 59b59810c..488a3b931 100644
--- a/tests/fuzz/cold-outputs.cpp
+++ b/tests/fuzz/cold-outputs.cpp
@@ -95,7 +95,9 @@ int ColdOutputsFuzzer::run(const std::string &filename)
int main(int argc, const char **argv)
{
+ TRY_ENTRY();
ColdOutputsFuzzer fuzzer;
return run_fuzzer(argc, argv, fuzzer);
+ CATCH_ENTRY_L0("main", 1);
}
diff --git a/tests/fuzz/cold-transaction.cpp b/tests/fuzz/cold-transaction.cpp
index da33dc318..fa3041ba3 100644
--- a/tests/fuzz/cold-transaction.cpp
+++ b/tests/fuzz/cold-transaction.cpp
@@ -97,6 +97,8 @@ int ColdTransactionFuzzer::run(const std::string &filename)
int main(int argc, const char **argv)
{
+ TRY_ENTRY();
ColdTransactionFuzzer fuzzer;
return run_fuzzer(argc, argv, fuzzer);
+ CATCH_ENTRY_L0("main", 1);
}
diff --git a/tests/fuzz/http-client.cpp b/tests/fuzz/http-client.cpp
index cd52643d9..909325832 100644
--- a/tests/fuzz/http-client.cpp
+++ b/tests/fuzz/http-client.cpp
@@ -92,7 +92,9 @@ int HTTPClientFuzzer::run(const std::string &filename)
int main(int argc, const char **argv)
{
+ TRY_ENTRY();
HTTPClientFuzzer fuzzer;
return run_fuzzer(argc, argv, fuzzer);
+ CATCH_ENTRY_L0("main", 1);
}
diff --git a/tests/fuzz/levin.cpp b/tests/fuzz/levin.cpp
index 4ced1837f..d0c5803f5 100644
--- a/tests/fuzz/levin.cpp
+++ b/tests/fuzz/levin.cpp
@@ -341,7 +341,9 @@ int LevinFuzzer::run(const std::string &filename)
int main(int argc, const char **argv)
{
+ TRY_ENTRY();
LevinFuzzer fuzzer;
return run_fuzzer(argc, argv, fuzzer);
+ CATCH_ENTRY_L0("main", 1);
}
diff --git a/tests/fuzz/load_from_binary.cpp b/tests/fuzz/load_from_binary.cpp
index 8f96c454f..89f122902 100644
--- a/tests/fuzz/load_from_binary.cpp
+++ b/tests/fuzz/load_from_binary.cpp
@@ -70,7 +70,9 @@ int PortableStorageFuzzer::run(const std::string &filename)
int main(int argc, const char **argv)
{
+ TRY_ENTRY();
PortableStorageFuzzer fuzzer;
return run_fuzzer(argc, argv, fuzzer);
+ CATCH_ENTRY_L0("main", 1);
}
diff --git a/tests/fuzz/load_from_json.cpp b/tests/fuzz/load_from_json.cpp
index b0c1a9bf3..083555f7e 100644
--- a/tests/fuzz/load_from_json.cpp
+++ b/tests/fuzz/load_from_json.cpp
@@ -70,7 +70,9 @@ int PortableStorageFuzzer::run(const std::string &filename)
int main(int argc, const char **argv)
{
+ TRY_ENTRY();
PortableStorageFuzzer fuzzer;
return run_fuzzer(argc, argv, fuzzer);
+ CATCH_ENTRY_L0("main", 1);
}
diff --git a/tests/fuzz/parse_url.cpp b/tests/fuzz/parse_url.cpp
index 8812cf9c2..fb5754a70 100644
--- a/tests/fuzz/parse_url.cpp
+++ b/tests/fuzz/parse_url.cpp
@@ -68,7 +68,9 @@ int ParseURLFuzzer::run(const std::string &filename)
int main(int argc, const char **argv)
{
+ TRY_ENTRY();
ParseURLFuzzer fuzzer;
return run_fuzzer(argc, argv, fuzzer);
+ CATCH_ENTRY_L0("main", 1);
}
diff --git a/tests/fuzz/signature.cpp b/tests/fuzz/signature.cpp
index 6dadf960d..f82ada8b4 100644
--- a/tests/fuzz/signature.cpp
+++ b/tests/fuzz/signature.cpp
@@ -92,6 +92,8 @@ int SignatureFuzzer::run(const std::string &filename)
int main(int argc, const char **argv)
{
+ TRY_ENTRY();
SignatureFuzzer fuzzer;
return run_fuzzer(argc, argv, fuzzer);
+ CATCH_ENTRY_L0("main", 1);
}
diff --git a/tests/fuzz/transaction.cpp b/tests/fuzz/transaction.cpp
index b3349c383..934bd4685 100644
--- a/tests/fuzz/transaction.cpp
+++ b/tests/fuzz/transaction.cpp
@@ -61,6 +61,8 @@ int TransactionFuzzer::run(const std::string &filename)
int main(int argc, const char **argv)
{
+ TRY_ENTRY();
TransactionFuzzer fuzzer;
return run_fuzzer(argc, argv, fuzzer);
+ CATCH_ENTRY_L0("main", 1);
}
diff --git a/tests/net_load_tests/clt.cpp b/tests/net_load_tests/clt.cpp
index a65e02cab..77cce2be7 100644
--- a/tests/net_load_tests/clt.cpp
+++ b/tests/net_load_tests/clt.cpp
@@ -41,6 +41,7 @@
#include "misc_language.h"
#include "misc_log_ex.h"
#include "storages/levin_abstract_invoke2.h"
+#include "common/util.h"
#include "net_load_tests.h"
@@ -628,6 +629,7 @@ TEST_F(net_load_test_clt, permament_open_and_close_and_connections_closed_by_ser
int main(int argc, char** argv)
{
+ TRY_ENTRY();
tools::on_startup();
epee::debug::get_set_enable_assert(true, false);
//set up logging options
@@ -635,4 +637,5 @@ int main(int argc, char** argv)
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
+ CATCH_ENTRY_L0("main", 1);
}
diff --git a/tests/net_load_tests/srv.cpp b/tests/net_load_tests/srv.cpp
index 6518d9117..092c6955c 100644
--- a/tests/net_load_tests/srv.cpp
+++ b/tests/net_load_tests/srv.cpp
@@ -34,6 +34,7 @@
#include "include_base_utils.h"
#include "misc_log_ex.h"
#include "storages/levin_abstract_invoke2.h"
+#include "common/util.h"
#include "net_load_tests.h"
@@ -215,6 +216,7 @@ namespace
int main(int argc, char** argv)
{
+ TRY_ENTRY();
tools::on_startup();
//set up logging options
mlog_configure(mlog_get_default_log_path("net_load_tests_srv.log"), true);
@@ -233,4 +235,5 @@ int main(int argc, char** argv)
if (!tcp_server.run_server(thread_count, true))
return 2;
return 0;
+ CATCH_ENTRY_L0("main", 1);
}
diff --git a/tests/unit_tests/CMakeLists.txt b/tests/unit_tests/CMakeLists.txt
index d6bcbde46..e248ed965 100644
--- a/tests/unit_tests/CMakeLists.txt
+++ b/tests/unit_tests/CMakeLists.txt
@@ -61,6 +61,7 @@ set(unit_tests_sources
mul_div.cpp
multiexp.cpp
multisig.cpp
+ notify.cpp
parse_amount.cpp
random.cpp
serialization.cpp
@@ -122,4 +123,8 @@ SET_PROPERTY(SOURCE memwipe.cpp PROPERTY COMPILE_FLAGS -Ofast)
add_test(
NAME unit_tests
- COMMAND unit_tests --data-dir "${TEST_DATA_DIR}")
+ COMMAND unit_tests --data-dir "${TEST_DATA_DIR} --binary-dir ${CMAKE_BINARY_DIR}")
+
+add_executable(test_notifier test_notifier.cpp)
+target_link_libraries(test_notifier ${EXTRA_LIBRARIES})
+set_property(TARGET test_notifier PROPERTY FOLDER "tests")
diff --git a/tests/unit_tests/aligned.cpp b/tests/unit_tests/aligned.cpp
index ad4837bec..2b733faf2 100644
--- a/tests/unit_tests/aligned.cpp
+++ b/tests/unit_tests/aligned.cpp
@@ -84,3 +84,24 @@ TEST(aligned, contents_smaller)
aligned_free(ptr2);
}
+TEST(aligned, alignment)
+{
+ static const size_t good_alignments[] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192};
+ for (size_t a = 0; a <= 8192; ++a)
+ {
+ bool good = false;
+ for (const auto t: good_alignments) if (a == t) good = true;
+ void *ptr = aligned_malloc(1, a);
+ if (good)
+ {
+ ASSERT_TRUE(ptr != NULL);
+ aligned_free(ptr);
+ }
+ else
+ {
+ ASSERT_TRUE(ptr == NULL);
+ }
+ }
+
+ ASSERT_TRUE(aligned_malloc(1, ~0) == NULL);
+}
diff --git a/tests/unit_tests/notify.cpp b/tests/unit_tests/notify.cpp
new file mode 100644
index 000000000..d6811c6bd
--- /dev/null
+++ b/tests/unit_tests/notify.cpp
@@ -0,0 +1,57 @@
+// Copyright (c) 2018, The Monero Project
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are
+// permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other
+// materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its contributors may be
+// used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "gtest/gtest.h"
+
+#include <boost/filesystem.hpp>
+
+#include "misc_language.h"
+#include "string_tools.h"
+#include "file_io_utils.h"
+#include "common/notify.h"
+
+TEST(notify, works)
+{
+ char name_template[] = "/tmp/monero-notify-unit-test-XXXXXX";
+ int fd = mkstemp(name_template);
+ ASSERT_TRUE(fd >= 0);
+ close(fd);
+
+ const std::string spec = epee::string_tools::get_current_module_folder() + "/test_notifier " + name_template + " %s";
+
+ tools::Notify notify(spec.c_str());
+ notify.notify("1111111111111111111111111111111111111111111111111111111111111111");
+
+ epee::misc_utils::sleep_no_w(100);
+
+ std::string s;
+ ASSERT_TRUE(epee::file_io_utils::load_file_to_string(name_template, s));
+ ASSERT_TRUE(s == "1111111111111111111111111111111111111111111111111111111111111111");
+
+ boost::filesystem::remove(name_template);
+}
diff --git a/tests/unit_tests/ringdb.cpp b/tests/unit_tests/ringdb.cpp
index 0d92049ac..ab634ea82 100644
--- a/tests/unit_tests/ringdb.cpp
+++ b/tests/unit_tests/ringdb.cpp
@@ -136,21 +136,21 @@ TEST(ringdb, different_genesis)
ASSERT_FALSE(ringdb.get_ring(KEY_2, KEY_IMAGE_1, outs2));
}
-TEST(blackball, not_found)
+TEST(spent_outputs, not_found)
{
RingDB ringdb;
ASSERT_TRUE(ringdb.blackball(OUTPUT_1));
ASSERT_FALSE(ringdb.blackballed(OUTPUT_2));
}
-TEST(blackball, found)
+TEST(spent_outputs, found)
{
RingDB ringdb;
ASSERT_TRUE(ringdb.blackball(OUTPUT_1));
ASSERT_TRUE(ringdb.blackballed(OUTPUT_1));
}
-TEST(blackball, vector)
+TEST(spent_outputs, vector)
{
RingDB ringdb;
std::vector<std::pair<uint64_t, uint64_t>> outputs;
@@ -174,7 +174,7 @@ TEST(blackball, vector)
ASSERT_TRUE(ringdb.blackballed(std::make_pair(30, 5)));
}
-TEST(blackball, unblackball)
+TEST(spent_outputs, mark_as_unspent)
{
RingDB ringdb;
ASSERT_TRUE(ringdb.blackball(OUTPUT_1));
@@ -182,7 +182,7 @@ TEST(blackball, unblackball)
ASSERT_FALSE(ringdb.blackballed(OUTPUT_1));
}
-TEST(blackball, clear)
+TEST(spent_outputs, clear)
{
RingDB ringdb;
ASSERT_TRUE(ringdb.blackball(OUTPUT_1));
diff --git a/tests/unit_tests/test_notifier.cpp b/tests/unit_tests/test_notifier.cpp
new file mode 100644
index 000000000..7fd9809c5
--- /dev/null
+++ b/tests/unit_tests/test_notifier.cpp
@@ -0,0 +1,54 @@
+// Copyright (c) 2018, The Monero Project
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are
+// permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other
+// materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its contributors may be
+// used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+int main(int argc, char **argv)
+{
+ if (argc < 3)
+ {
+ fprintf(stderr, "usage: %s <filename> <hash>\n", argv[0]);
+ return 1;
+ }
+ const char *filename = argv[1];
+ const char *hash = argv[2];
+
+ FILE *f = fopen(filename, "a+");
+ if (!f)
+ {
+ fprintf(stderr, "error opening file %s: %s\n", filename, strerror(errno));
+ return 1;
+ }
+ fprintf(f, "%s", hash);
+ fclose(f);
+
+ return 0;
+}