Skip to content

Commit

Permalink
Auto merge of zcash#1870 - str4d:1749-benchmark-rescanning, r=str4d
Browse files Browse the repository at this point in the history
Add benchmarks for rescan components

Part of zcash#1749.
  • Loading branch information
zkbot committed Dec 9, 2016
2 parents a398121 + 9755eb8 commit 8a6c070
Show file tree
Hide file tree
Showing 9 changed files with 272 additions and 125 deletions.
18 changes: 18 additions & 0 deletions qa/zcash/performance-measurements.sh
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,12 @@ case "$1" in
validatelargetx)
zcash_rpc zcbenchmark validatelargetx 5
;;
trydecryptnotes)
zcash_rpc zcbenchmark trydecryptnotes 1000 "${@:3}"
;;
incnotewitnesses)
zcash_rpc zcbenchmark incnotewitnesses 100 "${@:3}"
;;
*)
zcashd_stop
echo "Bad arguments."
Expand Down Expand Up @@ -116,6 +122,12 @@ case "$1" in
verifyequihash)
zcash_rpc zcbenchmark verifyequihash 1
;;
trydecryptnotes)
zcash_rpc zcbenchmark trydecryptnotes 1 "${@:3}"
;;
incnotewitnesses)
zcash_rpc zcbenchmark incnotewitnesses 1 "${@:3}"
;;
*)
zcashd_massif_stop
echo "Bad arguments."
Expand Down Expand Up @@ -145,6 +157,12 @@ case "$1" in
verifyequihash)
zcash_rpc zcbenchmark verifyequihash 1
;;
trydecryptnotes)
zcash_rpc zcbenchmark trydecryptnotes 1 "${@:3}"
;;
incnotewitnesses)
zcash_rpc zcbenchmark incnotewitnesses 1 "${@:3}"
;;
*)
zcashd_valgrind_stop
echo "Bad arguments."
Expand Down
2 changes: 2 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,8 @@ libbitcoin_server_a_SOURCES = \
# when wallet enabled
libbitcoin_wallet_a_CPPFLAGS = $(BITCOIN_INCLUDES)
libbitcoin_wallet_a_SOURCES = \
utiltest.cpp \
utiltest.h \
zcbenchmarks.cpp \
zcbenchmarks.h \
wallet/asyncrpcoperation_sendmany.cpp \
Expand Down
5 changes: 4 additions & 1 deletion src/Makefile.gtest.include
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,11 @@ zcash_gtest_SOURCES = \
gtest/test_txid.cpp \
gtest/test_libzcash_utils.cpp \
gtest/test_proofs.cpp \
gtest/test_checkblock.cpp \
gtest/test_checkblock.cpp
if ENABLE_WALLET
zcash_gtest_SOURCES += \
wallet/gtest/test_wallet.cpp
endif

zcash_gtest_CPPFLAGS = -DMULTICORE -fopenmp -DBINARY_OUTPUT -DCURVE_ALT_BN128 -DSTATIC

Expand Down
144 changes: 144 additions & 0 deletions src/utiltest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
// Copyright (c) 2016 The Zcash developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "utiltest.h"

CWalletTx GetValidReceive(ZCJoinSplit& params,
const libzcash::SpendingKey& sk, CAmount value,
bool randomInputs) {
CMutableTransaction mtx;
mtx.nVersion = 2; // Enable JoinSplits
mtx.vin.resize(2);
if (randomInputs) {
mtx.vin[0].prevout.hash = GetRandHash();
mtx.vin[1].prevout.hash = GetRandHash();
} else {
mtx.vin[0].prevout.hash = uint256S("0000000000000000000000000000000000000000000000000000000000000001");
mtx.vin[1].prevout.hash = uint256S("0000000000000000000000000000000000000000000000000000000000000002");
}
mtx.vin[0].prevout.n = 0;
mtx.vin[1].prevout.n = 0;

// Generate an ephemeral keypair.
uint256 joinSplitPubKey;
unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES];
crypto_sign_keypair(joinSplitPubKey.begin(), joinSplitPrivKey);
mtx.joinSplitPubKey = joinSplitPubKey;

boost::array<libzcash::JSInput, 2> inputs = {
libzcash::JSInput(), // dummy input
libzcash::JSInput() // dummy input
};

boost::array<libzcash::JSOutput, 2> outputs = {
libzcash::JSOutput(sk.address(), value),
libzcash::JSOutput(sk.address(), value)
};

boost::array<libzcash::Note, 2> output_notes;

// Prepare JoinSplits
uint256 rt;
JSDescription jsdesc {params, mtx.joinSplitPubKey, rt,
inputs, outputs, 2*value, 0, false};
mtx.vjoinsplit.push_back(jsdesc);

// Empty output script.
CScript scriptCode;
CTransaction signTx(mtx);
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL);

// Add the signature
assert(crypto_sign_detached(&mtx.joinSplitSig[0], NULL,
dataToBeSigned.begin(), 32,
joinSplitPrivKey
) == 0);

