]> Git Repo - VerusCoin.git/blame - src/test/rpc_wallet_tests.cpp
Auto merge of #1370 - ageis:improve-fetch-params, r=daira
[VerusCoin.git] / src / test / rpc_wallet_tests.cpp
CommitLineData
3fc68461 1// Copyright (c) 2013-2014 The Bitcoin Core developers
78253fcb 2// Distributed under the MIT software license, see the accompanying
3fc68461
WL
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5094f8d4
WL
5#include "rpcserver.h"
6#include "rpcclient.h"
7
8#include "base58.h"
8a893c94 9#include "main.h"
50c72f23 10#include "wallet/wallet.h"
5094f8d4 11
51598b26
PW
12#include "test/test_bitcoin.h"
13
60f762a5
S
14#include "zcash/Address.hpp"
15
b922924d
S
16#include "rpcserver.h"
17#include "asyncrpcqueue.h"
18#include "asyncrpcoperation.h"
19#include "wallet/asyncrpcoperation_sendmany.h"
fc4b127e 20#include "rpcprotocol.h"
7b79275e 21#include "init.h"
b922924d
S
22
23#include <chrono>
24#include <thread>
25
60f762a5
S
26#include <fstream>
27#include <unordered_set>
28
5094f8d4
WL
29#include <boost/algorithm/string.hpp>
30#include <boost/test/unit_test.hpp>
60f762a5 31#include <boost/format.hpp>
5094f8d4
WL
32
33using namespace std;
34using namespace json_spirit;
35
bc470c43 36extern Array createArgs(int nRequired, const char* address1 = NULL, const char* address2 = NULL);
5094f8d4
WL
37extern Value CallRPC(string args);
38
fd67424c
GA
39extern CWallet* pwalletMain;
40
da5e7e51
S
41bool find_error(const Object& objError, const std::string& expected) {
42 return find_value(objError, "message").get_str().find(expected) != string::npos;
43}
44
51598b26 45BOOST_FIXTURE_TEST_SUITE(rpc_wallet_tests, TestingSetup)
5094f8d4
WL
46
47BOOST_AUTO_TEST_CASE(rpc_addmultisig)
48{
fd67424c
GA
49 LOCK(pwalletMain->cs_wallet);
50
5094f8d4
WL
51 rpcfn_type addmultisig = tableRPC["addmultisigaddress"]->actor;
52
53 // old, 65-byte-long:
54 const char address1Hex[] = "0434e3e09f49ea168c5bbf53f877ff4206923858aab7c7e1df25bc263978107c95e35065a27ef6f1b27222db0ec97e0e895eaca603d3ee0d4c060ce3d8a00286c8";
55 // new, compressed:
56 const char address2Hex[] = "0388c2037017c62240b6b72ac1a2a5f94da790596ebd06177c8572752922165cb4";
57
58 Value v;
59 CBitcoinAddress address;
60 BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(1, address1Hex), false));
61 address.SetString(v.get_str());
62 BOOST_CHECK(address.IsValid() && address.IsScript());
63
64 BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(1, address1Hex, address2Hex), false));
65 address.SetString(v.get_str());
66 BOOST_CHECK(address.IsValid() && address.IsScript());
67
68 BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(2, address1Hex, address2Hex), false));
69 address.SetString(v.get_str());
70 BOOST_CHECK(address.IsValid() && address.IsScript());
71
72 BOOST_CHECK_THROW(addmultisig(createArgs(0), false), runtime_error);
73 BOOST_CHECK_THROW(addmultisig(createArgs(1), false), runtime_error);
74 BOOST_CHECK_THROW(addmultisig(createArgs(2, address1Hex), false), runtime_error);
75
76 BOOST_CHECK_THROW(addmultisig(createArgs(1, ""), false), runtime_error);
77 BOOST_CHECK_THROW(addmultisig(createArgs(1, "NotAValidPubkey"), false), runtime_error);
78
bc470c43 79 string short1(address1Hex, address1Hex + sizeof(address1Hex) - 2); // last byte missing
5094f8d4
WL
80 BOOST_CHECK_THROW(addmultisig(createArgs(2, short1.c_str()), false), runtime_error);
81
bc470c43 82 string short2(address1Hex + 1, address1Hex + sizeof(address1Hex)); // first byte missing
5094f8d4
WL
83 BOOST_CHECK_THROW(addmultisig(createArgs(2, short2.c_str()), false), runtime_error);
84}
85
86BOOST_AUTO_TEST_CASE(rpc_wallet)
87{
88 // Test RPC calls for various wallet statistics
89 Value r;
90
ed671005 91 LOCK2(cs_main, pwalletMain->cs_wallet);
fd67424c 92
75ebced4 93 CPubKey demoPubkey = pwalletMain->GenerateNewKey();
bc470c43
ES
94 CBitcoinAddress demoAddress = CBitcoinAddress(CTxDestination(demoPubkey.GetID()));
95 Value retValue;
96 string strAccount = "walletDemoAccount";
97 string strPurpose = "receive";
98 BOOST_CHECK_NO_THROW({ /*Initialize Wallet with an account */
99 CWalletDB walletdb(pwalletMain->strWalletFile);
100 CAccount account;
101 account.vchPubKey = demoPubkey;
102 pwalletMain->SetAddressBook(account.vchPubKey.GetID(), strAccount, strPurpose);
103 walletdb.WriteAccount(strAccount, account);
104 });
75ebced4 105
31d6390f 106 CPubKey setaccountDemoPubkey = pwalletMain->GenerateNewKey();
bc470c43
ES
107 CBitcoinAddress setaccountDemoAddress = CBitcoinAddress(CTxDestination(setaccountDemoPubkey.GetID()));
108
109 /*********************************
110 * setaccount
111 *********************************/
112 BOOST_CHECK_NO_THROW(CallRPC("setaccount " + setaccountDemoAddress.ToString() + " nullaccount"));
113 /* 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ is not owned by the test wallet. */
114 BOOST_CHECK_THROW(CallRPC("setaccount 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ nullaccount"), runtime_error);
115 BOOST_CHECK_THROW(CallRPC("setaccount"), runtime_error);
116 /* 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4X (33 chars) is an illegal address (should be 34 chars) */
117 BOOST_CHECK_THROW(CallRPC("setaccount 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4X nullaccount"), runtime_error);
75ebced4 118
7c5dd603
EF
119
120 /*********************************
121 * getbalance
122 *********************************/
123 BOOST_CHECK_NO_THROW(CallRPC("getbalance"));
124 BOOST_CHECK_NO_THROW(CallRPC("getbalance " + demoAddress.ToString()));
125
75ebced4
AM
126 /*********************************
127 * listunspent
128 *********************************/
5094f8d4
WL
129 BOOST_CHECK_NO_THROW(CallRPC("listunspent"));
130 BOOST_CHECK_THROW(CallRPC("listunspent string"), runtime_error);
131 BOOST_CHECK_THROW(CallRPC("listunspent 0 string"), runtime_error);
132 BOOST_CHECK_THROW(CallRPC("listunspent 0 1 not_array"), runtime_error);
133 BOOST_CHECK_THROW(CallRPC("listunspent 0 1 [] extra"), runtime_error);
bc470c43 134 BOOST_CHECK_NO_THROW(r = CallRPC("listunspent 0 1 []"));
5094f8d4
WL
135 BOOST_CHECK(r.get_array().empty());
136
75ebced4 137 /*********************************
bc470c43
ES
138 * listreceivedbyaddress
139 *********************************/
5094f8d4
WL
140 BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress"));
141 BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress 0"));
142 BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress not_int"), runtime_error);
143 BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress 0 not_bool"), runtime_error);
144 BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress 0 true"));
145 BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress 0 true extra"), runtime_error);
146
75ebced4 147 /*********************************
bc470c43
ES
148 * listreceivedbyaccount
149 *********************************/
5094f8d4
WL
150 BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount"));
151 BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount 0"));
152 BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount not_int"), runtime_error);
153 BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount 0 not_bool"), runtime_error);
154 BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount 0 true"));
155 BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount 0 true extra"), runtime_error);
75ebced4 156
7c5dd603
EF
157 /*********************************
158 * listsinceblock
159 *********************************/
160 BOOST_CHECK_NO_THROW(CallRPC("listsinceblock"));
161
162 /*********************************
163 * listtransactions
164 *********************************/
165 BOOST_CHECK_NO_THROW(CallRPC("listtransactions"));
166 BOOST_CHECK_NO_THROW(CallRPC("listtransactions " + demoAddress.ToString()));
167 BOOST_CHECK_NO_THROW(CallRPC("listtransactions " + demoAddress.ToString() + " 20"));
168 BOOST_CHECK_NO_THROW(CallRPC("listtransactions " + demoAddress.ToString() + " 20 0"));
169 BOOST_CHECK_THROW(CallRPC("listtransactions " + demoAddress.ToString() + " not_int"), runtime_error);
170
171 /*********************************
172 * listlockunspent
173 *********************************/
174 BOOST_CHECK_NO_THROW(CallRPC("listlockunspent"));
175
176 /*********************************
177 * listaccounts
178 *********************************/
179 BOOST_CHECK_NO_THROW(CallRPC("listaccounts"));
180
181 /*********************************
182 * listaddressgroupings
183 *********************************/
184 BOOST_CHECK_NO_THROW(CallRPC("listaddressgroupings"));
185
75ebced4 186 /*********************************
bc470c43
ES
187 * getrawchangeaddress
188 *********************************/
75ebced4
AM
189 BOOST_CHECK_NO_THROW(CallRPC("getrawchangeaddress"));
190
191 /*********************************
bc470c43
ES
192 * getnewaddress
193 *********************************/
75ebced4
AM
194 BOOST_CHECK_NO_THROW(CallRPC("getnewaddress"));
195 BOOST_CHECK_NO_THROW(CallRPC("getnewaddress getnewaddress_demoaccount"));
196
197 /*********************************
bc470c43
ES
198 * getaccountaddress
199 *********************************/
75ebced4 200 BOOST_CHECK_NO_THROW(CallRPC("getaccountaddress \"\""));
bc470c43
ES
201 BOOST_CHECK_NO_THROW(CallRPC("getaccountaddress accountThatDoesntExists")); // Should generate a new account
202 BOOST_CHECK_NO_THROW(retValue = CallRPC("getaccountaddress " + strAccount));
203 BOOST_CHECK(CBitcoinAddress(retValue.get_str()).Get() == demoAddress.Get());
75ebced4 204
bc470c43
ES
205 /*********************************
206 * getaccount
207 *********************************/
208 BOOST_CHECK_THROW(CallRPC("getaccount"), runtime_error);
209 BOOST_CHECK_NO_THROW(CallRPC("getaccount " + demoAddress.ToString()));
210
211 /*********************************
212 * signmessage + verifymessage
213 *********************************/
214 BOOST_CHECK_NO_THROW(retValue = CallRPC("signmessage " + demoAddress.ToString() + " mymessage"));
215 BOOST_CHECK_THROW(CallRPC("signmessage"), runtime_error);
216 /* Should throw error because this address is not loaded in the wallet */
217 BOOST_CHECK_THROW(CallRPC("signmessage 1QFqqMUD55ZV3PJEJZtaKCsQmjLT6JkjvJ mymessage"), runtime_error);
218
219 /* missing arguments */
220 BOOST_CHECK_THROW(CallRPC("verifymessage " + demoAddress.ToString()), runtime_error);
221 BOOST_CHECK_THROW(CallRPC("verifymessage " + demoAddress.ToString() + " " + retValue.get_str()), runtime_error);
222 /* Illegal address */
223 BOOST_CHECK_THROW(CallRPC("verifymessage 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4X " + retValue.get_str() + " mymessage"), runtime_error);
224 /* wrong address */
225 BOOST_CHECK(CallRPC("verifymessage 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ " + retValue.get_str() + " mymessage").get_bool() == false);
226 /* Correct address and signature but wrong message */
227 BOOST_CHECK(CallRPC("verifymessage " + demoAddress.ToString() + " " + retValue.get_str() + " wrongmessage").get_bool() == false);
228 /* Correct address, message and signature*/
229 BOOST_CHECK(CallRPC("verifymessage " + demoAddress.ToString() + " " + retValue.get_str() + " mymessage").get_bool() == true);
230
231 /*********************************
232 * getaddressesbyaccount
233 *********************************/
234 BOOST_CHECK_THROW(CallRPC("getaddressesbyaccount"), runtime_error);
235 BOOST_CHECK_NO_THROW(retValue = CallRPC("getaddressesbyaccount " + strAccount));
236 Array arr = retValue.get_array();
237 BOOST_CHECK(arr.size() > 0);
238 BOOST_CHECK(CBitcoinAddress(arr[0].get_str()).Get() == demoAddress.Get());
5d50130b
S
239
240 /*
241 * getblocksubsidy
242 */
243 BOOST_CHECK_THROW(CallRPC("getblocksubsidy too many args"), runtime_error);
244 BOOST_CHECK_THROW(CallRPC("getblocksubsidy -1"), runtime_error);
245 BOOST_CHECK_NO_THROW(retValue = CallRPC("getblocksubsidy 50000"));
246 Object obj = retValue.get_obj();
247 BOOST_CHECK(find_value(obj, "miner") == 10.0);
248 BOOST_CHECK(find_value(obj, "founders") == 2.5);
249 BOOST_CHECK_NO_THROW(retValue = CallRPC("getblocksubsidy 1000000"));
250 obj = retValue.get_obj();
251 BOOST_CHECK(find_value(obj, "miner") == 6.25);
252 BOOST_CHECK(find_value(obj, "founders") == 0.0);
253 BOOST_CHECK_NO_THROW(retValue = CallRPC("getblocksubsidy 2000000"));
254 obj = retValue.get_obj();
255 BOOST_CHECK(find_value(obj, "miner") == 3.125);
256 BOOST_CHECK(find_value(obj, "founders") == 0.0);
5094f8d4
WL
257}
258
e883ffef
S
259BOOST_AUTO_TEST_CASE(rpc_wallet_getbalance)
260{
261 SelectParams(CBaseChainParams::TESTNET);
262
263 LOCK(pwalletMain->cs_wallet);
264
265
266 BOOST_CHECK_THROW(CallRPC("z_getbalance too many args"), runtime_error);
267 BOOST_CHECK_THROW(CallRPC("z_getbalance invalidaddress"), runtime_error);
268 BOOST_CHECK_NO_THROW(CallRPC("z_getbalance mhu9XfNv9o9JfTmEoTA6xKJHBfH2BVF8qG"));
269 BOOST_CHECK_THROW(CallRPC("z_getbalance mhu9XfNv9o9JfTmEoTA6xKJHBfH2BVF8qG -1"), runtime_error);
270 BOOST_CHECK_NO_THROW(CallRPC("z_getbalance mhu9XfNv9o9JfTmEoTA6xKJHBfH2BVF8qG 0"));
271 BOOST_CHECK_THROW(CallRPC("z_getbalance tnRZ8bPq2pff3xBWhTJhNkVUkm2uhzksDeW5PvEa7aFKGT9Qi3YgTALZfjaY4jU3HLVKBtHdSXxoPoLA3naMPcHBcY88FcF 1"), runtime_error);
272
273
274 BOOST_CHECK_THROW(CallRPC("z_gettotalbalance too manyargs"), runtime_error);
275 BOOST_CHECK_THROW(CallRPC("z_gettotalbalance -1"), runtime_error);
276 BOOST_CHECK_NO_THROW(CallRPC("z_gettotalbalance 0"));
277
278
279 BOOST_CHECK_THROW(CallRPC("z_listreceivedbyaddress too many args"), runtime_error);
280 // negative minconf not allowed
281 BOOST_CHECK_THROW(CallRPC("z_listreceivedbyaddress mhu9XfNv9o9JfTmEoTA6xKJHBfH2BVF8qG -1"), runtime_error);
282 // invalid zaddr, taddr not allowed
283 BOOST_CHECK_THROW(CallRPC("z_listreceivedbyaddress mhu9XfNv9o9JfTmEoTA6xKJHBfH2BVF8qG 0"), runtime_error);
284 // don't have the spending key
285 BOOST_CHECK_THROW(CallRPC("z_listreceivedbyaddress tnRZ8bPq2pff3xBWhTJhNkVUkm2uhzksDeW5PvEa7aFKGT9Qi3YgTALZfjaY4jU3HLVKBtHdSXxoPoLA3naMPcHBcY88FcF 1"), runtime_error);
286}
287
60f762a5
S
288/*
289 * This test covers RPC command z_exportwallet
290 */
291BOOST_AUTO_TEST_CASE(rpc_wallet_z_exportwallet)
292{
293 LOCK2(cs_main, pwalletMain->cs_wallet);
294
4b2e5571 295 // wallet should be empty
60f762a5
S
296 std::set<libzcash::PaymentAddress> addrs;
297 pwalletMain->GetPaymentAddresses(addrs);
298 BOOST_CHECK(addrs.size()==0);
299
300 // wallet should have one key
301 CZCPaymentAddress paymentAddress = pwalletMain->GenerateNewZKey();
302 pwalletMain->GetPaymentAddresses(addrs);
303 BOOST_CHECK(addrs.size()==1);
304
305 BOOST_CHECK_THROW(CallRPC("z_exportwallet"), runtime_error);
306
307
308 boost::filesystem::path temp = boost::filesystem::temp_directory_path() /
309 boost::filesystem::unique_path();
310 const std::string path = temp.native();
311
312 BOOST_CHECK_NO_THROW(CallRPC(string("z_exportwallet ") + path));
313
314 auto addr = paymentAddress.Get();
315 libzcash::SpendingKey key;
316 BOOST_CHECK(pwalletMain->GetSpendingKey(addr, key));
317
318 std::string s1 = paymentAddress.ToString();
319 std::string s2 = CZCSpendingKey(key).ToString();
320
321 // There's no way to really delete a private key so we will read in the
322 // exported wallet file and search for the spending key and payment address.
323
324 EnsureWalletIsUnlocked();
325
326 ifstream file;
327 file.open(path.c_str(), std::ios::in | std::ios::ate);
328 BOOST_CHECK(file.is_open());
329 bool fVerified = false;
330 int64_t nFilesize = std::max((int64_t)1, (int64_t)file.tellg());
331 file.seekg(0, file.beg);
332 while (file.good()) {
333 std::string line;
334 std::getline(file, line);
335 if (line.empty() || line[0] == '#')
336 continue;
337 if (line.find(s1) != std::string::npos && line.find(s2) != std::string::npos) {
338 fVerified = true;
339 break;
340 }
341 }
342 BOOST_CHECK(fVerified);
343}
344
345
346/*
347 * This test covers RPC command z_importwallet
348 */
349BOOST_AUTO_TEST_CASE(rpc_wallet_z_importwallet)
350{
351 LOCK2(cs_main, pwalletMain->cs_wallet);
352
353 // error if no args
354 BOOST_CHECK_THROW(CallRPC("z_importwallet"), runtime_error);
355
356 // create a random key locally
357 auto testSpendingKey = libzcash::SpendingKey::random();
358 auto testPaymentAddress = testSpendingKey.address();
359 std::string testAddr = CZCPaymentAddress(testPaymentAddress).ToString();
360 std::string testKey = CZCSpendingKey(testSpendingKey).ToString();
60f762a5
S
361
362 // create test data using the random key
363 std::string format_str = "# Wallet dump created by Zcash v0.11.2.0.z8-9155cc6-dirty (2016-08-11 11:37:00 -0700)\n"
364 "# * Created on 2016-08-12T21:55:36Z\n"
365 "# * Best block at time of backup was 0 (0de0a3851fef2d433b9b4f51d4342bdd24c5ddd793eb8fba57189f07e9235d52),\n"
366 "# mined on 2009-01-03T18:15:05Z\n"
367 "\n"
368 "# Zkeys\n"
369 "\n"
370 "%s 2016-08-12T21:55:36Z # zaddr=%s\n"
371 "\n"
372 "\n# End of dump";
373
374 boost::format formatobject(format_str);
375 std::string testWalletDump = (formatobject % testKey % testAddr).str();
60f762a5
S
376
377 // write test data to file
378 boost::filesystem::path temp = boost::filesystem::temp_directory_path() /
379 boost::filesystem::unique_path();
380 const std::string path = temp.native();
381 std::ofstream file(path);
382 file << testWalletDump;
383 file << std::flush;
384
385 // wallet should currently be empty
386 std::set<libzcash::PaymentAddress> addrs;
387 pwalletMain->GetPaymentAddresses(addrs);
388 BOOST_CHECK(addrs.size()==0);
389
390 // import test data from file into wallet
391 BOOST_CHECK_NO_THROW(CallRPC(string("z_importwallet ") + path));
392
393 // wallet should now have one zkey
394 pwalletMain->GetPaymentAddresses(addrs);
395 BOOST_CHECK(addrs.size()==1);
396
397 // check that we have the spending key for the address
398 CZCPaymentAddress address(testAddr);
399 auto addr = address.Get();
400 BOOST_CHECK(pwalletMain->HaveSpendingKey(addr));
401
4b2e5571 402 // Verify the spending key is the same as the test data
60f762a5
S
403 libzcash::SpendingKey k;
404 BOOST_CHECK(pwalletMain->GetSpendingKey(addr, k));
405 CZCSpendingKey spendingkey(k);
406 BOOST_CHECK_EQUAL(testKey, spendingkey.ToString());
60f762a5
S
407}
408
409
410/*
4b2e5571 411 * This test covers RPC commands z_listaddresses, z_importkey, z_exportkey
60f762a5
S
412 */
413BOOST_AUTO_TEST_CASE(rpc_wallet_z_importexport)
414{
415 LOCK2(cs_main, pwalletMain->cs_wallet);
416 Value retValue;
417 int n1 = 1000; // number of times to import/export
418 int n2 = 1000; // number of addresses to create and list
419
420 // error if no args
421 BOOST_CHECK_THROW(CallRPC("z_importkey"), runtime_error);
422 BOOST_CHECK_THROW(CallRPC("z_exportkey"), runtime_error);
423
424 // wallet should currently be empty
425 std::set<libzcash::PaymentAddress> addrs;
426 pwalletMain->GetPaymentAddresses(addrs);
427 BOOST_CHECK(addrs.size()==0);
428
429 // verify import and export key
430 for (int i = 0; i < n1; i++) {
431 // create a random key locally
432 auto testSpendingKey = libzcash::SpendingKey::random();
433 auto testPaymentAddress = testSpendingKey.address();
434 std::string testAddr = CZCPaymentAddress(testPaymentAddress).ToString();
435 std::string testKey = CZCSpendingKey(testSpendingKey).ToString();
436 BOOST_CHECK_NO_THROW(CallRPC(string("z_importkey ") + testKey));
437 BOOST_CHECK_NO_THROW(retValue = CallRPC(string("z_exportkey ") + testAddr));
438 BOOST_CHECK_EQUAL(retValue.get_str(), testKey);
439 }
440
441 // Verify we can list the keys imported
442 BOOST_CHECK_NO_THROW(retValue = CallRPC("z_listaddresses"));
443 Array arr = retValue.get_array();
444 BOOST_CHECK(arr.size() == n1);
445
446 // Put addresses into a set
447 std::unordered_set<std::string> myaddrs;
448 for (Value element : arr) {
449 myaddrs.insert(element.get_str());
450 }
451
452 // Make new addresses for the set
453 for (int i=0; i<n2; i++) {
454 myaddrs.insert((pwalletMain->GenerateNewZKey()).ToString());
455 }
456
457 // Verify number of addresses stored in wallet is n1+n2
458 int numAddrs = myaddrs.size();
459 BOOST_CHECK(numAddrs == n1+n2);
460 pwalletMain->GetPaymentAddresses(addrs);
461 BOOST_CHECK(addrs.size()==numAddrs);
462
463 // Ask wallet to list addresses
464 BOOST_CHECK_NO_THROW(retValue = CallRPC("z_listaddresses"));
465 arr = retValue.get_array();
466 BOOST_CHECK(arr.size() == numAddrs);
467
4b2e5571 468 // Create a set from them
60f762a5
S
469 std::unordered_set<std::string> listaddrs;
470 for (Value element : arr) {
471 listaddrs.insert(element.get_str());
472 }
473
474 // Verify the two sets of addresses are the same
475 BOOST_CHECK(listaddrs.size() == numAddrs);
476 BOOST_CHECK(myaddrs == listaddrs);
badb9a9c
S
477
478 // Add one more address
479 BOOST_CHECK_NO_THROW(retValue = CallRPC("z_getnewaddress"));
480 std::string newaddress = retValue.get_str();
481 CZCPaymentAddress pa(newaddress);
482 auto newAddr = pa.Get();
483 BOOST_CHECK(pwalletMain->HaveSpendingKey(newAddr));
60f762a5 484}
b922924d
S
485
486
487
488/**
fc4b127e 489 * Test Async RPC operations.
b922924d
S
490 * Tip: Create mock operations by subclassing AsyncRPCOperation.
491 */
fc4b127e 492
b922924d
S
493class MockSleepOperation : public AsyncRPCOperation {
494public:
495 std::chrono::milliseconds naptime;
496 MockSleepOperation(int t=1000) {
497 this->naptime = std::chrono::milliseconds(t);
498 }
499 virtual ~MockSleepOperation() {
500 }
501 virtual void main() {
502 set_state(OperationStatus::EXECUTING);
503 start_execution_clock();
504 std::this_thread::sleep_for(std::chrono::milliseconds(naptime));
505 stop_execution_clock();
506 set_result(Value("done"));
507 set_state(OperationStatus::SUCCESS);
508 }
509};
510
511
512/*
513 * Test Aysnc RPC queue and operations.
514 */
515BOOST_AUTO_TEST_CASE(rpc_wallet_async_operations)
516{
517 std::shared_ptr<AsyncRPCQueue> q = std::make_shared<AsyncRPCQueue>();
518 BOOST_CHECK(q->getNumberOfWorkers() == 0);
519 std::vector<AsyncRPCOperationId> ids = q->getAllOperationIds();
520 BOOST_CHECK(ids.size()==0);
521
522 std::shared_ptr<AsyncRPCOperation> op1 = std::make_shared<AsyncRPCOperation>();
523 q->addOperation(op1);
524 BOOST_CHECK(q->getOperationCount() == 1);
525
526 OperationStatus status = op1->getState();
527 BOOST_CHECK(status == OperationStatus::READY);
528
529 AsyncRPCOperationId id1 = op1->getId();
530 int64_t creationTime1 = op1->getCreationTime();
531
532 q->addWorker();
533 BOOST_CHECK(q->getNumberOfWorkers() == 1);
534
535 // an AsyncRPCOperation doesn't do anything so will finish immediately
536 std::this_thread::sleep_for(std::chrono::seconds(1));
537 BOOST_CHECK(q->getOperationCount() == 0);
538
539 // operation should be a success
540 BOOST_CHECK_EQUAL(op1->isCancelled(), false);
541 BOOST_CHECK_EQUAL(op1->isExecuting(), false);
542 BOOST_CHECK_EQUAL(op1->isReady(), false);
543 BOOST_CHECK_EQUAL(op1->isFailed(), false);
544 BOOST_CHECK_EQUAL(op1->isSuccess(), true);
545 BOOST_CHECK(op1->getError() == Value::null );
546 BOOST_CHECK(op1->getResult().is_null() == false );
547 BOOST_CHECK_EQUAL(op1->getStateAsString(), "success");
548 BOOST_CHECK_NE(op1->getStateAsString(), "executing");
549
550 // Create a second operation which just sleeps
551 std::shared_ptr<AsyncRPCOperation> op2(new MockSleepOperation(2500));
552 AsyncRPCOperationId id2 = op2->getId();
553 int64_t creationTime2 = op2->getCreationTime();
554
555 // it's different from the previous operation
556 BOOST_CHECK_NE(op1.get(), op2.get());
557 BOOST_CHECK_NE(id1, id2);
558 BOOST_CHECK_NE(creationTime1, creationTime2);
559
560 // Only the first operation has been added to the queue
561 std::vector<AsyncRPCOperationId> v = q->getAllOperationIds();
562 std::set<AsyncRPCOperationId> opids(v.begin(), v.end());
563 BOOST_CHECK(opids.size() == 1);
564 BOOST_CHECK(opids.count(id1)==1);
565 BOOST_CHECK(opids.count(id2)==0);
566 std::shared_ptr<AsyncRPCOperation> p1 = q->getOperationForId(id1);
567 BOOST_CHECK_EQUAL(p1.get(), op1.get());
568 std::shared_ptr<AsyncRPCOperation> p2 = q->getOperationForId(id2);
569 BOOST_CHECK(!p2); // null ptr as not added to queue yet
570
571 // Add operation 2 and 3 to the queue
572 q->addOperation(op2);
573 std::shared_ptr<AsyncRPCOperation> op3(new MockSleepOperation(1000));
574 q->addOperation(op3);
575 std::this_thread::sleep_for(std::chrono::milliseconds(500));
576 BOOST_CHECK_EQUAL(op2->isExecuting(), true);
577 op2->cancel(); // too late, already executing
578 op3->cancel();
579 std::this_thread::sleep_for(std::chrono::milliseconds(3000));
580 BOOST_CHECK_EQUAL(op2->isSuccess(), true);
581 BOOST_CHECK_EQUAL(op2->isCancelled(), false);
582 BOOST_CHECK_EQUAL(op3->isCancelled(), true);
583
584
585 v = q->getAllOperationIds();
586 std::copy( v.begin(), v.end(), std::inserter( opids, opids.end() ) );
587 BOOST_CHECK(opids.size() == 3);
588 BOOST_CHECK(opids.count(id1)==1);
589 BOOST_CHECK(opids.count(id2)==1);
590 BOOST_CHECK(opids.count(op3->getId())==1);
591 q->finishAndWait();
592}
593
594
595// The CountOperation will increment this global
596std::atomic<int64_t> gCounter(0);
597
598class CountOperation : public AsyncRPCOperation {
599public:
600 CountOperation() {}
601 virtual ~CountOperation() {}
602 virtual void main() {
603 set_state(OperationStatus::EXECUTING);
604 gCounter++;
605 std::this_thread::sleep_for(std::chrono::milliseconds(1000));
606 set_state(OperationStatus::SUCCESS);
607 }
608};
609
610// This tests the queue waiting for multiple workers to finish
611BOOST_AUTO_TEST_CASE(rpc_wallet_async_operations_parallel_wait)
612{
613 gCounter = 0;
614
615 std::shared_ptr<AsyncRPCQueue> q = std::make_shared<AsyncRPCQueue>();
616 q->addWorker();
617 q->addWorker();
618 q->addWorker();
619 q->addWorker();
620 BOOST_CHECK(q->getNumberOfWorkers() == 4);
621
622 int64_t numOperations = 10; // 10 * 1000ms / 4 = 2.5 secs to finish
623 for (int i=0; i<numOperations; i++) {
624 std::shared_ptr<AsyncRPCOperation> op(new CountOperation());
625 q->addOperation(op);
626 }
627
628 std::vector<AsyncRPCOperationId> ids = q->getAllOperationIds();
629 BOOST_CHECK(ids.size()==numOperations);
630 q->finishAndWait();
631 BOOST_CHECK_EQUAL(q->isFinishing(), true);
632 BOOST_CHECK_EQUAL(numOperations, gCounter.load());
633}
634
635// This tests the queue shutting down immediately
636BOOST_AUTO_TEST_CASE(rpc_wallet_async_operations_parallel_cancel)
637{
638 gCounter = 0;
639
640 std::shared_ptr<AsyncRPCQueue> q = std::make_shared<AsyncRPCQueue>();
641 q->addWorker();
642 q->addWorker();
643 BOOST_CHECK(q->getNumberOfWorkers() == 2);
644
fc4b127e 645 int numOperations = 10000; // 10000 seconds to complete
b922924d
S
646 for (int i=0; i<numOperations; i++) {
647 std::shared_ptr<AsyncRPCOperation> op(new CountOperation());
648 q->addOperation(op);
649 }
650 std::vector<AsyncRPCOperationId> ids = q->getAllOperationIds();
651 BOOST_CHECK(ids.size()==numOperations);
652 q->closeAndWait();
b922924d
S
653
654 int numSuccess = 0;
655 int numCancelled = 0;
656 for (auto & id : ids) {
657 std::shared_ptr<AsyncRPCOperation> ptr = q->popOperationForId(id);
658 if (ptr->isCancelled()) {
659 numCancelled++;
660 } else if (ptr->isSuccess()) {
661 numSuccess++;
662 }
663 }
60f762a5 664
b922924d
S
665 BOOST_CHECK_EQUAL(numOperations, numSuccess+numCancelled);
666 BOOST_CHECK_EQUAL(gCounter.load(), numSuccess);
667 BOOST_CHECK(q->getOperationCount() == 0);
668 ids = q->getAllOperationIds();
669 BOOST_CHECK(ids.size()==0);
670}
671
fc4b127e
S
672// This tests z_getoperationstatus, z_getoperationresult, z_listoperationids
673BOOST_AUTO_TEST_CASE(rpc_z_getoperations)
674{
675 std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue();
676 std::shared_ptr<AsyncRPCQueue> sharedInstance = AsyncRPCQueue::sharedInstance();
677 BOOST_CHECK(q == sharedInstance);
678
679 BOOST_CHECK_NO_THROW(CallRPC("z_getoperationstatus"));
680 BOOST_CHECK_NO_THROW(CallRPC("z_getoperationstatus []"));
681 BOOST_CHECK_NO_THROW(CallRPC("z_getoperationstatus [\"opid-1234\"]"));
682 BOOST_CHECK_THROW(CallRPC("z_getoperationstatus [] toomanyargs"), runtime_error);
683 BOOST_CHECK_THROW(CallRPC("z_getoperationstatus not_an_array"), runtime_error);
684
685 BOOST_CHECK_NO_THROW(CallRPC("z_getoperationresult"));
686 BOOST_CHECK_NO_THROW(CallRPC("z_getoperationresult []"));
687 BOOST_CHECK_NO_THROW(CallRPC("z_getoperationresult [\"opid-1234\"]"));
688 BOOST_CHECK_THROW(CallRPC("z_getoperationresult [] toomanyargs"), runtime_error);
689 BOOST_CHECK_THROW(CallRPC("z_getoperationresult not_an_array"), runtime_error);
690
691 std::shared_ptr<AsyncRPCOperation> op1 = std::make_shared<AsyncRPCOperation>();
692 q->addOperation(op1);
693 std::shared_ptr<AsyncRPCOperation> op2 = std::make_shared<AsyncRPCOperation>();
694 q->addOperation(op2);
695
696 BOOST_CHECK(q->getOperationCount() == 2);
697 BOOST_CHECK(q->getNumberOfWorkers() == 0);
698 q->addWorker();
699 BOOST_CHECK(q->getNumberOfWorkers() == 1);
700 std::this_thread::sleep_for(std::chrono::milliseconds(1000));
701 BOOST_CHECK(q->getOperationCount() == 0);
702
703 Value retValue;
704 BOOST_CHECK_NO_THROW(retValue = CallRPC("z_listoperationids"));
705 BOOST_CHECK(retValue.get_array().size() == 2);
706
707 BOOST_CHECK_NO_THROW(retValue = CallRPC("z_getoperationstatus"));
708 Array array = retValue.get_array();
709 BOOST_CHECK(array.size() == 2);
710
711 // idempotent
712 BOOST_CHECK_NO_THROW(retValue = CallRPC("z_getoperationstatus"));
713 array = retValue.get_array();
714 BOOST_CHECK(array.size() == 2);
715
716 for (Value v : array) {
717 Object obj = v.get_obj();
718 Value id = find_value(obj, "id");
719
720 Value result;
721 // removes result from internal storage
722 BOOST_CHECK_NO_THROW(result = CallRPC("z_getoperationresult [\"" + id.get_str() + "\"]"));
723 Array resultArray = result.get_array();
724 BOOST_CHECK(resultArray.size() == 1);
725
726 Object resultObj = resultArray.front().get_obj();
727 Value resultId = find_value(resultObj, "id");
728 BOOST_CHECK_EQUAL(id.get_str(), resultId.get_str());
da5e7e51
S
729
730 // verify the operation has been removed
731 BOOST_CHECK_NO_THROW(result = CallRPC("z_getoperationresult [\"" + id.get_str() + "\"]"));
732 resultArray = result.get_array();
733 BOOST_CHECK(resultArray.size() == 0);
fc4b127e
S
734 }
735
736 // operations removed
737 BOOST_CHECK_NO_THROW(retValue = CallRPC("z_getoperationstatus"));
738 array = retValue.get_array();
739 BOOST_CHECK(array.size() == 0);
740
741 q->close();
742}
743
744BOOST_AUTO_TEST_CASE(rpc_z_sendmany_parameters)
745{
746 SelectParams(CBaseChainParams::TESTNET);
747
748 LOCK(pwalletMain->cs_wallet);
749
750 BOOST_CHECK_THROW(CallRPC("z_sendmany"), runtime_error);
751 BOOST_CHECK_THROW(CallRPC("z_sendmany toofewargs"), runtime_error);
752 BOOST_CHECK_THROW(CallRPC("z_sendmany too many args here"), runtime_error);
753
754 // bad from address
da5e7e51
S
755 BOOST_CHECK_THROW(CallRPC("z_sendmany "
756 "INVALIDmwehwBzEHJTB5hiyxjmVkuFu9CHD2Cojjs []"), runtime_error);
fc4b127e 757 // empty amounts
da5e7e51
S
758 BOOST_CHECK_THROW(CallRPC("z_sendmany "
759 "mwehwBzEHJTB5hiyxjmVkuFu9CHD2Cojjs []"), runtime_error);
fc4b127e
S
760
761 // don't have the spending key for this address
da5e7e51
S
762 BOOST_CHECK_THROW(CallRPC("z_sendmany "
763 "tnpoQJVnYBZZqkFadj2bJJLThNCxbADGB5gSGeYTAGGrT5tejsxY9Zc1BtY8nnHmZkB"
764 "UkJ1oSfbhTJhm72WiZizvkZz5aH1 []"), runtime_error);
fc4b127e
S
765
766 // duplicate address
da5e7e51
S
767 BOOST_CHECK_THROW(CallRPC("z_sendmany "
768 "mwehwBzEHJTB5hiyxjmVkuFu9CHD2Cojjs "
769 "[{\"address\":\"mvBkHw3UTeV2ivipmSA6uo8yjN4DqZ5KoG\", \"amount\":50.0},"
770 " {\"address\":\"mvBkHw3UTeV2ivipmSA6uo8yjN4DqZ5KoG\", \"amount\":12.0} ]"
771 ), runtime_error);
fc4b127e
S
772
773 // memo bigger than allowed length of ZC_MEMO_SIZE
cff6f0ac
S
774 std::vector<char> v (2 * (ZC_MEMO_SIZE+1)); // x2 for hexadecimal string format
775 std::fill(v.begin(),v.end(), 'A');
fc4b127e
S
776 std::string badmemo(v.begin(), v.end());
777 CZCPaymentAddress pa = pwalletMain->GenerateNewZKey();
778 std::string zaddr1 = pa.ToString();
da5e7e51
S
779 BOOST_CHECK_THROW(CallRPC(string("z_sendmany mwehwBzEHJTB5hiyxjmVkuFu9CHD2Cojjs ")
780 + "[{\"address\":\"" + zaddr1 + "\", \"amount\":123.456}]"), runtime_error);
fc4b127e
S
781
782 // Test constructor of AsyncRPCOperation_sendmany
783 try {
784 std::shared_ptr<AsyncRPCOperation> operation(new AsyncRPCOperation_sendmany("",{}, {}, -1));
785 } catch (const Object& objError) {
da5e7e51 786 BOOST_CHECK( find_error(objError, "Minconf cannot be negative"));
fc4b127e
S
787 }
788
789 try {
790 std::shared_ptr<AsyncRPCOperation> operation(new AsyncRPCOperation_sendmany("",{}, {}, 1));
791 } catch (const Object& objError) {
da5e7e51 792 BOOST_CHECK( find_error(objError, "From address parameter missing"));
fc4b127e
S
793 }
794
795 try {
796 std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_sendmany("mwehwBzEHJTB5hiyxjmVkuFu9CHD2Cojjs", {}, {}, 1) );
797 } catch (const Object& objError) {
da5e7e51 798 BOOST_CHECK( find_error(objError, "No recipients"));
fc4b127e
S
799 }
800
801 try {
802 std::vector<SendManyRecipient> recipients = { SendManyRecipient("dummy",1.0, "") };
803 std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_sendmany("INVALID", recipients, {}, 1) );
804 } catch (const Object& objError) {
da5e7e51 805 BOOST_CHECK( find_error(objError, "payment address is invalid"));
fc4b127e
S
806 }
807
808 // This test is for testnet addresses which begin with 't' not 'z'.
809 try {
810 std::vector<SendManyRecipient> recipients = { SendManyRecipient("dummy",1.0, "") };
811 std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_sendmany("zcMuhvq8sEkHALuSU2i4NbNQxshSAYrpCExec45ZjtivYPbuiFPwk6WHy4SvsbeZ4siy1WheuRGjtaJmoD1J8bFqNXhsG6U", recipients, {}, 1) );
812 } catch (const Object& objError) {
da5e7e51 813 BOOST_CHECK( find_error(objError, "payment address is for wrong network type"));
fc4b127e
S
814 }
815
816 // Note: The following will crash as a google test because AsyncRPCOperation_sendmany
817 // invokes a method on pwalletMain, which is undefined in the google test environment.
818 try {
819 std::vector<SendManyRecipient> recipients = { SendManyRecipient("dummy",1.0, "") };
820 std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_sendmany("tnpoQJVnYBZZqkFadj2bJJLThNCxbADGB5gSGeYTAGGrT5tejsxY9Zc1BtY8nnHmZkBUkJ1oSfbhTJhm72WiZizvkZz5aH1", recipients, {}, 1) );
821 } catch (const Object& objError) {
da5e7e51 822 BOOST_CHECK( find_error(objError, "no spending key found for zaddr"));
fc4b127e
S
823 }
824}
825
cff6f0ac 826
fc4b127e
S
827// TODO: test private methods
828BOOST_AUTO_TEST_CASE(rpc_z_sendmany_internals)
829{
830 SelectParams(CBaseChainParams::TESTNET);
831
832 LOCK(pwalletMain->cs_wallet);
833
834 Value retValue;
835
836 // add keys manually
837 BOOST_CHECK_NO_THROW(retValue = CallRPC("getnewaddress"));
838 std::string taddr1 = retValue.get_str();
839 CZCPaymentAddress pa = pwalletMain->GenerateNewZKey();
840 std::string zaddr1 = pa.ToString();
841
842 // there are no utxos to spend
843 {
844 std::vector<SendManyRecipient> recipients = { SendManyRecipient(zaddr1,100.0, "DEADBEEF") };
845 std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_sendmany(taddr1, {}, recipients, 1) );
846 operation->main();
847 BOOST_CHECK(operation->isFailed());
848 std::string msg = operation->getErrorMessage();
849 BOOST_CHECK( msg.find("Insufficient funds, no UTXOs found") != string::npos);
850 }
851
852 // there are no unspent notes to spend
853 {
854 std::vector<SendManyRecipient> recipients = { SendManyRecipient(taddr1,100.0, "DEADBEEF") };
855 std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_sendmany(zaddr1, recipients, {}, 1) );
856 operation->main();
857 BOOST_CHECK(operation->isFailed());
858 std::string msg = operation->getErrorMessage();
859 BOOST_CHECK( msg.find("Insufficient funds, no unspent notes") != string::npos);
860 }
861
cff6f0ac
S
862 // get_memo_from_hex_string())
863 {
864 std::vector<SendManyRecipient> recipients = { SendManyRecipient(zaddr1,100.0, "DEADBEEF") };
865 std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_sendmany(zaddr1, recipients, {}, 1) );
866 std::shared_ptr<AsyncRPCOperation_sendmany> ptr = std::dynamic_pointer_cast<AsyncRPCOperation_sendmany> (operation);
867 TEST_FRIEND_AsyncRPCOperation_sendmany proxy(ptr);
868
869 std::string memo = "DEADBEEF";
870 boost::array<unsigned char, ZC_MEMO_SIZE> array = proxy.get_memo_from_hex_string(memo);
871 BOOST_CHECK_EQUAL(array[0], 0xDE);
872 BOOST_CHECK_EQUAL(array[1], 0xAD);
873 BOOST_CHECK_EQUAL(array[2], 0xBE);
874 BOOST_CHECK_EQUAL(array[3], 0xEF);
875 for (int i=4; i<ZC_MEMO_SIZE; i++) {
876 BOOST_CHECK_EQUAL(array[i], 0x00); // zero padding
877 }
878
879 // memo is longer than allowed
880 std::vector<char> v (2 * (ZC_MEMO_SIZE+1));
881 std::fill(v.begin(),v.end(), 'A');
882 std::string bigmemo(v.begin(), v.end());
883
884 try {
885 proxy.get_memo_from_hex_string(bigmemo);
886 } catch (const Object& objError) {
da5e7e51 887 BOOST_CHECK( find_error(objError, "too big"));
cff6f0ac
S
888 }
889
890 // invalid hexadecimal string
891 std::fill(v.begin(),v.end(), '@'); // not a hex character
892 std::string badmemo(v.begin(), v.end());
893
894 try {
895 proxy.get_memo_from_hex_string(badmemo);
896 } catch (const Object& objError) {
da5e7e51 897 BOOST_CHECK( find_error(objError, "hexadecimal format"));
cff6f0ac
S
898 }
899
900 // odd length hexadecimal string
901 std::fill(v.begin(),v.end(), 'A');
902 v.resize(v.size() - 1);
da5e7e51 903 assert(v.size() %2 == 1); // odd length
cff6f0ac
S
904 std::string oddmemo(v.begin(), v.end());
905 try {
906 proxy.get_memo_from_hex_string(oddmemo);
907 } catch (const Object& objError) {
da5e7e51 908 BOOST_CHECK( find_error(objError, "hexadecimal format"));
cff6f0ac
S
909 }
910 }
911
912
913 // add_taddr_change_output_to_tx() will append a vout to a raw transaction
914 {
915 std::vector<SendManyRecipient> recipients = { SendManyRecipient(zaddr1,100.0, "DEADBEEF") };
916 std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_sendmany(zaddr1, recipients, {}, 1) );
917 std::shared_ptr<AsyncRPCOperation_sendmany> ptr = std::dynamic_pointer_cast<AsyncRPCOperation_sendmany> (operation);
918 TEST_FRIEND_AsyncRPCOperation_sendmany proxy(ptr);
919
920 CTransaction tx = proxy.getTx();
921 BOOST_CHECK(tx.vout.size() == 0);
922
923 CAmount amount = 123.456;
924 proxy.add_taddr_change_output_to_tx(amount);
925 tx = proxy.getTx();
926 BOOST_CHECK(tx.vout.size() == 1);
927 CTxOut out = tx.vout[0];
928 BOOST_CHECK_EQUAL(out.nValue, amount);
929
930 amount = 1.111;
931 proxy.add_taddr_change_output_to_tx(amount);
932 tx = proxy.getTx();
933 BOOST_CHECK(tx.vout.size() == 2);
934 out = tx.vout[1];
935 BOOST_CHECK_EQUAL(out.nValue, amount);
936 }
937
938 // add_taddr_outputs_to_tx() will append many vouts to a raw transaction
939 {
940 std::vector<SendManyRecipient> recipients = {
941 SendManyRecipient("my53aS89nQ8SgJ8YgJ34cMHTWR33P5RTJ5",CAmount(1.23), ""),
942 SendManyRecipient("mzFCFsENQq5VxfCeKwTTb1QPWKYcKXPNvj",CAmount(4.56), ""),
943 SendManyRecipient("n4MmVRZdq7EgcJXgcvF5jkZT7wzH2CaWkv",CAmount(7.89), ""),
944 };
945 std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_sendmany(zaddr1, recipients, {}, 1) );
946 std::shared_ptr<AsyncRPCOperation_sendmany> ptr = std::dynamic_pointer_cast<AsyncRPCOperation_sendmany> (operation);
947 TEST_FRIEND_AsyncRPCOperation_sendmany proxy(ptr);
948
949 proxy.add_taddr_outputs_to_tx();
950
951 CTransaction tx = proxy.getTx();
952 BOOST_CHECK(tx.vout.size() == 3);
953 BOOST_CHECK_EQUAL(tx.vout[0].nValue, CAmount(1.23));
954 BOOST_CHECK_EQUAL(tx.vout[1].nValue, CAmount(4.56));
955 BOOST_CHECK_EQUAL(tx.vout[2].nValue, CAmount(7.89));
956 }
957
958
959 // Raw joinsplit is a zaddr->zaddr
960 {
961 std::string raw = "020000000000000000000100000000000000001027000000000000183a0d4c46c369078705e39bcfebee59a978dbd210ce8de3efc9555a03fbabfd3cea16693d730c63850d7e48ccde79854c19adcb7e9dcd7b7d18805ee09083f6b16e1860729d2d4a90e2f2acd009cf78b5eb0f4a6ee4bdb64b1262d7ce9eb910c460b02022991e968d0c50ee44908e4ccccbc591d0053bcca154dd6d6fc400a29fa686af4682339832ccea362a62aeb9df0d5aa74f86a1e75ac0f48a8ccc41e0a940643c6c33e1d09223b0a46eaf47a1bb4407cfc12b1dcf83a29c0cef51e45c7876ca5b9e5bae86d92976eb3ef68f29cd29386a8be8451b50f82bf9da10c04651868655194da8f6ed3d241bb5b5ff93a3e2bbe44644544d88bcde5cc35978032ee92699c7a61fcbb395e7583f47e698c4d53ede54f956629400bf510fb5e22d03158cc10bdcaaf29e418ef18eb6480dd9c8b9e2a377809f9f32a556ef872febd0021d4ad013aa9f0b7255e98e408d302abefd33a71180b720271835b487ab309e160b06dfe51932120fb84a7ede16b20c53599a11071592109e10260f265ee60d48c62bfe24074020e9b586ce9e9356e68f2ad1a9538258234afe4b83a209f178f45202270eaeaeecaf2ce3100b2c5a714f75f35777a9ebff5ebf47059d2bbf6f3726190216468f2b152673b766225b093f3a2f827c86d6b48b42117fec1d0ac38dd7af700308dcfb02eba821612b16a2c164c47715b9b0c93900893b1aba2ea03765c94d87022db5be06ab338d1912e0936dfe87586d0a8ee49144a6cd2e306abdcb652faa3e0222739deb23154d778b50de75069a4a2cce1208cd1ced3cb4744c9888ce1c2fcd2e66dc31e62d3aa9e423d7275882525e9981f92e84ac85975b8660739407efbe1e34c2249420fde7e17db3096d5b22e83d051d01f0e6e7690dca7d168db338aadf0897fedac10de310db2b1bff762d322935dddbb60c2efb8b15d231fa17b84630371cb275c209f0c4c7d0c68b150ea5cd514122215e3f7fcfb351d69514788d67c2f3c8922581946e3a04bdf1f07f15696ca76eb95b10698bf1188fd882945c57657515889d042a6fc45d38cbc943540c4f0f6d1c45a1574c81f3e42d1eb8702328b729909adee8a5cfed7c79d54627d1fd389af941d878376f7927b9830ca659bf9ab18c5ca5192d52d02723008728d03701b8ab3e1c4a3109409ec0b13df334c7deec3523eeef4c97b5603e643de3a647b873f4c1b47fbfc6586ba66724f112e51fc93839648005043620aa3ce458e246d77977b19c53d98e3e812de006afc1a79744df236582943631d04cc02941ac4be500e4ed9fb9e3e7cc187b1c4050fad1d9d09d5fd70d5d01d615b439d8c0015d2eb10398bcdbf8c4b2bd559dbe4c288a186aed3f86f608da4d582e120c4a896e015e2241900d1daeccd05db968852677c71d752bec46de9962174b46f980e8cc603654daf8b98a3ee92dac066033954164a89568b70b1780c2ce2410b2f816dbeddb2cd463e0c8f21a52cf6427d9647a6fd4bafa8fb4cd4d47ac057b0160bee86c6b2fb8adce214c2bcdda277512200adf0eaa5d2114a2c077b009836a68ec254bfe56f51d147b9afe2ddd9cb917c0c2de19d81b7b8fd9f4574f51fa1207630dc13976f4d7587c962f761af267de71f3909a576e6bedaf6311633910d291ac292c467cc8331ef577aef7646a5d949322fa0367a49f20597a13def53136ee31610395e3e48d291fd8f58504374031fe9dcfba5e06086ebcf01a9106f6a4d6e16e19e4c5bb893f7da79419c94eca31a384be6fa1747284dee0fc3bbc8b1b860172c10b29c1594bb8c747d7fe05827358ff2160f49050001625ffe2e880bd7fc26cd0ffd89750745379a8e862816e08a5a2008043921ab6a4976064ac18f7ee37b6628bc0127d8d5ebd3548e41d8881a082d86f20b32e33094f15a0e6ea6074b08c6cd28142de94713451640a55985051f5577eb54572699d838cb34a79c8939e981c0c277d06a6e2ce69ccb74f8a691ff08f81d8b99e6a86223d29a2b7c8e7b041aba44ea678ae654277f7e91cbfa79158b989164a3d549d9f4feb0cc43169699c13e321fe3f4b94258c75d198ff9184269cd6986c55409e07528c93f64942c6c283ce3917b4bf4c3be2fe3173c8c38cccb35f1fbda0ca88b35a599c0678cb22aa8eabea8249dbd2e4f849fffe69803d299e435ebcd7df95854003d8eda17a74d98b4be0e62d45d7fe48c06a6f464a14f8e0570077cc631279092802a89823f031eef5e1028a6d6fdbd502869a731ee7d28b4d6c71b419462a30d31442d3ee444ffbcbd16d558c9000c97e949c2b1f9d6f6d8db7b9131ebd963620d3fc8595278d6f8fdf49084325373196d53e64142fa5a23eccd6ef908c4d80b8b3e6cc334b7f7012103a3682e4678e9b518163d262a39a2c1a69bf88514c52b7ccd7cc8dc80e71f7c2ec0701cff982573eb0c2c4daeb47fa0b586f4451c10d1da2e5d182b03dd067a5e971b3a6138ca6667aaf853d2ac03b80a1d5870905f2cfb6c78ec3c3719c02f973d638a0f973424a2b0f2b0023f136d60092fe15fba4bc180b9176bd0ff576e053f1af6939fe9ca256203ffaeb3e569f09774d2a6cbf91873e56651f4d6ff77e0b5374b0a1a201d7e523604e0247644544cc571d48c458a4f96f45580b";
962 Object obj;
963 obj.push_back(Pair("rawtxn", raw));
964
965 // we have the spending key for the dummy recipient zaddr1
966 std::vector<SendManyRecipient> recipients = { SendManyRecipient(zaddr1, 0.0005, "ABCD") };
967
968 std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_sendmany(zaddr1, {}, recipients, 1) );
969 std::shared_ptr<AsyncRPCOperation_sendmany> ptr = std::dynamic_pointer_cast<AsyncRPCOperation_sendmany> (operation);
970 TEST_FRIEND_AsyncRPCOperation_sendmany proxy(ptr);
971
972 // Enable test mode so tx is not sent
973 static_cast<AsyncRPCOperation_sendmany *>(operation.get())->testmode = true;
da5e7e51
S
974
975 // Pretend that the operation completed successfully
976 proxy.set_state(OperationStatus::SUCCESS);
cff6f0ac 977
da5e7e51 978 // Verify test mode is returning output (since no input taddrs, signed and unsigned are the same).
cff6f0ac 979 BOOST_CHECK_NO_THROW( proxy.sign_send_raw_transaction(obj) );
da5e7e51
S
980 Value result = operation->getResult();
981 BOOST_CHECK(!result.is_null());
982 Object resultObj = result.get_obj();
983 std::string hex = find_value(resultObj, "hex").get_str();
984 BOOST_CHECK_EQUAL(hex, raw);
cff6f0ac 985 }
7b79275e
S
986
987
988 // Test the perform_joinsplit methods.
989 {
990 // Dummy input so the operation object can be instantiated.
991 std::vector<SendManyRecipient> recipients = { SendManyRecipient(zaddr1, 0.0005, "ABCD") };
992
993 std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_sendmany(zaddr1, {}, recipients, 1) );
994 std::shared_ptr<AsyncRPCOperation_sendmany> ptr = std::dynamic_pointer_cast<AsyncRPCOperation_sendmany> (operation);
995 TEST_FRIEND_AsyncRPCOperation_sendmany proxy(ptr);
996
997 // Enable test mode so tx is not sent and proofs are not generated
998 static_cast<AsyncRPCOperation_sendmany *>(operation.get())->testmode = true;
999
1000 AsyncJoinSplitInfo info;
1001 std::vector<boost::optional < ZCIncrementalWitness>> witnesses;
1002 uint256 anchor;
1003 try {
1004 proxy.perform_joinsplit(info, witnesses, anchor);
1005 } catch (const std::runtime_error & e) {
1006 BOOST_CHECK( string(e.what()).find("anchor is null")!= string::npos);
1007 }
1008
1009 try {
1010 std::vector<JSOutPoint> v;
1011 proxy.perform_joinsplit(info, v);
1012 } catch (const std::runtime_error & e) {
1013 BOOST_CHECK( string(e.what()).find("anchor is null")!= string::npos);
1014 }
1015
1016 info.notes.push_back(Note());
1017 try {
1018 proxy.perform_joinsplit(info);
1019 } catch (const std::runtime_error & e) {
1020 BOOST_CHECK( string(e.what()).find("number of notes")!= string::npos);
1021 }
1022
1023 info.notes.clear();
1024 info.vjsin.push_back(JSInput());
1025 info.vjsin.push_back(JSInput());
1026 info.vjsin.push_back(JSInput());
1027 try {
1028 proxy.perform_joinsplit(info);
1029 } catch (const std::runtime_error & e) {
1030 BOOST_CHECK( string(e.what()).find("unsupported joinsplit input")!= string::npos);
1031 }
1032
1033 info.vjsin.clear();
1034 try {
1035 proxy.perform_joinsplit(info);
1036 } catch (const std::runtime_error & e) {
1037 BOOST_CHECK( string(e.what()).find("JoinSplit verifying key not loaded")!= string::npos);
1038 }
1039 }
1040
fc4b127e
S
1041}
1042
60f762a5 1043
b922924d 1044BOOST_AUTO_TEST_SUITE_END()
This page took 0.278903 seconds and 4 git commands to generate.