Bitcoin Core
31.1.0
P2P Digital Currency
Toggle main menu visibility
Loading...
Searching...
No Matches
src
qt
paymentserver.cpp
Go to the documentation of this file.
1
// Copyright (c) 2011-present The Bitcoin Core developers
2
// Distributed under the MIT software license, see the accompanying
3
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5
#include <
qt/paymentserver.h
>
6
7
#include <
qt/bitcoinunits.h
>
8
#include <
qt/guiutil.h
>
9
#include <
qt/optionsmodel.h
>
10
11
#include <chainparams.h>
12
#include <
common/args.h
>
13
#include <
interfaces/node.h
>
14
#include <
key_io.h
>
15
#include <
node/interface_ui.h
>
16
#include <
policy/policy.h
>
17
#include <
wallet/wallet.h
>
18
19
#include <cstdlib>
20
#include <memory>
21
22
#include <QApplication>
23
#include <QByteArray>
24
#include <QDataStream>
25
#include <QDebug>
26
#include <QFile>
27
#include <QFileOpenEvent>
28
#include <QHash>
29
#include <QList>
30
#include <QLocalServer>
31
#include <QLocalSocket>
32
#include <QStringList>
33
#include <QUrlQuery>
34
35
const
int
BITCOIN_IPC_CONNECT_TIMEOUT
= 1000;
// milliseconds
36
const
QString
BITCOIN_IPC_PREFIX
(
"bitcoin:"
);
37
38
//
39
// Create a name that is unique for:
40
// testnet / non-testnet
41
// data directory
42
//
43
static
QString
ipcServerName
()
44
{
45
QString
name
(
"BitcoinQt"
);
46
47
// Append a simple hash of the datadir
48
// Note that gArgs.GetDataDirNet() returns a different path
49
// for -testnet versus main net
50
QString ddir(
GUIUtil::PathToQString
(
gArgs
.GetDataDirNet()));
51
name
.append(QString::number(qHash(ddir)));
52
53
return
name
;
54
}
55
56
//
57
// We store payment URIs and requests received before
58
// the main GUI window is up and ready to ask the user
59
// to send payment.
60
61
static
QSet<QString>
savedPaymentRequests
;
62
63
//
64
// Sending to the server is done synchronously, at startup.
65
// If the server isn't already running, startup continues,
66
// and the items in savedPaymentRequest will be handled
67
// when uiReady() is called.
68
//
69
// Warning: ipcSendCommandLine() is called early in init,
70
// so don't use "Q_EMIT message()", but "QMessageBox::"!
71
//
72
void
PaymentServer::ipcParseCommandLine
(
int
argc,
char
* argv[])
73
{
74
for
(
int
i = 1; i < argc; i++)
75
{
76
QString arg(argv[i]);
77
if
(arg.startsWith(
"-"
))
continue
;
78
79
if
(arg.startsWith(
BITCOIN_IPC_PREFIX
, Qt::CaseInsensitive))
// bitcoin: URI
80
{
81
savedPaymentRequests
.insert(arg);
82
}
83
}
84
}
85
86
//
87
// Sending to the server is done synchronously, at startup.
88
// If the server isn't already running, startup continues,
89
// and the items in savedPaymentRequest will be handled
90
// when uiReady() is called.
91
//
92
bool
PaymentServer::ipcSendCommandLine
()
93
{
94
bool
fResult =
false
;
95
for
(
const
QString& r :
savedPaymentRequests
)
96
{
97
QLocalSocket* socket =
new
QLocalSocket();
98
socket->connectToServer(
ipcServerName
(), QIODevice::WriteOnly);
99
if
(!socket->waitForConnected(
BITCOIN_IPC_CONNECT_TIMEOUT
))
100
{
101
delete
socket;
102
socket =
nullptr
;
103
return
false
;
104
}
105
106
QByteArray block;
107
QDataStream out(&block, QIODevice::WriteOnly);
108
out.setVersion(QDataStream::Qt_4_0);
109
out << r;
110
out.device()->seek(0);
111
112
socket->write(block);
113
socket->flush();
114
socket->waitForBytesWritten(
BITCOIN_IPC_CONNECT_TIMEOUT
);
115
socket->disconnectFromServer();
116
117
delete
socket;
118
socket =
nullptr
;
119
fResult =
true
;
120
}
121
122
return
fResult;
123
}
124
125
PaymentServer::PaymentServer
(QObject* parent,
bool
startLocalServer)
126
: QObject(parent)
127
{
128
// Install global event filter to catch QFileOpenEvents
129
// on Mac: sent when you click bitcoin: links
130
// other OSes: helpful when dealing with payment request files
131
if
(parent)
132
parent->installEventFilter(
this
);
133
134
QString
name
=
ipcServerName
();
135
136
// Clean up old socket leftover from a crash:
137
QLocalServer::removeServer(
name
);
138
139
if
(startLocalServer)
140
{
141
uriServer
=
new
QLocalServer(
this
);
142
143
if
(!
uriServer
->listen(
name
)) {
144
// constructor is called early in init, so don't use "Q_EMIT message()" here
145
QMessageBox::critical(
nullptr
, tr(
"Payment request error"
),
146
tr(
"Cannot start bitcoin: click-to-pay handler"
));
147
}
148
else
{
149
connect(
uriServer
, &QLocalServer::newConnection,
this
, &
PaymentServer::handleURIConnection
);
150
}
151
}
152
}
153
154
PaymentServer::~PaymentServer
() =
default
;
155
156
//
157
// OSX-specific way of handling bitcoin: URIs
158
//
159
bool
PaymentServer::eventFilter
(QObject *
object
, QEvent *event)
160
{
161
if
(event->type() == QEvent::FileOpen) {
162
QFileOpenEvent *fileEvent =
static_cast<
QFileOpenEvent*
>
(event);
163
if
(!fileEvent->file().isEmpty())
164
handleURIOrFile
(fileEvent->file());
165
else
if
(!fileEvent->url().isEmpty())
166
handleURIOrFile
(fileEvent->url().toString());
167
168
return
true
;
169
}
170
171
return
QObject::eventFilter(
object
, event);
172
}
173
174
void
PaymentServer::uiReady
()
175
{
176
saveURIs
=
false
;
177
for
(
const
QString& s :
savedPaymentRequests
)
178
{
179
handleURIOrFile
(s);
180
}
181
savedPaymentRequests
.clear();
182
}
183
184
void
PaymentServer::handleURIOrFile
(
const
QString& s)
185
{
186
if
(
saveURIs
)
187
{
188
savedPaymentRequests
.insert(s);
189
return
;
190
}
191
192
if
(s.startsWith(
"bitcoin://"
, Qt::CaseInsensitive))
193
{
194
Q_EMIT
message
(tr(
"URI handling"
), tr(
"'bitcoin://' is not a valid URI. Use 'bitcoin:' instead."
),
195
CClientUIInterface::MSG_ERROR
);
196
}
197
else
if
(s.startsWith(
BITCOIN_IPC_PREFIX
, Qt::CaseInsensitive))
// bitcoin: URI
198
{
199
QUrlQuery uri((QUrl(s)));
200
// normal URI
201
{
202
SendCoinsRecipient
recipient;
203
if
(
GUIUtil::parseBitcoinURI
(s, &recipient))
204
{
205
std::string error_msg;
206
const
CTxDestination
dest =
DecodeDestination
(recipient.
address
.toStdString(), error_msg);
207
208
if
(!
IsValidDestination
(dest)) {
209
if
(uri.hasQueryItem(
"r"
)) {
// payment request
210
Q_EMIT
message
(tr(
"URI handling"
),
211
tr(
"Cannot process payment request because BIP70 is not supported.\n"
212
"Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.\n"
213
"If you are receiving this error you should request the merchant provide a BIP21 compatible URI."
),
214
CClientUIInterface::ICON_WARNING
);
215
}
216
Q_EMIT
message
(tr(
"URI handling"
), QString::fromStdString(error_msg),
217
CClientUIInterface::MSG_ERROR
);
218
}
219
else
220
Q_EMIT
receivedPaymentRequest
(recipient);
221
}
222
else
223
Q_EMIT
message
(tr(
"URI handling"
),
224
tr(
"URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters."
),
225
CClientUIInterface::ICON_WARNING
);
226
227
return
;
228
}
229
}
230
231
if
(QFile::exists(s))
// payment request file
232
{
233
Q_EMIT
message
(tr(
"Payment request file handling"
),
234
tr(
"Cannot process payment request because BIP70 is not supported.\n"
235
"Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.\n"
236
"If you are receiving this error you should request the merchant provide a BIP21 compatible URI."
),
237
CClientUIInterface::ICON_WARNING
);
238
}
239
}
240
241
void
PaymentServer::handleURIConnection
()
242
{
243
QLocalSocket *clientConnection =
uriServer
->nextPendingConnection();
244
245
while
(clientConnection->bytesAvailable() < (
int
)
sizeof
(quint32))
246
clientConnection->waitForReadyRead();
247
248
connect(clientConnection, &QLocalSocket::disconnected, clientConnection, &QLocalSocket::deleteLater);
249
250
QDataStream in(clientConnection);
251
in.setVersion(QDataStream::Qt_4_0);
252
if
(clientConnection->bytesAvailable() < (
int
)
sizeof
(quint16)) {
253
return
;
254
}
255
QString msg;
256
in >> msg;
257
258
handleURIOrFile
(msg);
259
}
260
261
void
PaymentServer::setOptionsModel
(
OptionsModel
*_optionsModel)
262
{
263
this->
optionsModel
= _optionsModel;
264
}
IsValidDestination
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination corresponds to one with an address.
Definition
addresstype.cpp:171
CTxDestination
std::variant< CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, PayToAnchor, WitnessUnknown > CTxDestination
A txout script categorized into standard templates.
Definition
addresstype.h:143
gArgs
ArgsManager gArgs
Definition
args.cpp:40
args.h
bitcoinunits.h
CClientUIInterface::MSG_ERROR
@ MSG_ERROR
Definition
interface_ui.h:68
CClientUIInterface::ICON_WARNING
@ ICON_WARNING
Definition
interface_ui.h:31
OptionsModel
Interface from Qt to configuration data structure for Bitcoin client.
Definition
optionsmodel.h:43
PaymentServer::~PaymentServer
~PaymentServer()
PaymentServer::ipcSendCommandLine
static bool ipcSendCommandLine()
Definition
paymentserver.cpp:92
PaymentServer::setOptionsModel
void setOptionsModel(OptionsModel *optionsModel)
Definition
paymentserver.cpp:261
PaymentServer::PaymentServer
PaymentServer(QObject *parent, bool startLocalServer=true)
Definition
paymentserver.cpp:125
PaymentServer::message
void message(const QString &title, const QString &message, unsigned int style)
PaymentServer::handleURIConnection
void handleURIConnection()
Definition
paymentserver.cpp:241
PaymentServer::ipcParseCommandLine
static void ipcParseCommandLine(int argc, char *argv[])
Definition
paymentserver.cpp:72
PaymentServer::uriServer
QLocalServer * uriServer
Definition
paymentserver.h:103
PaymentServer::saveURIs
bool saveURIs
Definition
paymentserver.h:102
PaymentServer::receivedPaymentRequest
void receivedPaymentRequest(SendCoinsRecipient)
PaymentServer::uiReady
void uiReady()
Definition
paymentserver.cpp:174
PaymentServer::eventFilter
bool eventFilter(QObject *object, QEvent *event) override
Definition
paymentserver.cpp:159
PaymentServer::handleURIOrFile
void handleURIOrFile(const QString &s)
Definition
paymentserver.cpp:184
PaymentServer::optionsModel
OptionsModel * optionsModel
Definition
paymentserver.h:104
SendCoinsRecipient
Definition
sendcoinsrecipient.h:16
SendCoinsRecipient::address
QString address
Definition
sendcoinsrecipient.h:27
guiutil.h
interface_ui.h
DecodeDestination
CTxDestination DecodeDestination(const std::string &str, std::string &error_msg, std::vector< int > *error_locations)
Definition
key_io.cpp:299
key_io.h
GUIUtil::PathToQString
QString PathToQString(const fs::path &path)
Convert OS specific boost path to QString through UTF-8.
Definition
guiutil.cpp:675
GUIUtil::parseBitcoinURI
bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out)
Definition
guiutil.cpp:149
node.h
optionsmodel.h
ipcServerName
static QString ipcServerName()
Definition
paymentserver.cpp:43
BITCOIN_IPC_CONNECT_TIMEOUT
const int BITCOIN_IPC_CONNECT_TIMEOUT
Definition
paymentserver.cpp:35
savedPaymentRequests
static QSet< QString > savedPaymentRequests
Definition
paymentserver.cpp:61
paymentserver.h
BITCOIN_IPC_PREFIX
QT_END_NAMESPACE const QString BITCOIN_IPC_PREFIX
policy.h
name
const char * name
Definition
rest.cpp:48
wallet.h
Generated on
for Bitcoin Core by
1.17.0