Master Core  v0.0.9 - 49a5c0d97abf09ef2911ddfe8d9551df59f9efd3-dirty
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
paymentserver.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2013 The Bitcoin developers
2 // Distributed under the MIT/X11 software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include "paymentserver.h"
6 
7 #include "bitcoinunits.h"
8 #include "guiconstants.h"
9 #include "guiutil.h"
10 #include "optionsmodel.h"
11 
12 #include "base58.h"
13 #include "ui_interface.h"
14 #include "wallet.h"
15 
16 #include <cstdlib>
17 
18 #include <openssl/x509.h>
19 #include <openssl/x509_vfy.h>
20 #include <QApplication>
21 #include <QByteArray>
22 #include <QDataStream>
23 #include <QDateTime>
24 #include <QDebug>
25 #include <QFile>
26 #include <QFileOpenEvent>
27 #include <QHash>
28 #include <QList>
29 #include <QLocalServer>
30 #include <QLocalSocket>
31 #include <QNetworkAccessManager>
32 #include <QNetworkProxy>
33 #include <QNetworkReply>
34 #include <QNetworkRequest>
35 #include <QSslCertificate>
36 #include <QSslError>
37 #include <QSslSocket>
38 #include <QStringList>
39 #include <QTextDocument>
40 
41 #if QT_VERSION < 0x050000
42 #include <QUrl>
43 #else
44 #include <QUrlQuery>
45 #endif
46 
47 using namespace boost;
48 
49 const int BITCOIN_IPC_CONNECT_TIMEOUT = 1000; // milliseconds
50 const QString BITCOIN_IPC_PREFIX("bitcoin:");
51 const char* BITCOIN_REQUEST_MIMETYPE = "application/bitcoin-paymentrequest";
52 const char* BITCOIN_PAYMENTACK_MIMETYPE = "application/bitcoin-paymentack";
53 const char* BITCOIN_PAYMENTACK_CONTENTTYPE = "application/bitcoin-payment";
54 
55 X509_STORE* PaymentServer::certStore = NULL;
57 {
58  if (PaymentServer::certStore != NULL)
59  {
60  X509_STORE_free(PaymentServer::certStore);
62  }
63 }
64 
65 //
66 // Create a name that is unique for:
67 // testnet / non-testnet
68 // data directory
69 //
70 static QString ipcServerName()
71 {
72  QString name("BitcoinQt");
73 
74  // Append a simple hash of the datadir
75  // Note that GetDataDir(true) returns a different path
76  // for -testnet versus main net
77  QString ddir(QString::fromStdString(GetDataDir(true).string()));
78  name.append(QString::number(qHash(ddir)));
79 
80  return name;
81 }
82 
83 //
84 // We store payment URIs and requests received before
85 // the main GUI window is up and ready to ask the user
86 // to send payment.
87 
88 static QList<QString> savedPaymentRequests;
89 
90 static void ReportInvalidCertificate(const QSslCertificate& cert)
91 {
92  qDebug() << "ReportInvalidCertificate : Payment server found an invalid certificate: " << cert.subjectInfo(QSslCertificate::CommonName);
93 }
94 
95 //
96 // Load OpenSSL's list of root certificate authorities
97 //
98 void PaymentServer::LoadRootCAs(X509_STORE* _store)
99 {
100  if (PaymentServer::certStore == NULL)
102  else
103  freeCertStore();
104 
105  // Unit tests mostly use this, to pass in fake root CAs:
106  if (_store)
107  {
108  PaymentServer::certStore = _store;
109  return;
110  }
111 
112  // Normal execution, use either -rootcertificates or system certs:
113  PaymentServer::certStore = X509_STORE_new();
114 
115  // Note: use "-system-" default here so that users can pass -rootcertificates=""
116  // and get 'I don't like X.509 certificates, don't trust anybody' behavior:
117  QString certFile = QString::fromStdString(GetArg("-rootcertificates", "-system-"));
118 
119  if (certFile.isEmpty())
120  return; // Empty store
121 
122  QList<QSslCertificate> certList;
123 
124  if (certFile != "-system-")
125  {
126  certList = QSslCertificate::fromPath(certFile);
127  // Use those certificates when fetching payment requests, too:
128  QSslSocket::setDefaultCaCertificates(certList);
129  }
130  else
131  certList = QSslSocket::systemCaCertificates ();
132 
133  int nRootCerts = 0;
134  const QDateTime currentTime = QDateTime::currentDateTime();
135  foreach (const QSslCertificate& cert, certList)
136  {
137  if (currentTime < cert.effectiveDate() || currentTime > cert.expiryDate()) {
139  continue;
140  }
141 #if QT_VERSION >= 0x050000
142  if (cert.isBlacklisted()) {
144  continue;
145  }
146 #endif
147  QByteArray certData = cert.toDer();
148  const unsigned char *data = (const unsigned char *)certData.data();
149 
150  X509* x509 = d2i_X509(0, &data, certData.size());
151  if (x509 && X509_STORE_add_cert(PaymentServer::certStore, x509))
152  {
153  // Note: X509_STORE_free will free the X509* objects when
154  // the PaymentServer is destroyed
155  ++nRootCerts;
156  }
157  else
158  {
160  continue;
161  }
162  }
163  qDebug() << "PaymentServer::LoadRootCAs : Loaded " << nRootCerts << " root certificates";
164 
165  // Project for another day:
166  // Fetch certificate revocation lists, and add them to certStore.
167  // Issues to consider:
168  // performance (start a thread to fetch in background?)
169  // privacy (fetch through tor/proxy so IP address isn't revealed)
170  // would it be easier to just use a compiled-in blacklist?
171  // or use Qt's blacklist?
172  // "certificate stapling" with server-side caching is more efficient
173 }
174 
175 //
176 // Sending to the server is done synchronously, at startup.
177 // If the server isn't already running, startup continues,
178 // and the items in savedPaymentRequest will be handled
179 // when uiReady() is called.
180 //
181 bool PaymentServer::ipcParseCommandLine(int argc, char* argv[])
182 {
183  for (int i = 1; i < argc; i++)
184  {
185  QString arg(argv[i]);
186  if (arg.startsWith("-"))
187  continue;
188 
189  if (arg.startsWith(BITCOIN_IPC_PREFIX, Qt::CaseInsensitive)) // bitcoin: URI
190  {
191  savedPaymentRequests.append(arg);
192 
194  if (GUIUtil::parseBitcoinURI(arg, &r) && !r.address.isEmpty())
195  {
196  CBitcoinAddress address(r.address.toStdString());
197 
199  if (!address.IsValid())
200  {
202  }
203  }
204  }
205  else if (QFile::exists(arg)) // Filename
206  {
207  savedPaymentRequests.append(arg);
208 
209  PaymentRequestPlus request;
210  if (readPaymentRequest(arg, request))
211  {
212  if (request.getDetails().network() == "main")
214  else
216  }
217  }
218  else
219  {
220  // Printing to debug.log is about the best we can do here, the
221  // GUI hasn't started yet so we can't pop up a message box.
222  qDebug() << "PaymentServer::ipcSendCommandLine : Payment request file does not exist: " << arg;
223  }
224  }
225  return true;
226 }
227 
228 //
229 // Sending to the server is done synchronously, at startup.
230 // If the server isn't already running, startup continues,
231 // and the items in savedPaymentRequest will be handled
232 // when uiReady() is called.
233 //
235 {
236  bool fResult = false;
237  foreach (const QString& r, savedPaymentRequests)
238  {
239  QLocalSocket* socket = new QLocalSocket();
240  socket->connectToServer(ipcServerName(), QIODevice::WriteOnly);
241  if (!socket->waitForConnected(BITCOIN_IPC_CONNECT_TIMEOUT))
242  {
243  delete socket;
244  return false;
245  }
246 
247  QByteArray block;
248  QDataStream out(&block, QIODevice::WriteOnly);
249  out.setVersion(QDataStream::Qt_4_0);
250  out << r;
251  out.device()->seek(0);
252  socket->write(block);
253  socket->flush();
254 
255  socket->waitForBytesWritten(BITCOIN_IPC_CONNECT_TIMEOUT);
256  socket->disconnectFromServer();
257  delete socket;
258  fResult = true;
259  }
260 
261  return fResult;
262 }
263 
264 PaymentServer::PaymentServer(QObject* parent, bool startLocalServer) :
265  QObject(parent),
266  saveURIs(true),
267  uriServer(0),
268  netManager(0),
269  optionsModel(0)
270 {
271  // Verify that the version of the library that we linked against is
272  // compatible with the version of the headers we compiled against.
273  GOOGLE_PROTOBUF_VERIFY_VERSION;
274 
275  // Install global event filter to catch QFileOpenEvents
276  // on Mac: sent when you click bitcoin: links
277  // other OSes: helpful when dealing with payment request files (in the future)
278  if (parent)
279  parent->installEventFilter(this);
280 
281  QString name = ipcServerName();
282 
283  // Clean up old socket leftover from a crash:
284  QLocalServer::removeServer(name);
285 
286  if (startLocalServer)
287  {
288  uriServer = new QLocalServer(this);
289 
290  if (!uriServer->listen(name)) {
291  // constructor is called early in init, so don't use "emit message()" here
292  QMessageBox::critical(0, tr("Payment request error"),
293  tr("Cannot start bitcoin: click-to-pay handler"));
294  }
295  else {
296  connect(uriServer, SIGNAL(newConnection()), this, SLOT(handleURIConnection()));
297  connect(this, SIGNAL(receivedPaymentACK(QString)), this, SLOT(handlePaymentACK(QString)));
298  }
299  }
300 }
301 
303 {
304  google::protobuf::ShutdownProtobufLibrary();
305 }
306 
307 //
308 // OSX-specific way of handling bitcoin: URIs and
309 // PaymentRequest mime types
310 //
311 bool PaymentServer::eventFilter(QObject *object, QEvent *event)
312 {
313  // clicking on bitcoin: URIs creates FileOpen events on the Mac
314  if (event->type() == QEvent::FileOpen)
315  {
316  QFileOpenEvent *fileEvent = static_cast<QFileOpenEvent*>(event);
317  if (!fileEvent->file().isEmpty())
318  handleURIOrFile(fileEvent->file());
319  else if (!fileEvent->url().isEmpty())
320  handleURIOrFile(fileEvent->url().toString());
321 
322  return true;
323  }
324 
325  return QObject::eventFilter(object, event);
326 }
327 
329 {
330  if (!optionsModel)
331  return;
332  if (netManager != NULL)
333  delete netManager;
334 
335  // netManager is used to fetch paymentrequests given in bitcoin: URIs
336  netManager = new QNetworkAccessManager(this);
337 
338  QNetworkProxy proxy;
339 
340  // Query active proxy (fails if no SOCKS5 proxy)
341  if (optionsModel->getProxySettings(proxy)) {
342  if (proxy.type() == QNetworkProxy::Socks5Proxy) {
343  netManager->setProxy(proxy);
344 
345  qDebug() << "PaymentServer::initNetManager : Using SOCKS5 proxy" << proxy.hostName() << ":" << proxy.port();
346  }
347  else
348  qDebug() << "PaymentServer::initNetManager : No active proxy server found.";
349  }
350  else
351  emit message(tr("Net manager warning"),
352  tr("Your active proxy doesn't support SOCKS5, which is required for payment requests via proxy."),
354 
355  connect(netManager, SIGNAL(finished(QNetworkReply*)),
356  this, SLOT(netRequestFinished(QNetworkReply*)));
357  connect(netManager, SIGNAL(sslErrors(QNetworkReply*, const QList<QSslError> &)),
358  this, SLOT(reportSslErrors(QNetworkReply*, const QList<QSslError> &)));
359 }
360 
362 {
363  initNetManager();
364 
365  saveURIs = false;
366  foreach (const QString& s, savedPaymentRequests)
367  {
368  handleURIOrFile(s);
369  }
370  savedPaymentRequests.clear();
371 }
372 
373 void PaymentServer::handleURIOrFile(const QString& s)
374 {
375  if (saveURIs)
376  {
377  savedPaymentRequests.append(s);
378  return;
379  }
380 
381  if (s.startsWith(BITCOIN_IPC_PREFIX, Qt::CaseInsensitive)) // bitcoin: URI
382  {
383 #if QT_VERSION < 0x050000
384  QUrl uri(s);
385 #else
386  QUrlQuery uri((QUrl(s)));
387 #endif
388  if (uri.hasQueryItem("r")) // payment request URI
389  {
390  QByteArray temp;
391  temp.append(uri.queryItemValue("r"));
392  QString decoded = QUrl::fromPercentEncoding(temp);
393  QUrl fetchUrl(decoded, QUrl::StrictMode);
394 
395  if (fetchUrl.isValid())
396  {
397  qDebug() << "PaymentServer::handleURIOrFile : fetchRequest(" << fetchUrl << ")";
398  fetchRequest(fetchUrl);
399  }
400  else
401  {
402  qDebug() << "PaymentServer::handleURIOrFile : Invalid URL: " << fetchUrl;
403  emit message(tr("URI handling"),
404  tr("Payment request fetch URL is invalid: %1").arg(fetchUrl.toString()),
406  }
407 
408  return;
409  }
410  else // normal URI
411  {
412  SendCoinsRecipient recipient;
413  if (GUIUtil::parseBitcoinURI(s, &recipient))
414  emit receivedPaymentRequest(recipient);
415  else
416  emit message(tr("URI handling"),
417  tr("URI can not be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters."),
419 
420  return;
421  }
422  }
423 
424  if (QFile::exists(s)) // payment request file
425  {
426  PaymentRequestPlus request;
427  SendCoinsRecipient recipient;
428  if (readPaymentRequest(s, request) && processPaymentRequest(request, recipient))
429  emit receivedPaymentRequest(recipient);
430  else
431  emit message(tr("Payment request file handling"),
432  tr("Payment request file can not be read or processed! This can be caused by an invalid payment request file."),
434 
435  return;
436  }
437 }
438 
440 {
441  QLocalSocket *clientConnection = uriServer->nextPendingConnection();
442 
443  while (clientConnection->bytesAvailable() < (int)sizeof(quint32))
444  clientConnection->waitForReadyRead();
445 
446  connect(clientConnection, SIGNAL(disconnected()),
447  clientConnection, SLOT(deleteLater()));
448 
449  QDataStream in(clientConnection);
450  in.setVersion(QDataStream::Qt_4_0);
451  if (clientConnection->bytesAvailable() < (int)sizeof(quint16)) {
452  return;
453  }
454  QString msg;
455  in >> msg;
456 
457  handleURIOrFile(msg);
458 }
459 
460 bool PaymentServer::readPaymentRequest(const QString& filename, PaymentRequestPlus& request)
461 {
462  QFile f(filename);
463  if (!f.open(QIODevice::ReadOnly))
464  {
465  qDebug() << "PaymentServer::readPaymentRequest : Failed to open " << filename;
466  return false;
467  }
468 
469  if (f.size() > MAX_PAYMENT_REQUEST_SIZE)
470  {
471  qDebug() << "PaymentServer::readPaymentRequest : " << filename << " too large";
472  return false;
473  }
474 
475  QByteArray data = f.readAll();
476 
477  return request.parse(data);
478 }
479 
481 {
482  if (!optionsModel)
483  return false;
484 
485  recipient.paymentRequest = request;
486  recipient.message = GUIUtil::HtmlEscape(request.getDetails().memo());
487 
489 
490  QList<std::pair<CScript, qint64> > sendingTos = request.getPayTo();
491  QStringList addresses;
492 
493  foreach(const PAIRTYPE(CScript, qint64)& sendingTo, sendingTos) {
494  // Extract and check destination addresses
495  CTxDestination dest;
496  if (ExtractDestination(sendingTo.first, dest)) {
497  // Append destination address
498  addresses.append(QString::fromStdString(CBitcoinAddress(dest).ToString()));
499  }
500  else if (!recipient.authenticatedMerchant.isEmpty()){
501  // Insecure payments to custom bitcoin addresses are not supported
502  // (there is no good way to tell the user where they are paying in a way
503  // they'd have a chance of understanding).
504  emit message(tr("Payment request error"),
505  tr("Unverified payment requests to custom payment scripts are unsupported."),
507  return false;
508  }
509 
510  // Extract and check amounts
511  CTxOut txOut(sendingTo.second, sendingTo.first);
513  QString msg = tr("Requested payment amount of %1 is too small (considered dust).")
514  .arg(BitcoinUnits::formatWithUnit(optionsModel->getDisplayUnit(), sendingTo.second));
515 
516  qDebug() << "PaymentServer::processPaymentRequest : " << msg;
517  emit message(tr("Payment request error"), msg, CClientUIInterface::MSG_ERROR);
518  return false;
519  }
520 
521  recipient.amount += sendingTo.second;
522  }
523  // Store addresses and format them to fit nicely into the GUI
524  recipient.address = addresses.join("<br />");
525 
526  if (!recipient.authenticatedMerchant.isEmpty()) {
527  qDebug() << "PaymentServer::processPaymentRequest : Secure payment request from " << recipient.authenticatedMerchant;
528  }
529  else {
530  qDebug() << "PaymentServer::processPaymentRequest : Insecure payment request to " << addresses.join(", ");
531  }
532 
533  return true;
534 }
535 
537 {
538  QNetworkRequest netRequest;
539  netRequest.setAttribute(QNetworkRequest::User, "PaymentRequest");
540  netRequest.setUrl(url);
541  netRequest.setRawHeader("User-Agent", CLIENT_NAME.c_str());
542  netRequest.setRawHeader("Accept", BITCOIN_REQUEST_MIMETYPE);
543  netManager->get(netRequest);
544 }
545 
546 void PaymentServer::fetchPaymentACK(CWallet* wallet, SendCoinsRecipient recipient, QByteArray transaction)
547 {
548  const payments::PaymentDetails& details = recipient.paymentRequest.getDetails();
549  if (!details.has_payment_url())
550  return;
551 
552  QNetworkRequest netRequest;
553  netRequest.setAttribute(QNetworkRequest::User, "PaymentACK");
554  netRequest.setUrl(QString::fromStdString(details.payment_url()));
555  netRequest.setHeader(QNetworkRequest::ContentTypeHeader, BITCOIN_PAYMENTACK_CONTENTTYPE);
556  netRequest.setRawHeader("User-Agent", CLIENT_NAME.c_str());
557  netRequest.setRawHeader("Accept", BITCOIN_PAYMENTACK_MIMETYPE);
558 
559  payments::Payment payment;
560  payment.set_merchant_data(details.merchant_data());
561  payment.add_transactions(transaction.data(), transaction.size());
562 
563  // Create a new refund address, or re-use:
564  QString account = tr("Refund from %1").arg(recipient.authenticatedMerchant);
565  std::string strAccount = account.toStdString();
566  set<CTxDestination> refundAddresses = wallet->GetAccountAddresses(strAccount);
567  if (!refundAddresses.empty()) {
568  CScript s; s.SetDestination(*refundAddresses.begin());
569  payments::Output* refund_to = payment.add_refund_to();
570  refund_to->set_script(&s[0], s.size());
571  }
572  else {
573  CPubKey newKey;
574  if (wallet->GetKeyFromPool(newKey)) {
575  LOCK(wallet->cs_wallet); // SetAddressBook
576  CKeyID keyID = newKey.GetID();
577  wallet->SetAddressBook(keyID, strAccount, "refund");
578 
579  CScript s; s.SetDestination(keyID);
580  payments::Output* refund_to = payment.add_refund_to();
581  refund_to->set_script(&s[0], s.size());
582  }
583  else {
584  // This should never happen, because sending coins should have just unlocked the wallet
585  // and refilled the keypool
586  qDebug() << "PaymentServer::fetchPaymentACK : Error getting refund key, refund_to not set";
587  }
588  }
589 
590  int length = payment.ByteSize();
591  netRequest.setHeader(QNetworkRequest::ContentLengthHeader, length);
592  QByteArray serData(length, '\0');
593  if (payment.SerializeToArray(serData.data(), length)) {
594  netManager->post(netRequest, serData);
595  }
596  else {
597  // This should never happen, either:
598  qDebug() << "PaymentServer::fetchPaymentACK : Error serializing payment message";
599  }
600 }
601 
602 void PaymentServer::netRequestFinished(QNetworkReply* reply)
603 {
604  reply->deleteLater();
605  if (reply->error() != QNetworkReply::NoError)
606  {
607  QString msg = tr("Error communicating with %1: %2")
608  .arg(reply->request().url().toString())
609  .arg(reply->errorString());
610 
611  qDebug() << "PaymentServer::netRequestFinished : " << msg;
612  emit message(tr("Payment request error"), msg, CClientUIInterface::MSG_ERROR);
613  return;
614  }
615 
616  QByteArray data = reply->readAll();
617 
618  QString requestType = reply->request().attribute(QNetworkRequest::User).toString();
619  if (requestType == "PaymentRequest")
620  {
621  PaymentRequestPlus request;
622  SendCoinsRecipient recipient;
623  if (request.parse(data) && processPaymentRequest(request, recipient))
624  {
625  emit receivedPaymentRequest(recipient);
626  }
627  else
628  {
629  qDebug() << "PaymentServer::netRequestFinished : Error processing payment request";
630  emit message(tr("Payment request error"),
631  tr("Payment request can not be parsed or processed!"),
633  }
634 
635  return;
636  }
637  else if (requestType == "PaymentACK")
638  {
639  payments::PaymentACK paymentACK;
640  if (!paymentACK.ParseFromArray(data.data(), data.size()))
641  {
642  QString msg = tr("Bad response from server %1")
643  .arg(reply->request().url().toString());
644 
645  qDebug() << "PaymentServer::netRequestFinished : " << msg;
646  emit message(tr("Payment request error"), msg, CClientUIInterface::MSG_ERROR);
647  }
648  else
649  {
650  emit receivedPaymentACK(GUIUtil::HtmlEscape(paymentACK.memo()));
651  }
652  }
653 }
654 
655 void PaymentServer::reportSslErrors(QNetworkReply* reply, const QList<QSslError> &errs)
656 {
657  Q_UNUSED(reply);
658 
659  QString errString;
660  foreach (const QSslError& err, errs) {
661  qDebug() << "PaymentServer::reportSslErrors : " << err;
662  errString += err.errorString() + "\n";
663  }
664  emit message(tr("Network request error"), errString, CClientUIInterface::MSG_ERROR);
665 }
666 
668 {
669  this->optionsModel = optionsModel;
670 }
671 
672 void PaymentServer::handlePaymentACK(const QString& paymentACKMsg)
673 {
674  // currently we don't futher process or store the paymentACK message
675  emit message(tr("Payment acknowledged"), paymentACKMsg, CClientUIInterface::ICON_INFORMATION | CClientUIInterface::MODAL);
676 }
const boost::filesystem::path & GetDataDir(bool fNetSpecific)
Definition: util.cpp:973
const char * BITCOIN_PAYMENTACK_MIMETYPE
bool IsDust(int64_t nMinRelayTxFee) const
Definition: core.h:151
bool SetAddressBook(const CTxDestination &address, const std::string &strName, const std::string &purpose)
Definition: wallet.cpp:1548
const char * BITCOIN_REQUEST_MIMETYPE
PaymentRequestPlus paymentRequest
Definition: walletmodel.h:55
void message(const QString &title, const QString &message, unsigned int style)
static QString formatWithUnit(int unit, qint64 amount, bool plussign=false)
Format as string (with unit)
static bool readPaymentRequest(const QString &filename, PaymentRequestPlus &request)
static const int MAX_PAYMENT_REQUEST_SIZE
Definition: guiconstants.h:36
Definition: init.h:13
void set_script(const ::std::string &value)
void setOptionsModel(OptionsModel *optionsModel)
#define PAIRTYPE(t1, t2)
Definition: util.h:48
CCriticalSection cs_wallet
Main wallet lock.
Definition: wallet.h:132
bool eventFilter(QObject *object, QEvent *event)
void handlePaymentACK(const QString &paymentACKMsg)
bool getMerchant(X509_STORE *certStore, QString &merchant) const
void receivedPaymentACK(const QString &paymentACKMsg)
const std::string CLIENT_NAME
void set_merchant_data(const ::std::string &value)
void receivedPaymentRequest(SendCoinsRecipient)
QString HtmlEscape(const QString &str, bool fMultiLine)
Definition: guiutil.cpp:222
base58-encoded Bitcoin addresses.
Definition: base58.h:101
const char * BITCOIN_PAYMENTACK_CONTENTTYPE
bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out)
Definition: guiutil.cpp:115
inline::std::string * add_transactions()
QLocalServer * uriServer
static X509_STORE * certStore
void handleURIOrFile(const QString &s)
static bool ipcParseCommandLine(int argc, char *argv[])
static void freeCertStore()
Force blocking, modal message box dialog (not just OS notification)
Definition: ui_interface.h:64
const ::std::string & payment_url() const
void SetDestination(const CTxDestination &address)
Definition: script.cpp:1925
static void ReportInvalidCertificate(const QSslCertificate &cert)
static bool ipcSendCommandLine()
const char * url
Definition: rpcconsole.cpp:35
void netRequestFinished(QNetworkReply *)
const ::std::string & memo() const
const int BITCOIN_IPC_CONNECT_TIMEOUT
void SelectParams(CChainParams::Network network)
Sets the params returned by Params() to those for the given network.
#define LOCK(cs)
Definition: sync.h:156
void fetchRequest(const QUrl &url)
bool getProxySettings(QNetworkProxy &proxy) const
An encapsulated public key.
Definition: key.h:42
const ::std::string & network() const
const payments::PaymentDetails & getDetails() const
An output of a transaction.
Definition: core.h:119
PaymentServer(QObject *parent, bool startLocalServer=true)
int getDisplayUnit()
Definition: optionsmodel.h:58
QNetworkAccessManager * netManager
std::set< CTxDestination > GetAccountAddresses(std::string strAccount) const
Definition: wallet.cpp:1889
static QList< QString > savedPaymentRequests
bool parse(const QByteArray &data)
void reportSslErrors(QNetworkReply *, const QList< QSslError > &)
void fetchPaymentACK(CWallet *wallet, SendCoinsRecipient recipient, QByteArray transaction)
Interface from Qt to configuration data structure for Bitcoin client.
Definition: optionsmodel.h:20
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:401
const QString BITCOIN_IPC_PREFIX("bitcoin:")
A reference to a CKey: the Hash160 of its serialized public key.
Definition: key.h:26
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Definition: script.cpp:1493
static QString ipcServerName()
A CWallet is an extension of a keystore, which also maintains a set of transactions and balances...
Definition: wallet.h:100
void handleURIConnection()
static int64_t nMinRelayTxFee
Fees smaller than this (in satoshi) are considered zero fee (for relaying and mining) ...
Definition: core.h:187
inline::payments::Output * add_refund_to()
bool processPaymentRequest(PaymentRequestPlus &request, SendCoinsRecipient &recipient)
const ::std::string & memo() const
OptionsModel * optionsModel
std::string GetArg(const std::string &strArg, const std::string &strDefault)
Return string argument or default value.
Definition: util.cpp:505
bool GetKeyFromPool(CPubKey &key)
Definition: wallet.cpp:1726
boost::variant< CNoDestination, CKeyID, CScriptID > CTxDestination
A txout script template with a specific destination.
Definition: script.h:218
static const CCheckpointData data
Definition: checkpoints.cpp:56
CKeyID GetID() const
Definition: key.h:131
static void LoadRootCAs(X509_STORE *store=NULL)
const ::std::string & merchant_data() const
QString authenticatedMerchant
Definition: walletmodel.h:57
QList< std::pair< CScript, qint64 > > getPayTo() const