2016-04-07 14:37:39 -07:00
|
|
|
#include <unistd.h>
|
|
|
|
#include <boost/filesystem.hpp>
|
2016-08-04 20:05:38 -07:00
|
|
|
#include <boost/thread.hpp>
|
2016-04-07 14:37:39 -07:00
|
|
|
#include "coins.h"
|
|
|
|
#include "util.h"
|
|
|
|
#include "init.h"
|
|
|
|
#include "primitives/transaction.h"
|
2016-06-07 16:28:12 -07:00
|
|
|
#include "base58.h"
|
2016-04-11 07:05:13 -07:00
|
|
|
#include "crypto/equihash.h"
|
|
|
|
#include "chainparams.h"
|
2016-06-07 16:28:12 -07:00
|
|
|
#include "consensus/validation.h"
|
|
|
|
#include "main.h"
|
|
|
|
#include "miner.h"
|
2016-04-11 09:02:09 -07:00
|
|
|
#include "pow.h"
|
2016-06-07 16:28:12 -07:00
|
|
|
#include "script/sign.h"
|
2016-04-11 10:51:12 -07:00
|
|
|
#include "sodium.h"
|
|
|
|
#include "streams.h"
|
2016-06-07 16:28:12 -07:00
|
|
|
#include "wallet/wallet.h"
|
2016-04-07 14:37:39 -07:00
|
|
|
|
|
|
|
#include "zcbenchmarks.h"
|
|
|
|
|
2016-05-04 17:26:21 -07:00
|
|
|
#include "zcash/Zcash.h"
|
|
|
|
#include "zcash/IncrementalMerkleTree.hpp"
|
|
|
|
|
|
|
|
using namespace libzcash;
|
|
|
|
|
2016-04-07 14:37:39 -07:00
|
|
|
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
|
2016-08-18 12:17:55 -07:00
|
|
|
boost::filesystem::path pk_path = ZC_GetParamsDir() / "z9-proving.key";
|
|
|
|
boost::filesystem::path vk_path = ZC_GetParamsDir() / "z9-verifying.key";
|
2016-04-07 14:37:39 -07:00
|
|
|
|
|
|
|
timer_start();
|
2016-05-04 17:26:21 -07:00
|
|
|
|
|
|
|
auto newParams = ZCJoinSplit::Unopened();
|
|
|
|
|
|
|
|
newParams->loadVerifyingKey(vk_path.string());
|
|
|
|
newParams->setProvingKeyPath(pk_path.string());
|
|
|
|
newParams->loadProvingKey();
|
|
|
|
|
|
|
|
double ret = timer_stop();
|
|
|
|
|
|
|
|
delete newParams;
|
|
|
|
|
|
|
|
return ret;
|
2016-04-07 14:37:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
double benchmark_create_joinsplit()
|
|
|
|
{
|
2016-05-04 17:26:19 -07:00
|
|
|
uint256 pubKeyHash;
|
2016-04-07 14:37:39 -07:00
|
|
|
|
|
|
|
/* Get the anchor of an empty commitment tree. */
|
2016-05-04 17:25:38 -07:00
|
|
|
uint256 anchor = ZCIncrementalMerkleTree().root();
|
2016-04-07 14:37:39 -07:00
|
|
|
|
|
|
|
timer_start();
|
2016-07-16 15:45:41 -07:00
|
|
|
JSDescription jsdesc(*pzcashParams,
|
|
|
|
pubKeyHash,
|
|
|
|
anchor,
|
|
|
|
{JSInput(), JSInput()},
|
|
|
|
{JSOutput(), JSOutput()},
|
|
|
|
0,
|
|
|
|
0);
|
2016-04-07 14:37:39 -07:00
|
|
|
double ret = timer_stop();
|
2016-05-04 17:26:19 -07:00
|
|
|
|
2016-07-16 15:45:41 -07:00
|
|
|
assert(jsdesc.Verify(*pzcashParams, pubKeyHash));
|
2016-04-07 14:37:39 -07:00
|
|
|
return ret;
|
|
|
|
}
|
2016-04-11 07:05:13 -07:00
|
|
|
|
2016-07-10 22:02:10 -07:00
|
|
|
double benchmark_verify_joinsplit(const JSDescription &joinsplit)
|
2016-04-11 09:02:09 -07:00
|
|
|
{
|
|
|
|
timer_start();
|
2016-05-04 17:26:19 -07:00
|
|
|
uint256 pubKeyHash;
|
2016-05-04 17:26:21 -07:00
|
|
|
joinsplit.Verify(*pzcashParams, pubKeyHash);
|
2016-04-11 09:02:09 -07:00
|
|
|
return timer_stop();
|
|
|
|
}
|
|
|
|
|
2016-08-04 20:05:38 -07:00
|
|
|
double benchmark_solve_equihash(bool time)
|
2016-04-11 07:05:13 -07:00
|
|
|
{
|
2016-04-11 10:51:12 -07:00
|
|
|
CBlock pblock;
|
|
|
|
CEquihashInput I{pblock};
|
|
|
|
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
|
|
|
ss << I;
|
|
|
|
|
2016-05-04 20:00:44 -07:00
|
|
|
unsigned int n = Params(CBaseChainParams::MAIN).EquihashN();
|
|
|
|
unsigned int k = Params(CBaseChainParams::MAIN).EquihashK();
|
2016-04-11 07:05:13 -07:00
|
|
|
crypto_generichash_blake2b_state eh_state;
|
2016-05-04 20:00:44 -07:00
|
|
|
EhInitialiseState(n, k, eh_state);
|
2016-04-11 10:51:12 -07:00
|
|
|
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());
|
|
|
|
|
2016-08-04 20:05:38 -07:00
|
|
|
if (time)
|
|
|
|
timer_start();
|
2016-05-04 20:00:44 -07:00
|
|
|
std::set<std::vector<unsigned int>> solns;
|
2016-07-27 00:15:49 -07:00
|
|
|
EhOptimisedSolveUncancellable(n, k, eh_state,
|
2016-08-13 20:04:13 -07:00
|
|
|
[](std::vector<unsigned char> soln) { return false; });
|
2016-08-04 20:05:38 -07:00
|
|
|
if (time)
|
|
|
|
return timer_stop();
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
double benchmark_solve_equihash_threaded(int nThreads)
|
|
|
|
{
|
|
|
|
boost::thread_group solverThreads;
|
|
|
|
timer_start();
|
|
|
|
for (int i = 0; i < nThreads; i++)
|
|
|
|
solverThreads.create_thread(boost::bind(&benchmark_solve_equihash, false));
|
|
|
|
solverThreads.join_all();
|
2016-04-11 07:05:13 -07:00
|
|
|
return timer_stop();
|
|
|
|
}
|
2016-04-11 08:17:02 -07:00
|
|
|
|
2016-04-11 09:02:09 -07:00
|
|
|
double benchmark_verify_equihash()
|
2016-04-11 08:17:02 -07:00
|
|
|
{
|
2016-04-11 09:02:09 -07:00
|
|
|
CChainParams params = Params(CBaseChainParams::MAIN);
|
|
|
|
CBlock genesis = Params(CBaseChainParams::MAIN).GenesisBlock();
|
|
|
|
CBlockHeader genesis_header = genesis.GetBlockHeader();
|
2016-04-11 08:17:02 -07:00
|
|
|
timer_start();
|
2016-04-11 09:02:09 -07:00
|
|
|
CheckEquihashSolution(&genesis_header, params);
|
2016-04-11 08:17:02 -07:00
|
|
|
return timer_stop();
|
|
|
|
}
|
2016-04-11 09:02:09 -07:00
|
|
|
|
2016-07-06 11:07:50 -07:00
|
|
|
double benchmark_large_tx()
|
2016-06-07 16:28:12 -07:00
|
|
|
{
|
2016-07-06 11:07:50 -07:00
|
|
|
// Number of inputs in the spending transaction that we will simulate
|
2016-07-07 15:53:16 -07:00
|
|
|
const size_t NUM_INPUTS = 11100;
|
2016-07-06 11:07:50 -07:00
|
|
|
|
|
|
|
// Create priv/pub key
|
|
|
|
CKey priv;
|
|
|
|
priv.MakeNewKey(false);
|
|
|
|
auto pub = priv.GetPubKey();
|
|
|
|
CBasicKeyStore tempKeystore;
|
|
|
|
tempKeystore.AddKey(priv);
|
|
|
|
|
|
|
|
// The "original" transaction that the spending transaction will spend
|
|
|
|
// from.
|
|
|
|
CMutableTransaction m_orig_tx;
|
|
|
|
m_orig_tx.vout.resize(1);
|
|
|
|
m_orig_tx.vout[0].nValue = 1000000;
|
|
|
|
CScript prevPubKey = GetScriptForDestination(pub.GetID());
|
|
|
|
m_orig_tx.vout[0].scriptPubKey = prevPubKey;
|
|
|
|
|
|
|
|
auto orig_tx = CTransaction(m_orig_tx);
|
|
|
|
|
|
|
|
CMutableTransaction spending_tx;
|
2016-08-30 12:49:38 -07:00
|
|
|
auto input_hash = orig_tx.GetHash();
|
2016-07-06 11:07:50 -07:00
|
|
|
// Add NUM_INPUTS inputs
|
|
|
|
for (size_t i = 0; i < NUM_INPUTS; i++) {
|
|
|
|
spending_tx.vin.emplace_back(input_hash, 0);
|
2016-06-07 16:28:12 -07:00
|
|
|
}
|
|
|
|
|
2016-07-06 11:07:50 -07:00
|
|
|
// Sign for all the inputs
|
|
|
|
for (size_t i = 0; i < NUM_INPUTS; i++) {
|
|
|
|
SignSignature(tempKeystore, prevPubKey, spending_tx, i, SIGHASH_ALL);
|
2016-06-07 16:28:12 -07:00
|
|
|
}
|
|
|
|
|
2016-07-06 11:07:50 -07:00
|
|
|
// Serialize:
|
|
|
|
{
|
|
|
|
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
|
|
|
ss << spending_tx;
|
|
|
|
//std::cout << "SIZE OF SPENDING TX: " << ss.size() << std::endl;
|
2016-06-07 16:28:12 -07:00
|
|
|
|
2016-07-06 11:07:50 -07:00
|
|
|
auto error = MAX_BLOCK_SIZE / 20; // 5% error
|
|
|
|
assert(ss.size() < MAX_BLOCK_SIZE + error);
|
|
|
|
assert(ss.size() > MAX_BLOCK_SIZE - error);
|
2016-06-07 16:28:12 -07:00
|
|
|
}
|
|
|
|
|
2016-08-07 23:54:50 -07:00
|
|
|
// Spending tx has all its inputs signed and does not need to be mutated anymore
|
|
|
|
CTransaction final_spending_tx(spending_tx);
|
|
|
|
|
2016-07-06 11:07:50 -07:00
|
|
|
// Benchmark signature verification costs:
|
2016-06-07 16:28:12 -07:00
|
|
|
timer_start();
|
2016-07-06 11:07:50 -07:00
|
|
|
for (size_t i = 0; i < NUM_INPUTS; i++) {
|
|
|
|
ScriptError serror = SCRIPT_ERR_OK;
|
2016-08-08 00:51:27 -07:00
|
|
|
assert(VerifyScript(final_spending_tx.vin[i].scriptSig,
|
2016-07-06 11:07:50 -07:00
|
|
|
prevPubKey,
|
|
|
|
STANDARD_SCRIPT_VERIFY_FLAGS,
|
2016-08-07 23:54:50 -07:00
|
|
|
TransactionSignatureChecker(&final_spending_tx, i),
|
2016-07-06 11:07:50 -07:00
|
|
|
&serror));
|
|
|
|
}
|
|
|
|
return timer_stop();
|
2016-06-07 16:28:12 -07:00
|
|
|
}
|
|
|
|
|