Auto merge of #846 - DoNotUseThisCodeJUSTFORKS:automated-performance-measurement-zcash-cli-method, r=ebfull

Automated performance measurement

Supersedes #843 because that one would have merged into the wrong branch. (Oh yeah and I rebased).

**REBASED AND FORCE PUSHED**
This commit is contained in:
zkbot
2016-04-11 21:56:12 +00:00
8 changed files with 342 additions and 1 deletions

View File

@@ -226,6 +226,7 @@ libbitcoin_server_a_SOURCES = \
# when wallet enabled
libbitcoin_wallet_a_CPPFLAGS = $(BITCOIN_INCLUDES)
libbitcoin_wallet_a_SOURCES = \
zcbenchmarks.cpp \
wallet/crypter.cpp \
wallet/db.cpp \
wallet/rpcdump.cpp \

View File

@@ -94,7 +94,8 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "zcrawpour", 1 },
{ "zcrawpour", 2 },
{ "zcrawpour", 3 },
{ "zcrawpour", 4 }
{ "zcrawpour", 4 },
{ "zcbenchmark", 1 }
};
class CRPCConvertTable

View File

@@ -376,6 +376,7 @@ static const CRPCCommand vRPCCommands[] =
{ "wallet", "walletlock", &walletlock, true },
{ "wallet", "walletpassphrasechange", &walletpassphrasechange, true },
{ "wallet", "walletpassphrase", &walletpassphrase, true },
{ "wallet", "zcbenchmark", &zc_benchmark, true },
{ "wallet", "zcrawkeygen", &zc_raw_keygen, true },
{ "wallet", "zcrawpour", &zc_raw_pour, true },
{ "wallet", "zcrawreceive", &zc_raw_receive, true }

View File

@@ -208,6 +208,7 @@ extern json_spirit::Value getblockchaininfo(const json_spirit::Array& params, bo
extern json_spirit::Value getnetworkinfo(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value setmocktime(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value resendwallettransactions(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value zc_benchmark(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value zc_raw_keygen(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value zc_raw_pour(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value zc_raw_receive(const json_spirit::Array& params, bool fHelp);

View File

@@ -17,6 +17,7 @@
#include "wallet.h"
#include "walletdb.h"
#include "primitives/transaction.h"
#include "zcbenchmarks.h"
#include <stdint.h>
@@ -2345,6 +2346,89 @@ Value listunspent(const Array& params, bool fHelp)
return results;
}
Value zc_benchmark(const json_spirit::Array& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp)) {
return Value::null;
}
if (fHelp || params.size() < 2) {
throw runtime_error(
"zcbenchmark benchmarktype samplecount\n"
"\n"
"Runs a benchmark of the selected type samplecount times,\n"
"returning the running times of each sample.\n"
"\n"
"Output: [\n"
" {\n"
" \"runningtime\": runningtime\n"
" },\n"
" {\n"
" \"runningtime\": runningtime\n"
" }\n"
" ...\n"
"]\n"
);
}
LOCK(cs_main);
std::string benchmarktype = params[0].get_str();
int samplecount = params[1].get_int();
if (samplecount <= 0) {
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid samplecount");
}
std::vector<double> sample_times;
if (benchmarktype == "createjoinsplit") {
/* Load the proving now key so that it doesn't happen as part of the
* first joinsplit. */
pzerocashParams->loadProvingKey();
}
for (int i = 0; i < samplecount; i++) {
if (benchmarktype == "sleep") {
sample_times.push_back(benchmark_sleep());
} else if (benchmarktype == "parameterloading") {
sample_times.push_back(benchmark_parameter_loading());
} else if (benchmarktype == "createjoinsplit") {
sample_times.push_back(benchmark_create_joinsplit());
} else if (benchmarktype == "verifyjoinsplit") {
if (params.size() != 3) {
throw JSONRPCError(RPC_TYPE_ERROR, "Please provide a transaction with a JoinSplit.");
}
CTransaction tx;
if (!DecodeHexTx(tx, params[2].get_str())) {
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
}
if (tx.vpour.size() != 1) {
throw JSONRPCError(RPC_TYPE_ERROR, "The transaction must have exactly one JoinSplit.");
}
sample_times.push_back(benchmark_verify_joinsplit(tx.vpour[0]));
} else if (benchmarktype == "solveequihash") {
sample_times.push_back(benchmark_solve_equihash());
} else if (benchmarktype == "verifyequihash") {
sample_times.push_back(benchmark_verify_equihash());
} else {
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid benchmarktype");
}
}
Array results;
for (int i = 0; i < samplecount; i++) {
Object result;
result.push_back(Pair("runningtime", sample_times.at(i)));
results.push_back(result);
}
return results;
}
Value zc_raw_receive(const json_spirit::Array& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp)) {

136
src/zcbenchmarks.cpp Normal file
View File

@@ -0,0 +1,136 @@
#include <unistd.h>
#include <boost/filesystem.hpp>
#include "zerocash/ZerocashParams.h"
#include "coins.h"
#include "util.h"
#include "init.h"
#include "primitives/transaction.h"
#include "crypto/equihash.h"
#include "chainparams.h"
#include "pow.h"
#include "sodium.h"
#include "streams.h"
#include "zcbenchmarks.h"
struct timeval tv_start;
void timer_start()
{
gettimeofday(&tv_start, 0);
}
double timer_stop()
{
double elapsed;
struct timeval tv_end;
gettimeofday(&tv_end, 0);
elapsed = double(tv_end.tv_sec-tv_start.tv_sec) +
(tv_end.tv_usec-tv_start.tv_usec)/double(1000000);
return elapsed;
}
double benchmark_sleep()
{
timer_start();
sleep(1);
return timer_stop();
}
double benchmark_parameter_loading()
{
// FIXME: this is duplicated with the actual loading code
boost::filesystem::path pk_path = ZC_GetParamsDir() / "zc-testnet-public-alpha-proving.key";
boost::filesystem::path vk_path = ZC_GetParamsDir() / "zc-testnet-public-alpha-verification.key";
timer_start();
auto vk_loaded = libzerocash::ZerocashParams::LoadVerificationKeyFromFile(
vk_path.string(),
INCREMENTAL_MERKLE_TREE_DEPTH
);
auto pk_loaded = libzerocash::ZerocashParams::LoadProvingKeyFromFile(
pk_path.string(),
INCREMENTAL_MERKLE_TREE_DEPTH
);
libzerocash::ZerocashParams zerocashParams = libzerocash::ZerocashParams(
INCREMENTAL_MERKLE_TREE_DEPTH,
&pk_loaded,
&vk_loaded
);
return timer_stop();
}
double benchmark_create_joinsplit()
{
CScript scriptPubKey;
std::vector<PourInput> vpourin;
std::vector<PourOutput> vpourout;
while (vpourin.size() < NUM_POUR_INPUTS) {
vpourin.push_back(PourInput(INCREMENTAL_MERKLE_TREE_DEPTH));
}
while (vpourout.size() < NUM_POUR_OUTPUTS) {
vpourout.push_back(PourOutput(0));
}
/* Get the anchor of an empty commitment tree. */
IncrementalMerkleTree blank_tree(INCREMENTAL_MERKLE_TREE_DEPTH);
std::vector<unsigned char> newrt_v(32);
blank_tree.getRootValue(newrt_v);
uint256 anchor = uint256(newrt_v);
timer_start();
CPourTx pourtx(*pzerocashParams,
scriptPubKey,
anchor,
{vpourin[0], vpourin[1]},
{vpourout[0], vpourout[1]},
0,
0);
double ret = timer_stop();
assert(pourtx.Verify(*pzerocashParams));
return ret;
}
double benchmark_verify_joinsplit(const CPourTx &joinsplit)
{
timer_start();
joinsplit.Verify(*pzerocashParams);
return timer_stop();
}
double benchmark_solve_equihash()
{
CBlock pblock;
CEquihashInput I{pblock};
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << I;
Equihash eh {Params(CBaseChainParams::MAIN).EquihashN(), Params(CBaseChainParams::MAIN).EquihashK()};
crypto_generichash_blake2b_state eh_state;
eh.InitialiseState(eh_state);
crypto_generichash_blake2b_update(&eh_state, (unsigned char*)&ss[0], ss.size());
uint256 nonce;
randombytes_buf(nonce.begin(), 32);
crypto_generichash_blake2b_update(&eh_state,
nonce.begin(),
nonce.size());
timer_start();
eh.BasicSolve(eh_state);
return timer_stop();
}
double benchmark_verify_equihash()
{
CChainParams params = Params(CBaseChainParams::MAIN);
CBlock genesis = Params(CBaseChainParams::MAIN).GenesisBlock();
CBlockHeader genesis_header = genesis.GetBlockHeader();
timer_start();
CheckEquihashSolution(&genesis_header, params);
return timer_stop();
}

14
src/zcbenchmarks.h Normal file
View File

@@ -0,0 +1,14 @@
#ifndef BENCHMARKS_H
#define BENCHMARKS_H
#include <sys/time.h>
#include <stdlib.h>
extern double benchmark_sleep();
extern double benchmark_parameter_loading();
extern double benchmark_create_joinsplit();
extern double benchmark_solve_equihash();
extern double benchmark_verify_joinsplit(const CPourTx &joinsplit);
extern double benchmark_verify_equihash();
#endif