CTransaction tx {mtx};
CWalletTx wtx {NULL, tx};
return wtx;
}

libzcash::Note GetNote(ZCJoinSplit& params,
const libzcash::SpendingKey& sk,
const CTransaction& tx, size_t js, size_t n) {
ZCNoteDecryption decryptor {sk.viewing_key()};
auto hSig = tx.vjoinsplit[js].h_sig(params, tx.joinSplitPubKey);
auto note_pt = libzcash::NotePlaintext::decrypt(
decryptor,
tx.vjoinsplit[js].ciphertexts[n],
tx.vjoinsplit[js].ephemeralKey,
hSig,
(unsigned char) n);
return note_pt.note(sk.address());
}

CWalletTx GetValidSpend(ZCJoinSplit& params,
const libzcash::SpendingKey& sk,
const libzcash::Note& note, CAmount value) {
CMutableTransaction mtx;
mtx.vout.resize(2);
mtx.vout[0].nValue = value;
mtx.vout[1].nValue = 0;

// Generate an ephemeral keypair.
uint256 joinSplitPubKey;
unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES];
crypto_sign_keypair(joinSplitPubKey.begin(), joinSplitPrivKey);
mtx.joinSplitPubKey = joinSplitPubKey;

// Fake tree for the unused witness
ZCIncrementalMerkleTree tree;

libzcash::JSOutput dummyout;
libzcash::JSInput dummyin;

{
if (note.value > value) {
libzcash::SpendingKey dummykey = libzcash::SpendingKey::random();
libzcash::PaymentAddress dummyaddr = dummykey.address();
dummyout = libzcash::JSOutput(dummyaddr, note.value - value);
} else if (note.value < value) {
libzcash::SpendingKey dummykey = libzcash::SpendingKey::random();
libzcash::PaymentAddress dummyaddr = dummykey.address();
libzcash::Note dummynote(dummyaddr.a_pk, (value - note.value), uint256(), uint256());
tree.append(dummynote.cm());
dummyin = libzcash::JSInput(tree.witness(), dummynote, dummykey);
}
}

tree.append(note.cm());

boost::array<libzcash::JSInput, 2> inputs = {
libzcash::JSInput(tree.witness(), note, sk),
dummyin
};

boost::array<libzcash::JSOutput, 2> outputs = {
dummyout, // dummy output
libzcash::JSOutput() // dummy output
};

boost::array<libzcash::Note, 2> output_notes;

// Prepare JoinSplits
uint256 rt = tree.root();
JSDescription jsdesc {params, mtx.joinSplitPubKey, rt,
inputs, outputs, 0, value, false};
mtx.vjoinsplit.push_back(jsdesc);

// Empty output script.
CScript scriptCode;
CTransaction signTx(mtx);
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL);

// Add the signature
assert(crypto_sign_detached(&mtx.joinSplitSig[0], NULL,
dataToBeSigned.begin(), 32,
joinSplitPrivKey
) == 0);
CTransaction tx {mtx};
CWalletTx wtx {NULL, tx};
return wtx;
}
18 changes: 18 additions & 0 deletions src/utiltest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright (c) 2016 The Zcash developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "wallet/wallet.h"
#include "zcash/JoinSplit.hpp"
#include "zcash/Note.hpp"
#include "zcash/NoteEncryption.hpp"

CWalletTx GetValidReceive(ZCJoinSplit& params,
const libzcash::SpendingKey& sk, CAmount value,
bool randomInputs);
libzcash::Note GetNote(ZCJoinSplit& params,
const libzcash::SpendingKey& sk,
const CTransaction& tx, size_t js, size_t n);
CWalletTx GetValidSpend(ZCJoinSplit& params,
const libzcash::SpendingKey& sk,
const libzcash::Note& note, CAmount value);
128 changes: 4 additions & 124 deletions src/wallet/gtest/test_wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "chainparams.h"
#include "main.h"
#include "random.h"
#include "utiltest.h"
#include "wallet/wallet.h"
#include "zcash/JoinSplit.hpp"
#include "zcash/Note.hpp"
Expand Down Expand Up @@ -65,138 +66,17 @@ class TestWallet : public CWallet {
};

CWalletTx GetValidReceive(const libzcash::SpendingKey& sk, CAmount value, bool randomInputs) {
CMutableTransaction mtx;
mtx.nVersion = 2; // Enable JoinSplits
mtx.vin.resize(2);
if (randomInputs) {
mtx.vin[0].prevout.hash = GetRandHash();
mtx.vin[1].prevout.hash = GetRandHash();
} else {
mtx.vin[0].prevout.hash = uint256S("0000000000000000000000000000000000000000000000000000000000000001");
mtx.vin[1].prevout.hash = uint256S("0000000000000000000000000000000000000000000000000000000000000002");
}
mtx.vin[0].prevout.n = 0;
mtx.vin[1].prevout.n = 0;

// Generate an ephemeral keypair.
uint256 joinSplitPubKey;
unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES];
crypto_sign_keypair(joinSplitPubKey.begin(), joinSplitPrivKey);
mtx.joinSplitPubKey = joinSplitPubKey;

