@@ -1427,27 +1427,43 @@ UniValue viewshieldedtransaction(const JSONRPCRequest& request)
14271427static UniValue CreateShieldedTransaction (const JSONRPCRequest& request)
14281428{
14291429 EnsureWalletIsUnlocked ();
1430+ LOCK2 (cs_main, pwalletMain->cs_wallet );
1431+ int nextBlockHeight = chainActive.Height () + 1 ;
1432+ TransactionBuilder txBuilder = TransactionBuilder (Params ().GetConsensus (), nextBlockHeight, pwalletMain);
1433+ SaplingOperation operation (txBuilder);
14301434
1431- // Check that the from address is valid.
1432- auto fromaddress = request.params [0 ].get_str ();
1433- // Whether is from a shielded addr or a transparent addr
1434- CTxDestination fromTAddressDest = DecodeDestination (fromaddress);
1435- bool fromSapling = !IsValidDestination (fromTAddressDest);
1436- libzcash::SaplingPaymentAddress fromShieldedAddress;
1437- if (fromSapling) {
1438- auto res = KeyIO::DecodePaymentAddress (fromaddress);
1439- if (!IsValidPaymentAddress (res)) {
1440- // invalid
1441- throw JSONRPCError (RPC_INVALID_ADDRESS_OR_KEY, " Invalid from address, should be a taddr or shielded addr." );
1442- }
1443-
1444- fromShieldedAddress = *boost::get<libzcash::SaplingPaymentAddress>(&res);
1445- // Check that we have the spending key
1446- if (!pwalletMain->HaveSpendingKeyForPaymentAddress (fromShieldedAddress)) {
1447- throw JSONRPCError (RPC_INVALID_ADDRESS_OR_KEY, " From address does not belong to this node, shielded addr spending key not found." );
1435+ // Param 0: source of funds. Can either be a valid address, sapling address,
1436+ // or the string "from_transparent"|"from_shielded"
1437+ bool fromSapling = false ;
1438+ std::string sendFromStr = request.params [0 ].get_str ();
1439+ if (sendFromStr == " from_transparent" ) {
1440+ // send from any transparent address
1441+ operation.setSelectTransparentCoins (true );
1442+ } else if (sendFromStr == " from_shielded" ) {
1443+ // send from any shielded address
1444+ operation.setSelectShieldedCoins (true );
1445+ fromSapling = true ;
1446+ } else {
1447+ CTxDestination fromTAddressDest = DecodeDestination (sendFromStr);
1448+ if (!IsValidDestination (fromTAddressDest)) {
1449+ auto res = KeyIO::DecodePaymentAddress (sendFromStr);
1450+ if (!IsValidPaymentAddress (res)) {
1451+ throw JSONRPCError (RPC_INVALID_ADDRESS_OR_KEY, " Invalid from address, should be a taddr or shielded addr." );
1452+ }
1453+ libzcash::SaplingPaymentAddress fromShieldedAddress = *boost::get<libzcash::SaplingPaymentAddress>(&res);
1454+ if (!pwalletMain->HaveSpendingKeyForPaymentAddress (fromShieldedAddress)) {
1455+ throw JSONRPCError (RPC_INVALID_ADDRESS_OR_KEY, " From address does not belong to this node, shielded addr spending key not found." );
1456+ }
1457+ // send from user-supplied shielded address
1458+ operation.setFromAddress (fromShieldedAddress);
1459+ fromSapling = true ;
1460+ } else {
1461+ // send from user-supplied transparent address
1462+ operation.setFromAddress (fromTAddressDest);
14481463 }
14491464 }
14501465
1466+ // Param 1: array of outputs
14511467 UniValue outputs = request.params [1 ].get_array ();
14521468 if (outputs.empty ())
14531469 throw JSONRPCError (RPC_INVALID_PARAMETER, " Invalid parameter, amounts array is empty." );
@@ -1517,8 +1533,6 @@ static UniValue CreateShieldedTransaction(const JSONRPCRequest& request)
15171533 }
15181534
15191535 // Check network status
1520- LOCK2 (cs_main, pwalletMain->cs_wallet );
1521- int nextBlockHeight = chainActive.Height () + 1 ;
15221536 if (!Params ().GetConsensus ().NetworkUpgradeActive (nextBlockHeight, Consensus::UPGRADE_V5_DUMMY)) {
15231537 // If Sapling is not active, do not allow sending from or sending to Sapling addresses.
15241538 if (fromSapling || containsSaplingOutput) {
@@ -1553,13 +1567,13 @@ static UniValue CreateShieldedTransaction(const JSONRPCRequest& request)
15531567 throw JSONRPCError (RPC_INVALID_PARAMETER, strprintf (" Too many outputs, size of raw transaction would be larger than limit of %d bytes" , max_tx_size ));
15541568 }
15551569
1556- // Minimum confirmations
1570+ // Param 2: Minimum confirmations
15571571 int nMinDepth = request.params .size () > 2 ? request.params [2 ].get_int () : 1 ;
15581572 if (nMinDepth < 0 ) {
15591573 throw JSONRPCError (RPC_INVALID_PARAMETER, " Minimum number of confirmations cannot be less than 0" );
15601574 }
15611575
1562- // Fee
1576+ // Param 3: Fee
15631577 CAmount nFee = DEFAULT_SAPLING_FEE; // Default fee hardcoded for now to 10000 sats. Change it in a future focused PR.
15641578 CAmount nDefaultFee = nFee;
15651579 if (request.params .size () > 3 ) {
@@ -1596,16 +1610,7 @@ static UniValue CreateShieldedTransaction(const JSONRPCRequest& request)
15961610 throw JSONRPCError (RPC_INVALID_PARAMETER, " Minconf cannot be negative" );
15971611 }
15981612
1599- // Create the operation and process it
1600- TransactionBuilder txBuilder = TransactionBuilder (Params ().GetConsensus (), nextBlockHeight, pwalletMain);
1601- SaplingOperation operation (txBuilder);
1602-
1603- if (!fromSapling) {
1604- operation.setFromAddress (fromTAddressDest);
1605- } else {
1606- operation.setFromAddress (fromShieldedAddress);
1607- }
1608-
1613+ // Process the send operation
16091614 std::string txHash;
16101615 OperationResult res = operation.setFee (nFee)
16111616 ->setMinDepth (nMinDepth)
@@ -1627,6 +1632,8 @@ UniValue shielded_sendmany(const JSONRPCRequest& request)
16271632 + HelpRequiringPassphrase () + " \n "
16281633 " \n Arguments:\n "
16291634 " 1. \" fromaddress\" (string, required) The transparent addr or shielded addr to send the funds from.\n "
1635+ " It can also be the string \" from_transparent\" |\" from_shielded\" to send the funds\n "
1636+ " from any transparent|shielded address available.\n "
16301637 " 2. \" amounts\" (array, required) An array of json objects representing the amounts to send.\n "
16311638 " [{\n "
16321639 " \" address\" :address (string, required) The address is a transparent addr or shielded addr\n "
0 commit comments