aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt100
-rw-r--r--README.md44
-rw-r--r--cmake/CheckLinkerFlag.c14
-rw-r--r--cmake/CheckLinkerFlag.cmake47
-rw-r--r--cmake/FindReadline.cmake55
-rw-r--r--contrib/epee/include/memwipe.h (renamed from src/common/memwipe.h)0
-rw-r--r--contrib/epee/include/net/http_auth.h7
-rw-r--r--contrib/epee/include/net/http_protocol_handler.h3
-rw-r--r--contrib/epee/include/net/http_server_impl_base.h3
-rw-r--r--contrib/epee/include/net/network_throttle.hpp3
-rw-r--r--contrib/epee/include/serialization/keyvalue_serialization.h1
-rw-r--r--contrib/epee/include/storages/portable_storage_val_converters.h6
-rw-r--r--contrib/epee/src/CMakeLists.txt9
-rw-r--r--contrib/epee/src/connection_basic.cpp1
-rw-r--r--contrib/epee/src/http_auth.cpp7
-rw-r--r--contrib/epee/src/memwipe.c (renamed from src/common/memwipe.c)0
-rw-r--r--contrib/epee/src/wipeable_string.cpp2
-rw-r--r--external/db_drivers/liblmdb/CMakeLists.txt1
-rw-r--r--external/easylogging++/CMakeLists.txt1
-rw-r--r--external/easylogging++/ea_config.h11
-rw-r--r--external/miniupnpc/CMakeLists.txt7
-rw-r--r--external/unbound/CMakeLists.txt2
-rw-r--r--src/blockchain_db/blockchain_db.h5
-rw-r--r--src/blockchain_db/lmdb/db_lmdb.cpp70
-rw-r--r--src/blockchain_db/lmdb/db_lmdb.h2
-rw-r--r--src/blockchain_utilities/CMakeLists.txt4
-rw-r--r--src/blockchain_utilities/blockchain_import.cpp4
-rw-r--r--src/blocks/CMakeLists.txt4
-rw-r--r--src/common/CMakeLists.txt9
-rw-r--r--src/common/i18n.cpp43
-rw-r--r--src/common/password.cpp2
-rw-r--r--src/common/stack_trace.cpp3
-rw-r--r--src/common/threadpool.cpp8
-rw-r--r--src/common/util.cpp1
-rw-r--r--src/crypto/CMakeLists.txt1
-rw-r--r--src/crypto/blake256.c2
-rw-r--r--src/crypto/chacha.h2
-rw-r--r--src/crypto/crypto.h2
-rw-r--r--src/cryptonote_basic/cryptonote_basic.h1
-rw-r--r--src/cryptonote_basic/cryptonote_basic_impl.cpp2
-rw-r--r--src/cryptonote_basic/cryptonote_format_utils.cpp1
-rw-r--r--src/cryptonote_core/blockchain.cpp4
-rw-r--r--src/cryptonote_core/blockchain.h2
-rw-r--r--src/cryptonote_core/tx_pool.cpp39
-rw-r--r--src/cryptonote_protocol/cryptonote_protocol_handler.inl5
-rw-r--r--src/daemon/CMakeLists.txt6
-rw-r--r--src/daemon/core.h1
-rw-r--r--src/daemon/daemon.cpp3
-rw-r--r--src/daemon/executor.cpp1
-rw-r--r--src/daemon/main.cpp2
-rw-r--r--src/daemon/protocol.h2
-rw-r--r--src/daemon/rpc_command_executor.cpp2
-rw-r--r--src/gen_multisig/CMakeLists.txt2
-rw-r--r--src/mnemonics/CMakeLists.txt1
-rw-r--r--src/mnemonics/electrum-words.cpp2
-rw-r--r--src/p2p/CMakeLists.txt1
-rw-r--r--src/ringct/rctTypes.h2
-rw-r--r--src/rpc/CMakeLists.txt2
-rw-r--r--src/rpc/core_rpc_server.cpp3
-rw-r--r--src/serialization/container.h113
-rw-r--r--src/serialization/deque.h64
-rw-r--r--src/serialization/list.h72
-rw-r--r--src/serialization/serialization.h16
-rw-r--r--src/serialization/set.h85
-rw-r--r--src/serialization/unordered_set.h58
-rw-r--r--src/serialization/vector.h82
-rw-r--r--src/simplewallet/CMakeLists.txt2
-rw-r--r--src/simplewallet/simplewallet.cpp311
-rw-r--r--src/simplewallet/simplewallet.h3
-rw-r--r--src/wallet/api/utils.cpp5
-rw-r--r--src/wallet/api/wallet2_api.h1
-rw-r--r--src/wallet/wallet2.cpp256
-rw-r--r--src/wallet/wallet2.h10
-rw-r--r--src/wallet/wallet_errors.h11
-rw-r--r--src/wallet/wallet_rpc_server.cpp413
-rw-r--r--src/wallet/wallet_rpc_server.h5
-rw-r--r--src/wallet/wallet_rpc_server_commands_defs.h14
-rw-r--r--tests/fuzz/cold-outputs.cpp10
-rw-r--r--tests/fuzz/cold-transaction.cpp10
-rw-r--r--tests/fuzz/signature.cpp10
-rw-r--r--tests/gtest/cmake/internal_utils.cmake2
-rw-r--r--tests/hash/CMakeLists.txt1
-rw-r--r--tests/performance_tests/CMakeLists.txt2
-rw-r--r--tests/performance_tests/main.cpp3
-rw-r--r--tests/performance_tests/subaddress_expand.h65
-rw-r--r--tests/unit_tests/crypto.cpp24
-rw-r--r--tests/unit_tests/hardfork.cpp2
-rw-r--r--tests/unit_tests/http.cpp22
-rw-r--r--tests/unit_tests/memwipe.cpp4
-rw-r--r--tests/unit_tests/serialization.cpp1
-rw-r--r--tests/unit_tests/subaddress.cpp17
-rw-r--r--tests/unit_tests/varint.cpp1
-rw-r--r--translations/CMakeLists.txt63
-rw-r--r--translations/generate_translations_header.c86
-rw-r--r--translations/monero.ts10
-rw-r--r--translations/monero_fr.ts10
-rw-r--r--translations/monero_it.ts10
-rw-r--r--utils/build_scripts/android32.Dockerfile2
-rw-r--r--utils/build_scripts/android64.Dockerfile2
99 files changed, 1496 insertions, 952 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 11c549d7c..a0508adfd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -27,6 +27,13 @@
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
+list(INSERT CMAKE_MODULE_PATH 0
+ "${CMAKE_SOURCE_DIR}/cmake")
+include(CheckCCompilerFlag)
+include(CheckCXXCompilerFlag)
+include(CheckLinkerFlag)
+include(CheckLibraryExists)
+
if (IOS)
INCLUDE(CmakeLists_IOS.txt)
endif()
@@ -48,6 +55,31 @@ function (die msg)
message(FATAL_ERROR "${BoldRed}${msg}${ColourReset}")
endfunction ()
+function (add_c_flag_if_supported flag var)
+ string(REPLACE "-" "_" supported ${flag}_c)
+ check_c_compiler_flag(${flag} ${supported})
+ if(${${supported}})
+ set(${var} "${${var}} ${flag}" PARENT_SCOPE)
+ endif()
+endfunction()
+
+function (add_cxx_flag_if_supported flag var)
+ string(REPLACE "-" "_" supported ${flag}_cxx)
+ check_cxx_compiler_flag(${flag} ${supported})
+ if(${${supported}})
+ set(${var} "${${var}} ${flag}" PARENT_SCOPE)
+ endif()
+endfunction()
+
+function (add_linker_flag_if_supported flag var)
+ string(REPLACE "-" "_" supported ${flag}_ld)
+ string(REPLACE "," "_" supported ${flag}_ld)
+ check_linker_flag(${flag} ${supported})
+ if(${${supported}})
+ set(${var} "${${var}} ${flag}" PARENT_SCOPE)
+ endif()
+endfunction()
+
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
message(STATUS "Setting default build type: ${CMAKE_BUILD_TYPE}")
@@ -210,11 +242,11 @@ endif()
if (BUILD_SHARED_LIBS)
message(STATUS "Building internal libraries with position independent code")
- set(PIC_FLAG "-fPIC")
add_definitions("-DBUILD_SHARED_LIBS")
else()
message(STATUS "Building internal libraries as static")
endif()
+set(PIC_FLAG "-fPIC")
if(MINGW)
string(REGEX MATCH "^[^/]:/[^/]*" msys2_install_path "${CMAKE_C_COMPILER}")
@@ -365,6 +397,14 @@ endif()
add_definitions(-DAUTO_INITIALIZE_EASYLOGGINGPP)
+# Generate header for embedded translations
+include(ExternalProject)
+ExternalProject_Add(generate_translations_header
+ SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/translations"
+ BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/translations"
+ INSTALL_COMMAND cmake -E echo "")
+include_directories("${CMAKE_CURRENT_BINARY_DIR}/translations")
+
add_subdirectory(external)
# Final setup for miniupnpc
@@ -470,6 +510,52 @@ else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-strict-aliasing")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-strict-aliasing")
+ # if those don't work for your compiler, single it out where appropriate
+ if(CMAKE_BUILD_TYPE STREQUAL "Release")
+ set(C_SECURITY_FLAGS "${C_SECURITY_FLAGS} -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1")
+ set(CXX_SECURITY_FLAGS "${CXX_SECURITY_FLAGS} -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1")
+ endif()
+
+ # warnings
+ add_c_flag_if_supported(-Wformat C_SECURITY_FLAGS)
+ add_cxx_flag_if_supported(-Wformat CXX_SECURITY_FLAGS)
+ add_c_flag_if_supported(-Wformat-security C_SECURITY_FLAGS)
+ add_cxx_flag_if_supported(-Wformat-security CXX_SECURITY_FLAGS)
+
+ # -fstack-protector
+ add_c_flag_if_supported(-fstack-protector C_SECURITY_FLAGS)
+ add_cxx_flag_if_supported(-fstack-protector CXX_SECURITY_FLAGS)
+ add_c_flag_if_supported(-fstack-protector-strong C_SECURITY_FLAGS)
+ add_cxx_flag_if_supported(-fstack-protector-strong CXX_SECURITY_FLAGS)
+
+ # linker
+ if (NOT WIN32)
+ # Windows binaries die on startup with PIE
+ add_linker_flag_if_supported(-pie LD_SECURITY_FLAGS)
+ endif()
+ add_linker_flag_if_supported(-Wl,-z,relro LD_SECURITY_FLAGS)
+ add_linker_flag_if_supported(-Wl,-z,now LD_SECURITY_FLAGS)
+ add_linker_flag_if_supported(-Wl,-z,noexecstack noexecstack_SUPPORTED)
+ if (noexecstack_SUPPORTED)
+ set(LD_SECURITY_FLAGS "${LD_SECURITY_FLAGS} -Wl,-z,noexecstack")
+ set(LD_RAW_FLAGS ${LD_RAW_FLAGS} -z noexecstack)
+ endif()
+ add_linker_flag_if_supported(-Wl,-z,noexecheap noexecheap_SUPPORTED)
+ if (noexecheap_SUPPORTED)
+ set(LD_SECURITY_FLAGS "${LD_SECURITY_FLAGS} -Wl,-z,noexecheap")
+ set(LD_RAW_FLAGS ${LD_RAW_FLAGS} -z noexecheap)
+ endif()
+
+ # some windows linker bits
+ if (WIN32)
+ add_linker_flag_if_supported(-Wl,--dynamicbase LD_SECURITY_FLAGS)
+ add_linker_flag_if_supported(-Wl,--nxcompat LD_SECURITY_FLAGS)
+ endif()
+
+ message(STATUS "Using C security hardening flags: ${C_SECURITY_FLAGS}")
+ message(STATUS "Using C++ security hardening flags: ${CXX_SECURITY_FLAGS}")
+ message(STATUS "Using linker security hardening flags: ${LD_SECURITY_FLAGS}")
+
option(NO_AES "Explicitly disable AES support" ${NO_AES})
if(NO_AES)
@@ -498,8 +584,9 @@ else()
message(STATUS "AES support disabled")
endif()
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -D_GNU_SOURCE ${MINGW_FLAG} ${STATIC_ASSERT_FLAG} ${WARNINGS} ${C_WARNINGS} ${ARCH_FLAG} ${COVERAGE_FLAGS} ${PIC_FLAG}")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -D_GNU_SOURCE ${MINGW_FLAG} ${STATIC_ASSERT_CPP_FLAG} ${WARNINGS} ${CXX_WARNINGS} ${ARCH_FLAG} ${COVERAGE_FLAGS} ${PIC_FLAG}")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -D_GNU_SOURCE ${MINGW_FLAG} ${STATIC_ASSERT_FLAG} ${WARNINGS} ${C_WARNINGS} ${ARCH_FLAG} ${COVERAGE_FLAGS} ${PIC_FLAG} ${C_SECURITY_FLAGS}")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -D_GNU_SOURCE ${MINGW_FLAG} ${STATIC_ASSERT_CPP_FLAG} ${WARNINGS} ${CXX_WARNINGS} ${ARCH_FLAG} ${COVERAGE_FLAGS} ${PIC_FLAG} ${CXX_SECURITY_FLAGS}")
+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LD_SECURITY_FLAGS}")
# With GCC 6.1.1 the compiled binary malfunctions due to aliasing. Until that
# is fixed in the code (Issue #847), force compiler to be conservative.
@@ -586,6 +673,7 @@ else()
if(ANDROID AND NOT BUILD_GUI_DEPS STREQUAL "ON" OR IOS)
#From Android 5: "only position independent executables (PIE) are supported"
message(STATUS "Enabling PIE executable")
+ set(PIC_FLAG "")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIE")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIE")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_CXX_FLAGS} -fPIE -pie")
@@ -672,7 +760,7 @@ if(NOT Boost_FOUND)
die("Could not find Boost libraries, please make sure you have installed Boost or libboost-all-dev (1.58) or the equivalent")
elseif(Boost_FOUND)
message(STATUS "Found Boost Version: ${Boost_VERSION}")
- if (Boost_VERSION VERSION_LESS 1.62 AND NOT (OPENSSL_VERSION VERSION_LESS 1.1))
+ if (Boost_VERSION VERSION_LESS 106200 AND NOT (OPENSSL_VERSION VERSION_LESS 1.1))
message(FATAL_ERROR "Boost older than 1.62 is too old to link with OpenSSL 1.1 or newer. "
"Update Boost or install OpenSSL 1.0 and set path to it when running cmake: "
"cmake -DOPENSSL_ROOT_DIR='/usr/include/openssl-1.0;/usr/lib/openssl-1.0'")
@@ -778,11 +866,11 @@ option(BUILD_GUI_DEPS "Build GUI dependencies." OFF)
option(INSTALL_VENDORED_LIBUNBOUND "Install libunbound binary built from source vendored with this repo." OFF)
-include(CheckCCompilerFlag)
-
CHECK_C_COMPILER_FLAG(-std=c11 HAVE_C11)
include(CheckLibraryExists)
+include(CheckFunctionExists)
check_library_exists(c memset_s "string.h" HAVE_MEMSET_S)
check_library_exists(c explicit_bzero "strings.h" HAVE_EXPLICIT_BZERO)
+check_function_exists(strptime HAVE_STRPTIME)
diff --git a/README.md b/README.md
index d76137b6f..105500289 100644
--- a/README.md
+++ b/README.md
@@ -60,16 +60,12 @@ As with many development projects, the repository on Github is considered to be
## Supporting the project
-Monero development can be supported directly through donations.
-
-Both Monero and Bitcoin donations can be made to donate.getmonero.org if using a client that supports the [OpenAlias](https://openalias.org) standard
+Monero is a 100% community-sponsored endeavor. If you want to join our efforts, the easiest thing you can do is support the project financially. Both Monero and Bitcoin donations can be made to **donate.getmonero.org** if using a client that supports the [OpenAlias](https://openalias.org) standard. Alternatively you can send XMR to the Monero donation address via the `donate` command (type `help` in the command-line wallet for details).
The Monero donation address is: `44AFFq5kSiGBoZ4NMDwYtN18obc8AemS33DBLWs3H7otXft3XjrpDtQGv7SqSsaBYBb98uNbr2VBBEt7f2wfn3RVGQBEP3A` (viewkey: `f359631075708155cc3d92a32b75a7d02a5dcf27756707b47a2b31b21c389501`)
The Bitcoin donation address is: `1KTexdemPdxSBcG55heUuTjDRYqbC5ZL8H`
-*Note: you can easily donate XMR to the Monero donation address by using the `donate` command. Type `help` in the command-line wallet for details.*
-
Core development funding and/or some supporting services are also graciously provided by sponsors:
[<img width="80" src="https://static.getmonero.org/images/sponsors/mymonero.png"/>](https://mymonero.com)
@@ -167,25 +163,25 @@ sources are also used for statically-linked builds because distribution
packages often include only shared library binaries (`.so`) but not static
library archives (`.a`).
-| Dep | Min. version | Vendored | Debian/Ubuntu pkg | Arch pkg | Optional | Purpose |
-| -------------- | ------------- | ---------| ------------------ | -------------- | -------- | -------------- |
-| GCC | 4.7.3 | NO | `build-essential` | `base-devel` | NO | |
-| CMake | 3.0.0 | NO | `cmake` | `cmake` | NO | |
-| pkg-config | any | NO | `pkg-config` | `base-devel` | NO | |
-| Boost | 1.58 | NO | `libboost-all-dev` | `boost` | NO | C++ libraries |
-| OpenSSL | basically any | NO | `libssl-dev` | `openssl` | NO | sha256 sum |
-| libzmq | 3.0.0 | NO | `libzmq3-dev` | `zeromq` | NO | ZeroMQ library |
-| libunbound | 1.4.16 | YES | `libunbound-dev` | `unbound` | NO | DNS resolver |
-| libsodium | ? | NO | `libsodium-dev` | ? | NO | libsodium |
-| libminiupnpc | 2.0 | YES | `libminiupnpc-dev` | `miniupnpc` | YES | NAT punching |
-| libunwind | any | NO | `libunwind8-dev` | `libunwind` | YES | Stack traces |
-| liblzma | any | NO | `liblzma-dev` | `xz` | YES | For libunwind |
-| libreadline | 6.3.0 | NO | `libreadline6-dev` | `readline` | YES | Input editing |
-| ldns | 1.6.17 | NO | `libldns-dev` | `ldns` | YES | SSL toolkit |
-| expat | 1.1 | NO | `libexpat1-dev` | `expat` | YES | XML parsing |
-| GTest | 1.5 | YES | `libgtest-dev`^ | `gtest` | YES | Test suite |
-| Doxygen | any | NO | `doxygen` | `doxygen` | YES | Documentation |
-| Graphviz | any | NO | `graphviz` | `graphviz` | YES | Documentation |
+| Dep | Min. version | Vendored | Debian/Ubuntu pkg | Arch pkg | Fedora | Optional | Purpose |
+| ------------ | ------------- | -------- | ------------------ | ------------ | ----------------- | -------- | -------------- |
+| GCC | 4.7.3 | NO | `build-essential` | `base-devel` | `gcc` | NO | |
+| CMake | 3.0.0 | NO | `cmake` | `cmake` | `cmake` | NO | |
+| pkg-config | any | NO | `pkg-config` | `base-devel` | `pkgconf` | NO | |
+| Boost | 1.58 | NO | `libboost-all-dev` | `boost` | `boost-devel` | NO | C++ libraries |
+| OpenSSL | basically any | NO | `libssl-dev` | `openssl` | `openssl-devel` | NO | sha256 sum |
+| libzmq | 3.0.0 | NO | `libzmq3-dev` | `zeromq` | `cppzmq-devel` | NO | ZeroMQ library |
+| libunbound | 1.4.16 | YES | `libunbound-dev` | `unbound` | `unbound-devel` | NO | DNS resolver |
+| libsodium | ? | NO | `libsodium-dev` | ? | `libsodium-devel` | NO | libsodium |
+| libminiupnpc | 2.0 | YES | `libminiupnpc-dev` | `miniupnpc` | `miniupnpc-devel` | YES | NAT punching |
+| libunwind | any | NO | `libunwind8-dev` | `libunwind` | `libunwind-devel` | YES | Stack traces |
+| liblzma | any | NO | `liblzma-dev` | `xz` | `xz-devel` | YES | For libunwind |
+| libreadline | 6.3.0 | NO | `libreadline6-dev` | `readline` | `readline-devel` | YES | Input editing |
+| ldns | 1.6.17 | NO | `libldns-dev` | `ldns` | `ldns-devel` | YES | SSL toolkit |
+| expat | 1.1 | NO | `libexpat1-dev` | `expat` | `expat-devel` | YES | XML parsing |
+| GTest | 1.5 | YES | `libgtest-dev`^ | `gtest` | `gtest-devel` | YES | Test suite |
+| Doxygen | any | NO | `doxygen` | `doxygen` | `doxygen` | YES | Documentation |
+| Graphviz | any | NO | `graphviz` | `graphviz` | `graphviz` | YES | Documentation |
[^] On Debian/Ubuntu `libgtest-dev` only includes sources and headers. You must
diff --git a/cmake/CheckLinkerFlag.c b/cmake/CheckLinkerFlag.c
new file mode 100644
index 000000000..a0dcc168d
--- /dev/null
+++ b/cmake/CheckLinkerFlag.c
@@ -0,0 +1,14 @@
+#ifdef __CLASSIC_C__
+int main()
+{
+ int ac;
+ char* av[];
+#else
+int main(int ac, char* av[])
+{
+#endif
+ if (ac > 1000) {
+ return *av[0];
+ }
+ return 0;
+}
diff --git a/cmake/CheckLinkerFlag.cmake b/cmake/CheckLinkerFlag.cmake
new file mode 100644
index 000000000..a3879d0be
--- /dev/null
+++ b/cmake/CheckLinkerFlag.cmake
@@ -0,0 +1,47 @@
+include(CheckCCompilerFlag)
+
+macro(CHECK_LINKER_FLAG flag VARIABLE)
+ if(NOT DEFINED "${VARIABLE}")
+ if(NOT CMAKE_REQUIRED_QUIET)
+ message(STATUS "Looking for ${flag} linker flag")
+ endif()
+
+ set(_cle_source ${CMAKE_SOURCE_DIR}/cmake/CheckLinkerFlag.c)
+
+ set(saved_CMAKE_C_FLAGS ${CMAKE_C_FLAGS})
+ set(CMAKE_C_FLAGS "${flag}")
+ try_compile(${VARIABLE}
+ ${CMAKE_BINARY_DIR}
+ ${_cle_source}
+ COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} ${flag}
+ CMAKE_FLAGS
+ OUTPUT_VARIABLE OUTPUT)
+ unset(_cle_source)
+ set(CMAKE_C_FLAGS ${saved_CMAKE_C_FLAGS})
+ unset(saved_CMAKE_C_FLAGS)
+
+ if ("${OUTPUT}" MATCHES "warning.*ignored")
+ set(${VARIABLE} 0)
+ endif()
+
+ if(${VARIABLE})
+ if(NOT CMAKE_REQUIRED_QUIET)
+ message(STATUS "Looking for ${flag} linker flag - found")
+ endif()
+ set(${VARIABLE} 1 CACHE INTERNAL "Have linker flag ${flag}")
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+ "Determining if the ${flag} linker flag is supported "
+ "passed with the following output:\n"
+ "${OUTPUT}\n\n")
+ else()
+ if(NOT CMAKE_REQUIRED_QUIET)
+ message(STATUS "Looking for ${flag} linker flag - not found")
+ endif()
+ set(${VARIABLE} "" CACHE INTERNAL "Have linker flag ${flag}")
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+ "Determining if the ${flag} linker flag is suppored "
+ "failed with the following output:\n"
+ "${OUTPUT}\n\n")
+ endif()
+ endif()
+endmacro()
diff --git a/cmake/FindReadline.cmake b/cmake/FindReadline.cmake
index cdce0bfca..87f8ccace 100644
--- a/cmake/FindReadline.cmake
+++ b/cmake/FindReadline.cmake
@@ -15,8 +15,11 @@
#
# READLINE_FOUND System has readline, include and lib dirs found
# GNU_READLINE_FOUND Version of readline found is GNU readline, not libedit!
+# LIBEDIT_FOUND Version of readline found is libedit, not GNU readline!
# Readline_INCLUDE_DIR The readline include directories.
# Readline_LIBRARY The readline library.
+# GNU_READLINE_LIBRARY The GNU readline library or empty string.
+# LIBEDIT_LIBRARY The libedit library or empty string.
find_path(Readline_ROOT_DIR
NAMES include/readline/readline.h
@@ -36,14 +39,18 @@ find_library(Readline_LIBRARY
NO_DEFAULT_PATH
)
-if(Readline_INCLUDE_DIR AND Readline_LIBRARY AND Ncurses_LIBRARY)
+find_library(Termcap_LIBRARY
+ NAMES tinfo termcap ncursesw ncurses cursesw curses
+)
+
+if(Readline_INCLUDE_DIR AND Readline_LIBRARY)
set(READLINE_FOUND TRUE)
-else(Readline_INCLUDE_DIR AND Readline_LIBRARY AND Ncurses_LIBRARY)
+else(Readline_INCLUDE_DIR AND Readline_LIBRARY)
FIND_LIBRARY(Readline_LIBRARY NAMES readline PATHS Readline_ROOT_DIR)
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Readline DEFAULT_MSG Readline_INCLUDE_DIR Readline_LIBRARY )
MARK_AS_ADVANCED(Readline_INCLUDE_DIR Readline_LIBRARY)
-endif(Readline_INCLUDE_DIR AND Readline_LIBRARY AND Ncurses_LIBRARY)
+endif(Readline_INCLUDE_DIR AND Readline_LIBRARY)
mark_as_advanced(
Readline_ROOT_DIR
@@ -53,22 +60,30 @@ mark_as_advanced(
set(CMAKE_REQUIRED_INCLUDES ${Readline_INCLUDE_DIR})
set(CMAKE_REQUIRED_LIBRARIES ${Readline_LIBRARY})
-INCLUDE(CheckCXXSourceCompiles)
-CHECK_CXX_SOURCE_COMPILES(
-"
-#include <stdio.h>
-#include <readline/readline.h>
-int
-main()
-{
- char * s = rl_copy_text(0, 0);
-}
-" GNU_READLINE_FOUND)
-if(NOT Readline_LIBRARY)
- set(Readline_LIBRARY "")
-endif()
+include(CheckFunctionExists)
+check_function_exists(rl_copy_text HAVE_COPY_TEXT)
+check_function_exists(rl_filename_completion_function HAVE_COMPLETION_FUNCTION)
+
+if(NOT HAVE_COMPLETION_FUNCTION)
+ set(CMAKE_REQUIRED_LIBRARIES ${Readline_LIBRARY} ${Termcap_LIBRARY})
+ check_function_exists(rl_copy_text HAVE_COPY_TEXT_TC)
+ check_function_exists(rl_filename_completion_function HAVE_COMPLETION_FUNCTION_TC)
+ set(HAVE_COMPLETION_FUNCTION ${HAVE_COMPLETION_FUNCTION_TC})
+ set(HAVE_COPY_TEXT ${HAVE_COPY_TEXT_TC})
+ if(HAVE_COMPLETION_FUNCTION)
+ set(Readline_LIBRARY ${Readline_LIBRARY} ${Termcap_LIBRARY})
+ endif(HAVE_COMPLETION_FUNCTION)
+endif(NOT HAVE_COMPLETION_FUNCTION)
+
+set(LIBEDIT_LIBRARY "")
+set(GNU_READLINE_LIBRARY "")
+
+if(HAVE_COMPLETION_FUNCTION AND HAVE_COPY_TEXT)
+ set(GNU_READLINE_FOUND TRUE)
+ set(GNU_READLINE_LIBRARY ${Readline_LIBRARY})
+elseif(READLINE_FOUND AND NOT HAVE_COPY_TEXT)
+ set(LIBEDIT_FOUND TRUE)
+ set(LIBEDIT_LIBRARY ${Readline_LIBRARY})
+endif(HAVE_COMPLETION_FUNCTION AND HAVE_COPY_TEXT)
-if(Readline_LIBRARY AND OPENBSD)
- list(APPEND EXTRA_LIBRARIES curses)
-endif()
diff --git a/src/common/memwipe.h b/contrib/epee/include/memwipe.h
index c3b4ce8ab..c3b4ce8ab 100644
--- a/src/common/memwipe.h
+++ b/contrib/epee/include/memwipe.h
diff --git a/contrib/epee/include/net/http_auth.h b/contrib/epee/include/net/http_auth.h
index 841cebc17..71f56b570 100644
--- a/contrib/epee/include/net/http_auth.h
+++ b/contrib/epee/include/net/http_auth.h
@@ -71,8 +71,8 @@ namespace net_utils
std::uint32_t counter;
};
- http_server_auth() : user() {}
- http_server_auth(login credentials);
+ http_server_auth() : user(), rng() {}
+ http_server_auth(login credentials, std::function<void(size_t, uint8_t*)> r);
//! \return Auth response, or `boost::none` iff `request` had valid auth.
boost::optional<http_response_info> get_response(const http_request_info& request)
@@ -81,10 +81,13 @@ namespace net_utils
return do_get_response(request);
return boost::none;
}
+
private:
boost::optional<http_response_info> do_get_response(const http_request_info& request);
boost::optional<session> user;
+
+ std::function<void(size_t, uint8_t*)> rng;
};
//! Implements RFC 2617 digest auth. Digests from RFC 7616 can be added.
diff --git a/contrib/epee/include/net/http_protocol_handler.h b/contrib/epee/include/net/http_protocol_handler.h
index 652d8ff6f..b4485d1cd 100644
--- a/contrib/epee/include/net/http_protocol_handler.h
+++ b/contrib/epee/include/net/http_protocol_handler.h
@@ -160,6 +160,7 @@ namespace net_utils
struct custum_handler_config: public http_server_config
{
i_http_server_handler<t_connection_context>* m_phandler;
+ std::function<void(size_t, uint8_t*)> rng;
};
/************************************************************************/
@@ -176,7 +177,7 @@ namespace net_utils
: simple_http_connection_handler<t_connection_context>(psnd_hndlr, config),
m_config(config),
m_conn_context(conn_context),
- m_auth(m_config.m_user ? http_server_auth{*m_config.m_user} : http_server_auth{})
+ m_auth(m_config.m_user ? http_server_auth{*m_config.m_user, config.rng} : http_server_auth{})
{}
inline bool handle_request(const http_request_info& query_info, http_response_info& response)
{
diff --git a/contrib/epee/include/net/http_server_impl_base.h b/contrib/epee/include/net/http_server_impl_base.h
index 8b8e31b51..1a97e610a 100644
--- a/contrib/epee/include/net/http_server_impl_base.h
+++ b/contrib/epee/include/net/http_server_impl_base.h
@@ -55,13 +55,14 @@ namespace epee
: m_net_server(external_io_service)
{}
- bool init(const std::string& bind_port = "0", const std::string& bind_ip = "0.0.0.0",
+ bool init(std::function<void(size_t, uint8_t*)> rng, const std::string& bind_port = "0", const std::string& bind_ip = "0.0.0.0",
std::vector<std::string> access_control_origins = std::vector<std::string>(),
boost::optional<net_utils::http::login> user = boost::none)
{
//set self as callback handler
m_net_server.get_config_object().m_phandler = static_cast<t_child_class*>(this);
+ m_net_server.get_config_object().rng = std::move(rng);
//here set folder for hosting reqests
m_net_server.get_config_object().m_folder = "";
diff --git a/contrib/epee/include/net/network_throttle.hpp b/contrib/epee/include/net/network_throttle.hpp
index fffd22a6a..225ffee04 100644
--- a/contrib/epee/include/net/network_throttle.hpp
+++ b/contrib/epee/include/net/network_throttle.hpp
@@ -99,8 +99,6 @@ struct calculate_times_struct {
typedef calculate_times_struct calculate_times_struct;
-namespace cryptonote { class cryptonote_protocol_handler_base; } // a friend class // TODO friend not working
-
/***
@brief Access to simple throttles, with singlton to access global network limits
*/
@@ -117,7 +115,6 @@ class network_throttle_manager {
static boost::mutex m_lock_get_global_throttle_inreq;
static boost::mutex m_lock_get_global_throttle_out;
- friend class cryptonote::cryptonote_protocol_handler_base; // FRIEND - to directly access global throttle-s. !! REMEMBER TO USE LOCKS!
friend class connection_basic; // FRIEND - to directly access global throttle-s. !! REMEMBER TO USE LOCKS!
friend class connection_basic_pimpl; // ditto
diff --git a/contrib/epee/include/serialization/keyvalue_serialization.h b/contrib/epee/include/serialization/keyvalue_serialization.h
index d4413a71b..5791e1998 100644
--- a/contrib/epee/include/serialization/keyvalue_serialization.h
+++ b/contrib/epee/include/serialization/keyvalue_serialization.h
@@ -31,7 +31,6 @@
#include "misc_log_ex.h"
#include "enableable.h"
#include "keyvalue_serialization_overloads.h"
-#include "serialization/serialization.h"
namespace epee
{
diff --git a/contrib/epee/include/storages/portable_storage_val_converters.h b/contrib/epee/include/storages/portable_storage_val_converters.h
index 52aa09eba..36bb28627 100644
--- a/contrib/epee/include/storages/portable_storage_val_converters.h
+++ b/contrib/epee/include/storages/portable_storage_val_converters.h
@@ -28,6 +28,7 @@
#pragma once
+#include <time.h>
#include <boost/regex.hpp>
#include "misc_language.h"
@@ -149,9 +150,14 @@ POP_WARNINGS
else if (boost::regex_match (from, boost::regex("\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\dZ")))
{
// Convert to unix timestamp
+#ifdef HAVE_STRPTIME
+ struct tm tm;
+ if (strptime(from.c_str(), "%Y-%m-%dT%H:%M:%S", &tm))
+#else
std::tm tm = {};
std::istringstream ss(from);
if (ss >> std::get_time(&tm, "%Y-%m-%dT%H:%M:%S"))
+#endif
to = std::mktime(&tm);
} else
ASSERT_AND_THROW_WRONG_CONVERSION();
diff --git a/contrib/epee/src/CMakeLists.txt b/contrib/epee/src/CMakeLists.txt
index b6967e8fc..538c7ce91 100644
--- a/contrib/epee/src/CMakeLists.txt
+++ b/contrib/epee/src/CMakeLists.txt
@@ -26,12 +26,16 @@
# 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.
-add_library(epee STATIC hex.cpp http_auth.cpp mlog.cpp net_utils_base.cpp string_tools.cpp wipeable_string.cpp
+add_library(epee STATIC hex.cpp http_auth.cpp mlog.cpp net_utils_base.cpp string_tools.cpp wipeable_string.cpp memwipe.c
connection_basic.cpp network_throttle.cpp network_throttle-detail.cpp)
if (USE_READLINE AND GNU_READLINE_FOUND)
add_library(epee_readline STATIC readline_buffer.cpp)
endif()
+if(HAVE_C11)
+SET_PROPERTY(SOURCE memwipe.c PROPERTY COMPILE_FLAGS -std=c11)
+endif()
+
# Build and install libepee if we're building for GUI
if (BUILD_GUI_DEPS)
if(IOS)
@@ -49,7 +53,6 @@ endif()
target_link_libraries(epee
PUBLIC
- cncrypto
easylogging
${Boost_FILESYSTEM_LIBRARY}
PRIVATE
@@ -61,5 +64,5 @@ if (USE_READLINE AND GNU_READLINE_FOUND)
PUBLIC
easylogging
PRIVATE
- ${Readline_LIBRARY})
+ ${GNU_READLINE_LIBRARY})
endif()
diff --git a/contrib/epee/src/connection_basic.cpp b/contrib/epee/src/connection_basic.cpp
index 534044a79..5848d1268 100644
--- a/contrib/epee/src/connection_basic.cpp
+++ b/contrib/epee/src/connection_basic.cpp
@@ -78,7 +78,6 @@
// TODO:
#include "net/network_throttle-detail.hpp"
-#include "cryptonote_core/cryptonote_core.h"
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "net.p2p"
diff --git a/contrib/epee/src/http_auth.cpp b/contrib/epee/src/http_auth.cpp
index f06f05528..5b8d892ff 100644
--- a/contrib/epee/src/http_auth.cpp
+++ b/contrib/epee/src/http_auth.cpp
@@ -66,7 +66,6 @@
#include <tuple>
#include <type_traits>
-#include "crypto/crypto.h"
#include "hex.h"
#include "md5_l.h"
#include "string_coding.h"
@@ -711,8 +710,8 @@ namespace epee
{
namespace http
{
- http_server_auth::http_server_auth(login credentials)
- : user(session{std::move(credentials)}) {
+ http_server_auth::http_server_auth(login credentials, std::function<void(size_t, uint8_t*)> r)
+ : user(session{std::move(credentials)}), rng(std::move(r)) {
}
boost::optional<http_response_info> http_server_auth::do_get_response(const http_request_info& request)
@@ -746,7 +745,7 @@ namespace epee
user->counter = 0;
{
std::array<std::uint8_t, 16> rand_128bit{{}};
- crypto::rand(rand_128bit.size(), rand_128bit.data());
+ rng(rand_128bit.size(), rand_128bit.data());
user->nonce = string_encoding::base64_encode(rand_128bit.data(), rand_128bit.size());
}
return create_digest_response(user->nonce, is_stale);
diff --git a/src/common/memwipe.c b/contrib/epee/src/memwipe.c
index da7e9f346..da7e9f346 100644
--- a/src/common/memwipe.c
+++ b/contrib/epee/src/memwipe.c
diff --git a/contrib/epee/src/wipeable_string.cpp b/contrib/epee/src/wipeable_string.cpp
index 894c47bbd..08a975e58 100644
--- a/contrib/epee/src/wipeable_string.cpp
+++ b/contrib/epee/src/wipeable_string.cpp
@@ -100,7 +100,7 @@ void wipeable_string::grow(size_t sz, size_t reserved)
wipefunc(buffer.data(), old_sz * sizeof(char));
buffer.reserve(reserved);
buffer.resize(sz);
- memcpy(buffer.data(), tmp.get(), sz * sizeof(char));
+ memcpy(buffer.data(), tmp.get(), old_sz * sizeof(char));
wipefunc(tmp.get(), old_sz * sizeof(char));
}
diff --git a/external/db_drivers/liblmdb/CMakeLists.txt b/external/db_drivers/liblmdb/CMakeLists.txt
index d3d3df6ad..3a09712de 100644
--- a/external/db_drivers/liblmdb/CMakeLists.txt
+++ b/external/db_drivers/liblmdb/CMakeLists.txt
@@ -54,3 +54,4 @@ if(${ARCH_WIDTH} EQUAL 32)
target_compile_definitions(lmdb
PUBLIC -DMDB_VL32)
endif()
+set_property(TARGET lmdb APPEND PROPERTY COMPILE_FLAGS "-fPIC")
diff --git a/external/easylogging++/CMakeLists.txt b/external/easylogging++/CMakeLists.txt
index 97d0bf571..8fe3fa487 100644
--- a/external/easylogging++/CMakeLists.txt
+++ b/external/easylogging++/CMakeLists.txt
@@ -54,4 +54,5 @@ if (BUILD_GUI_DEPS)
ARCHIVE DESTINATION ${lib_folder}
LIBRARY DESTINATION ${lib_folder})
endif()
+set_property(TARGET easylogging APPEND PROPERTY COMPILE_FLAGS "-fPIC")
diff --git a/external/easylogging++/ea_config.h b/external/easylogging++/ea_config.h
index 6215e67de..4c74925d3 100644
--- a/external/easylogging++/ea_config.h
+++ b/external/easylogging++/ea_config.h
@@ -2,10 +2,13 @@
#define ELPP_THREAD_SAFE
#define ELPP_DEFAULT_LOG_FILE ""
-#if !defined __GNUC__ || defined __MINGW32__ || defined __MINGW64__ || defined __ANDROID__
-#else
-#define ELPP_FEATURE_CRASH_LOG 1
-#endif
#define ELPP_DISABLE_DEFAULT_CRASH_HANDLING
#define ELPP_NO_CHECK_MACROS
#define ELPP_WINSOCK2
+#define ELPP_NO_DEBUG_MACROS
+
+#ifdef EASYLOGGING_CC
+#if !(!defined __GNUC__ || defined __MINGW32__ || defined __MINGW64__ || defined __ANDROID__)
+#define ELPP_FEATURE_CRASH_LOG
+#endif
+#endif
diff --git a/external/miniupnpc/CMakeLists.txt b/external/miniupnpc/CMakeLists.txt
index bc9685699..2df8d474b 100644
--- a/external/miniupnpc/CMakeLists.txt
+++ b/external/miniupnpc/CMakeLists.txt
@@ -73,6 +73,13 @@ if (CMAKE_COMPILER_IS_GNUC)
endif ()
endif()
+# always add -fPIC
+set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
+set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fPIC")
+set (CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fPIC")
+set (CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -fPIC")
+set (CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL} -fPIC")
+
configure_file (${CMAKE_CURRENT_SOURCE_DIR}/miniupnpcstrings.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/miniupnpcstrings.h)
include_directories (${CMAKE_CURRENT_BINARY_DIR})
diff --git a/external/unbound/CMakeLists.txt b/external/unbound/CMakeLists.txt
index a2e475232..7d4da33e2 100644
--- a/external/unbound/CMakeLists.txt
+++ b/external/unbound/CMakeLists.txt
@@ -50,9 +50,11 @@ else()
add_definitions(-D_GNU_SOURCE)
endif()
add_definitions(-std=c99)
+add_definitions(-fPIC)
option(USE_ECDSA "Use ECDSA algorithms" ON)
option(USE_SHA2 "Enable SHA2 support" ON)
+option(USE_SHA1 "Enable SHA1 support" ON)
set(ENABLE_DNSTAP 0)
set(HAVE_SSL 1)
if (CMAKE_USE_PTHREADS_INIT AND NOT CMAKE_USE_WIN32_THREADS_INIT)
diff --git a/src/blockchain_db/blockchain_db.h b/src/blockchain_db/blockchain_db.h
index 88034a927..33c3341fa 100644
--- a/src/blockchain_db/blockchain_db.h
+++ b/src/blockchain_db/blockchain_db.h
@@ -1333,10 +1333,11 @@ public:
* @brief get a txpool transaction's metadata
*
* @param txid the transaction id of the transation to lookup
+ * @param meta the metadata to return
*
- * @return the metadata associated with that transaction
+ * @return true if the tx meta was found, false otherwise
*/
- virtual txpool_tx_meta_t get_txpool_tx_meta(const crypto::hash& txid) const = 0;
+ virtual bool get_txpool_tx_meta(const crypto::hash& txid, txpool_tx_meta_t &meta) const = 0;
/**
* @brief get a txpool transaction's blob
diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp
index ee4368e86..d19399bec 100644
--- a/src/blockchain_db/lmdb/db_lmdb.cpp
+++ b/src/blockchain_db/lmdb/db_lmdb.cpp
@@ -1621,7 +1621,7 @@ void BlockchainLMDB::remove_txpool_tx(const crypto::hash& txid)
}
}
-txpool_tx_meta_t BlockchainLMDB::get_txpool_tx_meta(const crypto::hash& txid) const
+bool BlockchainLMDB::get_txpool_tx_meta(const crypto::hash& txid, txpool_tx_meta_t &meta) const
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
@@ -1632,12 +1632,14 @@ txpool_tx_meta_t BlockchainLMDB::get_txpool_tx_meta(const crypto::hash& txid) co
MDB_val k = {sizeof(txid), (void *)&txid};
MDB_val v;
auto result = mdb_cursor_get(m_cur_txpool_meta, &k, &v, MDB_SET);
+ if (result == MDB_NOTFOUND)
+ return false;
if (result != 0)
throw1(DB_ERROR(lmdb_error("Error finding txpool tx meta: ", result).c_str()));
- const txpool_tx_meta_t meta = *(const txpool_tx_meta_t*)v.mv_data;
+ meta = *(const txpool_tx_meta_t*)v.mv_data;
TXN_POSTFIX_RDONLY();
- return meta;
+ return true;
}
bool BlockchainLMDB::get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata &bd) const
@@ -2623,6 +2625,12 @@ bool BlockchainLMDB::batch_start(uint64_t batch_num_blocks, uint64_t batch_bytes
m_batch_active = true;
memset(&m_wcursors, 0, sizeof(m_wcursors));
+ if (m_tinfo.get())
+ {
+ if (m_tinfo->m_ti_rflags.m_rf_txn)
+ mdb_txn_reset(m_tinfo->m_ti_rtxn);
+ memset(&m_tinfo->m_ti_rflags, 0, sizeof(m_tinfo->m_ti_rflags));
+ }
LOG_PRINT_L3("batch transaction: begin");
return true;
@@ -2732,29 +2740,34 @@ void BlockchainLMDB::set_batch_transactions(bool batch_transactions)
bool BlockchainLMDB::block_rtxn_start(MDB_txn **mtxn, mdb_txn_cursors **mcur) const
{
bool ret = false;
+ mdb_threadinfo *tinfo;
if (m_write_txn && m_writer == boost::this_thread::get_id()) {
*mtxn = m_write_txn->m_txn;
*mcur = (mdb_txn_cursors *)&m_wcursors;
return ret;
}
- if (!m_tinfo.get())
+ /* Check for existing info and force reset if env doesn't match -
+ * only happens if env was opened/closed multiple times in same process
+ */
+ if (!(tinfo = m_tinfo.get()) || mdb_txn_env(tinfo->m_ti_rtxn) != m_env)
{
- m_tinfo.reset(new mdb_threadinfo);
- memset(&m_tinfo->m_ti_rcursors, 0, sizeof(m_tinfo->m_ti_rcursors));
- memset(&m_tinfo->m_ti_rflags, 0, sizeof(m_tinfo->m_ti_rflags));
- if (auto mdb_res = lmdb_txn_begin(m_env, NULL, MDB_RDONLY, &m_tinfo->m_ti_rtxn))
+ tinfo = new mdb_threadinfo;
+ m_tinfo.reset(tinfo);
+ memset(&tinfo->m_ti_rcursors, 0, sizeof(tinfo->m_ti_rcursors));
+ memset(&tinfo->m_ti_rflags, 0, sizeof(tinfo->m_ti_rflags));
+ if (auto mdb_res = lmdb_txn_begin(m_env, NULL, MDB_RDONLY, &tinfo->m_ti_rtxn))
throw0(DB_ERROR_TXN_START(lmdb_error("Failed to create a read transaction for the db: ", mdb_res).c_str()));
ret = true;
- } else if (!m_tinfo->m_ti_rflags.m_rf_txn)
+ } else if (!tinfo->m_ti_rflags.m_rf_txn)
{
- if (auto mdb_res = lmdb_txn_renew(m_tinfo->m_ti_rtxn))
+ if (auto mdb_res = lmdb_txn_renew(tinfo->m_ti_rtxn))
throw0(DB_ERROR_TXN_START(lmdb_error("Failed to renew a read transaction for the db: ", mdb_res).c_str()));
ret = true;
}
if (ret)
- m_tinfo->m_ti_rflags.m_rf_txn = true;
- *mtxn = m_tinfo->m_ti_rtxn;
- *mcur = &m_tinfo->m_ti_rcursors;
+ tinfo->m_ti_rflags.m_rf_txn = true;
+ *mtxn = tinfo->m_ti_rtxn;
+ *mcur = &tinfo->m_ti_rcursors;
if (ret)
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
@@ -2772,28 +2785,9 @@ void BlockchainLMDB::block_txn_start(bool readonly)
{
if (readonly)
{
- bool didit = false;
- if (m_write_txn && m_writer == boost::this_thread::get_id())
- return;
- if (!m_tinfo.get())
- {
- m_tinfo.reset(new mdb_threadinfo);
- memset(&m_tinfo->m_ti_rcursors, 0, sizeof(m_tinfo->m_ti_rcursors));
- memset(&m_tinfo->m_ti_rflags, 0, sizeof(m_tinfo->m_ti_rflags));
- if (auto mdb_res = lmdb_txn_begin(m_env, NULL, MDB_RDONLY, &m_tinfo->m_ti_rtxn))
- throw0(DB_ERROR_TXN_START(lmdb_error("Failed to create a read transaction for the db: ", mdb_res).c_str()));
- didit = true;
- } else if (!m_tinfo->m_ti_rflags.m_rf_txn)
- {
- if (auto mdb_res = lmdb_txn_renew(m_tinfo->m_ti_rtxn))
- throw0(DB_ERROR_TXN_START(lmdb_error("Failed to renew a read transaction for the db: ", mdb_res).c_str()));
- didit = true;
- }
- if (didit)
- {
- m_tinfo->m_ti_rflags.m_rf_txn = true;
- LOG_PRINT_L3("BlockchainLMDB::" << __func__ << " RO");
- }
+ MDB_txn *mtxn;
+ mdb_txn_cursors *mcur;
+ block_rtxn_start(&mtxn, &mcur);
return;
}
@@ -2818,6 +2812,12 @@ void BlockchainLMDB::block_txn_start(bool readonly)
throw0(DB_ERROR_TXN_START(lmdb_error("Failed to create a transaction for the db: ", mdb_res).c_str()));
}
memset(&m_wcursors, 0, sizeof(m_wcursors));
+ if (m_tinfo.get())
+ {
+ if (m_tinfo->m_ti_rflags.m_rf_txn)
+ mdb_txn_reset(m_tinfo->m_ti_rtxn);
+ memset(&m_tinfo->m_ti_rflags, 0, sizeof(m_tinfo->m_ti_rflags));
+ }
} else if (m_writer != boost::this_thread::get_id())
throw0(DB_ERROR_TXN_START((std::string("Attempted to start new write txn when batch txn already exists in ")+__FUNCTION__).c_str()));
}
diff --git a/src/blockchain_db/lmdb/db_lmdb.h b/src/blockchain_db/lmdb/db_lmdb.h
index 85b62b5db..ecd14f11b 100644
--- a/src/blockchain_db/lmdb/db_lmdb.h
+++ b/src/blockchain_db/lmdb/db_lmdb.h
@@ -246,7 +246,7 @@ public:
virtual uint64_t get_txpool_tx_count(bool include_unrelayed_txes = true) const;
virtual bool txpool_has_tx(const crypto::hash &txid) const;
virtual void remove_txpool_tx(const crypto::hash& txid);
- virtual txpool_tx_meta_t get_txpool_tx_meta(const crypto::hash& txid) const;
+ virtual bool get_txpool_tx_meta(const crypto::hash& txid, txpool_tx_meta_t &meta) const;
virtual bool get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata &bd) const;
virtual cryptonote::blobdata get_txpool_tx_blob(const crypto::hash& txid) const;
virtual bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata*)> f, bool include_blob = false, bool include_unrelayed_txes = true) const;
diff --git a/src/blockchain_utilities/CMakeLists.txt b/src/blockchain_utilities/CMakeLists.txt
index bd32e0c55..6c55e8d2d 100644
--- a/src/blockchain_utilities/CMakeLists.txt
+++ b/src/blockchain_utilities/CMakeLists.txt
@@ -29,9 +29,9 @@
set(blocksdat "")
if(PER_BLOCK_CHECKPOINT)
if(APPLE)
- add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*)
+ add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*)
else()
- add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ../blocks/checkpoints.dat blocks.dat && ${CMAKE_LINKER} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat)
+ add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ../blocks/checkpoints.dat blocks.dat && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat)
endif()
set(blocksdat "blocksdat.o")
endif()
diff --git a/src/blockchain_utilities/blockchain_import.cpp b/src/blockchain_utilities/blockchain_import.cpp
index 758deb7e4..edb8881e0 100644
--- a/src/blockchain_utilities/blockchain_import.cpp
+++ b/src/blockchain_utilities/blockchain_import.cpp
@@ -594,8 +594,8 @@ int main(int argc, char* argv[])
const command_line::arg_descriptor<std::string> arg_database = {
"database", available_dbs.c_str(), default_db_type
};
- const command_line::arg_descriptor<bool> arg_verify = {"verify",
- "Verify blocks and transactions during import", true};
+ const command_line::arg_descriptor<bool> arg_verify = {"guard-against-pwnage",
+ "Verify blocks and transactions during import (only disable if you exported the file yourself)", true};
const command_line::arg_descriptor<bool> arg_batch = {"batch",
"Batch transactions for faster import", true};
const command_line::arg_descriptor<bool> arg_resume = {"resume",
diff --git a/src/blocks/CMakeLists.txt b/src/blocks/CMakeLists.txt
index 3a866af5b..9317d585b 100644
--- a/src/blocks/CMakeLists.txt
+++ b/src/blocks/CMakeLists.txt
@@ -30,8 +30,8 @@ if(APPLE)
add_library(blocks STATIC blockexports.c)
set_target_properties(blocks PROPERTIES LINKER_LANGUAGE C)
else()
- add_custom_command(OUTPUT blocks.o MAIN_DEPENDENCY blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocks.o blocks.dat)
- add_custom_command(OUTPUT testnet_blocks.o MAIN_DEPENDENCY testnet_blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/testnet_blocks.o testnet_blocks.dat)
+ add_custom_command(OUTPUT blocks.o MAIN_DEPENDENCY blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocks.o blocks.dat)
+ add_custom_command(OUTPUT testnet_blocks.o MAIN_DEPENDENCY testnet_blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/testnet_blocks.o testnet_blocks.dat)
add_library(blocks STATIC blocks.o testnet_blocks.o blockexports.c)
set_target_properties(blocks PROPERTIES LINKER_LANGUAGE C)
endif()
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 7ad08ea83..7ce0229da 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -35,7 +35,6 @@ set(common_sources
download.cpp
util.cpp
i18n.cpp
- memwipe.c
password.cpp
perf_timer.cpp
threadpool.cpp
@@ -64,7 +63,6 @@ set(common_private_headers
util.h
varint.h
i18n.h
- memwipe.h
password.h
perf_timer.h
stack_trace.h
@@ -76,7 +74,8 @@ monero_private_headers(common
monero_add_library(common
${common_sources}
${common_headers}
- ${common_private_headers})
+ ${common_private_headers}
+ DEPENDS generate_translations_header)
target_link_libraries(common
PUBLIC
epee
@@ -92,9 +91,5 @@ target_link_libraries(common
${OPENSSL_LIBRARIES}
${EXTRA_LIBRARIES})
-if(HAVE_C11)
-SET_PROPERTY(SOURCE memwipe.c PROPERTY COMPILE_FLAGS -std=c11)
-endif()
-
#monero_install_headers(common
# ${common_headers})
diff --git a/src/common/i18n.cpp b/src/common/i18n.cpp
index 4a76e76fc..28a186bf0 100644
--- a/src/common/i18n.cpp
+++ b/src/common/i18n.cpp
@@ -35,6 +35,7 @@
#include "file_io_utils.h"
#include "common/util.h"
#include "common/i18n.h"
+#include "translation_files.h"
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "i18n"
@@ -62,6 +63,7 @@ std::string i18n_get_language()
e = "en";
std::string language = e;
+ language = language.substr(0, language.find("."));
std::transform(language.begin(), language.end(), language.begin(), tolower);
return language;
}
@@ -137,25 +139,40 @@ int i18n_set_language(const char *directory, const char *base, std::string langu
i18n_log("Loading translations for language " << language);
boost::system::error_code ignored_ec;
- if (!boost::filesystem::exists(filename, ignored_ec)) {
+ if (boost::filesystem::exists(filename, ignored_ec)) {
+ if (!epee::file_io_utils::load_file_to_string(filename, contents)) {
+ i18n_log("Failed to load translations file: " << filename);
+ return -1;
+ }
+ } else {
i18n_log("Translations file not found: " << filename);
- const char *underscore = strchr(language.c_str(), '_');
- if (underscore) {
- std::string fallback_language = std::string(language, 0, underscore - language.c_str());
- filename = std::string(directory) + "/" + base + "_" + fallback_language + ".qm";
- i18n_log("Not found, loading translations for language " << fallback_language);
- if (!boost::filesystem::exists(filename, ignored_ec)) {
- i18n_log("Translations file not found: " << filename);
+ filename = std::string(base) + "_" + language + ".qm";
+ if (!find_embedded_file(filename, contents)) {
+ i18n_log("Embedded translations file not found: " << filename);
+ const char *underscore = strchr(language.c_str(), '_');
+ if (underscore) {
+ std::string fallback_language = std::string(language, 0, underscore - language.c_str());
+ filename = std::string(directory) + "/" + base + "_" + fallback_language + ".qm";
+ i18n_log("Loading translations for language " << fallback_language);
+ if (boost::filesystem::exists(filename, ignored_ec)) {
+ if (!epee::file_io_utils::load_file_to_string(filename, contents)) {
+ i18n_log("Failed to load translations file: " << filename);
+ return -1;
+ }
+ } else {
+ i18n_log("Translations file not found: " << filename);
+ filename = std::string(base) + "_" + fallback_language + ".qm";
+ if (!find_embedded_file(filename, contents)) {
+ i18n_log("Embedded translations file not found: " << filename);
+ return -1;
+ }
+ }
+ } else {
return -1;
}
}
}
- if (!epee::file_io_utils::load_file_to_string(filename, contents)) {
- i18n_log("Failed to load translations file: " << filename);
- return -1;
- }
-
data = (const unsigned char*)contents.c_str();
datalen = contents.size();
idx = 0;
diff --git a/src/common/password.cpp b/src/common/password.cpp
index dc0856160..011123300 100644
--- a/src/common/password.cpp
+++ b/src/common/password.cpp
@@ -46,7 +46,7 @@
#include "readline_buffer.h"
#endif
-#include "common/memwipe.h"
+#include "memwipe.h"
namespace
{
diff --git a/src/common/stack_trace.cpp b/src/common/stack_trace.cpp
index bcdf72b60..ed1093309 100644
--- a/src/common/stack_trace.cpp
+++ b/src/common/stack_trace.cpp
@@ -28,7 +28,10 @@
#if !defined __GNUC__ || defined __MINGW32__ || defined __MINGW64__ || defined __ANDROID__
#define USE_UNWIND
+#else
+#define ELPP_FEATURE_CRASH_LOG 1
#endif
+#include "easylogging++/easylogging++.h"
#include <stdexcept>
#ifdef USE_UNWIND
diff --git a/src/common/threadpool.cpp b/src/common/threadpool.cpp
index 20c5765b0..5d749e08e 100644
--- a/src/common/threadpool.cpp
+++ b/src/common/threadpool.cpp
@@ -34,6 +34,8 @@
#include "cryptonote_config.h"
#include "common/util.h"
+static __thread int depth = 0;
+
namespace tools
{
threadpool::threadpool() : running(true), active(0) {
@@ -60,11 +62,13 @@ threadpool::~threadpool() {
void threadpool::submit(waiter *obj, std::function<void()> f) {
entry e = {obj, f};
boost::unique_lock<boost::mutex> lock(mutex);
- if (active == max && !queue.empty()) {
+ if ((active == max && !queue.empty()) || depth > 0) {
// if all available threads are already running
// and there's work waiting, just run in current thread
lock.unlock();
+ ++depth;
f();
+ --depth;
} else {
if (obj)
obj->inc();
@@ -106,7 +110,9 @@ void threadpool::run() {
e = queue.front();
queue.pop_front();
lock.unlock();
+ ++depth;
e.f();
+ --depth;
if (e.wo)
e.wo->dec();
diff --git a/src/common/util.cpp b/src/common/util.cpp
index 2a2f50c4f..a4a435104 100644
--- a/src/common/util.cpp
+++ b/src/common/util.cpp
@@ -39,6 +39,7 @@
#include "wipeable_string.h"
using namespace epee;
+#include "crypto/crypto.h"
#include "util.h"
#include "memwipe.h"
#include "cryptonote_config.h"
diff --git a/src/crypto/CMakeLists.txt b/src/crypto/CMakeLists.txt
index fd71a87e7..764b30273 100644
--- a/src/crypto/CMakeLists.txt
+++ b/src/crypto/CMakeLists.txt
@@ -76,6 +76,7 @@ monero_add_library(cncrypto
${crypto_private_headers})
target_link_libraries(cncrypto
PUBLIC
+ epee
${Boost_SYSTEM_LIBRARY}
PRIVATE
${EXTRA_LIBRARIES})
diff --git a/src/crypto/blake256.c b/src/crypto/blake256.c
index 1e43f9c4d..95b2a6927 100644
--- a/src/crypto/blake256.c
+++ b/src/crypto/blake256.c
@@ -157,7 +157,7 @@ void blake256_update(state *S, const uint8_t *data, uint64_t datalen) {
int left = S->buflen >> 3;
int fill = 64 - left;
- if (left && (((datalen >> 3) & 0x3F) >= (unsigned) fill)) {
+ if (left && (((datalen >> 3)) >= (unsigned) fill)) {
memcpy((void *) (S->buf + left), (void *) data, fill);
S->t[0] += 512;
if (S->t[0] == 0) S->t[1]++;
diff --git a/src/crypto/chacha.h b/src/crypto/chacha.h
index a9665030d..c11e4aa2f 100644
--- a/src/crypto/chacha.h
+++ b/src/crypto/chacha.h
@@ -39,7 +39,7 @@
#if defined(__cplusplus)
#include <memory.h>
-#include "common/memwipe.h"
+#include "memwipe.h"
#include "hash.h"
namespace crypto {
diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h
index 0ce5e6d7a..a929302c1 100644
--- a/src/crypto/crypto.h
+++ b/src/crypto/crypto.h
@@ -41,7 +41,7 @@
#include "common/pod-class.h"
#include "common/util.h"
-#include "common/memwipe.h"
+#include "memwipe.h"
#include "generic-ops.h"
#include "hex.h"
#include "span.h"
diff --git a/src/cryptonote_basic/cryptonote_basic.h b/src/cryptonote_basic/cryptonote_basic.h
index 821c21d84..c81901f4e 100644
--- a/src/cryptonote_basic/cryptonote_basic.h
+++ b/src/cryptonote_basic/cryptonote_basic.h
@@ -36,7 +36,6 @@
#include <cstring> // memcmp
#include <sstream>
#include <atomic>
-#include "serialization/serialization.h"
#include "serialization/variant.h"
#include "serialization/vector.h"
#include "serialization/binary_archive.h"
diff --git a/src/cryptonote_basic/cryptonote_basic_impl.cpp b/src/cryptonote_basic/cryptonote_basic_impl.cpp
index 1183fda06..929be0d5a 100644
--- a/src/cryptonote_basic/cryptonote_basic_impl.cpp
+++ b/src/cryptonote_basic/cryptonote_basic_impl.cpp
@@ -34,7 +34,7 @@ using namespace epee;
#include "cryptonote_basic_impl.h"
#include "string_tools.h"
#include "serialization/binary_utils.h"
-#include "serialization/vector.h"
+#include "serialization/container.h"
#include "cryptonote_format_utils.h"
#include "cryptonote_config.h"
#include "misc_language.h"
diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp
index 21fa63842..5f6dc3bd6 100644
--- a/src/cryptonote_basic/cryptonote_format_utils.cpp
+++ b/src/cryptonote_basic/cryptonote_format_utils.cpp
@@ -35,6 +35,7 @@ using namespace epee;
#include <boost/algorithm/string.hpp>
#include "wipeable_string.h"
#include "string_tools.h"
+#include "serialization/string.h"
#include "cryptonote_format_utils.h"
#include "cryptonote_config.h"
#include "crypto/crypto.h"
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp
index 709c5e852..4af987c3b 100644
--- a/src/cryptonote_core/blockchain.cpp
+++ b/src/cryptonote_core/blockchain.cpp
@@ -4198,9 +4198,9 @@ uint64_t Blockchain::get_txpool_tx_count(bool include_unrelayed_txes) const
return m_db->get_txpool_tx_count(include_unrelayed_txes);
}
-txpool_tx_meta_t Blockchain::get_txpool_tx_meta(const crypto::hash& txid) const
+bool Blockchain::get_txpool_tx_meta(const crypto::hash& txid, txpool_tx_meta_t &meta) const
{
- return m_db->get_txpool_tx_meta(txid);
+ return m_db->get_txpool_tx_meta(txid, meta);
}
bool Blockchain::get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata &bd) const
diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h
index 2d5307ac0..25e573a2c 100644
--- a/src/cryptonote_core/blockchain.h
+++ b/src/cryptonote_core/blockchain.h
@@ -914,7 +914,7 @@ namespace cryptonote
void update_txpool_tx(const crypto::hash &txid, const txpool_tx_meta_t &meta);
void remove_txpool_tx(const crypto::hash &txid);
uint64_t get_txpool_tx_count(bool include_unrelayed_txes = true) const;
- txpool_tx_meta_t get_txpool_tx_meta(const crypto::hash& txid) const;
+ bool get_txpool_tx_meta(const crypto::hash& txid, txpool_tx_meta_t &meta) const;
bool get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata &bd) const;
cryptonote::blobdata get_txpool_tx_blob(const crypto::hash& txid) const;
bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata*)>, bool include_blob = false, bool include_unrelayed_txes = true) const;
diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp
index e6f217463..8773c1f74 100644
--- a/src/cryptonote_core/tx_pool.cpp
+++ b/src/cryptonote_core/tx_pool.cpp
@@ -371,7 +371,12 @@ namespace cryptonote
try
{
LockedTXN lock(m_blockchain);
- txpool_tx_meta_t meta = m_blockchain.get_txpool_tx_meta(id);
+ txpool_tx_meta_t meta;
+ if (!m_blockchain.get_txpool_tx_meta(id, meta))
+ {
+ MERROR("Failed to find tx in txpool");
+ return false;
+ }
cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(id);
if (!parse_and_validate_tx_from_blob(txblob, tx))
{
@@ -514,10 +519,13 @@ namespace cryptonote
{
try
{
- txpool_tx_meta_t meta = m_blockchain.get_txpool_tx_meta(it->first);
- meta.relayed = true;
- meta.last_relayed_time = now;
- m_blockchain.update_txpool_tx(it->first, meta);
+ txpool_tx_meta_t meta;
+ if (m_blockchain.get_txpool_tx_meta(it->first, meta))
+ {
+ meta.relayed = true;
+ meta.last_relayed_time = now;
+ m_blockchain.update_txpool_tx(it->first, meta);
+ }
}
catch (const std::exception &e)
{
@@ -696,7 +704,11 @@ namespace cryptonote
{
try
{
- meta = m_blockchain.get_txpool_tx_meta(tx_id_hash);
+ if (!m_blockchain.get_txpool_tx_meta(tx_id_hash, meta))
+ {
+ MERROR("Failed to get tx meta from txpool");
+ return false;
+ }
if (!meta.relayed)
// Do not include that transaction if in restricted mode and it's not relayed
continue;
@@ -918,7 +930,13 @@ namespace cryptonote
{
for (const crypto::hash &txid: it->second)
{
- txpool_tx_meta_t meta = m_blockchain.get_txpool_tx_meta(txid);
+ txpool_tx_meta_t meta;
+ if (!m_blockchain.get_txpool_tx_meta(txid, meta))
+ {
+ MERROR("Failed to find tx meta in txpool");
+ // continue, not fatal
+ continue;
+ }
if (!meta.double_spend_seen)
{
MDEBUG("Marking " << txid << " as double spending " << itk.k_image);
@@ -998,7 +1016,12 @@ namespace cryptonote
auto sorted_it = m_txs_by_fee_and_receive_time.begin();
while (sorted_it != m_txs_by_fee_and_receive_time.end())
{
- txpool_tx_meta_t meta = m_blockchain.get_txpool_tx_meta(sorted_it->second);
+ txpool_tx_meta_t meta;
+ if (!m_blockchain.get_txpool_tx_meta(sorted_it->second, meta))
+ {
+ MERROR(" failed to find tx meta");
+ continue;
+ }
LOG_PRINT_L2("Considering " << sorted_it->second << ", size " << meta.blob_size << ", current block size " << total_size << "/" << max_total_size << ", current coinbase " << print_money(best_coinbase));
// Can not exceed maximum block size
diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl
index 8aef31a5a..5d25d1058 100644
--- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl
+++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl
@@ -1059,6 +1059,11 @@ skip:
num_txs += block_entry.txs.size();
std::vector<tx_verification_context> tvc;
m_core.handle_incoming_txs(block_entry.txs, tvc, true, true, false);
+ if (tvc.size() != block_entry.txs.size())
+ {
+ LOG_ERROR_CCONTEXT("Internal error: tvc.size() != block_entry.txs.size()");
+ return true;
+ }
std::list<blobdata>::const_iterator it = block_entry.txs.begin();
for (size_t i = 0; i < tvc.size(); ++i, ++it)
{
diff --git a/src/daemon/CMakeLists.txt b/src/daemon/CMakeLists.txt
index ad84db450..237105d06 100644
--- a/src/daemon/CMakeLists.txt
+++ b/src/daemon/CMakeLists.txt
@@ -29,9 +29,9 @@
set(blocksdat "")
if(PER_BLOCK_CHECKPOINT)
if(APPLE)
- add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*)
+ add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*)
else()
- add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ../blocks/checkpoints.dat blocks.dat && ${CMAKE_LINKER} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat)
+ add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ../blocks/checkpoints.dat blocks.dat && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat)
endif()
set(blocksdat "blocksdat.o")
endif()
@@ -102,7 +102,7 @@ target_link_libraries(daemon
${Boost_SYSTEM_LIBRARY}
${CMAKE_THREAD_LIBS_INIT}
${ZMQ_LIB}
- ${Readline_LIBRARY}
+ ${GNU_READLINE_LIBRARY}
${EXTRA_LIBRARIES})
set_property(TARGET daemon
PROPERTY
diff --git a/src/daemon/core.h b/src/daemon/core.h
index 97f1cb8c1..bf4f9bb3d 100644
--- a/src/daemon/core.h
+++ b/src/daemon/core.h
@@ -31,7 +31,6 @@
#include "cryptonote_core/cryptonote_core.h"
#include "cryptonote_protocol/cryptonote_protocol_handler.h"
#include "misc_log_ex.h"
-#include "daemon/command_line_args.h"
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "daemon"
diff --git a/src/daemon/daemon.cpp b/src/daemon/daemon.cpp
index 3bc6ea392..55d868a3c 100644
--- a/src/daemon/daemon.cpp
+++ b/src/daemon/daemon.cpp
@@ -43,8 +43,9 @@
#include "daemon/protocol.h"
#include "daemon/rpc.h"
#include "daemon/command_server.h"
+#include "daemon/command_server.h"
+#include "daemon/command_line_args.h"
#include "version.h"
-#include "syncobj.h"
using namespace epee;
diff --git a/src/daemon/executor.cpp b/src/daemon/executor.cpp
index 6130bfa28..3379eeca4 100644
--- a/src/daemon/executor.cpp
+++ b/src/daemon/executor.cpp
@@ -30,7 +30,6 @@
#include "daemon/executor.h"
-#include "common/command_line.h"
#include "cryptonote_config.h"
#include "version.h"
diff --git a/src/daemon/main.cpp b/src/daemon/main.cpp
index 6ac47fcb2..a47e74c71 100644
--- a/src/daemon/main.cpp
+++ b/src/daemon/main.cpp
@@ -269,7 +269,7 @@ int main(int argc, char const * argv[])
}
else
{
- std::cerr << "Unknown command" << std::endl;
+ std::cerr << "Unknown command: " << command.front() << std::endl;
return 1;
}
}
diff --git a/src/daemon/protocol.h b/src/daemon/protocol.h
index fc5edbcaa..01de535d5 100644
--- a/src/daemon/protocol.h
+++ b/src/daemon/protocol.h
@@ -33,8 +33,6 @@
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "daemon"
-#include "common/scoped_message_writer.h"
-
namespace daemonize
{
diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp
index 8aca668ad..2e2411708 100644
--- a/src/daemon/rpc_command_executor.cpp
+++ b/src/daemon/rpc_command_executor.cpp
@@ -538,7 +538,7 @@ bool t_rpc_command_executor::print_blockchain_info(uint64_t start_block_index, u
std::cout << std::endl;
std::cout
<< "height: " << header.height << ", timestamp: " << header.timestamp << ", difficulty: " << header.difficulty
- << ", size: " << header.block_size << std::endl
+ << ", size: " << header.block_size << ", transactions: " << header.num_txes << std::endl
<< "major version: " << (unsigned)header.major_version << ", minor version: " << (unsigned)header.minor_version << std::endl
<< "block id: " << header.hash << ", previous block id: " << header.prev_hash << std::endl
<< "difficulty: " << header.difficulty << ", nonce " << header.nonce << ", reward " << cryptonote::print_money(header.reward) << std::endl;
diff --git a/src/gen_multisig/CMakeLists.txt b/src/gen_multisig/CMakeLists.txt
index ff3c46862..8c534d213 100644
--- a/src/gen_multisig/CMakeLists.txt
+++ b/src/gen_multisig/CMakeLists.txt
@@ -43,8 +43,8 @@ target_link_libraries(gen_multisig
${Boost_PROGRAM_OPTIONS_LIBRARY}
${Boost_FILESYSTEM_LIBRARY}
${Boost_THREAD_LIBRARY}
- ${Readline_LIBRARY}
${CMAKE_THREAD_LIBS_INIT}
+ ${GNU_READLINE_LIBRARY}
${EXTRA_LIBRARIES})
add_dependencies(gen_multisig
version)
diff --git a/src/mnemonics/CMakeLists.txt b/src/mnemonics/CMakeLists.txt
index 5ce2198ae..79964e873 100644
--- a/src/mnemonics/CMakeLists.txt
+++ b/src/mnemonics/CMakeLists.txt
@@ -57,6 +57,7 @@ monero_add_library(mnemonics
${mnemonics_private_headers})
target_link_libraries(mnemonics
PUBLIC
+ epee
easylogging
${Boost_SYSTEM_LIBRARY}
PRIVATE
diff --git a/src/mnemonics/electrum-words.cpp b/src/mnemonics/electrum-words.cpp
index ba67952aa..f44ad40aa 100644
--- a/src/mnemonics/electrum-words.cpp
+++ b/src/mnemonics/electrum-words.cpp
@@ -410,7 +410,7 @@ namespace crypto
std::vector<std::string> words_store;
uint32_t word_list_length = word_list.size();
- // 8 bytes -> 3 words. 8 digits base 16 -> 3 digits base 1626
+ // 4 bytes -> 3 words. 8 digits base 16 -> 3 digits base 1626
for (unsigned int i=0; i < len/4; i++, words += ' ')
{
uint32_t w1, w2, w3;
diff --git a/src/p2p/CMakeLists.txt b/src/p2p/CMakeLists.txt
index 123b0a272..3fc053dc7 100644
--- a/src/p2p/CMakeLists.txt
+++ b/src/p2p/CMakeLists.txt
@@ -46,5 +46,6 @@ target_link_libraries(p2p
${Boost_FILESYSTEM_LIBRARY}
${Boost_SYSTEM_LIBRARY}
${Boost_THREAD_LIBRARY}
+ ${Boost_SERIALIZATION_LIBRARY}
PRIVATE
${EXTRA_LIBRARIES})
diff --git a/src/ringct/rctTypes.h b/src/ringct/rctTypes.h
index 5ea2dcc7c..2df797360 100644
--- a/src/ringct/rctTypes.h
+++ b/src/ringct/rctTypes.h
@@ -47,7 +47,7 @@ extern "C" {
#include "hex.h"
#include "span.h"
-#include "serialization/serialization.h"
+#include "serialization/vector.h"
#include "serialization/debug_archive.h"
#include "serialization/binary_archive.h"
#include "serialization/json_archive.h"
diff --git a/src/rpc/CMakeLists.txt b/src/rpc/CMakeLists.txt
index 748c6b8c1..19ea93902 100644
--- a/src/rpc/CMakeLists.txt
+++ b/src/rpc/CMakeLists.txt
@@ -101,6 +101,7 @@ target_link_libraries(rpc_base
epee
${Boost_REGEX_LIBRARY}
${Boost_THREAD_LIBRARY}
+ ${Boost_PROGRAM_OPTIONS_LIBRARY}
PRIVATE
${EXTRA_LIBRARIES})
@@ -125,6 +126,7 @@ target_link_libraries(daemon_messages
target_link_libraries(daemon_rpc_server
LINK_PRIVATE
+ rpc
cryptonote_core
cryptonote_protocol
daemon_messages
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index a6109cb89..4966b107d 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -106,8 +106,9 @@ namespace cryptonote
if (rpc_config->login)
http_login.emplace(std::move(rpc_config->login->username), std::move(rpc_config->login->password).password());
+ auto rng = [](size_t len, uint8_t *ptr){ return crypto::rand(len, ptr); };
return epee::http_server_impl_base<core_rpc_server, connection_context>::init(
- std::move(port), std::move(rpc_config->bind_ip), std::move(rpc_config->access_control_origins), std::move(http_login)
+ rng, std::move(port), std::move(rpc_config->bind_ip), std::move(rpc_config->access_control_origins), std::move(http_login)
);
}
//------------------------------------------------------------------------------------------------------------------------------
diff --git a/src/serialization/container.h b/src/serialization/container.h
new file mode 100644
index 000000000..978a59d2a
--- /dev/null
+++ b/src/serialization/container.h
@@ -0,0 +1,113 @@
+// Copyright (c) 2014-2017, 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.
+//
+// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
+
+#pragma once
+
+#include "serialization.h"
+
+namespace serialization
+{
+ namespace detail
+ {
+ template <typename Archive, class T>
+ bool serialize_container_element(Archive& ar, T& e)
+ {
+ return ::do_serialize(ar, e);
+ }
+
+ template <typename Archive>
+ bool serialize_container_element(Archive& ar, uint32_t& e)
+ {
+ ar.serialize_varint(e);
+ return true;
+ }
+
+ template <typename Archive>
+ bool serialize_container_element(Archive& ar, uint64_t& e)
+ {
+ ar.serialize_varint(e);
+ return true;
+ }
+
+ template <typename C>
+ void do_reserve(C &c, size_t N) {}
+ }
+}
+
+template <template <bool> class Archive, typename C>
+bool do_serialize_container(Archive<false> &ar, C &v)
+{
+ size_t cnt;
+ ar.begin_array(cnt);
+ if (!ar.stream().good())
+ return false;
+ v.clear();
+
+ // very basic sanity check
+ if (ar.remaining_bytes() < cnt) {
+ ar.stream().setstate(std::ios::failbit);
+ return false;
+ }
+
+ ::serialization::detail::do_reserve(v, cnt);
+
+ for (size_t i = 0; i < cnt; i++) {
+ if (i > 0)
+ ar.delimit_array();
+ typename C::value_type e;
+ if (!::serialization::detail::serialize_container_element(ar, e))
+ return false;
+ ::serialization::detail::do_add(v, std::move(e));
+ if (!ar.stream().good())
+ return false;
+ }
+ ar.end_array();
+ return true;
+}
+
+template <template <bool> class Archive, typename C>
+bool do_serialize_container(Archive<true> &ar, C &v)
+{
+ size_t cnt = v.size();
+ ar.begin_array(cnt);
+ for (auto i = v.begin(); i != v.end(); ++i)
+ {
+ if (!ar.stream().good())
+ return false;
+ if (i != v.begin())
+ ar.delimit_array();
+ if(!::serialization::detail::serialize_container_element(ar, const_cast<typename C::value_type&>(*i)))
+ return false;
+ if (!ar.stream().good())
+ return false;
+ }
+ ar.end_array();
+ return true;
+}
diff --git a/src/serialization/deque.h b/src/serialization/deque.h
new file mode 100644
index 000000000..994d3f195
--- /dev/null
+++ b/src/serialization/deque.h
@@ -0,0 +1,64 @@
+// Copyright (c) 2014-2017, 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.
+//
+// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
+
+#pragma once
+
+#include <deque>
+
+template <template <bool> class Archive, class T>
+bool do_serialize(Archive<false> &ar, std::deque<T> &v);
+template <template <bool> class Archive, class T>
+bool do_serialize(Archive<true> &ar, std::deque<T> &v);
+
+namespace serialization
+{
+ namespace detail
+ {
+ template <typename T>
+ void do_reserve(std::deque<T> &c, size_t N)
+ {
+ c.reserve(N);
+ }
+
+ template <typename T>
+ void do_add(std::deque<T> &c, T &&e)
+ {
+ c.emplace_back(std::move(e));
+ }
+ }
+}
+
+#include "serialization.h"
+
+template <template <bool> class Archive, class T>
+bool do_serialize(Archive<false> &ar, std::deque<T> &v) { return do_serialize_container(ar, v); }
+template <template <bool> class Archive, class T>
+bool do_serialize(Archive<true> &ar, std::deque<T> &v) { return do_serialize_container(ar, v); }
+
diff --git a/src/serialization/list.h b/src/serialization/list.h
index d0fb72163..d725458e7 100644
--- a/src/serialization/list.h
+++ b/src/serialization/list.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2015, The Monero Project
+// Copyright (c) 2014-2017, The Monero Project
//
// All rights reserved.
//
@@ -30,71 +30,29 @@
#pragma once
-#include "serialization.h"
+#include <list>
+
+template <template <bool> class Archive, class T>
+bool do_serialize(Archive<false> &ar, std::list<T> &v);
+template <template <bool> class Archive, class T>
+bool do_serialize(Archive<true> &ar, std::list<T> &v);
namespace serialization
{
namespace detail
{
- template <typename Archive, class T>
- bool serialize_list_element(Archive& ar, T& e)
- {
- return ::do_serialize(ar, e);
- }
-
- template <typename Archive>
- bool serialize_list_element(Archive& ar, uint64_t& e)
+ template <typename T>
+ void do_add(std::list<T> &c, T &&e)
{
- ar.serialize_varint(e);
- return true;
+ c.emplace_back(std::move(e));
}
}
}
-template <template <bool> class Archive, class T>
-bool do_serialize(Archive<false> &ar, std::list<T> &l)
-{
- size_t cnt;
- ar.begin_array(cnt);
- if (!ar.stream().good())
- return false;
- l.clear();
-
- // very basic sanity check
- if (ar.remaining_bytes() < cnt) {
- ar.stream().setstate(std::ios::failbit);
- return false;
- }
-
- for (size_t i = 0; i < cnt; i++) {
- if (i > 0)
- ar.delimit_array();
- l.push_back(T());
- T &t = l.back();
- if (!::serialization::detail::serialize_list_element(ar, t))
- return false;
- if (!ar.stream().good())
- return false;
- }
- ar.end_array();
- return true;
-}
+#include "serialization.h"
template <template <bool> class Archive, class T>
-bool do_serialize(Archive<true> &ar, std::list<T> &l)
-{
- size_t cnt = l.size();
- ar.begin_array(cnt);
- for (typename std::list<T>::iterator i = l.begin(); i != l.end(); ++i) {
- if (!ar.stream().good())
- return false;
- if (i != l.begin())
- ar.delimit_array();
- if(!::serialization::detail::serialize_list_element(ar, *i))
- return false;
- if (!ar.stream().good())
- return false;
- }
- ar.end_array();
- return true;
-}
+bool do_serialize(Archive<false> &ar, std::list<T> &v) { return do_serialize_container(ar, v); }
+template <template <bool> class Archive, class T>
+bool do_serialize(Archive<true> &ar, std::list<T> &v) { return do_serialize_container(ar, v); }
+
diff --git a/src/serialization/serialization.h b/src/serialization/serialization.h
index 9e23f0791..56496c790 100644
--- a/src/serialization/serialization.h
+++ b/src/serialization/serialization.h
@@ -63,15 +63,17 @@ struct is_blob_type { typedef boost::false_type type; };
template <class T>
struct has_free_serializer { typedef boost::true_type type; };
-/*! \struct is_pair_type
+/*! \struct is_basic_type
*
* \brief a descriptor for dispatching serialize
*/
template <class T>
-struct is_pair_type { typedef boost::false_type type; };
+struct is_basic_type { typedef boost::false_type type; };
template<typename F, typename S>
-struct is_pair_type<std::pair<F,S>> { typedef boost::true_type type; };
+struct is_basic_type<std::pair<F,S>> { typedef boost::true_type type; };
+template<>
+struct is_basic_type<std::string> { typedef boost::true_type type; };
/*! \struct serializer
*
@@ -89,7 +91,7 @@ struct is_pair_type<std::pair<F,S>> { typedef boost::true_type type; };
template <class Archive, class T>
struct serializer{
static bool serialize(Archive &ar, T &v) {
- return serialize(ar, v, typename boost::is_integral<T>::type(), typename is_blob_type<T>::type(), typename is_pair_type<T>::type());
+ return serialize(ar, v, typename boost::is_integral<T>::type(), typename is_blob_type<T>::type(), typename is_basic_type<T>::type());
}
template<typename A>
static bool serialize(Archive &ar, T &v, boost::false_type, boost::true_type, A a) {
@@ -361,9 +363,3 @@ namespace serialization {
return r && check_stream_state(ar);
}
}
-
-#include "string.h"
-#include "vector.h"
-#include "list.h"
-#include "pair.h"
-#include "set.h"
diff --git a/src/serialization/set.h b/src/serialization/set.h
index 54b4eb3ab..e6eff62a9 100644
--- a/src/serialization/set.h
+++ b/src/serialization/set.h
@@ -30,98 +30,29 @@
#pragma once
-#include "serialization.h"
+#include <set>
template <template <bool> class Archive, class T>
bool do_serialize(Archive<false> &ar, std::set<T> &v);
template <template <bool> class Archive, class T>
bool do_serialize(Archive<true> &ar, std::set<T> &v);
-template <template <bool> class Archive, class T>
-bool do_serialize(Archive<false> &ar, std::unordered_set<T> &v);
-template <template <bool> class Archive, class T>
-bool do_serialize(Archive<true> &ar, std::unordered_set<T> &v);
namespace serialization
{
namespace detail
{
- template <typename Archive, class T>
- bool serialize_set_element(Archive& ar, T& e)
+ template <typename T>
+ void do_add(std::set<T> &c, T &&e)
{
- return ::do_serialize(ar, e);
- }
-
- template <typename Archive>
- bool serialize_set_element(Archive& ar, uint32_t& e)
- {
- ar.serialize_varint(e);
- return true;
- }
-
- template <typename Archive>
- bool serialize_set_element(Archive& ar, uint64_t& e)
- {
- ar.serialize_varint(e);
- return true;
+ c.insert(std::move(e));
}
}
}
-template <template <bool> class Archive, class T>
-bool do_serialize_set(Archive<false> &ar, T &v)
-{
- size_t cnt;
- ar.begin_array(cnt);
- if (!ar.stream().good())
- return false;
- v.clear();
-
- // very basic sanity check
- if (ar.remaining_bytes() < cnt) {
- ar.stream().setstate(std::ios::failbit);
- return false;
- }
-
- for (size_t i = 0; i < cnt; i++) {
- if (i > 0)
- ar.delimit_array();
- typename T::key_type k;
- if (!::serialization::detail::serialize_set_element(ar, k))
- return false;
- v.insert(std::move(k));
- if (!ar.stream().good())
- return false;
- }
- ar.end_array();
- return true;
-}
-
-template <template <bool> class Archive, class T>
-bool do_serialize_set(Archive<true> &ar, T &v)
-{
- size_t cnt = v.size();
- ar.begin_array(cnt);
- bool first = true;
- for (const typename T::key_type &k: v) {
- if (!ar.stream().good())
- return false;
- if (!first)
- ar.delimit_array();
- if(!::serialization::detail::serialize_set_element(ar, const_cast<typename T::key_type&>(k)))
- return false;
- if (!ar.stream().good())
- return false;
- first = false;
- }
- ar.end_array();
- return true;
-}
+#include "serialization.h"
template <template <bool> class Archive, class T>
-bool do_serialize(Archive<false> &ar, std::set<T> &v) { return do_serialize_set(ar, v); }
+bool do_serialize(Archive<false> &ar, std::set<T> &v) { return do_serialize_container(ar, v); }
template <template <bool> class Archive, class T>
-bool do_serialize(Archive<true> &ar, std::set<T> &v) { return do_serialize_set(ar, v); }
-template <template <bool> class Archive, class T>
-bool do_serialize(Archive<false> &ar, std::unordered_set<T> &v) { return do_serialize_set(ar, v); }
-template <template <bool> class Archive, class T>
-bool do_serialize(Archive<true> &ar, std::unordered_set<T> &v) { return do_serialize_set(ar, v); }
+bool do_serialize(Archive<true> &ar, std::set<T> &v) { return do_serialize_container(ar, v); }
+
diff --git a/src/serialization/unordered_set.h b/src/serialization/unordered_set.h
new file mode 100644
index 000000000..b277f0c4a
--- /dev/null
+++ b/src/serialization/unordered_set.h
@@ -0,0 +1,58 @@
+// Copyright (c) 2014-2017, 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.
+//
+// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
+
+#pragma once
+
+#include <set>
+
+template <template <bool> class Archive, class T>
+bool do_serialize(Archive<false> &ar, std::unordered_set<T> &v);
+template <template <bool> class Archive, class T>
+bool do_serialize(Archive<true> &ar, std::unordered_set<T> &v);
+
+namespace serialization
+{
+ namespace detail
+ {
+ template <typename T>
+ void do_add(std::unordered_set<T> &c, T &&e)
+ {
+ c.insert(std::move(e));
+ }
+ }
+}
+
+#include "serialization.h"
+
+template <template <bool> class Archive, class T>
+bool do_serialize(Archive<false> &ar, std::unordered_set<T> &v) { return do_serialize_container(ar, v); }
+template <template <bool> class Archive, class T>
+bool do_serialize(Archive<true> &ar, std::unordered_set<T> &v) { return do_serialize_container(ar, v); }
+
diff --git a/src/serialization/vector.h b/src/serialization/vector.h
index 12fd59558..9cf3d8272 100644
--- a/src/serialization/vector.h
+++ b/src/serialization/vector.h
@@ -30,6 +30,7 @@
#pragma once
+#include <vector>
#include "serialization.h"
template <template <bool> class Archive, class T>
@@ -37,91 +38,28 @@ bool do_serialize(Archive<false> &ar, std::vector<T> &v);
template <template <bool> class Archive, class T>
bool do_serialize(Archive<true> &ar, std::vector<T> &v);
-template <template <bool> class Archive, class T>
-bool do_serialize(Archive<false> &ar, std::deque<T> &v);
-template <template <bool> class Archive, class T>
-bool do_serialize(Archive<true> &ar, std::deque<T> &v);
-
namespace serialization
{
namespace detail
{
- template <typename Archive, class T>
- bool serialize_vector_element(Archive& ar, T& e)
- {
- return ::do_serialize(ar, e);
- }
-
- template <typename Archive>
- bool serialize_vector_element(Archive& ar, uint32_t& e)
+ template <typename T>
+ void do_reserve(std::vector<T> &c, size_t N)
{
- ar.serialize_varint(e);
- return true;
+ c.reserve(N);
}
- template <typename Archive>
- bool serialize_vector_element(Archive& ar, uint64_t& e)
+ template <typename T>
+ void do_add(std::vector<T> &c, T &&e)
{
- ar.serialize_varint(e);
- return true;
+ c.emplace_back(std::move(e));
}
}
}
-template <template <bool> class Archive, class T>
-bool do_serialize_vd(Archive<false> &ar, T &v)
-{
- size_t cnt;
- ar.begin_array(cnt);
- if (!ar.stream().good())
- return false;
- v.clear();
-
- // very basic sanity check
- if (ar.remaining_bytes() < cnt) {
- ar.stream().setstate(std::ios::failbit);
- return false;
- }
-
- v.reserve(cnt);
- for (size_t i = 0; i < cnt; i++) {
- if (i > 0)
- ar.delimit_array();
- v.resize(i+1);
- if (!::serialization::detail::serialize_vector_element(ar, v[i]))
- return false;
- if (!ar.stream().good())
- return false;
- }
- ar.end_array();
- return true;
-}
-
-template <template <bool> class Archive, class T>
-bool do_serialize_vd(Archive<true> &ar, T &v)
-{
- size_t cnt = v.size();
- ar.begin_array(cnt);
- for (size_t i = 0; i < cnt; i++) {
- if (!ar.stream().good())
- return false;
- if (i > 0)
- ar.delimit_array();
- if(!::serialization::detail::serialize_vector_element(ar, v[i]))
- return false;
- if (!ar.stream().good())
- return false;
- }
- ar.end_array();
- return true;
-}
+#include "container.h"
template <template <bool> class Archive, class T>
-bool do_serialize(Archive<false> &ar, std::vector<T> &v) { return do_serialize_vd(ar, v); }
+bool do_serialize(Archive<false> &ar, std::vector<T> &v) { return do_serialize_container(ar, v); }
template <template <bool> class Archive, class T>
-bool do_serialize(Archive<true> &ar, std::vector<T> &v) { return do_serialize_vd(ar, v); }
+bool do_serialize(Archive<true> &ar, std::vector<T> &v) { return do_serialize_container(ar, v); }
-template <template <bool> class Archive, class T>
-bool do_serialize(Archive<false> &ar, std::deque<T> &v) { return do_serialize_vd(ar, v); }
-template <template <bool> class Archive, class T>
-bool do_serialize(Archive<true> &ar, std::deque<T> &v) { return do_serialize_vd(ar, v); }
diff --git a/src/simplewallet/CMakeLists.txt b/src/simplewallet/CMakeLists.txt
index beaacf0e9..f190ada8d 100644
--- a/src/simplewallet/CMakeLists.txt
+++ b/src/simplewallet/CMakeLists.txt
@@ -55,8 +55,8 @@ target_link_libraries(simplewallet
${Boost_PROGRAM_OPTIONS_LIBRARY}
${Boost_FILESYSTEM_LIBRARY}
${Boost_THREAD_LIBRARY}
- ${Readline_LIBRARY}
${CMAKE_THREAD_LIBS_INIT}
+ ${GNU_READLINE_LIBRARY}
${EXTRA_LIBRARIES})
set_property(TARGET simplewallet
PROPERTY
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index ed426aedd..ef4841523 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -121,6 +121,7 @@ namespace
const command_line::arg_descriptor<std::string> arg_mnemonic_language = {"mnemonic-language", sw::tr("Language for mnemonic"), ""};
const command_line::arg_descriptor<std::string> arg_electrum_seed = {"electrum-seed", sw::tr("Specify Electrum seed for wallet recovery/creation"), ""};
const command_line::arg_descriptor<bool> arg_restore_deterministic_wallet = {"restore-deterministic-wallet", sw::tr("Recover wallet using Electrum-style mnemonic seed"), false};
+ 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("Create 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_allow_mismatched_daemon_version = {"allow-mismatched-daemon-version", sw::tr("Allow communicating with a daemon that uses a different RPC version"), false};
@@ -516,48 +517,55 @@ bool simple_wallet::spendkey(const std::vector<std::string> &args/* = std::vecto
bool simple_wallet::print_seed(bool encrypted)
{
bool success = false;
- std::string electrum_words;
+ std::string seed;
+ bool ready, multisig;
- if (m_wallet->multisig())
- {
- fail_msg_writer() << tr("wallet is multisig and has no seed");
- return true;
- }
if (m_wallet->watch_only())
{
fail_msg_writer() << tr("wallet is watch-only and has no seed");
return true;
}
if (m_wallet->ask_password() && !get_and_verify_password()) { return true; }
- if (m_wallet->is_deterministic())
- {
- if (m_wallet->get_seed_language().empty())
- {
- std::string mnemonic_language = get_mnemonic_language();
- if (mnemonic_language.empty())
- return true;
- m_wallet->set_seed_language(mnemonic_language);
- }
- epee::wipeable_string seed_pass;
- if (encrypted)
+ multisig = m_wallet->multisig(&ready);
+ if (multisig)
+ {
+ if (!ready)
{
- auto pwd_container = tools::password_container::prompt(true, tr("Enter optional seed encryption passphrase, empty to see raw seed"));
- if (std::cin.eof() || !pwd_container)
- return true;
- seed_pass = pwd_container->password();
+ fail_msg_writer() << tr("wallet is multisig but not yet finalized");
+ return true;
}
+ }
+ else if (!m_wallet->is_deterministic())
+ {
+ fail_msg_writer() << tr("wallet is non-deterministic and has no seed");
+ return true;
+ }
- success = m_wallet->get_seed(electrum_words, seed_pass);
+ epee::wipeable_string seed_pass;
+ if (encrypted)
+ {
+#ifdef HAVE_READLINE
+ rdln::suspend_readline pause_readline;
+#endif
+ auto pwd_container = tools::password_container::prompt(true, tr("Enter optional seed encryption passphrase, empty to see raw seed"));
+ if (std::cin.eof() || !pwd_container)
+ return true;
+ seed_pass = pwd_container->password();
}
+ if (multisig)
+ success = m_wallet->get_multisig_seed(seed, seed_pass);
+ else if (m_wallet->is_deterministic())
+ success = m_wallet->get_seed(seed, seed_pass);
+
if (success)
{
- print_seed(electrum_words);
+ print_seed(seed);
}
else
{
- fail_msg_writer() << tr("wallet is non-deterministic and has no seed");
+ fail_msg_writer() << tr("Failed to retrieve seed");
}
return true;
}
@@ -1762,11 +1770,11 @@ simple_wallet::simple_wallet()
tr("Turn this wallet into a multisig wallet, extra step for N-1/N wallets"));
m_cmd_binder.set_handler("export_multisig_info",
boost::bind(&simple_wallet::export_multisig, this, _1),
- tr("export_multisig <filename>"),
+ tr("export_multisig_info <filename>"),
tr("Export multisig info for other participants"));
m_cmd_binder.set_handler("import_multisig_info",
boost::bind(&simple_wallet::import_multisig, this, _1),
- tr("import_multisig <filename> [<filename>...]"),
+ tr("import_multisig_info <filename> [<filename>...]"),
tr("Import multisig info from other participants"));
m_cmd_binder.set_handler("sign_multisig",
boost::bind(&simple_wallet::sign_multisig, this, _1),
@@ -1778,7 +1786,7 @@ simple_wallet::simple_wallet()
tr("Submit a signed multisig transaction from a file"));
m_cmd_binder.set_handler("export_raw_multisig_tx",
boost::bind(&simple_wallet::export_raw_multisig, this, _1),
- tr("export_raw_multisig <filename>"),
+ tr("export_raw_multisig_tx <filename>"),
tr("Export a signed multisig transaction to a file"));
m_cmd_binder.set_handler("help",
boost::bind(&simple_wallet::help, this, _1),
@@ -1984,6 +1992,8 @@ static bool might_be_partial_seed(std::string words)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::init(const boost::program_options::variables_map& vm)
{
+ std::string multisig_keys;
+
if (!handle_command_line(vm))
return false;
@@ -2001,49 +2011,91 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
{
std::string old_language;
// check for recover flag. if present, require electrum word list (only recovery option for now).
- if (m_restore_deterministic_wallet)
+ if (m_restore_deterministic_wallet || m_restore_multisig_wallet)
{
if (m_non_deterministic)
{
- fail_msg_writer() << tr("can't specify both --restore-deterministic-wallet and --non-deterministic");
+ fail_msg_writer() << tr("can't specify both --restore-deterministic-wallet or --restore-multisig-wallet and --non-deterministic");
return false;
}
if (!m_wallet_file.empty())
{
- fail_msg_writer() << tr("--restore-deterministic-wallet uses --generate-new-wallet, not --wallet-file");
+ if (m_restore_multisig_wallet)
+ fail_msg_writer() << tr("--restore-multisig-wallet uses --generate-new-wallet, not --wallet-file");
+ else
+ fail_msg_writer() << tr("--restore-deterministic-wallet uses --generate-new-wallet, not --wallet-file");
return false;
}
if (m_electrum_seed.empty())
{
- m_electrum_seed = "";
- do
+ if (m_restore_multisig_wallet)
{
- const char *prompt = m_electrum_seed.empty() ? "Specify Electrum seed: " : "Electrum seed continued: ";
- std::string electrum_seed = input_line(prompt);
- if (std::cin.eof())
- return false;
- if (electrum_seed.empty())
+ const char *prompt = "Specify multisig seed: ";
+ m_electrum_seed = input_line(prompt);
+ if (std::cin.eof())
+ return false;
+ if (m_electrum_seed.empty())
+ {
+ fail_msg_writer() << tr("specify a recovery parameter with the --electrum-seed=\"multisig seed here\"");
+ return false;
+ }
+ }
+ else
+ {
+ m_electrum_seed = "";
+ do
{
- fail_msg_writer() << tr("specify a recovery parameter with the --electrum-seed=\"words list here\"");
- return false;
- }
- m_electrum_seed += electrum_seed + " ";
- } while (might_be_partial_seed(m_electrum_seed));
+ const char *prompt = m_electrum_seed.empty() ? "Specify Electrum seed: " : "Electrum seed continued: ";
+ std::string electrum_seed = input_line(prompt);
+ if (std::cin.eof())
+ return false;
+ if (electrum_seed.empty())
+ {
+ fail_msg_writer() << tr("specify a recovery parameter with the --electrum-seed=\"words list here\"");
+ return false;
+ }
+ m_electrum_seed += electrum_seed + " ";
+ } while (might_be_partial_seed(m_electrum_seed));
+ }
}
- if (!crypto::ElectrumWords::words_to_bytes(m_electrum_seed, m_recovery_key, old_language))
+ if (m_restore_multisig_wallet)
{
- fail_msg_writer() << tr("Electrum-style word list failed verification");
- return false;
+ if (!epee::string_tools::parse_hexstr_to_binbuff(m_electrum_seed, multisig_keys))
+ {
+ fail_msg_writer() << tr("Multisig seed failed verification");
+ return false;
+ }
+ }
+ else
+ {
+ if (!crypto::ElectrumWords::words_to_bytes(m_electrum_seed, m_recovery_key, old_language))
+ {
+ fail_msg_writer() << tr("Electrum-style word list failed verification");
+ return false;
+ }
}
+#ifdef HAVE_READLINE
+ rdln::suspend_readline pause_readline;
+#endif
auto pwd_container = tools::password_container::prompt(false, tr("Enter seed encryption passphrase, empty if none"));
if (std::cin.eof() || !pwd_container)
return false;
epee::wipeable_string seed_pass = pwd_container->password();
if (!seed_pass.empty())
- m_recovery_key = cryptonote::decrypt_key(m_recovery_key, seed_pass);
+ {
+ if (m_restore_multisig_wallet)
+ {
+ crypto::secret_key key;
+ crypto::cn_slow_hash(seed_pass.data(), seed_pass.size(), (crypto::hash&)key);
+ sc_reduce32((unsigned char*)key.data);
+ multisig_keys = m_wallet->decrypt(multisig_keys, key, true);
+ }
+ else
+ m_recovery_key = cryptonote::decrypt_key(m_recovery_key, seed_pass);
+ }
}
if (!m_generate_from_view_key.empty())
{
@@ -2354,7 +2406,11 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
return false;
}
m_wallet_file = m_generate_new;
- bool r = new_wallet(vm, m_recovery_key, m_restore_deterministic_wallet, m_non_deterministic, old_language);
+ bool r;
+ if (m_restore_multisig_wallet)
+ r = new_wallet(vm, multisig_keys, old_language);
+ else
+ r = new_wallet(vm, m_recovery_key, m_restore_deterministic_wallet, m_non_deterministic, old_language);
CHECK_AND_ASSERT_MES(r, false, tr("account creation failed"));
}
if (!m_restore_height && m_restoring)
@@ -2485,6 +2541,7 @@ bool simple_wallet::handle_command_line(const boost::program_options::variables_
m_mnemonic_language = command_line::get_arg(vm, arg_mnemonic_language);
m_electrum_seed = command_line::get_arg(vm, arg_electrum_seed);
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);
m_allow_mismatched_daemon_version = command_line::get_arg(vm, arg_allow_mismatched_daemon_version);
@@ -2495,7 +2552,8 @@ bool simple_wallet::handle_command_line(const boost::program_options::variables_
!m_generate_from_keys.empty() ||
!m_generate_from_multisig_keys.empty() ||
!m_generate_from_json.empty() ||
- m_restore_deterministic_wallet;
+ m_restore_deterministic_wallet ||
+ m_restore_multisig_wallet;
return true;
}
@@ -2642,11 +2700,11 @@ bool simple_wallet::new_wallet(const boost::program_options::variables_map& vm,
success_msg_writer() <<
"**********************************************************************\n" <<
tr("Your wallet has been generated!\n"
- "To start synchronizing with the daemon, use \"refresh\" command.\n"
- "Use \"help\" command to see the list of available commands.\n"
+ "To start synchronizing with the daemon, use the \"refresh\" command.\n"
+ "Use the \"help\" command to see the list of available commands.\n"
"Use \"help <command>\" to see a command's documentation.\n"
- "Always use \"exit\" command when closing monero-wallet-cli to save your\n"
- "current session's state. Otherwise, you might need to synchronize \n"
+ "Always use the \"exit\" command when closing monero-wallet-cli to save \n"
+ "your current session's state. Otherwise, you might need to synchronize \n"
"your wallet again (your wallet keys are NOT at risk in any case).\n")
;
@@ -2695,6 +2753,49 @@ bool simple_wallet::new_wallet(const boost::program_options::variables_map& vm,
return true;
}
//----------------------------------------------------------------------------------------------------
+bool simple_wallet::new_wallet(const boost::program_options::variables_map& vm,
+ const std::string &multisig_keys, const std::string &old_language)
+{
+ auto rc = tools::wallet2::make_new(vm, password_prompter);
+ m_wallet = std::move(rc.first);
+ if (!m_wallet)
+ {
+ return false;
+ }
+
+ std::string mnemonic_language = old_language;
+
+ std::vector<std::string> language_list;
+ crypto::ElectrumWords::get_language_list(language_list);
+ if (mnemonic_language.empty() && std::find(language_list.begin(), language_list.end(), m_mnemonic_language) != language_list.end())
+ {
+ mnemonic_language = m_mnemonic_language;
+ }
+
+ m_wallet->set_seed_language(mnemonic_language);
+
+ try
+ {
+ m_wallet->generate(m_wallet_file, std::move(rc.second).password(), multisig_keys);
+ bool ready;
+ uint32_t threshold, total;
+ if (!m_wallet->multisig(&ready, &threshold, &total) || !ready)
+ {
+ fail_msg_writer() << tr("failed to generate new mutlisig wallet");
+ return false;
+ }
+ message_writer(console_color_white, true) << boost::format(tr("Generated new %u/%u multisig wallet: ")) % threshold % total
+ << m_wallet->get_account().get_public_address_str(m_wallet->testnet());
+ }
+ catch (const std::exception& e)
+ {
+ fail_msg_writer() << tr("failed to generate new wallet: ") << e.what();
+ return false;
+ }
+
+ return true;
+}
+//----------------------------------------------------------------------------------------------------
bool simple_wallet::open_wallet(const boost::program_options::variables_map& vm)
{
if (!tools::wallet2::wallet_valid_path_format(m_wallet_file))
@@ -2771,7 +2872,7 @@ bool simple_wallet::open_wallet(const boost::program_options::variables_map& vm)
}
success_msg_writer() <<
"**********************************************************************\n" <<
- tr("Use \"help\" command to see the list of available commands.\n") <<
+ tr("Use the \"help\" command to see the list of available commands.\n") <<
tr("Use \"help <command>\" to see a command's documentation.\n") <<
"**********************************************************************";
return true;
@@ -3206,6 +3307,13 @@ bool simple_wallet::show_incoming_transfers(const std::vector<std::string>& args
{
if (!parse_subaddress_indices(local_args[0], subaddr_indices))
return true;
+ local_args.erase(local_args.begin());
+ }
+
+ if (local_args.size() > 0)
+ {
+ fail_msg_writer() << tr("usage: incoming_transfers [available|unavailable] [verbose] [index=<N>]");
+ return true;
}
tools::wallet2::transfer_container transfers;
@@ -4391,90 +4499,9 @@ bool simple_wallet::sweep_single(const std::vector<std::string> &args_)
}
}
- catch (const tools::error::daemon_busy&)
- {
- fail_msg_writer() << tr("daemon is busy. Please try again later.");
- }
- catch (const tools::error::no_connection_to_daemon&)
- {
- fail_msg_writer() << tr("no connection to daemon. Please make sure daemon is running.");
- }
- catch (const tools::error::wallet_rpc_error& e)
- {
- LOG_ERROR("RPC error: " << e.to_string());
- fail_msg_writer() << tr("RPC error: ") << e.what();
- }
- catch (const tools::error::get_random_outs_error &e)
- {
- fail_msg_writer() << tr("failed to get random outputs to mix: ") << e.what();
- }
- catch (const tools::error::not_enough_money& e)
- {
- LOG_PRINT_L0(boost::format("not enough money to transfer, available only %s, sent amount %s") %
- print_money(e.available()) %
- print_money(e.tx_amount()));
- fail_msg_writer() << tr("Not enough money in unlocked balance");
- }
- catch (const tools::error::tx_not_possible& e)
- {
- LOG_PRINT_L0(boost::format("not enough money to transfer, available only %s, transaction amount %s = %s + %s (fee)") %
- print_money(e.available()) %
- print_money(e.tx_amount() + e.fee()) %
- print_money(e.tx_amount()) %
- print_money(e.fee()));
- fail_msg_writer() << tr("Failed to find a way to create transactions. This is usually due to dust which is so small it cannot pay for itself in fees, or trying to send more money than the unlocked balance, or not leaving enough for fees");
- }
- catch (const tools::error::not_enough_outs_to_mix& e)
- {
- auto writer = fail_msg_writer();
- writer << tr("not enough outputs for specified mixin_count") << " = " << e.mixin_count() << ":";
- for (std::pair<uint64_t, uint64_t> outs_for_amount : e.scanty_outs())
- {
- writer << "\n" << tr("output amount") << " = " << print_money(outs_for_amount.first) << ", " << tr("found outputs to mix") << " = " << outs_for_amount.second;
- }
- }
- catch (const tools::error::tx_not_constructed&)
- {
- fail_msg_writer() << tr("transaction was not constructed");
- }
- catch (const tools::error::tx_rejected& e)
- {
- fail_msg_writer() << (boost::format(tr("transaction %s was rejected by daemon with status: ")) % get_transaction_hash(e.tx())) << e.status();
- std::string reason = e.reason();
- if (!reason.empty())
- fail_msg_writer() << tr("Reason: ") << reason;
- }
- catch (const tools::error::tx_sum_overflow& e)
- {
- fail_msg_writer() << e.what();
- }
- catch (const tools::error::zero_destination&)
- {
- fail_msg_writer() << tr("one of destinations is zero");
- }
- catch (const tools::error::tx_too_big& e)
- {
- fail_msg_writer() << tr("failed to find a suitable way to split transactions");
- }
- catch (const tools::error::transfer_error& e)
- {
- LOG_ERROR("unknown transfer error: " << e.to_string());
- fail_msg_writer() << tr("unknown transfer error: ") << e.what();
- }
- catch (const tools::error::multisig_export_needed& e)
- {
- LOG_ERROR("Multisig error: " << e.to_string());
- fail_msg_writer() << tr("Multisig error: ") << e.what();
- }
- catch (const tools::error::wallet_internal_error& e)
- {
- LOG_ERROR("internal error: " << e.to_string());
- fail_msg_writer() << tr("internal error: ") << e.what();
- }
catch (const std::exception& e)
{
- LOG_ERROR("unexpected error: " << e.what());
- fail_msg_writer() << tr("unexpected error: ") << e.what();
+ handle_transfer_exception(std::current_exception());
}
catch (...)
{
@@ -4508,6 +4535,12 @@ bool simple_wallet::sweep_below(const std::vector<std::string> &args_)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::donate(const std::vector<std::string> &args_)
{
+ if(m_wallet->testnet())
+ {
+ fail_msg_writer() << tr("donations are not enabled on the testnet");
+ return true;
+ }
+
std::vector<std::string> local_args = args_;
if(local_args.empty() || local_args.size() > 5)
{
@@ -6175,6 +6208,7 @@ bool simple_wallet::export_key_images(const std::vector<std::string> &args)
try
{
+ LOCK_IDLE_SCOPE();
if (!m_wallet->export_key_images(filename))
{
fail_msg_writer() << tr("failed to save file ") << filename;
@@ -6207,6 +6241,7 @@ bool simple_wallet::import_key_images(const std::vector<std::string> &args)
}
std::string filename = args[0];
+ LOCK_IDLE_SCOPE();
try
{
uint64_t spent = 0, unspent = 0;
@@ -6238,6 +6273,7 @@ bool simple_wallet::export_outputs(const std::vector<std::string> &args)
if (m_wallet->ask_password() && !get_and_verify_password()) { return true; }
std::string filename = args[0];
+ LOCK_IDLE_SCOPE();
try
{
std::vector<tools::wallet2::transfer_details> outs = m_wallet->export_outputs();
@@ -6336,6 +6372,7 @@ bool simple_wallet::import_outputs(const std::vector<std::string> &args)
boost::archive::binary_iarchive ar(iss);
ar >> outputs;
}
+ LOCK_IDLE_SCOPE();
size_t n_outputs = m_wallet->import_outputs(outputs);
success_msg_writer() << boost::lexical_cast<std::string>(n_outputs) << " outputs imported";
}
@@ -6554,6 +6591,7 @@ int main(int argc, char* argv[])
command_line::add_arg(desc_params, arg_command);
command_line::add_arg(desc_params, arg_restore_deterministic_wallet );
+ command_line::add_arg(desc_params, arg_restore_multisig_wallet );
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);
@@ -6586,7 +6624,8 @@ int main(int argc, char* argv[])
std::vector<std::string> command = command_line::get_arg(*vm, arg_command);
if (!command.empty())
{
- w.process_command(command);
+ if (!w.process_command(command))
+ fail_msg_writer() << tr("Unknown command: ") << command.front();
w.stop();
w.deinit();
}
diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h
index e5c00e542..024077ca1 100644
--- a/src/simplewallet/simplewallet.h
+++ b/src/simplewallet/simplewallet.h
@@ -92,6 +92,8 @@ namespace cryptonote
bool recover, bool two_random, const std::string &old_language);
bool new_wallet(const boost::program_options::variables_map& vm, const cryptonote::account_public_address& address,
const boost::optional<crypto::secret_key>& spendkey, const crypto::secret_key& viewkey);
+ bool new_wallet(const boost::program_options::variables_map& vm,
+ const std::string &multisig_keys, const std::string &old_language);
bool open_wallet(const boost::program_options::variables_map& vm);
bool close_wallet();
@@ -306,6 +308,7 @@ namespace cryptonote
crypto::secret_key m_recovery_key; // recovery key (used as random for wallet gen)
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;
bool m_allow_mismatched_daemon_version;
diff --git a/src/wallet/api/utils.cpp b/src/wallet/api/utils.cpp
index a9646e038..e54dd9f1c 100644
--- a/src/wallet/api/utils.cpp
+++ b/src/wallet/api/utils.cpp
@@ -48,6 +48,11 @@ bool isAddressLocal(const std::string &address)
}
}
+void onStartup()
+{
+ tools::on_startup();
+}
+
}
diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h
index 8593bd1f9..ab1a48d6e 100644
--- a/src/wallet/api/wallet2_api.h
+++ b/src/wallet/api/wallet2_api.h
@@ -42,6 +42,7 @@ namespace Monero {
namespace Utils {
bool isAddressLocal(const std::string &hostaddr);
+ void onStartup();
}
template<typename T>
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 90977b20a..2af41f588 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -53,6 +53,7 @@ using namespace epee;
#include "profile_tools.h"
#include "crypto/crypto.h"
#include "serialization/binary_utils.h"
+#include "serialization/string.h"
#include "cryptonote_basic/blobdatatype.h"
#include "mnemonics/electrum-words.h"
#include "common/i18n.h"
@@ -62,7 +63,7 @@ using namespace epee;
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
#include "common/json_util.h"
-#include "common/memwipe.h"
+#include "memwipe.h"
#include "common/base58.h"
#include "ringct/rctSigs.h"
@@ -144,6 +145,16 @@ uint64_t calculate_fee(uint64_t fee_per_kb, const cryptonote::blobdata &blob, ui
return calculate_fee(fee_per_kb, blob.size(), fee_multiplier);
}
+std::string get_size_string(size_t sz)
+{
+ return std::to_string(sz) + " bytes (" + std::to_string((sz + 1023) / 1024) + " kB)";
+}
+
+std::string get_size_string(const cryptonote::blobdata &tx)
+{
+ return get_size_string(tx.size());
+}
+
std::unique_ptr<tools::wallet2> make_basic(const boost::program_options::variables_map& vm, const options& opts, const std::function<boost::optional<tools::password_container>(const char *, bool)> &password_prompter)
{
const bool testnet = command_line::get_arg(vm, opts.testnet);
@@ -600,6 +611,7 @@ wallet2::wallet2(bool testnet, bool restricted):
m_min_output_value(0),
m_merge_destinations(false),
m_confirm_backlog(true),
+ m_confirm_backlog_threshold(0),
m_is_initialized(false),
m_restricted(restricted),
is_old_file_format(false),
@@ -723,6 +735,70 @@ bool wallet2::get_seed(std::string& electrum_words, const epee::wipeable_string
return true;
}
+//----------------------------------------------------------------------------------------------------
+bool wallet2::get_multisig_seed(std::string& seed, const epee::wipeable_string &passphrase, bool raw) const
+{
+ bool ready;
+ uint32_t threshold, total;
+ if (!multisig(&ready, &threshold, &total))
+ {
+ std::cout << "This is not a multisig wallet" << std::endl;
+ return false;
+ }
+ if (!ready)
+ {
+ std::cout << "This multisig wallet is not yet finalized" << std::endl;
+ return false;
+ }
+ if (!raw && seed_language.empty())
+ {
+ std::cout << "seed_language not set" << std::endl;
+ return false;
+ }
+
+ crypto::secret_key skey;
+ crypto::public_key pkey;
+ const account_keys &keys = get_account().get_keys();
+ std::string data;
+ data.append((const char*)&threshold, sizeof(uint32_t));
+ data.append((const char*)&total, sizeof(uint32_t));
+ skey = keys.m_spend_secret_key;
+ data.append((const char*)&skey, sizeof(skey));
+ pkey = keys.m_account_address.m_spend_public_key;
+ data.append((const char*)&pkey, sizeof(pkey));
+ skey = keys.m_view_secret_key;
+ data.append((const char*)&skey, sizeof(skey));
+ pkey = keys.m_account_address.m_view_public_key;
+ data.append((const char*)&pkey, sizeof(pkey));
+ for (const auto &skey: keys.m_multisig_keys)
+ data.append((const char*)&skey, sizeof(skey));
+ for (const auto &signer: m_multisig_signers)
+ data.append((const char*)&signer, sizeof(signer));
+
+ if (!passphrase.empty())
+ {
+ crypto::secret_key key;
+ crypto::cn_slow_hash(passphrase.data(), passphrase.size(), (crypto::hash&)key);
+ sc_reduce32((unsigned char*)key.data);
+ data = encrypt(data, key, true);
+ }
+
+ if (raw)
+ {
+ seed = epee::string_tools::buff_to_hex_nodelimer(data);
+ }
+ else
+ {
+ if (!crypto::ElectrumWords::bytes_to_words(data.data(), data.size(), seed, seed_language))
+ {
+ std::cout << "Failed to encode seed";
+ return false;
+ }
+ }
+
+ return true;
+}
+//----------------------------------------------------------------------------------------------------
/*!
* \brief Gets the seed language
*/
@@ -1960,6 +2036,11 @@ void wallet2::fast_refresh(uint64_t stop_height, uint64_t &blocks_start_height,
pull_hashes(0, blocks_start_height, short_chain_history, hashes);
if (hashes.size() <= 3)
return;
+ if (blocks_start_height < m_blockchain.offset())
+ {
+ MERROR("Blocks start before blockchain offset: " << blocks_start_height << " " << m_blockchain.offset());
+ return;
+ }
if (hashes.size() + current_index < stop_height) {
drop_from_short_history(short_chain_history, 3);
std::list<crypto::hash>::iterator right = hashes.end();
@@ -2636,6 +2717,97 @@ bool wallet2::verify_password(const std::string& keys_file_name, const epee::wip
* \brief Generates a wallet or restores one.
* \param wallet_ Name of wallet file
* \param password Password of wallet file
+ * \param multisig_data The multisig restore info and keys
+ */
+void wallet2::generate(const std::string& wallet_, const epee::wipeable_string& password,
+ const std::string& multisig_data)
+{
+ clear();
+ prepare_file_names(wallet_);
+
+ if (!wallet_.empty())
+ {
+ boost::system::error_code ignored_ec;
+ THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_wallet_file, ignored_ec), error::file_exists, m_wallet_file);
+ THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_keys_file, ignored_ec), error::file_exists, m_keys_file);
+ }
+
+ m_account.generate(rct::rct2sk(rct::zero()), true, false);
+
+ THROW_WALLET_EXCEPTION_IF(multisig_data.size() < 32, error::invalid_multisig_seed);
+ size_t offset = 0;
+ uint32_t threshold = *(uint32_t*)(multisig_data.data() + offset);
+ offset += sizeof(uint32_t);
+ uint32_t total = *(uint32_t*)(multisig_data.data() + offset);
+ offset += sizeof(uint32_t);
+ THROW_WALLET_EXCEPTION_IF(threshold < 2, error::invalid_multisig_seed);
+ THROW_WALLET_EXCEPTION_IF(total != threshold && total != threshold + 1, error::invalid_multisig_seed);
+ const size_t n_multisig_keys = total == threshold ? 1 : threshold;
+ THROW_WALLET_EXCEPTION_IF(multisig_data.size() != 8 + 32 * (4 + n_multisig_keys + total), error::invalid_multisig_seed);
+
+ std::vector<crypto::secret_key> multisig_keys;
+ std::vector<crypto::public_key> multisig_signers;
+ crypto::secret_key spend_secret_key = *(crypto::secret_key*)(multisig_data.data() + offset);
+ offset += sizeof(crypto::secret_key);
+ crypto::public_key spend_public_key = *(crypto::public_key*)(multisig_data.data() + offset);
+ offset += sizeof(crypto::public_key);
+ crypto::secret_key view_secret_key = *(crypto::secret_key*)(multisig_data.data() + offset);
+ offset += sizeof(crypto::secret_key);
+ crypto::public_key view_public_key = *(crypto::public_key*)(multisig_data.data() + offset);
+ offset += sizeof(crypto::public_key);
+ for (size_t n = 0; n < n_multisig_keys; ++n)
+ {
+ multisig_keys.push_back(*(crypto::secret_key*)(multisig_data.data() + offset));
+ offset += sizeof(crypto::secret_key);
+ }
+ for (size_t n = 0; n < total; ++n)
+ {
+ multisig_signers.push_back(*(crypto::public_key*)(multisig_data.data() + offset));
+ offset += sizeof(crypto::public_key);
+ }
+
+ crypto::public_key calculated_view_public_key;
+ THROW_WALLET_EXCEPTION_IF(!crypto::secret_key_to_public_key(view_secret_key, calculated_view_public_key), error::invalid_multisig_seed);
+ THROW_WALLET_EXCEPTION_IF(view_public_key != calculated_view_public_key, error::invalid_multisig_seed);
+ crypto::public_key local_signer;
+ THROW_WALLET_EXCEPTION_IF(!crypto::secret_key_to_public_key(spend_secret_key, local_signer), error::invalid_multisig_seed);
+ THROW_WALLET_EXCEPTION_IF(std::find(multisig_signers.begin(), multisig_signers.end(), local_signer) == multisig_signers.end(), error::invalid_multisig_seed);
+ rct::key skey = rct::zero();
+ for (const auto &msk: multisig_keys)
+ sc_add(skey.bytes, skey.bytes, rct::sk2rct(msk).bytes);
+ THROW_WALLET_EXCEPTION_IF(!(rct::rct2sk(skey) == spend_secret_key), error::invalid_multisig_seed);
+
+ m_account.make_multisig(view_secret_key, spend_secret_key, spend_public_key, multisig_keys);
+ m_account.finalize_multisig(spend_public_key);
+
+ m_account_public_address = m_account.get_keys().m_account_address;
+ m_watch_only = false;
+ m_multisig = true;
+ m_multisig_threshold = threshold;
+ m_multisig_signers = multisig_signers;
+
+ if (!wallet_.empty())
+ {
+ bool r = store_keys(m_keys_file, password, false);
+ THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file);
+
+ r = file_io_utils::save_string_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_testnet));
+ if(!r) MERROR("String with address text not saved");
+ }
+
+ cryptonote::block b;
+ generate_genesis(b);
+ m_blockchain.push_back(get_block_hash(b));
+ add_subaddress_account(tr("Primary account"));
+
+ if (!wallet_.empty())
+ store();
+}
+
+/*!
+ * \brief Generates a wallet or restores one.
+ * \param wallet_ Name of wallet file
+ * \param password Password of wallet file
* \param recovery_param If it is a restore, the recovery key
* \param recover Whether it is a restore
* \param two_random Whether it is a non-deterministic wallet
@@ -5667,7 +5839,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
if (m_multisig)
{
crypto::public_key ignore = m_multisig_threshold == m_multisig_signers.size() ? crypto::null_pkey : multisig_signers.front();
- multisig_sigs.push_back({tx.rct_signatures, ignore, used_L, {}, msout});
+ multisig_sigs.push_back({tx.rct_signatures, ignore, used_L, std::unordered_set<crypto::public_key>(), msout});
if (m_multisig_threshold < m_multisig_signers.size())
{
@@ -5694,7 +5866,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sources, splitted_dsts, unlock_time, m_testnet);
THROW_WALLET_EXCEPTION_IF(upper_transaction_size_limit <= get_object_blobsize(tx), error::tx_too_big, tx, upper_transaction_size_limit);
THROW_WALLET_EXCEPTION_IF(cryptonote::get_transaction_prefix_hash(ms_tx) != prefix_hash, error::wallet_internal_error, "Multisig txes do not share prefix");
- multisig_sigs.push_back({ms_tx.rct_signatures, multisig_signers[signer_index], new_used_L, {}, msout});
+ multisig_sigs.push_back({ms_tx.rct_signatures, multisig_signers[signer_index], new_used_L, std::unordered_set<crypto::public_key>(), msout});
ms_tx.rct_signatures = tx.rct_signatures;
THROW_WALLET_EXCEPTION_IF(cryptonote::get_transaction_hash(ms_tx) != cryptonote::get_transaction_hash(tx), error::wallet_internal_error, "Multisig txes differ by more than the signatures");
@@ -5993,7 +6165,8 @@ void wallet2::light_wallet_get_unspent_outs()
add_tx_pub_key_to_extra(td.m_tx, tx_pub_key);
td.m_key_image = unspent_key_image;
- td.m_key_image_known = !m_watch_only;
+ td.m_key_image_known = !m_watch_only && !m_multisig;
+ td.m_key_image_partial = m_multisig;
td.m_amount = o.amount;
td.m_pk_index = 0;
td.m_internal_output_index = o.index;
@@ -6667,6 +6840,17 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
const size_t estimated_tx_size = estimate_tx_size(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size(), extra.size(), bulletproof);
needed_fee = calculate_fee(fee_per_kb, estimated_tx_size, fee_multiplier);
+ uint64_t inputs = 0, outputs = needed_fee;
+ for (size_t idx: tx.selected_transfers) inputs += m_transfers[idx].amount();
+ for (const auto &o: tx.dsts) outputs += o.amount;
+
+ if (inputs < outputs)
+ {
+ LOG_PRINT_L2("We don't have enough for the basic fee, switching to adding_fee");
+ adding_fee = true;
+ goto skip_tx;
+ }
+
LOG_PRINT_L2("Trying to create a tx now, with " << tx.dsts.size() << " outputs and " <<
tx.selected_transfers.size() << " inputs");
if (use_rct)
@@ -6678,7 +6862,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
auto txBlob = t_serializable_object_to_blob(test_ptx.tx);
needed_fee = calculate_fee(fee_per_kb, txBlob, fee_multiplier);
available_for_fee = test_ptx.fee + test_ptx.change_dts.amount + (!test_ptx.dust_added_to_fee ? test_ptx.dust : 0);
- LOG_PRINT_L2("Made a " << ((txBlob.size() + 1023) / 1024) << " kB tx, with " << print_money(available_for_fee) << " available for fee (" <<
+ LOG_PRINT_L2("Made a " << get_size_string(txBlob) << " tx, with " << print_money(available_for_fee) << " available for fee (" <<
print_money(needed_fee) << " needed)");
if (needed_fee > available_for_fee && !dsts.empty() && dsts[0].amount > 0)
@@ -6720,11 +6904,11 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx);
txBlob = t_serializable_object_to_blob(test_ptx.tx);
needed_fee = calculate_fee(fee_per_kb, txBlob, fee_multiplier);
- LOG_PRINT_L2("Made an attempt at a final " << ((txBlob.size() + 1023)/1024) << " kB tx, with " << print_money(test_ptx.fee) <<
+ LOG_PRINT_L2("Made an attempt at a final " << get_size_string(txBlob) << " tx, with " << print_money(test_ptx.fee) <<
" fee and " << print_money(test_ptx.change_dts.amount) << " change");
}
- LOG_PRINT_L2("Made a final " << ((txBlob.size() + 1023)/1024) << " kB tx, with " << print_money(test_ptx.fee) <<
+ LOG_PRINT_L2("Made a final " << get_size_string(txBlob) << " tx, with " << print_money(test_ptx.fee) <<
" fee and " << print_money(test_ptx.change_dts.amount) << " change");
tx.tx = test_tx;
@@ -6742,6 +6926,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
}
}
+skip_tx:
// if unused_*_indices is empty while unused_*_indices_per_subaddr has multiple elements, and if we still have something to pay,
// pop front of unused_*_indices_per_subaddr and have unused_*_indices point to the front of unused_*_indices_per_subaddr
if ((!dsts.empty() && dsts[0].amount > 0) || adding_fee)
@@ -6776,7 +6961,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
for (size_t idx: tx.selected_transfers)
tx_money += m_transfers[idx].amount();
LOG_PRINT_L1(" Transaction " << (1+std::distance(txes.begin(), i)) << "/" << txes.size() <<
- ": " << (tx.bytes+1023)/1024 << " kB, sending " << print_money(tx_money) << " in " << tx.selected_transfers.size() <<
+ ": " << get_size_string(tx.bytes) << ", sending " << print_money(tx_money) << " in " << tx.selected_transfers.size() <<
" outputs to " << tx.dsts.size() << " destination(s), including " <<
print_money(tx.ptx.fee) << " fee, " << print_money(tx.ptx.change_dts.amount) << " change");
ptx_vector.push_back(tx.ptx);
@@ -6794,37 +6979,48 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_all(uint64_t below
THROW_WALLET_EXCEPTION_IF(unlocked_balance(subaddr_account) == 0, error::wallet_internal_error, "No unlocked balance in the entire wallet");
- std::map<uint32_t, uint64_t> balance_per_subaddr = unlocked_balance_per_subaddress(subaddr_account);
-
- if (subaddr_indices.empty())
- {
- // in case subaddress index wasn't specified, choose non-empty subaddress randomly (with index=0 being chosen last)
- if (balance_per_subaddr.count(0) == 1 && balance_per_subaddr.size() > 1)
- balance_per_subaddr.erase(0);
- auto i = balance_per_subaddr.begin();
- std::advance(i, crypto::rand<size_t>() % balance_per_subaddr.size());
- subaddr_indices.insert(i->first);
- }
- for (uint32_t i : subaddr_indices)
- LOG_PRINT_L2("Spending from subaddress index " << i);
+ std::map<uint32_t, std::pair<std::vector<size_t>, std::vector<size_t>>> unused_transfer_dust_indices_per_subaddr;
- // gather all dust and non-dust outputs of specified subaddress
+ // gather all dust and non-dust outputs of specified subaddress (if any) and below specified threshold (if any)
+ bool fund_found = false;
for (size_t i = 0; i < m_transfers.size(); ++i)
{
const transfer_details& td = m_transfers[i];
- if (!td.m_spent && !td.m_key_image_partial && (use_rct ? true : !td.is_rct()) && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && subaddr_indices.count(td.m_subaddr_index.minor) == 1)
+ if (!td.m_spent && !td.m_key_image_partial && (use_rct ? true : !td.is_rct()) && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && (subaddr_indices.empty() || subaddr_indices.count(td.m_subaddr_index.minor) == 1))
{
+ fund_found = true;
if (below == 0 || td.amount() < below)
{
if ((td.is_rct()) || is_valid_decomposed_amount(td.amount()))
- unused_transfers_indices.push_back(i);
+ unused_transfer_dust_indices_per_subaddr[td.m_subaddr_index.minor].first.push_back(i);
else
- unused_dust_indices.push_back(i);
+ unused_transfer_dust_indices_per_subaddr[td.m_subaddr_index.minor].second.push_back(i);
}
}
}
+ THROW_WALLET_EXCEPTION_IF(!fund_found, error::wallet_internal_error, "No unlocked balance in the specified subaddress(es)");
+ THROW_WALLET_EXCEPTION_IF(unused_transfer_dust_indices_per_subaddr.empty(), error::wallet_internal_error, "The smallest amount found is not below the specified threshold");
- THROW_WALLET_EXCEPTION_IF(unused_transfers_indices.empty() && unused_dust_indices.empty(), error::not_enough_money, 0, 0, 0); // not sure if a new error class (something like 'cant_sweep_empty'?) should be introduced
+ if (subaddr_indices.empty())
+ {
+ // in case subaddress index wasn't specified, choose non-empty subaddress randomly (with index=0 being chosen last)
+ if (unused_transfer_dust_indices_per_subaddr.count(0) == 1 && unused_transfer_dust_indices_per_subaddr.size() > 1)
+ unused_transfer_dust_indices_per_subaddr.erase(0);
+ auto i = unused_transfer_dust_indices_per_subaddr.begin();
+ std::advance(i, crypto::rand<size_t>() % unused_transfer_dust_indices_per_subaddr.size());
+ unused_transfers_indices = i->second.first;
+ unused_dust_indices = i->second.second;
+ LOG_PRINT_L2("Spending from subaddress index " << i->first);
+ }
+ else
+ {
+ for (const auto& p : unused_transfer_dust_indices_per_subaddr)
+ {
+ unused_transfers_indices.insert(unused_transfers_indices.end(), p.second.first.begin(), p.second.first.end());
+ unused_dust_indices.insert(unused_dust_indices.end(), p.second.second.begin(), p.second.second.end());
+ LOG_PRINT_L2("Spending from subaddress index " << p.first);
+ }
+ }
return create_transactions_from(address, is_subaddress, unused_transfers_indices, unused_dust_indices, fake_outs_count, unlock_time, priority, extra, trusted_daemon);
}
@@ -6928,7 +7124,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
auto txBlob = t_serializable_object_to_blob(test_ptx.tx);
needed_fee = calculate_fee(fee_per_kb, txBlob, fee_multiplier);
available_for_fee = test_ptx.fee + test_ptx.dests[0].amount + test_ptx.change_dts.amount;
- LOG_PRINT_L2("Made a " << ((txBlob.size() + 1023) / 1024) << " kB tx, with " << print_money(available_for_fee) << " available for fee (" <<
+ LOG_PRINT_L2("Made a " << get_size_string(txBlob) << " tx, with " << print_money(available_for_fee) << " available for fee (" <<
print_money(needed_fee) << " needed)");
THROW_WALLET_EXCEPTION_IF(needed_fee > available_for_fee, error::wallet_internal_error, "Transaction cannot pay for itself");
@@ -6944,11 +7140,11 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx);
txBlob = t_serializable_object_to_blob(test_ptx.tx);
needed_fee = calculate_fee(fee_per_kb, txBlob, fee_multiplier);
- LOG_PRINT_L2("Made an attempt at a final " << ((txBlob.size() + 1023)/1024) << " kB tx, with " << print_money(test_ptx.fee) <<
+ LOG_PRINT_L2("Made an attempt at a final " << get_size_string(txBlob) << " tx, with " << print_money(test_ptx.fee) <<
" fee and " << print_money(test_ptx.change_dts.amount) << " change");
}
- LOG_PRINT_L2("Made a final " << ((txBlob.size() + 1023)/1024) << " kB tx, with " << print_money(test_ptx.fee) <<
+ LOG_PRINT_L2("Made a final " << get_size_string(txBlob) << " tx, with " << print_money(test_ptx.fee) <<
" fee and " << print_money(test_ptx.change_dts.amount) << " change");
tx.tx = test_tx;
@@ -6975,7 +7171,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
for (size_t idx: tx.selected_transfers)
tx_money += m_transfers[idx].amount();
LOG_PRINT_L1(" Transaction " << (1+std::distance(txes.begin(), i)) << "/" << txes.size() <<
- ": " << (tx.bytes+1023)/1024 << " kB, sending " << print_money(tx_money) << " in " << tx.selected_transfers.size() <<
+ ": " << get_size_string(tx.bytes) << ", sending " << print_money(tx_money) << " in " << tx.selected_transfers.size() <<
" outputs to " << tx.dsts.size() << " destination(s), including " <<
print_money(tx.ptx.fee) << " fee, " << print_money(tx.ptx.change_dts.amount) << " change");
ptx_vector.push_back(tx.ptx);
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index b1115f67b..2fbe05f89 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -436,6 +436,15 @@ namespace tools
typedef std::tuple<uint64_t, crypto::public_key, rct::key> get_outs_entry;
/*!
+ * \brief Generates a wallet or restores one.
+ * \param wallet_ Name of wallet file
+ * \param password Password of wallet file
+ * \param multisig_data The multisig restore info and keys
+ */
+ void generate(const std::string& wallet_, const epee::wipeable_string& password,
+ const std::string& multisig_data);
+
+ /*!
* \brief Generates a wallet or restores one.
* \param wallet_ Name of wallet file
* \param password Password of wallet file
@@ -610,6 +619,7 @@ namespace tools
bool watch_only() const { return m_watch_only; }
bool multisig(bool *ready = NULL, uint32_t *threshold = NULL, uint32_t *total = NULL) const;
bool has_multisig_partial_key_images() const;
+ bool get_multisig_seed(std::string& seed, const epee::wipeable_string &passphrase = std::string(), bool raw = true) const;
// locked & unlocked balance of given or current subaddress account
uint64_t balance(uint32_t subaddr_index_major) const;
diff --git a/src/wallet/wallet_errors.h b/src/wallet/wallet_errors.h
index 234c22d85..023b53f28 100644
--- a/src/wallet/wallet_errors.h
+++ b/src/wallet/wallet_errors.h
@@ -60,6 +60,7 @@ namespace tools
// file_save_error
// invalid_password
// invalid_priority
+ // invalid_multisig_seed
// refresh_error *
// acc_outs_lookup_error
// block_parse_error
@@ -266,6 +267,16 @@ namespace tools
std::string to_string() const { return wallet_logic_error::to_string(); }
};
+ struct invalid_multisig_seed : public wallet_logic_error
+ {
+ explicit invalid_multisig_seed(std::string&& loc)
+ : wallet_logic_error(std::move(loc), "invalid multisig seed")
+ {
+ }
+
+ std::string to_string() const { return wallet_logic_error::to_string(); }
+ };
+
//----------------------------------------------------------------------------------------------------
struct invalid_pregenerated_random : public wallet_logic_error
{
diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index f031b765d..e53fd6fce 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -89,6 +89,8 @@ namespace tools
//------------------------------------------------------------------------------------------------------------------------------
wallet_rpc_server::~wallet_rpc_server()
{
+ if (m_wallet)
+ delete m_wallet;
}
//------------------------------------------------------------------------------------------------------------------------------
void wallet_rpc_server::set_wallet(wallet2 *cr)
@@ -229,8 +231,9 @@ namespace tools
m_http_client.set_server(walvars->get_daemon_address(), walvars->get_daemon_login());
m_net_server.set_threads_prefix("RPC");
+ auto rng = [](size_t len, uint8_t *ptr) { return crypto::rand(len, ptr); };
return epee::http_server_impl_base<wallet_rpc_server, connection_context>::init(
- std::move(bind_port), std::move(rpc_config->bind_ip), std::move(rpc_config->access_control_origins), std::move(http_login)
+ rng, std::move(bind_port), std::move(rpc_config->bind_ip), std::move(rpc_config->access_control_origins), std::move(http_login)
);
}
//------------------------------------------------------------------------------------------------------------------------------
@@ -255,6 +258,7 @@ namespace tools
entry.note = m_wallet->get_tx_note(pd.m_tx_hash);
entry.type = "in";
entry.subaddr_index = pd.m_subaddr_index;
+ entry.address = m_wallet->get_subaddress_as_str(pd.m_subaddr_index);
}
//------------------------------------------------------------------------------------------------------------------------------
void wallet_rpc_server::fill_transfer_entry(tools::wallet_rpc::transfer_entry &entry, const crypto::hash &txid, const tools::wallet2::confirmed_transfer_details &pd)
@@ -280,6 +284,7 @@ namespace tools
entry.type = "out";
entry.subaddr_index = { pd.m_subaddr_account, 0 };
+ entry.address = m_wallet->get_subaddress_as_str({pd.m_subaddr_account, 0});
}
//------------------------------------------------------------------------------------------------------------------------------
void wallet_rpc_server::fill_transfer_entry(tools::wallet_rpc::transfer_entry &entry, const crypto::hash &txid, const tools::wallet2::unconfirmed_transfer_details &pd)
@@ -298,6 +303,7 @@ namespace tools
entry.note = m_wallet->get_tx_note(txid);
entry.type = is_failed ? "failed" : "pending";
entry.subaddr_index = { pd.m_subaddr_account, 0 };
+ entry.address = m_wallet->get_subaddress_as_str({pd.m_subaddr_account, 0});
}
//------------------------------------------------------------------------------------------------------------------------------
void wallet_rpc_server::fill_transfer_entry(tools::wallet_rpc::transfer_entry &entry, const crypto::hash &payment_id, const tools::wallet2::pool_payment_details &ppd)
@@ -316,6 +322,7 @@ namespace tools
entry.double_spend_seen = ppd.m_double_spend_seen;
entry.type = "pool";
entry.subaddr_index = pd.m_subaddr_index;
+ entry.address = m_wallet->get_subaddress_as_str(pd.m_subaddr_index);
}
//------------------------------------------------------------------------------------------------------------------------------
bool wallet_rpc_server::on_getbalance(const wallet_rpc::COMMAND_RPC_GET_BALANCE::request& req, wallet_rpc::COMMAND_RPC_GET_BALANCE::response& res, epee::json_rpc::error& er)
@@ -662,7 +669,98 @@ namespace tools
}
return true;
}
+ //------------------------------------------------------------------------------------------------------------------------------
+ static std::string ptx_to_string(const tools::wallet2::pending_tx &ptx)
+ {
+ std::ostringstream oss;
+ boost::archive::portable_binary_oarchive ar(oss);
+ try
+ {
+ ar << ptx;
+ }
+ catch (...)
+ {
+ return "";
+ }
+ return epee::string_tools::buff_to_hex_nodelimer(oss.str());
+ }
+ //------------------------------------------------------------------------------------------------------------------------------
+ template<typename T> static bool is_error_value(const T &val) { return false; }
+ static bool is_error_value(const std::string &s) { return s.empty(); }
+ //------------------------------------------------------------------------------------------------------------------------------
+ template<typename T, typename V>
+ static bool fill(T &where, V s)
+ {
+ if (is_error_value(s)) return false;
+ where = std::move(s);
+ return true;
+ }
+ //------------------------------------------------------------------------------------------------------------------------------
+ template<typename T, typename V>
+ static bool fill(std::list<T> &where, V s)
+ {
+ if (is_error_value(s)) return false;
+ where.emplace_back(std::move(s));
+ return true;
+ }
+ //------------------------------------------------------------------------------------------------------------------------------
+ static uint64_t total_amount(const tools::wallet2::pending_tx &ptx)
+ {
+ uint64_t amount = 0;
+ for (const auto &dest: ptx.dests) amount += dest.amount;
+ return amount;
+ }
+ //------------------------------------------------------------------------------------------------------------------------------
+ template<typename Ts, typename Tu>
+ bool wallet_rpc_server::fill_response(std::vector<tools::wallet2::pending_tx> &ptx_vector,
+ bool get_tx_key, Ts& tx_key, Tu &amount, Tu &fee, std::string &multisig_txset, bool do_not_relay,
+ Ts &tx_hash, bool get_tx_hex, Ts &tx_blob, bool get_tx_metadata, Ts &tx_metadata, epee::json_rpc::error &er)
+ {
+ for (const auto & ptx : ptx_vector)
+ {
+ if (get_tx_key)
+ {
+ std::string s = epee::string_tools::pod_to_hex(ptx.tx_key);
+ for (const crypto::secret_key& additional_tx_key : ptx.additional_tx_keys)
+ s += epee::string_tools::pod_to_hex(additional_tx_key);
+ fill(tx_key, s);
+ }
+ // Compute amount leaving wallet in tx. By convention dests does not include change outputs
+ fill(amount, total_amount(ptx));
+ fill(fee, ptx.fee);
+ }
+ if (m_wallet->multisig())
+ {
+ multisig_txset = epee::string_tools::buff_to_hex_nodelimer(m_wallet->save_multisig_tx(ptx_vector));
+ if (multisig_txset.empty())
+ {
+ er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
+ er.message = "Failed to save multisig tx set after creation";
+ return false;
+ }
+ }
+ else
+ {
+ if (!do_not_relay)
+ m_wallet->commit_tx(ptx_vector);
+
+ // populate response with tx hashes
+ for (auto & ptx : ptx_vector)
+ {
+ bool r = fill(tx_hash, epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(ptx.tx)));
+ r = r && (!get_tx_hex || fill(tx_blob, epee::string_tools::buff_to_hex_nodelimer(tx_to_blob(ptx.tx))));
+ r = r && (!get_tx_metadata || fill(tx_metadata, ptx_to_string(ptx)));
+ if (!r)
+ {
+ er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
+ er.message = "Failed to save tx info";
+ return false;
+ }
+ }
+ }
+ return true;
+ }
//------------------------------------------------------------------------------------------------------------------------------
bool wallet_rpc_server::on_transfer(const wallet_rpc::COMMAND_RPC_TRANSFER::request& req, wallet_rpc::COMMAND_RPC_TRANSFER::response& res, epee::json_rpc::error& er)
{
@@ -705,55 +803,8 @@ namespace tools
return false;
}
- if (req.get_tx_key)
- {
- res.tx_key = epee::string_tools::pod_to_hex(ptx_vector.back().tx_key);
- for (const crypto::secret_key& additional_tx_key : ptx_vector.back().additional_tx_keys)
- res.tx_key += epee::string_tools::pod_to_hex(additional_tx_key);
- }
- res.fee = ptx_vector.back().fee;
-
- if (m_wallet->multisig())
- {
- res.multisig_txset = epee::string_tools::buff_to_hex_nodelimer(m_wallet->save_multisig_tx(ptx_vector));
- if (res.multisig_txset.empty())
- {
- er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
- er.message = "Failed to save multisig tx set after creation";
- return false;
- }
- }
- else
- {
- if (!req.do_not_relay)
- m_wallet->commit_tx(ptx_vector);
-
- // populate response with tx hash
- res.tx_hash = epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(ptx_vector.back().tx));
- if (req.get_tx_hex)
- {
- cryptonote::blobdata blob;
- tx_to_blob(ptx_vector.back().tx, blob);
- res.tx_blob = epee::string_tools::buff_to_hex_nodelimer(blob);
- }
- if (req.get_tx_metadata)
- {
- std::ostringstream oss;
- boost::archive::portable_binary_oarchive ar(oss);
- try
- {
- ar << ptx_vector.back();
- }
- catch (...)
- {
- er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
- er.message = "Failed to save multisig tx set after creation";
- return false;
- }
- res.tx_metadata = epee::string_tools::buff_to_hex_nodelimer(oss.str());
- }
- }
- return true;
+ return fill_response(ptx_vector, req.get_tx_key, res.tx_key, res.amount, res.fee, res.multisig_txset, req.do_not_relay,
+ res.tx_hash, req.get_tx_hex, res.tx_blob, req.get_tx_metadata, res.tx_metadata, er);
}
catch (const std::exception& e)
{
@@ -786,82 +837,12 @@ namespace tools
try
{
uint64_t mixin = m_wallet->adjust_mixin(req.mixin);
- uint64_t ptx_amount;
- std::vector<wallet2::pending_tx> ptx_vector;
LOG_PRINT_L2("on_transfer_split calling create_transactions_2");
- ptx_vector = m_wallet->create_transactions_2(dsts, mixin, req.unlock_time, req.priority, extra, req.account_index, req.subaddr_indices, m_trusted_daemon);
+ std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_2(dsts, mixin, req.unlock_time, req.priority, extra, req.account_index, req.subaddr_indices, m_trusted_daemon);
LOG_PRINT_L2("on_transfer_split called create_transactions_2");
- // populate response with tx hashes
- for (const auto & ptx : ptx_vector)
- {
- if (req.get_tx_keys)
- {
- res.tx_key_list.push_back(epee::string_tools::pod_to_hex(ptx.tx_key));
- for (const crypto::secret_key& additional_tx_key : ptx.additional_tx_keys)
- res.tx_key_list.back() += epee::string_tools::pod_to_hex(additional_tx_key);
- }
- // Compute amount leaving wallet in tx. By convention dests does not include change outputs
- ptx_amount = 0;
- for(auto & dt: ptx.dests)
- ptx_amount += dt.amount;
- res.amount_list.push_back(ptx_amount);
-
- res.fee_list.push_back(ptx.fee);
- }
-
- if (m_wallet->multisig())
- {
- res.multisig_txset = epee::string_tools::buff_to_hex_nodelimer(m_wallet->save_multisig_tx(ptx_vector));
- if (res.multisig_txset.empty())
- {
- er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
- er.message = "Failed to save multisig tx set after creation";
- return false;
- }
- }
-
- // populate response with tx hashes
- for (const auto & ptx : ptx_vector)
- {
- if (!req.do_not_relay)
- {
- LOG_PRINT_L2("on_transfer_split calling commit_tx");
- m_wallet->commit_tx(ptx_vector);
- LOG_PRINT_L2("on_transfer_split called commit_tx");
- }
-
- // populate response with tx hashes
- for (auto & ptx : ptx_vector)
- {
- res.tx_hash_list.push_back(epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(ptx.tx)));
-
- if (req.get_tx_hex)
- {
- cryptonote::blobdata blob;
- tx_to_blob(ptx.tx, blob);
- res.tx_blob_list.push_back(epee::string_tools::buff_to_hex_nodelimer(blob));
- }
- if (req.get_tx_metadata)
- {
- std::ostringstream oss;
- boost::archive::portable_binary_oarchive ar(oss);
- try
- {
- ar << ptx;
- }
- catch (...)
- {
- er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
- er.message = "Failed to save multisig tx set after creation";
- return false;
- }
- res.tx_metadata_list.push_back(epee::string_tools::buff_to_hex_nodelimer(oss.str()));
- }
- }
- }
-
- return true;
+ return fill_response(ptx_vector, req.get_tx_keys, res.tx_key_list, res.amount_list, res.fee_list, res.multisig_txset, req.do_not_relay,
+ res.tx_hash_list, req.get_tx_hex, res.tx_blob_list, req.get_tx_metadata, res.tx_metadata_list, er);
}
catch (const std::exception& e)
{
@@ -885,69 +866,8 @@ namespace tools
{
std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_unmixable_sweep_transactions(m_trusted_daemon);
- for (const auto & ptx : ptx_vector)
- {
- if (req.get_tx_keys)
- {
- res.tx_key_list.push_back(epee::string_tools::pod_to_hex(ptx.tx_key));
- }
- res.fee_list.push_back(ptx.fee);
- }
-
- if (m_wallet->multisig())
- {
- for (tools::wallet2::pending_tx &ptx: ptx_vector)
- {
- std::ostringstream oss;
- boost::archive::portable_binary_oarchive ar(oss);
- try
- {
- ar << ptx;
- }
- catch (...)
- {
- er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
- er.message = "Failed to save multisig tx set after creation";
- return false;
- }
- res.multisig_txset.push_back(epee::string_tools::buff_to_hex_nodelimer(oss.str()));
- }
- }
- else
- {
- if (!req.do_not_relay)
- m_wallet->commit_tx(ptx_vector);
-
- // populate response with tx hashes
- for (auto & ptx : ptx_vector)
- {
- res.tx_hash_list.push_back(epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(ptx.tx)));
- if (req.get_tx_hex)
- {
- cryptonote::blobdata blob;
- tx_to_blob(ptx.tx, blob);
- res.tx_blob_list.push_back(epee::string_tools::buff_to_hex_nodelimer(blob));
- }
- if (req.get_tx_metadata)
- {
- std::ostringstream oss;
- boost::archive::portable_binary_oarchive ar(oss);
- try
- {
- ar << ptx;
- }
- catch (...)
- {
- er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
- er.message = "Failed to save multisig tx set after creation";
- return false;
- }
- res.tx_metadata_list.push_back(epee::string_tools::buff_to_hex_nodelimer(oss.str()));
- }
- }
- }
-
- return true;
+ return fill_response(ptx_vector, req.get_tx_keys, res.tx_key_list, res.amount_list, res.fee_list, res.multisig_txset, req.do_not_relay,
+ res.tx_hash_list, req.get_tx_hex, res.tx_blob_list, req.get_tx_metadata, res.tx_metadata_list, er);
}
catch (const std::exception& e)
{
@@ -985,68 +905,8 @@ namespace tools
uint64_t mixin = m_wallet->adjust_mixin(req.mixin);
std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_all(req.below_amount, dsts[0].addr, dsts[0].is_subaddress, mixin, req.unlock_time, req.priority, extra, req.account_index, req.subaddr_indices, m_trusted_daemon);
- for (const auto & ptx : ptx_vector)
- {
- if (req.get_tx_keys)
- {
- res.tx_key_list.push_back(epee::string_tools::pod_to_hex(ptx.tx_key));
- }
- }
-
- if (m_wallet->multisig())
- {
- for (tools::wallet2::pending_tx &ptx: ptx_vector)
- {
- std::ostringstream oss;
- boost::archive::portable_binary_oarchive ar(oss);
- try
- {
- ar << ptx;
- }
- catch (...)
- {
- er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
- er.message = "Failed to save multisig tx set after creation";
- return false;
- }
- res.multisig_txset.push_back(epee::string_tools::buff_to_hex_nodelimer(oss.str()));
- }
- }
- else
- {
- if (!req.do_not_relay)
- m_wallet->commit_tx(ptx_vector);
-
- // populate response with tx hashes
- for (auto & ptx : ptx_vector)
- {
- res.tx_hash_list.push_back(epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(ptx.tx)));
- if (req.get_tx_hex)
- {
- cryptonote::blobdata blob;
- tx_to_blob(ptx.tx, blob);
- res.tx_blob_list.push_back(epee::string_tools::buff_to_hex_nodelimer(blob));
- }
- if (req.get_tx_metadata)
- {
- std::ostringstream oss;
- boost::archive::portable_binary_oarchive ar(oss);
- try
- {
- ar << ptx;
- }
- catch (...)
- {
- er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
- er.message = "Failed to save multisig tx set after creation";
- return false;
- }
- res.tx_metadata_list.push_back(epee::string_tools::buff_to_hex_nodelimer(oss.str()));
- }
- }
- }
-
- return true;
+ return fill_response(ptx_vector, req.get_tx_keys, res.tx_key_list, res.amount_list, res.fee_list, res.multisig_txset, req.do_not_relay,
+ res.tx_hash_list, req.get_tx_hex, res.tx_blob_list, req.get_tx_metadata, res.tx_metadata_list, er);
}
catch (const std::exception& e)
{
@@ -1112,63 +972,12 @@ namespace tools
return false;
}
- if (req.get_tx_key)
- {
- res.tx_key = epee::string_tools::pod_to_hex(ptx.tx_key);
- }
-
- if (m_wallet->multisig())
- {
- res.multisig_txset = epee::string_tools::buff_to_hex_nodelimer(m_wallet->save_multisig_tx(ptx_vector));
- if (res.multisig_txset.empty())
- {
- er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
- er.message = "Failed to save multisig tx set after creation";
- return false;
- }
- }
- else
- {
- if (!req.do_not_relay)
- m_wallet->commit_tx(ptx_vector);
-
- // populate response with tx hashes
- res.tx_hash = epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(ptx.tx));
- if (req.get_tx_hex)
- {
- cryptonote::blobdata blob;
- tx_to_blob(ptx.tx, blob);
- res.tx_blob = epee::string_tools::buff_to_hex_nodelimer(blob);
- }
- if (req.get_tx_metadata)
- {
- std::ostringstream oss;
- boost::archive::portable_binary_oarchive ar(oss);
- try
- {
- ar << ptx;
- }
- catch (...)
- {
- er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
- er.message = "Failed to save multisig tx set after creation";
- return false;
- }
- res.tx_metadata = epee::string_tools::buff_to_hex_nodelimer(oss.str());
- }
- }
- return true;
- }
- catch (const tools::error::daemon_busy& e)
- {
- er.code = WALLET_RPC_ERROR_CODE_DAEMON_IS_BUSY;
- er.message = e.what();
- return false;
+ return fill_response(ptx_vector, req.get_tx_key, res.tx_key, res.amount, res.fee, res.multisig_txset, req.do_not_relay,
+ res.tx_hash, req.get_tx_hex, res.tx_blob, req.get_tx_metadata, res.tx_metadata, er);
}
catch (const std::exception& e)
{
- er.code = WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR;
- er.message = e.what();
+ handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR);
return false;
}
catch (...)
diff --git a/src/wallet/wallet_rpc_server.h b/src/wallet/wallet_rpc_server.h
index b20198b78..88f2a85a4 100644
--- a/src/wallet/wallet_rpc_server.h
+++ b/src/wallet/wallet_rpc_server.h
@@ -207,6 +207,11 @@ namespace tools
bool not_open(epee::json_rpc::error& er);
void handle_rpc_exception(const std::exception_ptr& e, epee::json_rpc::error& er, int default_error_code);
+ template<typename Ts, typename Tu>
+ bool fill_response(std::vector<tools::wallet2::pending_tx> &ptx_vector,
+ bool get_tx_key, Ts& tx_key, Tu &amount, Tu &fee, std::string &multisig_txset, bool do_not_relay,
+ Ts &tx_hash, bool get_tx_hex, Ts &tx_blob, bool get_tx_metadata, Ts &tx_metadata, epee::json_rpc::error &er);
+
wallet2 *m_wallet;
std::string m_wallet_dir;
tools::private_file rpc_login_file;
diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h
index 76c02039b..4abbb8386 100644
--- a/src/wallet/wallet_rpc_server_commands_defs.h
+++ b/src/wallet/wallet_rpc_server_commands_defs.h
@@ -411,6 +411,7 @@ namespace wallet_rpc
std::string tx_hash;
std::string tx_key;
std::list<std::string> amount_keys;
+ uint64_t amount;
uint64_t fee;
std::string tx_blob;
std::string tx_metadata;
@@ -420,6 +421,7 @@ namespace wallet_rpc
KV_SERIALIZE(tx_hash)
KV_SERIALIZE(tx_key)
KV_SERIALIZE(amount_keys)
+ KV_SERIALIZE(amount)
KV_SERIALIZE(fee)
KV_SERIALIZE(tx_blob)
KV_SERIALIZE(tx_metadata)
@@ -520,14 +522,16 @@ namespace wallet_rpc
{
std::list<std::string> tx_hash_list;
std::list<std::string> tx_key_list;
+ std::list<uint64_t> amount_list;
std::list<uint64_t> fee_list;
std::list<std::string> tx_blob_list;
std::list<std::string> tx_metadata_list;
- std::list<std::string> multisig_txset;
+ std::string multisig_txset;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(tx_hash_list)
KV_SERIALIZE(tx_key_list)
+ KV_SERIALIZE(amount_list)
KV_SERIALIZE(fee_list)
KV_SERIALIZE(tx_blob_list)
KV_SERIALIZE(tx_metadata_list)
@@ -582,14 +586,16 @@ namespace wallet_rpc
{
std::list<std::string> tx_hash_list;
std::list<std::string> tx_key_list;
+ std::list<uint64_t> amount_list;
std::list<uint64_t> fee_list;
std::list<std::string> tx_blob_list;
std::list<std::string> tx_metadata_list;
- std::list<std::string> multisig_txset;
+ std::string multisig_txset;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(tx_hash_list)
KV_SERIALIZE(tx_key_list)
+ KV_SERIALIZE(amount_list)
KV_SERIALIZE(fee_list)
KV_SERIALIZE(tx_blob_list)
KV_SERIALIZE(tx_metadata_list)
@@ -631,6 +637,7 @@ namespace wallet_rpc
{
std::string tx_hash;
std::string tx_key;
+ uint64_t amount;
uint64_t fee;
std::string tx_blob;
std::string tx_metadata;
@@ -639,6 +646,7 @@ namespace wallet_rpc
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(tx_hash)
KV_SERIALIZE(tx_key)
+ KV_SERIALIZE(amount)
KV_SERIALIZE(fee)
KV_SERIALIZE(tx_blob)
KV_SERIALIZE(tx_metadata)
@@ -1106,6 +1114,7 @@ namespace wallet_rpc
std::string type;
uint64_t unlock_time;
cryptonote::subaddress_index subaddr_index;
+ std::string address;
bool double_spend_seen;
BEGIN_KV_SERIALIZE_MAP()
@@ -1120,6 +1129,7 @@ namespace wallet_rpc
KV_SERIALIZE(type);
KV_SERIALIZE(unlock_time)
KV_SERIALIZE(subaddr_index);
+ KV_SERIALIZE(address);
KV_SERIALIZE(double_spend_seen)
END_KV_SERIALIZE_MAP()
};
diff --git a/tests/fuzz/cold-outputs.cpp b/tests/fuzz/cold-outputs.cpp
index 2785db05d..6e813d823 100644
--- a/tests/fuzz/cold-outputs.cpp
+++ b/tests/fuzz/cold-outputs.cpp
@@ -53,16 +53,8 @@ int ColdOutputsFuzzer::init()
try
{
- boost::filesystem::remove("/tmp/cold-outputs-test.keys");
- boost::filesystem::remove("/tmp/cold-outputs-test.address.txt");
- boost::filesystem::remove("/tmp/cold-outputs-test");
-
wallet.init("");
- wallet.generate("/tmp/cold-outputs-test", "", spendkey, true, false);
-
- boost::filesystem::remove("/tmp/cold-outputs-test.keys");
- boost::filesystem::remove("/tmp/cold-outputs-test.address.txt");
- boost::filesystem::remove("/tmp/cold-outputs-test");
+ wallet.generate("", "", spendkey, true, false);
}
catch (const std::exception &e)
{
diff --git a/tests/fuzz/cold-transaction.cpp b/tests/fuzz/cold-transaction.cpp
index f0b4b26d6..20715c9ed 100644
--- a/tests/fuzz/cold-transaction.cpp
+++ b/tests/fuzz/cold-transaction.cpp
@@ -54,16 +54,8 @@ int ColdTransactionFuzzer::init()
try
{
- boost::filesystem::remove("/tmp/cold-transaction-test.keys");
- boost::filesystem::remove("/tmp/cold-transaction-test.address.txt");
- boost::filesystem::remove("/tmp/cold-transaction-test");
-
wallet.init("");
- wallet.generate("/tmp/cold-transaction-test", "", spendkey, true, false);
-
- boost::filesystem::remove("/tmp/cold-transaction-test.keys");
- boost::filesystem::remove("/tmp/cold-transaction-test.address.txt");
- boost::filesystem::remove("/tmp/cold-transaction-test");
+ wallet.generate("", "", spendkey, true, false);
}
catch (const std::exception &e)
{
diff --git a/tests/fuzz/signature.cpp b/tests/fuzz/signature.cpp
index 7ec4434e6..e7a0a53df 100644
--- a/tests/fuzz/signature.cpp
+++ b/tests/fuzz/signature.cpp
@@ -54,16 +54,8 @@ int SignatureFuzzer::init()
try
{
- boost::filesystem::remove("/tmp/signature-test.keys");
- boost::filesystem::remove("/tmp/signature-test.address.txt");
- boost::filesystem::remove("/tmp/signature-test");
-
wallet.init("");
- wallet.generate("/tmp/signature-test", "", spendkey, true, false);
-
- boost::filesystem::remove("/tmp/signature-test.keys");
- boost::filesystem::remove("/tmp/signature-test.address.txt");
- boost::filesystem::remove("/tmp/signature-test");
+ wallet.generate("", "", spendkey, true, false);
cryptonote::address_parse_info info;
if (!cryptonote::get_account_address_from_str_or_url(info, true, "9uVsvEryzpN8WH2t1WWhFFCG5tS8cBNdmJYNRuckLENFimfauV5pZKeS1P2CbxGkSDTUPHXWwiYE5ZGSXDAGbaZgDxobqDN"))
diff --git a/tests/gtest/cmake/internal_utils.cmake b/tests/gtest/cmake/internal_utils.cmake
index 93e6dbb7c..364db5970 100644
--- a/tests/gtest/cmake/internal_utils.cmake
+++ b/tests/gtest/cmake/internal_utils.cmake
@@ -87,7 +87,7 @@ macro(config_compiler_and_linker)
set(cxx_no_exception_flags "-D_HAS_EXCEPTIONS=0")
set(cxx_no_rtti_flags "-GR-")
elseif (CMAKE_COMPILER_IS_GNUCXX)
- set(cxx_base_flags "-Wall -Wshadow")
+ set(cxx_base_flags "-Wall -Wshadow -fPIC")
set(cxx_exception_flags "-fexceptions")
set(cxx_no_exception_flags "-fno-exceptions")
# Until version 4.3.2, GCC doesn't define a macro to indicate
diff --git a/tests/hash/CMakeLists.txt b/tests/hash/CMakeLists.txt
index 5cc95efbb..950df10b1 100644
--- a/tests/hash/CMakeLists.txt
+++ b/tests/hash/CMakeLists.txt
@@ -36,6 +36,7 @@ add_executable(hash-tests
${hash_headers})
target_link_libraries(hash-tests
PRIVATE
+ common
cncrypto
${EXTRA_LIBRARIES})
set_property(TARGET hash-tests
diff --git a/tests/performance_tests/CMakeLists.txt b/tests/performance_tests/CMakeLists.txt
index 2b3a0d6f8..1a0677925 100644
--- a/tests/performance_tests/CMakeLists.txt
+++ b/tests/performance_tests/CMakeLists.txt
@@ -41,6 +41,7 @@ set(performance_tests_headers
generate_key_image_helper.h
generate_keypair.h
is_out_to_acc.h
+ subaddress_expand.h
multi_tx_test_base.h
performance_tests.h
performance_utils.h
@@ -51,6 +52,7 @@ add_executable(performance_tests
${performance_tests_headers})
target_link_libraries(performance_tests
PRIVATE
+ wallet
cryptonote_core
common
cncrypto
diff --git a/tests/performance_tests/main.cpp b/tests/performance_tests/main.cpp
index 459eecba4..2f3ce289d 100644
--- a/tests/performance_tests/main.cpp
+++ b/tests/performance_tests/main.cpp
@@ -44,6 +44,7 @@
#include "generate_key_image_helper.h"
#include "generate_keypair.h"
#include "is_out_to_acc.h"
+#include "subaddress_expand.h"
#include "sc_reduce32.h"
#include "cn_fast_hash.h"
@@ -112,6 +113,8 @@ int main(int argc, char** argv)
TEST_PERFORMANCE0(test_generate_keypair);
TEST_PERFORMANCE0(test_sc_reduce32);
+ TEST_PERFORMANCE2(test_wallet2_expand_subaddresses, 50, 200);
+
TEST_PERFORMANCE0(test_cn_slow_hash);
TEST_PERFORMANCE1(test_cn_fast_hash, 32);
TEST_PERFORMANCE1(test_cn_fast_hash, 16384);
diff --git a/tests/performance_tests/subaddress_expand.h b/tests/performance_tests/subaddress_expand.h
new file mode 100644
index 000000000..fea92d54b
--- /dev/null
+++ b/tests/performance_tests/subaddress_expand.h
@@ -0,0 +1,65 @@
+// Copyright (c) 2017, 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.
+//
+// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
+
+#pragma once
+
+#include "wallet/wallet2.h"
+#include "ringct/rctOps.h"
+
+#include "single_tx_test_base.h"
+
+template<size_t Major, size_t Minor>
+class test_wallet2_expand_subaddresses : public single_tx_test_base
+{
+public:
+ static const size_t loop_count = 1;
+ static const size_t major = Major;
+ static const size_t minor = Minor;
+
+ bool init()
+ {
+ if (!single_tx_test_base::init())
+ return false;
+ wallet.set_subaddress_lookahead(1, 1);
+ crypto::secret_key spendkey = rct::rct2sk(rct::skGen());
+ wallet.generate("", "", spendkey, true, false);
+ wallet.set_subaddress_lookahead(major, minor);
+ return true;
+ }
+
+ bool test()
+ {
+ wallet.expand_subaddresses({0, 0});
+ return true;
+ }
+
+private:
+ tools::wallet2 wallet;
+};
diff --git a/tests/unit_tests/crypto.cpp b/tests/unit_tests/crypto.cpp
index d9a7b8ad5..3a8e787ec 100644
--- a/tests/unit_tests/crypto.cpp
+++ b/tests/unit_tests/crypto.cpp
@@ -47,14 +47,6 @@ namespace
"8b655970153799af2aeadc9ff1add0ea6c7251d54154cfa92c173a0dd39c1f94"
"6c7251d54154cfa92c173a0dd39c1f948b655970153799af2aeadc9ff1add0ea";
- static std::uint8_t md[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00
- };
-
template<typename T>
bool is_formatted()
{
@@ -69,22 +61,6 @@ namespace
out << "BEGIN" << value << "END";
return out.str() == "BEGIN<" + std::string{expected, sizeof(T) * 2} + ">END";
}
-
- bool keccak_harness()
- {
- size_t inlen = sizeof(source);
- int mdlen = (int)sizeof(md);
- keccak(source, inlen, md, mdlen);
-
- if (md[0] != 0x00)
- {
- return true;
- }
- else
- {
- return false;
- }
- }
}
TEST(Crypto, Ostream)
diff --git a/tests/unit_tests/hardfork.cpp b/tests/unit_tests/hardfork.cpp
index c235f49fd..0a472a421 100644
--- a/tests/unit_tests/hardfork.cpp
+++ b/tests/unit_tests/hardfork.cpp
@@ -118,7 +118,7 @@ public:
virtual uint64_t get_txpool_tx_count(bool include_unrelayed_txes = true) const { return 0; }
virtual bool txpool_has_tx(const crypto::hash &txid) const { return false; }
virtual void remove_txpool_tx(const crypto::hash& txid) {}
- virtual txpool_tx_meta_t get_txpool_tx_meta(const crypto::hash& txid) const { return txpool_tx_meta_t(); }
+ virtual bool get_txpool_tx_meta(const crypto::hash& txid, txpool_tx_meta_t &meta) const { return false; }
virtual bool get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata &bd) const { return false; }
virtual cryptonote::blobdata get_txpool_tx_blob(const crypto::hash& txid) const { return ""; }
virtual bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata*)>, bool include_blob = false, bool include_unrelayed_txes = false) const { return false; }
diff --git a/tests/unit_tests/http.cpp b/tests/unit_tests/http.cpp
index 5e427f064..0e8f9f747 100644
--- a/tests/unit_tests/http.cpp
+++ b/tests/unit_tests/http.cpp
@@ -60,12 +60,18 @@
#include "md5_l.h"
#include "string_tools.h"
+#include "crypto/crypto.h"
namespace {
namespace http = epee::net_utils::http;
using fields = std::unordered_map<std::string, std::string>;
using auth_responses = std::vector<fields>;
+void rng(size_t len, uint8_t *ptr)
+{
+ crypto::rand(len, ptr);
+}
+
std::string quoted(std::string str)
{
str.insert(str.begin(), '"');
@@ -250,13 +256,13 @@ std::string get_nc(std::uint32_t count)
TEST(HTTP_Server_Auth, NotRequired)
{
- http::http_server_auth auth{};
+ http::http_server_auth auth{}; // no rng here
EXPECT_FALSE(auth.get_response(http::http_request_info{}));
}
TEST(HTTP_Server_Auth, MissingAuth)
{
- http::http_server_auth auth{{"foo", "bar"}};
+ http::http_server_auth auth{{"foo", "bar"}, rng};
EXPECT_TRUE(bool(auth.get_response(http::http_request_info{})));
{
http::http_request_info request{};
@@ -267,7 +273,7 @@ TEST(HTTP_Server_Auth, MissingAuth)
TEST(HTTP_Server_Auth, BadSyntax)
{
- http::http_server_auth auth{{"foo", "bar"}};
+ http::http_server_auth auth{{"foo", "bar"}, rng};
EXPECT_TRUE(bool(auth.get_response(make_request({{u8"algorithm", "fo\xFF"}}))));
EXPECT_TRUE(bool(auth.get_response(make_request({{u8"cnonce", "\"000\xFF\""}}))));
EXPECT_TRUE(bool(auth.get_response(make_request({{u8"cnonce \xFF =", "\"000\xFF\""}}))));
@@ -277,7 +283,7 @@ TEST(HTTP_Server_Auth, BadSyntax)
TEST(HTTP_Server_Auth, MD5)
{
http::login user{"foo", "bar"};
- http::http_server_auth auth{user};
+ http::http_server_auth auth{user, rng};
const auto response = auth.get_response(make_request(fields{}));
ASSERT_TRUE(bool(response));
@@ -326,7 +332,7 @@ TEST(HTTP_Server_Auth, MD5_sess)
constexpr const char cnonce[] = "not a good cnonce";
http::login user{"foo", "bar"};
- http::http_server_auth auth{user};
+ http::http_server_auth auth{user, rng};
const auto response = auth.get_response(make_request(fields{}));
ASSERT_TRUE(bool(response));
@@ -378,7 +384,7 @@ TEST(HTTP_Server_Auth, MD5_auth)
constexpr const char qop[] = "auth";
http::login user{"foo", "bar"};
- http::http_server_auth auth{user};
+ http::http_server_auth auth{user, rng};
const auto response = auth.get_response(make_request(fields{}));
ASSERT_TRUE(bool(response));
@@ -446,7 +452,7 @@ TEST(HTTP_Server_Auth, MD5_sess_auth)
constexpr const char qop[] = "auth";
http::login user{"foo", "bar"};
- http::http_server_auth auth{user};
+ http::http_server_auth auth{user, rng};
const auto response = auth.get_response(make_request(fields{}));
ASSERT_TRUE(bool(response));
@@ -523,7 +529,7 @@ TEST(HTTP_Auth, DogFood)
const http::login user{"some_user", "ultimate password"};
- http::http_server_auth server{user};
+ http::http_server_auth server{user, rng};
http::http_client_auth client{user};
http::http_request_info request{};
diff --git a/tests/unit_tests/memwipe.cpp b/tests/unit_tests/memwipe.cpp
index b2b19fbf5..59f50cef8 100644
--- a/tests/unit_tests/memwipe.cpp
+++ b/tests/unit_tests/memwipe.cpp
@@ -30,7 +30,7 @@
#include <stdint.h>
#include "misc_log_ex.h"
-#include "common/memwipe.h"
+#include "memwipe.h"
// Probably won't catch the optimized out case, but at least we test
// it works in the normal case
@@ -47,7 +47,7 @@ static void test(bool wipe)
if ((intptr_t)quux == foop)
{
MDEBUG(std::hex << std::setw(8) << std::setfill('0') << *(uint32_t*)quux);
- if (wipe) ASSERT_TRUE(!memcmp(quux, "\0\0\0", 3));
+ if (wipe) ASSERT_TRUE(memcmp(quux, "bar", 3));
}
else MWARNING("We did not get the same location, cannot check");
free(quux);
diff --git a/tests/unit_tests/serialization.cpp b/tests/unit_tests/serialization.cpp
index 2ef1097da..8a75ac435 100644
--- a/tests/unit_tests/serialization.cpp
+++ b/tests/unit_tests/serialization.cpp
@@ -38,7 +38,6 @@
#include "cryptonote_basic/cryptonote_basic.h"
#include "cryptonote_basic/cryptonote_basic_impl.h"
#include "ringct/rctSigs.h"
-#include "serialization/serialization.h"
#include "serialization/binary_archive.h"
#include "serialization/json_archive.h"
#include "serialization/debug_archive.h"
diff --git a/tests/unit_tests/subaddress.cpp b/tests/unit_tests/subaddress.cpp
index c304b7347..ca950b25d 100644
--- a/tests/unit_tests/subaddress.cpp
+++ b/tests/unit_tests/subaddress.cpp
@@ -44,7 +44,7 @@ class WalletSubaddress : public ::testing::Test
{
try
{
- w1.generate(wallet_name, password, recovery_key, true, false);
+ w1.generate("", password, recovery_key, true, false);
}
catch (const std::exception& e)
{
@@ -58,24 +58,9 @@ class WalletSubaddress : public ::testing::Test
virtual void TearDown()
{
- boost::filesystem::wpath wallet_file(wallet_name);
- boost::filesystem::wpath wallet_address_file(wallet_name + ".address.txt");
- boost::filesystem::wpath wallet_keys_file(wallet_name + ".keys");
-
- if ( boost::filesystem::exists(wallet_file) )
- boost::filesystem::remove(wallet_file);
-
- if ( boost::filesystem::exists(wallet_address_file) )
- boost::filesystem::remove(wallet_address_file);
-
- if ( boost::filesystem::exists(wallet_keys_file) )
- boost::filesystem::remove(wallet_keys_file);
}
tools::wallet2 w1;
- std::string path_working_dir = ".";
- std::string path_test_wallet = "test_wallet";
- const std::string wallet_name = path_working_dir + "/" + path_test_wallet;
const std::string password = "testpass";
crypto::secret_key recovery_key = crypto::secret_key();
const std::string test_label = "subaddress test label";
diff --git a/tests/unit_tests/varint.cpp b/tests/unit_tests/varint.cpp
index 2b31cdfdf..577ad4d26 100644
--- a/tests/unit_tests/varint.cpp
+++ b/tests/unit_tests/varint.cpp
@@ -36,7 +36,6 @@
#include <boost/foreach.hpp>
#include "cryptonote_basic/cryptonote_basic.h"
#include "cryptonote_basic/cryptonote_basic_impl.h"
-#include "serialization/serialization.h"
#include "serialization/binary_archive.h"
#include "serialization/json_archive.h"
#include "serialization/debug_archive.h"
diff --git a/translations/CMakeLists.txt b/translations/CMakeLists.txt
new file mode 100644
index 000000000..a069daea9
--- /dev/null
+++ b/translations/CMakeLists.txt
@@ -0,0 +1,63 @@
+# Copyright (c) 2017, 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.
+
+cmake_minimum_required(VERSION 2.8.7)
+
+project(translations)
+
+add_executable(generate_translations_header generate_translations_header.c)
+
+find_program(LRELEASE lrelease)
+if(LRELEASE STREQUAL "LRELEASE-NOTFOUND")
+ set(ts_files "")
+ message(WARNING "lrelease program not found, translation files not built")
+else()
+ execute_process(COMMAND ${LRELEASE} -version
+ RESULT_VARIABLE lrelease_ret)
+ if(NOT lrelease_ret EQUAL "0")
+ set(ts_files "")
+ message(WARNING "lrelease program not working, translation files not built")
+ else()
+ file(GLOB ts_files RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" *.ts)
+ foreach(ts_file ${ts_files})
+ string(REPLACE ".ts" ".qm" qm_file "${ts_file}")
+ add_custom_command(TARGET generate_translations_header
+ PRE_BUILD
+ COMMAND ${LRELEASE} "${CMAKE_CURRENT_SOURCE_DIR}/${ts_file}" -qm "${qm_file}"
+ WORKING_DIRECTORY "${CMAKE_CURRENT_BIN_DIR}")
+ endforeach()
+ endif()
+endif()
+
+string(REPLACE ".ts" ".qm" qm_files "${ts_files}")
+
+add_custom_command(TARGET generate_translations_header
+ POST_BUILD
+ COMMAND generate_translations_header ${qm_files}
+ WORKING_DIRECTORY "${CMAKE_CURRENT_BIN_DIR}"
+ COMMENT "Generating embedded translations header")
diff --git a/translations/generate_translations_header.c b/translations/generate_translations_header.c
new file mode 100644
index 000000000..69671913e
--- /dev/null
+++ b/translations/generate_translations_header.c
@@ -0,0 +1,86 @@
+// Copyright (c) 2013, Sergey Lyubka
+// Copyright (c) 2017, The Monero Project
+// All rights reserved.
+// Released under the MIT license.
+
+// This program takes a list of files as an input, and produces C++ code that
+// contains the contents of all these files as a collection of strings.
+//
+// Usage:
+// 1. Compile this file:
+// cc -o generate-translations-header generate-translations-header.c
+//
+// 2. Convert list of files into single header:
+// ./generate-translations-header monero_fr.qm monero_it.qm > translations_files.h
+//
+// 3. In your application code, include translations_files.h, then you can
+// access the files using this function:
+// static bool find_embedded_file(const std::string &file_name, std::string &data);
+// std::string data;
+// find_embedded_file("monero_fr.qm", data);
+
+#include <stdio.h>
+#include <stdlib.h>
+
+static const char *code =
+ "static bool find_embedded_file(const std::string &name, std::string &data) {\n"
+ " const struct embedded_file *p;\n"
+ " for (p = embedded_files; p->name != NULL; p++) {\n"
+ " if (*p->name == name) {\n"
+ " data = *p->data;\n"
+ " return true;\n"
+ " }\n"
+ " }\n"
+ " return false;\n"
+ "}\n";
+
+int main(int argc, char *argv[]) {
+ FILE *fp, *foutput;
+ int i, j, ch;
+
+ if((foutput = fopen("translation_files.h", "w")) == NULL) {
+ exit(EXIT_FAILURE);
+ }
+
+ fprintf(foutput, "#ifndef TRANSLATION_FILES_H\n");
+ fprintf(foutput, "#define TRANSLATION_FILES_H\n\n");
+ fprintf(foutput, "#include <string>\n\n");
+
+ for (i = 1; i < argc; i++) {
+ if ((fp = fopen(argv[i], "rb")) == NULL) {
+ exit(EXIT_FAILURE);
+ } else {
+ fprintf(foutput, "static const std::string translation_file_name_%d = \"%s\";\n", i, argv[i]);
+ fprintf(foutput, "static const std::string translation_file_data_%d = std::string(", i);
+ for (j = 0; (ch = fgetc(fp)) != EOF; j++) {
+ if ((j % 16) == 0) {
+ if (j > 0) {
+ fprintf(foutput, "%s", "\"");
+ }
+ fprintf(foutput, "%s", "\n \"");
+ }
+ fprintf(foutput, "\\x%02x", ch);
+ }
+ fprintf(foutput, "\",\n %d);\n\n", j);
+ fclose(fp);
+ }
+ }
+
+ fprintf(foutput, "%s", "static const struct embedded_file {\n");
+ fprintf(foutput, "%s", " const std::string *name;\n");
+ fprintf(foutput, "%s", " const std::string *data;\n");
+ fprintf(foutput, "%s", "} embedded_files[] = {\n");
+
+ for (i = 1; i < argc; i++) {
+ fprintf(foutput, " {&translation_file_name_%d, &translation_file_data_%d},\n", i, i);
+ }
+ fprintf(foutput, "%s", " {NULL, NULL}\n");
+ fprintf(foutput, "%s", "};\n\n");
+ fprintf(foutput, "%s\n", code);
+
+ fprintf(foutput, "#endif /* TRANSLATION_FILES_H */\n");
+
+ fclose(foutput);
+
+ return EXIT_SUCCESS;
+}
diff --git a/translations/monero.ts b/translations/monero.ts
index 9c1888ac2..4393d3457 100644
--- a/translations/monero.ts
+++ b/translations/monero.ts
@@ -654,7 +654,7 @@
</message>
<message>
<location filename="../src/simplewallet/simplewallet.cpp" line="1497"/>
- <source>Use &quot;help&quot; command to see the list of available commands.
+ <source>Use the &quot;help&quot; command to see the list of available commands.
</source>
<translation type="unfinished"></translation>
</message>
@@ -1624,10 +1624,10 @@ Warning: Some input keys being spent are from </source>
<message>
<location filename="../src/simplewallet/simplewallet.cpp" line="1385"/>
<source>Your wallet has been generated!
-To start synchronizing with the daemon, use &quot;refresh&quot; command.
-Use &quot;help&quot; command to see the list of available commands.
-Always use &quot;exit&quot; command when closing monero-wallet-cli to save your
-current session&apos;s state. Otherwise, you might need to synchronize
+To start synchronizing with the daemon, use the &quot;refresh&quot; command.
+Use the &quot;help&quot; command to see the list of available commands.
+Always use the &quot;exit&quot; command when closing monero-wallet-cli to save
+your current session&apos;s state. Otherwise, you might need to synchronize
your wallet again (your wallet keys are NOT at risk in any case).
</source>
<translation type="unfinished"></translation>
diff --git a/translations/monero_fr.ts b/translations/monero_fr.ts
index 7d07be125..8ebba52cf 100644
--- a/translations/monero_fr.ts
+++ b/translations/monero_fr.ts
@@ -666,7 +666,7 @@
</message>
<message>
<location filename="../src/simplewallet/simplewallet.cpp" line="1497"/>
- <source>Use &quot;help&quot; command to see the list of available commands.
+ <source>Use the &quot;help&quot; command to see the list of available commands.
</source>
<translation>Utilisez la commande &quot;help&quot; pour voir la liste des commandes disponibles.
</translation>
@@ -1656,10 +1656,10 @@ Attention : Certaines clés d&apos;entrées étant dépensées sont issues de <
<message>
<location filename="../src/simplewallet/simplewallet.cpp" line="1385"/>
<source>Your wallet has been generated!
-To start synchronizing with the daemon, use &quot;refresh&quot; command.
-Use &quot;help&quot; command to see the list of available commands.
-Always use &quot;exit&quot; command when closing monero-wallet-cli to save your
-current session&apos;s state. Otherwise, you might need to synchronize
+To start synchronizing with the daemon, use the &quot;refresh&quot; command.
+Use the &quot;help&quot; command to see the list of available commands.
+Always use the &quot;exit&quot; command when closing monero-wallet-cli to save
+your current session&apos;s state. Otherwise, you might need to synchronize
your wallet again (your wallet keys are NOT at risk in any case).
</source>
<translation>Votre portefeuille a été généré !
diff --git a/translations/monero_it.ts b/translations/monero_it.ts
index 787651da2..8ee3277fa 100644
--- a/translations/monero_it.ts
+++ b/translations/monero_it.ts
@@ -654,7 +654,7 @@
</message>
<message>
<location filename="../src/simplewallet/simplewallet.cpp" line="1497"/>
- <source>Use &quot;help&quot; command to see the list of available commands.
+ <source>Use the &quot;help&quot; command to see the list of available commands.
</source>
<translation>Usa il comando &quot;help&quot; per visualizzare la lista dei comandi disponibili.</translation>
</message>
@@ -1620,10 +1620,10 @@ Avviso: alcune chiavi di input spese vengono da </translation>
<message>
<location filename="../src/simplewallet/simplewallet.cpp" line="1385"/>
<source>Your wallet has been generated!
-To start synchronizing with the daemon, use &quot;refresh&quot; command.
-Use &quot;help&quot; command to see the list of available commands.
-Always use &quot;exit&quot; command when closing monero-wallet-cli to save your
-current session&apos;s state. Otherwise, you might need to synchronize
+To start synchronizing with the daemon, use the &quot;refresh&quot; command.
+Use the &quot;help&quot; command to see the list of available commands.
+Always use the &quot;exit&quot; command when closing monero-wallet-cli to save
+your current session&apos;s state. Otherwise, you might need to synchronize
your wallet again (your wallet keys are NOT at risk in any case).
</source>
<translation>Il tuo portafoglio è stato generato!
diff --git a/utils/build_scripts/android32.Dockerfile b/utils/build_scripts/android32.Dockerfile
index 37d012202..20b846aa1 100644
--- a/utils/build_scripts/android32.Dockerfile
+++ b/utils/build_scripts/android32.Dockerfile
@@ -80,7 +80,7 @@ RUN git clone https://github.com/zeromq/zeromq4-1.git \
&& CC=clang CXX=clang++ ./configure --host=arm-none-linux-gnueabi \
&& make
-RUN ln -s /opt/android/openssl/libcrypto.a /opt/android/openssl/libssl.a /opt/android/toolchain-arm/arm-linux-androideabi/lib/armv7-a
+RUN ln -s /opt/android/openssl/libcrypto.a /opt/android/openssl/libssl.a ${TOOLCHAIN_DIR}/arm-linux-androideabi/lib/armv7-a
RUN git clone https://github.com/monero-project/monero.git \
&& cd monero \
diff --git a/utils/build_scripts/android64.Dockerfile b/utils/build_scripts/android64.Dockerfile
index 70c3c2b41..83bcbad89 100644
--- a/utils/build_scripts/android64.Dockerfile
+++ b/utils/build_scripts/android64.Dockerfile
@@ -79,7 +79,7 @@ RUN git clone https://github.com/zeromq/zeromq4-1.git \
&& CC=clang CXX=clang++ ./configure --host=aarch64-linux-android \
&& make
-RUN ln -s /opt/android/openssl/libcrypto.a /opt/android/openssl/libssl.a /opt/android/toolchain-arm/aarch64-linux-android/lib
+RUN ln -s /opt/android/openssl/libcrypto.a /opt/android/openssl/libssl.a ${TOOLCHAIN_DIR}/aarch64-linux-android/lib
RUN git clone https://github.com/monero-project/monero.git \
&& cd monero \