]> Git Repo - VerusCoin.git/blame_incremental - src/zcbenchmarks.cpp
Update librustzcash again
[VerusCoin.git] / src / zcbenchmarks.cpp
... / ...
CommitLineData
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 "rpcserver.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
34using namespace libzcash;
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
68
69void timer_start(timeval &tv_start)
70{
71 gettimeofday(&tv_start, 0);
72}
73
74double timer_stop(timeval &tv_start)
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{
86 struct timeval tv_start;
87 timer_start(tv_start);
88 sleep(1);
89 return timer_stop(tv_start);
90}
91
92double benchmark_parameter_loading()
93{
94 // FIXME: this is duplicated with the actual loading code
95 boost::filesystem::path pk_path = ZC_GetParamsDir() / "sprout-proving.key";
96 boost::filesystem::path vk_path = ZC_GetParamsDir() / "sprout-verifying.key";
97
98 struct timeval tv_start;
99 timer_start(tv_start);
100
101 auto newParams = ZCJoinSplit::Prepared(vk_path.string(), pk_path.string());
102
103 double ret = timer_stop(tv_start);
104
105 delete newParams;
106
107 return ret;
108}
109
110double benchmark_create_joinsplit()
111{
112 uint256 pubKeyHash;
113
114 /* Get the anchor of an empty commitment tree. */
115 uint256 anchor = ZCIncrementalMerkleTree().root();
116
117 struct timeval tv_start;
118 timer_start(tv_start);
119 JSDescription jsdesc(false, // TODO: ?
120 *pzcashParams,
121 pubKeyHash,
122 anchor,
123 {JSInput(), JSInput()},
124 {JSOutput(), JSOutput()},
125 0,
126 0);
127 double ret = timer_stop(tv_start);
128
129 auto verifier = libzcash::ProofVerifier::Strict();
130 assert(jsdesc.Verify(*pzcashParams, verifier, pubKeyHash));
131 return ret;
132}
133
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
155double benchmark_verify_joinsplit(const JSDescription &joinsplit)
156{
157 struct timeval tv_start;
158 timer_start(tv_start);
159 uint256 pubKeyHash;
160 auto verifier = libzcash::ProofVerifier::Strict();
161 joinsplit.Verify(*pzcashParams, verifier, pubKeyHash);
162 return timer_stop(tv_start);
163}
164
165#ifdef ENABLE_MINING
166double benchmark_solve_equihash()
167{
168 CBlock pblock;
169 CEquihashInput I{pblock};
170 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
171 ss << I;
172
173 unsigned int n = Params(CBaseChainParams::MAIN).EquihashN();
174 unsigned int k = Params(CBaseChainParams::MAIN).EquihashK();
175 crypto_generichash_blake2b_state eh_state;
176 EhInitialiseState(n, k, eh_state);
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
185 struct timeval tv_start;
186 timer_start(tv_start);
187 std::set<std::vector<unsigned int>> solns;
188 EhOptimisedSolveUncancellable(n, k, eh_state,
189 [](std::vector<unsigned char> soln) { return false; });
190 return timer_stop(tv_start);
191}
192
193std::vector<double> benchmark_solve_equihash_threaded(int nThreads)
194{
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;
212}
213#endif // ENABLE_MINING
214
215double benchmark_verify_equihash()
216{
217 CChainParams params = Params(CBaseChainParams::MAIN);
218 CBlock genesis = Params(CBaseChainParams::MAIN).GenesisBlock();
219 CBlockHeader genesis_header = genesis.GetBlockHeader();
220 struct timeval tv_start;
221 timer_start(tv_start);
222 CheckEquihashSolution(&genesis_header, params);
223 return timer_stop(tv_start);
224}
225
226double benchmark_large_tx(size_t nInputs)
227{
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;
246 spending_tx.fOverwintered = true;
247 spending_tx.nVersionGroupId = SAPLING_VERSION_GROUP_ID;
248 spending_tx.nVersion = SAPLING_TX_VERSION;
249
250 auto input_hash = orig_tx.GetHash();
251 // Add nInputs inputs
252 for (size_t i = 0; i < nInputs; i++) {
253 spending_tx.vin.emplace_back(input_hash, 0);
254 }
255
256 // Sign for all the inputs
257 auto consensusBranchId = NetworkUpgradeInfo[Consensus::UPGRADE_SAPLING].nBranchId;
258 for (size_t i = 0; i < nInputs; i++) {
259 SignSignature(tempKeystore, prevPubKey, spending_tx, i, 1000000, SIGHASH_ALL, consensusBranchId);
260 }
261
262 // Spending tx has all its inputs signed and does not need to be mutated anymore
263 CTransaction final_spending_tx(spending_tx);
264
265 // Benchmark signature verification costs:
266 struct timeval tv_start;
267 timer_start(tv_start);
268 PrecomputedTransactionData txdata(final_spending_tx);
269 for (size_t i = 0; i < nInputs; i++) {
270 ScriptError serror = SCRIPT_ERR_OK;
271 assert(VerifyScript(final_spending_tx.vin[i].scriptSig,
272 prevPubKey,
273 STANDARD_SCRIPT_VERIFY_FLAGS,
274 TransactionSignatureChecker(&final_spending_tx, i, 1000000, txdata),
275 consensusBranchId,
276 &serror));
277 }
278 return timer_stop(tv_start);
279}
280
281double benchmark_try_decrypt_notes(size_t nAddrs)
282{
283 CWallet wallet;
284 for (int i = 0; i < nAddrs; i++) {
285 auto sk = libzcash::SproutSpendingKey::random();
286 wallet.AddSpendingKey(sk);
287 }
288
289 auto sk = libzcash::SproutSpendingKey::random();
290 auto tx = GetValidReceive(*pzcashParams, sk, 10, true);
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
298double benchmark_increment_note_witnesses(size_t nTxs)
299{
300 CWallet wallet;
301 ZCIncrementalMerkleTree tree;
302
303 auto sk = libzcash::SproutSpendingKey::random();
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();
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 }
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
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
370 bool GetNullifier(const uint256 &nf, ShieldedType type) const {
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,
385 CAnchorsSproutMap &mapSproutAnchors,
386 CNullifiersMap &mapSproutNullifiers,
387 CNullifiersMap& mapSaplingNullifiers) {
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
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
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}
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.046314 seconds and 4 git commands to generate.