diff options
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() @@ -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 ¬e); 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) |