]> Git Repo - VerusCoin.git/blob - src/zcbenchmarks.cpp
Fix stakeguard validation
[VerusCoin.git] / src / zcbenchmarks.cpp
1 #include <cstdio>
2 #include <future>
3 #include <map>
4 #include <thread>
5 #include <unistd.h>
6 #include <boost/filesystem.hpp>
7
8 #include "coins.h"
9 #include "util.h"
10 #include "init.h"
11 #include "primitives/transaction.h"
12 #include "base58.h"
13 #include "crypto/equihash.h"
14 #include "chain.h"
15 #include "chainparams.h"
16 #include "consensus/upgrades.h"
17 #include "consensus/validation.h"
18 #include "main.h"
19 #include "miner.h"
20 #include "pow.h"
21 #include "rpc/server.h"
22 #include "script/sign.h"
23 #include "sodium.h"
24 #include "streams.h"
25 #include "txdb.h"
26 #include "utiltest.h"
27 #include "wallet/wallet.h"
28
29 #include "zcbenchmarks.h"
30
31 #include "zcash/Zcash.h"
32 #include "zcash/IncrementalMerkleTree.hpp"
33 #include "zcash/Note.hpp"
34 #include "librustzcash.h"
35
36 using namespace libzcash;
37 // This method is based on Shutdown from init.cpp
38 void pre_wallet_load()
39 {
40     LogPrintf("%s: In progress...\n", __func__);
41     if (ShutdownRequested())
42         throw new std::runtime_error("The node is shutting down");
43
44     if (pwalletMain)
45         pwalletMain->Flush(false);
46 #ifdef ENABLE_MINING
47 #ifdef ENABLE_WALLET
48     GenerateBitcoins(false, NULL, 0);
49 #else
50     GenerateBitcoins(false, 0);
51 #endif
52 #endif
53     UnregisterNodeSignals(GetNodeSignals());
54     if (pwalletMain)
55         pwalletMain->Flush(true);
56
57     UnregisterValidationInterface(pwalletMain);
58     delete pwalletMain;
59     pwalletMain = NULL;
60     bitdb.Reset();
61     RegisterNodeSignals(GetNodeSignals());
62     LogPrintf("%s: done\n", __func__);
63 }
64
65 void post_wallet_load(){
66     RegisterValidationInterface(pwalletMain);
67 #ifdef ENABLE_MINING
68     // Generate coins in the background
69     if (pwalletMain || !GetArg("-mineraddress", "").empty())
70     {
71     #ifdef ENABLE_WALLET
72         GenerateBitcoins(GetBoolArg("-gen",false), pwalletMain, GetArg("-genproclimit", 0));
73     #else
74         GenerateBitcoins(GetBoolArg("-gen",false), GetArg("-genproclimit", 0));
75     #endif
76     }
77 #endif    
78 }
79
80
81 void timer_start(timeval &tv_start)
82 {
83     gettimeofday(&tv_start, 0);
84 }
85
86 double timer_stop(timeval &tv_start)
87 {
88     double elapsed;
89     struct timeval tv_end;
90     gettimeofday(&tv_end, 0);
91     elapsed = double(tv_end.tv_sec-tv_start.tv_sec) +
92         (tv_end.tv_usec-tv_start.tv_usec)/double(1000000);
93     return elapsed;
94 }
95
96 double benchmark_sleep()
97 {
98     struct timeval tv_start;
99     timer_start(tv_start);
100     sleep(1);
101     return timer_stop(tv_start);
102 }
103
104 double benchmark_parameter_loading()
105 {
106     // FIXME: this is duplicated with the actual loading code
107     boost::filesystem::path pk_path = ZC_GetParamsDir() / "sprout-proving.key";
108     boost::filesystem::path vk_path = ZC_GetParamsDir() / "sprout-verifying.key";
109
110     struct timeval tv_start;
111     timer_start(tv_start);
112
113     auto newParams = ZCJoinSplit::Prepared(vk_path.string(), pk_path.string());
114
115     double ret = timer_stop(tv_start);
116
117     delete newParams;
118
119     return ret;
120 }
121
122 double benchmark_create_joinsplit()
123 {
124     uint256 joinSplitPubKey;
125
126     /* Get the anchor of an empty commitment tree. */
127     uint256 anchor = SproutMerkleTree().root();
128
129     struct timeval tv_start;
130     timer_start(tv_start);
131     JSDescription jsdesc(true,
132                          *pzcashParams,
133                          joinSplitPubKey,
134                          anchor,
135                          {JSInput(), JSInput()},
136                          {JSOutput(), JSOutput()},
137                          0,
138                          0);
139     double ret = timer_stop(tv_start);
140
141     auto verifier = libzcash::ProofVerifier::Strict();
142     assert(jsdesc.Verify(*pzcashParams, verifier, joinSplitPubKey));
143     return ret;
144 }
145
146 std::vector<double> benchmark_create_joinsplit_threaded(int nThreads)
147 {
148     std::vector<double> ret;
149     std::vector<std::future<double>> tasks;
150     std::vector<std::thread> threads;
151     for (int i = 0; i < nThreads; i++) {
152         std::packaged_task<double(void)> task(&benchmark_create_joinsplit);
153         tasks.emplace_back(task.get_future());
154         threads.emplace_back(std::move(task));
155     }
156     std::future_status status;
157     for (auto it = tasks.begin(); it != tasks.end(); it++) {
158         it->wait();
159         ret.push_back(it->get());
160     }
161     for (auto it = threads.begin(); it != threads.end(); it++) {
162         it->join();
163     }
164     return ret;
165 }
166
167 double benchmark_verify_joinsplit(const JSDescription &joinsplit)
168 {
169     struct timeval tv_start;
170     timer_start(tv_start);
171     uint256 joinSplitPubKey;
172     auto verifier = libzcash::ProofVerifier::Strict();
173     joinsplit.Verify(*pzcashParams, verifier, joinSplitPubKey);
174     return timer_stop(tv_start);
175 }
176
177 #ifdef ENABLE_MINING
178 double benchmark_solve_equihash()
179 {
180     CBlock pblock;
181     CEquihashInput I{pblock};
182     CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
183     ss << I;
184
185     auto params = Params(CBaseChainParams::MAIN).GetConsensus();
186     unsigned int n = params.nEquihashN;
187     unsigned int k = params.nEquihashK;
188     crypto_generichash_blake2b_state eh_state;
189     EhInitialiseState(n, k, eh_state);
190     crypto_generichash_blake2b_update(&eh_state, (unsigned char*)&ss[0], ss.size());
191
192     uint256 nonce;
193     randombytes_buf(nonce.begin(), 32);
194     crypto_generichash_blake2b_update(&eh_state,
195                                     nonce.begin(),
196                                     nonce.size());
197
198     struct timeval tv_start;
199     timer_start(tv_start);
200     std::set<std::vector<unsigned int>> solns;
201     EhOptimisedSolveUncancellable(n, k, eh_state,
202                                   [](std::vector<unsigned char> soln) { return false; });
203     return timer_stop(tv_start);
204 }
205
206 std::vector<double> benchmark_solve_equihash_threaded(int nThreads)
207 {
208     std::vector<double> ret;
209     std::vector<std::future<double>> tasks;
210     std::vector<std::thread> threads;
211     for (int i = 0; i < nThreads; i++) {
212         std::packaged_task<double(void)> task(&benchmark_solve_equihash);
213         tasks.emplace_back(task.get_future());
214         threads.emplace_back(std::move(task));
215     }
216     std::future_status status;
217     for (auto it = tasks.begin(); it != tasks.end(); it++) {
218         it->wait();
219         ret.push_back(it->get());
220     }
221     for (auto it = threads.begin(); it != threads.end(); it++) {
222         it->join();
223     }
224     return ret;
225 }
226 #endif // ENABLE_MINING
227
228 double benchmark_verify_equihash()
229 {
230     CChainParams params = Params(CBaseChainParams::MAIN);
231     CBlock genesis = params.GenesisBlock();
232     CBlockHeader genesis_header = genesis.GetBlockHeader();
233     struct timeval tv_start;
234     timer_start(tv_start);
235     CheckEquihashSolution(&genesis_header, params.GetConsensus());
236     return timer_stop(tv_start);
237 }
238
239 double benchmark_large_tx(size_t nInputs)
240 {
241     // Create priv/pub key
242     CKey priv;
243     priv.MakeNewKey(false);
244     auto pub = priv.GetPubKey();
245     CBasicKeyStore tempKeystore;
246     tempKeystore.AddKey(priv);
247
248     // The "original" transaction that the spending transaction will spend
249     // from.
250     CMutableTransaction m_orig_tx;
251     m_orig_tx.vout.resize(1);
252     m_orig_tx.vout[0].nValue = 1000000;
253     CScript prevPubKey = GetScriptForDestination(pub.GetID());
254     m_orig_tx.vout[0].scriptPubKey = prevPubKey;
255
256     auto orig_tx = CTransaction(m_orig_tx);
257
258     CMutableTransaction spending_tx;
259     spending_tx.fOverwintered = true;
260     spending_tx.nVersionGroupId = SAPLING_VERSION_GROUP_ID;
261     spending_tx.nVersion = SAPLING_TX_VERSION;
262
263     auto input_hash = orig_tx.GetHash();
264     // Add nInputs inputs
265     for (size_t i = 0; i < nInputs; i++) {
266         spending_tx.vin.emplace_back(input_hash, 0);
267     }
268
269     // Sign for all the inputs
270     auto consensusBranchId = NetworkUpgradeInfo[Consensus::UPGRADE_SAPLING].nBranchId;
271     for (size_t i = 0; i < nInputs; i++) {
272         SignSignature(tempKeystore, prevPubKey, spending_tx, i, 1000000, SIGHASH_ALL, consensusBranchId);
273     }
274
275     // Spending tx has all its inputs signed and does not need to be mutated anymore
276     CTransaction final_spending_tx(spending_tx);
277
278     // Benchmark signature verification costs:
279     struct timeval tv_start;
280     timer_start(tv_start);
281     PrecomputedTransactionData txdata(final_spending_tx);
282     for (size_t i = 0; i < nInputs; i++) {
283         ScriptError serror = SCRIPT_ERR_OK;
284         assert(VerifyScript(final_spending_tx.vin[i].scriptSig,
285                             prevPubKey,
286                             STANDARD_SCRIPT_VERIFY_FLAGS,
287                             TransactionSignatureChecker(&final_spending_tx, i, 1000000, txdata),
288                             consensusBranchId,
289                             &serror));
290     }
291     return timer_stop(tv_start);
292 }
293
294 // The two benchmarks, try_decrypt_sprout_notes and try_decrypt_sapling_notes,
295 // are checking worst-case scenarios. In both we add n keys to a wallet, 
296 // create a transaction using a key not in our original list of n, and then
297 // check that the transaction is not associated with any of the keys in our 
298 // wallet. We call assert(...) to ensure that this is true.
299 double benchmark_try_decrypt_sprout_notes(size_t nKeys)
300 {
301     CWallet wallet;
302     for (int i = 0; i < nKeys; i++) {
303         auto sk = libzcash::SproutSpendingKey::random();
304         wallet.AddSproutSpendingKey(sk);
305     }
306
307     auto sk = libzcash::SproutSpendingKey::random();
308     auto tx = GetValidSproutReceive(*pzcashParams, sk, 10, true);
309
310     struct timeval tv_start;
311     timer_start(tv_start);
312     auto noteDataMap = wallet.FindMySproutNotes(tx);
313
314     assert(noteDataMap.empty());
315     return timer_stop(tv_start);
316 }
317
318 double benchmark_try_decrypt_sapling_notes(size_t nKeys)
319 {
320     // Set params
321     auto consensusParams = Params().GetConsensus();
322
323     auto masterKey = GetTestMasterSaplingSpendingKey();
324
325     CWallet wallet;
326
327     for (int i = 0; i < nKeys; i++) {
328         auto sk = masterKey.Derive(i);
329         wallet.AddSaplingSpendingKey(sk, sk.DefaultAddress());
330     }
331
332     // Generate a key that has not been added to the wallet
333     auto sk = masterKey.Derive(nKeys);
334     auto tx = GetValidSaplingReceive(consensusParams, wallet, sk, 10);
335
336     struct timeval tv_start;
337     timer_start(tv_start);
338     auto noteDataMapAndAddressesToAdd = wallet.FindMySaplingNotes(tx);
339     assert(noteDataMapAndAddressesToAdd.first.empty());
340     return timer_stop(tv_start);
341 }
342
343 CWalletTx CreateSproutTxWithNoteData(const libzcash::SproutSpendingKey& sk) {
344     auto wtx = GetValidSproutReceive(*pzcashParams, sk, 10, true);
345     auto note = GetSproutNote(*pzcashParams, sk, wtx, 0, 1);
346     auto nullifier = note.nullifier(sk);
347
348     mapSproutNoteData_t noteDataMap;
349     JSOutPoint jsoutpt {wtx.GetHash(), 0, 1};
350     SproutNoteData nd {sk.address(), nullifier};
351     noteDataMap[jsoutpt] = nd;
352
353     wtx.SetSproutNoteData(noteDataMap);
354
355     return wtx;
356 }
357
358 double benchmark_increment_sprout_note_witnesses(size_t nTxs)
359 {
360     auto consensusParams = Params().GetConsensus();
361
362     CWallet wallet;
363     SproutMerkleTree sproutTree;
364     SaplingMerkleTree saplingTree;
365
366     auto sproutSpendingKey = libzcash::SproutSpendingKey::random();
367     wallet.AddSproutSpendingKey(sproutSpendingKey);
368
369     // First block
370     CBlock block1;
371     for (int i = 0; i < nTxs; ++i) {
372         auto wtx = CreateSproutTxWithNoteData(sproutSpendingKey);
373         wallet.AddToWallet(wtx, true, NULL);
374         block1.vtx.push_back(wtx);
375     }
376
377     CBlockIndex index1(block1);
378     index1.SetHeight(1);
379
380     // Increment to get transactions witnessed
381     wallet.ChainTip(&index1, &block1, sproutTree, saplingTree, true);
382
383     // Second block
384     CBlock block2;
385     block2.hashPrevBlock = block1.GetHash();
386     {
387         auto sproutTx = CreateSproutTxWithNoteData(sproutSpendingKey);
388         wallet.AddToWallet(sproutTx, true, NULL);
389         block2.vtx.push_back(sproutTx);
390     }
391
392     CBlockIndex index2(block2);
393     index2.SetHeight(2);
394
395     struct timeval tv_start;
396     timer_start(tv_start);
397     wallet.ChainTip(&index2, &block2, sproutTree, saplingTree, true);
398     return timer_stop(tv_start);
399 }
400
401 CWalletTx CreateSaplingTxWithNoteData(const Consensus::Params& consensusParams,
402                                       CBasicKeyStore& keyStore,
403                                       const libzcash::SaplingExtendedSpendingKey &sk) {
404     auto wtx = GetValidSaplingReceive(consensusParams, keyStore, sk, 10);
405     auto testNote = GetTestSaplingNote(sk.DefaultAddress(), 10);
406     auto fvk = sk.expsk.full_viewing_key();
407     auto nullifier = testNote.note.nullifier(fvk, testNote.tree.witness().position()).get();
408
409     mapSaplingNoteData_t noteDataMap;
410     SaplingOutPoint outPoint {wtx.GetHash(), 0};
411     auto ivk = fvk.in_viewing_key();
412     SaplingNoteData noteData {ivk, nullifier};
413     noteDataMap[outPoint] = noteData;
414
415     wtx.SetSaplingNoteData(noteDataMap);
416
417     return wtx;
418 }
419
420 double benchmark_increment_sapling_note_witnesses(size_t nTxs)
421 {
422     auto consensusParams = Params().GetConsensus();
423
424     CWallet wallet;
425     SproutMerkleTree sproutTree;
426     SaplingMerkleTree saplingTree;
427
428     auto saplingSpendingKey = GetTestMasterSaplingSpendingKey();
429     wallet.AddSaplingSpendingKey(saplingSpendingKey, saplingSpendingKey.DefaultAddress());
430
431     // First block
432     CBlock block1;
433     for (int i = 0; i < nTxs; ++i) {
434         auto wtx = CreateSaplingTxWithNoteData(consensusParams, wallet, saplingSpendingKey);
435         wallet.AddToWallet(wtx, true, NULL);
436         block1.vtx.push_back(wtx);
437     }
438
439     CBlockIndex index1(block1);
440     index1.SetHeight(1);
441
442     // Increment to get transactions witnessed
443     wallet.ChainTip(&index1, &block1, sproutTree, saplingTree, true);
444
445     // Second block
446     CBlock block2;
447     block2.hashPrevBlock = block1.GetHash();
448     {
449         auto saplingTx = CreateSaplingTxWithNoteData(consensusParams, wallet, saplingSpendingKey);
450         wallet.AddToWallet(saplingTx, true, NULL);
451         block1.vtx.push_back(saplingTx);
452     }
453
454     CBlockIndex index2(block2);
455     index2.SetHeight(2);
456
457     struct timeval tv_start;
458     timer_start(tv_start);
459     wallet.ChainTip(&index2, &block2, sproutTree, saplingTree, true);
460     return timer_stop(tv_start);
461 }
462
463 // Fake the input of a given block
464 // This class is based on the class CCoinsViewDB, but with limited functionality.
465 // The construtor and the functions `GetCoins` and `HaveCoins` come directly from
466 // CCoinsViewDB, but the rest are either mocks and/or don't really do anything.
467
468 // The following constant is a duplicate of the one found in txdb.cpp
469 static const char DB_COINS = 'c';
470
471 class FakeCoinsViewDB : public CCoinsView {
472
473     CDBWrapper db;
474
475     uint256 hash;
476     SproutMerkleTree sproutTree;
477     SaplingMerkleTree saplingTree;
478
479 public:
480     FakeCoinsViewDB(std::string dbName, uint256& hash) : db(GetDataDir() / dbName, 100, false, false), hash(hash) {}
481
482     bool GetSproutAnchorAt(const uint256 &rt, SproutMerkleTree &tree) const {
483         if (rt == sproutTree.root()) {
484             tree = sproutTree;
485             return true;
486         }
487         return false;
488     }
489
490     bool GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &tree) const {
491         if (rt == saplingTree.root()) {
492             tree = saplingTree;
493             return true;
494         }
495         return false;
496     }
497
498     bool GetNullifier(const uint256 &nf, ShieldedType type) const {
499         return false;
500     }
501
502     bool GetCoins(const uint256 &txid, CCoins &coins) const {
503         return db.Read(std::make_pair(DB_COINS, txid), coins);
504     }
505
506     bool HaveCoins(const uint256 &txid) const {
507         return db.Exists(std::make_pair(DB_COINS, txid));
508     }
509
510     uint256 GetBestBlock() const {
511         return hash;
512     }
513
514     uint256 GetBestAnchor(ShieldedType type) const {
515         switch (type) {
516             case SPROUT:
517                 return sproutTree.root();
518             case SAPLING:
519                 return saplingTree.root();
520             default:
521                 throw new std::runtime_error("Unknown shielded type");
522         }
523     }
524
525     bool BatchWrite(CCoinsMap &mapCoins,
526                     const uint256 &hashBlock,
527                     const uint256 &hashSproutAnchor,
528                     const uint256 &hashSaplingAnchor,
529                     CAnchorsSproutMap &mapSproutAnchors,
530                     CAnchorsSaplingMap &mapSaplingAnchors,
531                     CNullifiersMap &mapSproutNullifiers,
532                     CNullifiersMap &mapSaplingNullifiers) {
533         return false;
534     }
535
536     bool GetStats(CCoinsStats &stats) const {
537         return false;
538     }
539 };
540
541 double benchmark_connectblock_slow()
542 {
543     // Test for issue 2017-05-01.a
544     SelectParams(CBaseChainParams::MAIN);
545     CBlock block;
546     FILE* fp = fopen((GetDataDir() / "benchmark/block-107134.dat").string().c_str(), "rb");
547     if (!fp) throw new std::runtime_error("Failed to open block data file");
548     CAutoFile blkFile(fp, SER_DISK, CLIENT_VERSION);
549     blkFile >> block;
550     blkFile.fclose();
551
552     // Fake its inputs
553     auto hashPrev = uint256S("00000000159a41f468e22135942a567781c3f3dc7ad62257993eb3c69c3f95ef");
554     FakeCoinsViewDB fakeDB("benchmark/block-107134-inputs", hashPrev);
555     CCoinsViewCache view(&fakeDB);
556
557     // Fake the chain
558     CBlockIndex index(block);
559     index.SetHeight(107134);
560     CBlockIndex indexPrev;
561     indexPrev.phashBlock = &hashPrev;
562     indexPrev.SetHeight(index.GetHeight() - 1);
563     index.pprev = &indexPrev;
564     mapBlockIndex.insert(std::make_pair(hashPrev, &indexPrev));
565
566     CValidationState state;
567     struct timeval tv_start;
568     timer_start(tv_start);
569     assert(ConnectBlock(block, state, &index, view, Params(), true));
570     auto duration = timer_stop(tv_start);
571
572     // Undo alterations to global state
573     mapBlockIndex.erase(hashPrev);
574     SelectParamsFromCommandLine();
575
576     return duration;
577 }
578
579 extern UniValue getnewaddress(const UniValue& params, bool fHelp); // in rpcwallet.cpp
580 extern UniValue sendtoaddress(const UniValue& params, bool fHelp);
581
582 double benchmark_sendtoaddress(CAmount amount)
583 {
584     UniValue params(UniValue::VARR);
585     auto addr = getnewaddress(params, false);
586
587     params.push_back(addr);
588     params.push_back(ValueFromAmount(amount));
589
590     struct timeval tv_start;
591     timer_start(tv_start);
592     auto txid = sendtoaddress(params, false);
593     return timer_stop(tv_start);
594 }
595
596 double benchmark_loadwallet()
597 {
598     pre_wallet_load();
599     struct timeval tv_start;
600     bool fFirstRunRet=true;
601     timer_start(tv_start);
602     pwalletMain = new CWallet("wallet.dat");
603     DBErrors nLoadWalletRet = pwalletMain->LoadWallet(fFirstRunRet);
604     auto res = timer_stop(tv_start);
605     post_wallet_load();
606     return res;
607 }
608
609 extern UniValue listunspent(const UniValue& params, bool fHelp);
610
611 double benchmark_listunspent()
612 {
613     UniValue params(UniValue::VARR);
614     struct timeval tv_start;
615     timer_start(tv_start);
616     auto unspent = listunspent(params, false);
617     return timer_stop(tv_start);
618 }
619
620 double benchmark_create_sapling_spend()
621 {
622     auto sk = libzcash::SaplingSpendingKey::random();
623     auto expsk = sk.expanded_spending_key();
624     auto address = sk.default_address();
625     SaplingNote note(address, GetRand(MAX_MONEY));
626     SaplingMerkleTree tree;
627     auto maybe_cm = note.cm();
628     tree.append(maybe_cm.get());
629     auto anchor = tree.root();
630     auto witness = tree.witness();
631     auto maybe_nf = note.nullifier(expsk.full_viewing_key(), witness.position());
632     if (!(maybe_cm && maybe_nf)) {
633         throw JSONRPCError(RPC_INTERNAL_ERROR, "Could not create note commitment and nullifier");
634     }
635
636     CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
637     ss << witness.path();
638     std::vector<unsigned char> witnessChars(ss.begin(), ss.end());
639
640     uint256 alpha;
641     librustzcash_sapling_generate_r(alpha.begin());
642
643     auto ctx = librustzcash_sapling_proving_ctx_init();
644
645     struct timeval tv_start;
646     timer_start(tv_start);
647
648     SpendDescription sdesc;
649     bool result = librustzcash_sapling_spend_proof(
650         ctx,
651         expsk.full_viewing_key().ak.begin(),
652         expsk.nsk.begin(),
653         note.d.data(),
654         note.r.begin(),
655         alpha.begin(),
656         note.value(),
657         anchor.begin(),
658         witnessChars.data(),
659         sdesc.cv.begin(),
660         sdesc.rk.begin(),
661         sdesc.zkproof.data());
662
663     double t = timer_stop(tv_start);
664     librustzcash_sapling_proving_ctx_free(ctx);
665     if (!result) {
666         throw JSONRPCError(RPC_INTERNAL_ERROR, "librustzcash_sapling_spend_proof() should return true");
667     }
668     return t;
669 }
670
671 double benchmark_create_sapling_output()
672 {
673     auto sk = libzcash::SaplingSpendingKey::random();
674     auto address = sk.default_address();
675
676     std::array<unsigned char, ZC_MEMO_SIZE> memo;
677     SaplingNote note(address, GetRand(MAX_MONEY));
678
679     libzcash::SaplingNotePlaintext notePlaintext(note, memo);
680     auto res = notePlaintext.encrypt(note.pk_d);
681     if (!res) {
682         throw JSONRPCError(RPC_INTERNAL_ERROR, "SaplingNotePlaintext::encrypt() failed");
683     }
684
685     auto enc = res.get();
686     auto encryptor = enc.second;
687
688     auto ctx = librustzcash_sapling_proving_ctx_init();
689
690     struct timeval tv_start;
691     timer_start(tv_start);
692
693     OutputDescription odesc;
694     bool result = librustzcash_sapling_output_proof(
695         ctx,
696         encryptor.get_esk().begin(),
697         note.d.data(),
698         note.pk_d.begin(),
699         note.r.begin(),
700         note.value(),
701         odesc.cv.begin(),
702         odesc.zkproof.begin());
703
704     double t = timer_stop(tv_start);
705     librustzcash_sapling_proving_ctx_free(ctx);
706     if (!result) {
707         throw JSONRPCError(RPC_INTERNAL_ERROR, "librustzcash_sapling_output_proof() should return true");
708     }
709     return t;
710 }
711
712 // Verify Sapling spend from testnet
713 // txid: abbd823cbd3d4e3b52023599d81a96b74817e95ce5bb58354f979156bd22ecc8
714 // position: 0
715 double benchmark_verify_sapling_spend()
716 {
717     SpendDescription spend;
718     CDataStream ss(ParseHex("8c6cf86bbb83bf0d075e5bd9bb4b5cd56141577be69f032880b11e26aa32aa5ef09fd00899e4b469fb11f38e9d09dc0379f0b11c23b5fe541765f76695120a03f0261d32af5d2a2b1e5c9a04200cd87d574dc42349de9790012ce560406a8a876a1e54cfcdc0eb74998abec2a9778330eeb2a0ac0e41d0c9ed5824fbd0dbf7da930ab299966ce333fd7bc1321dada0817aac5444e02c754069e218746bf879d5f2a20a8b028324fb2c73171e63336686aa5ec2e6e9a08eb18b87c14758c572f4531ccf6b55d09f44beb8b47563be4eff7a52598d80959dd9c9fee5ac4783d8370cb7d55d460053d3e067b5f9fe75ff2722623fb1825fcba5e9593d4205b38d1f502ff03035463043bd393a5ee039ce75a5d54f21b395255df6627ef96751566326f7d4a77d828aa21b1827282829fcbc42aad59cdb521e1a3aaa08b99ea8fe7fff0a04da31a52260fc6daeccd79bb877bdd8506614282258e15b3fe74bf71a93f4be3b770119edf99a317b205eea7d5ab800362b97384273888106c77d633600"), SER_NETWORK, PROTOCOL_VERSION);
719     ss >> spend;
720     uint256 dataToBeSigned = uint256S("0x2dbf83fe7b88a7cbd80fac0c719483906bb9a0c4fc69071e4780d5f2c76e592c");
721
722     auto ctx = librustzcash_sapling_verification_ctx_init();
723
724     struct timeval tv_start;
725     timer_start(tv_start);
726
727     bool result = librustzcash_sapling_check_spend(
728                 ctx,
729                 spend.cv.begin(),
730                 spend.anchor.begin(),
731                 spend.nullifier.begin(),
732                 spend.rk.begin(),
733                 spend.zkproof.begin(),
734                 spend.spendAuthSig.begin(),
735                 dataToBeSigned.begin()
736             );
737
738     double t = timer_stop(tv_start);
739     librustzcash_sapling_verification_ctx_free(ctx);
740     if (!result) {
741         throw JSONRPCError(RPC_INTERNAL_ERROR, "librustzcash_sapling_check_spend() should return true");
742     }
743     return t;
744 }
745
746 // Verify Sapling output from testnet
747 // txid: abbd823cbd3d4e3b52023599d81a96b74817e95ce5bb58354f979156bd22ecc8
748 // position: 0
749 double benchmark_verify_sapling_output()
750 {
751     OutputDescription output;
752     CDataStream ss(ParseHex("edd742af18857e5ec2d71d346a7fe2ac97c137339bd5268eea86d32e0ff4f38f76213fa8cfed3347ac4e8572dd88aff395c0c10a59f8b3f49d2bc539ed6c726667e29d4763f914ddd0abf1cdfa84e44de87c233434c7e69b8b5b8f4623c8aa444163425bae5cef842972fed66046c1c6ce65c866ad894d02e6e6dcaae7a962d9f2ef95757a09c486928e61f0f7aed90ad0a542b0d3dc5fe140dfa7626b9315c77e03b055f19cbacd21a866e46f06c00e0c7792b2a590a611439b510a9aaffcf1073bad23e712a9268b36888e3727033eee2ab4d869f54a843f93b36ef489fb177bf74b41a9644e5d2a0a417c6ac1c8869bc9b83273d453f878ed6fd96b82a5939903f7b64ecaf68ea16e255a7fb7cc0b6d8b5608a1c6b0ed3024cc62c2f0f9c5cfc7b431ae6e9d40815557aa1d010523f9e1960de77b2274cb6710d229d475c87ae900183206ba90cb5bbc8ec0df98341b82726c705e0308ca5dc08db4db609993a1046dfb43dfd8c760be506c0bed799bb2205fc29dc2e654dce731034a23b0aaf6da0199248702ee0523c159f41f4cbfff6c35ace4dd9ae834e44e09c76a0cbdda1d3f6a2c75ad71212daf9575ab5f09ca148718e667f29ddf18c8a330a86ace18a86e89454653902aa393c84c6b694f27d0d42e24e7ac9fe34733de5ec15f5066081ce912c62c1a804a2bb4dedcef7cc80274f6bb9e89e2fce91dc50d6a73c8aefb9872f1cf3524a92626a0b8f39bbf7bf7d96ca2f770fc04d7f457021c536a506a187a93b2245471ddbfb254a71bc4a0d72c8d639a31c7b1920087ffca05c24214157e2e7b28184e91989ef0b14f9b34c3dc3cc0ac64226b9e337095870cb0885737992e120346e630a416a9b217679ce5a778fb15779c136bcecca5efe79012013d77d90b4e99dd22c8f35bc77121716e160d05bd30d288ee8886390ee436f85bdc9029df888a3a3326d9d4ddba5cb5318b3274928829d662e96fea1d601f7a306251ed8c6cc4e5a3a7a98c35a3650482a0eee08f3b4c2da9b22947c96138f1505c2f081f8972d429f3871f32bef4aaa51aa6945df8e9c9760531ac6f627d17c1518202818a91ca304fb4037875c666060597976144fcbbc48a776a2c61beb9515fa8f3ae6d3a041d320a38a8ac75cb47bb9c866ee497fc3cd13299970c4b369c1c2ceb4220af082fbecdd8114492a8e4d713b5a73396fd224b36c1185bd5e20d683e6c8db35346c47ae7401988255da7cfffdced5801067d4d296688ee8fe424b4a8a69309ce257eefb9345ebfda3f6de46bb11ec94133e1f72cd7ac54934d6cf17b3440800e70b80ebc7c7bfc6fb0fc2c"), SER_NETWORK, PROTOCOL_VERSION);
753     ss >> output;
754
755     auto ctx = librustzcash_sapling_verification_ctx_init();
756
757     struct timeval tv_start;
758     timer_start(tv_start);
759
760     bool result = librustzcash_sapling_check_output(
761                 ctx,
762                 output.cv.begin(),
763                 output.cm.begin(),
764                 output.ephemeralKey.begin(),
765                 output.zkproof.begin()
766             );
767
768     double t = timer_stop(tv_start);
769     librustzcash_sapling_verification_ctx_free(ctx);
770     if (!result) {
771         throw JSONRPCError(RPC_INTERNAL_ERROR, "librustzcash_sapling_check_output() should return true");
772     }
773     return timer_stop(tv_start);
774 }
This page took 0.066148 seconds and 4 git commands to generate.