Merge pull request #4350 from dzutte-cpp/backport_14451_14686_14564_15063_15411

Backport 0.18 PRs #14451, #14686, #14564, #14568,#15063, #15411: deprecate BIP70 and build GUI without BIP70 support
This commit is contained in:
PastaPastaPasta 2021-08-29 13:20:41 -04:00 committed by GitHub
commit b9df9815ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 524 additions and 330 deletions

View File

@ -241,12 +241,12 @@ after_success:
BITCOIN_CONFIG="--enable-reduce-exports --disable-gui-tests" BITCOIN_CONFIG="--enable-reduce-exports --disable-gui-tests"
- stage: test - stage: test
name: '32-bit + dash [GOAL: install]' name: '32-bit + dash [GOAL: install] [GUI: no BIP70]'
env: >- env: >-
HOST=i686-pc-linux-gnu HOST=i686-pc-linux-gnu
PACKAGES="g++-multilib python3-zmq" PACKAGES="g++-multilib python3-zmq"
GOAL="install" GOAL="install"
BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++" BITCOIN_CONFIG="--enable-zmq --with-gui=qt5 --disable-bip70 --enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++"
CONFIG_SHELL="/bin/dash" CONFIG_SHELL="/bin/dash"
- stage: test - stage: test

View File

@ -55,7 +55,7 @@ elif [ "$BUILD_TARGET" = "win64" ]; then
export DIRECT_WINE_EXEC_TESTS=true export DIRECT_WINE_EXEC_TESTS=true
elif [ "$BUILD_TARGET" = "linux32" ]; then elif [ "$BUILD_TARGET" = "linux32" ]; then
export HOST=i686-pc-linux-gnu export HOST=i686-pc-linux-gnu
export BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports --enable-crash-hooks LDFLAGS=-static-libstdc++" export BITCOIN_CONFIG="--enable-zmq --disable-bip70 --enable-glibc-back-compat --enable-reduce-exports --enable-crash-hooks LDFLAGS=-static-libstdc++"
export USE_SHELL="/bin/dash" export USE_SHELL="/bin/dash"
export PYZMQ=true export PYZMQ=true
elif [ "$BUILD_TARGET" = "linux64" ]; then elif [ "$BUILD_TARGET" = "linux64" ]; then

View File

@ -227,6 +227,11 @@ AC_ARG_ENABLE([zmq],
[disable ZMQ notifications])], [disable ZMQ notifications])],
[use_zmq=$enableval], [use_zmq=$enableval],
[use_zmq=yes]) [use_zmq=yes])
AC_ARG_ENABLE([bip70],
[AS_HELP_STRING([--disable-bip70],
[disable BIP70 (payment protocol) support in GUI (enabled by default)])],
[enable_bip70=$enableval],
[enable_bip70=auto])
AC_ARG_WITH([protoc-bindir],[AS_HELP_STRING([--with-protoc-bindir=BIN_DIR],[specify protoc bin path])], [protoc_bin_path=$withval], []) AC_ARG_WITH([protoc-bindir],[AS_HELP_STRING([--with-protoc-bindir=BIN_DIR],[specify protoc bin path])], [protoc_bin_path=$withval], [])
@ -1250,7 +1255,9 @@ if test x$use_pkgconfig = xyes; then
[ [
PKG_CHECK_MODULES([SSL], [libssl],, [AC_MSG_ERROR(openssl not found.)]) PKG_CHECK_MODULES([SSL], [libssl],, [AC_MSG_ERROR(openssl not found.)])
PKG_CHECK_MODULES([CRYPTO], [libcrypto],,[AC_MSG_ERROR(libcrypto not found.)]) PKG_CHECK_MODULES([CRYPTO], [libcrypto],,[AC_MSG_ERROR(libcrypto not found.)])
BITCOIN_QT_CHECK([PKG_CHECK_MODULES([PROTOBUF], [protobuf], [have_protobuf=yes], [BITCOIN_QT_FAIL(libprotobuf 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 if test x$use_qr != xno; then
BITCOIN_QT_CHECK([PKG_CHECK_MODULES([QR], [libqrencode], [have_qrencode=yes], [have_qrencode=no])]) BITCOIN_QT_CHECK([PKG_CHECK_MODULES([QR], [libqrencode], [have_qrencode=yes], [have_qrencode=no])])
fi fi
@ -1310,7 +1317,9 @@ else
esac esac
fi fi
BITCOIN_QT_CHECK(AC_CHECK_LIB([protobuf] ,[main],[PROTOBUF_LIBS=-lprotobuf], BITCOIN_QT_FAIL(libprotobuf not found))) 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 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_LIB([qrencode], [main],[QR_LIBS=-lqrencode], [have_qrencode=no])])
BITCOIN_QT_CHECK([AC_CHECK_HEADER([qrencode.h],, have_qrencode=no)]) BITCOIN_QT_CHECK([AC_CHECK_HEADER([qrencode.h],, have_qrencode=no)])
@ -1379,7 +1388,11 @@ AM_CONDITIONAL([EMBEDDED_UNIVALUE],[test x$need_bundled_univalue = xyes])
AC_SUBST(UNIVALUE_CFLAGS) AC_SUBST(UNIVALUE_CFLAGS)
AC_SUBST(UNIVALUE_LIBS) AC_SUBST(UNIVALUE_LIBS)
BITCOIN_QT_PATH_PROGS([PROTOC], [protoc],$protoc_bin_path)
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 dashd]) AC_MSG_CHECKING([whether to build dashd])
AM_CONDITIONAL([BUILD_BITCOIND], [test x$build_bitcoind = xyes]) AM_CONDITIONAL([BUILD_BITCOIND], [test x$build_bitcoind = xyes])
@ -1493,6 +1506,23 @@ if test x$bitcoin_enable_qt != xno; then
else else
AC_MSG_RESULT([no]) AC_MSG_RESULT([no])
fi 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 fi
AM_CONDITIONAL([ENABLE_ZMQ], [test "x$use_zmq" = "xyes"]) AM_CONDITIONAL([ENABLE_ZMQ], [test "x$use_zmq" = "xyes"])
@ -1537,6 +1567,7 @@ AM_CONDITIONAL([ENABLE_TESTS],[test x$BUILD_TEST = xyes])
AM_CONDITIONAL([ENABLE_FUZZ],[test x$enable_fuzz = xyes]) AM_CONDITIONAL([ENABLE_FUZZ],[test x$enable_fuzz = xyes])
AM_CONDITIONAL([ENABLE_QT],[test x$bitcoin_enable_qt = 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_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([ENABLE_BENCH],[test x$use_bench = xyes])
AM_CONDITIONAL([USE_QRCODE], [test x$use_qr = xyes]) AM_CONDITIONAL([USE_QRCODE], [test x$use_qr = xyes])
AM_CONDITIONAL([USE_LCOV],[test x$use_lcov = xyes]) AM_CONDITIONAL([USE_LCOV],[test x$use_lcov = xyes])
@ -1671,6 +1702,7 @@ echo "Options used to compile and link:"
echo " with wallet = $enable_wallet" echo " with wallet = $enable_wallet"
echo " with gui / qt = $bitcoin_enable_qt" echo " with gui / qt = $bitcoin_enable_qt"
if test x$bitcoin_enable_qt != xno; then if test x$bitcoin_enable_qt != xno; then
echo " with bip70 = $enable_bip70"
echo " with qr = $use_qr" echo " with qr = $use_qr"
fi fi
echo " with zmq = $use_zmq" echo " with zmq = $use_zmq"

View File

@ -804,9 +804,11 @@ endif
osx_debug: $(bin_PROGRAMS) osx_debug: $(bin_PROGRAMS)
for i in $(bin_PROGRAMS); do mkdir -p $$i.dSYM/Contents/Resources/DWARF && $(DSYMUTIL_FLAT) -o $$i.dSYM/Contents/Resources/DWARF/$$(basename $$i) $$i &> /dev/null ; done for i in $(bin_PROGRAMS); do mkdir -p $$i.dSYM/Contents/Resources/DWARF && $(DSYMUTIL_FLAT) -o $$i.dSYM/Contents/Resources/DWARF/$$(basename $$i) $$i &> /dev/null ; done
if ENABLE_BIP70
%.pb.cc %.pb.h: %.proto %.pb.cc %.pb.h: %.proto
@test -f $(PROTOC) @test -f $(PROTOC)
$(AM_V_GEN) $(PROTOC) --cpp_out=$(@D) --proto_path=$(<D) $< $(AM_V_GEN) $(PROTOC) --cpp_out=$(@D) --proto_path=$(<D) $<
endif
if EMBEDDED_LEVELDB if EMBEDDED_LEVELDB
include Makefile.crc32c.include include Makefile.crc32c.include

View File

@ -121,9 +121,15 @@ QT_QRC = qt/dash.qrc
QT_QRC_LOCALE_CPP = qt/qrc_dash_locale.cpp QT_QRC_LOCALE_CPP = qt/qrc_dash_locale.cpp
QT_QRC_LOCALE = qt/dash_locale.qrc QT_QRC_LOCALE = qt/dash_locale.qrc
if ENABLE_BIP70
PROTOBUF_CC = qt/paymentrequest.pb.cc PROTOBUF_CC = qt/paymentrequest.pb.cc
PROTOBUF_H = qt/paymentrequest.pb.h PROTOBUF_H = qt/paymentrequest.pb.h
PROTOBUF_PROTO = qt/paymentrequest.proto PROTOBUF_PROTO = qt/paymentrequest.proto
else
PROTOBUF_CC =
PROTOBUF_H =
PROTOBUF_PROTO =
endif
BITCOIN_QT_H = \ BITCOIN_QT_H = \
qt/addressbookpage.h \ qt/addressbookpage.h \
@ -253,7 +259,6 @@ BITCOIN_QT_WALLET_CPP = \
qt/masternodelist.cpp \ qt/masternodelist.cpp \
qt/openuridialog.cpp \ qt/openuridialog.cpp \
qt/overviewpage.cpp \ qt/overviewpage.cpp \
qt/paymentrequestplus.cpp \
qt/paymentserver.cpp \ qt/paymentserver.cpp \
qt/qrdialog.cpp \ qt/qrdialog.cpp \
qt/receivecoinsdialog.cpp \ qt/receivecoinsdialog.cpp \
@ -273,13 +278,19 @@ BITCOIN_QT_WALLET_CPP = \
qt/walletmodeltransaction.cpp \ qt/walletmodeltransaction.cpp \
qt/walletview.cpp qt/walletview.cpp
BITCOIN_QT_WALLET_BIP70_CPP = \
qt/paymentrequestplus.cpp
BITCOIN_QT_CPP = $(BITCOIN_QT_BASE_CPP) BITCOIN_QT_CPP = $(BITCOIN_QT_BASE_CPP)
if TARGET_WINDOWS if TARGET_WINDOWS
BITCOIN_QT_CPP += $(BITCOIN_QT_WINDOWS_CPP) BITCOIN_QT_CPP += $(BITCOIN_QT_WINDOWS_CPP)
endif endif
if ENABLE_WALLET if ENABLE_WALLET
BITCOIN_QT_CPP += $(BITCOIN_QT_WALLET_CPP) BITCOIN_QT_CPP += $(BITCOIN_QT_WALLET_CPP)
endif if ENABLE_BIP70
BITCOIN_QT_CPP += $(BITCOIN_QT_WALLET_BIP70_CPP)
endif # ENABLE_BIP70
endif # ENABLE_WALLET
RES_IMAGES = \ RES_IMAGES = \
qt/res/images/arrow_down_dark.png \ qt/res/images/arrow_down_dark.png \
@ -408,8 +419,16 @@ if ENABLE_ZMQ
qt_dash_qt_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS) qt_dash_qt_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS)
endif endif
qt_dash_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) \ qt_dash_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) \
$(BACKTRACE_LIB) $(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \ $(BACKTRACE_LIB) $(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \
$(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(BLS_LIBS) $(GMP_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(BLS_LIBS) $(GMP_LIBS)
if ENABLE_BIP70
qt_dash_qt_LDADD += $(SSL_LIBS)
else
if TARGET_WINDOWS
qt_dash_qt_LDADD += $(SSL_LIBS)
endif
endif
qt_dash_qt_LDADD += $(CRYPTO_LIBS)
qt_dash_qt_LDFLAGS = $(LDFLAGS_WRAP_EXCEPTIONS) $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) qt_dash_qt_LDFLAGS = $(LDFLAGS_WRAP_EXCEPTIONS) $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
qt_dash_qt_LIBTOOLFLAGS = $(AM_LIBTOOLFLAGS) --tag CXX qt_dash_qt_LIBTOOLFLAGS = $(AM_LIBTOOLFLAGS) --tag CXX

View File

@ -15,9 +15,12 @@ TEST_QT_MOC_CPP = \
if ENABLE_WALLET if ENABLE_WALLET
TEST_QT_MOC_CPP += \ TEST_QT_MOC_CPP += \
qt/test/moc_addressbooktests.cpp \ qt/test/moc_addressbooktests.cpp \
qt/test/moc_paymentservertests.cpp \
qt/test/moc_wallettests.cpp qt/test/moc_wallettests.cpp
endif if ENABLE_BIP70
TEST_QT_MOC_CPP += \
qt/test/moc_paymentservertests.cpp
endif # ENABLE_BIP70
endif # ENABLE_WALLET
TEST_QT_H = \ TEST_QT_H = \
qt/test/addressbooktests.h \ qt/test/addressbooktests.h \
@ -51,10 +54,13 @@ qt_test_test_dash_qt_SOURCES = \
if ENABLE_WALLET if ENABLE_WALLET
qt_test_test_dash_qt_SOURCES += \ qt_test_test_dash_qt_SOURCES += \
qt/test/addressbooktests.cpp \ qt/test/addressbooktests.cpp \
qt/test/paymentservertests.cpp \
qt/test/wallettests.cpp \ qt/test/wallettests.cpp \
wallet/test/wallet_test_fixture.cpp wallet/test/wallet_test_fixture.cpp
endif if ENABLE_BIP70
qt_test_test_dash_qt_SOURCES += \
qt/test/paymentservertests.cpp
endif # ENABLE_BIP70
endif # ENABLE_WALLET
nodist_qt_test_test_dash_qt_SOURCES = $(TEST_QT_MOC_CPP) nodist_qt_test_test_dash_qt_SOURCES = $(TEST_QT_MOC_CPP)

View File

@ -3,10 +3,15 @@
// Distributed under the MIT software license, see the accompanying // Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#if defined(HAVE_CONFIG_H)
#include <config/dash-config.h>
#endif
#include <qt/coincontroldialog.h> #include <qt/coincontroldialog.h>
#include <qt/forms/ui_coincontroldialog.h> #include <qt/forms/ui_coincontroldialog.h>
#include <qt/addresstablemodel.h> #include <qt/addresstablemodel.h>
#include <base58.h>
#include <qt/bitcoinunits.h> #include <qt/bitcoinunits.h>
#include <qt/guiutil.h> #include <qt/guiutil.h>
#include <qt/optionsmodel.h> #include <qt/optionsmodel.h>

View File

@ -441,8 +441,10 @@ void BitcoinApplication::addWallet(WalletModel* walletModel)
window->setCurrentWallet(walletModel); window->setCurrentWallet(walletModel);
} }
#ifdef ENABLE_BIP70
connect(walletModel, &WalletModel::coinsSent, connect(walletModel, &WalletModel::coinsSent,
paymentServer, &PaymentServer::fetchPaymentACK); paymentServer, &PaymentServer::fetchPaymentACK);
#endif
connect(walletModel, &WalletModel::unload, this, &BitcoinApplication::removeWallet); connect(walletModel, &WalletModel::unload, this, &BitcoinApplication::removeWallet);
m_wallet_models.push_back(walletModel); m_wallet_models.push_back(walletModel);
@ -469,7 +471,9 @@ void BitcoinApplication::initializeResult(bool success)
// Log this only after AppInitMain finishes, as then logging setup is guaranteed complete // Log this only after AppInitMain finishes, as then logging setup is guaranteed complete
qWarning() << "Platform customization:" << gArgs.GetArg("-uiplatform", BitcoinGUI::DEFAULT_UIPLATFORM).c_str(); qWarning() << "Platform customization:" << gArgs.GetArg("-uiplatform", BitcoinGUI::DEFAULT_UIPLATFORM).c_str();
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
#ifdef ENABLE_BIP70
PaymentServer::LoadRootCAs(); PaymentServer::LoadRootCAs();
#endif
paymentServer->setOptionsModel(optionsModel); paymentServer->setOptionsModel(optionsModel);
#endif #endif
@ -540,7 +544,7 @@ WId BitcoinApplication::getMainWinId() const
static void SetupUIArgs() static void SetupUIArgs()
{ {
#ifdef ENABLE_WALLET #if defined(ENABLE_WALLET) && defined(ENABLE_BIP70)
gArgs.AddArg("-allowselfsignedrootcertificates", strprintf("Allow self signed root certificates (default: %u)", DEFAULT_SELFSIGNED_ROOTCERTS), true, OptionsCategory::GUI); gArgs.AddArg("-allowselfsignedrootcertificates", strprintf("Allow self signed root certificates (default: %u)", DEFAULT_SELFSIGNED_ROOTCERTS), true, OptionsCategory::GUI);
#endif #endif
gArgs.AddArg("-choosedatadir", strprintf(QObject::tr("Choose data directory on startup (default: %u)").toStdString(), DEFAULT_CHOOSE_DATADIR), false, OptionsCategory::GUI); gArgs.AddArg("-choosedatadir", strprintf(QObject::tr("Choose data directory on startup (default: %u)").toStdString(), DEFAULT_CHOOSE_DATADIR), false, OptionsCategory::GUI);

View File

@ -3,6 +3,10 @@
// Distributed under the MIT software license, see the accompanying // Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#if defined(HAVE_CONFIG_H)
#include <config/dash-config.h>
#endif
#include <qt/paymentserver.h> #include <qt/paymentserver.h>
#include <qt/bitcoinunits.h> #include <qt/bitcoinunits.h>
@ -46,6 +50,7 @@
const int BITCOIN_IPC_CONNECT_TIMEOUT = 1000; // milliseconds const int BITCOIN_IPC_CONNECT_TIMEOUT = 1000; // milliseconds
const QString BITCOIN_IPC_PREFIX("dash:"); const QString BITCOIN_IPC_PREFIX("dash:");
#ifdef ENABLE_BIP70
// BIP70 payment protocol messages // BIP70 payment protocol messages
const char* BIP70_MESSAGE_PAYMENTACK = "PaymentACK"; const char* BIP70_MESSAGE_PAYMENTACK = "PaymentACK";
const char* BIP70_MESSAGE_PAYMENTREQUEST = "PaymentRequest"; const char* BIP70_MESSAGE_PAYMENTREQUEST = "PaymentRequest";
@ -53,21 +58,7 @@ const char* BIP70_MESSAGE_PAYMENTREQUEST = "PaymentRequest";
const char* BIP71_MIMETYPE_PAYMENT = "application/dash-payment"; const char* BIP71_MIMETYPE_PAYMENT = "application/dash-payment";
const char* BIP71_MIMETYPE_PAYMENTACK = "application/dash-paymentack"; const char* BIP71_MIMETYPE_PAYMENTACK = "application/dash-paymentack";
const char* BIP71_MIMETYPE_PAYMENTREQUEST = "application/dash-paymentrequest"; const char* BIP71_MIMETYPE_PAYMENTREQUEST = "application/dash-paymentrequest";
#endif
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;
}
// //
// Create a name that is unique for: // Create a name that is unique for:
@ -94,6 +85,337 @@ static QString ipcServerName()
static QSet<QString> savedPaymentRequests; static QSet<QString> savedPaymentRequests;
//
// Sending to the server is done synchronously, at startup.
// If the server isn't already running, startup continues,
// and the items in savedPaymentRequest will be handled
// when uiReady() is called.
//
// Warning: ipcSendCommandLine() is called early in init,
// so don't use "Q_EMIT message()", but "QMessageBox::"!
//
void PaymentServer::ipcParseCommandLine(interfaces::Node& node, int argc, char* argv[])
{
for (int i = 1; i < argc; i++)
{
QString arg(argv[i]);
if (arg.startsWith("-"))
continue;
// If the dash: URI contains a payment request, we are not able to detect the
// network as that would require fetching and parsing the payment request.
// That means clicking such an URI which contains a testnet payment request
// will start a mainnet instance and throw a "wrong network" error.
if (arg.startsWith(BITCOIN_IPC_PREFIX, Qt::CaseInsensitive)) // dash: URI
{
if (savedPaymentRequests.contains(arg)) continue;
savedPaymentRequests.insert(arg);
SendCoinsRecipient r;
if (GUIUtil::parseBitcoinURI(arg, &r) && !r.address.isEmpty())
{
auto tempChainParams = CreateChainParams(CBaseChainParams::MAIN);
if (IsValidDestinationString(r.address.toStdString(), *tempChainParams)) {
node.selectParams(CBaseChainParams::MAIN);
} else {
tempChainParams = CreateChainParams(CBaseChainParams::TESTNET);
if (IsValidDestinationString(r.address.toStdString(), *tempChainParams)) {
node.selectParams(CBaseChainParams::TESTNET);
}
}
}
}
#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
}
}
//
// Sending to the server is done synchronously, at startup.
// If the server isn't already running, startup continues,
// and the items in savedPaymentRequest will be handled
// when uiReady() is called.
//
bool PaymentServer::ipcSendCommandLine()
{
bool fResult = false;
for (const QString& r : savedPaymentRequests)
{
QLocalSocket* socket = new QLocalSocket();
socket->connectToServer(ipcServerName(), QIODevice::WriteOnly);
if (!socket->waitForConnected(BITCOIN_IPC_CONNECT_TIMEOUT))
{
delete socket;
socket = nullptr;
return false;
}
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_0);
out << r;
out.device()->seek(0);
socket->write(block);
socket->flush();
socket->waitForBytesWritten(BITCOIN_IPC_CONNECT_TIMEOUT);
socket->disconnectFromServer();
delete socket;
socket = nullptr;
fResult = true;
}
return fResult;
}
PaymentServer::PaymentServer(QObject* parent, bool startLocalServer) :
QObject(parent),
saveURIs(true),
uriServer(nullptr),
#ifdef ENABLE_BIP70
netManager(nullptr),
#endif
optionsModel(nullptr)
{
#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 dash: links
// other OSes: helpful when dealing with payment request files
if (parent)
parent->installEventFilter(this);
QString name = ipcServerName();
// Clean up old socket leftover from a crash:
QLocalServer::removeServer(name);
if (startLocalServer)
{
uriServer = new QLocalServer(this);
if (!uriServer->listen(name)) {
// constructor is called early in init, so don't use "Q_EMIT message()" here
QMessageBox::critical(nullptr, tr("Payment request error"),
tr("Cannot start dash: click-to-pay handler"));
}
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 dash: URIs and PaymentRequest mime types.
// Also used by paymentservertests.cpp and when opening a payment request file
// via "Open URI..." menu entry.
//
bool PaymentServer::eventFilter(QObject *object, QEvent *event)
{
if (event->type() == QEvent::FileOpen) {
QFileOpenEvent *fileEvent = static_cast<QFileOpenEvent*>(event);
if (!fileEvent->file().isEmpty())
handleURIOrFile(fileEvent->file());
else if (!fileEvent->url().isEmpty())
handleURIOrFile(fileEvent->url().toString());
return true;
}
return QObject::eventFilter(object, event);
}
void PaymentServer::uiReady()
{
#ifdef ENABLE_BIP70
initNetManager();
#endif
saveURIs = false;
for (const QString& s : savedPaymentRequests)
{
handleURIOrFile(s);
}
savedPaymentRequests.clear();
}
void PaymentServer::handleURIOrFile(const QString& s)
{
if (saveURIs)
{
savedPaymentRequests.insert(s);
return;
}
if (s.startsWith("dash://", Qt::CaseInsensitive))
{
Q_EMIT message(tr("URI handling"), tr("'dash://' is not a valid URI. Use 'dash:' instead."),
CClientUIInterface::MSG_ERROR);
}
else if (s.startsWith(BITCOIN_IPC_PREFIX, Qt::CaseInsensitive)) // dash: URI
{
QUrlQuery uri((QUrl(s)));
#ifdef ENABLE_BIP70
if (uri.hasQueryItem("r")) // payment request URI
{
/* We have no intention of removing BIP70 support.
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."),
CClientUIInterface::ICON_WARNING);
}
#endif
Q_EMIT message(tr("URI handling"), tr("Invalid payment address %1").arg(recipient.address),
CClientUIInterface::MSG_ERROR);
}
else
Q_EMIT receivedPaymentRequest(recipient);
}
else
Q_EMIT message(tr("URI handling"),
tr("URI cannot be parsed! This can be caused by an invalid Dash address or malformed URI parameters."),
CClientUIInterface::ICON_WARNING);
return;
}
}
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."),
CClientUIInterface::ICON_WARNING);
#endif
}
}
void PaymentServer::handleURIConnection()
{
QLocalSocket *clientConnection = uriServer->nextPendingConnection();
while (clientConnection->bytesAvailable() < (int)sizeof(quint32))
clientConnection->waitForReadyRead();
connect(clientConnection, &QLocalSocket::disconnected, clientConnection, &QLocalSocket::deleteLater);
QDataStream in(clientConnection);
in.setVersion(QDataStream::Qt_4_0);
if (clientConnection->bytesAvailable() < (int)sizeof(quint16)) {
return;
}
QString msg;
in >> msg;
handleURIOrFile(msg);
}
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) 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); 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);
@ -154,6 +476,7 @@ void PaymentServer::LoadRootCAs(X509_STORE* _store)
ReportInvalidCertificate(cert); ReportInvalidCertificate(cert);
continue; continue;
} }
QByteArray certData = cert.toDer(); QByteArray certData = cert.toDer();
const unsigned char *data = (const unsigned char *)certData.data(); const unsigned char *data = (const unsigned char *)certData.data();
@ -182,176 +505,6 @@ void PaymentServer::LoadRootCAs(X509_STORE* _store)
// "certificate stapling" with server-side caching is more efficient // "certificate stapling" with server-side caching is more efficient
} }
//
// Sending to the server is done synchronously, at startup.
// If the server isn't already running, startup continues,
// and the items in savedPaymentRequest will be handled
// when uiReady() is called.
//
// Warning: ipcSendCommandLine() is called early in init,
// so don't use "Q_EMIT message()", but "QMessageBox::"!
//
void PaymentServer::ipcParseCommandLine(interfaces::Node& node, int argc, char* argv[])
{
for (int i = 1; i < argc; i++)
{
QString arg(argv[i]);
if (arg.startsWith("-"))
continue;
// If the dash: URI contains a payment request, we are not able to detect the
// network as that would require fetching and parsing the payment request.
// That means clicking such an URI which contains a testnet payment request
// will start a mainnet instance and throw a "wrong network" error.
if (arg.startsWith(BITCOIN_IPC_PREFIX, Qt::CaseInsensitive)) // dash: URI
{
if (savedPaymentRequests.contains(arg)) continue;
savedPaymentRequests.insert(arg);
SendCoinsRecipient r;
if (GUIUtil::parseBitcoinURI(arg, &r) && !r.address.isEmpty())
{
auto tempChainParams = CreateChainParams(CBaseChainParams::MAIN);
if (IsValidDestinationString(r.address.toStdString(), *tempChainParams)) {
node.selectParams(CBaseChainParams::MAIN);
} else {
tempChainParams = CreateChainParams(CBaseChainParams::TESTNET);
if (IsValidDestinationString(r.address.toStdString(), *tempChainParams)) {
node.selectParams(CBaseChainParams::TESTNET);
}
}
}
}
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;
}
}
}
//
// Sending to the server is done synchronously, at startup.
// If the server isn't already running, startup continues,
// and the items in savedPaymentRequest will be handled
// when uiReady() is called.
//
bool PaymentServer::ipcSendCommandLine()
{
bool fResult = false;
for (const QString& r : savedPaymentRequests)
{
QLocalSocket* socket = new QLocalSocket();
socket->connectToServer(ipcServerName(), QIODevice::WriteOnly);
if (!socket->waitForConnected(BITCOIN_IPC_CONNECT_TIMEOUT))
{
delete socket;
socket = nullptr;
return false;
}
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_0);
out << r;
out.device()->seek(0);
socket->write(block);
socket->flush();
socket->waitForBytesWritten(BITCOIN_IPC_CONNECT_TIMEOUT);
socket->disconnectFromServer();
delete socket;
socket = nullptr;
fResult = true;
}
return fResult;
}
PaymentServer::PaymentServer(QObject* parent, bool startLocalServer) :
QObject(parent),
saveURIs(true),
uriServer(nullptr),
netManager(nullptr),
optionsModel(nullptr)
{
// 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;
// Install global event filter to catch QFileOpenEvents
// on Mac: sent when you click dash: links
// other OSes: helpful when dealing with payment request files
if (parent)
parent->installEventFilter(this);
QString name = ipcServerName();
// Clean up old socket leftover from a crash:
QLocalServer::removeServer(name);
if (startLocalServer)
{
uriServer = new QLocalServer(this);
if (!uriServer->listen(name)) {
// constructor is called early in init, so don't use "Q_EMIT message()" here
QMessageBox::critical(nullptr, tr("Payment request error"),
tr("Cannot start dash: click-to-pay handler"));
}
else {
connect(uriServer, &QLocalServer::newConnection, this, &PaymentServer::handleURIConnection);
connect(this, &PaymentServer::receivedPaymentACK, this, &PaymentServer::handlePaymentACK);
}
}
}
PaymentServer::~PaymentServer()
{
google::protobuf::ShutdownProtobufLibrary();
}
//
// OSX-specific way of handling dash: URIs and PaymentRequest mime types.
// Also used by paymentservertests.cpp and when opening a payment request file
// via "Open URI..." menu entry.
//
bool PaymentServer::eventFilter(QObject *object, QEvent *event)
{
if (event->type() == QEvent::FileOpen) {
QFileOpenEvent *fileEvent = static_cast<QFileOpenEvent*>(event);
if (!fileEvent->file().isEmpty())
handleURIOrFile(fileEvent->file());
else if (!fileEvent->url().isEmpty())
handleURIOrFile(fileEvent->url().toString());
return true;
}
return QObject::eventFilter(object, event);
}
void PaymentServer::initNetManager() void PaymentServer::initNetManager()
{ {
if (!optionsModel) if (!optionsModel)
@ -376,114 +529,6 @@ void PaymentServer::initNetManager()
connect(netManager, &QNetworkAccessManager::sslErrors, this, &PaymentServer::reportSslErrors); connect(netManager, &QNetworkAccessManager::sslErrors, this, &PaymentServer::reportSslErrors);
} }
void PaymentServer::uiReady()
{
initNetManager();
saveURIs = false;
for (const QString& s : savedPaymentRequests)
{
handleURIOrFile(s);
}
savedPaymentRequests.clear();
}
void PaymentServer::handleURIOrFile(const QString& s)
{
if (saveURIs)
{
savedPaymentRequests.insert(s);
return;
}
if (s.startsWith("dash://", Qt::CaseInsensitive))
{
Q_EMIT message(tr("URI handling"), tr("'dash://' is not a valid URI. Use 'dash:' instead."),
CClientUIInterface::MSG_ERROR);
}
else if (s.startsWith(BITCOIN_IPC_PREFIX, Qt::CaseInsensitive)) // dash: URI
{
QUrlQuery uri((QUrl(s)));
if (uri.hasQueryItem("r")) // payment request URI
{
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 // normal URI
{
SendCoinsRecipient recipient;
if (GUIUtil::parseBitcoinURI(s, &recipient))
{
if (!IsValidDestinationString(recipient.address.toStdString())) {
Q_EMIT message(tr("URI handling"), tr("Invalid payment address %1").arg(recipient.address),
CClientUIInterface::MSG_ERROR);
}
else
Q_EMIT receivedPaymentRequest(recipient);
}
else
Q_EMIT message(tr("URI handling"),
tr("URI cannot be parsed! This can be caused by an invalid Dash address or malformed URI parameters."),
CClientUIInterface::ICON_WARNING);
return;
}
}
if (QFile::exists(s)) // payment request file
{
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;
}
}
void PaymentServer::handleURIConnection()
{
QLocalSocket *clientConnection = uriServer->nextPendingConnection();
while (clientConnection->bytesAvailable() < (int)sizeof(quint32))
clientConnection->waitForReadyRead();
connect(clientConnection, &QLocalSocket::disconnected, clientConnection, &QLocalSocket::deleteLater);
QDataStream in(clientConnection);
in.setVersion(QDataStream::Qt_4_0);
if (clientConnection->bytesAvailable() < (int)sizeof(quint16)) {
return;
}
QString msg;
in >> msg;
handleURIOrFile(msg);
}
// //
// Warning: readPaymentRequestFromFile() is used in ipcSendCommandLine() // Warning: readPaymentRequestFromFile() is used in ipcSendCommandLine()
// so don't use "Q_EMIT message()", but "QMessageBox::"! // so don't use "Q_EMIT message()", but "QMessageBox::"!
@ -732,11 +777,6 @@ void PaymentServer::reportSslErrors(QNetworkReply* reply, const QList<QSslError>
Q_EMIT message(tr("Network request error"), errString, CClientUIInterface::MSG_ERROR); Q_EMIT message(tr("Network request error"), errString, CClientUIInterface::MSG_ERROR);
} }
void PaymentServer::setOptionsModel(OptionsModel *_optionsModel)
{
this->optionsModel = _optionsModel;
}
void PaymentServer::handlePaymentACK(const QString& paymentACKMsg) void PaymentServer::handlePaymentACK(const QString& paymentACKMsg)
{ {
// currently we don't further process or store the paymentACK message // currently we don't further process or store the paymentACK message
@ -795,3 +835,4 @@ X509_STORE* PaymentServer::getCertStore()
{ {
return certStore.get(); return certStore.get();
} }
#endif

View File

@ -32,7 +32,13 @@
// sends them to the server. // sends them to the server.
// //
#if defined(HAVE_CONFIG_H)
#include <config/dash-config.h>
#endif
#ifdef ENABLE_BIP70
#include <qt/paymentrequestplus.h> #include <qt/paymentrequestplus.h>
#endif
#include <qt/walletmodel.h> #include <qt/walletmodel.h>
#include <QObject> #include <QObject>
@ -73,6 +79,10 @@ public:
explicit PaymentServer(QObject* parent, bool startLocalServer = true); explicit PaymentServer(QObject* parent, bool startLocalServer = true);
~PaymentServer(); ~PaymentServer();
// OptionsModel is used for getting proxy settings and display unit
void setOptionsModel(OptionsModel *optionsModel);
#ifdef ENABLE_BIP70
// Load root certificate authorities. Pass nullptr (default) // Load root certificate authorities. Pass nullptr (default)
// to read from the file specified in the -rootcertificates setting, // to read from the file specified in the -rootcertificates setting,
// or, if that's not set, to use the system default root certificates. // or, if that's not set, to use the system default root certificates.
@ -83,9 +93,6 @@ public:
// Return certificate store // Return certificate store
static X509_STORE* getCertStore(); static X509_STORE* getCertStore();
// OptionsModel is used for getting proxy settings and display unit
void setOptionsModel(OptionsModel *optionsModel);
// Verify that the payment request network matches the client network // Verify that the payment request network matches the client network
static bool verifyNetwork(interfaces::Node& node, const payments::PaymentDetails& requestDetails); static bool verifyNetwork(interfaces::Node& node, const payments::PaymentDetails& requestDetails);
// Verify if the payment request is expired // Verify if the payment request is expired
@ -94,33 +101,40 @@ public:
static bool verifySize(qint64 requestSize); static bool verifySize(qint64 requestSize);
// Verify the payment request amount is valid // Verify the payment request amount is valid
static bool verifyAmount(const CAmount& requestAmount); static bool verifyAmount(const CAmount& requestAmount);
#endif
Q_SIGNALS: Q_SIGNALS:
// Fired when a valid payment request is received // Fired when a valid payment request is received
void receivedPaymentRequest(SendCoinsRecipient); void receivedPaymentRequest(SendCoinsRecipient);
// Fired when a valid PaymentACK is received
void receivedPaymentACK(const QString &paymentACKMsg);
// Fired when a message should be reported to the user // Fired when a message should be reported to the user
void message(const QString &title, const QString &message, unsigned int style); 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: public Q_SLOTS:
// Signal this when the main window's UI is ready // Signal this when the main window's UI is ready
// to display payment requests to the user // to display payment requests to the user
void uiReady(); void uiReady();
// Submit Payment message to a merchant, get back PaymentACK:
void fetchPaymentACK(WalletModel* walletModel, const SendCoinsRecipient& recipient, QByteArray transaction);
// Handle an incoming URI, URI with local file scheme or file // Handle an incoming URI, URI with local file scheme or file
void handleURIOrFile(const QString& s); 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: private Q_SLOTS:
void handleURIConnection(); void handleURIConnection();
#ifdef ENABLE_BIP70
void netRequestFinished(QNetworkReply*); void netRequestFinished(QNetworkReply*);
void reportSslErrors(QNetworkReply*, const QList<QSslError> &); void reportSslErrors(QNetworkReply*, const QList<QSslError> &);
void handlePaymentACK(const QString& paymentACKMsg); void handlePaymentACK(const QString& paymentACKMsg);
#endif
protected: protected:
// Constructor registers this on the parent QApplication to // Constructor registers this on the parent QApplication to
@ -128,19 +142,19 @@ protected:
bool eventFilter(QObject *object, QEvent *event) override; bool eventFilter(QObject *object, QEvent *event) override;
private: private:
bool saveURIs; // true during startup
QLocalServer* uriServer;
OptionsModel *optionsModel;
#ifdef ENABLE_BIP70
static bool readPaymentRequestFromFile(const QString& filename, PaymentRequestPlus& request); static bool readPaymentRequestFromFile(const QString& filename, PaymentRequestPlus& request);
bool processPaymentRequest(const PaymentRequestPlus& request, SendCoinsRecipient& recipient); bool processPaymentRequest(const PaymentRequestPlus& request, SendCoinsRecipient& recipient);
void fetchRequest(const QUrl& url); void fetchRequest(const QUrl& url);
// Setup networking // Setup networking
void initNetManager(); void initNetManager();
bool saveURIs; // true during startup
QLocalServer* uriServer;
QNetworkAccessManager* netManager; // Used to fetch payment requests QNetworkAccessManager* netManager; // Used to fetch payment requests
#endif
OptionsModel *optionsModel;
}; };
#endif // BITCOIN_QT_PAYMENTSERVER_H #endif // BITCOIN_QT_PAYMENTSERVER_H

View File

@ -3,6 +3,10 @@
// Distributed under the MIT software license, see the accompanying // Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#if defined(HAVE_CONFIG_H)
#include <config/dash-config.h>
#endif
#include <qt/sendcoinsdialog.h> #include <qt/sendcoinsdialog.h>
#include <qt/forms/ui_sendcoinsdialog.h> #include <qt/forms/ui_sendcoinsdialog.h>
@ -318,7 +322,9 @@ void SendCoinsDialog::send(QList<SendCoinsRecipient> recipients)
QString recipientElement; QString recipientElement;
recipientElement = "<br />"; recipientElement = "<br />";
#ifdef ENABLE_BIP70
if (!rcp.paymentRequest.IsInitialized()) // normal payment if (!rcp.paymentRequest.IsInitialized()) // normal payment
#endif
{ {
if(rcp.label.length() > 0) // label with address if(rcp.label.length() > 0) // label with address
{ {
@ -330,6 +336,7 @@ void SendCoinsDialog::send(QList<SendCoinsRecipient> recipients)
recipientElement.append(tr("%1 to %2").arg(amount, address)); recipientElement.append(tr("%1 to %2").arg(amount, address));
} }
} }
#ifdef ENABLE_BIP70
else if(!rcp.authenticatedMerchant.isEmpty()) // authenticated payment request else if(!rcp.authenticatedMerchant.isEmpty()) // authenticated payment request
{ {
recipientElement.append(tr("%1 to %2").arg(amount, GUIUtil::HtmlEscape(rcp.authenticatedMerchant))); recipientElement.append(tr("%1 to %2").arg(amount, GUIUtil::HtmlEscape(rcp.authenticatedMerchant)));
@ -338,6 +345,7 @@ void SendCoinsDialog::send(QList<SendCoinsRecipient> recipients)
{ {
recipientElement.append(tr("%1 to %2").arg(amount, address)); recipientElement.append(tr("%1 to %2").arg(amount, address));
} }
#endif
formatted.append(recipientElement); formatted.append(recipientElement);
} }

View File

@ -3,6 +3,10 @@
// Distributed under the MIT software license, see the accompanying // Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#if defined(HAVE_CONFIG_H)
#include <config/dash-config.h>
#endif
#include <qt/sendcoinsentry.h> #include <qt/sendcoinsentry.h>
#include <qt/forms/ui_sendcoinsentry.h> #include <qt/forms/ui_sendcoinsentry.h>
@ -140,9 +144,11 @@ bool SendCoinsEntry::validate(interfaces::Node& node)
// Check input validity // Check input validity
bool retval = true; bool retval = true;
#ifdef ENABLE_BIP70
// Skip checks for payment request // Skip checks for payment request
if (recipient.paymentRequest.IsInitialized()) if (recipient.paymentRequest.IsInitialized())
return retval; return retval;
#endif
if (!model->validateAddress(ui->payTo->text())) if (!model->validateAddress(ui->payTo->text()))
{ {
@ -173,9 +179,11 @@ bool SendCoinsEntry::validate(interfaces::Node& node)
SendCoinsRecipient SendCoinsEntry::getValue() SendCoinsRecipient SendCoinsEntry::getValue()
{ {
#ifdef ENABLE_BIP70
// Payment request // Payment request
if (recipient.paymentRequest.IsInitialized()) if (recipient.paymentRequest.IsInitialized())
return recipient; return recipient;
#endif
// Normal payment // Normal payment
recipient.address = ui->payTo->text(); recipient.address = ui->payTo->text();
@ -203,6 +211,7 @@ void SendCoinsEntry::setValue(const SendCoinsRecipient &value)
{ {
recipient = value; recipient = value;
#ifdef ENABLE_BIP70
if (recipient.paymentRequest.IsInitialized()) // payment request if (recipient.paymentRequest.IsInitialized()) // payment request
{ {
if (recipient.authenticatedMerchant.isEmpty()) // unauthenticated if (recipient.authenticatedMerchant.isEmpty()) // unauthenticated
@ -223,6 +232,7 @@ void SendCoinsEntry::setValue(const SendCoinsRecipient &value)
} }
} }
else // normal payment else // normal payment
#endif
{ {
// message // message
ui->messageTextLabel->setText(recipient.message); ui->messageTextLabel->setText(recipient.message);

View File

@ -2,7 +2,13 @@
// Distributed under the MIT software license, see the accompanying // Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#if defined(HAVE_CONFIG_H)
#include <config/dash-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 #include <qt/paymentrequestplus.h> // this includes protobuf's port.h which defines its own bswap macos
#endif
#include <qt/test/compattests.h> #include <qt/test/compattests.h>

View File

@ -16,9 +16,11 @@
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
#include <qt/test/addressbooktests.h> #include <qt/test/addressbooktests.h>
#ifdef ENABLE_BIP70
#include <qt/test/paymentservertests.h> #include <qt/test/paymentservertests.h>
#endif // ENABLE_BIP70
#include <qt/test/wallettests.h> #include <qt/test/wallettests.h>
#endif #endif // ENABLE_WALLET
#include <QApplication> #include <QApplication>
#include <QObject> #include <QObject>
@ -76,7 +78,7 @@ int main(int argc, char *argv[])
if (QTest::qExec(&test1) != 0) { if (QTest::qExec(&test1) != 0) {
fInvalid = true; fInvalid = true;
} }
#ifdef ENABLE_WALLET #if defined(ENABLE_WALLET) && defined(ENABLE_BIP70)
PaymentServerTests test2; PaymentServerTests test2;
if (QTest::qExec(&test2) != 0) { if (QTest::qExec(&test2) != 0) {
fInvalid = true; fInvalid = true;

View File

@ -3,6 +3,7 @@
#include <coinjoin/coinjoin-client.h> #include <coinjoin/coinjoin-client.h>
#include <interfaces/node.h> #include <interfaces/node.h>
#include <base58.h>
#include <qt/bitcoinamountfield.h> #include <qt/bitcoinamountfield.h>
#include <qt/callback.h> #include <qt/callback.h>
#include <qt/clientmodel.h> #include <qt/clientmodel.h>

View File

@ -3,6 +3,10 @@
// Distributed under the MIT software license, see the accompanying // Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifdef HAVE_CONFIG_H
#include <config/dash-config.h>
#endif
#include <qt/transactiondesc.h> #include <qt/transactiondesc.h>
#include <qt/bitcoinunits.h> #include <qt/bitcoinunits.h>
@ -267,6 +271,7 @@ QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wall
if (r.first == "Message") if (r.first == "Message")
strHTML += "<br><b>" + tr("Message") + ":</b><br>" + GUIUtil::HtmlEscape(r.second, true) + "<br>"; strHTML += "<br><b>" + tr("Message") + ":</b><br>" + GUIUtil::HtmlEscape(r.second, true) + "<br>";
#ifdef ENABLE_BIP70
// //
// PaymentRequest info: // PaymentRequest info:
// //
@ -281,6 +286,7 @@ QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wall
strHTML += "<b>" + tr("Merchant") + ":</b> " + GUIUtil::HtmlEscape(merchant) + "<br>"; strHTML += "<b>" + tr("Merchant") + ":</b> " + GUIUtil::HtmlEscape(merchant) + "<br>";
} }
} }
#endif
if (wtx.is_coinbase) if (wtx.is_coinbase)
{ {

View File

@ -16,7 +16,9 @@
#include <qt/guiconstants.h> #include <qt/guiconstants.h>
#include <qt/guiutil.h> #include <qt/guiutil.h>
#include <qt/intro.h> #include <qt/intro.h>
#ifdef ENABLE_BIP70
#include <qt/paymentrequestplus.h> #include <qt/paymentrequestplus.h>
#endif
#include <clientversion.h> #include <clientversion.h>
#include <init.h> #include <init.h>

View File

@ -3,6 +3,10 @@
// Distributed under the MIT software license, see the accompanying // Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#if defined(HAVE_CONFIG_H)
#include <config/dash-config.h>
#endif
#include <qt/walletmodel.h> #include <qt/walletmodel.h>
#include <qt/addresstablemodel.h> #include <qt/addresstablemodel.h>
@ -182,6 +186,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
if (rcp.fSubtractFeeFromAmount) if (rcp.fSubtractFeeFromAmount)
fSubtractFeeFromAmount = true; fSubtractFeeFromAmount = true;
#ifdef ENABLE_BIP70
if (rcp.paymentRequest.IsInitialized()) if (rcp.paymentRequest.IsInitialized())
{ // PaymentRequest... { // PaymentRequest...
CAmount subtotal = 0; CAmount subtotal = 0;
@ -204,6 +209,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
total += subtotal; total += subtotal;
} }
else else
#endif
{ // User-entered dash address / amount: { // User-entered dash address / amount:
if(!validateAddress(rcp.address)) if(!validateAddress(rcp.address))
{ {
@ -273,6 +279,7 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran
std::vector<std::pair<std::string, std::string>> vOrderForm; std::vector<std::pair<std::string, std::string>> vOrderForm;
for (const SendCoinsRecipient &rcp : transaction.getRecipients()) for (const SendCoinsRecipient &rcp : transaction.getRecipients())
{ {
#ifdef ENABLE_BIP70
if (rcp.paymentRequest.IsInitialized()) if (rcp.paymentRequest.IsInitialized())
{ {
// Make sure any payment requests involved are still valid. // Make sure any payment requests involved are still valid.
@ -285,7 +292,9 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran
rcp.paymentRequest.SerializeToString(&value); rcp.paymentRequest.SerializeToString(&value);
vOrderForm.emplace_back("PaymentRequest", std::move(value)); vOrderForm.emplace_back("PaymentRequest", std::move(value));
} }
else if (!rcp.message.isEmpty()) // Message from normal dash:URI (dash:XyZ...?message=example) else
#endif
if (!rcp.message.isEmpty()) // Message from normal dash:URI (dash:XyZ...?message=example)
vOrderForm.emplace_back("Message", rcp.message.toStdString()); vOrderForm.emplace_back("Message", rcp.message.toStdString());
} }
@ -309,7 +318,9 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran
for (const SendCoinsRecipient &rcp : transaction.getRecipients()) for (const SendCoinsRecipient &rcp : transaction.getRecipients())
{ {
// Don't touch the address book when we have a payment request // Don't touch the address book when we have a payment request
#ifdef ENABLE_BIP70
if (!rcp.paymentRequest.IsInitialized()) if (!rcp.paymentRequest.IsInitialized())
#endif
{ {
std::string strAddress = rcp.address.toStdString(); std::string strAddress = rcp.address.toStdString();
CTxDestination dest = DecodeDestination(strAddress); CTxDestination dest = DecodeDestination(strAddress);

View File

@ -10,7 +10,13 @@
#include <serialize.h> #include <serialize.h>
#include <script/standard.h> #include <script/standard.h>
#if defined(HAVE_CONFIG_H)
#include <config/dash-config.h>
#endif
#ifdef ENABLE_BIP70
#include <qt/paymentrequestplus.h> #include <qt/paymentrequestplus.h>
#endif
#include <qt/walletmodeltransaction.h> #include <qt/walletmodeltransaction.h>
#include <interfaces/wallet.h> #include <interfaces/wallet.h>
@ -60,8 +66,14 @@ public:
// If from a payment request, this is used for storing the memo // If from a payment request, this is used for storing the memo
QString message; QString message;
#ifdef ENABLE_BIP70
// If from a payment request, paymentRequest.IsInitialized() will be true // If from a payment request, paymentRequest.IsInitialized() will be true
PaymentRequestPlus paymentRequest; 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. // Empty if no authentication or invalid signature/cert/etc.
QString authenticatedMerchant; QString authenticatedMerchant;
@ -73,16 +85,20 @@ public:
SERIALIZE_METHODS(SendCoinsRecipient, obj) SERIALIZE_METHODS(SendCoinsRecipient, obj)
{ {
std::string address_str, label_str, message_str, auth_merchant_str, sPaymentRequest; std::string address_str, label_str, message_str, auth_merchant_str, sPaymentRequest;
#ifdef ENABLE_BIP70
PaymentRequestPlus paymentRequest; PaymentRequestPlus paymentRequest;
#endif
SER_WRITE(obj, address_str = obj.address.toStdString()); SER_WRITE(obj, address_str = obj.address.toStdString());
SER_WRITE(obj, label_str = obj.label.toStdString()); SER_WRITE(obj, label_str = obj.label.toStdString());
SER_WRITE(obj, message_str = obj.message.toStdString()); SER_WRITE(obj, message_str = obj.message.toStdString());
SER_WRITE(obj, auth_merchant_str = obj.authenticatedMerchant.toStdString()); SER_WRITE(obj, auth_merchant_str = obj.authenticatedMerchant.toStdString());
#ifdef ENABLE_BIP70
SER_WRITE(obj, paymentRequest = obj.paymentRequest); SER_WRITE(obj, paymentRequest = obj.paymentRequest);
if (paymentRequest.IsInitialized()) { if (paymentRequest.IsInitialized()) {
paymentRequest.SerializeToString(&sPaymentRequest); paymentRequest.SerializeToString(&sPaymentRequest);
} }
#endif
READWRITE(obj.nVersion, address_str, label_str, obj.amount, message_str, sPaymentRequest, auth_merchant_str); READWRITE(obj.nVersion, address_str, label_str, obj.amount, message_str, sPaymentRequest, auth_merchant_str);
@ -90,9 +106,11 @@ public:
SER_READ(obj, obj.label = QString::fromStdString(label_str)); SER_READ(obj, obj.label = QString::fromStdString(label_str));
SER_READ(obj, obj.message = QString::fromStdString(message_str)); SER_READ(obj, obj.message = QString::fromStdString(message_str));
SER_READ(obj, obj.authenticatedMerchant = QString::fromStdString(auth_merchant_str)); SER_READ(obj, obj.authenticatedMerchant = QString::fromStdString(auth_merchant_str));
#ifdef ENABLE_BIP70
if (!sPaymentRequest.empty()) { if (!sPaymentRequest.empty()) {
SER_READ(obj, obj.paymentRequest.parse(QByteArray::fromRawData(sPaymentRequest.data(), sPaymentRequest.size()))); SER_READ(obj, obj.paymentRequest.parse(QByteArray::fromRawData(sPaymentRequest.data(), sPaymentRequest.size())));
} }
#endif
} }
}; };

View File

@ -2,6 +2,10 @@
// Distributed under the MIT software license, see the accompanying // Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifdef HAVE_CONFIG_H
#include <config/dash-config.h>
#endif
#include <qt/walletmodeltransaction.h> #include <qt/walletmodeltransaction.h>
#include <interfaces/node.h> #include <interfaces/node.h>
@ -45,6 +49,7 @@ void WalletModelTransaction::reassignAmounts()
{ {
SendCoinsRecipient& rcp = (*it); SendCoinsRecipient& rcp = (*it);
#ifdef ENABLE_BIP70
if (rcp.paymentRequest.IsInitialized()) if (rcp.paymentRequest.IsInitialized())
{ {
CAmount subtotal = 0; CAmount subtotal = 0;
@ -65,6 +70,7 @@ void WalletModelTransaction::reassignAmounts()
rcp.amount = subtotal; rcp.amount = subtotal;
} }
else // normal recipient (no payment request) else // normal recipient (no payment request)
#endif
{ {
for (const auto& txout : wtx->get().vout) { for (const auto& txout : wtx->get().vout) {
CScript scriptPubKey = GetScriptForDestination(DecodeDestination(rcp.address.toStdString())); CScript scriptPubKey = GetScriptForDestination(DecodeDestination(rcp.address.toStdString()));

View File

@ -8,6 +8,7 @@
#include <qt/walletmodel.h> #include <qt/walletmodel.h>
#include <memory> #include <memory>
#include <amount.h>
#include <QObject> #include <QObject>