diff options
31 files changed, 822 insertions, 351 deletions
diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..c87dceac9 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,63 @@ +sudo: required +dist: trusty +os: linux +language: minimal +cache: + directories: + - contrib/depends/built + - contrib/depends/sdk-sources + - $HOME/.ccache +env: + global: + - MAKEJOBS=-j3 + - RUN_TESTS=false + - BOOST_TEST_RANDOM=1$TRAVIS_BUILD_ID + - CCACHE_SIZE=100M + - CCACHE_TEMPDIR=/tmp/.ccache-temp + - CCACHE_COMPRESS=1 + - CCACHE_DIR=$HOME/.ccache + - BASE_OUTDIR=$TRAVIS_BUILD_DIR/out + - SDK_URL=https://bitcoincore.org/depends-sources/sdks + - PYTHON_DEBUG=1 + - WINEDEBUG=fixme-all + - DOCKER_PACKAGES="build-essential libtool cmake autotools-dev automake pkg-config bsdmainutils curl git ca-certificates ccache" + matrix: +# ARM v7 + - HOST=arm-linux-gnueabihf PACKAGES="g++-arm-linux-gnueabihf" +# ARM v8 + - HOST=aarch64-linux-gnu PACKAGES="g++-aarch64-linux-gnu" +# i686 Linux + - HOST=i686-pc-linux-gnu PACKAGES="cmake g++-multilib bc python3-zmq" RUN_TESTS=true +# Win64 + - HOST=x86_64-w64-mingw32 PACKAGES="cmake python3 nsis g++-mingw-w64-x86-64 wine-binfmt wine64 bc" RUN_TESTS=true +# x86_64 Linux + - HOST=x86_64-unknown-linux-gnu PACKAGES="cmake python3-zmq protobuf-compiler libdbus-1-dev libharfbuzz-dev libprotobuf-dev" RUN_TESTS=true +# Cross-Mac + - HOST=x86_64-apple-darwin11 PACKAGES="cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev python3-setuptools-git" OSX_SDK=10.11 + +before_install: + - export PATH=$(echo $PATH | tr ':' "\n" | sed '/\/opt\/python/d' | tr "\n" ":" | sed "s|::|:|g") +install: + - env | grep -E '^(CCACHE_|WINEDEBUG|DISPLAY|BOOST_TEST_RANDOM|CONFIG_SHELL)' | tee /tmp/env + - if [[ $HOST = *-mingw32 ]]; then DOCKER_ADMIN="--cap-add SYS_ADMIN"; fi + - DOCKER_ID=$(docker run $DOCKER_ADMIN -idt --mount type=bind,src=$TRAVIS_BUILD_DIR,dst=$TRAVIS_BUILD_DIR --mount type=bind,src=$CCACHE_DIR,dst=$CCACHE_DIR -w $TRAVIS_BUILD_DIR --env-file /tmp/env ubuntu:18.04) + - DOCKER_EXEC="docker exec $DOCKER_ID" + - if [ -n "$DPKG_ADD_ARCH" ]; then $DOCKER_EXEC dpkg --add-architecture "$DPKG_ADD_ARCH" ; fi + - travis_retry $DOCKER_EXEC apt-get update + - travis_retry $DOCKER_EXEC apt-get install --no-install-recommends --no-upgrade -qq $PACKAGES $DOCKER_PACKAGES +before_script: + - mkdir -p contrib/depends/SDKs contrib/depends/sdk-sources + - if [ -n "$OSX_SDK" -a ! -f contrib/depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz ]; then curl --location --fail $SDK_URL/MacOSX${OSX_SDK}.sdk.tar.gz -o contrib/depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz; fi + - if [ -n "$OSX_SDK" -a -f contrib/depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz ]; then tar -C contrib/depends/SDKs -xf contrib/depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz; fi + - if [[ $HOST = *-mingw32 ]]; then $DOCKER_EXEC bash -c "update-alternatives --set $HOST-g++ \$(which $HOST-g++-posix)"; fi + - if [ -z "$NO_DEPENDS" ]; then $DOCKER_EXEC bash -c "CONFIG_SHELL= make $MAKEJOBS -C contrib/depends HOST=$HOST $DEP_OPTS"; fi +script: + - git submodule init && git submodule update + - export TRAVIS_COMMIT_LOG=`git log --format=fuller -1` + - OUTDIR=$BASE_OUTDIR/$TRAVIS_PULL_REQUEST/$TRAVIS_JOB_NUMBER-$HOST + - if [ -z "$NO_DEPENDS" ]; then $DOCKER_EXEC ccache --max-size=$CCACHE_SIZE; fi + - $DOCKER_EXEC bash -c "mkdir build && cd build && cmake -DCMAKE_TOOLCHAIN_FILE=$TRAVIS_BUILD_DIR/contrib/depends/$HOST/share/toolchain.cmake .. && make $MAKEJOBS" + - export LD_LIBRARY_PATH=$TRAVIS_BUILD_DIR/contrib/depends/$HOST/lib +after_script: + - echo $TRAVIS_COMMIT_RANGE + - echo $TRAVIS_COMMIT_LOG diff --git a/CMakeLists.txt b/CMakeLists.txt index a95e14b65..994d47691 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -435,7 +435,7 @@ if(STATIC AND NOT IOS) endif() endif() -find_package(PCSC) +find_package(HIDAPI) add_definition_if_library_exists(c memset_s "string.h" HAVE_MEMSET_S) add_definition_if_library_exists(c explicit_bzero "strings.h" HAVE_EXPLICIT_BZERO) @@ -476,14 +476,14 @@ endif() include_directories(${LIBUNWIND_INCLUDE}) link_directories(${LIBUNWIND_LIBRARY_DIRS}) -# Final setup for libpcsc -if (PCSC_FOUND) - message(STATUS "Using PCSC include dir at ${PCSC_INCLUDE_DIR}") - add_definitions(-DHAVE_PCSC) - include_directories(${PCSC_INCLUDE_DIR}) - link_directories(${LIBPCSC_LIBRARY_DIRS}) -else (PCSC_FOUND) - message(STATUS "Could not find PCSC") +# Final setup for hid +if (HIDAPI_FOUND) + message(STATUS "Using HIDAPI include dir at ${HIDAPI_INCLUDE_DIR}") + add_definitions(-DHAVE_HIDAPI) + include_directories(${HIDAPI_INCLUDE_DIR}) + link_directories(${LIBHIDAPI_LIBRARY_DIRS}) +else (HIDAPI_FOUND) + message(STATUS "Could not find HIDAPI") endif() if(MSVC) @@ -874,13 +874,25 @@ elseif(DRAGONFLY) set(EXTRA_LIBRARIES execinfo ${COMPAT}) elseif(CMAKE_SYSTEM_NAME MATCHES "(SunOS|Solaris)") set(EXTRA_LIBRARIES socket nsl resolv) -elseif(NOT MSVC) +elseif(NOT MSVC AND NOT DEPENDS) find_library(RT rt) set(EXTRA_LIBRARIES ${RT}) endif() list(APPEND EXTRA_LIBRARIES ${CMAKE_DL_LIBS}) +if (HIDAPI_FOUND) + if (APPLE) + find_library(COREFOUNDATION CoreFoundation) + find_library(IOKIT IOKit) + list(APPEND EXTRA_LIBRARIES ${IOKIT}) + list(APPEND EXTRA_LIBRARIES ${COREFOUNDATION}) + endif() + if (WIN32) + list(APPEND EXTRA_LIBRARIES setupapi) + endif() +endif() + option(USE_READLINE "Build with GNU readline support." ON) if(USE_READLINE) find_package(Readline) diff --git a/Dockerfile b/Dockerfile index c518b5d03..40ba81d9c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -112,6 +112,7 @@ RUN set -ex \ WORKDIR /src COPY . . +ENV USE_SINGLE_BUILDDIR=1 ARG NPROC RUN set -ex && \ rm -rf build && \ @@ -128,7 +129,7 @@ RUN set -ex && \ apt-get --no-install-recommends --yes install ca-certificates && \ apt-get clean && \ rm -rf /var/lib/apt -COPY --from=builder /src/build/Linux/master/release/* /usr/local/bin/ +COPY --from=builder /src/build/release/bin /usr/local/bin/ # Contains the blockchain VOLUME /root/.bitmonero @@ -118,52 +118,6 @@ X's indicate that these details have not been determined as of commit date. Approximately three months prior to a scheduled software upgrade, a branch from Master will be created with the new release version tag. Pull requests that address bugs should then be made to both Master and the new release branch. Pull requests that require extensive review and testing (generally, optimizations and new features) should *not* be made to the release branch. -<<<<<<< HEAD -======= -## Installing Monero from a package - -Packages are available for - -* Ubuntu and [snap supported](https://snapcraft.io/docs/core/install) systems, via a community contributed build. - - snap install monero --beta - -Installing a snap is very quick. Snaps are secure. They are isolated with all of their dependencies. Snaps also auto update when a new version is released. - -* Arch Linux (via [AUR](https://aur.archlinux.org/)): - - Stable release: [`monero`](https://aur.archlinux.org/packages/monero) - - Bleeding edge: [`monero-git`](https://aur.archlinux.org/packages/monero-git) - -* Void Linux: - - xbps-install -S monero - -* GuixSD - - guix package -i monero - -* OS X via [Homebrew](http://brew.sh) - - brew tap sammy007/cryptonight - brew install monero --build-from-source - -* Docker - - # Build using all available cores - docker build -t monero . - - # or build using a specific number of cores (reduce RAM requirement) - docker build --build-arg NPROC=1 -t monero . - - # either run in foreground - docker run -it -v /monero/chain:/root/.bitmonero -v /monero/wallet:/wallet -p 18080:18080 monero - - # or in background - docker run -it -d -v /monero/chain:/root/.bitmonero -v /monero/wallet:/wallet -p 18080:18080 monero - -Packaging for your favorite distribution would be a welcome contribution! - ->>>>>>> f6d62ab... Formating commands inside README.md ## Compiling Monero from source ### Dependencies diff --git a/cmake/FindHIDAPI.cmake b/cmake/FindHIDAPI.cmake new file mode 100644 index 000000000..a689fb4eb --- /dev/null +++ b/cmake/FindHIDAPI.cmake @@ -0,0 +1,46 @@ +# - try to find HIDAPI library +# from http://www.signal11.us/oss/hidapi/ +# +# Cache Variables: (probably not for direct use in your scripts) +# HIDAPI_INCLUDE_DIR +# HIDAPI_LIBRARY +# +# Non-cache variables you might use in your CMakeLists.txt: +# HIDAPI_FOUND +# HIDAPI_INCLUDE_DIRS +# HIDAPI_LIBRARIES +# +# Requires these CMake modules: +# FindPackageHandleStandardArgs (known included with CMake >=2.6.2) +# +# Original Author: +# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net> +# http://academic.cleardefinition.com +# Iowa State University HCI Graduate Program/VRAC +# +# Copyright Iowa State University 2009-2010. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +find_library(HIDAPI_LIBRARY + NAMES hidapi hidapi-libusb) + +find_path(HIDAPI_INCLUDE_DIR + NAMES hidapi.h + PATH_SUFFIXES + hidapi) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(HIDAPI + DEFAULT_MSG + HIDAPI_LIBRARY + HIDAPI_INCLUDE_DIR) + +if(HIDAPI_FOUND) + set(HIDAPI_LIBRARIES "${HIDAPI_LIBRARY}") + + set(HIDAPI_INCLUDE_DIRS "${HIDAPI_INCLUDE_DIR}") +endif() + +mark_as_advanced(HIDAPI_INCLUDE_DIR HIDAPI_LIBRARY) diff --git a/cmake/FindPCSC.cmake b/cmake/FindPCSC.cmake deleted file mode 100644 index 081919655..000000000 --- a/cmake/FindPCSC.cmake +++ /dev/null @@ -1,54 +0,0 @@ -# - Find PCSC -# Find the native PCSC includes and library -# -# PCSC_INCLUDE_DIR - where to find winscard.h, wintypes.h, etc. -# PCSC_LIBRARIES - List of libraries when using PCSC. -# PCSC_FOUND - True if PCSC found. - - -IF (PCSC_INCLUDE_DIR AND PCSC_LIBRARIES) - # Already in cache, be silent - SET(PCSC_FIND_QUIETLY TRUE) -ENDIF (PCSC_INCLUDE_DIR AND PCSC_LIBRARIES) - -IF (NOT WIN32) - FIND_PACKAGE(PkgConfig) - PKG_CHECK_MODULES(PC_PCSC libpcsclite) - - FIND_PATH(PCSC_INCLUDE_DIR winscard.h - HINTS - /usr/include/PCSC - ${PC_PCSC_INCLUDEDIR} - ${PC_PCSC_INCLUDE_DIRS} - PATH_SUFFIXES PCSC - ) - - FIND_LIBRARY(PCSC_LIBRARY NAMES pcsclite libpcsclite PCSC - HINTS - ${PC_PCSC_LIBDIR} - ${PC_PCSC_LIBRARY_DIRS} - ) - -ELSE (NOT WIN32) - IF(BUILD_64 STREQUAL "ON") - set(PCSC_INCLUDE_DIR /mingw64/x86_64-w64-mingw32/include) - set(PCSC_LIBRARY /mingw64/x86_64-w64-mingw32/lib/libwinscard.a) - ELSE(BUILD_64 STREQUAL "ON") - set(PCSC_INCLUDE_DIR /mingw32/i686-w64-mingw32/include) - set(PCSC_LIBRARY /mingw32/i686-w64-mingw32/lib/libwinscard.a) - ENDIF(BUILD_64 STREQUAL "ON") -ENDIF (NOT WIN32) - -# handle the QUIETLY and REQUIRED arguments and set PCSC_FOUND to TRUE if -# all listed variables are TRUE -INCLUDE(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCSC DEFAULT_MSG PCSC_LIBRARY PCSC_INCLUDE_DIR) - -IF(PCSC_FOUND) - SET( PCSC_LIBRARIES ${PCSC_LIBRARY} ) - SET(PCSC_STATIC_LIBRARIES ${PCSC_STATIC_LIBRARY}) -ELSE(PCSC_FOUND) - SET( PCSC_LIBRARIES ) -ENDIF(PCSC_FOUND) - -MARK_AS_ADVANCED( PCSC_LIBRARY PCSC_INCLUDE_DIR PCSC_STATIC_LIBRARY) diff --git a/contrib/depends/hosts/darwin.mk b/contrib/depends/hosts/darwin.mk index 4e58bec74..6f8f2ffe2 100644 --- a/contrib/depends/hosts/darwin.mk +++ b/contrib/depends/hosts/darwin.mk @@ -2,13 +2,13 @@ OSX_MIN_VERSION=10.8 OSX_SDK_VERSION=10.11 OSX_SDK=$(SDK_PATH)/MacOSX$(OSX_SDK_VERSION).sdk LD64_VERSION=253.9 -darwin_CC=clang -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(OSX_SDK) -mlinker-version=$(LD64_VERSION) -darwin_CXX=clang++ -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(OSX_SDK) -mlinker-version=$(LD64_VERSION) -stdlib=libc++ +darwin_CC=clang -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(OSX_SDK) -mlinker-version=$(LD64_VERSION) -B $(host_prefix)/native/bin +darwin_CXX=clang++ -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(OSX_SDK) -mlinker-version=$(LD64_VERSION) -stdlib=libc++ -B $(host_prefix)/native/bin darwin_CFLAGS=-pipe darwin_CXXFLAGS=$(darwin_CFLAGS) -darwin_release_CFLAGS=-O2 +darwin_release_CFLAGS=-O1 darwin_release_CXXFLAGS=$(darwin_release_CFLAGS) darwin_debug_CFLAGS=-O1 diff --git a/contrib/depends/packages/packages.mk b/contrib/depends/packages/packages.mk index 28eaf34c5..114f8e9c0 100644 --- a/contrib/depends/packages/packages.mk +++ b/contrib/depends/packages/packages.mk @@ -1,16 +1,19 @@ -packages:=boost openssl libevent zeromq cppzmq zlib expat ldns cppzmq readline libiconv qt sodium +packages:=boost openssl libevent zeromq cppzmq zlib expat ldns cppzmq readline libiconv qt native_packages := native_ccache wallet_packages=bdb darwin_native_packages = native_biplist native_ds_store native_mac_alias +darwin_packages += sodium-darwin ifeq ($(host_os),linux) packages += pcsc-lite packages += unwind +packages += sodium endif ifeq ($(host_os),mingw32) packages += icu4c +packages += sodium endif ifneq ($(build_os),darwin) @@ -18,4 +21,3 @@ darwin_native_packages += native_cctools native_cdrkit native_libdmg-hfsplus packages += readline endif - diff --git a/contrib/depends/packages/sodium-darwin.mk b/contrib/depends/packages/sodium-darwin.mk new file mode 100644 index 000000000..796bead16 --- /dev/null +++ b/contrib/depends/packages/sodium-darwin.mk @@ -0,0 +1,24 @@ +package=sodium-darwin +$(package)_version=1.0.15 +$(package)_download_path=https://download.libsodium.org/libsodium/releases/ +$(package)_file_name=libsodium-$($(package)_version).tar.gz +$(package)_sha256_hash=fb6a9e879a2f674592e4328c5d9f79f082405ee4bb05cb6e679b90afe9e178f4 + +define $(package)_set_vars +$(package)_config_opts=--enable-static +$(package)_config_opts+=--prefix=$(host_prefix) +endef + +define $(package)_config_cmds + ./autogen.sh &&\ + $($(package)_autoconf) $($(package)_config_opts) RANLIB="$(host_prefix)/native/bin/x86_64-apple-darwin11-ranlib" AR="$(host_prefix)/native/bin/x86_64-apple-darwin11-ar" +endef + +define $(package)_build_cmds + echo "path is problematic here" &&\ + make +endef + +define $(package)_stage_cmds + $(MAKE) DESTDIR=$($(package)_staging_dir) install +endef diff --git a/contrib/depends/packages/sodium.mk b/contrib/depends/packages/sodium.mk index 885b1ea19..0e6668062 100644 --- a/contrib/depends/packages/sodium.mk +++ b/contrib/depends/packages/sodium.mk @@ -1,8 +1,8 @@ package=sodium -$(package)_version=1.0.16 -$(package)_download_path=https://github.com/jedisct1/libsodium/archive -$(package)_file_name=$($(package)_version).tar.gz -$(package)_sha256_hash=0c14604bbeab2e82a803215d65c3b6e74bb28291aaee6236d65c699ccfe1a98c +$(package)_version=1.0.15 +$(package)_download_path=https://download.libsodium.org/libsodium/releases/ +$(package)_file_name=libsodium-$($(package)_version).tar.gz +$(package)_sha256_hash=fb6a9e879a2f674592e4328c5d9f79f082405ee4bb05cb6e679b90afe9e178f4 define $(package)_set_vars $(package)_config_opts=--enable-static diff --git a/contrib/depends/toolchain.cmake.in b/contrib/depends/toolchain.cmake.in index b594ddd62..375533557 100644 --- a/contrib/depends/toolchain.cmake.in +++ b/contrib/depends/toolchain.cmake.in @@ -26,9 +26,9 @@ SET(BOOST_IGNORE_SYSTEM_PATH ON) SET(BOOST_ROOT @prefix@) SET(BOOST_LIBRARYDIR @prefix@/lib) SET(BOOST_IGNORE_SYSTEM_PATHS_DEFAULT OFF) -SET(Boost_NO_SYSTEM_PATHS TRUE) -SET(Boost_USE_STATIC_LIBS TRUE) -SET(Boost_USE_STATIC_RUNTIME TRUE) +SET(BOOST_NO_SYSTEM_PATHS TRUE) +SET(BOOST_USE_STATIC_LIBS TRUE) +SET(BOOST_USE_STATIC_RUNTIME TRUE) SET(OpenSSL_DIR @prefix@/lib) SET(ARCHITECTURE @arch@) diff --git a/src/crypto/slow-hash.c b/src/crypto/slow-hash.c index 914ba6dc0..80bf4e06f 100644 --- a/src/crypto/slow-hash.c +++ b/src/crypto/slow-hash.c @@ -198,6 +198,22 @@ extern int aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *exp } while (0) #endif +#define VARIANT2_2_PORTABLE() \ + if (variant >= 2) { \ + xor_blocks(long_state + (j ^ 0x10), d); \ + xor_blocks(d, long_state + (j ^ 0x20)); \ + } + +#define VARIANT2_2() \ + do if (variant >= 2) \ + { \ + *U64(hp_state + (j ^ 0x10)) ^= hi; \ + *(U64(hp_state + (j ^ 0x10)) + 1) ^= lo; \ + hi ^= *U64(hp_state + (j ^ 0x20)); \ + lo ^= *(U64(hp_state + (j ^ 0x20)) + 1); \ + } while (0) + + #if !defined NO_AES && (defined(__x86_64__) || (defined(_MSC_VER) && defined(_WIN64))) // Optimised code below, uses x86-specific intrinsics, SSE2, AES-NI // Fall back to more portable code is down at the bottom @@ -282,6 +298,7 @@ extern int aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *exp b[0] = p[0]; b[1] = p[1]; \ VARIANT2_INTEGER_MATH_SSE2(b, c); \ __mul(); \ + VARIANT2_2(); \ VARIANT2_SHUFFLE_ADD_SSE2(hp_state, j); \ a[0] += hi; a[1] += lo; \ p = U64(&hp_state[j]); \ @@ -884,6 +901,7 @@ union cn_slow_hash_state b[0] = p[0]; b[1] = p[1]; \ VARIANT2_PORTABLE_INTEGER_MATH(b, c); \ __mul(); \ + VARIANT2_2(); \ VARIANT2_SHUFFLE_ADD_NEON(hp_state, j); \ a[0] += hi; a[1] += lo; \ p = U64(&hp_state[j]); \ @@ -1305,6 +1323,7 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int VARIANT2_PORTABLE_INTEGER_MATH(c, c1); mul(c1, c, d); + VARIANT2_2_PORTABLE(); VARIANT2_PORTABLE_SHUFFLE_ADD(long_state, j); sum_half_blocks(a, d); swap_blocks(a, c); @@ -1486,6 +1505,7 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int copy_block(c2, &long_state[j]); VARIANT2_PORTABLE_INTEGER_MATH(c2, c1); mul(c1, c2, d); + VARIANT2_2_PORTABLE(); VARIANT2_PORTABLE_SHUFFLE_ADD(long_state, j); swap_blocks(a, c1); sum_half_blocks(c1, d); diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 0dc3f3bb4..6f1d26c5a 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -158,6 +158,8 @@ static const struct { { 5, 35000, 0, 1521360000 }, { 6, 36000, 0, 1521480000 }, { 7, 37000, 0, 1521600000 }, + { 8, 176456, 0, 1537821770 }, + { 9, 177176, 0, 1537821771 }, }; //------------------------------------------------------------------ diff --git a/src/device/CMakeLists.txt b/src/device/CMakeLists.txt index cc2d20a54..8f446f42a 100644 --- a/src/device/CMakeLists.txt +++ b/src/device/CMakeLists.txt @@ -32,18 +32,27 @@ set(device_sources log.cpp ) -if(PCSC_FOUND) - set(device_sources ${device_sources} device_ledger.cpp) +if(HIDAPI_FOUND) + set(device_sources + ${device_sources} + device_ledger.cpp + device_io_hid.cpp + ) endif() set(device_headers device.hpp + device_io.hpp device_default.hpp log.hpp ) -if(PCSC_FOUND) - set(device_headers ${device_headers} device_ledger.hpp) +if(HIDAPI_FOUND) + set(device_headers + ${device_headers} + device_ledger.hpp + device_io_hid.hpp + ) endif() set(device_private_headers) @@ -65,7 +74,7 @@ monero_add_library(device target_link_libraries(device PUBLIC - ${PCSC_LIBRARIES} + ${HIDAPI_LIBRARIES} cncrypto ringct_basic ${OPENSSL_CRYPTO_LIBRARIES} diff --git a/src/device/device.cpp b/src/device/device.cpp index 8a8b40061..50041baef 100644 --- a/src/device/device.cpp +++ b/src/device/device.cpp @@ -29,7 +29,7 @@ #include "device.hpp" #include "device_default.hpp" -#ifdef HAVE_PCSC +#ifdef WITH_DEVICE_LEDGER #include "device_ledger.hpp" #endif #include "misc_log_ex.h" @@ -45,7 +45,7 @@ namespace hw { device_registry::device_registry(){ hw::core::register_all(registry); - #ifdef HAVE_PCSC + #ifdef WITH_DEVICE_LEDGER hw::ledger::register_all(registry); #endif } diff --git a/src/device/device.hpp b/src/device/device.hpp index 87f1430f4..cb9117650 100644 --- a/src/device/device.hpp +++ b/src/device/device.hpp @@ -48,11 +48,12 @@ #include "crypto/chacha.h" #include "ringct/rctTypes.h" + #ifndef USE_DEVICE_LEDGER #define USE_DEVICE_LEDGER 1 #endif -#if !defined(HAVE_PCSC) +#if !defined(HAVE_HIDAPI) #undef USE_DEVICE_LEDGER #define USE_DEVICE_LEDGER 0 #endif diff --git a/src/device/device_io.hpp b/src/device/device_io.hpp new file mode 100644 index 000000000..96163a211 --- /dev/null +++ b/src/device/device_io.hpp @@ -0,0 +1,56 @@ +// Copyright (c) 2017-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + + + + +#pragma once + + +namespace hw { + namespace io { + + class device_io { + + public: + + device_io() {}; + ~device_io() {}; + + virtual void init() = 0; + virtual void release() = 0; + + virtual void connect(void *parms) = 0; + virtual void disconnect() = 0; + virtual bool connected() const = 0; + + virtual int exchange(unsigned char *command, unsigned int cmd_len, unsigned char *response, unsigned int max_resp_len) = 0; + }; + }; +}; diff --git a/src/device/device_io_hid.cpp b/src/device/device_io_hid.cpp new file mode 100644 index 000000000..562aca8b8 --- /dev/null +++ b/src/device/device_io_hid.cpp @@ -0,0 +1,288 @@ +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +#if defined(HAVE_HIDAPI) + +#include "log.hpp" +#include "device_io_hid.hpp" + +namespace hw { + namespace io { + + #undef MONERO_DEFAULT_LOG_CATEGORY + #define MONERO_DEFAULT_LOG_CATEGORY "device.io" + + #define ASSERT_X(exp,msg) CHECK_AND_ASSERT_THROW_MES(exp, msg); + + #define MAX_BLOCK 64 + + static std::string safe_hid_error(hid_device *hwdev) { + if (hwdev) { + return std::string((char*)hid_error(hwdev)); + } + return std::string("NULL device"); + } + + static std::string safe_hid_path(const hid_device_info *hwdev_info) { + if (hwdev_info && hwdev_info->path) { + return std::string(hwdev_info->path); + } + return std::string("NULL path"); + } + + device_io_hid::device_io_hid(unsigned short c, unsigned char t, unsigned int ps, unsigned int to) : + channel(c), + tag(t), + packet_size(ps), + timeout(to), + usb_vid(0), + usb_pid(0), + usb_device(NULL) { + } + + device_io_hid::device_io_hid() : device_io_hid(DEFAULT_CHANNEL, DEFAULT_TAG, DEFAULT_PACKET_SIZE, DEFAULT_TIMEOUT) { + } + + void device_io_hid::io_hid_log(int read, unsigned char* buffer, int block_len) { + if (hid_verbose) { + char strbuffer[1024]; + hw::buffer_to_str(strbuffer, sizeof(strbuffer), (char*)buffer, block_len); + MDEBUG( "HID " << (read?"<":">") <<" : "<<strbuffer); + } + } + + void device_io_hid::init() { + int r; + r = hid_init(); + ASSERT_X(r>=0, "Unable to init hidapi library. Error "+std::to_string(r)+": "+safe_hid_error(this->usb_device)); + } + + void device_io_hid::connect(void *params) { + hid_conn_params *p = (struct hid_conn_params*)params; + this->connect(p->vid, p->pid, p->interface_number, p->usage_page, p->interface_OR_page); + } + + void device_io_hid::connect(unsigned int vid, unsigned int pid, unsigned int interface_number, unsigned int usage_page, bool interface_OR_page ) { + hid_device_info *hwdev_info, *hwdev_info_list; + hid_device *hwdev; + + this->disconnect(); + + hwdev_info_list = hid_enumerate(vid, pid); + ASSERT_X(hwdev_info_list, "Unable to enumerate device "+std::to_string(vid)+":"+std::to_string(vid)+ ": "+ safe_hid_error(this->usb_device)); + hwdev = NULL; + hwdev_info = hwdev_info_list; + while (hwdev_info) { + if ((interface_OR_page && ((usage_page == 0xffa0) || (interface_number == 0))) || + ((usage_page == 0xffa0) && (interface_number == 0)) ) { + MDEBUG("HID Device found: " << safe_hid_path(hwdev_info)); + hwdev = hid_open_path(hwdev_info->path); + break; + } else { + MDEBUG("HID Device discard: " << safe_hid_path(hwdev_info) << "("+std::to_string(hwdev_info->usage_page) << "," << std::to_string(hwdev_info->interface_number) << ")"); + } + hwdev_info = hwdev_info->next; + } + hid_free_enumeration(hwdev_info_list); + ASSERT_X(hwdev, "Unable to open device "+std::to_string(pid)+":"+std::to_string(vid)); + this->usb_vid = vid; + this->usb_pid = pid; + this->usb_device = hwdev; + } + + + bool device_io_hid::connected() const { + return this->usb_device != NULL; + } + + int device_io_hid::exchange(unsigned char *command, unsigned int cmd_len, unsigned char *response, unsigned int max_resp_len) { + unsigned char buffer[400]; + unsigned char padding_buffer[MAX_BLOCK+1]; + unsigned int result; + int hid_ret; + unsigned int sw_offset; + unsigned int remaining; + unsigned int offset = 0; + + ASSERT_X(this->usb_device,"No device opened"); + + //Split command in several HID packet + memset(buffer, 0, sizeof(buffer)); + result = this->wrapCommand(command, cmd_len, buffer, sizeof(buffer)); + remaining = result; + + while (remaining > 0) { + int block_size = (remaining > MAX_BLOCK ? MAX_BLOCK : remaining); + memset(padding_buffer, 0, sizeof(padding_buffer)); + memcpy(padding_buffer+1, buffer + offset, block_size); + io_hid_log(0, padding_buffer, block_size+1); + hid_ret = hid_write(this->usb_device, padding_buffer, block_size+1); + ASSERT_X(hid_ret>=0, "Unable to send hidapi command. Error "+std::to_string(result)+": "+ safe_hid_error(this->usb_device)); + offset += block_size; + remaining -= block_size; + } + + //get first response + memset(buffer, 0, sizeof(buffer)); + hid_ret = hid_read_timeout(this->usb_device, buffer, MAX_BLOCK, this->timeout); + ASSERT_X(hid_ret>=0, "Unable to read hidapi response. Error "+std::to_string(result)+": "+ safe_hid_error(this->usb_device)); + result = (unsigned int)hid_ret; + io_hid_log(1, buffer, result); + offset = MAX_BLOCK; + //parse first response and get others if any + for (;;) { + result = this->unwrapReponse(buffer, offset, response, max_resp_len); + if (result != 0) { + break; + } + hid_ret = hid_read_timeout(this->usb_device, buffer + offset, MAX_BLOCK, this->timeout); + ASSERT_X(hid_ret>=0, "Unable to receive hidapi response. Error "+std::to_string(result)+": "+ safe_hid_error(this->usb_device)); + result = (unsigned int)hid_ret; + io_hid_log(1, buffer + offset, result); + offset += MAX_BLOCK; + } + return result; + } + + void device_io_hid::disconnect(void) { + if (this->usb_device) { + hid_close(this->usb_device); + } + this->usb_vid = 0; + this->usb_pid = 0; + this->usb_device = NULL; + } + + void device_io_hid::release() { + /* Do not exit, as the lib context is global*/ + //hid_exit(); + } + + unsigned int device_io_hid::wrapCommand(const unsigned char *command, size_t command_len, unsigned char *out, size_t out_len) { + unsigned int sequence_idx = 0; + unsigned int offset = 0; + unsigned int offset_out = 0; + unsigned int block_size; + + ASSERT_X(this->packet_size >= 3, "Invalid Packet size: "+std::to_string(this->packet_size)) ; + ASSERT_X(out_len >= 7, "out_len too short: "+std::to_string(out_len)); + + out_len -= 7; + out[offset_out++] = ((this->channel >> 8) & 0xff); + out[offset_out++] = (this->channel & 0xff); + out[offset_out++] = this->tag; + out[offset_out++] = ((sequence_idx >> 8) & 0xff); + out[offset_out++] = (sequence_idx & 0xff); + sequence_idx++; + out[offset_out++] = ((command_len >> 8) & 0xff); + out[offset_out++] = (command_len & 0xff); + block_size = (command_len > this->packet_size - 7 ? this->packet_size - 7 : command_len); + ASSERT_X(out_len >= block_size, "out_len too short: "+std::to_string(out_len)); + out_len -= block_size; + memcpy(out + offset_out, command + offset, block_size); + offset_out += block_size; + offset += block_size; + while (offset != command_len) { + ASSERT_X(out_len >= 5, "out_len too short: "+std::to_string(out_len)); + out_len -= 5; + out[offset_out++] = ((this->channel >> 8) & 0xff); + out[offset_out++] = (this->channel & 0xff); + out[offset_out++] = this->tag; + out[offset_out++] = ((sequence_idx >> 8) & 0xff); + out[offset_out++] = (sequence_idx & 0xff); + sequence_idx++; + block_size = ((command_len - offset) > this->packet_size - 5 ? this->packet_size - 5 : command_len - offset); + ASSERT_X(out_len >= block_size, "out_len too short: "+std::to_string(out_len)); + out_len -= block_size; + memcpy(out + offset_out, command + offset, block_size); + offset_out += block_size; + offset += block_size; + } + while ((offset_out % this->packet_size) != 0) { + ASSERT_X(out_len >= 1, "out_len too short: "+std::to_string(out_len)); + out_len--; + out[offset_out++] = 0; + } + return offset_out; + } + + /* + * return 0 if more data are needed + * >0 if response is fully available + */ + unsigned int device_io_hid::unwrapReponse(const unsigned char *data, size_t data_len, unsigned char *out, size_t out_len) { + unsigned int sequence_idx = 0; + unsigned int offset = 0; + unsigned int offset_out = 0; + unsigned int response_len; + unsigned int block_size; + unsigned int val; + + //end? + if ((data == NULL) || (data_len < 7 + 5)) { + return 0; + } + + //check hid header + val = (data[offset]<<8) + data[offset+1]; + offset += 2; + ASSERT_X(val == this->channel, "Wrong Channel"); + val = data[offset]; + offset++; + ASSERT_X(val == this->tag, "Wrong TAG"); + val = (data[offset]<<8) + data[offset+1]; + offset += 2; + ASSERT_X(val == sequence_idx, "Wrong sequence_idx"); + + //fetch + response_len = (data[offset++] << 8); + response_len |= data[offset++]; + ASSERT_X(out_len >= response_len, "Out Buffer too short"); + if (data_len < (7 + response_len)) { + return 0; + } + block_size = (response_len > (this->packet_size - 7) ? this->packet_size - 7 : response_len); + memcpy(out + offset_out, data + offset, block_size); + offset += block_size; + offset_out += block_size; + while (offset_out != response_len) { + sequence_idx++; + if (offset == data_len) { + return 0; + } + val = (data[offset]<<8) + data[offset+1]; + offset += 2; + ASSERT_X(val == this->channel, "Wrong Channel"); + val = data[offset]; + offset++; + ASSERT_X(val == this->tag, "Wrong TAG"); + val = (data[offset]<<8) + data[offset+1]; + offset += 2; + ASSERT_X(val == sequence_idx, "Wrong sequence_idx"); + + block_size = ((response_len - offset_out) > this->packet_size - 5 ? this->packet_size - 5 : response_len - offset_out); + if (block_size > (data_len - offset)) { + return 0; + } + memcpy(out + offset_out, data + offset, block_size); + offset += block_size; + offset_out += block_size; + } + return offset_out; + } + + + } +} + +#endif //#if defined(HAVE_HIDAPI) diff --git a/src/device/device_io_hid.hpp b/src/device/device_io_hid.hpp new file mode 100644 index 000000000..560208c77 --- /dev/null +++ b/src/device/device_io_hid.hpp @@ -0,0 +1,112 @@ +// Copyright (c) 2017-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#if defined(HAVE_HIDAPI) + +#include <hidapi/hidapi.h> +#include "device_io.hpp" + +#pragma once + +namespace hw { + namespace io { + + + + /** HID class base. Commands are formated as follow: + * + * |----------------------------------------------------------| + * | 2 bytes | 1 byte | 2 bytes | 2 bytes | len bytes | + * |-----------|----------|-----------|----------|------------| + * | channel | tag | sequence | len | payload | + * |----------------------------------------------------------| + */ + + + struct hid_conn_params { + unsigned int vid; + unsigned int pid; + unsigned int interface_number; + unsigned int usage_page; + bool interface_OR_page ; + }; + + + class device_io_hid: device_io { + + + private: + + + unsigned short channel; + unsigned char tag; + unsigned int packet_size; + unsigned int timeout; + + unsigned int usb_vid; + unsigned int usb_pid; + hid_device *usb_device; + + void io_hid_log(int read, unsigned char* buf, int buf_len); + void io_hid_init(); + void io_hid_exit() ; + void io_hid_open(int vid, int pid, int mode); + void io_hid_close (void); + + unsigned int wrapCommand(const unsigned char *command, size_t command_len, unsigned char *out, size_t out_len); + unsigned int unwrapReponse(const unsigned char *data, size_t data_len, unsigned char *out, size_t out_len); + + + public: + bool hid_verbose = false; + + const unsigned int OR_SELECT = 1; + const unsigned int AND_SELECT = 2; + + const unsigned char DEFAULT_CHANNEL = 0x0001; + const unsigned char DEFAULT_TAG = 0x01; + const unsigned int DEFAULT_PACKET_SIZE = 64; + const unsigned int DEFAULT_TIMEOUT = 120000; + + device_io_hid(unsigned short channel, unsigned char tag, unsigned int packet_zize, unsigned int timeout); + device_io_hid(); + ~device_io_hid() {}; + + void init(); + void connect(void *params); + void connect(unsigned int vid, unsigned int pid, unsigned int interface_number, unsigned int usage_page, bool interface_OR_page ); + bool connected() const; + int exchange(unsigned char *command, unsigned int cmd_len, unsigned char *response, unsigned int max_resp_len); + void disconnect(); + void release(); + }; + }; +}; + +#endif //#if defined(HAVE_HIDAPI) diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp index 9b5ea0fd7..456eda739 100644 --- a/src/device/device_ledger.cpp +++ b/src/device/device_ledger.cpp @@ -185,41 +185,8 @@ namespace hw { #define INS_GET_RESPONSE 0xc0 - void device_ledger::logCMD() { - if (apdu_verbose) { - char strbuffer[1024]; - snprintf(strbuffer, sizeof(strbuffer), "%.02x %.02x %.02x %.02x %.02x ", - this->buffer_send[0], - this->buffer_send[1], - this->buffer_send[2], - this->buffer_send[3], - this->buffer_send[4] - ); - const size_t len = strlen(strbuffer); - buffer_to_str(strbuffer+len, sizeof(strbuffer)-len, (char*)(this->buffer_send+5), this->length_send-5); - MDEBUG( "CMD :" << strbuffer); - } - } - - void device_ledger::logRESP() { - if (apdu_verbose) { - char strbuffer[1024]; - snprintf(strbuffer, sizeof(strbuffer), "%.02x%.02x ", - this->buffer_recv[this->length_recv-2], - this->buffer_recv[this->length_recv-1] - ); - const size_t len = strlen(strbuffer); - buffer_to_str(strbuffer+len, sizeof(strbuffer)-len, (char*)(this->buffer_recv), this->length_recv-2); - MDEBUG( "RESP :" << strbuffer); - - } - } - - /* -------------------------------------------------------------- */ - device_ledger::device_ledger() { + device_ledger::device_ledger(): hw_device(0x0101, 0x05, 64, 10000) { this->id = device_id++; - this->hCard = 0; - this->hContext = 0; this->reset_buffer(); this->mode = NONE; this->has_view_key = false; @@ -272,10 +239,39 @@ namespace hw { MDEBUG( "Device "<<this->name << " UNLOCKed"); } + /* ======================================================================= */ - /* MISC */ + /* IO */ /* ======================================================================= */ - int device_ledger::set_command_header(BYTE ins, BYTE p1, BYTE p2) { + + void device_ledger::logCMD() { + if (apdu_verbose) { + char strbuffer[1024]; + snprintf(strbuffer, sizeof(strbuffer), "%.02x %.02x %.02x %.02x %.02x ", + this->buffer_send[0], + this->buffer_send[1], + this->buffer_send[2], + this->buffer_send[3], + this->buffer_send[4] + ); + const size_t len = strlen(strbuffer); + buffer_to_str(strbuffer+len, sizeof(strbuffer)-len, (char*)(this->buffer_send+5), this->length_send-5); + MDEBUG( "CMD : " << strbuffer); + } + } + + void device_ledger::logRESP() { + if (apdu_verbose) { + char strbuffer[1024]; + snprintf(strbuffer, sizeof(strbuffer), "%.04x ", this->sw); + const size_t len = strlen(strbuffer); + buffer_to_str(strbuffer+len, sizeof(strbuffer)-len, (char*)(this->buffer_recv), this->length_recv); + MDEBUG( "RESP : " << strbuffer); + + } + } + + int device_ledger::set_command_header(unsigned char ins, unsigned char p1, unsigned char p2) { reset_buffer(); int offset = 0; this->buffer_send[0] = 0x00; @@ -286,7 +282,7 @@ namespace hw { return 5; } - int device_ledger::set_command_header_noopt(BYTE ins, BYTE p1, BYTE p2) { + int device_ledger::set_command_header_noopt(unsigned char ins, unsigned char p1, unsigned char p2) { int offset = set_command_header(ins, p1, p2); //options this->buffer_send[offset++] = 0; @@ -294,7 +290,7 @@ namespace hw { return offset; } - void device_ledger::send_simple(BYTE ins, BYTE p1) { + void device_ledger::send_simple(unsigned char ins, unsigned char p1) { this->length_send = set_command_header_noopt(ins, p1); this->exchange(); } @@ -305,23 +301,17 @@ namespace hw { } unsigned int device_ledger::exchange(unsigned int ok, unsigned int mask) { - LONG rv; - unsigned int sw; - - ASSERT_T0(this->length_send <= BUFFER_SEND_SIZE); logCMD(); - this->length_recv = BUFFER_RECV_SIZE; - rv = SCardTransmit(this->hCard, - SCARD_PCI_T0, this->buffer_send, this->length_send, - NULL, this->buffer_recv, &this->length_recv); - ASSERT_RV(rv); - ASSERT_T0(this->length_recv >= 2); - ASSERT_T0(this->length_recv <= BUFFER_RECV_SIZE); - logRESP(); - sw = (this->buffer_recv[this->length_recv-2]<<8) | this->buffer_recv[this->length_recv-1]; - ASSERT_SW(sw,ok,msk); - return sw; + this->length_recv = hw_device.exchange(this->buffer_send, this->length_send, this->buffer_recv, BUFFER_SEND_SIZE); + ASSERT_X(this->length_recv>=2, "Communication error, less than tow bytes received"); + + this->length_recv -= 2; + this->sw = (this->buffer_recv[length_recv]<<8) | this->buffer_recv[length_recv+1]; + ASSERT_SW(this->sw,ok,msk); + + logRESP(); + return this->sw; } void device_ledger::reset_buffer() { @@ -341,101 +331,25 @@ namespace hw { } const std::string device_ledger::get_name() const { - if (this->full_name.empty() || (this->hCard == 0)) { + if (this->full_name.empty() || !this->connected()) { return std::string("<disconnected:").append(this->name).append(">"); } - return this->full_name; + return this->name; } bool device_ledger::init(void) { #ifdef DEBUG_HWDEVICE this->controle_device = &hw::get_device("default"); #endif - LONG rv; this->release(); - rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM,0,0, &this->hContext); - ASSERT_RV(rv); - MDEBUG( "Device "<<this->id <<" SCardContext created: hContext="<<this->hContext); - this->hCard = 0; - return true; - } - - bool device_ledger::release() { - this->disconnect(); - if (this->hContext) { - SCardReleaseContext(this->hContext); - MDEBUG( "Device "<<this->id <<" SCardContext released: hContext="<<this->hContext); - this->hContext = 0; - this->full_name.clear(); - } + hw_device.init(); + MDEBUG( "Device "<<this->id <<" HIDUSB inited"); return true; } bool device_ledger::connect(void) { - BYTE pbAtr[MAX_ATR_SIZE]; - LPSTR mszReaders; - DWORD dwReaders; - LONG rv; - DWORD dwState, dwProtocol, dwAtrLen, dwReaderLen; - this->disconnect(); -#ifdef SCARD_AUTOALLOCATE - dwReaders = SCARD_AUTOALLOCATE; - rv = SCardListReaders(this->hContext, NULL, (LPSTR)&mszReaders, &dwReaders); -#else - dwReaders = 0; - rv = SCardListReaders(this->hContext, NULL, NULL, &dwReaders); - if (rv != SCARD_S_SUCCESS) - return false; - mszReaders = (LPSTR)calloc(dwReaders, sizeof(char)); - rv = SCardListReaders(this->hContext, NULL, mszReaders, &dwReaders); -#endif - if (rv == SCARD_S_SUCCESS) { - char* p; - const char* prefix = this->name.c_str(); - - p = mszReaders; - MDEBUG( "Looking for " << std::string(prefix)); - while (*p) { - MDEBUG( "Device Found: " << std::string(p)); - if ((strncmp(prefix, p, strlen(prefix))==0)) { - MDEBUG( "Device Match: " << std::string(p)); - if ((rv = SCardConnect(this->hContext, - p, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_T0, - &this->hCard, &dwProtocol))!=SCARD_S_SUCCESS) { - break; - } - MDEBUG( "Device "<<this->id <<" Connected: hCard="<<this->hCard); - dwAtrLen = sizeof(pbAtr); - if ((rv = SCardStatus(this->hCard, NULL, &dwReaderLen, &dwState, &dwProtocol, pbAtr, &dwAtrLen))!=SCARD_S_SUCCESS) { - break; - } - MDEBUG( "Device "<<this->id <<" Status OK"); - rv = SCARD_S_SUCCESS ; - this->full_name = std::string(p); - break; - } - p += strlen(p) +1; - } - } - - if (rv == SCARD_S_SUCCESS && mszReaders) { - #ifdef SCARD_AUTOALLOCATE - SCardFreeMemory(this->hContext, mszReaders); - #else - free(mszReaders); - #endif - mszReaders = NULL; - } - if (rv != SCARD_S_SUCCESS) { - if ( hCard) { - SCardDisconnect(this->hCard, SCARD_UNPOWER_CARD); - MDEBUG( "Device "<<this->id <<" disconnected: hCard="<<this->hCard); - this->hCard = 0; - } - } - ASSERT_RV(rv); - + hw_device.connect(0x2c97,0x0001, 0, 0xffa0, hw_device.OR_SELECT); this->reset(); #ifdef DEBUG_HWDEVICE cryptonote::account_public_address pubkey; @@ -445,15 +359,21 @@ namespace hw { crypto::secret_key skey; this->get_secret_keys(vkey,skey); - return rv==SCARD_S_SUCCESS; + return true; + } + + bool device_ledger::connected(void) const { + return hw_device.connected(); } bool device_ledger::disconnect() { - if (this->hCard) { - SCardDisconnect(this->hCard, SCARD_UNPOWER_CARD); - MDEBUG( "Device "<<this->id <<" disconnected: hCard="<<this->hCard); - this->hCard = 0; - } + hw_device.disconnect(); + return true; + } + + bool device_ledger::release() { + this->disconnect(); + hw_device.release(); return true; } diff --git a/src/device/device_ledger.hpp b/src/device/device_ledger.hpp index cd97d42a0..dde69fbfd 100644 --- a/src/device/device_ledger.hpp +++ b/src/device/device_ledger.hpp @@ -33,13 +33,7 @@ #include <cstddef> #include <string> #include "device.hpp" -#ifdef WIN32 -#include <winscard.h> -#define MAX_ATR_SIZE 33 -#else -#include <PCSC/winscard.h> -#include <PCSC/wintypes.h> -#endif +#include "device_io_hid.hpp" #include <boost/thread/mutex.hpp> #include <boost/thread/recursive_mutex.hpp> @@ -89,22 +83,23 @@ namespace hw { mutable boost::recursive_mutex device_locker; mutable boost::mutex command_locker; - //PCSC management - std::string full_name; - SCARDCONTEXT hContext; - SCARDHANDLE hCard; - DWORD length_send; - BYTE buffer_send[BUFFER_SEND_SIZE]; - DWORD length_recv; - BYTE buffer_recv[BUFFER_RECV_SIZE]; - unsigned int id; + //IO + hw::io::device_io_hid hw_device; + std::string full_name; + unsigned int length_send; + unsigned char buffer_send[BUFFER_SEND_SIZE]; + unsigned int length_recv; + unsigned char buffer_recv[BUFFER_RECV_SIZE]; + unsigned int sw; + unsigned int id; void logCMD(void); void logRESP(void); - unsigned int exchange(unsigned int ok=0x9000, unsigned int mask=0xFFFF); + unsigned int exchange(unsigned int ok=0x9000, unsigned int mask=0xFFFF); void reset_buffer(void); - int set_command_header(BYTE ins, BYTE p1 = 0x00, BYTE p2 = 0x00); - int set_command_header_noopt(BYTE ins, BYTE p1 = 0x00, BYTE p2 = 0x00); - void send_simple(BYTE ins, BYTE p1 = 0x00); + int set_command_header(unsigned char ins, unsigned char p1 = 0x00, unsigned char p2 = 0x00); + int set_command_header_noopt(unsigned char ins, unsigned char p1 = 0x00, unsigned char p2 = 0x00); + void send_simple(unsigned char ins, unsigned char p1 = 0x00); + // hw running mode device_mode mode; @@ -127,7 +122,7 @@ namespace hw { device_ledger(const device_ledger &device) = delete ; device_ledger& operator=(const device_ledger &device) = delete; - explicit operator bool() const override {return this->hContext != 0;} + explicit operator bool() const override {return this->connected(); } bool reset(void); @@ -141,6 +136,7 @@ namespace hw { bool release() override; bool connect(void) override; bool disconnect() override; + bool connected(void) const; bool set_mode(device_mode mode) override; diff --git a/src/device/log.cpp b/src/device/log.cpp index 1707524fb..c9d3b551b 100644 --- a/src/device/log.cpp +++ b/src/device/log.cpp @@ -32,29 +32,34 @@ namespace hw { - #ifdef WITH_DEVICE_LEDGER - namespace ledger { - - #undef MONERO_DEFAULT_LOG_CATEGORY - #define MONERO_DEFAULT_LOG_CATEGORY "device.ledger" + #undef MONERO_DEFAULT_LOG_CATEGORY + #define MONERO_DEFAULT_LOG_CATEGORY "device" - void buffer_to_str(char *to_buff, size_t to_len, const char *buff, size_t len) { - CHECK_AND_ASSERT_THROW_MES(to_len > (len*2), "destination buffer too short. At least" << (len*2+1) << " bytes required"); - for (size_t i=0; i<len; i++) { - sprintf(to_buff+2*i, "%.02x", (unsigned char)buff[i]); - } + void buffer_to_str(char *to_buff, size_t to_len, const char *buff, size_t len) { + CHECK_AND_ASSERT_THROW_MES(to_len > (len*2), "destination buffer too short. At least" << (len*2+1) << " bytes required"); + for (size_t i=0; i<len; i++) { + sprintf(to_buff+2*i, "%.02x", (unsigned char)buff[i]); } + } - void log_hexbuffer(const std::string &msg, const char* buff, size_t len) { - char logstr[1025]; - buffer_to_str(logstr, sizeof(logstr), buff, len); - MDEBUG(msg<< ": " << logstr); - } + void log_hexbuffer(const std::string &msg, const char* buff, size_t len) { + char logstr[1025]; + buffer_to_str(logstr, sizeof(logstr), buff, len); + MDEBUG(msg<< ": " << logstr); + } - void log_message(const std::string &msg, const std::string &info ) { - MDEBUG(msg << ": " << info); - } + void log_message(const std::string &msg, const std::string &info ) { + MDEBUG(msg << ": " << info); + } + + + #ifdef WITH_DEVICE_LEDGER + namespace ledger { + + #undef MONERO_DEFAULT_LOG_CATEGORY + #define MONERO_DEFAULT_LOG_CATEGORY "device.ledger" + #ifdef DEBUG_HWDEVICE extern crypto::secret_key dbg_viewkey; extern crypto::secret_key dbg_spendkey; diff --git a/src/device/log.hpp b/src/device/log.hpp index 1d1635dc1..25a214a6c 100644 --- a/src/device/log.hpp +++ b/src/device/log.hpp @@ -40,12 +40,13 @@ namespace hw { + void buffer_to_str(char *to_buff, size_t to_len, const char *buff, size_t len) ; + void log_hexbuffer(const std::string &msg, const char* buff, size_t len); + void log_message(const std::string &msg, const std::string &info ); + #ifdef WITH_DEVICE_LEDGER namespace ledger { - void buffer_to_str(char *to_buff, size_t to_len, const char *buff, size_t len) ; - void log_hexbuffer(const std::string &msg, const char* buff, size_t len); - void log_message(const std::string &msg, const std::string &info ); #ifdef DEBUG_HWDEVICE #define TRACK printf("file %s:%d\n",__FILE__, __LINE__) //#define TRACK MCDEBUG("ledger"," At file " << __FILE__ << ":" << __LINE__) diff --git a/src/ringct/bulletproofs.cc b/src/ringct/bulletproofs.cc index abe4ef18d..381f50872 100644 --- a/src/ringct/bulletproofs.cc +++ b/src/ringct/bulletproofs.cc @@ -1068,6 +1068,14 @@ bool bulletproof_VERIFY(const std::vector<const Bulletproof*> &proofs) CHECK_AND_ASSERT_MES(!(x_ip == rct::zero()), false, "x_ip == 0"); PERF_TIMER_STOP(VERIFY_start); + // pre-multiply some points by 8 + rct::keyV proof8_V = proof.V; for (rct::key &k: proof8_V) k = rct::scalarmult8(k); + rct::keyV proof8_L = proof.L; for (rct::key &k: proof8_L) k = rct::scalarmult8(k); + rct::keyV proof8_R = proof.R; for (rct::key &k: proof8_R) k = rct::scalarmult8(k); + rct::key proof8_T1 = rct::scalarmult8(proof.T1); + rct::key proof8_T2 = rct::scalarmult8(proof.T2); + rct::key proof8_S = rct::scalarmult8(proof.S); + PERF_TIMER_START_BP(VERIFY_line_61); // PAPER LINE 61 sc_muladd(y0.bytes, proof.taux.bytes, weight.bytes, y0.bytes); @@ -1090,26 +1098,22 @@ bool bulletproof_VERIFY(const std::vector<const Bulletproof*> &proofs) multiexp_data.reserve(proof.V.size()); sc_sub(tmp.bytes, proof.t.bytes, tmp.bytes); sc_muladd(y1.bytes, tmp.bytes, weight.bytes, y1.bytes); - for (size_t j = 0; j < proof.V.size(); j++) + for (size_t j = 0; j < proof8_V.size(); j++) { - sc_mul(tmp.bytes, zpow[j+2].bytes, EIGHT.bytes); - multiexp_data.emplace_back(tmp, proof.V[j]); + multiexp_data.emplace_back(zpow[j+2], proof8_V[j]); } rct::addKeys(Y2, Y2, rct::scalarmultKey(multiexp(multiexp_data, false), weight)); - rct::key weight8; - sc_mul(weight8.bytes, weight.bytes, EIGHT.bytes); - sc_mul(tmp.bytes, x.bytes, weight8.bytes); - rct::addKeys(Y3, Y3, rct::scalarmultKey(proof.T1, tmp)); + sc_mul(tmp.bytes, x.bytes, weight.bytes); + rct::addKeys(Y3, Y3, rct::scalarmultKey(proof8_T1, tmp)); rct::key xsq; sc_mul(xsq.bytes, x.bytes, x.bytes); - sc_mul(tmp.bytes, xsq.bytes, weight8.bytes); - rct::addKeys(Y4, Y4, rct::scalarmultKey(proof.T2, tmp)); + sc_mul(tmp.bytes, xsq.bytes, weight.bytes); + rct::addKeys(Y4, Y4, rct::scalarmultKey(proof8_T2, tmp)); PERF_TIMER_STOP(VERIFY_line_61rl_new); PERF_TIMER_START_BP(VERIFY_line_62); // PAPER LINE 62 - sc_mul(tmp.bytes, x.bytes, EIGHT.bytes); - rct::addKeys(Z0, Z0, rct::scalarmultKey(rct::addKeys(rct::scalarmult8(proof.A), rct::scalarmultKey(proof.S, tmp)), weight)); + rct::addKeys(Z0, Z0, rct::scalarmultKey(rct::addKeys(rct::scalarmult8(proof.A), rct::scalarmultKey(proof8_S, x)), weight)); PERF_TIMER_STOP(VERIFY_line_62); // Compute the number of rounds for the inner product @@ -1192,11 +1196,9 @@ bool bulletproof_VERIFY(const std::vector<const Bulletproof*> &proofs) for (size_t i = 0; i < rounds; ++i) { sc_mul(tmp.bytes, w[i].bytes, w[i].bytes); - sc_mul(tmp.bytes, tmp.bytes, EIGHT.bytes); - multiexp_data.emplace_back(tmp, proof.L[i]); + multiexp_data.emplace_back(tmp, proof8_L[i]); sc_mul(tmp.bytes, winv[i].bytes, winv[i].bytes); - sc_mul(tmp.bytes, tmp.bytes, EIGHT.bytes); - multiexp_data.emplace_back(tmp, proof.R[i]); + multiexp_data.emplace_back(tmp, proof8_R[i]); } rct::key acc = multiexp(multiexp_data, false); rct::addKeys(Z2, Z2, rct::scalarmultKey(acc, weight)); diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index 8b25096a2..5827e4d1a 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -1385,7 +1385,7 @@ PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, const for (uint32_t index = 0; index < m_wallet->get_num_subaddresses(subaddr_account); ++index) subaddr_indices.insert(index); } - transaction->m_pending_tx = m_wallet->create_transactions_all(0, info.address, info.is_subaddress, fake_outs_count, 0 /* unlock_time */, + transaction->m_pending_tx = m_wallet->create_transactions_all(0, info.address, info.is_subaddress, 1, fake_outs_count, 0 /* unlock_time */, adjusted_priority, extra, subaddr_account, subaddr_indices); } diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h index e3a300317..64350cee7 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.h @@ -79,7 +79,7 @@ public: bool recoverFromDevice(const std::string &path, const std::string &password, const std::string &device_name); - Device getDeviceType() const; + Device getDeviceType() const override; bool close(bool store = true); std::string seed() const override; std::string getSeedLanguage() const override; diff --git a/src/wallet/api/wallet_manager.h b/src/wallet/api/wallet_manager.h index 573e80d1a..b3c0d6c00 100644 --- a/src/wallet/api/wallet_manager.h +++ b/src/wallet/api/wallet_manager.h @@ -76,7 +76,7 @@ public: virtual bool closeWallet(Wallet *wallet, bool store = true) override; bool walletExists(const std::string &path) override; bool verifyWalletPassword(const std::string &keys_file_name, const std::string &password, bool no_spend_key, uint64_t kdf_rounds = 1) const override; - bool queryWalletDevice(Wallet::Device& device_type, const std::string &keys_file_name, const std::string &password, uint64_t kdf_rounds = 1) const; + bool queryWalletDevice(Wallet::Device& device_type, const std::string &keys_file_name, const std::string &password, uint64_t kdf_rounds = 1) const override; std::vector<std::string> findWallets(const std::string &path) override; std::string errorString() const override; void setDaemonAddress(const std::string &address) override; diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index 6361a6cfa..e6eb64d12 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -1553,7 +1553,7 @@ namespace tools rpc_transfers.spent = td.m_spent; rpc_transfers.global_index = td.m_global_output_index; rpc_transfers.tx_hash = epee::string_tools::pod_to_hex(td.m_txid); - rpc_transfers.subaddr_index = td.m_subaddr_index.minor; + rpc_transfers.subaddr_index = {td.m_subaddr_index.major, td.m_subaddr_index.minor}; rpc_transfers.key_image = req.verbose && td.m_key_image_known ? epee::string_tools::pod_to_hex(td.m_key_image) : ""; res.transfers.push_back(rpc_transfers); } @@ -3294,9 +3294,12 @@ class t_daemon private: const boost::program_options::variables_map& vm; + std::unique_ptr<tools::wallet_rpc_server> wrpc; + public: t_daemon(boost::program_options::variables_map const & _vm) : vm(_vm) + , wrpc(new tools::wallet_rpc_server) { } @@ -3386,17 +3389,16 @@ public: return false; } just_dir: - tools::wallet_rpc_server wrpc; - if (wal) wrpc.set_wallet(wal.release()); - bool r = wrpc.init(&vm); + if (wal) wrpc->set_wallet(wal.release()); + bool r = wrpc->init(&vm); CHECK_AND_ASSERT_MES(r, false, tools::wallet_rpc_server::tr("Failed to initialize wallet RPC server")); - tools::signal_handler::install([&wrpc](int) { - wrpc.send_stop_signal(); + tools::signal_handler::install([this](int) { + wrpc->send_stop_signal(); }); LOG_PRINT_L0(tools::wallet_rpc_server::tr("Starting wallet RPC server")); try { - wrpc.run(); + wrpc->run(); } catch (const std::exception &e) { @@ -3407,7 +3409,7 @@ public: try { LOG_PRINT_L0(tools::wallet_rpc_server::tr("Saving wallet...")); - wrpc.stop(); + wrpc->stop(); LOG_PRINT_L0(tools::wallet_rpc_server::tr("Successfully saved")); } catch (const std::exception& e) @@ -3417,6 +3419,11 @@ public: } return true; } + + void stop() + { + wrpc->send_stop_signal(); + } }; class t_executor final @@ -3424,7 +3431,9 @@ class t_executor final public: static std::string const NAME; - std::string const & name() + typedef ::t_daemon t_daemon; + + std::string const & name() const { return NAME; } @@ -3467,6 +3476,7 @@ int main(int argc, char** argv) { command_line::add_arg(desc_params, arg_prompt_for_password); daemonizer::init_options(hidden_options, desc_params); + desc_params.add(hidden_options); boost::optional<po::variables_map> vm; bool should_terminate = false; diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h index 5d9c22971..2168e0f71 100644 --- a/src/wallet/wallet_rpc_server_commands_defs.h +++ b/src/wallet/wallet_rpc_server_commands_defs.h @@ -863,7 +863,7 @@ namespace wallet_rpc bool spent; uint64_t global_index; std::string tx_hash; - uint32_t subaddr_index; + cryptonote::subaddress_index subaddr_index; std::string key_image; BEGIN_KV_SERIALIZE_MAP() diff --git a/tests/hash/tests-slow-2.txt b/tests/hash/tests-slow-2.txt index 8f90d05c9..79afd2712 100644 --- a/tests/hash/tests-slow-2.txt +++ b/tests/hash/tests-slow-2.txt @@ -1,10 +1,10 @@ -4cf1ff9ca46eb433b36cd9f70e02b14cc06bfd18ca77fa9ccaafd1fd96c674b0 5468697320697320612074657374205468697320697320612074657374205468697320697320612074657374 -7d292e43f4751714ec07dbcb0e4bbffe2a7afb6066420960684ff57d7474c871 4c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e73656374657475722061646970697363696e67 -335563425256edebf1d92dc342369c2f4770ebb4112ba975659bd8a0f210abd0 656c69742c2073656420646f20656975736d6f642074656d706f7220696e6369646964756e74207574206c61626f7265 -47758e86d2f57210366cec36fff26f9464d89efd116fe6ef28b718b5da120801 657420646f6c6f7265206d61676e6120616c697175612e20557420656e696d206164206d696e696d2076656e69616d2c -48787b48d5c68f0c1dd825c32580af741cc0ee314f08133135c1e86d87a24a95 71756973206e6f737472756420657865726369746174696f6e20756c6c616d636f206c61626f726973206e697369 -93bdf47495854f7cfaaca1af8c0f39ef4a3024c10eb0dea23726b0e06ef29e84 757420616c697175697020657820656120636f6d6d6f646f20636f6e7365717561742e20447569732061757465 -a375a71d0541057ccc96719150dfe10b6e6f486b19cf4a0835e19605413a8417 697275726520646f6c6f7220696e20726570726568656e646572697420696e20766f6c7570746174652076656c6974 -163478a76f8f1432533fbdd1284d65c89f37479e54f20841c6ce4eba56c73854 657373652063696c6c756d20646f6c6f726520657520667567696174206e756c6c612070617269617475722e -356b0470c6eea75cad7a108179e232905b23bdaf03c2824c6e619d503ee93677 4578636570746575722073696e74206f6363616563617420637570696461746174206e6f6e2070726f6964656e742c -a47e2b007dc25bb279e197a1b91f67ecebe2ddd8791cd32dd2cb76dd21ed943f 73756e7420696e2063756c706120717569206f666669636961206465736572756e74206d6f6c6c697420616e696d20696420657374206c61626f72756d2e +353fdc068fd47b03c04b9431e005e00b68c2168a3cc7335c8b9b308156591a4f 5468697320697320612074657374205468697320697320612074657374205468697320697320612074657374 +72f134fc50880c330fe65a2cb7896d59b2e708a0221c6a9da3f69b3a702d8682 4c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e73656374657475722061646970697363696e67 +410919660ec540fc49d8695ff01f974226a2a28dbbac82949c12f541b9a62d2f 656c69742c2073656420646f20656975736d6f642074656d706f7220696e6369646964756e74207574206c61626f7265 +4472fecfeb371e8b7942ce0378c0ba5e6d0c6361b669c587807365c787ae652d 657420646f6c6f7265206d61676e6120616c697175612e20557420656e696d206164206d696e696d2076656e69616d2c +577568395203f1f1225f2982b637f7d5e61b47a0f546ba16d46020b471b74076 71756973206e6f737472756420657865726369746174696f6e20756c6c616d636f206c61626f726973206e697369 +f6fd7efe95a5c6c4bb46d9b429e3faf65b1ce439e116742d42b928e61de52385 757420616c697175697020657820656120636f6d6d6f646f20636f6e7365717561742e20447569732061757465 +422f8cfe8060cf6c3d9fd66f68e3c9977adb683aea2788029308bbe9bc50d728 697275726520646f6c6f7220696e20726570726568656e646572697420696e20766f6c7570746174652076656c6974 +512e62c8c8c833cfbd9d361442cb00d63c0a3fd8964cfd2fedc17c7c25ec2d4b 657373652063696c6c756d20646f6c6f726520657520667567696174206e756c6c612070617269617475722e +12a794c1aa13d561c9c6111cee631ca9d0a321718d67d3416add9de1693ba41e 4578636570746575722073696e74206f6363616563617420637570696461746174206e6f6e2070726f6964656e742c +2659ff95fc74b6215c1dc741e85b7a9710101b30620212f80eb59c3c55993f9d 73756e7420696e2063756c706120717569206f666669636961206465736572756e74206d6f6c6c697420616e696d20696420657374206c61626f72756d2e diff --git a/utils/build_scripts/android32.Dockerfile b/utils/build_scripts/android32.Dockerfile index 2738d8d57..8647341cb 100644 --- a/utils/build_scripts/android32.Dockerfile +++ b/utils/build_scripts/android32.Dockerfile @@ -138,4 +138,5 @@ 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 -j${NPROC} |