]> Git Repo - VerusCoin.git/blame - src/zcbenchmarks.cpp
Add sapling nullifiers to db and mempool
[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);
22de1602
SB
119 JSDescription jsdesc(*pzcashParams,
120 pubKeyHash,
121 anchor,
122 {JSInput(), JSInput()},
123 {JSOutput(), JSOutput()},
124 0,
125 0);
9e52ca32 126 double ret = timer_stop(tv_start);
21406393 127
bc59f537
SB
128 auto verifier = libzcash::ProofVerifier::Strict();
129 assert(jsdesc.Verify(*pzcashParams, verifier, pubKeyHash));
6962bb3d
TH
130 return ret;
131}
bf8def97 132
4082dcb1
JG
133std::vector<double> benchmark_create_joinsplit_threaded(int nThreads)
134{
135 std::vector<double> ret;
136 std::vector<std::future<double>> tasks;
137 std::vector<std::thread> threads;
138 for (int i = 0; i < nThreads; i++) {
139 std::packaged_task<double(void)> task(&benchmark_create_joinsplit);
140 tasks.emplace_back(task.get_future());
141 threads.emplace_back(std::move(task));
142 }
143 std::future_status status;
144 for (auto it = tasks.begin(); it != tasks.end(); it++) {
145 it->wait();
146 ret.push_back(it->get());
147 }
148 for (auto it = threads.begin(); it != threads.end(); it++) {
149 it->join();
150 }
151 return ret;
152}
153
a8c68ffe 154double benchmark_verify_joinsplit(const JSDescription &joinsplit)
a1cd1a27 155{
9e52ca32
JG
156 struct timeval tv_start;
157 timer_start(tv_start);
21406393 158 uint256 pubKeyHash;
bc59f537
SB
159 auto verifier = libzcash::ProofVerifier::Strict();
160 joinsplit.Verify(*pzcashParams, verifier, pubKeyHash);
9e52ca32 161 return timer_stop(tv_start);
a1cd1a27
TH
162}
163
2cc0a252 164#ifdef ENABLE_MINING
9e52ca32 165double benchmark_solve_equihash()
bf8def97 166{
722b0117
TH
167 CBlock pblock;
168 CEquihashInput I{pblock};
169 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
170 ss << I;
171
e9574728
JG
172 unsigned int n = Params(CBaseChainParams::MAIN).EquihashN();
173 unsigned int k = Params(CBaseChainParams::MAIN).EquihashK();
bf8def97 174 crypto_generichash_blake2b_state eh_state;
e9574728 175 EhInitialiseState(n, k, eh_state);
722b0117
TH
176 crypto_generichash_blake2b_update(&eh_state, (unsigned char*)&ss[0], ss.size());
177
178 uint256 nonce;
179 randombytes_buf(nonce.begin(), 32);
180 crypto_generichash_blake2b_update(&eh_state,
181 nonce.begin(),
182 nonce.size());
183
9e52ca32
JG
184 struct timeval tv_start;
185 timer_start(tv_start);
e9574728 186 std::set<std::vector<unsigned int>> solns;
51eb5273 187 EhOptimisedSolveUncancellable(n, k, eh_state,
5be6abbf 188 [](std::vector<unsigned char> soln) { return false; });
9e52ca32 189 return timer_stop(tv_start);
f7478de6
JG
190}
191
9e52ca32 192std::vector<double> benchmark_solve_equihash_threaded(int nThreads)
f7478de6 193{
9e52ca32
JG
194 std::vector<double> ret;
195 std::vector<std::future<double>> tasks;
196 std::vector<std::thread> threads;
197 for (int i = 0; i < nThreads; i++) {
198 std::packaged_task<double(void)> task(&benchmark_solve_equihash);
199 tasks.emplace_back(task.get_future());
200 threads.emplace_back(std::move(task));
201 }
202 std::future_status status;
203 for (auto it = tasks.begin(); it != tasks.end(); it++) {
204 it->wait();
205 ret.push_back(it->get());
206 }
207 for (auto it = threads.begin(); it != threads.end(); it++) {
208 it->join();
209 }
210 return ret;
bf8def97 211}
2cc0a252 212#endif // ENABLE_MINING
d44feea4 213
a1cd1a27 214double benchmark_verify_equihash()
d44feea4 215{
a1cd1a27
TH
216 CChainParams params = Params(CBaseChainParams::MAIN);
217 CBlock genesis = Params(CBaseChainParams::MAIN).GenesisBlock();
218 CBlockHeader genesis_header = genesis.GetBlockHeader();
9e52ca32
JG
219 struct timeval tv_start;
220 timer_start(tv_start);
a1cd1a27 221 CheckEquihashSolution(&genesis_header, params);
9e52ca32 222 return timer_stop(tv_start);
d44feea4 223}
a1cd1a27 224
818b94f9 225double benchmark_large_tx(size_t nInputs)
f5edc37f 226{
9c45b501
SB
227 // Create priv/pub key
228 CKey priv;
229 priv.MakeNewKey(false);
230 auto pub = priv.GetPubKey();
231 CBasicKeyStore tempKeystore;
232 tempKeystore.AddKey(priv);
233
234 // The "original" transaction that the spending transaction will spend
235 // from.
236 CMutableTransaction m_orig_tx;
237 m_orig_tx.vout.resize(1);
238 m_orig_tx.vout[0].nValue = 1000000;
239 CScript prevPubKey = GetScriptForDestination(pub.GetID());
240 m_orig_tx.vout[0].scriptPubKey = prevPubKey;
241
242 auto orig_tx = CTransaction(m_orig_tx);
243
244 CMutableTransaction spending_tx;
45539018 245 spending_tx.fOverwintered = true;
b1608eed 246 spending_tx.nVersion = OVERWINTER_TX_VERSION;
45539018
JG
247 spending_tx.nVersionGroupId = OVERWINTER_VERSION_GROUP_ID;
248
805344dc 249 auto input_hash = orig_tx.GetHash();
818b94f9
JG
250 // Add nInputs inputs
251 for (size_t i = 0; i < nInputs; i++) {
9c45b501 252 spending_tx.vin.emplace_back(input_hash, 0);
f5edc37f
JG
253 }
254
9c45b501 255 // Sign for all the inputs
be126699 256 auto consensusBranchId = NetworkUpgradeInfo[Consensus::UPGRADE_OVERWINTER].nBranchId;
818b94f9 257 for (size_t i = 0; i < nInputs; i++) {
be126699 258 SignSignature(tempKeystore, prevPubKey, spending_tx, i, 1000000, SIGHASH_ALL, consensusBranchId);
f5edc37f 259 }
f5edc37f 260
822b84b6
S
261 // Spending tx has all its inputs signed and does not need to be mutated anymore
262 CTransaction final_spending_tx(spending_tx);
263
9c45b501 264 // Benchmark signature verification costs:
9e52ca32
JG
265 struct timeval tv_start;
266 timer_start(tv_start);
45539018 267 PrecomputedTransactionData txdata(final_spending_tx);
818b94f9 268 for (size_t i = 0; i < nInputs; i++) {
9c45b501 269 ScriptError serror = SCRIPT_ERR_OK;
75c2f268 270 assert(VerifyScript(final_spending_tx.vin[i].scriptSig,
9c45b501
SB
271 prevPubKey,
272 STANDARD_SCRIPT_VERIFY_FLAGS,
45539018 273 TransactionSignatureChecker(&final_spending_tx, i, 1000000, txdata),
be126699 274 consensusBranchId,
9c45b501
SB
275 &serror));
276 }
9e52ca32 277 return timer_stop(tv_start);
f5edc37f
JG
278}
279
88b7f3c2 280double benchmark_try_decrypt_notes(size_t nAddrs)
0fbab55b 281{
0fbab55b 282 CWallet wallet;
88b7f3c2 283 for (int i = 0; i < nAddrs; i++) {
0fbab55b
JG
284 auto sk = libzcash::SpendingKey::random();
285 wallet.AddSpendingKey(sk);
286 }
287
88b7f3c2
JG
288 auto sk = libzcash::SpendingKey::random();
289 auto tx = GetValidReceive(*pzcashParams, sk, 10, true);
0fbab55b
JG
290
291 struct timeval tv_start;
292 timer_start(tv_start);
293 auto nd = wallet.FindMyNotes(tx);
294 return timer_stop(tv_start);
295}
296
0bb3d40f
JG
297double benchmark_increment_note_witnesses(size_t nTxs)
298{
299 CWallet wallet;
300 ZCIncrementalMerkleTree tree;
301
302 auto sk = libzcash::SpendingKey::random();
303 wallet.AddSpendingKey(sk);
304
305 // First block
306 CBlock block1;
307 for (int i = 0; i < nTxs; i++) {
308 auto wtx = GetValidReceive(*pzcashParams, sk, 10, true);
309 auto note = GetNote(*pzcashParams, sk, wtx, 0, 1);
310 auto nullifier = note.nullifier(sk);
311
312 mapNoteData_t noteData;
313 JSOutPoint jsoutpt {wtx.GetHash(), 0, 1};
314 CNoteData nd {sk.address(), nullifier};
315 noteData[jsoutpt] = nd;
316
317 wtx.SetNoteData(noteData);
318 wallet.AddToWallet(wtx, true, NULL);
319 block1.vtx.push_back(wtx);
320 }
321 CBlockIndex index1(block1);
322 index1.nHeight = 1;
323
324 // Increment to get transactions witnessed
325 wallet.ChainTip(&index1, &block1, tree, true);
326
327 // Second block
328 CBlock block2;
329 block2.hashPrevBlock = block1.GetHash();
9755eb82
JG
330 {
331 auto wtx = GetValidReceive(*pzcashParams, sk, 10, true);
332 auto note = GetNote(*pzcashParams, sk, wtx, 0, 1);
333 auto nullifier = note.nullifier(sk);
334
335 mapNoteData_t noteData;
336 JSOutPoint jsoutpt {wtx.GetHash(), 0, 1};
337 CNoteData nd {sk.address(), nullifier};
338 noteData[jsoutpt] = nd;
339
340 wtx.SetNoteData(noteData);
341 wallet.AddToWallet(wtx, true, NULL);
342 block2.vtx.push_back(wtx);
343 }
0bb3d40f
JG
344 CBlockIndex index2(block2);
345 index2.nHeight = 2;
346
347 struct timeval tv_start;
348 timer_start(tv_start);
349 wallet.ChainTip(&index2, &block2, tree, true);
350 return timer_stop(tv_start);
351}
352
c66c731a
JG
353// Fake the input of a given block
354class FakeCoinsViewDB : public CCoinsViewDB {
355 uint256 hash;
356 ZCIncrementalMerkleTree t;
357
358public:
359 FakeCoinsViewDB(std::string dbName, uint256& hash) : CCoinsViewDB(dbName, 100, false, false), hash(hash) {}
360
361 bool GetAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const {
362 if (rt == t.root()) {
363 tree = t;
364 return true;
365 }
366 return false;
367 }
368
708c87f1 369 bool GetNullifier(const uint256 &nf, NullifierType type) const {
c66c731a
JG
370 return false;
371 }
372
373 uint256 GetBestBlock() const {
374 return hash;
375 }
376
377 uint256 GetBestAnchor() const {
378 return t.root();
379 }
380
381 bool BatchWrite(CCoinsMap &mapCoins,
382 const uint256 &hashBlock,
383 const uint256 &hashAnchor,
384 CAnchorsMap &mapAnchors,
685e936c
EOW
385 CNullifiersMap &mapNullifiers,
386 CNullifiersMap& mapSaplingNullifiers) {
c66c731a
JG
387 return false;
388 }
389
390 bool GetStats(CCoinsStats &stats) const {
391 return false;
392 }
393};
394
395double benchmark_connectblock_slow()
396{
397 // Test for issue 2017-05-01.a
398 SelectParams(CBaseChainParams::MAIN);
399 CBlock block;
400 FILE* fp = fopen((GetDataDir() / "benchmark/block-107134.dat").string().c_str(), "rb");
401 if (!fp) throw new std::runtime_error("Failed to open block data file");
402 CAutoFile blkFile(fp, SER_DISK, CLIENT_VERSION);
403 blkFile >> block;
404 blkFile.fclose();
405
406 // Fake its inputs
407 auto hashPrev = uint256S("00000000159a41f468e22135942a567781c3f3dc7ad62257993eb3c69c3f95ef");
408 FakeCoinsViewDB fakeDB("benchmark/block-107134-inputs", hashPrev);
409 CCoinsViewCache view(&fakeDB);
410
411 // Fake the chain
412 CBlockIndex index(block);
413 index.nHeight = 107134;
414 CBlockIndex indexPrev;
415 indexPrev.phashBlock = &hashPrev;
416 indexPrev.nHeight = index.nHeight - 1;
417 index.pprev = &indexPrev;
418 mapBlockIndex.insert(std::make_pair(hashPrev, &indexPrev));
419
420 CValidationState state;
421 struct timeval tv_start;
422 timer_start(tv_start);
423 assert(ConnectBlock(block, state, &index, view, true));
424 auto duration = timer_stop(tv_start);
425
426 // Undo alterations to global state
427 mapBlockIndex.erase(hashPrev);
428 SelectParamsFromCommandLine();
429
430 return duration;
431}
432
a76174b7
JG
433double benchmark_sendtoaddress(CAmount amount)
434{
435 UniValue params(UniValue::VARR);
436 auto addr = getnewaddress(params, false);
437
438 params.push_back(addr);
439 params.push_back(ValueFromAmount(amount));
440
441 struct timeval tv_start;
442 timer_start(tv_start);
443 auto txid = sendtoaddress(params, false);
444 return timer_stop(tv_start);
445}
446
2e8aefdc
AG
447double benchmark_loadwallet()
448{
449 pre_wallet_load();
450 struct timeval tv_start;
451 bool fFirstRunRet=true;
452 timer_start(tv_start);
453 pwalletMain = new CWallet("wallet.dat");
454 DBErrors nLoadWalletRet = pwalletMain->LoadWallet(fFirstRunRet);
455 auto res = timer_stop(tv_start);
456 post_wallet_load();
457 return res;
458}
99dd50c3
JG
459
460double benchmark_listunspent()
461{
462 UniValue params(UniValue::VARR);
463 struct timeval tv_start;
464 timer_start(tv_start);
465 auto unspent = listunspent(params, false);
466 return timer_stop(tv_start);
467}
This page took 0.152125 seconds and 4 git commands to generate.