PIVX Core  5.6.99
P2P Digital Currency
sapling_rpc_wallet_tests.cpp
Go to the documentation of this file.
1 // Copyright (c) 2016-2020 The ZCash developers
2 // Copyright (c) 2020-2022 The PIVX Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #include "fs.h"
7 
10 
11 #include "rpc/server.h"
12 
13 #include "core_io.h"
14 #include "key_io.h"
15 #include "consensus/merkle.h"
16 #include "wallet/wallet.h"
17 #include "wallet/walletutil.h"
18 
19 #include "sapling/key_io_sapling.h"
20 #include "sapling/address.h"
22 
23 #include <unordered_set>
24 
25 #include <boost/test/unit_test.hpp>
26 
27 #include <univalue.h>
28 
29 
30 extern UniValue CallRPC(std::string args); // Implemented in rpc_tests.cpp
31 
32 namespace {
33 
35  class PushCurrentDirectory {
36  public:
37  explicit PushCurrentDirectory(const std::string &new_cwd)
38  : old_cwd(fs::current_path()) {
39  fs::current_path(new_cwd);
40  }
41 
42  ~PushCurrentDirectory() {
43  fs::current_path(old_cwd);
44  }
45  private:
46  fs::path old_cwd;
47  };
48 
49 }
50 
51 BOOST_FIXTURE_TEST_SUITE(sapling_rpc_wallet_tests, WalletTestingSetup)
52 
53 
57 BOOST_AUTO_TEST_CASE(rpc_wallet_sapling_validateaddress)
58 {
60  vpwallets.insert(vpwallets.begin(), &m_wallet);
61 
62  UniValue retValue;
63 
64  // Check number of args
65  BOOST_CHECK_THROW(CallRPC("validateaddress"), std::runtime_error);
66  BOOST_CHECK_THROW(CallRPC("validateaddress toomany args"), std::runtime_error);
67 
68  // Wallet should be empty:
69  std::set<libzcash::SaplingPaymentAddress> addrs;
70  m_wallet.GetSaplingPaymentAddresses(addrs);
71  BOOST_CHECK(addrs.size()==0);
72 
73  // This Sapling address is not valid, it belongs to another network
74  BOOST_CHECK_NO_THROW(retValue = CallRPC("validateaddress ptestsapling1nrn6exksuqtpld9gu6fwdz4hwg54h2x37gutdds89pfyg6mtjf63km45a8eare5qla45cj75vs8"));
75  UniValue resultObj = retValue.get_obj();
76  bool b = find_value(resultObj, "isvalid").get_bool();
77  BOOST_CHECK_EQUAL(b, false);
78 
79  // This Sapling address is valid, but the spending key is not in this wallet
80  BOOST_CHECK_NO_THROW(retValue = CallRPC("validateaddress ps1u87kylcmn28yclnx2uy0psnvuhs2xn608ukm6n2nshrpg2nzyu3n62ls8j77m9cgp40dx40evej"));
81  resultObj = retValue.get_obj();
82  b = find_value(resultObj, "isvalid").get_bool();
83  BOOST_CHECK_EQUAL(b, true);
84  b = find_value(resultObj, "ismine").get_bool();
85  BOOST_CHECK_EQUAL(b, false);
86  BOOST_CHECK_EQUAL(find_value(resultObj, "diversifier").get_str(), "e1fd627f1b9a8e4c7e6657");
87  BOOST_CHECK_EQUAL(find_value(resultObj, "diversifiedtransmissionkey").get_str(), "d35e0d0897edbd3cf02b3d2327622a14c685534dbd2d3f4f4fa3e0e56cc2f008");
88 
89  vpwallets.erase(vpwallets.begin());
90 }
91 
92 BOOST_AUTO_TEST_CASE(rpc_wallet_getbalance)
93 {
94  {
95  LOCK(m_wallet.cs_wallet);
96  m_wallet.SetMinVersion(FEATURE_SAPLING);
97  m_wallet.SetupSPKM(false);
98  }
99  vpwallets.insert(vpwallets.begin(), &m_wallet);
100 
101  BOOST_CHECK_THROW(CallRPC("getshieldbalance too many args"), std::runtime_error);
102  BOOST_CHECK_THROW(CallRPC("getshieldbalance invalidaddress"), std::runtime_error);
103  BOOST_CHECK_THROW(CallRPC("getshieldbalance tmC6YZnCUhm19dEXxh3Jb7srdBJxDawaCab"), std::runtime_error);
104  BOOST_CHECK_NO_THROW(CallRPC("getshieldbalance ps1u87kylcmn28yclnx2uy0psnvuhs2xn608ukm6n2nshrpg2nzyu3n62ls8j77m9cgp40dx40evej"));
105  BOOST_CHECK_THROW(CallRPC("getshieldbalance ps1u87kylcmn28yclnx2uy0psnvuhs2xn608ukm6n2nshrpg2nzyu3n62ls8j77m9cgp40dx40evej -1"), std::runtime_error);
106  BOOST_CHECK_NO_THROW(CallRPC("getshieldbalance ps1u87kylcmn28yclnx2uy0psnvuhs2xn608ukm6n2nshrpg2nzyu3n62ls8j77m9cgp40dx40evej 0"));
107  BOOST_CHECK_THROW(CallRPC("getshieldbalance tnRZ8bPq2pff3xBWhTJhNkVUkm2uhzksDeW5PvEa7aFKGT9Qi3YgTALZfjaY4jU3HLVKBtHdSXxoPoLA3naMPcHBcY88FcF 1"), std::runtime_error);
108  BOOST_CHECK_NO_THROW(CallRPC("getshieldbalance *"));
109  BOOST_CHECK_NO_THROW(CallRPC("getshieldbalance * 6"));
110  BOOST_CHECK_THROW(CallRPC("getshieldbalance * -1"), std::runtime_error);
111 
112  BOOST_CHECK_THROW(CallRPC("listreceivedbyshieldaddress too many args"), std::runtime_error);
113  // negative minconf not allowed
114  BOOST_CHECK_THROW(CallRPC("listreceivedbyshieldaddress DMKU6mc52un1MThGCsnNwAtEvncaTdAuaZ -1"), std::runtime_error);
115  // invalid zaddr, taddr not allowed
116  BOOST_CHECK_THROW(CallRPC("listreceivedbyshieldaddress DMKU6mc52un1MThGCsnNwAtEvncaTdAuaZ 0"), std::runtime_error);
117  // don't have the spending key
118  BOOST_CHECK_THROW(CallRPC("listreceivedbyshieldaddress ps1u87kylcmn28yclnx2uy0psnvuhs2xn608ukm6n2nshrpg2nzyu3n62ls8j77m9cgp40dx40evej 1"), std::runtime_error);
119 
120  vpwallets.erase(vpwallets.begin());
121 }
122 
123 BOOST_AUTO_TEST_CASE(rpc_wallet_sapling_importkey_paymentaddress)
124 {
125  {
126  LOCK(m_wallet.cs_wallet);
127  m_wallet.SetMinVersion(FEATURE_SAPLING);
128  m_wallet.SetupSPKM(false);
129  }
130  vpwallets.insert(vpwallets.begin(), &m_wallet);
131 
132  auto testAddress = [](const std::string& key) {
133  UniValue ret;
134  BOOST_CHECK_NO_THROW(ret = CallRPC("importsaplingkey " + key));
135  auto defaultAddr = find_value(ret, "address").get_str();
136  BOOST_CHECK_NO_THROW(ret = CallRPC("validateaddress " + defaultAddr));
137  ret = ret.get_obj();
138  BOOST_CHECK_EQUAL(true, find_value(ret, "isvalid").get_bool());
139  BOOST_CHECK_EQUAL(true, find_value(ret, "ismine").get_bool());
140  };
141 
142  testAddress("p-secret-spending-key-main1qv09u0wlqqqqpqp75kpmat6l3ce29k"
143  "g9half9epsm80wya5n92j4d8mtmesrukzxlsmm2f74v3nvvx2shxy4z5v5x39p"
144  "eelsy5y2uxmvadaku8crd20q6vt8cvd68wp08cjyec6cku0dcf5lc9c2kykg5c"
145  "8uqmqlx8ccxpsw7ae243quhwr0zyekrrc520gs9z0j8pm954c3cev2yvp29vrc"
146  "0zweu7stxkwhp593p6drheps9uhz9pvkrfgvpxzte8d60uzw0qxadnsc77tcd");
147 
148  vpwallets.erase(vpwallets.begin());
149 }
150 
151 /*
152  * This test covers RPC commands listsaplingaddresses, importsaplingkey, exportsaplingkey
153  */
154 BOOST_AUTO_TEST_CASE(rpc_wallet_sapling_importexport)
155 {
156  {
157  LOCK(m_wallet.cs_wallet);
158  m_wallet.SetMinVersion(FEATURE_SAPLING);
159  m_wallet.SetupSPKM(false);
160  }
161  vpwallets.insert(vpwallets.begin(), &m_wallet);
162 
163  UniValue retValue;
164  int n1 = 1000; // number of times to import/export
165  int n2 = 1000; // number of addresses to create and list
166 
167  // error if no args
168  BOOST_CHECK_THROW(CallRPC("importsaplingkey"), std::runtime_error);
169  BOOST_CHECK_THROW(CallRPC("exportsaplingkey"), std::runtime_error);
170 
171  // error if too many args
172  BOOST_CHECK_THROW(CallRPC("importsaplingkey way too many args"), std::runtime_error);
173  BOOST_CHECK_THROW(CallRPC("exportsaplingkey toomany args"), std::runtime_error);
174 
175  // error if invalid args
177  std::string prefix = std::string("importsaplingkey ") + KeyIO::EncodeSpendingKey(m) + " yes ";
178  BOOST_CHECK_THROW(CallRPC(prefix + "-1"), std::runtime_error);
179  BOOST_CHECK_THROW(CallRPC(prefix + "2147483647"), std::runtime_error); // allowed, but > height of active chain tip
180  BOOST_CHECK_THROW(CallRPC(prefix + "2147483648"), std::runtime_error); // not allowed, > int32 used for nHeight
181  BOOST_CHECK_THROW(CallRPC(prefix + "100badchars"), std::runtime_error);
182 
183  // wallet should currently be empty
184  std::set<libzcash::SaplingPaymentAddress> saplingAddrs;
185  m_wallet.GetSaplingPaymentAddresses(saplingAddrs);
186  BOOST_CHECK(saplingAddrs.empty());
187 
188  // verify import and export key
189  for (int i = 0; i < n1; i++) {
190  // create a random Sapling key locally
191  auto testSaplingSpendingKey = m.Derive(i);
192  auto testSaplingPaymentAddress = testSaplingSpendingKey.DefaultAddress();
193  std::string testSaplingAddr = KeyIO::EncodePaymentAddress(testSaplingPaymentAddress);
194  std::string testSaplingKey = KeyIO::EncodeSpendingKey(testSaplingSpendingKey);
195  BOOST_CHECK_NO_THROW(CallRPC(std::string("importsaplingkey ") + testSaplingKey));
196  BOOST_CHECK_NO_THROW(retValue = CallRPC(std::string("exportsaplingkey ") + testSaplingAddr));
197  BOOST_CHECK_EQUAL(retValue.get_str(), testSaplingKey);
198  }
199 
200  // Verify we can list the keys imported
201  BOOST_CHECK_NO_THROW(retValue = CallRPC("listshieldaddresses"));
202  UniValue arr = retValue.get_array();
203  BOOST_CHECK((int) arr.size() == n1);
204 
205  // Put addresses into a set
206  std::unordered_set<std::string> myaddrs;
207  for (const UniValue& element : arr.getValues()) {
208  myaddrs.insert(element.get_str());
209  }
210 
211  // Make new addresses for the set
212  for (int i=0; i<n2; i++) {
213  myaddrs.insert(KeyIO::EncodePaymentAddress(m_wallet.GenerateNewSaplingZKey()));
214  }
215 
216  // Verify number of addresses stored in wallet is n1+n2
217  int numAddrs = myaddrs.size();
218  BOOST_CHECK(numAddrs == n1 + n2);
219  m_wallet.GetSaplingPaymentAddresses(saplingAddrs);
220  BOOST_CHECK((int) saplingAddrs.size() == numAddrs);
221 
222  // Ask wallet to list addresses
223  BOOST_CHECK_NO_THROW(retValue = CallRPC("listshieldaddresses"));
224  arr = retValue.get_array();
225  BOOST_CHECK((int) arr.size() == numAddrs);
226 
227  // Create a set from them
228  std::unordered_set<std::string> listaddrs;
229  for (const UniValue& element : arr.getValues()) {
230  listaddrs.insert(element.get_str());
231  }
232 
233  // Verify the two sets of addresses are the same
234  BOOST_CHECK((int) listaddrs.size() == numAddrs);
235  BOOST_CHECK(myaddrs == listaddrs);
236 
237  vpwallets.erase(vpwallets.begin());
238 }
239 
240 // Check if address is of given type and spendable from our wallet.
241 void CheckHaveAddr(CWallet& pwallet, const libzcash::PaymentAddress& addr)
242 {
243 
245  auto addr_of_type = boost::get<libzcash::SaplingPaymentAddress>(&addr);
246  BOOST_ASSERT(addr_of_type != nullptr);
247  BOOST_CHECK(pwallet.HaveSpendingKeyForPaymentAddress(*addr_of_type));
248 }
249 
250 BOOST_AUTO_TEST_CASE(rpc_wallet_getnewshieldaddress)
251 {
252  {
253  LOCK(m_wallet.cs_wallet);
254  m_wallet.SetMinVersion(FEATURE_SAPLING);
255  m_wallet.SetupSPKM(false);
256  }
257  vpwallets.insert(vpwallets.begin(), &m_wallet);
258 
259  // No parameter defaults to sapling address
260  UniValue addr = CallRPC("getnewshieldaddress");
262  // Too many arguments will throw with the help
263  BOOST_CHECK_THROW(CallRPC("getnewshieldaddress many args"), std::runtime_error);
264 
265  vpwallets.erase(vpwallets.begin());
266 }
267 
268 BOOST_AUTO_TEST_CASE(rpc_shieldsendmany_parameters)
269 {
270  {
271  LOCK(m_wallet.cs_wallet);
272  m_wallet.SetMinVersion(FEATURE_SAPLING);
273  m_wallet.SetupSPKM(false);
274  }
275  vpwallets.insert(vpwallets.begin(), &m_wallet);
276 
277  BOOST_CHECK_THROW(CallRPC("shieldsendmany"), std::runtime_error);
278  BOOST_CHECK_THROW(CallRPC("shieldsendmany toofewargs"), std::runtime_error);
279  BOOST_CHECK_THROW(CallRPC("shieldsendmany just too many args here"), std::runtime_error);
280 
281  // bad from address
282  BOOST_CHECK_THROW(CallRPC("shieldsendmany "
283  "INVALIDDMKU6mc52un1MThGCsnNwAtEvncaTdAuaZ []"), std::runtime_error);
284  // empty amounts
285  BOOST_CHECK_THROW(CallRPC("shieldsendmany "
286  "DMKU6mc52un1MThGCsnNwAtEvncaTdAuaZ []"), std::runtime_error);
287 
288  // don't have the spending key for this address
289  BOOST_CHECK_THROW(CallRPC("shieldsendmany "
290  "ps1u87kylcmn28yclnx2uy0psnvuhs2xn608ukm6n2nshrpg2nzyu3n62ls8j77m9cgp40dx40evej []"), std::runtime_error);
291 
292  // duplicate address
293  BOOST_CHECK_THROW(CallRPC("shieldsendmany "
294  "DDTBEPEaub5sk31mUifiv5nHGXtHGnuAJc "
295  "[{\"address\":\"DMKU6mc52un1MThGCsnNwAtEvncaTdAuaZ\", \"amount\":50.0},"
296  " {\"address\":\"DMKU6mc52un1MThGCsnNwAtEvncaTdAuaZ\", \"amount\":12.0} ]"
297  ), std::runtime_error);
298 
299  // invalid fee amount, cannot be negative
300  BOOST_CHECK_THROW(CallRPC("shieldsendmany "
301  "DDTBEPEaub5sk31mUifiv5nHGXtHGnuAJc "
302  "[{\"address\":\"DMKU6mc52un1MThGCsnNwAtEvncaTdAuaZ\", \"amount\":50.0}] "
303  "1 -0.0001"
304  ), std::runtime_error);
305 
306  // invalid fee amount, bigger than MAX_MONEY
307  BOOST_CHECK_THROW(CallRPC("shieldsendmany "
308  "DDTBEPEaub5sk31mUifiv5nHGXtHGnuAJc "
309  "[{\"address\":\"DMKU6mc52un1MThGCsnNwAtEvncaTdAuaZ\", \"amount\":50.0}] "
310  "1 21000001"
311  ), std::runtime_error);
312 
313  // fee amount is bigger than sum of outputs
314  BOOST_CHECK_THROW(CallRPC("shieldsendmany "
315  "DDTBEPEaub5sk31mUifiv5nHGXtHGnuAJc "
316  "[{\"address\":\"DMKU6mc52un1MThGCsnNwAtEvncaTdAuaZ\", \"amount\":50.0}] "
317  "1 50.00000001"
318  ), std::runtime_error);
319 
320  // memo bigger than allowed length of ZC_MEMO_SIZE
321  std::vector<char> v (2 * (ZC_MEMO_SIZE+1)); // x2 for hexadecimal string format
322  std::fill(v.begin(),v.end(), 'A');
323  std::string badmemo(v.begin(), v.end());
324  auto pa = m_wallet.GenerateNewSaplingZKey();
325  std::string zaddr1 = KeyIO::EncodePaymentAddress(pa);
326  BOOST_CHECK_THROW(CallRPC(std::string("shieldsendmany DMKU6mc52un1MThGCsnNwAtEvncaTdAuaZ ")
327  + "[{\"address\":\"" + zaddr1 + "\", \"amount\":123.456}]"), std::runtime_error);
328 
329  vpwallets.erase(vpwallets.begin());
330 }
331 
332 // TODO: test private methods
333 BOOST_AUTO_TEST_CASE(saplingOperationTests)
334 {
335  {
336  LOCK2(cs_main, m_wallet.cs_wallet);
337  m_wallet.SetupSPKM(false);
338  }
339  auto consensusParams = Params().GetConsensus();
340  vpwallets.insert(vpwallets.begin(), &m_wallet);
341 
342  UniValue retValue;
343 
344  // add keys manually
345  BOOST_CHECK_NO_THROW(retValue = CallRPC("getnewaddress"));
346  const std::string& taddrStr = retValue.get_str();
347  const CTxDestination& taddr1 = DecodeDestination(taddrStr);
348  const auto& zaddr1 = m_wallet.GenerateNewSaplingZKey();
349  std::string ret;
350 
351  // there are no utxos to spend
352  {
353  std::vector<SendManyRecipient> recipients = { SendManyRecipient(zaddr1, COIN, "DEADBEEF", false) };
354  SaplingOperation operation(consensusParams, &m_wallet);
355  operation.setFromAddress(taddr1);
356  auto res = operation.setRecipients(recipients)->buildAndSend(ret);
357  BOOST_CHECK(!res);
358  BOOST_CHECK(res.getError().find("Insufficient funds, no available UTXO to spend") != std::string::npos);
359  }
360 
361  // minconf cannot be zero when sending from zaddr
362  {
363  std::vector<SendManyRecipient> recipients = { SendManyRecipient(zaddr1, COIN, "DEADBEEF", false) };
364  SaplingOperation operation(consensusParams, &m_wallet);
365  operation.setFromAddress(zaddr1);
366  auto res = operation.setRecipients(recipients)->setMinDepth(0)->buildAndSend(ret);
367  BOOST_CHECK(!res);
368  BOOST_CHECK(res.getError().find("Minconf cannot be zero when sending from shielded address") != std::string::npos);
369  }
370 
371  // there are no unspent notes to spend
372  {
373  std::vector<SendManyRecipient> recipients = { SendManyRecipient(taddr1, COIN, false) };
374  SaplingOperation operation(consensusParams, &m_wallet);
375  operation.setFromAddress(zaddr1);
376  auto res = operation.setRecipients(recipients)->buildAndSend(ret);
377  BOOST_CHECK(!res);
378  BOOST_CHECK(res.getError().find("Insufficient funds, no available notes to spend") != std::string::npos);
379  }
380 
381  // GetMemoFromString
382  {
383  std::string memoStr = "Sapling memo!";
384  std::array<unsigned char, ZC_MEMO_SIZE> memo;
385 
386  BOOST_CHECK(GetMemoFromString(memoStr, memo));
387  BOOST_CHECK_EQUAL(memo[0], 0x53); // S
388  BOOST_CHECK_EQUAL(memo[1], 0x61); // a
389  BOOST_CHECK_EQUAL(memo[2], 0x70); // p
390  BOOST_CHECK_EQUAL(memo[3], 0x6C); // l
391  BOOST_CHECK_EQUAL(memo[4], 0x69); // i
392  BOOST_CHECK_EQUAL(memo[5], 0x6E); // n
393  BOOST_CHECK_EQUAL(memo[6], 0x67); // g
394  BOOST_CHECK_EQUAL(memo[12], 0x21); // !
395  for (int i = 13; i < ZC_MEMO_SIZE; i++) {
396  BOOST_CHECK_EQUAL(memo[i], 0x00); // zero padding
397  }
398 
399  // memo is longer than allowed
400  std::vector<char> v (2 * (ZC_MEMO_SIZE+1));
401  std::fill(v.begin(),v.end(), 'A');
402  std::string bigmemo(v.begin(), v.end());
403 
404  OperationResult res = GetMemoFromString(bigmemo, memo);
405  BOOST_CHECK(!res);
406  const std::string& errStr = res.getError();
407  BOOST_CHECK(errStr.find("too big") != std::string::npos);
408  }
409 
410  vpwallets.erase(vpwallets.begin());
411 }
412 
413 
414 BOOST_AUTO_TEST_CASE(rpc_shieldsendmany_taddr_to_sapling)
415 {
416  {
417  LOCK2(cs_main, m_wallet.cs_wallet);
418  m_wallet.SetupSPKM(false);
419  }
420  vpwallets.insert(vpwallets.begin(), &m_wallet);
421 
422  UniValue retValue;
423 
424  // add keys manually
425  auto res = m_wallet.getNewAddress("");
426  BOOST_CHECK(res);
427  CTxDestination taddr = *res.getObjResult();
428  std::string taddr1 = EncodeDestination(taddr);
429  auto zaddr1 = m_wallet.GenerateNewSaplingZKey();
430 
431  auto consensusParams = Params().GetConsensus();
432 
433  // Add a fake transaction to the wallet
435  mtx.vout.emplace_back(5 * COIN, GetScriptForDestination(taddr));
436  // Add to wallet and get the updated wtx
437  CWalletTx wtxIn(&m_wallet, MakeTransactionRef(mtx));
438  m_wallet.LoadToWallet(wtxIn);
439  CWalletTx& wtx = m_wallet.mapWallet.at(mtx.GetHash());
440 
441  // Fake-mine the transaction
443  CBlock block;
445  block.vtx.emplace_back(wtx.tx);
446  block.hashMerkleRoot = BlockMerkleRoot(block);
447  auto blockHash = block.GetHash();
448  CBlockIndex fakeIndex {block};
449  fakeIndex.nHeight = 1;
450  BlockMap::iterator mi = mapBlockIndex.emplace(blockHash, &fakeIndex).first;
451  fakeIndex.phashBlock = &((*mi).first);
452  chainActive.SetTip(&fakeIndex);
453  BOOST_CHECK(chainActive.Contains(&fakeIndex));
455  m_wallet.BlockConnected(std::make_shared<CBlock>(block), mi->second);
456  BOOST_CHECK_MESSAGE(m_wallet.GetAvailableBalance() > 0, "tx not confirmed");
457 
458  std::vector<SendManyRecipient> recipients = { SendManyRecipient(zaddr1, 1 * COIN, "ABCD", false) };
459  SaplingOperation operation(consensusParams, &m_wallet);
460  operation.setFromAddress(taddr);
461  BOOST_CHECK(operation.setRecipients(recipients)
462  ->setMinDepth(0)
463  ->build());
464 
465  // try from auto-selected transparent address
466  std::vector<SendManyRecipient> recipients2 = { SendManyRecipient(zaddr1, 1 * COIN, "ABCD", false) };
467  SaplingOperation operation2(consensusParams, &m_wallet);
468  BOOST_CHECK(operation2.setSelectTransparentCoins(true)
469  ->setRecipients(recipients2)
470  ->setMinDepth(0)
471  ->build());
472 
473  // Get the transaction
474  // Test mode does not send the transaction to the network.
475  auto hexTx = EncodeHexTx(operation.getFinalTx());
476  CDataStream ss(ParseHex(hexTx), SER_NETWORK, PROTOCOL_VERSION);
477  CTransaction tx(deserialize, ss);
478  BOOST_ASSERT(!tx.sapData->vShieldedOutput.empty());
479 
480  // We shouldn't be able to decrypt with the empty ovk
482  tx.sapData->vShieldedOutput[0].outCiphertext,
483  uint256(),
484  tx.sapData->vShieldedOutput[0].cv,
485  tx.sapData->vShieldedOutput[0].cmu,
486  tx.sapData->vShieldedOutput[0].ephemeralKey));
487 
489  tx.sapData->vShieldedOutput[0].outCiphertext,
490  m_wallet.GetSaplingScriptPubKeyMan()->getCommonOVK(),
491  tx.sapData->vShieldedOutput[0].cv,
492  tx.sapData->vShieldedOutput[0].cmu,
493  tx.sapData->vShieldedOutput[0].ephemeralKey));
494 
495  // Tear down
496  chainActive.SetTip(nullptr);
497  mapBlockIndex.erase(blockHash);
498  vpwallets.erase(vpwallets.begin());
499 }
500 
501 BOOST_AUTO_TEST_CASE(rpc_listshieldunspent_parameters)
502 {
503  {
504  LOCK(m_wallet.cs_wallet);
505  m_wallet.SetupSPKM(false);
506  }
507  vpwallets.insert(vpwallets.begin(), &m_wallet);
508 
509  UniValue retValue;
510 
511  // too many args
512  BOOST_CHECK_THROW(CallRPC("listshieldunspent 1 2 3 4 5"), std::runtime_error);
513 
514  // minconf must be >= 0
515  BOOST_CHECK_THROW(CallRPC("listshieldunspent -1"), std::runtime_error);
516 
517  // maxconf must be > minconf
518  BOOST_CHECK_THROW(CallRPC("listshieldunspent 2 1"), std::runtime_error);
519 
520  // maxconf must not be out of range
521  BOOST_CHECK_THROW(CallRPC("listshieldunspent 1 9999999999"), std::runtime_error);
522 
523  // must be an array of addresses
524  BOOST_CHECK_THROW(CallRPC("listshieldunspent 1 999 false ps1u87kylcmn28yclnx2uy0psnvuhs2xn608ukm6n2nshrpg2nzyu3n62ls8j77m9cgp40dx40evej"), std::runtime_error);
525 
526  // address must be string
527  BOOST_CHECK_THROW(CallRPC("listshieldunspent 1 999 false [123456]"), std::runtime_error);
528 
529  // no spending key
530  BOOST_CHECK_THROW(CallRPC("listshieldunspent 1 999 false [\"ps1u87kylcmn28yclnx2uy0psnvuhs2xn608ukm6n2nshrpg2nzyu3n62ls8j77m9cgp40dx40evej\"]"), std::runtime_error);
531 
532  // allow watch only
533  BOOST_CHECK_NO_THROW(CallRPC("listshieldunspent 1 999 true [\"ps1u87kylcmn28yclnx2uy0psnvuhs2xn608ukm6n2nshrpg2nzyu3n62ls8j77m9cgp40dx40evej\"]"));
534 
535  // wrong network, testnet/regtest instead of mainnet
536  BOOST_CHECK_THROW(CallRPC("listshieldunspent 1 999 true [\"ptestsapling1wpurflqllgkcs48m46yu9ktlfe3ahndely20dpaanqq3lw9l5xw7yfehst68yclvlpz7x8cltxe\"]"), std::runtime_error);
537 
538  // create shielded address so we have the spending key
539  BOOST_CHECK_NO_THROW(retValue = CallRPC("getnewshieldaddress"));
540  std::string myzaddr = retValue.get_str();
541 
542  // return empty array for this address
543  BOOST_CHECK_NO_THROW(retValue = CallRPC("listshieldunspent 1 999 false [\"" + myzaddr + "\"]"));
544  UniValue arr = retValue.get_array();
545  BOOST_CHECK_EQUAL(0, arr.size());
546 
547  // duplicate address error
548  BOOST_CHECK_THROW(CallRPC("listshieldunspent 1 999 false [\"" + myzaddr + "\", \"" + myzaddr + "\"]"), std::runtime_error);
549 
550  vpwallets.erase(vpwallets.begin());
551 }
552 
bool IsValidPaymentAddress(const libzcash::PaymentAddress &zaddr)
Check whether a PaymentAddress is not an InvalidEncoding.
Definition: address.cpp:92
void SelectParams(const std::string &network)
Sets the params returned by Params() to those for the given chain name.
const CChainParams & Params()
Return the currently selected parameters.
static const std::string MAIN
Chain name strings.
uint256 hashPrevBlock
Definition: block.h:28
uint256 hashMerkleRoot
Definition: block.h:29
uint256 GetHash() const
Definition: block.cpp:15
Definition: block.h:80
std::vector< CTransactionRef > vtx
Definition: block.h:83
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: chain.h:139
uint256 GetBlockHash() const
Definition: chain.h:215
CBlockIndex * Tip(bool fProofOfStake=false) const
Returns the index entry for the tip of this chain, or nullptr if none.
Definition: chain.h:405
int Height() const
Return the maximal height in the chain.
Definition: chain.h:450
void SetTip(CBlockIndex *pindex)
Set/initialize a chain with a given tip.
Definition: chain.cpp:14
bool Contains(const CBlockIndex *pindex) const
Efficiently check whether a block is present in this chain.
Definition: chain.h:435
const Consensus::Params & GetConsensus() const
Definition: chainparams.h:72
The basic transaction that is broadcasted on the network and contained in blocks.
Definition: transaction.h:244
Optional< SaplingTxData > sapData
Definition: transaction.h:275
A CWallet is an extension of a keystore, which also maintains a set of transactions and balances,...
Definition: wallet.h:577
bool HaveSpendingKeyForPaymentAddress(const libzcash::SaplingPaymentAddress &zaddr) const
Returns true if the wallet contains the spending key.
Definition: wallet.cpp:4738
A transaction with a bunch of additional info that only the owner cares about.
Definition: wallet.h:325
CTransactionRef tx
Definition: wallet.h:364
std::string getError() const
CTransaction getFinalTx()
void setFromAddress(const CTxDestination &)
SaplingOperation * setRecipients(std::vector< SendManyRecipient > &vec)
SaplingOperation * setMinDepth(int _mindepth)
OperationResult build()
OperationResult buildAndSend(std::string &retTxHash)
SaplingOperation * setSelectTransparentCoins(const bool select, const bool _fIncludeDelegated=false)
const std::string & get_str() const
const UniValue & get_obj() const
size_t size() const
Definition: univalue.h:68
const std::vector< UniValue > & getValues() const
const UniValue & get_array() const
bool get_bool() const
256-bit opaque blob.
Definition: uint256.h:138
std::string EncodeHexTx(const CTransaction &tx)
Definition: core_write.cpp:116
BOOST_AUTO_TEST_SUITE_END()
@ LOCK
Definition: lockunlock.h:16
uint256 BlockMerkleRoot(const CBlock &block, bool *mutated)
Definition: merkle.cpp:154
std::string EncodePaymentAddress(const libzcash::PaymentAddress &zaddr)
libzcash::PaymentAddress DecodePaymentAddress(const std::string &str)
std::string EncodeSpendingKey(const libzcash::SpendingKey &zkey)
std::string EncodeDestination(const CWDestination &address, const CChainParams::Base58Type addrType)
CWDestination DecodeDestination(const std::string &strAddress)
boost::variant< InvalidEncoding, SaplingPaymentAddress > PaymentAddress
Definition: address.h:127
Optional< SaplingOutPlaintext > AttemptSaplingOutDecryption(const SaplingOutCiphertext &ciphertext, const uint256 &ovk, const uint256 &cv, const uint256 &cm, const uint256 &epk)
RecursiveMutex cs_main
Global state.
Definition: validation.cpp:80
#define BOOST_CHECK_THROW(stmt, excMatch)
Definition: object.cpp:19
#define BOOST_FIXTURE_TEST_SUITE(a, b)
Definition: object.cpp:14
#define BOOST_CHECK_EQUAL(v1, v2)
Definition: object.cpp:18
#define BOOST_CHECK_NO_THROW(stmt)
Definition: object.cpp:28
#define BOOST_CHECK(expr)
Definition: object.cpp:17
const char * prefix
Definition: rest.cpp:564
#define ZC_MEMO_SIZE
Definition: sapling.h:24
OperationResult GetMemoFromString(const std::string &s, std::array< unsigned char, ZC_MEMO_SIZE > &memoRet)
UniValue CallRPC(std::string args)
Definition: rpc_tests.cpp:32
BOOST_AUTO_TEST_CASE(rpc_wallet_sapling_validateaddress)
This test covers RPC command validateaddress.
void CheckHaveAddr(CWallet &pwallet, const libzcash::PaymentAddress &addr)
@ SER_NETWORK
Definition: serialize.h:174
constexpr deserialize_type deserialize
Definition: serialize.h:57
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a PIVX scriptPubKey for the given CTxDestination.
Definition: standard.cpp:278
boost::variant< CNoDestination, CKeyID, CScriptID, CExchangeKeyID > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:72
A mutable version of CTransaction.
Definition: transaction.h:409
uint256 GetHash() const
Compute the hash of this CMutableTransaction.
Definition: transaction.cpp:96
std::vector< CTxOut > vout
Definition: transaction.h:411
#define LOCK2(cs1, cs2)
Definition: sync.h:221
const UniValue & find_value(const UniValue &obj, const std::string &name)
Definition: univalue.cpp:234
std::vector< unsigned char > ParseHex(const char *psz)
libzcash::SaplingExtendedSpendingKey GetTestMasterSaplingSpendingKey()
Definition: utiltest.cpp:16
BlockMap mapBlockIndex
Definition: validation.cpp:82
CChain chainActive
The currently-connected chain of blocks (protected by cs_main).
Definition: validation.cpp:84
std::vector< CWalletRef > vpwallets
Definition: wallet.cpp:33
@ FEATURE_SAPLING
Definition: wallet.h:118