aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt33
-rw-r--r--Dockerfile10
-rw-r--r--README.md20
-rw-r--r--cmake/FindPCSC.cmake3
-rw-r--r--contrib/depends/.gitignore10
-rw-r--r--contrib/depends/Makefile227
-rw-r--r--contrib/depends/README.md66
-rw-r--r--contrib/depends/builders/darwin.mk22
-rw-r--r--contrib/depends/builders/default.mk20
-rw-r--r--contrib/depends/builders/linux.mk2
-rwxr-xr-xcontrib/depends/config.guess1466
-rw-r--r--contrib/depends/config.site.in100
-rwxr-xr-xcontrib/depends/config.sub1836
-rw-r--r--contrib/depends/description.md53
-rw-r--r--contrib/depends/funcs.mk245
-rw-r--r--contrib/depends/hosts/darwin.mk17
-rw-r--r--contrib/depends/hosts/default.mk26
-rw-r--r--contrib/depends/hosts/linux.mk31
-rw-r--r--contrib/depends/hosts/mingw32.mk10
-rw-r--r--contrib/depends/packages.md147
-rw-r--r--contrib/depends/packages/bdb.mk31
-rw-r--r--contrib/depends/packages/boost.mk41
-rw-r--r--contrib/depends/packages/cmake/conf/mxe-conf.cmake.in67
-rw-r--r--contrib/depends/packages/cmake/conf/target-cmake.in29
-rw-r--r--contrib/depends/packages/cmake/test/CMakeLists.txt18
-rw-r--r--contrib/depends/packages/cppzmq.mk15
-rw-r--r--contrib/depends/packages/expat.mk22
-rw-r--r--contrib/depends/packages/graphviz.mk30
-rw-r--r--contrib/depends/packages/icu4c.mk32
-rw-r--r--contrib/depends/packages/ldns.mk28
-rw-r--r--contrib/depends/packages/libICE.mk23
-rw-r--r--contrib/depends/packages/libSM.mk23
-rw-r--r--contrib/depends/packages/libevent.mk30
-rw-r--r--contrib/depends/packages/libiconv.mk17
-rw-r--r--contrib/depends/packages/miniupnpc.mk28
-rw-r--r--contrib/depends/packages/native_biplist.mk20
-rw-r--r--contrib/depends/packages/native_ccache.mk25
-rw-r--r--contrib/depends/packages/native_cctools.mk65
-rw-r--r--contrib/depends/packages/native_cdrkit.mk26
-rw-r--r--contrib/depends/packages/native_ds_store.mk17
-rw-r--r--contrib/depends/packages/native_libdmg-hfsplus.mk22
-rw-r--r--contrib/depends/packages/native_mac_alias.mk21
-rw-r--r--contrib/depends/packages/openssl.mk78
-rw-r--r--contrib/depends/packages/packages.mk21
-rw-r--r--contrib/depends/packages/pcsc-lite.mk26
-rw-r--r--contrib/depends/packages/protobuf.mk29
-rw-r--r--contrib/depends/packages/qt.mk150
-rw-r--r--contrib/depends/packages/readline.mk33
-rw-r--r--contrib/depends/packages/sodium.mk23
-rw-r--r--contrib/depends/packages/unbound.mk28
-rw-r--r--contrib/depends/packages/unwind.mk22
-rw-r--r--contrib/depends/packages/xproto.mk21
-rw-r--r--contrib/depends/packages/zeromq.mk34
-rw-r--r--contrib/depends/packages/zlib.mk27
-rw-r--r--contrib/depends/patches/cmake/cmake-1-fixes.patch67
-rw-r--r--contrib/depends/patches/icu4c/icu-001-dont-build-static-dynamic-twice.patch37
-rw-r--r--contrib/depends/patches/native_biplist/sorted_list.patch29
-rw-r--r--contrib/depends/patches/native_cdrkit/cdrkit-deterministic.patch86
-rw-r--r--contrib/depends/patches/native_mac_alias/python3.patch72
-rw-r--r--contrib/depends/patches/qt/fix_qt_pkgconfig.patch11
-rw-r--r--contrib/depends/patches/qt/pidlist_absolute.patch37
-rw-r--r--contrib/depends/patches/qt/qfixed-coretext.patch34
-rw-r--r--contrib/depends/patches/readline/readline-1.patch187
-rw-r--r--contrib/depends/patches/zeromq/9114d3957725acd34aa8b8d011585812f3369411.patch22
-rw-r--r--contrib/depends/patches/zeromq/9e6745c12e0b100cd38acecc16ce7db02905e27c.patch22
-rw-r--r--contrib/depends/protobuf.mk29
-rw-r--r--contrib/depends/toolchain.cmake.in82
-rw-r--r--contrib/epee/include/hex.h1
-rw-r--r--contrib/epee/include/misc_os_dependent.h2
-rw-r--r--contrib/epee/include/span.h46
-rw-r--r--contrib/epee/include/wipeable_string.h19
-rw-r--r--contrib/epee/src/mlog.cpp2
-rw-r--r--contrib/epee/src/wipeable_string.cpp3
-rw-r--r--external/CMakeLists.txt2
-rw-r--r--src/blockchain_db/lmdb/db_lmdb.cpp2
-rw-r--r--src/blockchain_utilities/CMakeLists.txt4
-rw-r--r--src/blockchain_utilities/blockchain_blackball.cpp14
-rw-r--r--src/checkpoints/CMakeLists.txt10
-rw-r--r--src/common/CMakeLists.txt4
-rw-r--r--src/common/error.cpp75
-rw-r--r--src/common/error.h52
-rw-r--r--src/common/expect.cpp70
-rw-r--r--src/common/expect.h447
-rw-r--r--src/crypto/crypto_ops_builder/ietf.txt1404
-rw-r--r--src/cryptonote_basic/CMakeLists.txt10
-rw-r--r--src/cryptonote_basic/account.cpp8
-rw-r--r--src/cryptonote_basic/account.h3
-rw-r--r--src/cryptonote_core/blockchain.cpp15
-rw-r--r--src/cryptonote_core/cryptonote_core.cpp7
-rw-r--r--src/cryptonote_core/cryptonote_core.h12
-rw-r--r--src/daemon/CMakeLists.txt4
-rw-r--r--src/daemon/main.cpp7
-rw-r--r--src/daemon/rpc_command_executor.cpp2
-rw-r--r--src/device/device.cpp70
-rw-r--r--src/device/device.hpp24
-rw-r--r--src/device/device_default.hpp2
-rw-r--r--src/device/device_ledger.hpp4
-rw-r--r--src/gen_multisig/gen_multisig.cpp4
-rw-r--r--src/mnemonics/chinese_simplified.h9
-rw-r--r--src/mnemonics/dutch.h9
-rw-r--r--src/mnemonics/english.h9
-rw-r--r--src/mnemonics/english_old.h9
-rw-r--r--src/mnemonics/esperanto.h9
-rw-r--r--src/mnemonics/french.h9
-rw-r--r--src/mnemonics/german.h9
-rw-r--r--src/mnemonics/italian.h9
-rw-r--r--src/mnemonics/japanese.h9
-rw-r--r--src/mnemonics/language_base.h13
-rw-r--r--src/mnemonics/lojban.h9
-rw-r--r--src/mnemonics/portuguese.h9
-rw-r--r--src/mnemonics/russian.h9
-rw-r--r--src/mnemonics/spanish.h9
-rw-r--r--src/ringct/rctOps.cpp19
-rw-r--r--src/ringct/rctOps.h1
-rw-r--r--src/ringct/rctSigs.cpp12
-rw-r--r--src/ringct/rctTypes.h4
-rw-r--r--src/rpc/core_rpc_server.cpp13
-rw-r--r--src/rpc/core_rpc_server_commands_defs.h6
-rw-r--r--src/rpc/rpc_args.cpp14
-rw-r--r--src/simplewallet/simplewallet.cpp82
-rw-r--r--src/simplewallet/simplewallet.h3
-rw-r--r--src/wallet/CMakeLists.txt2
-rw-r--r--src/wallet/api/wallet.cpp75
-rw-r--r--src/wallet/api/wallet.h4
-rw-r--r--src/wallet/api/wallet2_api.h29
-rw-r--r--src/wallet/api/wallet_manager.cpp8
-rw-r--r--src/wallet/api/wallet_manager.h1
-rw-r--r--src/wallet/wallet2.cpp149
-rw-r--r--src/wallet/wallet2.h15
-rw-r--r--src/wallet/wallet_rpc_server.cpp314
-rw-r--r--tests/difficulty/difficulty.cpp1
-rw-r--r--tests/functional_tests/transactions_flow_test.cpp4
-rw-r--r--tests/unit_tests/CMakeLists.txt1
-rw-r--r--tests/unit_tests/epee_utils.cpp57
-rw-r--r--tests/unit_tests/expect.cpp915
-rw-r--r--tests/unit_tests/multisig.cpp2
-rw-r--r--tests/unit_tests/wipeable_string.cpp7
-rw-r--r--translations/CMakeLists.txt9
-rw-r--r--utils/build_scripts/android32.Dockerfile42
139 files changed, 8672 insertions, 1757 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5e47edcca..039a1bf71 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -372,6 +372,9 @@ add_definitions("-DBLOCKCHAIN_DB=${BLOCKCHAIN_DB}")
if (APPLE)
set(DEFAULT_STACK_TRACE OFF)
set(LIBUNWIND_LIBRARIES "")
+elseif (DEPENDS AND NOT LINUX)
+ set(DEFAULT_STACK_TRACE OFF)
+ set(LIBUNWIND_LIBRARIES "")
elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND NOT MINGW)
set(DEFAULT_STACK_TRACE ON)
set(STACK_TRACE_LIB "easylogging++") # for diag output only
@@ -410,6 +413,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "(SunOS|Solaris)")
endif ()
if (APPLE AND NOT IOS)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=x86-64 -fvisibility=default")
if (NOT OpenSSL_DIR)
EXECUTE_PROCESS(COMMAND brew --prefix openssl
OUTPUT_VARIABLE OPENSSL_ROOT_DIR
@@ -436,9 +440,16 @@ add_definition_if_function_found(strptime HAVE_STRPTIME)
add_definitions(-DAUTO_INITIALIZE_EASYLOGGINGPP)
# Generate header for embedded translations
-add_subdirectory(translations)
+# Generate header for embedded translations, use target toolchain if depends, otherwise use the
+# lrelease and lupdate binaries from the host
+include(ExternalProject)
+ExternalProject_Add(generate_translations_header
+ SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/translations"
+ BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/translations"
+ STAMP_DIR ${LRELEASE_PATH}
+ CMAKE_ARGS -DLRELEASE_PATH=${LRELEASE_PATH}
+ INSTALL_COMMAND cmake -E echo "")
include_directories("${CMAKE_CURRENT_BINARY_DIR}/translations")
-
add_subdirectory(external)
# Final setup for libunbound
@@ -483,7 +494,11 @@ if(MSVC)
include_directories(SYSTEM src/platform/msc)
else()
include(TestCXXAcceptsFlag)
- set(ARCH native CACHE STRING "CPU to build for: -march value or 'default' to not pass -march at all")
+ if (NOT ARM6)
+ if(NOT DEPENDS OR DEPENDS AND NOT ARM)
+ set(ARCH native CACHE STRING "CPU to build for: -march value or 'default' to not pass -march at all")
+ endif()
+ endif()
message(STATUS "Building on ${CMAKE_SYSTEM_PROCESSOR} for ${ARCH}")
if(ARCH STREQUAL "default")
set(ARCH_FLAG "")
@@ -690,6 +705,10 @@ else()
message(STATUS "Selecting VFP for ARMv6")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=vfp")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfpu=vfp")
+ if(DEPENDS)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -marm")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -marm")
+ endif()
endif(ARM6)
if(ARM7)
@@ -744,7 +763,7 @@ else()
endif()
if(APPLE)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGTEST_HAS_TR1_TUPLE=0")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -DGTEST_HAS_TR1_TUPLE=0")
endif()
set(DEBUG_FLAGS "-g3")
@@ -835,7 +854,11 @@ include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
if(MINGW)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wa,-mbig-obj")
set(EXTRA_LIBRARIES mswsock;ws2_32;iphlpapi;crypt32)
- set(ICU_LIBRARIES ${Boost_LOCALE_LIBRARY} icuio icuin icuuc icudt icutu iconv)
+ if(DEPENDS)
+ set(ICU_LIBRARIES ${Boost_LOCALE_LIBRARY} sicuio sicuin sicuuc sicudt sicutu iconv)
+ else()
+ set(ICU_LIBRARIES ${Boost_LOCALE_LIBRARY} icuio icuin icuuc icudt icutu iconv)
+ endif()
elseif(APPLE OR OPENBSD OR ANDROID)
set(EXTRA_LIBRARIES "")
elseif(FREEBSD)
diff --git a/Dockerfile b/Dockerfile
index 5fde5a477..96526e450 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -23,9 +23,9 @@ RUN set -ex && \
WORKDIR /usr/local
#Cmake
-ARG CMAKE_VERSION=3.12.0
+ARG CMAKE_VERSION=3.12.1
ARG CMAKE_VERSION_DOT=v3.12
-ARG CMAKE_HASH=d0781a90f6cdb9049d104ac16a150f9350b693498b9dea8a0331e799db6b9d69
+ARG CMAKE_HASH=c53d5c2ce81d7a957ee83e3e635c8cda5dfe20c9d501a4828ee28e1615e57ab2
RUN set -ex \
&& curl -s -O https://cmake.org/files/${CMAKE_VERSION_DOT}/cmake-${CMAKE_VERSION}.tar.gz \
&& echo "${CMAKE_HASH} cmake-${CMAKE_VERSION}.tar.gz" | sha256sum -c \
@@ -36,9 +36,9 @@ RUN set -ex \
&& make install
## Boost
-ARG BOOST_VERSION=1_67_0
-ARG BOOST_VERSION_DOT=1.67.0
-ARG BOOST_HASH=2684c972994ee57fc5632e03bf044746f6eb45d4920c343937a465fd67a5adba
+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://dl.bintray.com/boostorg/release/${BOOST_VERSION_DOT}/source/boost_${BOOST_VERSION}.tar.bz2 \
&& echo "${BOOST_HASH} boost_${BOOST_VERSION}.tar.bz2" | sha256sum -c \
diff --git a/README.md b/README.md
index 7f8edf877..325782b01 100644
--- a/README.md
+++ b/README.md
@@ -134,7 +134,7 @@ library archives (`.a`).
| Dep | Min. version | Vendored | Debian/Ubuntu pkg | Arch pkg | Fedora | Optional | Purpose |
| ------------ | ------------- | -------- | ------------------ | ------------ | ----------------- | -------- | -------------- |
| GCC | 4.7.3 | NO | `build-essential` | `base-devel` | `gcc` | NO | |
-| CMake | 3.0.0 | NO | `cmake` | `cmake` | `cmake` | NO | |
+| CMake | 3.5 | NO | `cmake` | `cmake` | `cmake` | NO | |
| pkg-config | any | NO | `pkg-config` | `base-devel` | `pkgconf` | NO | |
| Boost | 1.58 | NO | `libboost-all-dev` | `boost` | `boost-devel` | NO | C++ libraries |
| OpenSSL | basically any | NO | `libssl-dev` | `openssl` | `openssl-devel` | NO | sha256 sum |
@@ -479,7 +479,7 @@ Then you can run make as usual.
# Get binaries
docker cp monero-android:/opt/android/monero/build/release/bin .
-### Building portable statically linked binaries
+### Building portable statically linked binaries (Cross Compiling)
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:
@@ -534,6 +534,22 @@ Installing a snap is very quick. Snaps are secure. They are isolated with all of
Packaging for your favorite distribution would be a welcome contribution!
+You can also cross-compile binaries on linux for windows and macos with the depends system. Go to contrib/depends and type:
+
+* ```make HOST=x86_64-linux-gnu``` for 64-bit linux binaries.
+* ```make HOST=x86_64-w64-mingw32``` for 64-bit windows binaries. Requires: python3 nsis g++-mingw-w64-x86-64 wine1.6 bc
+* ```make HOST=x86_64-apple-darwin11``` for darwin binaries. Requires: cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev
+* ```make HOST=i686-linux-gnu``` for 32-bit linux binaries. Requires: g++-multilib bc
+* ```make HOST=i686-w64-mingw32``` for 32-bit windows binaries. Requires: python3 nsis g++-mingw-w64-i686
+* ```make HOST=arm-linux-gnueabihf``` for armv6 binaries. Requires: g++-arm-linux-gnueabihf
+
+The required packages are the names for each toolchain on apt. Depending on your distro, they may have different names.
+Then go back to the source dir and type for example for windows 64bit:
+
+* ```cmake -DCMAKE_TOOLCHAIN_FILE=`pwd`/contrib/depends/x86_64-w64-mingw32```
+
+Using depends might also be easier to compile monero on windows than using msys. Activate windows subsystem for linux (for example ubuntu) install the apt build-essentials and follow the depends steps as depicted above.
+
## Running monerod
The build places the binary in `bin/` sub-directory within the build directory
diff --git a/cmake/FindPCSC.cmake b/cmake/FindPCSC.cmake
index b5e8420e6..081919655 100644
--- a/cmake/FindPCSC.cmake
+++ b/cmake/FindPCSC.cmake
@@ -46,8 +46,9 @@ 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 )
+MARK_AS_ADVANCED( PCSC_LIBRARY PCSC_INCLUDE_DIR PCSC_STATIC_LIBRARY)
diff --git a/contrib/depends/.gitignore b/contrib/depends/.gitignore
new file mode 100644
index 000000000..3cb4b9ac1
--- /dev/null
+++ b/contrib/depends/.gitignore
@@ -0,0 +1,10 @@
+SDKs/
+work/
+built/
+sources/
+config.site
+x86_64*
+i686*
+mips*
+arm*
+aarch64*
diff --git a/contrib/depends/Makefile b/contrib/depends/Makefile
new file mode 100644
index 000000000..b0c032c09
--- /dev/null
+++ b/contrib/depends/Makefile
@@ -0,0 +1,227 @@
+.NOTPARALLEL :
+
+SOURCES_PATH ?= $(BASEDIR)/sources
+BASE_CACHE ?= $(BASEDIR)/built
+SDK_PATH ?= $(BASEDIR)/SDKs
+NO_QT ?=
+NO_WALLET ?=
+NO_UPNP ?=
+FALLBACK_DOWNLOAD_PATH ?= https://bitcoincore.org/depends-sources
+
+BUILD = $(shell ./config.guess)
+HOST ?= $(BUILD)
+PATCHES_PATH = $(BASEDIR)/patches
+BASEDIR = $(CURDIR)
+HASH_LENGTH:=11
+DOWNLOAD_CONNECT_TIMEOUT:=10
+DOWNLOAD_RETRIES:=3
+HOST_ID_SALT ?= salt
+BUILD_ID_SALT ?= salt
+
+host:=$(BUILD)
+ifneq ($(HOST),)
+host:=$(HOST)
+host_toolchain:=$(HOST)-
+endif
+
+ifneq ($(DEBUG),)
+release_type=debug
+else
+release_type=release
+endif
+
+base_build_dir=$(BASEDIR)/work/build
+base_staging_dir=$(BASEDIR)/work/staging
+base_download_dir=$(BASEDIR)/work/download
+canonical_host:=$(shell ./config.sub $(HOST))
+build:=$(shell ./config.sub $(BUILD))
+
+build_arch =$(firstword $(subst -, ,$(build)))
+build_vendor=$(word 2,$(subst -, ,$(build)))
+full_build_os:=$(subst $(build_arch)-$(build_vendor)-,,$(build))
+build_os:=$(findstring linux,$(full_build_os))
+build_os+=$(findstring darwin,$(full_build_os))
+build_os:=$(strip $(build_os))
+ifeq ($(build_os),)
+build_os=$(full_build_os)
+endif
+
+host_arch=$(firstword $(subst -, ,$(canonical_host)))
+host_vendor=$(word 2,$(subst -, ,$(canonical_host)))
+full_host_os:=$(subst $(host_arch)-$(host_vendor)-,,$(canonical_host))
+host_os:=$(findstring linux,$(full_host_os))
+host_os+=$(findstring darwin,$(full_host_os))
+host_os+=$(findstring mingw32,$(full_host_os))
+host_os:=$(strip $(host_os))
+ifeq ($(host_os),)
+host_os=$(full_host_os)
+endif
+
+$(host_arch)_$(host_os)_prefix=$(BASEDIR)/$(host)
+$(host_arch)_$(host_os)_host=$(host)
+host_prefix=$($(host_arch)_$(host_os)_prefix)
+build_prefix=$(host_prefix)/native
+ifeq ($(host_os),mingw32)
+host_cmake=Windows
+endif
+ifeq ($(host_os),linux)
+host_cmake=Linux
+endif
+ifeq ($(host_os),darwin)
+host_cmake=Darwin
+endif
+
+AT_$(V):=
+AT_:=@
+AT:=$(AT_$(V))
+
+all: install
+
+include hosts/$(host_os).mk
+include hosts/default.mk
+include builders/$(build_os).mk
+include builders/default.mk
+include packages/packages.mk
+
+build_id_string:=$(BUILD_ID_SALT)
+build_id_string+=$(shell $(build_CC) --version 2>/dev/null)
+build_id_string+=$(shell $(build_AR) --version 2>/dev/null)
+build_id_string+=$(shell $(build_CXX) --version 2>/dev/null)
+build_id_string+=$(shell $(build_RANLIB) --version 2>/dev/null)
+build_id_string+=$(shell $(build_STRIP) --version 2>/dev/null)
+
+$(host_arch)_$(host_os)_id_string:=$(HOST_ID_SALT)
+$(host_arch)_$(host_os)_id_string+=$(shell $(host_CC) --version 2>/dev/null)
+$(host_arch)_$(host_os)_id_string+=$(shell $(host_AR) --version 2>/dev/null)
+$(host_arch)_$(host_os)_id_string+=$(shell $(host_CXX) --version 2>/dev/null)
+$(host_arch)_$(host_os)_id_string+=$(shell $(host_RANLIB) --version 2>/dev/null)
+$(host_arch)_$(host_os)_id_string+=$(shell $(host_STRIP) --version 2>/dev/null)
+
+qt_packages_$(NO_QT) = $(qt_packages) $(qt_$(host_os)_packages) $(qt_$(host_arch)_$(host_os)_packages)
+wallet_packages_$(NO_WALLET) = $(wallet_packages)
+upnp_packages_$(NO_UPNP) = $(upnp_packages)
+
+packages += $($(host_arch)_$(host_os)_packages) $($(host_os)_packages) $(qt_packages_) $(wallet_packages_) $(upnp_packages_)
+native_packages += $($(host_arch)_$(host_os)_native_packages) $($(host_os)_native_packages)
+
+ifneq ($(qt_packages_),)
+native_packages += $(qt_native_packages)
+endif
+
+all_packages = $(packages) $(native_packages)
+
+meta_depends = Makefile funcs.mk builders/default.mk hosts/default.mk hosts/$(host_os).mk builders/$(build_os).mk
+
+$(host_arch)_$(host_os)_native_toolchain?=$($(host_os)_native_toolchain)
+
+include funcs.mk
+
+CONF_PKGS := cmake-conf mxe-conf
+
+build-only-$(1)_$(3): CMAKE_RUNRESULT_FILE = $(PREFIX)/share/cmake/modules/TryRunResults.cmake
+build-only-$(1)_$(3): CMAKE_TOOLCHAIN_FILE = $(PREFIX)/$(3)/share/cmake/mxe-conf.cmake
+build-only-$(1)_$(3): CMAKE_TOOLCHAIN_DIR = $(PREFIX)/$(3)/share/cmake/mxe-conf.d
+build-only-$(1)_$(3): CMAKE_STATIC_BOOL = $(if $(findstring shared,$(3)),OFF,ON)
+build-only-$(1)_$(3): CMAKE_SHARED_BOOL = $(if $(findstring shared,$(3)),ON,OFF)
+
+
+toolchain_path=$($($(host_arch)_$(host_os)_native_toolchain)_prefixbin)
+final_build_id_long+=$(shell $(build_SHA256SUM) config.site.in)
+final_build_id_long+=$(shell $(build_SHA256SUM) toolchain.cmake.in)
+final_build_id+=$(shell echo -n "$(final_build_id_long)" | $(build_SHA256SUM) | cut -c-$(HASH_LENGTH))
+$(host_prefix)/.stamp_$(final_build_id): $(native_packages) $(packages)
+ $(AT)rm -rf $(@D)
+ $(AT)mkdir -p $(@D)
+ $(AT)echo copying packages: $^
+ $(AT)echo to: $(@D)
+ $(AT)cd $(@D); $(foreach package,$^, tar xf $($(package)_cached); )
+ $(AT)touch $@
+
+$(host_prefix)/share/config.site : config.site.in $(host_prefix)/.stamp_$(final_build_id)
+ $(AT)@mkdir -p $(@D)
+ $(AT)sed -e 's|@HOST@|$(host)|' \
+ -e 's|@CC@|$(toolchain_path)$(host_CC)|' \
+ -e 's|@CXX@|$(toolchain_path)$(host_CXX)|' \
+ -e 's|@AR@|$(toolchain_path)$(host_AR)|' \
+ -e 's|@RANLIB@|$(toolchain_path)$(host_RANLIB)|' \
+ -e 's|@NM@|$(toolchain_path)$(host_NM)|' \
+ -e 's|@STRIP@|$(toolchain_path)$(host_STRIP)|' \
+ -e 's|@build_os@|$(build_os)|' \
+ -e 's|@host_os@|$(host_os)|' \
+ -e 's|@CFLAGS@|$(strip $(host_CFLAGS) $(host_$(release_type)_CFLAGS))|' \
+ -e 's|@CXXFLAGS@|$(strip $(host_CXXFLAGS) $(host_$(release_type)_CXXFLAGS))|' \
+ -e 's|@CPPFLAGS@|$(strip $(host_CPPFLAGS) $(host_$(release_type)_CPPFLAGS))|' \
+ -e 's|@LDFLAGS@|$(strip $(host_LDFLAGS) $(host_$(release_type)_LDFLAGS))|' \
+ -e 's|@allow_host_packages@|$(ALLOW_HOST_PACKAGES)|' \
+ -e 's|@no_qt@|$(NO_QT)|' \
+ -e 's|@no_wallet@|$(NO_WALLET)|' \
+ -e 's|@no_upnp@|$(NO_UPNP)|' \
+ -e 's|@debug@|$(DEBUG)|' \
+ $< > $@
+ $(AT)touch $@
+
+$(host_prefix)/share/toolchain.cmake : toolchain.cmake.in $(host_prefix)/.stamp_$(final_build_id)
+ $(AT)@mkdir -p $(@D)
+ $(AT)sed -e 's|@HOST@|$(host)|' \
+ -e 's|@CC@|$(toolchain_path)$(host_CC)|' \
+ -e 's|@CXX@|$(toolchain_path)$(host_CXX)|' \
+ -e 's|@AR@|$(toolchain_path)$(host_AR)|' \
+ -e 's|@RANLIB@|$(toolchain_path)$(host_RANLIB)|' \
+ -e 's|@NM@|$(toolchain_path)$(host_NM)|' \
+ -e 's|@STRIP@|$(toolchain_path)$(host_STRIP)|' \
+ -e 's|@build_os@|$(build_os)|' \
+ -e 's|@host_os@|$(host_os)|' \
+ -e 's|@CFLAGS@|$(strip $(host_CFLAGS) $(host_$(release_type)_CFLAGS))|' \
+ -e 's|@CXXFLAGS@|$(strip $(host_CXXFLAGS) $(host_$(release_type)_CXXFLAGS))|' \
+ -e 's|@CPPFLAGS@|$(strip $(host_CPPFLAGS) $(host_$(release_type)_CPPFLAGS))|' \
+ -e 's|@LDFLAGS@|$(strip $(host_LDFLAGS) $(host_$(release_type)_LDFLAGS))|' \
+ -e 's|@allow_host_packages@|$(ALLOW_HOST_PACKAGES)|' \
+ -e 's|@no_qt@|$(NO_QT)|' \
+ -e 's|@no_wallet@|$(NO_WALLET)|' \
+ -e 's|@no_upnp@|$(NO_UPNP)|' \
+ -e 's|@debug@|$(DEBUG)|' \
+ -e 's|@depends@|$(host_cmake)|' \
+ -e 's|@prefix@|$($(host_arch)_$(host_os)_prefix)|'\
+ -e 's|@sdk@|$(SDK_PATH)|'\
+ -e 's|@arch@|$(host_arch)|'\
+ $< > $@
+ $(AT)touch $@
+
+define check_or_remove_cached
+ mkdir -p $(BASE_CACHE)/$(host)/$(package) && cd $(BASE_CACHE)/$(host)/$(package); \
+ $(build_SHA256SUM) -c $($(package)_cached_checksum) >/dev/null 2>/dev/null || \
+ ( rm -f $($(package)_cached_checksum); \
+ if test -f "$($(package)_cached)"; then echo "Checksum mismatch for $(package). Forcing rebuild.."; rm -f $($(package)_cached_checksum) $($(package)_cached); fi )
+endef
+
+define check_or_remove_sources
+ mkdir -p $($(package)_source_dir); cd $($(package)_source_dir); \
+ test -f $($(package)_fetched) && ( $(build_SHA256SUM) -c $($(package)_fetched) >/dev/null 2>/dev/null || \
+ ( echo "Checksum missing or mismatched for $(package) source. Forcing re-download."; \
+ rm -f $($(package)_all_sources) $($(1)_fetched))) || true
+endef
+
+check-packages:
+ @$(foreach package,$(all_packages),$(call check_or_remove_cached,$(package));)
+check-sources:
+ @$(foreach package,$(all_packages),$(call check_or_remove_sources,$(package));)
+
+$(host_prefix)/share/config.site: check-packages
+$(host_prefix)/share/toolchain.cmake: check-packages
+
+check-packages: check-sources
+
+install: check-packages $(host_prefix)/share/config.site
+install: check-packages $(host_prefix)/share/toolchain.cmake
+
+download-one: check-sources $(all_sources)
+
+download-osx:
+ @$(MAKE) -s HOST=x86_64-apple-darwin11 download-one
+download-linux:
+ @$(MAKE) -s HOST=x86_64-unknown-linux-gnu download-one
+download-win:
+ @$(MAKE) -s HOST=x86_64-w64-mingw32 download-one
+download: download-osx download-linux download-win
+
+.PHONY: install cached download-one download-osx download-linux download-win download check-packages check-sources
diff --git a/contrib/depends/README.md b/contrib/depends/README.md
new file mode 100644
index 000000000..dd2824569
--- /dev/null
+++ b/contrib/depends/README.md
@@ -0,0 +1,66 @@
+### Usage
+
+To build dependencies for the current arch+OS:
+
+ make
+
+To build for another arch/OS:
+
+ make HOST=host-platform-triplet
+
+For example:
+
+ make HOST=x86_64-w64-mingw32 -j4
+
+A prefix will be generated that's suitable for plugging into Bitcoin's
+configure. In the above example, a dir named x86_64-w64-mingw32 will be
+created. To use it for Bitcoin:
+
+ ./configure --prefix=`pwd`/depends/x86_64-w64-mingw32
+
+Common `host-platform-triplets` for cross compilation are:
+
+- `i686-w64-mingw32` for Win32
+- `x86_64-w64-mingw32` for Win64
+- `x86_64-apple-darwin11` for MacOSX
+- `arm-linux-gnueabihf` for Linux ARM 32 bit
+- `aarch64-linux-gnu` for Linux ARM 64 bit
+
+No other options are needed, the paths are automatically configured.
+
+Dependency Options:
+The following can be set when running make: make FOO=bar
+
+ SOURCES_PATH: downloaded sources will be placed here
+ BASE_CACHE: built packages will be placed here
+ SDK_PATH: Path where sdk's can be found (used by OSX)
+ FALLBACK_DOWNLOAD_PATH: If a source file can't be fetched, try here before giving up
+ NO_QT: Don't download/build/cache qt and its dependencies
+ NO_WALLET: Don't download/build/cache libs needed to enable the wallet
+ NO_UPNP: Don't download/build/cache packages needed for enabling upnp
+ DEBUG: disable some optimizations and enable more runtime checking
+ HOST_ID_SALT: Optional salt to use when generating host package ids
+ BUILD_ID_SALT: Optional salt to use when generating build package ids
+
+If some packages are not built, for example `make NO_WALLET=1`, the appropriate
+options will be passed to bitcoin's configure. In this case, `--disable-wallet`.
+
+Additional targets:
+
+ download: run 'make download' to fetch all sources without building them
+ download-osx: run 'make download-osx' to fetch all sources needed for osx builds
+ download-win: run 'make download-win' to fetch all sources needed for win builds
+ download-linux: run 'make download-linux' to fetch all sources needed for linux builds
+
+#Darwin (macos) builds:
+
+To build with the x86_64-apple-darwin11 you require the mac os developer tools in MacOSX10.11.sdk.
+Download it from apple, or search for it on github. Create a new directoty called SDKs in this
+directory and place the entire MacOSX10.11.sdk folder in it. The depends build will then pick it up automatically
+(without requiring SDK_PATH).
+
+### Other documentation
+
+- [description.md](description.md): General description of the depends system
+- [packages.md](packages.md): Steps for adding packages
+
diff --git a/contrib/depends/builders/darwin.mk b/contrib/depends/builders/darwin.mk
new file mode 100644
index 000000000..27f550ab0
--- /dev/null
+++ b/contrib/depends/builders/darwin.mk
@@ -0,0 +1,22 @@
+build_darwin_CC: = $(shell xcrun -f clang)
+build_darwin_CXX: = $(shell xcrun -f clang++)
+build_darwin_AR: = $(shell xcrun -f ar)
+build_darwin_RANLIB: = $(shell xcrun -f ranlib)
+build_darwin_STRIP: = $(shell xcrun -f strip)
+build_darwin_OTOOL: = $(shell xcrun -f otool)
+build_darwin_NM: = $(shell xcrun -f nm)
+build_darwin_INSTALL_NAME_TOOL:=$(shell xcrun -f install_name_tool)
+build_darwin_SHA256SUM = shasum -a 256
+build_darwin_DOWNLOAD = curl --location --fail --connect-timeout $(DOWNLOAD_CONNECT_TIMEOUT) --retry $(DOWNLOAD_RETRIES) -o
+
+#darwin host on darwin builder. overrides darwin host preferences.
+darwin_CC=$(shell xcrun -f clang) -mmacosx-version-min=$(OSX_MIN_VERSION)
+darwin_CXX:=$(shell xcrun -f clang++) -mmacosx-version-min=$(OSX_MIN_VERSION) -stdlib=libc++
+darwin_AR:=$(shell xcrun -f ar)
+darwin_RANLIB:=$(shell xcrun -f ranlib)
+darwin_STRIP:=$(shell xcrun -f strip)
+darwin_LIBTOOL:=$(shell xcrun -f libtool)
+darwin_OTOOL:=$(shell xcrun -f otool)
+darwin_NM:=$(shell xcrun -f nm)
+darwin_INSTALL_NAME_TOOL:=$(shell xcrun -f install_name_tool)
+darwin_native_toolchain=
diff --git a/contrib/depends/builders/default.mk b/contrib/depends/builders/default.mk
new file mode 100644
index 000000000..f097db65d
--- /dev/null
+++ b/contrib/depends/builders/default.mk
@@ -0,0 +1,20 @@
+default_build_CC = gcc
+default_build_CXX = g++
+default_build_AR = ar
+default_build_RANLIB = ranlib
+default_build_STRIP = strip
+default_build_NM = nm
+default_build_OTOOL = otool
+default_build_INSTALL_NAME_TOOL = install_name_tool
+
+define add_build_tool_func
+build_$(build_os)_$1 ?= $$(default_build_$1)
+build_$(build_arch)_$(build_os)_$1 ?= $$(build_$(build_os)_$1)
+build_$1=$$(build_$(build_arch)_$(build_os)_$1)
+endef
+$(foreach var,CC CXX AR RANLIB NM STRIP SHA256SUM DOWNLOAD OTOOL INSTALL_NAME_TOOL,$(eval $(call add_build_tool_func,$(var))))
+define add_build_flags_func
+build_$(build_arch)_$(build_os)_$1 += $(build_$(build_os)_$1)
+build_$1=$$(build_$(build_arch)_$(build_os)_$1)
+endef
+$(foreach flags, CFLAGS CXXFLAGS LDFLAGS, $(eval $(call add_build_flags_func,$(flags))))
diff --git a/contrib/depends/builders/linux.mk b/contrib/depends/builders/linux.mk
new file mode 100644
index 000000000..b03f42401
--- /dev/null
+++ b/contrib/depends/builders/linux.mk
@@ -0,0 +1,2 @@
+build_linux_SHA256SUM = sha256sum
+build_linux_DOWNLOAD = curl --location --fail --connect-timeout $(DOWNLOAD_CONNECT_TIMEOUT) --retry $(DOWNLOAD_RETRIES) -o
diff --git a/contrib/depends/config.guess b/contrib/depends/config.guess
new file mode 100755
index 000000000..69ed3e573
--- /dev/null
+++ b/contrib/depends/config.guess
@@ -0,0 +1,1466 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright 1992-2017 Free Software Foundation, Inc.
+
+timestamp='2017-03-05'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that
+# program. This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+#
+# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
+#
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
+#
+# Please send patches to <config-patches@gnu.org>.
+
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright 1992-2017 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,) echo "int x;" > $dummy.c ;
+ for c in cc gcc c89 c99 ; do
+ if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+ CC_FOR_BUILD="$c"; break ;
+ fi ;
+ done ;
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found ;
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+case "${UNAME_SYSTEM}" in
+Linux|GNU|GNU/*)
+ # If the system lacks a compiler, then just pick glibc.
+ # We could probably try harder.
+ LIBC=gnu
+
+ eval $set_cc_for_build
+ cat <<-EOF > $dummy.c
+ #include <features.h>
+ #if defined(__UCLIBC__)
+ LIBC=uclibc
+ #elif defined(__dietlibc__)
+ LIBC=dietlibc
+ #else
+ LIBC=gnu
+ #endif
+ EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
+ ;;
+esac
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ sysctl="sysctl -n hw.machine_arch"
+ UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
+ /sbin/$sysctl 2>/dev/null || \
+ /usr/sbin/$sysctl 2>/dev/null || \
+ echo unknown)`
+ case "${UNAME_MACHINE_ARCH}" in
+ armeb) machine=armeb-unknown ;;
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ sh5el) machine=sh5le-unknown ;;
+ earmv*)
+ arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
+ endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'`
+ machine=${arch}${endian}-unknown
+ ;;
+ *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently (or will in the future) and ABI.
+ case "${UNAME_MACHINE_ARCH}" in
+ earm*)
+ os=netbsdelf
+ ;;
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ELF__
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # Determine ABI tags.
+ case "${UNAME_MACHINE_ARCH}" in
+ earm*)
+ expr='s/^earmv[0-9]/-eabi/;s/eb$//'
+ abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"`
+ ;;
+ esac
+ # The OS release
+ # Debian GNU/NetBSD machines have a different userland, and
+ # thus, need a distinct triplet. However, they do not need
+ # kernel version information, so it can be replaced with a
+ # suitable tag, in the style of linux-gnu.
+ case "${UNAME_VERSION}" in
+ Debian*)
+ release='-gnu'
+ ;;
+ *)
+ release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2`
+ ;;
+ esac
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "${machine}-${os}${release}${abi}"
+ exit ;;
+ *:Bitrig:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
+ exit ;;
+ *:OpenBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+ exit ;;
+ *:LibertyBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE}
+ exit ;;
+ *:ekkoBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+ exit ;;
+ *:SolidBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+ exit ;;
+ macppc:MirBSD:*:*)
+ echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ *:MirBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ *:Sortix:*:*)
+ echo ${UNAME_MACHINE}-unknown-sortix
+ exit ;;
+ alpha:OSF1:*:*)
+ case $UNAME_RELEASE in
+ *4.0)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+ # OSF/1 and Tru64 systems produced since 1995. I hope that
+ # covers most systems running today. This code pipes the CPU
+ # types through head -n 1, so we only detect the type of CPU 0.
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case "$ALPHA_CPU_TYPE" in
+ "EV4 (21064)")
+ UNAME_MACHINE=alpha ;;
+ "EV4.5 (21064)")
+ UNAME_MACHINE=alpha ;;
+ "LCA4 (21066/21068)")
+ UNAME_MACHINE=alpha ;;
+ "EV5 (21164)")
+ UNAME_MACHINE=alphaev5 ;;
+ "EV5.6 (21164A)")
+ UNAME_MACHINE=alphaev56 ;;
+ "EV5.6 (21164PC)")
+ UNAME_MACHINE=alphapca56 ;;
+ "EV5.7 (21164PC)")
+ UNAME_MACHINE=alphapca57 ;;
+ "EV6 (21264)")
+ UNAME_MACHINE=alphaev6 ;;
+ "EV6.7 (21264A)")
+ UNAME_MACHINE=alphaev67 ;;
+ "EV6.8CB (21264C)")
+ UNAME_MACHINE=alphaev68 ;;
+ "EV6.8AL (21264B)")
+ UNAME_MACHINE=alphaev68 ;;
+ "EV6.8CX (21264D)")
+ UNAME_MACHINE=alphaev68 ;;
+ "EV6.9A (21264/EV69A)")
+ UNAME_MACHINE=alphaev69 ;;
+ "EV7 (21364)")
+ UNAME_MACHINE=alphaev7 ;;
+ "EV7.9 (21364A)")
+ UNAME_MACHINE=alphaev79 ;;
+ esac
+ # A Pn.n version is a patched version.
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+ # Reset EXIT trap before exiting to avoid spurious non-zero exit code.
+ exitcode=$?
+ trap '' 0
+ exit $exitcode ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
+ exit ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit ;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-morphos
+ exit ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit ;;
+ *:z/VM:*:*)
+ echo s390-ibm-zvmoe
+ exit ;;
+ *:OS400:*:*)
+ echo powerpc-ibm-os400
+ exit ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit ;;
+ arm*:riscos:*:*|arm*:RISCOS:*:*)
+ echo arm-unknown-riscos
+ exit ;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit ;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit ;;
+ DRS?6000:unix:4.0:6*)
+ echo sparc-icl-nx6
+ exit ;;
+ DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7; exit ;;
+ esac ;;
+ s390x:SunOS:*:*)
+ echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
+ echo i386-pc-auroraux${UNAME_RELEASE}
+ exit ;;
+ i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+ eval $set_cc_for_build
+ SUN_ARCH=i386
+ # If there is a compiler, see if it is configured for 64-bit objects.
+ # Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
+ # This test works for both compilers.
+ if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
+ if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ SUN_ARCH=x86_64
+ fi
+ fi
+ echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit ;;
+ m68k:machten:*:*)
+ echo m68k-apple-machten${UNAME_RELEASE}
+ exit ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c &&
+ dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+ SYSTEM_NAME=`$dummy $dummyarg` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit ;;
+ Motorola:*:4.3:PL8-*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+ [ ${TARGET_BINARY_INTERFACE}x = x ]
+ then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else
+ echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit ;;
+ ia64:AIX:*:*)
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+ then
+ echo "$SYSTEM_NAME"
+ else
+ echo rs6000-ibm-aix3.2.5
+ fi
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit ;;
+ *:AIX:*:[4567])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/lslpp ] ; then
+ IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
+ awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH=hppa2.0n ;;
+ 64) HP_ARCH=hppa2.0w ;;
+ '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if [ "${HP_ARCH}" = "" ]; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+ fi ;;
+ esac
+ if [ ${HP_ARCH} = hppa2.0w ]
+ then
+ eval $set_cc_for_build
+
+ # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+ # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
+ # generating 64-bit code. GNU and HP use different nomenclature:
+ #
+ # $ CC_FOR_BUILD=cc ./config.guess
+ # => hppa2.0w-hp-hpux11.23
+ # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+ # => hppa64-hp-hpux11.23
+
+ if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) |
+ grep -q __LP64__
+ then
+ HP_ARCH=hppa2.0w
+ else
+ HP_ARCH=hppa64
+ fi
+ fi
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo unknown-hitachi-hiuxwe2
+ exit ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ *:UNICOS/mp:*:*)
+ echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+ FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
+ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:FreeBSD:*:*)
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ case ${UNAME_PROCESSOR} in
+ amd64)
+ UNAME_PROCESSOR=x86_64 ;;
+ i386)
+ UNAME_PROCESSOR=i586 ;;
+ esac
+ echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit ;;
+ *:MINGW64*:*)
+ echo ${UNAME_MACHINE}-pc-mingw64
+ exit ;;
+ *:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit ;;
+ *:MSYS*:*)
+ echo ${UNAME_MACHINE}-pc-msys
+ exit ;;
+ i*:windows32*:*)
+ # uname -m includes "-pc" on this system.
+ echo ${UNAME_MACHINE}-mingw32
+ exit ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit ;;
+ *:Interix*:*)
+ case ${UNAME_MACHINE} in
+ x86)
+ echo i586-pc-interix${UNAME_RELEASE}
+ exit ;;
+ authenticamd | genuineintel | EM64T)
+ echo x86_64-unknown-interix${UNAME_RELEASE}
+ exit ;;
+ IA64)
+ echo ia64-unknown-interix${UNAME_RELEASE}
+ exit ;;
+ esac ;;
+ [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+ echo i${UNAME_MACHINE}-pc-mks
+ exit ;;
+ 8664:Windows_NT:*)
+ echo x86_64-pc-mks
+ exit ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i586-pc-interix
+ exit ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit ;;
+ amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+ echo x86_64-unknown-cygwin
+ exit ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ *:GNU:*:*)
+ # the GNU system
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
+ exit ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit ;;
+ aarch64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ aarch64_be:Linux:*:*)
+ UNAME_MACHINE=aarch64_be
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep -q ld.so.1
+ if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ arc:Linux:*:* | arceb:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ arm*:Linux:*:*)
+ eval $set_cc_for_build
+ if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_EABI__
+ then
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ else
+ if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_PCS_VFP
+ then
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
+ else
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
+ fi
+ fi
+ exit ;;
+ avr32*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ cris:Linux:*:*)
+ echo ${UNAME_MACHINE}-axis-linux-${LIBC}
+ exit ;;
+ crisv32:Linux:*:*)
+ echo ${UNAME_MACHINE}-axis-linux-${LIBC}
+ exit ;;
+ e2k:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ frv:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ hexagon:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ i*86:Linux:*:*)
+ echo ${UNAME_MACHINE}-pc-linux-${LIBC}
+ exit ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ k1om:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ m32r*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ mips:Linux:*:* | mips64:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef ${UNAME_MACHINE}
+ #undef ${UNAME_MACHINE}el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=${UNAME_MACHINE}el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=${UNAME_MACHINE}
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
+ ;;
+ mips64el:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ openrisc*:Linux:*:*)
+ echo or1k-unknown-linux-${LIBC}
+ exit ;;
+ or32:Linux:*:* | or1k*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ padre:Linux:*:*)
+ echo sparc-unknown-linux-${LIBC}
+ exit ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-${LIBC}
+ exit ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
+ PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
+ *) echo hppa-unknown-linux-${LIBC} ;;
+ esac
+ exit ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-${LIBC}
+ exit ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-${LIBC}
+ exit ;;
+ ppc64le:Linux:*:*)
+ echo powerpc64le-unknown-linux-${LIBC}
+ exit ;;
+ ppcle:Linux:*:*)
+ echo powerpcle-unknown-linux-${LIBC}
+ exit ;;
+ riscv32:Linux:*:* | riscv64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
+ exit ;;
+ sh64*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ tile*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ vax:Linux:*:*)
+ echo ${UNAME_MACHINE}-dec-linux-${LIBC}
+ exit ;;
+ x86_64:Linux:*:*)
+ echo ${UNAME_MACHINE}-pc-linux-${LIBC}
+ exit ;;
+ xtensa*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ echo i386-sequent-sysv4
+ exit ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ echo ${UNAME_MACHINE}-pc-os2-emx
+ exit ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit ;;
+ i*86:syllable:*:*)
+ echo ${UNAME_MACHINE}-pc-syllable
+ exit ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit ;;
+ i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+ UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ fi
+ exit ;;
+ i*86:*:5:[678]*)
+ # UnixWare 7.x, OpenUNIX and OpenServer 6.
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ exit ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i586.
+ # Note: whatever this is, it MUST be the same as what config.sub
+ # prints for the "djgpp" host, or else GDB configure will decide that
+ # this is a cross-build.
+ echo i586-pc-msdosdjgpp
+ exit ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ echo m68k-convergent-sysv
+ exit ;;
+ M680?0:D-NIX:5.3:*)
+ echo m68k-diab-dnix
+ exit ;;
+ M68*:*:R3V[5678]*:*)
+ test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+ 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4; exit; } ;;
+ NCR*:*:4.2:* | MPRAS*:*:4.2:*)
+ OS_REL='.3'
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit ;;
+ i*86:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo ${UNAME_MACHINE}-stratus-vos
+ exit ;;
+ *:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo hppa1.1-stratus-vos
+ exit ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit ;;
+ BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
+ echo i586-pc-haiku
+ exit ;;
+ x86_64:Haiku:*:*)
+ echo x86_64-unknown-haiku
+ exit ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-6:SUPER-UX:*:*)
+ echo sx6-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-7:SUPER-UX:*:*)
+ echo sx7-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-8:SUPER-UX:*:*)
+ echo sx8-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-8R:SUPER-UX:*:*)
+ echo sx8r-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-ACE:SUPER-UX:*:*)
+ echo sxace-nec-superux${UNAME_RELEASE}
+ exit ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Darwin:*:*)
+ UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+ eval $set_cc_for_build
+ if test "$UNAME_PROCESSOR" = unknown ; then
+ UNAME_PROCESSOR=powerpc
+ fi
+ if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
+ if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
+ if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ case $UNAME_PROCESSOR in
+ i386) UNAME_PROCESSOR=x86_64 ;;
+ powerpc) UNAME_PROCESSOR=powerpc64 ;;
+ esac
+ fi
+ fi
+ elif test "$UNAME_PROCESSOR" = i386 ; then
+ # Avoid executing cc on OS X 10.9, as it ships with a stub
+ # that puts up a graphical alert prompting to install
+ # developer tools. Any system running Mac OS X 10.7 or
+ # later (Darwin 11 and later) is required to have a 64-bit
+ # processor. This is not true of the ARM version of Darwin
+ # that Apple uses in portable devices.
+ UNAME_PROCESSOR=x86_64
+ fi
+ echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+ exit ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = x86; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+ exit ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit ;;
+ NEO-?:NONSTOP_KERNEL:*:*)
+ echo neo-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ NSE-*:NONSTOP_KERNEL:*:*)
+ echo nse-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ NSR-?:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ NSX-?:NONSTOP_KERNEL:*:*)
+ echo nsx-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "$cputype" = 386; then
+ UNAME_MACHINE=i386
+ else
+ UNAME_MACHINE="$cputype"
+ fi
+ echo ${UNAME_MACHINE}-unknown-plan9
+ exit ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit ;;
+ SEI:*:*:SEIUX)
+ echo mips-sei-seiux${UNAME_RELEASE}
+ exit ;;
+ *:DragonFly:*:*)
+ echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit ;;
+ *:*VMS:*:*)
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case "${UNAME_MACHINE}" in
+ A*) echo alpha-dec-vms ; exit ;;
+ I*) echo ia64-dec-vms ; exit ;;
+ V*) echo vax-dec-vms ; exit ;;
+ esac ;;
+ *:XENIX:*:SysV)
+ echo i386-pc-xenix
+ exit ;;
+ i*86:skyos:*:*)
+ echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'`
+ exit ;;
+ i*86:rdos:*:*)
+ echo ${UNAME_MACHINE}-pc-rdos
+ exit ;;
+ i*86:AROS:*:*)
+ echo ${UNAME_MACHINE}-pc-aros
+ exit ;;
+ x86_64:VMkernel:*:*)
+ echo ${UNAME_MACHINE}-unknown-esx
+ exit ;;
+ amd64:Isilon\ OneFS:*:*)
+ echo x86_64-unknown-onefs
+ exit ;;
+esac
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script (version $timestamp), has failed to recognize the
+operating system you are using. If your script is old, overwrite
+config.guess and config.sub with the latest versions from:
+
+ http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
+and
+ http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
+
+If $0 has already been updated, send the following data and any
+information you think might be pertinent to config-patches@gnu.org to
+provide the necessary information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/contrib/depends/config.site.in b/contrib/depends/config.site.in
new file mode 100644
index 000000000..0a4a9c327
--- /dev/null
+++ b/contrib/depends/config.site.in
@@ -0,0 +1,100 @@
+depends_prefix="`dirname ${ac_site_file}`/.."
+
+cross_compiling=maybe
+host_alias=@HOST@
+ac_tool_prefix=${host_alias}-
+
+if test -z $with_boost; then
+ with_boost=$depends_prefix
+fi
+if test -z $with_qt_plugindir; then
+ with_qt_plugindir=$depends_prefix/plugins
+fi
+if test -z $with_qt_translationdir; then
+ with_qt_translationdir=$depends_prefix/translations
+fi
+if test -z $with_qt_bindir && test -z "@no_qt@"; then
+ with_qt_bindir=$depends_prefix/native/bin
+fi
+if test -z $with_protoc_bindir && test -z "@no_qt@"; then
+ with_protoc_bindir=$depends_prefix/native/bin
+fi
+
+
+if test -z $enable_wallet && test -n "@no_wallet@"; then
+ enable_wallet=no
+fi
+
+if test -z $with_miniupnpc && test -n "@no_upnp@"; then
+ with_miniupnpc=no
+fi
+
+if test -z $with_gui && test -n "@no_qt@"; then
+ with_gui=no
+fi
+
+if test x@host_os@ = xdarwin; then
+ BREW=no
+ PORT=no
+fi
+
+if test x@host_os@ = xmingw32; then
+ if test -z $with_qt_incdir; then
+ with_qt_incdir=$depends_prefix/include
+ fi
+ if test -z $with_qt_libdir; then
+ with_qt_libdir=$depends_prefix/lib
+ fi
+fi
+
+PATH=$depends_prefix/native/bin:$PATH
+PKG_CONFIG="`which pkg-config` --static"
+
+# These two need to remain exported because pkg-config does not see them
+# otherwise. That means they must be unexported at the end of configure.ac to
+# avoid ruining the cache. Sigh.
+export PKG_CONFIG_PATH=$depends_prefix/share/pkgconfig:$depends_prefix/lib/pkgconfig
+if test -z "@allow_host_packages@"; then
+ export PKGCONFIG_LIBDIR=
+fi
+
+CPPFLAGS="-I$depends_prefix/include/ $CPPFLAGS"
+LDFLAGS="-L$depends_prefix/lib $LDFLAGS"
+
+CC="@CC@"
+CXX="@CXX@"
+OBJC="${CC}"
+CCACHE=$depends_prefix/native/bin/ccache
+PYTHONPATH=$depends_prefix/native/lib/python/dist-packages:$PYTHONPATH
+
+if test -n "@AR@"; then
+ AR=@AR@
+ ac_cv_path_ac_pt_AR=${AR}
+fi
+
+if test -n "@RANLIB@"; then
+ RANLIB=@RANLIB@
+ ac_cv_path_ac_pt_RANLIB=${RANLIB}
+fi
+
+if test -n "@NM@"; then
+ NM=@NM@
+ ac_cv_path_ac_pt_NM=${NM}
+fi
+
+if test -n "@debug@"; then
+ enable_reduce_exports=no
+fi
+
+if test -n "@CFLAGS@"; then
+ CFLAGS="@CFLAGS@ $CFLAGS"
+fi
+if test -n "@CXXFLAGS@"; then
+ CXXFLAGS="@CXXFLAGS@ $CXXFLAGS"
+fi
+if test -n "@CPPFLAGS@"; then
+ CPPFLAGS="@CPPFLAGS@ $CPPFLAGS"
+fi
+if test -n "@LDFLAGS@"; then
+ LDFLAGS="@LDFLAGS@ $LDFLAGS"
+fi
diff --git a/contrib/depends/config.sub b/contrib/depends/config.sub
new file mode 100755
index 000000000..40ea5dfe1
--- /dev/null
+++ b/contrib/depends/config.sub
@@ -0,0 +1,1836 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright 1992-2017 Free Software Foundation, Inc.
+
+timestamp='2017-04-02'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that
+# program. This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+
+
+# Please send patches to <config-patches@gnu.org>.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright 1992-2017 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help"
+ exit 1 ;;
+
+ *local*)
+ # First pass through any local machine types.
+ echo $1
+ exit ;;
+
+ * )
+ break ;;
+ esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+ exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+ exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
+ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
+ knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \
+ kopensolaris*-gnu* | cloudabi*-eabi* | \
+ storm-chaos* | os2-emx* | rtmk-nova*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ android-linux)
+ os=-linux-android
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple | -axis | -knuth | -cray | -microblaze*)
+ os=
+ basic_machine=$1
+ ;;
+ -bluegene*)
+ os=-cnk
+ ;;
+ -sim | -cisco | -oki | -wec | -winbond)
+ os=
+ basic_machine=$1
+ ;;
+ -scout)
+ ;;
+ -wrs)
+ os=-vxworks
+ basic_machine=$1
+ ;;
+ -chorusos*)
+ os=-chorusos
+ basic_machine=$1
+ ;;
+ -chorusrdb)
+ os=-chorusrdb
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco6)
+ os=-sco5v6
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco5)
+ os=-sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco5v6*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -udk*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*178)
+ os=-lynxos178
+ ;;
+ -lynx*5)
+ os=-lynxos5
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+ -mint | -mint[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ 1750a | 580 \
+ | a29k \
+ | aarch64 | aarch64_be \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | am33_2.0 \
+ | arc | arceb \
+ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
+ | avr | avr32 \
+ | ba \
+ | be32 | be64 \
+ | bfin \
+ | c4x | c8051 | clipper \
+ | d10v | d30v | dlx | dsp16xx \
+ | e2k | epiphany \
+ | fido | fr30 | frv | ft32 \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | hexagon \
+ | i370 | i860 | i960 | ia16 | ia64 \
+ | ip2k | iq2000 \
+ | k1om \
+ | le32 | le64 \
+ | lm32 \
+ | m32c | m32r | m32rle | m68000 | m68k | m88k \
+ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+ | mips64octeon | mips64octeonel \
+ | mips64orion | mips64orionel \
+ | mips64r5900 | mips64r5900el \
+ | mips64vr | mips64vrel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mips64vr5900 | mips64vr5900el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa32r6 | mipsisa32r6el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64r6 | mipsisa64r6el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipsr5900 | mipsr5900el \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | moxie \
+ | mt \
+ | msp430 \
+ | nds32 | nds32le | nds32be \
+ | nios | nios2 | nios2eb | nios2el \
+ | ns16k | ns32k \
+ | open8 | or1k | or1knd | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle \
+ | pru \
+ | pyramid \
+ | riscv32 | riscv64 \
+ | rl78 | rx \
+ | score \
+ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+ | sh64 | sh64le \
+ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+ | spu \
+ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
+ | ubicom32 \
+ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
+ | visium \
+ | wasm32 \
+ | we32k \
+ | x86 | xc16x | xstormy16 | xtensa \
+ | z8k | z80)
+ basic_machine=$basic_machine-unknown
+ ;;
+ c54x)
+ basic_machine=tic54x-unknown
+ ;;
+ c55x)
+ basic_machine=tic55x-unknown
+ ;;
+ c6x)
+ basic_machine=tic6x-unknown
+ ;;
+ leon|leon[3-9])
+ basic_machine=sparc-$basic_machine
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ ;;
+ ms1)
+ basic_machine=mt-unknown
+ ;;
+
+ strongarm | thumb | xscale)
+ basic_machine=arm-unknown
+ ;;
+ xgate)
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ xscaleeb)
+ basic_machine=armeb-unknown
+ ;;
+
+ xscaleel)
+ basic_machine=armel-unknown
+ ;;
+
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ 580-* \
+ | a29k-* \
+ | aarch64-* | aarch64_be-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
+ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
+ | avr-* | avr32-* \
+ | ba-* \
+ | be32-* | be64-* \
+ | bfin-* | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* \
+ | c8051-* | clipper-* | craynv-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | e2k-* | elxsi-* \
+ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | hexagon-* \
+ | i*86-* | i860-* | i960-* | ia16-* | ia64-* \
+ | ip2k-* | iq2000-* \
+ | k1om-* \
+ | le32-* | le64-* \
+ | lm32-* \
+ | m32c-* | m32r-* | m32rle-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
+ | microblaze-* | microblazeel-* \
+ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+ | mips64octeon-* | mips64octeonel-* \
+ | mips64orion-* | mips64orionel-* \
+ | mips64r5900-* | mips64r5900el-* \
+ | mips64vr-* | mips64vrel-* \
+ | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* \
+ | mips64vr5000-* | mips64vr5000el-* \
+ | mips64vr5900-* | mips64vr5900el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa32r2-* | mipsisa32r2el-* \
+ | mipsisa32r6-* | mipsisa32r6el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64r2-* | mipsisa64r2el-* \
+ | mipsisa64r6-* | mipsisa64r6el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipsr5900-* | mipsr5900el-* \
+ | mipstx39-* | mipstx39el-* \
+ | mmix-* \
+ | mt-* \
+ | msp430-* \
+ | nds32-* | nds32le-* | nds32be-* \
+ | nios-* | nios2-* | nios2eb-* | nios2el-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | open8-* \
+ | or1k*-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
+ | pru-* \
+ | pyramid-* \
+ | riscv32-* | riscv64-* \
+ | rl78-* | romp-* | rs6000-* | rx-* \
+ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+ | sparclite-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \
+ | tahoe-* \
+ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+ | tile*-* \
+ | tron-* \
+ | ubicom32-* \
+ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
+ | vax-* \
+ | visium-* \
+ | wasm32-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xc16x-* | xps100-* \
+ | xstormy16-* | xtensa*-* \
+ | ymp-* \
+ | z8k-* | z80-*)
+ ;;
+ # Recognize the basic CPU types without company name, with glob match.
+ xtensa*)
+ basic_machine=$basic_machine-unknown
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 386bsd)
+ basic_machine=i386-unknown
+ os=-bsd
+ ;;
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ abacus)
+ basic_machine=abacus-unknown
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ os=-scout
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amd64)
+ basic_machine=x86_64-pc
+ ;;
+ amd64-*)
+ basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-unknown
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ os=-amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ os=-bsd
+ ;;
+ aros)
+ basic_machine=i386-pc
+ os=-aros
+ ;;
+ asmjs)
+ basic_machine=asmjs-unknown
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ blackfin)
+ basic_machine=bfin-unknown
+ os=-linux
+ ;;
+ blackfin-*)
+ basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ bluegene*)
+ basic_machine=powerpc-ibm
+ os=-cnk
+ ;;
+ c54x-*)
+ basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ c55x-*)
+ basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ c6x-*)
+ basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ c90)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ cegcc)
+ basic_machine=arm-unknown
+ os=-cegcc
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | j90)
+ basic_machine=j90-cray
+ os=-unicos
+ ;;
+ craynv)
+ basic_machine=craynv-cray
+ os=-unicosmp
+ ;;
+ cr16 | cr16-*)
+ basic_machine=cr16-unknown
+ os=-elf
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ crisv32 | crisv32-* | etraxfs*)
+ basic_machine=crisv32-axis
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ crx)
+ basic_machine=crx-unknown
+ os=-elf
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ decsystem10* | dec10*)
+ basic_machine=pdp10-dec
+ os=-tops10
+ ;;
+ decsystem20* | dec20*)
+ basic_machine=pdp10-dec
+ os=-tops20
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ dicos)
+ basic_machine=i686-pc
+ os=-dicos
+ ;;
+ djgpp)
+ basic_machine=i586-pc
+ os=-msdosdjgpp
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ e500v[12])
+ basic_machine=powerpc-unknown
+ os=$os"spe"
+ ;;
+ e500v[12]-*)
+ basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=$os"spe"
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ os=-ose
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ os=-go32
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ os=-xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=-osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=-proelf
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ ;;
+ i*86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i*86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i*86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i*86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ os=-mach
+ ;;
+ i386-vsta | vsta)
+ basic_machine=i386-unknown
+ os=-vsta
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ leon-*|leon[3-9]-*)
+ basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'`
+ ;;
+ m68knommu)
+ basic_machine=m68k-unknown
+ os=-linux
+ ;;
+ m68knommu-*)
+ basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ microblaze*)
+ basic_machine=microblaze-xilinx
+ ;;
+ mingw64)
+ basic_machine=x86_64-pc
+ os=-mingw64
+ ;;
+ mingw32)
+ basic_machine=i686-pc
+ os=-mingw32
+ ;;
+ mingw32ce)
+ basic_machine=arm-unknown
+ os=-mingw32ce
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=-morphos
+ ;;
+ moxiebox)
+ basic_machine=moxie-unknown
+ os=-moxiebox
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ ms1-*)
+ basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+ ;;
+ msys)
+ basic_machine=i686-pc
+ os=-msys
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+ nacl)
+ basic_machine=le32-unknown
+ os=-nacl
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-unknown
+ os=-netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ os=-linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ os=-sysv
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ os=-mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ os=-nonstopux
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ neo-tandem)
+ basic_machine=neo-tandem
+ ;;
+ nse-tandem)
+ basic_machine=nse-tandem
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ nsx-tandem)
+ basic_machine=nsx-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ openrisc | openrisc-*)
+ basic_machine=or32-unknown
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ os=-os400
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=-ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ os=-os68k
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ parisc)
+ basic_machine=hppa-unknown
+ os=-linux
+ ;;
+ parisc-*)
+ basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pc98)
+ basic_machine=i386-pc
+ ;;
+ pc98-*)
+ basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium | p5 | k5 | k6 | nexgen | viac3)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86 | athlon | athlon_*)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2 | pentiumiii | pentium3)
+ basic_machine=i686-pc
+ ;;
+ pentium4)
+ basic_machine=i786-pc
+ ;;
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-* | 6x86-* | athlon-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium4-*)
+ basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=power-ibm
+ ;;
+ ppc | ppcbe) basic_machine=powerpc-unknown
+ ;;
+ ppc-* | ppcbe-*)
+ basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64) basic_machine=powerpc64-unknown
+ ;;
+ ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64le | powerpc64little)
+ basic_machine=powerpc64le-unknown
+ ;;
+ ppc64le-* | powerpc64little-*)
+ basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ os=-pw32
+ ;;
+ rdos | rdos64)
+ basic_machine=x86_64-pc
+ os=-rdos
+ ;;
+ rdos32)
+ basic_machine=i386-pc
+ os=-rdos
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ s390 | s390-*)
+ basic_machine=s390-ibm
+ ;;
+ s390x | s390x-*)
+ basic_machine=s390x-ibm
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ sb1)
+ basic_machine=mipsisa64sb1-unknown
+ ;;
+ sb1el)
+ basic_machine=mipsisa64sb1el-unknown
+ ;;
+ sde)
+ basic_machine=mipsisa32-sde
+ os=-elf
+ ;;
+ sei)
+ basic_machine=mips-sei
+ os=-seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sh5el)
+ basic_machine=sh5le-unknown
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparclite-wrs | simso-wrs)
+ basic_machine=sparclite-wrs
+ os=-vxworks
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ os=-sysv4
+ ;;
+ strongarm-* | thumb-*)
+ basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ os=-unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ os=-unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ os=-unicos
+ ;;
+ tile*)
+ basic_machine=$basic_machine-unknown
+ os=-linux-gnu
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=-tops20
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ os=-tpf
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ os=-none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ wasm32)
+ basic_machine=wasm32-unknown
+ ;;
+ w65*)
+ basic_machine=w65-wdc
+ os=-none
+ ;;
+ w89k-*)
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
+ xbox)
+ basic_machine=i686-pc
+ os=-mingw32
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ xscale-* | xscalee[bl]-*)
+ basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ z80-*-coff)
+ basic_machine=z80-unknown
+ os=-sim
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ basic_machine=hppa1.1-winbond
+ ;;
+ op50n)
+ basic_machine=hppa1.1-oki
+ ;;
+ op60c)
+ basic_machine=hppa1.1-oki
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ mmix)
+ basic_machine=mmix-knuth
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp10)
+ # there are many clones, so DEC is not a safe bet
+ basic_machine=pdp10-unknown
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
+ basic_machine=sh-unknown
+ ;;
+ sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ basic_machine=m68k-apple
+ ;;
+ pmac | pmac-mpw)
+ basic_machine=powerpc-apple
+ ;;
+ *-unknown)
+ # Make sure to match an already-canonicalized machine name.
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -auroraux)
+ os=-auroraux
+ ;;
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
+ | -sym* | -kopensolaris* | -plan9* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* | -aros* | -cloudabi* | -sortix* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+ | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \
+ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -chorusos* | -chorusrdb* | -cegcc* | -glidix* \
+ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
+ | -linux-newlib* | -linux-musl* | -linux-uclibc* \
+ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
+ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \
+ | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -qnx*)
+ case $basic_machine in
+ x86-* | i*86-*)
+ ;;
+ *)
+ os=-nto$os
+ ;;
+ esac
+ ;;
+ -nto-qnx*)
+ ;;
+ -nto*)
+ os=`echo $os | sed -e 's|nto|nto-qnx|'`
+ ;;
+ -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ -linux-dietlibc)
+ os=-linux-dietlibc
+ ;;
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -opened*)
+ os=-openedition
+ ;;
+ -os400*)
+ os=-os400
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -atheos*)
+ os=-atheos
+ ;;
+ -syllable*)
+ os=-syllable
+ ;;
+ -386bsd)
+ os=-bsd
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -nova*)
+ os=-rtmk-nova
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ -nsk*)
+ os=-nsk
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -tpf*)
+ os=-tpf
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -ose*)
+ os=-ose
+ ;;
+ -es1800*)
+ os=-ose
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ os=-mint
+ ;;
+ -aros*)
+ os=-aros
+ ;;
+ -zvmoe)
+ os=-zvmoe
+ ;;
+ -dicos*)
+ os=-dicos
+ ;;
+ -nacl*)
+ ;;
+ -ios)
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ score-*)
+ os=-elf
+ ;;
+ spu-*)
+ os=-elf
+ ;;
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-rebel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
+ c8051-*)
+ os=-elf
+ ;;
+ hexagon-*)
+ os=-elf
+ ;;
+ tic54x-*)
+ os=-coff
+ ;;
+ tic55x-*)
+ os=-coff
+ ;;
+ tic6x-*)
+ os=-coff
+ ;;
+ # This must come before the *-dec entry.
+ pdp10-*)
+ os=-tops20
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ ;;
+ m68*-cisco)
+ os=-aout
+ ;;
+ mep-*)
+ os=-elf
+ ;;
+ mips*-cisco)
+ os=-elf
+ ;;
+ mips*-*)
+ os=-elf
+ ;;
+ or32-*)
+ os=-coff
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ pru-*)
+ os=-elf
+ ;;
+ *-be)
+ os=-beos
+ ;;
+ *-haiku)
+ os=-haiku
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-knuth)
+ os=-mmixware
+ ;;
+ *-wec)
+ os=-proelf
+ ;;
+ *-winbond)
+ os=-proelf
+ ;;
+ *-oki)
+ os=-proelf
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigaos
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f30[01]-fujitsu | f700-fujitsu)
+ os=-uxpv
+ ;;
+ *-rom68k)
+ os=-coff
+ ;;
+ *-*bug)
+ os=-coff
+ ;;
+ *-apple)
+ os=-macos
+ ;;
+ *-atari*)
+ os=-mint
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -cnk*|-aix*)
+ vendor=ibm
+ ;;
+ -beos*)
+ vendor=be
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -mpeix*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs* | -opened*)
+ vendor=ibm
+ ;;
+ -os400*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -tpf*)
+ vendor=ibm
+ ;;
+ -vxsim* | -vxworks* | -windiss*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ -hms*)
+ vendor=hitachi
+ ;;
+ -mpw* | -macos*)
+ vendor=apple
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ vendor=atari
+ ;;
+ -vos*)
+ vendor=stratus
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/contrib/depends/description.md b/contrib/depends/description.md
new file mode 100644
index 000000000..74f9ef3f2
--- /dev/null
+++ b/contrib/depends/description.md
@@ -0,0 +1,53 @@
+This is a system of building and caching dependencies necessary for building Bitcoin.
+There are several features that make it different from most similar systems:
+
+### It is designed to be builder and host agnostic
+
+In theory, binaries for any target OS/architecture can be created, from a
+builder running any OS/architecture. In practice, build-side tools must be
+specified when the defaults don't fit, and packages must be amended to work
+on new hosts. For now, a build architecture of x86_64 is assumed, either on
+Linux or OSX.
+
+### No reliance on timestamps
+
+File presence is used to determine what needs to be built. This makes the
+results distributable and easily digestable by automated builders.
+
+### Each build only has its specified dependencies available at build-time.
+
+For each build, the sysroot is wiped and the (recursive) dependencies are
+installed. This makes each build deterministic, since there will never be any
+unknown files available to cause side-effects.
+
+### Each package is cached and only rebuilt as needed.
+
+Before building, a unique build-id is generated for each package. This id
+consists of a hash of all files used to build the package (Makefiles, packages,
+etc), and as well as a hash of the same data for each recursive dependency. If
+any portion of a package's build recipe changes, it will be rebuilt as well as
+any other package that depends on it. If any of the main makefiles (Makefile,
+funcs.mk, etc) are changed, all packages will be rebuilt. After building, the
+results are cached into a tarball that can be re-used and distributed.
+
+### Package build results are (relatively) deterministic.
+
+Each package is configured and patched so that it will yield the same
+build-results with each consequent build, within a reasonable set of
+constraints. Some things like timestamp insertion are unavoidable, and are
+beyond the scope of this system. Additionally, the toolchain itself must be
+capable of deterministic results. When revisions are properly bumped, a cached
+build should represent an exact single payload.
+
+### Sources are fetched and verified automatically
+
+Each package must define its source location and checksum. The build will fail
+if the fetched source does not match. Sources may be pre-seeded and/or cached
+as desired.
+
+### Self-cleaning
+
+Build and staging dirs are wiped after use, and any previous version of a
+cached result is removed following a successful build. Automated builders
+should be able to build each revision and store the results with no further
+intervention.
diff --git a/contrib/depends/funcs.mk b/contrib/depends/funcs.mk
new file mode 100644
index 000000000..15e404e42
--- /dev/null
+++ b/contrib/depends/funcs.mk
@@ -0,0 +1,245 @@
+define int_vars
+#Set defaults for vars which may be overridden per-package
+$(1)_cc=$($($(1)_type)_CC)
+$(1)_cxx=$($($(1)_type)_CXX)
+$(1)_objc=$($($(1)_type)_OBJC)
+$(1)_objcxx=$($($(1)_type)_OBJCXX)
+$(1)_ar=$($($(1)_type)_AR)
+$(1)_ranlib=$($($(1)_type)_RANLIB)
+$(1)_libtool=$($($(1)_type)_LIBTOOL)
+$(1)_nm=$($($(1)_type)_NM)
+$(1)_cflags=$($($(1)_type)_CFLAGS) $($($(1)_type)_$(release_type)_CFLAGS)
+$(1)_cxxflags=$($($(1)_type)_CXXFLAGS) $($($(1)_type)_$(release_type)_CXXFLAGS)
+$(1)_ldflags=$($($(1)_type)_LDFLAGS) $($($(1)_type)_$(release_type)_LDFLAGS) -L$($($(1)_type)_prefix)/lib
+$(1)_cppflags=$($($(1)_type)_CPPFLAGS) $($($(1)_type)_$(release_type)_CPPFLAGS) -I$($($(1)_type)_prefix)/include
+$(1)_recipe_hash:=
+endef
+
+define int_get_all_dependencies
+$(sort $(foreach dep,$(2),$(2) $(call int_get_all_dependencies,$(1),$($(dep)_dependencies))))
+endef
+
+define fetch_file_inner
+ ( mkdir -p $$($(1)_download_dir) && echo Fetching $(3) from $(2) && \
+ $(build_DOWNLOAD) "$$($(1)_download_dir)/$(4).temp" "$(2)/$(3)" && \
+ echo "$(5) $$($(1)_download_dir)/$(4).temp" > $$($(1)_download_dir)/.$(4).hash && \
+ $(build_SHA256SUM) -c $$($(1)_download_dir)/.$(4).hash && \
+ mv $$($(1)_download_dir)/$(4).temp $$($(1)_source_dir)/$(4) && \
+ rm -rf $$($(1)_download_dir) )
+endef
+
+define fetch_file
+ ( test -f $$($(1)_source_dir)/$(4) || \
+ ( $(call fetch_file_inner,$(1),$(2),$(3),$(4),$(5)) || \
+ $(call fetch_file_inner,$(1),$(FALLBACK_DOWNLOAD_PATH),$(3),$(4),$(5))))
+endef
+
+define int_get_build_recipe_hash
+$(eval $(1)_all_file_checksums:=$(shell $(build_SHA256SUM) $(meta_depends) packages/$(1).mk $(addprefix $(PATCHES_PATH)/$(1)/,$($(1)_patches)) | cut -d" " -f1))
+$(eval $(1)_recipe_hash:=$(shell echo -n "$($(1)_all_file_checksums)" | $(build_SHA256SUM) | cut -d" " -f1))
+endef
+
+define int_get_build_id
+$(eval $(1)_dependencies += $($(1)_$(host_arch)_$(host_os)_dependencies) $($(1)_$(host_os)_dependencies))
+$(eval $(1)_all_dependencies:=$(call int_get_all_dependencies,$(1),$($($(1)_type)_native_toolchain) $($(1)_dependencies)))
+$(foreach dep,$($(1)_all_dependencies),$(eval $(1)_build_id_deps+=$(dep)-$($(dep)_version)-$($(dep)_recipe_hash)))
+$(eval $(1)_build_id_long:=$(1)-$($(1)_version)-$($(1)_recipe_hash)-$(release_type) $($(1)_build_id_deps) $($($(1)_type)_id_string))
+$(eval $(1)_build_id:=$(shell echo -n "$($(1)_build_id_long)" | $(build_SHA256SUM) | cut -c-$(HASH_LENGTH)))
+final_build_id_long+=$($(package)_build_id_long)
+
+#compute package-specific paths
+$(1)_build_subdir?=.
+$(1)_download_file?=$($(1)_file_name)
+$(1)_source_dir:=$(SOURCES_PATH)
+$(1)_source:=$$($(1)_source_dir)/$($(1)_file_name)
+$(1)_staging_dir=$(base_staging_dir)/$(host)/$(1)/$($(1)_version)-$($(1)_build_id)
+$(1)_staging_prefix_dir:=$$($(1)_staging_dir)$($($(1)_type)_prefix)
+$(1)_extract_dir:=$(base_build_dir)/$(host)/$(1)/$($(1)_version)-$($(1)_build_id)
+$(1)_download_dir:=$(base_download_dir)/$(1)-$($(1)_version)
+$(1)_build_dir:=$$($(1)_extract_dir)/$$($(1)_build_subdir)
+$(1)_cached_checksum:=$(BASE_CACHE)/$(host)/$(1)/$(1)-$($(1)_version)-$($(1)_build_id).tar.gz.hash
+$(1)_patch_dir:=$(base_build_dir)/$(host)/$(1)/$($(1)_version)-$($(1)_build_id)/.patches-$($(1)_build_id)
+$(1)_prefixbin:=$($($(1)_type)_prefix)/bin/
+$(1)_cached:=$(BASE_CACHE)/$(host)/$(1)/$(1)-$($(1)_version)-$($(1)_build_id).tar.gz
+$(1)_all_sources=$($(1)_file_name) $($(1)_extra_sources)
+
+#stamps
+$(1)_fetched=$(SOURCES_PATH)/download-stamps/.stamp_fetched-$(1)-$($(1)_file_name).hash
+$(1)_extracted=$$($(1)_extract_dir)/.stamp_extracted
+$(1)_preprocessed=$$($(1)_extract_dir)/.stamp_preprocessed
+$(1)_cleaned=$$($(1)_extract_dir)/.stamp_cleaned
+$(1)_built=$$($(1)_build_dir)/.stamp_built
+$(1)_configured=$$($(1)_build_dir)/.stamp_configured
+$(1)_staged=$$($(1)_staging_dir)/.stamp_staged
+$(1)_postprocessed=$$($(1)_staging_prefix_dir)/.stamp_postprocessed
+$(1)_download_path_fixed=$(subst :,\:,$$($(1)_download_path))
+
+
+#default commands
+$(1)_fetch_cmds ?= $(call fetch_file,$(1),$(subst \:,:,$$($(1)_download_path_fixed)),$$($(1)_download_file),$($(1)_file_name),$($(1)_sha256_hash))
+$(1)_extract_cmds ?= mkdir -p $$($(1)_extract_dir) && echo "$$($(1)_sha256_hash) $$($(1)_source)" > $$($(1)_extract_dir)/.$$($(1)_file_name).hash && $(build_SHA256SUM) -c $$($(1)_extract_dir)/.$$($(1)_file_name).hash && tar --strip-components=1 -xf $$($(1)_source)
+$(1)_preprocess_cmds ?=
+$(1)_build_cmds ?=
+$(1)_config_cmds ?=
+$(1)_stage_cmds ?=
+$(1)_set_vars ?=
+
+
+all_sources+=$$($(1)_fetched)
+endef
+#$(foreach dep_target,$($(1)_all_dependencies),$(eval $(1)_dependency_targets=$($(dep_target)_cached)))
+
+
+define int_config_attach_build_config
+$(eval $(call $(1)_set_vars,$(1)))
+$(1)_cflags+=$($(1)_cflags_$(release_type))
+$(1)_cflags+=$($(1)_cflags_$(host_arch)) $($(1)_cflags_$(host_arch)_$(release_type))
+$(1)_cflags+=$($(1)_cflags_$(host_os)) $($(1)_cflags_$(host_os)_$(release_type))
+$(1)_cflags+=$($(1)_cflags_$(host_arch)_$(host_os)) $($(1)_cflags_$(host_arch)_$(host_os)_$(release_type))
+
+$(1)_cxxflags+=$($(1)_cxxflags_$(release_type))
+$(1)_cxxflags+=$($(1)_cxxflags_$(host_arch)) $($(1)_cxxflags_$(host_arch)_$(release_type))
+$(1)_cxxflags+=$($(1)_cxxflags_$(host_os)) $($(1)_cxxflags_$(host_os)_$(release_type))
+$(1)_cxxflags+=$($(1)_cxxflags_$(host_arch)_$(host_os)) $($(1)_cxxflags_$(host_arch)_$(host_os)_$(release_type))
+
+$(1)_cppflags+=$($(1)_cppflags_$(release_type))
+$(1)_cppflags+=$($(1)_cppflags_$(host_arch)) $($(1)_cppflags_$(host_arch)_$(release_type))
+$(1)_cppflags+=$($(1)_cppflags_$(host_os)) $($(1)_cppflags_$(host_os)_$(release_type))
+$(1)_cppflags+=$($(1)_cppflags_$(host_arch)_$(host_os)) $($(1)_cppflags_$(host_arch)_$(host_os)_$(release_type))
+
+$(1)_ldflags+=$($(1)_ldflags_$(release_type))
+$(1)_ldflags+=$($(1)_ldflags_$(host_arch)) $($(1)_ldflags_$(host_arch)_$(release_type))
+$(1)_ldflags+=$($(1)_ldflags_$(host_os)) $($(1)_ldflags_$(host_os)_$(release_type))
+$(1)_ldflags+=$($(1)_ldflags_$(host_arch)_$(host_os)) $($(1)_ldflags_$(host_arch)_$(host_os)_$(release_type))
+
+$(1)_build_opts+=$$($(1)_build_opts_$(release_type))
+$(1)_build_opts+=$$($(1)_build_opts_$(host_arch)) $$($(1)_build_opts_$(host_arch)_$(release_type))
+$(1)_build_opts+=$$($(1)_build_opts_$(host_os)) $$($(1)_build_opts_$(host_os)_$(release_type))
+$(1)_build_opts+=$$($(1)_build_opts_$(host_arch)_$(host_os)) $$($(1)_build_opts_$(host_arch)_$(host_os)_$(release_type))
+
+$(1)_config_opts+=$$($(1)_config_opts_$(release_type))
+$(1)_config_opts+=$$($(1)_config_opts_$(host_arch)) $$($(1)_config_opts_$(host_arch)_$(release_type))
+$(1)_config_opts+=$$($(1)_config_opts_$(host_os)) $$($(1)_config_opts_$(host_os)_$(release_type))
+$(1)_config_opts+=$$($(1)_config_opts_$(host_arch)_$(host_os)) $$($(1)_config_opts_$(host_arch)_$(host_os)_$(release_type))
+
+$(1)_config_env+=$$($(1)_config_env_$(release_type))
+$(1)_config_env+=$($(1)_config_env_$(host_arch)) $($(1)_config_env_$(host_arch)_$(release_type))
+$(1)_config_env+=$($(1)_config_env_$(host_os)) $($(1)_config_env_$(host_os)_$(release_type))
+$(1)_config_env+=$($(1)_config_env_$(host_arch)_$(host_os)) $($(1)_config_env_$(host_arch)_$(host_os)_$(release_type))
+
+$(1)_config_env+=PKG_CONFIG_LIBDIR=$($($(1)_type)_prefix)/lib/pkgconfig
+$(1)_config_env+=PKG_CONFIG_PATH=$($($(1)_type)_prefix)/share/pkgconfig
+$(1)_config_env+=PATH=$(build_prefix)/bin:$(PATH)
+$(1)_build_env+=PATH=$(build_prefix)/bin:$(PATH)
+$(1)_stage_env+=PATH=$(build_prefix)/bin:$(PATH)
+$(1)_autoconf=./configure --host=$($($(1)_type)_host) --disable-dependency-tracking --prefix=$($($(1)_type)_prefix) $$($(1)_config_opts) CC="$$($(1)_cc)" CXX="$$($(1)_cxx)"
+
+ifneq ($($(1)_nm),)
+$(1)_autoconf += NM="$$($(1)_nm)"
+endif
+ifneq ($($(1)_ranlib),)
+$(1)_autoconf += RANLIB="$$($(1)_ranlib)"
+endif
+ifneq ($($(1)_ar),)
+$(1)_autoconf += AR="$$($(1)_ar)"
+endif
+ifneq ($($(1)_cflags),)
+$(1)_autoconf += CFLAGS="$$($(1)_cflags)"
+endif
+ifneq ($($(1)_cxxflags),)
+$(1)_autoconf += CXXFLAGS="$$($(1)_cxxflags)"
+endif
+ifneq ($($(1)_cppflags),)
+$(1)_autoconf += CPPFLAGS="$$($(1)_cppflags)"
+endif
+ifneq ($($(1)_ldflags),)
+$(1)_autoconf += LDFLAGS="$$($(1)_ldflags)"
+endif
+endef
+
+define int_add_cmds
+$($(1)_fetched):
+ $(AT)mkdir -p $$(@D) $(SOURCES_PATH)
+ $(AT)rm -f $$@
+ $(AT)touch $$@
+ $(AT)cd $$(@D); $(call $(1)_fetch_cmds,$(1))
+ $(AT)cd $($(1)_source_dir); $(foreach source,$($(1)_all_sources),$(build_SHA256SUM) $(source) >> $$(@);)
+ $(AT)touch $$@
+$($(1)_extracted): | $($(1)_fetched)
+ $(AT)echo Extracting $(1)...
+ $(AT)mkdir -p $$(@D)
+ $(AT)cd $$(@D); $(call $(1)_extract_cmds,$(1))
+ $(AT)touch $$@
+$($(1)_preprocessed): | $($(1)_dependencies) $($(1)_extracted)
+ $(AT)echo Preprocessing $(1)...
+ $(AT)mkdir -p $$(@D) $($(1)_patch_dir)
+ $(AT)$(foreach patch,$($(1)_patches),cd $(PATCHES_PATH)/$(1); cp $(patch) $($(1)_patch_dir) ;)
+ $(AT)cd $$(@D); $(call $(1)_preprocess_cmds, $(1))
+ $(AT)touch $$@
+$($(1)_configured): | $($(1)_preprocessed)
+ $(AT)echo Configuring $(1)...
+ $(AT)rm -rf $(host_prefix); mkdir -p $(host_prefix)/lib; cd $(host_prefix); $(foreach package,$($(1)_all_dependencies), tar xf $($(package)_cached); )
+ $(AT)mkdir -p $$(@D)
+ $(AT)+cd $$(@D); $($(1)_config_env) $(call $(1)_config_cmds, $(1))
+ $(AT)touch $$@
+$($(1)_built): | $($(1)_configured)
+ $(AT)echo Building $(1)...
+ $(AT)mkdir -p $$(@D)
+ $(AT)+cd $$(@D); $($(1)_build_env) $(call $(1)_build_cmds, $(1))
+ $(AT)touch $$@
+$($(1)_staged): | $($(1)_built)
+ $(AT)echo Staging $(1)...
+ $(AT)mkdir -p $($(1)_staging_dir)/$(host_prefix)
+ $(AT)cd $($(1)_build_dir); $($(1)_stage_env) $(call $(1)_stage_cmds, $(1))
+ $(AT)rm -rf $($(1)_extract_dir)
+ $(AT)touch $$@
+$($(1)_postprocessed): | $($(1)_staged)
+ $(AT)echo Postprocessing $(1)...
+ $(AT)cd $($(1)_staging_prefix_dir); $(call $(1)_postprocess_cmds)
+ $(AT)touch $$@
+$($(1)_cached): | $($(1)_dependencies) $($(1)_postprocessed)
+ $(AT)echo Caching $(1)...
+ $(AT)cd $$($(1)_staging_dir)/$(host_prefix); find . | sort | tar --no-recursion -czf $$($(1)_staging_dir)/$$(@F) -T -
+ $(AT)mkdir -p $$(@D)
+ $(AT)rm -rf $$(@D) && mkdir -p $$(@D)
+ $(AT)mv $$($(1)_staging_dir)/$$(@F) $$(@)
+ $(AT)rm -rf $($(1)_staging_dir)
+$($(1)_cached_checksum): $($(1)_cached)
+ $(AT)cd $$(@D); $(build_SHA256SUM) $$(<F) > $$(@)
+
+.PHONY: $(1)
+$(1): | $($(1)_cached_checksum)
+.SECONDARY: $($(1)_cached) $($(1)_postprocessed) $($(1)_staged) $($(1)_built) $($(1)_configured) $($(1)_preprocessed) $($(1)_extracted) $($(1)_fetched)
+
+endef
+
+# These functions create the build targets for each package. They must be
+# broken down into small steps so that each part is done for all packages
+# before moving on to the next step. Otherwise, a package's info
+# (build-id for example) would only be available to another package if it
+# happened to be computed already.
+
+#set the type for host/build packages.
+$(foreach native_package,$(native_packages),$(eval $(native_package)_type=build))
+$(foreach package,$(packages),$(eval $(package)_type=$(host_arch)_$(host_os)))
+
+#set overridable defaults
+$(foreach package,$(all_packages),$(eval $(call int_vars,$(package))))
+
+#include package files
+$(foreach package,$(all_packages),$(eval include packages/$(package).mk))
+
+#compute a hash of all files that comprise this package's build recipe
+$(foreach package,$(all_packages),$(eval $(call int_get_build_recipe_hash,$(package))))
+
+#generate a unique id for this package, incorporating its dependencies as well
+$(foreach package,$(all_packages),$(eval $(call int_get_build_id,$(package))))
+
+#compute final vars after reading package vars
+$(foreach package,$(all_packages),$(eval $(call int_config_attach_build_config,$(package))))
+
+#create build targets
+$(foreach package,$(all_packages),$(eval $(call int_add_cmds,$(package))))
+
+#special exception: if a toolchain package exists, all non-native packages depend on it
+$(foreach package,$(packages),$(eval $($(package)_unpacked): |$($($(host_arch)_$(host_os)_native_toolchain)_cached) ))
diff --git a/contrib/depends/hosts/darwin.mk b/contrib/depends/hosts/darwin.mk
new file mode 100644
index 000000000..4e58bec74
--- /dev/null
+++ b/contrib/depends/hosts/darwin.mk
@@ -0,0 +1,17 @@
+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_CFLAGS=-pipe
+darwin_CXXFLAGS=$(darwin_CFLAGS)
+
+darwin_release_CFLAGS=-O2
+darwin_release_CXXFLAGS=$(darwin_release_CFLAGS)
+
+darwin_debug_CFLAGS=-O1
+darwin_debug_CXXFLAGS=$(darwin_debug_CFLAGS)
+
+darwin_native_toolchain=native_cctools
diff --git a/contrib/depends/hosts/default.mk b/contrib/depends/hosts/default.mk
new file mode 100644
index 000000000..6f60d6b3f
--- /dev/null
+++ b/contrib/depends/hosts/default.mk
@@ -0,0 +1,26 @@
+default_host_CC = $(host_toolchain)gcc
+default_host_CXX = $(host_toolchain)g++
+default_host_AR = $(host_toolchain)ar
+default_host_RANLIB = $(host_toolchain)ranlib
+default_host_STRIP = $(host_toolchain)strip
+default_host_LIBTOOL = $(host_toolchain)libtool
+default_host_INSTALL_NAME_TOOL = $(host_toolchain)install_name_tool
+default_host_OTOOL = $(host_toolchain)otool
+default_host_NM = $(host_toolchain)nm
+
+define add_host_tool_func
+$(host_os)_$1?=$$(default_host_$1)
+$(host_arch)_$(host_os)_$1?=$$($(host_os)_$1)
+$(host_arch)_$(host_os)_$(release_type)_$1?=$$($(host_os)_$1)
+host_$1=$$($(host_arch)_$(host_os)_$1)
+endef
+
+define add_host_flags_func
+$(host_arch)_$(host_os)_$1 += $($(host_os)_$1)
+$(host_arch)_$(host_os)_$(release_type)_$1 += $($(host_os)_$(release_type)_$1)
+host_$1 = $$($(host_arch)_$(host_os)_$1)
+host_$(release_type)_$1 = $$($(host_arch)_$(host_os)_$(release_type)_$1)
+endef
+
+$(foreach tool,CC CXX AR RANLIB STRIP NM LIBTOOL OTOOL INSTALL_NAME_TOOL,$(eval $(call add_host_tool_func,$(tool))))
+$(foreach flags,CFLAGS CXXFLAGS CPPFLAGS LDFLAGS, $(eval $(call add_host_flags_func,$(flags))))
diff --git a/contrib/depends/hosts/linux.mk b/contrib/depends/hosts/linux.mk
new file mode 100644
index 000000000..b13a0f1ad
--- /dev/null
+++ b/contrib/depends/hosts/linux.mk
@@ -0,0 +1,31 @@
+linux_CFLAGS=-pipe
+linux_CXXFLAGS=$(linux_CFLAGS)
+
+linux_release_CFLAGS=-O2
+linux_release_CXXFLAGS=$(linux_release_CFLAGS)
+
+linux_debug_CFLAGS=-O1
+linux_debug_CXXFLAGS=$(linux_debug_CFLAGS)
+
+linux_debug_CPPFLAGS=-D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC
+
+ifeq (86,$(findstring 86,$(build_arch)))
+i686_linux_CC=gcc -m32
+i686_linux_CXX=g++ -m32
+i686_linux_AR=ar
+i686_linux_RANLIB=ranlib
+i686_linux_NM=nm
+i686_linux_STRIP=strip
+
+x86_64_linux_CC=gcc -m64
+x86_64_linux_CXX=g++ -m64
+x86_64_linux_AR=ar
+x86_64_linux_RANLIB=ranlib
+x86_64_linux_NM=nm
+x86_64_linux_STRIP=strip
+else
+i686_linux_CC=$(default_host_CC) -m32
+i686_linux_CXX=$(default_host_CXX) -m32
+x86_64_linux_CC=$(default_host_CC) -m64
+x86_64_linux_CXX=$(default_host_CXX) -m64
+endif
diff --git a/contrib/depends/hosts/mingw32.mk b/contrib/depends/hosts/mingw32.mk
new file mode 100644
index 000000000..dbfb62fdc
--- /dev/null
+++ b/contrib/depends/hosts/mingw32.mk
@@ -0,0 +1,10 @@
+mingw32_CFLAGS=-pipe
+mingw32_CXXFLAGS=$(mingw32_CFLAGS)
+
+mingw32_release_CFLAGS=-O2
+mingw32_release_CXXFLAGS=$(mingw32_release_CFLAGS)
+
+mingw32_debug_CFLAGS=-O1
+mingw32_debug_CXXFLAGS=$(mingw32_debug_CFLAGS)
+
+mingw32_debug_CPPFLAGS=-D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC
diff --git a/contrib/depends/packages.md b/contrib/depends/packages.md
new file mode 100644
index 000000000..7c8036250
--- /dev/null
+++ b/contrib/depends/packages.md
@@ -0,0 +1,147 @@
+Each recipe consists of 3 main parts: defining identifiers, setting build
+variables, and defining build commands.
+
+The package "mylib" will be used here as an example
+
+General tips:
+- mylib_foo is written as $(package)_foo in order to make recipes more similar.
+
+## Identifiers
+Each package is required to define at least these variables:
+
+ $(package)_version:
+ Version of the upstream library or program. If there is no version, a
+ placeholder such as 1.0 can be used.
+
+ $(package)_download_path:
+ Location of the upstream source, without the file-name. Usually http or
+ ftp.
+
+ $(package)_file_name:
+ The upstream source filename available at the download path.
+
+ $(package)_sha256_hash:
+ The sha256 hash of the upstream file
+
+These variables are optional:
+
+ $(package)_build_subdir:
+ cd to this dir before running configure/build/stage commands.
+
+ $(package)_download_file:
+ The file-name of the upstream source if it differs from how it should be
+ stored locally. This can be used to avoid storing file-names with strange
+ characters.
+
+ $(package)_dependencies:
+ Names of any other packages that this one depends on.
+
+ $(package)_patches:
+ Filenames of any patches needed to build the package
+
+ $(package)_extra_sources:
+ Any extra files that will be fetched via $(package)_fetch_cmds. These are
+ specified so that they can be fetched and verified via 'make download'.
+
+
+## Build Variables:
+After defining the main identifiers, build variables may be added or customized
+before running the build commands. They should be added to a function called
+$(package)_set_vars. For example:
+
+ define $(package)_set_vars
+ ...
+ endef
+
+Most variables can be prefixed with the host, architecture, or both, to make
+the modifications specific to that case. For example:
+
+ Universal: $(package)_cc=gcc
+ Linux only: $(package)_linux_cc=gcc
+ x86_64 only: $(package)_x86_64_cc = gcc
+ x86_64 linux only: $(package)_x86_64_linux_cc = gcc
+
+These variables may be set to override or append their default values.
+
+ $(package)_cc
+ $(package)_cxx
+ $(package)_objc
+ $(package)_objcxx
+ $(package)_ar
+ $(package)_ranlib
+ $(package)_libtool
+ $(package)_nm
+ $(package)_cflags
+ $(package)_cxxflags
+ $(package)_ldflags
+ $(package)_cppflags
+ $(package)_config_env
+ $(package)_build_env
+ $(package)_stage_env
+ $(package)_build_opts
+ $(package)_config_opts
+
+The *_env variables are used to add environment variables to the respective
+commands.
+
+Many variables respect a debug/release suffix as well, in order to use them for
+only the appropriate build config. For example:
+
+ $(package)_cflags_release = -O3
+ $(package)_cflags_i686_debug = -g
+ $(package)_config_opts_release = --disable-debug
+
+These will be used in addition to the options that do not specify
+debug/release. All builds are considered to be release unless DEBUG=1 is set by
+the user. Other variables may be defined as needed.
+
+## Build commands:
+
+ For each build, a unique build dir and staging dir are created. For example,
+ `work/build/mylib/1.0-1adac830f6e` and `work/staging/mylib/1.0-1adac830f6e`.
+
+ The following build commands are available for each recipe:
+
+ $(package)_fetch_cmds:
+ Runs from: build dir
+ Fetch the source file. If undefined, it will be fetched and verified
+ against its hash.
+
+ $(package)_extract_cmds:
+ Runs from: build dir
+ Verify the source file against its hash and extract it. If undefined, the
+ source is assumed to be a tarball.
+
+ $(package)_preprocess_cmds:
+ Runs from: build dir/$(package)_build_subdir
+ Preprocess the source as necessary. If undefined, does nothing.
+
+ $(package)_config_cmds:
+ Runs from: build dir/$(package)_build_subdir
+ Configure the source. If undefined, does nothing.
+
+ $(package)_build_cmds:
+ Runs from: build dir/$(package)_build_subdir
+ Build the source. If undefined, does nothing.
+
+ $(package)_stage_cmds:
+ Runs from: build dir/$(package)_build_subdir
+ Stage the build results. If undefined, does nothing.
+
+ The following variables are available for each recipe:
+
+ $(1)_staging_dir: package's destination sysroot path
+ $(1)_staging_prefix_dir: prefix path inside of the package's staging dir
+ $(1)_extract_dir: path to the package's extracted sources
+ $(1)_build_dir: path where configure/build/stage commands will be run
+ $(1)_patch_dir: path where the package's patches (if any) are found
+
+Notes on build commands:
+
+For packages built with autotools, $($(package)_autoconf) can be used in the
+configure step to (usually) correctly configure automatically. Any
+$($(package)_config_opts) will be appended.
+
+Most autotools projects can be properly staged using:
+
+ $(MAKE) DESTDIR=$($(package)_staging_dir) install
diff --git a/contrib/depends/packages/bdb.mk b/contrib/depends/packages/bdb.mk
new file mode 100644
index 000000000..6c9876c2c
--- /dev/null
+++ b/contrib/depends/packages/bdb.mk
@@ -0,0 +1,31 @@
+package=bdb
+$(package)_version=4.8.30
+$(package)_download_path=http://download.oracle.com/berkeley-db
+$(package)_file_name=db-$($(package)_version).NC.tar.gz
+$(package)_sha256_hash=12edc0df75bf9abd7f82f821795bcee50f42cb2e5f76a6a281b85732798364ef
+$(package)_build_subdir=build_unix
+
+define $(package)_set_vars
+$(package)_config_opts=--disable-shared --enable-cxx --disable-replication
+$(package)_config_opts_mingw32=--enable-mingw
+$(package)_config_opts_linux=--with-pic
+$(package)_cxxflags=-std=c++11
+endef
+
+define $(package)_preprocess_cmds
+ sed -i.old 's/__atomic_compare_exchange/__atomic_compare_exchange_db/' dbinc/atomic.h && \
+ sed -i.old 's/atomic_init/atomic_init_db/' dbinc/atomic.h mp/mp_region.c mp/mp_mvcc.c mp/mp_fget.c mutex/mut_method.c mutex/mut_tas.c && \
+ cp -f $(BASEDIR)/config.guess $(BASEDIR)/config.sub dist
+endef
+
+define $(package)_config_cmds
+ ../dist/$($(package)_autoconf)
+endef
+
+define $(package)_build_cmds
+ $(MAKE) libdb_cxx-4.8.a libdb-4.8.a
+endef
+
+define $(package)_stage_cmds
+ $(MAKE) DESTDIR=$($(package)_staging_dir) install_lib install_include
+endef
diff --git a/contrib/depends/packages/boost.mk b/contrib/depends/packages/boost.mk
new file mode 100644
index 000000000..89db5a415
--- /dev/null
+++ b/contrib/depends/packages/boost.mk
@@ -0,0 +1,41 @@
+package=boost
+$(package)_version=1_64_0
+$(package)_download_path=https://dl.bintray.com/boostorg/release/1.64.0/source/
+$(package)_file_name=$(package)_$($(package)_version).tar.bz2
+$(package)_sha256_hash=7bcc5caace97baa948931d712ea5f37038dbb1c5d89b43ad4def4ed7cb683332
+
+define $(package)_set_vars
+$(package)_config_opts_release=variant=release
+$(package)_config_opts_debug=variant=debug
+$(package)_config_opts=--layout=tagged --build-type=complete --user-config=user-config.jam
+$(package)_config_opts+=threading=multi link=static -sNO_BZIP2=1 -sNO_ZLIB=1
+$(package)_config_opts_linux=threadapi=pthread runtime-link=shared
+$(package)_config_opts_darwin=--toolset=darwin-4.2.1 runtime-link=shared
+$(package)_config_opts_mingw32=binary-format=pe target-os=windows threadapi=win32 runtime-link=static
+$(package)_config_opts_x86_64_mingw32=address-model=64
+$(package)_config_opts_i686_mingw32=address-model=32
+$(package)_config_opts_i686_linux=address-model=32 architecture=x86
+$(package)_toolset_$(host_os)=gcc
+$(package)_archiver_$(host_os)=$($(package)_ar)
+$(package)_toolset_darwin=darwin
+$(package)_archiver_darwin=$($(package)_libtool)
+$(package)_config_libraries=chrono,filesystem,program_options,system,thread,test,date_time,regex,serialization,locale
+$(package)_cxxflags=-std=c++11 -fvisibility=hidden
+$(package)_cxxflags_linux=-fPIC
+endef
+
+define $(package)_preprocess_cmds
+ echo "using $(boost_toolset_$(host_os)) : : $($(package)_cxx) : <cxxflags>\"$($(package)_cxxflags) $($(package)_cppflags)\" <linkflags>\"$($(package)_ldflags)\" <archiver>\"$(boost_archiver_$(host_os))\" <striper>\"$(host_STR IP)\" <ranlib>\"$(host_RANLIB)\" <rc>\"$(host_WINDRES)\" : ;" > user-config.jam
+endef
+
+define $(package)_config_cmds
+ ./bootstrap.sh --without-icu --with-libraries=$(boost_config_libraries)
+endef
+
+define $(package)_build_cmds
+ ./b2 -d2 -j2 -d1 --prefix=$($(package)_staging_prefix_dir) $($(package)_config_opts) stage
+endef
+
+define $(package)_stage_cmds
+ ./b2 -d0 -j4 --prefix=$($(package)_staging_prefix_dir) $($(package)_config_opts) install
+endef
diff --git a/contrib/depends/packages/cmake/conf/mxe-conf.cmake.in b/contrib/depends/packages/cmake/conf/mxe-conf.cmake.in
new file mode 100644
index 000000000..8bd4cf1f7
--- /dev/null
+++ b/contrib/depends/packages/cmake/conf/mxe-conf.cmake.in
@@ -0,0 +1,67 @@
+# This file is part of MXE. See LICENSE.md for licensing information.
+
+# https://cmake.org/cmake/help/latest
+
+# Can't set `cmake_minimum_required` or `cmake_policy` in toolchain
+# since toolchain is read before CMakeLists.txt
+# See `target-cmake.in` for CMAKE_POLICY_DEFAULT_CMPNNNN
+
+# Check if we are using mxe supplied version
+# - toolchain is included multiple times so set a guard in
+# environment to suppress duplicate messages
+if(NOT ${CMAKE_COMMAND} STREQUAL @PREFIX@/@BUILD@/bin/cmake AND NOT DEFINED ENV{_MXE_CMAKE_TOOLCHAIN_INCLUDED})
+ message(WARNING "
+** Warning: direct use of toolchain file is deprecated
+** Please use prefixed wrapper script instead:
+ @TARGET@-cmake [options] <path-to-source>
+ - uses mxe supplied cmake version @CMAKE_VERSION@
+ - loads toolchain
+ - loads common run results
+ - sets various policy defaults
+ ")
+ set(ENV{_MXE_CMAKE_TOOLCHAIN_INCLUDED} TRUE)
+endif()
+
+## General configuration
+set(CMAKE_SYSTEM_NAME Windows)
+set(MSYS 1)
+set(CMAKE_EXPORT_NO_PACKAGE_REGISTRY ON)
+# Workaround for https://www.cmake.org/Bug/view.php?id=14075
+set(CMAKE_CROSS_COMPILING ON)
+
+
+## Library config
+set(BUILD_SHARED_LIBS @CMAKE_SHARED_BOOL@ CACHE BOOL "BUILD_SHARED_LIBS" FORCE)
+set(BUILD_STATIC_LIBS @CMAKE_STATIC_BOOL@ CACHE BOOL "BUILD_STATIC_LIBS" FORCE)
+set(BUILD_SHARED @CMAKE_SHARED_BOOL@ CACHE BOOL "BUILD_SHARED" FORCE)
+set(BUILD_STATIC @CMAKE_STATIC_BOOL@ CACHE BOOL "BUILD_STATIC" FORCE)
+set(LIBTYPE @LIBTYPE@)
+
+
+## Paths etc.
+set(CMAKE_FIND_ROOT_PATH @PREFIX@/@TARGET@)
+set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+set(CMAKE_PREFIX_PATH @PREFIX@/@TARGET@)
+set(CMAKE_INSTALL_PREFIX @PREFIX@/@TARGET@ CACHE PATH "Installation Prefix")
+# For custom mxe FindPackage scripts
+set(CMAKE_MODULE_PATH "@PREFIX@/share/cmake/modules" ${CMAKE_MODULE_PATH})
+
+
+## Programs
+set(CMAKE_C_COMPILER @PREFIX@/bin/@TARGET@-gcc)
+set(CMAKE_CXX_COMPILER @PREFIX@/bin/@TARGET@-g++)
+set(CMAKE_Fortran_COMPILER @PREFIX@/bin/@TARGET@-gfortran)
+set(CMAKE_RC_COMPILER @PREFIX@/bin/@TARGET@-windres)
+# CMAKE_RC_COMPILE_OBJECT is defined in:
+# <cmake root>/share/cmake-X.Y/Modules/Platform/Windows-windres.cmake
+set(CPACK_NSIS_EXECUTABLE @TARGET@-makensis)
+
+## Individual package configuration
+file(GLOB mxe_cmake_files
+ "@CMAKE_TOOLCHAIN_DIR@/*.cmake"
+)
+foreach(mxe_cmake_file ${mxe_cmake_files})
+ include(${mxe_cmake_file})
+endforeach()
diff --git a/contrib/depends/packages/cmake/conf/target-cmake.in b/contrib/depends/packages/cmake/conf/target-cmake.in
new file mode 100644
index 000000000..a78bcf58d
--- /dev/null
+++ b/contrib/depends/packages/cmake/conf/target-cmake.in
@@ -0,0 +1,29 @@
+#!/usr/bin/env bash
+echo "== Using MXE wrapper: @PREFIX@/bin/@TARGET@-cmake"
+
+# https://cmake.org/cmake/help/latest/manual/cmake-policies.7.html
+# https://cmake.org/cmake/help/latest/variable/CMAKE_POLICY_DEFAULT_CMPNNNN.html
+POLICIES=(0017,0020)
+
+unset NO_MXE_TOOLCHAIN
+if echo -- "$@" | grep -Ewq "(--build|-E|--system-information)" ; then
+ NO_MXE_TOOLCHAIN=1
+fi
+if [[ "$NO_MXE_TOOLCHAIN" == "1" ]]; then
+ echo "== Skip using MXE toolchain: @CMAKE_TOOLCHAIN_FILE@"
+ # see https://github.com/mxe/mxe/issues/932
+ exec "@PREFIX@/@BUILD@/bin/cmake" "$@"
+else
+ echo " - cmake version @CMAKE_VERSION@"
+ echo " - warnings for unused CMAKE_POLICY_DEFAULT variables can be ignored"
+ echo "== Using MXE toolchain: @CMAKE_TOOLCHAIN_FILE@"
+ echo "== Using MXE runresult: @CMAKE_RUNRESULT_FILE@"
+ if ! ( echo "$@" | grep --silent "DCMAKE_BUILD_TYPE" ) ; then
+ echo '== Adding "-DCMAKE_BUILD_TYPE=Release"'
+ set -- "-DCMAKE_BUILD_TYPE=Release" "$@"
+ fi
+ exec "@PREFIX@/@BUILD@/bin/cmake" \
+ -DCMAKE_TOOLCHAIN_FILE="@CMAKE_TOOLCHAIN_FILE@" \
+ `eval echo -DCMAKE_POLICY_DEFAULT_CMP{$POLICIES}=NEW` \
+ -C"@CMAKE_RUNRESULT_FILE@" "$@"
+fi
diff --git a/contrib/depends/packages/cmake/test/CMakeLists.txt b/contrib/depends/packages/cmake/test/CMakeLists.txt
new file mode 100644
index 000000000..6075a8f5a
--- /dev/null
+++ b/contrib/depends/packages/cmake/test/CMakeLists.txt
@@ -0,0 +1,18 @@
+# This file is part of MXE. See LICENSE.md for licensing information.
+
+# 2.8.9 is Debian Wheezy version
+cmake_minimum_required(VERSION 2.8.9)
+
+# use default C and CXX languages
+project(mxe)
+
+# see cmake --help-policy <cmp> for details
+cmake_policy(SET CMP0017 NEW)
+if (POLICY CMP0020)
+ cmake_policy(SET CMP0020 NEW)
+endif()
+
+# so we can find pkg-test.cmake files to include
+set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/../.. ${CMAKE_MODULE_PATH})
+
+include(${PKG}-test)
diff --git a/contrib/depends/packages/cppzmq.mk b/contrib/depends/packages/cppzmq.mk
new file mode 100644
index 000000000..6c0faf084
--- /dev/null
+++ b/contrib/depends/packages/cppzmq.mk
@@ -0,0 +1,15 @@
+package=cppzmq
+$(package)_version=4.2.3
+$(package)_download_path=https://github.com/zeromq/cppzmq/archive/
+$(package)_file_name=v$($(package)_version).tar.gz
+$(package)_sha256_hash=3e6b57bf49115f4ae893b1ff7848ead7267013087dc7be1ab27636a97144d373
+$(package)_dependencies=zeromq
+
+define $(package)_stage_cmds
+ mkdir $($(package)_staging_prefix_dir)/include &&\
+ cp zmq.hpp $($(package)_staging_prefix_dir)/include
+endef
+
+define $(package)_postprocess_cmds
+ rm -rf bin share
+endef
diff --git a/contrib/depends/packages/expat.mk b/contrib/depends/packages/expat.mk
new file mode 100644
index 000000000..bd2cea1b6
--- /dev/null
+++ b/contrib/depends/packages/expat.mk
@@ -0,0 +1,22 @@
+package=expat
+$(package)_version=2.2.4
+$(package)_download_path=https://downloads.sourceforge.net/project/expat/expat/$($(package)_version)
+$(package)_file_name=$(package)-$($(package)_version).tar.bz2
+$(package)_sha256_hash=03ad85db965f8ab2d27328abcf0bc5571af6ec0a414874b2066ee3fdd372019e
+
+define $(package)_set_vars
+$(package)_config_opts=--enable-static
+$(package)_config_opts+=--prefix=$(host_prefix)
+endef
+
+define $(package)_config_cmds
+ $($(package)_autoconf) $($(package)_config_opts)
+endef
+
+define $(package)_build_cmds
+ $(MAKE)
+endef
+
+define $(package)_stage_cmds
+ $(MAKE) DESTDIR=$($(package)_staging_dir) install
+endef
diff --git a/contrib/depends/packages/graphviz.mk b/contrib/depends/packages/graphviz.mk
new file mode 100644
index 000000000..1c4bc1b71
--- /dev/null
+++ b/contrib/depends/packages/graphviz.mk
@@ -0,0 +1,30 @@
+package=graphviz
+$(package)_version=2.40.1
+$(package)_download_path=www.graphviz.org/pub/graphviz/stable/SOURCES/
+$(package)_file_name=$(package)-$($(package)_version).tar.gz
+$(package)_sha256_hash=ca5218fade0204d59947126c38439f432853543b0818d9d728c589dfe7f3a421
+
+define $(package)_preprocess_cmds
+ ./autogen.sh
+endef
+
+define $(package)_set_vars
+ $(package)_config_opts=--disable-shared --enable-multibye --without-purify --without-curses
+ $(package)_config_opts_release=--disable-debug-mode
+ $(package)_config_opts_linux=--with-pic
+endef
+
+define $(package)_config_cmds
+ $($(package)_autoconf)
+endef
+
+define $(package)_build_cmds
+ $(MAKE)
+endef
+
+define $(package)_stage_cmds
+ $(MAKE) DESTDIR=$($(package)_staging_dir) install
+endef
+
+define $(package)_postprocess_cmds
+endef
diff --git a/contrib/depends/packages/icu4c.mk b/contrib/depends/packages/icu4c.mk
new file mode 100644
index 000000000..7e092425e
--- /dev/null
+++ b/contrib/depends/packages/icu4c.mk
@@ -0,0 +1,32 @@
+package=icu4c
+$(package)_version=55.1
+$(package)_download_path=https://github.com/TheCharlatan/icu4c/archive
+$(package)_file_name=55.1.tar.gz
+$(package)_sha256_hash=1f912c54035533fb4268809701d65c7468d00e292efbc31e6444908450cc46ef
+$(package)_patches=icu-001-dont-build-static-dynamic-twice.patch
+
+define $(package)_set_vars
+ $(package)_build_opts=CFLAGS="$($(package)_cflags) $($(package)_cppflags) -DU_USING_ICU_NAMESPACE=0 --std=gnu++0x -DU_STATIC_IMPLEMENTATION -DU_COMBINED_IMPLEMENTATION -fPIC"
+endef
+
+define $(package)_config_cmds
+ patch -p1 < $($(package)_patch_dir)/icu-001-dont-build-static-dynamic-twice.patch &&\
+ mkdir builda &&\
+ mkdir buildb &&\
+ cd builda &&\
+ sh ../source/runConfigureICU Linux &&\
+ make &&\
+ cd ../buildb &&\
+ sh ../source/$($(package)_autoconf) --enable-static=yes --enable-shared=yes --disable-layoutex --prefix=$(host_prefix) --with-cross-build=`pwd`/../builda &&\
+ $(MAKE) $($(package)_build_opts)
+endef
+
+#define $(package)_build_cmds
+# cd source &&\
+ $(MAKE) $($((package)_build_opts) `nproc`
+#endef
+
+define $(package)_stage_cmds
+ cd buildb &&\
+ $(MAKE) $($(package)_build_opts) DESTDIR=$($(package)_staging_dir) install lib/*
+endef
diff --git a/contrib/depends/packages/ldns.mk b/contrib/depends/packages/ldns.mk
new file mode 100644
index 000000000..a9565a581
--- /dev/null
+++ b/contrib/depends/packages/ldns.mk
@@ -0,0 +1,28 @@
+package=ldns
+$(package)_version=1.6.17
+$(package)_download_path=http://www.nlnetlabs.nl/downloads/ldns/
+$(package)_file_name=$(package)-$($(package)_version).tar.gz
+$(package)_sha256_hash=8b88e059452118e8949a2752a55ce59bc71fa5bc414103e17f5b6b06f9bcc8cd
+$(package)_dependencies=openssl
+
+define $(package)_set_vars
+ $(package)_config_opts=--disable-shared --enable-static --disable-dane-ta-usage --with-drill
+ $(package)_config_opts=--with-ssl=$(host_prefix)
+ $(package)_config_opts_release=--disable-debug-mode
+ $(package)_config_opts_linux=--with-pic
+endef
+
+define $(package)_config_cmds
+ $($(package)_autoconf)
+endef
+
+define $(package)_build_cmds
+ $(MAKE)
+endef
+
+define $(package)_stage_cmds
+ $(MAKE) DESTDIR=$($(package)_staging_dir) install-h install-lib
+endef
+
+define $(package)_postprocess_cmds
+endef
diff --git a/contrib/depends/packages/libICE.mk b/contrib/depends/packages/libICE.mk
new file mode 100644
index 000000000..fc60323b1
--- /dev/null
+++ b/contrib/depends/packages/libICE.mk
@@ -0,0 +1,23 @@
+package=libICE
+$(package)_version=1.0.9
+$(package)_download_path=http://xorg.freedesktop.org/releases/individual/lib/
+$(package)_file_name=$(package)-$($(package)_version).tar.bz2
+$(package)_sha256_hash=8f7032f2c1c64352b5423f6b48a8ebdc339cc63064af34d66a6c9aa79759e202
+$(package)_dependencies=xtrans xproto
+
+define $(package)_set_vars
+ $(package)_config_opts=--disable-static --disable-docs --disable-specs --without-xsltproc
+ $(package)_config_opts_linux=--with-pic
+endef
+
+define $(package)_config_cmds
+ $($(package)_autoconf)
+endef
+
+define $(package)_build_cmds
+ $(MAKE)
+endef
+
+define $(package)_stage_cmds
+ $(MAKE) DESTDIR=$($(package)_staging_dir) install
+endef
diff --git a/contrib/depends/packages/libSM.mk b/contrib/depends/packages/libSM.mk
new file mode 100644
index 000000000..0f9307ca7
--- /dev/null
+++ b/contrib/depends/packages/libSM.mk
@@ -0,0 +1,23 @@
+package=libSM
+$(package)_version=1.2.2
+$(package)_download_path=http://xorg.freedesktop.org/releases/individual/lib/
+$(package)_file_name=$(package)-$($(package)_version).tar.bz2
+$(package)_sha256_hash=0baca8c9f5d934450a70896c4ad38d06475521255ca63b717a6510fdb6e287bd
+$(package)_dependencies=xtrans xproto libICE
+
+define $(package)_set_vars
+ $(package)_config_opts=--without-libuuid --without-xsltproc --disable-docs --disable-static
+ $(package)_config_opts_linux=--with-pic
+endef
+
+define $(package)_config_cmds
+ $($(package)_autoconf)
+endef
+
+define $(package)_build_cmds
+ $(MAKE)
+endef
+
+define $(package)_stage_cmds
+ $(MAKE) DESTDIR=$($(package)_staging_dir) install
+endef
diff --git a/contrib/depends/packages/libevent.mk b/contrib/depends/packages/libevent.mk
new file mode 100644
index 000000000..5f622f8e6
--- /dev/null
+++ b/contrib/depends/packages/libevent.mk
@@ -0,0 +1,30 @@
+package=libevent
+$(package)_version=2.1.8-stable
+$(package)_download_path=https://github.com/libevent/libevent/archive/
+$(package)_file_name=release-$($(package)_version).tar.gz
+$(package)_sha256_hash=316ddb401745ac5d222d7c529ef1eada12f58f6376a66c1118eee803cb70f83d
+
+define $(package)_preprocess_cmds
+ ./autogen.sh
+endef
+
+define $(package)_set_vars
+ $(package)_config_opts=--disable-shared --disable-openssl --disable-libevent-regress --disable-samples
+ $(package)_config_opts_release=--disable-debug-mode
+ $(package)_config_opts_linux=--with-pic
+endef
+
+define $(package)_config_cmds
+ $($(package)_autoconf)
+endef
+
+define $(package)_build_cmds
+ $(MAKE)
+endef
+
+define $(package)_stage_cmds
+ $(MAKE) DESTDIR=$($(package)_staging_dir) install
+endef
+
+define $(package)_postprocess_cmds
+endef
diff --git a/contrib/depends/packages/libiconv.mk b/contrib/depends/packages/libiconv.mk
new file mode 100644
index 000000000..87e30b208
--- /dev/null
+++ b/contrib/depends/packages/libiconv.mk
@@ -0,0 +1,17 @@
+package=libiconv
+$(package)_version=1.15
+$(package)_download_path=https://ftp.gnu.org/gnu/libiconv
+$(package)_file_name=libiconv-$($(package)_version).tar.gz
+$(package)_sha256_hash=ccf536620a45458d26ba83887a983b96827001e92a13847b45e4925cc8913178
+
+define $(package)_config_cmds
+ $($(package)_autoconf) --disable-nls --enable-static --disable-shared
+endef
+
+define $(package)_build_cmds
+ $(MAKE)
+endef
+
+define $(package)_stage_cmds
+ $(MAKE) DESTDIR=$($(package)_staging_dir) install
+endef
diff --git a/contrib/depends/packages/miniupnpc.mk b/contrib/depends/packages/miniupnpc.mk
new file mode 100644
index 000000000..1bb8cb5d2
--- /dev/null
+++ b/contrib/depends/packages/miniupnpc.mk
@@ -0,0 +1,28 @@
+package=miniupnpc
+$(package)_version=2.0.20170509
+$(package)_download_path=http://miniupnp.free.fr/files
+$(package)_file_name=$(package)-$($(package)_version).tar.gz
+$(package)_sha256_hash=d3c368627f5cdfb66d3ebd64ca39ba54d6ff14a61966dbecb8dd296b7039f16a
+
+define $(package)_set_vars
+$(package)_build_opts=CC="$($(package)_cc)"
+$(package)_build_opts_darwin=OS=Darwin LIBTOOL="$($(package)_libtool)"
+$(package)_build_opts_mingw32=-f Makefile.mingw
+$(package)_build_env+=CFLAGS="$($(package)_cflags) $($(package)_cppflags)" AR="$($(package)_ar)"
+endef
+
+define $(package)_preprocess_cmds
+ mkdir dll && \
+ sed -e 's|MINIUPNPC_VERSION_STRING \"version\"|MINIUPNPC_VERSION_STRING \"$($(package)_version)\"|' -e 's|OS/version|$(host)|' miniupnpcstrings.h.in > miniupnpcstrings.h && \
+ sed -i.old "s|miniupnpcstrings.h: miniupnpcstrings.h.in wingenminiupnpcstrings|miniupnpcstrings.h: miniupnpcstrings.h.in|" Makefile.mingw
+endef
+
+define $(package)_build_cmds
+ $(MAKE) libminiupnpc.a $($(package)_build_opts)
+endef
+
+define $(package)_stage_cmds
+ mkdir -p $($(package)_staging_prefix_dir)/include/miniupnpc $($(package)_staging_prefix_dir)/lib &&\
+ install *.h $($(package)_staging_prefix_dir)/include/miniupnpc &&\
+ install libminiupnpc.a $($(package)_staging_prefix_dir)/lib
+endef
diff --git a/contrib/depends/packages/native_biplist.mk b/contrib/depends/packages/native_biplist.mk
new file mode 100644
index 000000000..3c6e8900f
--- /dev/null
+++ b/contrib/depends/packages/native_biplist.mk
@@ -0,0 +1,20 @@
+package=native_biplist
+$(package)_version=0.9
+$(package)_download_path=https://pypi.python.org/packages/source/b/biplist
+$(package)_file_name=biplist-$($(package)_version).tar.gz
+$(package)_sha256_hash=b57cadfd26e4754efdf89e9e37de87885f9b5c847b2615688ca04adfaf6ca604
+$(package)_install_libdir=$(build_prefix)/lib/python/dist-packages
+$(package)_patches=sorted_list.patch
+
+define $(package)_preprocess_cmds
+ patch -p1 < $($(package)_patch_dir)/sorted_list.patch
+endef
+
+define $(package)_build_cmds
+ python setup.py build
+endef
+
+define $(package)_stage_cmds
+ mkdir -p $($(package)_install_libdir) && \
+ python setup.py install --root=$($(package)_staging_dir) --prefix=$(build_prefix) --install-lib=$($(package)_install_libdir)
+endef
diff --git a/contrib/depends/packages/native_ccache.mk b/contrib/depends/packages/native_ccache.mk
new file mode 100644
index 000000000..966804ce8
--- /dev/null
+++ b/contrib/depends/packages/native_ccache.mk
@@ -0,0 +1,25 @@
+package=native_ccache
+$(package)_version=3.3.4
+$(package)_download_path=https://samba.org/ftp/ccache
+$(package)_file_name=ccache-$($(package)_version).tar.bz2
+$(package)_sha256_hash=fa9d7f38367431bc86b19ad107d709ca7ecf1574fdacca01698bdf0a47cd8567
+
+define $(package)_set_vars
+$(package)_config_opts=
+endef
+
+define $(package)_config_cmds
+ $($(package)_autoconf)
+endef
+
+define $(package)_build_cmds
+ $(MAKE)
+endef
+
+define $(package)_stage_cmds
+ $(MAKE) DESTDIR=$($(package)_staging_dir) install
+endef
+
+define $(package)_postprocess_cmds
+ rm -rf lib include
+endef
diff --git a/contrib/depends/packages/native_cctools.mk b/contrib/depends/packages/native_cctools.mk
new file mode 100644
index 000000000..44d238cc4
--- /dev/null
+++ b/contrib/depends/packages/native_cctools.mk
@@ -0,0 +1,65 @@
+package=native_cctools
+$(package)_version=807d6fd1be5d2224872e381870c0a75387fe05e6
+$(package)_download_path=https://github.com/theuni/cctools-port/archive
+$(package)_file_name=$($(package)_version).tar.gz
+$(package)_sha256_hash=a09c9ba4684670a0375e42d9d67e7f12c1f62581a27f28f7c825d6d7032ccc6a
+$(package)_build_subdir=cctools
+$(package)_clang_version=3.7.1
+$(package)_clang_download_path=http://llvm.org/releases/$($(package)_clang_version)
+$(package)_clang_download_file=clang+llvm-$($(package)_clang_version)-x86_64-linux-gnu-ubuntu-14.04.tar.xz
+$(package)_clang_file_name=clang-llvm-$($(package)_clang_version)-x86_64-linux-gnu-ubuntu-14.04.tar.xz
+$(package)_clang_sha256_hash=99b28a6b48e793705228a390471991386daa33a9717cd9ca007fcdde69608fd9
+$(package)_extra_sources=$($(package)_clang_file_name)
+
+define $(package)_fetch_cmds
+$(call fetch_file,$(package),$($(package)_download_path),$($(package)_download_file),$($(package)_file_name),$($(package)_sha256_hash)) && \
+$(call fetch_file,$(package),$($(package)_clang_download_path),$($(package)_clang_download_file),$($(package)_clang_file_name),$($(package)_clang_sha256_hash))
+endef
+
+define $(package)_extract_cmds
+ mkdir -p $($(package)_extract_dir) && \
+ echo "$($(package)_sha256_hash) $($(package)_source)" > $($(package)_extract_dir)/.$($(package)_file_name).hash && \
+ echo "$($(package)_clang_sha256_hash) $($(package)_source_dir)/$($(package)_clang_file_name)" >> $($(package)_extract_dir)/.$($(package)_file_name).hash && \
+ $(build_SHA256SUM) -c $($(package)_extract_dir)/.$($(package)_file_name).hash && \
+ mkdir -p toolchain/bin toolchain/lib/clang/3.5/include && \
+ tar --strip-components=1 -C toolchain -xf $($(package)_source_dir)/$($(package)_clang_file_name) && \
+ rm -f toolchain/lib/libc++abi.so* && \
+ echo "#!/bin/sh" > toolchain/bin/$(host)-dsymutil && \
+ echo "exit 0" >> toolchain/bin/$(host)-dsymutil && \
+ chmod +x toolchain/bin/$(host)-dsymutil && \
+ tar --strip-components=1 -xf $($(package)_source)
+endef
+
+define $(package)_set_vars
+$(package)_config_opts=--target=$(host) --disable-lto-support
+$(package)_ldflags+=-Wl,-rpath=\\$$$$$$$$\$$$$$$$$ORIGIN/../lib
+$(package)_cc=$($(package)_extract_dir)/toolchain/bin/clang
+$(package)_cxx=$($(package)_extract_dir)/toolchain/bin/clang++
+endef
+
+define $(package)_preprocess_cmds
+ cd $($(package)_build_subdir); ./autogen.sh && \
+ sed -i.old "/define HAVE_PTHREADS/d" ld64/src/ld/InputFiles.h
+endef
+
+define $(package)_config_cmds
+ $($(package)_autoconf)
+endef
+
+define $(package)_build_cmds
+ $(MAKE)
+endef
+
+define $(package)_stage_cmds
+ $(MAKE) DESTDIR=$($(package)_staging_dir) install && \
+ cd $($(package)_extract_dir)/toolchain && \
+ mkdir -p $($(package)_staging_prefix_dir)/lib/clang/$($(package)_clang_version)/include && \
+ mkdir -p $($(package)_staging_prefix_dir)/bin $($(package)_staging_prefix_dir)/include && \
+ cp bin/clang $($(package)_staging_prefix_dir)/bin/ &&\
+ cp -P bin/clang++ $($(package)_staging_prefix_dir)/bin/ &&\
+ cp lib/libLTO.so $($(package)_staging_prefix_dir)/lib/ && \
+ cp -rf lib/clang/$($(package)_clang_version)/include/* $($(package)_staging_prefix_dir)/lib/clang/$($(package)_clang_version)/include/ && \
+ cp bin/llvm-dsymutil $($(package)_staging_prefix_dir)/bin/$(host)-dsymutil && \
+ if `test -d include/c++/`; then cp -rf include/c++/ $($(package)_staging_prefix_dir)/include/; fi && \
+ if `test -d lib/c++/`; then cp -rf lib/c++/ $($(package)_staging_prefix_dir)/lib/; fi
+endef
diff --git a/contrib/depends/packages/native_cdrkit.mk b/contrib/depends/packages/native_cdrkit.mk
new file mode 100644
index 000000000..cf694edb3
--- /dev/null
+++ b/contrib/depends/packages/native_cdrkit.mk
@@ -0,0 +1,26 @@
+package=native_cdrkit
+$(package)_version=1.1.11
+$(package)_download_path=http://distro.ibiblio.org/fatdog/source/600/c
+$(package)_file_name=cdrkit-$($(package)_version).tar.bz2
+$(package)_sha256_hash=b50d64c214a65b1a79afe3a964c691931a4233e2ba605d793eb85d0ac3652564
+$(package)_patches=cdrkit-deterministic.patch
+
+define $(package)_preprocess_cmds
+ patch -p1 < $($(package)_patch_dir)/cdrkit-deterministic.patch
+endef
+
+define $(package)_config_cmds
+ cmake -DCMAKE_INSTALL_PREFIX=$(build_prefix)
+endef
+
+define $(package)_build_cmds
+ $(MAKE) genisoimage
+endef
+
+define $(package)_stage_cmds
+ $(MAKE) DESTDIR=$($(package)_staging_dir) -C genisoimage install
+endef
+
+define $(package)_postprocess_cmds
+ rm bin/isovfy bin/isoinfo bin/isodump bin/isodebug bin/devdump
+endef
diff --git a/contrib/depends/packages/native_ds_store.mk b/contrib/depends/packages/native_ds_store.mk
new file mode 100644
index 000000000..49f5829ac
--- /dev/null
+++ b/contrib/depends/packages/native_ds_store.mk
@@ -0,0 +1,17 @@
+package=native_ds_store
+$(package)_version=1.1.0
+$(package)_download_path=https://bitbucket.org/al45tair/ds_store/get
+$(package)_download_file=v$($(package)_version).tar.bz2
+$(package)_file_name=$(package)-$($(package)_version).tar.bz2
+$(package)_sha256_hash=921596764d71d1bbd3297a90ef6d286f718794d667e4f81d91d14053525d64c1
+$(package)_install_libdir=$(build_prefix)/lib/python/dist-packages
+$(package)_dependencies=native_biplist
+
+define $(package)_build_cmds
+ python setup.py build
+endef
+
+define $(package)_stage_cmds
+ mkdir -p $($(package)_install_libdir) && \
+ python setup.py install --root=$($(package)_staging_dir) --prefix=$(build_prefix) --install-lib=$($(package)_install_libdir)
+endef
diff --git a/contrib/depends/packages/native_libdmg-hfsplus.mk b/contrib/depends/packages/native_libdmg-hfsplus.mk
new file mode 100644
index 000000000..a4ffb6046
--- /dev/null
+++ b/contrib/depends/packages/native_libdmg-hfsplus.mk
@@ -0,0 +1,22 @@
+package=native_libdmg-hfsplus
+$(package)_version=0.1
+$(package)_download_path=https://github.com/theuni/libdmg-hfsplus/archive
+$(package)_file_name=libdmg-hfsplus-v$($(package)_version).tar.gz
+$(package)_sha256_hash=6569a02eb31c2827080d7d59001869ea14484c281efab0ae7f2b86af5c3120b3
+$(package)_build_subdir=build
+
+define $(package)_preprocess_cmds
+ mkdir build
+endef
+
+define $(package)_config_cmds
+ cmake -DCMAKE_INSTALL_PREFIX:PATH=$(build_prefix)/bin ..
+endef
+
+define $(package)_build_cmds
+ $(MAKE) -C dmg
+endef
+
+define $(package)_stage_cmds
+ $(MAKE) DESTDIR=$($(package)_staging_dir) -C dmg install
+endef
diff --git a/contrib/depends/packages/native_mac_alias.mk b/contrib/depends/packages/native_mac_alias.mk
new file mode 100644
index 000000000..85a8a402b
--- /dev/null
+++ b/contrib/depends/packages/native_mac_alias.mk
@@ -0,0 +1,21 @@
+package=native_mac_alias
+$(package)_version=1.1.0
+$(package)_download_path=https://bitbucket.org/al45tair/mac_alias/get
+$(package)_download_file=v$($(package)_version).tar.bz2
+$(package)_file_name=$(package)-$($(package)_version).tar.bz2
+$(package)_sha256_hash=87ad827e66790028361e43fc754f68ed041a9bdb214cca03c853f079b04fb120
+$(package)_install_libdir=$(build_prefix)/lib/python/dist-packages
+$(package)_patches=python3.patch
+
+define $(package)_preprocess_cmds
+ patch -p1 < $($(package)_patch_dir)/python3.patch
+endef
+
+define $(package)_build_cmds
+ python setup.py build
+endef
+
+define $(package)_stage_cmds
+ mkdir -p $($(package)_install_libdir) && \
+ python setup.py install --root=$($(package)_staging_dir) --prefix=$(build_prefix) --install-lib=$($(package)_install_libdir)
+endef
diff --git a/contrib/depends/packages/openssl.mk b/contrib/depends/packages/openssl.mk
new file mode 100644
index 000000000..5ee9f17a6
--- /dev/null
+++ b/contrib/depends/packages/openssl.mk
@@ -0,0 +1,78 @@
+package=openssl
+$(package)_version=1.0.1k
+$(package)_download_path=https://www.openssl.org/source
+$(package)_file_name=$(package)-$($(package)_version).tar.gz
+$(package)_sha256_hash=8f9faeaebad088e772f4ef5e38252d472be4d878c6b3a2718c10a4fcebe7a41c
+
+define $(package)_set_vars
+$(package)_config_env=AR="$($(package)_ar)" RANLIB="$($(package)_ranlib)" CC="$($(package)_cc)"
+$(package)_config_opts=--prefix=$(host_prefix) --openssldir=$(host_prefix)/etc/openssl
+$(package)_config_opts+=no-camellia
+$(package)_config_opts+=no-capieng
+$(package)_config_opts+=no-cast
+$(package)_config_opts+=no-comp
+$(package)_config_opts+=no-dso
+$(package)_config_opts+=no-dtls1
+$(package)_config_opts+=no-ec_nistp_64_gcc_128
+$(package)_config_opts+=no-gost
+$(package)_config_opts+=no-gmp
+$(package)_config_opts+=no-heartbeats
+$(package)_config_opts+=no-idea
+$(package)_config_opts+=no-jpake
+$(package)_config_opts+=no-krb5
+$(package)_config_opts+=no-libunbound
+$(package)_config_opts+=no-md2
+$(package)_config_opts+=no-mdc2
+$(package)_config_opts+=no-rc4
+$(package)_config_opts+=no-rc5
+$(package)_config_opts+=no-rdrand
+$(package)_config_opts+=no-rfc3779
+$(package)_config_opts+=no-rsax
+$(package)_config_opts+=no-sctp
+$(package)_config_opts+=no-seed
+$(package)_config_opts+=no-sha0
+$(package)_config_opts+=no-shared
+$(package)_config_opts+=no-ssl-trace
+$(package)_config_opts+=no-ssl2
+$(package)_config_opts+=no-ssl3
+$(package)_config_opts+=no-static_engine
+$(package)_config_opts+=no-store
+$(package)_config_opts+=no-unit-test
+$(package)_config_opts+=no-weak-ssl-ciphers
+$(package)_config_opts+=no-whirlpool
+$(package)_config_opts+=no-zlib
+$(package)_config_opts+=no-zlib-dynamic
+$(package)_config_opts+=$($(package)_cflags) $($(package)_cppflags)
+$(package)_config_opts_linux=-fPIC -Wa,--noexecstack
+$(package)_config_opts_x86_64_linux=linux-x86_64
+$(package)_config_opts_i686_linux=linux-generic32
+$(package)_config_opts_arm_linux=linux-generic32
+$(package)_config_opts_aarch64_linux=linux-generic64
+$(package)_config_opts_mipsel_linux=linux-generic32
+$(package)_config_opts_mips_linux=linux-generic32
+$(package)_config_opts_powerpc_linux=linux-generic32
+$(package)_config_opts_x86_64_darwin=darwin64-x86_64-cc
+$(package)_config_opts_x86_64_mingw32=mingw64
+$(package)_config_opts_i686_mingw32=mingw
+endef
+
+define $(package)_preprocess_cmds
+ sed -i.old "/define DATE/d" util/mkbuildinf.pl && \
+ sed -i.old "s|engines apps test|engines|" Makefile.org
+endef
+
+define $(package)_config_cmds
+ ./Configure $($(package)_config_opts)
+endef
+
+define $(package)_build_cmds
+ $(MAKE) -j1 build_libs libcrypto.pc libssl.pc openssl.pc
+endef
+
+define $(package)_stage_cmds
+ $(MAKE) INSTALL_PREFIX=$($(package)_staging_dir) -j1 install_sw
+endef
+
+define $(package)_postprocess_cmds
+ rm -rf share bin etc
+endef
diff --git a/contrib/depends/packages/packages.mk b/contrib/depends/packages/packages.mk
new file mode 100644
index 000000000..28eaf34c5
--- /dev/null
+++ b/contrib/depends/packages/packages.mk
@@ -0,0 +1,21 @@
+packages:=boost openssl libevent zeromq cppzmq zlib expat ldns cppzmq readline libiconv qt sodium
+native_packages := native_ccache
+
+wallet_packages=bdb
+
+darwin_native_packages = native_biplist native_ds_store native_mac_alias
+
+ifeq ($(host_os),linux)
+packages += pcsc-lite
+packages += unwind
+endif
+ifeq ($(host_os),mingw32)
+packages += icu4c
+endif
+
+ifneq ($(build_os),darwin)
+darwin_native_packages += native_cctools native_cdrkit native_libdmg-hfsplus
+packages += readline
+endif
+
+
diff --git a/contrib/depends/packages/pcsc-lite.mk b/contrib/depends/packages/pcsc-lite.mk
new file mode 100644
index 000000000..06be0e585
--- /dev/null
+++ b/contrib/depends/packages/pcsc-lite.mk
@@ -0,0 +1,26 @@
+package=pcsc-lite
+$(package)_version=1.8.23
+$(package)_download_path=https://pcsclite.apdu.fr/files
+$(package)_file_name=$(package)-$($(package)_version).tar.bz2
+$(package)_sha256_hash=5a27262586eff39cfd5c19aadc8891dd71c0818d3d629539bd631b958be689c9
+
+define $(package)_set_vars
+ $(package)_build_opts=CC="$($(package)_cc)"
+ $(package)_config_env=AR="$($(package)_ar)" RANLIB="$($(package)_ranlib)" CC="$($(package)_cc)"
+ $(package)_config_opts=--prefix=$(host_prefix)
+ $(package)_config_opts_release=--disable-debug-mode --disable-libsystemd --disable-libudev --enable-static --disable-shared --disable-libusb
+ $(package)_build_opts=CFLAGS="$($(package)_cflags) $($(package)_cppflags) -fPIC"
+endef
+
+define $(package)_config_cmds
+ ./bootstrap &&\
+ $($(package)_autoconf) $($(package)_config_opts)
+endef
+
+define $(package)_build_cmds
+ $(MAKE) $($(package)_build_opts)
+endef
+
+define $(package)_stage_cmds
+ $(MAKE) DESTDIR=$($(package)_staging_dir) install
+endef
diff --git a/contrib/depends/packages/protobuf.mk b/contrib/depends/packages/protobuf.mk
new file mode 100644
index 000000000..54d3fd924
--- /dev/null
+++ b/contrib/depends/packages/protobuf.mk
@@ -0,0 +1,29 @@
+package=protobuf
+$(package)_version=$(native_$(package)_version)
+$(package)_download_path=$(native_$(package)_download_path)
+$(package)_file_name=$(native_$(package)_file_name)
+$(package)_sha256_hash=$(native_$(package)_sha256_hash)
+$(package)_dependencies=native_$(package)
+$(package)_cxxflags=-std=c++11
+
+define $(package)_set_vars
+ $(package)_config_opts=--disable-shared --with-protoc=$(build_prefix)/bin/protoc
+ $(package)_config_opts_linux=--with-pic
+endef
+
+define $(package)_config_cmds
+ $($(package)_autoconf)
+endef
+
+define $(package)_build_cmds
+ $(MAKE) -C src libprotobuf.la
+endef
+
+define $(package)_stage_cmds
+ $(MAKE) DESTDIR=$($(package)_staging_dir) -C src install-libLTLIBRARIES install-nobase_includeHEADERS &&\
+ $(MAKE) DESTDIR=$($(package)_staging_dir) install-pkgconfigDATA
+endef
+
+define $(package)_postprocess_cmds
+ rm lib/libprotoc.a
+endef
diff --git a/contrib/depends/packages/qt.mk b/contrib/depends/packages/qt.mk
new file mode 100644
index 000000000..32ca4a84c
--- /dev/null
+++ b/contrib/depends/packages/qt.mk
@@ -0,0 +1,150 @@
+PACKAGE=qt
+$(package)_version=5.7.1
+$(package)_download_path=http://download.qt.io/official_releases/qt/5.7/$($(package)_version)/submodules
+$(package)_suffix=opensource-src-$($(package)_version).tar.gz
+$(package)_file_name=qtbase-$($(package)_suffix)
+$(package)_sha256_hash=95f83e532d23b3ddbde7973f380ecae1bac13230340557276f75f2e37984e410
+$(package)_dependencies=openssl zlib
+$(package)_build_subdir=qtbase
+$(package)_qt_libs=corelib
+$(package)_patches=pidlist_absolute.patch fix_qt_pkgconfig.patch qfixed-coretext.patch
+
+$(package)_qttranslations_file_name=qttranslations-$($(package)_suffix)
+$(package)_qttranslations_sha256_hash=3a15aebd523c6d89fb97b2d3df866c94149653a26d27a00aac9b6d3020bc5a1d
+
+$(package)_qttools_file_name=qttools-$($(package)_suffix)
+$(package)_qttools_sha256_hash=22d67de915cb8cd93e16fdd38fa006224ad9170bd217c2be1e53045a8dd02f0f
+
+$(package)_extra_sources = $($(package)_qttranslations_file_name)
+$(package)_extra_sources += $($(package)_qttools_file_name)
+
+define $(package)_set_vars
+$(package)_config_opts_release = -release
+$(package)_config_opts_debug = -debug
+$(package)_config_opts += -bindir $(build_prefix)/bin
+$(package)_config_opts += -c++std c++11
+$(package)_config_opts += -confirm-license
+$(package)_config_opts += -dbus-runtime
+$(package)_config_opts += -no-alsa
+$(package)_config_opts += -no-audio-backend
+$(package)_config_opts += -no-cups
+$(package)_config_opts += -no-egl
+$(package)_config_opts += -no-eglfs
+$(package)_config_opts += -no-feature-style-windowsmobile
+$(package)_config_opts += -no-feature-style-windowsce
+$(package)_config_opts += -no-freetype
+$(package)_config_opts += -no-gif
+$(package)_config_opts += -no-glib
+$(package)_config_opts += -no-gstreamer
+$(package)_config_opts += -no-icu
+$(package)_config_opts += -no-iconv
+$(package)_config_opts += -no-kms
+$(package)_config_opts += -no-linuxfb
+$(package)_config_opts += -no-libudev
+$(package)_config_opts += -no-mitshm
+$(package)_config_opts += -no-mtdev
+$(package)_config_opts += -no-pulseaudio
+$(package)_config_opts += -no-openvg
+$(package)_config_opts += -no-reduce-relocations
+$(package)_config_opts += -no-qml-debug
+$(package)_config_opts += -no-sql-db2
+$(package)_config_opts += -no-sql-ibase
+$(package)_config_opts += -no-sql-oci
+$(package)_config_opts += -no-sql-tds
+$(package)_config_opts += -no-sql-mysql
+$(package)_config_opts += -no-sql-odbc
+$(package)_config_opts += -no-sql-psql
+$(package)_config_opts += -no-sql-sqlite
+$(package)_config_opts += -no-sql-sqlite2
+$(package)_config_opts += -no-use-gold-linker
+$(package)_config_opts += -no-xinput2
+$(package)_config_opts += -no-xrender
+$(package)_config_opts += -nomake examples
+$(package)_config_opts += -nomake tests
+$(package)_config_opts += -opensource
+$(package)_config_opts += -openssl-linked
+$(package)_config_opts += -optimized-qmake
+$(package)_config_opts += -pch
+$(package)_config_opts += -pkg-config
+$(package)_config_opts += -qt-libpng
+$(package)_config_opts += -qt-libjpeg
+$(package)_config_opts += -qt-pcre
+$(package)_config_opts += -system-zlib
+$(package)_config_opts += -reduce-exports
+$(package)_config_opts += -static
+$(package)_config_opts += -silent
+$(package)_config_opts += -v
+$(package)_config_opts += -no-feature-printer
+$(package)_config_opts += -no-feature-printdialog
+$(package)_config_opts += -no-gui
+$(package)_config_opts += -no-freetype
+$(package)_config_opts += -no-sm
+$(package)_config_opts += -no-fontconfig
+$(package)_config_opts += -no-opengl
+$(package)_config_opts += -no-xkb
+$(package)_config_opts += -no-xcb
+$(package)_config_opts += -no-xshape
+$(package)_build_env = QT_RCC_TEST=1
+endef
+
+define $(package)_fetch_cmds
+$(call fetch_file,$(package),$($(package)_download_path),$($(package)_download_file),$($(package)_file_name),$($(package)_sha256_hash)) && \
+$(call fetch_file,$(package),$($(package)_download_path),$($(package)_qttranslations_file_name),$($(package)_qttranslations_file_name),$($(package)_qttranslations_sha256_hash)) && \
+$(call fetch_file,$(package),$($(package)_download_path),$($(package)_qttools_file_name),$($(package)_qttools_file_name),$($(package)_qttools_sha256_hash))
+endef
+
+define $(package)_extract_cmds
+ mkdir -p $($(package)_extract_dir) && \
+ echo "$($(package)_sha256_hash) $($(package)_source)" > $($(package)_extract_dir)/.$($(package)_file_name).hash && \
+ echo "$($(package)_qttranslations_sha256_hash) $($(package)_source_dir)/$($(package)_qttranslations_file_name)" >> $($(package)_extract_dir)/.$($(package)_file_name).hash && \
+ echo "$($(package)_qttools_sha256_hash) $($(package)_source_dir)/$($(package)_qttools_file_name)" >> $($(package)_extract_dir)/.$($(package)_file_name).hash && \
+ $(build_SHA256SUM) -c $($(package)_extract_dir)/.$($(package)_file_name).hash && \
+ mkdir qtbase && \
+ tar --strip-components=1 -xf $($(package)_source) -C qtbase && \
+ mkdir qttranslations && \
+ tar --strip-components=1 -xf $($(package)_source_dir)/$($(package)_qttranslations_file_name) -C qttranslations && \
+ mkdir qttools && \
+ tar --strip-components=1 -xf $($(package)_source_dir)/$($(package)_qttools_file_name) -C qttools
+endef
+
+
+define $(package)_preprocess_cmds
+ sed -i.old "s|updateqm.commands = \$$$$\$$$$LRELEASE|updateqm.commands = $($(package)_extract_dir)/qttools/bin/lrelease|" qttranslations/translations/translations.pro && \
+ sed -i.old "/updateqm.depends =/d" qttranslations/translations/translations.pro && \
+ patch -p1 < $($(package)_patch_dir)/pidlist_absolute.patch && \
+ patch -p1 < $($(package)_patch_dir)/fix_qt_pkgconfig.patch && \
+ patch -p1 < $($(package)_patch_dir)/qfixed-coretext.patch && \
+ echo "!host_build: QMAKE_CFLAGS += $($(package)_cflags) $($(package)_cppflags)" >> qtbase/mkspecs/common/gcc-base.conf && \
+ echo "!host_build: QMAKE_CXXFLAGS += $($(package)_cxxflags) $($(package)_cppflags)" >> qtbase/mkspecs/common/gcc-base.conf && \
+ echo "!host_build: QMAKE_LFLAGS += $($(package)_ldflags)" >> qtbase/mkspecs/common/gcc-base.conf
+endef
+
+define $(package)_config_cmds
+ export PKG_CONFIG_SYSROOT_DIR=/ && \
+ export PKG_CONFIG_LIBDIR=$(host_prefix)/lib/pkgconfig && \
+ export PKG_CONFIG_PATH=$(host_prefix)/share/pkgconfig && \
+ ./configure $($(package)_config_opts) && \
+ echo "host_build: QT_CONFIG ~= s/system-zlib/zlib" >> mkspecs/qconfig.pri && \
+ echo "CONFIG += force_bootstrap" >> mkspecs/qconfig.pri && \
+ $(MAKE) sub-src-clean && \
+ cd ../qttranslations && ../qtbase/bin/qmake qttranslations.pro -o Makefile && \
+ cd translations && ../../qtbase/bin/qmake translations.pro -o Makefile && cd ../.. &&\
+ cd qttools/src/linguist/lrelease/ && ../../../../qtbase/bin/qmake lrelease.pro -o Makefile
+endef
+
+define $(package)_build_cmds
+ $(MAKE) -C src $(addprefix sub-,$($(package)_qt_libs)) && \
+ $(MAKE) -C ../qttools/src/linguist/lrelease && \
+ $(MAKE) -C ../qttranslations
+endef
+
+define $(package)_stage_cmds
+ $(MAKE) -C src INSTALL_ROOT=$($(package)_staging_dir) $(addsuffix -install_subtargets,$(addprefix sub-,$($(package)_qt_libs))) && cd .. &&\
+ $(MAKE) -C qttools/src/linguist/lrelease INSTALL_ROOT=$($(package)_staging_dir) install_target && \
+ $(MAKE) -C qttranslations INSTALL_ROOT=$($(package)_staging_dir) install_subtargets
+endef
+
+define $(package)_postprocess_cmds
+ rm -rf native/mkspecs/ native/lib/ lib/cmake/ && \
+ rm -f lib/lib*.la lib/*.prl plugins/*/*.prl
+endef
diff --git a/contrib/depends/packages/readline.mk b/contrib/depends/packages/readline.mk
new file mode 100644
index 000000000..826c1029e
--- /dev/null
+++ b/contrib/depends/packages/readline.mk
@@ -0,0 +1,33 @@
+package=readline
+$(package)_version=6.3
+$(package)_download_path=ftp://ftp.cwru.edu/pub/bash/
+$(package)_file_name=$(package)-$($(package)_version).tar.gz
+$(package)_sha256_hash=56ba6071b9462f980c5a72ab0023893b65ba6debb4eeb475d7a563dc65cafd43
+$(package)_patches=readline-1.patch
+
+define $(package)_set_vars
+ $(package)_build_opts=CC="$($(package)_cc)"
+ $(package)_config_env=AR="$($(package)_ar)" RANLIB="$($(package)_ranlib)" CC="$($(package)_cc)"
+ $(package)_config_opts=--prefix=$(host_prefix)
+ $(package)_config_opts+=--disable-shared --enable-multibye --without-purify --without-curses
+ $(package)_config_opts_release=--disable-debug-mode
+ $(package)_build_opts=CFLAGS="$($(package)_cflags) $($(package)_cppflags) -fPIC"
+endef
+
+define $(package)_config_cmds
+ patch -p1 < $($(package)_patch_dir)/readline-1.patch &&\
+ export bash_cv_have_mbstate_t=yes &&\
+ export bash_cv_wcwidth_broken=yes &&\
+ ./configure $($(package)_config_opts)
+endef
+
+define $(package)_build_cmds
+ $(MAKE) $($(package)_build_opts)
+endef
+
+define $(package)_stage_cmds
+ $(MAKE) DESTDIR=$($(package)_staging_dir) install
+endef
+
+define $(package)_postprocess_cmds
+endef
diff --git a/contrib/depends/packages/sodium.mk b/contrib/depends/packages/sodium.mk
new file mode 100644
index 000000000..885b1ea19
--- /dev/null
+++ b/contrib/depends/packages/sodium.mk
@@ -0,0 +1,23 @@
+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
+
+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)
+endef
+
+define $(package)_build_cmds
+ $(MAKE)
+endef
+
+define $(package)_stage_cmds
+ $(MAKE) DESTDIR=$($(package)_staging_dir) install
+endef
diff --git a/contrib/depends/packages/unbound.mk b/contrib/depends/packages/unbound.mk
new file mode 100644
index 000000000..beeeb54c1
--- /dev/null
+++ b/contrib/depends/packages/unbound.mk
@@ -0,0 +1,28 @@
+package=unbound
+$(package)_version=1.6.8
+$(package)_download_path=http://www.unbound.net/downloads/
+$(package)_file_name=$(package)-$($(package)_version).tar.gz
+$(package)_sha256_hash=e3b428e33f56a45417107448418865fe08d58e0e7fea199b855515f60884dd49
+$(package)_dependencies=openssl expat ldns
+
+define $(package)_set_vars
+ $(package)_config_opts=--disable-shared --enable-static --without-pyunbound --prefix=$(host_prefix) --with-libexpat=$(host_prefix) --with-ssl=$(host_prefix) --with-libevent=no --without-pythonmodule --disable-flto --with-pthreads
+ $(package)_config_opts_linux=--with-pic
+ $(package)_config_opts_w64=--enable-static-exe --sysconfdir=/etc --prefix=$(host_prefix) --target=$(host_prefix)
+ $(package)_build_opts_mingw32=LDFLAGS="$($(package)_ldflags) -lpthread"
+endef
+
+define $(package)_config_cmds
+ $($(package)_autoconf) $($(package)_config_opts)
+endef
+
+define $(package)_build_cmds
+ $(MAKE) $($(package)_build_opts)
+endef
+
+define $(package)_stage_cmds
+ $(MAKE) DESTDIR=$($(package)_staging_dir) install
+endef
+
+define $(package)_postprocess_cmds
+endef
diff --git a/contrib/depends/packages/unwind.mk b/contrib/depends/packages/unwind.mk
new file mode 100644
index 000000000..e1bcb35b2
--- /dev/null
+++ b/contrib/depends/packages/unwind.mk
@@ -0,0 +1,22 @@
+package=unwind
+$(package)_version=1.2
+$(package)_download_path=http://download.savannah.nongnu.org/releases/libunwind
+$(package)_file_name=lib$(package)-$($(package)_version).tar.gz
+$(package)_sha256_hash=1de38ffbdc88bd694d10081865871cd2bfbb02ad8ef9e1606aee18d65532b992
+
+define $(package)_config_cmds
+ cp -f $(BASEDIR)/config.guess config/config.guess &&\
+ cp -f $(BASEDIR)/config.sub config/config.sub &&\
+ $($(package)_autoconf) --disable-shared --enable-static
+endef
+
+define $(package)_build_cmds
+ $(MAKE)
+endef
+
+define $(package)_stage_cmds
+ $(MAKE) DESTDIR=$($(package)_staging_dir) install
+endef
+
+define $(package)_postprocess_cmds
+endef
diff --git a/contrib/depends/packages/xproto.mk b/contrib/depends/packages/xproto.mk
new file mode 100644
index 000000000..50a90b268
--- /dev/null
+++ b/contrib/depends/packages/xproto.mk
@@ -0,0 +1,21 @@
+package=xproto
+$(package)_version=7.0.26
+$(package)_download_path=http://xorg.freedesktop.org/releases/individual/proto
+$(package)_file_name=$(package)-$($(package)_version).tar.bz2
+$(package)_sha256_hash=636162c1759805a5a0114a369dffdeccb8af8c859ef6e1445f26a4e6e046514f
+
+define $(package)_set_vars
+$(package)_config_opts=--disable-shared
+endef
+
+define $(package)_config_cmds
+ $($(package)_autoconf)
+endef
+
+define $(package)_build_cmds
+ $(MAKE)
+endef
+
+define $(package)_stage_cmds
+ $(MAKE) DESTDIR=$($(package)_staging_dir) install
+endef
diff --git a/contrib/depends/packages/zeromq.mk b/contrib/depends/packages/zeromq.mk
new file mode 100644
index 000000000..01146c26f
--- /dev/null
+++ b/contrib/depends/packages/zeromq.mk
@@ -0,0 +1,34 @@
+package=zeromq
+$(package)_version=4.1.5
+$(package)_download_path=https://github.com/zeromq/zeromq4-1/releases/download/v$($(package)_version)/
+$(package)_file_name=$(package)-$($(package)_version).tar.gz
+$(package)_sha256_hash=04aac57f081ffa3a2ee5ed04887be9e205df3a7ddade0027460b8042432bdbcf
+$(package)_patches=9114d3957725acd34aa8b8d011585812f3369411.patch 9e6745c12e0b100cd38acecc16ce7db02905e27c.patch
+
+define $(package)_set_vars
+ $(package)_config_opts=--without-documentation --disable-shared --without-libsodium --disable-curve
+ $(package)_config_opts_linux=--with-pic
+ $(package)_cxxflags=-std=c++11
+endef
+
+define $(package)_preprocess_cmds
+ patch -p1 < $($(package)_patch_dir)/9114d3957725acd34aa8b8d011585812f3369411.patch && \
+ patch -p1 < $($(package)_patch_dir)/9e6745c12e0b100cd38acecc16ce7db02905e27c.patch && \
+ ./autogen.sh
+endef
+
+define $(package)_config_cmds
+ $($(package)_autoconf)
+endef
+
+define $(package)_build_cmds
+ $(MAKE) libzmq.la
+endef
+
+define $(package)_stage_cmds
+ $(MAKE) DESTDIR=$($(package)_staging_dir) install-libLTLIBRARIES install-includeHEADERS install-pkgconfigDATA
+endef
+
+define $(package)_postprocess_cmds
+ rm -rf bin share
+endef
diff --git a/contrib/depends/packages/zlib.mk b/contrib/depends/packages/zlib.mk
new file mode 100644
index 000000000..589490800
--- /dev/null
+++ b/contrib/depends/packages/zlib.mk
@@ -0,0 +1,27 @@
+package=zlib
+$(package)_version=1.2.11
+$(package)_download_path=http://www.zlib.net
+$(package)_file_name=$(package)-$($(package)_version).tar.gz
+$(package)_sha256_hash=c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1
+
+define $(package)_set_vars
+$(package)_build_opts= CC="$($(package)_cc)"
+$(package)_build_opts+=CFLAGS="$($(package)_cflags) $($(package)_cppflags) -fPIC"
+$(package)_build_opts+=RANLIB="$($(package)_ranlib)"
+$(package)_build_opts+=AR="$($(package)_ar)"
+$(package)_build_opts_darwin+=AR="$($(package)_libtool)"
+$(package)_build_opts_darwin+=ARFLAGS="-o"
+endef
+
+define $(package)_config_cmds
+ ./configure --static --prefix=$(host_prefix)
+endef
+
+define $(package)_build_cmds
+ $(MAKE) $($(package)_build_opts) libz.a
+endef
+
+define $(package)_stage_cmds
+ $(MAKE) DESTDIR=$($(package)_staging_dir) install $($(package)_build_opts)
+endef
+
diff --git a/contrib/depends/patches/cmake/cmake-1-fixes.patch b/contrib/depends/patches/cmake/cmake-1-fixes.patch
new file mode 100644
index 000000000..062c06767
--- /dev/null
+++ b/contrib/depends/patches/cmake/cmake-1-fixes.patch
@@ -0,0 +1,67 @@
+This file is part of MXE. See LICENSE.md for licensing information.
+
+Contains ad hoc patches for cross building.
+
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Tony Theodore <tonyt@logyst.com>
+Date: Fri, 12 Aug 2016 02:01:20 +1000
+Subject: [PATCH 1/3] fix windres invocation options
+
+windres doesn't recognise various gcc flags like -mms-bitfields,
+-fopenmp, -mthreads etc. (basically not `-D` or `-I`)
+
+diff --git a/Modules/Platform/Windows-windres.cmake b/Modules/Platform/Windows-windres.cmake
+index 1111111..2222222 100644
+--- a/Modules/Platform/Windows-windres.cmake
++++ b/Modules/Platform/Windows-windres.cmake
+@@ -1 +1 @@
+-set(CMAKE_RC_COMPILE_OBJECT "<CMAKE_RC_COMPILER> -O coff <DEFINES> <INCLUDES> <FLAGS> <SOURCE> <OBJECT>")
++set(CMAKE_RC_COMPILE_OBJECT "<CMAKE_RC_COMPILER> -O coff <DEFINES> <INCLUDES> <SOURCE> <OBJECT>")
+
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Tony Theodore <tonyt@logyst.com>
+Date: Tue, 25 Jul 2017 20:34:56 +1000
+Subject: [PATCH 2/3] add option to disable -isystem
+
+taken from (not accepted):
+https://gitlab.kitware.com/cmake/cmake/merge_requests/895
+
+see also:
+https://gitlab.kitware.com/cmake/cmake/issues/16291
+https://gitlab.kitware.com/cmake/cmake/issues/16919
+
+diff --git a/Modules/Compiler/GNU.cmake b/Modules/Compiler/GNU.cmake
+index 1111111..2222222 100644
+--- a/Modules/Compiler/GNU.cmake
++++ b/Modules/Compiler/GNU.cmake
+@@ -42,7 +42,7 @@ macro(__compiler_gnu lang)
+ string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT " -O2 -g -DNDEBUG")
+ set(CMAKE_${lang}_CREATE_PREPROCESSED_SOURCE "<CMAKE_${lang}_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
+ set(CMAKE_${lang}_CREATE_ASSEMBLY_SOURCE "<CMAKE_${lang}_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -S <SOURCE> -o <ASSEMBLY_SOURCE>")
+- if(NOT APPLE OR NOT CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 4) # work around #4462
++ if(NOT APPLE OR NOT CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 4 AND (NOT MXE_DISABLE_INCLUDE_SYSTEM_FLAG)) # work around #4462
+ set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-isystem ")
+ endif()
+ endmacro()
+
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Tony Theodore <tonyt@logyst.com>
+Date: Tue, 15 Aug 2017 15:25:06 +1000
+Subject: [PATCH 3/3] add CPACK_NSIS_EXECUTABLE variable
+
+
+diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx
+index 1111111..2222222 100644
+--- a/Source/CPack/cmCPackNSISGenerator.cxx
++++ b/Source/CPack/cmCPackNSISGenerator.cxx
+@@ -384,7 +384,9 @@ int cmCPackNSISGenerator::InitializeInternal()
+ }
+ #endif
+
+- nsisPath = cmSystemTools::FindProgram("makensis", path, false);
++ this->SetOptionIfNotSet("CPACK_NSIS_EXECUTABLE", "makensis");
++ nsisPath = cmSystemTools::FindProgram(
++ this->GetOption("CPACK_NSIS_EXECUTABLE"), path, false);
+
+ if (nsisPath.empty()) {
+ cmCPackLogger(
diff --git a/contrib/depends/patches/icu4c/icu-001-dont-build-static-dynamic-twice.patch b/contrib/depends/patches/icu4c/icu-001-dont-build-static-dynamic-twice.patch
new file mode 100644
index 000000000..bbd4e99e7
--- /dev/null
+++ b/contrib/depends/patches/icu4c/icu-001-dont-build-static-dynamic-twice.patch
@@ -0,0 +1,37 @@
+Don't build object files twice
+
+When passed --enable-static and --enable-shared, icu will generate
+both a shared and a static version of its libraries.
+
+However, in order to do so, it builds each and every object file
+twice: once with -fPIC (for the shared library), and once without
+-fPIC (for the static library). While admittedly building -fPIC for a
+static library generates a slightly suboptimal code, this is what all
+the autotools-based project are doing. They build each object file
+once, and they use it for both the static and shared libraries.
+
+icu builds the object files for the shared library as .o files, and
+the object files for static library as .ao files. By simply changing
+the suffix of object files used for static libraries to ".o", we tell
+icu to use the ones built for the shared library (i.e, with -fPIC),
+and avoid the double build of icu.
+
+On a fast build server, this brings the target icu build from
+3m41.302s down to 1m43.926s (approximate numbers: some other builds
+are running on the system at the same time).
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+
+Index: b/source/config/mh-linux
+===================================================================
+--- a/source/config/mh-linux
++++ b/source/config/mh-linux
+@@ -38,7 +38,7 @@
+ ## Shared object suffix
+ SO = so
+ ## Non-shared intermediate object suffix
+-STATIC_O = ao
++STATIC_O = o
+
+ ## Compilation rules
+ %.$(STATIC_O): $(srcdir)/%.c
diff --git a/contrib/depends/patches/native_biplist/sorted_list.patch b/contrib/depends/patches/native_biplist/sorted_list.patch
new file mode 100644
index 000000000..89abdb1b7
--- /dev/null
+++ b/contrib/depends/patches/native_biplist/sorted_list.patch
@@ -0,0 +1,29 @@
+--- a/biplist/__init__.py 2014-10-26 19:03:11.000000000 +0000
++++ b/biplist/__init__.py 2016-07-19 19:30:17.663521999 +0000
+@@ -541,7 +541,7 @@
+ return HashableWrapper(n)
+ elif isinstance(root, dict):
+ n = {}
+- for key, value in iteritems(root):
++ for key, value in sorted(iteritems(root)):
+ n[self.wrapRoot(key)] = self.wrapRoot(value)
+ return HashableWrapper(n)
+ elif isinstance(root, list):
+@@ -616,7 +616,7 @@
+ elif isinstance(obj, dict):
+ size = proc_size(len(obj))
+ self.incrementByteCount('dictBytes', incr=1+size)
+- for key, value in iteritems(obj):
++ for key, value in sorted(iteritems(obj)):
+ check_key(key)
+ self.computeOffsets(key, asReference=True)
+ self.computeOffsets(value, asReference=True)
+@@ -714,7 +714,7 @@
+ keys = []
+ values = []
+ objectsToWrite = []
+- for key, value in iteritems(obj):
++ for key, value in sorted(iteritems(obj)):
+ keys.append(key)
+ values.append(value)
+ for key in keys:
diff --git a/contrib/depends/patches/native_cdrkit/cdrkit-deterministic.patch b/contrib/depends/patches/native_cdrkit/cdrkit-deterministic.patch
new file mode 100644
index 000000000..8ab0993dc
--- /dev/null
+++ b/contrib/depends/patches/native_cdrkit/cdrkit-deterministic.patch
@@ -0,0 +1,86 @@
+--- cdrkit-1.1.11.old/genisoimage/tree.c 2008-10-21 19:57:47.000000000 -0400
++++ cdrkit-1.1.11/genisoimage/tree.c 2013-12-06 00:23:18.489622668 -0500
+@@ -1139,8 +1139,9 @@
+ scan_directory_tree(struct directory *this_dir, char *path,
+ struct directory_entry *de)
+ {
+- DIR *current_dir;
++ int current_file;
+ char whole_path[PATH_MAX];
++ struct dirent **d_list;
+ struct dirent *d_entry;
+ struct directory *parent;
+ int dflag;
+@@ -1164,7 +1165,8 @@
+ this_dir->dir_flags |= DIR_WAS_SCANNED;
+
+ errno = 0; /* Paranoia */
+- current_dir = opendir(path);
++ //current_dir = opendir(path);
++ current_file = scandir(path, &d_list, NULL, alphasort);
+ d_entry = NULL;
+
+ /*
+@@ -1173,12 +1175,12 @@
+ */
+ old_path = path;
+
+- if (current_dir) {
++ if (current_file >= 0) {
+ errno = 0;
+- d_entry = readdir(current_dir);
++ d_entry = d_list[0];
+ }
+
+- if (!current_dir || !d_entry) {
++ if (current_file < 0 || !d_entry) {
+ int ret = 1;
+
+ #ifdef USE_LIBSCHILY
+@@ -1191,8 +1193,8 @@
+ de->isorec.flags[0] &= ~ISO_DIRECTORY;
+ ret = 0;
+ }
+- if (current_dir)
+- closedir(current_dir);
++ if(d_list)
++ free(d_list);
+ return (ret);
+ }
+ #ifdef ABORT_DEEP_ISO_ONLY
+@@ -1208,7 +1210,7 @@
+ errmsgno(EX_BAD, "use Rock Ridge extensions via -R or -r,\n");
+ errmsgno(EX_BAD, "or allow deep ISO9660 directory nesting via -D.\n");
+ }
+- closedir(current_dir);
++ free(d_list);
+ return (1);
+ }
+ #endif
+@@ -1250,13 +1252,13 @@
+ * The first time through, skip this, since we already asked
+ * for the first entry when we opened the directory.
+ */
+- if (dflag)
+- d_entry = readdir(current_dir);
++ if (dflag && current_file >= 0)
++ d_entry = d_list[current_file];
+ dflag++;
+
+- if (!d_entry)
++ if (current_file < 0)
+ break;
+-
++ current_file--;
+ /* OK, got a valid entry */
+
+ /* If we do not want all files, then pitch the backups. */
+@@ -1348,7 +1350,7 @@
+ insert_file_entry(this_dir, whole_path, d_entry->d_name);
+ #endif /* APPLE_HYB */
+ }
+- closedir(current_dir);
++ free(d_list);
+
+ #ifdef APPLE_HYB
+ /*
diff --git a/contrib/depends/patches/native_mac_alias/python3.patch b/contrib/depends/patches/native_mac_alias/python3.patch
new file mode 100644
index 000000000..1a32340be
--- /dev/null
+++ b/contrib/depends/patches/native_mac_alias/python3.patch
@@ -0,0 +1,72 @@
+diff -dur a/mac_alias/alias.py b/mac_alias/alias.py
+--- a/mac_alias/alias.py 2015-10-19 12:12:48.000000000 +0200
++++ b/mac_alias/alias.py 2016-04-03 12:13:12.037159417 +0200
+@@ -243,10 +243,10 @@
+ alias = Alias()
+ alias.appinfo = appinfo
+
+- alias.volume = VolumeInfo (volname.replace('/',':'),
++ alias.volume = VolumeInfo (volname.decode().replace('/',':'),
+ voldate, fstype, disktype,
+ volattrs, volfsid)
+- alias.target = TargetInfo (kind, filename.replace('/',':'),
++ alias.target = TargetInfo (kind, filename.decode().replace('/',':'),
+ folder_cnid, cnid,
+ crdate, creator_code, type_code)
+ alias.target.levels_from = levels_from
+@@ -261,9 +261,9 @@
+ b.read(1)
+
+ if tag == TAG_CARBON_FOLDER_NAME:
+- alias.target.folder_name = value.replace('/',':')
++ alias.target.folder_name = value.decode().replace('/',':')
+ elif tag == TAG_CNID_PATH:
+- alias.target.cnid_path = struct.unpack(b'>%uI' % (length // 4),
++ alias.target.cnid_path = struct.unpack('>%uI' % (length // 4),
+ value)
+ elif tag == TAG_CARBON_PATH:
+ alias.target.carbon_path = value
+@@ -298,9 +298,9 @@
+ alias.target.creation_date \
+ = mac_epoch + datetime.timedelta(seconds=seconds)
+ elif tag == TAG_POSIX_PATH:
+- alias.target.posix_path = value
++ alias.target.posix_path = value.decode()
+ elif tag == TAG_POSIX_PATH_TO_MOUNTPOINT:
+- alias.volume.posix_path = value
++ alias.volume.posix_path = value.decode()
+ elif tag == TAG_RECURSIVE_ALIAS_OF_DISK_IMAGE:
+ alias.volume.disk_image_alias = Alias.from_bytes(value)
+ elif tag == TAG_USER_HOME_LENGTH_PREFIX:
+@@ -422,13 +422,13 @@
+ # (so doing so is ridiculous, and nothing could rely on it).
+ b.write(struct.pack(b'>h28pI2shI64pII4s4shhI2s10s',
+ self.target.kind,
+- carbon_volname, voldate,
++ carbon_volname, int(voldate),
+ self.volume.fs_type,
+ self.volume.disk_type,
+ self.target.folder_cnid,
+ carbon_filename,
+ self.target.cnid,
+- crdate,
++ int(crdate),
+ self.target.creator_code,
+ self.target.type_code,
+ self.target.levels_from,
+@@ -449,12 +449,12 @@
+
+ b.write(struct.pack(b'>hhQhhQ',
+ TAG_HIGH_RES_VOLUME_CREATION_DATE,
+- 8, long(voldate * 65536),
++ 8, int(voldate * 65536),
+ TAG_HIGH_RES_CREATION_DATE,
+- 8, long(crdate * 65536)))
++ 8, int(crdate * 65536)))
+
+ if self.target.cnid_path:
+- cnid_path = struct.pack(b'>%uI' % len(self.target.cnid_path),
++ cnid_path = struct.pack('>%uI' % len(self.target.cnid_path),
+ *self.target.cnid_path)
+ b.write(struct.pack(b'>hh', TAG_CNID_PATH,
+ len(cnid_path)))
diff --git a/contrib/depends/patches/qt/fix_qt_pkgconfig.patch b/contrib/depends/patches/qt/fix_qt_pkgconfig.patch
new file mode 100644
index 000000000..34302a9f2
--- /dev/null
+++ b/contrib/depends/patches/qt/fix_qt_pkgconfig.patch
@@ -0,0 +1,11 @@
+--- old/qtbase/mkspecs/features/qt_module.prf
++++ new/qtbase/mkspecs/features/qt_module.prf
+@@ -245,7 +245,7 @@
+ load(qt_targets)
+
+ # this builds on top of qt_common
+-!internal_module:!lib_bundle:if(unix|mingw) {
++unix|mingw {
+ CONFIG += create_pc
+ QMAKE_PKGCONFIG_DESTDIR = pkgconfig
+ host_build: \
diff --git a/contrib/depends/patches/qt/pidlist_absolute.patch b/contrib/depends/patches/qt/pidlist_absolute.patch
new file mode 100644
index 000000000..c79282417
--- /dev/null
+++ b/contrib/depends/patches/qt/pidlist_absolute.patch
@@ -0,0 +1,37 @@
+diff -dur old/qtbase/src/plugins/platforms/windows/qwindowscontext.h new/qtbase/src/plugins/platforms/windows/qwindowscontext.h
+--- old/qtbase/src/plugins/platforms/windows/qwindowscontext.h
++++ new/qtbase/src/plugins/platforms/windows/qwindowscontext.h
+@@ -136,10 +136,18 @@
+ inline void init();
+
+ typedef HRESULT (WINAPI *SHCreateItemFromParsingName)(PCWSTR, IBindCtx *, const GUID&, void **);
++#if defined(Q_CC_MINGW) && (!defined(__MINGW64_VERSION_MAJOR) || __MINGW64_VERSION_MAJOR < 3)
++ typedef HRESULT (WINAPI *SHGetKnownFolderIDList)(const GUID &, DWORD, HANDLE, ITEMIDLIST **);
++#else
+ typedef HRESULT (WINAPI *SHGetKnownFolderIDList)(const GUID &, DWORD, HANDLE, PIDLIST_ABSOLUTE *);
++#endif
+ typedef HRESULT (WINAPI *SHGetStockIconInfo)(int , int , _SHSTOCKICONINFO *);
+ typedef HRESULT (WINAPI *SHGetImageList)(int, REFIID , void **);
++#if defined(Q_CC_MINGW) && (!defined(__MINGW64_VERSION_MAJOR) || __MINGW64_VERSION_MAJOR < 3)
++ typedef HRESULT (WINAPI *SHCreateItemFromIDList)(const ITEMIDLIST *, REFIID, void **);
++#else
+ typedef HRESULT (WINAPI *SHCreateItemFromIDList)(PCIDLIST_ABSOLUTE, REFIID, void **);
++#endif
+
+ SHCreateItemFromParsingName sHCreateItemFromParsingName;
+ SHGetKnownFolderIDList sHGetKnownFolderIDList;
+diff -dur old/qtbase/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp new/qtbase/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
+--- old/qtbase/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
++++ new/qtbase/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
+@@ -1016,7 +1016,11 @@
+ qWarning() << __FUNCTION__ << ": Invalid CLSID: " << url.path();
+ return Q_NULLPTR;
+ }
++#if defined(Q_CC_MINGW) && (!defined(__MINGW64_VERSION_MAJOR) || __MINGW64_VERSION_MAJOR < 3)
++ ITEMIDLIST *idList;
++#else
+ PIDLIST_ABSOLUTE idList;
++#endif
+ HRESULT hr = QWindowsContext::shell32dll.sHGetKnownFolderIDList(uuid, 0, 0, &idList);
+ if (FAILED(hr)) {
+ qErrnoWarning("%s: SHGetKnownFolderIDList(%s)) failed", __FUNCTION__, qPrintable(url.toString()));
diff --git a/contrib/depends/patches/qt/qfixed-coretext.patch b/contrib/depends/patches/qt/qfixed-coretext.patch
new file mode 100644
index 000000000..aa56f1e1d
--- /dev/null
+++ b/contrib/depends/patches/qt/qfixed-coretext.patch
@@ -0,0 +1,34 @@
+From dbdd5f0ffbce52c8b789ed09f1aa3f1da6c02e23 Mon Sep 17 00:00:00 2001
+From: Gabriel de Dietrich <gabriel.dedietrich@qt.io>
+Date: Fri, 30 Mar 2018 11:58:16 -0700
+Subject: [PATCH] QCoreTextFontEngine: Fix build with Xcode 9.3
+
+Apple LLVM version 9.1.0 (clang-902.0.39.1)
+
+Error message:
+
+.../qfontengine_coretext.mm:827:20: error: qualified reference to
+ 'QFixed' is a constructor name rather than a type in this context
+ return QFixed::QFixed(int(CTFontGetUnitsPerEm(ctfont)));
+
+Change-Id: Iebe26b3b087a16b10664208fc8851cbddb47f043
+Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
+---
+ src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git old/qtbase/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm new/qtbase/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
+index 25ff69d877d..98b753eff96 100644
+--- old/qtbase/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
++++ new/qtbase/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
+@@ -824,7 +824,7 @@ void QCoreTextFontEngine::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, gl
+
+ QFixed QCoreTextFontEngine::emSquareSize() const
+ {
+- return QFixed::QFixed(int(CTFontGetUnitsPerEm(ctfont)));
++ return QFixed(int(CTFontGetUnitsPerEm(ctfont)));
+ }
+
+ QFontEngine *QCoreTextFontEngine::cloneWithSize(qreal pixelSize) const
+--
+2.16.3 \ No newline at end of file
diff --git a/contrib/depends/patches/readline/readline-1.patch b/contrib/depends/patches/readline/readline-1.patch
new file mode 100644
index 000000000..7610a29eb
--- /dev/null
+++ b/contrib/depends/patches/readline/readline-1.patch
@@ -0,0 +1,187 @@
+From c0572cecbeadc8fe24c70c5c39d49210a39ac719 Mon Sep 17 00:00:00 2001
+From: Timothy Gu <timothygu99@gmail.com>
+Date: Tue, 30 Sep 2014 10:32:33 -0700
+Subject: [PATCH 1/2] signals: safeguard the remaining usage of frequently
+ missing signals
+
+diff --git a/input.c b/input.c
+index 117dfe8..465f0b9 100644
+--- a/input.c
++++ b/input.c
+@@ -532,9 +532,17 @@ rl_getc (stream)
+ Otherwise (not EINTR), some error occurred, also signifying EOF. */
+ if (errno != EINTR)
+ return (RL_ISSTATE (RL_STATE_READCMD) ? READERR : EOF);
+- else if (_rl_caught_signal == SIGHUP || _rl_caught_signal == SIGTERM)
++ else if (_rl_caught_signal == SIGTERM
++#if defined(SIGHUP)
++ || _rl_caught_signal == SIGHUP
++#endif
++ )
+ return (RL_ISSTATE (RL_STATE_READCMD) ? READERR : EOF);
+- else if (_rl_caught_signal == SIGINT || _rl_caught_signal == SIGQUIT)
++ else if (_rl_caught_signal == SIGINT
++#if defined(SIGQUIT)
++ || _rl_caught_signal == SIGQUIT
++#endif
++ )
+ RL_CHECK_SIGNALS ();
+
+ if (rl_signal_event_hook)
+diff --git a/signals.c b/signals.c
+index 61f02f9..7c921d6 100644
+--- a/signals.c
++++ b/signals.c
+@@ -216,7 +216,9 @@ _rl_handle_signal (sig)
+ /* FALLTHROUGH */
+
+ case SIGTERM:
++#if defined (SIGHUP)
+ case SIGHUP:
++#endif
+ #if defined (SIGTSTP)
+ case SIGTSTP:
+ case SIGTTOU:
+@@ -426,7 +428,9 @@ rl_set_signals ()
+
+ rl_maybe_set_sighandler (SIGINT, rl_signal_handler, &old_int);
+ rl_maybe_set_sighandler (SIGTERM, rl_signal_handler, &old_term);
++#if defined (SIGHUP)
+ rl_maybe_set_sighandler (SIGHUP, rl_signal_handler, &old_hup);
++#endif
+ #if defined (SIGQUIT)
+ rl_maybe_set_sighandler (SIGQUIT, rl_signal_handler, &old_quit);
+ #endif
+@@ -491,7 +495,9 @@ rl_clear_signals ()
+ overhead */
+ rl_maybe_restore_sighandler (SIGINT, &old_int);
+ rl_maybe_restore_sighandler (SIGTERM, &old_term);
++#if defined (SIGHUP)
+ rl_maybe_restore_sighandler (SIGHUP, &old_hup);
++#endif
+ #if defined (SIGQUIT)
+ rl_maybe_restore_sighandler (SIGQUIT, &old_quit);
+ #endif
+--
+1.8.3.2
+
+
+From 6896ffa4fc85bf0dfae58e69a860d2076c1d9fd2 Mon Sep 17 00:00:00 2001
+From: Timothy Gu <timothygu99@gmail.com>
+Date: Tue, 30 Sep 2014 17:16:32 -0700
+Subject: [PATCH 2/2] Handle missing S_IS* macros more gracefully
+
+diff --git a/colors.c b/colors.c
+index 89d9035..ec19844 100644
+--- a/colors.c
++++ b/colors.c
+@@ -152,14 +152,22 @@ _rl_print_color_indicator (char *f)
+ {
+ colored_filetype = C_FILE;
+
++#if defined (S_ISUID)
+ if ((mode & S_ISUID) != 0 && is_colored (C_SETUID))
+ colored_filetype = C_SETUID;
+- else if ((mode & S_ISGID) != 0 && is_colored (C_SETGID))
++ else
++#endif
++#if defined (S_ISGID)
++ if ((mode & S_ISGID) != 0 && is_colored (C_SETGID))
+ colored_filetype = C_SETGID;
+- else if (is_colored (C_CAP) && 0) //f->has_capability)
++ else
++#endif
++ if (is_colored (C_CAP) && 0) //f->has_capability)
+ colored_filetype = C_CAP;
++#if defined(S_IXUGO)
+ else if ((mode & S_IXUGO) != 0 && is_colored (C_EXEC))
+ colored_filetype = C_EXEC;
++#endif
+ else if ((1 < astat.st_nlink) && is_colored (C_MULTIHARDLINK))
+ colored_filetype = C_MULTIHARDLINK;
+ }
+@@ -173,8 +181,10 @@ _rl_print_color_indicator (char *f)
+ colored_filetype = C_STICKY_OTHER_WRITABLE;
+ else
+ #endif
++#if defined (S_IWOTH)
+ if ((mode & S_IWOTH) != 0 && is_colored (C_OTHER_WRITABLE))
+ colored_filetype = C_OTHER_WRITABLE;
++#endif
+ #if defined (S_ISVTX)
+ else if ((mode & S_ISVTX) != 0 && is_colored (C_STICKY))
+ colored_filetype = C_STICKY;
+diff --git a/colors.h b/colors.h
+index fc926e5..e62edd0 100644
+--- a/colors.h
++++ b/colors.h
+@@ -96,7 +96,7 @@ enum indicator_no
+ };
+
+
+-#if !S_IXUGO
++#if !S_IXUGO && defined(S_IXUSR) && defined(S_IXGRP) && defined(S_IXOTH)
+ # define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH)
+ #endif
+
+diff --git a/posixstat.h b/posixstat.h
+index 3eb7f29..854a2c9 100644
+--- a/posixstat.h
++++ b/posixstat.h
+@@ -78,30 +78,44 @@
+
+ #if defined (S_IFBLK) && !defined (S_ISBLK)
+ #define S_ISBLK(m) (((m)&S_IFMT) == S_IFBLK) /* block device */
++#elif !defined (S_IFBLK)
++#define S_ISBLK(m) 0
+ #endif
+
+ #if defined (S_IFCHR) && !defined (S_ISCHR)
+ #define S_ISCHR(m) (((m)&S_IFMT) == S_IFCHR) /* character device */
++#elif !defined (S_IFCHR)
++#define S_ISCHR(m) 0
+ #endif
+
+ #if defined (S_IFDIR) && !defined (S_ISDIR)
+ #define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR) /* directory */
++#elif !defined (S_IFDIR)
++#define S_ISDIR(m) 0
+ #endif
+
+ #if defined (S_IFREG) && !defined (S_ISREG)
+ #define S_ISREG(m) (((m)&S_IFMT) == S_IFREG) /* file */
++#elif !defined (S_IFREG)
++#define S_ISREG(m) 0
+ #endif
+
+ #if defined (S_IFIFO) && !defined (S_ISFIFO)
+ #define S_ISFIFO(m) (((m)&S_IFMT) == S_IFIFO) /* fifo - named pipe */
++#elif !defined (S_IFIFO)
++#define S_ISFIFO(m) 0
+ #endif
+
+ #if defined (S_IFLNK) && !defined (S_ISLNK)
+ #define S_ISLNK(m) (((m)&S_IFMT) == S_IFLNK) /* symbolic link */
++#elif !defined (S_IFLNK)
++#define S_ISLNK(m) 0
+ #endif
+
+ #if defined (S_IFSOCK) && !defined (S_ISSOCK)
+ #define S_ISSOCK(m) (((m)&S_IFMT) == S_IFSOCK) /* socket */
++#elif !defined (S_IFSOCK)
++#define S_ISSOCK(m) 0
+ #endif
+
+ /*
+@@ -137,6 +151,8 @@
+ /* These are non-standard, but are used in builtins.c$symbolic_umask() */
+ #define S_IRUGO (S_IRUSR | S_IRGRP | S_IROTH)
+ #define S_IWUGO (S_IWUSR | S_IWGRP | S_IWOTH)
++#if defined(S_IXUSR) && defined(S_IXGRP) && defined(S_IXOTH)
+ #define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH)
++#endif
+
+ #endif /* _POSIXSTAT_H_ */
+--
+1.8.3.2
+
diff --git a/contrib/depends/patches/zeromq/9114d3957725acd34aa8b8d011585812f3369411.patch b/contrib/depends/patches/zeromq/9114d3957725acd34aa8b8d011585812f3369411.patch
new file mode 100644
index 000000000..f704b3d94
--- /dev/null
+++ b/contrib/depends/patches/zeromq/9114d3957725acd34aa8b8d011585812f3369411.patch
@@ -0,0 +1,22 @@
+From 9114d3957725acd34aa8b8d011585812f3369411 Mon Sep 17 00:00:00 2001
+From: Jeroen Ooms <jeroenooms@gmail.com>
+Date: Tue, 20 Oct 2015 13:10:38 +0200
+Subject: [PATCH] enable static libraries on mingw
+
+---
+ configure.ac | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/configure.ac b/configure.ac
+index 393505b..e92131a 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -265,7 +265,7 @@ case "${host_os}" in
+ libzmq_dso_visibility="no"
+
+ if test "x$enable_static" = "xyes"; then
+- AC_MSG_ERROR([Building static libraries is not supported under MinGW32])
++ CPPFLAGS="-DZMQ_STATIC"
+ fi
+
+ # Set FD_SETSIZE to 1024 \ No newline at end of file
diff --git a/contrib/depends/patches/zeromq/9e6745c12e0b100cd38acecc16ce7db02905e27c.patch b/contrib/depends/patches/zeromq/9e6745c12e0b100cd38acecc16ce7db02905e27c.patch
new file mode 100644
index 000000000..9aff2c179
--- /dev/null
+++ b/contrib/depends/patches/zeromq/9e6745c12e0b100cd38acecc16ce7db02905e27c.patch
@@ -0,0 +1,22 @@
+From 9e6745c12e0b100cd38acecc16ce7db02905e27c Mon Sep 17 00:00:00 2001
+From: David Millard <dmillard10@gmail.com>
+Date: Tue, 10 May 2016 13:53:53 -0700
+Subject: [PATCH] Fix autotools for static MinGW builds
+
+---
+ configure.ac | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/configure.ac b/configure.ac
+index 5a0fa14..def6ea7 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -259,7 +259,7 @@ case "${host_os}" in
+ libzmq_dso_visibility="no"
+
+ if test "x$enable_static" = "xyes"; then
+- CPPFLAGS="-DZMQ_STATIC"
++ CPPFLAGS="-DZMQ_STATIC $CPPFLAGS"
+ fi
+
+ # Set FD_SETSIZE to 1024 \ No newline at end of file
diff --git a/contrib/depends/protobuf.mk b/contrib/depends/protobuf.mk
new file mode 100644
index 000000000..54d3fd924
--- /dev/null
+++ b/contrib/depends/protobuf.mk
@@ -0,0 +1,29 @@
+package=protobuf
+$(package)_version=$(native_$(package)_version)
+$(package)_download_path=$(native_$(package)_download_path)
+$(package)_file_name=$(native_$(package)_file_name)
+$(package)_sha256_hash=$(native_$(package)_sha256_hash)
+$(package)_dependencies=native_$(package)
+$(package)_cxxflags=-std=c++11
+
+define $(package)_set_vars
+ $(package)_config_opts=--disable-shared --with-protoc=$(build_prefix)/bin/protoc
+ $(package)_config_opts_linux=--with-pic
+endef
+
+define $(package)_config_cmds
+ $($(package)_autoconf)
+endef
+
+define $(package)_build_cmds
+ $(MAKE) -C src libprotobuf.la
+endef
+
+define $(package)_stage_cmds
+ $(MAKE) DESTDIR=$($(package)_staging_dir) -C src install-libLTLIBRARIES install-nobase_includeHEADERS &&\
+ $(MAKE) DESTDIR=$($(package)_staging_dir) install-pkgconfigDATA
+endef
+
+define $(package)_postprocess_cmds
+ rm lib/libprotoc.a
+endef
diff --git a/contrib/depends/toolchain.cmake.in b/contrib/depends/toolchain.cmake.in
new file mode 100644
index 000000000..b594ddd62
--- /dev/null
+++ b/contrib/depends/toolchain.cmake.in
@@ -0,0 +1,82 @@
+# Set the system name, either Darwin, Linux, or Windows
+SET(CMAKE_SYSTEM_NAME @depends@)
+SET(CMAKE_BUILD_TYPE release)
+
+SET(STATIC true)
+SET(UNBOUND_STATIC true)
+
+# where is the target environment
+SET(CMAKE_FIND_ROOT_PATH @prefix@ /usr)
+
+SET(ENV{PKG_CONFIG_PATH} @prefix@/lib/pkgconfig)
+
+SET(LRELEASE_PATH @prefix@/native/bin CACHE FILEPATH "path to lrelease" FORCE)
+
+SET(Readline_ROOT_DIR @prefix@)
+
+SET(LIBUNWIND_INCLUDE_DIR @prefix@/include)
+SET(LIBUNWIND_LIBRARIES @prefix@/lib/libunwind.a)
+SET(LIBUNWIND_LIBRARY_DIRS @prefix@/lib)
+
+SET(ZMQ_INCLUDE_PATH @prefix@/include)
+SET(ZMQ_LIB @prefix@/lib/libzmq.a)
+
+SET(BOOST_IGNORE_SYSTEM_PATHS_DEFAULT ON)
+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(OpenSSL_DIR @prefix@/lib)
+SET(ARCHITECTURE @arch@)
+
+# for libraries and headers in the target directories
+set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # Find programs on host
+set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) # Find libs in target
+set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) # Find includes in target
+
+# specify the cross compiler to be used. Darwin uses clang provided by the SDK.
+if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+ SET(CMAKE_C_COMPILER @prefix@/native/bin/clang)
+ SET(CMAKE_C_COMPILER_TARGET x86_64-apple-darwin11)
+ SET(CMAKE_CXX_COMPILER @prefix@/native/bin/clang++ -stdlib=libc++)
+ SET(CMAKE_CXX_COMPILER_TARGET x86_64-apple-darwin11)
+ SET(_CMAKE_TOOLCHAIN_PREFIX x86_64-apple-darwin11-)
+ SET(APPLE True)
+ SET(BUILD_TAG "mac-x64")
+ SET(BUILD_64 ON)
+ SET(ARCH "x86_64")
+ SET(BREW OFF)
+ SET(PORT OFF)
+ SET(CMAKE_OSX_SYSROOT "@sdk@/MacOSX10.11.sdk/")
+ SET(CMAKE_OSX_DEPLOYMENT_TARGET "10.08")
+ SET(CMAKE_CXX_STANDARD 11)
+ SET(CMAKE_OSX_ARCHITECTURES "x86_64")
+ SET(LLVM_ENABLE_PIC OFF)
+ SET(LLVM_ENABLE_PIE OFF)
+else()
+ SET(CMAKE_C_COMPILER @CC@)
+ SET(CMAKE_CXX_COMPILER @CXX@)
+endif()
+
+if(ARCHITECTURE STREQUAL "arm")
+ set(ARCH "armv7-a")
+ set(ARM ON)
+ set(ARM_ID "armv7-a")
+ set(BUILD_64 OFF)
+ set(CMAKE_BUILD_TYPE release)
+ set(BUILD_TAG "linux-armv7")
+ set(ARM7)
+elseif(ARCHITECTURE STREQUAL "aarch64")
+ set(ARCH "armv8-a")
+ set(ARM ON)
+ set(ARM_ID "armv8-a")
+ set(BUILD_TAG "linux-armv8")
+ set(BUILD_64 ON)
+endif()
+
+#Create a new global cmake flag that indicates building with depends
+set (DEPENDS true)
diff --git a/contrib/epee/include/hex.h b/contrib/epee/include/hex.h
index 02600c320..901c666a9 100644
--- a/contrib/epee/include/hex.h
+++ b/contrib/epee/include/hex.h
@@ -44,6 +44,7 @@ namespace epee
static std::string string(const span<const std::uint8_t> src);
//! \return A epee::wipeable_string containing hex of `src`.
static epee::wipeable_string wipeable_string(const span<const std::uint8_t> src);
+ template<typename T> static epee::wipeable_string wipeable_string(const T &pod) { return wipeable_string(span<const uint8_t>((const uint8_t*)&pod, sizeof(pod))); }
//! \return An array containing hex of `src`.
template<std::size_t N>
diff --git a/contrib/epee/include/misc_os_dependent.h b/contrib/epee/include/misc_os_dependent.h
index ffe575501..0d09683d6 100644
--- a/contrib/epee/include/misc_os_dependent.h
+++ b/contrib/epee/include/misc_os_dependent.h
@@ -24,7 +24,7 @@
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#ifdef _WIN32
-#include <Winsock2.h>
+#include <winsock2.h>
#endif
#ifdef WIN32
diff --git a/contrib/epee/include/span.h b/contrib/epee/include/span.h
index 452cc088f..174915ecf 100644
--- a/contrib/epee/include/span.h
+++ b/contrib/epee/include/span.h
@@ -28,6 +28,7 @@
#pragma once
+#include <algorithm>
#include <cstdint>
#include <memory>
#include <type_traits>
@@ -52,11 +53,15 @@ namespace epee
template<typename T>
class span
{
- /* Supporting class types is tricky - the {ptr,len} constructor will allow
- derived-to-base conversions. This is NOT desireable because an array of
- derived types is not an array of base types. It is possible to handle
- this case, implement when/if needed. */
- static_assert(!std::is_class<T>(), "no class types are currently allowed");
+ template<typename U>
+ static constexpr bool safe_conversion() noexcept
+ {
+ // Allow exact matches or `T*` -> `const T*`.
+ using with_const = typename std::add_const<U>::type;
+ return std::is_same<T, U>() ||
+ (std::is_const<T>() && std::is_same<T, with_const>());
+ }
+
public:
using value_type = T;
using size_type = std::size_t;
@@ -71,7 +76,9 @@ namespace epee
constexpr span() noexcept : ptr(nullptr), len(0) {}
constexpr span(std::nullptr_t) noexcept : span() {}
- constexpr span(T* const src_ptr, const std::size_t count) noexcept
+ //! Prevent derived-to-base conversions; invalid in this context.
+ template<typename U, typename = typename std::enable_if<safe_conversion<U>()>::type>
+ constexpr span(U* const src_ptr, const std::size_t count) noexcept
: ptr(src_ptr), len(count) {}
//! Conversion from C-array. Prevents common bugs with sizeof + arrays.
@@ -81,6 +88,16 @@ namespace epee
constexpr span(const span&) noexcept = default;
span& operator=(const span&) noexcept = default;
+ /*! Try to remove `amount` elements from beginning of span.
+ \return Number of elements removed. */
+ std::size_t remove_prefix(std::size_t amount) noexcept
+ {
+ amount = std::min(len, amount);
+ ptr += amount;
+ len -= amount;
+ return amount;
+ }
+
constexpr iterator begin() const noexcept { return ptr; }
constexpr const_iterator cbegin() const noexcept { return ptr; }
@@ -105,6 +122,14 @@ namespace epee
return {src.data(), src.size()};
}
+ //! \return `span<T::value_type>` from a STL compatible `src`.
+ template<typename T>
+ constexpr span<typename T::value_type> to_mut_span(T& src)
+ {
+ // compiler provides diagnostic if size() is not size_t.
+ return {src.data(), src.size()};
+ }
+
template<typename T>
constexpr bool has_padding() noexcept
{
@@ -127,4 +152,13 @@ namespace epee
static_assert(!has_padding<T>(), "source type may have padding");
return {reinterpret_cast<const std::uint8_t*>(std::addressof(src)), sizeof(T)};
}
+
+ //! \return `span<std::uint8_t>` which represents the bytes at `&src`.
+ template<typename T>
+ span<std::uint8_t> as_mut_byte_span(T& src) noexcept
+ {
+ static_assert(!std::is_empty<T>(), "empty types will not work -> sizeof == 1");
+ static_assert(!has_padding<T>(), "source type may have padding");
+ return {reinterpret_cast<std::uint8_t*>(std::addressof(src)), sizeof(T)};
+ }
}
diff --git a/contrib/epee/include/wipeable_string.h b/contrib/epee/include/wipeable_string.h
index 4cebe5fdf..31854fe2e 100644
--- a/contrib/epee/include/wipeable_string.h
+++ b/contrib/epee/include/wipeable_string.h
@@ -28,10 +28,11 @@
#pragma once
-#include <boost/optional/optional_fwd.hpp>
+#include <boost/optional/optional.hpp>
#include <stddef.h>
#include <vector>
#include <string>
+#include "memwipe.h"
#include "fnv1.h"
namespace epee
@@ -65,6 +66,8 @@ namespace epee
void trim();
void split(std::vector<wipeable_string> &fields) const;
boost::optional<wipeable_string> parse_hexstr() const;
+ template<typename T> inline bool hex_to_pod(T &pod) const;
+ template<typename T> inline bool hex_to_pod(tools::scrubbed<T> &pod) const { return hex_to_pod(unwrap(pod)); }
void resize(size_t sz);
void reserve(size_t sz);
void clear();
@@ -79,6 +82,20 @@ namespace epee
private:
std::vector<char> buffer;
};
+
+ template<typename T> inline bool wipeable_string::hex_to_pod(T &pod) const
+ {
+ static_assert(std::is_pod<T>::value, "expected pod type");
+ if (size() != sizeof(T) * 2)
+ return false;
+ boost::optional<epee::wipeable_string> blob = parse_hexstr();
+ if (!blob)
+ return false;
+ if (blob->size() != sizeof(T))
+ return false;
+ pod = *(const T*)blob->data();
+ return true;
+ }
}
namespace std
diff --git a/contrib/epee/src/mlog.cpp b/contrib/epee/src/mlog.cpp
index 818fc0a69..cd9867ff5 100644
--- a/contrib/epee/src/mlog.cpp
+++ b/contrib/epee/src/mlog.cpp
@@ -97,7 +97,7 @@ static const char *get_default_categories(int level)
switch (level)
{
case 0:
- categories = "*:WARNING,net:FATAL,net.p2p:FATAL,net.cn:FATAL,global:INFO,verify:FATAL,stacktrace:INFO,logging:INFO,msgwriter:INFO";
+ categories = "*:WARNING,net:FATAL,net.http:FATAL,net.p2p:FATAL,net.cn:FATAL,global:INFO,verify:FATAL,stacktrace:INFO,logging:INFO,msgwriter:INFO";
break;
case 1:
categories = "*:INFO,global:INFO,stacktrace:INFO,logging:INFO,msgwriter:INFO";
diff --git a/contrib/epee/src/wipeable_string.cpp b/contrib/epee/src/wipeable_string.cpp
index 7c9722765..69f92e106 100644
--- a/contrib/epee/src/wipeable_string.cpp
+++ b/contrib/epee/src/wipeable_string.cpp
@@ -32,6 +32,8 @@
#include "misc_log_ex.h"
#include "wipeable_string.h"
+static constexpr const char hex[] = u8"0123456789abcdef";
+
namespace
{
int atolower(int c)
@@ -197,7 +199,6 @@ boost::optional<epee::wipeable_string> wipeable_string::parse_hexstr() const
const size_t len = size();
const char *d = data();
res->grow(0, len / 2);
- static constexpr const char hex[] = u8"0123456789abcdef";
for (size_t i = 0; i < len; i += 2)
{
char c = atolower(d[i]);
diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt
index 358d47a4f..7553f87ea 100644
--- a/external/CMakeLists.txt
+++ b/external/CMakeLists.txt
@@ -38,9 +38,7 @@
find_package(Miniupnpc REQUIRED)
message(STATUS "Using in-tree miniupnpc")
-
add_subdirectory(miniupnp/miniupnpc)
-
set_property(TARGET libminiupnpc-static PROPERTY FOLDER "external")
if(MSVC)
set_property(TARGET libminiupnpc-static APPEND_STRING PROPERTY COMPILE_FLAGS " -wd4244 -wd4267")
diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp
index 9e22e2e4b..b0f3ca5f0 100644
--- a/src/blockchain_db/lmdb/db_lmdb.cpp
+++ b/src/blockchain_db/lmdb/db_lmdb.cpp
@@ -3391,8 +3391,10 @@ bool BlockchainLMDB::get_output_distribution(uint64_t amount, uint64_t from_heig
break;
}
+ distribution[0] += base;
for (size_t n = 1; n < distribution.size(); ++n)
distribution[n] += distribution[n - 1];
+ base = 0;
TXN_POSTFIX_RDONLY();
diff --git a/src/blockchain_utilities/CMakeLists.txt b/src/blockchain_utilities/CMakeLists.txt
index fe57895e1..37bca671f 100644
--- a/src/blockchain_utilities/CMakeLists.txt
+++ b/src/blockchain_utilities/CMakeLists.txt
@@ -28,7 +28,9 @@
set(blocksdat "")
if(PER_BLOCK_CHECKPOINT)
- if(APPLE)
+ if(APPLE AND DEPENDS)
+ add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} --target=x86_64-apple-darwin11 -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*)
+ elseif(APPLE AND NOT DEPENDS)
add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*)
else()
add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ../blocks/checkpoints.dat blocks.dat && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat)
diff --git a/src/blockchain_utilities/blockchain_blackball.cpp b/src/blockchain_utilities/blockchain_blackball.cpp
index d9a179f64..1c6e54d10 100644
--- a/src/blockchain_utilities/blockchain_blackball.cpp
+++ b/src/blockchain_utilities/blockchain_blackball.cpp
@@ -558,7 +558,7 @@ static std::vector<output_data> get_spent_outputs(MDB_txn *txn)
int dbr = mdb_cursor_open(txn, dbi_spent, &cur);
CHECK_AND_ASSERT_THROW_MES(!dbr, "Failed to open cursor for spent outputs: " + std::string(mdb_strerror(dbr)));
MDB_val k, v;
- uint64_t count = 0;
+ mdb_size_t count = 0;
dbr = mdb_cursor_get(cur, &k, &v, MDB_FIRST);
if (dbr != MDB_NOTFOUND)
{
@@ -898,7 +898,11 @@ static std::vector<std::pair<uint64_t, uint64_t>> load_outputs(const std::string
while (1)
{
char s[256];
- fgets(s, sizeof(s), f);
+ if (!fgets(s, sizeof(s), f))
+ {
+ MERROR("Error reading from " << filename << ": " << strerror(errno));
+ break;
+ }
if (feof(f))
break;
const size_t len = strlen(s);
@@ -968,7 +972,7 @@ static bool export_spent_outputs(MDB_cursor *cur, const std::string &filename)
if (pending_offsets.size() == 1)
fprintf(f, "%" PRIu64 "\n", pending_offsets.front());
else
- fprintf(f, "%" PRIu64 "*%" PRIu64 "\n", pending_offsets.front(), pending_offsets.size());
+ fprintf(f, "%" PRIu64 "*%zu\n", pending_offsets.front(), pending_offsets.size());
pending_offsets.clear();
}
if (pending_amount != amount)
@@ -983,7 +987,7 @@ static bool export_spent_outputs(MDB_cursor *cur, const std::string &filename)
if (pending_offsets.size() == 1)
fprintf(f, "%" PRIu64 "\n", pending_offsets.front());
else
- fprintf(f, "%" PRIu64 "*%" PRIu64 "\n", pending_offsets.front(), pending_offsets.size());
+ fprintf(f, "%" PRIu64 "*%zu\n", pending_offsets.front(), pending_offsets.size());
pending_offsets.clear();
}
fclose(f);
@@ -1396,7 +1400,7 @@ int main(int argc, char* argv[])
if (stop_requested)
{
MINFO("Stopping secondary passes. Secondary passes are not incremental, they will re-run fully.");
- return false;
+ return 0;
}
}
if (!blackballs.empty())
diff --git a/src/checkpoints/CMakeLists.txt b/src/checkpoints/CMakeLists.txt
index 02bb2891a..715006522 100644
--- a/src/checkpoints/CMakeLists.txt
+++ b/src/checkpoints/CMakeLists.txt
@@ -27,9 +27,13 @@
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
if(APPLE)
- find_library(IOKIT_LIBRARY IOKit)
- mark_as_advanced(IOKIT_LIBRARY)
- list(APPEND EXTRA_LIBRARIES ${IOKIT_LIBRARY})
+ if(DEPENDS)
+ list(APPEND EXTRA_LIBRARIES "-framework Foundation -framework ApplicationServices -framework AppKit -framework IOKit")
+ else()
+ find_library(IOKIT_LIBRARY IOKit)
+ mark_as_advanced(IOKIT_LIBRARY)
+ list(APPEND EXTRA_LIBRARIES ${IOKIT_LIBRARY})
+ endif()
endif()
set(checkpoints_sources
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index c6bac2199..e89dbbc24 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -33,6 +33,8 @@ set(common_sources
command_line.cpp
dns_utils.cpp
download.cpp
+ error.cpp
+ expect.cpp
util.cpp
i18n.cpp
password.cpp
@@ -55,6 +57,8 @@ set(common_private_headers
common_fwd.h
dns_utils.h
download.h
+ error.h
+ expect.h
http_connection.h
int-util.h
pod-class.h
diff --git a/src/common/error.cpp b/src/common/error.cpp
new file mode 100644
index 000000000..e091e4478
--- /dev/null
+++ b/src/common/error.cpp
@@ -0,0 +1,75 @@
+// Copyright (c) 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.
+#include "error.h"
+
+#include <string>
+
+namespace
+{
+ struct category final : std::error_category
+ {
+ virtual const char* name() const noexcept override final
+ {
+ return "common_category()";
+ }
+
+ virtual std::string message(int value) const override final
+ {
+ switch (common_error(value))
+ {
+ case common_error::kInvalidArgument:
+ return make_error_code(std::errc::invalid_argument).message();
+ case common_error::kInvalidErrorCode:
+ return "expect<T> was given an error value of zero";
+ default:
+ break;
+ }
+ return "Unknown basic_category() value";
+ }
+
+ virtual std::error_condition default_error_condition(int value) const noexcept override final
+ {
+ // maps specific errors to generic `std::errc` cases.
+ switch (common_error(value))
+ {
+ case common_error::kInvalidArgument:
+ case common_error::kInvalidErrorCode:
+ return std::errc::invalid_argument;
+ default:
+ break;
+ }
+ return std::error_condition{value, *this};
+ }
+ };
+}
+
+std::error_category const& common_category() noexcept
+{
+ static const category instance{};
+ return instance;
+}
+
diff --git a/src/common/error.h b/src/common/error.h
new file mode 100644
index 000000000..6fef3eb4b
--- /dev/null
+++ b/src/common/error.h
@@ -0,0 +1,52 @@
+// Copyright (c) 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
+
+#include <system_error>
+#include <type_traits>
+
+enum class common_error : int
+{
+ // 0 is reserved for no error, as per expect<T>
+ kInvalidArgument = 1, //!< A function argument is invalid
+ kInvalidErrorCode //!< Default `std::error_code` given to `expect<T>`
+};
+
+std::error_category const& common_category() noexcept;
+
+inline std::error_code make_error_code(::common_error value) noexcept
+{
+ return std::error_code{int(value), common_category()};
+}
+
+namespace std
+{
+ template<>
+ struct is_error_code_enum<::common_error>
+ : true_type
+ {};
+}
diff --git a/src/common/expect.cpp b/src/common/expect.cpp
new file mode 100644
index 000000000..c86e23e95
--- /dev/null
+++ b/src/common/expect.cpp
@@ -0,0 +1,70 @@
+//
+// 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.
+
+#include "expect.h"
+
+#include <easylogging++.h>
+#include <string>
+
+namespace detail
+{
+ namespace
+ {
+ std::string generate_error(const char* msg, const char* file, unsigned line)
+ {
+ std::string error_msg{};
+ if (msg)
+ {
+ error_msg.append(msg);
+ if (file)
+ error_msg.append(" (");
+ }
+ if (file)
+ {
+ error_msg.append("thrown at ");
+
+ // remove path, get just filename + extension
+ char buff[256] = {0};
+ el::base::utils::File::buildBaseFilename(file, buff, sizeof(buff) - 1);
+ error_msg.append(buff);
+
+ error_msg.push_back(':');
+ error_msg.append(std::to_string(line));
+ }
+ if (msg && file)
+ error_msg.push_back(')');
+ return error_msg;
+ }
+ }
+
+ void expect::throw_(std::error_code ec, const char* msg, const char* file, unsigned line)
+ {
+ if (msg || file)
+ throw std::system_error{ec, generate_error(msg, file, line)};
+ throw std::system_error{ec};
+ }
+} // detail
diff --git a/src/common/expect.h b/src/common/expect.h
new file mode 100644
index 000000000..326242502
--- /dev/null
+++ b/src/common/expect.h
@@ -0,0 +1,447 @@
+// Copyright (c) 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
+
+#include <cassert>
+#include <system_error>
+#include <type_traits>
+#include <utility>
+
+#include "common/error.h"
+
+//! If precondition fails, return `::error::kInvalidArgument` in current scope.
+#define MONERO_PRECOND(...) \
+ do \
+ { \
+ if (!( __VA_ARGS__ )) \
+ return {::common_error::kInvalidArgument}; \
+ } while (0)
+
+//! Check `expect<void>` and return errors in current scope.
+#define MONERO_CHECK(...) \
+ do \
+ { \
+ const ::expect<void> result = __VA_ARGS__ ; \
+ if (!result) \
+ return result.error(); \
+ } while (0)
+
+/*! Get `T` from `expect<T>` by `std::move` as-if by function call.
+ `expect<void>` returns nothing.
+
+ \throw std::system_error with `expect<T>::error()`, filename and line
+ number when `expect<T>::has_error() == true`.*/
+#define MONERO_UNWRAP(...) \
+ ::detail::expect::unwrap( __VA_ARGS__ , nullptr, __FILE__ , __LINE__ )
+
+/* \throw std::system_error with `code` and `msg` as part of the details. The
+filename and line number will automatically be injected into the explanation
+string. `code` can be any enum convertible to `std::error_code`. */
+#define MONERO_THROW(code, msg) \
+ ::detail::expect::throw_( code , msg , __FILE__ , __LINE__ )
+
+
+template<typename> class expect;
+
+namespace detail
+{
+ // Shortens the characters in the places that `enable_if` is used below.
+ template<bool C>
+ using enable_if = typename std::enable_if<C>::type;
+
+ struct expect
+ {
+ //! \throw std::system_error with `ec`, optional `msg` and/or optional `file` + `line`.
+ static void throw_(std::error_code ec, const char* msg, const char* file, unsigned line);
+
+ //! If `result.has_error()` call `throw_`. Otherwise, \return `*result` by move.
+ template<typename T>
+ static T unwrap(::expect<T>&& result, const char* error_msg, const char* file, unsigned line)
+ {
+ if (!result)
+ throw_(result.error(), error_msg, file, line);
+ return std::move(*result);
+ }
+
+ //! If `result.has_error()` call `throw_`.
+ static void unwrap(::expect<void>&& result, const char* error_msg, const char* file, unsigned line);
+ };
+}
+
+/*!
+ `expect<T>` is a value or error implementation, similar to Rust std::result
+ or various C++ proposals (boost::expected, boost::outcome). This
+ implementation currently has a strict error type, `std::error_code`, and a
+ templated value type `T`. `expect<T>` is implicitly convertible from `T`
+ or `std::error_code`, and one `expect<T>` object type is implicitly
+ convertible to another `expect<U>` object iff the destination value type
+ can be implicitly constructed from the source value type (i.e.
+ `struct U { ... U(T src) { ...} ... };`).
+
+ `operator==` and `operator!=` are the only comparison operators provided;
+ comparison between different value types is allowed provided the two values
+ types have a `operator==` defined between them (i.e.
+ `assert(expect<int>{100} == expect<short>{100});`). Comparisons can also be
+ done against `std::error_code` objects or error code enums directly (i.e.
+ `assert(expect<int>{make_error_code(common_error::kInvalidArgument)} == error::kInvalidArgument)`).
+ Comparison of default constructed `std::error_code` will always fail.
+ "Generic" comparisons can be done with `std::error_condition` via the `matches`
+ method only (i.e.
+ `assert(expect<int>{make_error_code{common_error::kInvalidErrorCode}.matches(std::errc::invalid_argument))`),
+ `operator==` and `operator!=` will not work with `std::errc` or
+ `std::error_condition`. A comparison with `matches` is more expensive
+ because an equivalency between error categories is computed, but is
+ recommended when an error can be one of several categories (this is going
+ to be the case in nearly every situation when calling a function from
+ another C++ struct/class).
+
+ `expect<void>` is a special case with no stored value. It is used by
+ functions that can fail, but otherwise would return `void`. It is useful
+ for consistency; all macros, standalone functions, and comparison operators
+ work with `expect<void>`.
+
+ \note See `src/common/error.h` for creating a custom error enum.
+ */
+template<typename T>
+class expect
+{
+ static_assert(std::is_nothrow_destructible<T>(), "T must have a nothrow destructor");
+
+ template<typename U>
+ static constexpr bool is_convertible() noexcept
+ {
+ return std::is_constructible<T, U>() &&
+ std::is_convertible<U, T>();
+ }
+
+ // MEMBERS
+ std::error_code code_;
+ typename std::aligned_storage<sizeof(T), alignof(T)>::type storage_;
+ // MEMBERS
+
+ T& get() noexcept
+ {
+ assert(has_value());
+ return *reinterpret_cast<T*>(std::addressof(storage_));
+ }
+
+ T const& get() const noexcept
+ {
+ assert(has_value());
+ return *reinterpret_cast<T const*>(std::addressof(storage_));
+ }
+
+ template<typename U>
+ void store(U&& value) noexcept(std::is_nothrow_constructible<T, U>())
+ {
+ new (std::addressof(storage_)) T{std::forward<U>(value)};
+ code_ = std::error_code{};
+ }
+
+ void maybe_throw() const
+ {
+ if (has_error())
+ ::detail::expect::throw_(error(), nullptr, nullptr, 0);
+ }
+
+public:
+ using value_type = T;
+ using error_type = std::error_code;
+
+ expect() = delete;
+
+ /*! Store an error, `code`, in the `expect` object. If `code` creates a
+ `std::error_code` object whose `.value() == 0`, then `error()` will be set
+ to `::common_error::kInvalidErrorCode`. */
+ expect(std::error_code const& code) noexcept
+ : code_(code), storage_()
+ {
+ if (!has_error())
+ code_ = ::common_error::kInvalidErrorCode;
+ }
+
+ //! Store a value, `val`, in the `expect` object.
+ expect(T val) noexcept(std::is_nothrow_move_constructible<T>())
+ : code_(), storage_()
+ {
+ store(std::move(val));
+ }
+
+ expect(expect const& src) noexcept(std::is_nothrow_copy_constructible<T>())
+ : code_(src.error()), storage_()
+ {
+ if (src.has_value())
+ store(src.get());
+ }
+
+ //! Copy conversion from `U` to `T`.
+ template<typename U, typename = detail::enable_if<is_convertible<U const&>()>>
+ expect(expect<U> const& src) noexcept(std::is_nothrow_constructible<T, U const&>())
+ : code_(src.error()), storage_()
+ {
+ if (src.has_value())
+ store(*src);
+ }
+
+ expect(expect&& src) noexcept(std::is_nothrow_move_constructible<T>())
+ : code_(src.error()), storage_()
+ {
+ if (src.has_value())
+ store(std::move(src.get()));
+ }
+
+ //! Move conversion from `U` to `T`.
+ template<typename U, typename = detail::enable_if<is_convertible<U>()>>
+ expect(expect<U>&& src) noexcept(std::is_nothrow_constructible<T, U>())
+ : code_(src.error()), storage_()
+ {
+ if (src.has_value())
+ store(std::move(*src));
+ }
+
+ ~expect() noexcept
+ {
+ if (has_value())
+ get().~T();
+ }
+
+ expect& operator=(expect const& src) noexcept(std::is_nothrow_copy_constructible<T>() && std::is_nothrow_copy_assignable<T>())
+ {
+ if (this != std::addressof(src))
+ {
+ if (has_value() && src.has_value())
+ get() = src.get();
+ else if (has_value())
+ get().~T();
+ else if (src.has_value())
+ store(src.get());
+ code_ = src.error();
+ }
+ return *this;
+ }
+
+ /*! Move `src` into `this`. If `src.has_value() && addressof(src) != this`
+ then `src.value() will be in a "moved from state". */
+ expect& operator=(expect&& src) noexcept(std::is_nothrow_move_constructible<T>() && std::is_nothrow_move_assignable<T>())
+ {
+ if (this != std::addressof(src))
+ {
+ if (has_value() && src.has_value())
+ get() = std::move(src.get());
+ else if (has_value())
+ get().~T();
+ else if (src.has_value())
+ store(std::move(src.get()));
+ code_ = src.error();
+ }
+ return *this;
+ }
+
+ //! \return True if `this` is storing a value instead of an error.
+ explicit operator bool() const noexcept { return has_value(); }
+
+ //! \return True if `this` is storing an error instead of a value.
+ bool has_error() const noexcept { return bool(code_); }
+
+ //! \return True if `this` is storing a value instead of an error.
+ bool has_value() const noexcept { return !has_error(); }
+
+ //! \return Error - always safe to call. Empty when `!has_error()`.
+ std::error_code error() const noexcept { return code_; }
+
+ //! \return Value if `has_value()` otherwise \throw `std::system_error{error()}`.
+ T& value() &
+ {
+ maybe_throw();
+ return get();
+ }
+
+ //! \return Value if `has_value()` otherwise \throw `std::system_error{error()}`.
+ T const& value() const &
+ {
+ maybe_throw();
+ return get();
+ }
+
+ /*! Same as other overloads, but expressions such as `foo(bar().value())`
+ will automatically perform moves with no copies. */
+ T&& value() &&
+ {
+ maybe_throw();
+ return std::move(get());
+ }
+
+ //! \return Value, \pre `has_value()`.
+ T* operator->() noexcept { return std::addressof(get()); }
+ //! \return Value, \pre `has_value()`.
+ T const* operator->() const noexcept { return std::addressof(get()); }
+ //! \return Value, \pre `has_value()`.
+ T& operator*() noexcept { return get(); }
+ //! \return Value, \pre `has_value()`.
+ T const& operator*() const noexcept { return get(); }
+
+ /*!
+ \note This function is `noexcept` when `U == T` is `noexcept`.
+ \return True if `has_value() == rhs.has_value()` and if values or errors are equal.
+ */
+ template<typename U>
+ bool equal(expect<U> const& rhs) const noexcept(noexcept(*std::declval<expect<T>>() == *rhs))
+ {
+ return has_value() && rhs.has_value() ?
+ get() == *rhs : error() == rhs.error();
+ }
+
+ //! \return False if `has_value()`, otherwise `error() == rhs`.
+ bool equal(std::error_code const& rhs) const noexcept
+ {
+ return has_error() && error() == rhs;
+ }
+
+ /*!
+ \note This function is `noexcept` when `U == T` is `noexcept`.
+ \return False if `has_error()`, otherwise `value() == rhs`.
+ */
+ template<typename U, typename = detail::enable_if<!std::is_constructible<std::error_code, U>::value>>
+ bool equal(U const& rhs) const noexcept(noexcept(*std::declval<expect<T>>() == rhs))
+ {
+ return has_value() && get() == rhs;
+ }
+
+ //! \return False if `has_value()`, otherwise `error() == rhs`.
+ bool matches(std::error_condition const& rhs) const noexcept
+ {
+ return has_error() && error() == rhs;
+ }
+};
+
+template<>
+class expect<void>
+{
+ std::error_code code_;
+
+public:
+ using value_type = void;
+ using error_type = std::error_code;
+
+ //! Create a successful object.
+ expect() = default;
+
+ expect(std::error_code const& code) noexcept
+ : code_(code)
+ {
+ if (!has_error())
+ code_ = ::common_error::kInvalidErrorCode;
+ }
+
+ expect(expect const&) = default;
+ ~expect() = default;
+ expect& operator=(expect const&) = default;
+
+ //! \return True if `this` is storing a value instead of an error.
+ explicit operator bool() const noexcept { return !has_error(); }
+
+ //! \return True if `this` is storing an error instead of a value.
+ bool has_error() const noexcept { return bool(code_); }
+
+ //! \return Error - alway
+ std::error_code error() const noexcept { return code_; }
+
+ //! \return `error() == rhs.error()`.
+ bool equal(expect const& rhs) const noexcept
+ {
+ return error() == rhs.error();
+ }
+
+ //! \return `has_error() && error() == rhs`.
+ bool equal(std::error_code const& rhs) const noexcept
+ {
+ return has_error() && error() == rhs;
+ }
+
+ //! \return False if `has_value()`, otherwise `error() == rhs`.
+ bool matches(std::error_condition const& rhs) const noexcept
+ {
+ return has_error() && error() == rhs;
+ }
+};
+
+//! \return An `expect<void>` object with `!has_error()`.
+inline expect<void> success() noexcept { return expect<void>{}; }
+
+template<typename T, typename U>
+inline
+bool operator==(expect<T> const& lhs, expect<U> const& rhs) noexcept(noexcept(lhs.equal(rhs)))
+{
+ return lhs.equal(rhs);
+}
+
+template<typename T, typename U>
+inline
+bool operator==(expect<T> const& lhs, U const& rhs) noexcept(noexcept(lhs.equal(rhs)))
+{
+ return lhs.equal(rhs);
+}
+
+template<typename T, typename U>
+inline
+bool operator==(T const& lhs, expect<U> const& rhs) noexcept(noexcept(rhs.equal(lhs)))
+{
+ return rhs.equal(lhs);
+}
+
+template<typename T, typename U>
+inline
+bool operator!=(expect<T> const& lhs, expect<U> const& rhs) noexcept(noexcept(lhs.equal(rhs)))
+{
+ return !lhs.equal(rhs);
+}
+
+template<typename T, typename U>
+inline
+bool operator!=(expect<T> const& lhs, U const& rhs) noexcept(noexcept(lhs.equal(rhs)))
+{
+ return !lhs.equal(rhs);
+}
+
+template<typename T, typename U>
+inline
+bool operator!=(T const& lhs, expect<U> const& rhs) noexcept(noexcept(rhs.equal(lhs)))
+{
+ return !rhs.equal(lhs);
+}
+
+namespace detail
+{
+ inline void expect::unwrap(::expect<void>&& result, const char* error_msg, const char* file, unsigned line)
+ {
+ if (!result)
+ throw_(result.error(), error_msg, file, line);
+ }
+}
+
diff --git a/src/crypto/crypto_ops_builder/ietf.txt b/src/crypto/crypto_ops_builder/ietf.txt
index 0736f71ec..609f5e75a 100644
--- a/src/crypto/crypto_ops_builder/ietf.txt
+++ b/src/crypto/crypto_ops_builder/ietf.txt
@@ -1,1402 +1,4 @@
-
+https://tools.ietf.org/id/draft-josefsson-eddsa-ed25519-02.txt
-[Docs] [txt|pdf] [Tracker] [Email] [Diff1] [Diff2] [Nits]
-
-Versions: 00 01 02
-
-Network Working Group S. Josefsson
-Internet-Draft SJD AB
-Intended status: Informational N. Moeller
-Expires: August 26, 2015
- February 22, 2015
-
-
- EdDSA and Ed25519
-
- draft-josefsson-eddsa-ed25519-02
-
-
-Abstract
-
- The elliptic curve signature scheme EdDSA and one instance of it
- called Ed25519 is described. An example implementation and test
- vectors are provided.
-
-Status of This Memo
-
- This Internet-Draft is submitted in full conformance with the
- provisions of BCP 78 and BCP 79.
-
- Internet-Drafts are working documents of the Internet Engineering
- Task Force (IETF). Note that other groups may also distribute
- working documents as Internet-Drafts. The list of current Internet-
- Drafts is at http://datatracker.ietf.org/drafts/current/.
-
- Internet-Drafts are draft documents valid for a maximum of six months
- and may be updated, replaced, or obsoleted by other documents at any
- time. It is inappropriate to use Internet-Drafts as reference
- material or to cite them other than as "work in progress."
-
- This Internet-Draft will expire on August 26, 2015.
-
-Copyright Notice
-
- Copyright (c) 2015 IETF Trust and the persons identified as the
- document authors. All rights reserved.
-
- This document is subject to BCP 78 and the IETF Trust's Legal
- Provisions Relating to IETF Documents
- (http://trustee.ietf.org/license-info) in effect on the date of
- publication of this document. Please review these documents
- carefully, as they describe your rights and restrictions with respect
- to this document. Code Components extracted from this document must
- include Simplified BSD License text as described in Section 4.e of
- the Trust Legal Provisions and are provided without warranty as
- described in the Simplified BSD License.
-
-
-
-
-Josefsson & Moeller Expires August 26, 2015 [Page 1]
-
-
-Internet-Draft EdDSA & Ed25519 February 2015
-
-
-Table of Contents
-
- 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 2
- 2. Notation . . . . . . . . . . . . . . . . . . . . . . . . . . 3
- 3. Background . . . . . . . . . . . . . . . . . . . . . . . . . 3
- 4. EdDSA . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
- 4.1. Encoding . . . . . . . . . . . . . . . . . . . . . . . . 4
- 4.2. Keys . . . . . . . . . . . . . . . . . . . . . . . . . . 5
- 4.3. Sign . . . . . . . . . . . . . . . . . . . . . . . . . . 5
- 4.4. Verify . . . . . . . . . . . . . . . . . . . . . . . . . 5
- 5. Ed25519 . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
- 5.1. Modular arithmetic . . . . . . . . . . . . . . . . . . . 6
- 5.2. Encoding . . . . . . . . . . . . . . . . . . . . . . . . 6
- 5.3. Decoding . . . . . . . . . . . . . . . . . . . . . . . . 6
- 5.4. Point addition . . . . . . . . . . . . . . . . . . . . . 7
- 5.5. Key Generation . . . . . . . . . . . . . . . . . . . . . 8
- 5.6. Sign . . . . . . . . . . . . . . . . . . . . . . . . . . 8
- 5.7. Verify . . . . . . . . . . . . . . . . . . . . . . . . . 9
- 5.8. Python illustration . . . . . . . . . . . . . . . . . . . 9
- 6. Test Vectors for Ed25519 . . . . . . . . . . . . . . . . . . 14
- 7. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . 17
- 8. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 18
- 9. Security Considerations . . . . . . . . . . . . . . . . . . . 18
- 9.1. Side-channel leaks . . . . . . . . . . . . . . . . . . . 18
- 10. References . . . . . . . . . . . . . . . . . . . . . . . . . 18
- 10.1. Normative References . . . . . . . . . . . . . . . . . . 18
- 10.2. Informative References . . . . . . . . . . . . . . . . . 18
- Appendix A. Ed25519 Python Library . . . . . . . . . . . . . . . 19
- Appendix B. Library driver . . . . . . . . . . . . . . . . . . . 23
- Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 24
-
-1. Introduction
-
-
- The Edwards-curve Digital Signature Algorithm (EdDSA) is a variant of
- Schnorr's signature system with Twisted Edwards curves. EdDSA needs
- to be instantiated with certain parameters and this document describe
- Ed25519 - an instantiation of EdDSA in a curve over GF(2^255-19). To
- facilitate adoption in the Internet community of Ed25519, this
- document describe the signature scheme in an implementation-oriented
- way, and we provide sample code and test vectors.
-
- The advantages with EdDSA and Ed25519 include:
-
- 1. High-performance on a variety of platforms.
-
- 2. Does not require the use of a unique random number for each
- signature.
-
-
-
-
-Josefsson & Moeller Expires August 26, 2015 [Page 2]
-
-
-Internet-Draft EdDSA & Ed25519 February 2015
-
-
- 3. More resilient to side-channel attacks.
-
- 4. Small public keys (32 bytes) and signatures (64 bytes).
-
- 5. The formulas are "strongly unified", i.e., they are valid for all
- points on the curve, with no exceptions. This obviates the need
- for EdDSA to perform expensive point validation on untrusted
- public values.
-
- 6. Collision resilience, meaning that hash-function collisions do
- not break this system.
-
- For further background, see the original EdDSA paper [EDDSA].
-
-2. Notation
-
-
- The following notation is used throughout the document:
-
- GF(p) finite field with p elements
-
- x^y x multiplied by itself y times
-
- B generator of the group or subgroup of interest
-
- n B B added to itself n times.
-
- h_i the i'th bit of h
-
- a || b (bit-)string a concatenated with (bit-)string b
-
-3. Background
-
-
- EdDSA is defined using an elliptic curve over GF(p) of the form
-
- -x^2 + y^2 = 1 + d x^2 y^2
-
- In general, p could be a prime power, but it is usually chosen as a
- prime number. It is required that p = 1 modulo 4 (which implies that
- -1 is a square modulo p) and that d is a non-square modulo p. For
- Ed25519, the curve used is equivalent to Curve25519 [CURVE25519],
- under a change of coordinates, which means that the difficulty of the
- discrete logarithm problem is the same as for Curve25519.
-
- Points on this curve form a group under addition, (x3, y3) = (x1, y1)
- + (x2, y2), with the formulas
-
-
-
-
-
-
-Josefsson & Moeller Expires August 26, 2015 [Page 3]
-
-
-Internet-Draft EdDSA & Ed25519 February 2015
-
-
- x1 y2 + x2 y1 y1 y2 + x1 x2
- x3 = -------------------, y3 = -------------------
- 1 + d x1 x2 y1 y2 1 - d x1 x2 y1 y2
-
- The neutral element in the group is (0, 1).
-
- Unlike manyy other curves used for cryptographic applications, these
- formulas are "strongly unified": they are valid for all points on the
- curve, with no exceptions. In particular, the denominators are non-
- zero for all input points.
-
- There are more efficient formulas, which are still strongly unified,
- which use homogeneous coordinates to avoid the expensive modulo p
- inversions. See [Faster-ECC] and [Edwards-revisited].
-
-4. EdDSA
-
-
- EdDSA is a digital signature system with several parameters. The
- generic EdDSA digital signature system is normally not implemented
- directly, but instead a particular instance of EdDSA (like Ed25519)
- is implemented. A precise explanation of the generic EdDSA is thus
- not particulary useful for implementers, but for background and
- completeness, a succint description of the generic EdDSA algorithm is
- given here.
-
- EdDSA has seven parameters:
-
- 1. an integer b >= 10.
-
- 2. a cryptographic hash function H producing 2b-bit outputs.
-
- 3. a prime power p congruent to 1 modulo 4.
-
- 4. a (b-1)-bit encoding of elements of the finite field GF(p).
-
- 5. a non-square element d of GF(p)
-
- 6. an element B != (0,1) of the set E = { (x,y) is a member of GF(p)
- x GF(p) such that -x^2 + y^2 = 1 + dx^2y^2 }.
-
- 7. a prime q, of size b-3 bits, such that qB = (0, 1), i.e., q is
- the order of B or a multiple thereof.
-
-4.1. Encoding
-
-
- An element (x,y) of E is encoded as a b-bit string called ENC(x,y)
- which is the (b-1)-bit encoding of y concatenated with one bit that
- is 1 if x is negative and 0 if x is not negative. Negative elements
-
-
-
-Josefsson & Moeller Expires August 26, 2015 [Page 4]
-
-
-Internet-Draft EdDSA & Ed25519 February 2015
-
-
- of GF(q) are those x which the (b-1)-bit encoding of x is
- lexicographically larger than the (b-1)-bit encoding of -x.
-
-4.2. Keys
-
-
- An EdDSA secret key is a b-bit string k. Let the hash H(k) = (h_0,
- h_1, ..., h_(2b-1)) determine an integer a which is 2^(b-2) plus the
- sum of m = 2^i * h_i for all i equal or larger than 3 and equal to or
- less than b-3 such that m is a member of the set { 2^(b-2), 2^(b-2) +
- 8, ..., 2^(b-1) - 8 }. The EdDSA public key is ENC(A) = ENC(aB).
- The bits h_b, ..., h_(2b-1) is used below during signing.
-
-4.3. Sign
-
-
- The signature of a message M under a secret key k is the 2b-bit
- string ENC(R) || ENC'(S), where ENC'(S) is defined as the b-bit
- little-endian encoding of S. R and S are derived as follows. First
- define r = H(h_b, ... h_(2b-1)), M) interpreting 2b-bit strings in
- little-endian form as integers in {0, 1, ..., 2^(2b)-1}. Let R=rB
- and S=(r+H(ENC(R) || ENC(A) || M)a) mod l.
-
-4.4. Verify
-
-
- To verify a signature ENC(R) || ENC'(S) on a message M under a public
- key ENC(A), proceed as follows. Parse the inputs so that A and R is
- an element of E, and S is a member of the set {0, 1, ..., l-1 }.
- Compute H' = H(ENC(R) || ENC(A) || M) and check the group equation
- 8SB = 8R + 8H'A in E. Verification is rejected if parsing fails or
- the group equation does not hold.
-
-5. Ed25519
-
-
- Theoretically, Ed25519 is EdDSA instantiated with b=256, H being
- SHA-512 [RFC4634], p is the prime 2^255-19, the 255-bit encoding of
- GF(2^255-19) being the little-endian encoding of {0, 1, ...,
- 2^255-20}, q is the prime 2^252 + 0x14def9dea2f79cd65812631a5cf5d3ed,
- d = -121665/121666 which is a member of GF(p), and B is the unique
- point (x, 4/5) in E for which x is "positive", which with the
- encoding used simply means that the least significant bit of x is 0.
- The curve p, prime q, d and B follows from [I-D.irtf-cfrg-curves].
-
- Written out explicitly, B is the point (15112221349535400772501151409
- 588531511454012693041857206046113283949847762202, 4631683569492647816
- 9428394003475163141307993866256225615783033603165251855960).
-
-
-
-
-
-
-
-Josefsson & Moeller Expires August 26, 2015 [Page 5]
-
-
-Internet-Draft EdDSA & Ed25519 February 2015
-
-
-5.1. Modular arithmetic
-
-
- For advise on how to implement arithmetic modulo p = 2^255 - 1
- efficiently and securely, see Curve25519 [CURVE25519]. For inversion
- modulo p, it is recommended to use the identity x^-1 = x^(p-2) (mod
- p).
-
- For point decoding or "decompression", square roots modulo p are
- needed. They can be computed using the Tonelli-Shanks algorithm, or
- the special case for p = 5 (mod 8). To find a square root of a,
- first compute the candidate root x = a^((p+3)/8) (mod p). Then there
- are three cases:
-
- x^2 = a (mod p). Then x is a square root.
-
- x^2 = -a (mod p). Then 2^((p-1)/4) x is a square root.
-
- a is not a square modulo p.
-
-5.2. Encoding
-
-
- All values are coded as octet strings, and integers are coded using
- little endian convention. I.e., a 32-octet string h h[0],...h[31]
- represents the integer h[0] + 2^8 h[1] + ... + 2^248 h[31].
-
- A curve point (x,y), with coordiantes in the range 0 <= x,y < p, is
- coded as follows. First encode the y-coordinate as a little-endian
- string of 32 octets. The most significant bit of the final octet is
- always zero. To form the encoding of the point, copy the least
- significant bit of the x-coordinate to the most significant bit of
- the final octet.
-
-5.3. Decoding
-
-
- Decoding a point, given as a 32-octet string, is a little more
- complicated.
-
- 1. First interpret the string as an integer in little-endian
- representation. Bit 255 of this number is the least significant
- bit of the x-coordinate, and denote this value x_0. The
- y-coordinate is recovered simply by clearing this bit. If the
- resulting value is >= p, decoding fails.
-
- 2. To recover the x coordinate, the curve equation implies x^2 =
- (y^2 - 1) / (d y^2 + 1) (mod p). Since d is a non-square and -1
- is a square, the numerator, (d y^2 + 1), is always invertible
- modulo p. Let u = y^2 - 1 and v = d y^2 + 1. To compute the
- square root of (u/v), the first step is to compute the candidate
-
-
-
-Josefsson & Moeller Expires August 26, 2015 [Page 6]
-
-
-Internet-Draft EdDSA & Ed25519 February 2015
-
-
- root x = (u/v)^((p+3)/8). This can be done using the following
- trick, to use a single modular powering for both the inversion of
- v and the square root:
-
- (p+3)/8 3 (p-5)/8
- x = (u/v) = u v (u v^7) (mod p)
-
- 3. Again, there are three cases:
-
- 1. If v x^2 = u (mod p), x is a square root.
-
- 2. If v x^2 = -u (mod p), set x <-- x 2^((p-1)/4), which is a
- square root.
-
- 3. Otherwise, no square root exists modulo p, and decoding
- fails.
-
- 4. Finally, use the x_0 bit to select the right square root. If x =
- 0, and x_0 = 1, decoding fails. Otherwise, if x_0 != x mod 2,
- set x <-- p - x. Return the decoded point (x,y).
-
-5.4. Point addition
-
-
- For point addition, the following method is recommended. A point
- (x,y) is represented in extended homogeneous coordinates (X, Y, Z,
- T), with x = X/Z, y = Y/Z, x y = T/Z.
-
- The following formulas for adding two points, (x3,y3) =
- (x1,y1)+(x2,y2) are described in [Edwards-revisited], section 3.1.
- They are strongly unified, i.e., they work for any pair of valid
- input points.
-
- A = (Y1-X1)*(Y2-X2)
- B = (Y1+X1)*(Y2+X2)
- C = T1*2*d*T2
- D = Z1*2*Z2
- E = B-A
- F = D-C
- G = D+C
- H = B+A
- X3 = E*F
- Y3 = G*H
- T3 = E*H
- Z3 = F*G
-
-
-
-
-
-
-
-Josefsson & Moeller Expires August 26, 2015 [Page 7]
-
-
-Internet-Draft EdDSA & Ed25519 February 2015
-
-
-5.5. Key Generation
-
-
- The secret is 32 octets (256 bits, corresponding to b) of
- cryptographically-secure random data. See [RFC4086] for a discussion
- about randomness.
-
- The 32-byte public key is generated by the following steps.
-
- 1. Hash the 32-byte secret using SHA-512, storing the digest in a
- 64-octet large buffer, denoted h. Only the lower 32 bytes are
- used for generating the public key.
-
- 2. Prune the buffer. In C terminology:
-
- h[0] &= ~0x07;
- h[31] &= 0x7F;
- h[31] |= 0x40;
-
- 3. Interpret the buffer as the little-endian integer, forming a
- secret scalar a. Perform a known-base-point scalar
- multiplication a B.
-
- 4. The public key A is the encoding of the point aB. First encode
- the y coordinate (in the range 0 <= y < p) as a little-endian
- string of 32 octets. The most significant bit of the final octet
- is always zero. To form the encoding of the point aB, copy the
- least significant bit of the x coordinate to the most significant
- bit of the final octet. The result is the public key.
-
-5.6. Sign
-
-
- The imputs to the signing procedure is the secret key, a 32-octet
- string, and a message M of arbitrary size.
-
- 1. Hash the secret key, 32-octets, using SHA-512. Let h denote the
- resulting digest. Construct the secret scalar a from the first
- half of the digest, and the corresponding public key A, as
- described in the previous section. Let prefix denote the second
- half of the hash digest, h[32],...,h[63].
-
- 2. Compute SHA-512(prefix || M), where M is the message to be
- signed. Interpret the 64-octet digest as a little-endian integer
- r.
-
- 3. Compute the point rB. For efficiency, do this by first reducing
- r modulo q, the group order of B. Let the string R be the
- encoding of this point.
-
-
-
-
-Josefsson & Moeller Expires August 26, 2015 [Page 8]
-
-
-Internet-Draft EdDSA & Ed25519 February 2015
-
-
- 4. Compute SHA512(R || A || M), and interpret the 64-octet digest as
- a little-endian integer k.
-
- 5. Compute s = (r + k a) mod q. For efficiency, again reduce k
- modulo q first.
-
- 6. Form the signature of the concatenation of R (32 octets) and the
- little-endian encoding of s (32 octets, three most significant
- bits of the final octets always zero).
-
-5.7. Verify
-
-
- 1. To verify a signature on a message M, first split the signature
- into two 32-octet halves. Decode the first half as a point R,
- and the second half as an integer s, in the range 0 <= s < q. If
- the decoding fails, the signature is invalid.
-
- 2. Compute SHA512(R || A || M), and interpret the 64-octet digest as
- a little-endian integer k.
-
- 3. Check the group equation 8s B = 8 R + 8k A. It's sufficient, but
- not required, to instead check s B = R + k A.
-
-5.8. Python illustration
-
-
- The rest of this section describes how Ed25519 can be implemented in
- Python (version 3.2 or later) for illustration. See appendix A for
- the complete implementation and appendix B for a test-driver to run
- it through some test vectors.
-
- First some preliminaries that will be needed.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Josefsson & Moeller Expires August 26, 2015 [Page 9]
-
-
-Internet-Draft EdDSA & Ed25519 February 2015
-
-
- import hashlib
-
- def sha512(s):
- return hashlib.sha512(s).digest()
-
- # Base field Z_p
- p = 2**255 - 19
-
- def modp_inv(x):
- return pow(x, p-2, p)
-
- # Curve constant
- d = -121665 * modp_inv(121666) % p
-
- # Group order
- q = 2**252 + 27742317777372353535851937790883648493
-
- def sha512_modq(s):
- return int.from_bytes(sha512(s), "little") % q
-
- Then follows functions to perform point operations.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Josefsson & Moeller Expires August 26, 2015 [Page 10]
-
-
-Internet-Draft EdDSA & Ed25519 February 2015
-
-
-# Points are represented as tuples (X, Y, Z, T) of extended coordinates,
-# with x = X/Z, y = Y/Z, x*y = T/Z
-
-def point_add(P, Q):
- A = (P[1]-P[0])*(Q[1]-Q[0]) % p
- B = (P[1]+P[0])*(Q[1]+Q[0]) % p
- C = 2 * P[3] * Q[3] * d % p
- D = 2 * P[2] * Q[2] % p
- E = B-A
- F = D-C
- G = D+C
- H = B+A
- return (E*F, G*H, F*G, E*H)
-
-# Computes Q = s * Q
-def point_mul(s, P):
- Q = (0, 1, 1, 0) # Neutral element
- while s > 0:
- # Is there any bit-set predicate?
- if s & 1:
- Q = point_add(Q, P)
- P = point_add(P, P)
- s >>= 1
- return Q
-
-def point_equal(P, Q):
- # x1 / z1 == x2 / z2 <==> x1 * z2 == x2 * z1
- if (P[0] * Q[2] - Q[0] * P[2]) % p != 0:
- return False
- if (P[1] * Q[2] - Q[1] * P[2]) % p != 0:
- return False
- return True
-
- Now follows functions for point compression.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Josefsson & Moeller Expires August 26, 2015 [Page 11]
-
-
-Internet-Draft EdDSA & Ed25519 February 2015
-
-
-# Square root of -1
-modp_sqrt_m1 = pow(2, (p-1) // 4, p)
-
-# Compute corresponding x coordinate, with low bit corresponding to sign,
-# or return None on failure
-def recover_x(y, sign):
- x2 = (y*y-1) * modp_inv(d*y*y+1)
- if x2 == 0:
- if sign:
- return None
- else:
- return 0
-
- # Compute square root of x2
- x = pow(x2, (p+3) // 8, p)
- if (x*x - x2) % p != 0:
- x = x * modp_sqrt_m1 % p
- if (x*x - x2) % p != 0:
- return None
-
- if (x & 1) != sign:
- x = p - x
- return x
-
-# Base point
-g_y = 4 * modp_inv(5) % p
-g_x = recover_x(g_y, 0)
-G = (g_x, g_y, 1, g_x * g_y % p)
-
-def point_compress(P):
- zinv = modp_inv(P[2])
- x = P[0] * zinv % p
- y = P[1] * zinv % p
- return int.to_bytes(y | ((x & 1) << 255), 32, "little")
-
-def point_decompress(s):
- if len(s) != 32:
- raise Exception("Invalid input length for decompression")
- y = int.from_bytes(s, "little")
- sign = y >> 255
- y &= (1 << 255) - 1
-
- x = recover_x(y, sign)
- if x is None:
- return None
- else:
- return (x, y, 1, x*y % p)
-
-
-
-
-Josefsson & Moeller Expires August 26, 2015 [Page 12]
-
-
-Internet-Draft EdDSA & Ed25519 February 2015
-
-
- These are functions for manipulating the secret.
-
- def secret_expand(secret):
- if len(secret) != 32:
- raise Exception("Bad size of private key")
- h = sha512(secret)
- a = int.from_bytes(h[:32], "little")
- a &= (1 << 254) - 8
- a |= (1 << 254)
- return (a, h[32:])
-
- def secret_to_public(secret):
- (a, dummy) = secret_expand(secret)
- return point_compress(point_mul(a, G))
-
- The signature function works as below.
-
- def sign(secret, msg):
- a, prefix = secret_expand(secret)
- A = point_compress(point_mul(a, G))
- r = sha512_modq(prefix + msg)
- R = point_mul(r, G)
- Rs = point_compress(R)
- h = sha512_modq(Rs + A + msg)
- s = (r + h * a) % q
- return Rs + int.to_bytes(s, 32, "little")
-
- And finally the verification function.
-
- def verify(public, msg, signature):
- if len(public) != 32:
- raise Exception("Bad public-key length")
- if len(signature) != 64:
- Exception("Bad signature length")
- A = point_decompress(public)
- if not A:
- return False
- Rs = signature[:32]
- R = point_decompress(Rs)
- if not R:
- return False
- s = int.from_bytes(signature[32:], "little")
- h = sha512_modq(Rs + public + msg)
- sB = point_mul(s, G)
- hA = point_mul(h, A)
- return point_equal(sB, point_add(R, hA))
-
-
-
-
-
-Josefsson & Moeller Expires August 26, 2015 [Page 13]
-
-
-Internet-Draft EdDSA & Ed25519 February 2015
-
-
-6. Test Vectors for Ed25519
-
-
- Below is a sequence of octets with test vectors for the the Ed25519
- signature algorithm. The octets are hex encoded and whitespace is
- inserted for readability. Private keys are 64 bytes, public keys 32
- bytes, message of arbitrary length, and signatures are 64 bytes. The
- test vectors are taken from [ED25519-TEST-VECTORS] (but we removed
- the public key as a suffix of the secret key, and removed the message
- from the signature) and [ED25519-LIBGCRYPT-TEST-VECTORS].
-
- -----TEST 1
- SECRET KEY:
- 9d61b19deffd5a60ba844af492ec2cc4
- 4449c5697b326919703bac031cae7f60
-
- PUBLIC KEY:
- d75a980182b10ab7d54bfed3c964073a
- 0ee172f3daa62325af021a68f707511a
-
- MESSAGE (length 0 bytes):
-
- SIGNATURE:
- e5564300c360ac729086e2cc806e828a
- 84877f1eb8e5d974d873e06522490155
- 5fb8821590a33bacc61e39701cf9b46b
- d25bf5f0595bbe24655141438e7a100b
-
- -----TEST 2
- SECRET KEY:
- 4ccd089b28ff96da9db6c346ec114e0f
- 5b8a319f35aba624da8cf6ed4fb8a6fb
-
- PUBLIC KEY:
- 3d4017c3e843895a92b70aa74d1b7ebc
- 9c982ccf2ec4968cc0cd55f12af4660c
-
- MESSAGE (length 1 byte):
- 72
-
- SIGNATURE:
- 92a009a9f0d4cab8720e820b5f642540
- a2b27b5416503f8fb3762223ebdb69da
- 085ac1e43e15996e458f3613d0f11d8c
- 387b2eaeb4302aeeb00d291612bb0c00
-
- -----TEST 3
- SECRET KEY:
- c5aa8df43f9f837bedb7442f31dcb7b1
-
-
-
-Josefsson & Moeller Expires August 26, 2015 [Page 14]
-
-
-Internet-Draft EdDSA & Ed25519 February 2015
-
-
- 66d38535076f094b85ce3a2e0b4458f7
-
- PUBLIC KEY:
- fc51cd8e6218a1a38da47ed00230f058
- 0816ed13ba3303ac5deb911548908025
-
- MESSAGE (length 2 bytes):
- af82
-
- SIGNATURE:
- 6291d657deec24024827e69c3abe01a3
- 0ce548a284743a445e3680d7db5ac3ac
- 18ff9b538d16f290ae67f760984dc659
- 4a7c15e9716ed28dc027beceea1ec40a
-
- -----TEST 1024
- SECRET KEY:
- f5e5767cf153319517630f226876b86c
- 8160cc583bc013744c6bf255f5cc0ee5
-
- PUBLIC KEY:
- 278117fc144c72340f67d0f2316e8386
- ceffbf2b2428c9c51fef7c597f1d426e
-
- MESSAGE:
- 08b8b2b733424243760fe426a4b54908
- 632110a66c2f6591eabd3345e3e4eb98
- fa6e264bf09efe12ee50f8f54e9f77b1
- e355f6c50544e23fb1433ddf73be84d8
- 79de7c0046dc4996d9e773f4bc9efe57
- 38829adb26c81b37c93a1b270b20329d
- 658675fc6ea534e0810a4432826bf58c
- 941efb65d57a338bbd2e26640f89ffbc
- 1a858efcb8550ee3a5e1998bd177e93a
- 7363c344fe6b199ee5d02e82d522c4fe
- ba15452f80288a821a579116ec6dad2b
- 3b310da903401aa62100ab5d1a36553e
- 06203b33890cc9b832f79ef80560ccb9
- a39ce767967ed628c6ad573cb116dbef
- efd75499da96bd68a8a97b928a8bbc10
- 3b6621fcde2beca1231d206be6cd9ec7
- aff6f6c94fcd7204ed3455c68c83f4a4
- 1da4af2b74ef5c53f1d8ac70bdcb7ed1
- 85ce81bd84359d44254d95629e9855a9
- 4a7c1958d1f8ada5d0532ed8a5aa3fb2
- d17ba70eb6248e594e1a2297acbbb39d
- 502f1a8c6eb6f1ce22b3de1a1f40cc24
- 554119a831a9aad6079cad88425de6bd
-
-
-
-Josefsson & Moeller Expires August 26, 2015 [Page 15]
-
-
-Internet-Draft EdDSA & Ed25519 February 2015
-
-
- e1a9187ebb6092cf67bf2b13fd65f270
- 88d78b7e883c8759d2c4f5c65adb7553
- 878ad575f9fad878e80a0c9ba63bcbcc
- 2732e69485bbc9c90bfbd62481d9089b
- eccf80cfe2df16a2cf65bd92dd597b07
- 07e0917af48bbb75fed413d238f5555a
- 7a569d80c3414a8d0859dc65a46128ba
- b27af87a71314f318c782b23ebfe808b
- 82b0ce26401d2e22f04d83d1255dc51a
- ddd3b75a2b1ae0784504df543af8969b
- e3ea7082ff7fc9888c144da2af58429e
- c96031dbcad3dad9af0dcbaaaf268cb8
- fcffead94f3c7ca495e056a9b47acdb7
- 51fb73e666c6c655ade8297297d07ad1
- ba5e43f1bca32301651339e22904cc8c
- 42f58c30c04aafdb038dda0847dd988d
- cda6f3bfd15c4b4c4525004aa06eeff8
- ca61783aacec57fb3d1f92b0fe2fd1a8
- 5f6724517b65e614ad6808d6f6ee34df
- f7310fdc82aebfd904b01e1dc54b2927
- 094b2db68d6f903b68401adebf5a7e08
- d78ff4ef5d63653a65040cf9bfd4aca7
- 984a74d37145986780fc0b16ac451649
- de6188a7dbdf191f64b5fc5e2ab47b57
- f7f7276cd419c17a3ca8e1b939ae49e4
- 88acba6b965610b5480109c8b17b80e1
- b7b750dfc7598d5d5011fd2dcc5600a3
- 2ef5b52a1ecc820e308aa342721aac09
- 43bf6686b64b2579376504ccc493d97e
- 6aed3fb0f9cd71a43dd497f01f17c0e2
- cb3797aa2a2f256656168e6c496afc5f
- b93246f6b1116398a346f1a641f3b041
- e989f7914f90cc2c7fff357876e506b5
- 0d334ba77c225bc307ba537152f3f161
- 0e4eafe595f6d9d90d11faa933a15ef1
- 369546868a7f3a45a96768d40fd9d034
- 12c091c6315cf4fde7cb68606937380d
- b2eaaa707b4c4185c32eddcdd306705e
- 4dc1ffc872eeee475a64dfac86aba41c
- 0618983f8741c5ef68d3a101e8a3b8ca
- c60c905c15fc910840b94c00a0b9d0
-
- SIGNATURE:
- 0aab4c900501b3e24d7cdf4663326a3a
- 87df5e4843b2cbdb67cbf6e460fec350
- aa5371b1508f9f4528ecea23c436d94b
- 5e8fcd4f681e30a6ac00a9704a188a03
-
-
-
-
-Josefsson & Moeller Expires August 26, 2015 [Page 16]
-
-
-Internet-Draft EdDSA & Ed25519 February 2015
-
-
- -----TEST 1A
- -----An additional test with the data from test 1 but using an
- -----uncompressed public key.
- SECRET KEY:
- 9d61b19deffd5a60ba844af492ec2cc4
- 4449c5697b326919703bac031cae7f60
-
- PUBLIC KEY:
- 0455d0e09a2b9d34292297e08d60d0f6
- 20c513d47253187c24b12786bd777645
- ce1a5107f7681a02af2523a6daf372e1
- 0e3a0764c9d3fe4bd5b70ab18201985a
- d7
-
- MSG (length 0 bytes):
-
- SIGNATURE:
- e5564300c360ac729086e2cc806e828a
- 84877f1eb8e5d974d873e06522490155
- 5fb8821590a33bacc61e39701cf9b46b
- d25bf5f0595bbe24655141438e7a100b
-
- -----TEST 1B
- -----An additional test with the data from test 1 but using an
- -----compressed prefix.
- SECRET KEY:
- 9d61b19deffd5a60ba844af492ec2cc4
- 4449c5697b326919703bac031cae7f60
-
- PUBLIC KEY:
- 40d75a980182b10ab7d54bfed3c96407
- 3a0ee172f3daa62325af021a68f70751
- 1a
-
- MESSAGE (length 0 bytes):
-
- SIGNATURE:
- e5564300c360ac729086e2cc806e828a
- 84877f1eb8e5d974d873e06522490155
- 5fb8821590a33bacc61e39701cf9b46b
- d25bf5f0595bbe24655141438e7a100b
- -----
-
-7. Acknowledgements
-
-
- Feedback on this document was received from Werner Koch and Damien
- Miller.
-
-
-
-
-Josefsson & Moeller Expires August 26, 2015 [Page 17]
-
-
-Internet-Draft EdDSA & Ed25519 February 2015
-
-
-8. IANA Considerations
-
-
- None.
-
-9. Security Considerations
-
-
-9.1. Side-channel leaks
-
-
- For implementations performing signatures, secrecy of the key is
- fundamental. It is possible to protect against some side-channel
- attacks by ensuring that the implementation executes exactly the same
- sequence of instructions and performs exactly the same memory
- accesses, for any value of the secret key.
-
- To make an implementation side-channel silent in this way, the modulo
- p arithmetic must not use any data-dependent branches, e.g., related
- to carry propagation. Side channel-silent point addition is
- straight-forward, thanks to the unified formulas.
-
- Scalar multiplication, multiplying a point by an integer, needs some
- additional effort to implement in a side-channel silent manner. One
- simple approach is to implement a side-channel silent conditional
- assignment, and use together with the binary algorithm to examine one
- bit of the integer at a time.
-
- Note that the example implementation in this document does not
- attempt to be side-channel silent.
-
-10. References
-
-
-10.1. Normative References
-
-
- [RFC4634] Eastlake, D. and T. Hansen, "US Secure Hash Algorithms
- (SHA and HMAC-SHA)", RFC 4634, July 2006.
-
- [I-D.irtf-cfrg-curves]
- Langley, A., Salz, R., and S. Turner, "Elliptic Curves for
- Security", draft-irtf-cfrg-curves-01 (work in progress),
- January 2015.
-
-10.2. Informative References
-
-
- [RFC4086] Eastlake, D., Schiller, J., and S. Crocker, "Randomness
- Requirements for Security", BCP 106, RFC 4086, June 2005.
-
-
-
-
-
-
-
-Josefsson & Moeller Expires August 26, 2015 [Page 18]
-
-
-Internet-Draft EdDSA & Ed25519 February 2015
-
-
- [EDDSA] Bernstein, D., Duif, N., Lange, T., Schwabe, P., and B.
- Yang, "High-speed high-security signatures", WWW
- http://ed25519.cr.yp.to/ed25519-20110926.pdf, September
- 2011.
-
- [Faster-ECC]
- Bernstein, D. and T. Lange, "Faster addition and doubling
- on elliptic curves", WWW http://eprint.iacr.org/2007/286,
- July 2007.
-
- [Edwards-revisited]
- Hisil, H., Wong, K., Carter, G., and E. Dawson, "Twisted
- Edwards Curves Revisited", WWW
- http://eprint.iacr.org/2008/522, December 2008.
-
- [CURVE25519]
- Bernstein, D., "Curve25519: new Diffie-Hellman speed
- records", WWW http://cr.yp.to/ecdh.html, February 2006.
-
- [ED25519-TEST-VECTORS]
- Bernstein, D., Duif, N., Lange, T., Schwabe, P., and B.
- Yang, "Ed25519 test vectors", WWW
- http://ed25519.cr.yp.to/python/sign.input, July 2011.
-
- [ED25519-LIBGCRYPT-TEST-VECTORS]
- Koch, W., "Ed25519 Libgcrypt test vectors", WWW
- http://git.gnupg.org/cgi-
- bin/gitweb.cgi?p=libgcrypt.git;a=blob;f=tests/t-ed25519.in
- p;h=e13566f826321eece65e02c593bc7d885b3dbe23;hb=refs/
- heads/master, July 2014.
-
-Appendix A. Ed25519 Python Library
-
-
- Below is an example implementation of Ed25519 written in Python,
- version 3.2 or higher is required.
-
-# Loosely based on the public domain code at
-# http://ed25519.cr.yp.to/software.html
-#
-# Needs python-3.2
-
-import hashlib
-
-
-def sha512(s):
- return hashlib.sha512(s).digest()
-
-# Base field Z_p
-
-
-
-Josefsson & Moeller Expires August 26, 2015 [Page 19]
-
-
-Internet-Draft EdDSA & Ed25519 February 2015
-
-
-p = 2**255 - 19
-
-
-def modp_inv(x):
- return pow(x, p-2, p)
-
-# Curve constant
-d = -121665 * modp_inv(121666) % p
-
-# Group order
-q = 2**252 + 27742317777372353535851937790883648493
-
-
-def sha512_modq(s):
- return int.from_bytes(sha512(s), "little") % q
-
-# Points are represented as tuples (X, Y, Z, T) of extended coordinates,
-# with x = X/Z, y = Y/Z, x*y = T/Z
-
-
-def point_add(P, Q):
- A = (P[1]-P[0])*(Q[1]-Q[0]) % p
- B = (P[1]+P[0])*(Q[1]+Q[0]) % p
- C = 2 * P[3] * Q[3] * d % p
- D = 2 * P[2] * Q[2] % p
- E = B-A
- F = D-C
- G = D+C
- H = B+A
- return (E*F, G*H, F*G, E*H)
-
-
-# Computes Q = s * Q
-def point_mul(s, P):
- Q = (0, 1, 1, 0) # Neutral element
- while s > 0:
- # Is there any bit-set predicate?
- if s & 1:
- Q = point_add(Q, P)
- P = point_add(P, P)
- s >>= 1
- return Q
-
-
-def point_equal(P, Q):
- # x1 / z1 == x2 / z2 <==> x1 * z2 == x2 * z1
- if (P[0] * Q[2] - Q[0] * P[2]) % p != 0:
- return False
-
-
-
-Josefsson & Moeller Expires August 26, 2015 [Page 20]
-
-
-Internet-Draft EdDSA & Ed25519 February 2015
-
-
- if (P[1] * Q[2] - Q[1] * P[2]) % p != 0:
- return False
- return True
-
-# Square root of -1
-modp_sqrt_m1 = pow(2, (p-1) // 4, p)
-
-
-# Compute corresponding x coordinate, with low bit corresponding to sign,
-# or return None on failure
-def recover_x(y, sign):
- x2 = (y*y-1) * modp_inv(d*y*y+1)
- if x2 == 0:
- if sign:
- return None
- else:
- return 0
-
- # Compute square root of x2
- x = pow(x2, (p+3) // 8, p)
- if (x*x - x2) % p != 0:
- x = x * modp_sqrt_m1 % p
- if (x*x - x2) % p != 0:
- return None
-
- if (x & 1) != sign:
- x = p - x
- return x
-
-# Base point
-g_y = 4 * modp_inv(5) % p
-g_x = recover_x(g_y, 0)
-G = (g_x, g_y, 1, g_x * g_y % p)
-
-
-def point_compress(P):
- zinv = modp_inv(P[2])
- x = P[0] * zinv % p
- y = P[1] * zinv % p
- return int.to_bytes(y | ((x & 1) << 255), 32, "little")
-
-
-def point_decompress(s):
- if len(s) != 32:
- raise Exception("Invalid input length for decompression")
- y = int.from_bytes(s, "little")
- sign = y >> 255
- y &= (1 << 255) - 1
-
-
-
-Josefsson & Moeller Expires August 26, 2015 [Page 21]
-
-
-Internet-Draft EdDSA & Ed25519 February 2015
-
-
- x = recover_x(y, sign)
- if x is None:
- return None
- else:
- return (x, y, 1, x*y % p)
-
-
-def secret_expand(secret):
- if len(secret) != 32:
- raise Exception("Bad size of private key")
- h = sha512(secret)
- a = int.from_bytes(h[:32], "little")
- a &= (1 << 254) - 8
- a |= (1 << 254)
- return (a, h[32:])
-
-
-def secret_to_public(secret):
- (a, dummy) = secret_expand(secret)
- return point_compress(point_mul(a, G))
-
-
-def sign(secret, msg):
- a, prefix = secret_expand(secret)
- A = point_compress(point_mul(a, G))
- r = sha512_modq(prefix + msg)
- R = point_mul(r, G)
- Rs = point_compress(R)
- h = sha512_modq(Rs + A + msg)
- s = (r + h * a) % q
- return Rs + int.to_bytes(s, 32, "little")
-
-
-def verify(public, msg, signature):
- if len(public) != 32:
- raise Exception("Bad public-key length")
- if len(signature) != 64:
- Exception("Bad signature length")
- A = point_decompress(public)
- if not A:
- return False
- Rs = signature[:32]
- R = point_decompress(Rs)
- if not R:
- return False
- s = int.from_bytes(signature[32:], "little")
- h = sha512_modq(Rs + public + msg)
- sB = point_mul(s, G)
-
-
-
-Josefsson & Moeller Expires August 26, 2015 [Page 22]
-
-
-Internet-Draft EdDSA & Ed25519 February 2015
-
-
- hA = point_mul(h, A)
- return point_equal(sB, point_add(R, hA))
-
-Appendix B. Library driver
-
-
- Below is a command-line tool that uses the library above to perform
- computations, for interactive use or for self-checking.
-
- import sys
- import binascii
-
- from ed25519 import *
-
- def point_valid(P):
- zinv = modp_inv(P[2])
- x = P[0] * zinv % p
- y = P[1] * zinv % p
- assert (x*y - P[3]*zinv) % p == 0
- return (-x*x + y*y - 1 - d*x*x*y*y) % p == 0
-
- assert point_valid(G)
- Z = (0, 1, 1, 0)
- assert point_valid(Z)
-
- assert point_equal(Z, point_add(Z, Z))
- assert point_equal(G, point_add(Z, G))
- assert point_equal(Z, point_mul(0, G))
- assert point_equal(G, point_mul(1, G))
- assert point_equal(point_add(G, G), point_mul(2, G))
- for i in range(0, 100):
- assert point_valid(point_mul(i, G))
- assert point_equal(Z, point_mul(q, G))
-
- def munge_string(s, pos, change):
- return (s[:pos] +
- int.to_bytes(s[pos] ^ change, 1, "little") +
- s[pos+1:])
-
- # Read a file in the format of
- # http://ed25519.cr.yp.to/python/sign.input
- lineno = 0
- while True:
- line = sys.stdin.readline()
- if not line:
- break
- lineno = lineno + 1
- print(lineno)
- fields = line.split(":")
-
-
-
-Josefsson & Moeller Expires August 26, 2015 [Page 23]
-
-
-Internet-Draft EdDSA & Ed25519 February 2015
-
-
- secret = (binascii.unhexlify(fields[0]))[:32]
- public = binascii.unhexlify(fields[1])
- msg = binascii.unhexlify(fields[2])
- signature = binascii.unhexlify(fields[3])[:64]
-
- assert public == secret_to_public(secret)
- assert signature == sign(secret, msg)
- assert verify(public, msg, signature)
- if len(msg) == 0:
- bad_msg = b"x"
- else:
- bad_msg = munge_string(msg, len(msg) // 3, 4)
- assert not verify(public, bad_msg, signature)
- bad_signature = munge_string(signature, 20, 8)
- assert not verify(public, msg, bad_signature)
- bad_signature = munge_string(signature, 40, 16)
- assert not verify(public, msg, bad_signature)
-
-Authors' Addresses
-
- Simon Josefsson
- SJD AB
-
- Email: simon@josefsson.org
- URI: http://josefsson.org/
-
-
- Niels Moeller
-
- Email: nisse@lysator.liu.se
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Josefsson & Moeller Expires August 26, 2015 [Page 24]
-
-
-
-Html markup produced by rfcmarkup 1.113, available from https://tools.ietf.org/tools/rfcmarkup/
+Note: This draft is now superseded by https://datatracker.ietf.org/doc/rfc8032/
+(review of the differences is left as an exercise for the reader)
diff --git a/src/cryptonote_basic/CMakeLists.txt b/src/cryptonote_basic/CMakeLists.txt
index d50a9df67..21445959d 100644
--- a/src/cryptonote_basic/CMakeLists.txt
+++ b/src/cryptonote_basic/CMakeLists.txt
@@ -27,9 +27,13 @@
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
if(APPLE)
- find_library(IOKIT_LIBRARY IOKit)
- mark_as_advanced(IOKIT_LIBRARY)
- list(APPEND EXTRA_LIBRARIES ${IOKIT_LIBRARY})
+ if(DEPENDS)
+ list(APPEND EXTRA_LIBRARIES "-framework Foundation -framework ApplicationServices -framework AppKit -framework IOKit")
+ else()
+ find_library(IOKIT_LIBRARY IOKit)
+ mark_as_advanced(IOKIT_LIBRARY)
+ list(APPEND EXTRA_LIBRARIES ${IOKIT_LIBRARY})
+ endif()
endif()
set(cryptonote_basic_sources
diff --git a/src/cryptonote_basic/account.cpp b/src/cryptonote_basic/account.cpp
index 4cbfa8142..e891a748d 100644
--- a/src/cryptonote_basic/account.cpp
+++ b/src/cryptonote_basic/account.cpp
@@ -197,10 +197,14 @@ DISABLE_VS_WARNINGS(4244 4345)
//-----------------------------------------------------------------
void account_base::create_from_device(const std::string &device_name)
{
-
hw::device &hwdev = hw::get_device(device_name);
- m_keys.set_device(hwdev);
hwdev.set_name(device_name);
+ create_from_device(hwdev);
+ }
+
+ void account_base::create_from_device(hw::device &hwdev)
+ {
+ m_keys.set_device(hwdev);
MCDEBUG("ledger", "device type: "<<typeid(hwdev).name());
hwdev.init();
hwdev.connect();
diff --git a/src/cryptonote_basic/account.h b/src/cryptonote_basic/account.h
index dac66ff1a..98bba55b1 100644
--- a/src/cryptonote_basic/account.h
+++ b/src/cryptonote_basic/account.h
@@ -77,7 +77,8 @@ namespace cryptonote
public:
account_base();
crypto::secret_key generate(const crypto::secret_key& recovery_key = crypto::secret_key(), bool recover = false, bool two_random = false);
- void create_from_device(const std::string &device_name) ;
+ void create_from_device(const std::string &device_name);
+ void create_from_device(hw::device &hwdev);
void create_from_keys(const cryptonote::account_public_address& address, const crypto::secret_key& spendkey, const crypto::secret_key& viewkey);
void create_from_viewkey(const cryptonote::account_public_address& address, const crypto::secret_key& viewkey);
bool make_multisig(const crypto::secret_key &view_secret_key, const crypto::secret_key &spend_secret_key, const crypto::public_key &spend_public_key, const std::vector<crypto::secret_key> &multisig_keys);
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp
index c7e2f5a65..0dc3f3bb4 100644
--- a/src/cryptonote_core/blockchain.cpp
+++ b/src/cryptonote_core/blockchain.cpp
@@ -109,6 +109,12 @@ static const struct {
// version 7 starts from block 1546000, which is on or around the 6th of April, 2018. Fork time finalised on 2018-03-17.
{ 7, 1546000, 0, 1521303150 },
+
+ // version 8 starts from block 1685555, which is on or around the 18th of October, 2018. Fork time finalised on 2018-09-02.
+ { 8, 1685555, 0, 1535889547 },
+
+ // version 9 starts from block 1686275, which is on or around the 19th of October, 2018. Fork time finalised on 2018-09-02.
+ { 9, 1686275, 0, 1535889548 },
};
static const uint64_t mainnet_hard_fork_version_1_till = 1009826;
@@ -1812,15 +1818,10 @@ bool Blockchain::get_output_distribution(uint64_t amount, uint64_t from_height,
{
std::vector<uint64_t> heights;
heights.reserve(to_height + 1 - start_height);
- uint64_t real_start_height = start_height > 0 ? start_height-1 : start_height;
- for (uint64_t h = real_start_height; h <= to_height; ++h)
+ for (uint64_t h = start_height; h <= to_height; ++h)
heights.push_back(h);
distribution = m_db->get_block_cumulative_rct_outputs(heights);
- if (start_height > 0)
- {
- base = distribution[0];
- distribution.erase(distribution.begin());
- }
+ base = 0;
return true;
}
else
diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp
index 7cbf414b7..3e3d3c19c 100644
--- a/src/cryptonote_core/cryptonote_core.cpp
+++ b/src/cryptonote_core/cryptonote_core.cpp
@@ -181,7 +181,8 @@ namespace cryptonote
m_last_json_checkpoints_update(0),
m_disable_dns_checkpoints(false),
m_update_download(0),
- m_nettype(UNDEFINED)
+ m_nettype(UNDEFINED),
+ m_update_available(false)
{
m_checkpoints_updating.clear();
set_cryptonote_protocol(pprotocol);
@@ -1541,10 +1542,14 @@ namespace cryptonote
return false;
if (tools::vercmp(version.c_str(), MONERO_VERSION) <= 0)
+ {
+ m_update_available = false;
return true;
+ }
std::string url = tools::get_update_url(software, subdir, buildtag, version, true);
MCLOG_CYAN(el::Level::Info, "global", "Version " << version << " of " << software << " for " << buildtag << " is available: " << url << ", SHA256 hash " << hash);
+ m_update_available = true;
if (check_updates_level == UPDATES_NOTIFY)
return true;
diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h
index b40575ae9..58fe5b7b5 100644
--- a/src/cryptonote_core/cryptonote_core.h
+++ b/src/cryptonote_core/cryptonote_core.h
@@ -739,6 +739,16 @@ namespace cryptonote
network_type get_nettype() const { return m_nettype; };
/**
+ * @brief check whether an update is known to be available or not
+ *
+ * This does not actually trigger a check, but returns the result
+ * of the last check
+ *
+ * @return whether an update is known to be available or not
+ */
+ bool is_update_available() const { return m_update_available; }
+
+ /**
* @brief get whether fluffy blocks are enabled
*
* @return whether fluffy blocks are enabled
@@ -966,6 +976,8 @@ namespace cryptonote
network_type m_nettype; //!< which network are we on?
+ std::atomic<bool> m_update_available;
+
std::string m_checkpoints_path; //!< path to json checkpoints file
time_t m_last_dns_checkpoints_update; //!< time when dns checkpoints were last updated
time_t m_last_json_checkpoints_update; //!< time when json checkpoints were last updated
diff --git a/src/daemon/CMakeLists.txt b/src/daemon/CMakeLists.txt
index 84004c3c6..b1c4b711d 100644
--- a/src/daemon/CMakeLists.txt
+++ b/src/daemon/CMakeLists.txt
@@ -28,7 +28,9 @@
set(blocksdat "")
if(PER_BLOCK_CHECKPOINT)
- if(APPLE)
+ if(APPLE AND DEPENDS)
+ add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} --target=x86_64-apple-darwin11 -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*)
+ elseif(APPLE AND NOT DEPENDS)
add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*)
else()
add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ../blocks/checkpoints.dat blocks.dat && ${CMAKE_LINKER} ${LD_RAW_FLAGS} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat)
diff --git a/src/daemon/main.cpp b/src/daemon/main.cpp
index 82ece62a9..f483ba6c9 100644
--- a/src/daemon/main.cpp
+++ b/src/daemon/main.cpp
@@ -239,11 +239,14 @@ int main(int argc, char const * argv[])
return 1;
}
+ const char *env_rpc_login = nullptr;
+ const bool has_rpc_arg = command_line::has_arg(vm, arg.rpc_login);
+ const bool use_rpc_env = !has_rpc_arg && (env_rpc_login = getenv("RPC_LOGIN")) != nullptr && strlen(env_rpc_login) > 0;
boost::optional<tools::login> login{};
- if (command_line::has_arg(vm, arg.rpc_login))
+ if (has_rpc_arg || use_rpc_env)
{
login = tools::login::parse(
- command_line::get_arg(vm, arg.rpc_login), false, [](bool verify) {
+ has_rpc_arg ? command_line::get_arg(vm, arg.rpc_login) : std::string(env_rpc_login), false, [](bool verify) {
#ifdef HAVE_READLINE
rdln::suspend_readline pause_readline;
#endif
diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp
index 9ab1be246..6b6c88907 100644
--- a/src/daemon/rpc_command_executor.cpp
+++ b/src/daemon/rpc_command_executor.cpp
@@ -533,6 +533,7 @@ bool t_rpc_command_executor::print_blockchain_info(uint64_t start_block_index, u
req.start_height = start_block_index;
req.end_height = end_block_index;
+ req.fill_pow_hash = false;
std::string fail_message = "Unsuccessful";
@@ -1746,6 +1747,7 @@ bool t_rpc_command_executor::print_blockchain_dynamic_stats(uint64_t nblocks)
bhreq.start_height = ires.height - nblocks;
bhreq.end_height = ires.height - 1;
+ bhreq.fill_pow_hash = false;
if (m_is_rpc)
{
if (!m_rpc_client->json_rpc_request(bhreq, bhres, "getblockheadersrange", fail_message.c_str()))
diff --git a/src/device/device.cpp b/src/device/device.cpp
index 983f59b60..8a8b40061 100644
--- a/src/device/device.cpp
+++ b/src/device/device.cpp
@@ -39,32 +39,60 @@ namespace hw {
/* ======================================================================= */
/* SETUP */
- /* ======================================================================= */
- device& get_device(const std::string device_descriptor) {
-
- struct s_devices {
- std::map<std::string, std::unique_ptr<device>> registry;
- s_devices() : registry() {
- hw::core::register_all(registry);
- #ifdef HAVE_PCSC
- hw::ledger::register_all(registry);
- #endif
- };
- };
-
- static const s_devices devices;
+ /* ======================================================================= */
+
+ static std::unique_ptr<device_registry> registry;
+
+ device_registry::device_registry(){
+ hw::core::register_all(registry);
+ #ifdef HAVE_PCSC
+ hw::ledger::register_all(registry);
+ #endif
+ }
+
+ bool device_registry::register_device(const std::string & device_name, device * hw_device){
+ auto search = registry.find(device_name);
+ if (search != registry.end()){
+ return false;
+ }
+
+ registry.insert(std::make_pair(device_name, std::unique_ptr<device>(hw_device)));
+ return true;
+ }
+
+ device& device_registry::get_device(const std::string & device_descriptor){
+ // Device descriptor can contain further specs after first :
+ auto delim = device_descriptor.find(':');
+ auto device_descriptor_lookup = device_descriptor;
+ if (delim != std::string::npos) {
+ device_descriptor_lookup = device_descriptor.substr(0, delim);
+ }
- auto device = devices.registry.find(device_descriptor);
- if (device == devices.registry.end()) {
- MERROR("device not found in registry: '" << device_descriptor << "'\n" <<
- "known devices:");
-
- for( const auto& sm_pair : devices.registry ) {
+ auto device = registry.find(device_descriptor_lookup);
+ if (device == registry.end()) {
+ MERROR("Device not found in registry: '" << device_descriptor << "'. Known devices: ");
+ for( const auto& sm_pair : registry ) {
MERROR(" - " << sm_pair.first);
}
- throw std::runtime_error("device not found: "+ device_descriptor);
+ throw std::runtime_error("device not found: " + device_descriptor);
}
return *device->second;
}
+ device& get_device(const std::string & device_descriptor) {
+ if (!registry){
+ registry.reset(new device_registry());
+ }
+
+ return registry->get_device(device_descriptor);
+ }
+
+ bool register_device(const std::string & device_name, device * hw_device){
+ if (!registry){
+ registry.reset(new device_registry());
+ }
+
+ return registry->register_device(device_name, hw_device);
+ }
+
}
diff --git a/src/device/device.hpp b/src/device/device.hpp
index c21456daf..87f1430f4 100644
--- a/src/device/device.hpp
+++ b/src/device/device.hpp
@@ -78,7 +78,6 @@ namespace hw {
return false;
}
-
class device {
protected:
std::string name;
@@ -96,6 +95,12 @@ namespace hw {
TRANSACTION_CREATE_FAKE,
TRANSACTION_PARSE
};
+ enum device_type
+ {
+ SOFTWARE = 0,
+ LEDGER = 1
+ };
+
/* ======================================================================= */
/* SETUP/TEARDOWN */
@@ -109,7 +114,9 @@ namespace hw {
virtual bool connect(void) = 0;
virtual bool disconnect(void) = 0;
- virtual bool set_mode(device_mode mode) = 0;
+ virtual bool set_mode(device_mode mode) = 0;
+
+ virtual device_type get_type() const = 0;
/* ======================================================================= */
@@ -202,6 +209,17 @@ namespace hw {
~reset_mode() { hwref.set_mode(hw::device::NONE);}
};
- device& get_device(const std::string device_descriptor) ;
+ class device_registry {
+ private:
+ std::map<std::string, std::unique_ptr<device>> registry;
+
+ public:
+ device_registry();
+ bool register_device(const std::string & device_name, device * hw_device);
+ device& get_device(const std::string & device_descriptor);
+ };
+
+ device& get_device(const std::string & device_descriptor);
+ bool register_device(const std::string & device_name, device * hw_device);
}
diff --git a/src/device/device_default.hpp b/src/device/device_default.hpp
index 8d841d9de..b697e1775 100644
--- a/src/device/device_default.hpp
+++ b/src/device/device_default.hpp
@@ -61,6 +61,8 @@ namespace hw {
bool set_mode(device_mode mode) override;
+ device_type get_type() const {return device_type::SOFTWARE;};
+
/* ======================================================================= */
/* LOCKER */
/* ======================================================================= */
diff --git a/src/device/device_ledger.hpp b/src/device/device_ledger.hpp
index e6c6e5b52..4a3625b2b 100644
--- a/src/device/device_ledger.hpp
+++ b/src/device/device_ledger.hpp
@@ -142,7 +142,9 @@ namespace hw {
bool connect(void) override;
bool disconnect() override;
- bool set_mode(device_mode mode) override;
+ bool set_mode(device_mode mode) override;
+
+ device_type get_type() const {return device_type::LEDGER;};
/* ======================================================================= */
/* LOCKER */
diff --git a/src/gen_multisig/gen_multisig.cpp b/src/gen_multisig/gen_multisig.cpp
index e680a8157..f11f442bc 100644
--- a/src/gen_multisig/gen_multisig.cpp
+++ b/src/gen_multisig/gen_multisig.cpp
@@ -91,8 +91,8 @@ static bool generate_multisig(uint32_t threshold, uint32_t total, const std::str
for (size_t n = 0; n < total; ++n)
{
std::string name = basename + "-" + std::to_string(n + 1);
- wallets[n].reset(new tools::wallet2(nettype));
- wallets[n]->init(false, "");
+ wallets[n].reset(new tools::wallet2(nettype, 1, false));
+ wallets[n]->init("");
wallets[n]->generate(name, pwd_container->password(), rct::rct2sk(rct::skGen()), false, false, create_address_file);
}
diff --git a/src/mnemonics/chinese_simplified.h b/src/mnemonics/chinese_simplified.h
index 1ae8c89d6..0566b1079 100644
--- a/src/mnemonics/chinese_simplified.h
+++ b/src/mnemonics/chinese_simplified.h
@@ -72,7 +72,10 @@ namespace Language
class Chinese_Simplified: public Base
{
public:
- Chinese_Simplified(): Base("简体中文 (中国)", "Chinese (simplified)", std::vector<std::string>({
+ Chinese_Simplified(): Base("简体中文 (中国)", "Chinese (simplified)", {}, 1)
+ {
+ static constexpr const char * const words[NWORDS] =
+ {
"的",
"一",
"是",
@@ -1699,8 +1702,8 @@ namespace Language
"秒",
"浙",
"貌"
- }), 1)
- {
+ };
+ set_words(words);
populate_maps();
}
};
diff --git a/src/mnemonics/dutch.h b/src/mnemonics/dutch.h
index c9806f450..801caf986 100644
--- a/src/mnemonics/dutch.h
+++ b/src/mnemonics/dutch.h
@@ -49,7 +49,10 @@ namespace Language
class Dutch: public Base
{
public:
- Dutch(): Base("Nederlands", "Dutch", std::vector<std::string>({
+ Dutch(): Base("Nederlands", "Dutch", {}, 4)
+ {
+ static constexpr const char * const words[NWORDS] =
+ {
"aalglad",
"aalscholver",
"aambeeld",
@@ -1676,8 +1679,8 @@ namespace Language
"zwiep",
"zwijmel",
"zworen"
- }), 4)
- {
+ };
+ set_words(words);
populate_maps();
}
};
diff --git a/src/mnemonics/english.h b/src/mnemonics/english.h
index ee087674d..d5c5594ef 100644
--- a/src/mnemonics/english.h
+++ b/src/mnemonics/english.h
@@ -49,7 +49,10 @@ namespace Language
class English: public Base
{
public:
- English(): Base("English", "English", std::vector<std::string>({
+ English(): Base("English", "English", {}, 3)
+ {
+ static constexpr const char * const words[NWORDS] =
+ {
"abbey",
"abducts",
"ability",
@@ -1676,8 +1679,8 @@ namespace Language
"zombie",
"zones",
"zoom"
- }), 3)
- {
+ };
+ set_words(words);
populate_maps();
}
};
diff --git a/src/mnemonics/english_old.h b/src/mnemonics/english_old.h
index b31491646..e35b907df 100644
--- a/src/mnemonics/english_old.h
+++ b/src/mnemonics/english_old.h
@@ -51,7 +51,10 @@ namespace Language
class EnglishOld: public Base
{
public:
- EnglishOld(): Base("EnglishOld", "English (old)", std::vector<std::string>({
+ EnglishOld(): Base("EnglishOld", "English (old)", {}, 4)
+ {
+ static constexpr const char * const words[NWORDS] =
+ {
"like",
"just",
"love",
@@ -1678,8 +1681,8 @@ namespace Language
"unseen",
"weapon",
"weary"
- }), 4)
- {
+ };
+ set_words(words);
populate_maps(ALLOW_DUPLICATE_PREFIXES | ALLOW_SHORT_WORDS);
}
};
diff --git a/src/mnemonics/esperanto.h b/src/mnemonics/esperanto.h
index a1d1a3f30..b0be235ed 100644
--- a/src/mnemonics/esperanto.h
+++ b/src/mnemonics/esperanto.h
@@ -58,7 +58,10 @@ namespace Language
class Esperanto: public Base
{
public:
- Esperanto(): Base("Esperanto", "Esperanto", std::vector<std::string>({
+ Esperanto(): Base("Esperanto", "Esperanto", {}, 4)
+ {
+ static constexpr const char * const words[NWORDS] =
+ {
"abako",
"abdiki",
"abelo",
@@ -1685,8 +1688,8 @@ namespace Language
"zorgi",
"zukino",
"zumilo",
- }), 4)
- {
+ };
+ set_words(words);
populate_maps();
}
};
diff --git a/src/mnemonics/french.h b/src/mnemonics/french.h
index 7eaf45650..48ec46f78 100644
--- a/src/mnemonics/french.h
+++ b/src/mnemonics/french.h
@@ -49,7 +49,10 @@ namespace Language
class French: public Base
{
public:
- French(): Base("Français", "French", std::vector<std::string>({
+ French(): Base("Français", "French", {}, 4)
+ {
+ static constexpr const char * const words[NWORDS] =
+ {
"abandon",
"abattre",
"aboi",
@@ -1676,8 +1679,8 @@ namespace Language
"zinc",
"zone",
"zoom"
- }), 4)
- {
+ };
+ set_words(words);
populate_maps();
}
};
diff --git a/src/mnemonics/german.h b/src/mnemonics/german.h
index 8eff43523..883a173a3 100644
--- a/src/mnemonics/german.h
+++ b/src/mnemonics/german.h
@@ -51,7 +51,10 @@ namespace Language
class German: public Base
{
public:
- German(): Base("Deutsch", "German", std::vector<std::string>({
+ German(): Base("Deutsch", "German", {}, 4)
+ {
+ static constexpr const char * const words[NWORDS] =
+ {
"Abakus",
"Abart",
"abbilden",
@@ -1678,8 +1681,8 @@ namespace Language
"Zündung",
"Zweck",
"Zyklop"
- }), 4)
- {
+ };
+ set_words(words);
populate_maps();
}
};
diff --git a/src/mnemonics/italian.h b/src/mnemonics/italian.h
index d5ecb74f4..57cdfa25e 100644
--- a/src/mnemonics/italian.h
+++ b/src/mnemonics/italian.h
@@ -51,7 +51,10 @@ namespace Language
class Italian: public Base
{
public:
- Italian(): Base("Italiano", "Italian", std::vector<std::string>({
+ Italian(): Base("Italiano", "Italian", {}, 4)
+ {
+ static constexpr const char * const words[NWORDS] =
+ {
"abbinare",
"abbonato",
"abisso",
@@ -1678,8 +1681,8 @@ namespace Language
"zolfo",
"zombie",
"zucchero"
- }), 4)
- {
+ };
+ set_words(words);
populate_maps();
}
};
diff --git a/src/mnemonics/japanese.h b/src/mnemonics/japanese.h
index f3b3e4924..5baabedf2 100644
--- a/src/mnemonics/japanese.h
+++ b/src/mnemonics/japanese.h
@@ -71,7 +71,10 @@ namespace Language
class Japanese: public Base
{
public:
- Japanese(): Base("日本語", "Japanese", std::vector<std::string>({
+ Japanese(): Base("日本語", "Japanese", {}, 3)
+ {
+ static constexpr const char * const words[NWORDS] =
+ {
"あいこくしん",
"あいさつ",
"あいだ",
@@ -1698,8 +1701,8 @@ namespace Language
"ひさん",
"びじゅつかん",
"ひしょ"
- }), 3)
- {
+ };
+ set_words(words);
populate_maps();
}
};
diff --git a/src/mnemonics/language_base.h b/src/mnemonics/language_base.h
index cf518ab2a..52e784cef 100644
--- a/src/mnemonics/language_base.h
+++ b/src/mnemonics/language_base.h
@@ -83,7 +83,10 @@ namespace Language
ALLOW_SHORT_WORDS = 1<<0,
ALLOW_DUPLICATE_PREFIXES = 1<<1,
};
- const std::vector<std::string> word_list; /*!< A pointer to the array of words */
+ enum {
+ NWORDS = 1626
+ };
+ std::vector<std::string> word_list; /*!< A pointer to the array of words */
std::unordered_map<epee::wipeable_string, uint32_t> word_map; /*!< hash table to find word's index */
std::unordered_map<epee::wipeable_string, uint32_t> trimmed_word_map; /*!< hash table to find word's trimmed index */
std::string language_name; /*!< Name of language */
@@ -96,7 +99,7 @@ namespace Language
{
int ii;
std::vector<std::string>::const_iterator it;
- if (word_list.size () != 1626)
+ if (word_list.size () != NWORDS)
throw std::runtime_error("Wrong word list length for " + language_name);
for (it = word_list.begin(), ii = 0; it != word_list.end(); it++, ii++)
{
@@ -138,6 +141,12 @@ namespace Language
virtual ~Base()
{
}
+ void set_words(const char * const words[])
+ {
+ word_list.resize(NWORDS);
+ for (size_t i = 0; i < NWORDS; ++i)
+ word_list[i] = words[i];
+ }
/*!
* \brief Returns a pointer to the word list.
* \return A pointer to the word list.
diff --git a/src/mnemonics/lojban.h b/src/mnemonics/lojban.h
index 0966a1169..5162a8ec9 100644
--- a/src/mnemonics/lojban.h
+++ b/src/mnemonics/lojban.h
@@ -56,7 +56,10 @@ namespace Language
class Lojban: public Base
{
public:
- Lojban(): Base("Lojban", "Lojban", std::vector<std::string>({
+ Lojban(): Base("Lojban", "Lojban", {}, 4)
+ {
+ static constexpr const char * const words[NWORDS] =
+ {
"backi",
"bacru",
"badna",
@@ -1683,8 +1686,8 @@ namespace Language
"noltruti'u",
"samtci",
"snaxa'a",
- }), 4)
- {
+ };
+ set_words(words);
populate_maps();
}
};
diff --git a/src/mnemonics/portuguese.h b/src/mnemonics/portuguese.h
index 0195389ce..af04f89c2 100644
--- a/src/mnemonics/portuguese.h
+++ b/src/mnemonics/portuguese.h
@@ -72,7 +72,10 @@ namespace Language
class Portuguese: public Base
{
public:
- Portuguese(): Base("Português", "Portuguese", std::vector<std::string>({
+ Portuguese(): Base("Português", "Portuguese", {}, 4)
+ {
+ static constexpr const char * const words[NWORDS] =
+ {
"abaular",
"abdominal",
"abeto",
@@ -1699,8 +1702,8 @@ namespace Language
"zeloso",
"zenite",
"zumbi"
- }), 4)
- {
+ };
+ set_words(words);
populate_maps();
}
};
diff --git a/src/mnemonics/russian.h b/src/mnemonics/russian.h
index d5dd556ef..f3e70ede6 100644
--- a/src/mnemonics/russian.h
+++ b/src/mnemonics/russian.h
@@ -51,7 +51,10 @@ namespace Language
class Russian: public Base
{
public:
- Russian(): Base("русский язык", "Russian", std::vector<std::string>({
+ Russian(): Base("русский язык", "Russian", {}, 4)
+ {
+ static constexpr const char * const words[NWORDS] =
+ {
"абажур",
"абзац",
"абонент",
@@ -1678,8 +1681,8 @@ namespace Language
"яхта",
"ячейка",
"ящик"
- }), 4)
- {
+ };
+ set_words(words);
populate_maps();
}
};
diff --git a/src/mnemonics/spanish.h b/src/mnemonics/spanish.h
index 51f38fede..4d7a896a6 100644
--- a/src/mnemonics/spanish.h
+++ b/src/mnemonics/spanish.h
@@ -72,7 +72,10 @@ namespace Language
class Spanish: public Base
{
public:
- Spanish(): Base("Español", "Spanish", std::vector<std::string>({
+ Spanish(): Base("Español", "Spanish", {}, 4)
+ {
+ static constexpr const char * const words[NWORDS] =
+ {
"ábaco",
"abdomen",
"abeja",
@@ -1699,8 +1702,8 @@ namespace Language
"risa",
"ritmo",
"rito"
- }), 4)
- {
+ };
+ set_words(words);
populate_maps(ALLOW_SHORT_WORDS);
}
};
diff --git a/src/ringct/rctOps.cpp b/src/ringct/rctOps.cpp
index 6c3c4500e..41bbf6ca3 100644
--- a/src/ringct/rctOps.cpp
+++ b/src/ringct/rctOps.cpp
@@ -252,6 +252,25 @@ namespace rct {
return k;
}
+ rct::key addKeys(const keyV &A) {
+ if (A.empty())
+ return rct::identity();
+ ge_p3 p3, tmp;
+ CHECK_AND_ASSERT_THROW_MES_L1(ge_frombytes_vartime(&p3, A[0].bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__));
+ for (size_t i = 1; i < A.size(); ++i)
+ {
+ CHECK_AND_ASSERT_THROW_MES_L1(ge_frombytes_vartime(&tmp, A[i].bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__));
+ ge_cached p2;
+ ge_p3_to_cached(&p2, &tmp);
+ ge_p1p1 p1;
+ ge_add(&p1, &p3, &p2);
+ ge_p1p1_to_p3(&p3, &p1);
+ }
+ rct::key res;
+ ge_p3_tobytes(res.bytes, &p3);
+ return res;
+ }
+
//addKeys1
//aGB = aG + B where a is a scalar, G is the basepoint, and B is a point
void addKeys1(key &aGB, const key &a, const key & B) {
diff --git a/src/ringct/rctOps.h b/src/ringct/rctOps.h
index 50645821c..60e920b3a 100644
--- a/src/ringct/rctOps.h
+++ b/src/ringct/rctOps.h
@@ -132,6 +132,7 @@ namespace rct {
//for curve points: AB = A + B
void addKeys(key &AB, const key &A, const key &B);
rct::key addKeys(const key &A, const key &B);
+ rct::key addKeys(const keyV &A);
//aGB = aG + B where a is a scalar, G is the basepoint, and B is a point
void addKeys1(key &aGB, const key &a, const key & B);
//aGbB = aG + bB where a, b are scalars, G is the basepoint and B is a point
diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp
index fe0cd9c57..0d1789a38 100644
--- a/src/ringct/rctSigs.cpp
+++ b/src/ringct/rctSigs.cpp
@@ -963,18 +963,16 @@ namespace rct {
const bool bulletproof = is_rct_bulletproof(rv.type);
const keyV &pseudoOuts = bulletproof ? rv.p.pseudoOuts : rv.pseudoOuts;
- key sumOutpks = identity();
+ rct::keyV masks(rv.outPk.size());
for (size_t i = 0; i < rv.outPk.size(); i++) {
- addKeys(sumOutpks, sumOutpks, rv.outPk[i].mask);
+ masks[i] = rv.outPk[i].mask;
}
+ key sumOutpks = addKeys(masks);
DP(sumOutpks);
- key txnFeeKey = scalarmultH(d2h(rv.txnFee));
+ const key txnFeeKey = scalarmultH(d2h(rv.txnFee));
addKeys(sumOutpks, txnFeeKey, sumOutpks);
- key sumPseudoOuts = identity();
- for (size_t i = 0 ; i < pseudoOuts.size() ; i++) {
- addKeys(sumPseudoOuts, sumPseudoOuts, pseudoOuts[i]);
- }
+ key sumPseudoOuts = addKeys(pseudoOuts);
DP(sumPseudoOuts);
//check pseudoOuts vs Outs..
diff --git a/src/ringct/rctTypes.h b/src/ringct/rctTypes.h
index ffc4df3ed..18290637b 100644
--- a/src/ringct/rctTypes.h
+++ b/src/ringct/rctTypes.h
@@ -313,10 +313,10 @@ namespace rct {
return false;
if (type == RCTTypeBulletproof)
{
- ar.tag("bp");
- ar.begin_array();
uint32_t nbp = bulletproofs.size();
FIELD(nbp)
+ ar.tag("bp");
+ ar.begin_array();
if (nbp > outputs)
return false;
PREPARE_CUSTOM_VECTOR_SERIALIZATION(nbp, bulletproofs);
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index db7f2dbaa..3508208bc 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -198,7 +198,7 @@ namespace cryptonote
res.block_size_limit = res.block_weight_limit = m_core.get_blockchain_storage().get_current_cumulative_block_weight_limit();
res.block_size_median = res.block_weight_median = m_core.get_blockchain_storage().get_current_cumulative_block_weight_median();
res.status = CORE_RPC_STATUS_OK;
- res.start_time = (uint64_t)m_core.get_start_time();
+ res.start_time = m_restricted ? 0 : (uint64_t)m_core.get_start_time();
res.free_space = m_restricted ? std::numeric_limits<uint64_t>::max() : m_core.get_free_space();
res.offline = m_core.offline();
res.bootstrap_daemon_address = m_bootstrap_daemon_address;
@@ -208,6 +208,7 @@ namespace cryptonote
res.was_bootstrap_ever_used = m_was_bootstrap_ever_used;
}
res.database_size = m_core.get_blockchain_storage().get_db().get_database_size();
+ res.update_available = m_core.is_update_available();
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
@@ -779,7 +780,13 @@ namespace cryptonote
boost::thread::attributes attrs;
attrs.set_stack_size(THREAD_STACK_SIZE);
- if(!m_core.get_miner().start(info.address, static_cast<size_t>(req.threads_count), attrs, req.do_background_mining, req.ignore_battery))
+ cryptonote::miner &miner= m_core.get_miner();
+ if (miner.is_mining())
+ {
+ res.status = "Already mining";
+ return true;
+ }
+ if(!miner.start(info.address, static_cast<size_t>(req.threads_count), attrs, req.do_background_mining, req.ignore_battery))
{
res.status = "Failed, mining not started";
LOG_PRINT_L0(res.status);
@@ -1241,6 +1248,7 @@ namespace cryptonote
response.depth = m_core.get_current_blockchain_height() - height - 1;
response.hash = string_tools::pod_to_hex(hash);
response.difficulty = m_core.get_blockchain_storage().block_difficulty(height);
+ response.cumulative_difficulty = response.block_weight = m_core.get_blockchain_storage().get_db().get_block_cumulative_difficulty(height);
response.reward = get_block_reward(blk);
response.block_size = response.block_weight = m_core.get_blockchain_storage().get_db().get_block_weight(height);
response.num_txes = blk.tx_hashes.size();
@@ -1588,6 +1596,7 @@ namespace cryptonote
res.was_bootstrap_ever_used = m_was_bootstrap_ever_used;
}
res.database_size = m_core.get_blockchain_storage().get_db().get_database_size();
+ res.update_available = m_core.is_update_available();
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h
index 1a84ee614..3b654d4cb 100644
--- a/src/rpc/core_rpc_server_commands_defs.h
+++ b/src/rpc/core_rpc_server_commands_defs.h
@@ -49,7 +49,7 @@ namespace cryptonote
// advance which version they will stop working with
// Don't go over 32767 for any of these
#define CORE_RPC_VERSION_MAJOR 2
-#define CORE_RPC_VERSION_MINOR 0
+#define CORE_RPC_VERSION_MINOR 1
#define MAKE_CORE_RPC_VERSION(major,minor) (((major)<<16)|(minor))
#define CORE_RPC_VERSION MAKE_CORE_RPC_VERSION(CORE_RPC_VERSION_MAJOR, CORE_RPC_VERSION_MINOR)
@@ -893,6 +893,7 @@ namespace cryptonote
uint64_t height_without_bootstrap;
bool was_bootstrap_ever_used;
uint64_t database_size;
+ bool update_available;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(status)
@@ -926,6 +927,7 @@ namespace cryptonote
KV_SERIALIZE(height_without_bootstrap)
KV_SERIALIZE(was_bootstrap_ever_used)
KV_SERIALIZE(database_size)
+ KV_SERIALIZE(update_available)
END_KV_SERIALIZE_MAP()
};
};
@@ -1120,6 +1122,7 @@ namespace cryptonote
uint64_t depth;
std::string hash;
difficulty_type difficulty;
+ difficulty_type cumulative_difficulty;
uint64_t reward;
uint64_t block_size;
uint64_t block_weight;
@@ -1137,6 +1140,7 @@ namespace cryptonote
KV_SERIALIZE(depth)
KV_SERIALIZE(hash)
KV_SERIALIZE(difficulty)
+ KV_SERIALIZE(cumulative_difficulty)
KV_SERIALIZE(reward)
KV_SERIALIZE(block_size)
KV_SERIALIZE_OPT(block_weight, (uint64_t)0)
diff --git a/src/rpc/rpc_args.cpp b/src/rpc/rpc_args.cpp
index d4044d11b..60c78480a 100644
--- a/src/rpc/rpc_args.cpp
+++ b/src/rpc/rpc_args.cpp
@@ -82,11 +82,17 @@ namespace cryptonote
}
}
- if (command_line::has_arg(vm, arg.rpc_login))
+ const char *env_rpc_login = nullptr;
+ const bool has_rpc_arg = command_line::has_arg(vm, arg.rpc_login);
+ const bool use_rpc_env = !has_rpc_arg && (env_rpc_login = getenv("RPC_LOGIN")) != nullptr && strlen(env_rpc_login) > 0;
+ boost::optional<tools::login> login{};
+ if (has_rpc_arg || use_rpc_env)
{
- config.login = tools::login::parse(command_line::get_arg(vm, arg.rpc_login), true, [](bool verify) {
- return tools::password_container::prompt(verify, "RPC server password");
- });
+ config.login = tools::login::parse(
+ has_rpc_arg ? command_line::get_arg(vm, arg.rpc_login) : std::string(env_rpc_login), true, [](bool verify) {
+ return tools::password_container::prompt(verify, "RPC server password");
+ });
+
if (!config.login)
return boost::none;
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index e535b6d27..b3c46bd50 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -2523,6 +2523,10 @@ simple_wallet::simple_wallet()
boost::bind(&simple_wallet::import_key_images, this, _1),
tr("import_key_images <file>"),
tr("Import a signed key images list and verify their spent status."));
+ m_cmd_binder.set_handler("hw_reconnect",
+ boost::bind(&simple_wallet::hw_reconnect, this, _1),
+ tr("hw_reconnect"),
+ tr("Attempts to reconnect HW wallet."));
m_cmd_binder.set_handler("export_outputs",
boost::bind(&simple_wallet::export_outputs, this, _1),
tr("export_outputs <file>"),
@@ -2650,6 +2654,7 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args)
success_msg_writer() << "subaddress-lookahead = " << lookahead.first << ":" << lookahead.second;
success_msg_writer() << "segregation-height = " << m_wallet->segregation_height();
success_msg_writer() << "ignore-fractional-outputs = " << m_wallet->ignore_fractional_outputs();
+ success_msg_writer() << "device_name = " << m_wallet->device_name();
return true;
}
else
@@ -3009,20 +3014,19 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
}
// parse view secret key
- std::string viewkey_string = input_line("View key: ");
+ epee::wipeable_string viewkey_string = input_secure_line("Secret view key: ");
if (std::cin.eof())
return false;
if (viewkey_string.empty()) {
fail_msg_writer() << tr("No data supplied, cancelled");
return false;
}
- cryptonote::blobdata viewkey_data;
- if(!epee::string_tools::parse_hexstr_to_binbuff(viewkey_string, viewkey_data) || viewkey_data.size() != sizeof(crypto::secret_key))
+ crypto::secret_key viewkey;
+ if (viewkey_string.hex_to_pod(unwrap(unwrap(viewkey))))
{
fail_msg_writer() << tr("failed to parse view key secret key");
return false;
}
- crypto::secret_key viewkey = *reinterpret_cast<const crypto::secret_key*>(viewkey_data.data());
m_wallet_file=m_generate_from_view_key;
@@ -3045,14 +3049,14 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
{
m_wallet_file = m_generate_from_spend_key;
// parse spend secret key
- std::string spendkey_string = input_line("Secret spend key: ");
+ epee::wipeable_string spendkey_string = input_secure_line("Secret spend key: ");
if (std::cin.eof())
return false;
if (spendkey_string.empty()) {
fail_msg_writer() << tr("No data supplied, cancelled");
return false;
}
- if (!epee::string_tools::hex_to_pod(spendkey_string, m_recovery_key))
+ if (!spendkey_string.hex_to_pod(unwrap(unwrap(m_recovery_key))))
{
fail_msg_writer() << tr("failed to parse spend key secret key");
return false;
@@ -3085,36 +3089,34 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
}
// parse spend secret key
- std::string spendkey_string = input_line("Secret spend key: ");
+ epee::wipeable_string spendkey_string = input_secure_line("Secret spend key: ");
if (std::cin.eof())
return false;
if (spendkey_string.empty()) {
fail_msg_writer() << tr("No data supplied, cancelled");
return false;
}
- cryptonote::blobdata spendkey_data;
- if(!epee::string_tools::parse_hexstr_to_binbuff(spendkey_string, spendkey_data) || spendkey_data.size() != sizeof(crypto::secret_key))
+ crypto::secret_key spendkey;
+ if (!spendkey_string.hex_to_pod(unwrap(unwrap(spendkey))))
{
fail_msg_writer() << tr("failed to parse spend key secret key");
return false;
}
- crypto::secret_key spendkey = *reinterpret_cast<const crypto::secret_key*>(spendkey_data.data());
// parse view secret key
- std::string viewkey_string = input_line("Secret view key: ");
+ epee::wipeable_string viewkey_string = input_secure_line("Secret view key: ");
if (std::cin.eof())
return false;
if (viewkey_string.empty()) {
fail_msg_writer() << tr("No data supplied, cancelled");
return false;
}
- cryptonote::blobdata viewkey_data;
- if(!epee::string_tools::parse_hexstr_to_binbuff(viewkey_string, viewkey_data) || viewkey_data.size() != sizeof(crypto::secret_key))
+ crypto::secret_key viewkey;
+ if(!viewkey_string.hex_to_pod(unwrap(unwrap(viewkey))))
{
fail_msg_writer() << tr("failed to parse view key secret key");
return false;
}
- crypto::secret_key viewkey = *reinterpret_cast<const crypto::secret_key*>(viewkey_data.data());
m_wallet_file=m_generate_from_keys;
@@ -3190,7 +3192,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
}
// parse secret view key
- std::string viewkey_string = input_line("Secret view key: ");
+ epee::wipeable_string viewkey_string = input_secure_line("Secret view key: ");
if (std::cin.eof())
return false;
if (viewkey_string.empty())
@@ -3198,13 +3200,12 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
fail_msg_writer() << tr("No data supplied, cancelled");
return false;
}
- cryptonote::blobdata viewkey_data;
- if(!epee::string_tools::parse_hexstr_to_binbuff(viewkey_string, viewkey_data) || viewkey_data.size() != sizeof(crypto::secret_key))
+ crypto::secret_key viewkey;
+ if(!viewkey_string.hex_to_pod(unwrap(unwrap(viewkey))))
{
fail_msg_writer() << tr("failed to parse secret view key");
return false;
}
- crypto::secret_key viewkey = *reinterpret_cast<const crypto::secret_key*>(viewkey_data.data());
// check that the view key matches the given address
crypto::public_key pkey;
@@ -3225,12 +3226,12 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
if(multisig_m == multisig_n)
{
std::vector<crypto::secret_key> multisig_secret_spendkeys(multisig_n);
- std::string spendkey_string;
+ epee::wipeable_string spendkey_string;
cryptonote::blobdata spendkey_data;
// get N secret spend keys from user
for(unsigned int i=0; i<multisig_n; ++i)
{
- spendkey_string = input_line(tr((boost::format(tr("Secret spend key (%u of %u):")) % (i+1) % multisig_m).str().c_str()));
+ spendkey_string = input_secure_line(tr((boost::format(tr("Secret spend key (%u of %u):")) % (i+1) % multisig_m).str().c_str()));
if (std::cin.eof())
return false;
if (spendkey_string.empty())
@@ -3238,12 +3239,11 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
fail_msg_writer() << tr("No data supplied, cancelled");
return false;
}
- if(!epee::string_tools::parse_hexstr_to_binbuff(spendkey_string, spendkey_data) || spendkey_data.size() != sizeof(crypto::secret_key))
+ if(!spendkey_string.hex_to_pod(unwrap(unwrap(multisig_secret_spendkeys[i]))))
{
fail_msg_writer() << tr("failed to parse spend key secret key");
return false;
}
- multisig_secret_spendkeys[i] = *reinterpret_cast<const crypto::secret_key*>(spendkey_data.data());
}
// sum the spend keys together to get the master spend key
@@ -3295,7 +3295,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
{
m_wallet_file = m_generate_from_device;
// create wallet
- auto r = new_wallet(vm, "Ledger");
+ auto r = new_wallet(vm);
CHECK_AND_ASSERT_MES(r, false, tr("account creation failed"));
password = *r;
// if no block_height is specified, assume its a new account and start it "now"
@@ -3703,8 +3703,8 @@ boost::optional<epee::wipeable_string> simple_wallet::new_wallet(const boost::pr
}
//----------------------------------------------------------------------------------------------------
-boost::optional<epee::wipeable_string> simple_wallet::new_wallet(const boost::program_options::variables_map& vm,
- const std::string &device_name) {
+boost::optional<epee::wipeable_string> simple_wallet::new_wallet(const boost::program_options::variables_map& vm)
+{
auto rc = tools::wallet2::make_new(vm, false, password_prompter);
m_wallet = std::move(rc.first);
if (!m_wallet)
@@ -3723,10 +3723,11 @@ boost::optional<epee::wipeable_string> simple_wallet::new_wallet(const boost::pr
if (m_restore_height)
m_wallet->set_refresh_from_block_height(m_restore_height);
+ auto device_desc = tools::wallet2::device_name_option(vm);
try
{
bool create_address_file = command_line::get_arg(vm, arg_create_address_file);
- m_wallet->restore(m_wallet_file, std::move(rc.second).password(), device_name, create_address_file);
+ m_wallet->restore(m_wallet_file, std::move(rc.second).password(), device_desc.empty() ? "Ledger" : device_desc, create_address_file);
message_writer(console_color_white, true) << tr("Generated new wallet on hw device: ")
<< m_wallet->get_account().get_public_address_str(m_wallet->nettype());
}
@@ -4083,7 +4084,7 @@ bool simple_wallet::set_daemon(const std::vector<std::string>& args)
daemon_url = args[0];
}
LOCK_IDLE_SCOPE();
- m_wallet->init(false, daemon_url);
+ m_wallet->init(daemon_url);
if (args.size() == 2)
{
@@ -4202,7 +4203,7 @@ boost::optional<epee::wipeable_string> simple_wallet::on_get_password(const char
// can't ask for password from a background thread
if (!m_in_manual_refresh.load(std::memory_order_relaxed))
{
- message_writer(console_color_red, false) << tr("Password needed - use the refresh command");
+ message_writer(console_color_red, false) << boost::format(tr("Password needed (%s) - use the refresh command")) % reason;
m_cmd_binder.print_prompt();
return boost::none;
}
@@ -7745,6 +7746,31 @@ bool simple_wallet::import_key_images(const std::vector<std::string> &args)
return true;
}
//----------------------------------------------------------------------------------------------------
+bool simple_wallet::hw_reconnect(const std::vector<std::string> &args)
+{
+ if (!m_wallet->key_on_device())
+ {
+ fail_msg_writer() << tr("command only supported by HW wallet");
+ return true;
+ }
+
+ LOCK_IDLE_SCOPE();
+ try
+ {
+ bool r = m_wallet->reconnect_device();
+ if (!r){
+ fail_msg_writer() << tr("Failed to reconnect device");
+ }
+ }
+ catch (const std::exception &e)
+ {
+ fail_msg_writer() << tr("Failed to reconnect device: ") << tr(e.what());
+ return true;
+ }
+
+ return true;
+}
+//----------------------------------------------------------------------------------------------------
bool simple_wallet::export_outputs(const std::vector<std::string> &args)
{
if (m_wallet->key_on_device())
diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h
index bfbe633ac..d50e4ce04 100644
--- a/src/simplewallet/simplewallet.h
+++ b/src/simplewallet/simplewallet.h
@@ -98,7 +98,7 @@ namespace cryptonote
const boost::optional<crypto::secret_key>& spendkey, const crypto::secret_key& viewkey);
boost::optional<epee::wipeable_string> new_wallet(const boost::program_options::variables_map& vm,
const epee::wipeable_string &multisig_keys, const std::string &old_language);
- boost::optional<epee::wipeable_string> new_wallet(const boost::program_options::variables_map& vm, const std::string& device_name);
+ boost::optional<epee::wipeable_string> new_wallet(const boost::program_options::variables_map& vm);
bool open_wallet(const boost::program_options::variables_map& vm);
bool close_wallet();
@@ -201,6 +201,7 @@ namespace cryptonote
bool verify(const std::vector<std::string> &args);
bool export_key_images(const std::vector<std::string> &args);
bool import_key_images(const std::vector<std::string> &args);
+ bool hw_reconnect(const std::vector<std::string> &args);
bool export_outputs(const std::vector<std::string> &args);
bool import_outputs(const std::vector<std::string> &args);
bool show_transfer(const std::vector<std::string> &args);
diff --git a/src/wallet/CMakeLists.txt b/src/wallet/CMakeLists.txt
index a16f4fe19..be10b9f62 100644
--- a/src/wallet/CMakeLists.txt
+++ b/src/wallet/CMakeLists.txt
@@ -90,6 +90,8 @@ target_link_libraries(wallet_rpc_server
cncrypto
common
version
+ daemonizer
+ ${EPEE_READLINE}
${Boost_CHRONO_LIBRARY}
${Boost_PROGRAM_OPTIONS_LIBRARY}
${Boost_FILESYSTEM_LIBRARY}
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index e9e9a4e67..8b25096a2 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -376,7 +376,7 @@ WalletImpl::WalletImpl(NetworkType nettype, uint64_t kdf_rounds)
, m_rebuildWalletCache(false)
, m_is_connected(false)
{
- m_wallet = new tools::wallet2(static_cast<cryptonote::network_type>(nettype), kdf_rounds);
+ m_wallet = new tools::wallet2(static_cast<cryptonote::network_type>(nettype), kdf_rounds, true);
m_history = new TransactionHistoryImpl(this);
m_wallet2Callback = new Wallet2CallbackImpl(this);
m_wallet->callback(m_wallet2Callback);
@@ -629,7 +629,7 @@ bool WalletImpl::recoverFromDevice(const std::string &path, const std::string &p
m_recoveringFromDevice = true;
try
{
- m_wallet->restore(path, password, device_name);
+ m_wallet->restore(path, password, device_name, false);
LOG_PRINT_L1("Generated new wallet from device: " + device_name);
}
catch (const std::exception& e) {
@@ -639,6 +639,11 @@ bool WalletImpl::recoverFromDevice(const std::string &path, const std::string &p
return true;
}
+Wallet::Device WalletImpl::getDeviceType() const
+{
+ return static_cast<Wallet::Device>(m_wallet->get_device_type());
+}
+
bool WalletImpl::open(const std::string &path, const std::string &password)
{
clearStatus();
@@ -1244,6 +1249,20 @@ size_t WalletImpl::importMultisigImages(const vector<string>& images) {
return 0;
}
+bool WalletImpl::hasMultisigPartialKeyImages() const {
+ try {
+ clearStatus();
+ checkMultisigWalletReady(m_wallet);
+
+ return m_wallet->has_multisig_partial_key_images();
+ } catch (const exception& e) {
+ LOG_ERROR("Error on checking for partial multisig key images: ") << e.what();
+ setStatusError(string(tr("Failed to check for partial multisig key images: ")) + e.what());
+ }
+
+ return false;
+}
+
PendingTransaction* WalletImpl::restoreMultisigTransaction(const string& signData) {
try {
clearStatus();
@@ -2033,7 +2052,7 @@ bool WalletImpl::isNewWallet() const
bool WalletImpl::doInit(const string &daemon_address, uint64_t upper_transaction_size_limit, bool ssl)
{
// claim RPC so there's no in-memory encryption for now
- if (!m_wallet->init(true, daemon_address, m_daemon_login, upper_transaction_size_limit, ssl))
+ if (!m_wallet->init(daemon_address, m_daemon_login, upper_transaction_size_limit, ssl))
return false;
// in case new wallet, this will force fast-refresh (pulling hashes instead of blocks)
@@ -2095,21 +2114,36 @@ bool WalletImpl::useForkRules(uint8_t version, int64_t early_blocks) const
return m_wallet->use_fork_rules(version,early_blocks);
}
-bool WalletImpl::blackballOutputs(const std::vector<std::string> &pubkeys, bool add)
+bool WalletImpl::blackballOutputs(const std::vector<std::string> &outputs, bool add)
{
- std::vector<crypto::public_key> raw_pubkeys;
- raw_pubkeys.reserve(pubkeys.size());
- for (const std::string &str: pubkeys)
+ std::vector<std::pair<uint64_t, uint64_t>> raw_outputs;
+ raw_outputs.reserve(outputs.size());
+ uint64_t amount = std::numeric_limits<uint64_t>::max(), offset, num_offsets;
+ for (const std::string &str: outputs)
{
- crypto::public_key pkey;
- if (!epee::string_tools::hex_to_pod(str, pkey))
+ if (sscanf(str.c_str(), "@%" PRIu64, &amount) == 1)
+ continue;
+ if (amount == std::numeric_limits<uint64_t>::max())
{
- setStatusError(tr("Failed to parse output public key"));
- return false;
+ setStatusError("First line is not an amount");
+ return true;
+ }
+ if (sscanf(str.c_str(), "%" PRIu64 "*%" PRIu64, &offset, &num_offsets) == 2 && num_offsets <= std::numeric_limits<uint64_t>::max() - offset)
+ {
+ while (num_offsets--)
+ raw_outputs.push_back(std::make_pair(amount, offset++));
+ }
+ else if (sscanf(str.c_str(), "%" PRIu64, &offset) == 1)
+ {
+ raw_outputs.push_back(std::make_pair(amount, offset));
+ }
+ else
+ {
+ setStatusError(tr("Invalid output: ") + str);
+ return false;
}
- raw_pubkeys.push_back(pkey);
}
- bool ret = m_wallet->set_blackballed_outputs(raw_pubkeys, add);
+ bool ret = m_wallet->set_blackballed_outputs(raw_outputs, add);
if (!ret)
{
setStatusError(tr("Failed to set blackballed outputs"));
@@ -2118,15 +2152,20 @@ bool WalletImpl::blackballOutputs(const std::vector<std::string> &pubkeys, bool
return true;
}
-bool WalletImpl::unblackballOutput(const std::string &pubkey)
+bool WalletImpl::unblackballOutput(const std::string &amount, const std::string &offset)
{
- crypto::public_key raw_pubkey;
- if (!epee::string_tools::hex_to_pod(pubkey, raw_pubkey))
+ uint64_t raw_amount, raw_offset;
+ if (!epee::string_tools::get_xtype_from_string(raw_amount, amount))
+ {
+ setStatusError(tr("Failed to parse output amount"));
+ return false;
+ }
+ if (!epee::string_tools::get_xtype_from_string(raw_offset, offset))
{
- setStatusError(tr("Failed to parse output public key"));
+ setStatusError(tr("Failed to parse output offset"));
return false;
}
- bool ret = m_wallet->unblackball_output(raw_pubkey);
+ bool ret = m_wallet->unblackball_output(std::make_pair(raw_amount, raw_offset));
if (!ret)
{
setStatusError(tr("Failed to unblackball output"));
diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h
index 0f3b1ce04..e3a300317 100644
--- a/src/wallet/api/wallet.h
+++ b/src/wallet/api/wallet.h
@@ -79,6 +79,7 @@ public:
bool recoverFromDevice(const std::string &path,
const std::string &password,
const std::string &device_name);
+ Device getDeviceType() const;
bool close(bool store = true);
std::string seed() const override;
std::string getSeedLanguage() const override;
@@ -139,6 +140,7 @@ public:
bool finalizeMultisig(const std::vector<std::string>& extraMultisigInfo) override;
bool exportMultisigImages(std::string& images) override;
size_t importMultisigImages(const std::vector<std::string>& images) override;
+ bool hasMultisigPartialKeyImages() const override;
PendingTransaction* restoreMultisigTransaction(const std::string& signData) override;
PendingTransaction * createTransaction(const std::string &dst_addr, const std::string &payment_id,
@@ -181,7 +183,7 @@ public:
virtual bool lightWalletLogin(bool &isNewWallet) const override;
virtual bool lightWalletImportWalletRequest(std::string &payment_id, uint64_t &fee, bool &new_request, bool &request_fulfilled, std::string &payment_address, std::string &status) override;
virtual bool blackballOutputs(const std::vector<std::string> &pubkeys, bool add) override;
- virtual bool unblackballOutput(const std::string &pubkey) override;
+ virtual bool unblackballOutput(const std::string &amount, const std::string &offset) override;
virtual bool getRing(const std::string &key_image, std::vector<uint64_t> &ring) const override;
virtual bool getRings(const std::string &txid, std::vector<std::pair<std::string, std::vector<uint64_t>>> &rings) const override;
virtual bool setRing(const std::string &key_image, const std::vector<uint64_t> &ring, bool relative) override;
diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h
index 5a52c6b17..e0d491705 100644
--- a/src/wallet/api/wallet2_api.h
+++ b/src/wallet/api/wallet2_api.h
@@ -373,6 +373,10 @@ struct WalletListener
*/
struct Wallet
{
+ enum Device {
+ Device_Software = 0,
+ Device_Ledger = 1
+ };
enum Status {
Status_Ok,
@@ -720,6 +724,11 @@ struct Wallet
* @return number of imported images
*/
virtual size_t importMultisigImages(const std::vector<std::string>& images) = 0;
+ /**
+ * @brief hasMultisigPartialKeyImages - checks if wallet needs to import multisig key images from other participants
+ * @return true if there are partial key images
+ */
+ virtual bool hasMultisigPartialKeyImages() const = 0;
/**
* @brief restoreMultisigTransaction creates PendingTransaction from signData
@@ -875,7 +884,7 @@ struct Wallet
virtual bool blackballOutputs(const std::vector<std::string> &pubkeys, bool add) = 0;
//! unblackballs an output
- virtual bool unblackballOutput(const std::string &pubkey) = 0;
+ virtual bool unblackballOutput(const std::string &amount, const std::string &offset) = 0;
//! gets the ring used for a key image, if any
virtual bool getRing(const std::string &key_image, std::vector<uint64_t> &ring) const = 0;
@@ -906,6 +915,12 @@ struct Wallet
virtual bool unlockKeysFile() = 0;
//! returns true if the keys file is locked
virtual bool isKeysFileLocked() = 0;
+
+ /*!
+ * \brief Queries backing device for wallet keys
+ * \return Device they are on
+ */
+ virtual Device getDeviceType() const = 0;
};
/**
@@ -1092,6 +1107,18 @@ struct WalletManager
virtual bool verifyWalletPassword(const std::string &keys_file_name, const std::string &password, bool no_spend_key, uint64_t kdf_rounds = 1) const = 0;
/*!
+ * \brief determine the key storage for the specified wallet file
+ * \param device_type (OUT) wallet backend as enumerated in Wallet::Device
+ * \param keys_file_name Keys file to verify password for
+ * \param password Password to verify
+ * \return true if password correct, else false
+ *
+ * for verification only - determines key storage hardware
+ *
+ */
+ virtual bool queryWalletDevice(Wallet::Device& device_type, const std::string &keys_file_name, const std::string &password, uint64_t kdf_rounds = 1) const = 0;
+
+ /*!
* \brief findWallets - searches for the wallet files by given path name recursively
* \param path - starting point to search
* \return - list of strings with found wallets (absolute paths);
diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp
index 3851ca9cc..5b262f1b7 100644
--- a/src/wallet/api/wallet_manager.cpp
+++ b/src/wallet/api/wallet_manager.cpp
@@ -167,6 +167,14 @@ bool WalletManagerImpl::verifyWalletPassword(const std::string &keys_file_name,
return tools::wallet2::verify_password(keys_file_name, password, no_spend_key, hw::get_device("default"), kdf_rounds);
}
+bool WalletManagerImpl::queryWalletDevice(Wallet::Device& device_type, const std::string &keys_file_name, const std::string &password, uint64_t kdf_rounds) const
+{
+ hw::device::device_type type;
+ bool r = tools::wallet2::query_device(type, keys_file_name, password, kdf_rounds);
+ device_type = static_cast<Wallet::Device>(type);
+ return r;
+}
+
std::vector<std::string> WalletManagerImpl::findWallets(const std::string &path)
{
std::vector<std::string> result;
diff --git a/src/wallet/api/wallet_manager.h b/src/wallet/api/wallet_manager.h
index 8b1c8be7f..573e80d1a 100644
--- a/src/wallet/api/wallet_manager.h
+++ b/src/wallet/api/wallet_manager.h
@@ -76,6 +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;
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/wallet2.cpp b/src/wallet/wallet2.cpp
index b266821d6..4e93309ed 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -161,6 +161,7 @@ struct options {
}
};
const command_line::arg_descriptor<uint64_t> kdf_rounds = {"kdf-rounds", tools::wallet2::tr("Number of rounds for the key derivation function"), 1};
+ const command_line::arg_descriptor<std::string> hw_device = {"hw-device", tools::wallet2::tr("HW device to use"), ""};
};
void do_prepare_file_names(const std::string& file_path, std::string& keys_file, std::string& wallet_file)
@@ -211,6 +212,7 @@ std::unique_ptr<tools::wallet2> make_basic(const boost::program_options::variabl
auto daemon_address = command_line::get_arg(vm, opts.daemon_address);
auto daemon_host = command_line::get_arg(vm, opts.daemon_host);
auto daemon_port = command_line::get_arg(vm, opts.daemon_port);
+ auto device_name = command_line::get_arg(vm, opts.hw_device);
THROW_WALLET_EXCEPTION_IF(!daemon_address.empty() && !daemon_host.empty() && 0 != daemon_port,
tools::error::wallet_internal_error, tools::wallet2::tr("can't specify daemon host or port more than once"));
@@ -261,10 +263,11 @@ std::unique_ptr<tools::wallet2> make_basic(const boost::program_options::variabl
catch (const std::exception &e) { }
}
- std::unique_ptr<tools::wallet2> wallet(new tools::wallet2(nettype, kdf_rounds));
- wallet->init(unattended, std::move(daemon_address), std::move(login), 0, false, *trusted_daemon);
+ std::unique_ptr<tools::wallet2> wallet(new tools::wallet2(nettype, kdf_rounds, unattended));
+ wallet->init(std::move(daemon_address), std::move(login), 0, false, *trusted_daemon);
boost::filesystem::path ringdb_path = command_line::get_arg(vm, opts.shared_ringdb_dir);
wallet->set_ring_database(ringdb_path.string());
+ wallet->device_name(device_name);
return wallet;
}
@@ -748,7 +751,7 @@ wallet_keys_unlocker::~wallet_keys_unlocker()
w.encrypt_keys(key);
}
-wallet2::wallet2(network_type nettype, uint64_t kdf_rounds):
+wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended):
m_multisig_rescan_info(NULL),
m_multisig_rescan_k(NULL),
m_run(true),
@@ -791,12 +794,12 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds):
m_light_wallet_connected(false),
m_light_wallet_balance(0),
m_light_wallet_unlocked_balance(0),
- m_key_on_device(false),
+ m_key_device_type(hw::device::device_type::SOFTWARE),
m_ring_history_saved(false),
m_ringdb(),
m_last_block_reward(0),
m_encrypt_keys_after_refresh(boost::none),
- m_unattended(false)
+ m_unattended(unattended)
{
}
@@ -814,6 +817,11 @@ bool wallet2::has_stagenet_option(const boost::program_options::variables_map& v
return command_line::get_arg(vm, options().stagenet);
}
+std::string wallet2::device_name_option(const boost::program_options::variables_map& vm)
+{
+ return command_line::get_arg(vm, options().hw_device);
+}
+
void wallet2::init_options(boost::program_options::options_description& desc_params)
{
const options opts{};
@@ -829,6 +837,7 @@ void wallet2::init_options(boost::program_options::options_description& desc_par
command_line::add_arg(desc_params, opts.stagenet);
command_line::add_arg(desc_params, opts.shared_ringdb_dir);
command_line::add_arg(desc_params, opts.kdf_rounds);
+ command_line::add_arg(desc_params, opts.hw_device);
}
std::unique_ptr<wallet2> wallet2::make_from_json(const boost::program_options::variables_map& vm, bool unattended, const std::string& json_file, const std::function<boost::optional<tools::password_container>(const char *, bool)> &password_prompter)
@@ -872,9 +881,8 @@ std::unique_ptr<wallet2> wallet2::make_dummy(const boost::program_options::varia
}
//----------------------------------------------------------------------------------------------------
-bool wallet2::init(bool unattended, std::string daemon_address, boost::optional<epee::net_utils::http::login> daemon_login, uint64_t upper_transaction_weight_limit, bool ssl, bool trusted_daemon)
+bool wallet2::init(std::string daemon_address, boost::optional<epee::net_utils::http::login> daemon_login, uint64_t upper_transaction_weight_limit, bool ssl, bool trusted_daemon)
{
- m_unattended = unattended;
m_checkpoints.init_default_checkpoints(m_nettype);
if(m_http_client.is_connected())
m_http_client.disconnect();
@@ -984,6 +992,27 @@ bool wallet2::get_multisig_seed(epee::wipeable_string& seed, const epee::wipeabl
return true;
}
//----------------------------------------------------------------------------------------------------
+bool wallet2::reconnect_device()
+{
+ bool r = true;
+ hw::device &hwdev = hw::get_device(m_device_name);
+ hwdev.set_name(m_device_name);
+ r = hwdev.init();
+ if (!r){
+ LOG_PRINT_L2("Could not init device");
+ return false;
+ }
+
+ r = hwdev.connect();
+ if (!r){
+ LOG_PRINT_L2("Could not connect to the device");
+ return false;
+ }
+
+ m_account.set_device(hwdev);
+ return true;
+}
+//----------------------------------------------------------------------------------------------------
/*!
* \brief Gets the seed language
*/
@@ -2879,7 +2908,7 @@ bool wallet2::store_keys(const std::string& keys_file_name, const epee::wipeable
rapidjson::Value value2(rapidjson::kNumberType);
- value2.SetInt(m_key_on_device?1:0);
+ value2.SetInt(m_key_device_type);
json.AddMember("key_on_device", value2, json.GetAllocator());
value2.SetInt(watch_only ? 1 :0); // WTF ? JSON has different true and false types, and not boolean ??
@@ -2980,6 +3009,9 @@ bool wallet2::store_keys(const std::string& keys_file_name, const epee::wipeable
value2.SetUint(1);
json.AddMember("encrypted_secret_keys", value2, json.GetAllocator());
+ value.SetString(m_device_name.c_str(), m_device_name.size());
+ json.AddMember("device_name", value, json.GetAllocator());
+
// Serialize the JSON object
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
@@ -3088,7 +3120,8 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_
m_ignore_fractional_outputs = true;
m_subaddress_lookahead_major = SUBADDRESS_LOOKAHEAD_MAJOR;
m_subaddress_lookahead_minor = SUBADDRESS_LOOKAHEAD_MINOR;
- m_key_on_device = false;
+ m_device_name = "";
+ m_key_device_type = hw::device::device_type::SOFTWARE;
encrypted_secret_keys = false;
}
else if(json.IsObject())
@@ -3108,8 +3141,8 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_
if (json.HasMember("key_on_device"))
{
- GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, key_on_device, int, Int, false, false);
- m_key_on_device = field_key_on_device;
+ GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, key_on_device, int, Int, false, hw::device::device_type::SOFTWARE);
+ m_key_device_type = static_cast<hw::device::device_type>(field_key_on_device);
}
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, seed_language, std::string, String, false, std::string());
@@ -3219,8 +3252,15 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_
m_subaddress_lookahead_major = field_subaddress_lookahead_major;
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, subaddress_lookahead_minor, uint32_t, Uint, false, SUBADDRESS_LOOKAHEAD_MINOR);
m_subaddress_lookahead_minor = field_subaddress_lookahead_minor;
+
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, encrypted_secret_keys, uint32_t, Uint, false, false);
encrypted_secret_keys = field_encrypted_secret_keys;
+
+ GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, device_name, std::string, String, false, std::string());
+ if (m_device_name.empty() && field_device_name_found)
+ {
+ m_device_name = field_device_name;
+ }
}
else
{
@@ -3229,13 +3269,17 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_
}
r = epee::serialization::load_t_from_binary(m_account, account_data);
- if (r && m_key_on_device) {
+ THROW_WALLET_EXCEPTION_IF(!r, error::invalid_password);
+ if (m_key_device_type == hw::device::device_type::LEDGER) {
LOG_PRINT_L0("Account on device. Initing device...");
- hw::device &hwdev = hw::get_device("Ledger");
+ hw::device &hwdev = hw::get_device(m_device_name);
+ hwdev.set_name(m_device_name);
hwdev.init();
hwdev.connect();
m_account.set_device(hwdev);
LOG_PRINT_L0("Device inited...");
+ } else if (key_on_device()) {
+ THROW_WALLET_EXCEPTION(error::wallet_internal_error, "hardware device not supported");
}
if (r)
@@ -3404,6 +3448,59 @@ void wallet2::create_keys_file(const std::string &wallet_, bool watch_only, cons
/*!
+ * \brief determine the key storage for the specified wallet file
+ * \param device_type (OUT) wallet backend as enumerated in hw::device::device_type
+ * \param keys_file_name Keys file to verify password for
+ * \param password Password to verify
+ * \return true if password correct, else false
+ *
+ * for verification only - determines key storage hardware
+ *
+ */
+bool wallet2::query_device(hw::device::device_type& device_type, const std::string& keys_file_name, const epee::wipeable_string& password, uint64_t kdf_rounds)
+{
+ rapidjson::Document json;
+ wallet2::keys_file_data keys_file_data;
+ std::string buf;
+ bool r = epee::file_io_utils::load_file_to_string(keys_file_name, buf);
+ THROW_WALLET_EXCEPTION_IF(!r, error::file_read_error, keys_file_name);
+
+ // Decrypt the contents
+ r = ::serialization::parse_binary(buf, keys_file_data);
+ THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "internal error: failed to deserialize \"" + keys_file_name + '\"');
+ crypto::chacha_key key;
+ crypto::generate_chacha_key(password.data(), password.size(), key, kdf_rounds);
+ std::string account_data;
+ account_data.resize(keys_file_data.account_data.size());
+ crypto::chacha20(keys_file_data.account_data.data(), keys_file_data.account_data.size(), key, keys_file_data.iv, &account_data[0]);
+ if (json.Parse(account_data.c_str()).HasParseError() || !json.IsObject())
+ crypto::chacha8(keys_file_data.account_data.data(), keys_file_data.account_data.size(), key, keys_file_data.iv, &account_data[0]);
+
+ // The contents should be JSON if the wallet follows the new format.
+ if (json.Parse(account_data.c_str()).HasParseError())
+ {
+ // old format before JSON wallet key file format
+ }
+ else
+ {
+ account_data = std::string(json["key_data"].GetString(), json["key_data"].GetString() +
+ json["key_data"].GetStringLength());
+
+ if (json.HasMember("key_on_device"))
+ {
+ GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, key_on_device, int, Int, false, hw::device::device_type::SOFTWARE);
+ device_type = static_cast<hw::device::device_type>(field_key_on_device);
+ }
+ }
+
+ cryptonote::account_base account_data_check;
+
+ r = epee::serialization::load_t_from_binary(account_data_check, account_data);
+ if (!r) return false;
+ return true;
+}
+
+/*!
* \brief Generates a wallet or restores one.
* \param wallet_ Name of wallet file
* \param password Password of wallet file
@@ -3477,7 +3574,7 @@ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string&
m_multisig = true;
m_multisig_threshold = threshold;
m_multisig_signers = multisig_signers;
- m_key_on_device = false;
+ m_key_device_type = hw::device::device_type::SOFTWARE;
setup_keys(password);
create_keys_file(wallet_, false, password, m_nettype != MAINNET || create_address_file);
@@ -3517,7 +3614,7 @@ crypto::secret_key wallet2::generate(const std::string& wallet_, const epee::wip
m_multisig = false;
m_multisig_threshold = 0;
m_multisig_signers.clear();
- m_key_on_device = false;
+ m_key_device_type = hw::device::device_type::SOFTWARE;
setup_keys(password);
// calculate a starting refresh height
@@ -3605,7 +3702,7 @@ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string&
m_multisig = false;
m_multisig_threshold = 0;
m_multisig_signers.clear();
- m_key_on_device = false;
+ m_key_device_type = hw::device::device_type::SOFTWARE;
setup_keys(password);
create_keys_file(wallet_, true, password, m_nettype != MAINNET || create_address_file);
@@ -3645,7 +3742,7 @@ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string&
m_multisig = false;
m_multisig_threshold = 0;
m_multisig_signers.clear();
- m_key_on_device = false;
+ m_key_device_type = hw::device::device_type::SOFTWARE;
setup_keys(password);
create_keys_file(wallet_, false, password, create_address_file);
@@ -3672,14 +3769,19 @@ void wallet2::restore(const std::string& wallet_, const epee::wipeable_string& p
THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_wallet_file, ignored_ec), error::file_exists, m_wallet_file);
THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_keys_file, ignored_ec), error::file_exists, m_keys_file);
}
- m_key_on_device = true;
- m_account.create_from_device(device_name);
+
+ auto &hwdev = hw::get_device(device_name);
+ hwdev.set_name(device_name);
+
+ m_account.create_from_device(hwdev);
+ m_key_device_type = m_account.get_device().get_type();
m_account_public_address = m_account.get_keys().m_account_address;
m_watch_only = false;
m_multisig = false;
m_multisig_threshold = 0;
m_multisig_signers.clear();
setup_keys(password);
+ m_device_name = device_name;
create_keys_file(wallet_, false, password, m_nettype != MAINNET || create_address_file);
if (m_subaddress_lookahead_major == SUBADDRESS_LOOKAHEAD_MAJOR && m_subaddress_lookahead_minor == SUBADDRESS_LOOKAHEAD_MINOR)
@@ -3769,7 +3871,7 @@ std::string wallet2::make_multisig(const epee::wipeable_string &password,
m_watch_only = false;
m_multisig = true;
m_multisig_threshold = threshold;
- m_key_on_device = false;
+ m_key_device_type = hw::device::device_type::SOFTWARE;
if (threshold == spend_keys.size() + 1)
{
@@ -10784,7 +10886,12 @@ size_t wallet2::import_multisig(std::vector<cryptonote::blobdata> blobs)
refresh(false);
}
- catch (...) {}
+ catch (...)
+ {
+ m_multisig_rescan_info = NULL;
+ m_multisig_rescan_k = NULL;
+ throw;
+ }
m_multisig_rescan_info = NULL;
m_multisig_rescan_k = NULL;
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index 402066b50..9eb9b04f2 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -172,6 +172,7 @@ namespace tools
static bool has_testnet_option(const boost::program_options::variables_map& vm);
static bool has_stagenet_option(const boost::program_options::variables_map& vm);
+ static std::string device_name_option(const boost::program_options::variables_map& vm);
static void init_options(boost::program_options::options_description& desc_params);
//! Uses stdin and stdout. Returns a wallet2 if no errors.
@@ -188,8 +189,9 @@ namespace tools
static std::unique_ptr<wallet2> make_dummy(const boost::program_options::variables_map& vm, bool unattended, const std::function<boost::optional<password_container>(const char *, bool)> &password_prompter);
static bool verify_password(const std::string& keys_file_name, const epee::wipeable_string& password, bool no_spend_key, hw::device &hwdev, uint64_t kdf_rounds);
+ static bool query_device(hw::device::device_type& device_type, const std::string& keys_file_name, const epee::wipeable_string& password, uint64_t kdf_rounds = 1);
- wallet2(cryptonote::network_type nettype = cryptonote::MAINNET, uint64_t kdf_rounds = 1);
+ wallet2(cryptonote::network_type nettype = cryptonote::MAINNET, uint64_t kdf_rounds = 1, bool unattended = false);
~wallet2();
struct multisig_info
@@ -638,7 +640,7 @@ namespace tools
bool explicit_refresh_from_block_height() const {return m_explicit_refresh_from_block_height;}
bool deinit();
- bool init(bool unatteded, std::string daemon_address = "http://localhost:8080",
+ bool init(std::string daemon_address = "http://localhost:8080",
boost::optional<epee::net_utils::http::login> daemon_login = boost::none, uint64_t upper_transaction_weight_limit = 0, bool ssl = false, bool trusted_daemon = false);
void stop() { m_run.store(false, std::memory_order_relaxed); }
@@ -708,7 +710,9 @@ namespace tools
bool has_multisig_partial_key_images() const;
bool has_unknown_key_images() const;
bool get_multisig_seed(epee::wipeable_string& seed, const epee::wipeable_string &passphrase = std::string(), bool raw = true) const;
- bool key_on_device() const { return m_key_on_device; }
+ bool key_on_device() const { return get_device_type() != hw::device::device_type::SOFTWARE; }
+ hw::device::device_type get_device_type() const { return m_key_device_type; }
+ bool reconnect_device();
// locked & unlocked balance of given or current subaddress account
uint64_t balance(uint32_t subaddr_index_major) const;
@@ -938,6 +942,8 @@ namespace tools
void ignore_fractional_outputs(bool value) { m_ignore_fractional_outputs = value; }
bool confirm_non_default_ring_size() const { return m_confirm_non_default_ring_size; }
void confirm_non_default_ring_size(bool always) { m_confirm_non_default_ring_size = always; }
+ const std::string & device_name() const { return m_device_name; }
+ void device_name(const std::string & device_name) { m_device_name = device_name; }
bool get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys) const;
void set_tx_key(const crypto::hash &txid, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys);
@@ -1280,7 +1286,7 @@ namespace tools
bool m_trusted_daemon;
i_wallet2_callback* m_callback;
- bool m_key_on_device;
+ hw::device::device_type m_key_device_type;
cryptonote::network_type m_nettype;
uint64_t m_kdf_rounds;
std::string seed_language; /*!< Language of the mnemonics (seed). */
@@ -1319,6 +1325,7 @@ namespace tools
NodeRPCProxy m_node_rpc_proxy;
std::unordered_set<crypto::hash> m_scanned_pool_txs[2];
size_t m_subaddress_lookahead_major, m_subaddress_lookahead_minor;
+ std::string m_device_name;
// Light wallet
bool m_light_wallet; /* sends view key to daemon for scanning */
diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index ee86587bc..86b46b173 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -51,6 +51,7 @@ using namespace epee;
#include "mnemonics/electrum-words.h"
#include "rpc/rpc_args.h"
#include "rpc/core_rpc_server_commands_defs.h"
+#include "daemonizer/daemonizer.h"
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "wallet.rpc"
@@ -759,10 +760,10 @@ namespace tools
{
if (get_tx_key)
{
- std::string s = epee::string_tools::pod_to_hex(ptx.tx_key);
+ epee::wipeable_string s = epee::to_hex::wipeable_string(ptx.tx_key);
for (const crypto::secret_key& additional_tx_key : ptx.additional_tx_keys)
- s += epee::string_tools::pod_to_hex(additional_tx_key);
- fill(tx_key, s);
+ s += epee::to_hex::wipeable_string(additional_tx_key);
+ fill(tx_key, std::string(s.data(), s.size()));
}
// Compute amount leaving wallet in tx. By convention dests does not include change outputs
fill(amount, total_amount(ptx));
@@ -1569,11 +1570,13 @@ namespace tools
}
else if(req.key_type.compare("view_key") == 0)
{
- res.key = string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_view_secret_key);
+ epee::wipeable_string key = epee::to_hex::wipeable_string(m_wallet->get_account().get_keys().m_view_secret_key);
+ res.key = std::string(key.data(), key.size());
}
else if(req.key_type.compare("spend_key") == 0)
{
- res.key = string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_spend_secret_key);
+ epee::wipeable_string key = epee::to_hex::wipeable_string(m_wallet->get_account().get_keys().m_spend_secret_key);
+ res.key = std::string(key.data(), key.size());
}
else
{
@@ -1799,11 +1802,11 @@ namespace tools
return false;
}
- std::ostringstream oss;
- oss << epee::string_tools::pod_to_hex(tx_key);
+ epee::wipeable_string s;
+ s += epee::to_hex::wipeable_string(tx_key);
for (size_t i = 0; i < additional_tx_keys.size(); ++i)
- oss << epee::string_tools::pod_to_hex(additional_tx_keys[i]);
- res.tx_key = oss.str();
+ s += epee::to_hex::wipeable_string(additional_tx_keys[i]);
+ res.tx_key = std::string(s.data(), s.size());
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
@@ -1819,26 +1822,33 @@ namespace tools
return false;
}
- std::string tx_key_str = req.tx_key;
+ epee::wipeable_string tx_key_str = req.tx_key;
+ if (tx_key_str.size() < 64 || tx_key_str.size() % 64)
+ {
+ er.code = WALLET_RPC_ERROR_CODE_WRONG_KEY;
+ er.message = "Tx key has invalid format";
+ return false;
+ }
+ const char *data = tx_key_str.data();
crypto::secret_key tx_key;
- if (!epee::string_tools::hex_to_pod(tx_key_str.substr(0, 64), tx_key))
+ if (!epee::wipeable_string(data, 64).hex_to_pod(unwrap(unwrap(tx_key))))
{
er.code = WALLET_RPC_ERROR_CODE_WRONG_KEY;
er.message = "Tx key has invalid format";
return false;
}
- tx_key_str = tx_key_str.substr(64);
+ size_t offset = 64;
std::vector<crypto::secret_key> additional_tx_keys;
- while (!tx_key_str.empty())
+ while (offset < tx_key_str.size())
{
additional_tx_keys.resize(additional_tx_keys.size() + 1);
- if (!epee::string_tools::hex_to_pod(tx_key_str.substr(0, 64), additional_tx_keys.back()))
+ if (!epee::wipeable_string(data + offset, 64).hex_to_pod(unwrap(unwrap(additional_tx_keys.back()))))
{
er.code = WALLET_RPC_ERROR_CODE_WRONG_KEY;
er.message = "Tx key has invalid format";
return false;
}
- tx_key_str = tx_key_str.substr(64);
+ offset += 64;
}
cryptonote::address_parse_info info;
@@ -3265,12 +3275,172 @@ namespace tools
//------------------------------------------------------------------------------------------------------------------------------
}
+class t_daemon
+{
+private:
+ const boost::program_options::variables_map& vm;
+
+public:
+ t_daemon(boost::program_options::variables_map const & _vm)
+ : vm(_vm)
+ {
+ }
+
+ bool run()
+ {
+ std::unique_ptr<tools::wallet2> wal;
+ try
+ {
+ const bool testnet = tools::wallet2::has_testnet_option(vm);
+ const bool stagenet = tools::wallet2::has_stagenet_option(vm);
+ if (testnet && stagenet)
+ {
+ MERROR(tools::wallet_rpc_server::tr("Can't specify more than one of --testnet and --stagenet"));
+ return false;
+ }
+
+ const auto arg_wallet_file = wallet_args::arg_wallet_file();
+ const auto arg_from_json = wallet_args::arg_generate_from_json();
+
+ const auto wallet_file = command_line::get_arg(vm, arg_wallet_file);
+ const auto from_json = command_line::get_arg(vm, arg_from_json);
+ const auto wallet_dir = command_line::get_arg(vm, arg_wallet_dir);
+ const auto prompt_for_password = command_line::get_arg(vm, arg_prompt_for_password);
+ const auto password_prompt = prompt_for_password ? password_prompter : nullptr;
+
+ if(!wallet_file.empty() && !from_json.empty())
+ {
+ LOG_ERROR(tools::wallet_rpc_server::tr("Can't specify more than one of --wallet-file and --generate-from-json"));
+ return false;
+ }
+
+ if (!wallet_dir.empty())
+ {
+ wal = NULL;
+ goto just_dir;
+ }
+
+ if (wallet_file.empty() && from_json.empty())
+ {
+ LOG_ERROR(tools::wallet_rpc_server::tr("Must specify --wallet-file or --generate-from-json or --wallet-dir"));
+ return false;
+ }
+
+ LOG_PRINT_L0(tools::wallet_rpc_server::tr("Loading wallet..."));
+ if(!wallet_file.empty())
+ {
+ wal = tools::wallet2::make_from_file(vm, true, wallet_file, password_prompt).first;
+ }
+ else
+ {
+ try
+ {
+ wal = tools::wallet2::make_from_json(vm, true, from_json, password_prompt);
+ }
+ catch (const std::exception &e)
+ {
+ MERROR("Error creating wallet: " << e.what());
+ return false;
+ }
+ }
+ if (!wal)
+ {
+ return false;
+ }
+
+ bool quit = false;
+ tools::signal_handler::install([&wal, &quit](int) {
+ assert(wal);
+ quit = true;
+ wal->stop();
+ });
+
+ wal->refresh(wal->is_trusted_daemon());
+ // if we ^C during potentially length load/refresh, there's no server loop yet
+ if (quit)
+ {
+ MINFO(tools::wallet_rpc_server::tr("Saving wallet..."));
+ wal->store();
+ MINFO(tools::wallet_rpc_server::tr("Successfully saved"));
+ return false;
+ }
+ MINFO(tools::wallet_rpc_server::tr("Successfully loaded"));
+ }
+ catch (const std::exception& e)
+ {
+ LOG_ERROR(tools::wallet_rpc_server::tr("Wallet initialization failed: ") << e.what());
+ return false;
+ }
+ just_dir:
+ tools::wallet_rpc_server wrpc;
+ 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();
+ });
+ LOG_PRINT_L0(tools::wallet_rpc_server::tr("Starting wallet RPC server"));
+ try
+ {
+ wrpc.run();
+ }
+ catch (const std::exception &e)
+ {
+ LOG_ERROR(tools::wallet_rpc_server::tr("Failed to run wallet: ") << e.what());
+ return false;
+ }
+ LOG_PRINT_L0(tools::wallet_rpc_server::tr("Stopped wallet RPC server"));
+ try
+ {
+ LOG_PRINT_L0(tools::wallet_rpc_server::tr("Saving wallet..."));
+ wrpc.stop();
+ LOG_PRINT_L0(tools::wallet_rpc_server::tr("Successfully saved"));
+ }
+ catch (const std::exception& e)
+ {
+ LOG_ERROR(tools::wallet_rpc_server::tr("Failed to save wallet: ") << e.what());
+ return false;
+ }
+ return true;
+ }
+};
+
+class t_executor final
+{
+public:
+ static std::string const NAME;
+
+ std::string const & name()
+ {
+ return NAME;
+ }
+
+ t_daemon create_daemon(boost::program_options::variables_map const & vm)
+ {
+ return t_daemon(vm);
+ }
+
+ bool run_non_interactive(boost::program_options::variables_map const & vm)
+ {
+ return t_daemon(vm).run();
+ }
+
+ bool run_interactive(boost::program_options::variables_map const & vm)
+ {
+ return t_daemon(vm).run();
+ }
+};
+
+std::string const t_executor::NAME = "Wallet RPC Daemon";
+
int main(int argc, char** argv) {
namespace po = boost::program_options;
const auto arg_wallet_file = wallet_args::arg_wallet_file();
const auto arg_from_json = wallet_args::arg_generate_from_json();
+ po::options_description hidden_options("Hidden");
+
po::options_description desc_params(wallet_args::tr("Wallet options"));
tools::wallet2::init_options(desc_params);
command_line::add_arg(desc_params, arg_rpc_bind_port);
@@ -3282,6 +3452,8 @@ int main(int argc, char** argv) {
command_line::add_arg(desc_params, arg_wallet_dir);
command_line::add_arg(desc_params, arg_prompt_for_password);
+ daemonizer::init_options(hidden_options, desc_params);
+
boost::optional<po::variables_map> vm;
bool should_terminate = false;
std::tie(vm, should_terminate) = wallet_args::main(
@@ -3303,115 +3475,5 @@ int main(int argc, char** argv) {
return 0;
}
- std::unique_ptr<tools::wallet2> wal;
- try
- {
- const bool testnet = tools::wallet2::has_testnet_option(*vm);
- const bool stagenet = tools::wallet2::has_stagenet_option(*vm);
- if (testnet && stagenet)
- {
- MERROR(tools::wallet_rpc_server::tr("Can't specify more than one of --testnet and --stagenet"));
- return 1;
- }
-
- const auto wallet_file = command_line::get_arg(*vm, arg_wallet_file);
- const auto from_json = command_line::get_arg(*vm, arg_from_json);
- const auto wallet_dir = command_line::get_arg(*vm, arg_wallet_dir);
- const auto prompt_for_password = command_line::get_arg(*vm, arg_prompt_for_password);
- const auto password_prompt = prompt_for_password ? password_prompter : nullptr;
-
- if(!wallet_file.empty() && !from_json.empty())
- {
- LOG_ERROR(tools::wallet_rpc_server::tr("Can't specify more than one of --wallet-file and --generate-from-json"));
- return 1;
- }
-
- if (!wallet_dir.empty())
- {
- wal = NULL;
- goto just_dir;
- }
-
- if (wallet_file.empty() && from_json.empty())
- {
- LOG_ERROR(tools::wallet_rpc_server::tr("Must specify --wallet-file or --generate-from-json or --wallet-dir"));
- return 1;
- }
-
- LOG_PRINT_L0(tools::wallet_rpc_server::tr("Loading wallet..."));
- if(!wallet_file.empty())
- {
- wal = tools::wallet2::make_from_file(*vm, true, wallet_file, password_prompt).first;
- }
- else
- {
- try
- {
- wal = tools::wallet2::make_from_json(*vm, true, from_json, password_prompt);
- }
- catch (const std::exception &e)
- {
- MERROR("Error creating wallet: " << e.what());
- return 1;
- }
- }
- if (!wal)
- {
- return 1;
- }
-
- bool quit = false;
- tools::signal_handler::install([&wal, &quit](int) {
- assert(wal);
- quit = true;
- wal->stop();
- });
-
- wal->refresh(wal->is_trusted_daemon());
- // if we ^C during potentially length load/refresh, there's no server loop yet
- if (quit)
- {
- MINFO(tools::wallet_rpc_server::tr("Saving wallet..."));
- wal->store();
- MINFO(tools::wallet_rpc_server::tr("Successfully saved"));
- return 1;
- }
- MINFO(tools::wallet_rpc_server::tr("Successfully loaded"));
- }
- catch (const std::exception& e)
- {
- LOG_ERROR(tools::wallet_rpc_server::tr("Wallet initialization failed: ") << e.what());
- return 1;
- }
-just_dir:
- tools::wallet_rpc_server wrpc;
- if (wal) wrpc.set_wallet(wal.release());
- bool r = wrpc.init(&(vm.get()));
- CHECK_AND_ASSERT_MES(r, 1, tools::wallet_rpc_server::tr("Failed to initialize wallet RPC server"));
- tools::signal_handler::install([&wrpc](int) {
- wrpc.send_stop_signal();
- });
- LOG_PRINT_L0(tools::wallet_rpc_server::tr("Starting wallet RPC server"));
- try
- {
- wrpc.run();
- }
- catch (const std::exception &e)
- {
- LOG_ERROR(tools::wallet_rpc_server::tr("Failed to run wallet: ") << e.what());
- return 1;
- }
- LOG_PRINT_L0(tools::wallet_rpc_server::tr("Stopped wallet RPC server"));
- try
- {
- LOG_PRINT_L0(tools::wallet_rpc_server::tr("Saving wallet..."));
- wrpc.stop();
- LOG_PRINT_L0(tools::wallet_rpc_server::tr("Successfully saved"));
- }
- catch (const std::exception& e)
- {
- LOG_ERROR(tools::wallet_rpc_server::tr("Failed to save wallet: ") << e.what());
- return 1;
- }
- return 0;
+ return daemonizer::daemonize(argc, const_cast<const char**>(argv), t_executor{}, *vm) ? 0 : 1;
}
diff --git a/tests/difficulty/difficulty.cpp b/tests/difficulty/difficulty.cpp
index 736a58237..996913a19 100644
--- a/tests/difficulty/difficulty.cpp
+++ b/tests/difficulty/difficulty.cpp
@@ -34,6 +34,7 @@
#include <iostream>
#include <vector>
#include <algorithm>
+#include <stdexcept>
#include "cryptonote_config.h"
#include "cryptonote_basic/difficulty.h"
diff --git a/tests/functional_tests/transactions_flow_test.cpp b/tests/functional_tests/transactions_flow_test.cpp
index 25dcc77bc..ffe500d21 100644
--- a/tests/functional_tests/transactions_flow_test.cpp
+++ b/tests/functional_tests/transactions_flow_test.cpp
@@ -138,7 +138,7 @@ bool transactions_flow_test(std::string& working_folder,
return false;
}
- w1.init(true, daemon_addr_a);
+ w1.init(daemon_addr_a);
uint64_t blocks_fetched = 0;
bool received_money;
@@ -149,7 +149,7 @@ bool transactions_flow_test(std::string& working_folder,
return false;
}
- w2.init(true, daemon_addr_b);
+ w2.init(daemon_addr_b);
MGINFO_GREEN("Using wallets: " << ENDL
<< "Source: " << w1.get_account().get_public_address_str(MAINNET) << ENDL << "Path: " << working_folder + "/" + path_source_wallet << ENDL
diff --git a/tests/unit_tests/CMakeLists.txt b/tests/unit_tests/CMakeLists.txt
index 741bb1882..d6bcbde46 100644
--- a/tests/unit_tests/CMakeLists.txt
+++ b/tests/unit_tests/CMakeLists.txt
@@ -47,6 +47,7 @@ set(unit_tests_sources
epee_boosted_tcp_server.cpp
epee_levin_protocol_handler_async.cpp
epee_utils.cpp
+ expect.cpp
fee.cpp
json_serialization.cpp
get_xtype_from_string.cpp
diff --git a/tests/unit_tests/epee_utils.cpp b/tests/unit_tests/epee_utils.cpp
index 3474000d8..c2b0b7647 100644
--- a/tests/unit_tests/epee_utils.cpp
+++ b/tests/unit_tests/epee_utils.cpp
@@ -166,12 +166,17 @@ TEST(Span, Traits)
TEST(Span, MutableConstruction)
{
struct no_conversion{};
+ struct inherited : no_conversion {};
EXPECT_TRUE(std::is_constructible<epee::span<char>>());
EXPECT_TRUE((std::is_constructible<epee::span<char>, char*, std::size_t>()));
EXPECT_FALSE((std::is_constructible<epee::span<char>, const char*, std::size_t>()));
EXPECT_FALSE((std::is_constructible<epee::span<char>, unsigned char*, std::size_t>()));
+ EXPECT_TRUE(std::is_constructible<epee::span<no_conversion>>());
+ EXPECT_TRUE((std::is_constructible<epee::span<no_conversion>, no_conversion*, std::size_t>()));
+ EXPECT_FALSE((std::is_constructible<epee::span<no_conversion>, inherited*, std::size_t>()));
+
EXPECT_TRUE((can_construct<epee::span<char>, std::nullptr_t>()));
EXPECT_TRUE((can_construct<epee::span<char>, char(&)[1]>()));
@@ -193,12 +198,19 @@ TEST(Span, MutableConstruction)
TEST(Span, ImmutableConstruction)
{
struct no_conversion{};
+ struct inherited : no_conversion {};
EXPECT_TRUE(std::is_constructible<epee::span<const char>>());
EXPECT_TRUE((std::is_constructible<epee::span<const char>, char*, std::size_t>()));
EXPECT_TRUE((std::is_constructible<epee::span<const char>, const char*, std::size_t>()));
EXPECT_FALSE((std::is_constructible<epee::span<const char>, unsigned char*, std::size_t>()));
+ EXPECT_TRUE(std::is_constructible<epee::span<const no_conversion>>());
+ EXPECT_TRUE((std::is_constructible<epee::span<const no_conversion>, const no_conversion*, std::size_t>()));
+ EXPECT_TRUE((std::is_constructible<epee::span<const no_conversion>, no_conversion*, std::size_t>()));
+ EXPECT_FALSE((std::is_constructible<epee::span<const no_conversion>, const inherited*, std::size_t>()));
+ EXPECT_FALSE((std::is_constructible<epee::span<const no_conversion>, inherited*, std::size_t>()));
+
EXPECT_FALSE((can_construct<epee::span<const char>, std::string>()));
EXPECT_FALSE((can_construct<epee::span<const char>, std::vector<char>>()));
EXPECT_FALSE((can_construct<epee::span<const char>, const std::vector<char>>()));
@@ -231,7 +243,6 @@ TEST(Span, NoExcept)
const epee::span<char> clvalue(data);
EXPECT_TRUE(noexcept(epee::span<char>()));
EXPECT_TRUE(noexcept(epee::span<char>(nullptr)));
- EXPECT_TRUE(noexcept(epee::span<char>(nullptr, 0)));
EXPECT_TRUE(noexcept(epee::span<char>(data)));
EXPECT_TRUE(noexcept(epee::span<char>(lvalue)));
EXPECT_TRUE(noexcept(epee::span<char>(clvalue)));
@@ -284,6 +295,25 @@ TEST(Span, Writing)
EXPECT_TRUE(boost::range::equal(expected, span));
}
+TEST(Span, RemovePrefix)
+{
+ const std::array<unsigned, 4> expected{0, 1, 2, 3};
+ auto span = epee::to_span(expected);
+
+ EXPECT_EQ(expected.begin(), span.begin());
+ EXPECT_EQ(expected.end(), span.end());
+
+ EXPECT_EQ(2u, span.remove_prefix(2));
+ EXPECT_EQ(expected.begin() + 2, span.begin());
+ EXPECT_EQ(expected.end(), span.end());
+
+ EXPECT_EQ(2u, span.remove_prefix(3));
+ EXPECT_EQ(span.begin(), span.end());
+ EXPECT_EQ(expected.end(), span.begin());
+
+ EXPECT_EQ(0u, span.remove_prefix(100));
+}
+
TEST(Span, ToByteSpan)
{
const char expected[] = {56, 44, 11, 5};
@@ -318,6 +348,30 @@ TEST(Span, AsByteSpan)
);
}
+TEST(Span, AsMutByteSpan)
+{
+ struct some_pod { char value[4]; };
+ some_pod actual {};
+
+ auto span = epee::as_mut_byte_span(actual);
+ boost::range::iota(span, 1);
+ EXPECT_TRUE(
+ boost::range::equal(
+ std::array<unsigned char, 4>{{1, 2, 3, 4}}, actual.value
+ )
+ );
+}
+
+TEST(Span, ToMutSpan)
+{
+ std::vector<unsigned> mut;
+ mut.resize(4);
+
+ auto span = epee::to_mut_span(mut);
+ boost::range::iota(span, 1);
+ EXPECT_EQ((std::vector<unsigned>{1, 2, 3, 4}), mut);
+}
+
TEST(ToHex, String)
{
EXPECT_TRUE(epee::to_hex::string(nullptr).empty());
@@ -330,6 +384,7 @@ TEST(ToHex, String)
EXPECT_EQ(
std_to_hex(all_bytes), epee::to_hex::string(epee::to_span(all_bytes))
);
+
}
TEST(ToHex, Array)
diff --git a/tests/unit_tests/expect.cpp b/tests/unit_tests/expect.cpp
new file mode 100644
index 000000000..efa843496
--- /dev/null
+++ b/tests/unit_tests/expect.cpp
@@ -0,0 +1,915 @@
+// Copyright (c) 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.
+
+#include <gtest/gtest.h>
+
+#include <boost/algorithm/string/predicate.hpp>
+#include <boost/utility/string_ref.hpp>
+#include <string>
+#include <system_error>
+#include <type_traits>
+
+#include "common/expect.h"
+
+namespace
+{
+ struct move_only;
+ struct throw_construct;
+ struct throw_copies;
+ struct throw_moves;
+
+ struct move_only
+ {
+ move_only() = default;
+ move_only(move_only const&) = delete;
+ move_only(move_only&&) = default;
+ ~move_only() = default;
+ move_only& operator=(move_only const&) = delete;
+ move_only& operator=(move_only&&) = default;
+ };
+
+ struct throw_construct
+ {
+ throw_construct() {}
+ throw_construct(int) {}
+ throw_construct(throw_construct const&) = default;
+ throw_construct(throw_construct&&) = default;
+ ~throw_construct() = default;
+ throw_construct& operator=(throw_construct const&) = default;
+ throw_construct& operator=(throw_construct&&) = default;
+ };
+
+ struct throw_copies
+ {
+ throw_copies() noexcept {}
+ throw_copies(throw_copies const&) {}
+ throw_copies(throw_copies&&) = default;
+ ~throw_copies() = default;
+ throw_copies& operator=(throw_copies const&) { return *this; }
+ throw_copies& operator=(throw_copies&&) = default;
+ bool operator==(throw_copies const&) noexcept { return true; }
+ bool operator==(throw_moves const&) noexcept { return true; }
+ };
+
+ struct throw_moves
+ {
+ throw_moves() noexcept {}
+ throw_moves(throw_moves const&) = default;
+ throw_moves(throw_moves&&) {}
+ ~throw_moves() = default;
+ throw_moves& operator=(throw_moves const&) = default;
+ throw_moves& operator=(throw_moves&&) { return *this; }
+ bool operator==(throw_moves const&) { return true; }
+ bool operator==(throw_copies const&) { return true; }
+ };
+
+ template<typename T>
+ void construction_bench()
+ {
+ EXPECT_TRUE(std::is_copy_constructible<expect<T>>());
+ EXPECT_TRUE(std::is_move_constructible<expect<T>>());
+ EXPECT_TRUE(std::is_copy_assignable<expect<T>>());
+ EXPECT_TRUE(std::is_move_assignable<expect<T>>());
+ EXPECT_TRUE(std::is_destructible<expect<T>>());
+ }
+
+ template<typename T>
+ void noexcept_bench()
+ {
+ EXPECT_TRUE(std::is_nothrow_copy_constructible<expect<T>>());
+ EXPECT_TRUE(std::is_nothrow_move_constructible<expect<T>>());
+ EXPECT_TRUE(std::is_nothrow_copy_assignable<expect<T>>());
+ EXPECT_TRUE(std::is_nothrow_move_assignable<expect<T>>());
+ EXPECT_TRUE(std::is_nothrow_destructible<expect<T>>());
+
+ EXPECT_TRUE(noexcept(bool(std::declval<expect<T>>())));
+ EXPECT_TRUE(noexcept(std::declval<expect<T>>().has_error()));
+ EXPECT_TRUE(noexcept(std::declval<expect<T>>().error()));
+ EXPECT_TRUE(noexcept(std::declval<expect<T>>().equal(std::declval<expect<T>>())));
+ EXPECT_TRUE(noexcept(std::declval<expect<T>>() == std::declval<expect<T>>()));
+ EXPECT_TRUE(noexcept(std::declval<expect<T>>() != std::declval<expect<T>>()));
+ }
+
+ template<typename T>
+ void conversion_bench()
+ {
+ EXPECT_TRUE((std::is_convertible<std::error_code, expect<T>>()));
+ EXPECT_TRUE((std::is_convertible<std::error_code&&, expect<T>>()));
+ EXPECT_TRUE((std::is_convertible<std::error_code&, expect<T>>()));
+ EXPECT_TRUE((std::is_convertible<std::error_code const&, expect<T>>()));
+
+ EXPECT_TRUE((std::is_constructible<expect<T>, std::error_code>()));
+ EXPECT_TRUE((std::is_constructible<expect<T>, std::error_code&&>()));
+ EXPECT_TRUE((std::is_constructible<expect<T>, std::error_code&>()));
+ EXPECT_TRUE((std::is_constructible<expect<T>, std::error_code const&>()));
+ }
+}
+
+
+TEST(Expect, Constructions)
+{
+ construction_bench<void>();
+ construction_bench<int>();
+
+ EXPECT_TRUE(std::is_constructible<expect<void>>());
+
+ EXPECT_TRUE((std::is_constructible<expect<throw_construct>, expect<int>>()));
+
+ EXPECT_TRUE(std::is_move_constructible<expect<move_only>>());
+ EXPECT_TRUE(std::is_move_assignable<expect<move_only>>());
+}
+
+TEST(Expect, Conversions)
+{
+ struct implicit { implicit(int) {} };
+ struct explicit_only { explicit explicit_only(int) {} };
+
+ conversion_bench<void>();
+ conversion_bench<int>();
+
+ EXPECT_TRUE((std::is_convertible<int, expect<int>>()));
+ EXPECT_TRUE((std::is_convertible<int&&, expect<int>>()));
+ EXPECT_TRUE((std::is_convertible<int&, expect<int>>()));
+ EXPECT_TRUE((std::is_convertible<int const, expect<int>>()));
+ EXPECT_TRUE((std::is_convertible<expect<unsigned>, expect<int>>()));
+ EXPECT_TRUE((std::is_convertible<expect<unsigned>&&, expect<int>>()));
+ EXPECT_TRUE((std::is_convertible<expect<unsigned>&, expect<int>>()));
+ EXPECT_TRUE((std::is_convertible<expect<unsigned> const&, expect<int>>()));
+ EXPECT_TRUE((std::is_convertible<expect<int>, expect<implicit>>()));
+ EXPECT_TRUE((std::is_convertible<expect<int>&&, expect<implicit>>()));
+ EXPECT_TRUE((std::is_convertible<expect<int>&, expect<implicit>>()));
+ EXPECT_TRUE((std::is_convertible<expect<int> const&, expect<implicit>>()));
+ EXPECT_TRUE(!(std::is_convertible<expect<int>, expect<explicit_only>>()));
+ EXPECT_TRUE(!(std::is_convertible<expect<int>&&, expect<explicit_only>>()));
+ EXPECT_TRUE(!(std::is_convertible<expect<int>&, expect<explicit_only>>()));
+ EXPECT_TRUE(!(std::is_convertible<expect<int> const&, expect<explicit_only>>()));
+
+ EXPECT_TRUE((std::is_constructible<expect<int>, int>()));
+ EXPECT_TRUE((std::is_constructible<expect<int>, int&&>()));
+ EXPECT_TRUE((std::is_constructible<expect<int>, int&>()));
+ EXPECT_TRUE((std::is_constructible<expect<int>, int const&>()));
+ EXPECT_TRUE((std::is_constructible<expect<int>, expect<unsigned>>()));
+ EXPECT_TRUE((std::is_constructible<expect<int>, expect<unsigned>&&>()));
+ EXPECT_TRUE((std::is_constructible<expect<int>, expect<unsigned>&>()));
+ EXPECT_TRUE((std::is_constructible<expect<int>, expect<unsigned> const&>()));
+ EXPECT_TRUE((std::is_constructible<expect<implicit>, expect<int>>()));
+ EXPECT_TRUE((std::is_constructible<expect<implicit>, expect<int>&&>()));
+ EXPECT_TRUE((std::is_constructible<expect<implicit>, expect<int>&>()));
+ EXPECT_TRUE((std::is_constructible<expect<implicit>, expect<int> const&>()));
+ EXPECT_TRUE(!(std::is_constructible<expect<explicit_only>, expect<int>>()));
+ EXPECT_TRUE(!(std::is_constructible<expect<explicit_only>, expect<int>&&>()));
+ EXPECT_TRUE(!(std::is_constructible<expect<explicit_only>, expect<int>&>()));
+ EXPECT_TRUE(!(std::is_constructible<expect<explicit_only>, expect<int> const&>()));
+
+ EXPECT_EQ(expect<int>{expect<short>{100}}.value(), 100);
+
+ expect<std::string> val1{std::string{}};
+ expect<const char*> val2{"foo"};
+
+ EXPECT_EQ(val1.value(), std::string{});
+ EXPECT_EQ(val2.value(), std::string{"foo"});
+
+ const expect<std::string> val3{val2};
+
+ EXPECT_EQ(val1.value(), std::string{});
+ EXPECT_EQ(val2.value(), std::string{"foo"});
+ EXPECT_EQ(val3.value(), std::string{"foo"});
+
+ val1 = val2;
+
+ EXPECT_EQ(val1.value(), "foo");
+ EXPECT_EQ(val2.value(), std::string{"foo"});
+ EXPECT_EQ(val3.value(), "foo");
+}
+
+TEST(Expect, NoExcept)
+{
+ noexcept_bench<void>();
+ noexcept_bench<int>();
+
+ EXPECT_TRUE(std::is_nothrow_constructible<expect<void>>());
+
+ EXPECT_TRUE((std::is_nothrow_constructible<expect<int>, int>()));
+ EXPECT_TRUE((std::is_nothrow_constructible<expect<int>, expect<unsigned>>()));
+ EXPECT_TRUE((std::is_nothrow_constructible<expect<int>, expect<unsigned>&&>()));
+ EXPECT_TRUE((std::is_nothrow_constructible<expect<int>, expect<unsigned>&>()));
+ EXPECT_TRUE((std::is_nothrow_constructible<expect<int>, expect<unsigned> const&>()));
+
+ EXPECT_TRUE(noexcept(expect<int>{std::declval<expect<unsigned>&&>()}));
+ EXPECT_TRUE(noexcept(expect<int>{std::declval<expect<unsigned> const&>()}));
+ EXPECT_TRUE(noexcept(std::declval<expect<int>>().has_value()));
+ EXPECT_TRUE(noexcept(*std::declval<expect<int>>()));
+ EXPECT_TRUE(noexcept(std::declval<expect<int>>().equal(std::declval<expect<unsigned>>())));
+ EXPECT_TRUE(noexcept(std::declval<expect<unsigned>>().equal(std::declval<expect<int>>())));
+ EXPECT_TRUE(noexcept(std::declval<expect<int>>().equal(0)));
+ EXPECT_TRUE(noexcept(std::declval<expect<int>>() == std::declval<expect<unsigned>>()));
+ EXPECT_TRUE(noexcept(std::declval<expect<unsigned>>() == std::declval<expect<int>>()));
+ EXPECT_TRUE(noexcept(std::declval<expect<int>>() == 0));
+ EXPECT_TRUE(noexcept(0 == std::declval<expect<int>>()));
+ EXPECT_TRUE(noexcept(std::declval<expect<int>>() != std::declval<expect<unsigned>>()));
+ EXPECT_TRUE(noexcept(std::declval<expect<unsigned>>() != std::declval<expect<int>>()));
+ EXPECT_TRUE(noexcept(std::declval<expect<int>>() != 0));
+ EXPECT_TRUE(noexcept(0 != std::declval<expect<int>>()));
+
+ EXPECT_TRUE((std::is_nothrow_constructible<expect<throw_construct>, std::error_code>()));
+ EXPECT_TRUE((std::is_nothrow_constructible<expect<throw_construct>, std::error_code&&>()));
+ EXPECT_TRUE((std::is_nothrow_constructible<expect<throw_construct>, std::error_code&>()));
+ EXPECT_TRUE((std::is_nothrow_constructible<expect<throw_construct>, std::error_code const&>()));
+ EXPECT_TRUE((std::is_nothrow_constructible<expect<throw_construct>, throw_construct>()));
+ EXPECT_TRUE((std::is_nothrow_constructible<expect<throw_construct>, throw_construct&&>()));
+ EXPECT_TRUE((std::is_nothrow_constructible<expect<throw_construct>, throw_construct&>()));
+ EXPECT_TRUE((std::is_nothrow_constructible<expect<throw_construct>, throw_construct const&>()));
+ EXPECT_TRUE(!(std::is_nothrow_constructible<expect<throw_construct>, expect<int>>()));
+ EXPECT_TRUE(!(std::is_nothrow_constructible<expect<throw_construct>, expect<int>&&>()));
+ EXPECT_TRUE(!(std::is_nothrow_constructible<expect<throw_construct>, expect<int>&>()));
+ EXPECT_TRUE(!(std::is_nothrow_constructible<expect<throw_construct>, expect<int> const&>()));
+ EXPECT_TRUE(std::is_nothrow_copy_constructible<expect<throw_construct>>());
+ EXPECT_TRUE(std::is_nothrow_move_constructible<expect<throw_construct>>());
+ EXPECT_TRUE(std::is_nothrow_copy_assignable<expect<throw_construct>>());
+ EXPECT_TRUE(std::is_nothrow_move_assignable<expect<throw_construct>>());
+ EXPECT_TRUE(std::is_nothrow_destructible<expect<throw_construct>>());
+
+ EXPECT_TRUE((std::is_nothrow_constructible<expect<throw_copies>, std::error_code>()));
+ EXPECT_TRUE((std::is_nothrow_constructible<expect<throw_copies>, std::error_code&&>()));
+ EXPECT_TRUE((std::is_nothrow_constructible<expect<throw_copies>, std::error_code&>()));
+ EXPECT_TRUE((std::is_nothrow_constructible<expect<throw_copies>, std::error_code const&>()));
+ EXPECT_TRUE((std::is_nothrow_constructible<expect<throw_copies>, throw_copies>()));
+ EXPECT_TRUE((std::is_nothrow_constructible<expect<throw_copies>, throw_copies&&>()));
+ EXPECT_TRUE(!(std::is_nothrow_constructible<expect<throw_copies>, throw_copies&>()));
+ EXPECT_TRUE(!(std::is_nothrow_constructible<expect<throw_copies>, throw_copies const&>()));
+ EXPECT_TRUE(!std::is_nothrow_copy_constructible<expect<throw_copies>>());
+ EXPECT_TRUE(std::is_nothrow_move_constructible<expect<throw_copies>>());
+ EXPECT_TRUE(!std::is_nothrow_copy_assignable<expect<throw_copies>>());
+ EXPECT_TRUE(std::is_nothrow_move_assignable<expect<throw_copies>>());
+ EXPECT_TRUE(std::is_nothrow_destructible<expect<throw_copies>>());
+ EXPECT_TRUE(noexcept(std::declval<expect<throw_copies>>().equal(std::declval<expect<throw_copies>>())));
+ EXPECT_TRUE(noexcept(std::declval<expect<throw_copies>>().equal(std::declval<throw_copies>())));
+ EXPECT_TRUE(noexcept(std::declval<expect<throw_copies>>() == std::declval<expect<throw_copies>>()));
+ EXPECT_TRUE(noexcept(std::declval<expect<throw_copies>>() == std::declval<throw_copies>()));
+ EXPECT_TRUE(noexcept(std::declval<throw_copies>() == std::declval<expect<throw_copies>>()));
+ EXPECT_TRUE(noexcept(std::declval<expect<throw_copies>>() != std::declval<expect<throw_copies>>()));
+ EXPECT_TRUE(noexcept(std::declval<expect<throw_copies>>() != std::declval<throw_copies>()));
+ EXPECT_TRUE(noexcept(std::declval<throw_copies>() != std::declval<expect<throw_copies>>()));
+ EXPECT_TRUE(noexcept(std::declval<expect<throw_copies>>().equal(std::declval<expect<throw_moves>>())));
+ EXPECT_TRUE(noexcept(std::declval<expect<throw_copies>>().equal(std::declval<throw_moves>())));
+ EXPECT_TRUE(noexcept(std::declval<expect<throw_copies>>() == std::declval<expect<throw_moves>>()));
+ EXPECT_TRUE(noexcept(std::declval<expect<throw_copies>>() == std::declval<throw_moves>()));
+ EXPECT_TRUE(noexcept(std::declval<throw_moves>() == std::declval<expect<throw_copies>>()));
+ EXPECT_TRUE(noexcept(std::declval<expect<throw_copies>>() != std::declval<expect<throw_moves>>()));
+ EXPECT_TRUE(noexcept(std::declval<expect<throw_copies>>() != std::declval<throw_moves>()));
+ EXPECT_TRUE(noexcept(std::declval<throw_moves>() != std::declval<expect<throw_copies>>()));
+
+ EXPECT_TRUE((std::is_nothrow_constructible<expect<throw_moves>, std::error_code>()));
+ EXPECT_TRUE((std::is_nothrow_constructible<expect<throw_moves>, std::error_code&&>()));
+ EXPECT_TRUE((std::is_nothrow_constructible<expect<throw_moves>, std::error_code&>()));
+ EXPECT_TRUE((std::is_nothrow_constructible<expect<throw_moves>, std::error_code const&>()));
+ EXPECT_TRUE(!(std::is_nothrow_constructible<expect<throw_moves>, throw_moves>()));
+ EXPECT_TRUE(!(std::is_nothrow_constructible<expect<throw_moves>, throw_moves&&>()));
+ EXPECT_TRUE(!(std::is_nothrow_constructible<expect<throw_moves>, throw_moves&>()));
+ EXPECT_TRUE(!(std::is_nothrow_constructible<expect<throw_moves>, throw_moves const&>()));
+ EXPECT_TRUE(std::is_nothrow_copy_constructible<expect<throw_moves>>());
+ EXPECT_TRUE(!std::is_nothrow_move_constructible<expect<throw_moves>>());
+ EXPECT_TRUE(std::is_nothrow_copy_assignable<expect<throw_moves>>());
+ EXPECT_TRUE(!std::is_nothrow_move_assignable<expect<throw_moves>>());
+ EXPECT_TRUE(std::is_nothrow_destructible<expect<throw_copies>>());
+ EXPECT_TRUE(!noexcept(std::declval<expect<throw_moves>>().equal(std::declval<expect<throw_moves>>())));
+ EXPECT_TRUE(!noexcept(std::declval<expect<throw_moves>>().equal(std::declval<throw_moves>())));
+ EXPECT_TRUE(!noexcept(std::declval<expect<throw_moves>>() == std::declval<expect<throw_moves>>()));
+ EXPECT_TRUE(!noexcept(std::declval<expect<throw_moves>>() == std::declval<throw_moves>()));
+ EXPECT_TRUE(!noexcept(std::declval<throw_moves>() == std::declval<expect<throw_moves>>()));
+ EXPECT_TRUE(!noexcept(std::declval<expect<throw_moves>>() != std::declval<expect<throw_moves>>()));
+ EXPECT_TRUE(!noexcept(std::declval<expect<throw_moves>>() != std::declval<throw_moves>()));
+ EXPECT_TRUE(!noexcept(std::declval<throw_moves>() != std::declval<expect<throw_moves>>()));
+ EXPECT_TRUE(!noexcept(std::declval<expect<throw_moves>>().equal(std::declval<expect<throw_copies>>())));
+ EXPECT_TRUE(!noexcept(std::declval<expect<throw_moves>>().equal(std::declval<throw_copies>())));
+ EXPECT_TRUE(!noexcept(std::declval<expect<throw_moves>>() == std::declval<expect<throw_copies>>()));
+ EXPECT_TRUE(!noexcept(std::declval<expect<throw_moves>>() == std::declval<throw_copies>()));
+ EXPECT_TRUE(!noexcept(std::declval<throw_copies>() == std::declval<expect<throw_moves>>()));
+ EXPECT_TRUE(!noexcept(std::declval<expect<throw_moves>>() != std::declval<expect<throw_copies>>()));
+ EXPECT_TRUE(!noexcept(std::declval<expect<throw_moves>>() != std::declval<throw_copies>()));
+ EXPECT_TRUE(!noexcept(std::declval<throw_copies>() != std::declval<expect<throw_moves>>()));
+}
+
+TEST(Expect, Trivial)
+{
+ EXPECT_TRUE(std::is_trivially_copy_constructible<expect<void>>());
+ EXPECT_TRUE(std::is_trivially_move_constructible<expect<void>>());
+ EXPECT_TRUE(std::is_trivially_destructible<expect<void>>());
+}
+
+TEST(Expect, Assignment)
+{
+ expect<std::string> val1{std::string{}};
+ expect<std::string> val2{"foobar"};
+
+ ASSERT_TRUE(val1.has_value());
+ ASSERT_TRUE(val2.has_value());
+ EXPECT_TRUE(bool(val1));
+ EXPECT_TRUE(bool(val2));
+ EXPECT_TRUE(!val1.has_error());
+ EXPECT_TRUE(!val2.has_error());
+ EXPECT_EQ(val1.value(), std::string{});
+ EXPECT_TRUE(*val1 == std::string{});
+ EXPECT_TRUE(boost::equals(val1->c_str(), ""));
+ EXPECT_TRUE(val2.value() == "foobar");
+ EXPECT_TRUE(*val2 == "foobar");
+ EXPECT_TRUE(boost::equals(val2->c_str(), "foobar"));
+ EXPECT_EQ(val1.error(), std::error_code{});
+ EXPECT_EQ(val2.error(), std::error_code{});
+ EXPECT_TRUE(!val1.equal(std::error_code{}));
+ EXPECT_TRUE(!val2.equal(std::error_code{}));
+ EXPECT_TRUE(!(val1 == std::error_code{}));
+ EXPECT_TRUE(!(std::error_code{} == val1));
+ EXPECT_TRUE(!(val2 == std::error_code{}));
+ EXPECT_TRUE(!(std::error_code{} == val2));
+ EXPECT_TRUE(val1 != std::error_code{});
+ EXPECT_TRUE(std::error_code{} != val1);
+ EXPECT_TRUE(val2 != std::error_code{});
+ EXPECT_TRUE(std::error_code{} != val2);
+ EXPECT_TRUE(!val1.matches(std::error_condition{}));
+ EXPECT_TRUE(!val2.matches(std::error_condition{}));
+
+ val1 = std::move(val2);
+
+ ASSERT_TRUE(val1.has_value());
+ ASSERT_TRUE(val2.has_value());
+ EXPECT_TRUE(bool(val1));
+ EXPECT_TRUE(bool(val2));
+ EXPECT_TRUE(!val1.has_error());
+ EXPECT_TRUE(!val2.has_error());
+ EXPECT_EQ(val1.value(), "foobar");
+ EXPECT_TRUE(*val1 == "foobar");
+ EXPECT_TRUE(boost::equals(val1->c_str(), "foobar"));
+ EXPECT_EQ(val2.value(), std::string{});
+ EXPECT_TRUE(*val2 == std::string{});
+ EXPECT_TRUE(boost::equals(val2->c_str(), ""));
+ EXPECT_EQ(val1.error(), std::error_code{});
+ EXPECT_EQ(val2.error(), std::error_code{});
+ EXPECT_TRUE(!val1.equal(std::error_code{}));
+ EXPECT_TRUE(!val2.equal(std::error_code{}));
+ EXPECT_TRUE(!(val1 == std::error_code{}));
+ EXPECT_TRUE(!(std::error_code{} == val1));
+ EXPECT_TRUE(!(val2 == std::error_code{}));
+ EXPECT_TRUE(!(std::error_code{} == val2));
+ EXPECT_TRUE(val1 != std::error_code{});
+ EXPECT_TRUE(std::error_code{} != val1);
+ EXPECT_TRUE(val2 != std::error_code{});
+ EXPECT_TRUE(std::error_code{} != val2);
+ EXPECT_TRUE(!val1.matches(std::error_condition{}));
+ EXPECT_TRUE(!val2.matches(std::error_condition{}));
+
+ val2 = val1;
+
+ ASSERT_TRUE(val1.has_value());
+ ASSERT_TRUE(val2.has_value());
+ EXPECT_TRUE(bool(val1));
+ EXPECT_TRUE(bool(val2));
+ EXPECT_TRUE(!val1.has_error());
+ EXPECT_TRUE(!val2.has_error());
+ EXPECT_EQ(val1.value(), "foobar");
+ EXPECT_TRUE(*val1 == "foobar");
+ EXPECT_TRUE(boost::equals(val1->c_str(), "foobar"));
+ EXPECT_EQ(val2.value(), "foobar");
+ EXPECT_TRUE(*val2 == "foobar");
+ EXPECT_TRUE(boost::equals(val2->c_str(), "foobar"));
+ EXPECT_EQ(val1.error(), std::error_code{});
+ EXPECT_EQ(val2.error(), std::error_code{});
+ EXPECT_TRUE(!val1.equal(std::error_code{}));
+ EXPECT_TRUE(!val2.equal(std::error_code{}));
+ EXPECT_TRUE(!(val1 == std::error_code{}));
+ EXPECT_TRUE(!(std::error_code{} == val1));
+ EXPECT_TRUE(!(val2 == std::error_code{}));
+ EXPECT_TRUE(!(std::error_code{} == val2));
+ EXPECT_TRUE(val1 != std::error_code{});
+ EXPECT_TRUE(std::error_code{} != val1);
+ EXPECT_TRUE(val2 != std::error_code{});
+ EXPECT_TRUE(std::error_code{} != val2);
+ EXPECT_TRUE(!val1.matches(std::error_condition{}));
+ EXPECT_TRUE(!val2.matches(std::error_condition{}));
+
+ val1 = make_error_code(common_error::kInvalidArgument);
+
+ ASSERT_TRUE(val1.has_error());
+ ASSERT_TRUE(val2.has_value());
+ EXPECT_TRUE(!val1);
+ EXPECT_TRUE(bool(val2));
+ EXPECT_TRUE(!val1.has_value());
+ EXPECT_TRUE(!val2.has_error());
+ EXPECT_EQ(val1.error(), common_error::kInvalidArgument);
+ EXPECT_TRUE(val1 == common_error::kInvalidArgument);
+ EXPECT_TRUE(common_error::kInvalidArgument == val1);
+ EXPECT_STREQ(val2.value().c_str(), "foobar");
+ EXPECT_TRUE(*val2 == "foobar");
+ EXPECT_TRUE(boost::equals(val2->c_str(), "foobar"));
+ EXPECT_NE(val1.error(), std::error_code{});
+ EXPECT_EQ(val2.error(), std::error_code{});
+ EXPECT_TRUE(val1.equal(common_error::kInvalidArgument));
+ EXPECT_TRUE(!val2.equal(std::error_code{}));
+ EXPECT_TRUE(!(val1 == std::error_code{}));
+ EXPECT_TRUE(!(std::error_code{} == val1));
+ EXPECT_TRUE(!(val2 == std::error_code{}));
+ EXPECT_TRUE(!(std::error_code{} == val2));
+ EXPECT_TRUE(val1 != std::error_code{});
+ EXPECT_TRUE(std::error_code{} != val1);
+ EXPECT_TRUE(val2 != std::error_code{});
+ EXPECT_TRUE(std::error_code{} != val2);
+ EXPECT_TRUE(val1.matches(std::errc::invalid_argument));
+ EXPECT_TRUE(!val1.matches(std::error_condition{}));
+ EXPECT_TRUE(!val2.matches(std::error_condition{}));
+
+ val2 = val1;
+
+ ASSERT_TRUE(val1.has_error());
+ ASSERT_TRUE(val2.has_error());
+ EXPECT_TRUE(!val1);
+ EXPECT_TRUE(!val2);
+ EXPECT_TRUE(!val1.has_value());
+ EXPECT_TRUE(!val2.has_value());
+ EXPECT_EQ(val1.error(), common_error::kInvalidArgument);
+ EXPECT_TRUE(val1 == common_error::kInvalidArgument);
+ EXPECT_TRUE(common_error::kInvalidArgument == val1);
+ EXPECT_EQ(val2.error(), common_error::kInvalidArgument);
+ EXPECT_TRUE(val2 == common_error::kInvalidArgument);
+ EXPECT_TRUE(common_error::kInvalidArgument == val2);
+ EXPECT_NE(val1.error(), std::error_code{});
+ EXPECT_NE(val2.error(), std::error_code{});
+ EXPECT_TRUE(val1.equal(common_error::kInvalidArgument));
+ EXPECT_TRUE(val2.equal(common_error::kInvalidArgument));
+ EXPECT_TRUE(!(val1 == std::error_code{}));
+ EXPECT_TRUE(!(std::error_code{} == val1));
+ EXPECT_TRUE(!(val2 == std::error_code{}));
+ EXPECT_TRUE(!(std::error_code{} == val2));
+ EXPECT_TRUE(val1 != std::error_code{});
+ EXPECT_TRUE(std::error_code{} != val1);
+ EXPECT_TRUE(val2 != std::error_code{});
+ EXPECT_TRUE(std::error_code{} != val2);
+ EXPECT_TRUE(val1.matches(std::errc::invalid_argument));
+ EXPECT_TRUE(val2.matches(std::errc::invalid_argument));
+ EXPECT_TRUE(!val1.matches(std::error_condition{}));
+ EXPECT_TRUE(!val2.matches(std::error_condition{}));
+
+ val1 = std::string{"barfoo"};
+
+ ASSERT_TRUE(val1.has_value());
+ ASSERT_TRUE(val2.has_error());
+ EXPECT_TRUE(bool(val1));
+ EXPECT_TRUE(!val2);
+ EXPECT_TRUE(!val1.has_error());
+ EXPECT_TRUE(!val2.has_value());
+ EXPECT_STREQ(val1.value().c_str(), "barfoo");
+ EXPECT_TRUE(*val1 == "barfoo");
+ EXPECT_TRUE(boost::equals(val1->c_str(), "barfoo"));
+ EXPECT_EQ(val2.error(), common_error::kInvalidArgument);
+ EXPECT_TRUE(val2 == common_error::kInvalidArgument);
+ EXPECT_TRUE(common_error::kInvalidArgument == val2);
+ EXPECT_EQ(val1.error(), std::error_code{});
+ EXPECT_NE(val2.error(), std::error_code{});
+ EXPECT_TRUE(!val1.equal(std::error_code{}));
+ EXPECT_TRUE(val2.equal(common_error::kInvalidArgument));
+ EXPECT_TRUE(!(val1 == std::error_code{}));
+ EXPECT_TRUE(!(std::error_code{} == val1));
+ EXPECT_TRUE(!(val2 == std::error_code{}));
+ EXPECT_TRUE(!(std::error_code{} == val2));
+ EXPECT_TRUE(val1 != std::error_code{});
+ EXPECT_TRUE(std::error_code{} != val1);
+ EXPECT_TRUE(val2 != std::error_code{});
+ EXPECT_TRUE(std::error_code{} != val2);
+ EXPECT_TRUE(val2.matches(std::errc::invalid_argument));
+ EXPECT_TRUE(!val1.matches(std::error_condition{}));
+ EXPECT_TRUE(!val2.matches(std::error_condition{}));
+
+ val2 = val1;
+
+ ASSERT_TRUE(val1.has_value());
+ ASSERT_TRUE(val2.has_value());
+ EXPECT_TRUE(bool(val1));
+ EXPECT_TRUE(bool(val2));
+ EXPECT_TRUE(!val1.has_error());
+ EXPECT_TRUE(!val2.has_error());
+ EXPECT_EQ(val1.value(), "barfoo");
+ EXPECT_TRUE(*val1 == "barfoo");
+ EXPECT_TRUE(boost::equals(val1->c_str(), "barfoo"));
+ EXPECT_EQ(val2.value(), "barfoo");
+ EXPECT_TRUE(*val2 == "barfoo");
+ EXPECT_TRUE(boost::equals(val2->c_str(), "barfoo"));
+ EXPECT_EQ(val1.error(), std::error_code{});
+ EXPECT_EQ(val2.error(), std::error_code{});
+ EXPECT_TRUE(!val1.equal(std::error_code{}));
+ EXPECT_TRUE(!val2.equal(std::error_code{}));
+ EXPECT_TRUE(!(val1 == std::error_code{}));
+ EXPECT_TRUE(!(std::error_code{} == val1));
+ EXPECT_TRUE(!(val2 == std::error_code{}));
+ EXPECT_TRUE(!(std::error_code{} == val2));
+ EXPECT_TRUE(val1 != std::error_code{});
+ EXPECT_TRUE(std::error_code{} != val1);
+ EXPECT_TRUE(val2 != std::error_code{});
+ EXPECT_TRUE(std::error_code{} != val2);
+ EXPECT_TRUE(!val1.matches(std::error_condition{}));
+ EXPECT_TRUE(!val2.matches(std::error_condition{}));
+}
+
+TEST(Expect, AssignmentThrowsOnMove)
+{
+ struct construct_error {};
+ struct assignment_error {};
+
+ struct throw_on_move {
+ std::string msg;
+
+ throw_on_move(const char* msg) : msg(msg) {}
+ throw_on_move(throw_on_move&&) {
+ throw construct_error{};
+ }
+ throw_on_move(throw_on_move const&) = default;
+ ~throw_on_move() = default;
+ throw_on_move& operator=(throw_on_move&&) {
+ throw assignment_error{};
+ }
+ throw_on_move& operator=(throw_on_move const&) = default;
+ };
+
+ expect<throw_on_move> val1{expect<const char*>{"foobar"}};
+ expect<throw_on_move> val2{common_error::kInvalidArgument};
+
+ ASSERT_TRUE(val1.has_value());
+ ASSERT_TRUE(val2.has_error());
+ EXPECT_TRUE(!val1.has_error());
+ EXPECT_TRUE(!val2.has_value());
+ EXPECT_STREQ(val1->msg.c_str(), "foobar");
+ EXPECT_EQ(val2.error(), common_error::kInvalidArgument);
+
+ EXPECT_THROW(val2 = std::move(val1), construct_error);
+
+ ASSERT_TRUE(val1.has_value());
+ ASSERT_TRUE(val2.has_error());
+ EXPECT_TRUE(!val1.has_error());
+ EXPECT_TRUE(!val2.has_value());
+ EXPECT_STREQ(val1->msg.c_str(), "foobar");
+ EXPECT_EQ(val2.error(), common_error::kInvalidArgument);
+
+ EXPECT_THROW(val1 = expect<const char*>{"barfoo"}, assignment_error);
+
+ ASSERT_TRUE(val1.has_value());
+ ASSERT_TRUE(val2.has_error());
+ EXPECT_TRUE(!val1.has_error());
+ EXPECT_TRUE(!val2.has_value());
+ EXPECT_STREQ(val1->msg.c_str(), "foobar");
+ EXPECT_EQ(val2.error(), common_error::kInvalidArgument);
+
+ EXPECT_NO_THROW(val2 = val1);
+
+ ASSERT_TRUE(val1.has_value());
+ ASSERT_TRUE(val2.has_value());
+ EXPECT_TRUE(!val1.has_error());
+ EXPECT_TRUE(!val2.has_error());
+ EXPECT_STREQ(val1->msg.c_str(), "foobar");
+ EXPECT_STREQ(val2->msg.c_str(), "foobar");
+}
+
+TEST(Expect, EqualWithStrings)
+{
+ expect<std::string> val1{std::string{}};
+ expect<std::string> val2{"barfoo"};
+ expect<boost::string_ref> val3{boost::string_ref{}};
+
+ EXPECT_TRUE(!val1.equal(val2));
+ EXPECT_TRUE(val1.equal(val3));
+ EXPECT_TRUE(!val2.equal(val1));
+ EXPECT_TRUE(!val2.equal(val3));
+ EXPECT_TRUE(val3.equal(val1));
+ EXPECT_TRUE(!val3.equal(val2));
+ EXPECT_TRUE(!(val1 == val2));
+ EXPECT_TRUE(!(val2 == val1));
+ EXPECT_TRUE(val1 == val3);
+ EXPECT_TRUE(val3 == val1);
+ EXPECT_TRUE(!(val2 == val3));
+ EXPECT_TRUE(!(val3 == val2));
+ EXPECT_TRUE(val1 != val2);
+ EXPECT_TRUE(val2 != val1);
+ EXPECT_TRUE(!(val1 != val3));
+ EXPECT_TRUE(!(val3 != val1));
+ EXPECT_TRUE(val2 != val3);
+ EXPECT_TRUE(val3 != val2);
+
+ EXPECT_TRUE(val1.equal(""));
+ EXPECT_TRUE(val2.equal("barfoo"));
+ EXPECT_TRUE(val3.equal(""));
+ EXPECT_TRUE(!val1.equal(std::error_code{}));
+ EXPECT_TRUE(!val2.equal(std::error_code{}));
+ EXPECT_TRUE(!val3.equal(std::error_code{}));
+ EXPECT_TRUE(val1 == "");
+ EXPECT_TRUE("" == val1);
+ EXPECT_TRUE(val2 == "barfoo");
+ EXPECT_TRUE("barfoo" == val2);
+ EXPECT_TRUE(val3 == "");
+ EXPECT_TRUE("" == val3);
+ EXPECT_TRUE(!(val1 != ""));
+ EXPECT_TRUE(!("" != val1));
+ EXPECT_TRUE(!(val2 != "barfoo"));
+ EXPECT_TRUE(!("barfoo" != val2));
+ EXPECT_TRUE(!(val3 != ""));
+ EXPECT_TRUE(!("" != val3));
+ EXPECT_TRUE(!(val1 == std::error_code{}));
+ EXPECT_TRUE(!(std::error_code{} == val1));
+ EXPECT_TRUE(!(val2 == std::error_code{}));
+ EXPECT_TRUE(!(std::error_code{} == val2));
+ EXPECT_TRUE(!(val3 == std::error_code{}));
+ EXPECT_TRUE(!(std::error_code{} == val3));
+ EXPECT_TRUE(val1 != std::error_code{});
+ EXPECT_TRUE(std::error_code{} != val1);
+ EXPECT_TRUE(val2 != std::error_code{});
+ EXPECT_TRUE(std::error_code{} != val2);
+ EXPECT_TRUE(val3 != std::error_code{});
+ EXPECT_TRUE(std::error_code{} != val3);
+ EXPECT_TRUE(!val1.matches(std::error_condition{}));
+ EXPECT_TRUE(!val2.matches(std::error_condition{}));
+ EXPECT_TRUE(!val3.matches(std::error_condition{}));
+
+ val2 = make_error_code(common_error::kInvalidArgument);
+
+ EXPECT_TRUE(!val1.equal(val2));
+ EXPECT_TRUE(val1.equal(val3));
+ EXPECT_TRUE(!val2.equal(val1));
+ EXPECT_TRUE(!val2.equal(val3));
+ EXPECT_TRUE(val3.equal(val1));
+ EXPECT_TRUE(!val3.equal(val2));
+ EXPECT_TRUE(!(val1 == val2));
+ EXPECT_TRUE(!(val2 == val1));
+ EXPECT_TRUE(val1 == val3);
+ EXPECT_TRUE(val3 == val1);
+ EXPECT_TRUE(!(val2 == val3));
+ EXPECT_TRUE(!(val3 == val2));
+ EXPECT_TRUE(val1 != val2);
+ EXPECT_TRUE(val2 != val1);
+ EXPECT_TRUE(!(val1 != val3));
+ EXPECT_TRUE(!(val3 != val1));
+ EXPECT_TRUE(val2 != val3);
+ EXPECT_TRUE(val3 != val2);
+
+ EXPECT_TRUE(!val1.equal(common_error::kInvalidArgument));
+ EXPECT_TRUE(val2.equal(common_error::kInvalidArgument));
+ EXPECT_TRUE(!val3.equal(common_error::kInvalidArgument));
+ EXPECT_TRUE(val2 == common_error::kInvalidArgument);
+ EXPECT_TRUE(common_error::kInvalidArgument == val2);
+ EXPECT_TRUE(!(val2 != common_error::kInvalidArgument));
+ EXPECT_TRUE(!(common_error::kInvalidArgument != val2));
+ EXPECT_TRUE(val2.matches(std::errc::invalid_argument));
+ EXPECT_TRUE(!val2.matches(std::error_condition{}));
+
+ val1 = expect<std::string>{"barfoo"};
+
+ EXPECT_TRUE(!val1.equal(val2));
+ EXPECT_TRUE(!val1.equal(val3));
+ EXPECT_TRUE(!val2.equal(val1));
+ EXPECT_TRUE(!val2.equal(val3));
+ EXPECT_TRUE(!val3.equal(val1));
+ EXPECT_TRUE(!val3.equal(val2));
+ EXPECT_TRUE(!(val1 == val2));
+ EXPECT_TRUE(!(val2 == val1));
+ EXPECT_TRUE(!(val1 == val3));
+ EXPECT_TRUE(!(val3 == val1));
+ EXPECT_TRUE(!(val2 == val3));
+ EXPECT_TRUE(!(val3 == val2));
+ EXPECT_TRUE(val1 != val2);
+ EXPECT_TRUE(val2 != val1);
+ EXPECT_TRUE(val1 != val3);
+ EXPECT_TRUE(val3 != val1);
+ EXPECT_TRUE(val2 != val3);
+ EXPECT_TRUE(val3 != val2);
+
+ EXPECT_TRUE(val1.equal("barfoo"));
+ EXPECT_TRUE(val1 == "barfoo");
+ EXPECT_TRUE("barfoo" == val1);
+ EXPECT_TRUE(!(val1 != "barfoo"));
+ EXPECT_TRUE(!("barfoo" != val1));
+ EXPECT_TRUE(!val1.equal(common_error::kInvalidArgument));
+ EXPECT_TRUE(!(val1 == common_error::kInvalidArgument));
+ EXPECT_TRUE(!(common_error::kInvalidArgument == val1));
+ EXPECT_TRUE(!(val1 == std::error_code{}));
+ EXPECT_TRUE(!(std::error_code{} == val1));
+ EXPECT_TRUE(!val1.matches(std::error_condition{}));
+ EXPECT_TRUE(!val1.matches(std::errc::invalid_argument));
+}
+
+TEST(Expect, EqualWithVoid)
+{
+ const expect<void> val1;
+ expect<void> val2;
+
+ EXPECT_TRUE(val1.equal(val2));
+ EXPECT_TRUE(val2.equal(val1));
+ EXPECT_TRUE(!val1.equal(std::error_code{}));
+ EXPECT_TRUE(!val2.equal(std::error_code{}));
+ EXPECT_TRUE(val1 == val2);
+ EXPECT_TRUE(val2 == val1);
+ EXPECT_TRUE(!(val1 == std::error_code{}));
+ EXPECT_TRUE(!(std::error_code{} == val1));
+ EXPECT_TRUE(!(val2 == std::error_code{}));
+ EXPECT_TRUE(!(std::error_code{} == val2));
+ EXPECT_TRUE(!(val1 != val2));
+ EXPECT_TRUE(!(val2 != val1));
+ EXPECT_TRUE(val1 != std::error_code{});
+ EXPECT_TRUE(std::error_code{} != val1);
+ EXPECT_TRUE(!(val2 == std::error_code{}));
+ EXPECT_TRUE(!(std::error_code{} == val2));
+
+ val2 = make_error_code(common_error::kInvalidArgument);
+
+ EXPECT_TRUE(!val1.equal(val2));
+ EXPECT_TRUE(!val2.equal(val1));
+ EXPECT_TRUE(!val1.equal(common_error::kInvalidArgument));
+ EXPECT_TRUE(val2.equal(common_error::kInvalidArgument));
+ EXPECT_TRUE(!val2.equal(std::error_code{}));
+ EXPECT_TRUE(!(val1 == val2));
+ EXPECT_TRUE(!(val2 == val1));
+ EXPECT_TRUE(val2 == common_error::kInvalidArgument);
+ EXPECT_TRUE(common_error::kInvalidArgument == val2);
+ EXPECT_TRUE(!(val2 == std::error_code{}));
+ EXPECT_TRUE(!(std::error_code{} == val2));
+ EXPECT_TRUE(val1 != val2);
+ EXPECT_TRUE(val2 != val1);
+ EXPECT_TRUE(!(val2 != common_error::kInvalidArgument));
+ EXPECT_TRUE(!(common_error::kInvalidArgument != val2));
+ EXPECT_TRUE(val2 != std::error_code{});
+ EXPECT_TRUE(std::error_code{} != val2);
+}
+
+TEST(Expect, EqualNoCopies)
+{
+ struct copy_error {};
+
+ struct throw_on_copy {
+ throw_on_copy() = default;
+ throw_on_copy(int) noexcept {}
+ throw_on_copy(throw_on_copy const&) {
+ throw copy_error{};
+ }
+ ~throw_on_copy() = default;
+ throw_on_copy& operator=(throw_on_copy const&) {
+ throw copy_error{};
+ }
+
+ bool operator==(throw_on_copy const&) const noexcept { return true; }
+ };
+
+ expect<throw_on_copy> val1{expect<int>{0}};
+ expect<throw_on_copy> val2{expect<int>{0}};
+
+ EXPECT_TRUE(val1.equal(val2));
+ EXPECT_TRUE(val2.equal(val1));
+ EXPECT_TRUE(val1 == val2);
+ EXPECT_TRUE(val2 == val1);
+ EXPECT_TRUE(!(val1 != val2));
+ EXPECT_TRUE(!(val2 != val1));
+
+ EXPECT_TRUE(val1.equal(throw_on_copy{}));
+ EXPECT_TRUE(val1 == throw_on_copy{});
+ EXPECT_TRUE(throw_on_copy{} == val1);
+ EXPECT_TRUE(!(val1 != throw_on_copy{}));
+ EXPECT_TRUE(!(throw_on_copy{} != val1));
+
+ throw_on_copy val3;
+
+ EXPECT_TRUE(val1.equal(val3));
+ EXPECT_TRUE(val1 == val3);
+ EXPECT_TRUE(val3 == val1);
+ EXPECT_TRUE(!(val1 != val3));
+ EXPECT_TRUE(!(val3 != val1));
+
+ expect<throw_on_copy> val4{common_error::kInvalidArgument};
+
+ EXPECT_TRUE(!val4.equal(throw_on_copy{}));
+ EXPECT_TRUE(!(val4 == throw_on_copy{}));
+ EXPECT_TRUE(!(throw_on_copy{} == val4));
+ EXPECT_TRUE(val4 != throw_on_copy{});
+ EXPECT_TRUE(throw_on_copy{} != val4);
+ EXPECT_TRUE(!val4.equal(val3));
+ EXPECT_TRUE(!(val4 == val3));
+ EXPECT_TRUE(!(val3 == val4));
+ EXPECT_TRUE(val4 != val3);
+ EXPECT_TRUE(val3 != val4);
+}
+
+TEST(Expect, Macros) {
+ EXPECT_TRUE(
+ [] () -> ::common_error {
+ MONERO_PRECOND(true);
+ return {common_error::kInvalidErrorCode};
+ } () == common_error::kInvalidErrorCode
+ );
+ EXPECT_TRUE(
+ [] () -> ::common_error {
+ MONERO_PRECOND(false);
+ return {common_error::kInvalidErrorCode};
+ } () == common_error::kInvalidArgument
+ );
+ EXPECT_TRUE(
+ [] () -> std::error_code {
+ MONERO_PRECOND(true);
+ return {common_error::kInvalidErrorCode};
+ } () == common_error::kInvalidErrorCode
+ );
+ EXPECT_TRUE(
+ [] () -> std::error_code {
+ MONERO_PRECOND(false);
+ return {common_error::kInvalidErrorCode};
+ } () == common_error::kInvalidArgument
+ );
+ EXPECT_TRUE(
+ [] () -> expect<void> {
+ MONERO_PRECOND(true);
+ return {common_error::kInvalidErrorCode};
+ } () == common_error::kInvalidErrorCode
+ );
+ EXPECT_TRUE(
+ [] () -> expect<void> {
+ MONERO_PRECOND(false);
+ return {common_error::kInvalidErrorCode};
+ } () == common_error::kInvalidArgument
+ );
+ EXPECT_TRUE(
+ [] () -> expect<int> {
+ MONERO_PRECOND(true);
+ return {common_error::kInvalidErrorCode};
+ } () == common_error::kInvalidErrorCode
+ );
+ EXPECT_TRUE(
+ [] () -> expect<int> {
+ MONERO_PRECOND(false);
+ return {common_error::kInvalidErrorCode};
+ } () == common_error::kInvalidArgument
+ );
+
+ EXPECT_TRUE(
+ [] () -> std::error_code {
+ MONERO_CHECK(expect<void>{});
+ return {common_error::kInvalidErrorCode};
+ } () == common_error::kInvalidErrorCode
+ );
+ EXPECT_TRUE(
+ [] () -> std::error_code {
+ MONERO_CHECK(expect<void>{common_error::kInvalidArgument});
+ return {common_error::kInvalidErrorCode};
+ } () == common_error::kInvalidArgument
+ );
+ EXPECT_TRUE(
+ [] () -> expect<void> {
+ MONERO_CHECK(expect<void>{});
+ return {common_error::kInvalidErrorCode};
+ } () == common_error::kInvalidErrorCode
+ );
+ EXPECT_TRUE(
+ [] () -> expect<void> {
+ MONERO_CHECK(expect<void>{common_error::kInvalidArgument});
+ return {common_error::kInvalidErrorCode};
+ } () == common_error::kInvalidArgument
+ );
+ EXPECT_TRUE(
+ [] () -> expect<int> {
+ MONERO_CHECK(expect<void>{});
+ return {common_error::kInvalidErrorCode};
+ } () == common_error::kInvalidErrorCode
+ );
+ EXPECT_TRUE(
+ [] () -> expect<int> {
+ MONERO_CHECK(expect<void>{common_error::kInvalidArgument});
+ return {common_error::kInvalidErrorCode};
+ } () == common_error::kInvalidArgument
+ );
+
+ EXPECT_NO_THROW(MONERO_UNWRAP(success()));
+ EXPECT_NO_THROW(MONERO_UNWRAP(expect<void>{}));
+ EXPECT_NO_THROW(MONERO_UNWRAP(expect<int>{0}));
+ EXPECT_THROW(
+ MONERO_UNWRAP(expect<void>{common_error::kInvalidArgument}), std::system_error
+ );
+ EXPECT_THROW(
+ MONERO_UNWRAP(expect<int>{common_error::kInvalidArgument}), std::system_error
+ );
+}
+
diff --git a/tests/unit_tests/multisig.cpp b/tests/unit_tests/multisig.cpp
index eb453b960..83924c7af 100644
--- a/tests/unit_tests/multisig.cpp
+++ b/tests/unit_tests/multisig.cpp
@@ -61,7 +61,7 @@ static void make_wallet(unsigned int idx, tools::wallet2 &wallet)
try
{
- wallet.init(false, "");
+ wallet.init("");
wallet.set_subaddress_lookahead(1, 1);
wallet.generate("", "", spendkey, true, false);
ASSERT_TRUE(test_addresses[idx].address == wallet.get_account().get_public_address_str(cryptonote::TESTNET));
diff --git a/tests/unit_tests/wipeable_string.cpp b/tests/unit_tests/wipeable_string.cpp
index 5ea1c1729..65718fd45 100644
--- a/tests/unit_tests/wipeable_string.cpp
+++ b/tests/unit_tests/wipeable_string.cpp
@@ -32,6 +32,7 @@
#include "misc_log_ex.h"
#include "wipeable_string.h"
+#include "hex.h"
TEST(wipeable_string, ctor)
{
@@ -202,3 +203,9 @@ TEST(wipeable_string, parse_hexstr)
ASSERT_TRUE((s = epee::wipeable_string("414243").parse_hexstr()));
ASSERT_EQ(*s, epee::wipeable_string("ABC"));
}
+
+TEST(wipeable_string, to_hex)
+{
+ ASSERT_TRUE(epee::to_hex::wipeable_string(epee::span<const uint8_t>((const uint8_t*)"", 0)) == epee::wipeable_string(""));
+ ASSERT_TRUE(epee::to_hex::wipeable_string(epee::span<const uint8_t>((const uint8_t*)"abc", 3)) == epee::wipeable_string("616263"));
+}
diff --git a/translations/CMakeLists.txt b/translations/CMakeLists.txt
index fdd5014a7..dc7772c1d 100644
--- a/translations/CMakeLists.txt
+++ b/translations/CMakeLists.txt
@@ -42,7 +42,12 @@ IF(NOT CMAKE_CROSSCOMPILING)
add_executable(generate_translations_header generate_translations_header.c)
ENDIF(NOT CMAKE_CROSSCOMPILING)
-find_program(LRELEASE lrelease)
+if(LRELEASE_PATH STREQUAL "")
+ find_program(LRELEASE lrelease)
+else()
+ set(LRELEASE ${LRELEASE_PATH}/lrelease)
+endif()
+
if(LRELEASE STREQUAL "LRELEASE-NOTFOUND")
set(ts_files "")
message(WARNING "lrelease program not found, translation files not built")
@@ -68,7 +73,7 @@ string(REPLACE ".ts" ".qm" qm_files "${ts_files}")
add_custom_command(TARGET generate_translations_header
POST_BUILD
- COMMAND generate_translations_header ${qm_files}
+ COMMAND ./generate_translations_header ${qm_files}
WORKING_DIRECTORY "${CMAKE_CURRENT_BIN_DIR}"
COMMENT "Generating embedded translations header")
diff --git a/utils/build_scripts/android32.Dockerfile b/utils/build_scripts/android32.Dockerfile
index e56fade50..2738d8d57 100644
--- a/utils/build_scripts/android32.Dockerfile
+++ b/utils/build_scripts/android32.Dockerfile
@@ -2,8 +2,6 @@ FROM debian:stable
RUN apt-get update && apt-get install -y unzip automake build-essential curl file pkg-config git python libtool
-ARG NPROC=1
-
WORKDIR /opt/android
## INSTALL ANDROID SDK
ENV ANDROID_SDK_REVISION 4333796
@@ -24,6 +22,7 @@ RUN curl -s -O https://dl.google.com/android/repository/android-ndk-r${ANDROID_N
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 \
@@ -50,11 +49,13 @@ RUN set -ex \
&& tar -xvf boost_${BOOST_VERSION}.tar.bz2 \
&& rm -f boost_${BOOST_VERSION}.tar.bz2 \
&& cd boost_${BOOST_VERSION} \
- && ./bootstrap.sh
+ && ./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
@@ -63,12 +64,12 @@ RUN curl -s -O http://ftp.gnu.org/pub/gnu/libiconv/libiconv-${ICONV_VERSION}.tar
&& 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=${WORKDIR}/libiconv --disable-rpath \
+ && 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=android32 --stagedir=android32 toolset=clang threading=multi threadapi=pthread target-os=android -sICONV_PATH=${WORKDIR}/libiconv stage -j${NPROC}
+ && ./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
@@ -97,8 +98,9 @@ RUN curl -s -O https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz
no-asm \
no-shared --static \
--with-zlib-include=${WORKDIR}/zlib/include --with-zlib-lib=${WORKDIR}/zlib/lib \
+ --prefix=${PREFIX} --openssldir=${PREFIX} \
&& make -j${NPROC} \
- && cd .. && mv openssl-${OPENSSL_VERSION} openssl
+ && make install
# ZMQ
ARG ZMQ_VERSION=v4.2.5
@@ -107,7 +109,7 @@ 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=${PWD}/prebuilt --host=arm-linux-androideabi --enable-static --disable-shared \
+ && CC=clang CXX=clang++ ./configure --prefix=${PREFIX} --host=arm-linux-androideabi --enable-static --disable-shared \
&& make -j${NPROC} \
&& make install
@@ -116,14 +118,24 @@ ARG CPPZMQ_VERSION=v4.2.3
ARG CPPZMQ_HASH=6aa3ab686e916cb0e62df7fa7d12e0b13ae9fae6
RUN git clone https://github.com/zeromq/cppzmq.git -b ${CPPZMQ_VERSION} \
&& cd cppzmq \
- && test `git rev-parse HEAD` = ${CPPZMQ_HASH} || exit 1
+ && test `git rev-parse HEAD` = ${CPPZMQ_HASH} || exit 1 \
+ && cp *.hpp ${PREFIX}/include
+
+# 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 \
- && BOOST_ROOT=${WORKDIR}/boost_${BOOST_VERSION} BOOST_LIBRARYDIR=${WORKDIR}/boost_${BOOST_VERSION}/android32/lib/ \
- OPENSSL_ROOT_DIR=${WORKDIR}/openssl/ \
- CMAKE_INCLUDE_PATH="${WORKDIR}/cppzmq:${WORKDIR}/libzmq/prebuilt/include" \
- CMAKE_LIBRARY_PATH=${WORKDIR}/libzmq/prebuilt/lib \
- ANDROID_STANDALONE_TOOLCHAIN_PATH=${TOOLCHAIN_DIR} \
- CXXFLAGS="-I ${WORKDIR}/libzmq/prebuilt/include/" \
- PATH=${HOST_PATH} make release-static-android -j${NPROC}
+ && CMAKE_INCLUDE_PATH="${PREFIX}/include" \
+ CMAKE_LIBRARY_PATH="${PREFIX}/lib" \
+ ANDROID_STANDALONE_TOOLCHAIN_PATH=${TOOLCHAIN_DIR} \
+ PATH=${HOST_PATH} make release-static-android -j${NPROC}