aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml36
-rw-r--r--CMakeLists.txt60
-rw-r--r--README.md13
-rw-r--r--src/blockchain_db/berkeleydb/db_bdb.cpp28
-rw-r--r--src/blockchain_db/berkeleydb/db_bdb.h2
-rw-r--r--src/blockchain_db/blockchain_db.h21
-rw-r--r--src/blockchain_db/lmdb/db_lmdb.cpp76
-rw-r--r--src/blockchain_db/lmdb/db_lmdb.h2
-rw-r--r--src/blockchain_utilities/blockchain_dump.cpp4
-rw-r--r--src/common/stack_trace.cpp38
-rw-r--r--src/cryptonote_core/hardfork.cpp23
-rw-r--r--src/cryptonote_core/hardfork.h7
-rw-r--r--src/daemon/rpc_command_executor.cpp4
-rw-r--r--src/daemonizer/posix_fork.cpp14
-rw-r--r--src/rpc/core_rpc_server.cpp7
-rw-r--r--src/rpc/core_rpc_server.h6
-rw-r--r--src/rpc/core_rpc_server_commands_defs.h22
-rw-r--r--src/simplewallet/simplewallet.cpp102
-rw-r--r--src/simplewallet/simplewallet.h5
-rw-r--r--src/wallet/api/pending_transaction.cpp4
-rw-r--r--src/wallet/wallet2.cpp68
-rw-r--r--src/wallet/wallet2.h5
-rw-r--r--src/wallet/wallet_rpc_server.cpp45
-rw-r--r--src/wallet/wallet_rpc_server.h4
-rw-r--r--src/wallet/wallet_rpc_server_commands_defs.h47
-rw-r--r--src/wallet/wallet_rpc_server_error_codes.h1
-rw-r--r--tests/hash-target.cpp2
-rw-r--r--tests/unit_tests/hardfork.cpp32
28 files changed, 414 insertions, 264 deletions
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 000000000..ba4df1cc9
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,36 @@
+sudo: required
+dist: trusty
+language: cpp
+compiler:
+- gcc
+addons:
+ apt:
+ packages:
+ - build-essential
+ - cmake
+ - doxygen
+ - g++
+ - gcc
+ - graphviz
+ - libboost1.55-all-dev
+ - libdb++-dev
+ - libdb-dev
+ - libgtest-dev
+ - libminiupnpc-dev
+ - libssl-dev
+ - libssl1.0.0
+ - libunbound-dev
+ - libunwind8-dev
+ #sources:
+ #- ubuntu-toolchain-r-test
+script: make -j2 && HAVE_DOT=YES doxygen Doxyfile
+notifications:
+ email: false
+ irc:
+ on_success: change
+ on_failure: change
+ channels:
+ - "chat.freenode.net#monero-dev"
+ nick: monero
+ template:
+ - "%{result} | %{repository}#%{build_number} (%{commit} : %{author}) | Build details : %{build_url}"
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6b9c81895..70c0c89f7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -294,7 +294,7 @@ 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")
+ # set(COMMON_C_FLAGS "${COMMON_C_FLAGS} /Dinline=__inline")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:10485760")
if(STATIC)
foreach(VAR CMAKE_C_FLAGS_DEBUG CMAKE_CXX_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELEASE)
@@ -314,15 +314,15 @@ else()
set(ARCH_FLAG "-march=${ARCH}")
endif()
endif()
- set(WARNINGS "-Wall -Wextra -Wpointer-arith -Wundef -Wvla -Wwrite-strings -Wno-error=extra -Wno-error=deprecated-declarations -Wno-error=sign-compare -Wno-error=strict-aliasing -Wno-error=type-limits -Wno-unused-parameter -Wno-error=unused-variable -Wno-error=undef -Wno-error=uninitialized")
- if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
- set(WARNINGS "${WARNINGS} -Wno-deprecated-register")
- endif()
+ set(WARNINGS "-Wall -Wextra -Wpointer-arith -Wundef -Wvla -Wwrite-strings -Wno-error=extra -Wno-error=deprecated-declarations -Wno-unused-parameter -Wno-error=unused-variable -Wno-error=undef -Wno-error=uninitialized")
if(NOT MINGW)
- set(WARNINGS "${WARNINGS} -Werror") # to allow pedantic but not stop compilation
+ set(WARNINGS_AS_ERRORS_FLAG "-Werror")
endif()
if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
- set(WARNINGS "${WARNINGS} -Wno-error=mismatched-tags -Wno-error=null-conversion -Wno-overloaded-shift-op-parentheses -Wno-error=shift-count-overflow -Wno-error=tautological-constant-out-of-range-compare -Wno-error=unused-private-field -Wno-error=unneeded-internal-declaration")
+ set(WARNINGS "${WARNINGS} -Wno-deprecated-register -Wno-error=mismatched-tags -Wno-error=null-conversion -Wno-overloaded-shift-op-parentheses -Wno-error=shift-count-overflow -Wno-error=tautological-constant-out-of-range-compare -Wno-error=unused-private-field -Wno-error=unneeded-internal-declaration")
+ if(ARM6 OR ARM7)
+ set(WARNINGS "${WARNINGS} -Wno-error=inline-asm")
+ endif()
else()
set(WARNINGS "${WARNINGS} -Wlogical-op -Wno-error=maybe-uninitialized")
endif()
@@ -347,15 +347,20 @@ else()
set(STATIC_ASSERT_FLAG "-Dstatic_assert=_Static_assert")
endif()
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -D_GNU_SOURCE ${MINGW_FLAG} ${STATIC_ASSERT_FLAG} ${WARNINGS} ${C_WARNINGS} ${ARCH_FLAG}")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -D_GNU_SOURCE ${MINGW_FLAG} ${WARNINGS} ${CXX_WARNINGS} ${ARCH_FLAG}")
+ set(COMMON_C_FLAGS "${COMMON_C_FLAGS} -std=c11 -D_GNU_SOURCE ${MINGW_FLAG} ${STATIC_ASSERT_FLAG} ${WARNINGS} ${C_WARNINGS} ${ARCH_FLAG}")
+ set(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} -std=c++11 -D_GNU_SOURCE ${MINGW_FLAG} ${WARNINGS} ${CXX_WARNINGS} ${ARCH_FLAG}")
+
+ # 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.
+ set(COMMON_C_FLAGS "${COMMON_C_FLAGS} -fno-strict-aliasing")
+ set(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} -fno-strict-aliasing")
option(NO_AES "Explicitly disable AES support" ${NO_AES})
if(NOT NO_AES AND NOT (ARM6 OR ARM7))
message(STATUS "AES support enabled")
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes")
+ set(COMMON_C_FLAGS "${COMMON_C_FLAGS} -maes")
+ set(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} -maes")
elseif(ARM7 OR ARM6)
message(STATUS "AES support disabled (not available on ARM)")
else()
@@ -364,18 +369,18 @@ else()
if(ARM6)
message(STATUS "Setting ARM6 C and C++ flags")
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=vfp -mfloat-abi=hard")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfpu=vfp -mfloat-abi=hard")
+ set(COMMON_C_FLAGS "${COMMON_C_FLAGS} -mfpu=vfp -mfloat-abi=hard")
+ set(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} -mfpu=vfp -mfloat-abi=hard")
endif()
if(ARM7)
message(STATUS "Setting ARM7 C and C++ flags")
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2 -mfloat-abi=hard")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -mfloat-abi=hard")
+ set(COMMON_C_FLAGS "${COMMON_C_FLAGS} -O2 -mfloat-abi=hard")
+ set(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} -O2 -mfloat-abi=hard")
endif()
if(APPLE)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGTEST_HAS_TR1_TUPLE=0")
+ set(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} -DGTEST_HAS_TR1_TUPLE=0")
endif()
if(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND NOT (CMAKE_C_COMPILER_VERSION VERSION_LESS 4.8))
set(DEBUG_FLAGS "-g3 -Og")
@@ -392,8 +397,10 @@ else()
# There is a clang bug that does not allow to compile code that uses AES-NI intrinsics if -flto is enabled, so explicitly disable
set(USE_LTO false)
# explicitly define stdlib for older versions of clang
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
- set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++")
+ if(CMAKE_C_COMPILER_VERSION VERSION_LESS 3.7)
+ set(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} -stdlib=libc++")
+ set(COMMON_EXE_LINKER_FLAGS "${COMMON_EXE_LINKER_FLAGS} -stdlib=libc++")
+ endif()
endif()
@@ -453,13 +460,21 @@ 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})
+list(APPEND EXTRA_LIBRARIES ${CMAKE_DL_LIBS})
+
+if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
+ if(NOT MINGW AND NOT APPLE)
+ find_library(ATOMIC atomic)
+ list(APPEND EXTRA_LIBRARIES ${ATOMIC})
+ endif()
endif()
include(version.cmake)
+# When building the following sources, treat warnings as errors
+set(CMAKE_C_FLAGS "${COMMON_C_FLAGS} ${WARNINGS_AS_ERRORS_FLAG}")
+set(CMAKE_CXX_FLAGS "${COMMON_CXX_FLAGS} ${WARNINGS_AS_ERRORS_FLAG}")
+
add_subdirectory(contrib)
add_subdirectory(src)
@@ -467,6 +482,9 @@ add_subdirectory(src)
option(BUILD_TESTS "Build tests." OFF)
if(BUILD_TESTS)
+ # When building tests, do *not* treat warnings as errors
+ set(CMAKE_C_FLAGS "${COMMON_C_FLAGS}")
+ set(CMAKE_CXX_FLAGS "${COMMON_CXX_FLAGS}")
add_subdirectory(tests)
endif()
diff --git a/README.md b/README.md
index 2278d80ae..14652d0eb 100644
--- a/README.md
+++ b/README.md
@@ -2,14 +2,15 @@
Copyright (c) 2014-2016, The Monero Project
+[![Build Status](https://travis-ci.org/monero-project/bitmonero.svg?branch=master)](https://travis-ci.org/monero-project/bitmonero)
+
## Development Resources
-Web: [getmonero.org](https://getmonero.org)
-Forum: [forum.getmonero.org](https://forum.getmonero.org)
-Mail: [dev@getmonero.org](mailto:dev@getmonero.org)
-Github (staging): [https://github.com/monero-project/bitmonero](https://github.com/monero-project/bitmonero)
-Github (development): [http://github.com/monero-project/bitmonero/tree/development](http://github.com/monero-project/bitmonero/tree/development)
-IRC: [#monero-dev on Freenode](irc://chat.freenode.net/#monero-dev)
+- Web: [getmonero.org](https://getmonero.org)
+- Forum: [forum.getmonero.org](https://forum.getmonero.org)
+- Mail: [dev@getmonero.org](mailto:dev@getmonero.org)
+- GitHub: [https://github.com/monero-project/bitmonero](https://github.com/monero-project/bitmonero)
+- IRC: [#monero-dev on Freenode](irc://chat.freenode.net/#monero-dev)
## Introduction
diff --git a/src/blockchain_db/berkeleydb/db_bdb.cpp b/src/blockchain_db/berkeleydb/db_bdb.cpp
index b11570e37..4d759d157 100644
--- a/src/blockchain_db/berkeleydb/db_bdb.cpp
+++ b/src/blockchain_db/berkeleydb/db_bdb.cpp
@@ -2186,34 +2186,6 @@ std::map<uint64_t, uint64_t>::BlockchainBDB::get_output_histogram(const std::vec
throw1(DB_ERROR("Not implemented."));
}
-void BlockchainBDB::set_hard_fork_starting_height(uint8_t version, uint64_t height)
-{
- LOG_PRINT_L3("BlockchainBDB::" << __func__);
- check_open();
-
- Dbt_copy<uint32_t> val_key(version + 1);
- Dbt_copy<uint64_t> val(height);
- if (m_hf_starting_heights->put(DB_DEFAULT_TX, &val_key, &val, 0))
- throw1(DB_ERROR("Error adding hard fork starting height to db transaction."));
-}
-
-uint64_t BlockchainBDB::get_hard_fork_starting_height(uint8_t version) const
-{
- LOG_PRINT_L3("BlockchainBDB::" << __func__);
- check_open();
-
- Dbt_copy<uint32_t> key(version + 1);
- Dbt_copy<uint64_t> result;
-
- auto get_result = m_hf_starting_heights->get(DB_DEFAULT_TX, &key, &result, 0);
- if (get_result == DB_NOTFOUND || get_result == DB_KEYEMPTY)
- return std::numeric_limits<uint64_t>::max();
- else if (get_result)
- throw0(DB_ERROR("Error attempting to retrieve hard fork starting height from the db"));
-
- return result;
-}
-
void BlockchainBDB::check_hard_fork_info()
{
LOG_PRINT_L3("BlockchainBDB::" << __func__);
diff --git a/src/blockchain_db/berkeleydb/db_bdb.h b/src/blockchain_db/berkeleydb/db_bdb.h
index 5c6bda4eb..6bc26ed3d 100644
--- a/src/blockchain_db/berkeleydb/db_bdb.h
+++ b/src/blockchain_db/berkeleydb/db_bdb.h
@@ -385,8 +385,6 @@ private:
virtual bool for_all_outputs(std::function<bool(uint64_t amount, const crypto::hash &tx_hash, size_t tx_idx)> f) const;
// Hard fork related storage
- virtual void set_hard_fork_starting_height(uint8_t version, uint64_t height);
- virtual uint64_t get_hard_fork_starting_height(uint8_t version) const;
virtual void set_hard_fork_version(uint64_t height, uint8_t version);
virtual uint8_t get_hard_fork_version(uint64_t height) const;
virtual void check_hard_fork_info();
diff --git a/src/blockchain_db/blockchain_db.h b/src/blockchain_db/blockchain_db.h
index 1445dd13c..ab5d2d44c 100644
--- a/src/blockchain_db/blockchain_db.h
+++ b/src/blockchain_db/blockchain_db.h
@@ -1274,27 +1274,6 @@ public:
// Hard fork related storage
//
- // FIXME: verify that this is all correct
- // - TW
- /**
- * @brief sets the height at which a hard fork has been voted to happen
- *
- *
- * @param version the version voted to fork to
- * @param height the height of the first block on the new fork
- */
- virtual void set_hard_fork_starting_height(uint8_t version, uint64_t height) = 0;
-
- /**
- * @brief gets the height at which a hard fork has been voted to happen
- *
- * @param version the version to check
- *
- * @return the height at which the hard fork was accepted, if it has been,
- * otherwise max(uint64_t)
- */
- virtual uint64_t get_hard_fork_starting_height(uint8_t version) const = 0;
-
/**
* @brief sets which hardfork version a height is on
*
diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp
index 8c51c09b1..9824d7376 100644
--- a/src/blockchain_db/lmdb/db_lmdb.cpp
+++ b/src/blockchain_db/lmdb/db_lmdb.cpp
@@ -117,13 +117,6 @@ int compare_uint64(const MDB_val *a, const MDB_val *b)
return (va < vb) ? -1 : va > vb;
}
-int compare_uint8(const MDB_val *a, const MDB_val *b)
-{
- const uint8_t va = *(const uint8_t*)a->mv_data;
- const uint8_t vb = *(const uint8_t*)b->mv_data;
- return va - vb;
-};
-
int compare_hash32(const MDB_val *a, const MDB_val *b)
{
uint32_t *va = (uint32_t*) a->mv_data;
@@ -1103,9 +1096,10 @@ void BlockchainLMDB::open(const std::string& filename, const int mdb_flags)
mdb_set_dupsort(txn, m_output_txs, compare_uint64);
mdb_set_dupsort(txn, m_block_info, compare_uint64);
- mdb_set_compare(txn, m_hf_starting_heights, compare_uint8);
mdb_set_compare(txn, m_properties, compare_string);
+ mdb_drop(txn, m_hf_starting_heights, 1);
+
// get and keep current height
MDB_stat db_stats;
if ((result = mdb_stat(txn, m_blocks, &db_stats)))
@@ -2638,29 +2632,6 @@ std::map<uint64_t, uint64_t> BlockchainLMDB::get_output_histogram(const std::vec
void BlockchainLMDB::check_hard_fork_info()
{
- LOG_PRINT_L3("BlockchainLMDB::" << __func__);
- check_open();
-
- TXN_PREFIX(0);
-
- MDB_stat db_stat1, db_stat2;
- if (mdb_stat(*txn_ptr, m_blocks, &db_stat1))
- throw0(DB_ERROR("Failed to query m_blocks"));
- if (mdb_stat(*txn_ptr, m_hf_versions, &db_stat2))
- throw0(DB_ERROR("Failed to query m_hf_starting_heights"));
- if (db_stat1.ms_entries != db_stat2.ms_entries)
- {
- // Empty, but don't delete. This allows this function to be called after
- // startup, after the subdbs have already been created, and rest of startup
- // can proceed. If these don't exist, hard fork's init() will fail.
- //
- // If these are empty, hard fork's init() will repopulate the hard fork
- // data.
- mdb_drop(*txn_ptr, m_hf_starting_heights, 0);
- mdb_drop(*txn_ptr, m_hf_versions, 0);
- }
-
- TXN_POSTFIX_SUCCESS();
}
void BlockchainLMDB::drop_hard_fork_info()
@@ -2676,49 +2647,6 @@ void BlockchainLMDB::drop_hard_fork_info()
TXN_POSTFIX_SUCCESS();
}
-void BlockchainLMDB::set_hard_fork_starting_height(uint8_t version, uint64_t height)
-{
- LOG_PRINT_L3("BlockchainLMDB::" << __func__);
- check_open();
-
- TXN_BLOCK_PREFIX(0);
-
- MDB_val_copy<uint8_t> val_key(version);
- MDB_val_copy<uint64_t> val_value(height);
- if (auto result = mdb_put(*txn_ptr, m_hf_starting_heights, &val_key, &val_value, MDB_APPEND))
- throw1(DB_ERROR(lmdb_error("Error adding hard fork starting height to db transaction: ", result).c_str()));
-
- TXN_BLOCK_POSTFIX_SUCCESS();
-}
-
-uint64_t BlockchainLMDB::get_hard_fork_starting_height(uint8_t version) const
-{
- LOG_PRINT_L3("BlockchainLMDB::" << __func__);
- check_open();
-
- TXN_PREFIX_RDONLY();
-
- MDB_val_copy<uint8_t> val_key(version);
- MDB_val val_ret;
- uint64_t ret = 0;
- auto result = mdb_get(m_txn, m_hf_starting_heights, &val_key, &val_ret);
- if (result == MDB_SUCCESS)
- {
-#ifdef MISALIGNED_OK
- ret = *(const uint64_t*)val_ret.mv_data;
-#else
- memcpy(&ret, val_ret.mv_data, sizeof(uint64_t));
-#endif
- } else if (result == MDB_NOTFOUND)
- {
- ret = std::numeric_limits<uint64_t>::max();
- } else if (result)
- throw0(DB_ERROR(lmdb_error("Error attempting to retrieve a hard fork starting height from the db", result).c_str()));
-
- TXN_POSTFIX_RDONLY();
- return ret;
-}
-
void BlockchainLMDB::set_hard_fork_version(uint64_t height, uint8_t version)
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
diff --git a/src/blockchain_db/lmdb/db_lmdb.h b/src/blockchain_db/lmdb/db_lmdb.h
index c7121bf63..d7a78617e 100644
--- a/src/blockchain_db/lmdb/db_lmdb.h
+++ b/src/blockchain_db/lmdb/db_lmdb.h
@@ -307,8 +307,6 @@ private:
virtual void remove_spent_key(const crypto::key_image& k_image);
// Hard fork
- virtual void set_hard_fork_starting_height(uint8_t version, uint64_t height);
- virtual uint64_t get_hard_fork_starting_height(uint8_t version) const;
virtual void set_hard_fork_version(uint64_t height, uint8_t version);
virtual uint8_t get_hard_fork_version(uint64_t height) const;
virtual void check_hard_fork_info();
diff --git a/src/blockchain_utilities/blockchain_dump.cpp b/src/blockchain_utilities/blockchain_dump.cpp
index 6fa5ce801..23619eaeb 100644
--- a/src/blockchain_utilities/blockchain_dump.cpp
+++ b/src/blockchain_utilities/blockchain_dump.cpp
@@ -419,10 +419,6 @@ int main(int argc, char* argv[])
for (uint64_t h = 0; h < height; ++h)
write_pod(d, boost::lexical_cast<std::string>(h), (unsigned int)db->get_hard_fork_version(h));
end_compound(d);
- start_struct(d, "hf_starting_heights", true);
- for (unsigned int v = 0; v <= 255; ++v)
- write_pod(d, boost::lexical_cast<std::string>(v), db->get_hard_fork_starting_height(v));
- end_compound(d);
}
#endif
end_compound(d);
diff --git a/src/common/stack_trace.cpp b/src/common/stack_trace.cpp
index 0d2ccb39d..44002e2d5 100644
--- a/src/common/stack_trace.cpp
+++ b/src/common/stack_trace.cpp
@@ -38,14 +38,33 @@
#endif
// from http://stackoverflow.com/questions/11665829/how-can-i-print-stack-trace-for-caught-exceptions-in-c-code-injection-in-c
+
+// The decl of __cxa_throw in /usr/include/.../cxxabi.h uses
+// 'std::type_info *', but GCC's built-in protype uses 'void *'.
+#ifdef __clang__
+#define CXA_THROW_INFO_T std::type_info
+#else // !__clang__
+#define CXA_THROW_INFO_T void
+#endif // !__clang__
+
#ifdef STATICLIB
#define CXA_THROW __wrap___cxa_throw
-extern "C" void __real___cxa_throw(void *ex, void *info, void (*dest)(void*));
-#else
+extern "C"
+__attribute__((noreturn))
+void __real___cxa_throw(void *ex, CXA_THROW_INFO_T *info, void (*dest)(void*));
+#else // !STATICLIB
#define CXA_THROW __cxa_throw
-#endif
+extern "C"
+typedef
+#ifdef __clang__ // only clang, not GCC, lets apply the attr in typedef
+__attribute__((noreturn))
+#endif // __clang__
+void (cxa_throw_t)(void *ex, CXA_THROW_INFO_T *info, void (*dest)(void*));
+#endif // !STATICLIB
-extern "C" void CXA_THROW(void *ex, void *info, void (*dest)(void*))
+extern "C"
+__attribute__((noreturn))
+void CXA_THROW(void *ex, CXA_THROW_INFO_T *info, void (*dest)(void*))
{
int status;
@@ -53,12 +72,13 @@ extern "C" void CXA_THROW(void *ex, void *info, void (*dest)(void*))
tools::log_stack_trace((std::string("Exception: ")+((!status && dsym) ? dsym : (const char*)info)).c_str());
free(dsym);
-#ifdef STATICLIB
+#ifndef STATICLIB
+#ifndef __clang__ // for GCC the attr can't be applied in typedef like for clang
+ __attribute__((noreturn))
+#endif // !__clang__
+ cxa_throw_t *__real___cxa_throw = (cxa_throw_t*)dlsym(RTLD_NEXT, "__cxa_throw");
+#endif // !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
diff --git a/src/cryptonote_core/hardfork.cpp b/src/cryptonote_core/hardfork.cpp
index 7e2e82c4a..d3262dbe3 100644
--- a/src/cryptonote_core/hardfork.cpp
+++ b/src/cryptonote_core/hardfork.cpp
@@ -137,10 +137,6 @@ bool HardFork::add(uint8_t block_version, uint8_t voting_version, uint64_t heigh
uint8_t voted = get_voted_fork_index(height + 1);
if (voted > current_fork_index) {
- for (int v = heights[current_fork_index].version + 1; v <= heights[voted].version; ++v) {
- // we reached the vote threshold with this block, next one will be forked
- db.set_hard_fork_starting_height(v, height + 1);
- }
current_fork_index = voted;
}
@@ -172,7 +168,12 @@ void HardFork::init()
else
height = 1;
- bool populate = db.get_hard_fork_starting_height(original_version) == std::numeric_limits<uint64_t>::max();
+ bool populate = false;
+ try
+ {
+ db.get_hard_fork_version(0);
+ }
+ catch (...) { populate = true; }
if (populate) {
LOG_PRINT_L0("The DB has no hard fork info, reparsing from start");
height = 1;
@@ -182,7 +183,6 @@ void HardFork::init()
reorganize_from_chain_height(height);
// reorg will not touch the genesis block, use this as a flag for populating done
db.set_hard_fork_version(0, original_version);
- db.set_hard_fork_starting_height(original_version, 0);
}
else {
rescan_from_chain_height(height);
@@ -215,7 +215,6 @@ bool HardFork::reorganize_from_block_height(uint64_t height)
const uint64_t rescan_height = height >= (window_size - 1) ? height - (window_size -1) : 0;
const uint8_t start_version = height == 0 ? original_version : db.get_hard_fork_version(height);
while (current_fork_index > 0 && heights[current_fork_index].version > start_version) {
- db.set_hard_fork_starting_height(heights[current_fork_index].version, std::numeric_limits<uint64_t>::max());
--current_fork_index;
}
for (uint64_t h = rescan_height; h <= height; ++h) {
@@ -227,10 +226,6 @@ bool HardFork::reorganize_from_block_height(uint64_t height)
uint8_t voted = get_voted_fork_index(height + 1);
if (voted > current_fork_index) {
- for (int v = heights[current_fork_index].version + 1; v <= heights[voted].version; ++v) {
- // we reached the vote threshold with this block, next one will be forked
- db.set_hard_fork_starting_height(v, height + 1);
- }
current_fork_index = voted;
}
@@ -337,12 +332,6 @@ uint8_t HardFork::get(uint64_t height) const
return db.get_hard_fork_version(height);
}
-uint64_t HardFork::get_start_height(uint8_t version) const
-{
- CRITICAL_REGION_LOCAL(lock);
- return db.get_hard_fork_starting_height(version);
-}
-
uint8_t HardFork::get_current_version() const
{
CRITICAL_REGION_LOCAL(lock);
diff --git a/src/cryptonote_core/hardfork.h b/src/cryptonote_core/hardfork.h
index d9ef04113..b3d485878 100644
--- a/src/cryptonote_core/hardfork.h
+++ b/src/cryptonote_core/hardfork.h
@@ -155,13 +155,6 @@ namespace cryptonote
uint8_t get(uint64_t height) const;
/**
- * @brief returns the height of the first block on the fork with th given version
- *
- * @param version version of the fork to query the starting block for
- */
- uint64_t get_start_height(uint8_t version) const;
-
- /**
* @brief returns the latest "ideal" version
*
* This is the latest version that's been scheduled
diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp
index ae9492111..0a0fc793d 100644
--- a/src/daemon/rpc_command_executor.cpp
+++ b/src/daemon/rpc_command_executor.cpp
@@ -1123,11 +1123,9 @@ bool t_rpc_command_executor::print_bans()
}
}
- time_t now = time(nullptr);
for (auto i = res.bans.begin(); i != res.bans.end(); ++i)
{
- time_t seconds = i->seconds - now;
- tools::msg_writer() << epee::string_tools::get_ip_string_from_int32(i->ip) << " banned for " << seconds << " seconds";
+ tools::msg_writer() << epee::string_tools::get_ip_string_from_int32(i->ip) << " banned for " << i->seconds << " seconds";
}
return true;
diff --git a/src/daemonizer/posix_fork.cpp b/src/daemonizer/posix_fork.cpp
index c068912ec..949c0f593 100644
--- a/src/daemonizer/posix_fork.cpp
+++ b/src/daemonizer/posix_fork.cpp
@@ -50,20 +50,6 @@ void fork()
// terminal.
setsid();
- // A process inherits its working directory from its parent. This could be
- // on a mounted filesystem, which means that the running daemon would
- // prevent this filesystem from being unmounted. Changing to the root
- // directory avoids this problem.
- if (chdir("/") < 0)
- {
- quit("Unable to change working directory to root");
- }
-
- // The file mode creation mask is also inherited from the parent process.
- // We don't want to restrict the permissions on files created by the
- // daemon, so the mask is cleared.
- umask(0);
-
// A second fork ensures the process cannot acquire a controlling terminal.
if (pid_t pid = ::fork())
{
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index ca18e7e09..35200c5f9 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -1146,6 +1146,13 @@ namespace cryptonote
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
+ bool core_rpc_server::on_get_version(const COMMAND_RPC_GET_VERSION::request& req, COMMAND_RPC_GET_VERSION::response& res, epee::json_rpc::error& error_resp)
+ {
+ res.version = CORE_RPC_VERSION;
+ res.status = CORE_RPC_STATUS_OK;
+ return true;
+ }
+ //------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::on_fast_exit(const COMMAND_RPC_FAST_EXIT::request& req, COMMAND_RPC_FAST_EXIT::response& res)
{
cryptonote::core::set_fast_exit();
diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h
index a7a54b59f..3d50c77be 100644
--- a/src/rpc/core_rpc_server.h
+++ b/src/rpc/core_rpc_server.h
@@ -107,10 +107,11 @@ namespace cryptonote
MAP_JON_RPC_WE_IF("get_connections", on_get_connections, COMMAND_RPC_GET_CONNECTIONS, !m_restricted)
MAP_JON_RPC_WE("get_info", on_get_info_json, COMMAND_RPC_GET_INFO)
MAP_JON_RPC_WE("hard_fork_info", on_hard_fork_info, COMMAND_RPC_HARD_FORK_INFO)
- MAP_JON_RPC_WE_IF("setbans", on_set_bans, COMMAND_RPC_SETBANS, !m_restricted)
- MAP_JON_RPC_WE_IF("getbans", on_get_bans, COMMAND_RPC_GETBANS, !m_restricted)
+ MAP_JON_RPC_WE_IF("set_bans", on_set_bans, COMMAND_RPC_SETBANS, !m_restricted)
+ MAP_JON_RPC_WE_IF("get_bans", on_get_bans, COMMAND_RPC_GETBANS, !m_restricted)
MAP_JON_RPC_WE_IF("flush_txpool", on_flush_txpool, COMMAND_RPC_FLUSH_TRANSACTION_POOL, !m_restricted)
MAP_JON_RPC_WE("get_output_histogram", on_get_output_histogram, COMMAND_RPC_GET_OUTPUT_HISTOGRAM)
+ MAP_JON_RPC_WE("get_version", on_get_version, COMMAND_RPC_GET_VERSION)
END_JSON_RPC_MAP()
END_URI_MAP2()
@@ -153,6 +154,7 @@ namespace cryptonote
bool on_get_bans(const COMMAND_RPC_GETBANS::request& req, COMMAND_RPC_GETBANS::response& res, epee::json_rpc::error& error_resp);
bool on_flush_txpool(const COMMAND_RPC_FLUSH_TRANSACTION_POOL::request& req, COMMAND_RPC_FLUSH_TRANSACTION_POOL::response& res, epee::json_rpc::error& error_resp);
bool on_get_output_histogram(const COMMAND_RPC_GET_OUTPUT_HISTOGRAM::request& req, COMMAND_RPC_GET_OUTPUT_HISTOGRAM::response& res, epee::json_rpc::error& error_resp);
+ bool on_get_version(const COMMAND_RPC_GET_VERSION::request& req, COMMAND_RPC_GET_VERSION::response& res, epee::json_rpc::error& error_resp);
//-----------------------
private:
diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h
index 392c7501f..63167e249 100644
--- a/src/rpc/core_rpc_server_commands_defs.h
+++ b/src/rpc/core_rpc_server_commands_defs.h
@@ -41,6 +41,8 @@ namespace cryptonote
#define CORE_RPC_STATUS_BUSY "BUSY"
#define CORE_RPC_STATUS_NOT_MINING "NOT MINING"
+#define CORE_RPC_VERSION 1
+
struct COMMAND_RPC_GET_HEIGHT
{
struct request
@@ -1102,5 +1104,25 @@ namespace cryptonote
END_KV_SERIALIZE_MAP()
};
};
+
+ struct COMMAND_RPC_GET_VERSION
+ {
+ struct request
+ {
+ BEGIN_KV_SERIALIZE_MAP()
+ END_KV_SERIALIZE_MAP()
+ };
+
+ struct response
+ {
+ std::string status;
+ uint32_t version;
+
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE(status)
+ KV_SERIALIZE(version)
+ END_KV_SERIALIZE_MAP()
+ };
+ };
}
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index 4a7a70b8c..d75f72464 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -115,6 +115,7 @@ namespace
const command_line::arg_descriptor<bool> arg_testnet = {"testnet", sw::tr("For testnet. Daemon must also be launched with --testnet flag"), false};
const command_line::arg_descriptor<bool> arg_restricted = {"restricted-rpc", sw::tr("Restricts RPC to view-only commands"), 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};
const command_line::arg_descriptor<uint64_t> arg_restore_height = {"restore-height", sw::tr("Restore from specific blockchain height"), 0};
const command_line::arg_descriptor< std::vector<std::string> > arg_command = {"command", ""};
@@ -623,7 +624,8 @@ bool simple_wallet::help(const std::vector<std::string> &args/* = std::vector<st
}
simple_wallet::simple_wallet()
- : m_daemon_port(0)
+ : m_allow_mismatched_daemon_version(false)
+ , m_daemon_port(0)
, m_refresh_progress_reporter(*this)
, m_auto_refresh_run(false)
, m_auto_refresh_refreshing(false)
@@ -658,6 +660,8 @@ simple_wallet::simple_wallet()
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("sign", boost::bind(&simple_wallet::sign, this, _1), tr("Sign the contents of a file"));
+ m_cmd_binder.set_handler("verify", boost::bind(&simple_wallet::verify, this, _1), tr("Verify a signature on the contents of a file"));
m_cmd_binder.set_handler("help", boost::bind(&simple_wallet::help, this, _1), tr("Show this help"));
}
//----------------------------------------------------------------------------------------------------
@@ -1439,18 +1443,28 @@ bool simple_wallet::handle_command_line(const boost::program_options::variables_
m_restore_deterministic_wallet = command_line::get_arg(vm, arg_restore_deterministic_wallet);
m_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);
m_restore_height = command_line::get_arg(vm, arg_restore_height);
return true;
}
//----------------------------------------------------------------------------------------------------
-bool simple_wallet::try_connect_to_daemon()
+bool simple_wallet::try_connect_to_daemon(bool silent)
{
- if (!m_wallet->check_connection())
+ bool same_version = false;
+ if (!m_wallet->check_connection(&same_version))
{
- fail_msg_writer() << tr("wallet failed to connect to daemon: ") << m_daemon_address << ". " <<
- tr("Daemon either is not started or wrong port was passed. "
- "Please make sure daemon is running or restart the wallet with the correct daemon address.");
+ if (!silent)
+ fail_msg_writer() << tr("wallet failed to connect to daemon: ") << m_daemon_address << ". " <<
+ tr("Daemon either is not started or wrong port was passed. "
+ "Please make sure daemon is running or restart the wallet with the correct daemon address.");
+ return false;
+ }
+ if (!m_allow_mismatched_daemon_version && !same_version)
+ {
+ if (!silent)
+ fail_msg_writer() << tr("Daemon uses a different RPC version that the wallet: ") << m_daemon_address << ". " <<
+ tr("Either update one of them, or use --allow-mismatched-daemon-version.");
return false;
}
return true;
@@ -3207,7 +3221,8 @@ void simple_wallet::wallet_refresh_thread()
try
{
uint64_t fetched_blocks;
- m_wallet->refresh(0, fetched_blocks);
+ if (try_connect_to_daemon(true))
+ m_wallet->refresh(0, fetched_blocks);
}
catch(...) {}
m_auto_refresh_refreshing = false;
@@ -3219,6 +3234,11 @@ void simple_wallet::wallet_refresh_thread()
//----------------------------------------------------------------------------------------------------
bool simple_wallet::run()
{
+ // check and display warning, but go on anyway
+ try_connect_to_daemon();
+
+ refresh_main(0, false);
+
std::string addr_start = m_wallet->get_account().get_public_address_str(m_wallet->testnet()).substr(0, 6);
m_auto_refresh_run = m_wallet->auto_refresh();
if (m_auto_refresh_run)
@@ -3348,7 +3368,7 @@ bool simple_wallet::get_tx_note(const std::vector<std::string> &args)
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())
+ if (!try_connect_to_daemon())
{
success_msg_writer() << "Refreshed " << local_height << "/?, no daemon connected";
return true;
@@ -3368,6 +3388,71 @@ bool simple_wallet::status(const std::vector<std::string> &args)
return true;
}
//----------------------------------------------------------------------------------------------------
+bool simple_wallet::sign(const std::vector<std::string> &args)
+{
+ if (args.size() != 1)
+ {
+ fail_msg_writer() << tr("usage: sign <filename>");
+ return true;
+ }
+ if (m_wallet->watch_only())
+ {
+ fail_msg_writer() << tr("wallet is watch-only and cannot sign");
+ return true;
+ }
+ std::string filename = args[0];
+ std::string data;
+ bool r = epee::file_io_utils::load_file_to_string(filename, data);
+ if (!r)
+ {
+ fail_msg_writer() << tr("failed to read file ") << filename;
+ return true;
+ }
+ std::string signature = m_wallet->sign(data);
+ success_msg_writer() << signature;
+ return true;
+}
+//----------------------------------------------------------------------------------------------------
+bool simple_wallet::verify(const std::vector<std::string> &args)
+{
+ if (args.size() != 3)
+ {
+ fail_msg_writer() << tr("usage: verify <filename> <address> <signature>");
+ return true;
+ }
+ std::string filename = args[0];
+ std::string address_string = args[1];
+ std::string signature= args[2];
+
+ std::string data;
+ bool r = epee::file_io_utils::load_file_to_string(filename, data);
+ if (!r)
+ {
+ fail_msg_writer() << tr("failed to read file ") << filename;
+ return true;
+ }
+
+ cryptonote::account_public_address address;
+ bool has_payment_id;
+ crypto::hash8 payment_id;
+ if(!get_account_integrated_address_from_str(address, has_payment_id, payment_id, m_wallet->testnet(), address_string))
+ {
+ fail_msg_writer() << tr("failed to parse address");
+ return true;
+ }
+
+ r = m_wallet->verify(data, address, signature);
+ if (!r)
+ {
+ fail_msg_writer() << tr("Bad signature from ") << address_string;
+ }
+ else
+ {
+ success_msg_writer() << tr("Good signature from ") << address_string;
+ }
+ return true;
+}
+//----------------------------------------------------------------------------------------------------
bool simple_wallet::process_command(const std::vector<std::string> &args)
{
return m_cmd_binder.process_command_vec(args);
@@ -3444,6 +3529,7 @@ int main(int argc, char* argv[])
command_line::add_arg(desc_params, arg_testnet);
command_line::add_arg(desc_params, arg_restricted);
command_line::add_arg(desc_params, arg_trusted_daemon);
+ command_line::add_arg(desc_params, arg_allow_mismatched_daemon_version);
command_line::add_arg(desc_params, arg_restore_height);
tools::wallet_rpc_server::init_options(desc_params);
diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h
index e0478eb6e..7d8e7730c 100644
--- a/src/simplewallet/simplewallet.h
+++ b/src/simplewallet/simplewallet.h
@@ -143,9 +143,11 @@ namespace cryptonote
bool get_tx_note(const std::vector<std::string> &args);
bool status(const std::vector<std::string> &args);
bool set_default_fee_multiplier(const std::vector<std::string> &args);
+ bool sign(const std::vector<std::string> &args);
+ bool verify(const std::vector<std::string> &args);
uint64_t get_daemon_blockchain_height(std::string& err);
- bool try_connect_to_daemon();
+ bool try_connect_to_daemon(bool silent = false);
bool ask_wallet_create_if_needed();
bool get_address_from_str(const std::string &str, cryptonote::account_public_address &address, bool &has_payment_id, crypto::hash8 &payment_id);
@@ -238,6 +240,7 @@ namespace cryptonote
bool m_restore_deterministic_wallet; // recover flag
bool m_non_deterministic; // old 2-random generation
bool m_trusted_daemon;
+ bool m_allow_mismatched_daemon_version;
uint64_t m_restore_height; // optional
std::string m_daemon_address;
diff --git a/src/wallet/api/pending_transaction.cpp b/src/wallet/api/pending_transaction.cpp
index c4a770f87..26ce9fc7e 100644
--- a/src/wallet/api/pending_transaction.cpp
+++ b/src/wallet/api/pending_transaction.cpp
@@ -118,7 +118,7 @@ uint64_t PendingTransactionImpl::amount() const
uint64_t PendingTransactionImpl::dust() const
{
- uint32_t result = 0;
+ uint64_t result = 0;
for (const auto & ptx : m_pending_tx) {
result += ptx.dust;
}
@@ -127,7 +127,7 @@ uint64_t PendingTransactionImpl::dust() const
uint64_t PendingTransactionImpl::fee() const
{
- uint32_t result = 0;
+ uint64_t result = 0;
for (const auto ptx : m_pending_tx) {
result += ptx.fee;
}
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index a153967ce..d18681f36 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -53,6 +53,7 @@ using namespace epee;
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
#include "common/json_util.h"
+#include "common/base58.h"
extern "C"
{
@@ -1435,22 +1436,39 @@ bool wallet2::prepare_file_names(const std::string& file_path)
return true;
}
//----------------------------------------------------------------------------------------------------
-bool wallet2::check_connection()
+bool wallet2::check_connection(bool *same_version)
{
boost::lock_guard<boost::mutex> lock(m_daemon_rpc_mutex);
- if(m_http_client.is_connected())
- return true;
+ if(!m_http_client.is_connected())
+ {
+ net_utils::http::url_content u;
+ net_utils::parse_url(m_daemon_address, u);
- net_utils::http::url_content u;
- net_utils::parse_url(m_daemon_address, u);
+ if(!u.port)
+ {
+ u.port = m_testnet ? config::testnet::RPC_DEFAULT_PORT : config::RPC_DEFAULT_PORT;
+ }
- if(!u.port)
+ if (!m_http_client.connect(u.host, std::to_string(u.port), WALLET_RCP_CONNECTION_TIMEOUT))
+ return false;
+ }
+
+ if (same_version)
{
- u.port = m_testnet ? config::testnet::RPC_DEFAULT_PORT : config::RPC_DEFAULT_PORT;
+ epee::json_rpc::request<cryptonote::COMMAND_RPC_GET_VERSION::request> req_t = AUTO_VAL_INIT(req_t);
+ epee::json_rpc::response<cryptonote::COMMAND_RPC_GET_VERSION::response, std::string> resp_t = AUTO_VAL_INIT(resp_t);
+ req_t.jsonrpc = "2.0";
+ req_t.id = epee::serialization::storage_entry(0);
+ req_t.method = "get_version";
+ bool r = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/json_rpc", req_t, resp_t, m_http_client);
+ if (!r || resp_t.result.status != CORE_RPC_STATUS_OK)
+ *same_version = false;
+ else
+ *same_version = resp_t.result.version == CORE_RPC_VERSION;
}
- return m_http_client.connect(u.host, std::to_string(u.port), WALLET_RCP_CONNECTION_TIMEOUT);
+ return true;
}
//----------------------------------------------------------------------------------------------------
bool wallet2::generate_chacha8_key_from_secret_keys(crypto::chacha8_key &key) const
@@ -3106,6 +3124,40 @@ std::string wallet2::get_tx_note(const crypto::hash &txid) const
return std::string();
return i->second;
}
+
+std::string wallet2::sign(const std::string &data) const
+{
+ crypto::hash hash;
+ crypto::cn_fast_hash(data.data(), data.size(), hash);
+ const cryptonote::account_keys &keys = m_account.get_keys();
+ crypto::signature signature;
+ crypto::generate_signature(hash, keys.m_account_address.m_spend_public_key, keys.m_spend_secret_key, signature);
+ return std::string("SigV1") + tools::base58::encode(std::string((const char *)&signature, sizeof(signature)));
+}
+
+bool wallet2::verify(const std::string &data, const cryptonote::account_public_address &address, const std::string &signature) const
+{
+ const size_t header_len = strlen("SigV1");
+ if (signature.size() < header_len || signature.substr(0, header_len) != "SigV1") {
+ LOG_PRINT_L0("Signature header check error");
+ return false;
+ }
+ crypto::hash hash;
+ crypto::cn_fast_hash(data.data(), data.size(), hash);
+ std::string decoded;
+ if (!tools::base58::decode(signature.substr(header_len), decoded)) {
+ LOG_PRINT_L0("Signature decoding error");
+ return false;
+ }
+ crypto::signature s;
+ if (sizeof(s) != decoded.size()) {
+ LOG_PRINT_L0("Signature decoding error");
+ return false;
+ }
+ memcpy(&s, decoded.data(), sizeof(s));
+ return crypto::check_signature(hash, address.m_spend_public_key, s);
+}
+
//----------------------------------------------------------------------------------------------------
void wallet2::generate_genesis(cryptonote::block& b) {
if (m_testnet)
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index c5149a10c..d004b7da9 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -296,7 +296,7 @@ namespace tools
std::vector<wallet2::pending_tx> create_transactions_2(std::vector<cryptonote::tx_destination_entry> dsts, const size_t fake_outs_count, const uint64_t unlock_time, uint64_t fee_multiplier, const std::vector<uint8_t> extra, bool trusted_daemon);
std::vector<wallet2::pending_tx> create_transactions_all(const cryptonote::account_public_address &address, const size_t fake_outs_count, const uint64_t unlock_time, uint64_t fee_multiplier, const std::vector<uint8_t> extra, bool trusted_daemon);
std::vector<pending_tx> create_unmixable_sweep_transactions(bool trusted_daemon);
- bool check_connection();
+ bool check_connection(bool *same_version = NULL);
void get_transfers(wallet2::transfer_container& incoming_transfers) const;
void get_payments(const crypto::hash& payment_id, std::list<wallet2::payment_details>& payments, uint64_t min_height = 0) const;
void get_payments(std::list<std::pair<crypto::hash,wallet2::payment_details>>& payments, uint64_t min_height, uint64_t max_height = (uint64_t)-1) const;
@@ -386,6 +386,9 @@ namespace tools
void set_tx_note(const crypto::hash &txid, const std::string &note);
std::string get_tx_note(const crypto::hash &txid) const;
+ std::string sign(const std::string &data) const;
+ bool verify(const std::string &data, const cryptonote::account_public_address &address, const std::string &signature) const;
+
private:
/*!
* \brief Stores wallet information to wallet file.
diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index 01ae00fe5..5c42e1c53 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -168,6 +168,13 @@ namespace tools
}
integrated_payment_id = new_payment_id;
cryptonote::set_encrypted_payment_id_to_tx_extra_nonce(extra_nonce, integrated_payment_id);
+
+ /* Append Payment ID data into extra */
+ if (!cryptonote::add_extra_nonce_to_tx_extra(extra, extra_nonce)) {
+ er.code = WALLET_RPC_ERROR_CODE_WRONG_PAYMENT_ID;
+ er.message = "Something went wrong with integrated payment_id.";
+ return false;
+ }
}
}
@@ -197,7 +204,7 @@ namespace tools
/* Append Payment ID data into extra */
if (!cryptonote::add_extra_nonce_to_tx_extra(extra, extra_nonce)) {
er.code = WALLET_RPC_ERROR_CODE_WRONG_PAYMENT_ID;
- er.message = "Something went wront with payment_id. Please check its format: \"" + payment_id_str + "\", expected 64-character string";
+ er.message = "Something went wrong with payment_id. Please check its format: \"" + payment_id_str + "\", expected 64-character string";
return false;
}
@@ -747,6 +754,42 @@ namespace tools
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
+ bool wallet_rpc_server::on_sign(const wallet_rpc::COMMAND_RPC_SIGN::request& req, wallet_rpc::COMMAND_RPC_SIGN::response& res, epee::json_rpc::error& er)
+ {
+ if (m_wallet.restricted())
+ {
+ er.code = WALLET_RPC_ERROR_CODE_DENIED;
+ er.message = "Command unavailable in restricted mode.";
+ return false;
+ }
+
+ res.signature = m_wallet.sign(req.data);
+ return true;
+ }
+ //------------------------------------------------------------------------------------------------------------------------------
+ bool wallet_rpc_server::on_verify(const wallet_rpc::COMMAND_RPC_VERIFY::request& req, wallet_rpc::COMMAND_RPC_VERIFY::response& res, epee::json_rpc::error& er)
+ {
+ if (m_wallet.restricted())
+ {
+ er.code = WALLET_RPC_ERROR_CODE_DENIED;
+ er.message = "Command unavailable in restricted mode.";
+ return false;
+ }
+
+ cryptonote::account_public_address address;
+ bool has_payment_id;
+ crypto::hash8 payment_id;
+ if(!get_account_integrated_address_from_str(address, has_payment_id, payment_id, m_wallet.testnet(), req.address))
+ {
+ er.code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS;
+ er.message = "";
+ return false;
+ }
+
+ res.good = m_wallet.verify(req.data, address, req.signature);
+ return true;
+ }
+ //------------------------------------------------------------------------------------------------------------------------------
bool wallet_rpc_server::on_stop_wallet(const wallet_rpc::COMMAND_RPC_STOP_WALLET::request& req, wallet_rpc::COMMAND_RPC_STOP_WALLET::response& res, epee::json_rpc::error& er)
{
if (m_wallet.restricted())
diff --git a/src/wallet/wallet_rpc_server.h b/src/wallet/wallet_rpc_server.h
index 8c90aecfe..205896332 100644
--- a/src/wallet/wallet_rpc_server.h
+++ b/src/wallet/wallet_rpc_server.h
@@ -80,6 +80,8 @@ namespace tools
MAP_JON_RPC_WE("set_tx_notes", on_set_tx_notes, wallet_rpc::COMMAND_RPC_SET_TX_NOTES)
MAP_JON_RPC_WE("get_tx_notes", on_get_tx_notes, wallet_rpc::COMMAND_RPC_GET_TX_NOTES)
MAP_JON_RPC_WE("get_transfers", on_get_transfers, wallet_rpc::COMMAND_RPC_GET_TRANSFERS)
+ MAP_JON_RPC_WE("sign", on_sign, wallet_rpc::COMMAND_RPC_SIGN)
+ MAP_JON_RPC_WE("verify", on_verify, wallet_rpc::COMMAND_RPC_VERIFY)
END_JSON_RPC_MAP()
END_URI_MAP2()
@@ -103,6 +105,8 @@ namespace tools
bool on_set_tx_notes(const wallet_rpc::COMMAND_RPC_SET_TX_NOTES::request& req, wallet_rpc::COMMAND_RPC_SET_TX_NOTES::response& res, epee::json_rpc::error& er);
bool on_get_tx_notes(const wallet_rpc::COMMAND_RPC_GET_TX_NOTES::request& req, wallet_rpc::COMMAND_RPC_GET_TX_NOTES::response& res, epee::json_rpc::error& er);
bool on_get_transfers(const wallet_rpc::COMMAND_RPC_GET_TRANSFERS::request& req, wallet_rpc::COMMAND_RPC_GET_TRANSFERS::response& res, epee::json_rpc::error& er);
+ bool on_sign(const wallet_rpc::COMMAND_RPC_SIGN::request& req, wallet_rpc::COMMAND_RPC_SIGN::response& res, epee::json_rpc::error& er);
+ bool on_verify(const wallet_rpc::COMMAND_RPC_VERIFY::request& req, wallet_rpc::COMMAND_RPC_VERIFY::response& res, epee::json_rpc::error& er);
bool handle_command_line(const boost::program_options::variables_map& vm);
diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h
index 3908476d6..1404340da 100644
--- a/src/wallet/wallet_rpc_server_commands_defs.h
+++ b/src/wallet/wallet_rpc_server_commands_defs.h
@@ -551,6 +551,51 @@ namespace wallet_rpc
};
};
+ struct COMMAND_RPC_SIGN
+ {
+ struct request
+ {
+ std::string data;
+
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE(data);
+ END_KV_SERIALIZE_MAP()
+ };
+
+ struct response
+ {
+ std::string signature;
+
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE(signature);
+ END_KV_SERIALIZE_MAP()
+ };
+ };
+
+ struct COMMAND_RPC_VERIFY
+ {
+ struct request
+ {
+ std::string data;
+ std::string address;
+ std::string signature;
+
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE(data);
+ KV_SERIALIZE(address);
+ KV_SERIALIZE(signature);
+ END_KV_SERIALIZE_MAP()
+ };
+
+ struct response
+ {
+ bool good;
+
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE(good);
+ END_KV_SERIALIZE_MAP()
+ };
+ };
+
}
}
-
diff --git a/src/wallet/wallet_rpc_server_error_codes.h b/src/wallet/wallet_rpc_server_error_codes.h
index 968836671..68edfe76e 100644
--- a/src/wallet/wallet_rpc_server_error_codes.h
+++ b/src/wallet/wallet_rpc_server_error_codes.h
@@ -39,3 +39,4 @@
#define WALLET_RPC_ERROR_CODE_TRANSFER_TYPE -6
#define WALLET_RPC_ERROR_CODE_DENIED -7
#define WALLET_RPC_ERROR_CODE_WRONG_TXID -8
+#define WALLET_RPC_ERROR_CODE_WRONG_SIGNATURE -9
diff --git a/tests/hash-target.cpp b/tests/hash-target.cpp
index c46f6722b..aeb6688bc 100644
--- a/tests/hash-target.cpp
+++ b/tests/hash-target.cpp
@@ -41,7 +41,7 @@ using cryptonote::check_hash;
int main(int argc, char *argv[]) {
crypto::hash h;
for (uint64_t diff = 1;; diff += 1 + (diff >> 8)) {
- for (int b = 0; b < 256; b++) {
+ for (uint16_t b = 0; b < 256; b++) {
memset(&h, b, sizeof(crypto::hash));
if (check_hash(h, diff) != (b == 0 || diff <= 255 / b)) {
return 1;
diff --git a/tests/unit_tests/hardfork.cpp b/tests/unit_tests/hardfork.cpp
index 1d1f85945..35973011a 100644
--- a/tests/unit_tests/hardfork.cpp
+++ b/tests/unit_tests/hardfork.cpp
@@ -42,10 +42,7 @@ using namespace cryptonote;
class TestDB: public BlockchainDB {
public:
- TestDB() {
- for (size_t n = 0; n < 256; ++n)
- starting_height[n] = std::numeric_limits<uint64_t>::max();
- }
+ TestDB() {};
virtual void open(const std::string& filename, const int db_flags = 0) { }
virtual void close() {}
virtual void sync() {}
@@ -122,12 +119,6 @@ public:
virtual block get_block_from_height(const uint64_t& height) const {
return blocks[height];
}
- virtual void set_hard_fork_starting_height(uint8_t version, uint64_t height) {
- starting_height[version] = height;
- }
- virtual uint64_t get_hard_fork_starting_height(uint8_t version) const {
- return starting_height[version];
- }
virtual void set_hard_fork_version(uint64_t height, uint8_t version) {
if (versions.size() <= height)
versions.resize(height+1);
@@ -140,7 +131,6 @@ public:
private:
std::vector<block> blocks;
- uint64_t starting_height[256];
std::deque<uint8_t> versions;
};
@@ -321,10 +311,6 @@ TEST(reorganize, Same)
uint8_t version = hh >= history ? block_versions[hh - history] : 1;
ASSERT_EQ(hf.get(hh), version);
}
- ASSERT_EQ(hf.get_start_height(1), 0);
- ASSERT_EQ(hf.get_start_height(4), 2 + history);
- ASSERT_EQ(hf.get_start_height(7), 4 + history);
- ASSERT_EQ(hf.get_start_height(9), 6 + history);
}
}
}
@@ -355,10 +341,6 @@ TEST(reorganize, Changed)
for (int hh = 0; hh < 16; ++hh) {
ASSERT_EQ(hf.get(hh), expected_versions[hh]);
}
- ASSERT_EQ(hf.get_start_height(1), 0);
- ASSERT_EQ(hf.get_start_height(4), 6);
- ASSERT_EQ(hf.get_start_height(7), 8);
- ASSERT_EQ(hf.get_start_height(9), 10);
}
// delay a bit for 9, and go back to 1 to check it stays at 9
@@ -379,10 +361,6 @@ TEST(reorganize, Changed)
for (int hh = 0; hh < 15; ++hh) {
ASSERT_EQ(hf.get(hh), expected_versions_new[hh]);
}
- ASSERT_EQ(hf.get_start_height(1), 0);
- ASSERT_EQ(hf.get_start_height(4), 6);
- ASSERT_EQ(hf.get_start_height(7), 11);
- ASSERT_EQ(hf.get_start_height(9), 14);
}
TEST(voting, threshold)
@@ -463,8 +441,6 @@ TEST(new_blocks, denied)
ASSERT_TRUE(hf.add(mkblock(1, 2), 8)); // we reach 50% of the last 4
ASSERT_FALSE(hf.add(mkblock(2, 1), 9)); // so this one can't get added
ASSERT_TRUE(hf.add(mkblock(2, 2), 9));
-
- ASSERT_EQ(hf.get_start_height(2), 9);
}
TEST(new_version, early)
@@ -485,8 +461,6 @@ TEST(new_version, early)
ASSERT_TRUE(hf.add(mkblock(2, 2), 5));
ASSERT_FALSE(hf.add(mkblock(2, 1), 6)); // we don't accept 1 anymore
ASSERT_TRUE(hf.add(mkblock(2, 2), 7)); // but we do accept 2
-
- ASSERT_EQ(hf.get_start_height(2), 4);
}
TEST(reorganize, changed)
@@ -521,8 +495,6 @@ TEST(reorganize, changed)
ADD_TRUE(3, 7);
ADD_TRUE(4, 8);
ADD_TRUE(4, 9);
- ASSERT_EQ(hf.get_start_height(2), 4); // reaches threshold 2 at height 3, so height 4 forks
- ASSERT_EQ(hf.get_start_height(3), 9);
ASSERT_EQ(hf.get_current_version(), 3);
// pop a few blocks and check current version goes back down
@@ -539,9 +511,7 @@ TEST(reorganize, changed)
ADD_TRUE(2, 7);
ADD_TRUE(2, 8);
ADD_TRUE(2, 9);
- ASSERT_EQ(hf.get_start_height(2), 4); // unchanged
ASSERT_EQ(hf.get_current_version(), 2); // we did not bump to 3 this time
- ASSERT_EQ(hf.get_start_height(3), std::numeric_limits<uint64_t>::max()); // not yet
}
TEST(get, higher)