]> Git Repo - VerusCoin.git/blame - src/test/rpc_wallet_tests.cpp
Merge pull request #23 from Asherda/dev
[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
4519a766
DC
5#include "rpc/server.h"
6#include "rpc/client.h"
5094f8d4 7
93bd00a0 8#include "key_io.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 "asyncrpcqueue.h"
17#include "asyncrpcoperation.h"
6e9c7629 18#include "wallet/asyncrpcoperation_mergetoaddress.h"
b922924d 19#include "wallet/asyncrpcoperation_sendmany.h"
06c19063
S
20#include "wallet/asyncrpcoperation_shieldcoinbase.h"
21
7b79275e 22#include "init.h"
b922924d 23
a6bbb26e 24#include <array>
b922924d
S
25#include <chrono>
26#include <thread>
27
60f762a5
S
28#include <fstream>
29#include <unordered_set>
30
5094f8d4
WL
31#include <boost/algorithm/string.hpp>
32#include <boost/test/unit_test.hpp>
60f762a5 33#include <boost/format.hpp>
6be367ea 34#include <boost/filesystem.hpp>
5094f8d4 35
a10a6e2a 36#include <univalue.h>
d014114d 37
5094f8d4 38using namespace std;
5094f8d4 39
851f58f9 40extern UniValue createArgs(int nRequired, const char* address1 = NULL, const char* address2 = NULL);
d014114d 41extern UniValue CallRPC(string args);
5094f8d4 42
fd67424c
GA
43extern CWallet* pwalletMain;
44
0d37ae3a 45bool find_error(const UniValue& objError, const std::string& expected) {
da5e7e51
S
46 return find_value(objError, "message").get_str().find(expected) != string::npos;
47}
48
bf69507c 49static UniValue ValueFromString(const std::string &str)
50{
51 UniValue value;
52 BOOST_CHECK(value.setNumStr(str));
53 return value;
54}
55
51598b26 56BOOST_FIXTURE_TEST_SUITE(rpc_wallet_tests, TestingSetup)
5094f8d4
WL
57
58BOOST_AUTO_TEST_CASE(rpc_addmultisig)
59{
fd67424c
GA
60 LOCK(pwalletMain->cs_wallet);
61
5094f8d4
WL
62 rpcfn_type addmultisig = tableRPC["addmultisigaddress"]->actor;
63
64 // old, 65-byte-long:
65 const char address1Hex[] = "0434e3e09f49ea168c5bbf53f877ff4206923858aab7c7e1df25bc263978107c95e35065a27ef6f1b27222db0ec97e0e895eaca603d3ee0d4c060ce3d8a00286c8";
66 // new, compressed:
67 const char address2Hex[] = "0388c2037017c62240b6b72ac1a2a5f94da790596ebd06177c8572752922165cb4";
68
d014114d 69 UniValue v;
b6be3e88 70 CTxDestination address;
5094f8d4 71 BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(1, address1Hex), false));
b6be3e88
JG
72 address = DecodeDestination(v.get_str());
73 BOOST_CHECK(IsValidDestination(address) && boost::get<CScriptID>(&address) != nullptr);
5094f8d4
WL
74
75 BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(1, address1Hex, address2Hex), false));
b6be3e88
JG
76 address = DecodeDestination(v.get_str());
77 BOOST_CHECK(IsValidDestination(address) && boost::get<CScriptID>(&address) != nullptr);
5094f8d4
WL
78
79 BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(2, address1Hex, address2Hex), false));
b6be3e88
JG
80 address = DecodeDestination(v.get_str());
81 BOOST_CHECK(IsValidDestination(address) && boost::get<CScriptID>(&address) != nullptr);
5094f8d4
WL
82
83 BOOST_CHECK_THROW(addmultisig(createArgs(0), false), runtime_error);
84 BOOST_CHECK_THROW(addmultisig(createArgs(1), false), runtime_error);
85 BOOST_CHECK_THROW(addmultisig(createArgs(2, address1Hex), false), runtime_error);
86
87 BOOST_CHECK_THROW(addmultisig(createArgs(1, ""), false), runtime_error);
88 BOOST_CHECK_THROW(addmultisig(createArgs(1, "NotAValidPubkey"), false), runtime_error);
89
bc470c43 90 string short1(address1Hex, address1Hex + sizeof(address1Hex) - 2); // last byte missing
5094f8d4
WL
91 BOOST_CHECK_THROW(addmultisig(createArgs(2, short1.c_str()), false), runtime_error);
92
bc470c43 93 string short2(address1Hex + 1, address1Hex + sizeof(address1Hex)); // first byte missing
5094f8d4
WL
94 BOOST_CHECK_THROW(addmultisig(createArgs(2, short2.c_str()), false), runtime_error);
95}
96
97BOOST_AUTO_TEST_CASE(rpc_wallet)
98{
99 // Test RPC calls for various wallet statistics
d014114d 100 UniValue r;
5094f8d4 101
ed671005 102 LOCK2(cs_main, pwalletMain->cs_wallet);
fd67424c 103
75ebced4 104 CPubKey demoPubkey = pwalletMain->GenerateNewKey();
b6be3e88 105 CTxDestination demoAddress(CTxDestination(demoPubkey.GetID()));
d014114d 106 UniValue retValue;
b6f100cf 107 string strAccount = "";
bc470c43
ES
108 string strPurpose = "receive";
109 BOOST_CHECK_NO_THROW({ /*Initialize Wallet with an account */
110 CWalletDB walletdb(pwalletMain->strWalletFile);
111 CAccount account;
112 account.vchPubKey = demoPubkey;
113 pwalletMain->SetAddressBook(account.vchPubKey.GetID(), strAccount, strPurpose);
114 walletdb.WriteAccount(strAccount, account);
115 });
75ebced4 116
31d6390f 117 CPubKey setaccountDemoPubkey = pwalletMain->GenerateNewKey();
b6be3e88 118 CTxDestination setaccountDemoAddress(CTxDestination(setaccountDemoPubkey.GetID()));
bc470c43
ES
119
120 /*********************************
121 * setaccount
122 *********************************/
b6be3e88 123 BOOST_CHECK_NO_THROW(CallRPC("setaccount " + EncodeDestination(setaccountDemoAddress) + " \"\""));
b6f100cf 124 /* Accounts are disabled */
b6be3e88 125 BOOST_CHECK_THROW(CallRPC("setaccount " + EncodeDestination(setaccountDemoAddress) + " nullaccount"), runtime_error);
ee64b5e7
JG
126 /* t1VtArtnn1dGPiD2WFfMXYXW5mHM3q1GpgV is not owned by the test wallet. */
127 BOOST_CHECK_THROW(CallRPC("setaccount t1VtArtnn1dGPiD2WFfMXYXW5mHM3q1GpgV nullaccount"), runtime_error);
bc470c43 128 BOOST_CHECK_THROW(CallRPC("setaccount"), runtime_error);
ee64b5e7
JG
129 /* t1VtArtnn1dGPiD2WFfMXYXW5mHM3q1Gpg (34 chars) is an illegal address (should be 35 chars) */
130 BOOST_CHECK_THROW(CallRPC("setaccount t1VtArtnn1dGPiD2WFfMXYXW5mHM3q1Gpg nullaccount"), runtime_error);
75ebced4 131
7c5dd603
EF
132
133 /*********************************
134 * getbalance
135 *********************************/
136 BOOST_CHECK_NO_THROW(CallRPC("getbalance"));
b6be3e88 137 BOOST_CHECK_THROW(CallRPC("getbalance " + EncodeDestination(demoAddress)), runtime_error);
7c5dd603 138
75ebced4
AM
139 /*********************************
140 * listunspent
141 *********************************/
5094f8d4
WL
142 BOOST_CHECK_NO_THROW(CallRPC("listunspent"));
143 BOOST_CHECK_THROW(CallRPC("listunspent string"), runtime_error);
144 BOOST_CHECK_THROW(CallRPC("listunspent 0 string"), runtime_error);
145 BOOST_CHECK_THROW(CallRPC("listunspent 0 1 not_array"), runtime_error);
146 BOOST_CHECK_THROW(CallRPC("listunspent 0 1 [] extra"), runtime_error);
bc470c43 147 BOOST_CHECK_NO_THROW(r = CallRPC("listunspent 0 1 []"));
5094f8d4
WL
148 BOOST_CHECK(r.get_array().empty());
149
75ebced4 150 /*********************************
bc470c43
ES
151 * listreceivedbyaddress
152 *********************************/
5094f8d4
WL
153 BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress"));
154 BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress 0"));
155 BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress not_int"), runtime_error);
156 BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress 0 not_bool"), runtime_error);
157 BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress 0 true"));
158 BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress 0 true extra"), runtime_error);
159
75ebced4 160 /*********************************
bc470c43
ES
161 * listreceivedbyaccount
162 *********************************/
5094f8d4
WL
163 BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount"));
164 BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount 0"));
165 BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount not_int"), runtime_error);
166 BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount 0 not_bool"), runtime_error);
167 BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount 0 true"));
168 BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount 0 true extra"), runtime_error);
75ebced4 169
7c5dd603
EF
170 /*********************************
171 * listsinceblock
172 *********************************/
173 BOOST_CHECK_NO_THROW(CallRPC("listsinceblock"));
174
175 /*********************************
176 * listtransactions
177 *********************************/
178 BOOST_CHECK_NO_THROW(CallRPC("listtransactions"));
b6be3e88
JG
179 BOOST_CHECK_NO_THROW(CallRPC("listtransactions " + EncodeDestination(demoAddress)));
180 BOOST_CHECK_NO_THROW(CallRPC("listtransactions " + EncodeDestination(demoAddress) + " 20"));
181 BOOST_CHECK_NO_THROW(CallRPC("listtransactions " + EncodeDestination(demoAddress) + " 20 0"));
182 BOOST_CHECK_THROW(CallRPC("listtransactions " + EncodeDestination(demoAddress) + " not_int"), runtime_error);
7c5dd603
EF
183
184 /*********************************
185 * listlockunspent
186 *********************************/
187 BOOST_CHECK_NO_THROW(CallRPC("listlockunspent"));
188
189 /*********************************
190 * listaccounts
191 *********************************/
192 BOOST_CHECK_NO_THROW(CallRPC("listaccounts"));
193
194 /*********************************
195 * listaddressgroupings
196 *********************************/
197 BOOST_CHECK_NO_THROW(CallRPC("listaddressgroupings"));
198
75ebced4 199 /*********************************
bc470c43
ES
200 * getrawchangeaddress
201 *********************************/
75ebced4
AM
202 BOOST_CHECK_NO_THROW(CallRPC("getrawchangeaddress"));
203
204 /*********************************
bc470c43
ES
205 * getnewaddress
206 *********************************/
75ebced4 207 BOOST_CHECK_NO_THROW(CallRPC("getnewaddress"));
b6f100cf
JG
208 BOOST_CHECK_NO_THROW(CallRPC("getnewaddress \"\""));
209 /* Accounts are deprecated */
210 BOOST_CHECK_THROW(CallRPC("getnewaddress getnewaddress_demoaccount"), runtime_error);
75ebced4
AM
211
212 /*********************************
bc470c43
ES
213 * getaccountaddress
214 *********************************/
75ebced4 215 BOOST_CHECK_NO_THROW(CallRPC("getaccountaddress \"\""));
b6f100cf
JG
216 /* Accounts are deprecated */
217 BOOST_CHECK_THROW(CallRPC("getaccountaddress accountThatDoesntExists"), runtime_error);
bc470c43 218 BOOST_CHECK_NO_THROW(retValue = CallRPC("getaccountaddress " + strAccount));
b6be3e88 219 BOOST_CHECK(DecodeDestination(retValue.get_str()) == demoAddress);
75ebced4 220
bc470c43
ES
221 /*********************************
222 * getaccount
223 *********************************/
224 BOOST_CHECK_THROW(CallRPC("getaccount"), runtime_error);
b6be3e88 225 BOOST_CHECK_NO_THROW(CallRPC("getaccount " + EncodeDestination(demoAddress)));
bc470c43
ES
226
227 /*********************************
228 * signmessage + verifymessage
229 *********************************/
b6be3e88 230 BOOST_CHECK_NO_THROW(retValue = CallRPC("signmessage " + EncodeDestination(demoAddress) + " mymessage"));
bc470c43
ES
231 BOOST_CHECK_THROW(CallRPC("signmessage"), runtime_error);
232 /* Should throw error because this address is not loaded in the wallet */
ee64b5e7 233 BOOST_CHECK_THROW(CallRPC("signmessage t1h8SqgtM3QM5e2M8EzhhT1yL2PXXtA6oqe mymessage"), runtime_error);
bc470c43
ES
234
235 /* missing arguments */
b6be3e88
JG
236 BOOST_CHECK_THROW(CallRPC("verifymessage " + EncodeDestination(demoAddress)), runtime_error);
237 BOOST_CHECK_THROW(CallRPC("verifymessage " + EncodeDestination(demoAddress) + " " + retValue.get_str()), runtime_error);
bc470c43 238 /* Illegal address */
ee64b5e7 239 BOOST_CHECK_THROW(CallRPC("verifymessage t1VtArtnn1dGPiD2WFfMXYXW5mHM3q1Gpg " + retValue.get_str() + " mymessage"), runtime_error);
bc470c43 240 /* wrong address */
ee64b5e7 241 BOOST_CHECK(CallRPC("verifymessage t1VtArtnn1dGPiD2WFfMXYXW5mHM3q1GpgV " + retValue.get_str() + " mymessage").get_bool() == false);
bc470c43 242 /* Correct address and signature but wrong message */
b6be3e88 243 BOOST_CHECK(CallRPC("verifymessage " + EncodeDestination(demoAddress) + " " + retValue.get_str() + " wrongmessage").get_bool() == false);
bc470c43 244 /* Correct address, message and signature*/
b6be3e88 245 BOOST_CHECK(CallRPC("verifymessage " + EncodeDestination(demoAddress) + " " + retValue.get_str() + " mymessage").get_bool() == true);
bc470c43
ES
246
247 /*********************************
248 * getaddressesbyaccount
249 *********************************/
250 BOOST_CHECK_THROW(CallRPC("getaddressesbyaccount"), runtime_error);
251 BOOST_CHECK_NO_THROW(retValue = CallRPC("getaddressesbyaccount " + strAccount));
851f58f9 252 UniValue arr = retValue.get_array();
b6f100cf
JG
253 BOOST_CHECK_EQUAL(4, arr.size());
254 bool notFound = true;
0d37ae3a 255 for (auto a : arr.getValues()) {
b6be3e88 256 notFound &= DecodeDestination(a.get_str()) != demoAddress;
b6f100cf
JG
257 }
258 BOOST_CHECK(!notFound);
5d50130b 259
3d8013a0
MC
260 /*********************************
261 * fundrawtransaction
262 *********************************/
263 BOOST_CHECK_THROW(CallRPC("fundrawtransaction 28z"), runtime_error);
264 BOOST_CHECK_THROW(CallRPC("fundrawtransaction 01000000000180969800000000001976a91450ce0a4b0ee0ddeb633da85199728b940ac3fe9488ac00000000"), runtime_error);
265
5d50130b
S
266 /*
267 * getblocksubsidy
268 */
269 BOOST_CHECK_THROW(CallRPC("getblocksubsidy too many args"), runtime_error);
270 BOOST_CHECK_THROW(CallRPC("getblocksubsidy -1"), runtime_error);
271 BOOST_CHECK_NO_THROW(retValue = CallRPC("getblocksubsidy 50000"));
0d37ae3a
JG
272 UniValue obj = retValue.get_obj();
273 BOOST_CHECK_EQUAL(find_value(obj, "miner").get_real(), 10.0);
274 BOOST_CHECK_EQUAL(find_value(obj, "founders").get_real(), 2.5);
5d50130b
S
275 BOOST_CHECK_NO_THROW(retValue = CallRPC("getblocksubsidy 1000000"));
276 obj = retValue.get_obj();
0d37ae3a
JG
277 BOOST_CHECK_EQUAL(find_value(obj, "miner").get_real(), 6.25);
278 BOOST_CHECK_EQUAL(find_value(obj, "founders").get_real(), 0.0);
5d50130b
S
279 BOOST_CHECK_NO_THROW(retValue = CallRPC("getblocksubsidy 2000000"));
280 obj = retValue.get_obj();
0d37ae3a
JG
281 BOOST_CHECK_EQUAL(find_value(obj, "miner").get_real(), 3.125);
282 BOOST_CHECK_EQUAL(find_value(obj, "founders").get_real(), 0.0);
7d3b1528
S
283
284 /*
285 * getblock
286 */
287 BOOST_CHECK_THROW(CallRPC("getblock too many args"), runtime_error);
288 BOOST_CHECK_THROW(CallRPC("getblock -1"), runtime_error);
289 BOOST_CHECK_THROW(CallRPC("getblock 2147483647"), runtime_error); // allowed, but > height of active chain tip
290 BOOST_CHECK_THROW(CallRPC("getblock 2147483648"), runtime_error); // not allowed, > int32 used for nHeight
291 BOOST_CHECK_THROW(CallRPC("getblock 100badchars"), runtime_error);
292 BOOST_CHECK_NO_THROW(CallRPC("getblock 0"));
9bd8f092
S
293 BOOST_CHECK_NO_THROW(CallRPC("getblock 0 0"));
294 BOOST_CHECK_NO_THROW(CallRPC("getblock 0 1"));
295 BOOST_CHECK_NO_THROW(CallRPC("getblock 0 2"));
296 BOOST_CHECK_THROW(CallRPC("getblock 0 -1"), runtime_error); // bad verbosity
297 BOOST_CHECK_THROW(CallRPC("getblock 0 3"), runtime_error); // bad verbosity
5094f8d4
WL
298}
299
e883ffef
S
300BOOST_AUTO_TEST_CASE(rpc_wallet_getbalance)
301{
302 SelectParams(CBaseChainParams::TESTNET);
303
304 LOCK(pwalletMain->cs_wallet);
305
06c19063 306
e883ffef
S
307 BOOST_CHECK_THROW(CallRPC("z_getbalance too many args"), runtime_error);
308 BOOST_CHECK_THROW(CallRPC("z_getbalance invalidaddress"), runtime_error);
ee64b5e7
JG
309 BOOST_CHECK_NO_THROW(CallRPC("z_getbalance tmC6YZnCUhm19dEXxh3Jb7srdBJxDawaCab"));
310 BOOST_CHECK_THROW(CallRPC("z_getbalance tmC6YZnCUhm19dEXxh3Jb7srdBJxDawaCab -1"), runtime_error);
311 BOOST_CHECK_NO_THROW(CallRPC("z_getbalance tmC6YZnCUhm19dEXxh3Jb7srdBJxDawaCab 0"));
e883ffef 312 BOOST_CHECK_THROW(CallRPC("z_getbalance tnRZ8bPq2pff3xBWhTJhNkVUkm2uhzksDeW5PvEa7aFKGT9Qi3YgTALZfjaY4jU3HLVKBtHdSXxoPoLA3naMPcHBcY88FcF 1"), runtime_error);
06c19063
S
313
314
e883ffef
S
315 BOOST_CHECK_THROW(CallRPC("z_gettotalbalance too manyargs"), runtime_error);
316 BOOST_CHECK_THROW(CallRPC("z_gettotalbalance -1"), runtime_error);
317 BOOST_CHECK_NO_THROW(CallRPC("z_gettotalbalance 0"));
06c19063
S
318
319
e883ffef
S
320 BOOST_CHECK_THROW(CallRPC("z_listreceivedbyaddress too many args"), runtime_error);
321 // negative minconf not allowed
ee64b5e7 322 BOOST_CHECK_THROW(CallRPC("z_listreceivedbyaddress tmC6YZnCUhm19dEXxh3Jb7srdBJxDawaCab -1"), runtime_error);
e883ffef 323 // invalid zaddr, taddr not allowed
ee64b5e7 324 BOOST_CHECK_THROW(CallRPC("z_listreceivedbyaddress tmC6YZnCUhm19dEXxh3Jb7srdBJxDawaCab 0"), runtime_error);
e883ffef
S
325 // don't have the spending key
326 BOOST_CHECK_THROW(CallRPC("z_listreceivedbyaddress tnRZ8bPq2pff3xBWhTJhNkVUkm2uhzksDeW5PvEa7aFKGT9Qi3YgTALZfjaY4jU3HLVKBtHdSXxoPoLA3naMPcHBcY88FcF 1"), runtime_error);
327}
328
4e16a724
S
329/**
330 * This test covers RPC command z_validateaddress
331 */
332BOOST_AUTO_TEST_CASE(rpc_wallet_z_validateaddress)
333{
334 SelectParams(CBaseChainParams::MAIN);
335
336 LOCK2(cs_main, pwalletMain->cs_wallet);
337
0d37ae3a 338 UniValue retValue;
4e16a724
S
339
340 // Check number of args
341 BOOST_CHECK_THROW(CallRPC("z_validateaddress"), runtime_error);
342 BOOST_CHECK_THROW(CallRPC("z_validateaddress toomany args"), runtime_error);
343
344 // Wallet should be empty
e5eab182 345 std::set<libzcash::SproutPaymentAddress> addrs;
25d5e80c 346 pwalletMain->GetSproutPaymentAddresses(addrs);
4e16a724
S
347 BOOST_CHECK(addrs.size()==0);
348
349 // This address is not valid, it belongs to another network
350 BOOST_CHECK_NO_THROW(retValue = CallRPC("z_validateaddress ztaaga95QAPyp1kSQ1hD2kguCpzyMHjxWZqaYDEkzbvo7uYQYAw2S8X4Kx98AvhhofMtQL8PAXKHuZsmhRcanavKRKmdCzk"));
0d37ae3a 351 UniValue resultObj = retValue.get_obj();
4e16a724
S
352 bool b = find_value(resultObj, "isvalid").get_bool();
353 BOOST_CHECK_EQUAL(b, false);
354
355 // This address is valid, but the spending key is not in this wallet
356 BOOST_CHECK_NO_THROW(retValue = CallRPC("z_validateaddress zcfA19SDAKRYHLoRDoShcoz4nPohqWxuHcqg8WAxsiB2jFrrs6k7oSvst3UZvMYqpMNSRBkxBsnyjjngX5L55FxMzLKach8"));
357 resultObj = retValue.get_obj();
358 b = find_value(resultObj, "isvalid").get_bool();
359 BOOST_CHECK_EQUAL(b, true);
bea87915 360 BOOST_CHECK_EQUAL(find_value(resultObj, "type").get_str(), "sprout");
4e16a724
S
361 b = find_value(resultObj, "ismine").get_bool();
362 BOOST_CHECK_EQUAL(b, false);
363
364 // Let's import a spending key to the wallet and validate its payment address
365 BOOST_CHECK_NO_THROW(CallRPC("z_importkey SKxoWv77WGwFnUJitQKNEcD636bL4X5Gd6wWmgaA4Q9x8jZBPJXT"));
366 BOOST_CHECK_NO_THROW(retValue = CallRPC("z_validateaddress zcWsmqT4X2V4jgxbgiCzyrAfRT1vi1F4sn7M5Pkh66izzw8Uk7LBGAH3DtcSMJeUb2pi3W4SQF8LMKkU2cUuVP68yAGcomL"));
367 resultObj = retValue.get_obj();
368 b = find_value(resultObj, "isvalid").get_bool();
369 BOOST_CHECK_EQUAL(b, true);
bea87915 370 BOOST_CHECK_EQUAL(find_value(resultObj, "type").get_str(), "sprout");
4e16a724
S
371 b = find_value(resultObj, "ismine").get_bool();
372 BOOST_CHECK_EQUAL(b, true);
373 BOOST_CHECK_EQUAL(find_value(resultObj, "payingkey").get_str(), "f5bb3c888ccc9831e3f6ba06e7528e26a312eec3acc1823be8918b6a3a5e20ad");
374 BOOST_CHECK_EQUAL(find_value(resultObj, "transmissionkey").get_str(), "7a58c7132446564e6b810cf895c20537b3528357dc00150a8e201f491efa9c1a");
bea87915
JG
375
376 // This Sapling address is not valid, it belongs to another network
377 BOOST_CHECK_NO_THROW(retValue = CallRPC("z_validateaddress ztestsapling1knww2nyjc62njkard0jmx7hlsj6twxmxwprn7anvrv4dc2zxanl3nemc0qx2hvplxmd2uau8gyw"));
378 resultObj = retValue.get_obj();
379 b = find_value(resultObj, "isvalid").get_bool();
380 BOOST_CHECK_EQUAL(b, false);
381
382 // This Sapling address is valid, but the spending key is not in this wallet
383 BOOST_CHECK_NO_THROW(retValue = CallRPC("z_validateaddress zs1z7rejlpsa98s2rrrfkwmaxu53e4ue0ulcrw0h4x5g8jl04tak0d3mm47vdtahatqrlkngh9slya"));
384 resultObj = retValue.get_obj();
385 b = find_value(resultObj, "isvalid").get_bool();
554e00e8 386 // TODO: Revert when we re-enable Sapling addresses on mainnet
bea87915 387 BOOST_CHECK_EQUAL(b, false);
554e00e8
JG
388 // BOOST_CHECK_EQUAL(find_value(resultObj, "type").get_str(), "sapling");
389 // b = find_value(resultObj, "ismine").get_bool();
390 // BOOST_CHECK_EQUAL(b, false);
391 // BOOST_CHECK_EQUAL(find_value(resultObj, "diversifier").get_str(), "1787997c30e94f050c634d");
392 // BOOST_CHECK_EQUAL(find_value(resultObj, "diversifiedtransmissionkey").get_str(), "34ed1f60f5db5763beee1ddbb37dd5f7e541d4d4fbdcc09fbfcc6b8e949bbe9d");
4e16a724
S
393}
394
60f762a5
S
395/*
396 * This test covers RPC command z_exportwallet
397 */
398BOOST_AUTO_TEST_CASE(rpc_wallet_z_exportwallet)
399{
400 LOCK2(cs_main, pwalletMain->cs_wallet);
4e16a724 401
4b2e5571 402 // wallet should be empty
e5eab182 403 std::set<libzcash::SproutPaymentAddress> addrs;
25d5e80c 404 pwalletMain->GetSproutPaymentAddresses(addrs);
60f762a5
S
405 BOOST_CHECK(addrs.size()==0);
406
407 // wallet should have one key
e5eab182
JG
408 auto address = pwalletMain->GenerateNewZKey();
409 BOOST_CHECK(IsValidPaymentAddress(address));
410 BOOST_ASSERT(boost::get<libzcash::SproutPaymentAddress>(&address) != nullptr);
411 auto addr = boost::get<libzcash::SproutPaymentAddress>(address);
25d5e80c 412 pwalletMain->GetSproutPaymentAddresses(addrs);
60f762a5 413 BOOST_CHECK(addrs.size()==1);
06c19063 414
9064d73b
S
415 // Set up paths
416 boost::filesystem::path tmppath = boost::filesystem::temp_directory_path();
417 boost::filesystem::path tmpfilename = boost::filesystem::unique_path("%%%%%%%%");
418 boost::filesystem::path exportfilepath = tmppath / tmpfilename;
419
420 // export will fail since exportdir is not set
421 BOOST_CHECK_THROW(CallRPC(string("z_exportwallet ") + tmpfilename.string()), runtime_error);
422
423 // set exportdir
c5b26aca 424 mapArgs["-exportdir"] = tmppath.string();
9064d73b
S
425
426 // run some tests
60f762a5 427 BOOST_CHECK_THROW(CallRPC("z_exportwallet"), runtime_error);
e346a0b3
S
428
429 BOOST_CHECK_THROW(CallRPC("z_exportwallet toomany args"), runtime_error);
430
9064d73b
S
431 BOOST_CHECK_THROW(CallRPC(string("z_exportwallet invalid!*/_chars.txt")), runtime_error);
432
433 BOOST_CHECK_NO_THROW(CallRPC(string("z_exportwallet ") + tmpfilename.string()));
60f762a5 434
60f762a5 435
e5eab182 436 libzcash::SproutSpendingKey key;
25d5e80c 437 BOOST_CHECK(pwalletMain->GetSproutSpendingKey(addr, key));
60f762a5 438
80ed13d5 439 std::string s1 = EncodePaymentAddress(addr);
472f75bc 440 std::string s2 = EncodeSpendingKey(key);
06c19063 441
60f762a5
S
442 // There's no way to really delete a private key so we will read in the
443 // exported wallet file and search for the spending key and payment address.
06c19063 444
60f762a5
S
445 EnsureWalletIsUnlocked();
446
447 ifstream file;
9064d73b 448 file.open(exportfilepath.string().c_str(), std::ios::in | std::ios::ate);
60f762a5
S
449 BOOST_CHECK(file.is_open());
450 bool fVerified = false;
451 int64_t nFilesize = std::max((int64_t)1, (int64_t)file.tellg());
452 file.seekg(0, file.beg);
453 while (file.good()) {
454 std::string line;
455 std::getline(file, line);
456 if (line.empty() || line[0] == '#')
457 continue;
458 if (line.find(s1) != std::string::npos && line.find(s2) != std::string::npos) {
459 fVerified = true;
460 break;
461 }
462 }
463 BOOST_CHECK(fVerified);
464}
465
466
467/*
468 * This test covers RPC command z_importwallet
469 */
470BOOST_AUTO_TEST_CASE(rpc_wallet_z_importwallet)
471{
472 LOCK2(cs_main, pwalletMain->cs_wallet);
06c19063 473
60f762a5
S
474 // error if no args
475 BOOST_CHECK_THROW(CallRPC("z_importwallet"), runtime_error);
476
e346a0b3
S
477 // error if too many args
478 BOOST_CHECK_THROW(CallRPC("z_importwallet toomany args"), runtime_error);
479
60f762a5 480 // create a random key locally
e5eab182 481 auto testSpendingKey = libzcash::SproutSpendingKey::random();
60f762a5 482 auto testPaymentAddress = testSpendingKey.address();
80ed13d5 483 std::string testAddr = EncodePaymentAddress(testPaymentAddress);
472f75bc 484 std::string testKey = EncodeSpendingKey(testSpendingKey);
06c19063 485
60f762a5 486 // create test data using the random key
2e500f50 487 std::string format_str = "# Wallet dump created by Komodo v0.11.2.0.z8-9155cc6-dirty (2016-08-11 11:37:00 -0700)\n"
60f762a5
S
488 "# * Created on 2016-08-12T21:55:36Z\n"
489 "# * Best block at time of backup was 0 (0de0a3851fef2d433b9b4f51d4342bdd24c5ddd793eb8fba57189f07e9235d52),\n"
490 "# mined on 2009-01-03T18:15:05Z\n"
491 "\n"
492 "# Zkeys\n"
493 "\n"
494 "%s 2016-08-12T21:55:36Z # zaddr=%s\n"
495 "\n"
496 "\n# End of dump";
06c19063 497
60f762a5
S
498 boost::format formatobject(format_str);
499 std::string testWalletDump = (formatobject % testKey % testAddr).str();
06c19063 500
60f762a5
S
501 // write test data to file
502 boost::filesystem::path temp = boost::filesystem::temp_directory_path() /
503 boost::filesystem::unique_path();
c5b26aca 504 const std::string path = temp.string();
60f762a5
S
505 std::ofstream file(path);
506 file << testWalletDump;
507 file << std::flush;
508
509 // wallet should currently be empty
e5eab182 510 std::set<libzcash::SproutPaymentAddress> addrs;
25d5e80c 511 pwalletMain->GetSproutPaymentAddresses(addrs);
60f762a5 512 BOOST_CHECK(addrs.size()==0);
06c19063 513
60f762a5
S
514 // import test data from file into wallet
515 BOOST_CHECK_NO_THROW(CallRPC(string("z_importwallet ") + path));
06c19063 516
60f762a5 517 // wallet should now have one zkey
25d5e80c 518 pwalletMain->GetSproutPaymentAddresses(addrs);
60f762a5 519 BOOST_CHECK(addrs.size()==1);
06c19063 520
60f762a5 521 // check that we have the spending key for the address
e5eab182
JG
522 auto address = DecodePaymentAddress(testAddr);
523 BOOST_CHECK(IsValidPaymentAddress(address));
524 BOOST_ASSERT(boost::get<libzcash::SproutPaymentAddress>(&address) != nullptr);
525 auto addr = boost::get<libzcash::SproutPaymentAddress>(address);
25d5e80c 526 BOOST_CHECK(pwalletMain->HaveSproutSpendingKey(addr));
06c19063 527
4b2e5571 528 // Verify the spending key is the same as the test data
e5eab182 529 libzcash::SproutSpendingKey k;
25d5e80c 530 BOOST_CHECK(pwalletMain->GetSproutSpendingKey(addr, k));
472f75bc 531 BOOST_CHECK_EQUAL(testKey, EncodeSpendingKey(k));
60f762a5
S
532}
533
534
535/*
4b2e5571 536 * This test covers RPC commands z_listaddresses, z_importkey, z_exportkey
60f762a5
S
537 */
538BOOST_AUTO_TEST_CASE(rpc_wallet_z_importexport)
539{
554e00e8
JG
540 SelectParams(CBaseChainParams::REGTEST);
541
60f762a5 542 LOCK2(cs_main, pwalletMain->cs_wallet);
0d37ae3a 543 UniValue retValue;
60f762a5
S
544 int n1 = 1000; // number of times to import/export
545 int n2 = 1000; // number of addresses to create and list
06c19063 546
60f762a5 547 // error if no args
06c19063
S
548 BOOST_CHECK_THROW(CallRPC("z_importkey"), runtime_error);
549 BOOST_CHECK_THROW(CallRPC("z_exportkey"), runtime_error);
60f762a5 550
e346a0b3 551 // error if too many args
a31ba7a0 552 BOOST_CHECK_THROW(CallRPC("z_importkey way too many args"), runtime_error);
e346a0b3
S
553 BOOST_CHECK_THROW(CallRPC("z_exportkey toomany args"), runtime_error);
554
33589401 555 // error if invalid args
e5eab182 556 auto sk = libzcash::SproutSpendingKey::random();
472f75bc 557 std::string prefix = std::string("z_importkey ") + EncodeSpendingKey(sk) + " yes ";
33589401
JG
558 BOOST_CHECK_THROW(CallRPC(prefix + "-1"), runtime_error);
559 BOOST_CHECK_THROW(CallRPC(prefix + "2147483647"), runtime_error); // allowed, but > height of active chain tip
560 BOOST_CHECK_THROW(CallRPC(prefix + "2147483648"), runtime_error); // not allowed, > int32 used for nHeight
561 BOOST_CHECK_THROW(CallRPC(prefix + "100badchars"), runtime_error);
562
60f762a5 563 // wallet should currently be empty
e5eab182 564 std::set<libzcash::SproutPaymentAddress> addrs;
25d5e80c 565 pwalletMain->GetSproutPaymentAddresses(addrs);
60f762a5 566 BOOST_CHECK(addrs.size()==0);
40dc060c
JG
567 std::set<libzcash::SaplingPaymentAddress> saplingAddrs;
568 pwalletMain->GetSaplingPaymentAddresses(saplingAddrs);
569 BOOST_CHECK(saplingAddrs.empty());
60f762a5 570
70b4ad2d
JG
571 std::vector<unsigned char, secure_allocator<unsigned char>> rawSeed(32);
572 HDSeed seed(rawSeed);
573 auto m = libzcash::SaplingExtendedSpendingKey::Master(seed);
60f762a5
S
574
575 // verify import and export key
576 for (int i = 0; i < n1; i++) {
8dd1dbcf 577 // create a random Sprout key locally
e5eab182 578 auto testSpendingKey = libzcash::SproutSpendingKey::random();
60f762a5 579 auto testPaymentAddress = testSpendingKey.address();
80ed13d5 580 std::string testAddr = EncodePaymentAddress(testPaymentAddress);
472f75bc 581 std::string testKey = EncodeSpendingKey(testSpendingKey);
60f762a5
S
582 BOOST_CHECK_NO_THROW(CallRPC(string("z_importkey ") + testKey));
583 BOOST_CHECK_NO_THROW(retValue = CallRPC(string("z_exportkey ") + testAddr));
584 BOOST_CHECK_EQUAL(retValue.get_str(), testKey);
70b4ad2d 585
8dd1dbcf 586 // create a random Sapling key locally
70b4ad2d
JG
587 auto testSaplingSpendingKey = m.Derive(i);
588 auto testSaplingPaymentAddress = testSaplingSpendingKey.DefaultAddress();
8dd1dbcf
JG
589 std::string testSaplingAddr = EncodePaymentAddress(testSaplingPaymentAddress);
590 std::string testSaplingKey = EncodeSpendingKey(testSaplingSpendingKey);
591 BOOST_CHECK_NO_THROW(CallRPC(string("z_importkey ") + testSaplingKey));
592 BOOST_CHECK_NO_THROW(retValue = CallRPC(string("z_exportkey ") + testSaplingAddr));
593 BOOST_CHECK_EQUAL(retValue.get_str(), testSaplingKey);
60f762a5
S
594 }
595
596 // Verify we can list the keys imported
597 BOOST_CHECK_NO_THROW(retValue = CallRPC("z_listaddresses"));
0d37ae3a 598 UniValue arr = retValue.get_array();
40dc060c 599 BOOST_CHECK(arr.size() == (2 * n1));
60f762a5
S
600
601 // Put addresses into a set
602 std::unordered_set<std::string> myaddrs;
0d37ae3a 603 for (UniValue element : arr.getValues()) {
60f762a5
S
604 myaddrs.insert(element.get_str());
605 }
06c19063 606
60f762a5
S
607 // Make new addresses for the set
608 for (int i=0; i<n2; i++) {
80ed13d5 609 myaddrs.insert(EncodePaymentAddress(pwalletMain->GenerateNewZKey()));
60f762a5
S
610 }
611
612 // Verify number of addresses stored in wallet is n1+n2
613 int numAddrs = myaddrs.size();
40dc060c 614 BOOST_CHECK(numAddrs == (2 * n1) + n2);
25d5e80c 615 pwalletMain->GetSproutPaymentAddresses(addrs);
40dc060c
JG
616 pwalletMain->GetSaplingPaymentAddresses(saplingAddrs);
617 BOOST_CHECK(addrs.size() + saplingAddrs.size() == numAddrs);
06c19063 618
60f762a5
S
619 // Ask wallet to list addresses
620 BOOST_CHECK_NO_THROW(retValue = CallRPC("z_listaddresses"));
621 arr = retValue.get_array();
622 BOOST_CHECK(arr.size() == numAddrs);
06c19063 623
4b2e5571 624 // Create a set from them
60f762a5 625 std::unordered_set<std::string> listaddrs;
0d37ae3a 626 for (UniValue element : arr.getValues()) {
60f762a5
S
627 listaddrs.insert(element.get_str());
628 }
06c19063 629
60f762a5
S
630 // Verify the two sets of addresses are the same
631 BOOST_CHECK(listaddrs.size() == numAddrs);
632 BOOST_CHECK(myaddrs == listaddrs);
badb9a9c
S
633
634 // Add one more address
635 BOOST_CHECK_NO_THROW(retValue = CallRPC("z_getnewaddress"));
636 std::string newaddress = retValue.get_str();
e5eab182
JG
637 auto address = DecodePaymentAddress(newaddress);
638 BOOST_CHECK(IsValidPaymentAddress(address));
639 BOOST_ASSERT(boost::get<libzcash::SproutPaymentAddress>(&address) != nullptr);
640 auto newAddr = boost::get<libzcash::SproutPaymentAddress>(address);
25d5e80c 641 BOOST_CHECK(pwalletMain->HaveSproutSpendingKey(newAddr));
e346a0b3
S
642
643 // Check if too many args
644 BOOST_CHECK_THROW(CallRPC("z_getnewaddress toomanyargs"), runtime_error);
60f762a5 645}
b922924d
S
646
647
648
649/**
fc4b127e 650 * Test Async RPC operations.
b922924d
S
651 * Tip: Create mock operations by subclassing AsyncRPCOperation.
652 */
fc4b127e 653
b922924d
S
654class MockSleepOperation : public AsyncRPCOperation {
655public:
656 std::chrono::milliseconds naptime;
657 MockSleepOperation(int t=1000) {
658 this->naptime = std::chrono::milliseconds(t);
659 }
660 virtual ~MockSleepOperation() {
661 }
662 virtual void main() {
663 set_state(OperationStatus::EXECUTING);
664 start_execution_clock();
665 std::this_thread::sleep_for(std::chrono::milliseconds(naptime));
666 stop_execution_clock();
0d37ae3a 667 set_result(UniValue(UniValue::VSTR, "done"));
b922924d
S
668 set_state(OperationStatus::SUCCESS);
669 }
670};
671
672
673/*
674 * Test Aysnc RPC queue and operations.
675 */
676BOOST_AUTO_TEST_CASE(rpc_wallet_async_operations)
677{
678 std::shared_ptr<AsyncRPCQueue> q = std::make_shared<AsyncRPCQueue>();
679 BOOST_CHECK(q->getNumberOfWorkers() == 0);
680 std::vector<AsyncRPCOperationId> ids = q->getAllOperationIds();
681 BOOST_CHECK(ids.size()==0);
682
683 std::shared_ptr<AsyncRPCOperation> op1 = std::make_shared<AsyncRPCOperation>();
06c19063 684 q->addOperation(op1);
b922924d 685 BOOST_CHECK(q->getOperationCount() == 1);
06c19063 686
b922924d
S
687 OperationStatus status = op1->getState();
688 BOOST_CHECK(status == OperationStatus::READY);
06c19063 689
b922924d
S
690 AsyncRPCOperationId id1 = op1->getId();
691 int64_t creationTime1 = op1->getCreationTime();
06c19063 692
b922924d
S
693 q->addWorker();
694 BOOST_CHECK(q->getNumberOfWorkers() == 1);
06c19063
S
695
696 // an AsyncRPCOperation doesn't do anything so will finish immediately
b922924d
S
697 std::this_thread::sleep_for(std::chrono::seconds(1));
698 BOOST_CHECK(q->getOperationCount() == 0);
699
700 // operation should be a success
701 BOOST_CHECK_EQUAL(op1->isCancelled(), false);
702 BOOST_CHECK_EQUAL(op1->isExecuting(), false);
703 BOOST_CHECK_EQUAL(op1->isReady(), false);
704 BOOST_CHECK_EQUAL(op1->isFailed(), false);
705 BOOST_CHECK_EQUAL(op1->isSuccess(), true);
0d37ae3a
JG
706 BOOST_CHECK_EQUAL(op1->getError().isNull(), true);
707 BOOST_CHECK_EQUAL(op1->getResult().isNull(), false);
b922924d
S
708 BOOST_CHECK_EQUAL(op1->getStateAsString(), "success");
709 BOOST_CHECK_NE(op1->getStateAsString(), "executing");
06c19063 710
b922924d
S
711 // Create a second operation which just sleeps
712 std::shared_ptr<AsyncRPCOperation> op2(new MockSleepOperation(2500));
713 AsyncRPCOperationId id2 = op2->getId();
714 int64_t creationTime2 = op2->getCreationTime();
715
716 // it's different from the previous operation
717 BOOST_CHECK_NE(op1.get(), op2.get());
718 BOOST_CHECK_NE(id1, id2);
719 BOOST_CHECK_NE(creationTime1, creationTime2);
720
721 // Only the first operation has been added to the queue
722 std::vector<AsyncRPCOperationId> v = q->getAllOperationIds();
723 std::set<AsyncRPCOperationId> opids(v.begin(), v.end());
724 BOOST_CHECK(opids.size() == 1);
725 BOOST_CHECK(opids.count(id1)==1);
726 BOOST_CHECK(opids.count(id2)==0);
727 std::shared_ptr<AsyncRPCOperation> p1 = q->getOperationForId(id1);
728 BOOST_CHECK_EQUAL(p1.get(), op1.get());
729 std::shared_ptr<AsyncRPCOperation> p2 = q->getOperationForId(id2);
730 BOOST_CHECK(!p2); // null ptr as not added to queue yet
731
732 // Add operation 2 and 3 to the queue
733 q->addOperation(op2);
734 std::shared_ptr<AsyncRPCOperation> op3(new MockSleepOperation(1000));
735 q->addOperation(op3);
736 std::this_thread::sleep_for(std::chrono::milliseconds(500));
737 BOOST_CHECK_EQUAL(op2->isExecuting(), true);
738 op2->cancel(); // too late, already executing
739 op3->cancel();
740 std::this_thread::sleep_for(std::chrono::milliseconds(3000));
741 BOOST_CHECK_EQUAL(op2->isSuccess(), true);
742 BOOST_CHECK_EQUAL(op2->isCancelled(), false);
743 BOOST_CHECK_EQUAL(op3->isCancelled(), true);
06c19063
S
744
745
b922924d
S
746 v = q->getAllOperationIds();
747 std::copy( v.begin(), v.end(), std::inserter( opids, opids.end() ) );
748 BOOST_CHECK(opids.size() == 3);
749 BOOST_CHECK(opids.count(id1)==1);
750 BOOST_CHECK(opids.count(id2)==1);
751 BOOST_CHECK(opids.count(op3->getId())==1);
752 q->finishAndWait();
753}
754
755
756// The CountOperation will increment this global
757std::atomic<int64_t> gCounter(0);
758
759class CountOperation : public AsyncRPCOperation {
760public:
761 CountOperation() {}
762 virtual ~CountOperation() {}
06c19063 763 virtual void main() {
b922924d
S
764 set_state(OperationStatus::EXECUTING);
765 gCounter++;
766 std::this_thread::sleep_for(std::chrono::milliseconds(1000));
767 set_state(OperationStatus::SUCCESS);
768 }
769};
770
771// This tests the queue waiting for multiple workers to finish
772BOOST_AUTO_TEST_CASE(rpc_wallet_async_operations_parallel_wait)
773{
774 gCounter = 0;
06c19063 775
b922924d
S
776 std::shared_ptr<AsyncRPCQueue> q = std::make_shared<AsyncRPCQueue>();
777 q->addWorker();
778 q->addWorker();
779 q->addWorker();
780 q->addWorker();
781 BOOST_CHECK(q->getNumberOfWorkers() == 4);
782
783 int64_t numOperations = 10; // 10 * 1000ms / 4 = 2.5 secs to finish
784 for (int i=0; i<numOperations; i++) {
785 std::shared_ptr<AsyncRPCOperation> op(new CountOperation());
786 q->addOperation(op);
787 }
788
789 std::vector<AsyncRPCOperationId> ids = q->getAllOperationIds();
790 BOOST_CHECK(ids.size()==numOperations);
791 q->finishAndWait();
792 BOOST_CHECK_EQUAL(q->isFinishing(), true);
793 BOOST_CHECK_EQUAL(numOperations, gCounter.load());
794}
795
796// This tests the queue shutting down immediately
797BOOST_AUTO_TEST_CASE(rpc_wallet_async_operations_parallel_cancel)
798{
799 gCounter = 0;
06c19063 800
b922924d
S
801 std::shared_ptr<AsyncRPCQueue> q = std::make_shared<AsyncRPCQueue>();
802 q->addWorker();
803 q->addWorker();
804 BOOST_CHECK(q->getNumberOfWorkers() == 2);
805
fc4b127e 806 int numOperations = 10000; // 10000 seconds to complete
b922924d
S
807 for (int i=0; i<numOperations; i++) {
808 std::shared_ptr<AsyncRPCOperation> op(new CountOperation());
809 q->addOperation(op);
810 }
811 std::vector<AsyncRPCOperationId> ids = q->getAllOperationIds();
812 BOOST_CHECK(ids.size()==numOperations);
813 q->closeAndWait();
b922924d
S
814
815 int numSuccess = 0;
06c19063 816 int numCancelled = 0;
b922924d
S
817 for (auto & id : ids) {
818 std::shared_ptr<AsyncRPCOperation> ptr = q->popOperationForId(id);
819 if (ptr->isCancelled()) {
820 numCancelled++;
821 } else if (ptr->isSuccess()) {
822 numSuccess++;
823 }
824 }
06c19063 825
b922924d
S
826 BOOST_CHECK_EQUAL(numOperations, numSuccess+numCancelled);
827 BOOST_CHECK_EQUAL(gCounter.load(), numSuccess);
828 BOOST_CHECK(q->getOperationCount() == 0);
829 ids = q->getAllOperationIds();
830 BOOST_CHECK(ids.size()==0);
831}
832
fc4b127e
S
833// This tests z_getoperationstatus, z_getoperationresult, z_listoperationids
834BOOST_AUTO_TEST_CASE(rpc_z_getoperations)
835{
836 std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue();
837 std::shared_ptr<AsyncRPCQueue> sharedInstance = AsyncRPCQueue::sharedInstance();
838 BOOST_CHECK(q == sharedInstance);
839
840 BOOST_CHECK_NO_THROW(CallRPC("z_getoperationstatus"));
841 BOOST_CHECK_NO_THROW(CallRPC("z_getoperationstatus []"));
842 BOOST_CHECK_NO_THROW(CallRPC("z_getoperationstatus [\"opid-1234\"]"));
843 BOOST_CHECK_THROW(CallRPC("z_getoperationstatus [] toomanyargs"), runtime_error);
844 BOOST_CHECK_THROW(CallRPC("z_getoperationstatus not_an_array"), runtime_error);
845
846 BOOST_CHECK_NO_THROW(CallRPC("z_getoperationresult"));
847 BOOST_CHECK_NO_THROW(CallRPC("z_getoperationresult []"));
848 BOOST_CHECK_NO_THROW(CallRPC("z_getoperationresult [\"opid-1234\"]"));
849 BOOST_CHECK_THROW(CallRPC("z_getoperationresult [] toomanyargs"), runtime_error);
850 BOOST_CHECK_THROW(CallRPC("z_getoperationresult not_an_array"), runtime_error);
06c19063 851
fc4b127e
S
852 std::shared_ptr<AsyncRPCOperation> op1 = std::make_shared<AsyncRPCOperation>();
853 q->addOperation(op1);
854 std::shared_ptr<AsyncRPCOperation> op2 = std::make_shared<AsyncRPCOperation>();
855 q->addOperation(op2);
06c19063 856
fc4b127e
S
857 BOOST_CHECK(q->getOperationCount() == 2);
858 BOOST_CHECK(q->getNumberOfWorkers() == 0);
859 q->addWorker();
860 BOOST_CHECK(q->getNumberOfWorkers() == 1);
861 std::this_thread::sleep_for(std::chrono::milliseconds(1000));
862 BOOST_CHECK(q->getOperationCount() == 0);
06c19063 863
e346a0b3
S
864 // Check if too many args
865 BOOST_CHECK_THROW(CallRPC("z_listoperationids toomany args"), runtime_error);
866
0d37ae3a 867 UniValue retValue;
fc4b127e
S
868 BOOST_CHECK_NO_THROW(retValue = CallRPC("z_listoperationids"));
869 BOOST_CHECK(retValue.get_array().size() == 2);
870
871 BOOST_CHECK_NO_THROW(retValue = CallRPC("z_getoperationstatus"));
0d37ae3a 872 UniValue array = retValue.get_array();
fc4b127e
S
873 BOOST_CHECK(array.size() == 2);
874
875 // idempotent
876 BOOST_CHECK_NO_THROW(retValue = CallRPC("z_getoperationstatus"));
877 array = retValue.get_array();
06c19063
S
878 BOOST_CHECK(array.size() == 2);
879
0d37ae3a
JG
880 for (UniValue v : array.getValues()) {
881 UniValue obj = v.get_obj();
882 UniValue id = find_value(obj, "id");
06c19063 883
0d37ae3a 884 UniValue result;
fc4b127e
S
885 // removes result from internal storage
886 BOOST_CHECK_NO_THROW(result = CallRPC("z_getoperationresult [\"" + id.get_str() + "\"]"));
0d37ae3a 887 UniValue resultArray = result.get_array();
fc4b127e 888 BOOST_CHECK(resultArray.size() == 1);
06c19063 889
0d37ae3a
JG
890 UniValue resultObj = resultArray[0].get_obj();
891 UniValue resultId = find_value(resultObj, "id");
fc4b127e 892 BOOST_CHECK_EQUAL(id.get_str(), resultId.get_str());
06c19063
S
893
894 // verify the operation has been removed
da5e7e51
S
895 BOOST_CHECK_NO_THROW(result = CallRPC("z_getoperationresult [\"" + id.get_str() + "\"]"));
896 resultArray = result.get_array();
897 BOOST_CHECK(resultArray.size() == 0);
fc4b127e 898 }
06c19063 899
fc4b127e
S
900 // operations removed
901 BOOST_CHECK_NO_THROW(retValue = CallRPC("z_getoperationstatus"));
902 array = retValue.get_array();
903 BOOST_CHECK(array.size() == 0);
904
905 q->close();
906}
907
908BOOST_AUTO_TEST_CASE(rpc_z_sendmany_parameters)
909{
910 SelectParams(CBaseChainParams::TESTNET);
911
912 LOCK(pwalletMain->cs_wallet);
913
914 BOOST_CHECK_THROW(CallRPC("z_sendmany"), runtime_error);
915 BOOST_CHECK_THROW(CallRPC("z_sendmany toofewargs"), runtime_error);
af53da02 916 BOOST_CHECK_THROW(CallRPC("z_sendmany just too many args here"), runtime_error);
fc4b127e
S
917
918 // bad from address
da5e7e51 919 BOOST_CHECK_THROW(CallRPC("z_sendmany "
ee64b5e7 920 "INVALIDtmRr6yJonqGK23UVhrKuyvTpF8qxQQjKigJ []"), runtime_error);
fc4b127e 921 // empty amounts
da5e7e51 922 BOOST_CHECK_THROW(CallRPC("z_sendmany "
ee64b5e7 923 "tmRr6yJonqGK23UVhrKuyvTpF8qxQQjKigJ []"), runtime_error);
fc4b127e
S
924
925 // don't have the spending key for this address
da5e7e51
S
926 BOOST_CHECK_THROW(CallRPC("z_sendmany "
927 "tnpoQJVnYBZZqkFadj2bJJLThNCxbADGB5gSGeYTAGGrT5tejsxY9Zc1BtY8nnHmZkB"
928 "UkJ1oSfbhTJhm72WiZizvkZz5aH1 []"), runtime_error);
fc4b127e
S
929
930 // duplicate address
da5e7e51 931 BOOST_CHECK_THROW(CallRPC("z_sendmany "
ee64b5e7
JG
932 "tmRr6yJonqGK23UVhrKuyvTpF8qxQQjKigJ "
933 "[{\"address\":\"tmQP9L3s31cLsghVYf2Jb5MhKj1jRBPoeQn\", \"amount\":50.0},"
934 " {\"address\":\"tmQP9L3s31cLsghVYf2Jb5MhKj1jRBPoeQn\", \"amount\":12.0} ]"
da5e7e51 935 ), runtime_error);
fc4b127e 936
af53da02
S
937 // invalid fee amount, cannot be negative
938 BOOST_CHECK_THROW(CallRPC("z_sendmany "
939 "tmRr6yJonqGK23UVhrKuyvTpF8qxQQjKigJ "
940 "[{\"address\":\"tmQP9L3s31cLsghVYf2Jb5MhKj1jRBPoeQn\", \"amount\":50.0}] "
941 "1 -0.0001"
942 ), runtime_error);
943
944 // invalid fee amount, bigger than MAX_MONEY
945 BOOST_CHECK_THROW(CallRPC("z_sendmany "
946 "tmRr6yJonqGK23UVhrKuyvTpF8qxQQjKigJ "
947 "[{\"address\":\"tmQP9L3s31cLsghVYf2Jb5MhKj1jRBPoeQn\", \"amount\":50.0}] "
948 "1 21000001"
949 ), runtime_error);
950
951 // fee amount is bigger than sum of outputs
952 BOOST_CHECK_THROW(CallRPC("z_sendmany "
953 "tmRr6yJonqGK23UVhrKuyvTpF8qxQQjKigJ "
954 "[{\"address\":\"tmQP9L3s31cLsghVYf2Jb5MhKj1jRBPoeQn\", \"amount\":50.0}] "
955 "1 50.00000001"
956 ), runtime_error);
957
fc4b127e 958 // memo bigger than allowed length of ZC_MEMO_SIZE
cff6f0ac
S
959 std::vector<char> v (2 * (ZC_MEMO_SIZE+1)); // x2 for hexadecimal string format
960 std::fill(v.begin(),v.end(), 'A');
fc4b127e 961 std::string badmemo(v.begin(), v.end());
80ed13d5
JG
962 auto pa = pwalletMain->GenerateNewZKey();
963 std::string zaddr1 = EncodePaymentAddress(pa);
ee64b5e7 964 BOOST_CHECK_THROW(CallRPC(string("z_sendmany tmRr6yJonqGK23UVhrKuyvTpF8qxQQjKigJ ")
da5e7e51 965 + "[{\"address\":\"" + zaddr1 + "\", \"amount\":123.456}]"), runtime_error);
06c19063 966
072099d7
S
967 // Mutable tx containing contextual information we need to build tx
968 UniValue retValue = CallRPC("getblockcount");
969 int nHeight = retValue.get_int();
970 CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nHeight + 1);
971 if (mtx.nVersion == 1) {
972 mtx.nVersion = 2;
973 }
974
06c19063 975 // Test constructor of AsyncRPCOperation_sendmany
fc4b127e 976 try {
36e2141d 977 std::shared_ptr<AsyncRPCOperation> operation(new AsyncRPCOperation_sendmany(boost::none, mtx, "",{}, {}, -1));
0d37ae3a 978 } catch (const UniValue& objError) {
da5e7e51 979 BOOST_CHECK( find_error(objError, "Minconf cannot be negative"));
fc4b127e
S
980 }
981
982 try {
36e2141d 983 std::shared_ptr<AsyncRPCOperation> operation(new AsyncRPCOperation_sendmany(boost::none, mtx, "",{}, {}, 1));
0d37ae3a 984 } catch (const UniValue& objError) {
da5e7e51 985 BOOST_CHECK( find_error(objError, "From address parameter missing"));
fc4b127e
S
986 }
987
988 try {
36e2141d 989 std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_sendmany(boost::none, mtx, "tmRr6yJonqGK23UVhrKuyvTpF8qxQQjKigJ", {}, {}, 1) );
0d37ae3a 990 } catch (const UniValue& objError) {
da5e7e51 991 BOOST_CHECK( find_error(objError, "No recipients"));
fc4b127e
S
992 }
993
994 try {
995 std::vector<SendManyRecipient> recipients = { SendManyRecipient("dummy",1.0, "") };
36e2141d 996 std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_sendmany(boost::none, mtx, "INVALID", recipients, {}, 1) );
0d37ae3a 997 } catch (const UniValue& objError) {
80ed13d5 998 BOOST_CHECK( find_error(objError, "Invalid from address"));
fc4b127e
S
999 }
1000
f92f0047 1001 // Testnet payment addresses begin with 'zt'. This test detects an incorrect prefix.
fc4b127e
S
1002 try {
1003 std::vector<SendManyRecipient> recipients = { SendManyRecipient("dummy",1.0, "") };
36e2141d 1004 std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_sendmany(boost::none, mtx, "zcMuhvq8sEkHALuSU2i4NbNQxshSAYrpCExec45ZjtivYPbuiFPwk6WHy4SvsbeZ4siy1WheuRGjtaJmoD1J8bFqNXhsG6U", recipients, {}, 1) );
0d37ae3a 1005 } catch (const UniValue& objError) {
80ed13d5 1006 BOOST_CHECK( find_error(objError, "Invalid from address"));
fc4b127e
S
1007 }
1008
1009 // Note: The following will crash as a google test because AsyncRPCOperation_sendmany
1010 // invokes a method on pwalletMain, which is undefined in the google test environment.
1011 try {
1012 std::vector<SendManyRecipient> recipients = { SendManyRecipient("dummy",1.0, "") };
36e2141d 1013 std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_sendmany(boost::none, mtx, "ztjiDe569DPNbyTE6TSdJTaSDhoXEHLGvYoUnBU1wfVNU52TEyT6berYtySkd21njAeEoh8fFJUT42kua9r8EnhBaEKqCpP", recipients, {}, 1) );
0d37ae3a 1014 } catch (const UniValue& objError) {
da5e7e51 1015 BOOST_CHECK( find_error(objError, "no spending key found for zaddr"));
fc4b127e
S
1016 }
1017}
1018
cff6f0ac 1019
fc4b127e
S
1020// TODO: test private methods
1021BOOST_AUTO_TEST_CASE(rpc_z_sendmany_internals)
1022{
1023 SelectParams(CBaseChainParams::TESTNET);
1024
1025 LOCK(pwalletMain->cs_wallet);
1026
0d37ae3a 1027 UniValue retValue;
06c19063 1028
072099d7
S
1029 // Mutable tx containing contextual information we need to build tx
1030 retValue = CallRPC("getblockcount");
1031 int nHeight = retValue.get_int();
1032 CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nHeight + 1);
1033 if (mtx.nVersion == 1) {
1034 mtx.nVersion = 2;
1035 }
1036
fc4b127e
S
1037 // add keys manually
1038 BOOST_CHECK_NO_THROW(retValue = CallRPC("getnewaddress"));
1039 std::string taddr1 = retValue.get_str();
80ed13d5
JG
1040 auto pa = pwalletMain->GenerateNewZKey();
1041 std::string zaddr1 = EncodePaymentAddress(pa);
06c19063 1042
fc4b127e
S
1043 // there are no utxos to spend
1044 {
1045 std::vector<SendManyRecipient> recipients = { SendManyRecipient(zaddr1,100.0, "DEADBEEF") };
36e2141d 1046 std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_sendmany(boost::none, mtx, taddr1, {}, recipients, 1) );
fc4b127e
S
1047 operation->main();
1048 BOOST_CHECK(operation->isFailed());
1049 std::string msg = operation->getErrorMessage();
1050 BOOST_CHECK( msg.find("Insufficient funds, no UTXOs found") != string::npos);
1051 }
b639bb1e
S
1052
1053 // minconf cannot be zero when sending from zaddr
1054 {
1055 try {
1056 std::vector<SendManyRecipient> recipients = {SendManyRecipient(taddr1, 100.0, "DEADBEEF")};
36e2141d 1057 std::shared_ptr<AsyncRPCOperation> operation(new AsyncRPCOperation_sendmany(boost::none, mtx, zaddr1, recipients, {}, 0));
b639bb1e
S
1058 BOOST_CHECK(false); // Fail test if an exception is not thrown
1059 } catch (const UniValue& objError) {
1060 BOOST_CHECK(find_error(objError, "Minconf cannot be zero when sending from zaddr"));
1061 }
1062 }
06c19063 1063
b639bb1e 1064
fc4b127e
S
1065 // there are no unspent notes to spend
1066 {
1067 std::vector<SendManyRecipient> recipients = { SendManyRecipient(taddr1,100.0, "DEADBEEF") };
36e2141d 1068 std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_sendmany(boost::none, mtx, zaddr1, recipients, {}, 1) );
fc4b127e
S
1069 operation->main();
1070 BOOST_CHECK(operation->isFailed());
1071 std::string msg = operation->getErrorMessage();
1072 BOOST_CHECK( msg.find("Insufficient funds, no unspent notes") != string::npos);
1073 }
1074
cff6f0ac
S
1075 // get_memo_from_hex_string())
1076 {
1077 std::vector<SendManyRecipient> recipients = { SendManyRecipient(zaddr1,100.0, "DEADBEEF") };
36e2141d 1078 std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_sendmany(boost::none, mtx, zaddr1, recipients, {}, 1) );
cff6f0ac
S
1079 std::shared_ptr<AsyncRPCOperation_sendmany> ptr = std::dynamic_pointer_cast<AsyncRPCOperation_sendmany> (operation);
1080 TEST_FRIEND_AsyncRPCOperation_sendmany proxy(ptr);
06c19063 1081
cff6f0ac 1082 std::string memo = "DEADBEEF";
a6bbb26e 1083 std::array<unsigned char, ZC_MEMO_SIZE> array = proxy.get_memo_from_hex_string(memo);
cff6f0ac
S
1084 BOOST_CHECK_EQUAL(array[0], 0xDE);
1085 BOOST_CHECK_EQUAL(array[1], 0xAD);
1086 BOOST_CHECK_EQUAL(array[2], 0xBE);
1087 BOOST_CHECK_EQUAL(array[3], 0xEF);
1088 for (int i=4; i<ZC_MEMO_SIZE; i++) {
1089 BOOST_CHECK_EQUAL(array[i], 0x00); // zero padding
1090 }
06c19063 1091
cff6f0ac
S
1092 // memo is longer than allowed
1093 std::vector<char> v (2 * (ZC_MEMO_SIZE+1));
1094 std::fill(v.begin(),v.end(), 'A');
1095 std::string bigmemo(v.begin(), v.end());
06c19063 1096
cff6f0ac
S
1097 try {
1098 proxy.get_memo_from_hex_string(bigmemo);
0d37ae3a 1099 } catch (const UniValue& objError) {
da5e7e51 1100 BOOST_CHECK( find_error(objError, "too big"));
cff6f0ac 1101 }
06c19063 1102
cff6f0ac
S
1103 // invalid hexadecimal string
1104 std::fill(v.begin(),v.end(), '@'); // not a hex character
1105 std::string badmemo(v.begin(), v.end());
06c19063 1106
cff6f0ac
S
1107 try {
1108 proxy.get_memo_from_hex_string(badmemo);
0d37ae3a 1109 } catch (const UniValue& objError) {
da5e7e51 1110 BOOST_CHECK( find_error(objError, "hexadecimal format"));
cff6f0ac 1111 }
06c19063 1112
cff6f0ac
S
1113 // odd length hexadecimal string
1114 std::fill(v.begin(),v.end(), 'A');
1115 v.resize(v.size() - 1);
da5e7e51 1116 assert(v.size() %2 == 1); // odd length
cff6f0ac
S
1117 std::string oddmemo(v.begin(), v.end());
1118 try {
1119 proxy.get_memo_from_hex_string(oddmemo);
0d37ae3a 1120 } catch (const UniValue& objError) {
da5e7e51 1121 BOOST_CHECK( find_error(objError, "hexadecimal format"));
cff6f0ac
S
1122 }
1123 }
06c19063
S
1124
1125
cff6f0ac
S
1126 // add_taddr_change_output_to_tx() will append a vout to a raw transaction
1127 {
1128 std::vector<SendManyRecipient> recipients = { SendManyRecipient(zaddr1,100.0, "DEADBEEF") };
36e2141d 1129 std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_sendmany(boost::none, mtx, zaddr1, recipients, {}, 1) );
cff6f0ac
S
1130 std::shared_ptr<AsyncRPCOperation_sendmany> ptr = std::dynamic_pointer_cast<AsyncRPCOperation_sendmany> (operation);
1131 TEST_FRIEND_AsyncRPCOperation_sendmany proxy(ptr);
06c19063 1132
cff6f0ac
S
1133 CTransaction tx = proxy.getTx();
1134 BOOST_CHECK(tx.vout.size() == 0);
bf69507c 1135 CAmount amount = AmountFromValue(ValueFromString("123.456"));
cff6f0ac
S
1136 proxy.add_taddr_change_output_to_tx(amount);
1137 tx = proxy.getTx();
1138 BOOST_CHECK(tx.vout.size() == 1);
1139 CTxOut out = tx.vout[0];
1140 BOOST_CHECK_EQUAL(out.nValue, amount);
bf69507c 1141 amount = AmountFromValue(ValueFromString("1.111"));
cff6f0ac
S
1142 proxy.add_taddr_change_output_to_tx(amount);
1143 tx = proxy.getTx();
1144 BOOST_CHECK(tx.vout.size() == 2);
1145 out = tx.vout[1];
1146 BOOST_CHECK_EQUAL(out.nValue, amount);
1147 }
06c19063 1148
cff6f0ac
S
1149 // add_taddr_outputs_to_tx() will append many vouts to a raw transaction
1150 {
1151 std::vector<SendManyRecipient> recipients = {
ee64b5e7
JG
1152 SendManyRecipient("tmTGScYwiLMzHe4uGZtBYmuqoW4iEoYNMXt",CAmount(1.23), ""),
1153 SendManyRecipient("tmUSbHz3vxnwLvRyNDXbwkZxjVyDodMJEhh",CAmount(4.56), ""),
1154 SendManyRecipient("tmYZAXYPCP56Xa5JQWWPZuK7o7bfUQW6kkd",CAmount(7.89), ""),
cff6f0ac 1155 };
36e2141d 1156 std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_sendmany(boost::none, mtx, zaddr1, recipients, {}, 1) );
cff6f0ac
S
1157 std::shared_ptr<AsyncRPCOperation_sendmany> ptr = std::dynamic_pointer_cast<AsyncRPCOperation_sendmany> (operation);
1158 TEST_FRIEND_AsyncRPCOperation_sendmany proxy(ptr);
06c19063 1159
cff6f0ac 1160 proxy.add_taddr_outputs_to_tx();
06c19063 1161
cff6f0ac
S
1162 CTransaction tx = proxy.getTx();
1163 BOOST_CHECK(tx.vout.size() == 3);
1164 BOOST_CHECK_EQUAL(tx.vout[0].nValue, CAmount(1.23));
1165 BOOST_CHECK_EQUAL(tx.vout[1].nValue, CAmount(4.56));
1166 BOOST_CHECK_EQUAL(tx.vout[2].nValue, CAmount(7.89));
1167 }
06c19063 1168
cff6f0ac
S
1169
1170 // Raw joinsplit is a zaddr->zaddr
1171 {
1172 std::string raw = "020000000000000000000100000000000000001027000000000000183a0d4c46c369078705e39bcfebee59a978dbd210ce8de3efc9555a03fbabfd3cea16693d730c63850d7e48ccde79854c19adcb7e9dcd7b7d18805ee09083f6b16e1860729d2d4a90e2f2acd009cf78b5eb0f4a6ee4bdb64b1262d7ce9eb910c460b02022991e968d0c50ee44908e4ccccbc591d0053bcca154dd6d6fc400a29fa686af4682339832ccea362a62aeb9df0d5aa74f86a1e75ac0f48a8ccc41e0a940643c6c33e1d09223b0a46eaf47a1bb4407cfc12b1dcf83a29c0cef51e45c7876ca5b9e5bae86d92976eb3ef68f29cd29386a8be8451b50f82bf9da10c04651868655194da8f6ed3d241bb5b5ff93a3e2bbe44644544d88bcde5cc35978032ee92699c7a61fcbb395e7583f47e698c4d53ede54f956629400bf510fb5e22d03158cc10bdcaaf29e418ef18eb6480dd9c8b9e2a377809f9f32a556ef872febd0021d4ad013aa9f0b7255e98e408d302abefd33a71180b720271835b487ab309e160b06dfe51932120fb84a7ede16b20c53599a11071592109e10260f265ee60d48c62bfe24074020e9b586ce9e9356e68f2ad1a9538258234afe4b83a209f178f45202270eaeaeecaf2ce3100b2c5a714f75f35777a9ebff5ebf47059d2bbf6f3726190216468f2b152673b766225b093f3a2f827c86d6b48b42117fec1d0ac38dd7af700308dcfb02eba821612b16a2c164c47715b9b0c93900893b1aba2ea03765c94d87022db5be06ab338d1912e0936dfe87586d0a8ee49144a6cd2e306abdcb652faa3e0222739deb23154d778b50de75069a4a2cce1208cd1ced3cb4744c9888ce1c2fcd2e66dc31e62d3aa9e423d7275882525e9981f92e84ac85975b8660739407efbe1e34c2249420fde7e17db3096d5b22e83d051d01f0e6e7690dca7d168db338aadf0897fedac10de310db2b1bff762d322935dddbb60c2efb8b15d231fa17b84630371cb275c209f0c4c7d0c68b150ea5cd514122215e3f7fcfb351d69514788d67c2f3c8922581946e3a04bdf1f07f15696ca76eb95b10698bf1188fd882945c57657515889d042a6fc45d38cbc943540c4f0f6d1c45a1574c81f3e42d1eb8702328b729909adee8a5cfed7c79d54627d1fd389af941d878376f7927b9830ca659bf9ab18c5ca5192d52d02723008728d03701b8ab3e1c4a3109409ec0b13df334c7deec3523eeef4c97b5603e643de3a647b873f4c1b47fbfc6586ba66724f112e51fc93839648005043620aa3ce458e246d77977b19c53d98e3e812de006afc1a79744df236582943631d04cc02941ac4be500e4ed9fb9e3e7cc187b1c4050fad1d9d09d5fd70d5d01d615b439d8c0015d2eb10398bcdbf8c4b2bd559dbe4c288a186aed3f86f608da4d582e120c4a896e015e2241900d1daeccd05db968852677c71d752bec46de9962174b46f980e8cc603654daf8b98a3ee92dac066033954164a89568b70b1780c2ce2410b2f816dbeddb2cd463e0c8f21a52cf6427d9647a6fd4bafa8fb4cd4d47ac057b0160bee86c6b2fb8adce214c2bcdda277512200adf0eaa5d2114a2c077b009836a68ec254bfe56f51d147b9afe2ddd9cb917c0c2de19d81b7b8fd9f4574f51fa1207630dc13976f4d7587c962f761af267de71f3909a576e6bedaf6311633910d291ac292c467cc8331ef577aef7646a5d949322fa0367a49f20597a13def53136ee31610395e3e48d291fd8f58504374031fe9dcfba5e06086ebcf01a9106f6a4d6e16e19e4c5bb893f7da79419c94eca31a384be6fa1747284dee0fc3bbc8b1b860172c10b29c1594bb8c747d7fe05827358ff2160f49050001625ffe2e880bd7fc26cd0ffd89750745379a8e862816e08a5a2008043921ab6a4976064ac18f7ee37b6628bc0127d8d5ebd3548e41d8881a082d86f20b32e33094f15a0e6ea6074b08c6cd28142de94713451640a55985051f5577eb54572699d838cb34a79c8939e981c0c277d06a6e2ce69ccb74f8a691ff08f81d8b99e6a86223d29a2b7c8e7b041aba44ea678ae654277f7e91cbfa79158b989164a3d549d9f4feb0cc43169699c13e321fe3f4b94258c75d198ff9184269cd6986c55409e07528c93f64942c6c283ce3917b4bf4c3be2fe3173c8c38cccb35f1fbda0ca88b35a599c0678cb22aa8eabea8249dbd2e4f849fffe69803d299e435ebcd7df95854003d8eda17a74d98b4be0e62d45d7fe48c06a6f464a14f8e0570077cc631279092802a89823f031eef5e1028a6d6fdbd502869a731ee7d28b4d6c71b419462a30d31442d3ee444ffbcbd16d558c9000c97e949c2b1f9d6f6d8db7b9131ebd963620d3fc8595278d6f8fdf49084325373196d53e64142fa5a23eccd6ef908c4d80b8b3e6cc334b7f7012103a3682e4678e9b518163d262a39a2c1a69bf88514c52b7ccd7cc8dc80e71f7c2ec0701cff982573eb0c2c4daeb47fa0b586f4451c10d1da2e5d182b03dd067a5e971b3a6138ca6667aaf853d2ac03b80a1d5870905f2cfb6c78ec3c3719c02f973d638a0f973424a2b0f2b0023f136d60092fe15fba4bc180b9176bd0ff576e053f1af6939fe9ca256203ffaeb3e569f09774d2a6cbf91873e56651f4d6ff77e0b5374b0a1a201d7e523604e0247644544cc571d48c458a4f96f45580b";
0d37ae3a 1173 UniValue obj(UniValue::VOBJ);
cff6f0ac 1174 obj.push_back(Pair("rawtxn", raw));
06c19063 1175
cff6f0ac
S
1176 // we have the spending key for the dummy recipient zaddr1
1177 std::vector<SendManyRecipient> recipients = { SendManyRecipient(zaddr1, 0.0005, "ABCD") };
06c19063 1178
36e2141d 1179 std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_sendmany(boost::none, mtx, zaddr1, {}, recipients, 1) );
cff6f0ac
S
1180 std::shared_ptr<AsyncRPCOperation_sendmany> ptr = std::dynamic_pointer_cast<AsyncRPCOperation_sendmany> (operation);
1181 TEST_FRIEND_AsyncRPCOperation_sendmany proxy(ptr);
06c19063 1182
cff6f0ac
S
1183 // Enable test mode so tx is not sent
1184 static_cast<AsyncRPCOperation_sendmany *>(operation.get())->testmode = true;
06c19063 1185
da5e7e51
S
1186 // Pretend that the operation completed successfully
1187 proxy.set_state(OperationStatus::SUCCESS);
cff6f0ac 1188
da5e7e51 1189 // Verify test mode is returning output (since no input taddrs, signed and unsigned are the same).
cff6f0ac 1190 BOOST_CHECK_NO_THROW( proxy.sign_send_raw_transaction(obj) );
0d37ae3a
JG
1191 UniValue result = operation->getResult();
1192 BOOST_CHECK(!result.isNull());
1193 UniValue resultObj = result.get_obj();
da5e7e51
S
1194 std::string hex = find_value(resultObj, "hex").get_str();
1195 BOOST_CHECK_EQUAL(hex, raw);
cff6f0ac 1196 }
06c19063
S
1197
1198
7b79275e
S
1199 // Test the perform_joinsplit methods.
1200 {
1201 // Dummy input so the operation object can be instantiated.
1202 std::vector<SendManyRecipient> recipients = { SendManyRecipient(zaddr1, 0.0005, "ABCD") };
06c19063 1203
36e2141d 1204 std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_sendmany(boost::none, mtx, zaddr1, {}, recipients, 1) );
7b79275e 1205 std::shared_ptr<AsyncRPCOperation_sendmany> ptr = std::dynamic_pointer_cast<AsyncRPCOperation_sendmany> (operation);
06c19063 1206 TEST_FRIEND_AsyncRPCOperation_sendmany proxy(ptr);
7b79275e
S
1207
1208 // Enable test mode so tx is not sent and proofs are not generated
1209 static_cast<AsyncRPCOperation_sendmany *>(operation.get())->testmode = true;
06c19063
S
1210
1211 AsyncJoinSplitInfo info;
8ea8ef98 1212 std::vector<boost::optional < SproutWitness>> witnesses;
7b79275e
S
1213 uint256 anchor;
1214 try {
1215 proxy.perform_joinsplit(info, witnesses, anchor);
1216 } catch (const std::runtime_error & e) {
1217 BOOST_CHECK( string(e.what()).find("anchor is null")!= string::npos);
1218 }
1219
1220 try {
1221 std::vector<JSOutPoint> v;
1222 proxy.perform_joinsplit(info, v);
1223 } catch (const std::runtime_error & e) {
1224 BOOST_CHECK( string(e.what()).find("anchor is null")!= string::npos);
1225 }
1226
b230fe68 1227 info.notes.push_back(SproutNote());
7b79275e
S
1228 try {
1229 proxy.perform_joinsplit(info);
1230 } catch (const std::runtime_error & e) {
1231 BOOST_CHECK( string(e.what()).find("number of notes")!= string::npos);
1232 }
06c19063 1233
7b79275e
S
1234 info.notes.clear();
1235 info.vjsin.push_back(JSInput());
1236 info.vjsin.push_back(JSInput());
1237 info.vjsin.push_back(JSInput());
1238 try {
1239 proxy.perform_joinsplit(info);
1240 } catch (const std::runtime_error & e) {
1241 BOOST_CHECK( string(e.what()).find("unsupported joinsplit input")!= string::npos);
1242 }
06c19063 1243
7b79275e
S
1244 info.vjsin.clear();
1245 try {
1246 proxy.perform_joinsplit(info);
1247 } catch (const std::runtime_error & e) {
bef1b5ce 1248 BOOST_CHECK( string(e.what()).find("error verifying joinsplit")!= string::npos);
7b79275e
S
1249 }
1250 }
06c19063 1251
fc4b127e
S
1252}
1253
60f762a5 1254
bb4b6982
JG
1255BOOST_AUTO_TEST_CASE(rpc_z_sendmany_taddr_to_sapling)
1256{
1257 SelectParams(CBaseChainParams::REGTEST);
1258 UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::ALWAYS_ACTIVE);
1259 UpdateNetworkUpgradeParameters(Consensus::UPGRADE_SAPLING, Consensus::NetworkUpgrade::ALWAYS_ACTIVE);
1260
1261 LOCK(pwalletMain->cs_wallet);
1262
1263 if (!pwalletMain->HaveHDSeed()) {
1264 pwalletMain->GenerateNewSeed();
1265 }
1266
1267 UniValue retValue;
1268
1269 // add keys manually
1270 auto taddr = pwalletMain->GenerateNewKey().GetID();
1271 std::string taddr1 = EncodeDestination(taddr);
1272 auto pa = pwalletMain->GenerateNewSaplingZKey();
1273 std::string zaddr1 = EncodePaymentAddress(pa);
1274
1275 auto consensusParams = Params().GetConsensus();
1276 retValue = CallRPC("getblockcount");
1277 int nextBlockHeight = retValue.get_int() + 1;
1278
1279 // Add a fake transaction to the wallet
1280 CMutableTransaction mtx = CreateNewContextualCMutableTransaction(consensusParams, nextBlockHeight);
1281 CScript scriptPubKey = CScript() << OP_DUP << OP_HASH160 << ToByteVector(taddr) << OP_EQUALVERIFY << OP_CHECKSIG;
1282 mtx.vout.push_back(CTxOut(5 * COIN, scriptPubKey));
1283 CWalletTx wtx(pwalletMain, mtx);
1284 pwalletMain->AddToWallet(wtx, true, NULL);
1285
1286 // Fake-mine the transaction
1287 BOOST_CHECK_EQUAL(0, chainActive.Height());
1288 CBlock block;
1289 block.hashPrevBlock = chainActive.Tip()->GetBlockHash();
1290 block.vtx.push_back(wtx);
1291 block.hashMerkleRoot = block.BuildMerkleTree();
1292 auto blockHash = block.GetHash();
1293 CBlockIndex fakeIndex {block};
1294 fakeIndex.nHeight = 1;
1295 mapBlockIndex.insert(std::make_pair(blockHash, &fakeIndex));
1296 chainActive.SetTip(&fakeIndex);
1297 BOOST_CHECK(chainActive.Contains(&fakeIndex));
1298 BOOST_CHECK_EQUAL(1, chainActive.Height());
1299 wtx.SetMerkleBranch(block);
1300 pwalletMain->AddToWallet(wtx, true, NULL);
1301
1302 // Context that z_sendmany requires
1303 auto builder = TransactionBuilder(consensusParams, nextBlockHeight, pwalletMain);
1304 mtx = CreateNewContextualCMutableTransaction(consensusParams, nextBlockHeight);
1305
1306 std::vector<SendManyRecipient> recipients = { SendManyRecipient(zaddr1, 1 * COIN, "ABCD") };
1307 std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_sendmany(builder, mtx, taddr1, {}, recipients, 0) );
1308 std::shared_ptr<AsyncRPCOperation_sendmany> ptr = std::dynamic_pointer_cast<AsyncRPCOperation_sendmany> (operation);
1309
1310 // Enable test mode so tx is not sent
1311 static_cast<AsyncRPCOperation_sendmany *>(operation.get())->testmode = true;
1312
1313 // Generate the Sapling shielding transaction
1314 operation->main();
1315 BOOST_CHECK(operation->isSuccess());
1316
1317 // Get the transaction
1318 auto result = operation->getResult();
1319 BOOST_ASSERT(result.isObject());
1320 auto hexTx = result["hex"].getValStr();
1321 CDataStream ss(ParseHex(hexTx), SER_NETWORK, PROTOCOL_VERSION);
1322 CTransaction tx;
1323 ss >> tx;
1324 BOOST_ASSERT(!tx.vShieldedOutput.empty());
1325
1326 // We shouldn't be able to decrypt with the empty ovk
1327 BOOST_CHECK(!AttemptSaplingOutDecryption(
1328 tx.vShieldedOutput[0].outCiphertext,
1329 uint256(),
1330 tx.vShieldedOutput[0].cv,
1331 tx.vShieldedOutput[0].cm,
1332 tx.vShieldedOutput[0].ephemeralKey));
1333
1334 // We should be able to decrypt the outCiphertext with the ovk
1335 // generated for transparent addresses
1336 HDSeed seed;
1337 BOOST_ASSERT(pwalletMain->GetHDSeed(seed));
1338 BOOST_CHECK(AttemptSaplingOutDecryption(
1339 tx.vShieldedOutput[0].outCiphertext,
1340 ovkForShieldingFromTaddr(seed),
1341 tx.vShieldedOutput[0].cv,
1342 tx.vShieldedOutput[0].cm,
1343 tx.vShieldedOutput[0].ephemeralKey));
1344
1345 // Tear down
1346 chainActive.SetTip(NULL);
1347 mapBlockIndex.erase(blockHash);
1348 mapArgs.erase("-developersapling");
1349 mapArgs.erase("-experimentalfeatures");
1350
1351 // Revert to default
1352 UpdateNetworkUpgradeParameters(Consensus::UPGRADE_SAPLING, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT);
1353 UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT);
1354}
1355
1356
73699cea
S
1357/*
1358 * This test covers storing encrypted zkeys in the wallet.
1359 */
b7f9a7ae 1360/* TODO: Uncomment during PR for #3388
73699cea
S
1361BOOST_AUTO_TEST_CASE(rpc_wallet_encrypted_wallet_zkeys)
1362{
1363 LOCK2(cs_main, pwalletMain->cs_wallet);
0d37ae3a 1364 UniValue retValue;
73699cea
S
1365 int n = 100;
1366
1367 // wallet should currently be empty
e5eab182 1368 std::set<libzcash::SproutPaymentAddress> addrs;
25d5e80c 1369 pwalletMain->GetSproutPaymentAddresses(addrs);
73699cea
S
1370 BOOST_CHECK(addrs.size()==0);
1371
1372 // create keys
1373 for (int i = 0; i < n; i++) {
1374 CallRPC("z_getnewaddress");
1375 }
1376
1377 // Verify we can list the keys imported
1378 BOOST_CHECK_NO_THROW(retValue = CallRPC("z_listaddresses"));
0d37ae3a 1379 UniValue arr = retValue.get_array();
73699cea
S
1380 BOOST_CHECK(arr.size() == n);
1381
d8e06e3f
JG
1382 // Verify that the wallet encryption RPC is disabled
1383 BOOST_CHECK_THROW(CallRPC("encryptwallet passphrase"), runtime_error);
1384
82bd9ee8 1385 // Encrypt the wallet (we can't call RPC encryptwallet as that shuts down node)
73699cea
S
1386 SecureString strWalletPass;
1387 strWalletPass.reserve(100);
1388 strWalletPass = "hello";
6be367ea
S
1389
1390 boost::filesystem::current_path(GetArg("-datadir","/tmp/thisshouldnothappen"));
73699cea 1391 BOOST_CHECK(pwalletMain->EncryptWallet(strWalletPass));
06c19063 1392
73699cea
S
1393 // Verify we can still list the keys imported
1394 BOOST_CHECK_NO_THROW(retValue = CallRPC("z_listaddresses"));
1395 arr = retValue.get_array();
1396 BOOST_CHECK(arr.size() == n);
06c19063 1397
73699cea
S
1398 // Try to add a new key, but we can't as the wallet is locked
1399 BOOST_CHECK_THROW(CallRPC("z_getnewaddress"), runtime_error);
06c19063 1400
73699cea
S
1401 // We can't call RPC walletpassphrase as that invokes RPCRunLater which breaks tests.
1402 // So we manually unlock.
1403 BOOST_CHECK(pwalletMain->Unlock(strWalletPass));
06c19063 1404
73699cea
S
1405 // Now add a key
1406 BOOST_CHECK_NO_THROW(CallRPC("z_getnewaddress"));
06c19063 1407
73699cea
S
1408 // Verify the key has been added
1409 BOOST_CHECK_NO_THROW(retValue = CallRPC("z_listaddresses"));
1410 arr = retValue.get_array();
06c19063 1411 BOOST_CHECK(arr.size() == n+1);
73699cea
S
1412
1413 // We can't simulate over RPC the wallet closing and being reloaded
1414 // but there are tests for this in gtest.
1415}
b7f9a7ae 1416*/
73699cea 1417
06c19063 1418
d72c19a6
S
1419BOOST_AUTO_TEST_CASE(rpc_z_listunspent_parameters)
1420{
1421 SelectParams(CBaseChainParams::TESTNET);
1422
1423 LOCK(pwalletMain->cs_wallet);
73699cea 1424
d72c19a6
S
1425 UniValue retValue;
1426
1427 // too many args
1428 BOOST_CHECK_THROW(CallRPC("z_listunspent 1 2 3 4 5"), runtime_error);
1429
1430 // minconf must be >= 0
1431 BOOST_CHECK_THROW(CallRPC("z_listunspent -1"), runtime_error);
1432
1433 // maxconf must be > minconf
1434 BOOST_CHECK_THROW(CallRPC("z_listunspent 2 1"), runtime_error);
1435
1436 // maxconf must not be out of range
1437 BOOST_CHECK_THROW(CallRPC("z_listunspent 1 9999999999"), runtime_error);
1438
1439 // must be an array of addresses
1440 BOOST_CHECK_THROW(CallRPC("z_listunspent 1 999 false ztjiDe569DPNbyTE6TSdJTaSDhoXEHLGvYoUnBU1wfVNU52TEyT6berYtySkd21njAeEoh8fFJUT42kua9r8EnhBaEKqCpP"), runtime_error);
1441
1442 // address must be string
1443 BOOST_CHECK_THROW(CallRPC("z_listunspent 1 999 false [123456]"), runtime_error);
1444
1445 // no spending key
1446 BOOST_CHECK_THROW(CallRPC("z_listunspent 1 999 false [\"ztjiDe569DPNbyTE6TSdJTaSDhoXEHLGvYoUnBU1wfVNU52TEyT6berYtySkd21njAeEoh8fFJUT42kua9r8EnhBaEKqCpP\"]"), runtime_error);
1447
1448 // allow watch only
1449 BOOST_CHECK_NO_THROW(CallRPC("z_listunspent 1 999 true [\"ztjiDe569DPNbyTE6TSdJTaSDhoXEHLGvYoUnBU1wfVNU52TEyT6berYtySkd21njAeEoh8fFJUT42kua9r8EnhBaEKqCpP\"]"));
1450
1451 // wrong network, mainnet instead of testnet
1452 BOOST_CHECK_THROW(CallRPC("z_listunspent 1 999 true [\"zcMuhvq8sEkHALuSU2i4NbNQxshSAYrpCExec45ZjtivYPbuiFPwk6WHy4SvsbeZ4siy1WheuRGjtaJmoD1J8bFqNXhsG6U\"]"), runtime_error);
1453
1454 // create shielded address so we have the spending key
1455 BOOST_CHECK_NO_THROW(retValue = CallRPC("z_getnewaddress"));
1456 std::string myzaddr = retValue.get_str();
1457
1458 // return empty array for this address
1459 BOOST_CHECK_NO_THROW(retValue = CallRPC("z_listunspent 1 999 false [\"" + myzaddr + "\"]"));
1460 UniValue arr = retValue.get_array();
1461 BOOST_CHECK_EQUAL(0, arr.size());
1462
1463 // duplicate address error
1464 BOOST_CHECK_THROW(CallRPC("z_listunspent 1 999 false [\"" + myzaddr + "\", \"" + myzaddr + "\"]"), runtime_error);
1465}
06c19063
S
1466
1467
1468BOOST_AUTO_TEST_CASE(rpc_z_shieldcoinbase_parameters)
1469{
1470 SelectParams(CBaseChainParams::TESTNET);
1471
1472 LOCK(pwalletMain->cs_wallet);
1473
1474 BOOST_CHECK_THROW(CallRPC("z_shieldcoinbase"), runtime_error);
1475 BOOST_CHECK_THROW(CallRPC("z_shieldcoinbase toofewargs"), runtime_error);
c5dabd2b 1476 BOOST_CHECK_THROW(CallRPC("z_shieldcoinbase too many args shown here"), runtime_error);
06c19063
S
1477
1478 // bad from address
1479 BOOST_CHECK_THROW(CallRPC("z_shieldcoinbase "
1480 "INVALIDtmRr6yJonqGK23UVhrKuyvTpF8qxQQjKigJ tnpoQJVnYBZZqkFadj2bJJLThNCxbADGB5gSGeYTAGGrT5tejsxY9Zc1BtY8nnHmZkB"), runtime_error);
1481
1482 // bad from address
1483 BOOST_CHECK_THROW(CallRPC("z_shieldcoinbase "
1484 "** tnpoQJVnYBZZqkFadj2bJJLThNCxbADGB5gSGeYTAGGrT5tejsxY9Zc1BtY8nnHmZkB"), runtime_error);
1485
1486 // bad to address
1487 BOOST_CHECK_THROW(CallRPC("z_shieldcoinbase "
1488 "tmRr6yJonqGK23UVhrKuyvTpF8qxQQjKigJ INVALIDtnpoQJVnYBZZqkFadj2bJJLThNCxbADGB5gSGeYTAGGrT5tejsxY9Zc1BtY8nnHmZkB"), runtime_error);
1489
1490 // invalid fee amount, cannot be negative
1491 BOOST_CHECK_THROW(CallRPC("z_shieldcoinbase "
1492 "tmRr6yJonqGK23UVhrKuyvTpF8qxQQjKigJ "
1493 "tnpoQJVnYBZZqkFadj2bJJLThNCxbADGB5gSGeYTAGGrT5tejsxY9Zc1BtY8nnHmZkB "
1494 "-0.0001"
1495 ), runtime_error);
1496
1497 // invalid fee amount, bigger than MAX_MONEY
1498 BOOST_CHECK_THROW(CallRPC("z_shieldcoinbase "
1499 "tmRr6yJonqGK23UVhrKuyvTpF8qxQQjKigJ "
1500 "tnpoQJVnYBZZqkFadj2bJJLThNCxbADGB5gSGeYTAGGrT5tejsxY9Zc1BtY8nnHmZkB "
1501 "21000001"
1502 ), runtime_error);
1503
c5dabd2b
S
1504 // invalid limit, must be at least 0
1505 BOOST_CHECK_THROW(CallRPC("z_shieldcoinbase "
1506 "tmRr6yJonqGK23UVhrKuyvTpF8qxQQjKigJ "
1507 "tnpoQJVnYBZZqkFadj2bJJLThNCxbADGB5gSGeYTAGGrT5tejsxY9Zc1BtY8nnHmZkB "
1508 "100 -1"
1509 ), runtime_error);
1510
072099d7
S
1511 // Mutable tx containing contextual information we need to build tx
1512 UniValue retValue = CallRPC("getblockcount");
1513 int nHeight = retValue.get_int();
1514 CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nHeight + 1);
1515 if (mtx.nVersion == 1) {
1516 mtx.nVersion = 2;
1517 }
1518
06c19063
S
1519 // Test constructor of AsyncRPCOperation_sendmany
1520 std::string testnetzaddr = "ztjiDe569DPNbyTE6TSdJTaSDhoXEHLGvYoUnBU1wfVNU52TEyT6berYtySkd21njAeEoh8fFJUT42kua9r8EnhBaEKqCpP";
1521 std::string mainnetzaddr = "zcMuhvq8sEkHALuSU2i4NbNQxshSAYrpCExec45ZjtivYPbuiFPwk6WHy4SvsbeZ4siy1WheuRGjtaJmoD1J8bFqNXhsG6U";
1522
1523 try {
072099d7 1524 std::shared_ptr<AsyncRPCOperation> operation(new AsyncRPCOperation_shieldcoinbase(mtx, {}, testnetzaddr, -1 ));
06c19063
S
1525 } catch (const UniValue& objError) {
1526 BOOST_CHECK( find_error(objError, "Fee is out of range"));
1527 }
1528
1529 try {
072099d7 1530 std::shared_ptr<AsyncRPCOperation> operation(new AsyncRPCOperation_shieldcoinbase(mtx, {}, testnetzaddr, 1));
06c19063
S
1531 } catch (const UniValue& objError) {
1532 BOOST_CHECK( find_error(objError, "Empty inputs"));
1533 }
1534
1535 // Testnet payment addresses begin with 'zt'. This test detects an incorrect prefix.
1536 try {
1537 std::vector<ShieldCoinbaseUTXO> inputs = { ShieldCoinbaseUTXO{uint256(),0,0} };
072099d7 1538 std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_shieldcoinbase(mtx, inputs, mainnetzaddr, 1) );
06c19063 1539 } catch (const UniValue& objError) {
80ed13d5 1540 BOOST_CHECK( find_error(objError, "Invalid to address"));
06c19063
S
1541 }
1542
1543}
1544
1545
1546
1547BOOST_AUTO_TEST_CASE(rpc_z_shieldcoinbase_internals)
1548{
1549 SelectParams(CBaseChainParams::TESTNET);
1550
1551 LOCK(pwalletMain->cs_wallet);
1552
072099d7
S
1553 // Mutable tx containing contextual information we need to build tx
1554 UniValue retValue = CallRPC("getblockcount");
1555 int nHeight = retValue.get_int();
1556 CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nHeight + 1);
1557 if (mtx.nVersion == 1) {
1558 mtx.nVersion = 2;
1559 }
1560
06c19063
S
1561 // Test that option -mempooltxinputlimit is respected.
1562 mapArgs["-mempooltxinputlimit"] = "1";
1563
1564 // Add keys manually
80ed13d5
JG
1565 auto pa = pwalletMain->GenerateNewZKey();
1566 std::string zaddr = EncodePaymentAddress(pa);
06c19063
S
1567
1568 // Supply 2 inputs when mempool limit is 1
1569 {
1570 std::vector<ShieldCoinbaseUTXO> inputs = { ShieldCoinbaseUTXO{uint256(),0,0}, ShieldCoinbaseUTXO{uint256(),0,0} };
072099d7 1571 std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_shieldcoinbase(mtx, inputs, zaddr) );
06c19063
S
1572 operation->main();
1573 BOOST_CHECK(operation->isFailed());
1574 std::string msg = operation->getErrorMessage();
1575 BOOST_CHECK( msg.find("Number of inputs 2 is greater than mempooltxinputlimit of 1") != string::npos);
1576 }
1577
1578 // Insufficient funds
1579 {
1580 std::vector<ShieldCoinbaseUTXO> inputs = { ShieldCoinbaseUTXO{uint256(),0,0} };
072099d7 1581 std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_shieldcoinbase(mtx, inputs, zaddr) );
06c19063
S
1582 operation->main();
1583 BOOST_CHECK(operation->isFailed());
1584 std::string msg = operation->getErrorMessage();
1585 BOOST_CHECK( msg.find("Insufficient coinbase funds") != string::npos);
1586 }
1587
1588 // Test the perform_joinsplit methods.
1589 {
1590 // Dummy input so the operation object can be instantiated.
1591 std::vector<ShieldCoinbaseUTXO> inputs = { ShieldCoinbaseUTXO{uint256(),0,100000} };
072099d7 1592 std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_shieldcoinbase(mtx, inputs, zaddr) );
06c19063
S
1593 std::shared_ptr<AsyncRPCOperation_shieldcoinbase> ptr = std::dynamic_pointer_cast<AsyncRPCOperation_shieldcoinbase> (operation);
1594 TEST_FRIEND_AsyncRPCOperation_shieldcoinbase proxy(ptr);
1595 static_cast<AsyncRPCOperation_shieldcoinbase *>(operation.get())->testmode = true;
1596
1597 ShieldCoinbaseJSInfo info;
1598 info.vjsin.push_back(JSInput());
1599 info.vjsin.push_back(JSInput());
1600 info.vjsin.push_back(JSInput());
1601 try {
1602 proxy.perform_joinsplit(info);
1603 } catch (const std::runtime_error & e) {
1604 BOOST_CHECK( string(e.what()).find("unsupported joinsplit input")!= string::npos);
1605 }
1606
1607 info.vjsin.clear();
1608 try {
1609 proxy.perform_joinsplit(info);
1610 } catch (const std::runtime_error & e) {
bef1b5ce 1611 BOOST_CHECK( string(e.what()).find("error verifying joinsplit")!= string::npos);
06c19063
S
1612 }
1613 }
1614
1615}
1616
1617
6e9c7629
JG
1618BOOST_AUTO_TEST_CASE(rpc_z_mergetoaddress_parameters)
1619{
1620 SelectParams(CBaseChainParams::TESTNET);
1621
1622 LOCK(pwalletMain->cs_wallet);
1623
1624 BOOST_CHECK_THROW(CallRPC("z_mergetoaddress"), runtime_error);
1625 BOOST_CHECK_THROW(CallRPC("z_mergetoaddress toofewargs"), runtime_error);
1626 BOOST_CHECK_THROW(CallRPC("z_mergetoaddress just too many args present for this method"), runtime_error);
1627
1628 // bad from address
1629 BOOST_CHECK_THROW(CallRPC("z_mergetoaddress "
1630 "[\"INVALIDtmRr6yJonqGK23UVhrKuyvTpF8qxQQjKigJ\"] tnpoQJVnYBZZqkFadj2bJJLThNCxbADGB5gSGeYTAGGrT5tejsxY9Zc1BtY8nnHmZkB"), runtime_error);
1631
1632 // bad from address
1633 BOOST_CHECK_THROW(CallRPC("z_mergetoaddress "
1634 "** tnpoQJVnYBZZqkFadj2bJJLThNCxbADGB5gSGeYTAGGrT5tejsxY9Zc1BtY8nnHmZkB"), runtime_error);
1635
1636 // bad from address
1637 BOOST_CHECK_THROW(CallRPC("z_mergetoaddress "
1638 "[\"**\"] tnpoQJVnYBZZqkFadj2bJJLThNCxbADGB5gSGeYTAGGrT5tejsxY9Zc1BtY8nnHmZkB"), runtime_error);
1639
1640 // bad from address
1641 BOOST_CHECK_THROW(CallRPC("z_mergetoaddress "
1642 "tmRr6yJonqGK23UVhrKuyvTpF8qxQQjKigJ tnpoQJVnYBZZqkFadj2bJJLThNCxbADGB5gSGeYTAGGrT5tejsxY9Zc1BtY8nnHmZkB"), runtime_error);
1643
1644 // bad from address
1645 BOOST_CHECK_THROW(CallRPC("z_mergetoaddress "
1646 "[tmRr6yJonqGK23UVhrKuyvTpF8qxQQjKigJ] tnpoQJVnYBZZqkFadj2bJJLThNCxbADGB5gSGeYTAGGrT5tejsxY9Zc1BtY8nnHmZkB"), runtime_error);
1647
1648 // bad to address
1649 BOOST_CHECK_THROW(CallRPC("z_mergetoaddress "
1650 "[\"tmRr6yJonqGK23UVhrKuyvTpF8qxQQjKigJ\"] INVALIDtnpoQJVnYBZZqkFadj2bJJLThNCxbADGB5gSGeYTAGGrT5tejsxY9Zc1BtY8nnHmZkB"), runtime_error);
1651
1652 // duplicate address
1653 BOOST_CHECK_THROW(CallRPC("z_mergetoaddress "
1654 "[\"tmRr6yJonqGK23UVhrKuyvTpF8qxQQjKigJ\", \"tmRr6yJonqGK23UVhrKuyvTpF8qxQQjKigJ\"] "
1655 "tmQP9L3s31cLsghVYf2Jb5MhKj1jRBPoeQn"
1656 ), runtime_error);
1657
1658 // invalid fee amount, cannot be negative
1659 BOOST_CHECK_THROW(CallRPC("z_mergetoaddress "
1660 "[\"tmRr6yJonqGK23UVhrKuyvTpF8qxQQjKigJ\"] "
1661 "tnpoQJVnYBZZqkFadj2bJJLThNCxbADGB5gSGeYTAGGrT5tejsxY9Zc1BtY8nnHmZkB "
1662 "-0.0001"
1663 ), runtime_error);
1664
1665 // invalid fee amount, bigger than MAX_MONEY
1666 BOOST_CHECK_THROW(CallRPC("z_mergetoaddress "
1667 "[\"tmRr6yJonqGK23UVhrKuyvTpF8qxQQjKigJ\"] "
1668 "tnpoQJVnYBZZqkFadj2bJJLThNCxbADGB5gSGeYTAGGrT5tejsxY9Zc1BtY8nnHmZkB "
1669 "21000001"
1670 ), runtime_error);
1671
1672 // invalid transparent limit, must be at least 0
1673 BOOST_CHECK_THROW(CallRPC("z_mergetoaddress "
1674 "[\"tmRr6yJonqGK23UVhrKuyvTpF8qxQQjKigJ\"] "
1675 "tnpoQJVnYBZZqkFadj2bJJLThNCxbADGB5gSGeYTAGGrT5tejsxY9Zc1BtY8nnHmZkB "
1676 "0.0001 -1"
1677 ), runtime_error);
1678
1679 // invalid shielded limit, must be at least 0
1680 BOOST_CHECK_THROW(CallRPC("z_mergetoaddress "
1681 "[\"tmRr6yJonqGK23UVhrKuyvTpF8qxQQjKigJ\"] "
1682 "tnpoQJVnYBZZqkFadj2bJJLThNCxbADGB5gSGeYTAGGrT5tejsxY9Zc1BtY8nnHmZkB "
1683 "0.0001 100 -1"
1684 ), runtime_error);
1685
1686 // memo bigger than allowed length of ZC_MEMO_SIZE
1687 std::vector<char> v (2 * (ZC_MEMO_SIZE+1)); // x2 for hexadecimal string format
1688 std::fill(v.begin(),v.end(), 'A');
1689 std::string badmemo(v.begin(), v.end());
80ed13d5
JG
1690 auto pa = pwalletMain->GenerateNewZKey();
1691 std::string zaddr1 = EncodePaymentAddress(pa);
6e9c7629
JG
1692 BOOST_CHECK_THROW(CallRPC(string("z_mergetoaddress [\"tmRr6yJonqGK23UVhrKuyvTpF8qxQQjKigJ\"] ")
1693 + zaddr1 + " 0.0001 100 100 " + badmemo), runtime_error);
1694
1695 // Mutable tx containing contextual information we need to build tx
1696 UniValue retValue = CallRPC("getblockcount");
1697 int nHeight = retValue.get_int();
1698 CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nHeight + 1);
1699
1700 // Test constructor of AsyncRPCOperation_mergetoaddress
1701 MergeToAddressRecipient testnetzaddr(
1702 "ztjiDe569DPNbyTE6TSdJTaSDhoXEHLGvYoUnBU1wfVNU52TEyT6berYtySkd21njAeEoh8fFJUT42kua9r8EnhBaEKqCpP",
1703 "testnet memo");
1704 MergeToAddressRecipient mainnetzaddr(
1705 "zcMuhvq8sEkHALuSU2i4NbNQxshSAYrpCExec45ZjtivYPbuiFPwk6WHy4SvsbeZ4siy1WheuRGjtaJmoD1J8bFqNXhsG6U",
1706 "mainnet memo");
1707
1708 try {
1709 std::shared_ptr<AsyncRPCOperation> operation(new AsyncRPCOperation_mergetoaddress(mtx, {}, {}, testnetzaddr, -1 ));
1710 BOOST_FAIL("Should have caused an error");
1711 } catch (const UniValue& objError) {
1712 BOOST_CHECK( find_error(objError, "Fee is out of range"));
1713 }
1714
1715 try {
1716 std::shared_ptr<AsyncRPCOperation> operation(new AsyncRPCOperation_mergetoaddress(mtx, {}, {}, testnetzaddr, 1));
1717 BOOST_FAIL("Should have caused an error");
1718 } catch (const UniValue& objError) {
1719 BOOST_CHECK( find_error(objError, "No inputs"));
1720 }
1721
1722 std::vector<MergeToAddressInputUTXO> inputs = { MergeToAddressInputUTXO{ COutPoint{uint256(), 0}, 0} };
1723
1724 try {
1725 MergeToAddressRecipient badaddr("", "memo");
1726 std::shared_ptr<AsyncRPCOperation> operation(new AsyncRPCOperation_mergetoaddress(mtx, inputs, {}, badaddr, 1));
1727 BOOST_FAIL("Should have caused an error");
1728 } catch (const UniValue& objError) {
1729 BOOST_CHECK( find_error(objError, "Recipient parameter missing"));
1730 }
1731
1732 // Testnet payment addresses begin with 'zt'. This test detects an incorrect prefix.
1733 try {
1734 std::vector<MergeToAddressInputUTXO> inputs = { MergeToAddressInputUTXO{ COutPoint{uint256(), 0}, 0} };
1735 std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_mergetoaddress(mtx, inputs, {}, mainnetzaddr, 1) );
1736 BOOST_FAIL("Should have caused an error");
1737 } catch (const UniValue& objError) {
80ed13d5 1738 BOOST_CHECK( find_error(objError, "Invalid recipient address"));
6e9c7629
JG
1739 }
1740}
1741
1742
1743// TODO: test private methods
1744BOOST_AUTO_TEST_CASE(rpc_z_mergetoaddress_internals)
1745{
1746 SelectParams(CBaseChainParams::TESTNET);
1747
1748 LOCK(pwalletMain->cs_wallet);
1749
1750 // Mutable tx containing contextual information we need to build tx
1751 UniValue retValue = CallRPC("getblockcount");
1752 int nHeight = retValue.get_int();
1753 CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nHeight + 1);
1754
1755 // Test that option -mempooltxinputlimit is respected.
1756 mapArgs["-mempooltxinputlimit"] = "1";
1757
1758 // Add keys manually
1759 BOOST_CHECK_NO_THROW(retValue = CallRPC("getnewaddress"));
1760 MergeToAddressRecipient taddr1(retValue.get_str(), "");
80ed13d5
JG
1761 auto pa = pwalletMain->GenerateNewZKey();
1762 MergeToAddressRecipient zaddr1(EncodePaymentAddress(pa), "DEADBEEF");
6e9c7629
JG
1763
1764 // Supply 2 inputs when mempool limit is 1
1765 {
1766 std::vector<MergeToAddressInputUTXO> inputs = {
1767 MergeToAddressInputUTXO{COutPoint{uint256(),0},0},
1768 MergeToAddressInputUTXO{COutPoint{uint256(),0},0}
1769 };
1770 std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_mergetoaddress(mtx, inputs, {}, zaddr1) );
1771 operation->main();
1772 BOOST_CHECK(operation->isFailed());
1773 std::string msg = operation->getErrorMessage();
1774 BOOST_CHECK( msg.find("Number of transparent inputs 2 is greater than mempooltxinputlimit of 1") != string::npos);
1775 }
1776
1777 // Insufficient funds
1778 {
1779 std::vector<MergeToAddressInputUTXO> inputs = { MergeToAddressInputUTXO{COutPoint{uint256(),0},0} };
1780 std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_mergetoaddress(mtx, inputs, {}, zaddr1) );
1781 operation->main();
1782 BOOST_CHECK(operation->isFailed());
1783 std::string msg = operation->getErrorMessage();
1784 BOOST_CHECK( msg.find("Insufficient funds, have 0.00 and miners fee is 0.0001") != string::npos);
1785 }
1786
1787 // get_memo_from_hex_string())
1788 {
1789 std::vector<MergeToAddressInputUTXO> inputs = { MergeToAddressInputUTXO{COutPoint{uint256(),0},100000} };
1790 std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_mergetoaddress(mtx, inputs, {}, zaddr1) );
1791 std::shared_ptr<AsyncRPCOperation_mergetoaddress> ptr = std::dynamic_pointer_cast<AsyncRPCOperation_mergetoaddress> (operation);
1792 TEST_FRIEND_AsyncRPCOperation_mergetoaddress proxy(ptr);
1793
1794 std::string memo = "DEADBEEF";
a6bbb26e 1795 std::array<unsigned char, ZC_MEMO_SIZE> array = proxy.get_memo_from_hex_string(memo);
6e9c7629
JG
1796 BOOST_CHECK_EQUAL(array[0], 0xDE);
1797 BOOST_CHECK_EQUAL(array[1], 0xAD);
1798 BOOST_CHECK_EQUAL(array[2], 0xBE);
1799 BOOST_CHECK_EQUAL(array[3], 0xEF);
1800 for (int i=4; i<ZC_MEMO_SIZE; i++) {
1801 BOOST_CHECK_EQUAL(array[i], 0x00); // zero padding
1802 }
1803
1804 // memo is longer than allowed
1805 std::vector<char> v (2 * (ZC_MEMO_SIZE+1));
1806 std::fill(v.begin(),v.end(), 'A');
1807 std::string bigmemo(v.begin(), v.end());
1808
1809 try {
1810 proxy.get_memo_from_hex_string(bigmemo);
1811 BOOST_FAIL("Should have caused an error");
1812 } catch (const UniValue& objError) {
1813 BOOST_CHECK( find_error(objError, "too big"));
1814 }
1815
1816 // invalid hexadecimal string
1817 std::fill(v.begin(),v.end(), '@'); // not a hex character
1818 std::string badmemo(v.begin(), v.end());
1819
1820 try {
1821 proxy.get_memo_from_hex_string(badmemo);
1822 BOOST_FAIL("Should have caused an error");
1823 } catch (const UniValue& objError) {
1824 BOOST_CHECK( find_error(objError, "hexadecimal format"));
1825 }
1826
1827 // odd length hexadecimal string
1828 std::fill(v.begin(),v.end(), 'A');
1829 v.resize(v.size() - 1);
1830 assert(v.size() %2 == 1); // odd length
1831 std::string oddmemo(v.begin(), v.end());
1832 try {
1833 proxy.get_memo_from_hex_string(oddmemo);
1834 BOOST_FAIL("Should have caused an error");
1835 } catch (const UniValue& objError) {
1836 BOOST_CHECK( find_error(objError, "hexadecimal format"));
1837 }
1838 }
1839
1840 // Test the perform_joinsplit methods.
1841 {
1842 // Dummy input so the operation object can be instantiated.
1843 std::vector<MergeToAddressInputUTXO> inputs = { MergeToAddressInputUTXO{COutPoint{uint256(),0},100000} };
1844 std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_mergetoaddress(mtx, inputs, {}, zaddr1) );
1845 std::shared_ptr<AsyncRPCOperation_mergetoaddress> ptr = std::dynamic_pointer_cast<AsyncRPCOperation_mergetoaddress> (operation);
1846 TEST_FRIEND_AsyncRPCOperation_mergetoaddress proxy(ptr);
1847
1848 // Enable test mode so tx is not sent and proofs are not generated
1849 static_cast<AsyncRPCOperation_sendmany *>(operation.get())->testmode = true;
1850
1851 MergeToAddressJSInfo info;
8ea8ef98 1852 std::vector<boost::optional < SproutWitness>> witnesses;
6e9c7629
JG
1853 uint256 anchor;
1854 try {
1855 proxy.perform_joinsplit(info, witnesses, anchor);
1856 BOOST_FAIL("Should have caused an error");
1857 } catch (const std::runtime_error & e) {
1858 BOOST_CHECK( string(e.what()).find("anchor is null")!= string::npos);
1859 }
1860
1861 try {
1862 std::vector<JSOutPoint> v;
1863 proxy.perform_joinsplit(info, v);
1864 BOOST_FAIL("Should have caused an error");
1865 } catch (const std::runtime_error & e) {
1866 BOOST_CHECK( string(e.what()).find("anchor is null")!= string::npos);
1867 }
1868
b230fe68 1869 info.notes.push_back(SproutNote());
6e9c7629
JG
1870 try {
1871 proxy.perform_joinsplit(info);
1872 BOOST_FAIL("Should have caused an error");
1873 } catch (const std::runtime_error & e) {
1874 BOOST_CHECK( string(e.what()).find("number of notes")!= string::npos);
1875 }
1876
1877 info.notes.clear();
1878 info.vjsin.push_back(JSInput());
1879 info.vjsin.push_back(JSInput());
1880 info.vjsin.push_back(JSInput());
1881 try {
1882 proxy.perform_joinsplit(info);
1883 BOOST_FAIL("Should have caused an error");
1884 } catch (const std::runtime_error & e) {
1885 BOOST_CHECK( string(e.what()).find("unsupported joinsplit input")!= string::npos);
1886 }
1887
1888 info.vjsin.clear();
1889 try {
1890 proxy.perform_joinsplit(info);
1891 BOOST_FAIL("Should have caused an error");
1892 } catch (const std::runtime_error & e) {
1893 BOOST_CHECK( string(e.what()).find("error verifying joinsplit")!= string::npos);
1894 }
1895 }
1896
1897 // Raw joinsplit is a zaddr->zaddr
1898 {
1899 std::string raw = "020000000000000000000100000000000000001027000000000000183a0d4c46c369078705e39bcfebee59a978dbd210ce8de3efc9555a03fbabfd3cea16693d730c63850d7e48ccde79854c19adcb7e9dcd7b7d18805ee09083f6b16e1860729d2d4a90e2f2acd009cf78b5eb0f4a6ee4bdb64b1262d7ce9eb910c460b02022991e968d0c50ee44908e4ccccbc591d0053bcca154dd6d6fc400a29fa686af4682339832ccea362a62aeb9df0d5aa74f86a1e75ac0f48a8ccc41e0a940643c6c33e1d09223b0a46eaf47a1bb4407cfc12b1dcf83a29c0cef51e45c7876ca5b9e5bae86d92976eb3ef68f29cd29386a8be8451b50f82bf9da10c04651868655194da8f6ed3d241bb5b5ff93a3e2bbe44644544d88bcde5cc35978032ee92699c7a61fcbb395e7583f47e698c4d53ede54f956629400bf510fb5e22d03158cc10bdcaaf29e418ef18eb6480dd9c8b9e2a377809f9f32a556ef872febd0021d4ad013aa9f0b7255e98e408d302abefd33a71180b720271835b487ab309e160b06dfe51932120fb84a7ede16b20c53599a11071592109e10260f265ee60d48c62bfe24074020e9b586ce9e9356e68f2ad1a9538258234afe4b83a209f178f45202270eaeaeecaf2ce3100b2c5a714f75f35777a9ebff5ebf47059d2bbf6f3726190216468f2b152673b766225b093f3a2f827c86d6b48b42117fec1d0ac38dd7af700308dcfb02eba821612b16a2c164c47715b9b0c93900893b1aba2ea03765c94d87022db5be06ab338d1912e0936dfe87586d0a8ee49144a6cd2e306abdcb652faa3e0222739deb23154d778b50de75069a4a2cce1208cd1ced3cb4744c9888ce1c2fcd2e66dc31e62d3aa9e423d7275882525e9981f92e84ac85975b8660739407efbe1e34c2249420fde7e17db3096d5b22e83d051d01f0e6e7690dca7d168db338aadf0897fedac10de310db2b1bff762d322935dddbb60c2efb8b15d231fa17b84630371cb275c209f0c4c7d0c68b150ea5cd514122215e3f7fcfb351d69514788d67c2f3c8922581946e3a04bdf1f07f15696ca76eb95b10698bf1188fd882945c57657515889d042a6fc45d38cbc943540c4f0f6d1c45a1574c81f3e42d1eb8702328b729909adee8a5cfed7c79d54627d1fd389af941d878376f7927b9830ca659bf9ab18c5ca5192d52d02723008728d03701b8ab3e1c4a3109409ec0b13df334c7deec3523eeef4c97b5603e643de3a647b873f4c1b47fbfc6586ba66724f112e51fc93839648005043620aa3ce458e246d77977b19c53d98e3e812de006afc1a79744df236582943631d04cc02941ac4be500e4ed9fb9e3e7cc187b1c4050fad1d9d09d5fd70d5d01d615b439d8c0015d2eb10398bcdbf8c4b2bd559dbe4c288a186aed3f86f608da4d582e120c4a896e015e2241900d1daeccd05db968852677c71d752bec46de9962174b46f980e8cc603654daf8b98a3ee92dac066033954164a89568b70b1780c2ce2410b2f816dbeddb2cd463e0c8f21a52cf6427d9647a6fd4bafa8fb4cd4d47ac057b0160bee86c6b2fb8adce214c2bcdda277512200adf0eaa5d2114a2c077b009836a68ec254bfe56f51d147b9afe2ddd9cb917c0c2de19d81b7b8fd9f4574f51fa1207630dc13976f4d7587c962f761af267de71f3909a576e6bedaf6311633910d291ac292c467cc8331ef577aef7646a5d949322fa0367a49f20597a13def53136ee31610395e3e48d291fd8f58504374031fe9dcfba5e06086ebcf01a9106f6a4d6e16e19e4c5bb893f7da79419c94eca31a384be6fa1747284dee0fc3bbc8b1b860172c10b29c1594bb8c747d7fe05827358ff2160f49050001625ffe2e880bd7fc26cd0ffd89750745379a8e862816e08a5a2008043921ab6a4976064ac18f7ee37b6628bc0127d8d5ebd3548e41d8881a082d86f20b32e33094f15a0e6ea6074b08c6cd28142de94713451640a55985051f5577eb54572699d838cb34a79c8939e981c0c277d06a6e2ce69ccb74f8a691ff08f81d8b99e6a86223d29a2b7c8e7b041aba44ea678ae654277f7e91cbfa79158b989164a3d549d9f4feb0cc43169699c13e321fe3f4b94258c75d198ff9184269cd6986c55409e07528c93f64942c6c283ce3917b4bf4c3be2fe3173c8c38cccb35f1fbda0ca88b35a599c0678cb22aa8eabea8249dbd2e4f849fffe69803d299e435ebcd7df95854003d8eda17a74d98b4be0e62d45d7fe48c06a6f464a14f8e0570077cc631279092802a89823f031eef5e1028a6d6fdbd502869a731ee7d28b4d6c71b419462a30d31442d3ee444ffbcbd16d558c9000c97e949c2b1f9d6f6d8db7b9131ebd963620d3fc8595278d6f8fdf49084325373196d53e64142fa5a23eccd6ef908c4d80b8b3e6cc334b7f7012103a3682e4678e9b518163d262a39a2c1a69bf88514c52b7ccd7cc8dc80e71f7c2ec0701cff982573eb0c2c4daeb47fa0b586f4451c10d1da2e5d182b03dd067a5e971b3a6138ca6667aaf853d2ac03b80a1d5870905f2cfb6c78ec3c3719c02f973d638a0f973424a2b0f2b0023f136d60092fe15fba4bc180b9176bd0ff576e053f1af6939fe9ca256203ffaeb3e569f09774d2a6cbf91873e56651f4d6ff77e0b5374b0a1a201d7e523604e0247644544cc571d48c458a4f96f45580b";
1900 UniValue obj(UniValue::VOBJ);
1901 obj.push_back(Pair("rawtxn", raw));
1902
1903 // we have the spending key for the dummy recipient zaddr1
1904 std::vector<MergeToAddressInputUTXO> inputs = { MergeToAddressInputUTXO{COutPoint{uint256(),0},100000} };
1905 std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_mergetoaddress(mtx, inputs, {}, zaddr1) );
1906 std::shared_ptr<AsyncRPCOperation_mergetoaddress> ptr = std::dynamic_pointer_cast<AsyncRPCOperation_mergetoaddress> (operation);
1907 TEST_FRIEND_AsyncRPCOperation_mergetoaddress proxy(ptr);
1908
1909 // Enable test mode so tx is not sent
1910 static_cast<AsyncRPCOperation_sendmany *>(operation.get())->testmode = true;
1911
1912 // Pretend that the operation completed successfully
1913 proxy.set_state(OperationStatus::SUCCESS);
1914
1915 // Verify test mode is returning output (since no input taddrs, signed and unsigned are the same).
1916 BOOST_CHECK_NO_THROW( proxy.sign_send_raw_transaction(obj) );
1917 UniValue result = operation->getResult();
1918 BOOST_CHECK(!result.isNull());
1919 UniValue resultObj = result.get_obj();
1920 std::string hex = find_value(resultObj, "hex").get_str();
1921 BOOST_CHECK_EQUAL(hex, raw);
1922 }
1923}
1924
1925
b922924d 1926BOOST_AUTO_TEST_SUITE_END()
This page took 0.62307 seconds and 4 git commands to generate.