// // 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 bitcoin: 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)) // bitcoin: URI { savedPaymentRequests.append(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 { savedPaymentRequests.append(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. // // Warning: ipcSendCommandLine() is called early in init, // so don't use "emit message()", but "QMessageBox::"! // void PaymentServer::ipcParseCommandLine(int argc, char* argv[]) { for (int i = 1; i < argc; i++) { QString arg(argv[i]); if (arg.startsWith("-")) continue; // If the bitcoin: 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)) // bitcoin: URI { savedPaymentRequests.append(arg); SendCoinsRecipient r; if (GUIUtil::parseBitcoinURI(arg, &r) && !r.address.isEmpty()) { CBitcoinAddress address(r.address.toStdString()); if (address.IsValid(Params(CBaseChainParams::MAIN))) { SelectParams(CBaseChainParams::MAIN); } else if (address.IsValid(Params(CBaseChainParams::TESTNET))) { SelectParams(CBaseChainParams::TESTNET); } } } else if (QFile::exists(arg)) // Filename { savedPaymentRequests.append(arg); PaymentRequestPlus request; if (readPaymentRequestFromFile(arg, request)) { if (request.getDetails().genesis() == "1a91e3dace36e2be3bf030a65679fe821aa1d6ef92e7c9902eb318182c355691") { SelectParams(CBaseChainParams::MAIN); } else if (request.getDetails().genesis() == "bb0a78264637406b6360aad926284d544d7049f45189db5664f3c4d07350559e") { 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. // // Warning: ipcSendCommandLine() is called early in init, // so don't use "emit message()", but "QMessageBox::"! // bool PaymentServer::ipcParseCommandLine(int argc, char* argv[]) { for (int i = 1; i < argc; i++) { QString arg(argv[i]); if (arg.startsWith("-")) continue; if (arg.startsWith(DEUSCOIN_IPC_PREFIX, Qt::CaseInsensitive)) // deuscoin: URI { savedPaymentRequests.append(arg); SendCoinsRecipient r; if (GUIUtil::parseDeuscoinURI(arg, &r) && !r.address.isEmpty()) { CDeuscoinAddress address(r.address.toStdString()); if (address.IsValid(Params(CBaseChainParams::MAIN))) { SelectParams(CBaseChainParams::MAIN); } else if (address.IsValid(Params(CBaseChainParams::TESTNET))) { SelectParams(CBaseChainParams::TESTNET); } } } else if (QFile::exists(arg)) // Filename { savedPaymentRequests.append(arg); PaymentRequestPlus request; if (readPaymentRequest(arg, request)) { if (request.getDetails().network() == "main") { SelectParams(CBaseChainParams::MAIN); } else if (request.getDetails().network() == "test") { 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; } } return true; }
// // 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 "emit message()", but "QMessageBox::"! // bool PaymentServer::ipcParseCommandLine(int argc, char* argv[]) { for (int i = 1; i < argc; i++) { QString arg(argv[i]); if (arg.startsWith("-")) continue; if (arg.startsWith(BITCOIN_IPC_PREFIX, Qt::CaseInsensitive)) // sherlockcoin: URI { savedPaymentRequests.append(arg); SendCoinsRecipient r; if (GUIUtil::parseBitcoinURI(arg, &r) && !r.address.isEmpty()) { CBitcoinAddress address(r.address.toStdString()); SelectParams(CChainParams::MAIN); if (!address.IsValid()) { SelectParams(CChainParams::TESTNET); } } } else if (QFile::exists(arg)) // Filename { savedPaymentRequests.append(arg); PaymentRequestPlus request; if (readPaymentRequest(arg, request)) { if (request.getDetails().genesis() == "1a91e3dace36e2be3bf030a65679fe821aa1d6ef92e7c9902eb318182c355691") { SelectParams(CChainParams::MAIN); } else if (request.getDetails().genesis() == "bb0a78264637406b6360aad926284d544d7049f45189db5664f3c4d07350559e") { SelectParams(CChainParams::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. qDebug() << "PaymentServer::ipcSendCommandLine : Payment request file does not exist: " << arg; } } return true; }
// // 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(int argc, char* argv[]) { bool fResult = false; for (int i = 1; i < argc; i++) { QString arg(argv[i]); if (arg.startsWith("-")) continue; if (arg.startsWith(SNORCOIN_IPC_PREFIX, Qt::CaseInsensitive)) // snorcoin: URI { savedPaymentRequests.append(arg); SendCoinsRecipient r; if (GUIUtil::parseSnorcoinURI(arg, &r)) { CSnorcoinAddress address(r.address.toStdString()); SelectParams(CChainParams::MAIN); if (!address.IsValid()) { SelectParams(CChainParams::TESTNET); } } } else if (QFile::exists(arg)) // Filename { savedPaymentRequests.append(arg); PaymentRequestPlus request; if (readPaymentRequest(arg, request)) { if (request.getDetails().network() == "main") SelectParams(CChainParams::MAIN); else SelectParams(CChainParams::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. qDebug() << "PaymentServer::ipcSendCommandLine : Payment request file does not exist: " << arg; } } foreach (const QString& r, savedPaymentRequests) { QLocalSocket* socket = new QLocalSocket(); socket->connectToServer(ipcServerName(), QIODevice::WriteOnly); if (!socket->waitForConnected(SNORCOIN_IPC_CONNECT_TIMEOUT)) { delete socket; 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(SNORCOIN_IPC_CONNECT_TIMEOUT); socket->disconnectFromServer(); delete socket; fResult = true; }
bool PaymentServer::processPaymentRequest(const PaymentRequestPlus& request, SendCoinsRecipient& recipient) { if (!optionsModel) return false; if (request.IsInitialized()) { // Payment request network matches client network? if (!verifyNetwork(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, ::dustRelayFee)) { 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; }