mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-25 02:33:24 -03:00
Merge #17165: Remove BIP70 support
8c6081a884
compat: remove bswap_* check on macOS (fanquake)2cba35ab38
build: skip building OpenSSL lib_ssl (fanquake)45a2d3c552
build: remove OpenSSL from Qt build (fanquake)befbc40eb5
build: remove EVP_MD_CTX_new detection (fanquake)fcee10c2d0
build: remove SSL lib detection (fanquake)c7f30dbca8
gui: Update BIP70 support message (fanquake)a3e810326d
build: remove BIP70 entries from macOS Info.plist (fanquake)72fe13a58d
gui: remove payment request file handling from OpenURI dialog (fanquake)3548e4aac7
Remove BIP70 Support (fanquake)1cb9a4e28c
docs: remove protobuf from docs (fanquake)67328bb7ca
build: remove protobuf from depends (fanquake) Pull request description: This removes [BIP70](https://github.com/bitcoin/bips/blob/master/bip-0070.mediawiki) support. It also removes OpenSSL linking from Qt and building OpenSSLs `lib_ssl` in depends, as well as SSL lib detection from the build system. It's something that I'd optimistically like to do for `0.20.0`. ACKs for top commit: laanwj: Code review ACK8c6081a884
MarcoFalke: ACK8c6081a884
fjahr: ACK8c6081a
Tree-SHA512: 9dd9153afa4eca1a795f983e5b31f5fee9fa9a064c2a95d2f98810689add3ad0bf221c4608282299e66e4d1ec31cd556d4b16eea55de7912c3b9931f64735883
This commit is contained in:
commit
d91af4768c
48 changed files with 38 additions and 2114 deletions
|
@ -104,7 +104,7 @@ jobs:
|
|||
FILE_ENV="./ci/test/00_setup_env_win64.sh"
|
||||
|
||||
- stage: test
|
||||
name: '32-bit + dash [GOAL: install] [GUI: BIP70 enabled]'
|
||||
name: '32-bit + dash [GOAL: install] [gui]'
|
||||
env: >-
|
||||
FILE_ENV="./ci/test/00_setup_env_i686.sh"
|
||||
|
||||
|
@ -145,7 +145,7 @@ jobs:
|
|||
FILE_ENV="./ci/test/00_setup_env_mac.sh"
|
||||
|
||||
- stage: test
|
||||
name: 'macOS 10.14 native [GOAL: install] [GUI: BIP70 enabled] [no depends]'
|
||||
name: 'macOS 10.14 native [GOAL: install] [GUI] [no depends]'
|
||||
os: osx
|
||||
# Use the most recent version:
|
||||
# Xcode 11, macOS 10.14, JDK 12.0.1
|
||||
|
|
|
@ -98,10 +98,6 @@
|
|||
*/
|
||||
#define HAVE_DECL_DAEMON 0
|
||||
|
||||
/* Define to 1 if you have the declaration of `EVP_MD_CTX_new', and to 0 if
|
||||
you don't. */
|
||||
//#define HAVE_DECL_EVP_MD_CTX_NEW 1
|
||||
|
||||
/* Define to 1 if you have the declaration of `htobe16', and to 0 if you
|
||||
don't. */
|
||||
#define HAVE_DECL_HTOBE16 0
|
||||
|
|
|
@ -7,8 +7,7 @@
|
|||
export LC_ALL=C.UTF-8
|
||||
|
||||
export HOST=i686-pc-linux-gnu
|
||||
export DEP_OPTS="PROTOBUF=1"
|
||||
export PACKAGES="g++-multilib python3-zmq"
|
||||
export GOAL="install"
|
||||
export BITCOIN_CONFIG="--enable-zmq --with-gui=qt5 --enable-bip70 --enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++"
|
||||
export BITCOIN_CONFIG="--enable-zmq --with-gui=qt5 --enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++"
|
||||
export CONFIG_SHELL="/bin/dash"
|
||||
|
|
|
@ -7,13 +7,13 @@
|
|||
export LC_ALL=C.UTF-8
|
||||
|
||||
export HOST=x86_64-apple-darwin14
|
||||
export BREW_PACKAGES="automake berkeley-db4 libtool boost miniupnpc pkg-config protobuf qt qrencode python3 ccache zeromq"
|
||||
export BREW_PACKAGES="automake berkeley-db4 libtool boost miniupnpc pkg-config qt qrencode python3 ccache zeromq"
|
||||
export PIP_PACKAGES="zmq"
|
||||
export RUN_CI_ON_HOST=true
|
||||
export RUN_UNIT_TESTS=true
|
||||
export RUN_FUNCTIONAL_TESTS=false
|
||||
export GOAL="install"
|
||||
export BITCOIN_CONFIG="--enable-gui --enable-bip70 --enable-reduce-exports --enable-werror"
|
||||
export BITCOIN_CONFIG="--enable-gui --enable-reduce-exports --enable-werror"
|
||||
# Run without depends
|
||||
export NO_DEPENDS=1
|
||||
export OSX_SDK=""
|
||||
|
|
51
configure.ac
51
configure.ac
|
@ -226,13 +226,16 @@ AC_ARG_ENABLE([zmq],
|
|||
[disable ZMQ notifications])],
|
||||
[use_zmq=$enableval],
|
||||
[use_zmq=yes])
|
||||
|
||||
AC_ARG_ENABLE([bip70],
|
||||
[AS_HELP_STRING([--enable-bip70],
|
||||
[enable BIP70 (payment protocol) support in the GUI (default is to disable)])],
|
||||
[BIP70 (payment protocol) support in the GUI (no longer supported)])],
|
||||
[enable_bip70=$enableval],
|
||||
[enable_bip70=no])
|
||||
|
||||
AC_ARG_WITH([protoc-bindir],[AS_HELP_STRING([--with-protoc-bindir=BIN_DIR],[specify protoc bin path])], [protoc_bin_path=$withval], [])
|
||||
if test x$enable_bip70 != xno; then
|
||||
AC_MSG_ERROR([BIP70 is no longer supported!])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(man,
|
||||
[AS_HELP_STRING([--disable-man],
|
||||
|
@ -1237,11 +1240,7 @@ if test x$use_pkgconfig = xyes; then
|
|||
m4_ifdef(
|
||||
[PKG_CHECK_MODULES],
|
||||
[
|
||||
PKG_CHECK_MODULES([SSL], [libssl],, [AC_MSG_ERROR(openssl not found.)])
|
||||
PKG_CHECK_MODULES([CRYPTO], [libcrypto],,[AC_MSG_ERROR(libcrypto not found.)])
|
||||
if test x$enable_bip70 != xno; then
|
||||
BITCOIN_QT_CHECK([PKG_CHECK_MODULES([PROTOBUF], [protobuf], [have_protobuf=yes], [have_protobuf=no])])
|
||||
fi
|
||||
if test x$use_qr != xno; then
|
||||
BITCOIN_QT_CHECK([PKG_CHECK_MODULES([QR], [libqrencode], [have_qrencode=yes], [have_qrencode=no])])
|
||||
fi
|
||||
|
@ -1267,9 +1266,6 @@ else
|
|||
AC_CHECK_HEADER([openssl/crypto.h],,AC_MSG_ERROR(libcrypto headers missing))
|
||||
AC_CHECK_LIB([crypto], [main],CRYPTO_LIBS=-lcrypto, AC_MSG_ERROR(libcrypto missing))
|
||||
|
||||
AC_CHECK_HEADER([openssl/ssl.h],, AC_MSG_ERROR(libssl headers missing),)
|
||||
AC_CHECK_LIB([ssl], [main],SSL_LIBS=-lssl, AC_MSG_ERROR(libssl missing))
|
||||
|
||||
if test x$build_bitcoin_cli$build_bitcoind$bitcoin_enable_qt$use_tests != xnononono; then
|
||||
AC_CHECK_HEADER([event2/event.h],, AC_MSG_ERROR(libevent headers missing),)
|
||||
AC_CHECK_LIB([event],[main],EVENT_LIBS=-levent,AC_MSG_ERROR(libevent missing))
|
||||
|
@ -1301,22 +1297,12 @@ else
|
|||
esac
|
||||
fi
|
||||
|
||||
if test x$enable_bip70 != xno; then
|
||||
BITCOIN_QT_CHECK(AC_CHECK_LIB([protobuf] ,[main],[PROTOBUF_LIBS=-lprotobuf], [have_protobuf=no]))
|
||||
fi
|
||||
if test x$use_qr != xno; then
|
||||
BITCOIN_QT_CHECK([AC_CHECK_LIB([qrencode], [main],[QR_LIBS=-lqrencode], [have_qrencode=no])])
|
||||
BITCOIN_QT_CHECK([AC_CHECK_HEADER([qrencode.h],, have_qrencode=no)])
|
||||
fi
|
||||
fi
|
||||
|
||||
save_CXXFLAGS="${CXXFLAGS}"
|
||||
CXXFLAGS="${CXXFLAGS} ${CRYPTO_CFLAGS} ${SSL_CFLAGS}"
|
||||
AC_CHECK_DECLS([EVP_MD_CTX_new],,,[AC_INCLUDES_DEFAULT
|
||||
#include <openssl/x509_vfy.h>
|
||||
])
|
||||
CXXFLAGS="${save_CXXFLAGS}"
|
||||
|
||||
dnl RapidCheck property-based testing
|
||||
|
||||
enable_property_tests=no
|
||||
|
@ -1381,12 +1367,6 @@ AM_CONDITIONAL([EMBEDDED_UNIVALUE],[test x$need_bundled_univalue = xyes])
|
|||
AC_SUBST(UNIVALUE_CFLAGS)
|
||||
AC_SUBST(UNIVALUE_LIBS)
|
||||
|
||||
|
||||
if test x$have_protobuf != xno &&
|
||||
test x$enable_bip70 != xno; then
|
||||
BITCOIN_QT_PATH_PROGS([PROTOC], [protoc],$protoc_bin_path)
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([whether to build bitcoind])
|
||||
AM_CONDITIONAL([BUILD_BITCOIND], [test x$build_bitcoind = xyes])
|
||||
AC_MSG_RESULT($build_bitcoind)
|
||||
|
@ -1508,23 +1488,6 @@ if test x$bitcoin_enable_qt != xno; then
|
|||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([whether to build BIP70 support])
|
||||
if test x$have_protobuf = xno; then
|
||||
if test x$enable_bip70 = xyes; then
|
||||
AC_MSG_ERROR(protobuf missing)
|
||||
fi
|
||||
enable_bip70=no
|
||||
AC_MSG_RESULT(no)
|
||||
else
|
||||
if test x$enable_bip70 != xno; then
|
||||
AC_DEFINE([ENABLE_BIP70],[1],[Define if BIP70 support should be compiled in])
|
||||
enable_bip70=yes
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL([ENABLE_ZMQ], [test "x$use_zmq" = "xyes"])
|
||||
|
@ -1557,7 +1520,6 @@ AM_CONDITIONAL([ENABLE_TESTS],[test x$BUILD_TEST = xyes])
|
|||
AM_CONDITIONAL([ENABLE_FUZZ],[test x$enable_fuzz = xyes])
|
||||
AM_CONDITIONAL([ENABLE_QT],[test x$bitcoin_enable_qt = xyes])
|
||||
AM_CONDITIONAL([ENABLE_QT_TESTS],[test x$BUILD_TEST_QT = xyes])
|
||||
AM_CONDITIONAL([ENABLE_BIP70],[test x$enable_bip70 = xyes])
|
||||
AM_CONDITIONAL([ENABLE_BENCH],[test x$use_bench = xyes])
|
||||
AM_CONDITIONAL([USE_QRCODE], [test x$use_qr = xyes])
|
||||
AM_CONDITIONAL([USE_LCOV],[test x$use_lcov = xyes])
|
||||
|
@ -1623,11 +1585,9 @@ AC_SUBST(LEVELDB_TARGET_FLAGS)
|
|||
AC_SUBST(MINIUPNPC_CPPFLAGS)
|
||||
AC_SUBST(MINIUPNPC_LIBS)
|
||||
AC_SUBST(CRYPTO_LIBS)
|
||||
AC_SUBST(SSL_LIBS)
|
||||
AC_SUBST(EVENT_LIBS)
|
||||
AC_SUBST(EVENT_PTHREADS_LIBS)
|
||||
AC_SUBST(ZMQ_LIBS)
|
||||
AC_SUBST(PROTOBUF_LIBS)
|
||||
AC_SUBST(QR_LIBS)
|
||||
AC_CONFIG_FILES([Makefile src/Makefile doc/man/Makefile share/setup.nsi share/qt/Info.plist test/config.ini])
|
||||
AC_CONFIG_FILES([contrib/devtools/split-debug.sh],[chmod +x contrib/devtools/split-debug.sh])
|
||||
|
@ -1682,7 +1642,6 @@ echo "Options used to compile and link:"
|
|||
echo " with wallet = $enable_wallet"
|
||||
echo " with gui / qt = $bitcoin_enable_qt"
|
||||
if test x$bitcoin_enable_qt != xno; then
|
||||
echo " with bip70 = $enable_bip70"
|
||||
echo " with qr = $use_qr"
|
||||
fi
|
||||
echo " with zmq = $use_zmq"
|
||||
|
|
|
@ -15,7 +15,7 @@ _bitcoind() {
|
|||
_get_comp_words_by_ref -n = cur prev words cword
|
||||
|
||||
case "$cur" in
|
||||
-conf=*|-pid=*|-loadblock=*|-rootcertificates=*|-rpccookiefile=*|-wallet=*)
|
||||
-conf=*|-pid=*|-loadblock=*|-rpccookiefile=*|-wallet=*)
|
||||
cur="${cur#*=}"
|
||||
_filedir
|
||||
return 0
|
||||
|
|
|
@ -9,7 +9,6 @@ WORK_PATH = $(BASEDIR)/work
|
|||
BASE_CACHE ?= $(BASEDIR)/built
|
||||
SDK_PATH ?= $(BASEDIR)/SDKs
|
||||
NO_QT ?=
|
||||
PROTOBUF ?=
|
||||
RAPIDCHECK ?=
|
||||
NO_WALLET ?=
|
||||
NO_ZMQ ?=
|
||||
|
@ -101,17 +100,11 @@ wallet_packages_$(NO_WALLET) = $(wallet_packages)
|
|||
upnp_packages_$(NO_UPNP) = $(upnp_packages)
|
||||
zmq_packages_$(NO_ZMQ) = $(zmq_packages)
|
||||
|
||||
protobuf_packages_$(PROTOBUF) = $(protobuf_packages)
|
||||
rapidcheck_packages_$(RAPIDCHECK) = $(rapidcheck_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)
|
||||
|
||||
ifeq ($(protobuf_packages_),)
|
||||
native_packages += $(protobuf_native_packages)
|
||||
packages += $(protobuf_packages)
|
||||
endif
|
||||
|
||||
ifneq ($(zmq_packages_),)
|
||||
packages += $(zmq_packages)
|
||||
endif
|
||||
|
@ -157,7 +150,6 @@ $(host_prefix)/share/config.site : config.site.in $(host_prefix)/.stamp_$(final_
|
|||
-e 's|@allow_host_packages@|$(ALLOW_HOST_PACKAGES)|' \
|
||||
-e 's|@no_qt@|$(NO_QT)|' \
|
||||
-e 's|@no_zmq@|$(NO_ZMQ)|' \
|
||||
-e 's|@enable_bip70@|$(PROTOBUF)|' \
|
||||
-e 's|@no_wallet@|$(NO_WALLET)|' \
|
||||
-e 's|@no_upnp@|$(NO_UPNP)|' \
|
||||
-e 's|@debug@|$(DEBUG)|' \
|
||||
|
|
|
@ -77,7 +77,6 @@ The following can be set when running make: make FOO=bar
|
|||
NO_UPNP: Don't download/build/cache packages needed for enabling upnp
|
||||
DEBUG: disable some optimizations and enable more runtime checking
|
||||
RAPIDCHECK: build rapidcheck (experimental, requires cmake)
|
||||
PROTOBUF: build protobuf (used for deprecated BIP70 support)
|
||||
HOST_ID_SALT: Optional salt to use when generating host package ids
|
||||
BUILD_ID_SALT: Optional salt to use when generating build package ids
|
||||
|
||||
|
|
|
@ -16,10 +16,6 @@ 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
|
||||
|
@ -37,10 +33,6 @@ if test -z $enable_zmq && test -n "@no_zmq@"; then
|
|||
enable_zmq=no
|
||||
fi
|
||||
|
||||
if test -n $enable_bip70 && test -n "@enable_bip70@"; then
|
||||
enable_bip70=yes
|
||||
fi
|
||||
|
||||
if test x@host_os@ = xdarwin; then
|
||||
BREW=no
|
||||
PORT=no
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
package=native_protobuf
|
||||
$(package)_version=2.6.1
|
||||
$(package)_download_path=https://github.com/google/protobuf/releases/download/v$($(package)_version)
|
||||
$(package)_file_name=protobuf-$($(package)_version).tar.bz2
|
||||
$(package)_sha256_hash=ee445612d544d885ae240ffbcbf9267faa9f593b7b101f21d58beceb92661910
|
||||
|
||||
define $(package)_set_vars
|
||||
$(package)_config_opts=--disable-shared --without-zlib
|
||||
endef
|
||||
|
||||
define $(package)_config_cmds
|
||||
$($(package)_autoconf)
|
||||
endef
|
||||
|
||||
define $(package)_build_cmds
|
||||
$(MAKE) -C src protoc
|
||||
endef
|
||||
|
||||
define $(package)_stage_cmds
|
||||
$(MAKE) -C src DESTDIR=$($(package)_staging_dir) install-strip
|
||||
endef
|
||||
|
||||
define $(package)_postprocess_cmds
|
||||
rm -rf lib include
|
||||
endef
|
|
@ -71,7 +71,7 @@ define $(package)_config_cmds
|
|||
endef
|
||||
|
||||
define $(package)_build_cmds
|
||||
$(MAKE) -j1 build_libs libcrypto.pc libssl.pc openssl.pc
|
||||
$(MAKE) -j1 build_crypto libcrypto.pc libssl.pc openssl.pc
|
||||
endef
|
||||
|
||||
define $(package)_stage_cmds
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
packages:=boost openssl libevent
|
||||
|
||||
protobuf_native_packages = native_protobuf
|
||||
protobuf_packages = protobuf
|
||||
|
||||
qt_packages = qrencode zlib
|
||||
|
||||
qt_linux_packages:=qt expat libxcb xcb_proto libXau xproto freetype fontconfig
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
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 --disable-dependency-tracking
|
||||
$(package)_config_opts_linux=--with-pic
|
||||
endef
|
||||
|
||||
define $(package)_preprocess_cmds
|
||||
cp -f $(BASEDIR)/config.guess $(BASEDIR)/config.sub . &&\
|
||||
cp -f $(BASEDIR)/config.guess $(BASEDIR)/config.sub gtest/build-aux
|
||||
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 lib/*.la
|
||||
endef
|
|
@ -4,7 +4,7 @@ $(package)_download_path=https://download.qt.io/official_releases/qt/5.9/$($(pac
|
|||
$(package)_suffix=opensource-src-$($(package)_version).tar.xz
|
||||
$(package)_file_name=qtbase-$($(package)_suffix)
|
||||
$(package)_sha256_hash=9b9dec1f67df1f94bce2955c5604de992d529dde72050239154c56352da0907d
|
||||
$(package)_dependencies=openssl zlib
|
||||
$(package)_dependencies=zlib
|
||||
$(package)_linux_dependencies=freetype fontconfig libxcb
|
||||
$(package)_build_subdir=qtbase
|
||||
$(package)_qt_libs=corelib network widgets gui plugins testlib
|
||||
|
@ -42,9 +42,11 @@ $(package)_config_opts += -no-linuxfb
|
|||
$(package)_config_opts += -no-libjpeg
|
||||
$(package)_config_opts += -no-libudev
|
||||
$(package)_config_opts += -no-mtdev
|
||||
$(package)_config_opts += -no-openssl
|
||||
$(package)_config_opts += -no-openvg
|
||||
$(package)_config_opts += -no-reduce-relocations
|
||||
$(package)_config_opts += -no-qml-debug
|
||||
$(package)_config_opts += -no-securetransport
|
||||
$(package)_config_opts += -no-sql-db2
|
||||
$(package)_config_opts += -no-sql-ibase
|
||||
$(package)_config_opts += -no-sql-oci
|
||||
|
@ -59,7 +61,6 @@ $(package)_config_opts += -no-xinput2
|
|||
$(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
|
||||
|
|
|
@ -44,7 +44,6 @@ Optional dependencies:
|
|||
miniupnpc | UPnP Support | Firewall-jumping support
|
||||
libdb4.8 | Berkeley DB | Wallet storage (only needed when wallet enabled)
|
||||
qt | GUI | GUI toolkit (only needed when GUI enabled)
|
||||
protobuf | Payments in GUI | Data interchange format used for payment protocol (only needed when BIP70 enabled)
|
||||
libqrencode | QR codes in GUI | Optional for generating QR codes (only needed when GUI enabled)
|
||||
univalue | Utility | JSON parsing and encoding (bundled version will be used unless --with-system-univalue passed to configure)
|
||||
libzmq3 | ZMQ notification | Optional, allows generating ZMQ notifications (requires ZMQ version >= 4.0.0)
|
||||
|
@ -118,10 +117,6 @@ libqrencode (optional) can be installed with:
|
|||
|
||||
sudo apt-get install libqrencode-dev
|
||||
|
||||
protobuf (optional) can be installed with:
|
||||
|
||||
sudo apt-get install libprotobuf-dev protobuf-compiler
|
||||
|
||||
Once these are installed, they will be found by configure and a bitcoin-qt executable will be
|
||||
built by default.
|
||||
|
||||
|
@ -150,10 +145,6 @@ libqrencode (optional) can be installed with:
|
|||
|
||||
sudo dnf install qrencode-devel
|
||||
|
||||
protobuf (optional) can be installed with:
|
||||
|
||||
sudo dnf install protobuf-devel
|
||||
|
||||
Notes
|
||||
-----
|
||||
The release is built with GCC and then "strip bitcoind" to strip the debug
|
||||
|
|
|
@ -62,8 +62,7 @@ First, install the general dependencies:
|
|||
sudo apt install build-essential libtool autotools-dev automake pkg-config bsdmainutils curl git
|
||||
|
||||
A host toolchain (`build-essential`) is necessary because some dependency
|
||||
packages (such as `protobuf`) need to build host utilities that are used in the
|
||||
build process.
|
||||
packages need to build host utilities that are used in the build process.
|
||||
|
||||
See [dependencies.md](dependencies.md) for a complete overview.
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@ These are the dependencies currently used by Bitcoin Core. You can find instruct
|
|||
| MiniUPnPc | [2.0.20180203](http://miniupnp.free.fr/files) | | No | | |
|
||||
| OpenSSL | [1.0.1k](https://www.openssl.org/source) | | Yes | | |
|
||||
| PCRE | | | | | [Yes](https://github.com/bitcoin/bitcoin/blob/master/depends/packages/qt.mk) |
|
||||
| protobuf | [2.6.1](https://github.com/google/protobuf/releases) | | No | | |
|
||||
| Python (tests) | | [3.5](https://www.python.org/downloads) | | | |
|
||||
| qrencode | [3.4.4](https://fukuchi.org/works/qrencode) | | No | | |
|
||||
| Qt | [5.9.7](https://download.qt.io/official_releases/qt/) | [5.5.1](https://github.com/bitcoin/bitcoin/issues/13478) | No | | |
|
||||
|
@ -35,7 +34,6 @@ Some dependencies are not needed in all configurations. The following are some f
|
|||
#### Options passed to `./configure`
|
||||
* MiniUPnPc is not needed with `--with-miniupnpc=no`.
|
||||
* Berkeley DB is not needed with `--disable-wallet`.
|
||||
* protobuf is only needed with `--enable-bip70`.
|
||||
* Qt is not needed with `--without-gui`.
|
||||
* If the qrencode dependency is absent, QR support won't be added. To force an error when that happens, pass `--with-qrencode`.
|
||||
* ZeroMQ is needed only with the `--with-zmq` option.
|
||||
|
|
|
@ -54,43 +54,6 @@
|
|||
</dict>
|
||||
</array>
|
||||
|
||||
<key>UTExportedTypeDeclarations</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>UTTypeIdentifier</key>
|
||||
<string>org.bitcoin.paymentrequest</string>
|
||||
<key>UTTypeDescription</key>
|
||||
<string>Bitcoin payment request</string>
|
||||
<key>UTTypeConformsTo</key>
|
||||
<array>
|
||||
<string>public.data</string>
|
||||
</array>
|
||||
<key>UTTypeTagSpecification</key>
|
||||
<dict>
|
||||
<key>public.mime-type</key>
|
||||
<string>application/x-bitcoin-payment-request</string>
|
||||
<key>public.filename-extension</key>
|
||||
<array>
|
||||
<string>bitcoinpaymentrequest</string>
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
</array>
|
||||
|
||||
<key>CFBundleDocumentTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>LSItemContentTypes</key>
|
||||
<array>
|
||||
<string>org.bitcoin.paymentrequest</string>
|
||||
</array>
|
||||
<key>LSHandlerRank</key>
|
||||
<string>Owner</string>
|
||||
</dict>
|
||||
</array>
|
||||
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ else
|
|||
LIBUNIVALUE = $(UNIVALUE_LIBS)
|
||||
endif
|
||||
|
||||
BITCOIN_INCLUDES=-I$(builddir) $(BDB_CPPFLAGS) $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) $(CRYPTO_CFLAGS) $(SSL_CFLAGS)
|
||||
BITCOIN_INCLUDES=-I$(builddir) $(BDB_CPPFLAGS) $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) $(CRYPTO_CFLAGS)
|
||||
|
||||
BITCOIN_INCLUDES += -I$(srcdir)/secp256k1/include
|
||||
BITCOIN_INCLUDES += $(UNIVALUE_CFLAGS)
|
||||
|
@ -701,12 +701,6 @@ if HARDEN
|
|||
$(AM_V_at) READELF=$(READELF) OBJDUMP=$(OBJDUMP) $(PYTHON) $(top_srcdir)/contrib/devtools/security-check.py < $(bin_PROGRAMS)
|
||||
endif
|
||||
|
||||
if ENABLE_BIP70
|
||||
%.pb.cc %.pb.h: %.proto
|
||||
@test -f $(PROTOC)
|
||||
$(AM_V_GEN) $(PROTOC) --cpp_out=$(@D) --proto_path=$(<D) $<
|
||||
endif
|
||||
|
||||
if EMBEDDED_LEVELDB
|
||||
include Makefile.leveldb.include
|
||||
endif
|
||||
|
|
|
@ -95,16 +95,6 @@ QT_QRC = qt/bitcoin.qrc
|
|||
QT_QRC_LOCALE_CPP = qt/qrc_bitcoin_locale.cpp
|
||||
QT_QRC_LOCALE = qt/bitcoin_locale.qrc
|
||||
|
||||
if ENABLE_BIP70
|
||||
PROTOBUF_CC = qt/paymentrequest.pb.cc
|
||||
PROTOBUF_H = qt/paymentrequest.pb.h
|
||||
PROTOBUF_PROTO = qt/paymentrequest.proto
|
||||
else
|
||||
PROTOBUF_CC =
|
||||
PROTOBUF_H =
|
||||
PROTOBUF_PROTO =
|
||||
endif
|
||||
|
||||
BITCOIN_QT_H = \
|
||||
qt/addressbookpage.h \
|
||||
qt/addresstablemodel.h \
|
||||
|
@ -134,7 +124,6 @@ BITCOIN_QT_H = \
|
|||
qt/optionsdialog.h \
|
||||
qt/optionsmodel.h \
|
||||
qt/overviewpage.h \
|
||||
qt/paymentrequestplus.h \
|
||||
qt/paymentserver.h \
|
||||
qt/peertablemodel.h \
|
||||
qt/platformstyle.h \
|
||||
|
@ -269,18 +258,12 @@ BITCOIN_QT_WALLET_CPP = \
|
|||
qt/walletmodeltransaction.cpp \
|
||||
qt/walletview.cpp
|
||||
|
||||
BITCOIN_QT_WALLET_BIP70_CPP = \
|
||||
qt/paymentrequestplus.cpp
|
||||
|
||||
BITCOIN_QT_CPP = $(BITCOIN_QT_BASE_CPP)
|
||||
if TARGET_WINDOWS
|
||||
BITCOIN_QT_CPP += $(BITCOIN_QT_WINDOWS_CPP)
|
||||
endif
|
||||
if ENABLE_WALLET
|
||||
BITCOIN_QT_CPP += $(BITCOIN_QT_WALLET_CPP)
|
||||
if ENABLE_BIP70
|
||||
BITCOIN_QT_CPP += $(BITCOIN_QT_WALLET_BIP70_CPP)
|
||||
endif # ENABLE_BIP70
|
||||
endif # ENABLE_WALLET
|
||||
|
||||
RES_IMAGES =
|
||||
|
@ -292,18 +275,17 @@ BITCOIN_RC = qt/res/bitcoin-qt-res.rc
|
|||
BITCOIN_QT_INCLUDES = -DQT_NO_KEYWORDS
|
||||
|
||||
qt_libbitcoinqt_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDES) \
|
||||
$(QT_INCLUDES) $(QT_DBUS_INCLUDES) $(PROTOBUF_CFLAGS) $(QR_CFLAGS)
|
||||
$(QT_INCLUDES) $(QT_DBUS_INCLUDES) $(QR_CFLAGS)
|
||||
qt_libbitcoinqt_a_CXXFLAGS = $(AM_CXXFLAGS) $(QT_PIE_FLAGS)
|
||||
qt_libbitcoinqt_a_OBJCXXFLAGS = $(AM_OBJCXXFLAGS) $(QT_PIE_FLAGS)
|
||||
|
||||
qt_libbitcoinqt_a_SOURCES = $(BITCOIN_QT_CPP) $(BITCOIN_QT_H) $(QT_FORMS_UI) \
|
||||
$(QT_QRC) $(QT_QRC_LOCALE) $(QT_TS) $(PROTOBUF_PROTO) $(RES_ICONS) $(RES_IMAGES) $(RES_MOVIES)
|
||||
$(QT_QRC) $(QT_QRC_LOCALE) $(QT_TS) $(RES_ICONS) $(RES_IMAGES) $(RES_MOVIES)
|
||||
if TARGET_DARWIN
|
||||
qt_libbitcoinqt_a_SOURCES += $(BITCOIN_MM)
|
||||
endif
|
||||
|
||||
nodist_qt_libbitcoinqt_a_SOURCES = $(QT_MOC_CPP) $(QT_MOC) $(PROTOBUF_CC) \
|
||||
$(PROTOBUF_H) $(QT_QRC_CPP) $(QT_QRC_LOCALE_CPP)
|
||||
nodist_qt_libbitcoinqt_a_SOURCES = $(QT_MOC_CPP) $(QT_MOC) $(QT_QRC_CPP) $(QT_QRC_LOCALE_CPP)
|
||||
|
||||
# forms/foo.h -> forms/ui_foo.h
|
||||
QT_FORMS_H=$(join $(dir $(QT_FORMS_UI)),$(addprefix ui_, $(notdir $(QT_FORMS_UI:.ui=.h))))
|
||||
|
@ -313,14 +295,9 @@ QT_FORMS_H=$(join $(dir $(QT_FORMS_UI)),$(addprefix ui_, $(notdir $(QT_FORMS_UI:
|
|||
$(QT_MOC): $(QT_FORMS_H)
|
||||
$(qt_libbitcoinqt_a_OBJECTS) $(qt_bitcoin_qt_OBJECTS) : | $(QT_MOC)
|
||||
|
||||
#Generating these with a half-written protobuf header leads to wacky results.
|
||||
#This makes sure it's done.
|
||||
$(QT_MOC): $(PROTOBUF_H)
|
||||
$(QT_MOC_CPP): $(PROTOBUF_H)
|
||||
|
||||
# bitcoin-qt binary #
|
||||
qt_bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDES) \
|
||||
$(QT_INCLUDES) $(PROTOBUF_CFLAGS) $(QR_CFLAGS)
|
||||
$(QT_INCLUDES) $(QR_CFLAGS)
|
||||
qt_bitcoin_qt_CXXFLAGS = $(AM_CXXFLAGS) $(QT_PIE_FLAGS)
|
||||
|
||||
qt_bitcoin_qt_SOURCES = qt/main.cpp
|
||||
|
@ -335,15 +312,8 @@ if ENABLE_ZMQ
|
|||
qt_bitcoin_qt_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS)
|
||||
endif
|
||||
qt_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) \
|
||||
$(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \
|
||||
$(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \
|
||||
$(EVENT_PTHREADS_LIBS) $(EVENT_LIBS)
|
||||
if ENABLE_BIP70
|
||||
qt_bitcoin_qt_LDADD += $(SSL_LIBS)
|
||||
else
|
||||
if TARGET_WINDOWS
|
||||
qt_bitcoin_qt_LDADD += $(SSL_LIBS)
|
||||
endif
|
||||
endif
|
||||
qt_bitcoin_qt_LDADD += $(CRYPTO_LIBS)
|
||||
qt_bitcoin_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
|
||||
qt_bitcoin_qt_LIBTOOLFLAGS = $(AM_LIBTOOLFLAGS) --tag CXX
|
||||
|
@ -368,7 +338,7 @@ $(QT_QRC_LOCALE_CPP): $(QT_QRC_LOCALE) $(QT_QM)
|
|||
$(SED) -e '/^\*\*.*Created:/d' -e '/^\*\*.*by:/d' > $@
|
||||
@rm $(@D)/temp_$(<F)
|
||||
|
||||
$(QT_QRC_CPP): $(QT_QRC) $(QT_FORMS_H) $(RES_ICONS) $(RES_IMAGES) $(RES_MOVIES) $(PROTOBUF_H)
|
||||
$(QT_QRC_CPP): $(QT_QRC) $(QT_FORMS_H) $(RES_ICONS) $(RES_IMAGES) $(RES_MOVIES)
|
||||
@test -f $(RCC)
|
||||
$(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(RCC) -name bitcoin $< | \
|
||||
$(SED) -e '/^\*\*.*Created:/d' -e '/^\*\*.*by:/d' > $@
|
||||
|
|
|
@ -15,10 +15,6 @@ if ENABLE_WALLET
|
|||
TEST_QT_MOC_CPP += \
|
||||
qt/test/moc_addressbooktests.cpp \
|
||||
qt/test/moc_wallettests.cpp
|
||||
if ENABLE_BIP70
|
||||
TEST_QT_MOC_CPP += \
|
||||
qt/test/moc_paymentservertests.cpp
|
||||
endif # ENABLE_BIP70
|
||||
endif # ENABLE_WALLET
|
||||
|
||||
TEST_QT_H = \
|
||||
|
@ -28,8 +24,6 @@ TEST_QT_H = \
|
|||
qt/test/rpcnestedtests.h \
|
||||
qt/test/uritests.h \
|
||||
qt/test/util.h \
|
||||
qt/test/paymentrequestdata.h \
|
||||
qt/test/paymentservertests.h \
|
||||
qt/test/wallettests.h
|
||||
|
||||
TEST_BITCOIN_CPP = \
|
||||
|
@ -39,7 +33,7 @@ TEST_BITCOIN_H = \
|
|||
test/setup_common.h
|
||||
|
||||
qt_test_test_bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDES) \
|
||||
$(QT_INCLUDES) $(QT_TEST_INCLUDES) $(PROTOBUF_CFLAGS)
|
||||
$(QT_INCLUDES) $(QT_TEST_INCLUDES)
|
||||
|
||||
qt_test_test_bitcoin_qt_SOURCES = \
|
||||
qt/test/apptests.cpp \
|
||||
|
@ -56,10 +50,6 @@ qt_test_test_bitcoin_qt_SOURCES += \
|
|||
qt/test/addressbooktests.cpp \
|
||||
qt/test/wallettests.cpp \
|
||||
wallet/test/wallet_test_fixture.cpp
|
||||
if ENABLE_BIP70
|
||||
qt_test_test_bitcoin_qt_SOURCES += \
|
||||
qt/test/paymentservertests.cpp
|
||||
endif # ENABLE_BIP70
|
||||
endif # ENABLE_WALLET
|
||||
|
||||
nodist_qt_test_test_bitcoin_qt_SOURCES = $(TEST_QT_MOC_CPP)
|
||||
|
@ -73,7 +63,7 @@ qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS)
|
|||
endif
|
||||
qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) \
|
||||
$(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BOOST_LIBS) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) $(QT_LIBS) \
|
||||
$(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \
|
||||
$(QR_LIBS) $(BDB_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \
|
||||
$(EVENT_PTHREADS_LIBS) $(EVENT_LIBS)
|
||||
qt_test_test_bitcoin_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
|
||||
qt_test_test_bitcoin_qt_CXXFLAGS = $(AM_CXXFLAGS) $(QT_PIE_FLAGS)
|
||||
|
|
|
@ -17,20 +17,13 @@
|
|||
|
||||
#if defined(MAC_OSX)
|
||||
|
||||
#if !defined(bswap_16)
|
||||
|
||||
// Mac OS X / Darwin features; we include a check for bswap_16 because if it is already defined, protobuf has
|
||||
// defined these macros for us already; if it isn't, we do it ourselves. In either case, we get the exact same
|
||||
// result regardless which path was taken
|
||||
#include <libkern/OSByteOrder.h>
|
||||
#define bswap_16(x) OSSwapInt16(x)
|
||||
#define bswap_32(x) OSSwapInt32(x)
|
||||
#define bswap_64(x) OSSwapInt64(x)
|
||||
|
||||
#endif // !defined(bswap_16)
|
||||
|
||||
#else
|
||||
// Non-Mac OS X / non-Darwin
|
||||
// Non-MacOS / non-Darwin
|
||||
|
||||
#if HAVE_DECL_BSWAP_16 == 0
|
||||
inline uint16_t bswap_16(uint16_t x)
|
||||
|
|
|
@ -354,7 +354,7 @@ void SetupServerArgs()
|
|||
std::vector<std::string> hidden_args = {
|
||||
"-dbcrashratio", "-forcecompactdb",
|
||||
// GUI args. These will be overwritten by SetupUIArgs for the GUI
|
||||
"-allowselfsignedrootcertificates", "-choosedatadir", "-lang=<lang>", "-min", "-resetguisettings", "-rootcertificates=<file>", "-splash", "-uiplatform"};
|
||||
"-choosedatadir", "-lang=<lang>", "-min", "-resetguisettings", "-splash", "-uiplatform"};
|
||||
|
||||
gArgs.AddArg("-version", "Print version and exit", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
|
||||
#if HAVE_SYSTEM
|
||||
|
|
|
@ -50,7 +50,7 @@ Various dialogs, e.g. to open a URL. Inherit from [QDialog](https://doc.qt.io/qt
|
|||
|
||||
### paymentserver.(h/cpp)
|
||||
|
||||
Used to process BIP21 and BIP70 (see https://github.com/bitcoin/bitcoin/pull/11622) payment URI / requests. Also handles URI based application switching (e.g. when following a bitcoin:... link from a browser).
|
||||
Used to process BIP21 payment URI requests. Also handles URI based application switching (e.g. when following a bitcoin:... link from a browser).
|
||||
|
||||
### walletview.(h/cpp)
|
||||
|
||||
|
|
|
@ -337,10 +337,6 @@ void BitcoinApplication::initializeResult(bool success)
|
|||
window->setWalletController(m_wallet_controller);
|
||||
if (paymentServer) {
|
||||
paymentServer->setOptionsModel(optionsModel);
|
||||
#ifdef ENABLE_BIP70
|
||||
PaymentServer::LoadRootCAs();
|
||||
connect(m_wallet_controller, &WalletController::coinsSent, paymentServer, &PaymentServer::fetchPaymentACK);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_WALLET
|
||||
|
@ -396,14 +392,10 @@ WId BitcoinApplication::getMainWinId() const
|
|||
|
||||
static void SetupUIArgs()
|
||||
{
|
||||
#if defined(ENABLE_WALLET) && defined(ENABLE_BIP70)
|
||||
gArgs.AddArg("-allowselfsignedrootcertificates", strprintf("Allow self signed root certificates (default: %u)", DEFAULT_SELFSIGNED_ROOTCERTS), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::GUI);
|
||||
#endif
|
||||
gArgs.AddArg("-choosedatadir", strprintf("Choose data directory on startup (default: %u)", DEFAULT_CHOOSE_DATADIR), ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
|
||||
gArgs.AddArg("-lang=<lang>", "Set language, for example \"de_DE\" (default: system locale)", ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
|
||||
gArgs.AddArg("-min", "Start minimized", ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
|
||||
gArgs.AddArg("-resetguisettings", "Reset all settings changed in the GUI", ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
|
||||
gArgs.AddArg("-rootcertificates=<file>", "Set SSL root certificates for payment request (default: -system-)", ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
|
||||
gArgs.AddArg("-splash", strprintf("Show splash screen on startup (default: %u)", DEFAULT_SPLASHSCREEN), ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
|
||||
gArgs.AddArg("-uiplatform", strprintf("Select platform to customize UI for (one of windows, macosx, other; default: %s)", BitcoinGUI::DEFAULT_UIPLATFORM), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::GUI);
|
||||
}
|
||||
|
|
|
@ -330,7 +330,7 @@ void BitcoinGUI::createActions()
|
|||
usedReceivingAddressesAction->setStatusTip(tr("Show the list of used receiving addresses and labels"));
|
||||
|
||||
openAction = new QAction(tr("Open &URI..."), this);
|
||||
openAction->setStatusTip(tr("Open a bitcoin: URI or payment request"));
|
||||
openAction->setStatusTip(tr("Open a bitcoin: URI"));
|
||||
|
||||
m_open_wallet_action = new QAction(tr("Open Wallet"), this);
|
||||
m_open_wallet_action->setEnabled(false);
|
||||
|
|
|
@ -11,16 +11,9 @@
|
|||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Open URI</string>
|
||||
<string>Open bitcoin URI</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Open payment request from URI or file</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
|
@ -33,19 +26,6 @@
|
|||
<item>
|
||||
<widget class="QValidatedLineEdit" name="uriEdit"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="selectFileButton">
|
||||
<property name="toolTip">
|
||||
<string>Select payment request file</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">…</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
|
|
|
@ -39,12 +39,3 @@ void OpenURIDialog::accept()
|
|||
ui->uriEdit->setValid(false);
|
||||
}
|
||||
}
|
||||
|
||||
void OpenURIDialog::on_selectFileButton_clicked()
|
||||
{
|
||||
QString filename = GUIUtil::getOpenFileName(this, tr("Select payment request file to open"), "", "", nullptr);
|
||||
if(filename.isEmpty())
|
||||
return;
|
||||
QUrl fileUri = QUrl::fromLocalFile(filename);
|
||||
ui->uriEdit->setText("bitcoin:?r=" + QUrl::toPercentEncoding(fileUri.toString()));
|
||||
}
|
||||
|
|
|
@ -24,9 +24,6 @@ public:
|
|||
protected Q_SLOTS:
|
||||
void accept();
|
||||
|
||||
private Q_SLOTS:
|
||||
void on_selectFileButton_clicked();
|
||||
|
||||
private:
|
||||
Ui::OpenURIDialog *ui;
|
||||
};
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#include <netbase.h>
|
||||
#include <txdb.h> // for -dbcache defaults
|
||||
|
||||
#include <QNetworkProxy>
|
||||
#include <QDebug>
|
||||
#include <QSettings>
|
||||
#include <QStringList>
|
||||
|
||||
|
@ -483,24 +483,6 @@ void OptionsModel::setDisplayUnit(const QVariant &value)
|
|||
}
|
||||
}
|
||||
|
||||
bool OptionsModel::getProxySettings(QNetworkProxy& proxy) const
|
||||
{
|
||||
// Directly query current base proxy, because
|
||||
// GUI settings can be overridden with -proxy.
|
||||
proxyType curProxy;
|
||||
if (m_node.getProxy(NET_IPV4, curProxy)) {
|
||||
proxy.setType(QNetworkProxy::Socks5Proxy);
|
||||
proxy.setHostName(QString::fromStdString(curProxy.proxy.ToStringIP()));
|
||||
proxy.setPort(curProxy.proxy.GetPort());
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
proxy.setType(QNetworkProxy::NoProxy);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void OptionsModel::setRestartRequired(bool fRequired)
|
||||
{
|
||||
QSettings settings;
|
||||
|
|
|
@ -13,10 +13,6 @@ namespace interfaces {
|
|||
class Node;
|
||||
}
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QNetworkProxy;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
extern const char *DEFAULT_GUI_PROXY_HOST;
|
||||
static constexpr unsigned short DEFAULT_GUI_PROXY_PORT = 9050;
|
||||
|
||||
|
@ -73,7 +69,6 @@ public:
|
|||
bool getMinimizeOnClose() const { return fMinimizeOnClose; }
|
||||
int getDisplayUnit() const { return nDisplayUnit; }
|
||||
QString getThirdPartyTxUrls() const { return strThirdPartyTxUrls; }
|
||||
bool getProxySettings(QNetworkProxy& proxy) const;
|
||||
bool getCoinControlFeatures() const { return fCoinControlFeatures; }
|
||||
const QString& getOverriddenByCommandLine() { return strOverriddenByCommandLine; }
|
||||
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
//
|
||||
// Simple Bitcoin Payment Protocol messages
|
||||
//
|
||||
// Use fields 100+ for extensions;
|
||||
// to avoid conflicts, register extensions at:
|
||||
// https://en.bitcoin.it/wiki/Payment_Request
|
||||
//
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
package payments;
|
||||
option java_package = "org.bitcoin.protocols.payments";
|
||||
option java_outer_classname = "Protos";
|
||||
|
||||
// Generalized form of "send payment to this/these bitcoin addresses"
|
||||
message Output {
|
||||
optional uint64 amount = 1 [default = 0]; // amount is integer-number-of-satoshis
|
||||
required bytes script = 2; // usually one of the standard Script forms
|
||||
}
|
||||
message PaymentDetails {
|
||||
optional string network = 1 [default = "main"]; // "main" or "test"
|
||||
repeated Output outputs = 2; // Where payment should be sent
|
||||
required uint64 time = 3; // Timestamp; when payment request created
|
||||
optional uint64 expires = 4; // Timestamp; when this request should be considered invalid
|
||||
optional string memo = 5; // Human-readable description of request for the customer
|
||||
optional string payment_url = 6; // URL to send Payment and get PaymentACK
|
||||
optional bytes merchant_data = 7; // Arbitrary data to include in the Payment message
|
||||
}
|
||||
message PaymentRequest {
|
||||
optional uint32 payment_details_version = 1 [default = 1];
|
||||
optional string pki_type = 2 [default = "none"]; // none / x509+sha256 / x509+sha1
|
||||
optional bytes pki_data = 3; // depends on pki_type
|
||||
required bytes serialized_payment_details = 4; // PaymentDetails
|
||||
optional bytes signature = 5; // pki-dependent signature
|
||||
}
|
||||
message X509Certificates {
|
||||
repeated bytes certificate = 1; // DER-encoded X.509 certificate chain
|
||||
}
|
||||
message Payment {
|
||||
optional bytes merchant_data = 1; // From PaymentDetails.merchant_data
|
||||
repeated bytes transactions = 2; // Signed transactions that satisfy PaymentDetails.outputs
|
||||
repeated Output refund_to = 3; // Where to send refunds, if a refund is necessary
|
||||
optional string memo = 4; // Human-readable message for the merchant
|
||||
}
|
||||
message PaymentACK {
|
||||
required Payment payment = 1; // Payment message that triggered this ACK
|
||||
optional string memo = 2; // human-readable message for customer
|
||||
}
|
|
@ -1,213 +0,0 @@
|
|||
// Copyright (c) 2011-2018 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
//
|
||||
// Wraps dumb protocol buffer paymentRequest
|
||||
// with some extra methods
|
||||
//
|
||||
|
||||
#include <qt/paymentrequestplus.h>
|
||||
|
||||
#include <util/system.h>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <openssl/x509_vfy.h>
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QSslCertificate>
|
||||
|
||||
class SSLVerifyError : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
explicit SSLVerifyError(std::string err) : std::runtime_error(err) { }
|
||||
};
|
||||
|
||||
bool PaymentRequestPlus::parse(const QByteArray& data)
|
||||
{
|
||||
bool parseOK = paymentRequest.ParseFromArray(data.data(), data.size());
|
||||
if (!parseOK) {
|
||||
qWarning() << "PaymentRequestPlus::parse: Error parsing payment request";
|
||||
return false;
|
||||
}
|
||||
if (paymentRequest.payment_details_version() > 1) {
|
||||
qWarning() << "PaymentRequestPlus::parse: Received up-version payment details, version=" << paymentRequest.payment_details_version();
|
||||
return false;
|
||||
}
|
||||
|
||||
parseOK = details.ParseFromString(paymentRequest.serialized_payment_details());
|
||||
if (!parseOK)
|
||||
{
|
||||
qWarning() << "PaymentRequestPlus::parse: Error parsing payment details";
|
||||
paymentRequest.Clear();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PaymentRequestPlus::SerializeToString(std::string* output) const
|
||||
{
|
||||
return paymentRequest.SerializeToString(output);
|
||||
}
|
||||
|
||||
bool PaymentRequestPlus::IsInitialized() const
|
||||
{
|
||||
return paymentRequest.IsInitialized();
|
||||
}
|
||||
|
||||
bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) const
|
||||
{
|
||||
merchant.clear();
|
||||
|
||||
if (!IsInitialized())
|
||||
return false;
|
||||
|
||||
// One day we'll support more PKI types, but just
|
||||
// x509 for now:
|
||||
const EVP_MD* digestAlgorithm = nullptr;
|
||||
if (paymentRequest.pki_type() == "x509+sha256") {
|
||||
digestAlgorithm = EVP_sha256();
|
||||
}
|
||||
else if (paymentRequest.pki_type() == "x509+sha1") {
|
||||
digestAlgorithm = EVP_sha1();
|
||||
}
|
||||
else if (paymentRequest.pki_type() == "none") {
|
||||
qWarning() << "PaymentRequestPlus::getMerchant: Payment request: pki_type == none";
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
qWarning() << "PaymentRequestPlus::getMerchant: Payment request: unknown pki_type " << QString::fromStdString(paymentRequest.pki_type());
|
||||
return false;
|
||||
}
|
||||
|
||||
payments::X509Certificates certChain;
|
||||
if (!certChain.ParseFromString(paymentRequest.pki_data())) {
|
||||
qWarning() << "PaymentRequestPlus::getMerchant: Payment request: error parsing pki_data";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<X509*> certs;
|
||||
const QDateTime currentTime = QDateTime::currentDateTime();
|
||||
for (int i = 0; i < certChain.certificate_size(); i++) {
|
||||
QByteArray certData(certChain.certificate(i).data(), certChain.certificate(i).size());
|
||||
QSslCertificate qCert(certData, QSsl::Der);
|
||||
if (currentTime < qCert.effectiveDate() || currentTime > qCert.expiryDate()) {
|
||||
qWarning() << "PaymentRequestPlus::getMerchant: Payment request: certificate expired or not yet active: " << qCert;
|
||||
return false;
|
||||
}
|
||||
if (qCert.isBlacklisted()) {
|
||||
qWarning() << "PaymentRequestPlus::getMerchant: Payment request: certificate blacklisted: " << qCert;
|
||||
return false;
|
||||
}
|
||||
const unsigned char *data = (const unsigned char *)certChain.certificate(i).data();
|
||||
X509 *cert = d2i_X509(nullptr, &data, certChain.certificate(i).size());
|
||||
if (cert)
|
||||
certs.push_back(cert);
|
||||
}
|
||||
if (certs.empty()) {
|
||||
qWarning() << "PaymentRequestPlus::getMerchant: Payment request: empty certificate chain";
|
||||
return false;
|
||||
}
|
||||
|
||||
// The first cert is the signing cert, the rest are untrusted certs that chain
|
||||
// to a valid root authority. OpenSSL needs them separately.
|
||||
STACK_OF(X509) *chain = sk_X509_new_null();
|
||||
for (int i = certs.size() - 1; i > 0; i--) {
|
||||
sk_X509_push(chain, certs[i]);
|
||||
}
|
||||
X509 *signing_cert = certs[0];
|
||||
|
||||
// Now create a "store context", which is a single use object for checking,
|
||||
// load the signing cert into it and verify.
|
||||
X509_STORE_CTX *store_ctx = X509_STORE_CTX_new();
|
||||
if (!store_ctx) {
|
||||
qWarning() << "PaymentRequestPlus::getMerchant: Payment request: error creating X509_STORE_CTX";
|
||||
return false;
|
||||
}
|
||||
|
||||
char *website = nullptr;
|
||||
bool fResult = true;
|
||||
try
|
||||
{
|
||||
if (!X509_STORE_CTX_init(store_ctx, certStore, signing_cert, chain))
|
||||
{
|
||||
int error = X509_STORE_CTX_get_error(store_ctx);
|
||||
throw SSLVerifyError(X509_verify_cert_error_string(error));
|
||||
}
|
||||
|
||||
// Now do the verification!
|
||||
int result = X509_verify_cert(store_ctx);
|
||||
if (result != 1) {
|
||||
int error = X509_STORE_CTX_get_error(store_ctx);
|
||||
// For testing payment requests, we allow self signed root certs!
|
||||
if (!(error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT && gArgs.GetBoolArg("-allowselfsignedrootcertificates", DEFAULT_SELFSIGNED_ROOTCERTS))) {
|
||||
throw SSLVerifyError(X509_verify_cert_error_string(error));
|
||||
} else {
|
||||
qDebug() << "PaymentRequestPlus::getMerchant: Allowing self signed root certificate, because -allowselfsignedrootcertificates is true.";
|
||||
}
|
||||
}
|
||||
X509_NAME *certname = X509_get_subject_name(signing_cert);
|
||||
|
||||
// Valid cert; check signature:
|
||||
payments::PaymentRequest rcopy(paymentRequest); // Copy
|
||||
rcopy.set_signature(std::string(""));
|
||||
std::string data_to_verify; // Everything but the signature
|
||||
rcopy.SerializeToString(&data_to_verify);
|
||||
|
||||
#if HAVE_DECL_EVP_MD_CTX_NEW
|
||||
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
|
||||
if (!ctx) throw SSLVerifyError("Error allocating OpenSSL context.");
|
||||
#else
|
||||
EVP_MD_CTX _ctx;
|
||||
EVP_MD_CTX *ctx;
|
||||
ctx = &_ctx;
|
||||
#endif
|
||||
EVP_PKEY *pubkey = X509_get_pubkey(signing_cert);
|
||||
EVP_MD_CTX_init(ctx);
|
||||
if (!EVP_VerifyInit_ex(ctx, digestAlgorithm, nullptr) ||
|
||||
!EVP_VerifyUpdate(ctx, data_to_verify.data(), data_to_verify.size()) ||
|
||||
!EVP_VerifyFinal(ctx, (const unsigned char*)paymentRequest.signature().data(), (unsigned int)paymentRequest.signature().size(), pubkey)) {
|
||||
throw SSLVerifyError("Bad signature, invalid payment request.");
|
||||
}
|
||||
#if HAVE_DECL_EVP_MD_CTX_NEW
|
||||
EVP_MD_CTX_free(ctx);
|
||||
#endif
|
||||
|
||||
// OpenSSL API for getting human printable strings from certs is baroque.
|
||||
int textlen = X509_NAME_get_text_by_NID(certname, NID_commonName, nullptr, 0);
|
||||
website = new char[textlen + 1];
|
||||
if (X509_NAME_get_text_by_NID(certname, NID_commonName, website, textlen + 1) == textlen && textlen > 0) {
|
||||
merchant = website;
|
||||
}
|
||||
else {
|
||||
throw SSLVerifyError("Bad certificate, missing common name.");
|
||||
}
|
||||
// TODO: detect EV certificates and set merchant = business name instead of unfriendly NID_commonName ?
|
||||
}
|
||||
catch (const SSLVerifyError& err) {
|
||||
fResult = false;
|
||||
qWarning() << "PaymentRequestPlus::getMerchant: SSL error: " << err.what();
|
||||
}
|
||||
|
||||
delete[] website;
|
||||
X509_STORE_CTX_free(store_ctx);
|
||||
for (unsigned int i = 0; i < certs.size(); i++)
|
||||
X509_free(certs[i]);
|
||||
|
||||
return fResult;
|
||||
}
|
||||
|
||||
QList<std::pair<CScript,CAmount> > PaymentRequestPlus::getPayTo() const
|
||||
{
|
||||
QList<std::pair<CScript,CAmount> > result;
|
||||
for (int i = 0; i < details.outputs_size(); i++)
|
||||
{
|
||||
const unsigned char* scriptStr = (const unsigned char*)details.outputs(i).script().data();
|
||||
CScript s(scriptStr, scriptStr+details.outputs(i).script().size());
|
||||
|
||||
result.append(std::make_pair(s, details.outputs(i).amount()));
|
||||
}
|
||||
return result;
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
// Copyright (c) 2011-2018 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_QT_PAYMENTREQUESTPLUS_H
|
||||
#define BITCOIN_QT_PAYMENTREQUESTPLUS_H
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#include <qt/paymentrequest.pb.h>
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#include <amount.h>
|
||||
#include <script/script.h>
|
||||
|
||||
#include <openssl/x509.h>
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
|
||||
static const bool DEFAULT_SELFSIGNED_ROOTCERTS = false;
|
||||
|
||||
//
|
||||
// Wraps dumb protocol buffer paymentRequest
|
||||
// with extra methods
|
||||
//
|
||||
|
||||
class PaymentRequestPlus
|
||||
{
|
||||
public:
|
||||
PaymentRequestPlus() { }
|
||||
|
||||
bool parse(const QByteArray& data);
|
||||
bool SerializeToString(std::string* output) const;
|
||||
|
||||
bool IsInitialized() const;
|
||||
// Returns true if merchant's identity is authenticated, and
|
||||
// returns human-readable merchant identity in merchant
|
||||
bool getMerchant(X509_STORE* certStore, QString& merchant) const;
|
||||
|
||||
// Returns list of outputs, amount
|
||||
QList<std::pair<CScript,CAmount> > getPayTo() const;
|
||||
|
||||
const payments::PaymentDetails& getDetails() const { return details; }
|
||||
|
||||
private:
|
||||
payments::PaymentRequest paymentRequest;
|
||||
payments::PaymentDetails details;
|
||||
};
|
||||
|
||||
#endif // BITCOIN_QT_PAYMENTREQUESTPLUS_H
|
|
@ -23,8 +23,6 @@
|
|||
#include <cstdlib>
|
||||
#include <memory>
|
||||
|
||||
#include <openssl/x509_vfy.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QByteArray>
|
||||
#include <QDataStream>
|
||||
|
@ -36,28 +34,11 @@
|
|||
#include <QList>
|
||||
#include <QLocalServer>
|
||||
#include <QLocalSocket>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkProxy>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkRequest>
|
||||
#include <QSslCertificate>
|
||||
#include <QSslConfiguration>
|
||||
#include <QSslError>
|
||||
#include <QStringList>
|
||||
#include <QTextDocument>
|
||||
#include <QUrlQuery>
|
||||
|
||||
const int BITCOIN_IPC_CONNECT_TIMEOUT = 1000; // milliseconds
|
||||
const QString BITCOIN_IPC_PREFIX("bitcoin:");
|
||||
#ifdef ENABLE_BIP70
|
||||
// BIP70 payment protocol messages
|
||||
const char* BIP70_MESSAGE_PAYMENTACK = "PaymentACK";
|
||||
const char* BIP70_MESSAGE_PAYMENTREQUEST = "PaymentRequest";
|
||||
// BIP71 payment protocol media types
|
||||
const char* BIP71_MIMETYPE_PAYMENT = "application/bitcoin-payment";
|
||||
const char* BIP71_MIMETYPE_PAYMENTACK = "application/bitcoin-paymentack";
|
||||
const char* BIP71_MIMETYPE_PAYMENTREQUEST = "application/bitcoin-paymentrequest";
|
||||
#endif
|
||||
|
||||
//
|
||||
// Create a name that is unique for:
|
||||
|
@ -125,32 +106,6 @@ void PaymentServer::ipcParseCommandLine(interfaces::Node& node, int argc, char*
|
|||
}
|
||||
}
|
||||
}
|
||||
#ifdef ENABLE_BIP70
|
||||
else if (QFile::exists(arg)) // Filename
|
||||
{
|
||||
if (savedPaymentRequests.contains(arg)) continue;
|
||||
savedPaymentRequests.insert(arg);
|
||||
|
||||
PaymentRequestPlus request;
|
||||
if (readPaymentRequestFromFile(arg, request))
|
||||
{
|
||||
if (request.getDetails().network() == "main")
|
||||
{
|
||||
node.selectParams(CBaseChainParams::MAIN);
|
||||
}
|
||||
else if (request.getDetails().network() == "test")
|
||||
{
|
||||
node.selectParams(CBaseChainParams::TESTNET);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Printing to debug.log is about the best we can do here, the
|
||||
// GUI hasn't started yet so we can't pop up a message box.
|
||||
qWarning() << "PaymentServer::ipcSendCommandLine: Payment request file does not exist: " << arg;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -198,16 +153,7 @@ PaymentServer::PaymentServer(QObject* parent, bool startLocalServer) :
|
|||
saveURIs(true),
|
||||
uriServer(nullptr),
|
||||
optionsModel(nullptr)
|
||||
#ifdef ENABLE_BIP70
|
||||
,netManager(nullptr)
|
||||
#endif
|
||||
{
|
||||
#ifdef ENABLE_BIP70
|
||||
// Verify that the version of the library that we linked against is
|
||||
// compatible with the version of the headers we compiled against.
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
#endif
|
||||
|
||||
// Install global event filter to catch QFileOpenEvents
|
||||
// on Mac: sent when you click bitcoin: links
|
||||
// other OSes: helpful when dealing with payment request files
|
||||
|
@ -230,24 +176,16 @@ PaymentServer::PaymentServer(QObject* parent, bool startLocalServer) :
|
|||
}
|
||||
else {
|
||||
connect(uriServer, &QLocalServer::newConnection, this, &PaymentServer::handleURIConnection);
|
||||
#ifdef ENABLE_BIP70
|
||||
connect(this, &PaymentServer::receivedPaymentACK, this, &PaymentServer::handlePaymentACK);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PaymentServer::~PaymentServer()
|
||||
{
|
||||
#ifdef ENABLE_BIP70
|
||||
google::protobuf::ShutdownProtobufLibrary();
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
// OSX-specific way of handling bitcoin: URIs and PaymentRequest mime types.
|
||||
// Also used by paymentservertests.cpp and when opening a payment request file
|
||||
// via "Open URI..." menu entry.
|
||||
// OSX-specific way of handling bitcoin: URIs
|
||||
//
|
||||
bool PaymentServer::eventFilter(QObject *object, QEvent *event)
|
||||
{
|
||||
|
@ -266,10 +204,6 @@ bool PaymentServer::eventFilter(QObject *object, QEvent *event)
|
|||
|
||||
void PaymentServer::uiReady()
|
||||
{
|
||||
#ifdef ENABLE_BIP70
|
||||
initNetManager();
|
||||
#endif
|
||||
|
||||
saveURIs = false;
|
||||
for (const QString& s : savedPaymentRequests)
|
||||
{
|
||||
|
@ -294,48 +228,19 @@ void PaymentServer::handleURIOrFile(const QString& s)
|
|||
else if (s.startsWith(BITCOIN_IPC_PREFIX, Qt::CaseInsensitive)) // bitcoin: URI
|
||||
{
|
||||
QUrlQuery uri((QUrl(s)));
|
||||
#ifdef ENABLE_BIP70
|
||||
if (uri.hasQueryItem("r")) // payment request URI
|
||||
{
|
||||
Q_EMIT message(tr("URI handling"),
|
||||
tr("You are using a BIP70 URL which will be unsupported in the future."),
|
||||
CClientUIInterface::ICON_WARNING);
|
||||
QByteArray temp;
|
||||
temp.append(uri.queryItemValue("r"));
|
||||
QString decoded = QUrl::fromPercentEncoding(temp);
|
||||
QUrl fetchUrl(decoded, QUrl::StrictMode);
|
||||
|
||||
if (fetchUrl.isValid())
|
||||
{
|
||||
qDebug() << "PaymentServer::handleURIOrFile: fetchRequest(" << fetchUrl << ")";
|
||||
fetchRequest(fetchUrl);
|
||||
}
|
||||
else
|
||||
{
|
||||
qWarning() << "PaymentServer::handleURIOrFile: Invalid URL: " << fetchUrl;
|
||||
Q_EMIT message(tr("URI handling"),
|
||||
tr("Payment request fetch URL is invalid: %1").arg(fetchUrl.toString()),
|
||||
CClientUIInterface::ICON_WARNING);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
// normal URI
|
||||
{
|
||||
SendCoinsRecipient recipient;
|
||||
if (GUIUtil::parseBitcoinURI(s, &recipient))
|
||||
{
|
||||
if (!IsValidDestinationString(recipient.address.toStdString())) {
|
||||
#ifndef ENABLE_BIP70
|
||||
if (uri.hasQueryItem("r")) { // payment request
|
||||
Q_EMIT message(tr("URI handling"),
|
||||
tr("Cannot process payment request because BIP70 support was not compiled in.")+
|
||||
tr("Cannot process payment request because BIP70 is not supported.")+
|
||||
tr("Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.")+
|
||||
tr("If you are receiving this error you should request the merchant provide a BIP21 compatible URI."),
|
||||
CClientUIInterface::ICON_WARNING);
|
||||
}
|
||||
#endif
|
||||
Q_EMIT message(tr("URI handling"), tr("Invalid payment address %1").arg(recipient.address),
|
||||
CClientUIInterface::MSG_ERROR);
|
||||
}
|
||||
|
@ -353,26 +258,11 @@ void PaymentServer::handleURIOrFile(const QString& s)
|
|||
|
||||
if (QFile::exists(s)) // payment request file
|
||||
{
|
||||
#ifdef ENABLE_BIP70
|
||||
PaymentRequestPlus request;
|
||||
SendCoinsRecipient recipient;
|
||||
if (!readPaymentRequestFromFile(s, request))
|
||||
{
|
||||
Q_EMIT message(tr("Payment request file handling"),
|
||||
tr("Payment request file cannot be read! This can be caused by an invalid payment request file."),
|
||||
CClientUIInterface::ICON_WARNING);
|
||||
}
|
||||
else if (processPaymentRequest(request, recipient))
|
||||
Q_EMIT receivedPaymentRequest(recipient);
|
||||
|
||||
return;
|
||||
#else
|
||||
Q_EMIT message(tr("Payment request file handling"),
|
||||
tr("Cannot process payment request because BIP70 support was not compiled in.")+
|
||||
tr("Cannot process payment request because BIP70 is not supported.")+
|
||||
tr("Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.")+
|
||||
tr("If you are receiving this error you should request the merchant provide a BIP21 compatible URI."),
|
||||
CClientUIInterface::ICON_WARNING);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -400,440 +290,3 @@ void PaymentServer::setOptionsModel(OptionsModel *_optionsModel)
|
|||
{
|
||||
this->optionsModel = _optionsModel;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_BIP70
|
||||
struct X509StoreDeleter {
|
||||
void operator()(X509_STORE* b) {
|
||||
X509_STORE_free(b);
|
||||
}
|
||||
};
|
||||
|
||||
struct X509Deleter {
|
||||
void operator()(X509* b) { X509_free(b); }
|
||||
};
|
||||
|
||||
namespace // Anon namespace
|
||||
{
|
||||
std::unique_ptr<X509_STORE, X509StoreDeleter> certStore;
|
||||
}
|
||||
|
||||
static void ReportInvalidCertificate(const QSslCertificate& cert)
|
||||
{
|
||||
qDebug() << QString("%1: Payment server found an invalid certificate: ").arg(__func__) << cert.serialNumber() << cert.subjectInfo(QSslCertificate::CommonName) << cert.subjectInfo(QSslCertificate::DistinguishedNameQualifier) << cert.subjectInfo(QSslCertificate::OrganizationalUnitName);
|
||||
}
|
||||
|
||||
//
|
||||
// Load OpenSSL's list of root certificate authorities
|
||||
//
|
||||
void PaymentServer::LoadRootCAs(X509_STORE* _store)
|
||||
{
|
||||
// Unit tests mostly use this, to pass in fake root CAs:
|
||||
if (_store)
|
||||
{
|
||||
certStore.reset(_store);
|
||||
return;
|
||||
}
|
||||
|
||||
// Normal execution, use either -rootcertificates or system certs:
|
||||
certStore.reset(X509_STORE_new());
|
||||
|
||||
// Note: use "-system-" default here so that users can pass -rootcertificates=""
|
||||
// and get 'I don't like X.509 certificates, don't trust anybody' behavior:
|
||||
QString certFile = QString::fromStdString(gArgs.GetArg("-rootcertificates", "-system-"));
|
||||
|
||||
// Empty store
|
||||
if (certFile.isEmpty()) {
|
||||
qDebug() << QString("PaymentServer::%1: Payment request authentication via X.509 certificates disabled.").arg(__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
QList<QSslCertificate> certList;
|
||||
|
||||
if (certFile != "-system-") {
|
||||
qDebug() << QString("PaymentServer::%1: Using \"%2\" as trusted root certificate.").arg(__func__).arg(certFile);
|
||||
|
||||
certList = QSslCertificate::fromPath(certFile);
|
||||
// Use those certificates when fetching payment requests, too:
|
||||
QSslConfiguration::defaultConfiguration().setCaCertificates(certList);
|
||||
} else
|
||||
certList = QSslConfiguration::systemCaCertificates();
|
||||
|
||||
int nRootCerts = 0;
|
||||
const QDateTime currentTime = QDateTime::currentDateTime();
|
||||
|
||||
for (const QSslCertificate& cert : certList) {
|
||||
// Don't log NULL certificates
|
||||
if (cert.isNull())
|
||||
continue;
|
||||
|
||||
// Not yet active/valid, or expired certificate
|
||||
if (currentTime < cert.effectiveDate() || currentTime > cert.expiryDate()) {
|
||||
ReportInvalidCertificate(cert);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Blacklisted certificate
|
||||
if (cert.isBlacklisted()) {
|
||||
ReportInvalidCertificate(cert);
|
||||
continue;
|
||||
}
|
||||
|
||||
QByteArray certData = cert.toDer();
|
||||
const unsigned char *data = (const unsigned char *)certData.data();
|
||||
|
||||
std::unique_ptr<X509, X509Deleter> x509(d2i_X509(0, &data, certData.size()));
|
||||
if (x509 && X509_STORE_add_cert(certStore.get(), x509.get()))
|
||||
{
|
||||
// Note: X509_STORE increases the reference count to the X509 object,
|
||||
// we still have to release our reference to it.
|
||||
++nRootCerts;
|
||||
}
|
||||
else
|
||||
{
|
||||
ReportInvalidCertificate(cert);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
qInfo() << "PaymentServer::LoadRootCAs: Loaded " << nRootCerts << " root certificates";
|
||||
|
||||
// Project for another day:
|
||||
// Fetch certificate revocation lists, and add them to certStore.
|
||||
// Issues to consider:
|
||||
// performance (start a thread to fetch in background?)
|
||||
// privacy (fetch through tor/proxy so IP address isn't revealed)
|
||||
// would it be easier to just use a compiled-in blacklist?
|
||||
// or use Qt's blacklist?
|
||||
// "certificate stapling" with server-side caching is more efficient
|
||||
}
|
||||
|
||||
void PaymentServer::initNetManager()
|
||||
{
|
||||
if (!optionsModel)
|
||||
return;
|
||||
delete netManager;
|
||||
|
||||
// netManager is used to fetch paymentrequests given in bitcoin: URIs
|
||||
netManager = new QNetworkAccessManager(this);
|
||||
|
||||
QNetworkProxy proxy;
|
||||
|
||||
// Query active SOCKS5 proxy
|
||||
if (optionsModel->getProxySettings(proxy)) {
|
||||
netManager->setProxy(proxy);
|
||||
|
||||
qDebug() << "PaymentServer::initNetManager: Using SOCKS5 proxy" << proxy.hostName() << ":" << proxy.port();
|
||||
}
|
||||
else
|
||||
qDebug() << "PaymentServer::initNetManager: No active proxy server found.";
|
||||
|
||||
connect(netManager, &QNetworkAccessManager::finished, this, &PaymentServer::netRequestFinished);
|
||||
connect(netManager, &QNetworkAccessManager::sslErrors, this, &PaymentServer::reportSslErrors);
|
||||
}
|
||||
|
||||
//
|
||||
// Warning: readPaymentRequestFromFile() is used in ipcSendCommandLine()
|
||||
// so don't use "Q_EMIT message()", but "QMessageBox::"!
|
||||
//
|
||||
bool PaymentServer::readPaymentRequestFromFile(const QString& filename, PaymentRequestPlus& request)
|
||||
{
|
||||
QFile f(filename);
|
||||
if (!f.open(QIODevice::ReadOnly)) {
|
||||
qWarning() << QString("PaymentServer::%1: Failed to open %2").arg(__func__).arg(filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
// BIP70 DoS protection
|
||||
if (!verifySize(f.size())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QByteArray data = f.readAll();
|
||||
|
||||
return request.parse(data);
|
||||
}
|
||||
|
||||
bool PaymentServer::processPaymentRequest(const PaymentRequestPlus& request, SendCoinsRecipient& recipient)
|
||||
{
|
||||
if (!optionsModel)
|
||||
return false;
|
||||
|
||||
if (request.IsInitialized()) {
|
||||
// Payment request network matches client network?
|
||||
if (!verifyNetwork(optionsModel->node(), request.getDetails())) {
|
||||
Q_EMIT message(tr("Payment request rejected"), tr("Payment request network doesn't match client network."),
|
||||
CClientUIInterface::MSG_ERROR);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure any payment requests involved are still valid.
|
||||
// This is re-checked just before sending coins in WalletModel::sendCoins().
|
||||
if (verifyExpired(request.getDetails())) {
|
||||
Q_EMIT message(tr("Payment request rejected"), tr("Payment request expired."),
|
||||
CClientUIInterface::MSG_ERROR);
|
||||
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
Q_EMIT message(tr("Payment request error"), tr("Payment request is not initialized."),
|
||||
CClientUIInterface::MSG_ERROR);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
recipient.paymentRequest = request;
|
||||
recipient.message = GUIUtil::HtmlEscape(request.getDetails().memo());
|
||||
|
||||
request.getMerchant(certStore.get(), recipient.authenticatedMerchant);
|
||||
|
||||
QList<std::pair<CScript, CAmount> > sendingTos = request.getPayTo();
|
||||
QStringList addresses;
|
||||
|
||||
for (const std::pair<CScript, CAmount>& sendingTo : sendingTos) {
|
||||
// Extract and check destination addresses
|
||||
CTxDestination dest;
|
||||
if (ExtractDestination(sendingTo.first, dest)) {
|
||||
// Append destination address
|
||||
addresses.append(QString::fromStdString(EncodeDestination(dest)));
|
||||
}
|
||||
else if (!recipient.authenticatedMerchant.isEmpty()) {
|
||||
// Unauthenticated payment requests to custom bitcoin addresses are not supported
|
||||
// (there is no good way to tell the user where they are paying in a way they'd
|
||||
// have a chance of understanding).
|
||||
Q_EMIT message(tr("Payment request rejected"),
|
||||
tr("Unverified payment requests to custom payment scripts are unsupported."),
|
||||
CClientUIInterface::MSG_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Bitcoin amounts are stored as (optional) uint64 in the protobuf messages (see paymentrequest.proto),
|
||||
// but CAmount is defined as int64_t. Because of that we need to verify that amounts are in a valid range
|
||||
// and no overflow has happened.
|
||||
if (!verifyAmount(sendingTo.second)) {
|
||||
Q_EMIT message(tr("Payment request rejected"), tr("Invalid payment request."), CClientUIInterface::MSG_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Extract and check amounts
|
||||
CTxOut txOut(sendingTo.second, sendingTo.first);
|
||||
if (IsDust(txOut, optionsModel->node().getDustRelayFee())) {
|
||||
Q_EMIT message(tr("Payment request error"), tr("Requested payment amount of %1 is too small (considered dust).")
|
||||
.arg(BitcoinUnits::formatWithUnit(optionsModel->getDisplayUnit(), sendingTo.second)),
|
||||
CClientUIInterface::MSG_ERROR);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
recipient.amount += sendingTo.second;
|
||||
// Also verify that the final amount is still in a valid range after adding additional amounts.
|
||||
if (!verifyAmount(recipient.amount)) {
|
||||
Q_EMIT message(tr("Payment request rejected"), tr("Invalid payment request."), CClientUIInterface::MSG_ERROR);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Store addresses and format them to fit nicely into the GUI
|
||||
recipient.address = addresses.join("<br />");
|
||||
|
||||
if (!recipient.authenticatedMerchant.isEmpty()) {
|
||||
qDebug() << "PaymentServer::processPaymentRequest: Secure payment request from " << recipient.authenticatedMerchant;
|
||||
}
|
||||
else {
|
||||
qDebug() << "PaymentServer::processPaymentRequest: Insecure payment request to " << addresses.join(", ");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PaymentServer::fetchRequest(const QUrl& url)
|
||||
{
|
||||
QNetworkRequest netRequest;
|
||||
netRequest.setAttribute(QNetworkRequest::User, BIP70_MESSAGE_PAYMENTREQUEST);
|
||||
netRequest.setUrl(url);
|
||||
netRequest.setRawHeader("User-Agent", CLIENT_NAME.c_str());
|
||||
netRequest.setRawHeader("Accept", BIP71_MIMETYPE_PAYMENTREQUEST);
|
||||
netManager->get(netRequest);
|
||||
}
|
||||
|
||||
void PaymentServer::fetchPaymentACK(WalletModel* walletModel, const SendCoinsRecipient& recipient, QByteArray transaction)
|
||||
{
|
||||
const payments::PaymentDetails& details = recipient.paymentRequest.getDetails();
|
||||
if (!details.has_payment_url())
|
||||
return;
|
||||
|
||||
QNetworkRequest netRequest;
|
||||
netRequest.setAttribute(QNetworkRequest::User, BIP70_MESSAGE_PAYMENTACK);
|
||||
netRequest.setUrl(QString::fromStdString(details.payment_url()));
|
||||
netRequest.setHeader(QNetworkRequest::ContentTypeHeader, BIP71_MIMETYPE_PAYMENT);
|
||||
netRequest.setRawHeader("User-Agent", CLIENT_NAME.c_str());
|
||||
netRequest.setRawHeader("Accept", BIP71_MIMETYPE_PAYMENTACK);
|
||||
|
||||
payments::Payment payment;
|
||||
payment.set_merchant_data(details.merchant_data());
|
||||
payment.add_transactions(transaction.data(), transaction.size());
|
||||
|
||||
// Create a new refund address, or re-use:
|
||||
CTxDestination dest;
|
||||
const OutputType change_type = walletModel->wallet().getDefaultChangeType() != OutputType::CHANGE_AUTO ? walletModel->wallet().getDefaultChangeType() : walletModel->wallet().getDefaultAddressType();
|
||||
if (walletModel->wallet().getNewDestination(change_type, "", dest)) {
|
||||
// BIP70 requests encode the scriptPubKey directly, so we are not restricted to address
|
||||
// types supported by the receiver. As a result, we choose the address format we also
|
||||
// use for change. Despite an actual payment and not change, this is a close match:
|
||||
// it's the output type we use subject to privacy issues, but not restricted by what
|
||||
// other software supports.
|
||||
std::string label = tr("Refund from %1").arg(recipient.authenticatedMerchant).toStdString();
|
||||
walletModel->wallet().setAddressBook(dest, label, "refund");
|
||||
|
||||
CScript s = GetScriptForDestination(dest);
|
||||
payments::Output* refund_to = payment.add_refund_to();
|
||||
refund_to->set_script(&s[0], s.size());
|
||||
} else {
|
||||
// This should never happen, because sending coins should have
|
||||
// just unlocked the wallet and refilled the keypool.
|
||||
qWarning() << "PaymentServer::fetchPaymentACK: Error getting refund key, refund_to not set";
|
||||
}
|
||||
|
||||
int length = payment.ByteSize();
|
||||
netRequest.setHeader(QNetworkRequest::ContentLengthHeader, length);
|
||||
QByteArray serData(length, '\0');
|
||||
if (payment.SerializeToArray(serData.data(), length)) {
|
||||
netManager->post(netRequest, serData);
|
||||
}
|
||||
else {
|
||||
// This should never happen, either.
|
||||
qWarning() << "PaymentServer::fetchPaymentACK: Error serializing payment message";
|
||||
}
|
||||
}
|
||||
|
||||
void PaymentServer::netRequestFinished(QNetworkReply* reply)
|
||||
{
|
||||
reply->deleteLater();
|
||||
|
||||
// BIP70 DoS protection
|
||||
if (!verifySize(reply->size())) {
|
||||
Q_EMIT message(tr("Payment request rejected"),
|
||||
tr("Payment request %1 is too large (%2 bytes, allowed %3 bytes).")
|
||||
.arg(reply->request().url().toString())
|
||||
.arg(reply->size())
|
||||
.arg(BIP70_MAX_PAYMENTREQUEST_SIZE),
|
||||
CClientUIInterface::MSG_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (reply->error() != QNetworkReply::NoError) {
|
||||
QString msg = tr("Error communicating with %1: %2")
|
||||
.arg(reply->request().url().toString())
|
||||
.arg(reply->errorString());
|
||||
|
||||
qWarning() << "PaymentServer::netRequestFinished: " << msg;
|
||||
Q_EMIT message(tr("Payment request error"), msg, CClientUIInterface::MSG_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray data = reply->readAll();
|
||||
|
||||
QString requestType = reply->request().attribute(QNetworkRequest::User).toString();
|
||||
if (requestType == BIP70_MESSAGE_PAYMENTREQUEST)
|
||||
{
|
||||
PaymentRequestPlus request;
|
||||
SendCoinsRecipient recipient;
|
||||
if (!request.parse(data))
|
||||
{
|
||||
qWarning() << "PaymentServer::netRequestFinished: Error parsing payment request";
|
||||
Q_EMIT message(tr("Payment request error"),
|
||||
tr("Payment request cannot be parsed!"),
|
||||
CClientUIInterface::MSG_ERROR);
|
||||
}
|
||||
else if (processPaymentRequest(request, recipient))
|
||||
Q_EMIT receivedPaymentRequest(recipient);
|
||||
|
||||
return;
|
||||
}
|
||||
else if (requestType == BIP70_MESSAGE_PAYMENTACK)
|
||||
{
|
||||
payments::PaymentACK paymentACK;
|
||||
if (!paymentACK.ParseFromArray(data.data(), data.size()))
|
||||
{
|
||||
QString msg = tr("Bad response from server %1")
|
||||
.arg(reply->request().url().toString());
|
||||
|
||||
qWarning() << "PaymentServer::netRequestFinished: " << msg;
|
||||
Q_EMIT message(tr("Payment request error"), msg, CClientUIInterface::MSG_ERROR);
|
||||
}
|
||||
else
|
||||
{
|
||||
Q_EMIT receivedPaymentACK(GUIUtil::HtmlEscape(paymentACK.memo()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PaymentServer::reportSslErrors(QNetworkReply* reply, const QList<QSslError> &errs)
|
||||
{
|
||||
Q_UNUSED(reply);
|
||||
|
||||
QString errString;
|
||||
for (const QSslError& err : errs) {
|
||||
qWarning() << "PaymentServer::reportSslErrors: " << err;
|
||||
errString += err.errorString() + "\n";
|
||||
}
|
||||
Q_EMIT message(tr("Network request error"), errString, CClientUIInterface::MSG_ERROR);
|
||||
}
|
||||
|
||||
void PaymentServer::handlePaymentACK(const QString& paymentACKMsg)
|
||||
{
|
||||
// currently we don't further process or store the paymentACK message
|
||||
Q_EMIT message(tr("Payment acknowledged"), paymentACKMsg, CClientUIInterface::ICON_INFORMATION | CClientUIInterface::MODAL);
|
||||
}
|
||||
|
||||
bool PaymentServer::verifyNetwork(interfaces::Node& node, const payments::PaymentDetails& requestDetails)
|
||||
{
|
||||
bool fVerified = requestDetails.network() == node.getNetwork();
|
||||
if (!fVerified) {
|
||||
qWarning() << QString("PaymentServer::%1: Payment request network \"%2\" doesn't match client network \"%3\".")
|
||||
.arg(__func__)
|
||||
.arg(QString::fromStdString(requestDetails.network()))
|
||||
.arg(QString::fromStdString(node.getNetwork()));
|
||||
}
|
||||
return fVerified;
|
||||
}
|
||||
|
||||
bool PaymentServer::verifyExpired(const payments::PaymentDetails& requestDetails)
|
||||
{
|
||||
bool fVerified = (requestDetails.has_expires() && (int64_t)requestDetails.expires() < GetTime());
|
||||
if (fVerified) {
|
||||
const QString requestExpires = QString::fromStdString(FormatISO8601DateTime((int64_t)requestDetails.expires()));
|
||||
qWarning() << QString("PaymentServer::%1: Payment request expired \"%2\".")
|
||||
.arg(__func__)
|
||||
.arg(requestExpires);
|
||||
}
|
||||
return fVerified;
|
||||
}
|
||||
|
||||
bool PaymentServer::verifySize(qint64 requestSize)
|
||||
{
|
||||
bool fVerified = (requestSize <= BIP70_MAX_PAYMENTREQUEST_SIZE);
|
||||
if (!fVerified) {
|
||||
qWarning() << QString("PaymentServer::%1: Payment request too large (%2 bytes, allowed %3 bytes).")
|
||||
.arg(__func__)
|
||||
.arg(requestSize)
|
||||
.arg(BIP70_MAX_PAYMENTREQUEST_SIZE);
|
||||
}
|
||||
return fVerified;
|
||||
}
|
||||
|
||||
bool PaymentServer::verifyAmount(const CAmount& requestAmount)
|
||||
{
|
||||
bool fVerified = MoneyRange(requestAmount);
|
||||
if (!fVerified) {
|
||||
qWarning() << QString("PaymentServer::%1: Payment request amount out of allowed range (%2, allowed 0 - %3).")
|
||||
.arg(__func__)
|
||||
.arg(requestAmount)
|
||||
.arg(MAX_MONEY);
|
||||
}
|
||||
return fVerified;
|
||||
}
|
||||
|
||||
X509_STORE* PaymentServer::getCertStore()
|
||||
{
|
||||
return certStore.get();
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -36,9 +36,6 @@
|
|||
#include <config/bitcoin-config.h>
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_BIP70
|
||||
#include <qt/paymentrequestplus.h>
|
||||
#endif
|
||||
#include <qt/walletmodel.h>
|
||||
|
||||
#include <QObject>
|
||||
|
@ -50,15 +47,9 @@ QT_BEGIN_NAMESPACE
|
|||
class QApplication;
|
||||
class QByteArray;
|
||||
class QLocalServer;
|
||||
class QNetworkAccessManager;
|
||||
class QNetworkReply;
|
||||
class QSslError;
|
||||
class QUrl;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
// BIP70 max payment request size in bytes (DoS protection)
|
||||
static const qint64 BIP70_MAX_PAYMENTREQUEST_SIZE = 50000;
|
||||
|
||||
class PaymentServer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -82,27 +73,6 @@ public:
|
|||
// OptionsModel is used for getting proxy settings and display unit
|
||||
void setOptionsModel(OptionsModel *optionsModel);
|
||||
|
||||
#ifdef ENABLE_BIP70
|
||||
// Load root certificate authorities. Pass nullptr (default)
|
||||
// to read from the file specified in the -rootcertificates setting,
|
||||
// or, if that's not set, to use the system default root certificates.
|
||||
// If you pass in a store, you should not X509_STORE_free it: it will be
|
||||
// freed either at exit or when another set of CAs are loaded.
|
||||
static void LoadRootCAs(X509_STORE* store = nullptr);
|
||||
|
||||
// Return certificate store
|
||||
static X509_STORE* getCertStore();
|
||||
|
||||
// Verify that the payment request network matches the client network
|
||||
static bool verifyNetwork(interfaces::Node& node, const payments::PaymentDetails& requestDetails);
|
||||
// Verify if the payment request is expired
|
||||
static bool verifyExpired(const payments::PaymentDetails& requestDetails);
|
||||
// Verify the payment request size is valid as per BIP70
|
||||
static bool verifySize(qint64 requestSize);
|
||||
// Verify the payment request amount is valid
|
||||
static bool verifyAmount(const CAmount& requestAmount);
|
||||
#endif
|
||||
|
||||
Q_SIGNALS:
|
||||
// Fired when a valid payment request is received
|
||||
void receivedPaymentRequest(SendCoinsRecipient);
|
||||
|
@ -110,11 +80,6 @@ Q_SIGNALS:
|
|||
// Fired when a message should be reported to the user
|
||||
void message(const QString &title, const QString &message, unsigned int style);
|
||||
|
||||
#ifdef ENABLE_BIP70
|
||||
// Fired when a valid PaymentACK is received
|
||||
void receivedPaymentACK(const QString &paymentACKMsg);
|
||||
#endif
|
||||
|
||||
public Q_SLOTS:
|
||||
// Signal this when the main window's UI is ready
|
||||
// to display payment requests to the user
|
||||
|
@ -123,18 +88,8 @@ public Q_SLOTS:
|
|||
// Handle an incoming URI, URI with local file scheme or file
|
||||
void handleURIOrFile(const QString& s);
|
||||
|
||||
#ifdef ENABLE_BIP70
|
||||
// Submit Payment message to a merchant, get back PaymentACK:
|
||||
void fetchPaymentACK(WalletModel* walletModel, const SendCoinsRecipient& recipient, QByteArray transaction);
|
||||
#endif
|
||||
|
||||
private Q_SLOTS:
|
||||
void handleURIConnection();
|
||||
#ifdef ENABLE_BIP70
|
||||
void netRequestFinished(QNetworkReply*);
|
||||
void reportSslErrors(QNetworkReply*, const QList<QSslError> &);
|
||||
void handlePaymentACK(const QString& paymentACKMsg);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
// Constructor registers this on the parent QApplication to
|
||||
|
@ -145,16 +100,6 @@ private:
|
|||
bool saveURIs; // true during startup
|
||||
QLocalServer* uriServer;
|
||||
OptionsModel *optionsModel;
|
||||
|
||||
#ifdef ENABLE_BIP70
|
||||
static bool readPaymentRequestFromFile(const QString& filename, PaymentRequestPlus& request);
|
||||
bool processPaymentRequest(const PaymentRequestPlus& request, SendCoinsRecipient& recipient);
|
||||
void fetchRequest(const QUrl& url);
|
||||
|
||||
// Setup networking
|
||||
void initNetManager();
|
||||
QNetworkAccessManager* netManager; // Used to fetch payment requests
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // BITCOIN_QT_PAYMENTSERVER_H
|
||||
|
|
|
@ -291,9 +291,6 @@ void SendCoinsDialog::on_sendButton_clicked()
|
|||
|
||||
QString recipientElement;
|
||||
|
||||
#ifdef ENABLE_BIP70
|
||||
if (!rcp.paymentRequest.IsInitialized()) // normal payment
|
||||
#endif
|
||||
{
|
||||
if(rcp.label.length() > 0) // label with address
|
||||
{
|
||||
|
@ -305,17 +302,6 @@ void SendCoinsDialog::on_sendButton_clicked()
|
|||
recipientElement.append(tr("%1 to %2").arg(amount, address));
|
||||
}
|
||||
}
|
||||
#ifdef ENABLE_BIP70
|
||||
else if(!rcp.authenticatedMerchant.isEmpty()) // authenticated payment request
|
||||
{
|
||||
recipientElement.append(tr("%1 to '%2'").arg(amount, rcp.authenticatedMerchant));
|
||||
}
|
||||
else // unauthenticated payment request
|
||||
{
|
||||
recipientElement.append(tr("%1 to %2").arg(amount, address));
|
||||
}
|
||||
#endif
|
||||
|
||||
formatted.append(recipientElement);
|
||||
}
|
||||
|
||||
|
|
|
@ -137,12 +137,6 @@ bool SendCoinsEntry::validate(interfaces::Node& node)
|
|||
// Check input validity
|
||||
bool retval = true;
|
||||
|
||||
#ifdef ENABLE_BIP70
|
||||
// Skip checks for payment request
|
||||
if (recipient.paymentRequest.IsInitialized())
|
||||
return retval;
|
||||
#endif
|
||||
|
||||
if (!model->validateAddress(ui->payTo->text()))
|
||||
{
|
||||
ui->payTo->setValid(false);
|
||||
|
@ -172,13 +166,6 @@ bool SendCoinsEntry::validate(interfaces::Node& node)
|
|||
|
||||
SendCoinsRecipient SendCoinsEntry::getValue()
|
||||
{
|
||||
#ifdef ENABLE_BIP70
|
||||
// Payment request
|
||||
if (recipient.paymentRequest.IsInitialized())
|
||||
return recipient;
|
||||
#endif
|
||||
|
||||
// Normal payment
|
||||
recipient.address = ui->payTo->text();
|
||||
recipient.label = ui->addAsLabel->text();
|
||||
recipient.amount = ui->payAmount->value();
|
||||
|
@ -203,29 +190,6 @@ QWidget *SendCoinsEntry::setupTabChain(QWidget *prev)
|
|||
void SendCoinsEntry::setValue(const SendCoinsRecipient &value)
|
||||
{
|
||||
recipient = value;
|
||||
|
||||
#ifdef ENABLE_BIP70
|
||||
if (recipient.paymentRequest.IsInitialized()) // payment request
|
||||
{
|
||||
if (recipient.authenticatedMerchant.isEmpty()) // unauthenticated
|
||||
{
|
||||
ui->payTo_is->setText(recipient.address);
|
||||
ui->memoTextLabel_is->setText(recipient.message);
|
||||
ui->payAmount_is->setValue(recipient.amount);
|
||||
ui->payAmount_is->setReadOnly(true);
|
||||
setCurrentWidget(ui->SendCoins_UnauthenticatedPaymentRequest);
|
||||
}
|
||||
else // authenticated
|
||||
{
|
||||
ui->payTo_s->setText(recipient.authenticatedMerchant);
|
||||
ui->memoTextLabel_s->setText(recipient.message);
|
||||
ui->payAmount_s->setValue(recipient.amount);
|
||||
ui->payAmount_s->setReadOnly(true);
|
||||
setCurrentWidget(ui->SendCoins_AuthenticatedPaymentRequest);
|
||||
}
|
||||
}
|
||||
else // normal payment
|
||||
#endif
|
||||
{
|
||||
// message
|
||||
ui->messageTextLabel->setText(recipient.message);
|
||||
|
|
|
@ -6,10 +6,6 @@
|
|||
#include <config/bitcoin-config.h>
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_WALLET) && defined(ENABLE_BIP70)
|
||||
#include <qt/paymentrequestplus.h> // this includes protobuf's port.h which defines its own bswap macos
|
||||
#endif
|
||||
|
||||
#include <qt/test/compattests.h>
|
||||
|
||||
#include <compat/byteswap.h>
|
||||
|
|
|
@ -1,465 +0,0 @@
|
|||
// Copyright (c) 2009-2018 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_QT_TEST_PAYMENTREQUESTDATA_H
|
||||
#define BITCOIN_QT_TEST_PAYMENTREQUESTDATA_H
|
||||
|
||||
//
|
||||
// Data for paymentservertests.cpp
|
||||
//
|
||||
|
||||
// Base64/DER-encoded fake certificate authority certificates.
|
||||
// Convert pem to base64/der with:
|
||||
// openssl x509 -in cert.pem -inform PEM -outform DER | openssl enc -base64
|
||||
|
||||
// Serial Number: 10302349811211485352 (0x8ef94c91b112c0a8)
|
||||
// Issuer: CN=PaymentRequest Test CA
|
||||
// Subject: CN=PaymentRequest Test CA
|
||||
// Not Valid After : Dec 8 16:37:24 2022 GMT
|
||||
//
|
||||
const char* caCert1_BASE64 =
|
||||
"\
|
||||
MIIB0DCCATmgAwIBAgIJAI75TJGxEsCoMA0GCSqGSIb3DQEBCwUAMCExHzAdBgNV\
|
||||
BAMTFlBheW1lbnRSZXF1ZXN0IFRlc3QgQ0EwHhcNMTIxMjEwMTYzNzI0WhcNMjIx\
|
||||
MjA4MTYzNzI0WjAhMR8wHQYDVQQDExZQYXltZW50UmVxdWVzdCBUZXN0IENBMIGf\
|
||||
MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCvua59nX9radoqDYyplcns5qdVDTN1\
|
||||
7tmcGixmMYOYU3UYMU55VSsJs0dWKnMm3COQDY+N63c0XSbRqarBcsLTkaNASuPX\
|
||||
FCv1VWuEKSyy5xe4zeoDU7CVSzlxtQD9wbZW/s3ISjgaXBpwn6eVmntb0JwYxxPc\
|
||||
M1u/hrMD8BDbSQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUA\
|
||||
A4GBADSaRgK5xe47XxycXBhHhr0Wgl4pAsFsufqA9aB9r8KNEHJ0yUvvbD/jaJJM\
|
||||
RtQcf0AJ9olzUMY4syehxbzUJP6aeXhZEYiMvdvcv9D55clq6+WLLlNT3jBgAaVn\
|
||||
p3waRjPD4bUX3nv+ojz5s4puw7Qq5QUZlhGsMzPvwDGCmZkL\
|
||||
";
|
||||
|
||||
// Serial Number: f0:da:97:e4:38:d7:64:16
|
||||
// Issuer: CN=PaymentRequest Test CA
|
||||
// Subject: CN=PaymentRequest Test CA
|
||||
// Not Valid After : Jan 8 18:21:06 2025 GMT
|
||||
//
|
||||
const char* caCert2_BASE64 =
|
||||
"\
|
||||
MIIC1TCCAb2gAwIBAgIJAPDal+Q412QWMA0GCSqGSIb3DQEBCwUAMCExHzAdBgNV\
|
||||
BAMMFlBheW1lbnRSZXF1ZXN0IFRlc3QgQ0EwHhcNMTUwMTExMTgyMTA2WhcNMjUw\
|
||||
MTA4MTgyMTA2WjAhMR8wHQYDVQQDDBZQYXltZW50UmVxdWVzdCBUZXN0IENBMIIB\
|
||||
IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1S9wVLfTplJuT/1OaaBgl/Mb\
|
||||
I392v8S9kHbzYz7B4OTMslaO7piz0v3SO3TKMh0dswjiRdHrIgpO7XdIUQiU/ugg\
|
||||
xDw0kuNehfz1ycaGedlFFtFHTNXqLyIUF3dlwHhQwaomM6RXoJmxLny5BhYHEcmk\
|
||||
yWwr3Cdjd9gAZpblugVJB9C1e40uyL8ao4PHdLzOqO27iSe6riP8SwwisJZEbMaz\
|
||||
AZpgNEEMbIXPJEFvm5HTRXSMtQCOTSZYMFF0M2yrtmlECnz7hWP19b9bcoDzZQB4\
|
||||
ylIsFG/7q2jV7MC/e2STZv+niJiHL08RUdoFpAgzaxMgqj63C7B55HgNDNHJYQID\
|
||||
AQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBGejPxLxj9\
|
||||
+crv6gUeEBMZPiUx7pUgcI22Wm5yymP96B4fwI3Y0DBehq20d76vbWGPN17Z6pH3\
|
||||
ge7PVY1SYqXtS6hXTo4olCm/BZADli+2Bs2xCiaa+Ltve4ufVej+bKJXN/YnrhvO\
|
||||
Kq+klQkuuHywU+GJV/NQeBqToIrSOBgi477NgLFCCCmmx2QWsxHoCFGfuRCBVseT\
|
||||
z2k/tMuALCDXGeZBRPTsGHu1y4cj84swAeoDK5QSQcI+Ub7GKc+zkoj02sdDLiMo\
|
||||
3wokYPcIy47oclhmb4xubHc+y7nF610yZBoC/zgbhbawnZ65hDDWkdQ/SVAnWZD7\
|
||||
9PFfmNnYPTQH\
|
||||
";
|
||||
|
||||
//
|
||||
// This payment request validates directly against the
|
||||
// caCert1 certificate authority.
|
||||
//
|
||||
const char* paymentrequest1_cert1_BASE64 =
|
||||
"\
|
||||
Egt4NTA5K3NoYTI1NhrxAwruAzCCAeowggFToAMCAQICAQEwDQYJKoZIhvcNAQEL\
|
||||
BQAwITEfMB0GA1UEAxMWUGF5bWVudFJlcXVlc3QgVGVzdCBDQTAeFw0xMjEyMTAx\
|
||||
NjM3MjRaFw0yMjEyMDgxNjM3MjRaMEMxGTAXBgNVBAMMEHRlc3RtZXJjaGFudC5v\
|
||||
cmcxJjAkBgNVBAoMHVBheW1lbnQgUmVxdWVzdCBUZXN0IE1lcmNoYW50MIGfMA0G\
|
||||
CSqGSIb3DQEBAQUAA4GNADCBiQKBgQDHkMy8W1u6HsWlSqdWTmMKf54gICxNfxbY\
|
||||
+rcMtAftr62hCYx2d2QiSRd1pCUzmo12IiSX3WxSHwaTnT3MFD6jRx6+zM6XdGar\
|
||||
I2zpYle11ANzu4gAthN17uRQHV2O5QxVtzNaMdKeJLXT2L9tfEdyL++9ZUqoQmdA\
|
||||
YG9ix330hQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4GB\
|
||||
AIkyO99KC68bi9PFRyQQ7nvn5GlQEb3Ca1bRG5+AKN9N5vc8rZ9G2hejtM8wEXni\
|
||||
eGBP+chVMsbTPEHKLrwREn7IvcyCcbAStaklPC3w0B/2idQSHskb6P3X13OR2bTH\
|
||||
a2+6wuhsOZRUrVNr24rM95DKx/eCC6JN1VW+qRPU6fqzIjQSHwiw2wYSGXapFJVg\
|
||||
igPI+6XpExtNLO/i1WFV8ZmoiKwYsuHFiwUqC1VuaXRUZXN0T25lKoABS0j59iMU\
|
||||
Uc9MdIfwsO1BskIET0eJSGNZ7eXb9N62u+qf831PMpEHkmlGpk8rHy92nPcgua/U\
|
||||
Yt8oZMn3QaTZ5A6HjJbc3A73eLylp1a0SwCl+KDMEvDQhqMn1jAVu2v92AH3uB7n\
|
||||
SiWVbw0tX/68iSQEGGfh9n6ee/8Myb3ICdw=\
|
||||
";
|
||||
|
||||
//
|
||||
// Signed, but expired, merchant cert in the request
|
||||
//
|
||||
const char* paymentrequest2_cert1_BASE64 =
|
||||
"\
|
||||
Egt4NTA5K3NoYTI1NhrsAwrpAzCCAeUwggFOoAMCAQICAQMwDQYJKoZIhvcNAQEL\
|
||||
BQAwITEfMB0GA1UEAxMWUGF5bWVudFJlcXVlc3QgVGVzdCBDQTAeFw0xMzAyMjMy\
|
||||
MTI2NDNaFw0xMzAyMjQyMTI2NDNaMD4xHDAaBgNVBAMME2V4cGlyZWRtZXJjaGFu\
|
||||
dC5vcmcxHjAcBgNVBAoMFUV4cGlyZWQgVGVzdCBNZXJjaGFudDCBnzANBgkqhkiG\
|
||||
9w0BAQEFAAOBjQAwgYkCgYEAx5DMvFtbuh7FpUqnVk5jCn+eICAsTX8W2Pq3DLQH\
|
||||
7a+toQmMdndkIkkXdaQlM5qNdiIkl91sUh8Gk509zBQ+o0cevszOl3RmqyNs6WJX\
|
||||
tdQDc7uIALYTde7kUB1djuUMVbczWjHSniS109i/bXxHci/vvWVKqEJnQGBvYsd9\
|
||||
9IUCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQAaU137\
|
||||
j53rvSjlmYZpZ4RWTP7EdD6fl5ZxBeXHytN6DQL33H0eD7OFHt+ofc7E6D7keubl\
|
||||
UfCu+jOvt/MvvPUmtCI9yXZ0dNC4sjyETv+wQpxO0UNZwOM4uegdCzlo6Bi3pD4/\
|
||||
KKLdMkWuUfuPBmoammny74lZaOVr5deKXztTuCI0Eh8IsNsGEhl2qRSVYIoDyPul\
|
||||
6RMbTSzv4tVhVfGZqIisGLLhxYsFKgtVbml0VGVzdFR3byqAAXHuo4nZEPniLpkd\
|
||||
y30TkwBxVgprWJ18a9z/7Py35Qss/JMbOXbnBhJtmJCdIowHRI0aa+zqt3KKKAXi\
|
||||
mm+V4seMgxTcxMS+eDDkiTcB/RtWWSyRcS2ANjFeY0T4SLMwiCL9qWPi03hr8j96\
|
||||
tejrSPOBNSJ3Mi/q5u2Yl4gJZY2b\
|
||||
";
|
||||
|
||||
//
|
||||
// 10-long certificate chain, all intermediates valid
|
||||
//
|
||||
const char* paymentrequest3_cert1_BASE64 =
|
||||
"\
|
||||
Egt4NTA5K3NoYTI1Nhq8JAr/AzCCAfswggFkoAMCAQICAQEwDQYJKoZIhvcNAQEL\
|
||||
BQAwPzEUMBIGA1UEAwwLdGVzdGNhOC5vcmcxJzAlBgNVBAoMHlBheW1lbnQgUmVx\
|
||||
dWVzdCBJbnRlcm1lZGlhdGUgODAeFw0xMzAyMjMyMjQyMzFaFw0yMzAyMjEyMjQy\
|
||||
MzFaMDYxGjAYBgNVBAMMEXRlc3RtZXJjaGFudDgub3JnMRgwFgYDVQQKDA9UZXN0\
|
||||
IE1lcmNoYW50IDgwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMMCHA3hiHbS\
|
||||
TKZ5K9jHRwE8NxkGp3IOx56PDB2diNkldG8XweTcRq7bBm7pdiBt4IVggtfs+6hE\
|
||||
hDYIOecyoAnVzPFTdvQ7KQdQ/fD9YLe6lk+o0edOqutPMyrxLFjSluXxEQyk7fdt\
|
||||
URloMMYfp3p1/hFCboA1rAsQ2RW38hR5AgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8w\
|
||||
DQYJKoZIhvcNAQELBQADgYEAPsdFatnc2RJSpvZsw+nCiPVsllycw5ELglq9vfJz\
|
||||
nJJucRxgzmqI2iuas1ugwbXn0BEIRLK7vMF/qBzQR6M/nTxttah+KEu+okjps9vJ\
|
||||
cIyhfTyGPC5xkHaHZ7sG+UHOFhPw0/kXn0x+pbVgBZ5315axqcp1R+DTSj/whMAr\
|
||||
n0AKiAQwggIEMIIBbaADAgECAgECMA0GCSqGSIb3DQEBCwUAMD8xFDASBgNVBAMM\
|
||||
C3Rlc3RjYTcub3JnMScwJQYDVQQKDB5QYXltZW50IFJlcXVlc3QgSW50ZXJtZWRp\
|
||||
YXRlIDcwHhcNMTMwMjIzMjI0MjMxWhcNMjMwMjIxMjI0MjMxWjA/MRQwEgYDVQQD\
|
||||
DAt0ZXN0Y2E4Lm9yZzEnMCUGA1UECgweUGF5bWVudCBSZXF1ZXN0IEludGVybWVk\
|
||||
aWF0ZSA4MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDexUFfxb1sThvabp7u\
|
||||
dZz59ciThGmmAW0nP4tjrgEACgvWIInr2dZpTHbiQNF34ycsk0le1JD93D7Qb8rd\
|
||||
25OrpaO8XS2Li2zjR9cleixXjSLwV/zv8zJ8yPl/27XL++PDTKBXVpJ8/Syp+9Ty\
|
||||
plV1BqDhqtIHb/QSHEkTQXjeYQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqG\
|
||||
SIb3DQEBCwUAA4GBACMooQVbkbIZ2DaPwHDc4ULwguG3VI2Kzj50UdExmHtzm2S4\
|
||||
MQei+n+HEPjtJAx5OY520+10nfuP+12H2DRLQmWmdvDpeQ/Cv0yavlw4ZRejRFo7\
|
||||
KS83C0wo5rd+qTvvOmAN4UTArWkzYcEUulPdiXnRamb0WQHTeVdIbHVkMormCogE\
|
||||
MIICBDCCAW2gAwIBAgIBAjANBgkqhkiG9w0BAQsFADA/MRQwEgYDVQQDDAt0ZXN0\
|
||||
Y2E2Lm9yZzEnMCUGA1UECgweUGF5bWVudCBSZXF1ZXN0IEludGVybWVkaWF0ZSA2\
|
||||
MB4XDTEzMDIyMzIyNDIzMVoXDTIzMDIyMTIyNDIzMVowPzEUMBIGA1UEAwwLdGVz\
|
||||
dGNhNy5vcmcxJzAlBgNVBAoMHlBheW1lbnQgUmVxdWVzdCBJbnRlcm1lZGlhdGUg\
|
||||
NzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtjBRazrkebXAhXsbjimrMIRm\
|
||||
W/f9SwAHwXfc042keNtl0t2z6XE6UPcR2v/KrssXuCZgodeYxz6IM6lWosCM1xot\
|
||||
C3ChKKFBfVO30reuKBRUxXfKAFqxaG0YOAEzdZkkY9AGhqWloeSmgxpIfhInU0EF\
|
||||
JjCwrJ6IkijBatGoAAECAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0B\
|
||||
AQsFAAOBgQDBRTi1MolmOA0niHYX0A2lN5QWHkCfX0A7GwyoMA3dvM45m/NYd4WB\
|
||||
X+HwfnfYcI6X9jOgNo5OWmc4GGsld0HlxwMYEKISBS9PbSHPBrb3TBOlw5ztQpXZ\
|
||||
91+bOhLux52Fr03sK7v9qExmBM12M8UR2ltpzAMiUgLLMHyPfiWkvQqIBDCCAgQw\
|
||||
ggFtoAMCAQICAQIwDQYJKoZIhvcNAQELBQAwPzEUMBIGA1UEAwwLdGVzdGNhNS5v\
|
||||
cmcxJzAlBgNVBAoMHlBheW1lbnQgUmVxdWVzdCBJbnRlcm1lZGlhdGUgNTAeFw0x\
|
||||
MzAyMjMyMjQyMzBaFw0yMzAyMjEyMjQyMzBaMD8xFDASBgNVBAMMC3Rlc3RjYTYu\
|
||||
b3JnMScwJQYDVQQKDB5QYXltZW50IFJlcXVlc3QgSW50ZXJtZWRpYXRlIDYwgZ8w\
|
||||
DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANJSH3xivX1t9olIdHsznI1aE9SD7t9i\
|
||||
SZJsIB0otoETHZRVv9M9LvyzBNK98ZV+kTOlST7PJgC0d9BQM9sgYApSRq5oqKDM\
|
||||
9FXbOm/yaReAbU3mkFNFw5roTlJ5ThEy0yOGT/DS0YBRaGIvRPRj2DiqDVdCZZ+w\
|
||||
4jo1IYHkZt4FAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQAD\
|
||||
gYEATm6+J1OmbrothO60xALKonWMBKr6hudb4amkFBqKbA9wMeM3jl+I/yKfz/Uf\
|
||||
xWuJ071IhiNv6Gxx5YwNvhUe1xMhUqHv0gpyK1Z47bD+kYS2se5sWNPNo3Y9qZDG\
|
||||
IXiGQxwHmrzaFk79Uy1xsmvsEz42w6hr25Yaw7HkIgrFveoKiAQwggIEMIIBbaAD\
|
||||
AgECAgECMA0GCSqGSIb3DQEBCwUAMD8xFDASBgNVBAMMC3Rlc3RjYTQub3JnMScw\
|
||||
JQYDVQQKDB5QYXltZW50IFJlcXVlc3QgSW50ZXJtZWRpYXRlIDQwHhcNMTMwMjIz\
|
||||
MjI0MjMwWhcNMjMwMjIxMjI0MjMwWjA/MRQwEgYDVQQDDAt0ZXN0Y2E1Lm9yZzEn\
|
||||
MCUGA1UECgweUGF5bWVudCBSZXF1ZXN0IEludGVybWVkaWF0ZSA1MIGfMA0GCSqG\
|
||||
SIb3DQEBAQUAA4GNADCBiQKBgQC7vVUFpxHzz2Tr/xij3k58s8d/BPA0R6D5RXTV\
|
||||
vmhAzc1Zuin4zUKRFs/aCj/0yED8Wu/COfNGF4tVlRNMdl9EcFsxa8XGEL4eAZa+\
|
||||
H/rOHH+7/1EINrrVWhZlUecyhilN8jmCZmqEM3ecuD0NAViqyMrgmaiFmsLoQZpE\
|
||||
GepDUQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4GBAEdJ\
|
||||
Ss8jWiooja3WZzHXeF95QkBJNjIlpDLGcpl4opOYLSuEl9Uxp//LaQQiXuzpj4/I\
|
||||
pkWGQmMy5HOyH1lqDyiMgXpcG8PE0jEQAoEUGZ0QEqB1mZ6BCrYvmUuf/5aSVd8Y\
|
||||
6lKMR3WzFDYU9Zy0nzuHB/3nvp6MeDRQeRMtYvz4CogEMIICBDCCAW2gAwIBAgIB\
|
||||
AjANBgkqhkiG9w0BAQsFADA/MRQwEgYDVQQDDAt0ZXN0Y2EzLm9yZzEnMCUGA1UE\
|
||||
CgweUGF5bWVudCBSZXF1ZXN0IEludGVybWVkaWF0ZSAzMB4XDTEzMDIyMzIyNDIy\
|
||||
OVoXDTIzMDIyMTIyNDIyOVowPzEUMBIGA1UEAwwLdGVzdGNhNC5vcmcxJzAlBgNV\
|
||||
BAoMHlBheW1lbnQgUmVxdWVzdCBJbnRlcm1lZGlhdGUgNDCBnzANBgkqhkiG9w0B\
|
||||
AQEFAAOBjQAwgYkCgYEAxYYo3w2UXiYg6O8b4QgwN/vgreTkiW122Ep/z2TiDrhV\
|
||||
MhfOOiKdwYESPflfnXnVaQQzCGexYTQqsvqvzHSyna5hL0zPTRJxSKmTVrXRsWtp\
|
||||
dCRhjxCGipS3tlQBDi7vb+7SNRIBK4dBjjGzALNk7gMCpy+yM8f6I043jTlmGb0C\
|
||||
AwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQDU+IQxt3Oh\
|
||||
KqaUYWC23+cB2gekvWqwMBnrCNrX/Dp+kjoJKUoR2Fs3qw53raHES4SIhpGT9l9l\
|
||||
rppNQgFe/JMHeYqOZMZO+6kuU0olJanBJ14tPIc7zlMTQ9OfmZ6v07IpyFbsQDtR\
|
||||
hpe80DpuvSFPfJ4fh0WrQf6kn3KDVpGDnAqIBDCCAgQwggFtoAMCAQICAQIwDQYJ\
|
||||
KoZIhvcNAQELBQAwPzEUMBIGA1UEAwwLdGVzdGNhMi5vcmcxJzAlBgNVBAoMHlBh\
|
||||
eW1lbnQgUmVxdWVzdCBJbnRlcm1lZGlhdGUgMjAeFw0xMzAyMjMyMjQyMjlaFw0y\
|
||||
MzAyMjEyMjQyMjlaMD8xFDASBgNVBAMMC3Rlc3RjYTMub3JnMScwJQYDVQQKDB5Q\
|
||||
YXltZW50IFJlcXVlc3QgSW50ZXJtZWRpYXRlIDMwgZ8wDQYJKoZIhvcNAQEBBQAD\
|
||||
gY0AMIGJAoGBANzgVP99Qg98e6NsKEz1v5KqRB7NTBRRsYnBvb/TSWipvMQaCYuE\
|
||||
yk1xG57x++QuASKeR3QHRQJOoAhQaj9JLUhSSv9GQ5PrFLLsOFv7L1tpzXHh2dOB\
|
||||
IW92X2yFRW2s39q+Q21yvN+N8uoKdqXhzRA+dDoXh3cavaVeHX1G+IrlAgMBAAGj\
|
||||
EDAOMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADgYEASTwg84cX+1UhOG9s\
|
||||
ejFV3m34QuI1hPZ+qhqVJlRYUtego8Wng1BburDSwqVAv4ch2wi3c2s4e8J7AXyL\
|
||||
tzSbSQG4RN0oZi0mR8EtTTN+Mix/hBIk79dMZg85+I29uFA6Zj2d9oAhQv2qkHhc\
|
||||
6tcaheNvkQRlCyH68k3iF1Fqf+4KiAQwggIEMIIBbaADAgECAgECMA0GCSqGSIb3\
|
||||
DQEBCwUAMD8xFDASBgNVBAMMC3Rlc3RjYTEub3JnMScwJQYDVQQKDB5QYXltZW50\
|
||||
IFJlcXVlc3QgSW50ZXJtZWRpYXRlIDEwHhcNMTMwMjIzMjI0MjI5WhcNMjMwMjIx\
|
||||
MjI0MjI5WjA/MRQwEgYDVQQDDAt0ZXN0Y2EyLm9yZzEnMCUGA1UECgweUGF5bWVu\
|
||||
dCBSZXF1ZXN0IEludGVybWVkaWF0ZSAyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB\
|
||||
iQKBgQDaV8zhfyQuSf/f+fauMfgs3g/RnWy9yxxUkvQneQQPH3uZzCyk3A6q72ip\
|
||||
TtwNqiibG9455L9A7SaUjGtnpUz0NKT/VWUdqbfCl1PqXjEZbDobbAQ5hxLGOTyL\
|
||||
RQhLIcgeq2/BnmeCqHsC4md04nUp+nBo1HwKyygvK+9sMbCp/wIDAQABoxAwDjAM\
|
||||
BgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4GBACvYyE+PPmWFkbjyRu9LAt8D\
|
||||
crtyYYLRClKSg6tVvutwukLG2l//kDOohYkJtgTqr6LnCIIIwYdXN+4wxugmw4cn\
|
||||
PIZmP6kovxjhhVM95okilor1zniTAo3RN7JDIfTGNgxLdGu1btt7DOFL4zTbeSJM\
|
||||
b8M1JpPftehH+x/VLyuUCuoDMIIB5jCCAU+gAwIBAgIBBTANBgkqhkiG9w0BAQsF\
|
||||
ADAhMR8wHQYDVQQDExZQYXltZW50UmVxdWVzdCBUZXN0IENBMB4XDTEzMDIyMzIy\
|
||||
NDIyOFoXDTIzMDIyMTIyNDIyOFowPzEUMBIGA1UEAwwLdGVzdGNhMS5vcmcxJzAl\
|
||||
BgNVBAoMHlBheW1lbnQgUmVxdWVzdCBJbnRlcm1lZGlhdGUgMTCBnzANBgkqhkiG\
|
||||
9w0BAQEFAAOBjQAwgYkCgYEAo5Vy9H3nA/OOkF5Ap89yfVNSiTay/LYCaB0eALpc\
|
||||
U690U75O9Q3w2M+2AN8wpbbHsJHZMIjEeBRoQfjlYXW1ucQTxWKyT+liu0D25mGX\
|
||||
X27CBXBd4iXTxVII/iX+u3lcjORjoHOBy7QgeIDIIS9y0vYu8eArpjh7m4thrVgI\
|
||||
RtMCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQB9LKcV\
|
||||
JK9sjASNzpQlpUp7nCiw5FSjVY+XMRIKK/kavzlKjZ+InsmmyRVGjDoZi9GrqG9P\
|
||||
VHgLBxi2VtVjmokZoNPqao3OfhqORAubC+JR/JLepM7aDaxDdTHVhSUk4lgNAvi2\
|
||||
6dGY7nZMsnHlPQ2tPp/HvRRiMq1oDjlylc8VTCI2Eh8IsNsGEhl2qRSVYIoDyPul\
|
||||
6RMbTSzv4tVhVfGZqIisGLLhxYsFKg1Vbml0VGVzdFRocmVlKoABn2HTsUQtMNI4\
|
||||
yNvkfkFNka3pRvTUTydJrvyfmEeLzImfM1BWddZjnywku9RToNFZZNgow5QnljmF\
|
||||
chhR/aHOuEMTxmc12K4rNlgYtHCsxLP9zd+6u0cva3TucZ6EzS8PKEib/+r12/52\
|
||||
664NuWA9WtsK7QCFrK2K95PnVCRmWl0=\
|
||||
";
|
||||
|
||||
//
|
||||
// Long certificate chain, with an expired certificate in the middle
|
||||
//
|
||||
const char* paymentrequest4_cert1_BASE64 =
|
||||
"\
|
||||
Egt4NTA5K3NoYTI1NhqeJAr/AzCCAfswggFkoAMCAQICAQEwDQYJKoZIhvcNAQEL\
|
||||
BQAwPzEUMBIGA1UEAwwLdGVzdGNhOC5vcmcxJzAlBgNVBAoMHlBheW1lbnQgUmVx\
|
||||
dWVzdCBJbnRlcm1lZGlhdGUgODAeFw0xMzAyMjMyMjQyMzFaFw0yMzAyMjEyMjQy\
|
||||
MzFaMDYxGjAYBgNVBAMMEXRlc3RtZXJjaGFudDgub3JnMRgwFgYDVQQKDA9UZXN0\
|
||||
IE1lcmNoYW50IDgwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMMCHA3hiHbS\
|
||||
TKZ5K9jHRwE8NxkGp3IOx56PDB2diNkldG8XweTcRq7bBm7pdiBt4IVggtfs+6hE\
|
||||
hDYIOecyoAnVzPFTdvQ7KQdQ/fD9YLe6lk+o0edOqutPMyrxLFjSluXxEQyk7fdt\
|
||||
URloMMYfp3p1/hFCboA1rAsQ2RW38hR5AgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8w\
|
||||
DQYJKoZIhvcNAQELBQADgYEAPsdFatnc2RJSpvZsw+nCiPVsllycw5ELglq9vfJz\
|
||||
nJJucRxgzmqI2iuas1ugwbXn0BEIRLK7vMF/qBzQR6M/nTxttah+KEu+okjps9vJ\
|
||||
cIyhfTyGPC5xkHaHZ7sG+UHOFhPw0/kXn0x+pbVgBZ5315axqcp1R+DTSj/whMAr\
|
||||
n0AKiAQwggIEMIIBbaADAgECAgECMA0GCSqGSIb3DQEBCwUAMD8xFDASBgNVBAMM\
|
||||
C3Rlc3RjYTcub3JnMScwJQYDVQQKDB5QYXltZW50IFJlcXVlc3QgSW50ZXJtZWRp\
|
||||
YXRlIDcwHhcNMTMwMjIzMjI0MjMxWhcNMjMwMjIxMjI0MjMxWjA/MRQwEgYDVQQD\
|
||||
DAt0ZXN0Y2E4Lm9yZzEnMCUGA1UECgweUGF5bWVudCBSZXF1ZXN0IEludGVybWVk\
|
||||
aWF0ZSA4MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDexUFfxb1sThvabp7u\
|
||||
dZz59ciThGmmAW0nP4tjrgEACgvWIInr2dZpTHbiQNF34ycsk0le1JD93D7Qb8rd\
|
||||
25OrpaO8XS2Li2zjR9cleixXjSLwV/zv8zJ8yPl/27XL++PDTKBXVpJ8/Syp+9Ty\
|
||||
plV1BqDhqtIHb/QSHEkTQXjeYQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqG\
|
||||
SIb3DQEBCwUAA4GBACMooQVbkbIZ2DaPwHDc4ULwguG3VI2Kzj50UdExmHtzm2S4\
|
||||
MQei+n+HEPjtJAx5OY520+10nfuP+12H2DRLQmWmdvDpeQ/Cv0yavlw4ZRejRFo7\
|
||||
KS83C0wo5rd+qTvvOmAN4UTArWkzYcEUulPdiXnRamb0WQHTeVdIbHVkMormCogE\
|
||||
MIICBDCCAW2gAwIBAgIBAjANBgkqhkiG9w0BAQsFADA/MRQwEgYDVQQDDAt0ZXN0\
|
||||
Y2E2Lm9yZzEnMCUGA1UECgweUGF5bWVudCBSZXF1ZXN0IEludGVybWVkaWF0ZSA2\
|
||||
MB4XDTEzMDIyMzIyNDIzMVoXDTIzMDIyMTIyNDIzMVowPzEUMBIGA1UEAwwLdGVz\
|
||||
dGNhNy5vcmcxJzAlBgNVBAoMHlBheW1lbnQgUmVxdWVzdCBJbnRlcm1lZGlhdGUg\
|
||||
NzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtjBRazrkebXAhXsbjimrMIRm\
|
||||
W/f9SwAHwXfc042keNtl0t2z6XE6UPcR2v/KrssXuCZgodeYxz6IM6lWosCM1xot\
|
||||
C3ChKKFBfVO30reuKBRUxXfKAFqxaG0YOAEzdZkkY9AGhqWloeSmgxpIfhInU0EF\
|
||||
JjCwrJ6IkijBatGoAAECAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0B\
|
||||
AQsFAAOBgQDBRTi1MolmOA0niHYX0A2lN5QWHkCfX0A7GwyoMA3dvM45m/NYd4WB\
|
||||
X+HwfnfYcI6X9jOgNo5OWmc4GGsld0HlxwMYEKISBS9PbSHPBrb3TBOlw5ztQpXZ\
|
||||
91+bOhLux52Fr03sK7v9qExmBM12M8UR2ltpzAMiUgLLMHyPfiWkvQqIBDCCAgQw\
|
||||
ggFtoAMCAQICAQIwDQYJKoZIhvcNAQELBQAwPzEUMBIGA1UEAwwLdGVzdGNhNS5v\
|
||||
cmcxJzAlBgNVBAoMHlBheW1lbnQgUmVxdWVzdCBJbnRlcm1lZGlhdGUgNTAeFw0x\
|
||||
MzAyMjMyMjQyMzBaFw0yMzAyMjEyMjQyMzBaMD8xFDASBgNVBAMMC3Rlc3RjYTYu\
|
||||
b3JnMScwJQYDVQQKDB5QYXltZW50IFJlcXVlc3QgSW50ZXJtZWRpYXRlIDYwgZ8w\
|
||||
DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANJSH3xivX1t9olIdHsznI1aE9SD7t9i\
|
||||
SZJsIB0otoETHZRVv9M9LvyzBNK98ZV+kTOlST7PJgC0d9BQM9sgYApSRq5oqKDM\
|
||||
9FXbOm/yaReAbU3mkFNFw5roTlJ5ThEy0yOGT/DS0YBRaGIvRPRj2DiqDVdCZZ+w\
|
||||
4jo1IYHkZt4FAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQAD\
|
||||
gYEATm6+J1OmbrothO60xALKonWMBKr6hudb4amkFBqKbA9wMeM3jl+I/yKfz/Uf\
|
||||
xWuJ071IhiNv6Gxx5YwNvhUe1xMhUqHv0gpyK1Z47bD+kYS2se5sWNPNo3Y9qZDG\
|
||||
IXiGQxwHmrzaFk79Uy1xsmvsEz42w6hr25Yaw7HkIgrFveoK6gMwggHmMIIBT6AD\
|
||||
AgECAgEGMA0GCSqGSIb3DQEBCwUAMCExHzAdBgNVBAMTFlBheW1lbnRSZXF1ZXN0\
|
||||
IFRlc3QgQ0EwHhcNMTMwMjIzMjI1OTUxWhcNMTMwMjI0MjI1OTUxWjA/MRQwEgYD\
|
||||
VQQDDAt0ZXN0Y2E1Lm9yZzEnMCUGA1UECgweUGF5bWVudCBSZXF1ZXN0IEludGVy\
|
||||
bWVkaWF0ZSA1MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7vVUFpxHzz2Tr\
|
||||
/xij3k58s8d/BPA0R6D5RXTVvmhAzc1Zuin4zUKRFs/aCj/0yED8Wu/COfNGF4tV\
|
||||
lRNMdl9EcFsxa8XGEL4eAZa+H/rOHH+7/1EINrrVWhZlUecyhilN8jmCZmqEM3ec\
|
||||
uD0NAViqyMrgmaiFmsLoQZpEGepDUQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0G\
|
||||
CSqGSIb3DQEBCwUAA4GBAEmcUEnhua/oiXy1fwScLgMqt+jk9mHRpE6SVsIop23Q\
|
||||
CY2JfpG6RxhMMzzzhGklEGN6cxG0HCi6B3HJx6PYrFEfTB0rW4K6m0Tvx3WpS9mN\
|
||||
uoEuJHLy18ausI/sYAPDHCL+SfBVcqorpaIG2sSpZouRBjRHAyqFAYlwlW87uq5n\
|
||||
CogEMIICBDCCAW2gAwIBAgIBAjANBgkqhkiG9w0BAQsFADA/MRQwEgYDVQQDDAt0\
|
||||
ZXN0Y2EzLm9yZzEnMCUGA1UECgweUGF5bWVudCBSZXF1ZXN0IEludGVybWVkaWF0\
|
||||
ZSAzMB4XDTEzMDIyMzIyNDIyOVoXDTIzMDIyMTIyNDIyOVowPzEUMBIGA1UEAwwL\
|
||||
dGVzdGNhNC5vcmcxJzAlBgNVBAoMHlBheW1lbnQgUmVxdWVzdCBJbnRlcm1lZGlh\
|
||||
dGUgNDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAxYYo3w2UXiYg6O8b4Qgw\
|
||||
N/vgreTkiW122Ep/z2TiDrhVMhfOOiKdwYESPflfnXnVaQQzCGexYTQqsvqvzHSy\
|
||||
na5hL0zPTRJxSKmTVrXRsWtpdCRhjxCGipS3tlQBDi7vb+7SNRIBK4dBjjGzALNk\
|
||||
7gMCpy+yM8f6I043jTlmGb0CAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG\
|
||||
9w0BAQsFAAOBgQDU+IQxt3OhKqaUYWC23+cB2gekvWqwMBnrCNrX/Dp+kjoJKUoR\
|
||||
2Fs3qw53raHES4SIhpGT9l9lrppNQgFe/JMHeYqOZMZO+6kuU0olJanBJ14tPIc7\
|
||||
zlMTQ9OfmZ6v07IpyFbsQDtRhpe80DpuvSFPfJ4fh0WrQf6kn3KDVpGDnAqIBDCC\
|
||||
AgQwggFtoAMCAQICAQIwDQYJKoZIhvcNAQELBQAwPzEUMBIGA1UEAwwLdGVzdGNh\
|
||||
Mi5vcmcxJzAlBgNVBAoMHlBheW1lbnQgUmVxdWVzdCBJbnRlcm1lZGlhdGUgMjAe\
|
||||
Fw0xMzAyMjMyMjQyMjlaFw0yMzAyMjEyMjQyMjlaMD8xFDASBgNVBAMMC3Rlc3Rj\
|
||||
YTMub3JnMScwJQYDVQQKDB5QYXltZW50IFJlcXVlc3QgSW50ZXJtZWRpYXRlIDMw\
|
||||
gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANzgVP99Qg98e6NsKEz1v5KqRB7N\
|
||||
TBRRsYnBvb/TSWipvMQaCYuEyk1xG57x++QuASKeR3QHRQJOoAhQaj9JLUhSSv9G\
|
||||
Q5PrFLLsOFv7L1tpzXHh2dOBIW92X2yFRW2s39q+Q21yvN+N8uoKdqXhzRA+dDoX\
|
||||
h3cavaVeHX1G+IrlAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEL\
|
||||
BQADgYEASTwg84cX+1UhOG9sejFV3m34QuI1hPZ+qhqVJlRYUtego8Wng1BburDS\
|
||||
wqVAv4ch2wi3c2s4e8J7AXyLtzSbSQG4RN0oZi0mR8EtTTN+Mix/hBIk79dMZg85\
|
||||
+I29uFA6Zj2d9oAhQv2qkHhc6tcaheNvkQRlCyH68k3iF1Fqf+4KiAQwggIEMIIB\
|
||||
baADAgECAgECMA0GCSqGSIb3DQEBCwUAMD8xFDASBgNVBAMMC3Rlc3RjYTEub3Jn\
|
||||
MScwJQYDVQQKDB5QYXltZW50IFJlcXVlc3QgSW50ZXJtZWRpYXRlIDEwHhcNMTMw\
|
||||
MjIzMjI0MjI5WhcNMjMwMjIxMjI0MjI5WjA/MRQwEgYDVQQDDAt0ZXN0Y2EyLm9y\
|
||||
ZzEnMCUGA1UECgweUGF5bWVudCBSZXF1ZXN0IEludGVybWVkaWF0ZSAyMIGfMA0G\
|
||||
CSqGSIb3DQEBAQUAA4GNADCBiQKBgQDaV8zhfyQuSf/f+fauMfgs3g/RnWy9yxxU\
|
||||
kvQneQQPH3uZzCyk3A6q72ipTtwNqiibG9455L9A7SaUjGtnpUz0NKT/VWUdqbfC\
|
||||
l1PqXjEZbDobbAQ5hxLGOTyLRQhLIcgeq2/BnmeCqHsC4md04nUp+nBo1HwKyygv\
|
||||
K+9sMbCp/wIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4GB\
|
||||
ACvYyE+PPmWFkbjyRu9LAt8DcrtyYYLRClKSg6tVvutwukLG2l//kDOohYkJtgTq\
|
||||
r6LnCIIIwYdXN+4wxugmw4cnPIZmP6kovxjhhVM95okilor1zniTAo3RN7JDIfTG\
|
||||
NgxLdGu1btt7DOFL4zTbeSJMb8M1JpPftehH+x/VLyuUCuoDMIIB5jCCAU+gAwIB\
|
||||
AgIBBTANBgkqhkiG9w0BAQsFADAhMR8wHQYDVQQDExZQYXltZW50UmVxdWVzdCBU\
|
||||
ZXN0IENBMB4XDTEzMDIyMzIyNDIyOFoXDTIzMDIyMTIyNDIyOFowPzEUMBIGA1UE\
|
||||
AwwLdGVzdGNhMS5vcmcxJzAlBgNVBAoMHlBheW1lbnQgUmVxdWVzdCBJbnRlcm1l\
|
||||
ZGlhdGUgMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAo5Vy9H3nA/OOkF5A\
|
||||
p89yfVNSiTay/LYCaB0eALpcU690U75O9Q3w2M+2AN8wpbbHsJHZMIjEeBRoQfjl\
|
||||
YXW1ucQTxWKyT+liu0D25mGXX27CBXBd4iXTxVII/iX+u3lcjORjoHOBy7QgeIDI\
|
||||
IS9y0vYu8eArpjh7m4thrVgIRtMCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkq\
|
||||
hkiG9w0BAQsFAAOBgQB9LKcVJK9sjASNzpQlpUp7nCiw5FSjVY+XMRIKK/kavzlK\
|
||||
jZ+InsmmyRVGjDoZi9GrqG9PVHgLBxi2VtVjmokZoNPqao3OfhqORAubC+JR/JLe\
|
||||
pM7aDaxDdTHVhSUk4lgNAvi26dGY7nZMsnHlPQ2tPp/HvRRiMq1oDjlylc8VTCI1\
|
||||
Eh8IsNsGEhl2qRSVYIoDyPul6RMbTSzv4tVhVfGZqIisGLLhxYsFKgxVbml0VGVz\
|
||||
dEZvdXIqgAEBE1PP93Tkpif35F+dYmXn9kLA/1djcPjCs2o2rwRMM4Uk356O5dgu\
|
||||
HXQjsfdR58qZQS9CS5DAtRUf0R8+43/wijO/hb49VNaNXmY+/cPHMkahP2aV3tZi\
|
||||
FAyZblLik9A7ZvF+UsjeFQiHB5wzWQvbqk5wQ4yabHIXoYv/E0q+eQ==\
|
||||
";
|
||||
|
||||
//
|
||||
// Validly signed, but by a CA not in our root CA list
|
||||
//
|
||||
const char* paymentrequest5_cert1_BASE64 =
|
||||
"\
|
||||
Egt4NTA5K3NoYTI1NhrxAwruAzCCAeowggFToAMCAQICAQEwDQYJKoZIhvcNAQEL\
|
||||
BQAwITEfMB0GA1UEAxMWUGF5bWVudFJlcXVlc3QgVGVzdCBDQTAeFw0xMzA0MTkx\
|
||||
NzIwMDZaFw0yMzA0MTcxNzIwMDZaMEMxGTAXBgNVBAMMEHRlc3RtZXJjaGFudC5v\
|
||||
cmcxJjAkBgNVBAoMHVBheW1lbnQgUmVxdWVzdCBUZXN0IE1lcmNoYW50MIGfMA0G\
|
||||
CSqGSIb3DQEBAQUAA4GNADCBiQKBgQDhV6Yn47aEEmbl50YLvXoqGEJA51I/40wr\
|
||||
Z6VQGdXYaRqYktagrWDlgYY9h0JQ1bQhm8HgW7ju0R4NaDTXUqxg4HjprF0z3Mfm\
|
||||
/6mmebkLOOptfkVD7ceAteNI7cyuqWGIAZA7D9mV97mXoCAtTlBUycvkmoiClCCS\
|
||||
h0EpF/UTaQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4GB\
|
||||
AGIRwW7I0QvLga+RnJoJSZNZQbtu4rQW3xmoz8WfZMBYXX3QBYg5ftycbdK+/IbP\
|
||||
qozfjGW2AS6DNArvpveSPDTK9+GJBNo1paiNtVqwXkC3Ddscv5AIms1eZGiIOQNC\
|
||||
mUvdLkpoXo48WAer3EGsZ3B15GyNEELc0q9W5yUebba1IjUSHwiw2wYSGXapFJVg\
|
||||
igPI+6XpExtNLO/i1WFV8ZmoiKwYuPvFiwUqDFVuaXRUZXN0Rml2ZSqAAXdsMgdG\
|
||||
ssymvca1S/1KeM3n8Ydi2fi1JUzAAr59xPvNJRUeqCLP9upHn5z7br3P12Oz9A20\
|
||||
5/4wL4ClPRPVnOHgij0bEg+y0tGESqmF1rfOfXDszlo2U92wCxS07kq79YAZJ1Zo\
|
||||
XYh860/Q4wvc7lfiTe+dXBzPKAKhMy91yETY\
|
||||
";
|
||||
|
||||
//
|
||||
// Contains a testnet paytoaddress, so payment request network doesn't match client network
|
||||
//
|
||||
const char* paymentrequest1_cert2_BASE64 =
|
||||
"\
|
||||
Egt4NTA5K3NoYTI1NhrQBArNBDCCAkkwggExoAMCAQICAQEwDQYJKoZIhvcNAQEL\
|
||||
BQAwITEfMB0GA1UEAwwWUGF5bWVudFJlcXVlc3QgVGVzdCBDQTAeFw0xNTAxMTEx\
|
||||
ODIxMDhaFw0yNTAxMDgxODIxMDhaMCExHzAdBgNVBAMMFlBheW1lbnRSZXF1ZXN0\
|
||||
IFRlc3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMsZqzkzeBGo+i2N\
|
||||
mUak3Ciodr1V7S062VOy7N0OQYNDQHYkgDFAUET7cEb5VJaHPv5m3ppTBpU9xBcf\
|
||||
wbHHUt4VjA+mhRmYrl1khjvZM+X8kEqvWn20BtcM9R6r0yIYec8UERDDHBleL/P8\
|
||||
RkxEnVLjYTV9zigCXfMsgYb3EQShAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJ\
|
||||
KoZIhvcNAQELBQADggEBABUJpl3QCqsoDSxAsQdV6zKT4VGV76AzoGj7etQsQY+r\
|
||||
+S26VfWh/fMobEzuxFChr0USgLJ6FoK78hAtoZvt1lrye9yqFv/ig3WLWsJKWHHb\
|
||||
3RT6oR03CIwZXFSUasi08QDVLxafwsU5OMcPLucF3a1lRL1ccYrNgVCCx1+X7Bos\
|
||||
tIgDGRQQ4AyoHTcfVd2hEGeUv7k14mOxFsAp6851yosHq9Q2kwmdH+rHEJbjof87\
|
||||
yyKLagc4owyXBZYkQmkeHWCNqnuRmO5vUsfVb0UUrkD64o7Th/NjwooA7SCiUXl6\
|
||||
dfygT1b7ggpx7GC+sP2DsIM47IAZ55drjqX5u2f+Ba0iPQoEdGVzdBIhCIDWwowE\
|
||||
Ehl2qRQErGqUUwSsaMpDvWIaGnJGNQqi8oisGNeMy6UFKgxKdXN0IFRlc3Rpbmcq\
|
||||
gAFwThsozZxkZxzCn4R8WxNiLFV6m0ye9fEtSbolfaW+EjBMpO03lr/dwNnrclhg\
|
||||
ew+A05xfZztrAt16XKEY7qKJ/eY2nLd0fVAIu/nIt+7/VYVXT83zLrWc150aRS7W\
|
||||
AdJbL3JOJLs6Eyp5zrPbfI8faRttFAdONKDrJgIpuW1E3g==\
|
||||
";
|
||||
|
||||
//
|
||||
// Expired payment request (expires is set to 1 = 1970-01-01 00:00:01)
|
||||
//
|
||||
const char* paymentrequest2_cert2_BASE64 =
|
||||
"\
|
||||
Egt4NTA5K3NoYTI1NhrQBArNBDCCAkkwggExoAMCAQICAQEwDQYJKoZIhvcNAQEL\
|
||||
BQAwITEfMB0GA1UEAwwWUGF5bWVudFJlcXVlc3QgVGVzdCBDQTAeFw0xNTAxMTEx\
|
||||
ODIxMDhaFw0yNTAxMDgxODIxMDhaMCExHzAdBgNVBAMMFlBheW1lbnRSZXF1ZXN0\
|
||||
IFRlc3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMsZqzkzeBGo+i2N\
|
||||
mUak3Ciodr1V7S062VOy7N0OQYNDQHYkgDFAUET7cEb5VJaHPv5m3ppTBpU9xBcf\
|
||||
wbHHUt4VjA+mhRmYrl1khjvZM+X8kEqvWn20BtcM9R6r0yIYec8UERDDHBleL/P8\
|
||||
RkxEnVLjYTV9zigCXfMsgYb3EQShAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJ\
|
||||
KoZIhvcNAQELBQADggEBABUJpl3QCqsoDSxAsQdV6zKT4VGV76AzoGj7etQsQY+r\
|
||||
+S26VfWh/fMobEzuxFChr0USgLJ6FoK78hAtoZvt1lrye9yqFv/ig3WLWsJKWHHb\
|
||||
3RT6oR03CIwZXFSUasi08QDVLxafwsU5OMcPLucF3a1lRL1ccYrNgVCCx1+X7Bos\
|
||||
tIgDGRQQ4AyoHTcfVd2hEGeUv7k14mOxFsAp6851yosHq9Q2kwmdH+rHEJbjof87\
|
||||
yyKLagc4owyXBZYkQmkeHWCNqnuRmO5vUsfVb0UUrkD64o7Th/NjwooA7SCiUXl6\
|
||||
dfygT1b7ggpx7GC+sP2DsIM47IAZ55drjqX5u2f+Ba0iQgoEdGVzdBIgCICt4gQS\
|
||||
GXapFASsapRTBKxoykO9YhoackY1CqLyiKwYiNLUpQUgASoQVGVzdGluZyB0ZXN0\
|
||||
bmV0ISqAATXq9A5nmJgtmee/bQTeHeif4w1YYFPBlKghwx6qbVgXTWnwBJtOQhhV\
|
||||
sZdzbTl95ENR7/Y7VJupW9kDWobCK7zUUhLAzUlwmLlcx6itHw8LTUF5HK+AwsZm\
|
||||
Zs85lISGvOS0NZW/ENa6l+oQRnL87oqVZr/EDGiuqjz6T0ThQi0l\
|
||||
";
|
||||
|
||||
//
|
||||
// Unexpired payment request (expires is set to 0x7FFFFFFFFFFFFFFF = max. int64_t)
|
||||
//
|
||||
const char* paymentrequest3_cert2_BASE64 =
|
||||
"\
|
||||
Egt4NTA5K3NoYTI1NhrQBArNBDCCAkkwggExoAMCAQICAQEwDQYJKoZIhvcNAQEL\
|
||||
BQAwITEfMB0GA1UEAwwWUGF5bWVudFJlcXVlc3QgVGVzdCBDQTAeFw0xNTAxMTEx\
|
||||
ODIxMDhaFw0yNTAxMDgxODIxMDhaMCExHzAdBgNVBAMMFlBheW1lbnRSZXF1ZXN0\
|
||||
IFRlc3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMsZqzkzeBGo+i2N\
|
||||
mUak3Ciodr1V7S062VOy7N0OQYNDQHYkgDFAUET7cEb5VJaHPv5m3ppTBpU9xBcf\
|
||||
wbHHUt4VjA+mhRmYrl1khjvZM+X8kEqvWn20BtcM9R6r0yIYec8UERDDHBleL/P8\
|
||||
RkxEnVLjYTV9zigCXfMsgYb3EQShAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJ\
|
||||
KoZIhvcNAQELBQADggEBABUJpl3QCqsoDSxAsQdV6zKT4VGV76AzoGj7etQsQY+r\
|
||||
+S26VfWh/fMobEzuxFChr0USgLJ6FoK78hAtoZvt1lrye9yqFv/ig3WLWsJKWHHb\
|
||||
3RT6oR03CIwZXFSUasi08QDVLxafwsU5OMcPLucF3a1lRL1ccYrNgVCCx1+X7Bos\
|
||||
tIgDGRQQ4AyoHTcfVd2hEGeUv7k14mOxFsAp6851yosHq9Q2kwmdH+rHEJbjof87\
|
||||
yyKLagc4owyXBZYkQmkeHWCNqnuRmO5vUsfVb0UUrkD64o7Th/NjwooA7SCiUXl6\
|
||||
dfygT1b7ggpx7GC+sP2DsIM47IAZ55drjqX5u2f+Ba0iSgoEdGVzdBIgCICt4gQS\
|
||||
GXapFASsapRTBKxoykO9YhoackY1CqLyiKwYyNfZpQUg//////////9/KhBUZXN0\
|
||||
aW5nIHRlc3RuZXQhKoABNwi8WnMW4aMvbmvorTiiWJLFhofLFnsoWCJnj3rWLnLh\
|
||||
n3w6q/fZ26p50ERL/noxdTUfeFsKnlECkUu/fOcOrqyYDiwvxI0SZ034DleVyFU1\
|
||||
Z3T+X0zcL8oe7bX01Yf+s2V+5JXQXarKnKBrZCGgv2ARjFNSZe7E7vGg5K4Q6Q8=\
|
||||
";
|
||||
|
||||
//
|
||||
// Unexpired payment request (expires is set to 0x8000000000000000 > max. int64_t, allowed uint64)
|
||||
//
|
||||
const char* paymentrequest4_cert2_BASE64 =
|
||||
"\
|
||||
Egt4NTA5K3NoYTI1NhrQBArNBDCCAkkwggExoAMCAQICAQEwDQYJKoZIhvcNAQEL\
|
||||
BQAwITEfMB0GA1UEAwwWUGF5bWVudFJlcXVlc3QgVGVzdCBDQTAeFw0xNTAxMTEx\
|
||||
ODIxMDhaFw0yNTAxMDgxODIxMDhaMCExHzAdBgNVBAMMFlBheW1lbnRSZXF1ZXN0\
|
||||
IFRlc3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMsZqzkzeBGo+i2N\
|
||||
mUak3Ciodr1V7S062VOy7N0OQYNDQHYkgDFAUET7cEb5VJaHPv5m3ppTBpU9xBcf\
|
||||
wbHHUt4VjA+mhRmYrl1khjvZM+X8kEqvWn20BtcM9R6r0yIYec8UERDDHBleL/P8\
|
||||
RkxEnVLjYTV9zigCXfMsgYb3EQShAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJ\
|
||||
KoZIhvcNAQELBQADggEBABUJpl3QCqsoDSxAsQdV6zKT4VGV76AzoGj7etQsQY+r\
|
||||
+S26VfWh/fMobEzuxFChr0USgLJ6FoK78hAtoZvt1lrye9yqFv/ig3WLWsJKWHHb\
|
||||
3RT6oR03CIwZXFSUasi08QDVLxafwsU5OMcPLucF3a1lRL1ccYrNgVCCx1+X7Bos\
|
||||
tIgDGRQQ4AyoHTcfVd2hEGeUv7k14mOxFsAp6851yosHq9Q2kwmdH+rHEJbjof87\
|
||||
yyKLagc4owyXBZYkQmkeHWCNqnuRmO5vUsfVb0UUrkD64o7Th/NjwooA7SCiUXl6\
|
||||
dfygT1b7ggpx7GC+sP2DsIM47IAZ55drjqX5u2f+Ba0iSwoEdGVzdBIgCICt4gQS\
|
||||
GXapFASsapRTBKxoykO9YhoackY1CqLyiKwYt+HZpQUggICAgICAgICAASoQVGVz\
|
||||
dGluZyB0ZXN0bmV0ISqAAXSQG8+GFA18VaKarlYrOz293rNMIub0swKGcQm8jAGX\
|
||||
HSLaRgHfUDeEPr4hydy4dtfu59KNwe2xsHOHu/SpO4L8SrA4Dm9A7SlNBVWdcLbw\
|
||||
d2hj739GDLz0b5KuJ2SG6VknMRQM976w/m2qlq0ccVGaaZ2zMIGfpzL3p6adwx/5\
|
||||
";
|
||||
|
||||
//
|
||||
// Payment request with amount overflow (amount is set to 21000001 BTC)
|
||||
//
|
||||
const char* paymentrequest5_cert2_BASE64 =
|
||||
"\
|
||||
Egt4NTA5K3NoYTI1NhrQBArNBDCCAkkwggExoAMCAQICAQEwDQYJKoZIhvcNAQEL\
|
||||
BQAwITEfMB0GA1UEAwwWUGF5bWVudFJlcXVlc3QgVGVzdCBDQTAeFw0xNTAxMTEx\
|
||||
ODIxMDhaFw0yNTAxMDgxODIxMDhaMCExHzAdBgNVBAMMFlBheW1lbnRSZXF1ZXN0\
|
||||
IFRlc3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMsZqzkzeBGo+i2N\
|
||||
mUak3Ciodr1V7S062VOy7N0OQYNDQHYkgDFAUET7cEb5VJaHPv5m3ppTBpU9xBcf\
|
||||
wbHHUt4VjA+mhRmYrl1khjvZM+X8kEqvWn20BtcM9R6r0yIYec8UERDDHBleL/P8\
|
||||
RkxEnVLjYTV9zigCXfMsgYb3EQShAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJ\
|
||||
KoZIhvcNAQELBQADggEBABUJpl3QCqsoDSxAsQdV6zKT4VGV76AzoGj7etQsQY+r\
|
||||
+S26VfWh/fMobEzuxFChr0USgLJ6FoK78hAtoZvt1lrye9yqFv/ig3WLWsJKWHHb\
|
||||
3RT6oR03CIwZXFSUasi08QDVLxafwsU5OMcPLucF3a1lRL1ccYrNgVCCx1+X7Bos\
|
||||
tIgDGRQQ4AyoHTcfVd2hEGeUv7k14mOxFsAp6851yosHq9Q2kwmdH+rHEJbjof87\
|
||||
yyKLagc4owyXBZYkQmkeHWCNqnuRmO5vUsfVb0UUrkD64o7Th/NjwooA7SCiUXl6\
|
||||
dfygT1b7ggpx7GC+sP2DsIM47IAZ55drjqX5u2f+Ba0iTAoEdGVzdBIkCIDC9P+F\
|
||||
vt0DEhl2qRQErGqUUwSsaMpDvWIaGnJGNQqi8oisGLzcrKYFKhhUZXN0aW5nIGFt\
|
||||
b3VudCBvdmVyZmxvdyEqgAG8S7WEDUC6tCL6q2CTBjop/AitgEy31RL9IqYruytR\
|
||||
iEBFUrBDJZU+UEezGwr7/zoECjo5ZY3PmtZcM2sILNjyweJF6XVzGqTxUw6pN6sW\
|
||||
XR2T3Gy2LzRvhVA25QgGqpz0/juS2BtmNbsZPkN9gMMwKimgzc+PuCzmEKwPK9cQ\
|
||||
YQ==\
|
||||
";
|
||||
|
||||
#endif // BITCOIN_QT_TEST_PAYMENTREQUESTDATA_H
|
|
@ -1,215 +0,0 @@
|
|||
// Copyright (c) 2009-2018 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <qt/test/paymentservertests.h>
|
||||
|
||||
#include <qt/optionsmodel.h>
|
||||
#include <qt/test/paymentrequestdata.h>
|
||||
|
||||
#include <amount.h>
|
||||
#include <interfaces/node.h>
|
||||
#include <random.h>
|
||||
#include <script/script.h>
|
||||
#include <script/standard.h>
|
||||
#include <test/setup_common.h>
|
||||
#include <util/strencodings.h>
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/x509_vfy.h>
|
||||
|
||||
#include <QFileOpenEvent>
|
||||
#include <QTemporaryFile>
|
||||
|
||||
X509 *parse_b64der_cert(const char* cert_data)
|
||||
{
|
||||
std::vector<unsigned char> data = DecodeBase64(cert_data);
|
||||
assert(data.size() > 0);
|
||||
const unsigned char* dptr = data.data();
|
||||
X509 *cert = d2i_X509(nullptr, &dptr, data.size());
|
||||
assert(cert);
|
||||
return cert;
|
||||
}
|
||||
|
||||
//
|
||||
// Test payment request handling
|
||||
//
|
||||
|
||||
static SendCoinsRecipient handleRequest(PaymentServer* server, std::vector<unsigned char>& data)
|
||||
{
|
||||
RecipientCatcher sigCatcher;
|
||||
QObject::connect(server, &PaymentServer::receivedPaymentRequest,
|
||||
&sigCatcher, &RecipientCatcher::getRecipient);
|
||||
|
||||
// Write data to a temp file:
|
||||
QTemporaryFile f;
|
||||
f.open();
|
||||
f.write((const char*)data.data(), data.size());
|
||||
f.close();
|
||||
|
||||
// Create a QObject, install event filter from PaymentServer
|
||||
// and send a file open event to the object
|
||||
QObject object;
|
||||
object.installEventFilter(server);
|
||||
QFileOpenEvent event(f.fileName());
|
||||
// If sending the event fails, this will cause sigCatcher to be empty,
|
||||
// which will lead to a test failure anyway.
|
||||
QCoreApplication::sendEvent(&object, &event);
|
||||
|
||||
QObject::disconnect(server, &PaymentServer::receivedPaymentRequest,
|
||||
&sigCatcher, &RecipientCatcher::getRecipient);
|
||||
|
||||
// Return results from sigCatcher
|
||||
return sigCatcher.recipient;
|
||||
}
|
||||
|
||||
void PaymentServerTests::paymentServerTests()
|
||||
{
|
||||
SSL_library_init();
|
||||
BasicTestingSetup testing_setup(CBaseChainParams::MAIN);
|
||||
auto node = interfaces::MakeNode();
|
||||
OptionsModel optionsModel(*node);
|
||||
PaymentServer* server = new PaymentServer(nullptr, false);
|
||||
X509_STORE* caStore = X509_STORE_new();
|
||||
X509_STORE_add_cert(caStore, parse_b64der_cert(caCert1_BASE64));
|
||||
PaymentServer::LoadRootCAs(caStore);
|
||||
server->setOptionsModel(&optionsModel);
|
||||
server->uiReady();
|
||||
|
||||
std::vector<unsigned char> data;
|
||||
SendCoinsRecipient r;
|
||||
QString merchant;
|
||||
|
||||
// Now feed PaymentRequests to server, and observe signals it produces
|
||||
|
||||
// This payment request validates directly against the
|
||||
// caCert1 certificate authority:
|
||||
data = DecodeBase64(paymentrequest1_cert1_BASE64);
|
||||
r = handleRequest(server, data);
|
||||
r.paymentRequest.getMerchant(caStore, merchant);
|
||||
QCOMPARE(merchant, QString("testmerchant.org"));
|
||||
|
||||
// Signed, but expired, merchant cert in the request:
|
||||
data = DecodeBase64(paymentrequest2_cert1_BASE64);
|
||||
r = handleRequest(server, data);
|
||||
r.paymentRequest.getMerchant(caStore, merchant);
|
||||
QCOMPARE(merchant, QString(""));
|
||||
|
||||
// 10-long certificate chain, all intermediates valid:
|
||||
data = DecodeBase64(paymentrequest3_cert1_BASE64);
|
||||
r = handleRequest(server, data);
|
||||
r.paymentRequest.getMerchant(caStore, merchant);
|
||||
QCOMPARE(merchant, QString("testmerchant8.org"));
|
||||
|
||||
// Long certificate chain, with an expired certificate in the middle:
|
||||
data = DecodeBase64(paymentrequest4_cert1_BASE64);
|
||||
r = handleRequest(server, data);
|
||||
r.paymentRequest.getMerchant(caStore, merchant);
|
||||
QCOMPARE(merchant, QString(""));
|
||||
|
||||
// Validly signed, but by a CA not in our root CA list:
|
||||
data = DecodeBase64(paymentrequest5_cert1_BASE64);
|
||||
r = handleRequest(server, data);
|
||||
r.paymentRequest.getMerchant(caStore, merchant);
|
||||
QCOMPARE(merchant, QString(""));
|
||||
|
||||
// Try again with no root CA's, verifiedMerchant should be empty:
|
||||
caStore = X509_STORE_new();
|
||||
PaymentServer::LoadRootCAs(caStore);
|
||||
data = DecodeBase64(paymentrequest1_cert1_BASE64);
|
||||
r = handleRequest(server, data);
|
||||
r.paymentRequest.getMerchant(caStore, merchant);
|
||||
QCOMPARE(merchant, QString(""));
|
||||
|
||||
// Load second root certificate
|
||||
caStore = X509_STORE_new();
|
||||
X509_STORE_add_cert(caStore, parse_b64der_cert(caCert2_BASE64));
|
||||
PaymentServer::LoadRootCAs(caStore);
|
||||
|
||||
QByteArray byteArray;
|
||||
|
||||
// For the tests below we just need the payment request data from
|
||||
// paymentrequestdata.h parsed + stored in r.paymentRequest.
|
||||
//
|
||||
// These tests require us to bypass the following normal client execution flow
|
||||
// shown below to be able to explicitly just trigger a certain condition!
|
||||
//
|
||||
// handleRequest()
|
||||
// -> PaymentServer::eventFilter()
|
||||
// -> PaymentServer::handleURIOrFile()
|
||||
// -> PaymentServer::readPaymentRequestFromFile()
|
||||
// -> PaymentServer::processPaymentRequest()
|
||||
|
||||
// Contains a testnet paytoaddress, so payment request network doesn't match client network:
|
||||
data = DecodeBase64(paymentrequest1_cert2_BASE64);
|
||||
byteArray = QByteArray((const char*)data.data(), data.size());
|
||||
r.paymentRequest.parse(byteArray);
|
||||
// Ensure the request is initialized, because network "main" is default, even for
|
||||
// uninitialized payment requests and that will fail our test here.
|
||||
QVERIFY(r.paymentRequest.IsInitialized());
|
||||
QCOMPARE(PaymentServer::verifyNetwork(*node, r.paymentRequest.getDetails()), false);
|
||||
|
||||
// Expired payment request (expires is set to 1 = 1970-01-01 00:00:01):
|
||||
data = DecodeBase64(paymentrequest2_cert2_BASE64);
|
||||
byteArray = QByteArray((const char*)data.data(), data.size());
|
||||
r.paymentRequest.parse(byteArray);
|
||||
// Ensure the request is initialized
|
||||
QVERIFY(r.paymentRequest.IsInitialized());
|
||||
// compares 1 < GetTime() == false (treated as expired payment request)
|
||||
QCOMPARE(PaymentServer::verifyExpired(r.paymentRequest.getDetails()), true);
|
||||
|
||||
// Unexpired payment request (expires is set to 0x7FFFFFFFFFFFFFFF = max. int64_t):
|
||||
// 9223372036854775807 (uint64), 9223372036854775807 (int64_t) and -1 (int32_t)
|
||||
// -1 is 1969-12-31 23:59:59 (for a 32 bit time values)
|
||||
data = DecodeBase64(paymentrequest3_cert2_BASE64);
|
||||
byteArray = QByteArray((const char*)data.data(), data.size());
|
||||
r.paymentRequest.parse(byteArray);
|
||||
// Ensure the request is initialized
|
||||
QVERIFY(r.paymentRequest.IsInitialized());
|
||||
// compares 9223372036854775807 < GetTime() == false (treated as unexpired payment request)
|
||||
QCOMPARE(PaymentServer::verifyExpired(r.paymentRequest.getDetails()), false);
|
||||
|
||||
// Unexpired payment request (expires is set to 0x8000000000000000 > max. int64_t, allowed uint64):
|
||||
// 9223372036854775808 (uint64), -9223372036854775808 (int64_t) and 0 (int32_t)
|
||||
// 0 is 1970-01-01 00:00:00 (for a 32 bit time values)
|
||||
data = DecodeBase64(paymentrequest4_cert2_BASE64);
|
||||
byteArray = QByteArray((const char*)data.data(), data.size());
|
||||
r.paymentRequest.parse(byteArray);
|
||||
// Ensure the request is initialized
|
||||
QVERIFY(r.paymentRequest.IsInitialized());
|
||||
// compares -9223372036854775808 < GetTime() == true (treated as expired payment request)
|
||||
QCOMPARE(PaymentServer::verifyExpired(r.paymentRequest.getDetails()), true);
|
||||
|
||||
// Test BIP70 DoS protection:
|
||||
auto randdata = FastRandomContext().randbytes(BIP70_MAX_PAYMENTREQUEST_SIZE + 1);
|
||||
|
||||
// Write data to a temp file:
|
||||
QTemporaryFile tempFile;
|
||||
tempFile.open();
|
||||
tempFile.write((const char*)randdata.data(), randdata.size());
|
||||
tempFile.close();
|
||||
// compares 50001 <= BIP70_MAX_PAYMENTREQUEST_SIZE == false
|
||||
QCOMPARE(PaymentServer::verifySize(tempFile.size()), false);
|
||||
|
||||
// Payment request with amount overflow (amount is set to 21000001 BTC):
|
||||
data = DecodeBase64(paymentrequest5_cert2_BASE64);
|
||||
byteArray = QByteArray((const char*)data.data(), data.size());
|
||||
r.paymentRequest.parse(byteArray);
|
||||
// Ensure the request is initialized
|
||||
QVERIFY(r.paymentRequest.IsInitialized());
|
||||
// Extract address and amount from the request
|
||||
QList<std::pair<CScript, CAmount> > sendingTos = r.paymentRequest.getPayTo();
|
||||
for (const std::pair<CScript, CAmount>& sendingTo : sendingTos) {
|
||||
CTxDestination dest;
|
||||
if (ExtractDestination(sendingTo.first, dest))
|
||||
QCOMPARE(PaymentServer::verifyAmount(sendingTo.second), false);
|
||||
}
|
||||
|
||||
delete server;
|
||||
}
|
||||
|
||||
void RecipientCatcher::getRecipient(const SendCoinsRecipient& r)
|
||||
{
|
||||
recipient = r;
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
// Copyright (c) 2009-2018 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_QT_TEST_PAYMENTSERVERTESTS_H
|
||||
#define BITCOIN_QT_TEST_PAYMENTSERVERTESTS_H
|
||||
|
||||
#include <qt/paymentserver.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QTest>
|
||||
|
||||
class PaymentServerTests : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private Q_SLOTS:
|
||||
void paymentServerTests();
|
||||
};
|
||||
|
||||
// Dummy class to receive paymentserver signals.
|
||||
// If SendCoinsRecipient was a proper QObject, then
|
||||
// we could use QSignalSpy... but it's not.
|
||||
class RecipientCatcher : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public Q_SLOTS:
|
||||
void getRecipient(const SendCoinsRecipient& r);
|
||||
|
||||
public:
|
||||
SendCoinsRecipient recipient;
|
||||
};
|
||||
|
||||
#endif // BITCOIN_QT_TEST_PAYMENTSERVERTESTS_H
|
|
@ -16,9 +16,6 @@
|
|||
|
||||
#ifdef ENABLE_WALLET
|
||||
#include <qt/test/addressbooktests.h>
|
||||
#ifdef ENABLE_BIP70
|
||||
#include <qt/test/paymentservertests.h>
|
||||
#endif // ENABLE_BIP70
|
||||
#include <qt/test/wallettests.h>
|
||||
#endif // ENABLE_WALLET
|
||||
|
||||
|
@ -79,12 +76,6 @@ int main(int argc, char *argv[])
|
|||
if (QTest::qExec(&test1) != 0) {
|
||||
fInvalid = true;
|
||||
}
|
||||
#if defined(ENABLE_WALLET) && defined(ENABLE_BIP70)
|
||||
PaymentServerTests test2;
|
||||
if (QTest::qExec(&test2) != 0) {
|
||||
fInvalid = true;
|
||||
}
|
||||
#endif
|
||||
RPCNestedTests test3;
|
||||
if (QTest::qExec(&test3) != 0) {
|
||||
fInvalid = true;
|
||||
|
|
|
@ -48,7 +48,6 @@ QString TransactionDesc::FormatTxStatus(const interfaces::WalletTx& wtx, const i
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef ENABLE_BIP70
|
||||
// Takes an encoded PaymentRequest as a string and tries to find the Common Name of the X.509 certificate
|
||||
// used to sign the PaymentRequest.
|
||||
bool GetPaymentRequestMerchant(const std::string& pr, QString& merchant)
|
||||
|
@ -76,7 +75,6 @@ bool GetPaymentRequestMerchant(const std::string& pr, QString& merchant)
|
|||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wallet, TransactionRecord *rec, int unit)
|
||||
{
|
||||
|
@ -294,19 +292,11 @@ QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wall
|
|||
if (r.first == "PaymentRequest")
|
||||
{
|
||||
QString merchant;
|
||||
#ifdef ENABLE_BIP70
|
||||
PaymentRequestPlus req;
|
||||
req.parse(QByteArray::fromRawData(r.second.data(), r.second.size()));
|
||||
if (!req.getMerchant(PaymentServer::getCertStore(), merchant)) {
|
||||
merchant.clear();
|
||||
}
|
||||
#else
|
||||
if (!GetPaymentRequestMerchant(r.second, merchant)) {
|
||||
merchant.clear();
|
||||
} else {
|
||||
merchant += tr(" (Certificate was not verified)");
|
||||
}
|
||||
#endif
|
||||
if (!merchant.isNull()) {
|
||||
strHTML += "<b>" + tr("Merchant") + ":</b> " + GUIUtil::HtmlEscape(merchant) + "<br>";
|
||||
}
|
||||
|
|
|
@ -11,9 +11,6 @@
|
|||
#include <qt/forms/ui_helpmessagedialog.h>
|
||||
|
||||
#include <qt/bitcoingui.h>
|
||||
#ifdef ENABLE_BIP70
|
||||
#include <qt/paymentrequestplus.h>
|
||||
#endif
|
||||
|
||||
#include <clientversion.h>
|
||||
#include <init.h>
|
||||
|
|
|
@ -143,31 +143,6 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
|
|||
{
|
||||
if (rcp.fSubtractFeeFromAmount)
|
||||
fSubtractFeeFromAmount = true;
|
||||
|
||||
#ifdef ENABLE_BIP70
|
||||
if (rcp.paymentRequest.IsInitialized())
|
||||
{ // PaymentRequest...
|
||||
CAmount subtotal = 0;
|
||||
const payments::PaymentDetails& details = rcp.paymentRequest.getDetails();
|
||||
for (int i = 0; i < details.outputs_size(); i++)
|
||||
{
|
||||
const payments::Output& out = details.outputs(i);
|
||||
if (out.amount() <= 0) continue;
|
||||
subtotal += out.amount();
|
||||
const unsigned char* scriptStr = (const unsigned char*)out.script().data();
|
||||
CScript scriptPubKey(scriptStr, scriptStr+out.script().size());
|
||||
CAmount nAmount = out.amount();
|
||||
CRecipient recipient = {scriptPubKey, nAmount, rcp.fSubtractFeeFromAmount};
|
||||
vecSend.push_back(recipient);
|
||||
}
|
||||
if (subtotal <= 0)
|
||||
{
|
||||
return InvalidAmount;
|
||||
}
|
||||
total += subtotal;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{ // User-entered bitcoin address / amount:
|
||||
if(!validateAddress(rcp.address))
|
||||
{
|
||||
|
@ -240,21 +215,6 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran
|
|||
std::vector<std::pair<std::string, std::string>> vOrderForm;
|
||||
for (const SendCoinsRecipient &rcp : transaction.getRecipients())
|
||||
{
|
||||
#ifdef ENABLE_BIP70
|
||||
if (rcp.paymentRequest.IsInitialized())
|
||||
{
|
||||
// Make sure any payment requests involved are still valid.
|
||||
if (PaymentServer::verifyExpired(rcp.paymentRequest.getDetails())) {
|
||||
return PaymentRequestExpired;
|
||||
}
|
||||
|
||||
// Store PaymentRequests in wtx.vOrderForm in wallet.
|
||||
std::string value;
|
||||
rcp.paymentRequest.SerializeToString(&value);
|
||||
vOrderForm.emplace_back("PaymentRequest", std::move(value));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (!rcp.message.isEmpty()) // Message from normal bitcoin:URI (bitcoin:123...?message=example)
|
||||
vOrderForm.emplace_back("Message", rcp.message.toStdString());
|
||||
}
|
||||
|
@ -271,10 +231,6 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran
|
|||
// and emit coinsSent signal for each recipient
|
||||
for (const SendCoinsRecipient &rcp : transaction.getRecipients())
|
||||
{
|
||||
// Don't touch the address book when we have a payment request
|
||||
#ifdef ENABLE_BIP70
|
||||
if (!rcp.paymentRequest.IsInitialized())
|
||||
#endif
|
||||
{
|
||||
std::string strAddress = rcp.address.toStdString();
|
||||
CTxDestination dest = DecodeDestination(strAddress);
|
||||
|
|
|
@ -5,18 +5,15 @@
|
|||
#ifndef BITCOIN_QT_WALLETMODEL_H
|
||||
#define BITCOIN_QT_WALLETMODEL_H
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include <config/bitcoin-config.h>
|
||||
#endif
|
||||
|
||||
#include <amount.h>
|
||||
#include <key.h>
|
||||
#include <serialize.h>
|
||||
#include <script/standard.h>
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include <config/bitcoin-config.h>
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_BIP70
|
||||
#include <qt/paymentrequestplus.h>
|
||||
#endif
|
||||
#include <qt/walletmodeltransaction.h>
|
||||
|
||||
#include <interfaces/wallet.h>
|
||||
|
@ -67,15 +64,9 @@ public:
|
|||
CAmount amount;
|
||||
// If from a payment request, this is used for storing the memo
|
||||
QString message;
|
||||
|
||||
#ifdef ENABLE_BIP70
|
||||
// If from a payment request, paymentRequest.IsInitialized() will be true
|
||||
PaymentRequestPlus paymentRequest;
|
||||
#else
|
||||
// If building with BIP70 is disabled, keep the payment request around as
|
||||
// serialized string to ensure load/store is lossless
|
||||
std::string sPaymentRequest;
|
||||
#endif
|
||||
// Empty if no authentication or invalid signature/cert/etc.
|
||||
QString authenticatedMerchant;
|
||||
|
||||
|
@ -91,11 +82,6 @@ public:
|
|||
std::string sAddress = address.toStdString();
|
||||
std::string sLabel = label.toStdString();
|
||||
std::string sMessage = message.toStdString();
|
||||
#ifdef ENABLE_BIP70
|
||||
std::string sPaymentRequest;
|
||||
if (!ser_action.ForRead() && paymentRequest.IsInitialized())
|
||||
paymentRequest.SerializeToString(&sPaymentRequest);
|
||||
#endif
|
||||
std::string sAuthenticatedMerchant = authenticatedMerchant.toStdString();
|
||||
|
||||
READWRITE(this->nVersion);
|
||||
|
@ -111,10 +97,6 @@ public:
|
|||
address = QString::fromStdString(sAddress);
|
||||
label = QString::fromStdString(sLabel);
|
||||
message = QString::fromStdString(sMessage);
|
||||
#ifdef ENABLE_BIP70
|
||||
if (!sPaymentRequest.empty())
|
||||
paymentRequest.parse(QByteArray::fromRawData(sPaymentRequest.data(), sPaymentRequest.size()));
|
||||
#endif
|
||||
authenticatedMerchant = QString::fromStdString(sAuthenticatedMerchant);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,25 +48,6 @@ void WalletModelTransaction::reassignAmounts(int nChangePosRet)
|
|||
for (QList<SendCoinsRecipient>::iterator it = recipients.begin(); it != recipients.end(); ++it)
|
||||
{
|
||||
SendCoinsRecipient& rcp = (*it);
|
||||
|
||||
#ifdef ENABLE_BIP70
|
||||
if (rcp.paymentRequest.IsInitialized())
|
||||
{
|
||||
CAmount subtotal = 0;
|
||||
const payments::PaymentDetails& details = rcp.paymentRequest.getDetails();
|
||||
for (int j = 0; j < details.outputs_size(); j++)
|
||||
{
|
||||
const payments::Output& out = details.outputs(j);
|
||||
if (out.amount() <= 0) continue;
|
||||
if (i == nChangePosRet)
|
||||
i++;
|
||||
subtotal += walletTransaction->vout[i].nValue;
|
||||
i++;
|
||||
}
|
||||
rcp.amount = subtotal;
|
||||
}
|
||||
else // normal recipient (no payment request)
|
||||
#endif
|
||||
{
|
||||
if (i == nChangePosRet)
|
||||
i++;
|
||||
|
|
Loading…
Add table
Reference in a new issue