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