From 29adaded0c2cd2bec0e9485213c9a24cdff1fb57 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Fri, 6 Apr 2018 23:51:18 +0500 Subject: [PATCH] Merge --- CMakeLists.txt | 108 ++++-- README.md | 89 +++-- ReleaseNotes.md | 4 +- src/Core/BlockChain.cpp | 11 +- src/Core/BlockChain.hpp | 2 +- src/Core/BlockChainFileFormat.cpp | 16 +- src/Core/BlockChainFileFormat.hpp | 2 +- src/Core/BlockChainState.hpp | 3 +- src/Core/Config.cpp | 10 +- src/Core/Config.hpp | 7 +- src/Core/CryptoNoteTools.cpp | 2 +- src/Core/CryptoNoteTools.hpp | 2 +- src/Core/Currency.cpp | 4 +- src/Core/Difficulty.cpp | 2 +- src/Core/Difficulty.hpp | 2 +- src/Core/Node.cpp | 86 +++-- src/Core/Node.hpp | 17 +- src/Core/NodeDownloader.cpp | 20 +- src/Core/NodeLegacyAPI.cpp | 48 ++- src/Core/TransactionBuilder.cpp | 9 +- src/Core/TransactionBuilder.hpp | 2 +- src/Core/TransactionExtra.cpp | 8 +- src/Core/TransactionExtra.hpp | 2 +- src/Core/Wallet.cpp | 67 ++-- src/Core/Wallet.hpp | 6 +- src/Core/WalletNode.cpp | 175 +++++---- src/Core/WalletNode.hpp | 10 +- src/Core/WalletSerializationV1.cpp | 2 +- src/Core/WalletSerializationV1.h | 32 +- src/Core/WalletState.cpp | 193 +++++----- src/Core/WalletState.hpp | 8 +- src/Core/WalletSync.cpp | 9 +- src/Core/WalletSync.hpp | 4 +- src/Core/rpc_api_serialization.cpp | 25 +- src/CryptoNote.hpp | 6 +- src/CryptoNoteConfig.hpp | 21 +- src/Miner/MiningConfig.cpp | 6 +- src/Miner/MiningConfig.hpp | 2 +- src/bitsum.rc | 8 +- src/bitsum/bitsum.cpp | 62 ++- src/common/Base58.cpp | 2 +- src/common/Base58.hpp | 2 +- src/common/Base64.cpp | 107 ++++++ src/common/Base64.hpp | 16 + src/common/BinaryArray.cpp | 2 +- src/common/BinaryArray.hpp | 2 +- src/common/CommandLine.cpp | 2 +- src/common/CommandLine.hpp | 2 +- src/common/ConsoleTools.hpp | 2 +- src/common/Ipv4Address.cpp | 10 +- src/common/Ipv4Address.hpp | 9 +- src/common/JsonValue.cpp | 128 ++++--- src/common/JsonValue.hpp | 15 +- src/common/Math.hpp | 2 +- src/common/MemoryStreams.cpp | 2 +- src/common/MemoryStreams.hpp | 2 +- src/common/Nocopy.hpp | 2 +- src/common/ScopeExit.hpp | 2 +- src/common/Streams.cpp | 6 +- src/common/Streams.hpp | 8 +- src/common/StringTools.cpp | 2 +- src/common/StringTools.hpp | 2 +- src/common/StringView.cpp | 170 +------- src/common/StringView.hpp | 89 +---- src/common/Varint.cpp | 2 +- src/common/Varint.hpp | 2 +- src/common/string.hpp | 42 ++ src/crypto/c_types.h | 2 +- src/crypto/chacha8.c | 10 +- src/crypto/crypto-ops-data.c | 2 +- src/crypto/crypto-ops-data.h | 2 +- src/crypto/crypto-ops.c | 2 +- src/crypto/crypto-ops.h | 2 +- src/crypto/crypto-util.c | 2 +- src/crypto/crypto-util.h | 2 +- src/crypto/crypto.cpp | 124 +++--- src/crypto/crypto.hpp | 91 +++-- src/crypto/generic-ops.hpp | 46 +-- src/crypto/hash-ctx.cpp | 65 ++-- src/crypto/hash-extra-blake.c | 2 +- src/crypto/hash-extra-groestl.c | 2 +- src/crypto/hash-extra-jh.c | 2 +- src/crypto/hash-extra-skein.c | 2 +- src/crypto/hash-impl.h | 6 +- src/crypto/hash-ops.h | 2 +- src/crypto/hash.c | 2 +- src/crypto/hash.hpp | 77 ++-- src/crypto/initializer.h | 2 +- src/crypto/int-util.h | 29 +- src/crypto/oaes_lib.c | 24 +- src/crypto/random.h | 2 +- src/crypto/slow-hash_stdc.c | 4 +- src/crypto/slow-hash_x86.c | 2 +- src/crypto/slow-hash_x86.inl | 2 +- src/crypto/tree-hash.c | 2 +- src/crypto/types.hpp | 31 +- src/http/Agent.cpp | 62 +-- src/http/Agent.hpp | 6 +- src/http/JsonRpc.cpp | 32 +- src/http/JsonRpc.h | 15 +- src/http/RequestParser.cpp | 8 +- src/http/RequestParser.hpp | 2 +- src/http/ResponseParser.cpp | 2 +- src/http/ResponseParser.hpp | 2 +- src/http/Server.cpp | 2 +- src/http/Server.hpp | 2 +- src/http/types.cpp | 4 +- src/http/types.hpp | 3 +- src/logging/CommonLogger.cpp | 2 +- src/logging/CommonLogger.hpp | 2 +- src/logging/ConsoleLogger.cpp | 2 +- src/logging/ConsoleLogger.hpp | 2 +- src/logging/FileLogger.cpp | 2 +- src/logging/FileLogger.hpp | 2 +- src/logging/ILogger.cpp | 2 +- src/logging/ILogger.hpp | 2 +- src/logging/LoggerGroup.cpp | 2 +- src/logging/LoggerGroup.hpp | 2 +- src/logging/LoggerManager.cpp | 2 +- src/logging/LoggerManager.hpp | 2 +- src/logging/LoggerMessage.cpp | 2 +- src/logging/LoggerMessage.hpp | 2 +- src/main_bitsumd.cpp | 103 +++++ src/main_tests.cpp | 7 +- src/main_wallet_rpc.cpp | 278 ++++++++++++++ src/p2p/CryptoNoteProtocolDefinitions.hpp | 2 +- src/p2p/LevinProtocol.cpp | 2 +- src/p2p/LevinProtocol.hpp | 2 +- src/p2p/P2P.cpp | 4 +- src/p2p/P2P.hpp | 2 +- src/p2p/P2PClientBasic.cpp | 4 +- src/p2p/P2PClientBasic.hpp | 4 +- src/p2p/P2pProtocolDefinitions.hpp | 6 +- src/p2p/P2pProtocolTypes.hpp | 4 +- src/p2p/P2pSeria.cpp | 4 +- src/p2p/PeerDB.cpp | 9 +- src/p2p/PeerDB.hpp | 2 +- src/platform/DB.hpp | 4 +- src/platform/DBlmdb.cpp | 4 +- src/platform/DBlmdb.hpp | 6 +- src/platform/DBsqlite3.cpp | 23 +- src/platform/DBsqlite3.hpp | 4 +- src/platform/ExclusiveLock.cpp | 4 +- src/platform/ExclusiveLock.hpp | 2 +- src/platform/Files.cpp | 21 +- src/platform/Files.hpp | 2 +- src/platform/Network.cpp | 339 ++++++++++++---- src/platform/Network.hpp | 103 ++++- src/platform/PathTools.cpp | 37 +- src/platform/PathTools.hpp | 15 +- src/platform/PathTools.mm | 6 +- src/platform/PreventSleep.cpp | 75 +++- src/platform/PreventSleep.hpp | 2 +- src/platform/Windows.hpp | 2 +- src/rpc_api.hpp | 54 ++- src/seria/BinaryInputStream.cpp | 2 +- src/seria/BinaryInputStream.hpp | 7 +- src/seria/BinaryOutputStream.cpp | 2 +- src/seria/BinaryOutputStream.hpp | 2 +- src/seria/ISeria.hpp | 9 +- src/seria/JsonInputValue.cpp | 2 +- src/seria/JsonInputValue.hpp | 2 +- src/seria/JsonOutputStream.cpp | 2 +- src/seria/JsonOutputStream.hpp | 2 +- src/seria/KVBinaryCommon.hpp | 2 +- src/seria/KVBinaryInputStream.cpp | 2 +- src/seria/KVBinaryInputStream.hpp | 7 +- src/seria/KVBinaryOutputStream.cpp | 2 +- src/seria/KVBinaryOutputStream.hpp | 2 +- src/version.hpp | 4 +- tests/crypto/test_crypto.cpp | 448 +++++++++++----------- tests/crypto/test_crypto.hpp | 4 +- tests/hash/test_hash.cpp | 114 +++--- tests/hash/test_hash.hpp | 4 +- tests/io.hpp | 106 +++++ tests/json/test_json.cpp | 23 +- tests/json/test_json.hpp | 4 +- 177 files changed, 2682 insertions(+), 1641 deletions(-) create mode 100644 src/common/Base64.cpp create mode 100644 src/common/Base64.hpp create mode 100644 src/common/string.hpp create mode 100644 src/main_bitsumd.cpp create mode 100644 src/main_wallet_rpc.cpp create mode 100644 tests/io.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 56cd1847..40f5a890 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,29 +1,32 @@ -# Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers, The Bitsum Foundation. -# Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +# Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. +# Licensed under the GNU Lesser General Public License. See LICENSE for details. cmake_minimum_required(VERSION 3.5) project(bitsum_core) +set(CMAKE_POSITION_INDEPENDENT_CODE ON) set(CMAKE_CXX_STANDARD 14) -message(STATUS "Bitsumd profile: According to cmake, sizeof(void *) == " ${CMAKE_SIZEOF_VOID_P}) +set(CMAKE_C_STANDARD 11) +# message(STATUS "Bitsumd profile: According to cmake, sizeof(void *) == " ${CMAKE_SIZEOF_VOID_P}) option(USE_INSTRUMENTATION "For testing - builds with address sanitizer instrument" OFF) -option(THREAD_SANITIZER "For testing - builds with thread sanitizer instrument, USE_INSTRUMENTATION must be also set" OFF) +option(WITH_THREAD_SANITIZER "For testing - builds with thread sanitizer instrument, USE_INSTRUMENTATION must be also set" OFF) if(CMAKE_SIZEOF_VOID_P EQUAL 8) - option(BYTECOIN_SQLITE "Builds with sqlite instead of lmdb. 4x slower, but works on 32-bit and mobile platforms" OFF) + option(USE_SQLITE "Builds with SQLite instead of LMDB. 4x slower, but works on 32-bit and mobile platforms" OFF) + option(USE_SSL "Builds with support of https between wallet-rpc and bitsumd" OFF) else() - option(BYTECOIN_SQLITE "Builds with sqlite instead of lmdb. 4x slower, but works on 32-bit and mobile platforms" ON) + option(USE_SQLITE "Builds with sqlite instead of LMDB. 4x slower, but works on 32-bit and mobile platforms" ON) + option(USE_SSL "Builds with support of https between wallet-rpc and bitsumd" OFF) endif() -option(BYTECOIN_SSL "Builds bitsumd capable of serving json requests via https" OFF) if(WIN32) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") add_definitions(-D_SCL_SECURE_NO_WARNINGS=1 -D_CRT_SECURE_NO_WARNINGS=1 -D_WIN32_WINNT=0x0501) else() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes -g -O2 -Wall -Wextra -Wno-strict-aliasing -Werror=return-type -Wno-unused-parameter") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -g -O2 -Wall -Wextra -Wno-strict-aliasing -Werror=return-type -Wno-unused-parameter") - message(STATUS "Using instrumentation: " ${USE_INSTRUMENTATION}) - message(STATUS "Using thread sanitizer: " ${THREAD_SANITIZER}) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes -g -O2 -Wall -Wextra -Werror=return-type -Wno-unused-parameter") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -g -O2 -Wall -Wextra -Werror=return-type -Wno-unused-parameter") + message(STATUS "Instrumentation usage: " ${USE_INSTRUMENTATION}) + message(STATUS "Thread sanitizer usage: " ${WITH_THREAD_SANITIZER}) if(USE_INSTRUMENTATION) - if(THREAD_SANITIZER) + if(WITH_THREAD_SANITIZER) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=thread") else() @@ -32,26 +35,48 @@ else() endif() endif() endif() -if(BYTECOIN_SQLITE) - # requires dl on Linux, we add it unconditionally for simplicity - message(STATUS "Bitsumd profile: database selected - SQLite 3 (make sure it is put into ../sqlite/)") +if(USE_SQLITE) + # Requires dl on Linux, we add it unconditionally for simplicity. + message(STATUS "Database selected: SQLite 3. Make sure it is put into ../sqlite/") include_directories(../sqlite) set(SRC_DB ../sqlite/sqlite3.c src/platform/DBsqlite3.cpp src/platform/DBsqlite3.hpp) - add_definitions(-DBYTECOIN_SQLITE=1) + add_definitions(-Dplatform_USE_SQLITE=1) else() - message(STATUS "Bitsumd profile: database selected - LMDB (make sure it is put into ../lmdb/)") + message(STATUS "Database selected: LMDB. Make sure it is put into ../lmdb/") include_directories(../lmdb/libraries/liblmdb) set(SRC_DB ../lmdb/libraries/liblmdb/mdb.c ../lmdb/libraries/liblmdb/midl.c src/platform/DBlmdb.cpp src/platform/DBlmdb.hpp) endif() -if(BYTECOIN_SSL) - message(STATUS "Bitsumd profile: SSL enabled, make sure openssl headers are in ../openssl/include and static libs are in ../openssl/") +if(USE_SSL) + message(STATUS "SSL usage: ON. Make sure openssl headers are in ../openssl/include and static libs are in ../openssl/") include_directories(../openssl/include) - link_directories(../openssl) # must be placed before add_executable, add_library + link_directories(../openssl) # Must be placed before add_executable, add_library. set(LINK_OPENSSL ssl crypto) - add_definitions(-DBYTECOIN_SSL=1) + add_definitions(-Dplatform_USE_SSL=1) +else() + message(STATUS "SSL usage: OFF") endif() file(GLOB SRC_BITSUM src/bitsum/*.cpp src/bitsum/*.hpp) -file(GLOB SRC_CRYPTO src/crypto/*.cpp src/crypto/*.c src/crypto/*.h src/crypto/*.hpp) +file(GLOB SRC_CRYPTO + src/crypto/*.cpp src/crypto/*.hpp src/crypto/*.h + src/crypto/blake256.c + src/crypto/chacha8.c + src/crypto/crypto-ops-data.c + src/crypto/crypto-ops.c + src/crypto/crypto-util.c + src/crypto/groestl.c + src/crypto/hash-extra-blake.c + src/crypto/hash-extra-groestl.c + src/crypto/hash-extra-jh.c + src/crypto/hash-extra-skein.c + src/crypto/hash.c + src/crypto/jh.c + src/crypto/keccak.c + src/crypto/oaes_lib.c + src/crypto/random.c + src/crypto/skein.c + src/crypto/slow-hash_x86.c + src/crypto/tree-hash.c +) file(GLOB SRC_COMMON src/common/*.cpp src/common/*.hpp) file(GLOB SRC_SERIALIZATION src/Serialization/*.cpp src/Serialization/*.hpp) file(GLOB SRC_SERIA src/seria/*.cpp src/seria/*.hpp) @@ -59,7 +84,7 @@ file(GLOB SRC_LOGGING src/logging/*.cpp src/logging/*.hpp) file(GLOB SRC_P2P src/p2p/*.cpp src/p2p/*.hpp) file(GLOB SRC_CORE src/Core/*.cpp src/Core/*.hpp src/Core/*.h) file(GLOB SRC_HTTP src/http/*.cpp src/http/*.hpp) -file(GLOB SRC_PLATFORM +file(GLOB SRC_PLATFORM src/platform/ExclusiveLock.cpp src/platform/ExclusiveLock.hpp src/platform/Files.cpp src/platform/Files.hpp src/platform/Network.cpp src/platform/Network.hpp @@ -99,44 +124,47 @@ set(SOURCE_FILES src/version.hpp ) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin") +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/libs") set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/libs") if(WIN32) - include_directories(SYSTEM $ENV{BOOST_INCLUDEDIR}) - link_directories(SYSTEM $ENV{BOOST_LIBRARYDIR}) # must be before add_executable, add_library + include_directories(SYSTEM ../boost) + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + link_directories(SYSTEM ../boost/stage/lib) # must be before add_executable, add_library + else() + link_directories(SYSTEM ../boost/stage32/lib) # must be before add_executable, add_library + endif() endif() add_library(bitsum SHARED ${SRC_BITSUM}) add_library(bitsum-crypto ${SRC_CRYPTO}) add_library(bitsum-core ${SOURCE_FILES}) target_link_libraries(bitsum-core bitsum-crypto) if(WIN32) - add_executable(walletd src/main_walletd.cpp src/bitsum.rc) # .rc works only if referenced directly in add_executable - add_executable(bitsumd src/main_bytecoind.cpp src/bitsum.rc) # .rc works only if referenced directly in add_executable + add_executable(wallet-rpc src/main_wallet_rpc.cpp src/bitsum.rc) # .rc works only if referenced directly in add_executable + add_executable(bitsumd src/main_bitsumd.cpp src/bitsum.rc) # .rc works only if referenced directly in add_executable else() - add_executable(walletd src/main_walletd.cpp) - add_executable(bitsumd src/main_bytecoind.cpp) + add_executable(wallet-rpc src/main_wallet_rpc.cpp) + add_executable(bitsumd src/main_bitsumd.cpp) endif() -#add_executable(tests src/main_tests.cpp tests/crypto/test_crypto.cpp tests/hash/test_hash.cpp tests/json/test_json.cpp) -set(Boost_USE_STATIC_LIBS OFF) +#add_executable(tests src/main_tests.cpp tests/io.hpp tests/crypto/test_crypto.cpp tests/hash/test_hash.cpp tests/json/test_json.cpp) +set(Boost_USE_STATIC_LIBS ON) add_definitions(-DBOOST_BIND_NO_PLACEHOLDERS=1 -DBOOST_CONFIG_SUPPRESS_OUTDATED_MESSAGE=1) # boost::_1 conflicts with std::_1 target_link_libraries(bitsum bitsum-crypto bitsum-core) -target_link_libraries(walletd bitsum-crypto bitsum-core) +target_link_libraries(wallet-rpc bitsum-crypto bitsum-core) target_link_libraries(bitsumd bitsum-crypto bitsum-core) -#target_link_libraries(tests bytecoin-crypto bytecoin-core) +#target_link_libraries(tests bitsum-crypto bitsum-core) if(WIN32) else() - #set(BOOST_ROOT ../boost) + set(BOOST_ROOT ../boost) set(Boost_USE_MULTITHREADED OFF) # all boost libraries are multithreaded since some version - find_package(Boost 1.56 REQUIRED COMPONENTS system) - + find_package(Boost 1.62 REQUIRED COMPONENTS system) include_directories(SYSTEM ${Boost_INCLUDE_DIRS}) set(Boost_LIBRARIES "${Boost_LIBRARIES}") if(APPLE) set(CMAKE_OSX_DEPLOYMENT_TARGET "10.11") - target_link_libraries(walletd "-framework Foundation" "-framework IOKit") + target_link_libraries(wallet-rpc "-framework Foundation" "-framework IOKit") target_link_libraries(bitsumd "-framework Foundation" "-framework IOKit") endif() - target_link_libraries(bitsum ${Boost_LIBRARIES} ${LINK_OPENSSL} dl pthread) - target_link_libraries(walletd ${Boost_LIBRARIES} ${LINK_OPENSSL} dl pthread) + target_link_libraries(wallet-rpc ${Boost_LIBRARIES} ${LINK_OPENSSL} dl pthread) target_link_libraries(bitsumd ${Boost_LIBRARIES} ${LINK_OPENSSL} dl pthread) -# target_link_libraries(tests ${Boost_LIBRARIES} ${LINK_OPENSSL} dl pthread) + #target_link_libraries(tests ${Boost_LIBRARIES} ${LINK_OPENSSL} dl pthread) endif() diff --git a/README.md b/README.md index 3fb9638a..eef9e0ea 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,12 @@ All commands below are adapted for Ubuntu, other distributions may need an other ### Building with standard options +Create directory `bitsum` somewhere and go there: +``` +$> mkdir bitsum +$> cd bitsum +``` + To go futher you have to have a number of packages and utilities. * `build-essential` package: @@ -30,18 +36,19 @@ To go futher you have to have a number of packages and utilities. ``` If version is too old, follow instructions on [the official site](https://cmake.org/download/). -* Boost (1.58 or newer): +* Boost (1.62 or newer): ``` $> sudo apt-get install libboost-all-dev $> cat /usr/include/boost/version.hpp | grep "BOOST_LIB_VERSION" ``` - If version is too old, follow instructions on [the official site](http://www.boost.org/users/download/). - -Then create directory `bitsum` somewhere and go there: -``` -$> mkdir bitsum -$> cd bitsum -``` + If version is too old, download boost from [boost.org](https://boost.org), unpack it into a folder inside `bitsum` and rename it from `boost_1_66_0` or similar to just `boost` + Build boost + ``` + $> cd boost + $bitsum/boost> ./bootstrap.sh + $bitsum/boost> ./b2 link=static -j 8 --build-dir=build64 --stagedir=stage + cd .. + ``` Git-clone (or git-pull) Bitsum Core source code in that folder: ``` @@ -53,17 +60,17 @@ Put LMDB source code in `bitsum` folder (source files are referenced via relativ $bitsum> git clone https://github.com/LMDB/lmdb.git ``` -Create build directory inside bitsum_core, go there and run CMake and Make: +Create build directory inside bytecoin, go there and run CMake and Make: ``` $bitsum> mkdir bitsum_core/build $bitsum> cd bitsum_core/build -$bitsum/bitsum_core/build> cmake .. +$bitsum/bitsum_core/build> cmake -DUSE_SSL=0 .. $bitsum/bitsum_core/build> time make -j4 ``` Check built binaries by running them from `../bin` folder ``` -$bitsum/bitsum_core/build> ../bin/bitsumd -v +$bitsum/bitsum_core/build> ../bin/bytecoind -v ``` ### Building with specific options @@ -72,7 +79,7 @@ Install OpenSSL to `bitsum/openssl` folder. (Use switch `linux-x86_64-clang` ins ``` $bitsum> git clone https://github.com/openssl/openssl.git $bitsum> cd openssl -$bitsum/openssl> ./Configure linux-x86_64 +$bitsum/openssl> ./Configure linux-x86_64 no-shared $bitsum/openssl> time make -j4 $bitsum/openssl> cd .. ``` @@ -84,7 +91,7 @@ Below are the commands which add OpenSSL support and switch from LMDB to SQLite ``` $bitsum> mkdir bitsum_core/build $bitsum> cd bitsum_core/build -$bitsum/bitsum_core/build> cmake -DBYTECOIN_SSL=1 -DBYTECOIN_SQLITE=1 .. +$bitsum/bitsum_core/build> cmake -DUSE_SSL=1 -DUSE_SQLITE=1 .. $bitsum/bitsum_core/build> time make -j4 ``` @@ -119,7 +126,7 @@ Create build directory inside bitsum_core, go there and run CMake and Make: ``` $bitsum> mkdir bitsum_core/build $bitsum> cd bitsum_core/build -$bitsum/bitsum_core/build> cmake .. +$bitsum/bitsum_core/build> cmake -DUSE_SSL=0 .. $bitsum/bitsum_core/build> time make -j4 ``` @@ -172,54 +179,64 @@ You add OpenSSL support or switch from LMDB to SQLite by providing options to CM ``` $bitsum> mkdir bitsum_core/build $bitsum> cd bitsum_core/build -$bitsum/bitsum_core/build> cmake -DBYTECOIN_SSL=1 -DBYTECOIN_SQLITE=1 .. +$bitsum/bitsum_core/build> cmake -DUSE_SSL=1 -DUSE_SQLITE=1 .. $bitsum/bitsum_core/build> time make -j4 ``` ## Building on Windows You need Microsoft Visual Studio Community 2017. [Download](https://microsoft.com) and install it selecting `C++`, `git`, `cmake integration` packages. - -Get [Boost](https://boost.org) and unpack it into a folder of your choice. We will use `C:\boost_1_58_0` in the further examples. - Run `Visual Studio x64 command prompt` from start menu. -Build boost +Create directory `bitsum` somewhere: ``` -$> cd C:\boost_1_58_0 -$C:\boost_1_58_0> bootstrap.bat -$C:\boost_1_58_0> b2.exe address-model=64 link=static +$C:\> mkdir bitsum +$C:\> cd bitsum ``` -Set boost environment variables, right-click Computer in start menu, select `Properties`, then click `advanced system settings`, `environment variables`. +Get [Boost](https://boost.org) and unpack it into a folder inside `bitsum` and rename it from `boost_1_66_0` or similar to just `boost`. -Set `BOOST_ROOT` to `C:\boost_1_58_0` - -Set `BOOST_INCLUDEDIR` to `C:\boost_1_58_0` - -Set `BOOST_LIBRARYDIR` to `C:\boost_1_58_0\stage\lib` - -Now create directory `bitsum` somewhere +Build boost (build 32-bit boost version only if you need 32-bit Bitsum Core binaries). ``` -$C:\> mkdir bitsum -$C:\> cd bitsum +$> cd boost +$C:\bitsum\boost> bootstrap.bat +$C:\bitsum\boost> b2.exe address-model=64 link=static -j 8 --build-dir=build64 --stagedir=stage +$C:\bitsum\boost> b2.exe address-model=32 link=static -j 8 --build-dir=build32 --stagedir=stage32 +cd .. ``` -You need Bitsum Core source code +Git-clone (or git-pull) Bitsum Core source code in that folder: ``` $C:\bitsum> git clone https://github.com/BitsumFoundation/bitsum_core.git ``` -You need lmdb in the same folder (source files are referenced via relative paths, so you do not need to separately build it) +Put LMDB in the same folder (source files are referenced via relative paths, so you do not need to separately build it): ``` $C:\bitsum> git clone https://github.com/LMDB/lmdb.git ``` +You need to build openssl, first install ActivePerl (select "add to PATH" option, then restart console): +``` +$C:\bitsum> git clone https://github.com/openssl/openssl.git +$C:\bitsum> cd openssl +$C:\bitsum\openssl> perl Configure VC-WIN64A no-shared no-asm +$C:\bitsum\openssl> nmake +$C:\bitsum\openssl> cd .. +``` +If you want to build 32-bit binaries, you will also need 32-bit build of openssl in separate folder (configuring openssl changes header files, so there is no way to have both 32-bit and 64-bit versions in the same folder): +``` +$C:\bitsum> git clone https://github.com/openssl/openssl.git openssl32 +$C:\bitsum> cd openssl32 +$C:\bitsum\openssl> perl Configure VC-WIN32 no-shared no-asm +$C:\bitsum\openssl> nmake +$C:\bitsum\openssl> cd .. +``` + Now launch Visual Studio, in File menu select `Open Folder`, select `C:\bitsum\bitsum_core` folder. Wait until CMake finishes running and `Build` appears in main menu. Select `x64-Debug` or `x64-Release` from standard toolbar, and then `Build/Build Solution` from the main menu. -You cannot add options to CMake running inside Visual Studio so just edit `CMakeLists.txt` and set `BYTECOIN_SSL` or `BYTECOIN_SQLITE` to `ON` if you wish to build with them. +You cannot add options to CMake running inside Visual Studio so just edit `CMakeLists.txt` and set `USE_SSL` or `USE_SQLITE` to `ON` if you wish to build with them. ## Building on 32-bit x86 platforms, iOS, Android and other ARM platforms @@ -229,7 +246,7 @@ Therefore SQLite option is automatically selected by CMake on 32-bit platforms a We build official x86 32-bit version for Windows only, because there is zero demand for 32-bit version for Linux or Mac. -Building source code for iOS, Android, Raspberry PI, etc is possible but requires major skills on your part. __TBD__ +Building source code for iOS, Android, Raspberry PI, etc is possible (we have experimental `bytecoind` and `walletd` running on ARM64 iPhone) but requires major skills on your part. __TBD__ ## Building on Big-Endian platforms diff --git a/ReleaseNotes.md b/ReleaseNotes.md index f38ba69c..fb25031d 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -1,5 +1,7 @@ ## Release Notes -### v0.18.3.18 (BETA) +### v1.18.4.5 +- Merge code with bytecoin v3.0.0 +### v0.18.3.18 (BETA) - Project is moved to the new public GitHub repository. diff --git a/src/Core/BlockChain.cpp b/src/Core/BlockChain.cpp index aa118b94..3b556cdd 100644 --- a/src/Core/BlockChain.cpp +++ b/src/Core/BlockChain.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "BlockChain.hpp" @@ -148,7 +148,7 @@ BlockChain::BlockChain(const Hash &genesis_bid, const std::string &coin_folder) DB::Cursor cur2 = m_db.rbegin(TIP_CHAIN_PREFIX + previous_versions[0] + "/"); m_internal_import_known_height = cur2.end() ? 0 : boost::lexical_cast(common::read_varint_sqlite4(cur2.get_suffix())); - test_print_structure(); + // test_print_structure(); } void BlockChain::db_commit() { @@ -205,9 +205,7 @@ BroadcastAction BlockChain::add_block(const PreparedBlock &pb, api::BlockHeader std::cout << "Exception while reorganizing blockchain, probably out of " "disk space ex.what=" << ex.what() << std::endl; - std::exit(api::BYTECOIND_DATABASE_ERROR); // TODO - rollback last - // transaction, reset state to - // last transaction state + std::exit(api::BYTECOIND_DATABASE_ERROR); } if (get_tip_height() % 50000 == 0) db_commit(); @@ -509,8 +507,7 @@ bool BlockChain::read_block(const Hash &bid, RawBlock &raw_block) const { } bool BlockChain::has_block(const Hash &bid) const { - // lmdb::Val ms; - TODO return fast check - std::string ms; + platform::DB::Value ms; auto key = BLOCK_PREFIX + DB::to_binary_key(bid.data, sizeof(bid.data)) + BLOCK_SUFFIX; if (!m_db.get(key, ms)) return false; diff --git a/src/Core/BlockChain.hpp b/src/Core/BlockChain.hpp index 12d6d68c..38e00042 100644 --- a/src/Core/BlockChain.hpp +++ b/src/Core/BlockChain.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/Core/BlockChainFileFormat.cpp b/src/Core/BlockChainFileFormat.cpp index 4f455b21..f876fbcf 100644 --- a/src/Core/BlockChainFileFormat.cpp +++ b/src/Core/BlockChainFileFormat.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "BlockChainFileFormat.hpp" #include "BlockChainState.hpp" @@ -10,6 +10,14 @@ using namespace common; using namespace bytecoin; +// Example +// LegacyBlockChainReader reader(import_path + "/blockindexesx.bin", import_path + "/blocksx.bin"); +// std::cout << "Importing blocks count=" << reader.get_block_count() << std::endl; +// for(Height h = 0; h != reader.get_block_count(); ++h){ +// PreparedBlock pb = reader.get_prepared_block_by_index(h); +// std::cout << "Block tx count=" << pb.block.transactions.size() << std::endl; +// } + LegacyBlockChainReader::LegacyBlockChainReader(const std::string &index_file_name, const std::string &item_file_name) { try { m_indexes_file = std::make_unique(index_file_name, platform::FileStream::READ_EXISTING); @@ -157,11 +165,11 @@ bool LegacyBlockChainReader::import_blockchain2(const std::string &coin_folder, // "difference\tMedian - Timestamp" // << std::endl; - LegacyBlockChainReader reader(coin_folder + "/blockindexes.bin", coin_folder + "/blocks.bin"); + LegacyBlockChainReader reader(coin_folder + "/blockindexesx.bin", coin_folder + "/blocksx.bin"); const size_t bs_count = reader.get_block_count(); if (block_chain.get_tip_height() > bs_count) { std::cout << "Skipping block chain import - we have more blocks than " - "blocks.bin tip_height=" + "blocksx.bin tip_height=" << block_chain.get_tip_height() << " bs_count=" << bs_count << std::endl; return true; } @@ -218,7 +226,7 @@ bool LegacyBlockChainWriter::export_blockchain2(const std::string &export_folder auto idea_start = std::chrono::high_resolution_clock::now(); std::cout << "Start exporting blocks" << std::endl; LegacyBlockChainWriter writer( - export_folder + "/blockindexes.bin", export_folder + "/blocks.bin", block_chain.get_tip_height() + 1); + export_folder + "/blockindexesx.bin", export_folder + "/blocksx.bin", block_chain.get_tip_height() + 1); for (Height ha = 0; ha != block_chain.get_tip_height() + 1; ++ha) { Hash bid{}; RawBlock raw_block; diff --git a/src/Core/BlockChainFileFormat.hpp b/src/Core/BlockChainFileFormat.hpp index ac61a1d2..d770add8 100644 --- a/src/Core/BlockChainFileFormat.hpp +++ b/src/Core/BlockChainFileFormat.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/Core/BlockChainState.hpp b/src/Core/BlockChainState.hpp index 8591372c..0a7aa313 100644 --- a/src/Core/BlockChainState.hpp +++ b/src/Core/BlockChainState.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once @@ -168,6 +168,7 @@ class BlockChainState : public BlockChain, private IBlockChainState { Timestamp &next_unlock_timestamp) const; RingCheckerMulticore ring_checker; + std::chrono::steady_clock::time_point log_redo_block_timestamp; }; } // namespace bytecoin diff --git a/src/Core/Config.cpp b/src/Core/Config.cpp index 8f217ad6..b2ab325b 100644 --- a/src/Core/Config.cpp +++ b/src/Core/Config.cpp @@ -61,7 +61,7 @@ Config::Config(common::CommandLine &cmd) } if (const char *pa = cmd.get("--p2p-external-port")) p2p_external_port = boost::lexical_cast(pa); - if (const char *pa = cmd.get("--walletd-bind-address")) { + if (const char *pa = cmd.get("--wallet-rpc-bind-address")) { if (!common::parse_ip_address_and_port(pa, walletd_bind_ip, walletd_bind_port)) throw std::runtime_error("Wrong address format " + std::string(pa) + ", should be ip:port"); } @@ -79,20 +79,20 @@ Config::Config(common::CommandLine &cmd) "Setting --ssl_certificate_password impossible - this binary is built without OpenSSL"); #endif } - if (const char *pa = cmd.get("--bytecoind-authorization")) { + if (const char *pa = cmd.get("--rpc-authorization")) { bytecoind_authorization = common::base64::encode(BinaryArray(pa, pa + strlen(pa))); } - if (const char *pa = cmd.get("--bytecoind-bind-address")) { + if (const char *pa = cmd.get("--daemon-rpc-bind-address")) { if (!common::parse_ip_address_and_port(pa, bytecoind_bind_ip, bytecoind_bind_port)) throw std::runtime_error("Wrong address format " + std::string(pa) + ", should be ip:port"); } - if (const char *pa = cmd.get("--bytecoind-remote-address")) { + if (const char *pa = cmd.get("--daemon-remote-address")) { std::string addr = pa; const std::string prefix = "https://"; if (addr.find(prefix) == 0) { #if !platform_USE_SSL throw std::runtime_error( - "Using https in --bytecoind-remote-address impossible - this binary is built without OpenSSL"); + "Using https in --daemon-remote-address impossible - this binary is built without OpenSSL"); #endif std::string sip; std::string sport; diff --git a/src/Core/Config.hpp b/src/Core/Config.hpp index 1862da4d..8151f50c 100644 --- a/src/Core/Config.hpp +++ b/src/Core/Config.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once @@ -64,9 +64,10 @@ class Config { // Consensus does not depend on those parameters PublicKey trusted_public_key{}; - std::string coin_directory; + std::string data_folder; - std::string get_coin_directory(const std::string &subdir = std::string(), bool create = true) const; + std::string get_data_folder() const { return data_folder; } // suppress creation of dir itself + std::string get_data_folder(const std::string &subdir) const; }; } // namespace bytecoin diff --git a/src/Core/CryptoNoteTools.cpp b/src/Core/CryptoNoteTools.cpp index aaf1fd00..d2bf1834 100644 --- a/src/Core/CryptoNoteTools.cpp +++ b/src/Core/CryptoNoteTools.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "CryptoNoteTools.hpp" #include "TransactionExtra.hpp" diff --git a/src/Core/CryptoNoteTools.hpp b/src/Core/CryptoNoteTools.hpp index 5168fe8a..0d9a7446 100644 --- a/src/Core/CryptoNoteTools.hpp +++ b/src/Core/CryptoNoteTools.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/Core/Currency.cpp b/src/Core/Currency.cpp index c206e6e5..9123e159 100644 --- a/src/Core/Currency.cpp +++ b/src/Core/Currency.cpp @@ -453,8 +453,8 @@ Difficulty Currency::next_difficulty(Height blockIndex, if (c_difficultyWindow > timestamps.size()) { t_difficultyWindow = timestamps.size(); } - std::vector timestamps_tmp(timestamps_o.end() - t_difficultyWindow, timestamps_o.end()); - std::vector cumulativeDifficulties_tmp(cumulativeDifficulties_o.end() - t_difficultyWindow, cumulativeDifficulties_o.end()); + std::vector timestamps_tmp(timestamps_o.end() - t_difficultyWindow, timestamps_o.end()); + std::vector cumulativeDifficulties_tmp(cumulativeDifficulties_o.end() - t_difficultyWindow, cumulativeDifficulties_o.end()); length = timestamps_tmp.size(); assert(length == cumulativeDifficulties_tmp.size()); diff --git a/src/Core/Difficulty.cpp b/src/Core/Difficulty.cpp index c293addd..4e064403 100644 --- a/src/Core/Difficulty.cpp +++ b/src/Core/Difficulty.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include #include diff --git a/src/Core/Difficulty.hpp b/src/Core/Difficulty.hpp index df1c4663..3e018a44 100644 --- a/src/Core/Difficulty.hpp +++ b/src/Core/Difficulty.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/Core/Node.cpp b/src/Core/Node.cpp index fb167124..9f4d0bd3 100644 --- a/src/Core/Node.cpp +++ b/src/Core/Node.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "Node.hpp" #include @@ -27,16 +27,16 @@ Node::Node(logging::ILogger &log, const Config &config, BlockChainState &block_c , m_commit_timer(std::bind(&Node::db_commit, this)) , m_downloader(this, block_chain) { const std::string old_path = platform::getDefaultDataDirectory(config.crypto_note_name); - const std::string new_path = config.get_coin_directory(); + const std::string new_path = config.get_data_folder(); if (!config.is_testnet) { m_block_chain_reader1 = - std::make_unique(new_path + "/blockindexes.bin", new_path + "/blocks.bin"); + std::make_unique(new_path + "/blockindexesx.bin", new_path + "/blocksx.bin"); if (m_block_chain_reader1->get_block_count() <= block_chain.get_tip_height()) m_block_chain_reader1.reset(); if (new_path != old_path) { // Current situation on Linux m_block_chain_reader2 = - std::make_unique(old_path + "/blockindexes.bin", old_path + "/blocks.bin"); + std::make_unique(old_path + "/blockindexesx.bin", old_path + "/blocksx.bin"); if (m_block_chain_reader2->get_block_count() <= block_chain.get_tip_height()) m_block_chain_reader2.reset(); } @@ -249,7 +249,7 @@ void Node::P2PClientBytecoin::on_msg_notify_new_transactions(NOTIFY_NEW_TRANSACT m_node->advance_long_poll(); } -#ifdef ALLOW_DEBUG_COMMANDS +#if bytecoin_ALLOW_DEBUG_COMMANDS void Node::P2PClientBytecoin::on_msg_network_state(COMMAND_REQUEST_NETWORK_STATE::request &&req) { if (!m_node->check_trust(req.tr)) { disconnect(std::string()); @@ -374,6 +374,7 @@ static const std::string beautiful_index_start = bytecoind • version )"; static const std::string beautiful_index_finish = " "; +static const std::string robots_txt = "User-agent: *\r\nDisallow: /"; bool Node::on_api_http_request(http::Client *who, http::RequestData &&request, http::ResponseData &response) { response.r.add_headers_nocache(); @@ -386,6 +387,12 @@ bool Node::on_api_http_request(http::Client *who, http::RequestData &&request, h beautiful_index_finish); return true; } + if (request.r.uri == "/robots.txt") { + response.r.headers.push_back({"Content-Type", "text/plain; charset=UTF-8"}); + response.r.status = 200; + response.set_body(std::string(robots_txt)); + return true; + } auto it = m_http_handlers.find(request.r.uri); if (it == m_http_handlers.end()) { response.r.status = 404; @@ -412,26 +419,26 @@ void Node::on_api_http_disconnect(http::Client *who) { } namespace { -template +/*template Node::HTTPHandlerFunction binMethod(bool (Node::*handler)(http::Client *who, http::RequestData &&raw_request, json_rpc::Request &&raw_js_request, CommandRequest &&, CommandResponse &)) { - return [handler](Node *obj, http::Client *who, http::RequestData &&request, http::ResponseData &response) { + return [handler](Node *obj, http::Client *who, http::RequestData &&request, http::ResponseData &response) { - CommandRequest req{}; - CommandResponse res{}; + CommandRequest req{}; + CommandResponse res{}; - if (!loadFromBinaryKeyValue(req, request.body)) { - return false; - } + if (!loadFromBinaryKeyValue(req, request.body)) { + return false; + } - bool result = (obj->*handler)(who, std::move(request), json_rpc::Request(), std::move(req), res); - if (result) { - response.set_body(storeToBinaryKeyValueStr(res)); - response.r.status = 200; - } - return result; - }; -} + bool result = (obj->*handler)(who, std::move(request), json_rpc::Request(), std::move(req), res); + if (result) { + response.set_body(storeToBinaryKeyValueStr(res)); + response.r.status = 200; + } + return result; + }; +}*/ template Node::HTTPHandlerFunction binMethod2(bool (Node::*handler)(http::Client *who, http::RequestData &&raw_request, @@ -472,27 +479,36 @@ Node::HTTPHandlerFunction jsonMethod(bool (Node::*handler)(http::Client *who, ht } } // anonymous namespace -std::unordered_map Node::m_http_handlers = { +const std::unordered_map Node::m_http_handlers = { {api::bytecoind::SyncBlocks::binMethod(), binMethod2(&Node::on_wallet_sync3)}, {api::bytecoind::SyncMemPool::binMethod(), binMethod2(&Node::on_sync_mempool3)}, {"/json_rpc", std::bind(&Node::process_json_rpc_request, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)}}; -std::unordered_map Node::m_jsonrpc_handlers = { - {api::bytecoind::GetBlockTemplate::method(), json_rpc::makeMemberMethodSeria(&Node::on_getblocktemplate)}, - {api::bytecoind::GetBlockTemplate::method_legacy(), json_rpc::makeMemberMethodSeria(&Node::on_getblocktemplate)}, - {api::bytecoind::GetCurrencyId::method(), json_rpc::makeMemberMethodSeria(&Node::on_get_currency_id)}, - {api::bytecoind::GetCurrencyId::method_legacy(), json_rpc::makeMemberMethodSeria(&Node::on_get_currency_id)}, - {api::bytecoind::SubmitBlock::method(), json_rpc::makeMemberMethodSeria(&Node::on_submitblock)}, - {api::bytecoind::SubmitBlockLegacy::method(), json_rpc::makeMemberMethodSeria(&Node::on_submitblock_legacy)}, - {api::bytecoind::GetRandomOutputs::method(), json_rpc::makeMemberMethodSeria(&Node::on_get_random_outputs3)}, - {api::bytecoind::GetStatus::method(), json_rpc::makeMemberMethodSeria(&Node::on_get_status3)}, - {api::bytecoind::GetStatus::method2(), json_rpc::makeMemberMethodSeria(&Node::on_get_status3)}, - {api::bytecoind::SendTransaction::method(), json_rpc::makeMemberMethodSeria(&Node::handle_send_transaction3)}, - {api::bytecoind::CheckSendProof::method(), json_rpc::makeMemberMethodSeria(&Node::handle_check_send_proof3)}, - {api::bytecoind::SyncBlocks::method(), json_rpc::makeMemberMethodSeria(&Node::on_wallet_sync3)}, - {api::bytecoind::SyncMemPool::method(), json_rpc::makeMemberMethodSeria(&Node::on_sync_mempool3)}}; +//{"getlastblockheader", JsonRpc::makeMemberMethod(&Node::on_get_last_block_header)}, +//{"getblockheaderbyhash", JsonRpc::makeMemberMethod(&Node::on_get_block_header_by_hash)}, +//{"getblockheaderbyheight", JsonRpc::makeMemberMethod(&Node::on_get_block_header_by_height)}, + +const std::unordered_map Node::m_jsonrpc_handlers = { + {api::bytecoind::GetLastBlockHeaderLegacy::method(), json_rpc::makeMemberMethod(&Node::on_get_last_block_header)}, + {api::bytecoind::GetBlockHeaderByHashLegacy::method(), + json_rpc::makeMemberMethod(&Node::on_get_block_header_by_hash)}, + {api::bytecoind::GetBlockHeaderByHeightLegacy::method(), + json_rpc::makeMemberMethod(&Node::on_get_block_header_by_height)}, + {api::bytecoind::GetBlockTemplate::method(), json_rpc::makeMemberMethod(&Node::on_getblocktemplate)}, + {api::bytecoind::GetBlockTemplate::method_legacy(), json_rpc::makeMemberMethod(&Node::on_getblocktemplate)}, + {api::bytecoind::GetCurrencyId::method(), json_rpc::makeMemberMethod(&Node::on_get_currency_id)}, + {api::bytecoind::GetCurrencyId::method_legacy(), json_rpc::makeMemberMethod(&Node::on_get_currency_id)}, + {api::bytecoind::SubmitBlock::method(), json_rpc::makeMemberMethod(&Node::on_submitblock)}, + {api::bytecoind::SubmitBlockLegacy::method(), json_rpc::makeMemberMethod(&Node::on_submitblock_legacy)}, + {api::bytecoind::GetRandomOutputs::method(), json_rpc::makeMemberMethod(&Node::on_get_random_outputs3)}, + {api::bytecoind::GetStatus::method(), json_rpc::makeMemberMethod(&Node::on_get_status3)}, + {api::bytecoind::GetStatus::method2(), json_rpc::makeMemberMethod(&Node::on_get_status3)}, + {api::bytecoind::SendTransaction::method(), json_rpc::makeMemberMethod(&Node::handle_send_transaction3)}, + {api::bytecoind::CheckSendProof::method(), json_rpc::makeMemberMethod(&Node::handle_check_send_proof3)}, + {api::bytecoind::SyncBlocks::method(), json_rpc::makeMemberMethod(&Node::on_wallet_sync3)}, + {api::bytecoind::SyncMemPool::method(), json_rpc::makeMemberMethod(&Node::on_sync_mempool3)}}; bool Node::on_get_random_outputs3(http::Client *, http::RequestData &&, json_rpc::Request &&, api::bytecoind::GetRandomOutputs::Request &&request, api::bytecoind::GetRandomOutputs::Response &response) { diff --git a/src/Core/Node.hpp b/src/Core/Node.hpp index c3895339..5577a576 100644 --- a/src/Core/Node.hpp +++ b/src/Core/Node.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once @@ -64,6 +64,13 @@ class Node { api::bytecoind::SubmitBlock::Request &&, api::bytecoind::SubmitBlock::Response &); bool on_submitblock_legacy(http::Client *, http::RequestData &&, json_rpc::Request &&, api::bytecoind::SubmitBlockLegacy::Request &&, api::bytecoind::SubmitBlockLegacy::Response &); + bool on_get_last_block_header(http::Client *, http::RequestData &&, json_rpc::Request &&, + api::bytecoind::GetLastBlockHeaderLegacy::Request &&, api::bytecoind::GetLastBlockHeaderLegacy::Response &); + bool on_get_block_header_by_hash(http::Client *, http::RequestData &&, json_rpc::Request &&, + api::bytecoind::GetBlockHeaderByHashLegacy::Request &&, api::bytecoind::GetBlockHeaderByHashLegacy::Response &); + bool on_get_block_header_by_height(http::Client *, http::RequestData &&, json_rpc::Request &&, + api::bytecoind::GetBlockHeaderByHeightLegacy::Request &&, + api::bytecoind::GetBlockHeaderByHeightLegacy::Response &); bool process_json_rpc_request(http::Client *, http::RequestData &&, http::ResponseData &); @@ -122,7 +129,7 @@ class Node { virtual void on_msg_timed_sync(COMMAND_TIMED_SYNC::response &&) override; virtual void on_msg_notify_new_block(NOTIFY_NEW_BLOCK::request &&) override; virtual void on_msg_notify_new_transactions(NOTIFY_NEW_TRANSACTIONS::request &&) override; -#ifdef ALLOW_DEBUG_COMMANDS +#if bytecoin_ALLOW_DEBUG_COMMANDS virtual void on_msg_network_state(COMMAND_REQUEST_NETWORK_STATE::request &&) override; virtual void on_msg_stat_info(COMMAND_REQUEST_STAT_INFO::request &&) override; #endif @@ -193,6 +200,8 @@ class Node { std::deque m_chain; // 10k-20k of hashes of the next wanted blocks NetworkAddress chain_source; // for banning culprit in case of a problem platform::Timer m_download_timer; + std::chrono::steady_clock::time_point log_request_timestamp; + std::chrono::steady_clock::time_point log_response_timestamp; // multicore preparator std::vector threads; @@ -232,8 +241,8 @@ class Node { void sync_transactions(P2PClientBytecoin *); - static std::unordered_map m_http_handlers; - static std::unordered_map m_jsonrpc_handlers; + static const std::unordered_map m_http_handlers; + static const std::unordered_map m_jsonrpc_handlers; }; } // namespace bytecoin diff --git a/src/Core/NodeDownloader.cpp b/src/Core/NodeDownloader.cpp index 9d28c622..75be526e 100644 --- a/src/Core/NodeDownloader.cpp +++ b/src/Core/NodeDownloader.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include #include "Config.hpp" @@ -15,7 +15,9 @@ Node::DownloaderV11::DownloaderV11(Node *node, BlockChainState &block_chain) : m_node(node) , m_block_chain(block_chain) , m_chain_timer(std::bind(&DownloaderV11::on_chain_timer, this)) - , m_download_timer(std::bind(&DownloaderV11::on_download_timer, this)) { + , m_download_timer(std::bind(&DownloaderV11::on_download_timer, this)) + , log_request_timestamp(std::chrono::steady_clock::now()) + , log_response_timestamp(std::chrono::steady_clock::now()) { if (multicore) { auto th_count = std::max(2, std::thread::hardware_concurrency() / 2); // we use more energy but have the same speed when using hyperthreading @@ -232,9 +234,12 @@ void Node::DownloaderV11::on_msg_notify_request_objects(P2PClientBytecoin *who, git->second -= 1; total_downloading_blocks -= 1; m_who_downloaded_block.push_back(who); - if (dc.expected_height % 100 == 0) - std::cout << "Received block with height=" << dc.expected_height << "(" << total_downloading_blocks - << ") from " << who->get_address() << std::endl; + auto now = std::chrono::steady_clock::now(); + if (std::chrono::duration_cast(now - log_response_timestamp).count() > 1000) { + log_response_timestamp = now; + std::cout << "Received block with height=" << dc.expected_height + << "(queue=" << total_downloading_blocks << ") from " << who->get_address() << std::endl; + } cell_found = true; if (multicore) { dc.status = DownloadCell::PREPARING; @@ -364,9 +369,12 @@ void Node::DownloaderV11::advance_download(Hash last_downloaded_block) { total_downloading_blocks += 1; NOTIFY_REQUEST_GET_OBJECTS::request msg; msg.blocks.push_back(dc.bid); - if (dc.expected_height % 100 == 0) + auto now = std::chrono::steady_clock::now(); + if (std::chrono::duration_cast(now - log_request_timestamp).count() > 1000) { + log_request_timestamp = now; std::cout << "Requesting block " << dc.expected_height << " from " << ready_client->get_address() << std::endl; + } BinaryArray raw_msg = LevinProtocol::send_message(NOTIFY_REQUEST_GET_OBJECTS::ID, LevinProtocol::encode(msg), false); ready_client->send(std::move(raw_msg)); diff --git a/src/Core/NodeLegacyAPI.cpp b/src/Core/NodeLegacyAPI.cpp index 47735031..91f06414 100644 --- a/src/Core/NodeLegacyAPI.cpp +++ b/src/Core/NodeLegacyAPI.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include #include "Core/Config.hpp" @@ -204,3 +204,49 @@ bool Node::on_submitblock_legacy(http::Client *who, http::RequestData &&rd, json } return on_submitblock(who, std::move(rd), std::move(jr), std::move(other_req), res); } + +bool Node::on_get_last_block_header(http::Client *, http::RequestData &&, json_rpc::Request &&, + api::bytecoind::GetLastBlockHeaderLegacy::Request &&, + api::bytecoind::GetLastBlockHeaderLegacy::Response &response) { + static_cast(response.block_header) = m_block_chain.get_tip(); + response.block_header.orphan_status = false; + response.block_header.depth = + api::HeightOrDepth(m_block_chain.get_tip_height()) - api::HeightOrDepth(response.block_header.height); + response.status = CORE_RPC_STATUS_OK; + return true; +} + +bool Node::on_get_block_header_by_hash(http::Client *, http::RequestData &&, json_rpc::Request &&, + api::bytecoind::GetBlockHeaderByHashLegacy::Request &&request, + api::bytecoind::GetBlockHeaderByHashLegacy::Response &response) { + if (!m_block_chain.read_header(request.hash, response.block_header)) + throw json_rpc::Error{CORE_RPC_ERROR_CODE_INTERNAL_ERROR, + "Internal error: can't get block by hash. Hash = " + common::pod_to_hex(request.hash) + '.'}; + Hash hash_at_height; + response.block_header.orphan_status = + m_block_chain.read_chain(response.block_header.height, hash_at_height) && hash_at_height == request.hash; + response.block_header.depth = + api::HeightOrDepth(m_block_chain.get_tip_height()) - api::HeightOrDepth(response.block_header.height); + response.status = CORE_RPC_STATUS_OK; + return true; +} + +bool Node::on_get_block_header_by_height(http::Client *, http::RequestData &&, json_rpc::Request &&, + api::bytecoind::GetBlockHeaderByHeightLegacy::Request &&request, + api::bytecoind::GetBlockHeaderByHeightLegacy::Response &response) { + Hash block_hash; + if (!m_block_chain.read_chain(request.height - 1, block_hash)) { // This call counts blocks from 1 + throw json_rpc::Error{CORE_RPC_ERROR_CODE_TOO_BIG_HEIGHT, + std::string("To big height: ") + common::to_string(request.height) + + ", current blockchain height = " + common::to_string(m_block_chain.get_tip_height())}; + } + if (!m_block_chain.read_header(block_hash, response.block_header)) + throw json_rpc::Error{CORE_RPC_ERROR_CODE_TOO_BIG_HEIGHT, + std::string("To big height: ") + common::to_string(request.height) + + ", current blockchain height = " + common::to_string(m_block_chain.get_tip_height())}; + response.block_header.orphan_status = false; + response.block_header.depth = + api::HeightOrDepth(m_block_chain.get_tip_height()) - api::HeightOrDepth(response.block_header.height); + response.status = CORE_RPC_STATUS_OK; + return true; +} diff --git a/src/Core/TransactionBuilder.cpp b/src/Core/TransactionBuilder.cpp index 749187ce..4c8508f8 100644 --- a/src/Core/TransactionBuilder.cpp +++ b/src/Core/TransactionBuilder.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "TransactionBuilder.hpp" #include @@ -7,6 +7,7 @@ #include "CryptoNoteTools.hpp" #include "Currency.hpp" #include "Wallet.hpp" +#include "common/string.hpp" #include "crypto/crypto.hpp" #include "crypto/random.h" #include "http/JsonRpc.h" @@ -145,7 +146,9 @@ Transaction TransactionBuilder::sign(const Hash &tx_derivation_seed) { KeyOutput outKey; if (!derive_public_key(m_output_descs[i].addr, txKeys.secretKey, i, outKey.key)) throw std::runtime_error("output keys detected as corrupted during output key derivation"); - TransactionOutput out = {m_output_descs[i].amount, outKey}; + TransactionOutput out; // TODO - return {} initializer after NDK compiler upgrade + out.amount = m_output_descs[i].amount; + out.target = outKey; m_transaction.outputs.at(i) = out; } @@ -190,7 +193,7 @@ void UnspentSelector::add_mixed_inputs(const SecretKey &view_secret_key, while (mix_outputs.size() < anonymity) { if (our_ra_outputs.empty()) throw std::runtime_error("Not enough anonymity for amount " + - std::to_string(uu.amount)); // TODO - return error code to json_rpc + common::to_string(uu.amount)); // TODO - return error code to json_rpc api::Output out = std::move(our_ra_outputs.back()); our_ra_outputs.pop_back(); if (out.global_index != uu.global_index) // Protect against collisions diff --git a/src/Core/TransactionBuilder.hpp b/src/Core/TransactionBuilder.hpp index aba626cc..99f8d57e 100644 --- a/src/Core/TransactionBuilder.hpp +++ b/src/Core/TransactionBuilder.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/Core/TransactionExtra.cpp b/src/Core/TransactionExtra.cpp index aa999262..54faddad 100644 --- a/src/Core/TransactionExtra.cpp +++ b/src/Core/TransactionExtra.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "TransactionExtra.hpp" @@ -50,8 +50,10 @@ bool parse_transaction_extra(const BinaryArray &transactionExtra, if (size > TX_EXTRA_PADDING_MAX_COUNT) { return false; } - - transactionExtraFields.push_back(TransactionExtraPadding{size}); + TransactionExtraPadding padding; + padding.size = size; + transactionExtraFields.push_back( + padding); // TODO - return {} initializer when Google updates NDK copmiler break; } diff --git a/src/Core/TransactionExtra.hpp b/src/Core/TransactionExtra.hpp index 5c34e0dc..2888cc46 100644 --- a/src/Core/TransactionExtra.hpp +++ b/src/Core/TransactionExtra.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/Core/Wallet.cpp b/src/Core/Wallet.cpp index 851dc62d..e82dd45f 100644 --- a/src/Core/Wallet.cpp +++ b/src/Core/Wallet.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "CryptoNoteTools.hpp" #include "WalletSerializationV1.h" @@ -44,8 +44,11 @@ static void decrypt_key_pair( } static void encrypt_key_pair(EncryptedWalletRecord &r, PublicKey pk, SecretKey sk, Timestamp ct, const WalletKey &key) { - ContainerStorageWalletRecord rec{pk, sk, ct}; - r.iv = crypto::rand(); + ContainerStorageWalletRecord rec; + rec.pk = pk; + rec.sk = sk; + rec.ct = ct; + r.iv = crypto::rand(); chacha8(&rec, sizeof(r.data), key, r.iv, r.data); } @@ -62,8 +65,9 @@ void Wallet::load_container_storage() { if (version < SERIALIZATION_VERSION_V2) throw Exception(api::WALLET_FILE_DECRYPT_ERROR, "Wallet version too old"); + Timestamp creation_timestamp = 0; // We ignore view keys timestamp on load decrypt_key_pair( - prefix.encrypted_view_keys, m_view_public_key, m_view_secret_key, m_creation_timestamp, m_wallet_key); + prefix.encrypted_view_keys, m_view_public_key, m_view_secret_key, creation_timestamp, m_wallet_key); if (!keys_match(m_view_secret_key, m_view_public_key)) throw Exception(api::WALLET_FILE_DECRYPT_ERROR, "Restored view public key doesn't correspond to secret key"); @@ -122,39 +126,30 @@ Wallet::Wallet(const std::string &path, const std::string &password, bool create if (create) { try { file.reset(new platform::FileStream(path, platform::FileStream::READ_EXISTING)); - } catch (const std::ios_base::failure &) { + } catch (const common::StreamError &) { // file does not exist } if (file.get()) // opened ok throw Exception(api::WALLET_FILE_EXISTS, - "Will not overwrite existing " - "wallet - delete it first or " - "specify another file " + - path); + "Will not overwrite existing wallet - delete it first or specify another file " + path); if (import_keys.empty()) { - m_creation_timestamp = m_oldest_timestamp = static_cast(std::time(nullptr)); - crypto::random_keys(m_view_public_key, m_view_secret_key); - generate_new_address(SecretKey{}, m_creation_timestamp); + m_oldest_timestamp = static_cast(std::time(nullptr)); + crypto::random_keypair(m_view_public_key, m_view_secret_key); + generate_new_address(SecretKey{}, m_oldest_timestamp); first_record = m_wallet_records.begin()->second; } else { - if (import_keys.size() != 128)//256) + if (import_keys.size() != 128) throw Exception(api::WALLET_FILE_DECRYPT_ERROR, "Imported keys should be exactly 128 hex bytes"); WalletRecord record{}; if (//!common::pod_from_hex(import_keys.substr(0, 64), record.spend_public_key) || - //!common::pod_from_hex(import_keys.substr(64, 64), m_view_public_key) || - !common::pod_from_hex(import_keys.substr(0, 64), record.spend_secret_key) || - !common::pod_from_hex(import_keys.substr(64, 64), m_view_secret_key)) + //!common::pod_from_hex(import_keys.substr(64, 64), m_view_public_key) || + !common::pod_from_hex(import_keys.substr(0, 64), record.spend_secret_key) || + !common::pod_from_hex(import_keys.substr(64, 64), m_view_secret_key)) throw Exception(api::WALLET_FILE_DECRYPT_ERROR, "Imported keys should contain only hex bytes"); - bool r = crypto::secret_key_to_public_key(record.spend_secret_key, record.spend_public_key); - r = crypto::secret_key_to_public_key(m_view_secret_key, m_view_public_key); - std::cout << r; - //if (!common::pod_from_hex(import_keys.substr(0, 64), record.spend_public_key) || - // !common::pod_from_hex(import_keys.substr(64, 64), m_view_public_key) || - // !common::pod_from_hex(import_keys.substr(128, 64), record.spend_secret_key) || - // !common::pod_from_hex(import_keys.substr(192, 64), m_view_secret_key)) - // throw Exception(api::WALLET_FILE_DECRYPT_ERROR, "Imported keys should contain only hex bytes"); + crypto::secret_key_to_public_key(record.spend_secret_key, record.spend_public_key); + crypto::secret_key_to_public_key(m_view_secret_key, m_view_public_key); if (!keys_match(m_view_secret_key, m_view_public_key)) throw Exception( api::WALLET_FILE_DECRYPT_ERROR, "Imported secret view key does not match corresponding public key"); @@ -162,14 +157,14 @@ Wallet::Wallet(const std::string &path, const std::string &password, bool create throw Exception(api::WALLET_FILE_DECRYPT_ERROR, "Imported secret spend key does not match corresponding public key"); m_wallet_records.insert(std::make_pair(record.spend_public_key, record)); - first_record = m_wallet_records.begin()->second; - m_creation_timestamp = m_oldest_timestamp = 0; // Alas, will scan entire blockchain + first_record = m_wallet_records.begin()->second; + m_oldest_timestamp = 0; // Alas, will scan entire blockchain } save_and_check(); } try { file.reset(new platform::FileStream(path, platform::FileStream::READ_WRITE_EXISTING)); - } catch (const std::ios_base::failure &) { // Read-only media? + } catch (const common::StreamError &) { // Read-only media? file.reset(new platform::FileStream(path, platform::FileStream::READ_EXISTING)); } uint8_t version = 0; @@ -180,7 +175,7 @@ Wallet::Wallet(const std::string &path, const std::string &password, bool create if (version < SERIALIZATION_VERSION_V2) { try { load_legacy_wallet_file(); - } catch (const std::ios_base::failure &ex) { + } catch (const common::StreamError &ex) { throw Exception(api::WALLET_FILE_READ_ERROR, std::string("Error reading wallet file ") + ex.what()); } catch (const std::exception &ex) { throw Exception(api::WALLET_FILE_DECRYPT_ERROR, std::string("Error decrypting wallet file ") + ex.what()); @@ -222,7 +217,7 @@ void Wallet::save(const std::string &export_path, bool view_only) { uint8_t version = SERIALIZATION_VERSION_V2; ContainerStoragePrefix prefix{}; encrypt_key_pair( - prefix.encrypted_view_keys, m_view_public_key, m_view_secret_key, m_creation_timestamp, m_wallet_key); + prefix.encrypted_view_keys, m_view_public_key, m_view_secret_key, m_oldest_timestamp, m_wallet_key); uint64_t item_count = m_wallet_records.size(); f.write(&version, 1); f.write(&prefix, sizeof(prefix)); @@ -254,7 +249,7 @@ void Wallet::save_and_check() { throw Exception(api::WALLET_FILE_WRITE_ERROR, "Error writing wallet file - records do not match"); file.reset(); if (!platform::atomic_replace_file(tmp_path, m_path)) - throw std::ios_base::failure("Error replacing wallet file"); + throw Exception(api::WALLET_FILE_WRITE_ERROR, "Error replacing wallet file"); std::swap(file, other.file); } @@ -269,7 +264,7 @@ void Wallet::export_view_only(const std::string &export_path) { std::unique_ptr export_file; try { export_file.reset(new platform::FileStream(export_path, platform::FileStream::READ_EXISTING)); - } catch (const std::ios_base::failure &) { + } catch (const common::StreamError &) { // file does not exist } if (export_file.get()) // opened ok @@ -283,14 +278,14 @@ void Wallet::export_view_only(const std::string &export_path) { bool Wallet::operator==(const Wallet &other) const { return m_view_public_key == other.m_view_public_key && m_view_secret_key == other.m_view_secret_key && - m_creation_timestamp == other.m_creation_timestamp && m_wallet_records == other.m_wallet_records; + m_oldest_timestamp == other.m_oldest_timestamp && m_wallet_records == other.m_wallet_records; } std::pair Wallet::generate_new_address(const SecretKey &sk, Timestamp ct) { WalletRecord record{}; record.creation_timestamp = ct; if (sk == SecretKey{}) - crypto::random_keys(record.spend_public_key, record.spend_secret_key); + crypto::random_keypair(record.spend_public_key, record.spend_secret_key); else { record.spend_secret_key = sk; if (!secret_key_to_public_key(sk, record.spend_public_key)) @@ -337,10 +332,10 @@ std::vector Wallet::generate_new_addresses(const std::vector m_wallet_records; - Timestamp m_creation_timestamp = 0; - Timestamp m_oldest_timestamp = std::numeric_limits::max(); + // Timestamp m_creation_timestamp = 0; + Timestamp m_oldest_timestamp = std::numeric_limits::max(); Hash m_seed; // Main seed, never used directly Hash m_tx_derivation_seed; // Hashed from seed diff --git a/src/Core/WalletNode.cpp b/src/Core/WalletNode.cpp index ae7cdba6..e3323881 100644 --- a/src/Core/WalletNode.cpp +++ b/src/Core/WalletNode.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "WalletNode.hpp" #include "Config.hpp" @@ -12,20 +12,18 @@ using namespace bytecoin; -WalletNode::HandlersMap WalletNode::m_jsonrpc3_handlers = { - {api::walletd::GetStatus::method(), json_rpc::makeMemberMethodSeria(&WalletNode::handle_get_status3)}, - {api::walletd::GetAddresses::method(), json_rpc::makeMemberMethodSeria(&WalletNode::handle_get_addresses3)}, - {api::walletd::CreateAddresses::method(), - json_rpc::makeMemberMethodSeria(&WalletNode::handle_create_address_list3)}, - {api::walletd::GetViewKeyPair::method(), json_rpc::makeMemberMethodSeria(&WalletNode::handle_get_view_key3)}, - {api::walletd::GetBalance::method(), json_rpc::makeMemberMethodSeria(&WalletNode::handle_get_balance3)}, - {api::walletd::GetUnspents::method(), json_rpc::makeMemberMethodSeria(&WalletNode::handle_get_unspent3)}, - {api::walletd::GetTransfers::method(), json_rpc::makeMemberMethodSeria(&WalletNode::handle_get_transfers3)}, - {api::walletd::CreateTransaction::method(), - json_rpc::makeMemberMethodSeria(&WalletNode::handle_create_transaction3)}, - {api::walletd::SendTransaction::method(), json_rpc::makeMemberMethodSeria(&WalletNode::handle_send_transaction3)}, - {api::walletd::CreateSendProof::method(), json_rpc::makeMemberMethodSeria(&WalletNode::handle_create_send_proof3)}, - {api::walletd::GetTransaction::method(), json_rpc::makeMemberMethodSeria(&WalletNode::handle_get_transaction3)}}; +const WalletNode::HandlersMap WalletNode::m_jsonrpc3_handlers = { + {api::walletd::GetStatus::method(), json_rpc::makeMemberMethod(&WalletNode::handle_get_status3)}, + {api::walletd::GetAddresses::method(), json_rpc::makeMemberMethod(&WalletNode::handle_get_addresses3)}, + {api::walletd::CreateAddresses::method(), json_rpc::makeMemberMethod(&WalletNode::handle_create_address_list3)}, + {api::walletd::GetViewKeyPair::method(), json_rpc::makeMemberMethod(&WalletNode::handle_get_view_key3)}, + {api::walletd::GetBalance::method(), json_rpc::makeMemberMethod(&WalletNode::handle_get_balance3)}, + {api::walletd::GetUnspents::method(), json_rpc::makeMemberMethod(&WalletNode::handle_get_unspent3)}, + {api::walletd::GetTransfers::method(), json_rpc::makeMemberMethod(&WalletNode::handle_get_transfers3)}, + {api::walletd::CreateTransaction::method(), json_rpc::makeMemberMethod(&WalletNode::handle_create_transaction3)}, + {api::walletd::SendTransaction::method(), json_rpc::makeMemberMethod(&WalletNode::handle_send_transaction3)}, + {api::walletd::CreateSendProof::method(), json_rpc::makeMemberMethod(&WalletNode::handle_create_send_proof3)}, + {api::walletd::GetTransaction::method(), json_rpc::makeMemberMethod(&WalletNode::handle_get_transaction3)}}; WalletNode::WalletNode(Node *inproc_node, logging::ILogger &log, const Config &config, WalletState &wallet_state) : WalletSync(log, config, wallet_state, std::bind(&WalletNode::advance_long_poll, this)) @@ -48,10 +46,11 @@ bool WalletNode::on_api_http_request(http::Client *who, http::RequestData &&requ return m_inproc_node->process_json_rpc_request(who, std::move(request), response); m_log(logging::INFO) << "http_request node tunneling url=" << request.r.uri << std::endl; http::RequestData original_request; - original_request.r = request.r; - request.r.http_version_major = 1; - request.r.http_version_minor = 1; - request.r.keep_alive = true; + original_request.r = request.r; + request.r.http_version_major = 1; + request.r.http_version_minor = 1; + request.r.keep_alive = true; + request.r.basic_authorization = m_config.bytecoind_authorization; add_waiting_command(who, std::move(original_request), json_rpc::OptionalJsonValue{}, std::move(request), [=](const WaitingClient &wc, http::ResponseData &&send_response) mutable { send_response.r.http_version_major = wc.original_request.r.http_version_major; @@ -60,6 +59,14 @@ bool WalletNode::on_api_http_request(http::Client *who, http::RequestData &&requ // bytecoind never sends connection-close, so we are safe to retain all // headers wc.original_who->write(std::move(send_response)); + }, + [=](const WaitingClient &wc, std::string err) { + http::ResponseData send_response; + send_response.r.http_version_major = wc.original_request.r.http_version_major; + send_response.r.http_version_minor = wc.original_request.r.http_version_minor; + send_response.r.keep_alive = wc.original_request.r.keep_alive; + send_response.r.status = 504; // TODO -test this code path + wc.original_who->write(std::move(send_response)); }); return false; } @@ -136,6 +143,7 @@ api::walletd::GetStatus::Response WalletNode::createStatusResponse3() const { response.top_block_timestamp = m_wallet_state.get_currency().genesis_block_template.timestamp; } response.transaction_pool_version = m_wallet_state.get_tx_pool_version(); + response.lower_level_error = m_sync_error; return response; } @@ -386,49 +394,39 @@ bool WalletNode::handle_create_transaction3(http::Client *who, http::RequestData http::RequestData new_request = json_rpc::create_request(api::bytecoind::url(), api::bytecoind::GetRandomOutputs::method(), ra_request); add_waiting_command(who, std::move(raw_request), raw_js_request.get_id(), std::move(new_request), - [=](WaitingClient &&wc, const http::ResponseData &random_response) mutable { - try { - m_log(logging::INFO) << "got random response" << std::endl; - Transaction tx{}; - api::walletd::CreateTransaction::Response last_response; - Hash tx_hash{}; - json_rpc::Response json_resp(random_response.body); - api::bytecoind::GetRandomOutputs::Response ra_response; - json_resp.get_result(ra_response); - std::unordered_map single_record = - m_wallet_state.get_wallet().get_single_record(spend_addr); - selector.add_mixed_inputs(m_wallet_state.get_wallet().get_view_secret_key(), - request.any_spend_address ? m_wallet_state.get_wallet().get_records() : single_record, builder, - request.transaction.anonymity, std::move(ra_response)); - tx = builder.sign(m_wallet_state.get_wallet().get_tx_derivation_seed()); - last_response.binary_transaction = seria::to_binary(tx); - tx_hash = get_transaction_hash(tx); - if (request.save_history && !m_wallet_state.get_wallet().save_history(tx_hash, history)) { - m_log(logging::ERROR) << "Saving transaction history failed, proof " - "of sending will not be available for tx=" - << common::pod_to_hex(tx_hash) << std::endl; - last_response.save_history_error = true; - } - if (!m_wallet_state.parse_raw_transaction(last_response.transaction, tx, tx_hash)) { - // TODO - process error - } - // m_log(logging::INFO) << "Replying with - // error" - //<< std::endl; - // last_response.transaction_hash = tx_hash; - http::ResponseData last_http_response = - json_rpc::create_response(wc.original_request, last_response, wc.original_jsonrpc_id); - wc.original_who->write(std::move(last_http_response)); - } catch (const std::exception &ex) { - json_rpc::Response last_json_resp; - last_json_resp.set_id(wc.original_jsonrpc_id); - last_json_resp.set_error(json_rpc::Error(json_rpc::errInvalidParams, ex.what())); - http::ResponseData last_http_response(wc.original_request.r); - last_http_response.r.headers.push_back({"Content-Type", "application/json; charset=utf-8"}); - last_http_response.set_body(last_json_resp.get_body()); - last_http_response.r.status = 200; - wc.original_who->write(std::move(last_http_response)); + [=](const WaitingClient &wc, const http::ResponseData &random_response) mutable { + m_log(logging::INFO) << "got random response" << std::endl; + Transaction tx{}; + api::walletd::CreateTransaction::Response last_response; + Hash tx_hash{}; + json_rpc::Response json_resp(random_response.body); + api::bytecoind::GetRandomOutputs::Response ra_response; + json_resp.get_result(ra_response); + std::unordered_map single_record = + m_wallet_state.get_wallet().get_single_record(spend_addr); + selector.add_mixed_inputs(m_wallet_state.get_wallet().get_view_secret_key(), + request.any_spend_address ? m_wallet_state.get_wallet().get_records() : single_record, builder, + request.transaction.anonymity, std::move(ra_response)); + tx = builder.sign(m_wallet_state.get_wallet().get_tx_derivation_seed()); + last_response.binary_transaction = seria::to_binary(tx); + tx_hash = get_transaction_hash(tx); + if (request.save_history && !m_wallet_state.get_wallet().save_history(tx_hash, history)) { + m_log(logging::ERROR) << "Saving transaction history failed, proof " + "of sending will not be available for tx=" + << common::pod_to_hex(tx_hash) << std::endl; + last_response.save_history_error = true; } + if (!m_wallet_state.parse_raw_transaction(last_response.transaction, tx, tx_hash)) { + // TODO - process error + } + http::ResponseData last_http_response = + json_rpc::create_response(wc.original_request, last_response, wc.original_jsonrpc_id); + wc.original_who->write(std::move(last_http_response)); + }, + [=](const WaitingClient &wc, std::string err) mutable { + http::ResponseData last_http_response = json_rpc::create_error_response( + wc.original_request, json_rpc::Error(json_rpc::errInternalError, err), wc.original_jsonrpc_id); + wc.original_who->write(std::move(last_http_response)); }); return false; } @@ -478,13 +476,29 @@ bool WalletNode::handle_send_transaction3(http::Client *who, http::RequestData & new_request.r.set_firstline("POST", api::bytecoind::url(), 1, 1); transient_transactions_counter += 1; add_waiting_command(who, std::move(raw_request), raw_js_request.get_id(), std::move(new_request), - [=](WaitingClient &&wc2, const http::ResponseData &send_response) mutable { + [=](const WaitingClient &wc2, const http::ResponseData &send_response) mutable { + transient_transactions_counter -= 1; + try { // Manual try to prevent double decrement of transient_transactions_counter + advance_sync(); + http::ResponseData resp(send_response); + resp.r.http_version_major = wc2.original_request.r.http_version_major; + resp.r.http_version_minor = wc2.original_request.r.http_version_minor; + resp.r.keep_alive = wc2.original_request.r.keep_alive; + wc2.original_who->write(std::move(resp)); + } catch (const std::exception &ex) { + http::ResponseData resp = json_rpc::create_error_response(wc2.original_request, + json_rpc::Error(json_rpc::errInternalError, ex.what()), wc2.original_jsonrpc_id); + wc2.original_who->write(std::move(resp)); + } catch (...) { + http::ResponseData resp = json_rpc::create_error_response(wc2.original_request, + json_rpc::Error(json_rpc::errInternalError, "catch..."), wc2.original_jsonrpc_id); + wc2.original_who->write(std::move(resp)); + } + }, + [=](const WaitingClient &wc2, std::string err) { transient_transactions_counter -= 1; - advance_sync(); - http::ResponseData resp(send_response); - resp.r.http_version_major = wc2.original_request.r.http_version_major; - resp.r.http_version_minor = wc2.original_request.r.http_version_minor; - resp.r.keep_alive = wc2.original_request.r.keep_alive; + http::ResponseData resp = json_rpc::create_error_response( + wc2.original_request, json_rpc::Error(json_rpc::errInternalError, err), wc2.original_jsonrpc_id); wc2.original_who->write(std::move(resp)); }); return false; @@ -503,14 +517,31 @@ void WalletNode::process_waiting_command_response(http::ResponseData &&resp) { m_command_request.reset(); if (cli.original_who) { - auto fun = std::move(cli.fun); - fun(std::move(cli), std::move(resp)); + auto err_fun = std::move(cli.err_fun); + auto fun = std::move(cli.fun); + try { + fun(cli, std::move(resp)); + } catch (std::exception &ex) { + std::cout << " Parsing received waiting command leads to throw/catch what=" << ex.what() << std::endl; + err_fun(cli, ex.what()); + } catch (...) { + std::cout << " Parsing received waiting command leads to throw/catch" << std::endl; + err_fun(cli, "catch ..."); + } } send_next_waiting_command(); } void WalletNode::process_waiting_command_error(std::string err) { - // TODO - on error processing waiting command... + WaitingClient cli = std::move(m_waiting_command_requests.front()); + m_waiting_command_requests.pop_front(); + m_command_request.reset(); + + if (cli.original_who) { + auto err_fun = std::move(cli.err_fun); + err_fun(cli, err); + } + send_next_waiting_command(); } void WalletNode::send_next_waiting_command() { @@ -524,12 +555,14 @@ void WalletNode::send_next_waiting_command() { void WalletNode::add_waiting_command(http::Client *who, http::RequestData &&original_request, const json_rpc::OptionalJsonValue &original_rpc_id, http::RequestData &&request, - std::function fun) { + std::function fun, + std::function err_fun) { WaitingClient wc2; wc2.original_who = who; wc2.original_request = std::move(original_request); wc2.original_jsonrpc_id = original_rpc_id; wc2.fun = fun; + wc2.err_fun = err_fun; wc2.request = std::move(request); m_waiting_command_requests.push_back(wc2); send_next_waiting_command(); diff --git a/src/Core/WalletNode.hpp b/src/Core/WalletNode.hpp index 2f9ec29f..efbf9fa0 100644 --- a/src/Core/WalletNode.hpp +++ b/src/Core/WalletNode.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once @@ -52,12 +52,14 @@ class WalletNode : public WalletSync { http::RequestData request; http::RequestData original_request; json_rpc::OptionalJsonValue original_jsonrpc_id; - std::function fun; + std::function fun; + std::function err_fun; }; std::deque m_waiting_command_requests; void add_waiting_command(http::Client *who, http::RequestData &&original_request, const json_rpc::OptionalJsonValue &original_rpc_id, http::RequestData &&request, - std::function fun); + std::function fun, + std::function err_fun); void send_next_waiting_command(); void process_waiting_command_response(http::ResponseData &&resp); void process_waiting_command_error(std::string err); @@ -72,7 +74,7 @@ class WalletNode : public WalletSync { void advance_long_poll(); typedef std::unordered_map HandlersMap; - static HandlersMap m_jsonrpc3_handlers; + static const HandlersMap m_jsonrpc3_handlers; api::walletd::GetStatus::Response createStatusResponse3() const; diff --git a/src/Core/WalletSerializationV1.cpp b/src/Core/WalletSerializationV1.cpp index c684db82..f7e4492c 100644 --- a/src/Core/WalletSerializationV1.cpp +++ b/src/Core/WalletSerializationV1.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "WalletSerializationV1.h" #include diff --git a/src/Core/WalletSerializationV1.h b/src/Core/WalletSerializationV1.h index ea788745..c3c708be 100644 --- a/src/Core/WalletSerializationV1.h +++ b/src/Core/WalletSerializationV1.h @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once @@ -14,8 +14,7 @@ class WalletSerializerV1 { public: WalletSerializerV1( // ITransfersObserver& transfersObserver, - crypto::PublicKey &view_public_key, - crypto::SecretKey &view_secret_key, + crypto::PublicKey &view_public_key, crypto::SecretKey &view_secret_key, // uint64_t &actual_balance, // uint64_t &pending_palance, std::vector &wallets_container @@ -52,18 +51,27 @@ class WalletSerializerV1 { void load_wallets(common::IInputStream &source, CryptoContext &); // void subscribeWallets(); // void load_balances(common::IInputStream &source, CryptoContext &); - // void loadTransfersSynchronizer(common::IInputStream& source, CryptoContext& cryptoContext); - // void loadObsoleteSpentOutputs(common::IInputStream& source, CryptoContext& cryptoContext); - // void loadUnlockTransactionsJobs(common::IInputStream& source, CryptoContext& cryptoContext); - // void loadObsoleteChange(common::IInputStream& source, CryptoContext& cryptoContext); - // void loadUncommitedTransactions(common::IInputStream& source, CryptoContext& cryptoContext); - // void loadTransactions(common::IInputStream& source, CryptoContext& cryptoContext); - // void loadTransfers(common::IInputStream& source, CryptoContext& cryptoContext, uint32_t version); + // void loadTransfersSynchronizer(common::IInputStream& source, + // CryptoContext& cryptoContext); + // void loadObsoleteSpentOutputs(common::IInputStream& source, CryptoContext& + // cryptoContext); + // void loadUnlockTransactionsJobs(common::IInputStream& source, + // CryptoContext& cryptoContext); + // void loadObsoleteChange(common::IInputStream& source, CryptoContext& + // cryptoContext); + // void loadUncommitedTransactions(common::IInputStream& source, + // CryptoContext& cryptoContext); + // void loadTransactions(common::IInputStream& source, CryptoContext& + // cryptoContext); + // void loadTransfers(common::IInputStream& source, CryptoContext& + // cryptoContext, uint32_t version); void load_wallet_v1_keys(seria::ISeria &s); // void loadWalletV1Details(BinaryInputStreamSerializer& serializer); - // void add_wallet_v1_details(const std::vector &txs, - // const std::vector &trs); + // void add_wallet_v1_details(const std::vector + //&txs, + // const std::vector + //&trs); // void resetCachedBalance(); // void updateTransactionsBaseStatus(); // void updateTransfersSign(); diff --git a/src/Core/WalletState.cpp b/src/Core/WalletState.cpp index d3315ec7..da6a872d 100644 --- a/src/Core/WalletState.cpp +++ b/src/Core/WalletState.cpp @@ -1,17 +1,18 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "WalletState.hpp" #include "Config.hpp" #include "CryptoNoteTools.hpp" #include "TransactionBuilder.hpp" #include "TransactionExtra.hpp" +#include "common/string.hpp" #include "crypto/crypto.hpp" #include "seria/BinaryInputStream.hpp" #include "seria/KVBinaryInputStream.hpp" #include "seria/KVBinaryOutputStream.hpp" -static const std::string version_current = "1"; +static const std::string version_current = "2"; static const std::string TRANSACTION_PREFIX = "tn/"; static const std::string HEIGHT_TRANSACTION_PREFIX = "htn/"; @@ -154,7 +155,7 @@ PreparedWalletBlock WalletPreparatorMulticore::get_ready_work(Height height) { template std::string toBinaryKey(const T &s) { static_assert(std::is_standard_layout::value, "T must be Standard Layout"); - return WalletState::DB::to_binary_key((const unsigned char *)&s, sizeof(s)); + return common::to_hex(&s, sizeof(s)); // WalletState::DB::to_binary_key((const unsigned char *)&s, sizeof(s)); } void WalletState::DeltaState::redo_transaction( @@ -255,8 +256,9 @@ WalletState::WalletState(Wallet &wallet, logging::ILogger &log, const Config &co , m_currency(currency) , m_log(log) , m_wallet(wallet) - , m_db(config.get_coin_directory("wallet_cache") + "/" + wallet.get_cache_name(), + , m_db(config.get_data_folder("wallet_cache") + "/" + wallet.get_cache_name(), 0x2000000000) // 128 gb + , log_redo_block(std::chrono::steady_clock::now()) , m_memory_state(0, 0) { std::string version; m_db.get("$version", version); @@ -289,7 +291,7 @@ void WalletState::wallet_addresses_updated() { std::string st; if (!m_db.get(keyuns, st) || wa.creation_timestamp < boost::lexical_cast(st)) { undo_timestamp = std::min(undo_timestamp, wa.creation_timestamp); - m_db.put(keyuns, std::to_string(wa.creation_timestamp), false); + m_db.put(keyuns, common::to_string(wa.creation_timestamp), false); } } // We never delete from ADDRESSES_PREFIX index, because it correctly reflects @@ -321,7 +323,7 @@ std::vector WalletState::generate_new_addresses(const std::vector< if (!m_db.get(keyuns, st) || wa.creation_timestamp < boost::lexical_cast(st)) { if (sks.at(i) != SecretKey{}) // Newly generated addresses never lead to undo undo_timestamp = std::min(undo_timestamp, wa.creation_timestamp); - m_db.put(keyuns, std::to_string(wa.creation_timestamp), false); + m_db.put(keyuns, common::to_string(wa.creation_timestamp), false); } } if (undo_timestamp == std::numeric_limits::max()) { @@ -400,6 +402,12 @@ bool WalletState::sync_with_blockchain(api::bytecoind::SyncBlocks::Response &res // pb(std::move(resp.blocks.at(bin).block), // m_wallet.get_view_secret_key()); redo_block(header, pb, block_gi, m_tip_height + 1); + auto now = std::chrono::steady_clock::now(); + if (std::chrono::duration_cast(now - log_redo_block).count() > 1000) { + log_redo_block = now; + std::cout << "WalletState redo block, height=" << m_tip_height << "/" + << resp.status.top_known_block_height << std::endl; + } } push_chain(header); m_tx_pool_version = 1; @@ -532,7 +540,12 @@ bool WalletState::redo_block(const api::BlockHeader &header, const PreparedWalle header.hash, pb.header.timestamp)) { } // just ignore } - delta_state.apply(this); + try { + delta_state.apply(this); + } catch (const std::exception &ex) { + std::cout << "Exception in delta_state.apply, probably out of disk space ex.what=" << ex.what() << std::endl; + std::exit(api::BYTECOIND_DATABASE_ERROR); + } if (our_block) { // AccountPublicAddress address{wallet.getRecords().begin()->first, // wallet.getViewPublicKey()}; @@ -544,31 +557,37 @@ bool WalletState::redo_block(const api::BlockHeader &header, const PreparedWalle } void WalletState::undo_block(Height height) { - auto prefix = HEIGHT_KEYIMAGE_PREFIX + DB::to_ascending_key(height) + "/"; - for (DB::Cursor cur = m_db.begin(prefix); !cur.end(); cur.erase()) { - KeyImage ki; - DB::from_binary_key(cur.get_suffix(), 0, ki.data, sizeof(ki.data)); - undo_height_keyimage(height, ki); - } - prefix = HEIGHT_OUTPUT_PREFIX + DB::to_ascending_key(height) + "/"; - for (DB::Cursor cur = m_db.begin(prefix); !cur.end(); cur.erase()) { - api::Output output; - seria::from_binary(output, cur.get_value_array()); - undo_keyimage_output(output); - } - // Undo history here - prefix = HEIGHT_TRANSACTION_PREFIX + DB::to_ascending_key(height) + "/"; - for (DB::Cursor cur = m_db.begin(prefix); !cur.end(); cur.erase()) { - Hash tid; - DB::from_binary_key(cur.get_suffix(), 0, tid.data, sizeof(tid.data)); - undo_transaction(height, tid); - } + try { + auto prefix = HEIGHT_KEYIMAGE_PREFIX + DB::to_ascending_key(height) + "/"; + for (DB::Cursor cur = m_db.begin(prefix); !cur.end(); cur.erase()) { + KeyImage ki; + DB::from_binary_key(cur.get_suffix(), 0, ki.data, sizeof(ki.data)); + undo_height_keyimage(height, ki); + } + prefix = HEIGHT_OUTPUT_PREFIX + DB::to_ascending_key(height) + "/"; + for (DB::Cursor cur = m_db.begin(prefix); !cur.end(); cur.erase()) { + api::Output output; + seria::from_binary(output, cur.get_value_array()); + undo_keyimage_output(output); + } + // Undo history here + prefix = HEIGHT_TRANSACTION_PREFIX + DB::to_ascending_key(height) + "/"; + for (DB::Cursor cur = m_db.begin(prefix); !cur.end(); cur.erase()) { + Hash tid; + DB::from_binary_key(cur.get_suffix(), 0, tid.data, sizeof(tid.data)); + undo_transaction(height, tid); + } - api::BlockHeader prev_header; - if (!read_chain(height - 1, prev_header)) - return; // If we are just undone tail block, there should be no outputs, so - // nothing to lock - lock_unlock(height - 1, height, prev_header.timestamp_unlock, m_tip.timestamp_unlock, true); + api::BlockHeader prev_header; + if (!read_chain(height - 1, prev_header)) + return; // If we are just undone tail block, there should be no outputs, so + // nothing to lock + lock_unlock(height - 1, height, prev_header.timestamp_unlock, m_tip.timestamp_unlock, true); + } catch (const std::exception &ex) { + std::cout << "Exception in WalletState undo_block, probably out of disk space ex.what=" << ex.what() + << std::endl; + std::exit(api::BYTECOIND_DATABASE_ERROR); + } } bool WalletState::parse_raw_transaction(api::Transaction &ptx, const TransactionPrefix &tx, Hash tid) const { @@ -756,21 +775,14 @@ bool WalletState::redo_transaction(const PreparedWalletTransaction &pwtx, const return true; } -void WalletState::undo_transaction(const TransactionPrefix &) {} - bool WalletState::read_tips() { BinaryArray rb; if (!m_db.get("$genesis_bid", rb)) return false; Hash other_genesis_bid; seria::from_binary(other_genesis_bid, rb); - if (m_genesis_bid != other_genesis_bid) - throw std::runtime_error("Database holds different genesis bid"); // TODO - - // return - // error - // or - // clear - // DB + if (m_genesis_bid != other_genesis_bid) // TODO - return error or clear DB + throw std::runtime_error("Database holds different genesis bid"); std::string val1; if (!m_db.get("$tip_height", val1)) throw std::logic_error("Database holds no tip_height"); @@ -786,9 +798,9 @@ void WalletState::push_chain(const api::BlockHeader &header) { m_tip_height += 1; BinaryArray ba = seria::to_binary(header); m_db.put(TIP_CHAIN_PREFIX + DB::to_ascending_key(m_tip_height), ba, true); - m_db.put("$tip_height", std::to_string(m_tip_height), false); + m_db.put("$tip_height", common::to_string(m_tip_height), false); m_tip = header; - m_db.put("$tail_height", std::to_string(m_tail_height), false); + m_db.put("$tail_height", common::to_string(m_tail_height), false); m_memory_state.set_height(m_tip_height + 1); } @@ -797,7 +809,7 @@ void WalletState::pop_chain() { throw std::logic_error("pop_chain tip_height == -1"); m_db.del(TIP_CHAIN_PREFIX + DB::to_ascending_key(m_tip_height), true); m_tip_height -= 1; - m_db.put("$tip_height", std::to_string(m_tip_height), false); + m_db.put("$tip_height", common::to_string(m_tip_height), false); m_tip = (m_tip_height + 1 == m_tail_height) ? api::BlockHeader{} : read_chain(m_tip_height); } @@ -844,7 +856,7 @@ void WalletState::undo_transaction(Height height, const Hash &tid) { BinaryArray data; if (!m_db.get(trkey, data)) throw std::logic_error("Invariant dead - transaction does not exist in undo_transaction"); - std::pair pa; + std::pair pa; seria::from_binary(pa, data); m_db.del(trkey, true); // db.del(hetrkey, true); // Will be deleted during iteration @@ -867,26 +879,30 @@ void WalletState::add_to_lock_index(const api::Output &output) { std::string unkey; uint32_t clamped_unlock_time = static_cast(std::min(output.unlock_time, 0xFFFFFFFF)); if (m_currency.is_transaction_spend_time_block(output.unlock_time)) - unkey = UNLOCK_BLOCK_PREFIX + DB::to_ascending_key(clamped_unlock_time) + "/" + std::to_string(output.amount) + - "/" + std::to_string(output.global_index); + unkey = UNLOCK_BLOCK_PREFIX + DB::to_ascending_key(clamped_unlock_time) + "/" + + common::to_string(output.amount) + "/" + common::to_string(output.global_index); else - unkey = UNLOCK_TIME_PREFIX + DB::to_ascending_key(clamped_unlock_time) + "/" + std::to_string(output.amount) + - "/" + std::to_string(output.global_index); + unkey = UNLOCK_TIME_PREFIX + DB::to_ascending_key(clamped_unlock_time) + "/" + + common::to_string(output.amount) + "/" + common::to_string(output.global_index); m_db.put(unkey, ba, true); } -void WalletState::remove_from_lock_index(const api::Output &output) { +bool WalletState::remove_from_lock_index(const api::Output &output, bool mustexist) { // std::cout << "Unlock am=" << output.amount / 1E8 << " gi=" << // output.global_index << " un=" << output.unlock_time << std::endl; std::string unkey; uint32_t clamped_unlock_time = static_cast(std::min(output.unlock_time, 0xFFFFFFFF)); if (m_currency.is_transaction_spend_time_block(output.unlock_time)) - unkey = UNLOCK_BLOCK_PREFIX + DB::to_ascending_key(clamped_unlock_time) + "/" + std::to_string(output.amount) + - "/" + std::to_string(output.global_index); + unkey = UNLOCK_BLOCK_PREFIX + DB::to_ascending_key(clamped_unlock_time) + "/" + + common::to_string(output.amount) + "/" + common::to_string(output.global_index); else - unkey = UNLOCK_TIME_PREFIX + DB::to_ascending_key(clamped_unlock_time) + "/" + std::to_string(output.amount) + - "/" + std::to_string(output.global_index); + unkey = UNLOCK_TIME_PREFIX + DB::to_ascending_key(clamped_unlock_time) + "/" + + common::to_string(output.amount) + "/" + common::to_string(output.global_index); + std::string was_value; + if (!mustexist && !m_db.get(unkey, was_value)) + return false; m_db.del(unkey, true); + return true; } void WalletState::add_to_unspent_index(const api::Output &output) { @@ -896,12 +912,12 @@ void WalletState::add_to_unspent_index(const api::Output &output) { // << " un=" << output.unlock_time << std::endl; modify_balance(output, 0, 1); auto keyuns = UNSPENT_HEIGHT_PREFIX + output.address + "/" + DB::to_ascending_key(output.height) + "/" + - std::to_string(output.amount) + "/" + std::to_string(output.global_index); + common::to_string(output.amount) + "/" + common::to_string(output.global_index); BinaryArray ba2 = seria::to_binary(output); m_db.put(keyuns, ba2, true); auto hekeyuns = HEIGHT_UNSPENT_PREFIX + DB::to_ascending_key(output.height) + "/" + output.address + "/" + - std::to_string(output.amount) + "/" + std::to_string(output.global_index); + common::to_string(output.amount) + "/" + common::to_string(output.global_index); m_db.put(hekeyuns, ba2, true); } @@ -912,17 +928,17 @@ void WalletState::remove_from_unspent_index(const api::Output &output) { // << " un=" << output.unlock_time << std::endl; modify_balance(output, 0, -1); auto keyuns = UNSPENT_HEIGHT_PREFIX + output.address + "/" + DB::to_ascending_key(output.height) + "/" + - std::to_string(output.amount) + "/" + std::to_string(output.global_index); + common::to_string(output.amount) + "/" + common::to_string(output.global_index); m_db.del(keyuns, true); auto hekeyuns = HEIGHT_UNSPENT_PREFIX + DB::to_ascending_key(output.height) + "/" + output.address + "/" + - std::to_string(output.amount) + "/" + std::to_string(output.global_index); + common::to_string(output.amount) + "/" + common::to_string(output.global_index); m_db.del(hekeyuns, true); } bool WalletState::is_unspent(const api::Output &output) const { BinaryArray ba = seria::to_binary(output); auto keyuns = UNSPENT_HEIGHT_PREFIX + output.address + "/" + DB::to_ascending_key(output.height) + "/" + - std::to_string(output.amount) + "/" + std::to_string(output.global_index); + common::to_string(output.amount) + "/" + common::to_string(output.global_index); return m_db.get(keyuns, ba); } @@ -976,8 +992,8 @@ void WalletState::redo_keyimage_output(const api::Output &output, return; } m_db.put(kikey, ba, true); - auto keyout = HEIGHT_OUTPUT_PREFIX + DB::to_ascending_key(output.height) + "/" + std::to_string(output.amount) + - "/" + std::to_string(output.global_index); + auto keyout = HEIGHT_OUTPUT_PREFIX + DB::to_ascending_key(output.height) + "/" + common::to_string(output.amount) + + "/" + common::to_string(output.global_index); m_db.put(keyout, ba, true); if (!m_currency.is_transaction_spend_time_unlocked(output.unlock_time, block_height, block_unlock_timestamp)) { @@ -1007,7 +1023,7 @@ void WalletState::undo_keyimage_output(const api::Output &output) { if (!m_currency.is_transaction_spend_time_unlocked(output.unlock_time, m_tip_height, m_tip.timestamp_unlock)) { modify_balance(output, -1, 0); - remove_from_lock_index(output); + remove_from_lock_index(output, true); return; } remove_from_unspent_index(output); // We remove height_unspent during iteration @@ -1060,18 +1076,16 @@ void WalletState::redo_height_keyimage(Height height, const KeyImage &keyimage) seria::from_binary(output, rb); // Code below is used temporarily to allow spending locked outputs (due to - // changes to unlock code in new - // version) + // changes to unlock code in new version) auto keyuns = UNSPENT_HEIGHT_PREFIX + output.address + "/" + DB::to_ascending_key(output.height) + "/" + - std::to_string(output.amount) + "/" + std::to_string(output.global_index); + common::to_string(output.amount) + "/" + common::to_string(output.global_index); bool was_unlocked = m_db.get(keyuns, rb); if (was_unlocked) remove_from_unspent_index(output); - if (output.unlock_time != 0) - remove_from_lock_index(output); + bool was_in_lockindex = remove_from_lock_index(output, false); auto hekey = HEIGHT_KEYIMAGE_PREFIX + DB::to_ascending_key(height) + "/" + toBinaryKey(keyimage); - m_db.put(hekey, seria::to_binary(was_unlocked), true); + m_db.put(hekey, seria::to_binary(std::make_pair(was_unlocked, was_in_lockindex)), true); } } @@ -1083,15 +1097,15 @@ void WalletState::undo_height_keyimage(Height height, const KeyImage &keyimage) throw std::logic_error("Invariant dead undo_height_keyimage keyimage does not exist"); api::Output output; seria::from_binary(output, rb); - if (output.unlock_time != 0) - add_to_lock_index(output); auto hekey = HEIGHT_KEYIMAGE_PREFIX + DB::to_ascending_key(height) + "/" + toBinaryKey(keyimage); BinaryArray ba; m_db.get(hekey, ba); - bool was_unlocked = true; - seria::from_binary(was_unlocked, ba); + std::pair was_unlocked_was_in_lockindex{}; + seria::from_binary(was_unlocked_was_in_lockindex, ba); - if (was_unlocked) + if (was_unlocked_was_in_lockindex.second) + add_to_lock_index(output); + if (was_unlocked_was_in_lockindex.first) add_to_unspent_index(output); // auto hekey = HEIGHT_KEYIMAGE_PREFIX + DB::to_ascending_key(height) + "/" //+ DB::to_binary_key(keyimage.data, @@ -1144,7 +1158,7 @@ std::vector WalletState::api_get_locked_or_unconfirmed_unspent(cons auto prefix = HEIGHT_UNSPENT_PREFIX; if (!address.empty()) prefix = UNSPENT_HEIGHT_PREFIX + address + "/"; - std::string middle = std::to_string(height + 1) + "/"; + std::string middle = common::to_string(height + 1) + "/"; for (DB::Cursor cur = m_db.begin(prefix, middle); !cur.end(); cur.next()) { std::string shei, rest; if (!common::split_string(cur.get_suffix(), "/", shei, rest)) @@ -1216,7 +1230,7 @@ bool WalletState::api_get_transaction(Hash tid, TransactionPrefix &tx, api::Tran BinaryArray data; if (!m_db.get(trkey, data)) return false; - std::pair pa; + std::pair pa; seria::from_binary(pa, data); tx = std::move(pa.first); ptx = std::move(pa.second); @@ -1274,6 +1288,8 @@ std::map, api::Output> WalletState::api_get_unlocked Height from_height, Height to_height) const { std::map, api::Output> locked; + if (m_tip_height + 1 == m_tail_height) + return locked; if (from_height >= to_height || from_height > m_tip_height || to_height <= m_tail_height) return locked; read_unlock_index(locked, UNLOCK_BLOCK_PREFIX, from_height, to_height); @@ -1286,35 +1302,6 @@ std::map, api::Output> WalletState::api_get_unlocked return locked; } -std::vector WalletState::api_list_history( - const std::string &address, Hash start_transaction, size_t max_count) const { - std::vector result; - auto trkey = TRANSACTION_PREFIX + toBinaryKey(start_transaction); - BinaryArray ba; - std::pair pa; - if (m_db.get(trkey, ba)) - seria::from_binary(pa, ba); - const api::Transaction &ptx = pa.second; - auto prefix = HEIGHT_TRANSACTION_PREFIX; - std::string middle; - if (ptx.block_height != 0) // Found transcation - middle = DB::to_ascending_key(ptx.block_height) + "/" + toBinaryKey(start_transaction); - if (!address.empty()) - prefix = ADDRESS_HEIGHT_TRANSACTION_PREFIX + address + "/"; - api::Block current_block; - DB::Cursor cur = m_db.rbegin(prefix, middle); - if (!cur.end() && ptx.block_height != 0) - cur.next(); // Skip start transaction - for (; !cur.end(); cur.next()) { - if (result.size() > max_count) - break; - std::pair pa2; - seria::from_binary(pa2, cur.get_value_array()); - result.push_back(pa2.second); - } - return result; -} - api::Balance WalletState::get_balance(const std::string &address, Height height) const { auto bakey = BALANCE_PREFIX; if (!address.empty()) diff --git a/src/Core/WalletState.hpp b/src/Core/WalletState.hpp index 03cd481f..1006e391 100644 --- a/src/Core/WalletState.hpp +++ b/src/Core/WalletState.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once @@ -137,8 +137,6 @@ class WalletState : private IWalletState { api::Block api_get_pool_as_history(const std::string &address) const; std::map, api::Output> api_get_unlocked_outputs( const std::string &address, Height from_height, Height to_height = std::numeric_limits::max()) const; - std::vector api_list_history(const std::string &address, Hash start_transaction, - size_t max_count = std::numeric_limits::max()) const; std::vector api_get_unspent( const std::string &address, Height height, Amount max_amount = std::numeric_limits::max()) const; std::vector api_get_locked_or_unconfirmed_unspent(const std::string &address, Height height) const; @@ -167,7 +165,6 @@ class WalletState : private IWalletState { Timestamp block_unlock_timestamp) const; bool redo_transaction(const PreparedWalletTransaction &pwtx, const std::vector &global_indices, DeltaState *delta_state, bool is_base, Hash tid, Hash bid, Timestamp tx_timestamp); - void undo_transaction(const TransactionPrefix &tx); void read_unlock_index(std::map, api::Output> &add, const std::string &index_prefix, uint32_t begin, uint32_t end) const; void lock_unlock(Height prev_height, Height now_height, Timestamp prev, Timestamp now, bool lock); @@ -175,7 +172,7 @@ class WalletState : private IWalletState { void remove_from_unspent_index(const api::Output &); bool is_unspent(const api::Output &) const; void add_to_lock_index(const api::Output &); - void remove_from_lock_index(const api::Output &); + bool remove_from_lock_index(const api::Output &, bool mustexist); virtual void redo_transaction( Height, const Hash &tid, const TransactionPrefix &tx, const api::Transaction &ptx) override; @@ -202,6 +199,7 @@ class WalletState : private IWalletState { Height m_tail_height = 0; api::BlockHeader m_tip; uint32_t m_tx_pool_version = 1; + std::chrono::steady_clock::time_point log_redo_block; bool read_tips(); void push_chain(const api::BlockHeader &); diff --git a/src/Core/WalletSync.cpp b/src/Core/WalletSync.cpp index 1683fff0..e86b7f66 100644 --- a/src/Core/WalletSync.cpp +++ b/src/Core/WalletSync.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "WalletSync.hpp" #include "Config.hpp" @@ -20,6 +20,7 @@ WalletSync::WalletSync( : m_state_changed_handler(state_changed_handler) , m_log(log, "WalletSync") , m_config(config) + , m_sync_error("CONNECTING") , m_status_timer(std::bind(&WalletSync::send_get_status, this)) , m_sync_agent(config.bytecoind_remote_ip, config.bytecoind_remote_port ? config.bytecoind_remote_port : config.bytecoind_bind_port) @@ -27,7 +28,6 @@ WalletSync::WalletSync( config.bytecoind_remote_port ? config.bytecoind_remote_port : config.bytecoind_bind_port) , m_wallet_state(wallet_state) , m_commit_timer(std::bind(&WalletSync::db_commit, this)) { - m_sync_error = "CONNECTING"; advance_sync(); m_commit_timer.once(DB_COMMIT_PERIOD_WALLET_CACHE); } @@ -38,6 +38,7 @@ void WalletSync::send_get_status() { req.transaction_pool_version = m_wallet_state.get_tx_pool_version(); req.outgoing_peer_count = m_last_node_status.outgoing_peer_count; req.incoming_peer_count = m_last_node_status.incoming_peer_count; + req.lower_level_error = m_last_node_status.lower_level_error; json_rpc::Request json_send_raw_req; json_send_raw_req.set_method(api::bytecoind::GetStatus::method()); json_send_raw_req.set_params(req); @@ -49,6 +50,10 @@ void WalletSync::send_get_status() { m_sync_request.reset(new http::Request(m_sync_agent, std::move(req_header), [&](http::ResponseData &&response) { m_sync_request.reset(); + if (response.r.status == 504) { // Common for longpoll + advance_sync(); + return; + } api::bytecoind::GetStatus::Response resp; json_rpc::parse_response(response.body, resp); m_last_node_status = resp; diff --git a/src/Core/WalletSync.hpp b/src/Core/WalletSync.hpp index aca736c6..dbc77418 100644 --- a/src/Core/WalletSync.hpp +++ b/src/Core/WalletSync.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once @@ -20,11 +20,11 @@ class WalletSync { protected: const std::function m_state_changed_handler; - std::string m_sync_error; logging::LoggerRef m_log; const Config &m_config; api::bytecoind::GetStatus::Response m_last_node_status; + std::string m_sync_error; platform::Timer m_status_timer; http::Agent m_sync_agent; std::unique_ptr m_sync_request; diff --git a/src/Core/rpc_api_serialization.cpp b/src/Core/rpc_api_serialization.cpp index ce3f8252..6769cc63 100644 --- a/src/Core/rpc_api_serialization.cpp +++ b/src/Core/rpc_api_serialization.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "CryptoNoteTools.hpp" #include "TransactionExtra.hpp" @@ -261,6 +261,8 @@ void ser_members(api::BlockHeader &v, ISeria &s) { seria_kv("prev_hash", v.previous_block_hash, s); seria_kv("nonce", v.nonce, s); + // s(depth, "depth"); - Used by legacy methods, hope no one uses it + // s(orphan_status, "orphan_status"); - Used by legacy methods, hope no one uses it seria_kv("height", v.height, s); seria_kv("hash", v.hash, s); seria_kv("reward", v.reward, s); @@ -388,6 +390,7 @@ void ser_members(api::bytecoind::GetStatus::Request &v, ISeria &s) { seria_kv("transaction_pool_version", v.transaction_pool_version, s); seria_kv("outgoing_peer_count", v.outgoing_peer_count, s); seria_kv("incoming_peer_count", v.incoming_peer_count, s); + seria_kv("lower_level_error", v.lower_level_error, s); } void ser_members(api::bytecoind::GetStatus::Response &v, ISeria &s) { ser_members(static_cast(v), s); @@ -473,10 +476,24 @@ void ser_members(bytecoin::api::bytecoind::GetBlockTemplate::Response &v, ISeria void ser_members(bytecoin::api::bytecoind::GetCurrencyId::Response &v, ISeria &s) { seria_kv("currency_id_blob", v.currency_id_blob, s); } -void ser_members(bytecoin::api::bytecoind::SubmitBlockLegacy::Response &v, ISeria &s) { - seria_kv("status", v.status, s); -} +void ser_members(bytecoin::api::bytecoind::SubmitBlock::Response &v, ISeria &s) { seria_kv("status", v.status, s); } void ser_members(bytecoin::api::bytecoind::SubmitBlock::Request &v, ISeria &s) { seria_kv("blocktemplate_blob", v.blocktemplate_blob, s); } +void ser_members(bytecoin::api::bytecoind::BlockHeaderLegacy &v, ISeria &s) { + ser_members(static_cast(v), s); + seria_kv("depth", v.depth, s); + seria_kv("orphan_status", v.orphan_status, s); +} +void ser_members(bytecoin::api::bytecoind::GetLastBlockHeaderLegacy::Response &v, ISeria &s) { + seria_kv("status", v.status, s); + seria_kv("block_header", v.block_header, s); +} +void ser_members(bytecoin::api::bytecoind::GetBlockHeaderByHashLegacy::Request &v, ISeria &s) { + seria_kv("hash", v.hash, s); +} +void ser_members(bytecoin::api::bytecoind::GetBlockHeaderByHeightLegacy::Request &v, ISeria &s) { + seria_kv("height", v.height, s); +} + } // namespace seria diff --git a/src/CryptoNote.hpp b/src/CryptoNote.hpp index 2359fbc7..cc6fc5f1 100644 --- a/src/CryptoNote.hpp +++ b/src/CryptoNote.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once @@ -10,7 +10,7 @@ #include "crypto/types.hpp" // We define here, as CryptoNoteConfig.h is never included anywhere anymore -#define ALLOW_DEBUG_COMMANDS 1 +#define bytecoin_ALLOW_DEBUG_COMMANDS 1 namespace bytecoin { @@ -69,7 +69,7 @@ struct Transaction : public TransactionPrefix { std::vector> signatures; }; -struct BaseTransaction : public TransactionPrefix {}; +struct BaseTransaction : public TransactionPrefix {}; // has 'ignored' field during seria struct ParentBlock { uint8_t major_version = 0; diff --git a/src/CryptoNoteConfig.hpp b/src/CryptoNoteConfig.hpp index fcdc9adf..65fdfaaf 100644 --- a/src/CryptoNoteConfig.hpp +++ b/src/CryptoNoteConfig.hpp @@ -74,8 +74,8 @@ const uint32_t CRYPTONOTE_MEMPOOL_TX_LIVETIME = 60 * 60 * 24; // seconds, one d const uint32_t UPGRADE_HEIGHT_V2 = 1; const uint32_t UPGRADE_HEIGHT_V3 = 2; -const char CRYPTONOTE_BLOCKS_FILENAME[] = "blocks.bin"; -const char CRYPTONOTE_BLOCKINDEXES_FILENAME[] = "blockindexes.bin"; +const char CRYPTONOTE_BLOCKS_FILENAME[] = "blocksx.bin"; +const char CRYPTONOTE_BLOCKINDEXES_FILENAME[] = "blockindexesx.bin"; } // parameters const char CRYPTONOTE_NAME[] = "bitsum"; @@ -108,11 +108,9 @@ const char P2P_STAT_TRUSTED_PUB_KEY[] = "7faf1b1a49aea1f5bc50f5df7b9087b622d const char *const SEED_NODES[] = { "89.40.4.205:28080", "188.166.29.175:28080", - //"80.208.225.17:18080", - //"80.209.227.121:18080", - //"188.166.29.175:18080", - //"31.135.214.69:18080", - //"178.218.207.75:18080", + "80.209.227.121:28080", + "31.135.214.69:28080", + "178.218.207.75:28080", }; struct CheckpointData { @@ -131,12 +129,11 @@ constexpr const CheckpointData CHECKPOINTS[] = { { 80000, "ce5ed3d782c172ef872303e01c59b99869dc1d4a9e9ac00c9d2230f26fd1df51" }, { 90000, "b8805db44aed06d03278c648648727095eaf232914f8b39fdf7f11fbb39df3fd" }, { 100000, "e44dca8383873edf13ee44ca5f177a6cce6aa12e46533ce2791ecbc3b36538d1" }, - //{ 106153, "597a09b94cbfccdc532c28f668db658cb76edfcbab0151f207599488734f79c9" }, - //{ 106195, "8cdb2723b88515c57281ff73e3b30c0e924aec284528b04748a57c5f77ea0c76" }, + { 106153, "597a09b94cbfccdc532c28f668db658cb76edfcbab0151f207599488734f79c9" }, + { 106195, "8cdb2723b88515c57281ff73e3b30c0e924aec284528b04748a57c5f77ea0c76" }, { 110000, "9041572d83e741652781036bc669756cfe1568b32053789fd91f17b2b1843049" }, - //{ 114595, "e31ca73e4761e9c3b027469ce18ec5f52ab103db9ba1ca3838ea16e6a9cd04d0" }, - //{ 114700, "6254290e38946fc1a00848753ae6e3bac3027b6f9fbb77d0de232c3d58b4f9ad" }, - + { 114595, "1cf88d40550f0aee26921008296cc775d5fd9d4d3fab3b66bf9f12fe2b25d28b" }, + { 117000, "d66aff91a6fddc87974d139c1343452fb5b84917d8f8b626bd353efad82e26e2" }, }; } // CryptoNote diff --git a/src/Miner/MiningConfig.cpp b/src/Miner/MiningConfig.cpp index 77b219ca..ca605279 100644 --- a/src/Miner/MiningConfig.cpp +++ b/src/Miner/MiningConfig.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "MiningConfig.hpp" #include "common/CommandLine.hpp" @@ -18,11 +18,11 @@ MiningConfig::MiningConfig(common::CommandLine &cmd) if (const char *pa = cmd.get("--address")) mining_address = pa; if (const char *pa = cmd.get("--bytecoind-address")) { - if (!common::parse_ip_address_and_port(bytecoind_ip, bytecoind_port, pa)) + if (!common::parse_ip_address_and_port(pa, bytecoind_ip, bytecoind_port)) throw std::runtime_error("Wrong address format " + std::string(pa) + ", should be ip:port"); } if (const char *pa = cmd.get("--daemon-address", "Use --bytecoind-address instead")) { - if (!common::parse_ip_address_and_port(bytecoind_ip, bytecoind_port, pa)) + if (!common::parse_ip_address_and_port(pa, bytecoind_ip, bytecoind_port)) throw std::runtime_error("Wrong address format " + std::string(pa) + ", should be ip:port"); } if (const char *pa = cmd.get("--daemon-host", "Use --bytecoind-address instead")) diff --git a/src/Miner/MiningConfig.hpp b/src/Miner/MiningConfig.hpp index 7f002ca2..47bb6528 100644 --- a/src/Miner/MiningConfig.hpp +++ b/src/Miner/MiningConfig.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/bitsum.rc b/src/bitsum.rc index a8cfc7fe..2b7d5525 100644 --- a/src/bitsum.rc +++ b/src/bitsum.rc @@ -5,8 +5,8 @@ // 1 VERSIONINFO - FILEVERSION 0,18,3,20 - PRODUCTVERSION 0,18,3,20 + FILEVERSION 1,18,4,5 + PRODUCTVERSION 1,18,4,5 FILEFLAGSMASK 0x3fL FILEFLAGS 0x0L FILEOS 0x40004L @@ -19,12 +19,12 @@ BEGIN BEGIN VALUE "CompanyName", "Bitsum Foundation" VALUE "FileDescription", "Bitsum" - VALUE "FileVersion", "0.18.3.20 (BETA)" + VALUE "FileVersion", "1.18.4.5" VALUE "InternalName", "bitsum.rc" VALUE "LegalCopyright", "Copyright (C) Bitsum Foundation, 2018" VALUE "OriginalFilename", "bitsum.rc" VALUE "ProductName", "Bitsum" - VALUE "ProductVersion", "0.18.3.20 (BETA)" + VALUE "ProductVersion", "1.18.4.5" END END BLOCK "VarFileInfo" diff --git a/src/bitsum/bitsum.cpp b/src/bitsum/bitsum.cpp index f107df3e..346fac5f 100644 --- a/src/bitsum/bitsum.cpp +++ b/src/bitsum/bitsum.cpp @@ -14,7 +14,11 @@ using namespace bytecoin; using namespace common; -extern "C" _declspec(dllexport)int __DaemonRun() +#if defined(_WIN32) +extern "C" _declspec(dllexport) int __DaemonRun() +#else +extern "C" int __DaemonRun() +#endif { try { @@ -24,21 +28,25 @@ extern "C" _declspec(dllexport)int __DaemonRun() common::CommandLine cmd(1, 0); bytecoin::Config config(cmd); bytecoin::Currency currency(config.is_testnet); - const std::string coinFolder = config.get_coin_directory(); + const std::string coinFolder = config.get_data_folder(); - platform::ExclusiveLock coin_lock(coinFolder, "bitsum.lock"); + platform::ExclusiveLock coin_lock(coinFolder, "bitsumd.lock"); logging::LoggerManager logManager; - logManager.configure_default(config.get_coin_directory("logs"), "daemon-"); + logManager.configure_default(config.get_data_folder("logs"), "bitsumd-"); + BlockChainState block_chain(logManager, config, currency); + boost::asio::io_service io; platform::EventLoop run_loop(io); + Node node(logManager, config, block_chain); - auto idea_ms = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - idea_start); - std::cout << "Daemon started seconds=" << double(idea_ms.count()) / 1000 << std::endl; - + + auto idea_ms = + std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - idea_start); + std::cout << "bitsumd started seconds=" << double(idea_ms.count()) / 1000 << std::endl; while (!io.stopped()) { - if (node.on_idle()) // Using it to load blockchain + if (node.on_idle()) // Using it to load blockchain io.poll(); else io.run_one(); @@ -52,7 +60,11 @@ extern "C" _declspec(dllexport)int __DaemonRun() } } -extern "C" _declspec(dllexport)int __WalletRun(char path[], char password[]) +#if defined(_WIN32) +extern "C" _declspec(dllexport) int __WalletRun(char path[], char password[]) +#else +extern "C" int __WalletRun(char path[], char password[]) +#endif { common::console::UnicodeConsoleSetup console_setup; auto idea_start = std::chrono::high_resolution_clock::now(); @@ -60,14 +72,14 @@ extern "C" _declspec(dllexport)int __WalletRun(char path[], char password[]) bytecoin::Config config(cmd); bytecoin::Currency currency(config.is_testnet); - const std::string coinFolder = config.get_coin_directory(); + const std::string coinFolder = config.get_data_folder(); std::unique_ptr walletcache_lock; std::unique_ptr wallet; try { wallet = std::make_unique(path, password, false); walletcache_lock = std::make_unique( - config.get_coin_directory("wallet_cache"), wallet->get_cache_name() + ".lock"); + config.get_data_folder("wallet_cache"), wallet->get_cache_name() + ".lock"); } catch (const std::ios_base::failure &ex) { std::cout << ex.what() << std::endl; @@ -83,7 +95,7 @@ extern "C" _declspec(dllexport)int __WalletRun(char path[], char password[]) } logging::LoggerManager logManagerWalletNode; - logManagerWalletNode.configure_default(config.get_coin_directory("logs"), "wallet-"); + logManagerWalletNode.configure_default(config.get_data_folder("logs"), "wallet-"); WalletState wallet_state(*wallet, logManagerWalletNode, config, currency); boost::asio::io_service io; @@ -101,7 +113,7 @@ extern "C" _declspec(dllexport)int __WalletRun(char path[], char password[]) auto idea_ms = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - idea_start); - std::cout << "Wallet started seconds=" << double(idea_ms.count()) / 1000 << std::endl; + std::cout << "wallet-rpc started seconds=" << double(idea_ms.count()) / 1000 << std::endl; while (!io.stopped()) { if (node && node->on_idle()) // We load blockchain there @@ -113,7 +125,11 @@ extern "C" _declspec(dllexport)int __WalletRun(char path[], char password[]) return 0; } -extern "C" _declspec(dllexport)int __WalletCreateContainer(char path[], char password[]) +#if defined(_WIN32) +extern "C" _declspec(dllexport) int __WalletCreateContainer(char path[], char password[]) +#else +extern "C" int __WalletCreateContainer(char path[], char password[]) +#endif { std::unique_ptr wallet; @@ -137,7 +153,11 @@ extern "C" _declspec(dllexport)int __WalletCreateContainer(char path[], char pas } } -extern "C" _declspec(dllexport)int __WalletImportContainer(char path[], char password[], char keys[]) +#if defined(_WIN32) +extern "C" _declspec(dllexport) int __WalletImportContainer(char path[], char password[], char keys[]) +#else +extern "C" int __WalletImportContainer(char path[], char password[], char keys[]) +#endif { std::unique_ptr wallet; @@ -160,7 +180,11 @@ extern "C" _declspec(dllexport)int __WalletImportContainer(char path[], char pas } } -extern "C" _declspec(dllexport)int __WalletChangeContainerPassword(char path[], char oldPassword[], char newPassword[]) +#if defined(_WIN32) +extern "C" _declspec(dllexport) int __WalletChangeContainerPassword(char path[], char oldPassword[], char newPassword[]) +#else +extern "C" int __WalletChangeContainerPassword(char path[], char oldPassword[], char newPassword[]) +#endif { std::unique_ptr wallet; @@ -183,7 +207,11 @@ extern "C" _declspec(dllexport)int __WalletChangeContainerPassword(char path[], } } -extern "C" _declspec(dllexport)bool __CheckAddress(char address[]) +#if defined(_WIN32) +extern "C" _declspec(dllexport) bool __CheckAddress(char address[]) +#else +extern "C" bool __CheckAddress(char address[]) +#endif { BinaryArray data; uint64_t prefix = 154; diff --git a/src/common/Base58.cpp b/src/common/Base58.cpp index b77d13a7..075350c1 100644 --- a/src/common/Base58.cpp +++ b/src/common/Base58.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "Base58.hpp" diff --git a/src/common/Base58.hpp b/src/common/Base58.hpp index 04eaff64..292d1cfb 100644 --- a/src/common/Base58.hpp +++ b/src/common/Base58.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/common/Base64.cpp b/src/common/Base64.cpp new file mode 100644 index 00000000..169e2ce0 --- /dev/null +++ b/src/common/Base64.cpp @@ -0,0 +1,107 @@ +// Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. + +#include "Base64.hpp" + +#include +#include + +namespace common { +namespace base64 { + +static const uint8_t from_base64[128] = { + // 8 rows of 16 = 128 + // note: only require 123 entries, as we only lookup for <= z , which z=122 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 62, + 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 0, 255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 63, 255, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255}; + +static const char to_base64[65] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + +std::string encode(const BinaryArray &data) { + std::string ret; + const uint8_t *const buf = data.data(); + const size_t bufLen = data.size(); + // Calculate how many bytes that needs to be added to get a multiple of 3 + size_t missing = 0; + size_t ret_size = bufLen; + while ((ret_size % 3) != 0) { + ++ret_size; + ++missing; + } + + // Expand the return string size to a multiple of 4 + ret_size = 4 * ret_size / 3; + + ret.reserve(ret_size); + + for (size_t i = 0; i < ret_size / 4; ++i) { + // Read a group of three bytes (avoid buffer overrun by replacing with 0) + const size_t index = i * 3; + const uint8_t b3_0 = (index + 0 < bufLen) ? buf[index + 0] : 0; + const uint8_t b3_1 = (index + 1 < bufLen) ? buf[index + 1] : 0; + const uint8_t b3_2 = (index + 2 < bufLen) ? buf[index + 2] : 0; + + // Transform into four base 64 characters + const uint8_t b4_0 = ((b3_0 & 0xfc) >> 2); + const uint8_t b4_1 = ((b3_0 & 0x03) << 4) + ((b3_1 & 0xf0) >> 4); + const uint8_t b4_2 = ((b3_1 & 0x0f) << 2) + ((b3_2 & 0xc0) >> 6); + const uint8_t b4_3 = ((b3_2 & 0x3f) << 0); + + // Add the base 64 characters to the return value + ret.push_back(to_base64[b4_0]); + ret.push_back(to_base64[b4_1]); + ret.push_back(to_base64[b4_2]); + ret.push_back(to_base64[b4_3]); + } + + // Replace data that is invalid (always as many as there are missing bytes) + for (size_t i = 0; i != missing; ++i) + ret[ret_size - i - 1] = '='; + return ret; +} + +bool decode(const std::string &in, BinaryArray &ret) { + // Make sure the *intended* string length is a multiple of 4 + size_t encoded_size = in.size(); + + while ((encoded_size % 4) != 0) + ++encoded_size; + + const size_t N = in.size(); + ret.clear(); + ret.reserve(3 * encoded_size / 4); + + for (size_t i = 0; i < encoded_size; i += 4) { + // Get values for each group of four base 64 characters + const uint8_t b4_0 = + (static_cast(in[i + 0]) <= 'z') ? from_base64[static_cast(in[i + 0])] : 0xff; + const uint8_t b4_1 = + (i + 1 < N && static_cast(in[i + 1]) <= 'z') ? from_base64[static_cast(in[i + 1])] : 0xff; + const uint8_t b4_2 = + (i + 2 < N && static_cast(in[i + 2]) <= 'z') ? from_base64[static_cast(in[i + 2])] : 0xff; + const uint8_t b4_3 = + (i + 3 < N && static_cast(in[i + 3]) <= 'z') ? from_base64[static_cast(in[i + 3])] : 0xff; + + // Transform into a group of three bytes + const uint8_t b3_0 = ((b4_0 & 0x3f) << 2) + ((b4_1 & 0x30) >> 4); + const uint8_t b3_1 = ((b4_1 & 0x0f) << 4) + ((b4_2 & 0x3c) >> 2); + const uint8_t b3_2 = ((b4_2 & 0x03) << 6) + ((b4_3 & 0x3f) >> 0); + + // Add the byte to the return value if it isn't part of an '=' character (indicated by 0xff) + if (b4_1 != 0xff) + ret.push_back(b3_0); + if (b4_2 != 0xff) + ret.push_back(b3_1); + if (b4_3 != 0xff) + ret.push_back(b3_2); + } + return true; // TODO - find decoder which returns false on invalid data +} +} +} diff --git a/src/common/Base64.hpp b/src/common/Base64.hpp new file mode 100644 index 00000000..15047b95 --- /dev/null +++ b/src/common/Base64.hpp @@ -0,0 +1,16 @@ +// Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. + +#pragma once + +#include +#include +#include "BinaryArray.hpp" + +namespace common { +namespace base64 { + +std::string encode(const BinaryArray &data); +bool decode(const std::string &enc, BinaryArray &data); +} +} diff --git a/src/common/BinaryArray.cpp b/src/common/BinaryArray.cpp index 6f60a75c..eca1f212 100644 --- a/src/common/BinaryArray.cpp +++ b/src/common/BinaryArray.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "BinaryArray.hpp" #include diff --git a/src/common/BinaryArray.hpp b/src/common/BinaryArray.hpp index 17de07f8..0e0fb028 100644 --- a/src/common/BinaryArray.hpp +++ b/src/common/BinaryArray.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/common/CommandLine.cpp b/src/common/CommandLine.cpp index 3f3385ef..2ebabe4d 100644 --- a/src/common/CommandLine.cpp +++ b/src/common/CommandLine.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "CommandLine.hpp" #include diff --git a/src/common/CommandLine.hpp b/src/common/CommandLine.hpp index 1f7e4ce7..863bee82 100644 --- a/src/common/CommandLine.hpp +++ b/src/common/CommandLine.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/common/ConsoleTools.hpp b/src/common/ConsoleTools.hpp index f5036238..31d2764a 100644 --- a/src/common/ConsoleTools.hpp +++ b/src/common/ConsoleTools.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/common/Ipv4Address.cpp b/src/common/Ipv4Address.cpp index d2caf27b..89a2c89b 100644 --- a/src/common/Ipv4Address.cpp +++ b/src/common/Ipv4Address.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "Ipv4Address.hpp" #include @@ -34,7 +34,7 @@ std::string ip_address_and_port_to_string(uint32_t ip, uint32_t port) { return std::string(buf); } -bool parse_ip_address(uint32_t &ip, const std::string &addr) { +bool parse_ip_address(const std::string &addr, uint32_t &ip) { uint32_t v[4]{}; if (sscanf(addr.c_str(), "%u.%u.%u.%u", &v[0], &v[1], &v[2], &v[3]) != 4) { @@ -51,7 +51,7 @@ bool parse_ip_address(uint32_t &ip, const std::string &addr) { return true; } -bool parse_ip_address_and_port(uint32_t &ip, uint32_t &port, const std::string &addr) { +bool parse_ip_address_and_port(const std::string &addr, uint32_t &ip, uint32_t &port) { uint32_t v[4]{}; uint32_t localPort = 0; @@ -72,9 +72,9 @@ bool parse_ip_address_and_port(uint32_t &ip, uint32_t &port, const std::string & return true; } -bool parse_ip_address_and_port(std::string &ip, uint16_t &port, const std::string &addr) { +bool parse_ip_address_and_port(const std::string &addr, std::string &ip, uint16_t &port) { uint32_t sip = 0, sport = 0; - if (!parse_ip_address_and_port(sip, sport, addr)) + if (!parse_ip_address_and_port(addr, sip, sport)) return false; port = static_cast(sport); ip = ip_address_to_string(sip); diff --git a/src/common/Ipv4Address.hpp b/src/common/Ipv4Address.hpp index 0841b893..4e0ea612 100644 --- a/src/common/Ipv4Address.hpp +++ b/src/common/Ipv4Address.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once @@ -10,10 +10,9 @@ namespace common { std::string ip_address_to_string(uint32_t ip); std::string ip_address_and_port_to_string(uint32_t ip, uint32_t port); -bool parse_ip_address(uint32_t &ip, const std::string &addr); -bool parse_ip_address_and_port(uint32_t &ip, uint32_t &port, const std::string &addr); -bool parse_ip_address_and_port( - std::string &ip, uint16_t &port, const std::string &addr); // convenient for config parsing +bool parse_ip_address(const std::string &addr, uint32_t &ip); +bool parse_ip_address_and_port(const std::string &addr, uint32_t &ip, uint32_t &port); +bool parse_ip_address_and_port(const std::string &addr, std::string &ip, uint16_t &port); bool is_ip_address_loopback(uint32_t ip); bool is_ip_address_private(uint32_t ip); } diff --git a/src/common/JsonValue.cpp b/src/common/JsonValue.cpp index 3ee7f0ee..3fd4e711 100644 --- a/src/common/JsonValue.cpp +++ b/src/common/JsonValue.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "JsonValue.hpp" #include @@ -13,7 +13,7 @@ JsonValue::JsonValue() : type(NIL) {} JsonValue::JsonValue(const JsonValue &other) { switch (other.type) { case ARRAY: - new (valueArray) Array(*reinterpret_cast(other.valueArray)); + new (&valueArray) Array(*reinterpret_cast(&other.valueArray)); break; case BOOL: valueBool = other.valueBool; @@ -27,13 +27,13 @@ JsonValue::JsonValue(const JsonValue &other) { case NIL: break; case OBJECT: - new (valueObject) Object(*reinterpret_cast(other.valueObject)); + new (&valueObject) Object(*reinterpret_cast(&other.valueObject)); break; case DOUBLE: valueReal = other.valueReal; break; case STRING: - new (valueString) String(*reinterpret_cast(other.valueString)); + new (&valueString) String(*reinterpret_cast(&other.valueString)); break; } @@ -43,8 +43,8 @@ JsonValue::JsonValue(const JsonValue &other) { JsonValue::JsonValue(JsonValue &&other) { switch (other.type) { case ARRAY: - new (valueArray) Array(std::move(*reinterpret_cast(other.valueArray))); - reinterpret_cast(other.valueArray)->~Array(); + new (&valueArray) Array(std::move(*reinterpret_cast(&other.valueArray))); + reinterpret_cast(&other.valueArray)->~Array(); break; case BOOL: valueBool = other.valueBool; @@ -58,15 +58,15 @@ JsonValue::JsonValue(JsonValue &&other) { case NIL: break; case OBJECT: - new (valueObject) Object(std::move(*reinterpret_cast(other.valueObject))); - reinterpret_cast(other.valueObject)->~Object(); + new (&valueObject) Object(std::move(*reinterpret_cast(&other.valueObject))); + reinterpret_cast(&other.valueObject)->~Object(); break; case DOUBLE: valueReal = other.valueReal; break; case STRING: - new (valueString) String(std::move(*reinterpret_cast(other.valueString))); - reinterpret_cast(other.valueString)->~String(); + new (&valueString) String(std::move(*reinterpret_cast(&other.valueString))); + reinterpret_cast(&other.valueString)->~String(); break; } @@ -77,15 +77,15 @@ JsonValue::JsonValue(JsonValue &&other) { JsonValue::JsonValue(Type valueType) { switch (valueType) { case ARRAY: - new (valueArray) Array; + new (&valueArray) Array; break; case NIL: break; case OBJECT: - new (valueObject) Object; + new (&valueObject) Object; break; case STRING: - new (valueString) String; + new (&valueString) String; break; default: throw std::runtime_error("Invalid JsonValue type for constructor"); @@ -95,12 +95,12 @@ JsonValue::JsonValue(Type valueType) { } JsonValue::JsonValue(const Array &value) { - new (valueArray) Array(value); + new (&valueArray) Array(value); type = ARRAY; } JsonValue::JsonValue(Array &&value) { - new (valueArray) Array(std::move(value)); + new (&valueArray) Array(std::move(value)); type = ARRAY; } @@ -113,24 +113,24 @@ JsonValue::JsonValue(Unsigned value) : type(UNSIGNED_INTEGER), valueUnsigned(val JsonValue::JsonValue(std::nullptr_t) : type(NIL) {} JsonValue::JsonValue(const Object &value) { - new (valueObject) Object(value); + new (&valueObject) Object(value); type = OBJECT; } JsonValue::JsonValue(Object &&value) { - new (valueObject) Object(std::move(value)); + new (&valueObject) Object(std::move(value)); type = OBJECT; } JsonValue::JsonValue(Double value) : type(DOUBLE), valueReal(value) {} JsonValue::JsonValue(const String &value) { - new (valueString) String(value); + new (&valueString) String(value); type = STRING; } JsonValue::JsonValue(String &&value) { - new (valueString) String(std::move(value)); + new (&valueString) String(std::move(value)); type = STRING; } @@ -144,7 +144,7 @@ JsonValue &JsonValue::operator=(const JsonValue &other) { switch (other.type) { case ARRAY: type = NIL; - new (valueArray) Array(*reinterpret_cast(other.valueArray)); + new (&valueArray) Array(*reinterpret_cast(&other.valueArray)); break; case BOOL: valueBool = other.valueBool; @@ -159,14 +159,14 @@ JsonValue &JsonValue::operator=(const JsonValue &other) { break; case OBJECT: type = NIL; - new (valueObject) Object(*reinterpret_cast(other.valueObject)); + new (&valueObject) Object(*reinterpret_cast(&other.valueObject)); break; case DOUBLE: valueReal = other.valueReal; break; case STRING: type = NIL; - new (valueString) String(*reinterpret_cast(other.valueString)); + new (&valueString) String(*reinterpret_cast(&other.valueString)); break; } @@ -174,7 +174,7 @@ JsonValue &JsonValue::operator=(const JsonValue &other) { } else { switch (type) { case ARRAY: - *reinterpret_cast(valueArray) = *reinterpret_cast(other.valueArray); + *reinterpret_cast(&valueArray) = *reinterpret_cast(&other.valueArray); break; case BOOL: valueBool = other.valueBool; @@ -188,13 +188,13 @@ JsonValue &JsonValue::operator=(const JsonValue &other) { case NIL: break; case OBJECT: - *reinterpret_cast(valueObject) = *reinterpret_cast(other.valueObject); + *reinterpret_cast(&valueObject) = *reinterpret_cast(&other.valueObject); break; case DOUBLE: valueReal = other.valueReal; break; case STRING: - *reinterpret_cast(valueString) = *reinterpret_cast(other.valueString); + *reinterpret_cast(&valueString) = *reinterpret_cast(&other.valueString); break; } } @@ -208,8 +208,8 @@ JsonValue &JsonValue::operator=(JsonValue &&other) { switch (other.type) { case ARRAY: type = NIL; - new (valueArray) Array(std::move(*reinterpret_cast(other.valueArray))); - reinterpret_cast(other.valueArray)->~Array(); + new (&valueArray) Array(std::move(*reinterpret_cast(&other.valueArray))); + reinterpret_cast(&other.valueArray)->~Array(); break; case BOOL: valueBool = other.valueBool; @@ -224,16 +224,16 @@ JsonValue &JsonValue::operator=(JsonValue &&other) { break; case OBJECT: type = NIL; - new (valueObject) Object(std::move(*reinterpret_cast(other.valueObject))); - reinterpret_cast(other.valueObject)->~Object(); + new (&valueObject) Object(std::move(*reinterpret_cast(&other.valueObject))); + reinterpret_cast(&other.valueObject)->~Object(); break; case DOUBLE: valueReal = other.valueReal; break; case STRING: type = NIL; - new (valueString) String(std::move(*reinterpret_cast(other.valueString))); - reinterpret_cast(other.valueString)->~String(); + new (&valueString) String(std::move(*reinterpret_cast(&other.valueString))); + reinterpret_cast(&other.valueString)->~String(); break; } @@ -241,8 +241,8 @@ JsonValue &JsonValue::operator=(JsonValue &&other) { } else { switch (type) { case ARRAY: - *reinterpret_cast(valueArray) = std::move(*reinterpret_cast(other.valueArray)); - reinterpret_cast(other.valueArray)->~Array(); + *reinterpret_cast(&valueArray) = std::move(*reinterpret_cast(&other.valueArray)); + reinterpret_cast(&other.valueArray)->~Array(); break; case BOOL: valueBool = other.valueBool; @@ -256,15 +256,17 @@ JsonValue &JsonValue::operator=(JsonValue &&other) { case NIL: break; case OBJECT: - *reinterpret_cast(valueObject) = std::move(*reinterpret_cast(other.valueObject)); - reinterpret_cast(other.valueObject)->~Object(); + *reinterpret_cast(&valueObject) = + std::move(*reinterpret_cast(&other.valueObject)); + reinterpret_cast(&other.valueObject)->~Object(); break; case DOUBLE: valueReal = other.valueReal; break; case STRING: - *reinterpret_cast(valueString) = std::move(*reinterpret_cast(other.valueString)); - reinterpret_cast(other.valueString)->~String(); + *reinterpret_cast(&valueString) = + std::move(*reinterpret_cast(&other.valueString)); + reinterpret_cast(&other.valueString)->~String(); break; } } @@ -275,10 +277,10 @@ JsonValue &JsonValue::operator=(JsonValue &&other) { JsonValue &JsonValue::operator=(const Array &value) { if (type != ARRAY) { destructValue(); - new (valueArray) Array(value); + new (&valueArray) Array(value); type = ARRAY; } else { - *reinterpret_cast(valueArray) = value; + *reinterpret_cast(&valueArray) = value; } return *this; } @@ -286,10 +288,10 @@ JsonValue &JsonValue::operator=(const Array &value) { JsonValue &JsonValue::operator=(Array &&value) { if (type != ARRAY) { destructValue(); - new (valueArray) Array(std::move(value)); + new (&valueArray) Array(std::move(value)); type = ARRAY; } else { - *reinterpret_cast(valueArray) = std::move(value); + *reinterpret_cast(&valueArray) = std::move(value); } return *this; } @@ -323,10 +325,10 @@ JsonValue &JsonValue::operator=(std::nullptr_t) { JsonValue &JsonValue::operator=(const Object &value) { if (type != OBJECT) { destructValue(); - new (valueObject) Object(value); + new (&valueObject) Object(value); type = OBJECT; } else { - *reinterpret_cast(valueObject) = value; + *reinterpret_cast(&valueObject) = value; } return *this; } @@ -334,10 +336,10 @@ JsonValue &JsonValue::operator=(const Object &value) { JsonValue &JsonValue::operator=(Object &&value) { if (type != OBJECT) { destructValue(); - new (valueObject) Object(std::move(value)); + new (&valueObject) Object(std::move(value)); type = OBJECT; } else { - *reinterpret_cast(valueObject) = std::move(value); + *reinterpret_cast(&valueObject) = std::move(value); } return *this; } @@ -352,10 +354,10 @@ JsonValue &JsonValue::operator=(Double value) { JsonValue &JsonValue::operator=(const String &value) { if (type != STRING) { destructValue(); - new (valueString) String(value); + new (&valueString) String(value); type = STRING; } else { - *reinterpret_cast(valueString) = value; + *reinterpret_cast(&valueString) = value; } return *this; } @@ -363,10 +365,10 @@ JsonValue &JsonValue::operator=(const String &value) { JsonValue &JsonValue::operator=(String &&value) { if (type != STRING) { destructValue(); - new (valueString) String(std::move(value)); + new (&valueString) String(std::move(value)); type = STRING; } else { - *reinterpret_cast(valueString) = std::move(value); + *reinterpret_cast(&valueString) = std::move(value); } return *this; } @@ -375,14 +377,14 @@ JsonValue::Array &JsonValue::get_array() { if (type != ARRAY) { throw std::runtime_error("JsonValue type is not ARRAY"); } - return *reinterpret_cast(valueArray); + return *reinterpret_cast(&valueArray); } const JsonValue::Array &JsonValue::get_array() const { if (type != ARRAY) { throw std::runtime_error("JsonValue type is not ARRAY"); } - return *reinterpret_cast(valueArray); + return *reinterpret_cast(&valueArray); } JsonValue::Bool JsonValue::get_bool() const { @@ -412,14 +414,14 @@ JsonValue::Object &JsonValue::get_object() { if (type != OBJECT) { throw std::runtime_error("JsonValue type is not OBJECT"); } - return *reinterpret_cast(valueObject); + return *reinterpret_cast(&valueObject); } const JsonValue::Object &JsonValue::get_object() const { if (type != OBJECT) { throw std::runtime_error("JsonValue type is not OBJECT"); } - return *reinterpret_cast(valueObject); + return *reinterpret_cast(&valueObject); } JsonValue::Double JsonValue::get_double() const { @@ -433,22 +435,22 @@ JsonValue::String &JsonValue::get_string() { if (type != STRING) { throw std::runtime_error("JsonValue type is not STRING"); } - return *reinterpret_cast(valueString); + return *reinterpret_cast(&valueString); } const JsonValue::String &JsonValue::get_string() const { if (type != STRING) { throw std::runtime_error("JsonValue type is not STRING"); } - return *reinterpret_cast(valueString); + return *reinterpret_cast(&valueString); } size_t JsonValue::size() const { switch (type) { case ARRAY: - return reinterpret_cast(valueArray)->size(); + return reinterpret_cast(&valueArray)->size(); case OBJECT: - return reinterpret_cast(valueObject)->size(); + return reinterpret_cast(&valueObject)->size(); default: throw std::runtime_error("JsonValue type is not ARRAY or OBJECT"); } @@ -540,7 +542,7 @@ static std::string escape_string(const std::string &str) { std::ostream &operator<<(std::ostream &out, const JsonValue &jsonValue) { switch (jsonValue.type) { case JsonValue::ARRAY: { - const JsonValue::Array &array = *reinterpret_cast(jsonValue.valueArray); + const JsonValue::Array &array = *reinterpret_cast(&jsonValue.valueArray); out << '['; if (array.size() > 0) { out << array[0]; @@ -565,7 +567,7 @@ std::ostream &operator<<(std::ostream &out, const JsonValue &jsonValue) { out << "null"; break; case JsonValue::OBJECT: { - const JsonValue::Object &object = *reinterpret_cast(jsonValue.valueObject); + const JsonValue::Object &object = *reinterpret_cast(&jsonValue.valueObject); out << '{'; auto iter = object.begin(); if (iter != object.end()) { @@ -591,7 +593,7 @@ std::ostream &operator<<(std::ostream &out, const JsonValue &jsonValue) { break; } case JsonValue::STRING: - out << '"' << escape_string(*reinterpret_cast(jsonValue.valueString)) << '"'; + out << '"' << escape_string(*reinterpret_cast(&jsonValue.valueString)) << '"'; break; } @@ -734,13 +736,13 @@ std::istream &operator>>(std::istream &in, JsonValue &jsonValue) { void JsonValue::destructValue() { switch (type) { case ARRAY: - reinterpret_cast(valueArray)->~Array(); + reinterpret_cast(&valueArray)->~Array(); break; case OBJECT: - reinterpret_cast(valueObject)->~Object(); + reinterpret_cast(&valueObject)->~Object(); break; case STRING: - reinterpret_cast(valueString)->~String(); + reinterpret_cast(&valueString)->~String(); break; default: break; diff --git a/src/common/JsonValue.hpp b/src/common/JsonValue.hpp index 8003e42a..54cd8013 100644 --- a/src/common/JsonValue.hpp +++ b/src/common/JsonValue.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once @@ -7,6 +7,7 @@ #include #include #include +#include #include namespace common { @@ -52,7 +53,7 @@ class JsonValue { JsonValue(String &&value); template JsonValue(const char (&value)[size]) { - new (valueString) String(value, size - 1); + new (&valueString) String(value, size - 1); type = STRING; } @@ -75,10 +76,10 @@ class JsonValue { JsonValue &operator=(const char (&value)[size]) { if (type != STRING) { destructValue(); - new (valueString) String(value, size - 1); + new (&valueString) String(value, size - 1); type = STRING; } else { - reinterpret_cast(valueString)->assign(value, size - 1); + reinterpret_cast(&valueString)->assign(value, size - 1); } return *this; } @@ -133,13 +134,13 @@ class JsonValue { private: Type type; union { - alignas(Array) uint8_t valueArray[sizeof(Array)]; + typename std::aligned_storage::type valueArray; Bool valueBool; Integer valueInteger; Unsigned valueUnsigned; - alignas(Object) uint8_t valueObject[sizeof(Object)]; + typename std::aligned_storage::type valueObject; Double valueReal; - alignas(std::string) uint8_t valueString[sizeof(std::string)]; + typename std::aligned_storage::type valueString; }; void destructValue(); diff --git a/src/common/Math.hpp b/src/common/Math.hpp index 3f58546f..359c84b9 100644 --- a/src/common/Math.hpp +++ b/src/common/Math.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/common/MemoryStreams.cpp b/src/common/MemoryStreams.cpp index 669a370c..28bb590a 100644 --- a/src/common/MemoryStreams.cpp +++ b/src/common/MemoryStreams.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "MemoryStreams.hpp" #include diff --git a/src/common/MemoryStreams.hpp b/src/common/MemoryStreams.hpp index 560a6dc8..ef9beaa5 100644 --- a/src/common/MemoryStreams.hpp +++ b/src/common/MemoryStreams.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/common/Nocopy.hpp b/src/common/Nocopy.hpp index faba1664..647af8a0 100644 --- a/src/common/Nocopy.hpp +++ b/src/common/Nocopy.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/common/ScopeExit.hpp b/src/common/ScopeExit.hpp index 6b376bad..760d8c7e 100644 --- a/src/common/ScopeExit.hpp +++ b/src/common/ScopeExit.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/common/Streams.cpp b/src/common/Streams.cpp index 396966be..8c62e86c 100644 --- a/src/common/Streams.cpp +++ b/src/common/Streams.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "Streams.hpp" #include @@ -13,7 +13,7 @@ void IInputStream::read(void *data, size_t count) { while (count != 0) { size_t rc = read_some(data, count); if (rc == 0) - throw std::runtime_error("IInputStream reading from empty stream"); + throw StreamError("IInputStream reading from empty stream"); data = (char *)data + rc; count -= rc; } @@ -23,7 +23,7 @@ void IOutputStream::write(const void *data, size_t size) { while (size != 0) { size_t wc = write_some(data, size); if (wc == 0) - throw std::runtime_error("IOutputStream error writing to full stream"); + throw StreamError("IOutputStream error writing to full stream"); data = (const char *)data + wc; size -= wc; } diff --git a/src/common/Streams.hpp b/src/common/Streams.hpp index 880ef52e..12d3d147 100644 --- a/src/common/Streams.hpp +++ b/src/common/Streams.hpp @@ -1,10 +1,11 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once #include #include +#include #include #include "BinaryArray.hpp" @@ -26,6 +27,11 @@ class IOutputStream { void write(const void *data, size_t size); }; +class StreamError : public std::runtime_error { +public: + explicit StreamError(const std::string &str) : std::runtime_error(str) {} +}; + void read(IInputStream &in, int8_t &value); void read(IInputStream &in, int16_t &value); void read(IInputStream &in, int32_t &value); diff --git a/src/common/StringTools.cpp b/src/common/StringTools.cpp index 2cac0389..38c00c05 100644 --- a/src/common/StringTools.cpp +++ b/src/common/StringTools.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "StringTools.hpp" #include diff --git a/src/common/StringTools.hpp b/src/common/StringTools.hpp index 43cdb6b8..047f78c5 100644 --- a/src/common/StringTools.hpp +++ b/src/common/StringTools.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/common/StringView.cpp b/src/common/StringView.cpp index 6aef444d..cae4feef 100644 --- a/src/common/StringView.cpp +++ b/src/common/StringView.cpp @@ -1,26 +1,18 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "StringView.hpp" #include #include #include +#include namespace common { -StringView::Char StringView::operator[](Size index) const { - assert(index < m_size); - return *(m_data + index); -} - -StringView::Char StringView::front() const { - assert(m_size > 0); - return *m_data; -} - -StringView::Char StringView::back() const { - assert(m_size > 0); - return *(m_data + (m_size - 1)); +StringView::Char StringView::at(Size index) const { + if (index >= m_size) + throw std::out_of_range("StringView::at"); + return (*this)[index]; } bool StringView::operator==(const StringView &other) const { @@ -38,154 +30,4 @@ bool StringView::operator<(const StringView &other) const { return res < 0; return m_size < other.m_size; } -/* -bool StringView::beginsWith(const Char &object) const { - if (m_size == 0) - return false; - return *m_data == object; -} - -bool StringView::beginsWith(StringView other) const { - if (m_size >= other.m_size) { - for (Size i = 0;; ++i) { - if (i == other.m_size) { - return true; - } - if (!(*(m_data + i) == *(other.m_data + i))) { - break; - } - } - } - return false; -} - -bool StringView::contains(const Char &object) const { - for (Size i = 0; i < m_size; ++i) { - if (*(m_data + i) == object) { - return true; - } - } - return false; -} - -bool StringView::contains(StringView other) const { - if (m_size >= other.m_size) { - Size i = m_size - other.m_size; - for (Size j = 0; !(i < j); ++j) { - for (Size k = 0;; ++k) { - if (k == other.m_size) { - return true; - } - if (!(*(m_data + j + k) == *(other.m_data + k))) { - break; - } - } - } - } - return false; -} - -bool StringView::endsWith(const Char &object) const { - if (m_size == 0) - return false; - return *(m_data + (m_size - 1)) == object; -} - -bool StringView::endsWith(StringView other) const { - if (m_size >= other.m_size) { - Size i = m_size - other.m_size; - for (Size j = 0;; ++j) { - if (j == other.m_size) { - return true; - } - if (!(*(m_data + i + j) == *(other.m_data + j))) { - break; - } - } - } - return false; -} - -StringView::Size StringView::find(const Char &object) const { - for (Size i = 0; i < m_size; ++i) { - if (*(m_data + i) == object) { - return i; - } - } - return INVALID; -} - -StringView::Size StringView::find(StringView other) const { - if (m_size >= other.m_size) { - Size i = m_size - other.m_size; - for (Size j = 0; !(i < j); ++j) { - for (Size k = 0;; ++k) { - if (k == other.m_size) { - return j; - } - if (!(*(m_data + j + k) == *(other.m_data + k))) { - break; - } - } - } - } - return INVALID; -} - -StringView::Size StringView::findLast(const Char &object) const { - for (Size i = 0; i < m_size; ++i) { - if (*(m_data + (m_size - 1 - i)) == object) { - return m_size - 1 - i; - } - } - return INVALID; -} - -StringView::Size StringView::findLast(StringView other) const { - if (m_size >= other.m_size) { - Size i = m_size - other.m_size; - for (Size j = 0; !(i < j); ++j) { - for (Size k = 0;; ++k) { - if (k == other.m_size) { - return i - j; - } - if (!(*(m_data + (i - j + k)) == *(other.m_data + k))) { - break; - } - } - } - } - return INVALID; -} - -StringView StringView::head(Size headSize) const { - assert(headSize <= m_size); - return StringView(m_data, headSize); -} - -StringView StringView::tail(Size tailSize) const { - assert(tailSize <= m_size); - return StringView(m_data + (m_size - tailSize), tailSize); -} - -StringView StringView::unhead(Size headSize) const { - assert(headSize <= m_size); - return StringView(m_data + headSize, m_size - headSize); -} - -StringView StringView::untail(Size tailSize) const { - assert(tailSize <= m_size); - return StringView(m_data, m_size - tailSize); -} - -StringView StringView::range(Size startIndex, Size endIndex) const { - assert(startIndex <= endIndex && endIndex <= m_size); - return StringView(m_data + startIndex, endIndex - startIndex); -} - -StringView StringView::slice(Size startIndex, Size sliceSize) const { - assert(startIndex <= m_size && startIndex + sliceSize <= m_size); - return StringView(m_data + startIndex, sliceSize); -} - */ } diff --git a/src/common/StringView.hpp b/src/common/StringView.hpp index 72c83769..a489f9e9 100644 --- a/src/common/StringView.hpp +++ b/src/common/StringView.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once @@ -37,17 +37,11 @@ class StringView { Size size() const { return m_size; } bool empty() const { return m_size == 0; } - // Get 'StringView' element by index. - // The behavior is undefined unless 'StringView' was initialized and 'index' < 'm_size'. - Char operator[](Size index) const; - - // Get first element. - // The behavior is undefined unless 'StringView' was initialized and 'm_size' > 0 - Char front() const; - - // Get last element. - // The behavior is undefined unless 'StringView' was initialized and 'm_size' > 0 - Char back() const; + Char operator[](Size index) const { + assert(index < m_size); + return *(m_data + index); + } + Char at(Size index) const; const Char *begin() const { return m_data; } const Char *end() const { return m_data + m_size; } @@ -58,78 +52,7 @@ class StringView { bool operator<=(const StringView &other) const { return !(other < *this); } bool operator>(const StringView &other) const { return other < *this; } bool operator>=(const StringView &other) const { return !(*this < other); } - /* - // Return false if 'StringView' does not contain 'object' at the beginning. - // The behavior is undefined unless 'StringView' was initialized. - bool beginsWith(const Char &object) const; - - // Return false if 'StringView' does not contain 'other' at the beginning. - // The behavior is undefined unless both strings were initialized. - bool beginsWith(StringView other) const; - - // Return false if 'StringView' does not contain 'object'. - // The behavior is undefined unless 'StringView' was initialized. - bool contains(const Char &object) const; - - // Return false if 'StringView' does not contain 'other'. - // The behavior is undefined unless both strings were initialized. - bool contains(StringView other) const; - - // Return false if 'StringView' does not contain 'object' at the end. - // The behavior is undefined unless 'StringView' was initialized. - bool endsWith(const Char &object) const; - - // Return false if 'StringView' does not contain 'other' at the end. - // The behavior is undefined unless both strings were initialized. - bool endsWith(StringView other) const; - - // Looks for the first occurence of 'object' in 'StringView', - // returns index or INVALID if there are no occurences. - // The behavior is undefined unless 'StringView' was initialized. - Size find(const Char &object) const; - - // Looks for the first occurence of 'other' in 'StringView', - // returns index or INVALID if there are no occurences. - // The behavior is undefined unless both strings were initialized. - Size find(StringView other) const; - - // Looks for the last occurence of 'object' in 'StringView', - // returns index or INVALID if there are no occurences. - // The behavior is undefined unless 'StringView' was initialized. - Size findLast(const Char &object) const; - - // Looks for the first occurence of 'other' in 'StringView', - // returns index or INVALID if there are no occurences. - // The behavior is undefined unless both strings were initialized. - Size findLast(StringView other) const; - - // Returns substring of 'headSize' first elements. - // The behavior is undefined unless 'StringView' was initialized and 'headSize' <= 'm_size'. - StringView head(Size headSize) const; - - // Returns substring of 'tailSize' last elements. - // The behavior is undefined unless 'StringView' was initialized and 'tailSize' <= 'm_size'. - StringView tail(Size tailSize) const; - - // Returns 'StringView' without 'headSize' first elements. - // The behavior is undefined unless 'StringView' was initialized and 'headSize' <= 'm_size'. - StringView unhead(Size headSize) const; - - // Returns 'StringView' without 'tailSize' last elements. - // The behavior is undefined unless 'StringView' was initialized and 'tailSize' <= 'm_size'. - StringView untail(Size tailSize) const; - - // Returns substring starting at 'startIndex' and contaning 'endIndex' - 'startIndex' elements. - // The behavior is undefined unless 'StringView' was initialized and 'startIndex' <= 'endIndex' and 'endIndex' - <= - // 'm_size'. - StringView range(Size startIndex, Size endIndex) const; - // Returns substring starting at 'startIndex' and contaning 'sliceSize' elements. - // The behavior is undefined unless 'StringView' was initialized and 'startIndex' <= 'm_size' and 'startIndex' + - // 'sliceSize' <= 'm_size'. - StringView slice(Size startIndex, Size sliceSize) const; - */ protected: const Char *m_data; Size m_size; diff --git a/src/common/Varint.cpp b/src/common/Varint.cpp index a94061a4..99f4ac14 100644 --- a/src/common/Varint.cpp +++ b/src/common/Varint.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "Varint.hpp" #include diff --git a/src/common/Varint.hpp b/src/common/Varint.hpp index 9d1b9be9..a6dc8b88 100644 --- a/src/common/Varint.hpp +++ b/src/common/Varint.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/common/string.hpp b/src/common/string.hpp new file mode 100644 index 00000000..e26ef5aa --- /dev/null +++ b/src/common/string.hpp @@ -0,0 +1,42 @@ +// Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. + +#pragma once + +// Get rid of this header as soon as Google NDK updates its compiler to support std::to_string family of functions + +#include + +#if defined(__ANDROID__) + +#include + +namespace common { + +template +inline std::string to_string(T value) { + std::ostringstream os; + os << value; + return os.str(); +} + +inline long long stoll(const std::string &key) { + long long val = 0; + if (sscanf(key.c_str(), "%lld", &val) != 1) + throw std::runtime_error("stoll failed to convert key=" + key); + return val; +} +} + +#else + +namespace common { +template +inline std::string to_string(T value) { + return std::to_string(value); +} + +inline long long stoll(const std::string &key) { return std::stoll(key); } +} + +#endif diff --git a/src/crypto/c_types.h b/src/crypto/c_types.h index 27ed72a9..11cd2d42 100644 --- a/src/crypto/c_types.h +++ b/src/crypto/c_types.h @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/crypto/chacha8.c b/src/crypto/chacha8.c index 30631c1a..aab8694e 100644 --- a/src/crypto/chacha8.c +++ b/src/crypto/chacha8.c @@ -34,7 +34,7 @@ Public domain. a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \ c = PLUS(c,d); b = ROTATE(XOR(b,c), 7); -static const char sigma[] = "expand 32-byte k"; +//static const char sigma[] = "expand 32-byte k"; void chacha8(const void* data, size_t length, const uint8_t* key, const uint8_t* iv, char* cipher) { uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; @@ -45,10 +45,10 @@ void chacha8(const void* data, size_t length, const uint8_t* key, const uint8_t* if (!length) return; - j0 = U8TO32_LITTLE(sigma + 0); - j1 = U8TO32_LITTLE(sigma + 4); - j2 = U8TO32_LITTLE(sigma + 8); - j3 = U8TO32_LITTLE(sigma + 12); + j0 = 1634760805; // U8TO32_LITTLE(sigma + 0); // + j1 = 857760878; // U8TO32_LITTLE(sigma + 4); // + j2 = 2036477234; // U8TO32_LITTLE(sigma + 8); // + j3 = 1797285236; // U8TO32_LITTLE(sigma + 12); // j4 = U8TO32_LITTLE(key + 0); j5 = U8TO32_LITTLE(key + 4); j6 = U8TO32_LITTLE(key + 8); diff --git a/src/crypto/crypto-ops-data.c b/src/crypto/crypto-ops-data.c index 513b9bca..02f162b8 100644 --- a/src/crypto/crypto-ops-data.c +++ b/src/crypto/crypto-ops-data.c @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include diff --git a/src/crypto/crypto-ops-data.h b/src/crypto/crypto-ops-data.h index 4e456748..a4b64304 100644 --- a/src/crypto/crypto-ops-data.h +++ b/src/crypto/crypto-ops-data.h @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/crypto/crypto-ops.c b/src/crypto/crypto-ops.c index d6da3b4f..cd77160a 100644 --- a/src/crypto/crypto-ops.c +++ b/src/crypto/crypto-ops.c @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include #include diff --git a/src/crypto/crypto-ops.h b/src/crypto/crypto-ops.h index cf176922..c006fab3 100644 --- a/src/crypto/crypto-ops.h +++ b/src/crypto/crypto-ops.h @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/crypto/crypto-util.c b/src/crypto/crypto-util.c index dc3da40c..c3c61434 100644 --- a/src/crypto/crypto-util.c +++ b/src/crypto/crypto-util.c @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include #include diff --git a/src/crypto/crypto-util.h b/src/crypto/crypto-util.h index 2053dd24..f295dafe 100644 --- a/src/crypto/crypto-util.h +++ b/src/crypto/crypto-util.h @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/crypto/crypto.cpp b/src/crypto/crypto.cpp index cf2b7cee..5fda7f99 100644 --- a/src/crypto/crypto.cpp +++ b/src/crypto/crypto.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include #include @@ -9,16 +9,16 @@ #include #include +#include "crypto-ops.h" #include "crypto.hpp" #include "hash.hpp" #include "random.h" -#include "crypto-ops.h" namespace crypto { static std::mutex random_lock; -void generate_random_bytes(size_t n, void *result){ +void generate_random_bytes(size_t n, void *result) { std::lock_guard lock(random_lock); unsafe_generate_random_bytes(n, result); } @@ -35,7 +35,7 @@ void hash_to_scalar(const void *data, size_t length, EllipticCurveScalar &res) { sc_reduce32(&res, h.data); } -void random_keys(PublicKey &pub, SecretKey &sec) { +void random_keypair(PublicKey &pub, SecretKey &sec) { ge_p3 point; random_scalar(sec); ge_scalarmult_base(&point, &sec); @@ -75,9 +75,9 @@ bool generate_key_derivation(const PublicKey &key1, const SecretKey &key2, KeyDe return true; } -//template -//typename std::enable_if::value && std::is_unsigned::value, void>::type -static void write_varint(uint8_t * &dest, size_t i) { +// template +// typename std::enable_if::value && std::is_unsigned::value, void>::type +static void write_varint(uint8_t *&dest, size_t i) { while (i >= 0x80) { *dest++ = (static_cast(i) & 0x7f) | 0x80; i >>= 7; @@ -89,20 +89,21 @@ static void derivation_to_scalar(const KeyDerivation &derivation, size_t output_ KeyDerivation derivation; uint8_t output_index[(sizeof(size_t) * 8 + 6) / 7]; } buf; - uint8_t *end = buf.output_index; + uint8_t *end = buf.output_index; buf.derivation = derivation; write_varint(end, output_index); assert(end <= buf.output_index + sizeof buf.output_index); hash_to_scalar(&buf, end - reinterpret_cast(&buf), res); } -static void derivation_to_scalar(const KeyDerivation &derivation, size_t output_index, const uint8_t* suffix, size_t suffixLength, EllipticCurveScalar &res) { +static void derivation_to_scalar(const KeyDerivation &derivation, size_t output_index, const uint8_t *suffix, + size_t suffixLength, EllipticCurveScalar &res) { assert(suffixLength <= 32); struct { KeyDerivation derivation; uint8_t output_index[(sizeof(size_t) * 8 + 6) / 7 + 32]; } buf; - uint8_t *end = buf.output_index; + uint8_t *end = buf.output_index; buf.derivation = derivation; write_varint(end, output_index); assert(end <= buf.output_index + sizeof buf.output_index); @@ -111,8 +112,8 @@ static void derivation_to_scalar(const KeyDerivation &derivation, size_t output_ hash_to_scalar(&buf, bufSize + suffixLength, res); } -bool derive_public_key(const KeyDerivation &derivation, size_t output_index, - const PublicKey &base, PublicKey &derived_key) { +bool derive_public_key( + const KeyDerivation &derivation, size_t output_index, const PublicKey &base, PublicKey &derived_key) { EllipticCurveScalar scalar; ge_p3 point1; ge_p3 point2; @@ -131,8 +132,8 @@ bool derive_public_key(const KeyDerivation &derivation, size_t output_index, return true; } -bool derive_public_key(const KeyDerivation &derivation, size_t output_index, - const PublicKey &base, const uint8_t* suffix, size_t suffixLength, PublicKey &derived_key) { +bool derive_public_key(const KeyDerivation &derivation, size_t output_index, const PublicKey &base, + const uint8_t *suffix, size_t suffixLength, PublicKey &derived_key) { EllipticCurveScalar scalar; ge_p3 point1; ge_p3 point2; @@ -152,7 +153,7 @@ bool derive_public_key(const KeyDerivation &derivation, size_t output_index, } bool underive_public_key_and_get_scalar(const KeyDerivation &derivation, size_t output_index, - const PublicKey &derived_key, PublicKey &base, EllipticCurveScalar &hashed_derivation) { + const PublicKey &derived_key, PublicKey &base, EllipticCurveScalar &hashed_derivation) { ge_p3 point1; ge_p3 point2; ge_cached point3; @@ -170,25 +171,24 @@ bool underive_public_key_and_get_scalar(const KeyDerivation &derivation, size_t return true; } -void derive_secret_key(const KeyDerivation &derivation, size_t output_index, - const SecretKey &base, SecretKey &derived_key) { +void derive_secret_key( + const KeyDerivation &derivation, size_t output_index, const SecretKey &base, SecretKey &derived_key) { EllipticCurveScalar scalar; assert(sc_isvalid_vartime(&base)); derivation_to_scalar(derivation, output_index, scalar); sc_add(&derived_key, &base, &scalar); } -void derive_secret_key(const KeyDerivation &derivation, size_t output_index, - const SecretKey &base, const uint8_t* suffix, size_t suffixLength, SecretKey &derived_key) { +void derive_secret_key(const KeyDerivation &derivation, size_t output_index, const SecretKey &base, + const uint8_t *suffix, size_t suffixLength, SecretKey &derived_key) { EllipticCurveScalar scalar; assert(sc_isvalid_vartime(&base)); derivation_to_scalar(derivation, output_index, suffix, suffixLength, scalar); sc_add(&derived_key, &base, &scalar); } - -bool underive_public_key(const KeyDerivation &derivation, size_t output_index, - const PublicKey &derived_key, PublicKey &base) { +bool underive_public_key( + const KeyDerivation &derivation, size_t output_index, const PublicKey &derived_key, PublicKey &base) { EllipticCurveScalar scalar; ge_p3 point1; ge_p3 point2; @@ -207,8 +207,8 @@ bool underive_public_key(const KeyDerivation &derivation, size_t output_index, return true; } -bool underive_public_key(const KeyDerivation &derivation, size_t output_index, - const PublicKey &derived_key, const uint8_t* suffix, size_t suffixLength, PublicKey &base) { +bool underive_public_key(const KeyDerivation &derivation, size_t output_index, const PublicKey &derived_key, + const uint8_t *suffix, size_t suffixLength, PublicKey &base) { EllipticCurveScalar scalar; ge_p3 point1; ge_p3 point2; @@ -251,8 +251,8 @@ void generate_signature(const Hash &prefix_hash, const PublicKey &pub, const Sec assert(pub == t2); } #endif - buf.h = prefix_hash; - buf.key = static_cast(pub); + buf.h = prefix_hash; + buf.key = static_cast(pub); random_scalar(k); ge_scalarmult_base(&tmp3, &k); ge_p3_tobytes(&buf.comm, &tmp3); @@ -260,17 +260,17 @@ void generate_signature(const Hash &prefix_hash, const PublicKey &pub, const Sec sc_mulsub(&sig.r, &sig.c, &sec, &k); } -bool check_signature(const Hash &prefix_hash, const PublicKey &pub, const Signature &sig, bool * key_corrupted) { - if( key_corrupted ) +bool check_signature(const Hash &prefix_hash, const PublicKey &pub, const Signature &sig, bool *key_corrupted) { + if (key_corrupted) *key_corrupted = false; ge_p2 tmp2; ge_p3 tmp3; EllipticCurveScalar c; s_comm buf; - buf.h = prefix_hash; - buf.key = static_cast(pub); + buf.h = prefix_hash; + buf.key = static_cast(pub); if (ge_frombytes_vartime(&tmp3, &pub) != 0) { - if( key_corrupted ) + if (key_corrupted) *key_corrupted = true; assert(false); return false; @@ -304,13 +304,13 @@ void hash_to_ec(const PublicKey &key, EllipticCurvePoint &res) { ge_p3_tobytes(&res, &tmp); } /*void hash_data_to_ec(const uint8_t* data, std::size_t len, EllipticCurvePoint & key) { - ge_p2 point; - ge_p1p1 point2; - Hash h = cn_fast_hash(data, len); - ge_fromfe_frombytes_vartime(&point, h.data); - ge_mul8(&point2, &point); - ge_p1p1_to_p2(&point, &point2); - ge_tobytes(&key, &point); + ge_p2 point; + ge_p1p1 point2; + Hash h = cn_fast_hash(data, len); + ge_fromfe_frombytes_vartime(&point, h.data); + ge_mul8(&point2, &point); + ge_p1p1_to_p2(&point, &point2); + ge_tobytes(&key, &point); }*/ void generate_key_image(const PublicKey &pub, const SecretKey &sec, KeyImage &image) { @@ -322,7 +322,7 @@ void generate_key_image(const PublicKey &pub, const SecretKey &sec, KeyImage &im ge_tobytes(&image, &point2); } -//void generate_incomplete_key_image(const PublicKey &pub, EllipticCurvePoint &incomplete_key_image) { +// void generate_incomplete_key_image(const PublicKey &pub, EllipticCurvePoint &incomplete_key_image) { // ge_p3 point; // hash_to_ec(pub, point); // ge_p3_tobytes(&incomplete_key_image, &point); @@ -333,25 +333,21 @@ struct rs_comm { Hash h; struct { EllipticCurvePoint a, b; - } ab[1]; // This structure is never instantiated, so instead of [0] we use standard-compliant [1] + } ab[1]; // This structure is never instantiated, so instead of [0] we use standard-compliant [1] }; #pragma pack(pop) -static size_t rs_comm_size(size_t pubs_count) { - return sizeof(Hash) + pubs_count * 2 * sizeof(EllipticCurvePoint); -} +static size_t rs_comm_size(size_t pubs_count) { return sizeof(Hash) + pubs_count * 2 * sizeof(EllipticCurvePoint); } -bool generate_ring_signature(const Hash &prefix_hash, const KeyImage &image, - const PublicKey *const pubs[], size_t pubs_count, - const SecretKey &sec, size_t sec_index, - Signature sigs[]) { - if(sec_index >= pubs_count) +bool generate_ring_signature(const Hash &prefix_hash, const KeyImage &image, const PublicKey *const pubs[], + size_t pubs_count, const SecretKey &sec, size_t sec_index, Signature sigs[]) { + if (sec_index >= pubs_count) return false; ge_p3 image_unp; ge_dsmp image_pre; EllipticCurveScalar sum, k, h; const size_t buf_size = rs_comm_size(pubs_count); - rs_comm *const buf = reinterpret_cast(alloca(buf_size)); + rs_comm *const buf = reinterpret_cast(alloca(buf_size)); #if !defined(NDEBUG) { ge_p3 t; @@ -402,16 +398,15 @@ bool generate_ring_signature(const Hash &prefix_hash, const KeyImage &image, return true; } -bool check_ring_signature(const Hash &prefix_hash, const KeyImage &image, - const PublicKey *const pubs[], size_t pubs_count, - const Signature sigs[], bool checkKeyImage, bool * key_corrupted) { - if( key_corrupted ) +bool check_ring_signature(const Hash &prefix_hash, const KeyImage &image, const PublicKey *const pubs[], + size_t pubs_count, const Signature sigs[], bool checkKeyImage, bool *key_corrupted) { + if (key_corrupted) *key_corrupted = false; ge_p3 image_unp; ge_dsmp image_pre; EllipticCurveScalar sum, h; const size_t buf_size = rs_comm_size(pubs_count); - rs_comm *const buf = reinterpret_cast(alloca(buf_size)); + rs_comm *const buf = reinterpret_cast(alloca(buf_size)); if (ge_frombytes_vartime(&image_unp, &image) != 0) { return false; } @@ -428,7 +423,7 @@ bool check_ring_signature(const Hash &prefix_hash, const KeyImage &image, return false; } if (ge_frombytes_vartime(&tmp3, pubs[i]) != 0) { - if( key_corrupted ) + if (key_corrupted) *key_corrupted = true; assert(false); return false; @@ -455,8 +450,8 @@ struct sp_comm { #pragma pack(pop) static_assert(sizeof(sp_comm) == 192, "Layout of sp_comm structure is wrong"); -bool generate_send_proof(const PublicKey &txkey_pub, const SecretKey &txkey_sec, - const PublicKey &receiver_view_key_pub, const KeyDerivation &derivation, const Hash &message_hash, Signature &proof) { +bool generate_send_proof(const PublicKey &txkey_pub, const SecretKey &txkey_sec, const PublicKey &receiver_view_key_pub, + const KeyDerivation &derivation, const Hash &message_hash, Signature &proof) { ge_p1p1 tmp1; ge_p2 tmp2; ge_p3 tmp3; @@ -465,10 +460,10 @@ bool generate_send_proof(const PublicKey &txkey_pub, const SecretKey &txkey_sec, if (ge_frombytes_vartime(&tmp3, &receiver_view_key_pub) != 0) { return false; } - comm.message_hash = message_hash; - comm.txkey = txkey_pub; + comm.message_hash = message_hash; + comm.txkey = txkey_pub; comm.receiver_view_key = receiver_view_key_pub; - comm.derivation = derivation; + comm.derivation = derivation; random_scalar(k); ge_scalarmult(&tmp2, &k, &tmp3); ge_scalarmult_base(&tmp3, &k); @@ -482,7 +477,7 @@ bool generate_send_proof(const PublicKey &txkey_pub, const SecretKey &txkey_sec, } bool check_send_proof(const PublicKey &txkey_pub, const PublicKey &receiver_view_key_pub, - const KeyDerivation &derivation, const Hash &message_hash, const Signature &proof) { + const KeyDerivation &derivation, const Hash &message_hash, const Signature &proof) { ge_p1p1 tmp1; ge_p2 tmp2; ge_p3 tmp3; @@ -492,10 +487,10 @@ bool check_send_proof(const PublicKey &txkey_pub, const PublicKey &receiver_view if (!sc_isvalid_vartime(&proof.c) || !sc_isvalid_vartime(&proof.r)) { return false; } - comm.message_hash = message_hash; - comm.txkey = txkey_pub; + comm.message_hash = message_hash; + comm.txkey = txkey_pub; comm.receiver_view_key = receiver_view_key_pub; - comm.derivation = derivation; + comm.derivation = derivation; if (ge_frombytes_vartime(&tmp3, &txkey_pub) != 0) { return false; } @@ -520,5 +515,4 @@ bool check_send_proof(const PublicKey &txkey_pub, const PublicKey &receiver_view sc_sub(&h, &h, &proof.c); return sc_iszero(&h); } - } diff --git a/src/crypto/crypto.hpp b/src/crypto/crypto.hpp index 4fbfb775..36f3d66d 100644 --- a/src/crypto/crypto.hpp +++ b/src/crypto/crypto.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once @@ -9,12 +9,12 @@ #include #include -#include "types.hpp" #include "random.h" +#include "types.hpp" namespace crypto { -void generate_random_bytes(size_t n, void *result); // thread-safe +void generate_random_bytes(size_t n, void *result); // thread-safe void random_scalar(EllipticCurveScalar &res); template @@ -24,27 +24,23 @@ typename std::enable_if::value, T>::type rand() { return res; } -template +template class random_engine { public: typedef T result_type; - constexpr static T min() { - return std::numeric_limits::min(); - } - constexpr static T max() { - return std::numeric_limits::max(); - } + constexpr static T min() { return std::numeric_limits::min(); } + constexpr static T max() { return std::numeric_limits::max(); } T operator()() { static_assert(std::is_unsigned::value, "random engine is defined only for unsigned types"); return rand(); } }; -void random_keys(PublicKey &pub, SecretKey &sec); +void random_keypair(PublicKey &pub, SecretKey &sec); -inline KeyPair random_keypair(){ +inline KeyPair random_keypair() { KeyPair k; - crypto::random_keys(k.publicKey, k.secretKey); + crypto::random_keypair(k.publicKey, k.secretKey); return k; } @@ -55,78 +51,77 @@ bool secret_key_to_public_key(const SecretKey &sec, PublicKey &pub); bool keys_match(const SecretKey &secret_key, const PublicKey &expected_public_key); // To generate an ephemeral key used to send money to: -// The sender generates a new key pair, which becomes the transaction key. The public transaction key is included in "extra" field. +// The sender generates a new key pair, which becomes the transaction key. The public transaction key is included in +// "extra" field. // Both the sender and the receiver generate key derivation from the transaction key and the receivers' "view" key. // The sender uses key derivation, the output index, and the receivers' "spend" key to derive an ephemeral public key. -// The receiver can either derive the public key (to check that the transaction is addressed to him) or the private key (to spend the money). +// The receiver can either derive the public key (to check that the transaction is addressed to him) or the private key +// (to spend the money). bool generate_key_derivation(const PublicKey &key1, const SecretKey &key2, KeyDerivation &derivation); -bool derive_public_key(const KeyDerivation &derivation, size_t output_index, - const PublicKey &base, const uint8_t* prefix, size_t prefixLength, PublicKey &derived_key); +bool derive_public_key(const KeyDerivation &derivation, size_t output_index, const PublicKey &base, + const uint8_t *prefix, size_t prefixLength, PublicKey &derived_key); -bool derive_public_key(const KeyDerivation &derivation, size_t output_index, - const PublicKey &base, PublicKey &derived_key); +bool derive_public_key( + const KeyDerivation &derivation, size_t output_index, const PublicKey &base, PublicKey &derived_key); bool underive_public_key_and_get_scalar(const KeyDerivation &derivation, std::size_t output_index, - const PublicKey &derived_key, PublicKey &base, EllipticCurveScalar &hashed_derivation); - -void derive_secret_key(const KeyDerivation &derivation, std::size_t output_index, - const SecretKey &base, const uint8_t* prefix, size_t prefixLength, SecretKey &derived_key); + const PublicKey &derived_key, PublicKey &base, EllipticCurveScalar &hashed_derivation); -void derive_secret_key(const KeyDerivation &derivation, std::size_t output_index, - const SecretKey &base, SecretKey &derived_key); +void derive_secret_key(const KeyDerivation &derivation, std::size_t output_index, const SecretKey &base, + const uint8_t *prefix, size_t prefixLength, SecretKey &derived_key); +void derive_secret_key( + const KeyDerivation &derivation, std::size_t output_index, const SecretKey &base, SecretKey &derived_key); -// Inverse function of derive_public_key. It can be used by the receiver to find which "spend" key was used to generate a transaction. This may be useful if the receiver used multiple addresses which only differ in "spend" key. -bool underive_public_key(const KeyDerivation &derivation, size_t output_index, - const PublicKey &derived_key, const uint8_t* prefix, size_t prefixLength, PublicKey &base); +// Inverse function of derive_public_key. It can be used by the receiver to find which "spend" key was used to generate +// a transaction. This may be useful if the receiver used multiple addresses which only differ in "spend" key. +bool underive_public_key(const KeyDerivation &derivation, size_t output_index, const PublicKey &derived_key, + const uint8_t *prefix, size_t prefixLength, PublicKey &base); -bool underive_public_key(const KeyDerivation &derivation, size_t output_index, - const PublicKey &derived_key, PublicKey &base); +bool underive_public_key( + const KeyDerivation &derivation, size_t output_index, const PublicKey &derived_key, PublicKey &base); // returns false if keys are corrupted/invalid void generate_signature(const Hash &prefix_hash, const PublicKey &pub, const SecretKey &sec, Signature &sig); -bool check_signature(const Hash &prefix_hash, const PublicKey &pub, const Signature &sig, bool * key_corrupted = nullptr); +bool check_signature( + const Hash &prefix_hash, const PublicKey &pub, const Signature &sig, bool *key_corrupted = nullptr); // To send money to a key: // The sender generates an ephemeral key and includes it in transaction output. // To spend the money, the receiver generates a key image from it. // Then he selects a bunch of outputs, including the one he spends, and uses them to generate a ring signature. -// To check the signature, it is necessary to collect all the keys that were used to generate it. To detect double spends, it is necessary to check that each key image is used at most once. +// To check the signature, it is necessary to collect all the keys that were used to generate it. To detect double +// spends, it is necessary to check that each key image is used at most once. void generate_key_image(const PublicKey &pub, const SecretKey &sec, KeyImage &image); -//void hash_data_to_ec(const uint8_t* data, std::size_t len, EllipticCurvePoint& key); +// void hash_data_to_ec(const uint8_t* data, std::size_t len, EllipticCurvePoint& key); // returns false if keys are corrupted/invalid -bool generate_ring_signature(const Hash &prefix_hash, const KeyImage &image, - const PublicKey *const pubs[], std::size_t pubs_count, - const SecretKey &sec, std::size_t sec_index, - Signature sigs[]); -bool check_ring_signature(const Hash &prefix_hash, const KeyImage &image, - const PublicKey *const pubs[], size_t pubs_count, - const Signature sigs[], bool checkKeyImage, bool * key_corrupted = nullptr); +bool generate_ring_signature(const Hash &prefix_hash, const KeyImage &image, const PublicKey *const pubs[], + std::size_t pubs_count, const SecretKey &sec, std::size_t sec_index, Signature sigs[]); +bool check_ring_signature(const Hash &prefix_hash, const KeyImage &image, const PublicKey *const pubs[], + size_t pubs_count, const Signature sigs[], bool checkKeyImage, bool *key_corrupted = nullptr); // TODO - remove one pair of funs // returns false if keys are corrupted/invalid inline bool generate_ring_signature(const Hash &prefix_hash, const KeyImage &image, - const std::vector &pubs, - const SecretKey &sec, size_t sec_index, Signature sigs[]) { + const std::vector &pubs, const SecretKey &sec, size_t sec_index, Signature sigs[]) { return generate_ring_signature(prefix_hash, image, pubs.data(), pubs.size(), sec, sec_index, sigs); } inline bool check_ring_signature(const Hash &prefix_hash, const KeyImage &image, - const std::vector &pubs, - const Signature sigs[], bool checkKeyImage, bool * key_corrupted = nullptr) { + const std::vector &pubs, const Signature sigs[], bool checkKeyImage, + bool *key_corrupted = nullptr) { return check_ring_signature(prefix_hash, image, pubs.data(), pubs.size(), sigs, checkKeyImage, key_corrupted); } -bool generate_send_proof(const PublicKey &txkey_pub, const SecretKey &txkey_sec, - const PublicKey &receiver_view_key_pub, const KeyDerivation &derivation, const Hash &message_hash, Signature &proof); +bool generate_send_proof(const PublicKey &txkey_pub, const SecretKey &txkey_sec, const PublicKey &receiver_view_key_pub, + const KeyDerivation &derivation, const Hash &message_hash, Signature &proof); // Transaction key and the derivation supplied with the proof can be invalid, this just means that the proof is invalid. bool check_send_proof(const PublicKey &txkey_pub, const PublicKey &receiver_view_key_pub, - const KeyDerivation &derivation, const Hash &message_hash, const Signature &proof); + const KeyDerivation &derivation, const Hash &message_hash, const Signature &proof); // TODO - what those funs do and why they all have different signatures void hash_to_scalar(const void *data, size_t length, EllipticCurveScalar &res); void hash_to_point_for_tests(const Hash &h, EllipticCurvePoint &res); void hash_to_ec(const PublicKey &key, EllipticCurvePoint &res); - } diff --git a/src/crypto/generic-ops.hpp b/src/crypto/generic-ops.hpp index 1540dda4..46a90108 100644 --- a/src/crypto/generic-ops.hpp +++ b/src/crypto/generic-ops.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once @@ -8,31 +8,21 @@ #include #include "crypto-util.h" -#define CRYPTO_MAKE_COMPARABLE(na, type, cmp) \ -namespace na { \ - inline bool operator==(const type &_v1, const type &_v2) { \ - return cmp(&_v1, &_v2, sizeof(type)) == 0; \ - } \ - inline bool operator!=(const type &_v1, const type &_v2) { \ - return cmp(&_v1, &_v2, sizeof(type)) != 0; \ - } \ - inline bool operator<(const type &_v1, const type &_v2) { \ - return cmp(&_v1, &_v2, sizeof(type)) < 0; \ - } \ -} +#define CRYPTO_MAKE_COMPARABLE(na, type, cmp) \ + namespace na { \ + inline bool operator==(const type &_v1, const type &_v2) { return cmp(&_v1, &_v2, sizeof(type)) == 0; } \ + inline bool operator!=(const type &_v1, const type &_v2) { return cmp(&_v1, &_v2, sizeof(type)) != 0; } \ + inline bool operator<(const type &_v1, const type &_v2) { return cmp(&_v1, &_v2, sizeof(type)) < 0; } \ + } -#define CRYPTO_MAKE_HASHABLE(na, type) \ -namespace na { \ - static_assert(sizeof(size_t) <= sizeof(type), "Size of " #type " must be at least that of size_t"); \ - inline size_t hash_value(const type &_v) { \ - return reinterpret_cast(_v); \ - } \ -} \ -namespace std { \ - template<> \ - struct hash { \ - size_t operator()(const na::type &_v) const { \ - return reinterpret_cast(_v); \ - } \ - }; \ -} +#define CRYPTO_MAKE_HASHABLE(na, type) \ + namespace na { \ + static_assert(sizeof(size_t) <= sizeof(type), "Size of " #type " must be at least that of size_t"); \ + inline size_t hash_value(const type &_v) { return reinterpret_cast(_v); } \ + } \ + namespace std { \ + template<> \ + struct hash { \ + size_t operator()(const na::type &_v) const { return reinterpret_cast(_v); } \ + }; \ + } diff --git a/src/crypto/hash-ctx.cpp b/src/crypto/hash-ctx.cpp index c5b1905c..e7cd5e91 100644 --- a/src/crypto/hash-ctx.cpp +++ b/src/crypto/hash-ctx.cpp @@ -1,8 +1,8 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. -#include #include +#include #include "hash.hpp" @@ -13,44 +13,41 @@ #endif namespace crypto { - - enum { - MAP_SIZE = SLOW_HASH_CONTEXT_SIZE + ((-SLOW_HASH_CONTEXT_SIZE) & 0xfff) - }; - + +enum { MAP_SIZE = SLOW_HASH_CONTEXT_SIZE + ((-SLOW_HASH_CONTEXT_SIZE) & 0xfff) }; + #if defined(_WIN32) - - CryptoNightContext::CryptoNightContext() { - data = VirtualAlloc(nullptr, MAP_SIZE, MEM_COMMIT, PAGE_READWRITE); - if (data == nullptr) { - throw std::bad_alloc(); - } - } - - CryptoNightContext::~CryptoNightContext() { - if(!VirtualFree(data, 0, MEM_RELEASE)) - assert(false); + +CryptoNightContext::CryptoNightContext() { + data = VirtualAlloc(nullptr, MAP_SIZE, MEM_COMMIT, PAGE_READWRITE); + if (data == nullptr) { + throw std::bad_alloc(); } - +} + +CryptoNightContext::~CryptoNightContext() { + if (!VirtualFree(data, 0, MEM_RELEASE)) + assert(false); +} + #else - - CryptoNightContext::CryptoNightContext() { + +CryptoNightContext::CryptoNightContext() { #if !defined(__APPLE__) - data = mmap(nullptr, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE, -1, 0); + data = mmap(nullptr, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE, -1, 0); #else - data = mmap(nullptr, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); + data = mmap(nullptr, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); #endif - if (data == MAP_FAILED) { - throw std::bad_alloc(); - } - mlock(data, MAP_SIZE); - } - - CryptoNightContext::~CryptoNightContext() { - if(munmap(data, MAP_SIZE) != 0) - assert(false); + if (data == MAP_FAILED) { + throw std::bad_alloc(); } - + mlock(data, MAP_SIZE); +} + +CryptoNightContext::~CryptoNightContext() { + if (munmap(data, MAP_SIZE) != 0) + assert(false); +} + #endif - } diff --git a/src/crypto/hash-extra-blake.c b/src/crypto/hash-extra-blake.c index 6623c907..4498508f 100644 --- a/src/crypto/hash-extra-blake.c +++ b/src/crypto/hash-extra-blake.c @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include #include diff --git a/src/crypto/hash-extra-groestl.c b/src/crypto/hash-extra-groestl.c index 7f9ad90b..98782d0f 100644 --- a/src/crypto/hash-extra-groestl.c +++ b/src/crypto/hash-extra-groestl.c @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include #include diff --git a/src/crypto/hash-extra-jh.c b/src/crypto/hash-extra-jh.c index 98042670..4649225a 100644 --- a/src/crypto/hash-extra-jh.c +++ b/src/crypto/hash-extra-jh.c @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include #include diff --git a/src/crypto/hash-extra-skein.c b/src/crypto/hash-extra-skein.c index 4a2bcd50..57706ea0 100644 --- a/src/crypto/hash-extra-skein.c +++ b/src/crypto/hash-extra-skein.c @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include #include diff --git a/src/crypto/hash-impl.h b/src/crypto/hash-impl.h index e18e14e7..b4a67e52 100644 --- a/src/crypto/hash-impl.h +++ b/src/crypto/hash-impl.h @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once @@ -15,11 +15,11 @@ namespace crypto { extern "C" { #endif -inline void *padd(void *p, size_t i) { +static inline void *padd(void *p, size_t i) { return (char *) p + i; } -inline const void *cpadd(const void *p, size_t i) { +static inline const void *cpadd(const void *p, size_t i) { return (const char *) p + i; } diff --git a/src/crypto/hash-ops.h b/src/crypto/hash-ops.h index 8e6f9c2b..c0e0e64e 100644 --- a/src/crypto/hash-ops.h +++ b/src/crypto/hash-ops.h @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/crypto/hash.c b/src/crypto/hash.c index 3f4fd56d..d9d675d7 100644 --- a/src/crypto/hash.c +++ b/src/crypto/hash.c @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include #include diff --git a/src/crypto/hash.hpp b/src/crypto/hash.hpp index 35867ffc..2a40af84 100644 --- a/src/crypto/hash.hpp +++ b/src/crypto/hash.hpp @@ -1,60 +1,61 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once #include -#include "types.hpp" #include "hash-ops.h" +#include "types.hpp" namespace crypto { - // Cryptonight hash functions +// Cryptonight hash functions - inline Hash cn_fast_hash(const void *data, size_t length) { - Hash h; - cn_fast_hash(data, length, h.data); - return h; - } +inline Hash cn_fast_hash(const void *data, size_t length) { + Hash h; + cn_fast_hash(data, length, h.data); + return h; +} // inline Hash cn_fast_hash(const std::vector & data) { // return cn_fast_hash(data.data(), data.size()); // } - class CryptoNightContext { - public: - CryptoNightContext(); +class CryptoNightContext { +public: + CryptoNightContext(); ~CryptoNightContext(); - CryptoNightContext(const CryptoNightContext &) = delete; - void operator=(const CryptoNightContext &) = delete; - - inline void cn_slow_hash(const void *src_data, size_t length, unsigned char * hash) { - crypto::cn_slow_hash(data, src_data, length, hash); - } - inline Hash cn_slow_hash(const void *src_data, size_t length) { - Hash hash; - crypto::cn_slow_hash(data, src_data, length, hash.data); - return hash; - } - private: - void *data; - }; - - inline Hash tree_hash(const Hash *hashes, size_t count) { - Hash root_hash; - tree_hash(reinterpret_cast(hashes), count, root_hash.data); - return root_hash; - } + CryptoNightContext(const CryptoNightContext &) = delete; + void operator=(const CryptoNightContext &) = delete; + + inline void cn_slow_hash(const void *src_data, size_t length, unsigned char *hash) { + crypto::cn_slow_hash(data, src_data, length, hash); + } + inline Hash cn_slow_hash(const void *src_data, size_t length) { + Hash hash; + crypto::cn_slow_hash(data, src_data, length, hash.data); + return hash; + } - inline void tree_branch(const Hash *hashes, size_t count, Hash *branch) { - tree_branch(reinterpret_cast(hashes), count, reinterpret_cast(branch)); - } +private: + void *data; +}; - inline Hash tree_hash_from_branch(const Hash *branch, size_t depth, const Hash &leaf, const void *path) { +inline Hash tree_hash(const Hash *hashes, size_t count) { Hash root_hash; - tree_hash_from_branch(reinterpret_cast(branch), depth, leaf.data, path, root_hash.data); - return root_hash; - } + tree_hash(reinterpret_cast(hashes), count, root_hash.data); + return root_hash; +} +inline void tree_branch(const Hash *hashes, size_t count, Hash *branch) { + tree_branch(reinterpret_cast(hashes), count, + reinterpret_cast(branch)); } +inline Hash tree_hash_from_branch(const Hash *branch, size_t depth, const Hash &leaf, const void *path) { + Hash root_hash; + tree_hash_from_branch( + reinterpret_cast(branch), depth, leaf.data, path, root_hash.data); + return root_hash; +} +} diff --git a/src/crypto/initializer.h b/src/crypto/initializer.h index ac756055..a1b4d55c 100644 --- a/src/crypto/initializer.h +++ b/src/crypto/initializer.h @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/crypto/int-util.h b/src/crypto/int-util.h index 1a60a1a8..18f38be3 100644 --- a/src/crypto/int-util.h +++ b/src/crypto/int-util.h @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once @@ -36,11 +36,11 @@ inline uint64_t rol64(uint64_t x, int r) { #if defined(__cplusplus) extern "C" { #endif -inline uint32_t rol32(uint32_t x, int r) { +static inline uint32_t rol32(uint32_t x, int r) { return (x << (r & 31)) | (x >> (-r & 31)); } -inline uint64_t rol64(uint64_t x, int r) { +static inline uint64_t rol64(uint64_t x, int r) { return (x << (r & 63)) | (x >> (-r & 63)); } #if defined(__cplusplus) @@ -53,15 +53,15 @@ inline uint64_t rol64(uint64_t x, int r) { extern "C" { #endif -inline uint64_t hi_dword(uint64_t val) { +static inline uint64_t hi_dword(uint64_t val) { return val >> 32; } -inline uint64_t lo_dword(uint64_t val) { +static inline uint64_t lo_dword(uint64_t val) { return val & 0xFFFFFFFF; } -inline uint64_t mul128(uint64_t multiplier, uint64_t multiplicand, uint64_t * product_hi) { +static inline uint64_t mul128(uint64_t multiplier, uint64_t multiplicand, uint64_t * product_hi) { #if defined(__GNUC__) && defined(__x86_64__) uint64_t hi, lo; __asm__("mulq %3\n\t" @@ -104,14 +104,14 @@ inline uint64_t mul128(uint64_t multiplier, uint64_t multiplicand, uint64_t * pr #endif } -inline uint64_t div_with_reminder(uint64_t dividend, uint32_t divisor, uint32_t* remainder) { +static inline uint64_t div_with_reminder(uint64_t dividend, uint32_t divisor, uint32_t* remainder) { dividend |= ((uint64_t)*remainder) << 32; *remainder = dividend % divisor; return dividend / divisor; } // Long division with 2^32 base -inline uint32_t div128_32(uint64_t dividend_hi, uint64_t dividend_lo, uint32_t divisor, uint64_t* quotient_hi, uint64_t* quotient_lo) { +static inline uint32_t div128_32(uint64_t dividend_hi, uint64_t dividend_lo, uint32_t divisor, uint64_t* quotient_hi, uint64_t* quotient_lo) { uint64_t dividend_dwords[4]; uint32_t remainder = 0; @@ -144,14 +144,14 @@ inline uint32_t div128_32(uint64_t dividend_hi, uint64_t dividend_lo, uint32_t d (((uint64_t) (x) & 0x00ff000000000000) >> 40) | \ (((uint64_t) (x) & 0xff00000000000000) >> 56)) -inline uint32_t ident32(uint32_t x) { return x; } -inline uint64_t ident64(uint64_t x) { return x; } +static inline uint32_t ident32(uint32_t x) { return x; } +static inline uint64_t ident64(uint64_t x) { return x; } -inline uint32_t swap32(uint32_t x) { +static inline uint32_t swap32(uint32_t x) { x = ((x & 0x00ff00ff) << 8) | ((x & 0xff00ff00) >> 8); return (x << 16) | (x >> 16); } -inline uint64_t swap64(uint64_t x) { +static inline uint64_t swap64(uint64_t x) { x = ((x & 0x00ff00ff00ff00ff) << 8) | ((x & 0xff00ff00ff00ff00) >> 8); x = ((x & 0x0000ffff0000ffff) << 16) | ((x & 0xffff0000ffff0000) >> 16); return (x << 32) | (x >> 32); @@ -199,7 +199,10 @@ inline uint64_t swap64(uint64_t x) { //} #if !defined(BYTE_ORDER) || !defined(LITTLE_ENDIAN) || !defined(BIG_ENDIAN) -static_assert(false, "BYTE_ORDER is undefined. Perhaps, GNU extensions are not enabled"); +//static_assert(false, "BYTE_ORDER is undefined. Perhaps, GNU extensions are not enabled"); +#define LITTLE_ENDIAN 1234 +#define BIG_ENDIAN 4321 +#define BYTE_ORDER LITTLE_ENDIAN #endif #if BYTE_ORDER == LITTLE_ENDIAN diff --git a/src/crypto/oaes_lib.c b/src/crypto/oaes_lib.c index 5c37b974..1a2c7b4a 100644 --- a/src/crypto/oaes_lib.c +++ b/src/crypto/oaes_lib.c @@ -34,7 +34,7 @@ #include #include -#include +//#include #ifdef __APPLE__ #include #else @@ -483,20 +483,20 @@ static void oaes_get_seed( char buf[RANDSIZ + 1] ) #else static uint32_t oaes_get_seed(void) { - struct timeb timer; - struct tm *gmTimer; - char * _test = NULL; +// struct timeb timer; +// struct tm *gmTimer; +// char * _test = NULL; uint32_t _ret = 0; - ftime (&timer); - gmTimer = gmtime( &timer.time ); - _test = (char *) calloc( sizeof( char ), timer.millitm ); - _ret = (uint32_t)(gmTimer->tm_year + 1900 + gmTimer->tm_mon + 1 + gmTimer->tm_mday + - gmTimer->tm_hour + gmTimer->tm_min + gmTimer->tm_sec + timer.millitm + - (uintptr_t) ( _test + timer.millitm )); +// ftime (&timer); +// gmTimer = gmtime( &timer.time ); +// _test = (char *) calloc( sizeof( char ), timer.millitm ); +// _ret = (uint32_t)(gmTimer->tm_year + 1900 + gmTimer->tm_mon + 1 + gmTimer->tm_mday + +// gmTimer->tm_hour + gmTimer->tm_min + gmTimer->tm_sec + timer.millitm + +// (uintptr_t) ( _test + timer.millitm )); - if( _test ) - free( _test ); +// if( _test ) +// free( _test ); return _ret; } diff --git a/src/crypto/random.h b/src/crypto/random.h index 9c615e7a..e072eab9 100644 --- a/src/crypto/random.h +++ b/src/crypto/random.h @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/crypto/slow-hash_stdc.c b/src/crypto/slow-hash_stdc.c index aa7bbf9e..e4d4d711 100644 --- a/src/crypto/slow-hash_stdc.c +++ b/src/crypto/slow-hash_stdc.c @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include #include @@ -151,7 +151,7 @@ static void cn_slow_hash_platform_independent(void * scratchpad, const void *dat oaes_free(&aes_ctx); } -#if TARGET_OS_IPHONE // We need if !x86, but no portable way to express that +#if TARGET_OS_IPHONE || defined(__ANDROID__) // We need if !x86, but no portable way to express that void cn_slow_hash(void * scratchpad, const void *data, size_t length, void *hash) { cn_slow_hash_platform_independent(scratchpad, data, length, hash); } diff --git a/src/crypto/slow-hash_x86.c b/src/crypto/slow-hash_x86.c index dd701498..ff707089 100644 --- a/src/crypto/slow-hash_x86.c +++ b/src/crypto/slow-hash_x86.c @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include #include diff --git a/src/crypto/slow-hash_x86.inl b/src/crypto/slow-hash_x86.inl index 19b5b0a2..d5aee11a 100644 --- a/src/crypto/slow-hash_x86.inl +++ b/src/crypto/slow-hash_x86.inl @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. // No protection from double-include, this file is included twice in slow-hash_x86.c diff --git a/src/crypto/tree-hash.c b/src/crypto/tree-hash.c index c949362f..5a26d640 100644 --- a/src/crypto/tree-hash.c +++ b/src/crypto/tree-hash.c @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include #include diff --git a/src/crypto/types.hpp b/src/crypto/types.hpp index ad6b2ea4..46815894 100644 --- a/src/crypto/types.hpp +++ b/src/crypto/types.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once @@ -13,45 +13,43 @@ namespace crypto { #pragma pack(push, 1) struct Hash { - uint8_t data[32]{}; + uint8_t data[32]{}; }; struct PublicKey : public EllipticCurvePoint { - PublicKey():EllipticCurvePoint{}{} + PublicKey() : EllipticCurvePoint{} {} }; struct SecretKey : public EllipticCurveScalar { - SecretKey():EllipticCurveScalar{}{} - ~SecretKey() { - sodium_memzero(data, sizeof(data)); - } + SecretKey() : EllipticCurveScalar{} {} + ~SecretKey() { sodium_memzero(data, sizeof(data)); } }; struct KeyDerivation : public EllipticCurvePoint { - KeyDerivation():EllipticCurvePoint{}{} + KeyDerivation() : EllipticCurvePoint{} {} }; struct KeyImage : public EllipticCurvePoint { - KeyImage():EllipticCurvePoint{}{} + KeyImage() : EllipticCurvePoint{} {} }; struct Signature { - EllipticCurveScalar c, r; - Signature():c{}, r{}{} + EllipticCurveScalar c, r; + Signature() : c{}, r{} {} }; #pragma pack(pop) static_assert(sizeof(EllipticCurvePoint) == 32 && sizeof(EllipticCurveScalar) == 32, "Invalid structure size"); -static_assert(sizeof(Hash) == 32 && sizeof(PublicKey) == 32 - && sizeof(SecretKey) == 32 && sizeof(KeyDerivation) == 32 - && sizeof(KeyImage) == 32 && sizeof(Signature) == 64, "Invalid structure size"); +static_assert(sizeof(Hash) == 32 && sizeof(PublicKey) == 32 && sizeof(SecretKey) == 32 && sizeof(KeyDerivation) == 32 && + sizeof(KeyImage) == 32 && + sizeof(Signature) == 64, + "Invalid structure size"); -struct KeyPair { // Never used as a pod +struct KeyPair { // Never used as a pod PublicKey publicKey; SecretKey secretKey; }; - } CRYPTO_MAKE_HASHABLE(crypto, Hash) @@ -67,4 +65,3 @@ CRYPTO_MAKE_HASHABLE(crypto, SecretKey) CRYPTO_MAKE_COMPARABLE(crypto, SecretKey, crypto::sodium_compare) CRYPTO_MAKE_COMPARABLE(crypto, Signature, std::memcmp) - diff --git a/src/http/Agent.cpp b/src/http/Agent.cpp index 883c60bb..c36d19ea 100644 --- a/src/http/Agent.cpp +++ b/src/http/Agent.cpp @@ -1,13 +1,17 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "Agent.hpp" +#include #include +#include #include #include using namespace http; +static const int REQUEST_TIMEOUT = 30; + Agent::Connection::Connection(handler r_handler, handler d_handler) : buffer(8192) , receiving_body(false) @@ -125,28 +129,27 @@ Agent::Agent(const std::string &address, uint16_t port) , address(address) , port(port) , client(std::bind(&Agent::on_client_response, this), std::bind(&Agent::on_client_disconnect, this)) - , reconnect_timer(std::bind(&Agent::on_reconnect_timer, this)) { - on_reconnect_timer(); -} + , reconnect_timer(std::bind(&Agent::on_reconnect_timer, this)) {} Agent::~Agent() { assert(!sent_request); } -bool Agent::disconnected_for_long_time() const { - return false; // TODO - implement. For now will wait forever for reconnection -} - void Agent::set_request(Request *req) { if (sent_request) throw std::logic_error("Agent is busy with previous request"); - sent_request = req; - send_request(); + sent_request = req; + request_start = std::chrono::steady_clock::now(); + if (!client.is_open() && !client.connect(address, port)) { + reconnect_timer.once(10); + return; + } + client.write(RequestData(sent_request->req)); } void Agent::cancel_request(Request *req) { if (sent_request == req) { sent_request = nullptr; client.disconnect(); - reconnect_timer.once(10); + reconnect_timer.cancel(); } } @@ -171,32 +174,39 @@ void Agent::on_client_response() { } } -void Agent::on_client_disconnect() { reconnect_timer.once(10); } - -void Agent::send_request() { - if (client.is_open()) - client.write(RequestData(sent_request->req)); +void Agent::on_client_disconnect() { + if (sent_request) + reconnect_timer.once(10); } void Agent::on_reconnect_timer() { - if (disconnected_for_long_time() && sent_request) { - auto was_sent_request = sent_request; - sent_request = nullptr; - if (was_sent_request) { - Request::E_handler e_handler = std::move(was_sent_request->e_handler); - e_handler("Timeout"); - } + if (!sent_request) + return; // Should not happen + auto idea_sec = std::chrono::duration_cast(std::chrono::steady_clock::now() - request_start); + if (idea_sec.count() > REQUEST_TIMEOUT) { + auto was_sent_request = sent_request; + sent_request = nullptr; + Request::E_handler e_handler = std::move(was_sent_request->e_handler); + e_handler("Timeout"); + return; } - if (!client.connect(address, port)) { + if (!client.is_open() && !client.connect(address, port)) { reconnect_timer.once(10); return; } - if (sent_request) - send_request(); + client.write(RequestData(sent_request->req)); } Request::Request(Agent &agent, RequestData &&req, R_handler r_handler, E_handler e_handler) : agent(agent), req(std::move(req)), r_handler(r_handler), e_handler(e_handler) { + std::string host = agent.address; + const std::string prefix1("https://"); + const std::string prefix2("ssl://"); + if (host.find(prefix1) == 0) + host = host.substr(prefix1.size()); + else if (host.find(prefix2) == 0) + host = host.substr(prefix2.size()); + this->req.r.host = host; agent.set_request(this); } diff --git a/src/http/Agent.hpp b/src/http/Agent.hpp index 39a633d9..c230a4f6 100644 --- a/src/http/Agent.hpp +++ b/src/http/Agent.hpp @@ -1,9 +1,10 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once #include +#include #include #include #include @@ -59,8 +60,8 @@ class Agent { uint16_t port; Connection client; platform::Timer reconnect_timer; + std::chrono::steady_clock::time_point request_start; - void send_request(); void on_client_response(); void on_client_disconnect(); void on_reconnect_timer(); @@ -71,7 +72,6 @@ class Agent { public: Agent(const std::string &address, uint16_t port); ~Agent(); - bool disconnected_for_long_time() const; }; class Request { diff --git a/src/http/JsonRpc.cpp b/src/http/JsonRpc.cpp index 9595e741..134db426 100644 --- a/src/http/JsonRpc.cpp +++ b/src/http/JsonRpc.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "http/JsonRpc.h" @@ -28,26 +28,26 @@ std::string Error::get_message(int code) { } Error::Error(int c, const std::string &msg) : code(c), message(msg) {} -void makeErrorResponse(const std::error_code &ec, common::JsonValue &resp) { - common::JsonValue error(common::JsonValue::OBJECT); +/*void makeErrorResponse(const std::error_code &ec, common::JsonValue &resp) { + common::JsonValue error(common::JsonValue::OBJECT); - // JsonValue code; - // code = static_cast(-32000); //Application specific error code + // JsonValue code; + // code = static_cast(-32000); //Application specific error code - // JsonValue message; - // message = ; + // JsonValue message; + // message = ; - common::JsonValue data(common::JsonValue::OBJECT); - // JsonValue appCode; - // appCode = static_cast(); - data.insert("application_code", common::JsonValue::Integer(ec.value())); + common::JsonValue data(common::JsonValue::OBJECT); + // JsonValue appCode; + // appCode = static_cast(); + data.insert("application_code", common::JsonValue::Integer(ec.value())); - error.insert("code", common::JsonValue::Integer(-32000)); - error.insert("message", ec.message()); - error.insert("data", data); + error.insert("code", common::JsonValue::Integer(-32000)); + error.insert("message", ec.message()); + error.insert("data", data); - resp.insert("error", error); -} + resp.insert("error", error); +}*/ void makeGenericErrorReponse(common::JsonValue &resp, const std::string &what, int errorCode) { common::JsonValue error(common::JsonValue::OBJECT); diff --git a/src/http/JsonRpc.h b/src/http/JsonRpc.h index 31d665a8..662eedd2 100644 --- a/src/http/JsonRpc.h +++ b/src/http/JsonRpc.h @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once @@ -176,7 +176,7 @@ bool invoke_method(Agent *agent, RawRequest &&raw_request, Request &&jsReq, Resp } template -std::function makeMemberMethodSeria( +std::function makeMemberMethod( bool (Owner::*handler)(Agent *, RawRequest &&, json_rpc::Request &&, Params &&, Result &)) { return [handler](Owner *obj, Agent *agent, RawRequest &&raw_request, Request &&req, Response &res) -> bool { return json_rpc::invoke_method(agent, std::move(raw_request), std::move(req), @@ -211,6 +211,17 @@ http::ResponseData create_response( last_http_response.r.status = 200; return last_http_response; } +inline http::ResponseData create_error_response( + const http::RequestData &request, const Error &response, const OptionalJsonValue &id = OptionalJsonValue{}) { + json_rpc::Response last_json_resp; + last_json_resp.set_id(id); + last_json_resp.set_error(response); + http::ResponseData last_http_response(request.r); + last_http_response.r.headers.push_back({"Content-Type", "application/json; charset=utf-8"}); + last_http_response.set_body(last_json_resp.get_body()); + last_http_response.r.status = 200; + return last_http_response; +} template void parse_response(const std::string &body, ResponseType &response, OptionalJsonValue *jid = nullptr) { diff --git a/src/http/RequestParser.cpp b/src/http/RequestParser.cpp index cd797b3c..bacc57af 100644 --- a/src/http/RequestParser.cpp +++ b/src/http/RequestParser.cpp @@ -4,7 +4,7 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "RequestParser.hpp" #include @@ -168,6 +168,11 @@ bool RequestParser::process_ready_header(request &req) { } return false; } + if (lowcase.name == "host") { + req.host = lowcase.value; + req.headers.pop_back(); + return true; + } if (lowcase.name == "connection") { if (lowcase.value == "close") { req.keep_alive = false; @@ -194,6 +199,7 @@ bool RequestParser::process_ready_header(request &req) { while (finish > start && (value[finish - 1] == ' ' || value[finish - 1] == '\t')) finish -= 1; req.basic_authorization = value.substr(start, finish - start); + req.headers.pop_back(); return true; } return true; diff --git a/src/http/RequestParser.hpp b/src/http/RequestParser.hpp index 514efe0f..93f78b8a 100644 --- a/src/http/RequestParser.hpp +++ b/src/http/RequestParser.hpp @@ -4,7 +4,7 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/http/ResponseParser.cpp b/src/http/ResponseParser.cpp index 4e34162a..7384e98d 100644 --- a/src/http/ResponseParser.cpp +++ b/src/http/ResponseParser.cpp @@ -4,7 +4,7 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "ResponseParser.hpp" #include diff --git a/src/http/ResponseParser.hpp b/src/http/ResponseParser.hpp index aeef638c..d9a94453 100644 --- a/src/http/ResponseParser.hpp +++ b/src/http/ResponseParser.hpp @@ -4,7 +4,7 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/http/Server.cpp b/src/http/Server.cpp index 72ef5ec7..8e3ac0c9 100644 --- a/src/http/Server.cpp +++ b/src/http/Server.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "Server.hpp" #include diff --git a/src/http/Server.hpp b/src/http/Server.hpp index 08f76d89..c5610d26 100644 --- a/src/http/Server.hpp +++ b/src/http/Server.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/http/types.cpp b/src/http/types.cpp index 1a2a3201..e96a14e9 100644 --- a/src/http/types.cpp +++ b/src/http/types.cpp @@ -4,7 +4,7 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "types.hpp" #include @@ -75,6 +75,8 @@ std::string request::to_string() const { std::stringstream ss; ss << method << " " << uri << " " << "HTTP/" << http_version_major << "." << http_version_minor << "\r\n"; + if (!host.empty()) + ss << "Host: " << host << "\r\n"; for (auto &&h : headers) ss << h.name << ": " << h.value << "\r\n"; if (!basic_authorization.empty()) diff --git a/src/http/types.hpp b/src/http/types.hpp index 39f50b5b..e7e2c53b 100644 --- a/src/http/types.hpp +++ b/src/http/types.hpp @@ -4,7 +4,7 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once @@ -26,6 +26,7 @@ struct request { std::vector
headers; std::string basic_authorization; + std::string host; bool keep_alive = true; size_t content_length = -1; diff --git a/src/logging/CommonLogger.cpp b/src/logging/CommonLogger.cpp index 87af402d..c2748ea5 100644 --- a/src/logging/CommonLogger.cpp +++ b/src/logging/CommonLogger.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "CommonLogger.hpp" diff --git a/src/logging/CommonLogger.hpp b/src/logging/CommonLogger.hpp index c0dfea22..786c3e1b 100644 --- a/src/logging/CommonLogger.hpp +++ b/src/logging/CommonLogger.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/logging/ConsoleLogger.cpp b/src/logging/ConsoleLogger.cpp index 14886087..0d459abe 100644 --- a/src/logging/ConsoleLogger.cpp +++ b/src/logging/ConsoleLogger.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "ConsoleLogger.hpp" #include diff --git a/src/logging/ConsoleLogger.hpp b/src/logging/ConsoleLogger.hpp index 1f6466a8..fbb57fa8 100644 --- a/src/logging/ConsoleLogger.hpp +++ b/src/logging/ConsoleLogger.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/logging/FileLogger.cpp b/src/logging/FileLogger.cpp index b72615e1..548ff90e 100644 --- a/src/logging/FileLogger.cpp +++ b/src/logging/FileLogger.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "FileLogger.hpp" #include "platform/PathTools.hpp" diff --git a/src/logging/FileLogger.hpp b/src/logging/FileLogger.hpp index a0af5a22..fbe58ca0 100644 --- a/src/logging/FileLogger.hpp +++ b/src/logging/FileLogger.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/logging/ILogger.cpp b/src/logging/ILogger.cpp index 9158d590..cd6c57fb 100644 --- a/src/logging/ILogger.cpp +++ b/src/logging/ILogger.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "ILogger.hpp" diff --git a/src/logging/ILogger.hpp b/src/logging/ILogger.hpp index 5fd2a3b3..6b9d88b4 100644 --- a/src/logging/ILogger.hpp +++ b/src/logging/ILogger.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/logging/LoggerGroup.cpp b/src/logging/LoggerGroup.cpp index 4b63863a..a080c3d1 100644 --- a/src/logging/LoggerGroup.cpp +++ b/src/logging/LoggerGroup.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "LoggerGroup.hpp" #include diff --git a/src/logging/LoggerGroup.hpp b/src/logging/LoggerGroup.hpp index d203385b..343cef46 100644 --- a/src/logging/LoggerGroup.hpp +++ b/src/logging/LoggerGroup.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/logging/LoggerManager.cpp b/src/logging/LoggerManager.cpp index ceddca3e..8bbdd9f4 100644 --- a/src/logging/LoggerManager.cpp +++ b/src/logging/LoggerManager.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "LoggerManager.hpp" #include diff --git a/src/logging/LoggerManager.hpp b/src/logging/LoggerManager.hpp index 7f731cfd..cd50050e 100644 --- a/src/logging/LoggerManager.hpp +++ b/src/logging/LoggerManager.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/logging/LoggerMessage.cpp b/src/logging/LoggerMessage.cpp index 9603bee2..8067f373 100644 --- a/src/logging/LoggerMessage.cpp +++ b/src/logging/LoggerMessage.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "LoggerMessage.hpp" diff --git a/src/logging/LoggerMessage.hpp b/src/logging/LoggerMessage.hpp index 78dfaee4..3ceca65d 100644 --- a/src/logging/LoggerMessage.hpp +++ b/src/logging/LoggerMessage.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/main_bitsumd.cpp b/src/main_bitsumd.cpp new file mode 100644 index 00000000..81fe4a24 --- /dev/null +++ b/src/main_bitsumd.cpp @@ -0,0 +1,103 @@ +// Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. + +#include +#include "Core/Config.hpp" +#include "Core/Node.hpp" +#include "common/CommandLine.hpp" +#include "common/ConsoleTools.hpp" +#include "logging/LoggerManager.hpp" +#include "platform/ExclusiveLock.hpp" +#include "platform/Network.hpp" +#include "platform/PathTools.hpp" +#include "version.hpp" + +using namespace bytecoin; + +static const char USAGE[] = + R"(bitsumd )" bytecoin_VERSION_STRING R"(. + +Usage: + bitsumd [options] + bitsumd --help | -h + bitsumd --version | -v + +Options: + --export-blocks= Export blockchain into specified directory as blocksx.bin and blockindexesx.bin, then exit. This overwrites existing files. + --allow-local-ip Allow local ip add to peer list, mostly in debug purposes. + --testnet Configure for testnet. + --p2p-bind-address= Interface and port for P2P network protocol [default: 0.0.0.0:28080]. + --p2p-external-port= External port for P2P network protocol, if port forwarding used with NAT [default: 28080]. + --daemon-rpc-bind-address= Interface and port for bitsumd RPC [default: 0.0.0.0:28081]. + --seed-node-address= Specify list (one or more) of nodes to start connecting to. + --priority-node-address= Specify list (one or more) of nodes to connect to and attempt to keep the connection open. + --exclusive-node-address= Specify list (one or more) of nodes to connect to only. All other nodes including seed nodes will be ignored. + --data-folder= Folder for blockchain, logs and peer DB [default: )" platform_DEFAULT_DATA_FOLDER_PATH_PREFIX + R"(bitsum]. +)" +#if platform_USE_SSL + R"( --ssl-certificate-pem-file= Full path to file containing both server SSL certificate and private key in PEM format. + --ssl-certificate-password= DEPRECATED. Will read password from stdin if not specified.)" +#endif + R"( --rpc-authorization= HTTP authorization for RPC.)"; + +int main(int argc, const char *argv[]) try { + common::console::UnicodeConsoleSetup console_setup; + auto idea_start = std::chrono::high_resolution_clock::now(); + common::CommandLine cmd(argc, argv); + + std::string export_blocks; + if (const char *pa = cmd.get("--export-blocks")) + export_blocks = pa; + bytecoin::Config config(cmd); + bytecoin::Currency currency(config.is_testnet); + + if (cmd.should_quit(USAGE, bytecoin::app_version())) + return 0; + + if (!config.ssl_certificate_pem_file.empty() && !config.ssl_certificate_password) { + std::string ssl_certificate_password; + std::cout << "Enter ssl certificate password: " << std::flush; + std::getline(std::cin, ssl_certificate_password); + boost::algorithm::trim(ssl_certificate_password); + + config.ssl_certificate_password = ssl_certificate_password; + } + + const std::string coinFolder = config.get_data_folder(); + + platform::ExclusiveLock coin_lock(coinFolder, "bitsumd.lock"); + + logging::LoggerManager logManager; + logManager.configure_default(config.get_data_folder("logs"), "bitsumd-"); + + BlockChainState block_chain(logManager, config, currency); + + if (!export_blocks.empty()) { + if (!LegacyBlockChainWriter::export_blockchain2(export_blocks, block_chain)) + return 1; + return 0; + } + + boost::asio::io_service io; + platform::EventLoop run_loop(io); + + Node node(logManager, config, block_chain); + + auto idea_ms = + std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - idea_start); + std::cout << "bitsumd started seconds=" << double(idea_ms.count()) / 1000 << std::endl; + while (!io.stopped()) { + if (node.on_idle()) // Using it to load blockchain + io.poll(); + else + io.run_one(); + } + return 0; +} catch (const platform::ExclusiveLock::FailedToLock &ex) { + std::cout << "bitsumd already running - " << ex.what() << std::endl; + return api::BYTECOIND_ALREADY_RUNNING; +} catch (const std::exception &ex) { // On Windows what() is not printed if thrown from main + std::cout << "Exception in main() - " << ex.what() << std::endl; + throw; +} diff --git a/src/main_tests.cpp b/src/main_tests.cpp index 9fb3a7f9..04cf1cba 100644 --- a/src/main_tests.cpp +++ b/src/main_tests.cpp @@ -1,12 +1,11 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include #include "Core/BlockChainState.hpp" #include "Core/Config.hpp" #include "Core/Difficulty.hpp" #include "Core/TransactionExtra.hpp" -#include "common/CommandLine.hpp" #include "crypto/crypto.hpp" #include "logging/ConsoleLogger.hpp" #include "seria/BinaryInputStream.hpp" @@ -48,8 +47,8 @@ static void fix_merge_mining_tag(BlockTemplate &block) { void test_blockchain(common::CommandLine &cmd) { logging::ConsoleLogger logger; Config config(cmd); - config.coin_directory = "/home/user/devbox/bytecoin/tests"; - bytecoin::BlockChain::DB::delete_db(config.coin_directory + "/blockchain"); + config.data_folder = "../tests"; + bytecoin::BlockChain::DB::delete_db(config.data_folder + "/blockchain"); Currency currency(config.is_testnet); BlockChainState block_chain(logger, config, currency); block_chain.test_print_structure(); diff --git a/src/main_wallet_rpc.cpp b/src/main_wallet_rpc.cpp new file mode 100644 index 00000000..2d70ccfe --- /dev/null +++ b/src/main_wallet_rpc.cpp @@ -0,0 +1,278 @@ +// Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. + +#include +#include +#include +#include "Core/Config.hpp" +#include "Core/Node.hpp" +#include "Core/WalletNode.hpp" +#include "common/CommandLine.hpp" +#include "common/ConsoleTools.hpp" +#include "logging/LoggerManager.hpp" +#include "platform/ExclusiveLock.hpp" +#include "platform/Network.hpp" +#include "platform/PathTools.hpp" +#include "version.hpp" + +using namespace bytecoin; + +static const char USAGE[] = + R"(wallet-rpc )" bytecoin_VERSION_STRING R"(. + +Usage: + wallet-rpc [options] --wallet-file= | --export-blocks= + wallet-rpc --help | -h + wallet-rpc --version | -v + +Options: + --wallet-file= Path to wallet file to open. + --wallet-password= DEPRECATED AND NOT RECOMMENDED (as entailing security risk). Use given string as password and not read it from stdin. + --create-wallet Create wallet file with new random keys. Must be used with --wallet-file option. + --import-keys Create wallet file with imported keys read as a line from stdin. Must be used with --create-wallet. + --set-password Read new password as a line from stdin (twice) and reencrypt wallet file. + --export-view-only= Export view-only version of wallet file with the same password, then exit. + --testnet Configure for testnet. + --wallet-rpc-bind-address= Interface and port for wallet-rpc [default: 127.0.0.1:28082]. + --data-folder= Folder for wallet cache, blockchain, logs and peer DB [default: )" platform_DEFAULT_DATA_FOLDER_PATH_PREFIX + R"(bitsum]. + --daemon-remote-address= Connect to remote bitsumd and suppress running built-in bitsumd. + --rpc-authorization= HTTP authorization for RCP. + +Options for built-in bitsumd (run when no --daemon-remote-address specified): + --allow-local-ip Allow local ip add to peer list, mostly in debug purposes. + --p2p-bind-address= Interface and port for P2P network protocol [default: 0.0.0.0:28080]. + --p2p-external-port= External port for P2P network protocol, if port forwarding used with NAT [default: 28080]. + --daemon-rpc-bind-address= Interface and port for bitsumd RPC [default: 0.0.0.0:28081]. + --seed-node-address= Specify list (one or more) of nodes to start connecting to. + --priority-node-address= Specify list (one or more) of nodes to connect to and attempt to keep the connection open. + --exclusive-node-address= Specify list (one or more) of nodes to connect to only. All other nodes including seed nodes will be ignored.)"; + +static const bool separate_thread_for_bytecoind = true; + +int main(int argc, const char *argv[]) try { + common::console::UnicodeConsoleSetup console_setup; + auto idea_start = std::chrono::high_resolution_clock::now(); + common::CommandLine cmd(argc, argv); + std::string wallet_file, password, new_password, export_view_only, import_keys_value; + bool set_password = false; + bool ask_password = true; + bool import_keys = false; + bool create_wallet = false; + if (const char *pa = cmd.get("--wallet-file")) + wallet_file = pa; + if (const char *pa = cmd.get("--container-file", "Use --wallet-file instead")) + wallet_file = pa; + if (cmd.get_bool("--create-wallet")) + create_wallet = true; + else if (cmd.get_bool("--generate-container", "Use --create-wallet instead")) + create_wallet = true; + if (const char *pa = cmd.get("--export-view-only")) + export_view_only = pa; + if (const char *pa = cmd.get("--wallet-password")) { + password = pa; + ask_password = false; + } else if (const char *pa = cmd.get("--container-password", "Use --wallet-password instead")) { + password = pa; + ask_password = false; + } + if (!ask_password) { + if (create_wallet) { + std::cout + << "When generating wallet, you cannot use --wallet-password. Wallet password will be read from stdin" + << std::endl; + return api::WALLETD_WRONG_ARGS; + } + common::console::set_text_color(common::console::BrightRed); + std::cout << "Password on command line is a security risk." << std::endl; + common::console::set_text_color(common::console::Default); + } + set_password = cmd.get_bool("--set-password"); // mark option as used + if (create_wallet) + import_keys = cmd.get_bool("--import-keys"); + bytecoin::Config config(cmd); + + bytecoin::Currency currency(config.is_testnet); + + if (cmd.should_quit(USAGE, bytecoin::app_version())) + return api::WALLETD_WRONG_ARGS; + logging::LoggerManager logManagerNode; + logManagerNode.configure_default(config.get_data_folder("logs"), "bitsumd-"); + + if (wallet_file.empty()) { + std::cout << "--wallet-file= argument is mandatory" << std::endl; + return api::WALLETD_WRONG_ARGS; + } + if (create_wallet && import_keys && import_keys_value.empty()) { + std::cout << "Enter imported keys as hex bytes (05AB6F... etc.): " << std::flush; + if (!std::getline(std::cin, import_keys_value)) { + std::cout << "Unexpected end of stdin" << std::endl; + return api::WALLETD_WRONG_ARGS; + } + boost::algorithm::trim(import_keys_value); + if (import_keys_value.empty()) { + std::cout << "Imported keys should not be empty" << std::endl; + return api::WALLETD_WRONG_ARGS; + } + } + if (!create_wallet && ask_password) { + std::cout << "Enter current wallet password: " << std::flush; + if (!std::getline(std::cin, password)) { + std::cout << "Unexpected end of stdin" << std::endl; + return api::WALLETD_WRONG_ARGS; + } + boost::algorithm::trim(password); + } + if (create_wallet || set_password) { + std::cout << "Enter new wallet password: " << std::flush; + if (!std::getline(std::cin, new_password)) { + std::cout << "Unexpected end of stdin" << std::endl; + return api::WALLETD_WRONG_ARGS; + } + boost::algorithm::trim(new_password); + std::cout << "Repeat new wallet password:" << std::flush; + std::string new_password2; + if (!std::getline(std::cin, new_password2)) { + std::cout << "Unexpected end of stdin" << std::endl; + return api::WALLETD_WRONG_ARGS; + } + boost::algorithm::trim(new_password2); + if (new_password != new_password2) { + std::cout << "New passwords do not match" << std::endl; + return api::WALLETD_WRONG_ARGS; + } + } + std::cout << "Enter HTTP authorization : for wallet-rpc: " << std::flush; + std::string auth; + if (!std::getline(std::cin, auth)) { + std::cout << "Unexpected end of stdin" << std::endl; + return api::WALLETD_WRONG_ARGS; + } + boost::algorithm::trim(auth); + config.walletd_authorization = common::base64::encode(BinaryArray(auth.data(), auth.data() + auth.size())); + if (config.walletd_authorization.empty()) { + common::console::set_text_color(common::console::BrightRed); + std::cout << "No authorization for RPC is a security risk. Use username with a strong password" << std::endl; + common::console::set_text_color(common::console::Default); + } else { + if (auth.find(":") == std::string::npos) { + std::cout << "HTTP authorization must be in the format :" << std::endl; + return api::WALLETD_WRONG_ARGS; + } + } + const std::string coinFolder = config.get_data_folder(); + // if (wallet_file.empty() && !generate_wallet) // No args can be provided when debugging with MSVC + // wallet_file = "C:\\Users\\user\\test.wallet"; + + std::unique_ptr blockchain_lock; + std::unique_ptr walletcache_lock; + std::unique_ptr wallet; + try { + if (!config.bytecoind_remote_port) + blockchain_lock = std::make_unique(coinFolder, "bitsumd.lock"); + } catch (const platform::ExclusiveLock::FailedToLock &ex) { + std::cout << "bitsumd already running - " << ex.what() << std::endl; + return api::BYTECOIND_ALREADY_RUNNING; + } + try { + wallet = std::make_unique( + wallet_file, create_wallet ? new_password : password, create_wallet, import_keys_value); + walletcache_lock = std::make_unique( + config.get_data_folder("wallet_cache"), wallet->get_cache_name() + ".lock"); + } catch (const common::StreamError &ex) { + std::cout << ex.what() << std::endl; + return api::WALLET_FILE_READ_ERROR; + } catch (const platform::ExclusiveLock::FailedToLock &ex) { + std::cout << ex.what() << std::endl; + return api::WALLET_WITH_THE_SAME_VIEWKEY_IN_USE; + } catch (const Wallet::Exception &ex) { + std::cout << ex.what() << std::endl; + return ex.return_code; + } + try { + if (set_password) + wallet->set_password(new_password); + if (!export_view_only.empty()) { + wallet->export_view_only(export_view_only); + return 0; + } + } catch (const common::StreamError &ex) { + std::cout << ex.what() << std::endl; + return api::WALLET_FILE_WRITE_ERROR; + } catch (const Wallet::Exception &ex) { + std::cout << ex.what() << std::endl; + return ex.return_code; + } + logging::LoggerManager logManagerWalletNode; + logManagerWalletNode.configure_default(config.get_data_folder("logs"), "wallet-rpc-"); + + WalletState wallet_state(*wallet, logManagerWalletNode, config, currency); + boost::asio::io_service io; + platform::EventLoop run_loop(io); + + std::unique_ptr block_chain; + std::unique_ptr node; + + std::promise prm; + std::thread bytecoind_thread; + if (!config.bytecoind_remote_port) { + try { + if (separate_thread_for_bytecoind) { + bytecoind_thread = std::thread([&prm, &logManagerNode, &config, ¤cy] { + boost::asio::io_service io; + platform::EventLoop separate_run_loop(io); + + std::unique_ptr separate_block_chain; + std::unique_ptr separate_node; + try { + separate_block_chain = std::make_unique(logManagerNode, config, currency); + separate_node = std::make_unique(logManagerNode, config, *separate_block_chain); + prm.set_value(); + } catch (...) { + prm.set_exception(std::current_exception()); + return; + } + while (!io.stopped()) { + if (separate_node->on_idle()) // We load blockchain there + io.poll(); + else + io.run_one(); + } + }); + std::future fut = prm.get_future(); + fut.get(); // propagates thread exception from here + } else { + block_chain = std::make_unique(logManagerNode, config, currency); + node = std::make_unique(logManagerNode, config, *block_chain); + } + } catch (const boost::system::system_error &ex) { + std::cout << ex.what() << std::endl; + if (bytecoind_thread.joinable()) + bytecoind_thread.join(); // otherwise terminate will be called in ~thread + return api::BYTECOIND_BIND_PORT_IN_USE; + } + } + + std::unique_ptr wallet_node; + try { + wallet_node = std::make_unique(nullptr, logManagerWalletNode, config, wallet_state); + } catch (const boost::system::system_error &ex) { + std::cout << ex.what() << std::endl; + return api::WALLETD_BIND_PORT_IN_USE; + } + + auto idea_ms = + std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - idea_start); + std::cout << "wallet-rpc started seconds=" << double(idea_ms.count()) / 1000 << std::endl; + + while (!io.stopped()) { + if (node && node->on_idle()) // We load blockchain there + io.poll(); + else + io.run_one(); + } + return 0; +} catch (const std::exception &ex) { // On Windows what() is not printed if thrown from main + std::cout << "Exception in main() - " << ex.what() << std::endl; + throw; +} diff --git a/src/p2p/CryptoNoteProtocolDefinitions.hpp b/src/p2p/CryptoNoteProtocolDefinitions.hpp index f599b4a6..05a08547 100644 --- a/src/p2p/CryptoNoteProtocolDefinitions.hpp +++ b/src/p2p/CryptoNoteProtocolDefinitions.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/p2p/LevinProtocol.cpp b/src/p2p/LevinProtocol.cpp index f92cd719..011473a9 100644 --- a/src/p2p/LevinProtocol.cpp +++ b/src/p2p/LevinProtocol.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "LevinProtocol.hpp" diff --git a/src/p2p/LevinProtocol.hpp b/src/p2p/LevinProtocol.hpp index cda36335..7daba27f 100644 --- a/src/p2p/LevinProtocol.hpp +++ b/src/p2p/LevinProtocol.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/p2p/P2P.cpp b/src/p2p/P2P.cpp index 7817992c..71c9e6fc 100644 --- a/src/p2p/P2P.cpp +++ b/src/p2p/P2P.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "P2P.hpp" #include @@ -179,7 +179,7 @@ void P2P::accept_all() { if (!la_socket->accept(next_client[incoming]->sock, addr)) return; NetworkAddress address; - common::parse_ip_address(address.ip, addr); + common::parse_ip_address(addr, address.ip); address.port = config.p2p_bind_port; next_client[incoming]->address = address; if (peers.is_peer_banned(address, get_local_time())) { diff --git a/src/p2p/P2P.hpp b/src/p2p/P2P.hpp index 32b57324..b1999e17 100644 --- a/src/p2p/P2P.hpp +++ b/src/p2p/P2P.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/p2p/P2PClientBasic.cpp b/src/p2p/P2PClientBasic.cpp index 2d636314..c5c2b9ef 100644 --- a/src/p2p/P2PClientBasic.cpp +++ b/src/p2p/P2PClientBasic.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "P2PClientBasic.hpp" #include @@ -33,7 +33,7 @@ std::map, P2PClientBasic::LevinHandlerFunction> P2PCli std::map, P2PClientBasic::LevinHandlerFunction> P2PClientBasic::after_handshake_handlers = { {{COMMAND_TIMED_SYNC::ID, false}, levinMethod(&P2PClientBasic::msg_timed_sync)}, {{COMMAND_TIMED_SYNC::ID, true}, levinMethod(&P2PClientBasic::msg_timed_sync)}, -#ifdef ALLOW_DEBUG_COMMANDS +#if bytecoin_ALLOW_DEBUG_COMMANDS {{COMMAND_REQUEST_NETWORK_STATE::ID, false}, levinMethod(&P2PClientBasic::on_msg_network_state)}, {{COMMAND_REQUEST_NETWORK_STATE::ID, true}, diff --git a/src/p2p/P2PClientBasic.hpp b/src/p2p/P2PClientBasic.hpp index 3c66fdf3..6d271ba7 100644 --- a/src/p2p/P2PClientBasic.hpp +++ b/src/p2p/P2PClientBasic.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once @@ -53,7 +53,7 @@ class P2PClientBasic : public P2PClient { virtual void on_msg_ping(COMMAND_PING::response &&) {} // called after some internal processing virtual void on_msg_timed_sync(COMMAND_TIMED_SYNC::request &&) {} // called after some internal processing virtual void on_msg_timed_sync(COMMAND_TIMED_SYNC::response &&) {} // called after some internal processing -#ifdef ALLOW_DEBUG_COMMANDS +#if bytecoin_ALLOW_DEBUG_COMMANDS virtual void on_msg_network_state(COMMAND_REQUEST_NETWORK_STATE::request &&) {} virtual void on_msg_network_state(COMMAND_REQUEST_NETWORK_STATE::response &&) {} virtual void on_msg_stat_info(COMMAND_REQUEST_STAT_INFO::request &&) {} diff --git a/src/p2p/P2pProtocolDefinitions.hpp b/src/p2p/P2pProtocolDefinitions.hpp index 795deb77..81d5711a 100644 --- a/src/p2p/P2pProtocolDefinitions.hpp +++ b/src/p2p/P2pProtocolDefinitions.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once @@ -83,7 +83,7 @@ struct COMMAND_PING { }; }; -#ifdef ALLOW_DEBUG_COMMANDS +#if bytecoin_ALLOW_DEBUG_COMMANDS // These commands are considered as insecure, and made in debug purposes for a limited lifetime. // Anyone who feel unsafe with this commands can disable the ALLOW_GET_STAT_COMMAND macro. @@ -159,7 +159,7 @@ void ser_members(bytecoin::COMMAND_TIMED_SYNC::request &v, seria::ISeria &s); void ser_members(bytecoin::COMMAND_TIMED_SYNC::response &v, seria::ISeria &s); void ser_members(bytecoin::COMMAND_PING::request &v, seria::ISeria &s); void ser_members(bytecoin::COMMAND_PING::response &v, seria::ISeria &s); -#ifdef ALLOW_DEBUG_COMMANDS +#if bytecoin_ALLOW_DEBUG_COMMANDS void ser_members(bytecoin::proof_of_trust &v, seria::ISeria &s); void ser_members(bytecoin::COMMAND_REQUEST_STAT_INFO::request &v, seria::ISeria &s); void ser_members(bytecoin::COMMAND_REQUEST_STAT_INFO::response &v, seria::ISeria &s); diff --git a/src/p2p/P2pProtocolTypes.hpp b/src/p2p/P2pProtocolTypes.hpp index 8f846c99..fffdbc13 100644 --- a/src/p2p/P2pProtocolTypes.hpp +++ b/src/p2p/P2pProtocolTypes.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once @@ -16,7 +16,7 @@ typedef uint64_t PeerIdType; #pragma pack(push, 1) struct UUID { - uint8_t data[16]{}; + uint8_t data[16]; // TODO - return {} initializer when Google updates NDK compiler }; struct NetworkAddress { diff --git a/src/p2p/P2pSeria.cpp b/src/p2p/P2pSeria.cpp index 443b3f3a..0da1ba2c 100644 --- a/src/p2p/P2pSeria.cpp +++ b/src/p2p/P2pSeria.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "CryptoNoteProtocolDefinitions.hpp" #include "P2pProtocolDefinitions.hpp" @@ -123,7 +123,7 @@ void ser_members(bytecoin::COMMAND_PING::response &v, seria::ISeria &s) { seria_kv("peer_id", v.peer_id, s); } -#ifdef ALLOW_DEBUG_COMMANDS +#if bytecoin_ALLOW_DEBUG_COMMANDS void ser_members(bytecoin::proof_of_trust &v, seria::ISeria &s) { seria_kv("peer_id", v.peer_id, s); seria_kv("time", v.time, s); diff --git a/src/p2p/PeerDB.cpp b/src/p2p/PeerDB.cpp index 4a58f9fe..cfc1bdf9 100644 --- a/src/p2p/PeerDB.cpp +++ b/src/p2p/PeerDB.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "PeerDB.hpp" #include "Core/Config.hpp" @@ -10,6 +10,7 @@ #include "seria/BinaryOutputStream.hpp" #include "common/Ipv4Address.hpp" +#include "common/string.hpp" #include "crypto/crypto.hpp" #include "seria/ISeria.hpp" @@ -35,7 +36,7 @@ static const float DB_COMMIT_PERIOD = 180; // 3 minutes sounds good compr PeerDB::PeerDB(const Config &config) : config(config) - , db(config.get_coin_directory() + "/peer_db", 1024 * 1024 * 128) + , db(config.get_data_folder() + "/peer_db", 1024 * 1024 * 128) , // make sure this is enough for seed node commit_timer(std::bind(&PeerDB::db_commit, this)) { read_db(WHITE_LIST, whitelist); @@ -82,12 +83,12 @@ void PeerDB::read_db(const std::string &prefix, peers_indexed &list) { } void PeerDB::update_db(const std::string &prefix, const Entry &entry) { - auto key = prefix + std::to_string(entry.adr.ip) + ":" + std::to_string(entry.adr.port); + auto key = prefix + common::to_string(entry.adr.ip) + ":" + common::to_string(entry.adr.port); db.put(key, seria::to_binary(entry), false); } void PeerDB::del_db(const std::string &prefix, const NetworkAddress &addr) { - auto key = prefix + std::to_string(addr.ip) + ":" + std::to_string(addr.port); + auto key = prefix + common::to_string(addr.ip) + ":" + common::to_string(addr.port); db.del(key, false); } diff --git a/src/p2p/PeerDB.hpp b/src/p2p/PeerDB.hpp index da5eb7e5..5f908256 100644 --- a/src/p2p/PeerDB.hpp +++ b/src/p2p/PeerDB.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/platform/DB.hpp b/src/platform/DB.hpp index 6aedc549..5fd6826b 100644 --- a/src/platform/DB.hpp +++ b/src/platform/DB.hpp @@ -1,9 +1,9 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once -#if BYTECOIN_SQLITE +#if platform_USE_SQLITE #include "platform/DBsqlite3.hpp" namespace platform { typedef DBsqlite DB; diff --git a/src/platform/DBlmdb.cpp b/src/platform/DBlmdb.cpp index 3ee70eb5..86faef2d 100644 --- a/src/platform/DBlmdb.cpp +++ b/src/platform/DBlmdb.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "DBlmdb.hpp" #include @@ -194,7 +194,7 @@ bool DBlmdb::get(const std::string &key, std::string &value) const { return true; } -bool DBlmdb::get(const std::string &key, lmdb::Val &value) const { return db_dbi->get(*db_txn, lmdb::Val(key), value); } +bool DBlmdb::get(const std::string &key, Value &value) const { return db_dbi->get(*db_txn, lmdb::Val(key), value); } void DBlmdb::del(const std::string &key, bool mustexist) { const int rc = ::mdb_del(db_txn->handle, db_dbi->handle, lmdb::Val(key), nullptr); diff --git a/src/platform/DBlmdb.hpp b/src/platform/DBlmdb.hpp index 5b5551fb..c9d20577 100644 --- a/src/platform/DBlmdb.hpp +++ b/src/platform/DBlmdb.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once @@ -74,7 +74,9 @@ class DBlmdb { bool get(const std::string &key, common::BinaryArray &value) const; bool get(const std::string &key, std::string &value) const; - bool get(const std::string &key, lmdb::Val &value) const; + + typedef lmdb::Val Value; + bool get(const std::string &key, Value &value) const; void del(const std::string &key, bool mustexist); diff --git a/src/platform/DBsqlite3.cpp b/src/platform/DBsqlite3.cpp index aa4a1465..b361ba73 100644 --- a/src/platform/DBsqlite3.cpp +++ b/src/platform/DBsqlite3.cpp @@ -1,16 +1,17 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "DBsqlite3.hpp" #include #include #include "PathTools.hpp" +#include "common/string.hpp" using namespace platform; static void sqlite_check(int rc, const char *msg) { if (rc != SQLITE_OK) - throw platform::sqlite::Error(msg + std::to_string(rc)); + throw platform::sqlite::Error(msg + common::to_string(rc)); } sqlite::Dbi::~Dbi() { @@ -46,12 +47,11 @@ DBsqlite::DBsqlite(const std::string &full_path, uint64_t max_db_size) : full_pa "sqlite3_prepare_v2 stmt_del "); sqlite_check(sqlite3_exec(db_dbi.handle, "BEGIN TRANSACTION", 0, 0, &err_msg), err_msg); commit_db_txn(); // We apply journal from last crash/exit immediately - // sqlite3_free(err_msg); } size_t DBsqlite::test_get_approximate_size() const { return 0; } -size_t DBsqlite::get_approximate_items_count() const { return 0; } +size_t DBsqlite::get_approximate_items_count() const { return 0; } // TODO static const size_t max_key_size = 128; @@ -95,7 +95,7 @@ void DBsqlite::Cursor::step_and_check() { return; } if (rc != SQLITE_ROW) - throw platform::sqlite::Error("Cursor step failed sqlite3_step in step_and_check " + std::to_string(rc)); + throw platform::sqlite::Error("Cursor step failed sqlite3_step in step_and_check " + common::to_string(rc)); size = sqlite3_column_bytes(stmt_get.handle, 0); data = reinterpret_cast(sqlite3_column_blob(stmt_get.handle, 0)); std::string itkey(data, size); @@ -146,7 +146,7 @@ static void put(sqlite::Stmt &stmt, const std::string &key, const void *data, si sqlite_check(sqlite3_bind_blob(stmt.handle, 2, data, static_cast(size), 0), "DB::put sqlite3_bind_blob 2 "); auto rc = sqlite3_step(stmt.handle); if (rc != SQLITE_DONE) - throw platform::sqlite::Error("DB::put failed sqlite3_step in put " + std::to_string(rc)); + throw platform::sqlite::Error("DB::put failed sqlite3_step in put " + common::to_string(rc)); } void DBsqlite::put(const std::string &key, const common::BinaryArray &value, bool nooverwrite) { @@ -167,7 +167,7 @@ static std::pair get(const sqlite::Stmt &stmt, co if (rc == SQLITE_DONE) return std::make_pair(nullptr, 0); if (rc != SQLITE_ROW) - throw platform::sqlite::Error("DB::get failed sqlite3_step in get " + std::to_string(rc)); + throw platform::sqlite::Error("DB::get failed sqlite3_step in get " + common::to_string(rc)); auto si = sqlite3_column_bytes(stmt.handle, 0); auto da = reinterpret_cast(sqlite3_column_blob(stmt.handle, 0)); si = sqlite3_column_bytes(stmt.handle, 1); @@ -197,7 +197,7 @@ void DBsqlite::del(const std::string &key, bool mustexist) { "DB::del sqlite3_bind_blob 1 "); auto rc = sqlite3_step(stmt_del.handle); if (rc != SQLITE_DONE) - throw platform::sqlite::Error("DB::del failed sqlite3_step in del " + std::to_string(rc)); + throw platform::sqlite::Error("DB::del failed sqlite3_step in del " + common::to_string(rc)); int deleted_rows = sqlite3_changes(db_dbi.handle); if (mustexist && deleted_rows != 1) throw platform::sqlite::Error("DB::del row does not exits"); @@ -210,7 +210,10 @@ std::string DBsqlite::to_ascending_key(uint32_t key) { } uint32_t DBsqlite::from_ascending_key(const std::string &key) { - return boost::lexical_cast(std::stoull(key, nullptr, 16)); + long long unsigned val = 0; + if (sscanf(key.c_str(), "%llx", &val) != 1) + throw std::runtime_error("from_ascending_key failed to convert key=" + key); + return boost::lexical_cast(val); // TODO - std::stoull(key, nullptr, 16) when Google updates NDK compiler } std::string DBsqlite::clean_key(const std::string &key) { @@ -240,6 +243,7 @@ void DBsqlite::run_tests() { DBsqlite db("temp_db"); std::string str; bool res = db.get("history/ha", str); + std::cout << "res=" << res << std::endl; db.put("history/ha", "ua", false); db.put("history/hb", "ub", false); @@ -258,6 +262,7 @@ void DBsqlite::run_tests() { } catch (...) { } res = db.get("history/ha", str); + std::cout << "res=" << res << std::endl; db.put("unspent/ua", "ua", false); db.put("unspent/ub", "ub", false); diff --git a/src/platform/DBsqlite3.hpp b/src/platform/DBsqlite3.hpp index 51a8a441..1559e891 100644 --- a/src/platform/DBsqlite3.hpp +++ b/src/platform/DBsqlite3.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once @@ -49,6 +49,8 @@ class DBsqlite { bool get(const std::string &key, common::BinaryArray &value) const; bool get(const std::string &key, std::string &value) const; + + typedef std::string Value; // bool get(const std::string &key, lmdb::Val &value) const; void del(const std::string &key, bool mustexist); diff --git a/src/platform/ExclusiveLock.cpp b/src/platform/ExclusiveLock.cpp index c177a695..2bd09954 100644 --- a/src/platform/ExclusiveLock.cpp +++ b/src/platform/ExclusiveLock.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "ExclusiveLock.hpp" #include @@ -22,7 +22,7 @@ using namespace platform; ExclusiveLock::ExclusiveLock(const std::string &folder, const std::string &file) { std::string full_path = folder + "/" + file; #if !TARGET_OS_IPHONE // We do not need lock on iOS because only 1 instance of app will be running - create_directories_if_necessary(folder); // We ignore result here +// create_directories_if_necessary(folder); // We ignore result here #ifdef _WIN32 auto wfull_path = FileStream::utf8_to_utf16(full_path); handle = CreateFileW(wfull_path.c_str(), GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); diff --git a/src/platform/ExclusiveLock.hpp b/src/platform/ExclusiveLock.hpp index 2a81591f..802fb17f 100644 --- a/src/platform/ExclusiveLock.hpp +++ b/src/platform/ExclusiveLock.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/platform/Files.cpp b/src/platform/Files.cpp index 069f0f38..afdae433 100644 --- a/src/platform/Files.cpp +++ b/src/platform/Files.cpp @@ -1,11 +1,12 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "Files.hpp" #include #include #include #include +#include "common/string.hpp" #ifdef _WIN32 #include "platform/Windows.hpp" #else @@ -25,12 +26,12 @@ FileStream::FileStream(const std::string &filename, OpenMode mode) { FILE_ATTRIBUTE_NORMAL, nullptr); DWORD err = GetLastError(); if (handle == INVALID_HANDLE_VALUE) - throw std::ios_base::failure("File failed to open " + filename); + throw common::StreamError("File failed to open " + filename); #else int m1 = (mode == TRUNCATE_READ_WRITE) ? (O_CREAT | O_TRUNC) : (mode == READ_WRITE_EXISTING) ? 0 : 0; fd = open(filename.c_str(), m1 | (mode == READ_EXISTING ? O_RDONLY : O_RDWR), 0600); if (fd == -1) - throw std::ios_base::failure("File failed to open " + filename); + throw common::StreamError("File failed to open " + filename); #endif } @@ -51,12 +52,12 @@ uint64_t FileStream::seek(uint64_t pos, int whence) { static_assert(SEEK_END == FILE_END && SEEK_CUR == FILE_CURRENT && SEEK_SET == FILE_BEGIN, "Whene definition between Windows and POSIX do not match"); if (!SetFilePointerEx(handle, lpos, &rpos, whence)) - throw std::ios_base::failure("Error seeking file in seek, GetLastError=" + std::to_string(GetLastError())); + throw common::StreamError("Error seeking file in seek, GetLastError=" + std::to_string(GetLastError())); return rpos.QuadPart; #else off_t res = lseek(fd, pos, whence); if (res == -1) - throw std::ios_base::failure("Error seeking file in seek, errno=" + std::to_string(errno)); + throw common::StreamError("Error seeking file in seek, errno=" + common::to_string(errno)); return res; #endif } @@ -66,12 +67,12 @@ size_t FileStream::write_some(const void *data, size_t size) { #ifdef _WIN32 DWORD si = 0; if (!WriteFile(handle, data, static_cast(size), &si, nullptr)) - throw std::ios_base::failure("Error writing file, GetLastError()=" + std::to_string(GetLastError())); + throw common::StreamError("Error writing file, GetLastError()=" + std::to_string(GetLastError())); return si; #else size_t si = ::write(fd, data, size); if (si == (size_t)-1) - throw std::ios_base::failure("Error writing file, errno=" + std::to_string(errno)); + throw common::StreamError("Error writing file, errno=" + common::to_string(errno)); return si; #endif } @@ -80,12 +81,12 @@ size_t FileStream::read_some(void *data, size_t size) { #ifdef _WIN32 DWORD si = 0; if (!ReadFile(handle, data, static_cast(size), &si, nullptr)) - throw std::ios_base::failure("Error reading file, GetLastError()=" + std::to_string(GetLastError())); + throw common::StreamError("Error reading file, GetLastError()=" + std::to_string(GetLastError())); return si; #else size_t si = ::read(fd, data, size); if (si == (size_t)-1) - throw std::ios_base::failure("Error reading file, errno=" + std::to_string(errno)); + throw common::StreamError("Error reading file, errno=" + common::to_string(errno)); return si; #endif } @@ -98,7 +99,7 @@ void FileStream::fdatasync() { #else if (::fdatasync(fd) == -1) #endif - throw std::ios_base::failure("Error syncing file to disk, errno=" + std::to_string(errno)); + throw common::StreamError("Error syncing file to disk, errno=" + common::to_string(errno)); } #ifdef _WIN32 diff --git a/src/platform/Files.hpp b/src/platform/Files.hpp index 328a7323..ac9339fc 100644 --- a/src/platform/Files.hpp +++ b/src/platform/Files.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/platform/Network.cpp b/src/platform/Network.cpp index 053e65ea..b1b5fd9d 100644 --- a/src/platform/Network.cpp +++ b/src/platform/Network.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "Network.hpp" #include "common/MemoryStreams.hpp" @@ -11,7 +11,125 @@ using namespace platform; -#if TARGET_OS_IPHONE +static std::pair split_ssl_address(const std::string &addr) { + std::string stripped_addr = addr; + bool ssl = false; + const std::string prefix1("https://"); + const std::string prefix2("ssl://"); + if (addr.find(prefix1) == 0) { + stripped_addr = addr.substr(prefix1.size()); + ssl = true; + } else if (addr.find(prefix2) == 0) { + stripped_addr = addr.substr(prefix2.size()); + ssl = true; + } + return std::make_pair(ssl, stripped_addr); +} +#if defined(__ANDROID__) +#include + +Timer::Timer(after_handler a_handler) : a_handler(a_handler), impl(nullptr) { + QObject::connect(&impl, &QTimer::timeout, [this]() { this->a_handler(); }); + impl.setSingleShot(true); +} + +void Timer::cancel() { impl.stop(); } + +void Timer::once(float after_seconds) { + cancel(); + impl.start(static_cast(after_seconds * 1000)); +} + +TCPSocket::TCPSocket(RW_handler rw_handler, D_handler d_handler) : rw_handler(rw_handler), d_handler(d_handler) {} + +void TCPSocket::close() { + if (impl) { + impl->deleteLater(); + impl.release(); + } + ready = false; +} + +bool TCPSocket::is_open() const { return impl && impl->state() != QAbstractSocket::UnconnectedState; } + +bool TCPSocket::connect(const std::string &addr, uint16_t port) { + close(); + // bool sup = QSslSocket::supportsSsl(); + // auto vs = QSslSocket::sslLibraryVersionString(); // "BoringSSL" + // auto vsv = QSslSocket::sslLibraryBuildVersionString(); // "OpenSSL 1.0.1j 15 Oct 2014" + + auto ssl_addr = split_ssl_address(addr); + + if (ssl_addr.first) { + auto s = std::make_unique(); + QObject::connect(s.get(), static_cast &)>(&QSslSocket::sslErrors), + [this](const QList &errors) { + QString str; + for (const auto &error : errors) + str = error.errorString(); + }); + QObject::connect(s.get(), &QSslSocket::encrypted, [this]() { + this->ready = true; + this->rw_handler(true, true); + }); + QObject::connect( + s.get(), &QSslSocket::encryptedBytesWritten, [this](qint64 bytes) { this->rw_handler(true, true); }); + QObject::connect(s.get(), &QAbstractSocket::readyRead, [this]() { this->rw_handler(true, true); }); + QObject::connect(s.get(), &QAbstractSocket::disconnected, [this]() { + this->close(); + this->d_handler(); + }); + QObject::connect(s.get(), + static_cast(&QAbstractSocket::error), + [this](QAbstractSocket::SocketError err) { + qDebug() << this->impl->errorString(); + this->close(); + this->d_handler(); + }); + s->connectToHostEncrypted(QString::fromUtf8(ssl_addr.second.data(), ssl_addr.second.size()), port); + impl = std::move(s); + } else { + impl = std::make_unique(); + QObject::connect( + impl.get(), &QAbstractSocket::bytesWritten, [this](qint64 bytes) { this->rw_handler(true, true); }); + QObject::connect(impl.get(), &QAbstractSocket::connected, [this]() { + this->ready = true; + this->rw_handler(true, true); + }); + QObject::connect(impl.get(), &QAbstractSocket::readyRead, [this]() { this->rw_handler(true, true); }); + QObject::connect(impl.get(), &QAbstractSocket::disconnected, [this]() { + this->close(); + this->d_handler(); + }); + QObject::connect(impl.get(), + static_cast(&QAbstractSocket::error), + [this](QAbstractSocket::SocketError err) { + this->close(); + this->d_handler(); + }); + impl->connectToHost(QString::fromUtf8(ssl_addr.second.data(), ssl_addr.second.size()), port); + } + return true; +} + +size_t TCPSocket::read_some(void *val, size_t count) { + qint64 res = (impl && ready) ? impl->read(reinterpret_cast(val), count) : 0; + if (res != 0) + res += 0; + return res; +} + +size_t TCPSocket::write_some(const void *val, size_t count) { + qint64 res = (impl && ready) ? impl->write(reinterpret_cast(val), count) : 0; + return res; +} + +void TCPSocket::shutdown_both() { + if (impl) + impl->disconnectFromHost(); +} + +#elif TARGET_OS_IPHONE #include #include #include "common/MemoryStreams.hpp" @@ -38,11 +156,6 @@ void Timer::once(float after_seconds) { CFRunLoopAddTimer(CFRunLoopGetCurrent(), impl, kCFRunLoopDefaultMode); } -TCPSocket::TCPSocket(RW_handler rw_handler, D_handler d_handler) - : rw_handler(rw_handler), d_handler(d_handler), readStream(nullptr), writeStream(nullptr) {} - -TCPSocket::~TCPSocket() { close(); } - void TCPSocket::close() { if (readStream) { CFReadStreamClose(readStream); @@ -67,7 +180,8 @@ bool TCPSocket::is_open() const { return readStream || writeStream; } bool TCPSocket::connect(const std::string &addr, uint16_t port) { close(); - CFStringRef hname = CFStringCreateWithCString(kCFAllocatorDefault, addr.c_str(), kCFStringEncodingUTF8); + auto ssl_addr = split_ssl_address(addr); + CFStringRef hname = CFStringCreateWithCString(kCFAllocatorDefault, ssl_addr.second.c_str(), kCFStringEncodingUTF8); CFHostRef host = CFHostCreateWithName(kCFAllocatorDefault, hname); CFRelease(hname); hname = nullptr; @@ -75,17 +189,18 @@ bool TCPSocket::connect(const std::string &addr, uint16_t port) { CFRelease(host); host = nullptr; // CFReadStreamSetProperty(readStream, NSStreamSocketSecurityLevelKey, securityDictRef); - CFMutableDictionaryRef securityDictRef = CFDictionaryCreateMutable( - kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - if (!securityDictRef) { - close(); - return false; + if (ssl_addr.first) { + CFMutableDictionaryRef securityDictRef = CFDictionaryCreateMutable( + kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (!securityDictRef) { + close(); + return false; + } + CFDictionarySetValue(securityDictRef, kCFStreamSSLValidatesCertificateChain, kCFBooleanTrue); + CFReadStreamSetProperty(readStream, kCFStreamPropertySSLSettings, securityDictRef); + CFRelease(securityDictRef); + securityDictRef = nullptr; } - CFDictionarySetValue(securityDictRef, kCFStreamSSLValidatesCertificateChain, kCFBooleanTrue); - CFReadStreamSetProperty(readStream, kCFStreamPropertySSLSettings, securityDictRef); - CFRelease(securityDictRef); - securityDictRef = nullptr; - CFStreamClientContext myContext = {0, this, nullptr, nullptr, nullptr}; if (!CFReadStreamSetClient(readStream, kCFStreamEventHasBytesAvailable | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered, @@ -183,12 +298,15 @@ void TCPSocket::write_callback(CFWriteStreamRef stream, CFStreamEventType event, #include #include -#if BYTECOIN_SSL +#if platform_USE_SSL #include +#include + namespace ssl = boost::asio::ssl; typedef ssl::stream SSLSocket; #ifdef _WIN32 +#include #pragma comment(lib, "libcrypto.lib") // OpenSSL library #pragma comment(lib, "libssl.lib") // OpenSSL library #pragma comment(lib, "crypt32.lib") // Windows SDK dependency of OpenSSL @@ -214,10 +332,76 @@ static void add_system_root_certs(ssl::context &ctx) { SSL_CTX_set_cert_store(ctx.native_handle(), store); } #else -static void add_system_root_certs(ssl::context &ctx) { ctx.set_default_verify_paths(); } +// https://letsencrypt.org/certs/isrgrootx1.pem.txt +static const char our_cert[] = R"( +-----BEGIN CERTIFICATE----- +MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw +TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh +cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4 +WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu +ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY +MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc +h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+ +0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U +A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW +T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH +B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC +B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv +KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn +OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn +jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw +qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI +rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq +hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL +ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ +3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK +NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5 +ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur +TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC +jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc +oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq +4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA +mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d +emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc= +-----END CERTIFICATE----- +)"; +// https://www.identrust.com/certificates/trustid/root-download-x3.html (converted to pem) +static const char our_cert2[] = R"( +-----BEGIN CERTIFICATE----- +MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ +MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT +DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow +PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD +Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O +rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq +OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b +xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw +7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD +aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG +SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 +ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr +AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz +R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 +JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo +Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ +-----END CERTIFICATE----- +)"; +static void add_system_root_certs(ssl::context &ctx) { + // We try all methods and hope for the best + ctx.set_default_verify_paths(); + ctx.add_verify_path("/etc/ssl/certs"); // read below for the cert folder mess on Linux + // https://www.happyassassin.net/2015/01/12/a-note-about-ssltls-trusted-certificate-stores-and-platforms/ + boost::asio::const_buffer cert(our_cert, sizeof(our_cert) - 1); + ctx.add_certificate_authority(cert); + boost::asio::const_buffer cert2(our_cert2, sizeof(our_cert2) - 1); + ctx.add_certificate_authority(cert2); +} #endif -static thread_local std::shared_ptr shared_client_context; +// static thread_local std::shared_ptr shared_client_context; #endif thread_local EventLoop *EventLoop::current_loop = 0; @@ -230,9 +414,9 @@ EventLoop::EventLoop(boost::asio::io_service &io_service) : io_service(io_servic EventLoop::~EventLoop() { current_loop = 0; -#if BYTECOIN_SSL - shared_client_context.reset(); -#endif + //#if platform_USE_SSL + // shared_client_context.reset(); + //#endif } void EventLoop::cancel() { io_service.stop(); } @@ -306,7 +490,7 @@ class TCPSocket::Impl { bool pending_write; bool pending_connect; boost::asio::ip::tcp::socket socket; -#if BYTECOIN_SSL +#if platform_USE_SSL std::shared_ptr ssl_context; // TCP socket may live longer than TCP acceptor std::unique_ptr ssl_socket; #endif @@ -314,7 +498,7 @@ class TCPSocket::Impl { common::CircularBuffer outgoing_buffer; void close(bool called_from_run_loop) { -#if BYTECOIN_SSL +#if platform_USE_SSL if (ssl_socket) ssl_socket->lowest_layer().close(); else @@ -333,7 +517,7 @@ class TCPSocket::Impl { pending_write = false; incoming_buffer.clear(); outgoing_buffer.clear(); -#if BYTECOIN_SSL +#if platform_USE_SSL ssl_socket.reset(); ssl_context.reset(); #endif @@ -343,7 +527,7 @@ class TCPSocket::Impl { } void start_shutdown() { boost::system::error_code ignored_ec; -#if BYTECOIN_SSL +#if platform_USE_SSL if (ssl_socket) { // TODO - // https://stackoverflow.com/questions/32046034/what-is-the-proper-way-to-securely-disconnect-an-asio-ssl-socket @@ -355,9 +539,9 @@ class TCPSocket::Impl { void handle_connect(const boost::system::error_code &e) { if (!e) { -#if BYTECOIN_SSL +#if platform_USE_SSL if (ssl_socket) { - start_server_handshake(); + start_handshake(ssl::stream_base::client); return; } #endif @@ -381,7 +565,7 @@ class TCPSocket::Impl { boost::array bufs{ {boost::asio::buffer(incoming_buffer.write_ptr(), incoming_buffer.write_count()), boost::asio::buffer(incoming_buffer.write_ptr2(), incoming_buffer.write_count2())}}; -#if BYTECOIN_SSL +#if platform_USE_SSL if (ssl_socket) ssl_socket->async_read_some( bufs, boost::bind(&Impl::handle_read, owner->impl, boost::asio::placeholders::error, @@ -403,6 +587,7 @@ class TCPSocket::Impl { return; } if (e != boost::asio::error::operation_aborted) { + // std::cout << e << " " << e.message() << std::endl; close(true); } } @@ -419,7 +604,7 @@ class TCPSocket::Impl { boost::array bufs{ {boost::asio::buffer(outgoing_buffer.read_ptr(), outgoing_buffer.read_count()), boost::asio::buffer(outgoing_buffer.read_ptr2(), outgoing_buffer.read_count2())}}; -#if BYTECOIN_SSL +#if platform_USE_SSL if (ssl_socket) ssl_socket->async_write_some( bufs, boost::bind(&Impl::handle_write, owner->impl, boost::asio::placeholders::error, @@ -444,20 +629,22 @@ class TCPSocket::Impl { close(true); } } -#if BYTECOIN_SSL - void start_server_handshake() { - ssl_socket->async_handshake(ssl::stream_base::server, - boost::bind(&Impl::handle_server_handshake, this, boost::asio::placeholders::error)); +#if platform_USE_SSL + void start_handshake(ssl::stream_base::handshake_type type) { + ssl_socket->async_handshake(type, boost::bind(&Impl::handle_handshake, this, boost::asio::placeholders::error)); } - void handle_server_handshake(const boost::system::error_code &e) { + void handle_handshake(const boost::system::error_code &e) { pending_connect = false; if (!e) { connected = true; start_read(); start_write(); + if (owner) + owner->rw_handler(true, true); return; } if (e != boost::asio::error::operation_aborted) { + std::cout << e << " " << e.message() << std::endl; close(true); } } @@ -471,45 +658,50 @@ TCPSocket::~TCPSocket() { close(); } void TCPSocket::close() { impl->close(false); } -bool TCPSocket::is_open() const { return impl->socket.lowest_layer().is_open(); } +bool TCPSocket::is_open() const { +#if platform_USE_SSL + if (impl->ssl_socket) + return impl->ssl_socket->lowest_layer().is_open(); +#endif + return impl->socket.lowest_layer().is_open(); +} bool TCPSocket::connect(const std::string &addr, uint16_t port) { close(); - std::string stripped_addr = addr; -#if BYTECOIN_SSL - bool ssl = false; - const std::string prefix1("https://"); - const std::string prefix2("ssl://"); - if (addr.find(prefix1) == 0) { - stripped_addr = addr.substr(prefix1.size()); - ssl = true; - } else if (addr.find(prefix2) == 0) { - stripped_addr = addr.substr(prefix2.size()); - ssl = true; - } -#endif + auto ssl_addr = split_ssl_address(addr); try { impl->pending_connect = true; - boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::address::from_string(stripped_addr), port); -#if BYTECOIN_SSL - if (ssl) { - if (shared_client_context == nullptr) { - shared_client_context = std::make_shared(ssl::context::tlsv12_client); - shared_client_context->set_options(ssl::context::default_workarounds | ssl::context::no_sslv2 | - ssl::context::no_sslv3 | ssl::context::tlsv12_client); - add_system_root_certs(*shared_client_context); - shared_client_context->set_verify_mode(ssl::verify_peer); - shared_client_context->set_verify_callback(ssl::rfc2818_verification(stripped_addr)); - } + if (ssl_addr.first) { +#if platform_USE_SSL + boost::asio::ip::tcp::resolver resolver(EventLoop::current()->io()); + boost::asio::ip::tcp::resolver::query query(ssl_addr.second, common::to_string(port)); + boost::asio::ip::tcp::resolver::iterator iter = resolver.resolve(query); + for (; iter != boost::asio::ip::tcp::resolver::iterator(); ++iter) + if (iter->endpoint().address().is_v4()) + break; + if (iter == boost::asio::ip::tcp::resolver::iterator()) + return false; + std::shared_ptr shared_client_context = + std::make_shared(ssl::context::tlsv12_client); + add_system_root_certs(*shared_client_context); + shared_client_context->set_verify_mode(ssl::verify_peer); + shared_client_context->set_verify_callback(ssl::rfc2818_verification(ssl_addr.second)); + impl->ssl_context = shared_client_context; impl->ssl_socket = std::make_unique(EventLoop::current()->io(), *impl->ssl_context); - impl->ssl_socket->lowest_layer().async_connect( - endpoint, boost::bind(&TCPSocket::Impl::handle_connect, impl, boost::asio::placeholders::error)); - } else + if (!SSL_set_tlsext_host_name(impl->ssl_socket->native_handle(), ssl_addr.second.c_str())) + return false; + impl->ssl_socket->lowest_layer().async_connect(iter->endpoint(), + boost::bind(&TCPSocket::Impl::handle_connect, impl, boost::asio::placeholders::error)); +#else + return false; #endif + } else { + boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::address::from_string(ssl_addr.second), port); impl->socket.async_connect( endpoint, boost::bind(&TCPSocket::Impl::handle_connect, impl, boost::asio::placeholders::error)); + } } catch (const std::exception &) { return false; } @@ -547,9 +739,10 @@ class TCPAcceptor::Impl { , pending_accept(false) , acceptor(EventLoop::current()->io()) , socket_being_accepted(EventLoop::current()->io()) -#if BYTECOIN_SSL +#if platform_USE_SSL , ssl_context(std::make_shared(ssl::context::sslv23)) - , ssl_socket_being_accepted(std::make_unique(EventLoop::current()->io(), *ssl_context)) + , ssl_socket_being_accepted( + ssl ? std::make_unique(EventLoop::current()->io(), *ssl_context) : nullptr) #endif , socket_ready(false) { } @@ -558,7 +751,7 @@ class TCPAcceptor::Impl { bool pending_accept; boost::asio::ip::tcp::acceptor acceptor; boost::asio::ip::tcp::socket socket_being_accepted; -#if BYTECOIN_SSL +#if platform_USE_SSL std::shared_ptr ssl_context; std::unique_ptr ssl_socket_being_accepted; #endif @@ -577,7 +770,7 @@ class TCPAcceptor::Impl { if (!owner) return; pending_accept = true; -#if BYTECOIN_SSL +#if platform_USE_SSL if (ssl) acceptor.async_accept(ssl_socket_being_accepted->next_layer(), boost::bind(&Impl::handle_accept, owner->impl, boost::asio::placeholders::error)); @@ -603,7 +796,7 @@ TCPAcceptor::TCPAcceptor(const std::string &addr, uint16_t port, A_handler a_han const std::string &ssl_certificate_password) : impl(std::make_shared(this, !ssl_pem_file.empty())), a_handler(a_handler) { -#if BYTECOIN_SSL +#if platform_USE_SSL if (impl->ssl) { impl->ssl_context->set_options( ssl::context::default_workarounds | ssl::context::no_sslv2); // | ssl::context::single_dh_use @@ -639,7 +832,7 @@ bool TCPAcceptor::accept(TCPSocket &socket, std::string &accepted_addr) { socket.close(); std::swap(socket.impl->socket, impl->socket_being_accepted); boost::system::error_code ec; -#if BYTECOIN_SSL +#if platform_USE_SSL std::swap(socket.impl->ssl_socket, impl->ssl_socket_being_accepted); auto endpoint = impl->ssl ? socket.impl->ssl_socket->next_layer().remote_endpoint(ec) : socket.impl->socket.remote_endpoint(ec); @@ -650,13 +843,13 @@ bool TCPAcceptor::accept(TCPSocket &socket, std::string &accepted_addr) { if (ec) return false; accepted_addr = endpoint.address().to_string(); -#if BYTECOIN_SSL +#if platform_USE_SSL if (impl->ssl) { if (!impl->ssl_socket_being_accepted) impl->ssl_socket_being_accepted = std::make_unique(EventLoop::current()->io(), *impl->ssl_context); socket.impl->ssl_context = impl->ssl_context; - socket.impl->start_server_handshake(); + socket.impl->start_handshake(ssl::stream_base::server); } else #endif { diff --git a/src/platform/Network.hpp b/src/platform/Network.hpp index 575745f2..e556c7f6 100644 --- a/src/platform/Network.hpp +++ b/src/platform/Network.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once @@ -12,7 +12,76 @@ #ifdef __APPLE__ #include "TargetConditionals.h" #endif -#if TARGET_OS_IPHONE + +#if defined(__ANDROID__) +#include +#include + +namespace platform { +class EventLoop { +public: + static void cancel_current() {} +}; +class Timer : private common::Nocopy { +public: + typedef std::function after_handler; + + explicit Timer(after_handler a_handler); + ~Timer() { cancel(); } + + void once(float after_seconds); // cancels previous once first + void cancel(); + +private: + after_handler a_handler; + QTimer impl; +}; + +// socket is not RAII because it can go to disconnected state by external interaction +class TCPSocket : public common::IInputStream, public common::IOutputStream, private common::Nocopy { +public: + typedef std::function RW_handler; + typedef std::function D_handler; + + explicit TCPSocket(RW_handler rw_handler, D_handler d_handler); + virtual ~TCPSocket() { close(); } + void close(); // after close you are guaranteed that no handlers will be called + bool is_open() const; // Connecting or connected + bool connect(const std::string &addr, + uint16_t port); // either returns false or returns true and will call rw_handler or d_handler in future + + virtual size_t read_some(void *val, size_t count) override; + // reads 0..count-1, if returns 0 (incoming buffer empty) would fire rw_handler or d_handler in future + virtual size_t write_some(const void *val, size_t count) override; + // writes 0..count-1, if returns 0 (outgoing buffer full) will fire rw_handler or d_handler in future + void shutdown_both(); // will fire d_handler only after all sent data is acknowledged or disconnect happens +private: + friend class TCPAcceptor; + RW_handler rw_handler; + D_handler d_handler; + std::unique_ptr impl; + bool ready = false; +}; +class TCPAcceptor : private common::Nocopy { +public: + typedef std::function A_handler; + + explicit TCPAcceptor(const std::string &addr, + uint16_t port, + A_handler a_handler, + const std::string &ssl_pem_file = std::string(), + const std::string &ssl_certificate_password = std::string()) + : a_handler(a_handler) {} + ~TCPAcceptor() {} + + bool accept(TCPSocket &socket, std::string &accepted_addr) { return false; } + bool accept(TCPSocket &socket) { return false; } + +private: + A_handler a_handler; +}; +} +#elif TARGET_OS_IPHONE #include #include @@ -43,24 +112,24 @@ class TCPSocket : public common::IInputStream, public common::IOutputStream, pri typedef std::function RW_handler; typedef std::function D_handler; - explicit TCPSocket(RW_handler rw_handler, D_handler d_handler); - virtual ~TCPSocket(); + explicit TCPSocket(RW_handler rw_handler, D_handler d_handler) : rw_handler(rw_handler), d_handler(d_handler) {} + virtual ~TCPSocket() { close(); } void close(); // after close you are guaranteed that no handlers will be called bool is_open() const; // Connecting or connected - bool connect(const std::string &addr, - uint16_t port); // either returns false or returns true and will call rw_handler or d_handler in future + bool connect(const std::string &addr, uint16_t port); + // either returns false or returns true and will call rw_handler or d_handler in future - virtual size_t read_some(void *val, size_t count) override; // reads 0..count-1, if returns 0 (incoming buffer - // empty) would fire rw_handler or d_handler in future - virtual size_t write_some(const void *val, size_t count) - override; // writes 0..count-1, if returns 0 (outgoing buffer full) will fire rw_handler or d_handler in future + virtual size_t read_some(void *val, size_t count) override; + // reads 0..count-1, if returns 0 (incoming buffer empty) would fire rw_handler or d_handler in future + virtual size_t write_some(const void *val, size_t count) override; + // writes 0..count-1, if returns 0 (outgoing buffer full) will fire rw_handler or d_handler in future void shutdown_both(); // will fire d_handler only after all sent data is acknowledged or disconnect happens private: friend class TCPAcceptor; RW_handler rw_handler; D_handler d_handler; - CFReadStreamRef readStream; - CFWriteStreamRef writeStream; + CFReadStreamRef readStream = nullptr; + CFWriteStreamRef writeStream = nullptr; void close_and_call(); static void read_callback(CFReadStreamRef stream, CFStreamEventType event, void *myPtr); static void write_callback(CFWriteStreamRef stream, CFStreamEventType event, void *myPtr); @@ -77,14 +146,8 @@ class TCPAcceptor : private common::Nocopy { : a_handler(a_handler) {} ~TCPAcceptor() {} - bool accept(TCPSocket &socket, - std::string &accepted_addr) { // if accept returns false, will fire accept_handler in future - return false; - } - bool accept(TCPSocket &socket) { - std::string a; - return accept(socket, a); - } + bool accept(TCPSocket &socket, std::string &accepted_addr) { return false; } + bool accept(TCPSocket &socket) { return false; } private: A_handler a_handler; diff --git a/src/platform/PathTools.cpp b/src/platform/PathTools.cpp index 03b5e220..53982e15 100644 --- a/src/platform/PathTools.cpp +++ b/src/platform/PathTools.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "PathTools.hpp" #include @@ -21,6 +21,10 @@ #include #endif +#ifdef __ANDROID__ +#include +#endif + namespace platform { #ifdef _WIN32 std::string get_os_version_string() { @@ -266,7 +270,12 @@ std::string getDefaultDataDirectory(const std::string &cryptonote_name) { } #endif // #if !TARGET_OS_IPHONE -#if !TARGET_OS_IPHONE +#ifdef __ANDROID__ +std::string get_app_data_folder(const std::string &app_name) { + QString dataPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); + return dataPath.toStdString(); +} +#elif !TARGET_OS_IPHONE std::string get_app_data_folder(const std::string &app_name) { #ifdef _WIN32 // Windows @@ -284,7 +293,24 @@ std::string get_app_data_folder(const std::string &app_name) { } #endif // #if !TARGET_OS_IPHONE -static bool create_path_element(const std::string &subpath) { +bool directory_exists(const std::string &path) { +#if defined(__MACH__) || defined(__linux__) + struct stat info; + + if (stat(path.c_str(), &info) != 0) + return false; // printf( "cannot access %s\n", pathname ); + if (info.st_mode & S_IFDIR) + return true; + return false; +#elif defined(_WIN32) + auto wsubpath = FileStream::utf8_to_utf16(path); + DWORD dwAttrib = GetFileAttributesW(wsubpath.c_str()); + + return dwAttrib != INVALID_FILE_ATTRIBUTES && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY); +#endif +} + +bool create_directory_if_necessary(const std::string &subpath) { #if defined(__MACH__) || defined(__linux__) mode_t mode = 0755; if (mkdir(subpath.c_str(), mode) != 0 && errno != EEXIST) @@ -302,10 +328,11 @@ static bool create_path_element(const std::string &subpath) { bool create_directories_if_necessary(const std::string &path) { size_t delim_pos = std::min(path.find("/"), path.find("\\")); while (delim_pos != std::string::npos) { - create_path_element(path.substr(0, delim_pos + 1)); // We ignore intermediate results, because of some systems + create_directory_if_necessary( + path.substr(0, delim_pos + 1)); // We ignore intermediate results, because of some systems delim_pos = std::min(path.find("/", delim_pos + 1), path.find("\\", delim_pos + 1)); } - return create_path_element(path); + return create_directory_if_necessary(path); } bool atomic_replace_file(const std::string &replacement_name, const std::string &old_file_name) { diff --git a/src/platform/PathTools.hpp b/src/platform/PathTools.hpp index b39ca9f6..9a095e23 100644 --- a/src/platform/PathTools.hpp +++ b/src/platform/PathTools.hpp @@ -1,10 +1,19 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once #include +// For documentation +#if defined(__MACH__) +#define platform_DEFAULT_DATA_FOLDER_PATH_PREFIX "~/Library/Application Support/" +#elif defined(_WIN32) +#define platform_DEFAULT_DATA_FOLDER_PATH_PREFIX "%appdata%/" +#else // defined(__linux__) and unknown platforms +#define platform_DEFAULT_DATA_FOLDER_PATH_PREFIX "~/." +#endif + namespace platform { std::string getDefaultDataDirectory( const std::string &cryptonote_name); // we avoid including app-specific headers into our platform code @@ -25,7 +34,9 @@ std::string get_app_data_folder(const std::string &app_name); // std::string getDefaultCacheFile(const std::string& dataDir); std::string get_os_version_string(); -bool create_directories_if_necessary(const std::string &path); +bool directory_exists(const std::string &path); +bool create_directory_if_necessary(const std::string &path); // Only last element +bool create_directories_if_necessary(const std::string &path); // Recursively all elements bool atomic_replace_file(const std::string &replacement_name, const std::string &old_file_name); // bool directoryExists(const std::string& path); } diff --git a/src/platform/PathTools.mm b/src/platform/PathTools.mm index ba5c48ce..9d533db3 100644 --- a/src/platform/PathTools.mm +++ b/src/platform/PathTools.mm @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #import @@ -35,9 +35,7 @@ //NSString *documentsDirectory = [paths objectAtIndex:0]; NSArray * paths = [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask]; //NSURL * documentsURL = [paths lastObject]; //config_folder = [[documentsURL absoluteString] UTF8String]; - config_folder = [[paths - objectAtIndex: - 0] UTF8String]; + config_folder = [[paths objectAtIndex:0] UTF8String]; return config_folder; } diff --git a/src/platform/PreventSleep.cpp b/src/platform/PreventSleep.cpp index 23e4f893..8a5a1769 100644 --- a/src/platform/PreventSleep.cpp +++ b/src/platform/PreventSleep.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "PreventSleep.hpp" #include @@ -7,12 +7,65 @@ #include "TargetConditionals.h" #endif -using namespace platform; +#if defined(__ANDROID__) +#include -#if TARGET_OS_IPHONE +static QAndroidJniObject m_wakeLock; +static std::atomic counter{0}; + +/*static void setActivityFlags(const char * method){ + QAndroidJniObject activity = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", +"activity", "()Landroid/app/Activity;"); + if (activity.isValid()) { + QAndroidJniObject window = activity.callObjectMethod("getWindow", "()Landroid/view/Window;"); + if (window.isValid()) { + const int FLAG_KEEP_SCREEN_ON = 128; + window.callMethod(method, "(I)V", FLAG_KEEP_SCREEN_ON); + } + } +}*/ + +platform::PreventSleep::PreventSleep(const char *reason) { + if (++counter == 1) { + QAndroidJniObject activity = QAndroidJniObject::callStaticObjectMethod( + "org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;"); + if (activity.isValid()) { + QAndroidJniObject serviceName = + QAndroidJniObject::getStaticObjectField("android/content/Context", "POWER_SERVICE"); + if (serviceName.isValid()) { + QAndroidJniObject powerMgr = activity.callObjectMethod( + "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;", serviceName.object()); + if (powerMgr.isValid()) { + jint levelAndFlags = + QAndroidJniObject::getStaticField("android/os/PowerManager", "SCREEN_DIM_WAKE_LOCK"); + + QAndroidJniObject tag = QAndroidJniObject::fromString("My Tag"); + + m_wakeLock = powerMgr.callObjectMethod("newWakeLock", + "(ILjava/lang/String;)Landroid/os/PowerManager$WakeLock;", levelAndFlags, + tag.object()); + } + } + } + if (m_wakeLock.isValid()) { + m_wakeLock.callMethod("acquire", "()V"); + // qDebug() << "Locked device, can't go to standby anymore"; + } + } +} +platform::PreventSleep::~PreventSleep() { + if (--counter == 0) { + if (m_wakeLock.isValid()) { + m_wakeLock.callMethod("release", "()V"); + // qDebug() << "Unlocked device, can now go to standby"; + } + } +} + +#elif TARGET_OS_IPHONE // No power modes on iOS, app will run when in foreground -PreventSleep::PreventSleep(const char *reason) {} -PreventSleep::~PreventSleep() {} +platform::PreventSleep::PreventSleep(const char *reason) {} +platform::PreventSleep::~PreventSleep() {} #elif TARGET_OS_MAC #include #include @@ -21,7 +74,7 @@ PreventSleep::~PreventSleep() {} static std::atomic counter{0}; static IOPMAssertionID assertionID = 0; -PreventSleep::PreventSleep(const char *reason) { +platform::PreventSleep::PreventSleep(const char *reason) { if (++counter == 1) { CFStringRef reasonForActivity = CFStringCreateWithCString(kCFAllocatorDefault, reason, kCFStringEncodingUTF8); IOReturn success = IOPMAssertionCreateWithName( @@ -30,7 +83,7 @@ PreventSleep::PreventSleep(const char *reason) { std::cout << "Preventing sleep " << reason << " success=" << success << std::endl; } } -PreventSleep::~PreventSleep() { +platform::PreventSleep::~PreventSleep() { if (--counter == 0) { IOReturn success = IOPMAssertionRelease(assertionID); std::cout << "Allowing sleep success=" << success << std::endl; @@ -42,13 +95,13 @@ PreventSleep::~PreventSleep() { #include "platform/Windows.hpp" static thread_local int counter = 0; -PreventSleep::PreventSleep(const char *reason) { +platform::PreventSleep::PreventSleep(const char *reason) { if (++counter == 1) { SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED); // ES_AWAYMODE_REQUIRED - only for media centers std::cout << "Preventing sleep " << reason << std::endl; } } -PreventSleep::~PreventSleep() { +platform::PreventSleep::~PreventSleep() { if (--counter == 0) { SetThreadExecutionState(ES_CONTINUOUS); std::cout << "Allowing sleep" << std::endl; @@ -57,7 +110,7 @@ PreventSleep::~PreventSleep() { #elif defined(__linux__) // Sorry, no power modes in '70s -PreventSleep::PreventSleep(const char *reason) {} -PreventSleep::~PreventSleep() {} +platform::PreventSleep::PreventSleep(const char *reason) {} +platform::PreventSleep::~PreventSleep() {} #endif diff --git a/src/platform/PreventSleep.hpp b/src/platform/PreventSleep.hpp index c1dfef5a..8651b349 100644 --- a/src/platform/PreventSleep.hpp +++ b/src/platform/PreventSleep.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/platform/Windows.hpp b/src/platform/Windows.hpp index 429b8041..a9e19712 100644 --- a/src/platform/Windows.hpp +++ b/src/platform/Windows.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/rpc_api.hpp b/src/rpc_api.hpp index 2433911c..5b4811b9 100644 --- a/src/rpc_api.hpp +++ b/src/rpc_api.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once @@ -164,9 +164,11 @@ struct GetStatus { uint32_t incoming_peer_count = 0; // You get longpoll (no immediate reply) until any parameter changes. // You can just send previous response as a next request if you are interested in all changes visible to API. + std::string + lower_level_error; // Problems on lower levels (like bytecoind errors in walletd status). Empty - no errors bool operator==(const Request &other) const { - return top_block_hash == other.top_block_hash && + return lower_level_error == other.lower_level_error && top_block_hash == other.top_block_hash && transaction_pool_version == other.transaction_pool_version && outgoing_peer_count == other.outgoing_peer_count && incoming_peer_count == other.incoming_peer_count; } @@ -293,9 +295,9 @@ struct CreateTransaction { SignedAmount fee_per_byte = 0; // Fee of created transaction will be close to the size of tx * fee_per_byte. // You can check it in response.transaction.fee before sending, if you wish std::string optimization; // Wallet outputs optimization (fusion). Leave empty to use normal optimization, good - // for wallets with balanced sends to recieves count. You can save on a few percent + // for wallets with balanced sends to receives count. You can save on a few percent // of fee (on average) by specifying "minimal" for wallet receiving far less - // transactions than sending. You should use "aggressive" for wallet recieving far + // transactions than sending. You should use "aggressive" for wallet receiving far // more transactions than sending, this option will use every opportunity to reduce // number of outputs. For better optimization use as little anonymity as possible. If // anonymity is set to 0, wallet will prioritize optimizing out dust and crazy (large @@ -474,20 +476,50 @@ struct GetCurrencyId { }; }; +struct SubmitBlock { + static std::string method() { return "submit_block"; } + struct Request { + BinaryArray blocktemplate_blob; + }; + struct Response { + std::string status; + }; +}; + +// Legacy methods struct SubmitBlockLegacy { static std::string method() { return "submitblock"; } // This name is used by old miners typedef std::vector Request; + typedef SubmitBlock::Response Response; +}; + +struct BlockHeaderLegacy : public api::BlockHeader { + bool orphan_status = false; + HeightOrDepth depth = 0; +}; +struct GetLastBlockHeaderLegacy { // Use GetStatus instead + static std::string method() { return "getlastblockheader"; } + typedef EmptyStruct Request; struct Response { std::string status; + BlockHeaderLegacy block_header; }; }; -struct SubmitBlock { - static std::string method() { return "submit_block"; } +struct GetBlockHeaderByHashLegacy { + static std::string method() { return "getblockheaderbyhash"; } struct Request { - BinaryArray blocktemplate_blob; + Hash hash; + }; + typedef GetLastBlockHeaderLegacy::Response Response; +}; + +struct GetBlockHeaderByHeightLegacy { + static std::string method() { return "getblockheaderbyheight"; } + struct Request { + Height height = 0; // Beware, in this call height starts from 1, not 0, so height=1 returns genesis }; - typedef SubmitBlockLegacy::Response Response; + typedef GetLastBlockHeaderLegacy::Response Response; }; } } @@ -539,6 +571,10 @@ void ser_members(bytecoin::api::bytecoind::GetBlockTemplate::Request &v, ISeria void ser_members(bytecoin::api::bytecoind::GetBlockTemplate::Response &v, ISeria &s); void ser_members(bytecoin::api::bytecoind::GetCurrencyId::Response &v, ISeria &s); void ser_members(bytecoin::api::bytecoind::SubmitBlock::Request &v, ISeria &s); -void ser_members(bytecoin::api::bytecoind::SubmitBlockLegacy::Response &v, ISeria &s); +void ser_members(bytecoin::api::bytecoind::SubmitBlock::Response &v, ISeria &s); +void ser_members(bytecoin::api::bytecoind::BlockHeaderLegacy &v, ISeria &s); +void ser_members(bytecoin::api::bytecoind::GetLastBlockHeaderLegacy::Response &v, ISeria &s); +void ser_members(bytecoin::api::bytecoind::GetBlockHeaderByHashLegacy::Request &v, ISeria &s); +void ser_members(bytecoin::api::bytecoind::GetBlockHeaderByHeightLegacy::Request &v, ISeria &s); } // namespace seria diff --git a/src/seria/BinaryInputStream.cpp b/src/seria/BinaryInputStream.cpp index 7d4c1928..9ee7b2f9 100644 --- a/src/seria/BinaryInputStream.cpp +++ b/src/seria/BinaryInputStream.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "BinaryInputStream.hpp" diff --git a/src/seria/BinaryInputStream.hpp b/src/seria/BinaryInputStream.hpp index a2ecef38..a863b39d 100644 --- a/src/seria/BinaryInputStream.hpp +++ b/src/seria/BinaryInputStream.hpp @@ -1,8 +1,9 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once +#include #include "ISeria.hpp" #include "common/MemoryStreams.hpp" @@ -48,11 +49,15 @@ void from_binary(T &obj, const common::BinaryArray &blob) { common::MemoryInputStream stream(blob.data(), blob.size()); BinaryInputStream ba(stream); ba(obj); + if (!stream.empty()) + throw std::runtime_error("Excess data in from_binary " + std::string(typeid(T).name())); } template void from_binary(T &obj, const std::string &blob) { common::MemoryInputStream stream(blob.data(), blob.size()); BinaryInputStream ba(stream); ba(obj); + if (!stream.empty()) + throw std::runtime_error("Excess data in from_binary " + std::string(typeid(T).name())); } } diff --git a/src/seria/BinaryOutputStream.cpp b/src/seria/BinaryOutputStream.cpp index 2e191316..5403181c 100644 --- a/src/seria/BinaryOutputStream.cpp +++ b/src/seria/BinaryOutputStream.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "BinaryOutputStream.hpp" diff --git a/src/seria/BinaryOutputStream.hpp b/src/seria/BinaryOutputStream.hpp index bf66192a..a3249512 100644 --- a/src/seria/BinaryOutputStream.hpp +++ b/src/seria/BinaryOutputStream.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/seria/ISeria.hpp b/src/seria/ISeria.hpp index 11fbe7e2..1fbb6982 100644 --- a/src/seria/ISeria.hpp +++ b/src/seria/ISeria.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once @@ -14,6 +14,7 @@ #include "common/BinaryArray.hpp" #include "common/StringView.hpp" +#include "common/string.hpp" namespace seria { class ISeria; @@ -169,15 +170,15 @@ void seria_map_integral(MapT &value, ISeria &s, std::true_type) { for (size_t i = 0; i != size; ++i) { std::string key; s.next_map_key(key); - typename MapT::key_type k = static_cast( - std::stoll(key)); // We use widest possible because no generic function provided in C++ + typename MapT::key_type k = static_cast(common::stoll(key)); + // We use widest possible conversion because no generic function provided in C++ typename MapT::mapped_type v; s(v); value.insert(std::make_pair(k, std::move(v))); } } else { for (auto &kv : value) { - auto str_key = std::to_string(kv.first); + auto str_key = common::to_string(kv.first); s.next_map_key(const_cast(str_key)); s(const_cast(kv.second)); } diff --git a/src/seria/JsonInputValue.cpp b/src/seria/JsonInputValue.cpp index 7c841a44..a52f541a 100644 --- a/src/seria/JsonInputValue.cpp +++ b/src/seria/JsonInputValue.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "JsonInputValue.hpp" diff --git a/src/seria/JsonInputValue.hpp b/src/seria/JsonInputValue.hpp index 4c5f8e13..d9d3351b 100644 --- a/src/seria/JsonInputValue.hpp +++ b/src/seria/JsonInputValue.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/seria/JsonOutputStream.cpp b/src/seria/JsonOutputStream.cpp index a135888e..531e51d0 100644 --- a/src/seria/JsonOutputStream.cpp +++ b/src/seria/JsonOutputStream.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "JsonOutputStream.hpp" #include diff --git a/src/seria/JsonOutputStream.hpp b/src/seria/JsonOutputStream.hpp index eea041d6..0ab0c941 100644 --- a/src/seria/JsonOutputStream.hpp +++ b/src/seria/JsonOutputStream.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/seria/KVBinaryCommon.hpp b/src/seria/KVBinaryCommon.hpp index 5cff9bdf..989cbf7a 100644 --- a/src/seria/KVBinaryCommon.hpp +++ b/src/seria/KVBinaryCommon.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/seria/KVBinaryInputStream.cpp b/src/seria/KVBinaryInputStream.cpp index c6036a73..297f8e50 100644 --- a/src/seria/KVBinaryInputStream.cpp +++ b/src/seria/KVBinaryInputStream.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "KVBinaryInputStream.hpp" diff --git a/src/seria/KVBinaryInputStream.hpp b/src/seria/KVBinaryInputStream.hpp index 1070fb8f..50ddfa58 100644 --- a/src/seria/KVBinaryInputStream.hpp +++ b/src/seria/KVBinaryInputStream.hpp @@ -1,8 +1,9 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once +#include #include "ISeria.hpp" #include "JsonInputValue.hpp" #include "common/MemoryStreams.hpp" @@ -22,11 +23,15 @@ void from_binary_key_value(T &v, const common::BinaryArray &buf) { common::MemoryInputStream stream(buf.data(), buf.size()); KVBinaryInputStream s(stream); s(v); + if (!stream.empty()) + throw std::runtime_error("Excess data in from_binary_key_value " + std::string(typeid(T).name())); } template void from_binary_key_value(T &v, const std::string &buf) { common::MemoryInputStream stream(buf.data(), buf.size()); KVBinaryInputStream s(stream); s(v); + if (!stream.empty()) + throw std::runtime_error("Excess data in from_binary_key_value " + std::string(typeid(T).name())); } } diff --git a/src/seria/KVBinaryOutputStream.cpp b/src/seria/KVBinaryOutputStream.cpp index 10666e55..85803339 100644 --- a/src/seria/KVBinaryOutputStream.cpp +++ b/src/seria/KVBinaryOutputStream.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "KVBinaryOutputStream.hpp" #include "KVBinaryCommon.hpp" diff --git a/src/seria/KVBinaryOutputStream.hpp b/src/seria/KVBinaryOutputStream.hpp index 700c1247..5fd1284d 100644 --- a/src/seria/KVBinaryOutputStream.hpp +++ b/src/seria/KVBinaryOutputStream.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once diff --git a/src/version.hpp b/src/version.hpp index c4a4097a..3faa843a 100644 --- a/src/version.hpp +++ b/src/version.hpp @@ -4,8 +4,8 @@ #pragma once // defines are for Windows resource compiler -#define bytecoin_VERSION_WINDOWS_COMMA 0, 18, 4, 5 -#define bytecoin_VERSION_STRING "0.18.4.5 (BETA)" +#define bytecoin_VERSION_WINDOWS_COMMA 1, 18, 4, 5 +#define bytecoin_VERSION_STRING "1.18.4.5" #ifdef __cplusplus diff --git a/tests/crypto/test_crypto.cpp b/tests/crypto/test_crypto.cpp index fb283d00..69b8a0c6 100644 --- a/tests/crypto/test_crypto.cpp +++ b/tests/crypto/test_crypto.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include #include @@ -9,232 +9,232 @@ #include "test_crypto.hpp" -#include "crypto/hash.hpp" +#include "../io.hpp" #include "crypto/crypto-ops.h" -#include "crypto/random.h" #include "crypto/crypto.hpp" -#include "../Io.h" +#include "crypto/hash.hpp" +#include "crypto/random.h" using namespace std; -void test_crypto(const std::string & test_vectors_filename) { - fstream input; - string cmd; - size_t test = 0; - crypto::initialize_random_for_tests(); -// if (argc != 2) { -// cerr << "invalid arguments" << endl; -// return 1; -// } - input.open(test_vectors_filename, ios_base::in); - for (;;) { - ++test; - input.exceptions(ios_base::badbit); - if (!(input >> cmd)) { - break; - } - input.exceptions(ios_base::badbit | ios_base::failbit | ios_base::eofbit); - if (cmd == "check_scalar") { - crypto::EllipticCurveScalar scalar; - bool expected = false, actual; - get(input, scalar, expected); - actual = sc_isvalid_vartime(&scalar); - if (expected != actual) { - goto error; - } - } else if (cmd == "random_scalar") { - crypto::EllipticCurveScalar expected, actual; - get(input, expected); - crypto::random_scalar(actual); - if (expected != actual) { - goto error; - } - } else if (cmd == "hash_to_scalar") { - vector data; - crypto::EllipticCurveScalar expected, actual; - get(input, data, expected); - crypto::hash_to_scalar(data.data(), data.size(), actual); - if (expected != actual) { - goto error; - } - } else if (cmd == "generate_keys") { - crypto::PublicKey expected1, actual1; - crypto::SecretKey expected2, actual2; - get(input, expected1, expected2); - random_keys(actual1, actual2); - if (expected1 != actual1 || expected2 != actual2) { - goto error; - } - } else if (cmd == "check_key") { - crypto::PublicKey key; - bool expected = false, actual; - get(input, key, expected); - actual = key_isvalid(key); - if (expected != actual) { - goto error; - } - } else if (cmd == "secret_key_to_public_key") { - crypto::SecretKey sec; - bool expected1 = false, actual1; - crypto::PublicKey expected2, actual2; - get(input, sec, expected1); - if (expected1) { - get(input, expected2); - } - actual1 = secret_key_to_public_key(sec, actual2); - if (expected1 != actual1 || (expected1 && expected2 != actual2)) { - goto error; - } - } else if (cmd == "generate_key_derivation") { - crypto::PublicKey key1; - crypto::SecretKey key2; - bool expected1 = false, actual1; - crypto::KeyDerivation expected2, actual2; - get(input, key1, key2, expected1); - if (expected1) { - get(input, expected2); - } - actual1 = generate_key_derivation(key1, key2, actual2); - if (expected1 != actual1 || (expected1 && expected2 != actual2)) { - goto error; - } - } else if (cmd == "derive_public_key") { - crypto::KeyDerivation derivation; - size_t output_index; - crypto::PublicKey base; - bool expected1 = false, actual1; - crypto::PublicKey expected2, actual2; - get(input, derivation, output_index, base, expected1); - if (expected1) { - get(input, expected2); - } - actual1 = derive_public_key(derivation, output_index, base, actual2); - if (expected1 != actual1 || (expected1 && expected2 != actual2)) { - goto error; - } - } else if (cmd == "derive_secret_key") { - crypto::KeyDerivation derivation; - size_t output_index; - crypto::SecretKey base; - crypto::SecretKey expected, actual; - get(input, derivation, output_index, base, expected); - derive_secret_key(derivation, output_index, base, actual); - if (expected != actual) { - goto error; - } - } else if (cmd == "underive_public_key") { - crypto::KeyDerivation derivation; - size_t output_index; - crypto::PublicKey derived_key; - bool expected1 = false, actual1; - crypto::PublicKey expected2, actual2; - get(input, derivation, output_index, derived_key, expected1); - if (expected1) { - get(input, expected2); - } - actual1 = underive_public_key(derivation, output_index, derived_key, actual2); - if (expected1 != actual1 || (expected1 && expected2 != actual2)) { - goto error; - } - } else if (cmd == "generate_signature") { - crypto::Hash prefix_hash; - crypto::PublicKey pub; - crypto::SecretKey sec; - crypto::Signature expected, actual; - get(input, prefix_hash, pub, sec, expected); - generate_signature(prefix_hash, pub, sec, actual); - if (expected != actual) { - goto error; - } - } else if (cmd == "check_signature") { - crypto::Hash prefix_hash; - crypto::PublicKey pub; - crypto::Signature sig; - bool expected = false, actual; - get(input, prefix_hash, pub, sig, expected); - actual = check_signature(prefix_hash, pub, sig); - if (expected != actual) { - goto error; - } - } else if (cmd == "hash_to_point") { - crypto::Hash h; - crypto::EllipticCurvePoint expected, actual; - get(input, h, expected); - hash_to_point_for_tests(h, actual); - if (expected != actual) { - goto error; - } - } else if (cmd == "hash_to_ec") { - crypto::PublicKey key; - crypto::EllipticCurvePoint expected, actual; - get(input, key, expected); - hash_to_ec(key, actual); - if (expected != actual) { - goto error; - } - } else if (cmd == "generate_key_image") { - crypto::PublicKey pub; - crypto::SecretKey sec; - crypto::KeyImage expected, actual; - get(input, pub, sec, expected); - generate_key_image(pub, sec, actual); - if (expected != actual) { - goto error; - } - } else if (cmd == "generate_ring_signature") { - crypto::Hash prefix_hash; - crypto::KeyImage image; - vector vpubs; - vector pubs; - size_t pubs_count; - crypto::SecretKey sec; - size_t sec_index; - vector expected, actual; - size_t i; - get(input, prefix_hash, image, pubs_count); - vpubs.resize(pubs_count); - pubs.resize(pubs_count); - for (i = 0; i < pubs_count; i++) { - get(input, vpubs[i]); - pubs[i] = &vpubs[i]; - } - get(input, sec, sec_index); - expected.resize(pubs_count); - getvar(input, pubs_count * sizeof(crypto::Signature), expected.data()); - actual.resize(pubs_count); - generate_ring_signature(prefix_hash, image, pubs.data(), pubs_count, sec, sec_index, actual.data()); - if (expected != actual) { - goto error; - } - } else if (cmd == "check_ring_signature") { - crypto::Hash prefix_hash; - crypto::KeyImage image; - vector vpubs; - vector pubs; - size_t pubs_count; - vector sigs; - bool expected = false, actual; - size_t i; - get(input, prefix_hash, image, pubs_count); - vpubs.resize(pubs_count); - pubs.resize(pubs_count); - for (i = 0; i < pubs_count; i++) { - get(input, vpubs[i]); - pubs[i] = &vpubs[i]; - } - sigs.resize(pubs_count); - getvar(input, pubs_count * sizeof(crypto::Signature), sigs.data()); - get(input, expected); - actual = check_ring_signature(prefix_hash, image, pubs.data(), pubs_count, sigs.data(), true); - if (expected != actual) { - goto error; - } - } else { - throw ios_base::failure("Unknown function: " + cmd); - } - continue; -error: - cerr << "Wrong result on test " << test << endl; - throw std::runtime_error("test_crypto failed"); - } +void test_crypto(const std::string &test_vectors_filename) { + fstream input; + string cmd; + size_t test = 0; + crypto::initialize_random_for_tests(); + // if (argc != 2) { + // cerr << "invalid arguments" << endl; + // return 1; + // } + input.open(test_vectors_filename, ios_base::in); + for (;;) { + ++test; + input.exceptions(ios_base::badbit); + if (!(input >> cmd)) { + break; + } + input.exceptions(ios_base::badbit | ios_base::failbit | ios_base::eofbit); + if (cmd == "check_scalar") { + crypto::EllipticCurveScalar scalar; + bool expected = false, actual; + get(input, scalar, expected); + actual = sc_isvalid_vartime(&scalar); + if (expected != actual) { + goto error; + } + } else if (cmd == "random_scalar") { + crypto::EllipticCurveScalar expected, actual; + get(input, expected); + crypto::random_scalar(actual); + if (expected != actual) { + goto error; + } + } else if (cmd == "hash_to_scalar") { + vector data; + crypto::EllipticCurveScalar expected, actual; + get(input, data, expected); + crypto::hash_to_scalar(data.data(), data.size(), actual); + if (expected != actual) { + goto error; + } + } else if (cmd == "generate_keys") { + crypto::PublicKey expected1, actual1; + crypto::SecretKey expected2, actual2; + get(input, expected1, expected2); + random_keypair(actual1, actual2); + if (expected1 != actual1 || expected2 != actual2) { + goto error; + } + } else if (cmd == "check_key") { + crypto::PublicKey key; + bool expected = false, actual; + get(input, key, expected); + actual = key_isvalid(key); + if (expected != actual) { + goto error; + } + } else if (cmd == "secret_key_to_public_key") { + crypto::SecretKey sec; + bool expected1 = false, actual1; + crypto::PublicKey expected2, actual2; + get(input, sec, expected1); + if (expected1) { + get(input, expected2); + } + actual1 = secret_key_to_public_key(sec, actual2); + if (expected1 != actual1 || (expected1 && expected2 != actual2)) { + goto error; + } + } else if (cmd == "generate_key_derivation") { + crypto::PublicKey key1; + crypto::SecretKey key2; + bool expected1 = false, actual1; + crypto::KeyDerivation expected2, actual2; + get(input, key1, key2, expected1); + if (expected1) { + get(input, expected2); + } + actual1 = generate_key_derivation(key1, key2, actual2); + if (expected1 != actual1 || (expected1 && expected2 != actual2)) { + goto error; + } + } else if (cmd == "derive_public_key") { + crypto::KeyDerivation derivation; + size_t output_index; + crypto::PublicKey base; + bool expected1 = false, actual1; + crypto::PublicKey expected2, actual2; + get(input, derivation, output_index, base, expected1); + if (expected1) { + get(input, expected2); + } + actual1 = derive_public_key(derivation, output_index, base, actual2); + if (expected1 != actual1 || (expected1 && expected2 != actual2)) { + goto error; + } + } else if (cmd == "derive_secret_key") { + crypto::KeyDerivation derivation; + size_t output_index; + crypto::SecretKey base; + crypto::SecretKey expected, actual; + get(input, derivation, output_index, base, expected); + derive_secret_key(derivation, output_index, base, actual); + if (expected != actual) { + goto error; + } + } else if (cmd == "underive_public_key") { + crypto::KeyDerivation derivation; + size_t output_index; + crypto::PublicKey derived_key; + bool expected1 = false, actual1; + crypto::PublicKey expected2, actual2; + get(input, derivation, output_index, derived_key, expected1); + if (expected1) { + get(input, expected2); + } + actual1 = underive_public_key(derivation, output_index, derived_key, actual2); + if (expected1 != actual1 || (expected1 && expected2 != actual2)) { + goto error; + } + } else if (cmd == "generate_signature") { + crypto::Hash prefix_hash; + crypto::PublicKey pub; + crypto::SecretKey sec; + crypto::Signature expected, actual; + get(input, prefix_hash, pub, sec, expected); + generate_signature(prefix_hash, pub, sec, actual); + if (expected != actual) { + goto error; + } + } else if (cmd == "check_signature") { + crypto::Hash prefix_hash; + crypto::PublicKey pub; + crypto::Signature sig; + bool expected = false, actual; + get(input, prefix_hash, pub, sig, expected); + actual = check_signature(prefix_hash, pub, sig); + if (expected != actual) { + goto error; + } + } else if (cmd == "hash_to_point") { + crypto::Hash h; + crypto::EllipticCurvePoint expected, actual; + get(input, h, expected); + hash_to_point_for_tests(h, actual); + if (expected != actual) { + goto error; + } + } else if (cmd == "hash_to_ec") { + crypto::PublicKey key; + crypto::EllipticCurvePoint expected, actual; + get(input, key, expected); + hash_to_ec(key, actual); + if (expected != actual) { + goto error; + } + } else if (cmd == "generate_key_image") { + crypto::PublicKey pub; + crypto::SecretKey sec; + crypto::KeyImage expected, actual; + get(input, pub, sec, expected); + generate_key_image(pub, sec, actual); + if (expected != actual) { + goto error; + } + } else if (cmd == "generate_ring_signature") { + crypto::Hash prefix_hash; + crypto::KeyImage image; + vector vpubs; + vector pubs; + size_t pubs_count; + crypto::SecretKey sec; + size_t sec_index; + vector expected, actual; + size_t i; + get(input, prefix_hash, image, pubs_count); + vpubs.resize(pubs_count); + pubs.resize(pubs_count); + for (i = 0; i < pubs_count; i++) { + get(input, vpubs[i]); + pubs[i] = &vpubs[i]; + } + get(input, sec, sec_index); + expected.resize(pubs_count); + getvar(input, pubs_count * sizeof(crypto::Signature), expected.data()); + actual.resize(pubs_count); + generate_ring_signature(prefix_hash, image, pubs.data(), pubs_count, sec, sec_index, actual.data()); + if (expected != actual) { + goto error; + } + } else if (cmd == "check_ring_signature") { + crypto::Hash prefix_hash; + crypto::KeyImage image; + vector vpubs; + vector pubs; + size_t pubs_count; + vector sigs; + bool expected = false, actual; + size_t i; + get(input, prefix_hash, image, pubs_count); + vpubs.resize(pubs_count); + pubs.resize(pubs_count); + for (i = 0; i < pubs_count; i++) { + get(input, vpubs[i]); + pubs[i] = &vpubs[i]; + } + sigs.resize(pubs_count); + getvar(input, pubs_count * sizeof(crypto::Signature), sigs.data()); + get(input, expected); + actual = check_ring_signature(prefix_hash, image, pubs.data(), pubs_count, sigs.data(), true); + if (expected != actual) { + goto error; + } + } else { + throw ios_base::failure("Unknown function: " + cmd); + } + continue; + error: + cerr << "Wrong result on test " << test << endl; + throw std::runtime_error("test_crypto failed"); + } } diff --git a/tests/crypto/test_crypto.hpp b/tests/crypto/test_crypto.hpp index da8496b3..0f901069 100644 --- a/tests/crypto/test_crypto.hpp +++ b/tests/crypto/test_crypto.hpp @@ -1,8 +1,8 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once #include -void test_crypto(const std::string & test_vectors_filename); \ No newline at end of file +void test_crypto(const std::string &test_vectors_filename); \ No newline at end of file diff --git a/tests/hash/test_hash.cpp b/tests/hash/test_hash.cpp index 9ed662fb..7e8dff9c 100644 --- a/tests/hash/test_hash.cpp +++ b/tests/hash/test_hash.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "test_hash.hpp" @@ -9,10 +9,10 @@ #include #include -#include "crypto/hash.hpp" +#include "../io.hpp" #include "common/StringTools.hpp" #include "crypto/hash-impl.h" -#include "../Io.h" +#include "crypto/hash.hpp" using namespace std; @@ -20,72 +20,73 @@ static crypto::CryptoNightContext context; extern "C" { #ifdef _MSC_VER -#pragma warning(disable: 4297) +#pragma warning(disable : 4297) #endif - static void hash_tree(const void *data, size_t length, unsigned char *hash) { - if ((length & 31) != 0) { - throw ios_base::failure("Invalid input length for tree_hash"); - } - crypto::tree_hash((const unsigned char (*)[32]) data, length >> 5, hash); - } +static void hash_tree(const void *data, size_t length, unsigned char *hash) { + if ((length & 31) != 0) { + throw ios_base::failure("Invalid input length for tree_hash"); + } + crypto::tree_hash((const unsigned char(*)[32])data, length >> 5, hash); +} - static void slow_hash(const void *data, size_t length, unsigned char *hash) { - context.cn_slow_hash(data, length, hash); - } +static void slow_hash(const void *data, size_t length, unsigned char *hash) { + context.cn_slow_hash(data, length, hash); +} } extern "C" typedef void hash_f(const void *, size_t, unsigned char *); struct hash_func { - const string name; - hash_f &f; + const string name; + hash_f &f; } hashes[] = {{"fast", crypto::cn_fast_hash}, {"slow", slow_hash}, {"tree", hash_tree}, - {"extra-blake", crypto::hash_extra_blake}, {"extra-groestl", crypto::hash_extra_groestl}, - {"extra-jh", crypto::hash_extra_jh}, {"extra-skein", crypto::hash_extra_skein}}; + {"extra-blake", crypto::hash_extra_blake}, {"extra-groestl", crypto::hash_extra_groestl}, + {"extra-jh", crypto::hash_extra_jh}, {"extra-skein", crypto::hash_extra_skein}}; -void test_hash(const char * test_fun_name, const std::string & test_vectors_filename) { - hash_f *f = nullptr; - fstream input; - vector data; - crypto::Hash expected, actual; - size_t test = 0; - for (hash_func * hf = hashes;; hf++) { - if (hf >= &hashes[sizeof(hashes) / sizeof(hash_func)]) { - cerr << "Unknown function" << endl; - throw std::runtime_error("test_hash failed"); - } - if (test_fun_name == hf->name) { - f = &hf->f; - break; - } - } -// if (f == slow_hash) { -// context = new Crypto::cn_context(); -// } - input.open(test_vectors_filename, ios_base::in); - for (;;) { - ++test; - input.exceptions(ios_base::badbit); - get(input, expected); - if (input.rdstate() & ios_base::eofbit) { - break; - } - input.exceptions(ios_base::badbit | ios_base::failbit | ios_base::eofbit); - input.clear(input.rdstate()); - get(input, data); - f(data.data(), data.size(), actual.data); - if (expected != actual) { - cerr << "Hash mismatch on test " << test << endl; -// cerr << "Input: " << common::pod_to_hex(data) << endl; - cerr << "Expected hash: " << common::pod_to_hex(expected) << endl; - cerr << "Actual hash: " << common::pod_to_hex(actual) << endl;; - throw std::runtime_error("test_hash failed"); +void test_hash(const char *test_fun_name, const std::string &test_vectors_filename) { + hash_f *f = nullptr; + fstream input; + vector data; + crypto::Hash expected, actual; + size_t test = 0; + for (hash_func *hf = hashes;; hf++) { + if (hf >= &hashes[sizeof(hashes) / sizeof(hash_func)]) { + cerr << "Unknown function" << endl; + throw std::runtime_error("test_hash failed"); + } + if (test_fun_name == hf->name) { + f = &hf->f; + break; + } + } + // if (f == slow_hash) { + // context = new Crypto::cn_context(); + // } + input.open(test_vectors_filename, ios_base::in); + for (;;) { + ++test; + input.exceptions(ios_base::badbit); + get(input, expected); + if (input.rdstate() & ios_base::eofbit) { + break; + } + input.exceptions(ios_base::badbit | ios_base::failbit | ios_base::eofbit); + input.clear(input.rdstate()); + get(input, data); + f(data.data(), data.size(), actual.data); + if (expected != actual) { + cerr << "Hash mismatch on test " << test << endl; + // cerr << "Input: " << common::pod_to_hex(data) << endl; + cerr << "Expected hash: " << common::pod_to_hex(expected) << endl; + cerr << "Actual hash: " << common::pod_to_hex(actual) << endl; + ; + throw std::runtime_error("test_hash failed"); + } } - } } -void test_hashes(const std::string & test_vectors_folder) { +void test_hashes(const std::string &test_vectors_folder) { test_hash("extra-blake", test_vectors_folder + "/tests-extra-blake.txt"); test_hash("extra-groestl", test_vectors_folder + "/tests-extra-groestl.txt"); test_hash("extra-jh", test_vectors_folder + "/tests-extra-jh.txt"); @@ -94,4 +95,3 @@ void test_hashes(const std::string & test_vectors_folder) { test_hash("slow", test_vectors_folder + "/tests-slow.txt"); test_hash("tree", test_vectors_folder + "/tests-tree.txt"); } - diff --git a/tests/hash/test_hash.hpp b/tests/hash/test_hash.hpp index cdea42c8..0edd51ae 100644 --- a/tests/hash/test_hash.hpp +++ b/tests/hash/test_hash.hpp @@ -1,8 +1,8 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once #include -void test_hashes(const std::string & test_vectors_folder); \ No newline at end of file +void test_hashes(const std::string &test_vectors_folder); \ No newline at end of file diff --git a/tests/io.hpp b/tests/io.hpp new file mode 100644 index 00000000..7edea334 --- /dev/null +++ b/tests/io.hpp @@ -0,0 +1,106 @@ +// Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. + +#pragma once + +#include +#include +#include +#include +#include + +inline bool hexdecode(const char *from, std::size_t length, void *to) { + std::size_t i; + for (i = 0; i < length; i++) { + int v = 0; + if (from[2 * i] >= '0' && from[2 * i] <= '9') { + v = from[2 * i] - '0'; + } else if (from[2 * i] >= 'a' && from[2 * i] <= 'f') { + v = from[2 * i] - 'a' + 10; + } else { + return false; + } + v <<= 4; + if (from[2 * i + 1] >= '0' && from[2 * i + 1] <= '9') { + v |= from[2 * i + 1] - '0'; + } else if (from[2 * i + 1] >= 'a' && from[2 * i + 1] <= 'f') { + v |= from[2 * i + 1] - 'a' + 10; + } else { + return false; + } + *(reinterpret_cast(to) + i) = v; + } + return true; +} + +inline void get(std::istream &input, bool &res) { + std::string sres; + input >> sres; + if (sres == "false") { + res = false; + } else if (sres == "true") { + res = true; + } else { + input.setstate(std::ios_base::failbit); + } +} + +template +typename std::enable_if::value, void>::type get(std::istream &input, T &res) { + input >> res; +} + +inline void getvar(std::istream &input, std::size_t length, void *res) { + std::string sres; + input >> sres; + if (sres.length() != 2 * length || !hexdecode(sres.data(), length, res)) { + input.setstate(std::ios_base::failbit); + } +} + +template +typename std::enable_if::value && !std::is_scalar::value, void>::type get( + std::istream &input, T &res) { + getvar(input, sizeof(T), &res); +} + +inline void get(std::istream &input, std::vector &res) { + std::string sres; + input >> sres; + if (sres == "x") { + res.clear(); + } else if (sres.length() % 2 != 0) { + input.setstate(std::ios_base::failbit); + } else { + std::size_t length = sres.length() / 2; + res.resize(length); + if (!hexdecode(sres.data(), length, res.data())) { + input.setstate(std::ios_base::failbit); + } + } +} + +#if !defined(_MSC_VER) || _MSC_VER >= 1800 + +template +typename std::enable_if<(sizeof...(TT) > 0), void>::type get(std::istream &input, T &res, TT &... resres) { + get(input, res); + get(input, resres...); +} + +#else +#include +#include +#include +#include +#include + +#define NESTED_GET(z, n, data) get(input, BOOST_PP_CAT(res, n)); +#define GET(z, n, data) \ + template \ + void get(std::istream &input, BOOST_PP_ENUM_BINARY_PARAMS(n, T, &res)) { \ + BOOST_PP_REPEAT(n, NESTED_GET, ~) \ + } +BOOST_PP_REPEAT_FROM_TO(2, 5, GET, ~) + +#endif diff --git a/tests/json/test_json.cpp b/tests/json/test_json.cpp index d6cc3c6c..7d5273f3 100644 --- a/tests/json/test_json.cpp +++ b/tests/json/test_json.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #include "test_json.hpp" @@ -7,33 +7,32 @@ #include #include #include -#include #include +#include #include "common/JsonValue.hpp" #include "common/StringTools.hpp" -void test_json(const std::string & filename, bool should_be) { +void test_json(const std::string &filename, bool should_be) { std::string content; - if( !common::load_file(filename, content) ) + if (!common::load_file(filename, content)) throw std::runtime_error("test file not found " + filename); bool success = false; - try{ + try { common::JsonValue val = common::JsonValue::from_string(content); - success = true; - }catch(const std::exception & ex){ + success = true; + } catch (const std::exception &ex) { std::cout << filename << " fail reason: " << ex.what() << std::endl; } - if( success != should_be ) + if (success != should_be) throw std::runtime_error("test case failed " + filename); } -void test_json(const std::string & test_vectors_folder) { - for(int i = 1; i != 4; ++i) +void test_json(const std::string &test_vectors_folder) { + for (int i = 1; i != 4; ++i) test_json(test_vectors_folder + "/pass" + std::to_string(i) + ".json", true); - for(int i = 1; i != 34; ++i) + for (int i = 1; i != 34; ++i) test_json(test_vectors_folder + "/fail" + std::to_string(i) + ".json", i == 1 || i == 18); // We pass fail1 because we relax rules on top-level object or array // We pass fail18 because we support infinite depth of arrays } - diff --git a/tests/json/test_json.hpp b/tests/json/test_json.hpp index c86b81a1..387442da 100644 --- a/tests/json/test_json.hpp +++ b/tests/json/test_json.hpp @@ -1,8 +1,8 @@ // Copyright (c) 2012-2018, The CryptoNote developers, The Bytecoin developers. -// Licensed under the GNU Lesser General Public License. See LICENSING.md for details. +// Licensed under the GNU Lesser General Public License. See LICENSE for details. #pragma once #include -void test_json(const std::string & test_vectors_folder); +void test_json(const std::string &test_vectors_folder);