Remove a use of KeyIO::DecodeDestination in z_shieldcoinbase
This commit is contained in:
parent
20266ac911
commit
eb91c7869a
|
@ -26,6 +26,7 @@
|
|||
#include "walletdb.h"
|
||||
#include "script/interpreter.h"
|
||||
#include "utiltime.h"
|
||||
#include "util/match.h"
|
||||
#include "zcash/IncrementalMerkleTree.hpp"
|
||||
#include "miner.h"
|
||||
#include "wallet/paymentdisclosuredb.h"
|
||||
|
@ -63,7 +64,7 @@ AsyncRPCOperation_shieldcoinbase::AsyncRPCOperation_shieldcoinbase(
|
|||
TransactionBuilder builder,
|
||||
CMutableTransaction contextualTx,
|
||||
std::vector<ShieldCoinbaseUTXO> inputs,
|
||||
std::string toAddress,
|
||||
PaymentAddress toAddress,
|
||||
CAmount fee,
|
||||
UniValue contextInfo) :
|
||||
builder_(builder), tx_(contextualTx), inputs_(inputs), fee_(fee), contextinfo_(contextInfo)
|
||||
|
@ -79,13 +80,23 @@ AsyncRPCOperation_shieldcoinbase::AsyncRPCOperation_shieldcoinbase(
|
|||
}
|
||||
|
||||
// Check the destination address is valid for this network i.e. not testnet being used on mainnet
|
||||
KeyIO keyIO(Params());
|
||||
auto address = keyIO.DecodePaymentAddress(toAddress);
|
||||
if (address.has_value()) {
|
||||
tozaddr_ = address.value();
|
||||
} else {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid to address");
|
||||
std::visit(match {
|
||||
[&](CKeyID addr) {
|
||||
throw JSONRPCError(RPC_VERIFY_REJECTED, "Cannot shield coinbase output to a p2pkh address.");
|
||||
},
|
||||
[&](CScriptID addr) {
|
||||
throw JSONRPCError(RPC_VERIFY_REJECTED, "Cannot shield coinbase output to a p2pkh address.");
|
||||
},
|
||||
[&](libzcash::SaplingPaymentAddress addr) {
|
||||
tozaddr_ = addr;
|
||||
},
|
||||
[&](libzcash::SproutPaymentAddress addr) {
|
||||
tozaddr_ = addr;
|
||||
},
|
||||
[&](libzcash::UnifiedAddress) {
|
||||
throw JSONRPCError(RPC_VERIFY_REJECTED, "Cannot shield coinbase output to a unified address.");
|
||||
}
|
||||
}, toAddress);
|
||||
|
||||
// Log the context info
|
||||
if (LogAcceptCategory("zrpcunsafe")) {
|
||||
|
|
|
@ -45,7 +45,7 @@ public:
|
|||
TransactionBuilder builder,
|
||||
CMutableTransaction contextualTx,
|
||||
std::vector<ShieldCoinbaseUTXO> inputs,
|
||||
std::string toAddress,
|
||||
PaymentAddress toAddress,
|
||||
CAmount fee = DEFAULT_FEE,
|
||||
UniValue contextInfo = NullUniValue);
|
||||
virtual ~AsyncRPCOperation_shieldcoinbase();
|
||||
|
|
|
@ -4207,31 +4207,46 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp)
|
|||
auto fromaddress = params[0].get_str();
|
||||
bool isFromWildcard = fromaddress == "*";
|
||||
KeyIO keyIO(Params());
|
||||
CTxDestination taddr;
|
||||
|
||||
// Set of source addresses to filter utxos by
|
||||
std::set<CTxDestination> sources = {};
|
||||
if (!isFromWildcard) {
|
||||
taddr = keyIO.DecodeDestination(fromaddress);
|
||||
if (!IsValidDestination(taddr)) {
|
||||
CTxDestination taddr = keyIO.DecodeDestination(fromaddress);
|
||||
if (IsValidDestination(taddr)) {
|
||||
sources.insert(taddr);
|
||||
} else {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address, should be a taddr or \"*\".");
|
||||
}
|
||||
}
|
||||
|
||||
// Validate the destination address
|
||||
auto destaddress = params[1].get_str();
|
||||
if (!keyIO.IsValidPaymentAddressString(destaddress)) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ") + destaddress );
|
||||
}
|
||||
|
||||
int nextBlockHeight = chainActive.Height() + 1;
|
||||
const bool canopyActive = Params().GetConsensus().NetworkUpgradeActive(nextBlockHeight, Consensus::UPGRADE_CANOPY);
|
||||
|
||||
// Validate the destination address
|
||||
auto destStr = params[1].get_str();
|
||||
auto destaddress = keyIO.DecodePaymentAddress(destStr);
|
||||
if (destaddress.has_value()) {
|
||||
std::visit(match {
|
||||
[&](const CKeyID& addr) {
|
||||
throw JSONRPCError(RPC_VERIFY_REJECTED, "Cannot shield coinbase output to a p2pkh address.");
|
||||
},
|
||||
[&](const CScriptID&) {
|
||||
throw JSONRPCError(RPC_VERIFY_REJECTED, "Cannot shield coinbase output to a p2sh address.");
|
||||
},
|
||||
[&](const libzcash::SaplingPaymentAddress& addr) {
|
||||
// OK
|
||||
},
|
||||
[&](const libzcash::SproutPaymentAddress& addr) {
|
||||
if (canopyActive) {
|
||||
auto decodeAddr = keyIO.DecodePaymentAddress(destaddress);
|
||||
if (decodeAddr.has_value()) {
|
||||
libzcash::PaymentAddress addr(decodeAddr.value());
|
||||
if (std::holds_alternative<libzcash::SproutPaymentAddress>(addr)) {
|
||||
throw JSONRPCError(RPC_VERIFY_REJECTED, "Sprout shielding is not supported after Canopy activation");
|
||||
}
|
||||
},
|
||||
[&](const libzcash::UnifiedAddress& ua) {
|
||||
throw JSONRPCError(RPC_VERIFY_REJECTED, "Cannot shield coinbase output to a unified address.");
|
||||
}
|
||||
}, destaddress.value());
|
||||
} else {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ") + destStr);
|
||||
}
|
||||
|
||||
// Convert fee from currency format to zatoshis
|
||||
|
@ -4273,10 +4288,7 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp)
|
|||
bool maxedOutFlag = false;
|
||||
const size_t mempoolLimit = nLimit;
|
||||
|
||||
// Set of addresses to filter utxos by
|
||||
std::set<CTxDestination> destinations = {};
|
||||
if (!isFromWildcard) {
|
||||
destinations.insert(taddr);
|
||||
}
|
||||
|
||||
// Get available utxos
|
||||
|
@ -4293,8 +4305,9 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp)
|
|||
if (!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) {
|
||||
continue;
|
||||
}
|
||||
// If taddr is not wildcard "*", filter utxos
|
||||
if (destinations.size() > 0 && !destinations.count(address)) {
|
||||
|
||||
// If from address was not the wildcard "*", filter utxos
|
||||
if (sources.size() > 0 && !sources.count(address)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -4363,7 +4376,7 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp)
|
|||
|
||||
// Create operation and add to global queue
|
||||
std::shared_ptr<AsyncRPCQueue> q = getAsyncRPCQueue();
|
||||
std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_shieldcoinbase(builder, contextualTx, inputs, destaddress, nFee, contextInfo) );
|
||||
std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_shieldcoinbase(builder, contextualTx, inputs, destaddress.value(), nFee, contextInfo) );
|
||||
q->addOperation(operation);
|
||||
AsyncRPCOperationId operationId = operation->getId();
|
||||
|
||||
|
|
|
@ -1770,8 +1770,8 @@ BOOST_AUTO_TEST_CASE(rpc_z_shieldcoinbase_parameters)
|
|||
}
|
||||
|
||||
// Test constructor of AsyncRPCOperation_shieldcoinbase
|
||||
std::string testnetzaddr = "ztjiDe569DPNbyTE6TSdJTaSDhoXEHLGvYoUnBU1wfVNU52TEyT6berYtySkd21njAeEoh8fFJUT42kua9r8EnhBaEKqCpP";
|
||||
std::string mainnetzaddr = "zcMuhvq8sEkHALuSU2i4NbNQxshSAYrpCExec45ZjtivYPbuiFPwk6WHy4SvsbeZ4siy1WheuRGjtaJmoD1J8bFqNXhsG6U";
|
||||
KeyIO keyIO(Params());
|
||||
auto testnetzaddr = std::get<libzcash::SproutPaymentAddress>(keyIO.DecodePaymentAddress("ztjiDe569DPNbyTE6TSdJTaSDhoXEHLGvYoUnBU1wfVNU52TEyT6berYtySkd21njAeEoh8fFJUT42kua9r8EnhBaEKqCpP").value());
|
||||
|
||||
try {
|
||||
std::shared_ptr<AsyncRPCOperation> operation(new AsyncRPCOperation_shieldcoinbase(TransactionBuilder(), mtx, {}, testnetzaddr, -1 ));
|
||||
|
@ -1784,15 +1784,6 @@ BOOST_AUTO_TEST_CASE(rpc_z_shieldcoinbase_parameters)
|
|||
} catch (const UniValue& objError) {
|
||||
BOOST_CHECK( find_error(objError, "Empty inputs"));
|
||||
}
|
||||
|
||||
// Testnet payment addresses begin with 'zt'. This test detects an incorrect prefix.
|
||||
try {
|
||||
std::vector<ShieldCoinbaseUTXO> inputs = { ShieldCoinbaseUTXO{uint256(),0,0} };
|
||||
std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_shieldcoinbase(TransactionBuilder(), mtx, inputs, mainnetzaddr, 1) );
|
||||
} catch (const UniValue& objError) {
|
||||
BOOST_CHECK( find_error(objError, "Invalid to address"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1810,14 +1801,12 @@ BOOST_AUTO_TEST_CASE(rpc_z_shieldcoinbase_internals)
|
|||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(consensusParams, nHeight + 1);
|
||||
|
||||
// Add keys manually
|
||||
KeyIO keyIO(Params());
|
||||
auto pa = pwalletMain->GenerateNewSproutZKey();
|
||||
std::string zaddr = keyIO.EncodePaymentAddress(pa);
|
||||
|
||||
// Insufficient funds
|
||||
{
|
||||
std::vector<ShieldCoinbaseUTXO> inputs = { ShieldCoinbaseUTXO{uint256(),0,0} };
|
||||
std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_shieldcoinbase(TransactionBuilder(), mtx, inputs, zaddr) );
|
||||
std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_shieldcoinbase(TransactionBuilder(), mtx, inputs, pa) );
|
||||
operation->main();
|
||||
BOOST_CHECK(operation->isFailed());
|
||||
std::string msg = operation->getErrorMessage();
|
||||
|
@ -1828,7 +1817,7 @@ BOOST_AUTO_TEST_CASE(rpc_z_shieldcoinbase_internals)
|
|||
{
|
||||
// Dummy input so the operation object can be instantiated.
|
||||
std::vector<ShieldCoinbaseUTXO> inputs = { ShieldCoinbaseUTXO{uint256(),0,100000} };
|
||||
std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_shieldcoinbase(TransactionBuilder(), mtx, inputs, zaddr) );
|
||||
std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_shieldcoinbase(TransactionBuilder(), mtx, inputs, pa) );
|
||||
std::shared_ptr<AsyncRPCOperation_shieldcoinbase> ptr = std::dynamic_pointer_cast<AsyncRPCOperation_shieldcoinbase> (operation);
|
||||
TEST_FRIEND_AsyncRPCOperation_shieldcoinbase proxy(ptr);
|
||||
static_cast<AsyncRPCOperation_shieldcoinbase *>(operation.get())->testmode = true;
|
||||
|
@ -1940,9 +1929,6 @@ BOOST_AUTO_TEST_CASE(rpc_z_mergetoaddress_parameters)
|
|||
MergeToAddressRecipient testnetzaddr(
|
||||
"ztjiDe569DPNbyTE6TSdJTaSDhoXEHLGvYoUnBU1wfVNU52TEyT6berYtySkd21njAeEoh8fFJUT42kua9r8EnhBaEKqCpP",
|
||||
"testnet memo");
|
||||
MergeToAddressRecipient mainnetzaddr(
|
||||
"zcMuhvq8sEkHALuSU2i4NbNQxshSAYrpCExec45ZjtivYPbuiFPwk6WHy4SvsbeZ4siy1WheuRGjtaJmoD1J8bFqNXhsG6U",
|
||||
"mainnet memo");
|
||||
|
||||
try {
|
||||
std::shared_ptr<AsyncRPCOperation> operation(new AsyncRPCOperation_mergetoaddress(std::nullopt, mtx, {}, {}, {}, testnetzaddr, -1 ));
|
||||
|
@ -1987,15 +1973,6 @@ BOOST_AUTO_TEST_CASE(rpc_z_mergetoaddress_parameters)
|
|||
} catch (const UniValue& objError) {
|
||||
BOOST_CHECK(find_error(objError, "Sprout notes are not supported by the TransactionBuilder"));
|
||||
}
|
||||
|
||||
// Testnet payment addresses begin with 'zt'. This test detects an incorrect prefix.
|
||||
try {
|
||||
std::vector<MergeToAddressInputUTXO> inputs = { MergeToAddressInputUTXO{ COutPoint{uint256(), 0}, 0, CScript()} };
|
||||
std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_mergetoaddress(std::nullopt, mtx, inputs, {}, {}, mainnetzaddr, 1) );
|
||||
BOOST_FAIL("Should have caused an error");
|
||||
} catch (const UniValue& objError) {
|
||||
BOOST_CHECK( find_error(objError, "Invalid recipient address"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue