diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -713,7 +713,10 @@ } #ifdef ENABLE_WALLET // Parse URIs on command line -- this can affect Params() - PaymentServer::ipcParseCommandLine(argc, argv); + std::string network = PaymentServer::ipcParseCommandLine(argc, argv); + if (!network.empty()) { + SelectParams(network); + } #endif QScopedPointer networkStyle(NetworkStyle::instantiate( diff --git a/src/qt/paymentserver.h b/src/qt/paymentserver.h --- a/src/qt/paymentserver.h +++ b/src/qt/paymentserver.h @@ -57,7 +57,7 @@ public: // Parse URIs on command line // Returns false on error - static void ipcParseCommandLine(int argc, char *argv[]); + static std::string ipcParseCommandLine(int argc, char *argv[]); // Returns true if there were URIs on the command line which were // successfully sent to an already-running process. diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -17,6 +17,7 @@ #include "wallet/wallet.h" #include +#include #include @@ -199,6 +200,35 @@ // "certificate stapling" with server-side caching is more efficient } +static std::pair ipcParseURI(const QString &arg) { + + std::vector networks = {CBaseChainParams::MAIN, + CBaseChainParams::TESTNET, + CBaseChainParams::REGTEST}; + + for (std::string net : networks) { + const CChainParams ¶ms(Params(net)); + const QString scheme = GUIUtil::bitcoinURIScheme(params, true); + + if (!arg.startsWith(scheme + ":", Qt::CaseInsensitive)) { + continue; + } + + SendCoinsRecipient r; + if (!GUIUtil::parseBitcoinURI(scheme, arg, &r)) { + return {false, std::string{}}; + } + + if (!IsValidDestinationString(r.address.toStdString(), params)) { + return {false, std::string{}}; + } + + savedPaymentRequests.append(arg); + return {true, net}; + } + return {false, std::string{}}; +} + // // Sending to the server is done synchronously, at startup. // If the server isn't already running, startup continues, and the items in @@ -207,34 +237,18 @@ // Warning: ipcSendCommandLine() is called early in init, so don't use "Q_EMIT // message()", but "QMessageBox::"! // -void PaymentServer::ipcParseCommandLine(int argc, char *argv[]) { +std::string PaymentServer::ipcParseCommandLine(int argc, char *argv[]) { + + std::string network; + for (int i = 1; i < argc; i++) { QString arg(argv[i]); if (arg.startsWith("-")) continue; - QString scheme = GUIUtil::bitcoinURIScheme(Params(), false); - // If the bitcoincash: 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(scheme + ":", - Qt::CaseInsensitive)) // bitcoincash: URI - { - savedPaymentRequests.append(arg); - - SendCoinsRecipient r; - if (GUIUtil::parseBitcoinURI(scheme, arg, &r) && - !r.address.isEmpty()) { - if (IsValidDestinationString(r.address.toStdString(), - Params(CBaseChainParams::MAIN))) { - SelectParams(CBaseChainParams::MAIN); - } else if (IsValidDestinationString( - r.address.toStdString(), - Params(CBaseChainParams::TESTNET))) { - SelectParams(CBaseChainParams::TESTNET); - } - } + bool parseOK; + std::tie(parseOK, network) = ipcParseURI(arg); + if (parseOK) { + continue; } else if (QFile::exists(arg)) { // Filename savedPaymentRequests.append(arg); @@ -255,6 +269,7 @@ << arg; } } + return network; } // @@ -392,7 +407,7 @@ } // bitcoincash: URI - QString scheme = GUIUtil::bitcoinURIScheme(Params(), false); + QString scheme = GUIUtil::bitcoinURIScheme(Params(), true); if (s.startsWith(scheme + ":", Qt::CaseInsensitive)) { #if QT_VERSION < 0x050000 QUrl uri(s);