aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt21
-rw-r--r--README.md18
-rw-r--r--cmake/FindLibunwind.cmake25
-rw-r--r--contrib/epee/include/net/abstract_tcp_server2.inl2
-rw-r--r--contrib/epee/include/net/net_utils_base.h2
-rw-r--r--contrib/epee/include/storages/portable_storage_from_bin.h2
-rw-r--r--contrib/epee/include/string_tools.h4
-rw-r--r--external/db_drivers/liblmdb/midl.h4
-rw-r--r--src/blockchain_utilities/cn_deserialize.cpp3
-rw-r--r--src/common/CMakeLists.txt7
-rw-r--r--src/common/stack_trace.cpp120
-rw-r--r--src/common/stack_trace.h43
-rw-r--r--src/crypto/crypto.cpp9
-rw-r--r--src/crypto/oaes_lib.c4
-rw-r--r--src/crypto/slow-hash.c13
-rw-r--r--src/cryptonote_core/tx_extra.h13
-rw-r--r--src/daemon/main.cpp2
-rw-r--r--src/p2p/connection_basic.cpp6
-rw-r--r--src/p2p/connection_basic.hpp2
-rw-r--r--src/p2p/data_logger.cpp2
-rw-r--r--src/p2p/data_logger.hpp2
-rw-r--r--src/rpc/core_rpc_server.cpp2
-rw-r--r--src/simplewallet/simplewallet.cpp34
-rw-r--r--src/simplewallet/simplewallet.h1
-rw-r--r--src/wallet/api/wallet.cpp58
-rw-r--r--src/wallet/api/wallet.h4
-rw-r--r--src/wallet/api/wallet_manager.cpp8
-rw-r--r--src/wallet/wallet2.cpp1
-rw-r--r--src/wallet/wallet2_api.h21
-rw-r--r--src/wallet/wallet_rpc_server.cpp20
-rw-r--r--tests/libwallet_api_tests/main.cpp84
-rw-r--r--tests/unit_tests/hardfork.cpp4
32 files changed, 466 insertions, 75 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c375defe6..084c087d8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -243,6 +243,15 @@ endif()
add_definitions("-DBLOCKCHAIN_DB=${BLOCKCHAIN_DB}")
+find_package(Libunwind)
+if(LIBUNWIND_FOUND)
+ message(STATUS "Using libunwind to provide stack traces")
+ add_definitions("-DHAVE_LIBUNWIND")
+else()
+ message(STATUS "Stack traces disabled")
+ set(LIBUNWIND_LIBRARIES "")
+endif()
+
if (UNIX AND NOT APPLE)
# Note that at the time of this writing the -Wstrict-prototypes flag added below will make this fail
set(THREADS_PREFER_PTHREAD_FLAG ON)
@@ -274,6 +283,10 @@ if (BERKELEY_DB)
include_directories(${BDB_INCLUDE})
endif()
+# Final setup for libunwind
+include_directories(${LIBUNWIND_INCLUDE})
+link_directories(${LIBUNWIND_LIBRARY_DIRS})
+
if(MSVC)
add_definitions("/bigobj /MP /W3 /GS- /D_CRT_SECURE_NO_WARNINGS /wd4996 /wd4345 /D_WIN32_WINNT=0x0600 /DWIN32_LEAN_AND_MEAN /DGTEST_HAS_TR1_TUPLE=0 /FIinline_c.h /D__SSE4_1__")
# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Dinline=__inline")
@@ -310,7 +323,7 @@ else()
endif()
if(MINGW)
set(WARNINGS "${WARNINGS} -Wno-error=unused-value -Wno-error=unused-but-set-variable")
- set(MINGW_FLAG "${MINGW_FLAG} -DWIN32_LEAN_AND_MEAN")
+ set(MINGW_FLAG "${MINGW_FLAG} -DWIN32_LEAN_AND_MEAN -D_POSIX_C_SOURCE")
set(Boost_THREADAPI win32)
include_directories(SYSTEM src/platform/mingw)
# mingw doesn't support LTO (multiple definition errors at link time)
@@ -394,6 +407,7 @@ else()
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${RELEASE_FLAGS}")
if(STATIC AND NOT APPLE AND NOT FREEBSD AND NOT OPENBSD)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++")
+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--wrap=__cxa_throw")
endif()
endif()
@@ -431,6 +445,11 @@ elseif(NOT MSVC)
set(EXTRA_LIBRARIES ${RT})
endif()
+if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT MINGW)
+ find_library(DL dl)
+ set(EXTRA_LIBRARIES ${DL})
+endif()
+
include(version.cmake)
add_subdirectory(contrib)
diff --git a/README.md b/README.md
index 3311c4ec9..81d5d75da 100644
--- a/README.md
+++ b/README.md
@@ -187,6 +187,24 @@ Dependencies: Doxygen 1.8.0 or later, Graphviz 2.28 or later (optional).
* If you have installed Graphviz, you can also generate in-doc diagrams by instead running `HAVE_DOT=YES doxygen Doxyfile`
* The output will be built in doc/html/
+## Running bitmonerod
+
+The build places the binary in `bin/` sub-directory within the build directory
+from which cmake was invoked (repository root by default). To run in
+foreground:
+
+ ./bin/bitmonerod
+
+To run in background:
+
+ ./bin/bitmonerod --log-file bitmonerod.log --detach
+
+To list all available options, run `./bin/bitmonerod --help`. Options can be
+specified either on the command line or in a configuration file passed by the
+`--config-file` argument. To specify an option in the configuration file, add
+a line with the syntax `argumentname=value`, where `argumentname` is the name
+of the argument without any dashes, for example `log-level=1`.
+
## Internationalization
See README.i18n
diff --git a/cmake/FindLibunwind.cmake b/cmake/FindLibunwind.cmake
new file mode 100644
index 000000000..9946e7cdd
--- /dev/null
+++ b/cmake/FindLibunwind.cmake
@@ -0,0 +1,25 @@
+# - Try to find libunwind
+# Once done this will define
+#
+# LIBUNWIND_FOUND - system has libunwind
+# LIBUNWIND_INCLUDE_DIR - the libunwind include directory
+# LIBUNWIND_LIBRARIES - Link these to use libunwind
+# LIBUNWIND_DEFINITIONS - Compiler switches required for using libunwind
+
+# Copyright (c) 2006, Alexander Dymo, <adymo@kdevelop.org>
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+find_path(LIBUNWIND_INCLUDE_DIR libunwind.h
+ /usr/include
+ /usr/local/include
+)
+
+find_library(LIBUNWIND_LIBRARIES NAMES unwind )
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(Libunwind "Could not find libunwind" LIBUNWIND_INCLUDE_DIR LIBUNWIND_LIBRARIES)
+# show the LIBUNWIND_INCLUDE_DIR and LIBUNWIND_LIBRARIES variables only in the advanced view
+mark_as_advanced(LIBUNWIND_INCLUDE_DIR LIBUNWIND_LIBRARIES )
+
diff --git a/contrib/epee/include/net/abstract_tcp_server2.inl b/contrib/epee/include/net/abstract_tcp_server2.inl
index ca9429c91..94dbe7458 100644
--- a/contrib/epee/include/net/abstract_tcp_server2.inl
+++ b/contrib/epee/include/net/abstract_tcp_server2.inl
@@ -88,7 +88,7 @@ PRAGMA_WARNING_DISABLE_VS(4355)
PRAGMA_WARNING_DISABLE_VS(4355)
//---------------------------------------------------------------------------------
template<class t_protocol_handler>
- connection<t_protocol_handler>::~connection()
+ connection<t_protocol_handler>::~connection() noexcept(false)
{
if(!m_was_shutdown)
{
diff --git a/contrib/epee/include/net/net_utils_base.h b/contrib/epee/include/net/net_utils_base.h
index f963e7746..78e555fac 100644
--- a/contrib/epee/include/net/net_utils_base.h
+++ b/contrib/epee/include/net/net_utils_base.h
@@ -119,7 +119,7 @@ namespace net_utils
virtual bool add_ref()=0;
virtual bool release()=0;
protected:
- virtual ~i_service_endpoint(){}
+ virtual ~i_service_endpoint() noexcept(false) {}
};
diff --git a/contrib/epee/include/storages/portable_storage_from_bin.h b/contrib/epee/include/storages/portable_storage_from_bin.h
index bc2fb1463..44a80cb21 100644
--- a/contrib/epee/include/storages/portable_storage_from_bin.h
+++ b/contrib/epee/include/storages/portable_storage_from_bin.h
@@ -68,7 +68,7 @@ namespace epee
++m_counter_ref;
CHECK_AND_ASSERT_THROW_MES(m_counter_ref < EPEE_PORTABLE_STORAGE_RECURSION_LIMIT_INTERNAL, "Wrong blob data in portable storage: recursion limitation (" << EPEE_PORTABLE_STORAGE_RECURSION_LIMIT_INTERNAL << ") exceeded");
}
- ~recursuion_limitation_guard()
+ ~recursuion_limitation_guard() noexcept(false)
{
CHECK_AND_ASSERT_THROW_MES(m_counter_ref != 0, "Internal error: m_counter_ref == 0 while ~recursuion_limitation_guard()");
--m_counter_ref;
diff --git a/contrib/epee/include/string_tools.h b/contrib/epee/include/string_tools.h
index 8289ee0ba..b973c6d48 100644
--- a/contrib/epee/include/string_tools.h
+++ b/contrib/epee/include/string_tools.h
@@ -139,9 +139,11 @@ namespace string_tools
}
//----------------------------------------------------------------------------
template<class CharT>
- bool parse_hexstr_to_binbuff(const std::basic_string<CharT>& s, std::basic_string<CharT>& res)
+ bool parse_hexstr_to_binbuff(const std::basic_string<CharT>& s, std::basic_string<CharT>& res, bool allow_partial_byte = false)
{
res.clear();
+ if (!allow_partial_byte && (s.size() & 1))
+ return false;
try
{
long v = 0;
diff --git a/external/db_drivers/liblmdb/midl.h b/external/db_drivers/liblmdb/midl.h
index e16aa0c3c..1555ecb19 100644
--- a/external/db_drivers/liblmdb/midl.h
+++ b/external/db_drivers/liblmdb/midl.h
@@ -60,11 +60,7 @@ typedef MDB_ID *MDB_IDL;
/* IDL sizes - likely should be even bigger
* limiting factors: sizeof(ID), thread stack size
*/
-#ifdef MDB_VL32
-#define MDB_IDL_LOGN 14 /* DB_SIZE is 2^14, UM_SIZE is 2^15 */
-#else
#define MDB_IDL_LOGN 16 /* DB_SIZE is 2^16, UM_SIZE is 2^17 */
-#endif
#define MDB_IDL_DB_SIZE (1<<MDB_IDL_LOGN)
#define MDB_IDL_UM_SIZE (1<<(MDB_IDL_LOGN+1))
diff --git a/src/blockchain_utilities/cn_deserialize.cpp b/src/blockchain_utilities/cn_deserialize.cpp
index b8d38c9af..a8448dcee 100644
--- a/src/blockchain_utilities/cn_deserialize.cpp
+++ b/src/blockchain_utilities/cn_deserialize.cpp
@@ -160,8 +160,9 @@ int main(int argc, char* argv[])
std::cout << "field " << n << ": ";
if (typeid(cryptonote::tx_extra_padding) == fields[n].type()) std::cout << "extra padding: " << boost::get<cryptonote::tx_extra_padding>(fields[n]).size << " bytes";
else if (typeid(cryptonote::tx_extra_pub_key) == fields[n].type()) std::cout << "extra pub key: " << boost::get<cryptonote::tx_extra_pub_key>(fields[n]).pub_key;
- else if (typeid(cryptonote::tx_extra_nonce) == fields[n].type()) std::cout << "extra nonce: " << boost::get<cryptonote::tx_extra_nonce>(fields[n]).nonce;
+ else if (typeid(cryptonote::tx_extra_nonce) == fields[n].type()) std::cout << "extra nonce: " << epee::string_tools::buff_to_hex_nodelimer(boost::get<cryptonote::tx_extra_nonce>(fields[n]).nonce);
else if (typeid(cryptonote::tx_extra_merge_mining_tag) == fields[n].type()) std::cout << "extra merge mining tag: depth " << boost::get<cryptonote::tx_extra_merge_mining_tag>(fields[n]).depth << ", merkle root " << boost::get<cryptonote::tx_extra_merge_mining_tag>(fields[n]).merkle_root;
+ else if (typeid(cryptonote::tx_extra_mysterious_minergate) == fields[n].type()) std::cout << "extra minergate custom: " << epee::string_tools::buff_to_hex_nodelimer(boost::get<cryptonote::tx_extra_mysterious_minergate>(fields[n]).data);
else std::cout << "unknown";
std::cout << std::endl;
}
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 2289704e5..9afbe4b82 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -31,7 +31,8 @@ set(common_sources
command_line.cpp
dns_utils.cpp
util.cpp
- i18n.cpp)
+ i18n.cpp
+ stack_trace.cpp)
set(common_headers)
@@ -48,7 +49,8 @@ set(common_private_headers
unordered_containers_boost_serialization.h
util.h
varint.h
- i18n.h)
+ i18n.h
+ stack_trace.h)
bitmonero_private_headers(common
${common_private_headers})
@@ -60,6 +62,7 @@ target_link_libraries(common
LINK_PRIVATE
crypto
${UNBOUND_LIBRARY}
+ ${LIBUNWIND_LIBRARIES}
${Boost_DATE_TIME_LIBRARY}
${Boost_FILESYSTEM_LIBRARY}
${Boost_SYSTEM_LIBRARY}
diff --git a/src/common/stack_trace.cpp b/src/common/stack_trace.cpp
new file mode 100644
index 000000000..2805e7604
--- /dev/null
+++ b/src/common/stack_trace.cpp
@@ -0,0 +1,120 @@
+// Copyright (c) 2016, The Monero Project
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are
+// permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other
+// materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its contributors may be
+// used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "common/stack_trace.h"
+#include "misc_log_ex.h"
+#ifdef HAVE_LIBUNWIND
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#endif
+#include <cxxabi.h>
+#include <dlfcn.h>
+
+// from http://stackoverflow.com/questions/11665829/how-can-i-print-stack-trace-for-caught-exceptions-in-c-code-injection-in-c
+#ifdef STATICLIB
+#define CXA_THROW __wrap___cxa_throw
+extern "C" void __real___cxa_throw(void *ex, void *info, void (*dest)(void*));
+#else
+#define CXA_THROW __cxa_throw
+#endif
+
+extern "C" void CXA_THROW(void *ex, void *info, void (*dest)(void*))
+{
+
+ int status;
+ char *dsym = abi::__cxa_demangle(((const std::type_info*)info)->name(), NULL, NULL, &status);
+ tools::log_stack_trace((std::string("Exception: ")+((!status && dsym) ? dsym : (const char*)info)).c_str());
+ free(dsym);
+
+#ifdef STATICLIB
+ __real___cxa_throw(ex, info, dest);
+#else
+ static void (*const rethrow)(void*, void*, void(*)(void*)) __attribute__((noreturn)) = (void(*)(void*, void*, void(*)(void*)))dlsym(RTLD_NEXT, "__cxa_throw");
+ rethrow(ex, info, dest);
+#endif
+}
+
+namespace
+{
+ std::string stack_trace_log;
+}
+
+namespace tools
+{
+
+void set_stack_trace_log(const std::string &log)
+{
+ stack_trace_log = log;
+}
+
+void log_stack_trace(const char *msg)
+{
+#ifdef HAVE_LIBUNWIND
+ unw_context_t ctx;
+ unw_cursor_t cur;
+ unw_word_t ip, off;
+ unsigned level;
+ char sym[512], *dsym;
+ int status;
+ const char *log = stack_trace_log.empty() ? NULL : stack_trace_log.c_str();
+
+ if (msg)
+ LOG_PRINT2(log, msg, LOG_LEVEL_0);
+ LOG_PRINT2(log, "Unwinded call stack:", LOG_LEVEL_0);
+ if (unw_getcontext(&ctx) < 0) {
+ LOG_PRINT2(log, "Failed to create unwind context", LOG_LEVEL_0);
+ return;
+ }
+ if (unw_init_local(&cur, &ctx) < 0) {
+ LOG_PRINT2(log, "Failed to find the first unwind frame", LOG_LEVEL_0);
+ return;
+ }
+ for (level = 1; level < 999; ++level) { // 999 for safety
+ int ret = unw_step(&cur);
+ if (ret < 0) {
+ LOG_PRINT2(log, "Failed to find the next frame", LOG_LEVEL_0);
+ return;
+ }
+ if (ret == 0)
+ break;
+ if (unw_get_reg(&cur, UNW_REG_IP, &ip) < 0) {
+ LOG_PRINT2(log, " " << std::setw(4) << level, LOG_LEVEL_0);
+ continue;
+ }
+ if (unw_get_proc_name(&cur, sym, sizeof(sym), &off) < 0) {
+ LOG_PRINT2(log, " " << std::setw(4) << level << std::setbase(16) << std::setw(20) << "0x" << ip, LOG_LEVEL_0);
+ continue;
+ }
+ dsym = abi::__cxa_demangle(sym, NULL, NULL, &status);
+ LOG_PRINT2(log, " " << std::setw(4) << level << std::setbase(16) << std::setw(20) << "0x" << ip << " " << (!status && dsym ? dsym : sym) << " + " << "0x" << off, LOG_LEVEL_0);
+ free(dsym);
+ }
+#endif
+}
+
+} // namespace tools
diff --git a/src/common/stack_trace.h b/src/common/stack_trace.h
new file mode 100644
index 000000000..25eec9fb3
--- /dev/null
+++ b/src/common/stack_trace.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2016, 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.
+
+#ifndef MONERO_EXCEPTION_H
+#define MONERO_EXCEPTION_H
+
+#include <stdexcept>
+#include <string>
+
+namespace tools
+{
+
+void set_stack_trace_log(const std::string &log);
+void log_stack_trace(const char *msg);
+
+} // namespace tools
+
+#endif
diff --git a/src/crypto/crypto.cpp b/src/crypto/crypto.cpp
index e251d0ec2..f5e655274 100644
--- a/src/crypto/crypto.cpp
+++ b/src/crypto/crypto.cpp
@@ -263,16 +263,17 @@ namespace crypto {
PUSH_WARNINGS
DISABLE_VS_WARNINGS(4200)
+ struct ec_point_pair {
+ ec_point a, b;
+ };
struct rs_comm {
hash h;
- struct {
- ec_point a, b;
- } ab[];
+ struct ec_point_pair ab[];
};
POP_WARNINGS
static inline size_t rs_comm_size(size_t pubs_count) {
- return sizeof(rs_comm) + pubs_count * sizeof(rs_comm().ab[0]);
+ return sizeof(rs_comm) + pubs_count * sizeof(ec_point_pair);
}
void crypto_ops::generate_ring_signature(const hash &prefix_hash, const key_image &image,
diff --git a/src/crypto/oaes_lib.c b/src/crypto/oaes_lib.c
index 7fbe96e4c..4c1446898 100644
--- a/src/crypto/oaes_lib.c
+++ b/src/crypto/oaes_lib.c
@@ -27,10 +27,6 @@
* POSSIBILITY OF SUCH DAMAGE.
* ---------------------------------------------------------------------------
*/
-static const char _NR[] = {
- 0x4e,0x61,0x62,0x69,0x6c,0x20,0x53,0x2e,0x20,
- 0x41,0x6c,0x20,0x52,0x61,0x6d,0x6c,0x69,0x00 };
-
#include <stddef.h>
#include <time.h>
#include <string.h>
diff --git a/src/crypto/slow-hash.c b/src/crypto/slow-hash.c
index 4efa8af6c..8a1807657 100644
--- a/src/crypto/slow-hash.c
+++ b/src/crypto/slow-hash.c
@@ -658,10 +658,6 @@ void slow_hash_free_state(void)
return;
}
-static void (*const extra_hashes[4])(const void *, size_t, char *) = {
- hash_extra_blake, hash_extra_groestl, hash_extra_jh, hash_extra_skein
-};
-
#define MEMORY (1 << 21) /* 2 MiB */
#define ITER (1 << 20)
#define AES_BLOCK_SIZE 16
@@ -683,7 +679,8 @@ static void (*const extra_hashes[4])(const void *, size_t, char *) = {
#include "aesb.c"
-/* The asm corresponds to this C code
+#ifndef ARM_MUL_IMPL_ASM
+/* The asm corresponds to this C code */
#define SHORT uint32_t
#define LONG uint64_t
@@ -714,7 +711,8 @@ void mul(const uint8_t *ca, const uint8_t *cb, uint8_t *cres) {
res[3] = t.tmp[2];
res[0] = t.tmp[6];
res[1] = t.tmp[7];
-} */
+}
+#else // ARM_MUL_IMPL_ASM (TODO: this fails hash-slow test with GCC 6.1.1)
/* Can work as inline, but actually runs slower. Keep it separate */
#define mul(a, b, c) cn_mul128(a, b, c)
@@ -749,6 +747,7 @@ __asm__ __volatile__(
: [A]"r"(aa[1]), [a]"r"(aa[0]), [B]"r"(bb[1]), [b]"r"(bb[0]), [r]"r"(r)
: "cc", "memory");
}
+#endif // ARM_MUL_IMPL_ASM
STATIC INLINE void sum_half_blocks(uint8_t* a, const uint8_t* b)
{
@@ -824,7 +823,7 @@ void cn_slow_hash(const void *data, size_t length, char *hash)
{
for(j = 0; j < INIT_SIZE_BLK; j++)
aesb_pseudo_round(&text[AES_BLOCK_SIZE * j], &text[AES_BLOCK_SIZE * j], expandedKey);
- memcpy(&long_state[i * INIT_SIZE_BYTE], text, INIT_SIZE_BYTE);
+ memcpy(&long_state[i * INIT_SIZE_BYTE], text, INIT_SIZE_BYTE);
}
U64(a)[0] = U64(&state.k[0])[0] ^ U64(&state.k[32])[0];
diff --git a/src/cryptonote_core/tx_extra.h b/src/cryptonote_core/tx_extra.h
index 93d2e21b3..6f5fbe466 100644
--- a/src/cryptonote_core/tx_extra.h
+++ b/src/cryptonote_core/tx_extra.h
@@ -38,6 +38,7 @@
#define TX_EXTRA_TAG_PUBKEY 0x01
#define TX_EXTRA_NONCE 0x02
#define TX_EXTRA_MERGE_MINING_TAG 0x03
+#define TX_EXTRA_MYSTERIOUS_MINERGATE_TAG 0xDE
#define TX_EXTRA_NONCE_PAYMENT_ID 0x00
#define TX_EXTRA_NONCE_ENCRYPTED_PAYMENT_ID 0x01
@@ -158,14 +159,24 @@ namespace cryptonote
}
};
+ struct tx_extra_mysterious_minergate
+ {
+ std::string data;
+
+ BEGIN_SERIALIZE()
+ FIELD(data)
+ END_SERIALIZE()
+ };
+
// tx_extra_field format, except tx_extra_padding and tx_extra_pub_key:
// varint tag;
// varint size;
// varint data[];
- typedef boost::variant<tx_extra_padding, tx_extra_pub_key, tx_extra_nonce, tx_extra_merge_mining_tag> tx_extra_field;
+ typedef boost::variant<tx_extra_padding, tx_extra_pub_key, tx_extra_nonce, tx_extra_merge_mining_tag, tx_extra_mysterious_minergate> tx_extra_field;
}
VARIANT_TAG(binary_archive, cryptonote::tx_extra_padding, TX_EXTRA_TAG_PADDING);
VARIANT_TAG(binary_archive, cryptonote::tx_extra_pub_key, TX_EXTRA_TAG_PUBKEY);
VARIANT_TAG(binary_archive, cryptonote::tx_extra_nonce, TX_EXTRA_NONCE);
VARIANT_TAG(binary_archive, cryptonote::tx_extra_merge_mining_tag, TX_EXTRA_MERGE_MINING_TAG);
+VARIANT_TAG(binary_archive, cryptonote::tx_extra_mysterious_minergate, TX_EXTRA_MYSTERIOUS_MINERGATE_TAG);
diff --git a/src/daemon/main.cpp b/src/daemon/main.cpp
index bfd829dea..2e2f8936c 100644
--- a/src/daemon/main.cpp
+++ b/src/daemon/main.cpp
@@ -31,6 +31,7 @@
#include "common/command_line.h"
#include "common/scoped_message_writer.h"
#include "common/util.h"
+#include "common/stack_trace.h"
#include "cryptonote_core/cryptonote_core.h"
#include "cryptonote_core/miner.h"
#include "daemon/command_server.h"
@@ -259,6 +260,7 @@ int main(int argc, char const * argv[])
, log_file_path.filename().string().c_str()
, log_file_path.parent_path().string().c_str()
);
+ tools::set_stack_trace_log(log_file_path.filename().string());
}
if (command_line::has_arg(vm, daemon_args::arg_max_concurrency))
diff --git a/src/p2p/connection_basic.cpp b/src/p2p/connection_basic.cpp
index c0b73bc3e..981a02882 100644
--- a/src/p2p/connection_basic.cpp
+++ b/src/p2p/connection_basic.cpp
@@ -161,16 +161,16 @@ connection_basic::connection_basic(boost::asio::io_service& io_service, std::ato
mI->m_peer_number = sock_number.fetch_add(1); // use, and increase the generated number
string remote_addr_str = "?";
- try { remote_addr_str = socket_.remote_endpoint().address().to_string(); } catch(...){} ;
+ try { boost::system::error_code e; remote_addr_str = socket_.remote_endpoint(e).address().to_string(); } catch(...){} ;
_note("Spawned connection p2p#"<<mI->m_peer_number<<" to " << remote_addr_str << " currently we have sockets count:" << m_ref_sock_count);
//boost::filesystem::create_directories("log/dr-monero/net/");
}
-connection_basic::~connection_basic() {
+connection_basic::~connection_basic() noexcept(false) {
string remote_addr_str = "?";
m_ref_sock_count--;
- try { remote_addr_str = socket_.remote_endpoint().address().to_string(); } catch(...){} ;
+ try { boost::system::error_code e; remote_addr_str = socket_.remote_endpoint(e).address().to_string(); } catch(...){} ;
_note("Destructing connection p2p#"<<mI->m_peer_number << " to " << remote_addr_str);
}
diff --git a/src/p2p/connection_basic.hpp b/src/p2p/connection_basic.hpp
index 8be798735..5452fa6fb 100644
--- a/src/p2p/connection_basic.hpp
+++ b/src/p2p/connection_basic.hpp
@@ -103,7 +103,7 @@ class connection_basic { // not-templated base class for rapid developmet of som
// first counter is the ++/-- count of current sockets, the other socket_number is only-increasing ++ number generator
connection_basic(boost::asio::io_service& io_service, std::atomic<long> &ref_sock_count, std::atomic<long> &sock_number);
- virtual ~connection_basic();
+ virtual ~connection_basic() noexcept(false);
// various handlers to be called from connection class:
void do_send_handler_write(const void * ptr , size_t cb);
diff --git a/src/p2p/data_logger.cpp b/src/p2p/data_logger.cpp
index ca0726c5f..fe54aef63 100644
--- a/src/p2p/data_logger.cpp
+++ b/src/p2p/data_logger.cpp
@@ -103,7 +103,7 @@ namespace net_utils
_info_c("dbg/data","Data logger constructed");
}
- data_logger::~data_logger() {
+ data_logger::~data_logger() noexcept(false) {
_note_c("dbg/data","Destructor of the data logger");
{
boost::lock_guard<boost::mutex> lock(mMutex);
diff --git a/src/p2p/data_logger.hpp b/src/p2p/data_logger.hpp
index 148afc0ab..278d08bfc 100644
--- a/src/p2p/data_logger.hpp
+++ b/src/p2p/data_logger.hpp
@@ -55,7 +55,7 @@ enum class data_logger_state { state_before_init, state_during_init, state_ready
public:
static data_logger &get_instance(); ///< singleton
static void kill_instance(); ///< call this before ending main to allow more gracefull shutdown of the main singleton and it's background thread
- ~data_logger(); ///< destr, will be called when singleton is killed when global m_obj dies. will kill theads etc
+ ~data_logger() noexcept(false); ///< destr, will be called when singleton is killed when global m_obj dies. will kill theads etc
private:
data_logger(); ///< constructor is private, use only via singleton get_instance
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index 9e8d1108e..cfe1057ac 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -930,7 +930,7 @@ namespace cryptonote
{
res.tx_hashes.push_back(epee::string_tools::pod_to_hex(blk.tx_hashes[n]));
}
- res.blob = t_serializable_object_to_blob(blk);
+ res.blob = string_tools::buff_to_hex_nodelimer(t_serializable_object_to_blob(blk));
res.json = obj_to_json_str(blk);
res.status = CORE_RPC_STATUS_OK;
return true;
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index 7d28de9c0..0581d9de9 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -595,6 +595,7 @@ simple_wallet::simple_wallet()
m_cmd_binder.set_handler("rescan_bc", boost::bind(&simple_wallet::rescan_blockchain, this, _1), tr("Rescan blockchain from scratch"));
m_cmd_binder.set_handler("set_tx_note", boost::bind(&simple_wallet::set_tx_note, this, _1), tr("Set an arbitrary string note for a txid"));
m_cmd_binder.set_handler("get_tx_note", boost::bind(&simple_wallet::get_tx_note, this, _1), tr("Get a string note for a txid"));
+ m_cmd_binder.set_handler("status", boost::bind(&simple_wallet::status, this, _1), tr("Show wallet status information"));
m_cmd_binder.set_handler("help", boost::bind(&simple_wallet::help, this, _1), tr("Show this help"));
}
//----------------------------------------------------------------------------------------------------
@@ -2968,13 +2969,17 @@ static std::string get_human_readable_timestamp(uint64_t ts)
return "<unknown>";
time_t tt = ts;
struct tm tm;
+#ifdef WIN32
+ gmtime_s(&tm, &tt);
+#else
gmtime_r(&tt, &tm);
+#endif
uint64_t now = time(NULL);
uint64_t diff = ts > now ? ts - now : now - ts;
if (diff > 24*3600)
- strftime(buffer, sizeof(buffer), "%F", &tm);
+ strftime(buffer, sizeof(buffer), "%Y-%m-%d", &tm);
else
- strftime(buffer, sizeof(buffer), "%r", &tm);
+ strftime(buffer, sizeof(buffer), "%I:%M:%S %p", &tm);
return std::string(buffer);
}
//----------------------------------------------------------------------------------------------------
@@ -2994,7 +2999,7 @@ bool simple_wallet::show_transfers(const std::vector<std::string> &args_)
}
LOCK_REFRESH_THREAD_SCOPE();
-
+
// optional in/out selector
if (local_args.size() > 0) {
if (local_args[0] == "in" || local_args[0] == "incoming") {
@@ -3261,6 +3266,29 @@ bool simple_wallet::get_tx_note(const std::vector<std::string> &args)
return true;
}
//----------------------------------------------------------------------------------------------------
+bool simple_wallet::status(const std::vector<std::string> &args)
+{
+ uint64_t local_height = m_wallet->get_blockchain_current_height();
+ if (!m_wallet->check_connection())
+ {
+ success_msg_writer() << "Refreshed " << local_height << "/?, no daemon connected";
+ return true;
+ }
+
+ std::string err;
+ uint64_t bc_height = get_daemon_blockchain_height(err);
+ if (err.empty())
+ {
+ bool synced = local_height == bc_height;
+ success_msg_writer() << "Refreshed " << local_height << "/" << bc_height << ", " << (synced ? "synced" : "syncing");
+ }
+ else
+ {
+ fail_msg_writer() << "Refreshed " << local_height << "/?, daemon connection error";
+ }
+ return true;
+}
+//----------------------------------------------------------------------------------------------------
bool simple_wallet::process_command(const std::vector<std::string> &args)
{
return m_cmd_binder.process_command_vec(args);
diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h
index 0c69f0440..66f74b456 100644
--- a/src/simplewallet/simplewallet.h
+++ b/src/simplewallet/simplewallet.h
@@ -141,6 +141,7 @@ namespace cryptonote
bool refresh_main(uint64_t start_height, bool reset = false);
bool set_tx_note(const std::vector<std::string> &args);
bool get_tx_note(const std::vector<std::string> &args);
+ bool status(const std::vector<std::string> &args);
uint64_t get_daemon_blockchain_height(std::string& err);
bool try_connect_to_daemon();
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index d72ebc8da..be379cb99 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -137,6 +137,12 @@ uint64_t Wallet::amountFromDouble(double amount)
return amountFromString(ss.str());
}
+std::string Wallet::genPaymentId()
+{
+ crypto::hash8 payment_id = crypto::rand<crypto::hash8>();
+ return epee::string_tools::pod_to_hex(payment_id);
+
+}
///////////////////////// WalletImpl implementation ////////////////////////
@@ -302,6 +308,15 @@ std::string WalletImpl::address() const
return m_wallet->get_account().get_public_address_str(m_wallet->testnet());
}
+std::string WalletImpl::integratedAddress(const std::string &payment_id) const
+{
+ crypto::hash8 pid;
+ if (!tools::wallet2::parse_short_payment_id(payment_id, pid)) {
+ pid = crypto::rand<crypto::hash8>();
+ }
+ return m_wallet->get_account().get_public_integrated_address_str(pid, m_wallet->testnet());
+}
+
bool WalletImpl::store(const std::string &path)
{
clearStatus();
@@ -380,31 +395,58 @@ bool WalletImpl::refresh()
// - payment_details;
// - unconfirmed_transfer_details;
// - confirmed_transfer_details)
-PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, uint64_t amount, uint32_t mixin_count)
+
+PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, const string &payment_id, uint64_t amount, uint32_t mixin_count)
{
clearStatus();
vector<cryptonote::tx_destination_entry> dsts;
cryptonote::tx_destination_entry de;
- bool has_payment_id;
- crypto::hash8 new_payment_id;
+ // indicates if dst_addr is integrated address (address + payment_id)
+ bool has_payment_id;
+ crypto::hash8 payment_id_short;
// TODO: (https://bitcointalk.org/index.php?topic=753252.msg9985441#msg9985441)
-
size_t fake_outs_count = mixin_count > 0 ? mixin_count : m_wallet->default_mixin();
if (fake_outs_count == 0)
fake_outs_count = DEFAULT_MIXIN;
- PendingTransactionImpl * transaction = new PendingTransactionImpl(this);
+ PendingTransactionImpl * transaction = new PendingTransactionImpl(*this);
do {
-
- if(!cryptonote::get_account_integrated_address_from_str(de.addr, has_payment_id, new_payment_id, m_wallet->testnet(), dst_addr)) {
+ if(!cryptonote::get_account_integrated_address_from_str(de.addr, has_payment_id, payment_id_short, m_wallet->testnet(), dst_addr)) {
// TODO: copy-paste 'if treating as an address fails, try as url' from simplewallet.cpp:1982
m_status = Status_Error;
m_errorString = "Invalid destination address";
break;
}
+
+ std::vector<uint8_t> extra;
+ // if dst_addr is not an integrated address, parse payment_id
+ if (!has_payment_id && !payment_id.empty()) {
+ // copy-pasted from simplewallet.cpp:2212
+ crypto::hash payment_id_long;
+ bool r = tools::wallet2::parse_long_payment_id(payment_id, payment_id_long);
+ if (r) {
+ std::string extra_nonce;
+ cryptonote::set_payment_id_to_tx_extra_nonce(extra_nonce, payment_id_long);
+ r = add_extra_nonce_to_tx_extra(extra, extra_nonce);
+ } else {
+ r = tools::wallet2::parse_short_payment_id(payment_id, payment_id_short);
+ if (r) {
+ std::string extra_nonce;
+ set_encrypted_payment_id_to_tx_extra_nonce(extra_nonce, payment_id_short);
+ r = add_extra_nonce_to_tx_extra(extra, extra_nonce);
+ }
+ }
+
+ if (!r) {
+ m_status = Status_Error;
+ m_errorString = tr("payment id has invalid format, expected 16 or 64 character hex string: ") + payment_id;
+ break;
+ }
+ }
+
de.amount = amount;
if (de.amount <= 0) {
m_status = Status_Error;
@@ -414,8 +456,6 @@ PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, uint64
dsts.push_back(de);
//std::vector<tools::wallet2::pending_tx> ptx_vector;
- std::vector<uint8_t> extra;
-
try {
transaction->m_pending_tx = m_wallet->create_transactions_2(dsts, fake_outs_count, 0 /* unlock_time */,
diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h
index 016116e96..164aede1a 100644
--- a/src/wallet/api/wallet.h
+++ b/src/wallet/api/wallet.h
@@ -60,6 +60,7 @@ public:
std::string errorString() const;
bool setPassword(const std::string &password);
std::string address() const;
+ std::string integratedAddress(const std::string &payment_id) const;
bool store(const std::string &path);
std::string filename() const;
std::string keysFilename() const;
@@ -70,7 +71,8 @@ public:
uint64_t balance() const;
uint64_t unlockedBalance() const;
bool refresh();
- PendingTransaction * createTransaction(const std::string &dst_addr, uint64_t amount, uint32_t mixin_count);
+ PendingTransaction * createTransaction(const std::string &dst_addr, const std::string &payment_id,
+ uint64_t amount, uint32_t mixin_count);
virtual void disposeTransaction(PendingTransaction * t);
virtual TransactionHistory * history() const;
virtual void setListener(WalletListener * l);
diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp
index 3a97538b4..4ed6e09fb 100644
--- a/src/wallet/api/wallet_manager.cpp
+++ b/src/wallet/api/wallet_manager.cpp
@@ -85,7 +85,7 @@ bool WalletManagerImpl::walletExists(const std::string &path)
std::vector<std::string> WalletManagerImpl::findWallets(const std::string &path)
{
std::vector<std::string> result;
- const boost::regex wallet_rx("(.*)\\.(address\\.txt)$"); // searching for <wallet_name>.address.txt files
+ const boost::regex wallet_rx("(.*)\\.(keys)$"); // searching for <wallet_name>.keys files
boost::filesystem::recursive_directory_iterator end_itr; // Default ctor yields past-the-end
boost::filesystem::path work_dir(path);
@@ -100,11 +100,9 @@ std::vector<std::string> WalletManagerImpl::findWallets(const std::string &path)
bool matched = boost::regex_match(filename, what, wallet_rx);
if (matched) {
- // if address file found, checking if there's corresponding .keys file and wallet file itself
+ // if keys file found, checking if there's wallet file itself
std::string wallet_file = (itr->path().parent_path() /= what[1]).string();
- std::string wallet_key_file = wallet_file + std::string(".keys");
- if (boost::filesystem::exists(wallet_file)
- && boost::filesystem::exists(wallet_key_file)) {
+ if (boost::filesystem::exists(wallet_file)) {
LOG_PRINT_L3("Found wallet: " << wallet_file);
result.push_back(wallet_file);
}
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 6f05929b4..02dd59862 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -3081,7 +3081,6 @@ std::string wallet2::get_tx_note(const crypto::hash &txid) const
return std::string();
return i->second;
}
-
//----------------------------------------------------------------------------------------------------
void wallet2::generate_genesis(cryptonote::block& b) {
if (m_testnet)
diff --git a/src/wallet/wallet2_api.h b/src/wallet/wallet2_api.h
index de0b50591..66987e4c5 100644
--- a/src/wallet/wallet2_api.h
+++ b/src/wallet/wallet2_api.h
@@ -134,6 +134,18 @@ struct Wallet
virtual std::string errorString() const = 0;
virtual bool setPassword(const std::string &password) = 0;
virtual std::string address() const = 0;
+
+ /*!
+ * \brief integratedAddress - returns integrated address for current wallet address and given payment_id.
+ * if passed "payment_id" param is an empty string or not-valid payment id string
+ * (16 characters hexadecimal string) - random payment_id will be generated
+ *
+ * \param payment_id - 16 characters hexadecimal string or empty string if new random payment id needs to be
+ * generated
+ * \return - 106 characters string representing integrated address
+ */
+ virtual std::string integratedAddress(const std::string &payment_id) const = 0;
+
/*!
* \brief store - stores wallet to file.
* \param path - main filename to store wallet to. additionally stores address file and keys file.
@@ -162,19 +174,24 @@ struct Wallet
static std::string displayAmount(uint64_t amount);
static uint64_t amountFromString(const std::string &amount);
static uint64_t amountFromDouble(double amount);
+ static std::string genPaymentId();
// TODO?
// virtual uint64_t unlockedDustBalance() const = 0;
virtual bool refresh() = 0;
/*!
- * \brief createTransaction creates transaction
+ * \brief createTransaction creates transaction. if dst_addr is an integrated address, payment_id is ignored
* \param dst_addr destination address as string
+ * \param payment_id optional payment_id, can be empty string
* \param amount amount
* \param mixin_count mixin count. if 0 passed, wallet will use default value
* \return PendingTransaction object. caller is responsible to check PendingTransaction::status()
* after object returned
*/
- virtual PendingTransaction * createTransaction(const std::string &dst_addr, uint64_t amount, uint32_t mixin_count) = 0;
+
+ virtual PendingTransaction * createTransaction(const std::string &dst_addr, const std::string &payment_id,
+ uint64_t amount, uint32_t mixin_count) = 0;
+
virtual void disposeTransaction(PendingTransaction * t) = 0;
virtual TransactionHistory * history() const = 0;
virtual void setListener(WalletListener *) = 0;
diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index a082f731b..5be9ae5b0 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -245,9 +245,9 @@ namespace tools
m_wallet.commit_tx(ptx_vector);
// populate response with tx hash
- res.tx_hash = boost::lexical_cast<std::string>(cryptonote::get_transaction_hash(ptx_vector.back().tx));
+ res.tx_hash = epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(ptx_vector.back().tx));
if (req.get_tx_key)
- res.tx_key = boost::lexical_cast<std::string>(ptx_vector.back().tx_key);
+ res.tx_key = epee::string_tools::pod_to_hex(ptx_vector.back().tx_key);
return true;
}
catch (const tools::error::daemon_busy& e)
@@ -308,9 +308,9 @@ namespace tools
// populate response with tx hashes
for (auto & ptx : ptx_vector)
{
- res.tx_hash_list.push_back(boost::lexical_cast<std::string>(cryptonote::get_transaction_hash(ptx.tx)));
+ res.tx_hash_list.push_back(epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(ptx.tx)));
if (req.get_tx_keys)
- res.tx_key_list.push_back(boost::lexical_cast<std::string>(ptx.tx_key));
+ res.tx_key_list.push_back(epee::string_tools::pod_to_hex(ptx.tx_key));
}
return true;
@@ -354,9 +354,9 @@ namespace tools
// populate response with tx hashes
for (auto & ptx : ptx_vector)
{
- res.tx_hash_list.push_back(boost::lexical_cast<std::string>(cryptonote::get_transaction_hash(ptx.tx)));
+ res.tx_hash_list.push_back(epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(ptx.tx)));
if (req.get_tx_keys)
- res.tx_key_list.push_back(boost::lexical_cast<std::string>(ptx.tx_key));
+ res.tx_key_list.push_back(epee::string_tools::pod_to_hex(ptx.tx_key));
}
return true;
@@ -413,9 +413,9 @@ namespace tools
// populate response with tx hashes
for (auto & ptx : ptx_vector)
{
- res.tx_hash_list.push_back(boost::lexical_cast<std::string>(cryptonote::get_transaction_hash(ptx.tx)));
+ res.tx_hash_list.push_back(epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(ptx.tx)));
if (req.get_tx_keys)
- res.tx_key_list.push_back(boost::lexical_cast<std::string>(ptx.tx_key));
+ res.tx_key_list.push_back(epee::string_tools::pod_to_hex(ptx.tx_key));
}
return true;
@@ -493,7 +493,7 @@ namespace tools
return false;
}
res.standard_address = get_account_address_as_str(m_wallet.testnet(),address);
- res.payment_id = boost::lexical_cast<std::string>(payment_id);
+ res.payment_id = epee::string_tools::pod_to_hex(payment_id);
return true;
}
catch (std::exception &e)
@@ -686,7 +686,7 @@ namespace tools
rpc_transfers.amount = td.amount();
rpc_transfers.spent = td.m_spent;
rpc_transfers.global_index = td.m_global_output_index;
- rpc_transfers.tx_hash = boost::lexical_cast<std::string>(cryptonote::get_transaction_hash(td.m_tx));
+ rpc_transfers.tx_hash = epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(td.m_tx));
rpc_transfers.tx_size = txBlob.size();
res.transfers.push_back(rpc_transfers);
}
diff --git a/tests/libwallet_api_tests/main.cpp b/tests/libwallet_api_tests/main.cpp
index ddd6969c6..f6f1b0832 100644
--- a/tests/libwallet_api_tests/main.cpp
+++ b/tests/libwallet_api_tests/main.cpp
@@ -62,12 +62,6 @@ const char * WALLET_LANG = "English";
const std::string WALLETS_ROOT_DIR = "/home/mbg033/dev/monero/testnet/";
-//const char * TESTNET_WALLET1_NAME = "/home/mbg033/dev/monero/testnet/wallet_01.bin";
-//const char * TESTNET_WALLET2_NAME = "/home/mbg033/dev/monero/testnet/wallet_02.bin";
-//const char * TESTNET_WALLET3_NAME = "/home/mbg033/dev/monero/testnet/wallet_03.bin";
-//const char * TESTNET_WALLET4_NAME = "/home/mbg033/dev/monero/testnet/wallet_04.bin";
-//const char * TESTNET_WALLET5_NAME = "/home/mbg033/dev/monero/testnet/wallet_05.bin";
-
const std::string TESTNET_WALLET1_NAME = WALLETS_ROOT_DIR + "wallet_01.bin";
const std::string TESTNET_WALLET2_NAME = WALLETS_ROOT_DIR + "wallet_02.bin";
const std::string TESTNET_WALLET3_NAME = WALLETS_ROOT_DIR + "wallet_03.bin";
@@ -85,6 +79,8 @@ const uint64_t AMOUNT_10XMR = 10000000000000L;
const uint64_t AMOUNT_5XMR = 5000000000000L;
const uint64_t AMOUNT_1XMR = 1000000000000L;
+const std::string PAYMENT_ID_EMPTY = "";
+
}
@@ -360,6 +356,23 @@ TEST_F(WalletManagerTest, WalletManagerFindsWallet)
}
+TEST_F(WalletManagerTest, WalletGeneratesPaymentId)
+{
+ std::string payment_id = Bitmonero::Wallet::genPaymentId();
+ ASSERT_TRUE(payment_id.length() == 16);
+}
+
+
+TEST_F(WalletManagerTest, WalletGeneratesIntegratedAddress)
+{
+ std::string payment_id = Bitmonero::Wallet::genPaymentId();
+
+ Bitmonero::Wallet * wallet1 = wmgr->openWallet(CURRENT_SRC_WALLET, TESTNET_WALLET_PASS, true);
+ std::string integrated_address = wallet1->integratedAddress(payment_id);
+ ASSERT_TRUE(integrated_address.length() == 106);
+}
+
+
TEST_F(WalletTest1, WalletShowsBalance)
{
// TODO: temporary disabled;
@@ -439,6 +452,8 @@ TEST_F(WalletTest1, WalletTransactionWithMixin)
mixins.push_back(20); mixins.push_back(25);
+ std::string payment_id = "";
+
Bitmonero::Wallet * wallet1 = wmgr->openWallet(CURRENT_SRC_WALLET, TESTNET_WALLET_PASS, true);
@@ -452,7 +467,7 @@ TEST_F(WalletTest1, WalletTransactionWithMixin)
for (auto mixin : mixins) {
std::cerr << "Transaction mixin count: " << mixin << std::endl;
Bitmonero::PendingTransaction * transaction = wallet1->createTransaction(
- recepient_address, AMOUNT_5XMR, mixin);
+ recepient_address, payment_id, AMOUNT_5XMR, mixin);
std::cerr << "Transaction status: " << transaction->status() << std::endl;
std::cerr << "Transaction fee: " << Bitmonero::Wallet::displayAmount(transaction->fee()) << std::endl;
@@ -504,7 +519,11 @@ TEST_F(WalletTest1, WalletTransactionAndHistory)
std::string wallet4_addr = Utils::get_wallet_address(CURRENT_DST_WALLET, TESTNET_WALLET_PASS);
- Bitmonero::PendingTransaction * tx = wallet_src->createTransaction(wallet4_addr, AMOUNT_10XMR * 5, 0);
+
+ Bitmonero::PendingTransaction * tx = wallet_src->createTransaction(wallet4_addr,
+ PAYMENT_ID_EMPTY,
+ AMOUNT_10XMR * 5, 0);
+
ASSERT_TRUE(tx->status() == Bitmonero::PendingTransaction::Status_Ok);
ASSERT_TRUE(tx->commit());
history = wallet_src->history();
@@ -518,6 +537,55 @@ TEST_F(WalletTest1, WalletTransactionAndHistory)
}
}
+
+TEST_F(WalletTest1, WalletTransactionWithPaymentId)
+{
+
+ Bitmonero::Wallet * wallet_src = wmgr->openWallet(CURRENT_SRC_WALLET, TESTNET_WALLET_PASS, true);
+ // make sure testnet daemon is running
+ ASSERT_TRUE(wallet_src->init(TESTNET_DAEMON_ADDRESS, 0));
+ ASSERT_TRUE(wallet_src->refresh());
+ Bitmonero::TransactionHistory * history = wallet_src->history();
+ history->refresh();
+ ASSERT_TRUE(history->count() > 0);
+ size_t count1 = history->count();
+
+ std::cout << "**** Transactions before transfer (" << count1 << ")" << std::endl;
+ for (auto t: history->getAll()) {
+ ASSERT_TRUE(t != nullptr);
+ Utils::print_transaction(t);
+ }
+
+ std::string wallet4_addr = Utils::get_wallet_address(CURRENT_DST_WALLET, TESTNET_WALLET_PASS);
+
+ std::string payment_id = Bitmonero::Wallet::genPaymentId();
+ ASSERT_TRUE(payment_id.length() == 16);
+
+
+ Bitmonero::PendingTransaction * tx = wallet_src->createTransaction(wallet4_addr,
+ payment_id,
+ AMOUNT_1XMR, 1);
+
+ ASSERT_TRUE(tx->status() == Bitmonero::PendingTransaction::Status_Ok);
+ ASSERT_TRUE(tx->commit());
+ history = wallet_src->history();
+ history->refresh();
+ ASSERT_TRUE(count1 != history->count());
+
+ bool payment_id_in_history = false;
+
+ std::cout << "**** Transactions after transfer (" << history->count() << ")" << std::endl;
+ for (auto t: history->getAll()) {
+ ASSERT_TRUE(t != nullptr);
+ Utils::print_transaction(t);
+ if (t->paymentId() == payment_id) {
+ payment_id_in_history = true;
+ }
+ }
+
+ ASSERT_TRUE(payment_id_in_history);
+}
+
struct MyWalletListener : public Bitmonero::WalletListener
{
diff --git a/tests/unit_tests/hardfork.cpp b/tests/unit_tests/hardfork.cpp
index 6d4a100df..1d1f85945 100644
--- a/tests/unit_tests/hardfork.cpp
+++ b/tests/unit_tests/hardfork.cpp
@@ -129,7 +129,9 @@ public:
return starting_height[version];
}
virtual void set_hard_fork_version(uint64_t height, uint8_t version) {
- if (versions.size() <= height) versions.resize(height+1); versions[height] = version;
+ if (versions.size() <= height)
+ versions.resize(height+1);
+ versions[height] = version;
}
virtual uint8_t get_hard_fork_version(uint64_t height) const {
return versions[height];