diff options
26 files changed, 258 insertions, 387 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 716b18590..7c28a71ce 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,6 +5,9 @@ on: [push, pull_request] # The below variables reduce repetitions across similar targets env: REMOVE_BUNDLED_BOOST : rm -rf /usr/local/share/boost + BUILD_DEFAULT_LINUX: | + ccache --max-size=150M + cmake -S . -B build -D ARCH="default" -D BUILD_TESTS=ON -D CMAKE_BUILD_TYPE=release && cmake --build build -j3 APT_INSTALL_LINUX: 'sudo apt -y install build-essential cmake libboost-all-dev miniupnpc libunbound-dev graphviz doxygen libunwind8-dev pkg-config libssl-dev libzmq3-dev libsodium-dev libhidapi-dev libnorm-dev libusb-1.0-0-dev libpgm-dev libprotobuf-dev protobuf-compiler ccache' APT_SET_CONF: | echo "Acquire::Retries \"3\";" | sudo tee -a /etc/apt/apt.conf.d/80-custom @@ -79,9 +82,7 @@ jobs: with: path: ~/.ccache key: ccache-ubuntu-build-${{ matrix.os }}-${{ github.sha }} - restore-keys: | - ccache-ubuntu-build-${{ matrix.os }} - ccache-ubuntu-build- + restore-keys: ccache-ubuntu-build-${{ matrix.os }} - name: remove bundled boost run: ${{env.REMOVE_BUNDLED_BOOST}} - name: set apt conf @@ -91,9 +92,7 @@ jobs: - name: install monero dependencies run: ${{env.APT_INSTALL_LINUX}} - name: build - run: | - ccache --max-size=150M - make -j3 + run: ${{env.BUILD_DEFAULT_LINUX}} libwallet-ubuntu: runs-on: ubuntu-latest @@ -137,8 +136,8 @@ jobs: uses: actions/cache@v2 with: path: ~/.ccache - key: test-ubuntu-ccache-${{ github.sha }} - restore-keys: test-ubuntu-ccache- + key: ccache-ubuntu-build-ubuntu-latest-${{ github.sha }} + restore-keys: ccache-ubuntu-build-ubuntu-latest - name: remove bundled boost run: ${{env.REMOVE_BUNDLED_BOOST}} - name: set apt conf @@ -153,11 +152,8 @@ jobs: env: CTEST_OUTPUT_ON_FAILURE: ON run: | - ccache --max-size=150M - DIR_BUILD="build/ci/release" - DIR_SRC="`pwd`" - mkdir -p "${DIR_BUILD}" && cd "${DIR_BUILD}" - cmake -S "${DIR_SRC}" -D ARCH="default" -D BUILD_SHARED_LIBS=ON -D BUILD_TESTS=ON -D CMAKE_BUILD_TYPE=release && make -j3 && make test + ${{env.BUILD_DEFAULT_LINUX}} + cmake --build build --target test # ARCH="default" (not "native") ensures, that a different execution host can execute binaries compiled elsewhere. # BUILD_SHARED_LIBS=ON speeds up the linkage part a bit, reduces size, and is the only place where the dynamic linkage is tested. diff --git a/.github/workflows/depends.yml b/.github/workflows/depends.yml index 3e0f048c7..8e4eaf177 100644 --- a/.github/workflows/depends.yml +++ b/.github/workflows/depends.yml @@ -45,15 +45,29 @@ jobs: - uses: actions/checkout@v1 with: submodules: recursive +# Most volatile cache - name: ccache uses: actions/cache@v2 with: - path: | - ~/.ccache - contrib/depends/built - contrib/depends/sdk-sources + path: ~/.ccache key: ccache-${{ matrix.toolchain.host }}-${{ github.sha }} restore-keys: ccache-${{ matrix.toolchain.host }}- +# Less volatile cache + - name: depends cache + uses: actions/cache@v2 + with: + path: contrib/depends/built + key: depends-${{ matrix.toolchain.host }}-${{ hashFiles('contrib/depends/packages/*') }} + restore-keys: | + depends-${{ matrix.toolchain.host }}-${{ hashFiles('contrib/depends/packages/*') }} + depends-${{ matrix.toolchain.host }}- +# Static cache + - name: OSX SDK cache + uses: actions/cache@v2 + with: + path: contrib/depends/sdk-sources + key: sdk-${{ matrix.toolchain.host }}-${{ matrix.toolchain.osx_sdk }} + restore-keys: sdk-${{ matrix.toolchain.host }}-${{ matrix.toolchain.osx_sdk }} - name: set apt conf run: | echo "Acquire::Retries \"3\";" | sudo tee -a /etc/apt/apt.conf.d/80-custom diff --git a/CMakeLists.txt b/CMakeLists.txt index 33b00a725..f8af45f4b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -234,7 +234,7 @@ add_library(l3 OBJECT incorrect_source.cpp) file(REMOVE_RECURSE "${TEST_PROJECT}") endforeach() endfunction() -if (NOT (CMAKE_SYSTEM_NAME MATCHES "kOpenBSD.*|OpenBSD.*")) +if (NOT (CMAKE_SYSTEM_NAME MATCHES "kOpenBSD.*|OpenBSD.*") AND NOT OSSFUZZ) forbid_undefined_symbols() endif() @@ -603,6 +603,23 @@ add_definitions(-DAUTO_INITIALIZE_EASYLOGGINGPP) set(MONERO_GENERATED_HEADERS_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated_include") include_directories(${MONERO_GENERATED_HEADERS_DIR}) +# As of OpenBSD 6.8, -march=<anything> breaks the build +function(set_default_arch) + if (OPENBSD) + set(ARCH default) + else() + set(ARCH native) + endif() + + set(ARCH ${ARCH} CACHE STRING "CPU to build for: -march value or 'default' to not pass -march at all") +endfunction() + +if (NOT (MSVC OR ARCH)) + set_default_arch() +endif() + +CHECK_C_COMPILER_FLAG(-std=c11 HAVE_C11) + option(COVERAGE "Enable profiling for test coverage report" OFF) if(COVERAGE) message(STATUS "Building with profiling for test coverage report") @@ -682,17 +699,6 @@ endif() # Trezor support check include(CheckTrezor) -# As of OpenBSD 6.8, -march=<anything> breaks the build -function(set_default_arch) - if (OPENBSD) - set(ARCH default) - else() - set(ARCH native) - endif() - - set(ARCH ${ARCH} CACHE STRING "CPU to build for: -march value or 'default' to not pass -march at all") -endfunction() - if(MSVC) add_definitions("/bigobj /MP /W3 /GS- /D_CRT_SECURE_NO_WARNINGS /wd4996 /wd4345 /D_WIN32_WINNT=0x0600 /DWIN32_LEAN_AND_MEAN /DGTEST_HAS_TR1_TUPLE=0 /FIinline_c.h /D__SSE4_1__") # set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Dinline=__inline") @@ -705,9 +711,6 @@ if(MSVC) include_directories(SYSTEM src/platform/msc) else() include(TestCXXAcceptsFlag) - if (NOT ARCH) - set_default_arch() - endif() message(STATUS "Building on ${CMAKE_SYSTEM_PROCESSOR} for ${ARCH}") if(ARCH STREQUAL "default") set(ARCH_FLAG "") @@ -1243,9 +1246,6 @@ option(BUILD_GUI_DEPS "Build GUI dependencies." OFF) # on libunbound shipped with their distribution instead option(INSTALL_VENDORED_LIBUNBOUND "Install libunbound binary built from source vendored with this repo." OFF) - -CHECK_C_COMPILER_FLAG(-std=c11 HAVE_C11) - find_package(PythonInterp) find_program(iwyu_tool_path NAMES iwyu_tool.py iwyu_tool) if (iwyu_tool_path AND PYTHONINTERP_FOUND) @@ -508,19 +508,6 @@ cd ../.. Then you can run make as usual. -### On Linux for Android (using docker): - -```bash -# Build image (for ARM 32-bit) -docker build -f utils/build_scripts/android32.Dockerfile -t monero-android . -# Build image (for ARM 64-bit) -docker build -f utils/build_scripts/android64.Dockerfile -t monero-android . -# Create container -docker create -it --name monero-android monero-android bash -# Get binaries -docker cp monero-android:/src/build/release/bin . -``` - ### Building portable statically linked binaries By default, in either dynamically or statically linked builds, binaries target the specific host processor on which the build happens and are not portable to other processors. Portable binaries can be built using the following targets: diff --git a/cmake/FindCcache.cmake b/cmake/FindCcache.cmake index 2eb2fa2fd..d98518134 100644 --- a/cmake/FindCcache.cmake +++ b/cmake/FindCcache.cmake @@ -50,7 +50,7 @@ option (CCACHE "") file(WRITE "${CMAKE_SOURCE_DIR}/test.cpp" "int main() { return 0; }") set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE}") set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK "${CCACHE}") -add_executable(test test.cpp) +add_executable(main test.cpp) ]=]) try_compile(RET "${TEST_PROJECT}/build" "${TEST_PROJECT}" "test" CMAKE_FLAGS -DCCACHE="${CCACHE_FOUND}") unset(TEST_PROJECT) diff --git a/contrib/depends/packages/freebsd_base.mk b/contrib/depends/packages/freebsd_base.mk index c6a209dcd..ad9975f8d 100644 --- a/contrib/depends/packages/freebsd_base.mk +++ b/contrib/depends/packages/freebsd_base.mk @@ -12,8 +12,8 @@ endef define $(package)_build_cmds mkdir bin &&\ - echo "exec /usr/bin/clang-8 -target x86_64-unknown-freebsd$($(package)_version) --sysroot=$(host_prefix)/native $$$$""@" > bin/clang-8 &&\ - echo "exec /usr/bin/clang++-8 -target x86_64-unknown-freebsd$($(package)_version) --sysroot=$(host_prefix)/native $$$$""@" > bin/clang++-8 &&\ + echo "#!/bin/sh\n\nexec /usr/bin/clang-8 -target x86_64-unknown-freebsd$($(package)_version) --sysroot=$(host_prefix)/native $$$$""@" > bin/clang-8 &&\ + echo "#!/bin/sh\n\nexec /usr/bin/clang++-8 -target x86_64-unknown-freebsd$($(package)_version) --sysroot=$(host_prefix)/native $$$$""@" > bin/clang++-8 &&\ chmod 755 bin/* endef diff --git a/contrib/epee/include/net/net_utils_base.h b/contrib/epee/include/net/net_utils_base.h index d86c62c17..722206ee1 100644 --- a/contrib/epee/include/net/net_utils_base.h +++ b/contrib/epee/include/net/net_utils_base.h @@ -236,6 +236,7 @@ namespace net_utils virtual address_type get_type_id() const = 0; virtual zone get_zone() const = 0; virtual bool is_blockable() const = 0; + virtual std::uint16_t port() const = 0; }; template<typename T> @@ -266,6 +267,7 @@ namespace net_utils virtual address_type get_type_id() const override { return value.get_type_id(); } virtual zone get_zone() const override { return value.get_zone(); } virtual bool is_blockable() const override { return value.is_blockable(); } + virtual std::uint16_t port() const override { return value.port(); } }; std::shared_ptr<interface> self; @@ -312,6 +314,7 @@ namespace net_utils address_type get_type_id() const { return self ? self->get_type_id() : address_type::invalid; } zone get_zone() const { return self ? self->get_zone() : zone::invalid; } bool is_blockable() const { return self ? self->is_blockable() : false; } + std::uint16_t port() const { return self ? self->port() : 0; } template<typename Type> const Type &as() const { return as_mutable<const Type>(); } BEGIN_KV_SERIALIZE_MAP() diff --git a/contrib/epee/src/net_ssl.cpp b/contrib/epee/src/net_ssl.cpp index 765dadce3..70cd0d0ad 100644 --- a/contrib/epee/src/net_ssl.cpp +++ b/contrib/epee/src/net_ssl.cpp @@ -576,7 +576,8 @@ boost::system::error_code store_ssl_keys(boost::asio::ssl::context& ssl, const b const auto ctx = ssl.native_handle(); CHECK_AND_ASSERT_MES(ctx, boost::system::error_code(EINVAL, boost::system::system_category()), "Context is null"); CHECK_AND_ASSERT_MES(base.has_filename(), boost::system::error_code(EINVAL, boost::system::system_category()), "Need filename"); - if (!(ssl_key = SSL_CTX_get0_privatekey(ctx)) || !(ssl_cert = SSL_CTX_get0_certificate(ctx))) + std::unique_ptr<SSL, decltype(&SSL_free)> dflt_SSL(SSL_new(ctx), SSL_free); + if (!dflt_SSL || !(ssl_key = SSL_get_privatekey(dflt_SSL.get())) || !(ssl_cert = SSL_get_certificate(dflt_SSL.get()))) return {EINVAL, boost::system::system_category()}; using file_closer = int(std::FILE*); diff --git a/src/common/util.cpp b/src/common/util.cpp index 445a11a75..af9843b95 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -1355,8 +1355,12 @@ std::string get_nix_version_display_string() 100743, 92152, 57565, 22533, 37564, 21823, 19980, 18277, 18402, 14344, 12142, 15842, 13677, 17631, 18294, 22270, 41422, 39296, 36688, 33512, 33831, 27582, 22276, 27516, 27317, 25505, 24426, 20566, 23045, 26766, - 28185, 26169, 27011, - 28642 // Blocks 1,990,000 to 1,999,999 in December 2019 + 28185, 26169, 27011, 28642, 34994, 34442, 30682, 34357, 31640, 41167, + 41301, 48616, 51075, 55061, 49909, 44606, 47091, 53828, 42520, 39023, + 55245, 56145, 51119, 60398, 71821, 48142, 60310, 56041, 54176, 66220, + 56336, 55248, 56656, 63305, 54029, 77136, 71902, 71618, 83587, 81068, + 69062, 54848, 53681, 53555, + 50616 // Blocks 2,400,000 to 2,409,999 in July 2021 }; const uint64_t block_range_size = 10000; diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl index 685968c08..106253082 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl @@ -2081,6 +2081,8 @@ skip: } MDEBUG(context << "Nothing to get from this peer, and it's not ahead of us, all done"); context.m_state = cryptonote_connection_context::state_normal; + if (m_core.get_current_blockchain_height() >= m_core.get_target_blockchain_height()) + on_connection_synchronized(); return true; } uint64_t next_needed_height = m_block_queue.get_next_needed_height(bc_height); @@ -2228,6 +2230,8 @@ skip: } MDEBUG(context << "Nothing to get from this peer, and it's not ahead of us, all done"); context.m_state = cryptonote_connection_context::state_normal; + if (m_core.get_current_blockchain_height() >= m_core.get_target_blockchain_height()) + on_connection_synchronized(); return true; } @@ -2419,10 +2423,7 @@ skip: if (context.m_remote_blockchain_height >= m_core.get_target_blockchain_height()) { if (m_core.get_current_blockchain_height() >= m_core.get_target_blockchain_height()) - { - MGINFO_GREEN("SYNCHRONIZED OK"); on_connection_synchronized(); - } } else { diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 8dd4b4476..cfeac3d37 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -270,9 +270,17 @@ namespace nodetool peerlist_entry pe{}; pe.adr = addr; - zone.second.m_peerlist.remove_from_peer_white(pe); - zone.second.m_peerlist.remove_from_peer_gray(pe); - zone.second.m_peerlist.remove_from_peer_anchor(addr); + if (addr.port() == 0) + { + zone.second.m_peerlist.evict_host_from_peerlist(true, pe); + zone.second.m_peerlist.evict_host_from_peerlist(false, pe); + } + else + { + zone.second.m_peerlist.remove_from_peer_white(pe); + zone.second.m_peerlist.remove_from_peer_gray(pe); + zone.second.m_peerlist.remove_from_peer_anchor(addr); + } for (const auto &c: conns) zone.second.m_net_server.get_config_object().close(c); @@ -332,6 +340,13 @@ namespace nodetool for (const auto &c: conns) zone.second.m_net_server.get_config_object().close(c); + for (int i = 0; i < 2; ++i) + zone.second.m_peerlist.filter(i == 0, [&subnet](const peerlist_entry &pe){ + if (pe.adr.get_type_id() != epee::net_utils::ipv4_network_address::get_type_id()) + return false; + return subnet.matches(pe.adr.as<const epee::net_utils::ipv4_network_address>()); + }); + conns.clear(); } diff --git a/src/p2p/net_peerlist.cpp b/src/p2p/net_peerlist.cpp index 42ab9727d..50dc6da77 100644 --- a/src/p2p/net_peerlist.cpp +++ b/src/p2p/net_peerlist.cpp @@ -289,17 +289,9 @@ namespace nodetool copy_peers(peers.anchor, m_peers_anchor.get<by_addr>()); } - void peerlist_manager::evict_host_from_white_peerlist(const peerlist_entry& pr) + void peerlist_manager::evict_host_from_peerlist(bool use_white, const peerlist_entry& pr) { - peers_indexed::index<by_time>::type& sorted_index=m_peers_white.get<by_time>(); - auto i = sorted_index.begin(); - while (i != sorted_index.end()) - { - if (i->adr.is_same_host(pr.adr)) - i = sorted_index.erase(i); - else - ++i; - } + filter(use_white, [&pr](const peerlist_entry& pe){ return pe.adr.is_same_host(pr.adr); }); } } diff --git a/src/p2p/net_peerlist.h b/src/p2p/net_peerlist.h index d8de6abe9..0662789b9 100644 --- a/src/p2p/net_peerlist.h +++ b/src/p2p/net_peerlist.h @@ -109,7 +109,7 @@ namespace nodetool bool get_white_peer_by_index(peerlist_entry& p, size_t i); bool get_gray_peer_by_index(peerlist_entry& p, size_t i); template<typename F> bool foreach(bool white, const F &f); - void evict_host_from_white_peerlist(const peerlist_entry& pr); + void evict_host_from_peerlist(bool white, const peerlist_entry& pr); bool append_with_peer_white(const peerlist_entry& pr, bool trust_last_seen = false); bool append_with_peer_gray(const peerlist_entry& pr); bool append_with_peer_anchor(const anchor_peerlist_entry& ple); @@ -120,6 +120,7 @@ namespace nodetool bool get_and_empty_anchor_peerlist(std::vector<anchor_peerlist_entry>& apl); bool remove_from_peer_anchor(const epee::net_utils::network_address& addr); bool remove_from_peer_white(const peerlist_entry& pe); + template<typename F> size_t filter(bool white, const F &f); // f returns true: drop, false: keep private: struct by_time{}; @@ -346,7 +347,7 @@ namespace nodetool if(by_addr_it_wt == m_peers_white.get<by_addr>().end()) { //put new record into white list - evict_host_from_white_peerlist(ple); + evict_host_from_peerlist(true, ple); m_peers_white.insert(ple); trim_white_peerlist(); }else @@ -520,5 +521,26 @@ namespace nodetool CATCH_ENTRY_L0("peerlist_manager::remove_from_peer_anchor()", false); } //-------------------------------------------------------------------------------------------------- + template<typename F> size_t peerlist_manager::filter(bool white, const F &f) + { + size_t filtered = 0; + TRY_ENTRY(); + CRITICAL_REGION_LOCAL(m_peerlist_lock); + peers_indexed::index<by_addr>::type& sorted_index = white ? m_peers_gray.get<by_addr>() : m_peers_white.get<by_addr>(); + auto i = sorted_index.begin(); + while (i != sorted_index.end()) + { + if (f(*i)) + { + i = sorted_index.erase(i); + ++filtered; + } + else + ++i; + } + CATCH_ENTRY_L0("peerlist_manager::filter()", filtered); + return filtered; + } + //-------------------------------------------------------------------------------------------------- } diff --git a/src/rpc/CMakeLists.txt b/src/rpc/CMakeLists.txt index aa4102481..15e433e10 100644 --- a/src/rpc/CMakeLists.txt +++ b/src/rpc/CMakeLists.txt @@ -39,7 +39,7 @@ set(rpc_sources core_rpc_server.cpp rpc_payment.cpp rpc_version_str.cpp - instanciations) + instanciations.cpp) set(daemon_messages_sources message.cpp diff --git a/src/serialization/json_object.cpp b/src/serialization/json_object.cpp index 67f042c2e..28e207ff2 100644 --- a/src/serialization/json_object.cpp +++ b/src/serialization/json_object.cpp @@ -1091,9 +1091,12 @@ void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const rct::rctSig& }; INSERT_INTO_JSON_OBJECT(dest, type, sig.type); - INSERT_INTO_JSON_OBJECT(dest, encrypted, sig.ecdhInfo); - INSERT_INTO_JSON_OBJECT(dest, commitments, transform(sig.outPk, just_mask)); - INSERT_INTO_JSON_OBJECT(dest, fee, sig.txnFee); + if (sig.type != rct::RCTTypeNull) + { + INSERT_INTO_JSON_OBJECT(dest, encrypted, sig.ecdhInfo); + INSERT_INTO_JSON_OBJECT(dest, commitments, transform(sig.outPk, just_mask)); + INSERT_INTO_JSON_OBJECT(dest, fee, sig.txnFee); + } // prunable if (!sig.p.bulletproofs.empty() || !sig.p.rangeSigs.empty() || !sig.p.MGs.empty() || !sig.get_pseudo_outs().empty()) @@ -1122,9 +1125,12 @@ void fromJsonValue(const rapidjson::Value& val, rct::rctSig& sig) } GET_FROM_JSON_OBJECT(val, sig.type, type); - GET_FROM_JSON_OBJECT(val, sig.ecdhInfo, encrypted); - GET_FROM_JSON_OBJECT(val, sig.outPk, commitments); - GET_FROM_JSON_OBJECT(val, sig.txnFee, fee); + if (sig.type != rct::RCTTypeNull) + { + GET_FROM_JSON_OBJECT(val, sig.ecdhInfo, encrypted); + GET_FROM_JSON_OBJECT(val, sig.outPk, commitments); + GET_FROM_JSON_OBJECT(val, sig.txnFee, fee); + } // prunable const auto prunable = val.FindMember("prunable"); diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index b4fa1ea8c..3a2074cc4 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -2392,6 +2392,11 @@ void WalletImpl::setOffline(bool offline) m_wallet->set_offline(offline); } +bool WalletImpl::isOffline() const +{ + return m_wallet->is_offline(); +} + void WalletImpl::hardForkInfo(uint8_t &version, uint64_t &earliest_height) const { m_wallet->get_hard_fork_info(version, earliest_height); diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h index 217f16e48..011a94ec4 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.h @@ -186,6 +186,7 @@ public: virtual std::string getCacheAttribute(const std::string &key) const override; virtual void setOffline(bool offline) override; + virtual bool isOffline() const override; virtual bool setUserNote(const std::string &txid, const std::string ¬e) override; virtual std::string getUserNote(const std::string &txid) const override; diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h index a08033033..ed8c55d3b 100644 --- a/src/wallet/api/wallet2_api.h +++ b/src/wallet/api/wallet2_api.h @@ -1034,6 +1034,7 @@ struct Wallet * \param offline - true/false */ virtual void setOffline(bool offline) = 0; + virtual bool isOffline() const = 0; //! blackballs a set of outputs virtual bool blackballOutputs(const std::vector<std::string> &outputs, bool add) = 0; diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 634d9b312..7f23ed4d6 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -144,6 +144,9 @@ using namespace cryptonote; #define IGNORE_LONG_PAYMENT_ID_FROM_BLOCK_VERSION 12 +#define DEFAULT_UNLOCK_TIME (CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE * DIFFICULTY_TARGET_V2) +#define RECENT_SPEND_WINDOW (50 * DIFFICULTY_TARGET_V2) + static const std::string MULTISIG_SIGNATURE_MAGIC = "SigMultisigPkV1"; static const std::string MULTISIG_EXTRA_INFO_MAGIC = "MultisigxV1"; @@ -1034,6 +1037,34 @@ uint64_t gamma_picker::pick() { double x = gamma(engine); x = exp(x); + + if (x > DEFAULT_UNLOCK_TIME) + { + // We are trying to select an output from the chain that appeared 'x' seconds before the + // current chain tip, where 'x' is selected from the gamma distribution recommended in Miller et al. + // (https://arxiv.org/pdf/1704.04299/). + // Our method is to get the average time delta between outputs in the recent past, estimate the number of + // outputs 'n' that would have appeared between 'chain_tip - x' and 'chain_tip', select the real output at + // 'current_num_outputs - n', then randomly select an output from the block where that output appears. + // Source code to paper: https://github.com/maltemoeser/moneropaper + // + // Due to the 'default spendable age' mechanic in Monero, 'current_num_outputs' only contains + // currently *unlocked* outputs, which means the earliest output that can be selected is not at the chain tip! + // Therefore, we must offset 'x' so it matches up with the timing of the outputs being considered. We do + // this by saying if 'x` equals the expected age of the first unlocked output (compared to the current + // chain tip - i.e. DEFAULT_UNLOCK_TIME), then select the first unlocked output. + x -= DEFAULT_UNLOCK_TIME; + } + else + { + // If the spent time suggested by the gamma is less than the unlock time, that means the gamma is suggesting an output + // that is no longer feasible to be spent (possible since the gamma was constructed when consensus rules did not enforce the + // lock time). The assumption made in this code is that an output expected spent quicker than the unlock time would likely + // be spent within RECENT_SPEND_WINDOW after allowed. So it returns an output that falls between 0 and the RECENT_SPEND_WINDOW. + // The RECENT_SPEND_WINDOW was determined with empirical analysis of observed data. + x = crypto::rand_idx(static_cast<uint64_t>(RECENT_SPEND_WINDOW)); + } + uint64_t output_index = x / average_output_time; if (output_index >= num_rct_outputs) return std::numeric_limits<uint64_t>::max(); // bad pick @@ -1219,6 +1250,7 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended, std wallet2::~wallet2() { + deinit(); } bool wallet2::has_testnet_option(const boost::program_options::variables_map& vm) @@ -2782,9 +2814,8 @@ void wallet2::process_parsed_blocks(uint64_t start_height, const std::vector<cry { if (tx_cache_data[i].empty()) continue; - tpool.submit(&waiter, [&hwdev, &gender, &tx_cache_data, i]() { + tpool.submit(&waiter, [&gender, &tx_cache_data, i]() { auto &slot = tx_cache_data[i]; - boost::unique_lock<hw::device> hwdev_lock(hwdev); for (auto &iod: slot.primary) gender(iod); for (auto &iod: slot.additional) @@ -3500,14 +3531,6 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo blocks_fetched += added_blocks; } THROW_WALLET_EXCEPTION_IF(!waiter.wait(), error::wallet_internal_error, "Exception in thread pool"); - if(!first && blocks_start_height == next_blocks_start_height) - { - m_node_rpc_proxy.set_height(m_blockchain.size()); - refreshed = true; - break; - } - - first = false; // handle error from async fetching thread if (error) @@ -3518,6 +3541,15 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo throw std::runtime_error("proxy exception in refresh thread"); } + if(!first && blocks_start_height == next_blocks_start_height) + { + m_node_rpc_proxy.set_height(m_blockchain.size()); + refreshed = true; + break; + } + + first = false; + if (!next_blocks.empty()) { const uint64_t expected_start_height = std::max(static_cast<uint64_t>(m_blockchain.size()), uint64_t(1)) - 1; @@ -3754,9 +3786,11 @@ void wallet2::detach_blockchain(uint64_t height, std::map<std::pair<uint64_t, ui //---------------------------------------------------------------------------------------------------- bool wallet2::deinit() { - m_is_initialized=false; - unlock_keys_file(); - m_account.deinit(); + if(m_is_initialized) { + m_is_initialized = false; + unlock_keys_file(); + m_account.deinit(); + } return true; } //---------------------------------------------------------------------------------------------------- @@ -4431,7 +4465,7 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st account_public_address device_account_public_address; THROW_WALLET_EXCEPTION_IF(!hwdev.get_public_address(device_account_public_address), error::wallet_internal_error, "Cannot get a device address"); - THROW_WALLET_EXCEPTION_IF(device_account_public_address != m_account.get_keys().m_account_address, error::wallet_internal_error, "Device wallet does not match wallet address. " + THROW_WALLET_EXCEPTION_IF(device_account_public_address != m_account.get_keys().m_account_address, error::wallet_internal_error, "Device wallet does not match wallet address. If the device uses the passphrase feature, please check whether the passphrase was entered correctly (it may have been misspelled - different passphrases generate different wallets, passphrase is case-sensitive). " "Device address: " + cryptonote::get_account_address_as_str(m_nettype, false, device_account_public_address) + ", wallet address: " + m_account.get_public_address_str(m_nettype)); LOG_PRINT_L0("Device inited..."); @@ -8596,18 +8630,30 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>> } // get the keys for those - req.get_txid = false; - + // the response can get large and end up rejected by the anti DoS limits, so chunk it if needed + size_t offset = 0; + while (offset < req.outputs.size()) { + static const size_t chunk_size = 1000; + COMMAND_RPC_GET_OUTPUTS_BIN::request chunk_req = AUTO_VAL_INIT(chunk_req); + COMMAND_RPC_GET_OUTPUTS_BIN::response chunk_daemon_resp = AUTO_VAL_INIT(chunk_daemon_resp); + chunk_req.get_txid = false; + for (size_t i = 0; i < std::min<size_t>(req.outputs.size() - offset, chunk_size); ++i) + chunk_req.outputs.push_back(req.outputs[offset + i]); + const boost::lock_guard<boost::recursive_mutex> lock{m_daemon_rpc_mutex}; uint64_t pre_call_credits = m_rpc_payment_state.credits; - req.client = get_client_signature(); - bool r = epee::net_utils::invoke_http_bin("/get_outs.bin", req, daemon_resp, *m_http_client, rpc_timeout); - THROW_ON_RPC_RESPONSE_ERROR(r, {}, daemon_resp, "get_outs.bin", error::get_outs_error, get_rpc_status(daemon_resp.status)); - THROW_WALLET_EXCEPTION_IF(daemon_resp.outs.size() != req.outputs.size(), error::wallet_internal_error, + chunk_req.client = get_client_signature(); + bool r = epee::net_utils::invoke_http_bin("/get_outs.bin", chunk_req, chunk_daemon_resp, *m_http_client, rpc_timeout); + THROW_ON_RPC_RESPONSE_ERROR(r, {}, chunk_daemon_resp, "get_outs.bin", error::get_outs_error, get_rpc_status(chunk_daemon_resp.status)); + THROW_WALLET_EXCEPTION_IF(chunk_daemon_resp.outs.size() != chunk_req.outputs.size(), error::wallet_internal_error, "daemon returned wrong response for get_outs.bin, wrong amounts count = " + - std::to_string(daemon_resp.outs.size()) + ", expected " + std::to_string(req.outputs.size())); - check_rpc_cost("/get_outs.bin", daemon_resp.credits, pre_call_credits, daemon_resp.outs.size() * COST_PER_OUT); + std::to_string(chunk_daemon_resp.outs.size()) + ", expected " + std::to_string(chunk_req.outputs.size())); + check_rpc_cost("/get_outs.bin", chunk_daemon_resp.credits, pre_call_credits, chunk_daemon_resp.outs.size() * COST_PER_OUT); + + offset += chunk_size; + for (size_t i = 0; i < chunk_daemon_resp.outs.size(); ++i) + daemon_resp.outs.push_back(std::move(chunk_daemon_resp.outs[i])); } std::unordered_map<uint64_t, uint64_t> scanty_outs; diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index b72817ba0..e1a06886b 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -1292,13 +1292,20 @@ namespace tools try { // gather info to ask the user - std::unordered_map<cryptonote::account_public_address, std::pair<std::string, uint64_t>> dests; + std::unordered_map<cryptonote::account_public_address, std::pair<std::string, uint64_t>> tx_dests; + std::unordered_map<cryptonote::account_public_address, std::pair<std::string, uint64_t>> all_dests; int first_known_non_zero_change_index = -1; + res.summary.amount_in = 0; + res.summary.amount_out = 0; + res.summary.change_amount = 0; + res.summary.fee = 0; for (size_t n = 0; n < tx_constructions.size(); ++n) { const tools::wallet2::tx_construction_data &cd = tx_constructions[n]; res.desc.push_back({0, 0, std::numeric_limits<uint32_t>::max(), 0, {}, "", 0, "", 0, 0, ""}); wallet_rpc::COMMAND_RPC_DESCRIBE_TRANSFER::transfer_description &desc = res.desc.back(); + // Clear the recipients collection ready for this loop iteration + tx_dests.clear(); std::vector<cryptonote::tx_extra_field> tx_extra_fields; bool has_encrypted_payment_id = false; @@ -1337,17 +1344,17 @@ namespace tools std::string address = cryptonote::get_account_address_as_str(m_wallet->nettype(), entry.is_subaddress, entry.addr); if (has_encrypted_payment_id && !entry.is_subaddress && address != entry.original) address = cryptonote::get_account_integrated_address_as_str(m_wallet->nettype(), entry.addr, payment_id8); - auto i = dests.find(entry.addr); - if (i == dests.end()) - dests.insert(std::make_pair(entry.addr, std::make_pair(address, entry.amount))); + auto i = tx_dests.find(entry.addr); + if (i == tx_dests.end()) + tx_dests.insert(std::make_pair(entry.addr, std::make_pair(address, entry.amount))); else i->second.second += entry.amount; desc.amount_out += entry.amount; } if (cd.change_dts.amount > 0) { - auto it = dests.find(cd.change_dts.addr); - if (it == dests.end()) + auto it = tx_dests.find(cd.change_dts.addr); + if (it == tx_dests.end()) { er.code = WALLET_RPC_ERROR_CODE_BAD_UNSIGNED_TX_DATA; er.message = "Claimed change does not go to a paid address"; @@ -1374,29 +1381,45 @@ namespace tools desc.change_amount += cd.change_dts.amount; it->second.second -= cd.change_dts.amount; if (it->second.second == 0) - dests.erase(cd.change_dts.addr); + tx_dests.erase(cd.change_dts.addr); } - for (auto i = dests.begin(); i != dests.end(); ) + for (auto i = tx_dests.begin(); i != tx_dests.end(); ++i) { if (i->second.second > 0) { desc.recipients.push_back({i->second.first, i->second.second}); + auto it_in_all = all_dests.find(i->first); + if (it_in_all == all_dests.end()) + all_dests.insert(std::make_pair(i->first, i->second)); + else + it_in_all->second.second += i->second.second; } else ++desc.dummy_outputs; - ++i; } if (desc.change_amount > 0) { const tools::wallet2::tx_construction_data &cd0 = tx_constructions[0]; desc.change_address = get_account_address_as_str(m_wallet->nettype(), cd0.subaddr_account > 0, cd0.change_dts.addr); + res.summary.change_address = desc.change_address; } desc.fee = desc.amount_in - desc.amount_out; desc.unlock_time = cd.unlock_time; desc.extra = epee::to_hex::string({cd.extra.data(), cd.extra.size()}); + + // Update summary items + res.summary.amount_in += desc.amount_in; + res.summary.amount_out += desc.amount_out; + res.summary.change_amount += desc.change_amount; + res.summary.fee += desc.fee; + } + // Populate the summary recipients list + for (auto i = all_dests.begin(); i != all_dests.end(); ++i) + { + res.summary.recipients.push_back({i->second.first, i->second.second}); } } catch (const std::exception &e) diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h index 6640441ed..248d31aa4 100644 --- a/src/wallet/wallet_rpc_server_commands_defs.h +++ b/src/wallet/wallet_rpc_server_commands_defs.h @@ -47,7 +47,7 @@ // advance which version they will stop working with // Don't go over 32767 for any of these #define WALLET_RPC_VERSION_MAJOR 1 -#define WALLET_RPC_VERSION_MINOR 22 +#define WALLET_RPC_VERSION_MINOR 23 #define MAKE_WALLET_RPC_VERSION(major,minor) (((major)<<16)|(minor)) #define WALLET_RPC_VERSION MAKE_WALLET_RPC_VERSION(WALLET_RPC_VERSION_MAJOR, WALLET_RPC_VERSION_MINOR) namespace tools @@ -701,6 +701,25 @@ namespace wallet_rpc END_KV_SERIALIZE_MAP() }; + struct txset_summary + { + uint64_t amount_in; + uint64_t amount_out; + std::list<recipient> recipients; + uint64_t change_amount; + std::string change_address; + uint64_t fee; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(amount_in) + KV_SERIALIZE(amount_out) + KV_SERIALIZE(recipients) + KV_SERIALIZE(change_amount) + KV_SERIALIZE(change_address) + KV_SERIALIZE(fee) + END_KV_SERIALIZE_MAP() + }; + struct request_t { std::string unsigned_txset; @@ -716,8 +735,10 @@ namespace wallet_rpc struct response_t { std::list<transfer_description> desc; + struct txset_summary summary; BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(summary) KV_SERIALIZE(desc) END_KV_SERIALIZE_MAP() }; diff --git a/tests/unit_tests/epee_boosted_tcp_server.cpp b/tests/unit_tests/epee_boosted_tcp_server.cpp index d10b2bb33..992122dd2 100644 --- a/tests/unit_tests/epee_boosted_tcp_server.cpp +++ b/tests/unit_tests/epee_boosted_tcp_server.cpp @@ -111,8 +111,7 @@ TEST(boosted_tcp_server, worker_threads_are_exception_resistant) { boost::unique_lock<boost::mutex> lock(mtx); - ASSERT_NE(boost::cv_status::timeout, cond.wait_for(lock, boost::chrono::seconds(5))); - ASSERT_EQ(4, counter); + ASSERT_TRUE(cond.wait_for(lock, boost::chrono::seconds(5), [&counter]{ return counter == 4; })); } // Check if threads are alive @@ -125,8 +124,7 @@ TEST(boosted_tcp_server, worker_threads_are_exception_resistant) { boost::unique_lock<boost::mutex> lock(mtx); - ASSERT_NE(boost::cv_status::timeout, cond.wait_for(lock, boost::chrono::seconds(5))); - ASSERT_EQ(4, counter); + ASSERT_TRUE(cond.wait_for(lock, boost::chrono::seconds(5), [&counter]{ return counter == 4; })); } srv.send_stop_signal(); diff --git a/tests/unit_tests/epee_utils.cpp b/tests/unit_tests/epee_utils.cpp index cbe3c61b1..b83a809b7 100644 --- a/tests/unit_tests/epee_utils.cpp +++ b/tests/unit_tests/epee_utils.cpp @@ -1512,6 +1512,7 @@ TEST(NetUtils, NetworkAddress) constexpr static epee::net_utils::address_type get_type_id() noexcept { return epee::net_utils::address_type(-1); } constexpr static epee::net_utils::zone get_zone() noexcept { return epee::net_utils::zone::invalid; } constexpr static bool is_blockable() noexcept { return false; } + constexpr static uint16_t port() { return 0; } }; const epee::net_utils::network_address empty; diff --git a/tests/unit_tests/node_server.cpp b/tests/unit_tests/node_server.cpp index 2c80acda5..cab600b3d 100644 --- a/tests/unit_tests/node_server.cpp +++ b/tests/unit_tests/node_server.cpp @@ -795,9 +795,11 @@ TEST(cryptonote_protocol_handler, race_condition) workers_t workers; } check; check.work = std::make_shared<work_t>(check.io_context); - check.workers.emplace_back([&check]{ - check.io_context.run(); - }); + while (check.workers.size() < 2) { + check.workers.emplace_back([&check]{ + check.io_context.run(); + }); + } while (daemon.main.conn.size() < 1) { daemon.main.conn.emplace_back(new connection_t(check.io_context, daemon.main.shared_state, {}, {})); daemon.alt.conn.emplace_back(new connection_t(io_context, daemon.alt.shared_state, {}, {})); @@ -856,7 +858,7 @@ TEST(cryptonote_protocol_handler, race_condition) } } while (daemon.main.conn.size() < 2) { - daemon.main.conn.emplace_back(new connection_t(io_context, daemon.main.shared_state, {}, {})); + daemon.main.conn.emplace_back(new connection_t(check.io_context, daemon.main.shared_state, {}, {})); daemon.alt.conn.emplace_back(new connection_t(io_context, daemon.alt.shared_state, {}, {})); create_conn_pair(daemon.main.conn.back(), daemon.alt.conn.back()); conduct_handshake(daemon.alt.net_node, daemon.alt.conn.back()); diff --git a/utils/build_scripts/android32.Dockerfile b/utils/build_scripts/android32.Dockerfile deleted file mode 100644 index c0931ce05..000000000 --- a/utils/build_scripts/android32.Dockerfile +++ /dev/null @@ -1,134 +0,0 @@ -FROM debian:stable - -RUN apt-get update && apt-get install -y unzip automake build-essential curl file pkg-config git python libtool libtinfo5 - -WORKDIR /opt/android -## INSTALL ANDROID SDK -ENV ANDROID_SDK_REVISION 4333796 -ENV ANDROID_SDK_HASH 92ffee5a1d98d856634e8b71132e8a95d96c83a63fde1099be3d86df3106def9 -RUN curl -s -O https://dl.google.com/android/repository/sdk-tools-linux-${ANDROID_SDK_REVISION}.zip \ - && echo "${ANDROID_SDK_HASH} sdk-tools-linux-${ANDROID_SDK_REVISION}.zip" | sha256sum -c \ - && unzip sdk-tools-linux-${ANDROID_SDK_REVISION}.zip \ - && rm -f sdk-tools-linux-${ANDROID_SDK_REVISION}.zip - -## INSTALL ANDROID NDK -ENV ANDROID_NDK_REVISION 17b -ENV ANDROID_NDK_HASH 5dfbbdc2d3ba859fed90d0e978af87c71a91a5be1f6e1c40ba697503d48ccecd -RUN curl -s -O https://dl.google.com/android/repository/android-ndk-r${ANDROID_NDK_REVISION}-linux-x86_64.zip \ - && echo "${ANDROID_NDK_HASH} android-ndk-r${ANDROID_NDK_REVISION}-linux-x86_64.zip" | sha256sum -c \ - && unzip android-ndk-r${ANDROID_NDK_REVISION}-linux-x86_64.zip \ - && rm -f android-ndk-r${ANDROID_NDK_REVISION}-linux-x86_64.zip - -ENV WORKDIR /opt/android -ENV ANDROID_SDK_ROOT ${WORKDIR}/tools -ENV ANDROID_NDK_ROOT ${WORKDIR}/android-ndk-r${ANDROID_NDK_REVISION} -ENV PREFIX /opt/android/prefix - -ENV TOOLCHAIN_DIR ${WORKDIR}/toolchain-arm -RUN ${ANDROID_NDK_ROOT}/build/tools/make_standalone_toolchain.py \ - --arch arm \ - --api 21 \ - --install-dir ${TOOLCHAIN_DIR} \ - --stl=libc++ - -#INSTALL cmake -ENV CMAKE_VERSION 3.12.1 -RUN cd /usr \ - && curl -s -O https://cmake.org/files/v3.12/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz \ - && tar -xzf /usr/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz \ - && rm -f /usr/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz -ENV PATH /usr/cmake-${CMAKE_VERSION}-Linux-x86_64/bin:$PATH - -## Boost -ARG BOOST_VERSION=1_68_0 -ARG BOOST_VERSION_DOT=1.68.0 -ARG BOOST_HASH=7f6130bc3cf65f56a618888ce9d5ea704fa10b462be126ad053e80e553d6d8b7 -RUN set -ex \ - && curl -s -L -o boost_${BOOST_VERSION}.tar.bz2 https://downloads.sourceforge.net/project/boost/boost/${BOOST_VERSION_DOT}/boost_${BOOST_VERSION}.tar.bz2 \ - && echo "${BOOST_HASH} boost_${BOOST_VERSION}.tar.bz2" | sha256sum -c \ - && tar -xvf boost_${BOOST_VERSION}.tar.bz2 \ - && rm -f boost_${BOOST_VERSION}.tar.bz2 \ - && cd boost_${BOOST_VERSION} \ - && ./bootstrap.sh --prefix=${PREFIX} - -ENV HOST_PATH $PATH -ENV PATH $TOOLCHAIN_DIR/arm-linux-androideabi/bin:$TOOLCHAIN_DIR/bin:$PATH - -ARG NPROC=1 - -# Build iconv for lib boost locale -ENV ICONV_VERSION 1.15 -ENV ICONV_HASH ccf536620a45458d26ba83887a983b96827001e92a13847b45e4925cc8913178 -RUN curl -s -O http://ftp.gnu.org/pub/gnu/libiconv/libiconv-${ICONV_VERSION}.tar.gz \ - && echo "${ICONV_HASH} libiconv-${ICONV_VERSION}.tar.gz" | sha256sum -c \ - && tar -xzf libiconv-${ICONV_VERSION}.tar.gz \ - && rm -f libiconv-${ICONV_VERSION}.tar.gz \ - && cd libiconv-${ICONV_VERSION} \ - && CC=arm-linux-androideabi-clang CXX=arm-linux-androideabi-clang++ ./configure --build=x86_64-linux-gnu --host=arm-eabi --prefix=${PREFIX} --disable-rpath \ - && make -j${NPROC} && make install - -## Build BOOST -RUN cd boost_${BOOST_VERSION} \ - && ./b2 --build-type=minimal link=static runtime-link=static --with-chrono --with-date_time --with-filesystem --with-program_options --with-regex --with-serialization --with-system --with-thread --with-locale --build-dir=android --stagedir=android toolset=clang threading=multi threadapi=pthread target-os=android -sICONV_PATH=${PREFIX} install -j${NPROC} - -#Note : we build openssl because the default lacks DSA1 - -# download, configure and make Zlib -ENV ZLIB_VERSION 1.2.11 -ENV ZLIB_HASH c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1 -RUN curl -s -O https://zlib.net/zlib-${ZLIB_VERSION}.tar.gz \ - && echo "${ZLIB_HASH} zlib-${ZLIB_VERSION}.tar.gz" | sha256sum -c \ - && tar -xzf zlib-${ZLIB_VERSION}.tar.gz \ - && rm zlib-${ZLIB_VERSION}.tar.gz \ - && mv zlib-${ZLIB_VERSION} zlib \ - && cd zlib && CC=clang CXX=clang++ ./configure --static \ - && make -j${NPROC} - -# open ssl -ARG OPENSSL_VERSION=1.0.2p -ARG OPENSSL_HASH=50a98e07b1a89eb8f6a99477f262df71c6fa7bef77df4dc83025a2845c827d00 -RUN curl -s -O https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz \ - && echo "${OPENSSL_HASH} openssl-${OPENSSL_VERSION}.tar.gz" | sha256sum -c \ - && tar -xzf openssl-${OPENSSL_VERSION}.tar.gz \ - && rm openssl-${OPENSSL_VERSION}.tar.gz \ - && cd openssl-${OPENSSL_VERSION} \ - && sed -i -e "s/mandroid/target\ armv7\-none\-linux\-androideabi/" Configure \ - && CC=clang CXX=clang++ \ - ./Configure android-armv7 \ - no-asm \ - no-shared --static \ - --with-zlib-include=${WORKDIR}/zlib/include --with-zlib-lib=${WORKDIR}/zlib/lib \ - --prefix=${PREFIX} --openssldir=${PREFIX} \ - && make -j${NPROC} \ - && make install - -# ZMQ -ARG ZMQ_VERSION=v4.2.5 -ARG ZMQ_HASH=d062edd8c142384792955796329baf1e5a3377cd -RUN git clone https://github.com/zeromq/libzmq.git -b ${ZMQ_VERSION} \ - && cd libzmq \ - && test `git rev-parse HEAD` = ${ZMQ_HASH} || exit 1 \ - && ./autogen.sh \ - && CC=clang CXX=clang++ ./configure --prefix=${PREFIX} --host=arm-linux-androideabi --enable-static --disable-shared \ - && make -j${NPROC} \ - && make install - -# Sodium -ARG SODIUM_VERSION=1.0.16 -ARG SODIUM_HASH=675149b9b8b66ff44152553fb3ebf9858128363d -RUN set -ex \ - && git clone https://github.com/jedisct1/libsodium.git -b ${SODIUM_VERSION} \ - && cd libsodium \ - && test `git rev-parse HEAD` = ${SODIUM_HASH} || exit 1 \ - && ./autogen.sh \ - && CC=clang CXX=clang++ ./configure --prefix=${PREFIX} --host=arm-linux-androideabi --enable-static --disable-shared \ - && make -j${NPROC} \ - && make install - -ADD . /src -RUN cd /src \ - && CMAKE_INCLUDE_PATH="${PREFIX}/include" \ - CMAKE_LIBRARY_PATH="${PREFIX}/lib" \ - ANDROID_STANDALONE_TOOLCHAIN_PATH=${TOOLCHAIN_DIR} \ - USE_SINGLE_BUILDDIR=1 \ - PATH=${HOST_PATH} make release-static-android-armv7 -j${NPROC} diff --git a/utils/build_scripts/android64.Dockerfile b/utils/build_scripts/android64.Dockerfile deleted file mode 100644 index 3a62da464..000000000 --- a/utils/build_scripts/android64.Dockerfile +++ /dev/null @@ -1,134 +0,0 @@ -FROM debian:stable - -RUN apt-get update && apt-get install -y unzip automake build-essential curl file pkg-config git python libtool libtinfo5 - -WORKDIR /opt/android -## INSTALL ANDROID SDK -ENV ANDROID_SDK_REVISION 4333796 -ENV ANDROID_SDK_HASH 92ffee5a1d98d856634e8b71132e8a95d96c83a63fde1099be3d86df3106def9 -RUN curl -s -O https://dl.google.com/android/repository/sdk-tools-linux-${ANDROID_SDK_REVISION}.zip \ - && echo "${ANDROID_SDK_HASH} sdk-tools-linux-${ANDROID_SDK_REVISION}.zip" | sha256sum -c \ - && unzip sdk-tools-linux-${ANDROID_SDK_REVISION}.zip \ - && rm -f sdk-tools-linux-${ANDROID_SDK_REVISION}.zip - -## INSTALL ANDROID NDK -ENV ANDROID_NDK_REVISION 17b -ENV ANDROID_NDK_HASH 5dfbbdc2d3ba859fed90d0e978af87c71a91a5be1f6e1c40ba697503d48ccecd -RUN curl -s -O https://dl.google.com/android/repository/android-ndk-r${ANDROID_NDK_REVISION}-linux-x86_64.zip \ - && echo "${ANDROID_NDK_HASH} android-ndk-r${ANDROID_NDK_REVISION}-linux-x86_64.zip" | sha256sum -c \ - && unzip android-ndk-r${ANDROID_NDK_REVISION}-linux-x86_64.zip \ - && rm -f android-ndk-r${ANDROID_NDK_REVISION}-linux-x86_64.zip - -ENV WORKDIR /opt/android -ENV ANDROID_SDK_ROOT ${WORKDIR}/tools -ENV ANDROID_NDK_ROOT ${WORKDIR}/android-ndk-r${ANDROID_NDK_REVISION} -ENV PREFIX /opt/android/prefix - -ENV TOOLCHAIN_DIR ${WORKDIR}/toolchain-arm -RUN ${ANDROID_NDK_ROOT}/build/tools/make_standalone_toolchain.py \ - --arch arm64 \ - --api 21 \ - --install-dir ${TOOLCHAIN_DIR} \ - --stl=libc++ - -#INSTALL cmake -ENV CMAKE_VERSION 3.12.1 -RUN cd /usr \ - && curl -s -O https://cmake.org/files/v3.12/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz \ - && tar -xzf /usr/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz \ - && rm -f /usr/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz -ENV PATH /usr/cmake-${CMAKE_VERSION}-Linux-x86_64/bin:$PATH - -## Boost -ARG BOOST_VERSION=1_68_0 -ARG BOOST_VERSION_DOT=1.68.0 -ARG BOOST_HASH=7f6130bc3cf65f56a618888ce9d5ea704fa10b462be126ad053e80e553d6d8b7 -RUN set -ex \ - && curl -s -L -o boost_${BOOST_VERSION}.tar.bz2 https://downloads.sourceforge.net/project/boost/boost/${BOOST_VERSION_DOT}/boost_${BOOST_VERSION}.tar.bz2 \ - && echo "${BOOST_HASH} boost_${BOOST_VERSION}.tar.bz2" | sha256sum -c \ - && tar -xvf boost_${BOOST_VERSION}.tar.bz2 \ - && rm -f boost_${BOOST_VERSION}.tar.bz2 \ - && cd boost_${BOOST_VERSION} \ - && ./bootstrap.sh --prefix=${PREFIX} - -ENV HOST_PATH $PATH -ENV PATH $TOOLCHAIN_DIR/aarch64-linux-android/bin:$TOOLCHAIN_DIR/bin:$PATH - -ARG NPROC=1 - -# Build iconv for lib boost locale -ENV ICONV_VERSION 1.15 -ENV ICONV_HASH ccf536620a45458d26ba83887a983b96827001e92a13847b45e4925cc8913178 -RUN curl -s -O http://ftp.gnu.org/pub/gnu/libiconv/libiconv-${ICONV_VERSION}.tar.gz \ - && echo "${ICONV_HASH} libiconv-${ICONV_VERSION}.tar.gz" | sha256sum -c \ - && tar -xzf libiconv-${ICONV_VERSION}.tar.gz \ - && rm -f libiconv-${ICONV_VERSION}.tar.gz \ - && cd libiconv-${ICONV_VERSION} \ - && CC=aarch64-linux-android-clang CXX=aarch64-linux-android-clang++ ./configure --build=x86_64-linux-gnu --host=arm-eabi --prefix=${PREFIX} --disable-rpath \ - && make -j${NPROC} && make install - -## Build BOOST -RUN cd boost_${BOOST_VERSION} \ - && ./b2 --build-type=minimal link=static runtime-link=static --with-chrono --with-date_time --with-filesystem --with-program_options --with-regex --with-serialization --with-system --with-thread --with-locale --build-dir=android --stagedir=android toolset=clang threading=multi threadapi=pthread target-os=android -sICONV_PATH=${PREFIX} install -j${NPROC} - -#Note : we build openssl because the default lacks DSA1 - -# download, configure and make Zlib -ENV ZLIB_VERSION 1.2.11 -ENV ZLIB_HASH c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1 -RUN curl -s -O https://zlib.net/zlib-${ZLIB_VERSION}.tar.gz \ - && echo "${ZLIB_HASH} zlib-${ZLIB_VERSION}.tar.gz" | sha256sum -c \ - && tar -xzf zlib-${ZLIB_VERSION}.tar.gz \ - && rm zlib-${ZLIB_VERSION}.tar.gz \ - && mv zlib-${ZLIB_VERSION} zlib \ - && cd zlib && CC=clang CXX=clang++ ./configure --static \ - && make -j${NPROC} - -# open ssl -ARG OPENSSL_VERSION=1.0.2p -ARG OPENSSL_HASH=50a98e07b1a89eb8f6a99477f262df71c6fa7bef77df4dc83025a2845c827d00 -RUN curl -s -O https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz \ - && echo "${OPENSSL_HASH} openssl-${OPENSSL_VERSION}.tar.gz" | sha256sum -c \ - && tar -xzf openssl-${OPENSSL_VERSION}.tar.gz \ - && rm openssl-${OPENSSL_VERSION}.tar.gz \ - && cd openssl-${OPENSSL_VERSION} \ - && sed -i -e "s/mandroid/target\ aarch64\-linux\-android/" Configure \ - && CC=clang CXX=clang++ \ - ./Configure android \ - no-asm \ - no-shared --static \ - --with-zlib-include=${WORKDIR}/zlib/include --with-zlib-lib=${WORKDIR}/zlib/lib \ - --prefix=${PREFIX} --openssldir=${PREFIX} \ - && make -j${NPROC} \ - && make install - -# ZMQ -ARG ZMQ_VERSION=master -ARG ZMQ_HASH=501d0815bf2b0abb93be8214fc66519918ef6c40 -RUN git clone https://github.com/zeromq/libzmq.git -b ${ZMQ_VERSION} \ - && cd libzmq \ - && git checkout ${ZMQ_HASH} \ - && ./autogen.sh \ - && CC=clang CXX=clang++ ./configure --prefix=${PREFIX} --host=aarch64-linux-android --enable-static --disable-shared \ - && make -j${NPROC} \ - && make install - -# Sodium -ARG SODIUM_VERSION=1.0.16 -ARG SODIUM_HASH=675149b9b8b66ff44152553fb3ebf9858128363d -RUN set -ex \ - && git clone https://github.com/jedisct1/libsodium.git -b ${SODIUM_VERSION} \ - && cd libsodium \ - && test `git rev-parse HEAD` = ${SODIUM_HASH} || exit 1 \ - && ./autogen.sh \ - && CC=clang CXX=clang++ ./configure --prefix=${PREFIX} --host=aarch64-linux-android --enable-static --disable-shared \ - && make -j${NPROC} \ - && make install - -ADD . /src -RUN cd /src \ - && CMAKE_INCLUDE_PATH="${PREFIX}/include" \ - CMAKE_LIBRARY_PATH="${PREFIX}/lib" \ - ANDROID_STANDALONE_TOOLCHAIN_PATH=${TOOLCHAIN_DIR} \ - USE_SINGLE_BUILDDIR=1 \ - PATH=${HOST_PATH} make release-static-android-armv8 -j${NPROC} |