[trivial] Fix typos in comments
[bitcoinplatinum.git] / src / qt / test / paymentservertests.cpp
blob08a76c7d49632b2da1eac7254eabffc398935a2b
1 // Copyright (c) 2009-2015 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.
5 #include "paymentservertests.h"
7 #include "optionsmodel.h"
8 #include "paymentrequestdata.h"
10 #include "amount.h"
11 #include "random.h"
12 #include "script/script.h"
13 #include "script/standard.h"
14 #include "util.h"
15 #include "utilstrencodings.h"
17 #include <openssl/x509.h>
18 #include <openssl/x509_vfy.h>
20 #include <QFileOpenEvent>
21 #include <QTemporaryFile>
23 X509 *parse_b64der_cert(const char* cert_data)
25 std::vector<unsigned char> data = DecodeBase64(cert_data);
26 assert(data.size() > 0);
27 const unsigned char* dptr = &data[0];
28 X509 *cert = d2i_X509(NULL, &dptr, data.size());
29 assert(cert);
30 return cert;
34 // Test payment request handling
37 static SendCoinsRecipient handleRequest(PaymentServer* server, std::vector<unsigned char>& data)
39 RecipientCatcher sigCatcher;
40 QObject::connect(server, SIGNAL(receivedPaymentRequest(SendCoinsRecipient)),
41 &sigCatcher, SLOT(getRecipient(SendCoinsRecipient)));
43 // Write data to a temp file:
44 QTemporaryFile f;
45 f.open();
46 f.write((const char*)&data[0], data.size());
47 f.close();
49 // Create a QObject, install event filter from PaymentServer
50 // and send a file open event to the object
51 QObject object;
52 object.installEventFilter(server);
53 QFileOpenEvent event(f.fileName());
54 // If sending the event fails, this will cause sigCatcher to be empty,
55 // which will lead to a test failure anyway.
56 QCoreApplication::sendEvent(&object, &event);
58 QObject::disconnect(server, SIGNAL(receivedPaymentRequest(SendCoinsRecipient)),
59 &sigCatcher, SLOT(getRecipient(SendCoinsRecipient)));
61 // Return results from sigCatcher
62 return sigCatcher.recipient;
65 void PaymentServerTests::paymentServerTests()
67 SelectParams(CBaseChainParams::MAIN);
68 OptionsModel optionsModel;
69 PaymentServer* server = new PaymentServer(NULL, false);
70 X509_STORE* caStore = X509_STORE_new();
71 X509_STORE_add_cert(caStore, parse_b64der_cert(caCert1_BASE64));
72 PaymentServer::LoadRootCAs(caStore);
73 server->setOptionsModel(&optionsModel);
74 server->uiReady();
76 std::vector<unsigned char> data;
77 SendCoinsRecipient r;
78 QString merchant;
80 // Now feed PaymentRequests to server, and observe signals it produces
82 // This payment request validates directly against the
83 // caCert1 certificate authority:
84 data = DecodeBase64(paymentrequest1_cert1_BASE64);
85 r = handleRequest(server, data);
86 r.paymentRequest.getMerchant(caStore, merchant);
87 QCOMPARE(merchant, QString("testmerchant.org"));
89 // Signed, but expired, merchant cert in the request:
90 data = DecodeBase64(paymentrequest2_cert1_BASE64);
91 r = handleRequest(server, data);
92 r.paymentRequest.getMerchant(caStore, merchant);
93 QCOMPARE(merchant, QString(""));
95 // 10-long certificate chain, all intermediates valid:
96 data = DecodeBase64(paymentrequest3_cert1_BASE64);
97 r = handleRequest(server, data);
98 r.paymentRequest.getMerchant(caStore, merchant);
99 QCOMPARE(merchant, QString("testmerchant8.org"));
101 // Long certificate chain, with an expired certificate in the middle:
102 data = DecodeBase64(paymentrequest4_cert1_BASE64);
103 r = handleRequest(server, data);
104 r.paymentRequest.getMerchant(caStore, merchant);
105 QCOMPARE(merchant, QString(""));
107 // Validly signed, but by a CA not in our root CA list:
108 data = DecodeBase64(paymentrequest5_cert1_BASE64);
109 r = handleRequest(server, data);
110 r.paymentRequest.getMerchant(caStore, merchant);
111 QCOMPARE(merchant, QString(""));
113 // Try again with no root CA's, verifiedMerchant should be empty:
114 caStore = X509_STORE_new();
115 PaymentServer::LoadRootCAs(caStore);
116 data = DecodeBase64(paymentrequest1_cert1_BASE64);
117 r = handleRequest(server, data);
118 r.paymentRequest.getMerchant(caStore, merchant);
119 QCOMPARE(merchant, QString(""));
121 // Load second root certificate
122 caStore = X509_STORE_new();
123 X509_STORE_add_cert(caStore, parse_b64der_cert(caCert2_BASE64));
124 PaymentServer::LoadRootCAs(caStore);
126 QByteArray byteArray;
128 // For the tests below we just need the payment request data from
129 // paymentrequestdata.h parsed + stored in r.paymentRequest.
131 // These tests require us to bypass the following normal client execution flow
132 // shown below to be able to explicitly just trigger a certain condition!
134 // handleRequest()
135 // -> PaymentServer::eventFilter()
136 // -> PaymentServer::handleURIOrFile()
137 // -> PaymentServer::readPaymentRequestFromFile()
138 // -> PaymentServer::processPaymentRequest()
140 // Contains a testnet paytoaddress, so payment request network doesn't match client network:
141 data = DecodeBase64(paymentrequest1_cert2_BASE64);
142 byteArray = QByteArray((const char*)&data[0], data.size());
143 r.paymentRequest.parse(byteArray);
144 // Ensure the request is initialized, because network "main" is default, even for
145 // uninitialized payment requests and that will fail our test here.
146 QVERIFY(r.paymentRequest.IsInitialized());
147 QCOMPARE(PaymentServer::verifyNetwork(r.paymentRequest.getDetails()), false);
149 // Expired payment request (expires is set to 1 = 1970-01-01 00:00:01):
150 data = DecodeBase64(paymentrequest2_cert2_BASE64);
151 byteArray = QByteArray((const char*)&data[0], data.size());
152 r.paymentRequest.parse(byteArray);
153 // Ensure the request is initialized
154 QVERIFY(r.paymentRequest.IsInitialized());
155 // compares 1 < GetTime() == false (treated as expired payment request)
156 QCOMPARE(PaymentServer::verifyExpired(r.paymentRequest.getDetails()), true);
158 // Unexpired payment request (expires is set to 0x7FFFFFFFFFFFFFFF = max. int64_t):
159 // 9223372036854775807 (uint64), 9223372036854775807 (int64_t) and -1 (int32_t)
160 // -1 is 1969-12-31 23:59:59 (for a 32 bit time values)
161 data = DecodeBase64(paymentrequest3_cert2_BASE64);
162 byteArray = QByteArray((const char*)&data[0], data.size());
163 r.paymentRequest.parse(byteArray);
164 // Ensure the request is initialized
165 QVERIFY(r.paymentRequest.IsInitialized());
166 // compares 9223372036854775807 < GetTime() == false (treated as unexpired payment request)
167 QCOMPARE(PaymentServer::verifyExpired(r.paymentRequest.getDetails()), false);
169 // Unexpired payment request (expires is set to 0x8000000000000000 > max. int64_t, allowed uint64):
170 // 9223372036854775808 (uint64), -9223372036854775808 (int64_t) and 0 (int32_t)
171 // 0 is 1970-01-01 00:00:00 (for a 32 bit time values)
172 data = DecodeBase64(paymentrequest4_cert2_BASE64);
173 byteArray = QByteArray((const char*)&data[0], data.size());
174 r.paymentRequest.parse(byteArray);
175 // Ensure the request is initialized
176 QVERIFY(r.paymentRequest.IsInitialized());
177 // compares -9223372036854775808 < GetTime() == true (treated as expired payment request)
178 QCOMPARE(PaymentServer::verifyExpired(r.paymentRequest.getDetails()), true);
180 // Test BIP70 DoS protection:
181 unsigned char randData[BIP70_MAX_PAYMENTREQUEST_SIZE + 1];
182 GetRandBytes(randData, sizeof(randData));
183 // Write data to a temp file:
184 QTemporaryFile tempFile;
185 tempFile.open();
186 tempFile.write((const char*)randData, sizeof(randData));
187 tempFile.close();
188 // compares 50001 <= BIP70_MAX_PAYMENTREQUEST_SIZE == false
189 QCOMPARE(PaymentServer::verifySize(tempFile.size()), false);
191 // Payment request with amount overflow (amount is set to 21000001 BTC):
192 data = DecodeBase64(paymentrequest5_cert2_BASE64);
193 byteArray = QByteArray((const char*)&data[0], data.size());
194 r.paymentRequest.parse(byteArray);
195 // Ensure the request is initialized
196 QVERIFY(r.paymentRequest.IsInitialized());
197 // Extract address and amount from the request
198 QList<std::pair<CScript, CAmount> > sendingTos = r.paymentRequest.getPayTo();
199 Q_FOREACH (const PAIRTYPE(CScript, CAmount)& sendingTo, sendingTos) {
200 CTxDestination dest;
201 if (ExtractDestination(sendingTo.first, dest))
202 QCOMPARE(PaymentServer::verifyAmount(sendingTo.second), false);
205 delete server;
208 void RecipientCatcher::getRecipient(SendCoinsRecipient r)
210 recipient = r;