diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 801b2d574..9023b80f6 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3485,12 +3485,13 @@ UniValue z_getoperationstatus_IMPL(const UniValue& params, bool fRemoveFinishedO } +// JSDescription size depends on the transaction version +#define V3_JS_DESCRIPTION_SIZE (GetSerializeSize(JSDescription(), SER_NETWORK, (OVERWINTER_TX_VERSION | (1 << 31)))) // 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_BEFORE_SAPLING ((MAX_TX_SIZE_BEFORE_SAPLING / GetSerializeSize(JSDescription(), SER_NETWORK, PROTOCOL_VERSION)) - 1) -#define Z_SENDMANY_MAX_ZADDR_OUTPUTS ((MAX_TX_SIZE_AFTER_SAPLING / GetSerializeSize(JSDescription(), SER_NETWORK, PROTOCOL_VERSION)) - 1) +#define Z_SENDMANY_MAX_ZADDR_OUTPUTS_BEFORE_SAPLING ((MAX_TX_SIZE_BEFORE_SAPLING / V3_JS_DESCRIPTION_SIZE) - 1) // transaction.h comment: spending taddr output requires CTxIn >= 148 bytes and typical taddr txout is 34 bytes #define CTXIN_SPEND_DUST_SIZE 148 @@ -3507,7 +3508,7 @@ UniValue z_sendmany(const UniValue& params, bool fHelp) "\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 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) + + strprintf("\nBefore Sapling activates, the maximum number of zaddr outputs is %d due to transaction size limits.\n", Z_SENDMANY_MAX_ZADDR_OUTPUTS_BEFORE_SAPLING) + HelpRequiringPassphrase() + "\n" "\nArguments:\n" "1. \"fromaddress\" (string, required) The taddr or zaddr to send the funds from.\n" @@ -3622,24 +3623,33 @@ UniValue z_sendmany(const UniValue& params, bool fHelp) } int nextBlockHeight = chainActive.Height() + 1; - size_t max_zaddr_outputs = Z_SENDMANY_MAX_ZADDR_OUTPUTS; + CMutableTransaction mtx; + mtx.fOverwintered = true; + mtx.nVersionGroupId = SAPLING_VERSION_GROUP_ID; + mtx.nVersion = SAPLING_TX_VERSION; unsigned int max_tx_size = MAX_TX_SIZE_AFTER_SAPLING; if (!NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING)) { - max_zaddr_outputs = Z_SENDMANY_MAX_ZADDR_OUTPUTS_BEFORE_SAPLING; - max_tx_size = MAX_TX_SIZE_BEFORE_SAPLING; - } + if (NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER)) { + mtx.nVersionGroupId = OVERWINTER_VERSION_GROUP_ID; + mtx.nVersion = OVERWINTER_TX_VERSION; + } else { + mtx.fOverwintered = false; + mtx.nVersion = 2; + } - // Check the number of zaddr outputs does not exceed the limit. - if (zaddrRecipients.size() > max_zaddr_outputs) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, too many zaddr outputs"); + max_tx_size = MAX_TX_SIZE_BEFORE_SAPLING; + + // Check the number of zaddr outputs does not exceed the limit. + if (zaddrRecipients.size() > Z_SENDMANY_MAX_ZADDR_OUTPUTS_BEFORE_SAPLING) { + 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++) { + // TODO Check whether the recipient is a Sprout or Sapling address mtx.vjoinsplit.push_back(JSDescription()); } CTransaction tx(mtx);