boost::array<libzcash::JSInput, 2> inputs = {
libzcash::JSInput(), // dummy input
libzcash::JSInput() // dummy input
};

boost::array<libzcash::JSOutput, 2> outputs = {
libzcash::JSOutput(sk.address(), value),
libzcash::JSOutput(sk.address(), value)
};

boost::array<libzcash::Note, 2> output_notes;

// Prepare JoinSplits
uint256 rt;
JSDescription jsdesc {*params, mtx.joinSplitPubKey, rt,
inputs, outputs, 2*value, 0, false};
mtx.vjoinsplit.push_back(jsdesc);

// Empty output script.
CScript scriptCode;
CTransaction signTx(mtx);
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL);

// Add the signature
assert(crypto_sign_detached(&mtx.joinSplitSig[0], NULL,
dataToBeSigned.begin(), 32,
joinSplitPrivKey
) == 0);

CTransaction tx {mtx};
CWalletTx wtx {NULL, tx};
return wtx;
return GetValidReceive(*params, sk, value, randomInputs);
}

libzcash::Note GetNote(const libzcash::SpendingKey& sk,
const CTransaction& tx, size_t js, size_t n) {
ZCNoteDecryption decryptor {sk.viewing_key()};
auto hSig = tx.vjoinsplit[js].h_sig(*params, tx.joinSplitPubKey);
auto note_pt = libzcash::NotePlaintext::decrypt(
decryptor,
tx.vjoinsplit[js].ciphertexts[n],
tx.vjoinsplit[js].ephemeralKey,
hSig,
(unsigned char) n);
return note_pt.note(sk.address());
return GetNote(*params, sk, tx, js, n);
}

CWalletTx GetValidSpend(const libzcash::SpendingKey& sk,
const libzcash::Note& note, CAmount value) {
CMutableTransaction mtx;
mtx.vout.resize(2);
mtx.vout[0].nValue = value;
mtx.vout[1].nValue = 0;

// Generate an ephemeral keypair.
uint256 joinSplitPubKey;
unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES];
crypto_sign_keypair(joinSplitPubKey.begin(), joinSplitPrivKey);
mtx.joinSplitPubKey = joinSplitPubKey;

// Fake tree for the unused witness
ZCIncrementalMerkleTree tree;

libzcash::JSOutput dummyout;
libzcash::JSInput dummyin;

{
if (note.value > value) {
libzcash::SpendingKey dummykey = libzcash::SpendingKey::random();
libzcash::PaymentAddress dummyaddr = dummykey.address();
dummyout = libzcash::JSOutput(dummyaddr, note.value - value);
} else if (note.value < value) {
libzcash::SpendingKey dummykey = libzcash::SpendingKey::random();
libzcash::PaymentAddress dummyaddr = dummykey.address();
libzcash::Note dummynote(dummyaddr.a_pk, (value - note.value), uint256(), uint256());
tree.append(dummynote.cm());
dummyin = libzcash::JSInput(tree.witness(), dummynote, dummykey);
}
}

tree.append(note.cm());

boost::array<libzcash::JSInput, 2> inputs = {
libzcash::JSInput(tree.witness(), note, sk),
dummyin
};

boost::array<libzcash::JSOutput, 2> outputs = {
dummyout, // dummy output
libzcash::JSOutput() // dummy output
};

boost::array<libzcash::Note, 2> output_notes;

// Prepare JoinSplits
uint256 rt = tree.root();
JSDescription jsdesc {*params, mtx.joinSplitPubKey, rt,
inputs, outputs, 0, value, false};
mtx.vjoinsplit.push_back(jsdesc);

// Empty output script.
CScript scriptCode;
CTransaction signTx(mtx);
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL);

// Add the signature
assert(crypto_sign_detached(&mtx.joinSplitSig[0], NULL,
dataToBeSigned.begin(), 32,
joinSplitPrivKey
) == 0);
CTransaction tx {mtx};
CWalletTx wtx {NULL, tx};
return wtx;
return GetValidSpend(*params, sk, note, value);
}

TEST(wallet_tests, setup_datadir_location_run_as_first_test) {
Expand Down
6 changes: 6 additions & 0 deletions src/wallet/rpcwallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2480,6 +2480,12 @@ Value zc_benchmark(const json_spirit::Array& params, bool fHelp)
sample_times.push_back(benchmark_verify_equihash());
} else if (benchmarktype == "validatelargetx") {
sample_times.push_back(benchmark_large_tx());
} else if (benchmarktype == "trydecryptnotes") {
int nAddrs = params[2].get_int();
sample_times.push_back(benchmark_try_decrypt_notes(nAddrs));
} else if (benchmarktype == "incnotewitnesses") {
int nTxs = params[2].get_int();
sample_times.push_back(benchmark_increment_note_witnesses(nTxs));
} else {
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid benchmarktype");
}
Expand Down
Loading

0 comments on commit 8a6c070

Please sign in to comment.