Browse Source

Add benchmark for incrementing note witnesses

v1.0.9-lin
Jack Grigg 8 years ago
parent
commit
0bb3d40f90
No known key found for this signature in database GPG Key ID: 6A6914DAFBEA00DA
  1. 9
      qa/zcash/performance-measurements.sh
  2. 2
      src/Makefile.am
  3. 5
      src/Makefile.gtest.include
  4. 144
      src/utiltest.cpp
  5. 18
      src/utiltest.h
  6. 128
      src/wallet/gtest/test_wallet.cpp
  7. 3
      src/wallet/rpcwallet.cpp
  8. 43
      src/zcbenchmarks.cpp
  9. 1
      src/zcbenchmarks.h

9
qa/zcash/performance-measurements.sh

@ -91,6 +91,9 @@ case "$1" in
trydecryptnotes)
zcash_rpc zcbenchmark trydecryptnotes 1000 "\"$RAWJOINSPLIT\""
;;
incnotewitnesses)
zcash_rpc zcbenchmark incnotewitnesses 100 "${@:3}"
;;
*)
zcashd_stop
echo "Bad arguments."
@ -122,6 +125,9 @@ case "$1" in
trydecryptnotes)
zcash_rpc zcbenchmark trydecryptnotes 1 "\"$RAWJOINSPLIT\""
;;
incnotewitnesses)
zcash_rpc zcbenchmark incnotewitnesses 1 "${@:3}"
;;
*)
zcashd_massif_stop
echo "Bad arguments."
@ -154,6 +160,9 @@ case "$1" in
trydecryptnotes)
zcash_rpc zcbenchmark trydecryptnotes 1 "\"$RAWJOINSPLIT\""
;;
incnotewitnesses)
zcash_rpc zcbenchmark incnotewitnesses 1 "${@:3}"
;;
*)
zcashd_valgrind_stop
echo "Bad arguments."

2
src/Makefile.am

@ -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 \

5
src/Makefile.gtest.include

@ -27,8 +27,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

144
src/utiltest.cpp

@ -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
src/utiltest.h

@ -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
src/wallet/gtest/test_wallet.cpp

@ -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"
@ -65,138 +66,17 @@ public:
};
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) {

3
src/wallet/rpcwallet.cpp

@ -2483,6 +2483,9 @@ Value zc_benchmark(const json_spirit::Array& params, bool fHelp)
sample_times.push_back(benchmark_large_tx());
} else if (benchmarktype == "trydecryptnotes") {
sample_times.push_back(benchmark_try_decrypt_notes(samplejoinsplit));
} 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");
}

43
src/zcbenchmarks.cpp

@ -17,6 +17,7 @@
#include "script/sign.h"
#include "sodium.h"
#include "streams.h"
#include "utiltest.h"
#include "wallet/wallet.h"
#include "zcbenchmarks.h"
@ -243,3 +244,45 @@ double benchmark_try_decrypt_notes(const JSDescription &joinsplit)
return timer_stop(tv_start);
}
double benchmark_increment_note_witnesses(size_t nTxs)
{
CWallet wallet;
ZCIncrementalMerkleTree tree;
auto sk = libzcash::SpendingKey::random();
wallet.AddSpendingKey(sk);
// First block
CBlock block1;
for (int i = 0; i < nTxs; i++) {
auto wtx = GetValidReceive(*pzcashParams, sk, 10, true);
auto note = GetNote(*pzcashParams, sk, wtx, 0, 1);
auto nullifier = note.nullifier(sk);
mapNoteData_t noteData;
JSOutPoint jsoutpt {wtx.GetHash(), 0, 1};
CNoteData nd {sk.address(), nullifier};
noteData[jsoutpt] = nd;
wtx.SetNoteData(noteData);
wallet.AddToWallet(wtx, true, NULL);
block1.vtx.push_back(wtx);
}
CBlockIndex index1(block1);
index1.nHeight = 1;
// Increment to get transactions witnessed
wallet.ChainTip(&index1, &block1, tree, true);
// Second block
CBlock block2;
block2.hashPrevBlock = block1.GetHash();
CBlockIndex index2(block2);
index2.nHeight = 2;
struct timeval tv_start;
timer_start(tv_start);
wallet.ChainTip(&index2, &block2, tree, true);
return timer_stop(tv_start);
}

1
src/zcbenchmarks.h

@ -13,5 +13,6 @@ extern double benchmark_verify_joinsplit(const JSDescription &joinsplit);
extern double benchmark_verify_equihash();
extern double benchmark_large_tx();
extern double benchmark_try_decrypt_notes(const JSDescription &joinsplit);
extern double benchmark_increment_note_witnesses(size_t nTxs);
#endif

Loading…
Cancel
Save