Skip to content

Commit 4241fbf

Browse files
committed
[RPC] Add option to send from multiple addresses in shielded_sendmany
1 parent 60b7c9b commit 4241fbf

File tree

1 file changed

+38
-31
lines changed

1 file changed

+38
-31
lines changed

src/wallet/rpcwallet.cpp

Lines changed: 38 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1427,27 +1427,43 @@ UniValue viewshieldedtransaction(const JSONRPCRequest& request)
14271427
static 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
"\nArguments:\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

Comments
 (0)