Remove uses of KeyIO::DecodeDestination
This commit is contained in:
parent
d376e28382
commit
20266ac911
|
@ -82,9 +82,11 @@ class WalletShieldingCoinbaseTest (BitcoinTestFramework):
|
|||
# Node 3 will test that watch only address utxos are not selected
|
||||
self.nodes[3].importaddress(mytaddr)
|
||||
recipients= [{"address":myzaddr, "amount": Decimal('1')}]
|
||||
myopid = self.nodes[3].z_sendmany(mytaddr, recipients)
|
||||
|
||||
wait_and_assert_operationid_status(self.nodes[3], myopid, "failed", "Insufficient transparent funds, no UTXOs found for taddr from address.", 10)
|
||||
try:
|
||||
myopid = self.nodes[3].z_sendmany(mytaddr, recipients)
|
||||
except JSONRPCException as e:
|
||||
errorString = e.error['message']
|
||||
assert_equal("Invalid from address: does not belong to this node, spending key not found.", errorString);
|
||||
|
||||
# This send will fail because our wallet does not allow any change when shielding a coinbase utxo,
|
||||
# as it's currently not possible to specify a change address in z_sendmany.
|
||||
|
|
|
@ -822,10 +822,10 @@ CScript CChainParams::GetFoundersRewardScriptAtHeight(int nHeight) const {
|
|||
assert(nHeight > 0 && nHeight <= consensus.GetLastFoundersRewardBlockHeight(nHeight));
|
||||
|
||||
KeyIO keyIO(*this);
|
||||
CTxDestination address = keyIO.DecodeDestination(GetFoundersRewardAddressAtHeight(nHeight).c_str());
|
||||
assert(IsValidDestination(address));
|
||||
assert(IsScriptDestination(address));
|
||||
CScriptID scriptID = std::get<CScriptID>(address); // address is a variant
|
||||
auto address = keyIO.DecodePaymentAddress(GetFoundersRewardAddressAtHeight(nHeight).c_str());
|
||||
assert(address.has_value());
|
||||
assert(std::holds_alternative<CScriptID>(address.value()));
|
||||
CScriptID scriptID = std::get<CScriptID>(address.value());
|
||||
CScript script = CScript() << OP_HASH160 << ToByteVector(scriptID) << OP_EQUAL;
|
||||
return script;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <script/standard.h>
|
||||
#include "upgrades.h"
|
||||
#include "util.h"
|
||||
#include "util/match.h"
|
||||
|
||||
namespace Consensus {
|
||||
bool Params::NetworkUpgradeActive(int nHeight, Consensus::UpgradeIndex idx) const {
|
||||
|
@ -163,18 +164,26 @@ namespace Consensus {
|
|||
|
||||
// Parse the address strings into concrete types.
|
||||
std::vector<FundingStreamAddress> addresses;
|
||||
for (auto addr : strAddresses) {
|
||||
auto taddr = keyIO.DecodeDestination(addr);
|
||||
if (IsValidDestination(taddr)) {
|
||||
addresses.push_back(GetScriptForDestination(taddr));
|
||||
} else {
|
||||
auto zaddr = keyIO.DecodePaymentAddress(addr);
|
||||
if (!(zaddr.has_value() && std::holds_alternative<libzcash::SaplingPaymentAddress>(zaddr.value()))) {
|
||||
for (const auto& strAddr : strAddresses) {
|
||||
auto addr = keyIO.DecodePaymentAddress(strAddr);
|
||||
if (!addr.has_value()) {
|
||||
throw std::runtime_error("Funding stream address was not valid Zcash address.");
|
||||
}
|
||||
|
||||
std::visit(match {
|
||||
[&](const CKeyID& keyId) {
|
||||
addresses.push_back(GetScriptForDestination(keyId));
|
||||
},
|
||||
[&](const CScriptID& scriptId) {
|
||||
addresses.push_back(GetScriptForDestination(scriptId));
|
||||
},
|
||||
[&](const libzcash::SaplingPaymentAddress& zaddr) {
|
||||
addresses.push_back(zaddr);
|
||||
},
|
||||
[&](const auto& zaddr) {
|
||||
throw std::runtime_error("Funding stream address was not a valid transparent or Sapling address.");
|
||||
}
|
||||
|
||||
addresses.push_back(std::get<libzcash::SaplingPaymentAddress>(zaddr.value()));
|
||||
}
|
||||
}, addr.value());
|
||||
}
|
||||
|
||||
auto validationResult = FundingStream::ValidateFundingStream(params, startHeight, endHeight, addresses);
|
||||
|
|
15
src/init.cpp
15
src/init.cpp
|
@ -1098,16 +1098,11 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
|||
KeyIO keyIO(chainparams);
|
||||
#ifdef ENABLE_MINING
|
||||
if (mapArgs.count("-mineraddress")) {
|
||||
CTxDestination addr = keyIO.DecodeDestination(mapArgs["-mineraddress"]);
|
||||
if (!IsValidDestination(addr)) {
|
||||
// Try a payment address
|
||||
auto zaddr = keyIO.DecodePaymentAddress(mapArgs["-mineraddress"]);
|
||||
if (!zaddr.has_value() || std::visit(ExtractMinerAddress(), zaddr.value()).has_value())
|
||||
{
|
||||
return InitError(strprintf(
|
||||
_("Invalid address for -mineraddress=<addr>: '%s' (must be a Sapling or transparent address)"),
|
||||
mapArgs["-mineraddress"]));
|
||||
}
|
||||
auto addr = keyIO.DecodePaymentAddress(mapArgs["-mineraddress"]);
|
||||
if (!(addr.has_value() && std::visit(ExtractMinerAddress(), addr.value()).has_value())) {
|
||||
return InitError(strprintf(
|
||||
_("Invalid address for -mineraddress=<addr>: '%s' (must be a Sapling or transparent address)"),
|
||||
mapArgs["-mineraddress"]));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "timedata.h"
|
||||
#include "transaction_builder.h"
|
||||
#include "util.h"
|
||||
#include "util/match.h"
|
||||
#include "utilmoneystr.h"
|
||||
#include "utiltime.h"
|
||||
#include "wallet.h"
|
||||
|
@ -96,18 +97,36 @@ AsyncRPCOperation_mergetoaddress::AsyncRPCOperation_mergetoaddress(
|
|||
}
|
||||
|
||||
KeyIO keyIO(Params());
|
||||
toTaddr_ = keyIO.DecodeDestination(std::get<0>(recipient));
|
||||
isToTaddr_ = IsValidDestination(toTaddr_);
|
||||
isToTaddr_ = false;
|
||||
isToZaddr_ = false;
|
||||
|
||||
if (!isToTaddr_) {
|
||||
auto address = keyIO.DecodePaymentAddress(std::get<0>(recipient));
|
||||
if (address.has_value()) {
|
||||
isToZaddr_ = true;
|
||||
toPaymentAddress_ = address.value();
|
||||
} else {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid recipient address");
|
||||
}
|
||||
auto address = keyIO.DecodePaymentAddress(std::get<0>(recipient));
|
||||
if (address.has_value()) {
|
||||
std::visit(match {
|
||||
[&](const CKeyID& keyId) {
|
||||
toTaddr_ = keyId;
|
||||
isToTaddr_ = true;
|
||||
},
|
||||
[&](const CScriptID& scriptId) {
|
||||
toTaddr_ = scriptId;
|
||||
isToTaddr_ = true;
|
||||
},
|
||||
[&](const libzcash::SproutPaymentAddress& addr) {
|
||||
toPaymentAddress_ = addr;
|
||||
isToZaddr_ = true;
|
||||
},
|
||||
[&](const libzcash::SaplingPaymentAddress& addr) {
|
||||
toPaymentAddress_ = addr;
|
||||
isToZaddr_ = true;
|
||||
},
|
||||
[&](const libzcash::UnifiedAddress& addr) {
|
||||
throw JSONRPCError(
|
||||
RPC_INVALID_ADDRESS_OR_KEY,
|
||||
"z_mergetoaddress does not yet support sending to unified addresses");
|
||||
},
|
||||
}, address.value());
|
||||
} else {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid recipient address");
|
||||
}
|
||||
|
||||
// Log the context info i.e. the call parameters to z_mergetoaddress
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "transaction_builder.h"
|
||||
#include "timedata.h"
|
||||
#include "util.h"
|
||||
#include "util/match.h"
|
||||
#include "utilmoneystr.h"
|
||||
#include "wallet.h"
|
||||
#include "walletdb.h"
|
||||
|
@ -92,20 +93,41 @@ AsyncRPCOperation_sendmany::AsyncRPCOperation_sendmany(
|
|||
KeyIO keyIO(Params());
|
||||
|
||||
useanyutxo_ = fromAddress == "ANY_TADDR";
|
||||
fromtaddr_ = keyIO.DecodeDestination(fromAddress);
|
||||
isfromtaddr_ = useanyutxo_ || IsValidDestination(fromtaddr_);
|
||||
isfromzaddr_ = false;
|
||||
|
||||
if (!isfromtaddr_) {
|
||||
if (useanyutxo_) {
|
||||
isfromtaddr_ = true;
|
||||
} else {
|
||||
auto address = keyIO.DecodePaymentAddress(fromAddress);
|
||||
if (address.has_value()) {
|
||||
// We don't need to lock on the wallet as spending key related methods are thread-safe
|
||||
if (!std::visit(HaveSpendingKeyForPaymentAddress(pwalletMain), address.value())) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address, no spending key found for zaddr");
|
||||
throw JSONRPCError(
|
||||
RPC_INVALID_ADDRESS_OR_KEY,
|
||||
"Invalid from address, no spending key found for address");
|
||||
}
|
||||
|
||||
isfromzaddr_ = true;
|
||||
frompaymentaddress_ = address.value();
|
||||
std::visit(match {
|
||||
[&](const CKeyID& keyId) {
|
||||
fromtaddr_ = keyId;
|
||||
isfromtaddr_ = true;
|
||||
},
|
||||
[&](const CScriptID& scriptId) {
|
||||
fromtaddr_ = scriptId;
|
||||
isfromtaddr_ = true;
|
||||
},
|
||||
[&](const libzcash::SproutPaymentAddress& addr) {
|
||||
frompaymentaddress_ = addr;
|
||||
isfromzaddr_ = true;
|
||||
},
|
||||
[&](const libzcash::SaplingPaymentAddress& addr) {
|
||||
frompaymentaddress_ = addr;
|
||||
isfromzaddr_ = true;
|
||||
},
|
||||
[&](const libzcash::UnifiedAddress& addr) {
|
||||
throw JSONRPCError(
|
||||
RPC_INVALID_ADDRESS_OR_KEY,
|
||||
"Unified addresses are not yet supported by z_sendmany");
|
||||
}
|
||||
}, address.value());
|
||||
} else {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address");
|
||||
}
|
||||
|
|
|
@ -94,14 +94,14 @@ private:
|
|||
|
||||
UniValue contextinfo_; // optional data to include in return value from getStatus()
|
||||
|
||||
bool isUsingBuilder_; // Indicates that no Sprout addresses are involved
|
||||
bool isUsingBuilder_{false}; // Indicates that no Sprout addresses are involved
|
||||
uint32_t consensusBranchId_;
|
||||
CAmount fee_;
|
||||
int mindepth_;
|
||||
int mindepth_{0};
|
||||
std::string fromaddress_;
|
||||
bool useanyutxo_;
|
||||
bool isfromtaddr_;
|
||||
bool isfromzaddr_;
|
||||
bool useanyutxo_{false};
|
||||
bool isfromtaddr_{false};
|
||||
bool isfromzaddr_{false};
|
||||
CTxDestination fromtaddr_;
|
||||
PaymentAddress frompaymentaddress_;
|
||||
|
||||
|
|
|
@ -2991,24 +2991,13 @@ UniValue z_listaddresses(const UniValue& params, bool fHelp)
|
|||
return ret;
|
||||
}
|
||||
|
||||
CAmount getBalanceTaddr(std::string transparentAddress, int minDepth=1, bool ignoreUnspendable=true) {
|
||||
std::set<CTxDestination> destinations;
|
||||
CAmount getBalanceTaddr(const std::optional<CTxDestination>& taddr, int minDepth=1, bool ignoreUnspendable=true) {
|
||||
vector<COutput> vecOutputs;
|
||||
CAmount balance = 0;
|
||||
|
||||
KeyIO keyIO(Params());
|
||||
if (transparentAddress.length() > 0) {
|
||||
CTxDestination taddr = keyIO.DecodeDestination(transparentAddress);
|
||||
if (!IsValidDestination(taddr)) {
|
||||
throw std::runtime_error("invalid transparent address");
|
||||
}
|
||||
destinations.insert(taddr);
|
||||
}
|
||||
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
|
||||
pwalletMain->AvailableCoins(vecOutputs, false, NULL, true);
|
||||
|
||||
for (const COutput& out : vecOutputs) {
|
||||
if (out.nDepth < minDepth) {
|
||||
continue;
|
||||
|
@ -3018,13 +3007,13 @@ CAmount getBalanceTaddr(std::string transparentAddress, int minDepth=1, bool ign
|
|||
continue;
|
||||
}
|
||||
|
||||
if (destinations.size()) {
|
||||
if (taddr.has_value()) {
|
||||
CTxDestination address;
|
||||
if (!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!destinations.count(address)) {
|
||||
if (address != taddr.value()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -3244,26 +3233,35 @@ UniValue z_getbalance(const UniValue& params, bool fHelp)
|
|||
KeyIO keyIO(Params());
|
||||
// Check that the from address is valid.
|
||||
auto fromaddress = params[0].get_str();
|
||||
bool fromTaddr = false;
|
||||
CTxDestination taddr = keyIO.DecodeDestination(fromaddress);
|
||||
auto pa = keyIO.DecodePaymentAddress(fromaddress);
|
||||
fromTaddr = IsValidDestination(taddr);
|
||||
if (!fromTaddr) {
|
||||
if (!pa.has_value()) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address, should be a taddr or zaddr.");
|
||||
}
|
||||
if (!std::visit(PaymentAddressBelongsToWallet(pwalletMain), pa.value())) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "From address does not belong to this node, spending key or viewing key not found.");
|
||||
}
|
||||
|
||||
if (!pa.has_value()) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address, should be a taddr or zaddr.");
|
||||
}
|
||||
if (!std::visit(PaymentAddressBelongsToWallet(pwalletMain), pa.value())) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "From address does not belong to this node.");
|
||||
}
|
||||
|
||||
CAmount nBalance = 0;
|
||||
if (fromTaddr) {
|
||||
nBalance = getBalanceTaddr(fromaddress, nMinDepth, false);
|
||||
} else {
|
||||
// TODO: Return an error if a UA is provided (once we support UAs).
|
||||
nBalance = getBalanceZaddr(pa, nMinDepth, INT_MAX, false);
|
||||
}
|
||||
std::visit(match {
|
||||
[&](const CKeyID& addr) {
|
||||
nBalance = getBalanceTaddr(addr, nMinDepth, false);
|
||||
},
|
||||
[&](const CScriptID& addr) {
|
||||
nBalance = getBalanceTaddr(addr, nMinDepth, false);
|
||||
},
|
||||
[&](const libzcash::SproutPaymentAddress& addr) {
|
||||
nBalance = getBalanceZaddr(addr, nMinDepth, INT_MAX, false);
|
||||
},
|
||||
[&](const libzcash::SaplingPaymentAddress& addr) {
|
||||
nBalance = getBalanceZaddr(addr, nMinDepth, INT_MAX, false);
|
||||
},
|
||||
[&](const libzcash::UnifiedAddress& addr) {
|
||||
throw JSONRPCError(
|
||||
RPC_INVALID_ADDRESS_OR_KEY,
|
||||
"Unified addresses are not yet supported for z_getbalance.");
|
||||
},
|
||||
}, pa.value());
|
||||
|
||||
// inZat
|
||||
if (params.size() > 2 && params[2].get_bool()) {
|
||||
|
@ -3323,7 +3321,7 @@ UniValue z_gettotalbalance(const UniValue& params, bool fHelp)
|
|||
// but they don't because wtx.GetAmounts() does not handle tx where there are no outputs
|
||||
// pwalletMain->GetBalance() does not accept min depth parameter
|
||||
// so we use our own method to get balance of utxos.
|
||||
CAmount nBalance = getBalanceTaddr("", nMinDepth, !fIncludeWatchonly);
|
||||
CAmount nBalance = getBalanceTaddr(std::nullopt, nMinDepth, !fIncludeWatchonly);
|
||||
CAmount nPrivateBalance = getBalanceZaddr(std::nullopt, nMinDepth, INT_MAX, !fIncludeWatchonly);
|
||||
CAmount nTotalBalance = nBalance + nPrivateBalance;
|
||||
UniValue result(UniValue::VOBJ);
|
||||
|
@ -3730,24 +3728,40 @@ UniValue z_sendmany(const UniValue& params, bool fHelp)
|
|||
if (fromaddress == "ANY_TADDR") {
|
||||
fromTaddr = true;
|
||||
} else {
|
||||
CTxDestination taddr = keyIO.DecodeDestination(fromaddress);
|
||||
fromTaddr = IsValidDestination(taddr);
|
||||
if (!fromTaddr) {
|
||||
auto addr = keyIO.DecodePaymentAddress(fromaddress);
|
||||
if (!addr.has_value()) {
|
||||
// invalid
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address, should be a taddr or zaddr.");
|
||||
}
|
||||
|
||||
// This is a sanity check; the actual checks will come later when the spend is attempted.
|
||||
if (!std::visit(HaveSpendingKeyForPaymentAddress(pwalletMain), addr.value())) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "From address does not belong to this node, zaddr spending key not found.");
|
||||
}
|
||||
|
||||
// Remember whether this is a Sprout or Sapling address
|
||||
fromSapling = std::holds_alternative<libzcash::SaplingPaymentAddress>(addr.value());
|
||||
fromSprout = std::holds_alternative<libzcash::SproutPaymentAddress>(addr.value());
|
||||
auto addr = keyIO.DecodePaymentAddress(fromaddress);
|
||||
if (!addr.has_value()) {
|
||||
throw JSONRPCError(
|
||||
RPC_INVALID_ADDRESS_OR_KEY,
|
||||
"Invalid from address: should be a taddr, a zaddr, or the string 'ANY_TADDR'.");
|
||||
}
|
||||
|
||||
// This is a sanity check; the actual checks will come later when the spend is attempted.
|
||||
if (!std::visit(HaveSpendingKeyForPaymentAddress(pwalletMain), addr.value())) {
|
||||
throw JSONRPCError(
|
||||
RPC_INVALID_ADDRESS_OR_KEY,
|
||||
"Invalid from address: does not belong to this node, spending key not found.");
|
||||
}
|
||||
|
||||
// Remember what sort of address this is
|
||||
std::visit(match {
|
||||
[&](const CKeyID&) {
|
||||
fromTaddr = true;
|
||||
},
|
||||
[&](const CScriptID&) {
|
||||
fromTaddr = true;
|
||||
},
|
||||
[&](const libzcash::SaplingPaymentAddress& addr) {
|
||||
fromSapling = true;
|
||||
},
|
||||
[&](const libzcash::SproutPaymentAddress& addr) {
|
||||
fromSprout = true;
|
||||
},
|
||||
[&](const libzcash::UnifiedAddress& ua) {
|
||||
throw JSONRPCError(
|
||||
RPC_INVALID_ADDRESS_OR_KEY,
|
||||
"Invalid from address: unified addresses are not yet supported.");
|
||||
}
|
||||
}, addr.value());
|
||||
}
|
||||
|
||||
UniValue outputs = params[1].get_array();
|
||||
|
@ -3780,45 +3794,57 @@ UniValue z_sendmany(const UniValue& params, bool fHelp)
|
|||
}
|
||||
|
||||
string address = find_value(o, "address").get_str();
|
||||
|
||||
bool isZaddr = false;
|
||||
CTxDestination taddr = keyIO.DecodeDestination(address);
|
||||
if (!IsValidDestination(taddr)) {
|
||||
auto addr = keyIO.DecodePaymentAddress(address);
|
||||
if (addr.has_value()) {
|
||||
isZaddr = true;
|
||||
|
||||
bool toSapling = std::holds_alternative<libzcash::SaplingPaymentAddress>(addr.value());
|
||||
bool toSprout = std::holds_alternative<libzcash::SproutPaymentAddress>(addr.value());
|
||||
noSproutAddrs = !toSprout && noSproutAddrs && toSapling;
|
||||
|
||||
containsSproutOutput |= toSprout;
|
||||
containsSaplingOutput |= toSapling;
|
||||
|
||||
// Sending to both Sprout and Sapling is currently unsupported using z_sendmany
|
||||
if (containsSproutOutput && containsSaplingOutput) {
|
||||
auto toAddr = keyIO.DecodePaymentAddress(address);
|
||||
if (toAddr.has_value()) {
|
||||
bool toSprout = false;
|
||||
bool toSapling = false;
|
||||
std::visit(match {
|
||||
[&](const CKeyID&) { },
|
||||
[&](const CScriptID&) { },
|
||||
[&](const libzcash::SaplingPaymentAddress& addr) {
|
||||
isZaddr = true;
|
||||
toSapling = true;
|
||||
containsSaplingOutput = true;
|
||||
},
|
||||
[&](const libzcash::SproutPaymentAddress& addr) {
|
||||
isZaddr = true;
|
||||
toSprout = true;
|
||||
containsSproutOutput = true;
|
||||
noSproutAddrs = false;
|
||||
},
|
||||
[&](const libzcash::UnifiedAddress& ua) {
|
||||
throw JSONRPCError(
|
||||
RPC_INVALID_PARAMETER,
|
||||
"Cannot send to both Sprout and Sapling addresses using z_sendmany");
|
||||
RPC_INVALID_ADDRESS_OR_KEY,
|
||||
"Invalid recipient address: unified addresses are not yet supported.");
|
||||
}
|
||||
}, toAddr.value());
|
||||
|
||||
// If sending between shielded addresses, they must be the same type
|
||||
if ((fromSprout && toSapling) || (fromSapling && toSprout)) {
|
||||
throw JSONRPCError(
|
||||
RPC_INVALID_PARAMETER,
|
||||
"Cannot send between Sprout and Sapling addresses using z_sendmany");
|
||||
}
|
||||
|
||||
int nextBlockHeight = chainActive.Height() + 1;
|
||||
|
||||
if (fromTaddr && toSprout) {
|
||||
const bool canopyActive = Params().GetConsensus().NetworkUpgradeActive(nextBlockHeight, Consensus::UPGRADE_CANOPY);
|
||||
if (canopyActive) {
|
||||
throw JSONRPCError(RPC_VERIFY_REJECTED, "Sprout shielding is not supported after Canopy");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ")+address );
|
||||
// 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 sending between shielded addresses, they must be the same type
|
||||
if ((fromSprout && toSapling) || (fromSapling && toSprout)) {
|
||||
throw JSONRPCError(
|
||||
RPC_INVALID_PARAMETER,
|
||||
"Cannot send between Sprout and Sapling addresses using z_sendmany");
|
||||
}
|
||||
|
||||
int nextBlockHeight = chainActive.Height() + 1;
|
||||
|
||||
if (fromTaddr && toSprout) {
|
||||
const bool canopyActive = Params().GetConsensus().NetworkUpgradeActive(nextBlockHeight, Consensus::UPGRADE_CANOPY);
|
||||
if (canopyActive) {
|
||||
throw JSONRPCError(RPC_VERIFY_REJECTED, "Sprout shielding is not supported after Canopy");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ")+address );
|
||||
}
|
||||
|
||||
if (setAddress.count(address))
|
||||
|
|
|
@ -362,20 +362,25 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_getbalance)
|
|||
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
|
||||
UniValue retValue;
|
||||
BOOST_CHECK_NO_THROW(retValue = CallRPC("getnewaddress"));
|
||||
std::string taddr1 = retValue.get_str();
|
||||
|
||||
BOOST_CHECK_THROW(CallRPC("z_getbalance too many args"), runtime_error);
|
||||
BOOST_CHECK_THROW(CallRPC("z_getbalance invalidaddress"), runtime_error);
|
||||
BOOST_CHECK_NO_THROW(CallRPC("z_getbalance tmC6YZnCUhm19dEXxh3Jb7srdBJxDawaCab"));
|
||||
BOOST_CHECK_THROW(CallRPC("z_getbalance tmC6YZnCUhm19dEXxh3Jb7srdBJxDawaCab -1"), runtime_error);
|
||||
BOOST_CHECK_NO_THROW(CallRPC("z_getbalance tmC6YZnCUhm19dEXxh3Jb7srdBJxDawaCab 0"));
|
||||
// address does not belong to wallet
|
||||
BOOST_CHECK_THROW(CallRPC("z_getbalance tmC6YZnCUhm19dEXxh3Jb7srdBJxDawaCab"), runtime_error);
|
||||
BOOST_CHECK_NO_THROW(CallRPC(std::string("z_getbalance ") + taddr1));
|
||||
// negative minconf not allowed
|
||||
BOOST_CHECK_THROW(CallRPC(std::string("z_getbalance ") + taddr1 + " -1"), runtime_error);
|
||||
BOOST_CHECK_NO_THROW(CallRPC(std::string("z_getbalance ") + taddr1 + std::string(" 0")));
|
||||
// don't have the spending key
|
||||
BOOST_CHECK_THROW(CallRPC("z_getbalance tnRZ8bPq2pff3xBWhTJhNkVUkm2uhzksDeW5PvEa7aFKGT9Qi3YgTALZfjaY4jU3HLVKBtHdSXxoPoLA3naMPcHBcY88FcF 1"), runtime_error);
|
||||
|
||||
|
||||
BOOST_CHECK_THROW(CallRPC("z_gettotalbalance too manyargs"), runtime_error);
|
||||
BOOST_CHECK_THROW(CallRPC("z_gettotalbalance -1"), runtime_error);
|
||||
BOOST_CHECK_NO_THROW(CallRPC("z_gettotalbalance 0"));
|
||||
|
||||
|
||||
BOOST_CHECK_THROW(CallRPC("z_listreceivedbyaddress too many args"), runtime_error);
|
||||
// negative minconf not allowed
|
||||
BOOST_CHECK_THROW(CallRPC("z_listreceivedbyaddress tmC6YZnCUhm19dEXxh3Jb7srdBJxDawaCab -1"), runtime_error);
|
||||
|
@ -1217,7 +1222,7 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_parameters)
|
|||
std::vector<SendManyRecipient> recipients = { SendManyRecipient("dummy", 1*COIN, "") };
|
||||
std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_sendmany(std::nullopt, mtx, "ztjiDe569DPNbyTE6TSdJTaSDhoXEHLGvYoUnBU1wfVNU52TEyT6berYtySkd21njAeEoh8fFJUT42kua9r8EnhBaEKqCpP", recipients, {}, 1) );
|
||||
} catch (const UniValue& objError) {
|
||||
BOOST_CHECK( find_error(objError, "no spending key found for zaddr"));
|
||||
BOOST_CHECK( find_error(objError, "no spending key found for address"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue