|
|
|
|
@@ -3840,475 +3840,6 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp, const CPubKey& m
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UniValue zc_sample_joinsplit(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
|
|
|
|
{
|
|
|
|
|
if (fHelp) {
|
|
|
|
|
throw runtime_error(
|
|
|
|
|
"zcsamplejoinsplit\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"Perform a joinsplit and return the JSDescription.\n"
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LOCK(cs_main);
|
|
|
|
|
|
|
|
|
|
uint256 joinSplitPubKey;
|
|
|
|
|
uint256 anchor = SproutMerkleTree().root();
|
|
|
|
|
JSDescription samplejoinsplit(*pzcashParams,
|
|
|
|
|
joinSplitPubKey,
|
|
|
|
|
anchor,
|
|
|
|
|
{JSInput(), JSInput()},
|
|
|
|
|
{JSOutput(), JSOutput()},
|
|
|
|
|
0,
|
|
|
|
|
0);
|
|
|
|
|
|
|
|
|
|
CDataStream ss(SER_NETWORK, SAPLING_TX_VERSION | (1 << 31));
|
|
|
|
|
ss << samplejoinsplit;
|
|
|
|
|
|
|
|
|
|
return HexStr(ss.begin(), ss.end());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UniValue zc_benchmark(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
|
|
|
|
{
|
|
|
|
|
if (!EnsureWalletIsAvailable(fHelp)) {
|
|
|
|
|
return NullUniValue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
JSDescription samplejoinsplit;
|
|
|
|
|
|
|
|
|
|
if (benchmarktype == "verifyjoinsplit") {
|
|
|
|
|
CDataStream ss(ParseHexV(params[2].get_str(), "js"), SER_NETWORK, SAPLING_TX_VERSION | (1 << 31));
|
|
|
|
|
ss >> samplejoinsplit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < samplecount; i++) {
|
|
|
|
|
if (benchmarktype == "sleep") {
|
|
|
|
|
sample_times.push_back(benchmark_sleep());
|
|
|
|
|
} else if (benchmarktype == "createjoinsplit") {
|
|
|
|
|
if (params.size() < 3) {
|
|
|
|
|
sample_times.push_back(benchmark_create_joinsplit());
|
|
|
|
|
} else {
|
|
|
|
|
int nThreads = params[2].get_int();
|
|
|
|
|
std::vector<double> vals = benchmark_create_joinsplit_threaded(nThreads);
|
|
|
|
|
// Divide by nThreads^2 to get average seconds per JoinSplit because
|
|
|
|
|
// we are running one JoinSplit per thread.
|
|
|
|
|
sample_times.push_back(std::accumulate(vals.begin(), vals.end(), 0.0) / (nThreads*nThreads));
|
|
|
|
|
}
|
|
|
|
|
} else if (benchmarktype == "verifyjoinsplit") {
|
|
|
|
|
sample_times.push_back(benchmark_verify_joinsplit(samplejoinsplit));
|
|
|
|
|
#ifdef ENABLE_MINING
|
|
|
|
|
} else if (benchmarktype == "solveequihash") {
|
|
|
|
|
if (params.size() < 3) {
|
|
|
|
|
sample_times.push_back(benchmark_solve_equihash());
|
|
|
|
|
} else {
|
|
|
|
|
int nThreads = params[2].get_int();
|
|
|
|
|
std::vector<double> vals = benchmark_solve_equihash_threaded(nThreads);
|
|
|
|
|
sample_times.insert(sample_times.end(), vals.begin(), vals.end());
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
} else if (benchmarktype == "verifyequihash") {
|
|
|
|
|
sample_times.push_back(benchmark_verify_equihash());
|
|
|
|
|
} else if (benchmarktype == "validatelargetx") {
|
|
|
|
|
// Number of inputs in the spending transaction that we will simulate
|
|
|
|
|
int nInputs = 11130;
|
|
|
|
|
if (params.size() >= 3) {
|
|
|
|
|
nInputs = params[2].get_int();
|
|
|
|
|
}
|
|
|
|
|
sample_times.push_back(benchmark_large_tx(nInputs));
|
|
|
|
|
} 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 if (benchmarktype == "connectblockslow") {
|
|
|
|
|
if (Params().NetworkIDString() != "regtest") {
|
|
|
|
|
throw JSONRPCError(RPC_TYPE_ERROR, "Benchmark must be run in regtest mode");
|
|
|
|
|
}
|
|
|
|
|
sample_times.push_back(benchmark_connectblock_slow());
|
|
|
|
|
} else if (benchmarktype == "sendtoaddress") {
|
|
|
|
|
if (Params().NetworkIDString() != "regtest") {
|
|
|
|
|
throw JSONRPCError(RPC_TYPE_ERROR, "Benchmark must be run in regtest mode");
|
|
|
|
|
}
|
|
|
|
|
auto amount = AmountFromValue(params[2]);
|
|
|
|
|
sample_times.push_back(benchmark_sendtoaddress(amount));
|
|
|
|
|
} else if (benchmarktype == "loadwallet") {
|
|
|
|
|
if (Params().NetworkIDString() != "regtest") {
|
|
|
|
|
throw JSONRPCError(RPC_TYPE_ERROR, "Benchmark must be run in regtest mode");
|
|
|
|
|
}
|
|
|
|
|
sample_times.push_back(benchmark_loadwallet());
|
|
|
|
|
} else if (benchmarktype == "listunspent") {
|
|
|
|
|
sample_times.push_back(benchmark_listunspent());
|
|
|
|
|
} else if (benchmarktype == "createsaplingspend") {
|
|
|
|
|
sample_times.push_back(benchmark_create_sapling_spend());
|
|
|
|
|
} else if (benchmarktype == "createsaplingoutput") {
|
|
|
|
|
sample_times.push_back(benchmark_create_sapling_output());
|
|
|
|
|
} else if (benchmarktype == "verifysaplingspend") {
|
|
|
|
|
sample_times.push_back(benchmark_verify_sapling_spend());
|
|
|
|
|
} else if (benchmarktype == "verifysaplingoutput") {
|
|
|
|
|
sample_times.push_back(benchmark_verify_sapling_output());
|
|
|
|
|
} else {
|
|
|
|
|
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid benchmarktype");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UniValue results(UniValue::VARR);
|
|
|
|
|
for (auto time : sample_times) {
|
|
|
|
|
UniValue result(UniValue::VOBJ);
|
|
|
|
|
result.push_back(Pair("runningtime", time));
|
|
|
|
|
results.push_back(result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return results;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UniValue zc_raw_receive(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
|
|
|
|
{
|
|
|
|
|
if (!EnsureWalletIsAvailable(fHelp)) {
|
|
|
|
|
return NullUniValue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (fHelp || params.size() != 2) {
|
|
|
|
|
throw runtime_error(
|
|
|
|
|
"zcrawreceive zcsecretkey encryptednote\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"DEPRECATED. Decrypts encryptednote and checks if the coin commitments\n"
|
|
|
|
|
"are in the blockchain as indicated by the \"exists\" result.\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"Output: {\n"
|
|
|
|
|
" \"amount\": value,\n"
|
|
|
|
|
" \"note\": noteplaintext,\n"
|
|
|
|
|
" \"exists\": exists\n"
|
|
|
|
|
"}\n"
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)(UniValue::VSTR));
|
|
|
|
|
|
|
|
|
|
LOCK(cs_main);
|
|
|
|
|
|
|
|
|
|
auto spendingkey = DecodeSpendingKey(params[0].get_str());
|
|
|
|
|
if (!IsValidSpendingKey(spendingkey)) {
|
|
|
|
|
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid spending key");
|
|
|
|
|
}
|
|
|
|
|
if (boost::get<libzcash::SproutSpendingKey>(&spendingkey) == nullptr) {
|
|
|
|
|
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Only works with Sprout spending keys");
|
|
|
|
|
}
|
|
|
|
|
SproutSpendingKey k = boost::get<libzcash::SproutSpendingKey>(spendingkey);
|
|
|
|
|
|
|
|
|
|
uint256 epk;
|
|
|
|
|
unsigned char nonce;
|
|
|
|
|
ZCNoteEncryption::Ciphertext ct;
|
|
|
|
|
uint256 h_sig;
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
CDataStream ssData(ParseHexV(params[1], "encrypted_note"), SER_NETWORK, PROTOCOL_VERSION);
|
|
|
|
|
try {
|
|
|
|
|
ssData >> nonce;
|
|
|
|
|
ssData >> epk;
|
|
|
|
|
ssData >> ct;
|
|
|
|
|
ssData >> h_sig;
|
|
|
|
|
} catch(const std::exception &) {
|
|
|
|
|
throw runtime_error(
|
|
|
|
|
"encrypted_note could not be decoded"
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ZCNoteDecryption decryptor(k.receiving_key());
|
|
|
|
|
|
|
|
|
|
SproutNotePlaintext npt = SproutNotePlaintext::decrypt(
|
|
|
|
|
decryptor,
|
|
|
|
|
ct,
|
|
|
|
|
epk,
|
|
|
|
|
h_sig,
|
|
|
|
|
nonce
|
|
|
|
|
);
|
|
|
|
|
SproutPaymentAddress payment_addr = k.address();
|
|
|
|
|
SproutNote decrypted_note = npt.note(payment_addr);
|
|
|
|
|
|
|
|
|
|
assert(pwalletMain != NULL);
|
|
|
|
|
std::vector<boost::optional<SproutWitness>> witnesses;
|
|
|
|
|
uint256 anchor;
|
|
|
|
|
uint256 commitment = decrypted_note.cm();
|
|
|
|
|
pwalletMain->WitnessNoteCommitment(
|
|
|
|
|
{commitment},
|
|
|
|
|
witnesses,
|
|
|
|
|
anchor
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
|
|
|
|
ss << npt;
|
|
|
|
|
|
|
|
|
|
UniValue result(UniValue::VOBJ);
|
|
|
|
|
result.push_back(Pair("amount", ValueFromAmount(decrypted_note.value())));
|
|
|
|
|
result.push_back(Pair("note", HexStr(ss.begin(), ss.end())));
|
|
|
|
|
result.push_back(Pair("exists", (bool) witnesses[0]));
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
|
|
|
|
{
|
|
|
|
|
if (!EnsureWalletIsAvailable(fHelp)) {
|
|
|
|
|
return NullUniValue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (fHelp || params.size() != 5) {
|
|
|
|
|
throw runtime_error(
|
|
|
|
|
"zcrawjoinsplit rawtx inputs outputs vpub_old vpub_new\n"
|
|
|
|
|
" inputs: a JSON object mapping {note: zcsecretkey, ...}\n"
|
|
|
|
|
" outputs: a JSON object mapping {zcaddr: value, ...}\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"DEPRECATED. Splices a joinsplit into rawtx. Inputs are unilaterally confidential.\n"
|
|
|
|
|
"Outputs are confidential between sender/receiver. The vpub_old and\n"
|
|
|
|
|
"vpub_new values are globally public and move transparent value into\n"
|
|
|
|
|
"or out of the confidential value store, respectively.\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"Note: The caller is responsible for delivering the output enc1 and\n"
|
|
|
|
|
"enc2 to the appropriate recipients, as well as signing rawtxout and\n"
|
|
|
|
|
"ensuring it is mined. (A future RPC call will deliver the confidential\n"
|
|
|
|
|
"payments in-band on the blockchain.)\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"Output: {\n"
|
|
|
|
|
" \"encryptednote1\": enc1,\n"
|
|
|
|
|
" \"encryptednote2\": enc2,\n"
|
|
|
|
|
" \"rawtxn\": rawtxout\n"
|
|
|
|
|
"}\n"
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LOCK(cs_main);
|
|
|
|
|
|
|
|
|
|
CTransaction tx;
|
|
|
|
|
if (!DecodeHexTx(tx, params[0].get_str()))
|
|
|
|
|
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
|
|
|
|
|
|
|
|
|
|
UniValue inputs = params[1].get_obj();
|
|
|
|
|
UniValue outputs = params[2].get_obj();
|
|
|
|
|
|
|
|
|
|
CAmount vpub_old(0);
|
|
|
|
|
CAmount vpub_new(0);
|
|
|
|
|
|
|
|
|
|
if (params[3].get_real() != 0.0)
|
|
|
|
|
vpub_old = AmountFromValue(params[3]);
|
|
|
|
|
|
|
|
|
|
if (params[4].get_real() != 0.0)
|
|
|
|
|
vpub_new = AmountFromValue(params[4]);
|
|
|
|
|
|
|
|
|
|
std::vector<JSInput> vjsin;
|
|
|
|
|
std::vector<JSOutput> vjsout;
|
|
|
|
|
std::vector<SproutNote> notes;
|
|
|
|
|
std::vector<SproutSpendingKey> keys;
|
|
|
|
|
std::vector<uint256> commitments;
|
|
|
|
|
|
|
|
|
|
for (const string& name_ : inputs.getKeys()) {
|
|
|
|
|
auto spendingkey = DecodeSpendingKey(inputs[name_].get_str());
|
|
|
|
|
if (!IsValidSpendingKey(spendingkey)) {
|
|
|
|
|
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid spending key");
|
|
|
|
|
}
|
|
|
|
|
if (boost::get<libzcash::SproutSpendingKey>(&spendingkey) == nullptr) {
|
|
|
|
|
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Only works with Sprout spending keys");
|
|
|
|
|
}
|
|
|
|
|
SproutSpendingKey k = boost::get<libzcash::SproutSpendingKey>(spendingkey);
|
|
|
|
|
|
|
|
|
|
keys.push_back(k);
|
|
|
|
|
|
|
|
|
|
SproutNotePlaintext npt;
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
CDataStream ssData(ParseHexV(name_, "note"), SER_NETWORK, PROTOCOL_VERSION);
|
|
|
|
|
ssData >> npt;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SproutPaymentAddress addr = k.address();
|
|
|
|
|
SproutNote note = npt.note(addr);
|
|
|
|
|
notes.push_back(note);
|
|
|
|
|
commitments.push_back(note.cm());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint256 anchor;
|
|
|
|
|
std::vector<boost::optional<SproutWitness>> witnesses;
|
|
|
|
|
pwalletMain->WitnessNoteCommitment(commitments, witnesses, anchor);
|
|
|
|
|
|
|
|
|
|
assert(witnesses.size() == notes.size());
|
|
|
|
|
assert(notes.size() == keys.size());
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
for (size_t i = 0; i < witnesses.size(); i++) {
|
|
|
|
|
if (!witnesses[i]) {
|
|
|
|
|
throw runtime_error(
|
|
|
|
|
"joinsplit input could not be found in tree"
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vjsin.push_back(JSInput(*witnesses[i], notes[i], keys[i]));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (vjsin.size() < ZC_NUM_JS_INPUTS) {
|
|
|
|
|
vjsin.push_back(JSInput());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const string& name_ : outputs.getKeys()) {
|
|
|
|
|
auto addrTo = DecodePaymentAddress(name_);
|
|
|
|
|
if (!IsValidPaymentAddress(addrTo)) {
|
|
|
|
|
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid recipient address.");
|
|
|
|
|
}
|
|
|
|
|
if (boost::get<libzcash::SproutPaymentAddress>(&addrTo) == nullptr) {
|
|
|
|
|
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Only works with Sprout payment addresses");
|
|
|
|
|
}
|
|
|
|
|
CAmount nAmount = AmountFromValue(outputs[name_]);
|
|
|
|
|
|
|
|
|
|
vjsout.push_back(JSOutput(boost::get<libzcash::SproutPaymentAddress>(addrTo), nAmount));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (vjsout.size() < ZC_NUM_JS_OUTPUTS) {
|
|
|
|
|
vjsout.push_back(JSOutput());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO
|
|
|
|
|
if (vjsout.size() != ZC_NUM_JS_INPUTS || vjsin.size() != ZC_NUM_JS_OUTPUTS) {
|
|
|
|
|
throw runtime_error("unsupported joinsplit input/output counts");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint256 joinSplitPubKey;
|
|
|
|
|
unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES];
|
|
|
|
|
crypto_sign_keypair(joinSplitPubKey.begin(), joinSplitPrivKey);
|
|
|
|
|
|
|
|
|
|
CMutableTransaction mtx(tx);
|
|
|
|
|
mtx.nVersion = 2;
|
|
|
|
|
mtx.joinSplitPubKey = joinSplitPubKey;
|
|
|
|
|
|
|
|
|
|
JSDescription jsdesc(*pzcashParams,
|
|
|
|
|
joinSplitPubKey,
|
|
|
|
|
anchor,
|
|
|
|
|
{vjsin[0], vjsin[1]},
|
|
|
|
|
{vjsout[0], vjsout[1]},
|
|
|
|
|
vpub_old,
|
|
|
|
|
vpub_new);
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
auto verifier = libzcash::ProofVerifier::Strict();
|
|
|
|
|
assert(jsdesc.Verify(*pzcashParams, verifier, joinSplitPubKey));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mtx.vjoinsplit.push_back(jsdesc);
|
|
|
|
|
|
|
|
|
|
// Empty output script.
|
|
|
|
|
CScript scriptCode;
|
|
|
|
|
CTransaction signTx(mtx);
|
|
|
|
|
auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
|
|
|
|
|
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
|
|
|
|
|
|
|
|
|
|
// Add the signature
|
|
|
|
|
assert(crypto_sign_detached(&mtx.joinSplitSig[0], NULL,
|
|
|
|
|
dataToBeSigned.begin(), 32,
|
|
|
|
|
joinSplitPrivKey
|
|
|
|
|
) == 0);
|
|
|
|
|
|
|
|
|
|
// Sanity check
|
|
|
|
|
assert(crypto_sign_verify_detached(&mtx.joinSplitSig[0],
|
|
|
|
|
dataToBeSigned.begin(), 32,
|
|
|
|
|
mtx.joinSplitPubKey.begin()
|
|
|
|
|
) == 0);
|
|
|
|
|
|
|
|
|
|
CTransaction rawTx(mtx);
|
|
|
|
|
|
|
|
|
|
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
|
|
|
|
ss << rawTx;
|
|
|
|
|
|
|
|
|
|
std::string encryptedNote1;
|
|
|
|
|
std::string encryptedNote2;
|
|
|
|
|
{
|
|
|
|
|
CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION);
|
|
|
|
|
ss2 << ((unsigned char) 0x00);
|
|
|
|
|
ss2 << jsdesc.ephemeralKey;
|
|
|
|
|
ss2 << jsdesc.ciphertexts[0];
|
|
|
|
|
ss2 << jsdesc.h_sig(*pzcashParams, joinSplitPubKey);
|
|
|
|
|
|
|
|
|
|
encryptedNote1 = HexStr(ss2.begin(), ss2.end());
|
|
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION);
|
|
|
|
|
ss2 << ((unsigned char) 0x01);
|
|
|
|
|
ss2 << jsdesc.ephemeralKey;
|
|
|
|
|
ss2 << jsdesc.ciphertexts[1];
|
|
|
|
|
ss2 << jsdesc.h_sig(*pzcashParams, joinSplitPubKey);
|
|
|
|
|
|
|
|
|
|
encryptedNote2 = HexStr(ss2.begin(), ss2.end());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UniValue result(UniValue::VOBJ);
|
|
|
|
|
result.push_back(Pair("encryptednote1", encryptedNote1));
|
|
|
|
|
result.push_back(Pair("encryptednote2", encryptedNote2));
|
|
|
|
|
result.push_back(Pair("rawtxn", HexStr(ss.begin(), ss.end())));
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UniValue zc_raw_keygen(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
|
|
|
|
{
|
|
|
|
|
if (!EnsureWalletIsAvailable(fHelp)) {
|
|
|
|
|
return NullUniValue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (fHelp || params.size() != 0) {
|
|
|
|
|
throw runtime_error(
|
|
|
|
|
"zcrawkeygen\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"DEPRECATED. Generate a zcaddr which can send and receive confidential values.\n"
|
|
|
|
|
"\n"
|
|
|
|
|
"Output: {\n"
|
|
|
|
|
" \"zcaddress\": zcaddr,\n"
|
|
|
|
|
" \"zcsecretkey\": zcsecretkey,\n"
|
|
|
|
|
" \"zcviewingkey\": zcviewingkey,\n"
|
|
|
|
|
"}\n"
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto k = SproutSpendingKey::random();
|
|
|
|
|
auto addr = k.address();
|
|
|
|
|
auto viewing_key = k.viewing_key();
|
|
|
|
|
|
|
|
|
|
UniValue result(UniValue::VOBJ);
|
|
|
|
|
result.push_back(Pair("zcaddress", EncodePaymentAddress(addr)));
|
|
|
|
|
result.push_back(Pair("zcsecretkey", EncodeSpendingKey(k)));
|
|
|
|
|
result.push_back(Pair("zcviewingkey", EncodeViewingKey(viewing_key)));
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
UniValue z_getnewaddress(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
|
|
|
|
{
|
|
|
|
|
if (!EnsureWalletIsAvailable(fHelp))
|
|
|
|
|
@@ -8776,11 +8307,6 @@ static const CRPCCommand commands[] =
|
|
|
|
|
{ "wallet", "walletlock", &walletlock, true },
|
|
|
|
|
{ "wallet", "walletpassphrasechange", &walletpassphrasechange, true },
|
|
|
|
|
{ "wallet", "walletpassphrase", &walletpassphrase, true },
|
|
|
|
|
{ "wallet", "zcbenchmark", &zc_benchmark, true },
|
|
|
|
|
{ "wallet", "zcrawkeygen", &zc_raw_keygen, true },
|
|
|
|
|
{ "wallet", "zcrawjoinsplit", &zc_raw_joinsplit, true },
|
|
|
|
|
{ "wallet", "zcrawreceive", &zc_raw_receive, true },
|
|
|
|
|
{ "wallet", "zcsamplejoinsplit", &zc_sample_joinsplit, true },
|
|
|
|
|
{ "wallet", "z_listreceivedbyaddress", &z_listreceivedbyaddress, false },
|
|
|
|
|
{ "wallet", "z_listunspent", &z_listunspent, false },
|
|
|
|
|
{ "wallet", "z_getbalance", &z_getbalance, false },
|
|
|
|
|
|