diff --git a/qa/rpc-tests/wallet_sapling.py b/qa/rpc-tests/wallet_sapling.py index c3b17af50..1aecba5d3 100755 --- a/qa/rpc-tests/wallet_sapling.py +++ b/qa/rpc-tests/wallet_sapling.py @@ -4,6 +4,7 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. from test_framework.test_framework import BitcoinTestFramework +from test_framework.authproxy import JSONRPCException from test_framework.util import ( assert_equal, start_nodes, @@ -144,5 +145,18 @@ class WalletSaplingTest(BitcoinTestFramework): self.nodes[2].z_importkey(sk1, "yes") assert_equal(self.nodes[2].z_getbalance(saplingAddr1), Decimal('5')) + # Make sure we get a useful error when trying to send to both sprout and sapling + node4_sproutaddr = self.nodes[3].z_getnewaddress('sprout') + node4_saplingaddr = self.nodes[3].z_getnewaddress('sapling') + try: + self.nodes[1].z_sendmany( + taddr1, + [{'address': node4_sproutaddr, 'amount': 2.5}, {'address': node4_saplingaddr, 'amount': 2.4999}], + 1, 0.0001 + ) + raise AssertionError("Should have thrown an exception") + except JSONRPCException as e: + assert_equal("Cannot send to both Sprout and Sapling addresses using z_sendmany", e.error['message']) + if __name__ == '__main__': WalletSaplingTest().main() diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index b85ab8f89..4bbf6271c 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3687,6 +3687,9 @@ UniValue z_sendmany(const UniValue& params, bool fHelp) std::vector zaddrRecipients; CAmount nTotalOut = 0; + bool containsSproutOutput = false; + bool containsSaplingOutput = false; + for (const UniValue& o : outputs.getValues()) { if (!o.isObject()) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected object"); @@ -3710,6 +3713,16 @@ UniValue z_sendmany(const UniValue& params, bool fHelp) bool toSprout = !toSapling; noSproutAddrs = noSproutAddrs && toSapling; + containsSproutOutput |= toSprout; + containsSaplingOutput |= toSapling; + + // Sending to both Sprout and Sapling is currently unsupported using z_sendmany + if (containsSproutOutput && containsSaplingOutput) { + throw JSONRPCError( + RPC_INVALID_PARAMETER, + "Cannot send to both Sprout and Sapling addresses using z_sendmany"); + } + // If we are sending from a shielded address, all recipient // shielded addresses must be of the same type. if (fromSprout && toSapling) {