]> Git Repo - VerusCoin.git/blame - src/zcbenchmarks.cpp
Update librustzcash again
[VerusCoin.git] / src / zcbenchmarks.cpp
CommitLineData
c66c731a 1#include <cstdio>
9e52ca32 2#include <future>
c66c731a 3#include <map>
9e52ca32 4#include <thread>
6962bb3d
TH
5#include <unistd.h>
6#include <boost/filesystem.hpp>
9e52ca32 7
6962bb3d
TH
8#include "coins.h"
9#include "util.h"
10#include "init.h"
11#include "primitives/transaction.h"
f5edc37f 12#include "base58.h"
bf8def97 13#include "crypto/equihash.h"
c66c731a 14#include "chain.h"
bf8def97 15#include "chainparams.h"
be126699 16#include "consensus/upgrades.h"
f5edc37f
JG
17#include "consensus/validation.h"
18#include "main.h"
19#include "miner.h"
a1cd1a27 20#include "pow.h"
a76174b7 21#include "rpcserver.h"
f5edc37f 22#include "script/sign.h"
722b0117
TH
23#include "sodium.h"
24#include "streams.h"
c66c731a 25#include "txdb.h"
0bb3d40f 26#include "utiltest.h"
f5edc37f 27#include "wallet/wallet.h"
6962bb3d
TH
28
29#include "zcbenchmarks.h"
30
2dc35992
SB
31#include "zcash/Zcash.h"
32#include "zcash/IncrementalMerkleTree.hpp"
33
34using namespace libzcash;
2e8aefdc
AG
35// This method is based on Shutdown from init.cpp
36void pre_wallet_load()
37{
38 LogPrintf("%s: In progress...\n", __func__);
39 if (ShutdownRequested())
40 throw new std::runtime_error("The node is shutting down");
41
42 if (pwalletMain)
43 pwalletMain->Flush(false);
44#ifdef ENABLE_MINING
45 GenerateBitcoins(false, NULL, 0);
46#endif
47 UnregisterNodeSignals(GetNodeSignals());
48 if (pwalletMain)
49 pwalletMain->Flush(true);
50
51 UnregisterValidationInterface(pwalletMain);
52 delete pwalletMain;
53 pwalletMain = NULL;
54 bitdb.Reset();
55 RegisterNodeSignals(GetNodeSignals());
56 LogPrintf("%s: done\n", __func__);
57}
58
59void post_wallet_load(){
60 RegisterValidationInterface(pwalletMain);
61#ifdef ENABLE_MINING
62 // Generate coins in the background
63 if (pwalletMain || !GetArg("-mineraddress", "").empty())
64 GenerateBitcoins(GetBoolArg("-gen", false), pwalletMain, GetArg("-genproclimit", 1));
65#endif
66}
67
2dc35992 68
9e52ca32 69void timer_start(timeval &tv_start)
6962bb3d
TH
70{
71 gettimeofday(&tv_start, 0);
72}
73
9e52ca32 74double timer_stop(timeval &tv_start)
6962bb3d
TH
75{
76 double elapsed;
77 struct timeval tv_end;
78 gettimeofday(&tv_end, 0);
79 elapsed = double(tv_end.tv_sec-tv_start.tv_sec) +
80 (tv_end.tv_usec-tv_start.tv_usec)/double(1000000);
81 return elapsed;
82}
83
84double benchmark_sleep()
85{
9e52ca32
JG
86 struct timeval tv_start;
87 timer_start(tv_start);
6962bb3d 88 sleep(1);
9e52ca32 89 return timer_stop(tv_start);
6962bb3d
TH
90}
91
92double benchmark_parameter_loading()
93{
94 // FIXME: this is duplicated with the actual loading code
27e3f362
SB
95 boost::filesystem::path pk_path = ZC_GetParamsDir() / "sprout-proving.key";
96 boost::filesystem::path vk_path = ZC_GetParamsDir() / "sprout-verifying.key";
6962bb3d 97
9e52ca32
JG
98 struct timeval tv_start;
99 timer_start(tv_start);
2dc35992 100
1a9543d0 101 auto newParams = ZCJoinSplit::Prepared(vk_path.string(), pk_path.string());
2dc35992 102
9e52ca32 103 double ret = timer_stop(tv_start);
2dc35992
SB
104
105 delete newParams;
106
107 return ret;
6962bb3d
TH
108}
109
110double benchmark_create_joinsplit()
111{
21406393 112 uint256 pubKeyHash;
6962bb3d 113
6962bb3d 114 /* Get the anchor of an empty commitment tree. */
5961dcb6 115 uint256 anchor = ZCIncrementalMerkleTree().root();
6962bb3d 116
9e52ca32
JG
117 struct timeval tv_start;
118 timer_start(tv_start);
b7a6c321
SB
119 JSDescription jsdesc(false, // TODO: ?
120 *pzcashParams,
22de1602
SB
121 pubKeyHash,
122 anchor,
123 {JSInput(), JSInput()},
124 {JSOutput(), JSOutput()},
125 0,
126 0);
9e52ca32 127 double ret = timer_stop(tv_start);
21406393 128
bc59f537
SB
129 auto verifier = libzcash::ProofVerifier::Strict();
130 assert(jsdesc.Verify(*pzcashParams, verifier, pubKeyHash));
6962bb3d
TH
131 return ret;
132}
bf8def97 133
4082dcb1
JG
134std::vector<double> benchmark_create_joinsplit_threaded(int nThreads)
135{
136 std::vector<double> ret;
137 std::vector<std::future<double>> tasks;
138 std::vector<std::thread> threads;
139 for (int i = 0; i < nThreads; i++) {
140 std::packaged_task<double(void)> task(&benchmark_create_joinsplit);
141 tasks.emplace_back(task.get_future());
142 threads.emplace_back(std::move(task));
143 }
144 std::future_status status;
145 for (auto it = tasks.begin(); it != tasks.end(); it++) {
146 it->wait();
147 ret.push_back(it->get());
148 }
149 for (auto it = threads.begin(); it != threads.end(); it++) {
150 it->join();
151 }
152 return ret;
153}
154
a8c68ffe 155double benchmark_verify_joinsplit(const JSDescription &joinsplit)
a1cd1a27 156{
9e52ca32
JG
157 struct timeval tv_start;
158 timer_start(tv_start);
21406393 159 uint256 pubKeyHash;
bc59f537
SB
160 auto verifier = libzcash::ProofVerifier::Strict();
161 joinsplit.Verify(*pzcashParams, verifier, pubKeyHash);
9e52ca32 162 return timer_stop(tv_start);
a1cd1a27
TH
163}
164
2cc0a252 165#ifdef ENABLE_MINING
9e52ca32 166double benchmark_solve_equihash()
bf8def97 167{
722b0117
TH
168 CBlock pblock;
169 CEquihashInput I{pblock};
170 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
171 ss << I;
172
e9574728
JG
173 unsigned int n = Params(CBaseChainParams::MAIN).EquihashN();
174 unsigned int k = Params(CBaseChainParams::MAIN).EquihashK();
bf8def97 175 crypto_generichash_blake2b_state eh_state;
e9574728 176 EhInitialiseState(n, k, eh_state);
722b0117
TH
177 crypto_generichash_blake2b_update(&eh_state, (unsigned char*)&ss[0], ss.size());
178
179 uint256 nonce;
180 randombytes_buf(nonce.begin(), 32);
181 crypto_generichash_blake2b_update(&eh_state,
182 nonce.begin(),
183 nonce.size());
184
9e52ca32
JG
185 struct timeval tv_start;
186 timer_start(tv_start);
e9574728 187 std::set<std::vector<unsigned int>> solns;
51eb5273 188 EhOptimisedSolveUncancellable(n, k, eh_state,
5be6abbf 189 [](std::vector<unsigned char> soln) { return false; });
9e52ca32 190 return timer_stop(tv_start);
f7478de6
JG
191}
192
9e52ca32 193std::vector<double> benchmark_solve_equihash_threaded(int nThreads)
f7478de6 194{
9e52ca32
JG
195 std::vector<double> ret;
196 std::vector<std::future<double>> tasks;
197 std::vector<std::thread> threads;
198 for (int i = 0; i < nThreads; i++) {
199 std::packaged_task<double(void)> task(&benchmark_solve_equihash);
200 tasks.emplace_back(task.get_future());
201 threads.emplace_back(std::move(task));
202 }
203 std::future_status status;
204 for (auto it = tasks.begin(); it != tasks.end(); it++) {
205 it->wait();
206 ret.push_back(it->get());
207 }
208 for (auto it = threads.begin(); it != threads.end(); it++) {
209 it->join();
210 }
211 return ret;
bf8def97 212}
2cc0a252 213#endif // ENABLE_MINING
d44feea4 214
a1cd1a27 215double benchmark_verify_equihash()
d44feea4 216{
a1cd1a27
TH
217 CChainParams params = Params(CBaseChainParams::MAIN);
218 CBlock genesis = Params(CBaseChainParams::MAIN).GenesisBlock();
219 CBlockHeader genesis_header = genesis.GetBlockHeader();
9e52ca32
JG
220 struct timeval tv_start;
221 timer_start(tv_start);
a1cd1a27 222 CheckEquihashSolution(&genesis_header, params);
9e52ca32 223 return timer_stop(tv_start);
d44feea4 224}
a1cd1a27 225
818b94f9 226double benchmark_large_tx(size_t nInputs)
f5edc37f 227{
9c45b501
SB
228 // Create priv/pub key
229 CKey priv;
230 priv.MakeNewKey(false);
231 auto pub = priv.GetPubKey();
232 CBasicKeyStore tempKeystore;
233 tempKeystore.AddKey(priv);
234
235 // The "original" transaction that the spending transaction will spend
236 // from.
237 CMutableTransaction m_orig_tx;
238 m_orig_tx.vout.resize(1);
239 m_orig_tx.vout[0].nValue = 1000000;
240 CScript prevPubKey = GetScriptForDestination(pub.GetID());
241 m_orig_tx.vout[0].scriptPubKey = prevPubKey;
242
243 auto orig_tx = CTransaction(m_orig_tx);
244
245 CMutableTransaction spending_tx;
45539018 246 spending_tx.fOverwintered = true;
ddcee7e1
JG
247 spending_tx.nVersionGroupId = SAPLING_VERSION_GROUP_ID;
248 spending_tx.nVersion = SAPLING_TX_VERSION;
45539018 249
805344dc 250 auto input_hash = orig_tx.GetHash();
818b94f9
JG
251 // Add nInputs inputs
252 for (size_t i = 0; i < nInputs; i++) {
9c45b501 253 spending_tx.vin.emplace_back(input_hash, 0);
f5edc37f
JG
254 }
255
9c45b501 256 // Sign for all the inputs
ddcee7e1 257 auto consensusBranchId = NetworkUpgradeInfo[Consensus::UPGRADE_SAPLING].nBranchId;
818b94f9 258 for (size_t i = 0; i < nInputs; i++) {
be126699 259 SignSignature(tempKeystore, prevPubKey, spending_tx, i, 1000000, SIGHASH_ALL, consensusBranchId);
f5edc37f 260 }
f5edc37f 261
822b84b6
S
262 // Spending tx has all its inputs signed and does not need to be mutated anymore
263 CTransaction final_spending_tx(spending_tx);
264
9c45b501 265 // Benchmark signature verification costs:
9e52ca32
JG
266 struct timeval tv_start;
267 timer_start(tv_start);
45539018 268 PrecomputedTransactionData txdata(final_spending_tx);
818b94f9 269 for (size_t i = 0; i < nInputs; i++) {
9c45b501 270 ScriptError serror = SCRIPT_ERR_OK;
75c2f268 271 assert(VerifyScript(final_spending_tx.vin[i].scriptSig,
9c45b501
SB
272 prevPubKey,
273 STANDARD_SCRIPT_VERIFY_FLAGS,
45539018 274 TransactionSignatureChecker(&final_spending_tx, i, 1000000, txdata),
be126699 275 consensusBranchId,
9c45b501
SB
276 &serror));
277 }
9e52ca32 278 return timer_stop(tv_start);
f5edc37f
JG
279}
280
88b7f3c2 281double benchmark_try_decrypt_notes(size_t nAddrs)
0fbab55b 282{
0fbab55b 283 CWallet wallet;
88b7f3c2 284 for (int i = 0; i < nAddrs; i++) {
e5eab182 285 auto sk = libzcash::SproutSpendingKey::random();
0fbab55b
JG
286 wallet.AddSpendingKey(sk);
287 }
288
e5eab182 289 auto sk = libzcash::SproutSpendingKey::random();
88b7f3c2 290 auto tx = GetValidReceive(*pzcashParams, sk, 10, true);
0fbab55b
JG
291
292 struct timeval tv_start;
293 timer_start(tv_start);
294 auto nd = wallet.FindMyNotes(tx);
295 return timer_stop(tv_start);
296}
297
0bb3d40f
JG
298double benchmark_increment_note_witnesses(size_t nTxs)
299{
300 CWallet wallet;
301 ZCIncrementalMerkleTree tree;
302
e5eab182 303 auto sk = libzcash::SproutSpendingKey::random();
0bb3d40f
JG
304 wallet.AddSpendingKey(sk);
305
306 // First block
307 CBlock block1;
308 for (int i = 0; i < nTxs; i++) {
309 auto wtx = GetValidReceive(*pzcashParams, sk, 10, true);
310 auto note = GetNote(*pzcashParams, sk, wtx, 0, 1);
311 auto nullifier = note.nullifier(sk);
312
313 mapNoteData_t noteData;
314 JSOutPoint jsoutpt {wtx.GetHash(), 0, 1};
315 CNoteData nd {sk.address(), nullifier};
316 noteData[jsoutpt] = nd;
317
318 wtx.SetNoteData(noteData);
319 wallet.AddToWallet(wtx, true, NULL);
320 block1.vtx.push_back(wtx);
321 }
322 CBlockIndex index1(block1);
323 index1.nHeight = 1;
324
325 // Increment to get transactions witnessed
326 wallet.ChainTip(&index1, &block1, tree, true);
327
328 // Second block
329 CBlock block2;
330 block2.hashPrevBlock = block1.GetHash();
9755eb82
JG
331 {
332 auto wtx = GetValidReceive(*pzcashParams, sk, 10, true);
333 auto note = GetNote(*pzcashParams, sk, wtx, 0, 1);
334 auto nullifier = note.nullifier(sk);
335
336 mapNoteData_t noteData;
337 JSOutPoint jsoutpt {wtx.GetHash(), 0, 1};
338 CNoteData nd {sk.address(), nullifier};
339 noteData[jsoutpt] = nd;
340
341 wtx.SetNoteData(noteData);
342 wallet.AddToWallet(wtx, true, NULL);
343 block2.vtx.push_back(wtx);
344 }
0bb3d40f
JG
345 CBlockIndex index2(block2);
346 index2.nHeight = 2;
347
348 struct timeval tv_start;
349 timer_start(tv_start);
350 wallet.ChainTip(&index2, &block2, tree, true);
351 return timer_stop(tv_start);
352}
353
c66c731a
JG
354// Fake the input of a given block
355class FakeCoinsViewDB : public CCoinsViewDB {
356 uint256 hash;
357 ZCIncrementalMerkleTree t;
358
359public:
360 FakeCoinsViewDB(std::string dbName, uint256& hash) : CCoinsViewDB(dbName, 100, false, false), hash(hash) {}
361
362 bool GetAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const {
363 if (rt == t.root()) {
364 tree = t;
365 return true;
366 }
367 return false;
368 }
369
28d20bdb 370 bool GetNullifier(const uint256 &nf, ShieldedType type) const {
c66c731a
JG
371 return false;
372 }
373
374 uint256 GetBestBlock() const {
375 return hash;
376 }
377
378 uint256 GetBestAnchor() const {
379 return t.root();
380 }
381
382 bool BatchWrite(CCoinsMap &mapCoins,
383 const uint256 &hashBlock,
384 const uint256 &hashAnchor,
d455828f 385 CAnchorsSproutMap &mapSproutAnchors,
9669920f 386 CNullifiersMap &mapSproutNullifiers,
685e936c 387 CNullifiersMap& mapSaplingNullifiers) {
c66c731a
JG
388 return false;
389 }
390
391 bool GetStats(CCoinsStats &stats) const {
392 return false;
393 }
394};
395
396double benchmark_connectblock_slow()
397{
398 // Test for issue 2017-05-01.a
399 SelectParams(CBaseChainParams::MAIN);
400 CBlock block;
401 FILE* fp = fopen((GetDataDir() / "benchmark/block-107134.dat").string().c_str(), "rb");
402 if (!fp) throw new std::runtime_error("Failed to open block data file");
403 CAutoFile blkFile(fp, SER_DISK, CLIENT_VERSION);
404 blkFile >> block;
405 blkFile.fclose();
406
407 // Fake its inputs
408 auto hashPrev = uint256S("00000000159a41f468e22135942a567781c3f3dc7ad62257993eb3c69c3f95ef");
409 FakeCoinsViewDB fakeDB("benchmark/block-107134-inputs", hashPrev);
410 CCoinsViewCache view(&fakeDB);
411
412 // Fake the chain
413 CBlockIndex index(block);
414 index.nHeight = 107134;
415 CBlockIndex indexPrev;
416 indexPrev.phashBlock = &hashPrev;
417 indexPrev.nHeight = index.nHeight - 1;
418 index.pprev = &indexPrev;
419 mapBlockIndex.insert(std::make_pair(hashPrev, &indexPrev));
420
421 CValidationState state;
422 struct timeval tv_start;
423 timer_start(tv_start);
424 assert(ConnectBlock(block, state, &index, view, true));
425 auto duration = timer_stop(tv_start);
426
427 // Undo alterations to global state
428 mapBlockIndex.erase(hashPrev);
429 SelectParamsFromCommandLine();
430
431 return duration;
432}
433
a76174b7
JG
434double benchmark_sendtoaddress(CAmount amount)
435{
436 UniValue params(UniValue::VARR);
437 auto addr = getnewaddress(params, false);
438
439 params.push_back(addr);
440 params.push_back(ValueFromAmount(amount));
441
442 struct timeval tv_start;
443 timer_start(tv_start);
444 auto txid = sendtoaddress(params, false);
445 return timer_stop(tv_start);
446}
447
2e8aefdc
AG
448double benchmark_loadwallet()
449{
450 pre_wallet_load();
451 struct timeval tv_start;
452 bool fFirstRunRet=true;
453 timer_start(tv_start);
454 pwalletMain = new CWallet("wallet.dat");
455 DBErrors nLoadWalletRet = pwalletMain->LoadWallet(fFirstRunRet);
456 auto res = timer_stop(tv_start);
457 post_wallet_load();
458 return res;
459}
99dd50c3
JG
460
461double benchmark_listunspent()
462{
463 UniValue params(UniValue::VARR);
464 struct timeval tv_start;
465 timer_start(tv_start);
466 auto unspent = listunspent(params, false);
467 return timer_stop(tv_start);
468}
This page took 0.129414 seconds and 4 git commands to generate.