Merge remote-tracking branch 'zcash/master' into rebase

# Conflicts:
#	README.md
#	src/Makefile.gtest.include
#	src/chainparams.cpp
#	src/init.cpp
#	src/miner.cpp
#	src/wallet/wallet.cpp
This commit is contained in:
jl777
2016-12-12 12:19:13 +02:00
94 changed files with 3461 additions and 808 deletions

View File

@@ -2622,6 +2622,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");
}
@@ -2849,7 +2855,10 @@ Value zc_raw_joinsplit(const json_spirit::Array& params, bool fHelp)
vpub_old,
vpub_new);
assert(jsdesc.Verify(*pzcashParams, joinSplitPubKey));
{
auto verifier = libzcash::ProofVerifier::Strict();
assert(jsdesc.Verify(*pzcashParams, verifier, joinSplitPubKey));
}
mtx.vjoinsplit.push_back(jsdesc);
@@ -3310,17 +3319,29 @@ Value z_getoperationstatus_IMPL(const Array& params, bool fRemoveFinishedOperati
return ret;
}
// Here we define the maximum number of zaddr outputs that can be included in a transaction.
// If input notes are small, we might actually require more than one joinsplit per zaddr output.
// For now though, we assume we use one joinsplit per zaddr output (and the second output note is change).
// We reduce the result by 1 to ensure there is room for non-joinsplit CTransaction data.
#define Z_SENDMANY_MAX_ZADDR_OUTPUTS ((MAX_TX_SIZE / JSDescription().GetSerializeSize(SER_NETWORK, PROTOCOL_VERSION)) - 1)
// transaction.h comment: spending taddr output requires CTxIn >= 148 bytes and typical taddr txout is 34 bytes
#define CTXIN_SPEND_DUST_SIZE 148
#define CTXOUT_REGULAR_SIZE 34
Value z_sendmany(const Array& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return Value::null;
if (fHelp || params.size() < 2 || params.size() > 3)
if (fHelp || params.size() < 2 || params.size() > 4)
throw runtime_error(
"z_sendmany \"fromaddress\" [{\"address\":... ,\"amount\":...},...] ( minconf )\n"
"z_sendmany \"fromaddress\" [{\"address\":... ,\"amount\":...},...] ( minconf ) ( fee )\n"
"\nSend multiple times. Amounts are double-precision floating point numbers."
"\nChange from a taddr flows to a new taddr address, while change from zaddr returns to itself."
"\nWhen sending coinbase UTXOs to a zaddr, change is not alllowed. The entire value of the UTXO(s) must be consumed."
"\nWhen sending coinbase UTXOs to a zaddr, change is not allowed. The entire value of the UTXO(s) must be consumed."
+ strprintf("\nCurrently, the maximum number of zaddr outputs is %d due to transaction size limits.\n", Z_SENDMANY_MAX_ZADDR_OUTPUTS)
+ HelpRequiringPassphrase() + "\n"
"\nArguments:\n"
"1. \"fromaddress\" (string, required) The taddr or zaddr to send the funds from.\n"
@@ -3331,6 +3352,8 @@ Value z_sendmany(const Array& params, bool fHelp)
" \"memo\":memo (string, optional) If the address is a zaddr, raw data represented in hexadecimal string format\n"
" }, ... ]\n"
"3. minconf (numeric, optional, default=1) Only use funds confirmed at least this many times.\n"
"4. fee (numeric, optional, default="
+ strprintf("%s", FormatMoney(ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE)) + ") The fee amount to attach to this transaction.\n"
"\nResult:\n"
"\"operationid\" (string) An operationid to pass to z_getoperationstatus to get the result of the operation.\n"
);
@@ -3371,6 +3394,7 @@ Value z_sendmany(const Array& params, bool fHelp)
// Recipients
std::vector<SendManyRecipient> taddrRecipients;
std::vector<SendManyRecipient> zaddrRecipients;
CAmount nTotalOut = 0;
BOOST_FOREACH(Value& output, outputs)
{
@@ -3426,6 +3450,32 @@ Value z_sendmany(const Array& params, bool fHelp)
} else {
taddrRecipients.push_back( SendManyRecipient(address, nAmount, memo) );
}
nTotalOut += nAmount;
}
// Check the number of zaddr outputs does not exceed the limit.
if (zaddrRecipients.size() > Z_SENDMANY_MAX_ZADDR_OUTPUTS) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, too many zaddr outputs");
}
// As a sanity check, estimate and verify that the size of the transaction will be valid.
// Depending on the input notes, the actual tx size may turn out to be larger and perhaps invalid.
size_t txsize = 0;
CMutableTransaction mtx;
mtx.nVersion = 2;
for (int i = 0; i < zaddrRecipients.size(); i++) {
mtx.vjoinsplit.push_back(JSDescription());
}
CTransaction tx(mtx);
txsize += tx.GetSerializeSize(SER_NETWORK, tx.nVersion);
if (fromTaddr) {
txsize += CTXIN_SPEND_DUST_SIZE;
txsize += CTXOUT_REGULAR_SIZE; // There will probably be taddr change
}
txsize += CTXOUT_REGULAR_SIZE * taddrRecipients.size();
if (txsize > MAX_TX_SIZE) {
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Too many outputs, size of raw transaction would be larger than limit of %d bytes", MAX_TX_SIZE ));
}
// Minimum confirmations
@@ -3437,9 +3487,19 @@ Value z_sendmany(const Array& params, bool fHelp)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Minimum number of confirmations cannot be less than 0");
}
// Fee in Zatoshis, not currency format)
CAmount nFee = ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE;
if (params.size() > 3) {
nFee = AmountFromValue( params[3] );
// Check that the user specified fee is sane.
if (nFee > nTotalOut) {
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Fee %s is greater than the sum of outputs %s", FormatMoney(nFee), FormatMoney(nTotalOut)));
}
}
// Create operation and add to global queue
std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue();
std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_sendmany(fromaddress, taddrRecipients, zaddrRecipients, nMinDepth) );
std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_sendmany(fromaddress, taddrRecipients, zaddrRecipients, nMinDepth, nFee) );
q->addOperation(operation);
AsyncRPCOperationId operationId = operation->getId();
return operationId;