Use libzcash::PaymentAddress instead of std::string in mergetoaddress
This commit is contained in:
parent
eb91c7869a
commit
9702b47e2a
|
@ -68,7 +68,7 @@ AsyncRPCOperation_mergetoaddress::AsyncRPCOperation_mergetoaddress(
|
|||
CAmount fee,
|
||||
UniValue contextInfo) :
|
||||
tx_(contextualTx), utxoInputs_(utxoInputs), sproutNoteInputs_(sproutNoteInputs),
|
||||
saplingNoteInputs_(saplingNoteInputs), recipient_(recipient), fee_(fee), contextinfo_(contextInfo)
|
||||
saplingNoteInputs_(saplingNoteInputs), memo_(recipient.second), fee_(fee), contextinfo_(contextInfo)
|
||||
{
|
||||
if (fee < 0 || fee > MAX_MONEY) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Fee is out of range");
|
||||
|
@ -78,10 +78,6 @@ AsyncRPCOperation_mergetoaddress::AsyncRPCOperation_mergetoaddress(
|
|||
throw JSONRPCError(RPC_INVALID_PARAMETER, "No inputs");
|
||||
}
|
||||
|
||||
if (std::get<0>(recipient).size() == 0) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Recipient parameter missing");
|
||||
}
|
||||
|
||||
if (sproutNoteInputs.size() > 0 && saplingNoteInputs.size() > 0) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot send from both Sprout and Sapling addresses using z_mergetoaddress");
|
||||
}
|
||||
|
@ -100,34 +96,29 @@ AsyncRPCOperation_mergetoaddress::AsyncRPCOperation_mergetoaddress(
|
|||
isToTaddr_ = false;
|
||||
isToZaddr_ = false;
|
||||
|
||||
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");
|
||||
}
|
||||
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");
|
||||
},
|
||||
}, recipient.first);
|
||||
|
||||
// Log the context info i.e. the call parameters to z_mergetoaddress
|
||||
if (LogAcceptCategory("zrpcunsafe")) {
|
||||
|
@ -350,9 +341,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl()
|
|||
if (isToTaddr_) {
|
||||
builder_.AddTransparentOutput(toTaddr_, sendAmount);
|
||||
} else {
|
||||
std::string zaddr = std::get<0>(recipient_);
|
||||
std::string memo = std::get<1>(recipient_);
|
||||
std::array<unsigned char, ZC_MEMO_SIZE> hexMemo = get_memo_from_hex_string(memo);
|
||||
std::array<unsigned char, ZC_MEMO_SIZE> hexMemo = get_memo_from_hex_string(memo_);
|
||||
auto saplingPaymentAddress = std::get_if<libzcash::SaplingPaymentAddress>(&toPaymentAddress_);
|
||||
if (saplingPaymentAddress == nullptr) {
|
||||
// This should never happen as we have already determined that the payment is to sapling
|
||||
|
@ -404,14 +393,11 @@ bool AsyncRPCOperation_mergetoaddress::main_impl()
|
|||
* END SCENARIO #1
|
||||
*/
|
||||
|
||||
|
||||
// Prepare raw transaction to handle JoinSplits
|
||||
CMutableTransaction mtx(tx_);
|
||||
ed25519_generate_keypair(&joinSplitPrivKey_, &joinSplitPubKey_);
|
||||
mtx.joinSplitPubKey = joinSplitPubKey_;
|
||||
tx_ = CTransaction(mtx);
|
||||
std::string hexMemo = std::get<1>(recipient_);
|
||||
|
||||
|
||||
/**
|
||||
* SCENARIO #2
|
||||
|
@ -427,8 +413,8 @@ bool AsyncRPCOperation_mergetoaddress::main_impl()
|
|||
info.vpub_new = 0;
|
||||
|
||||
JSOutput jso = JSOutput(std::get<libzcash::SproutPaymentAddress>(toPaymentAddress_), sendAmount);
|
||||
if (hexMemo.size() > 0) {
|
||||
jso.memo = get_memo_from_hex_string(hexMemo);
|
||||
if (memo_.size() > 0) {
|
||||
jso.memo = get_memo_from_hex_string(memo_);
|
||||
}
|
||||
info.vjsout.push_back(jso);
|
||||
|
||||
|
@ -716,8 +702,8 @@ bool AsyncRPCOperation_mergetoaddress::main_impl()
|
|||
if (isToZaddr_ && vpubNewProcessed) {
|
||||
outputType = "target";
|
||||
jso.addr = std::get<libzcash::SproutPaymentAddress>(toPaymentAddress_);
|
||||
if (!hexMemo.empty()) {
|
||||
jso.memo = get_memo_from_hex_string(hexMemo);
|
||||
if (!memo_.empty()) {
|
||||
jso.memo = get_memo_from_hex_string(memo_);
|
||||
}
|
||||
}
|
||||
info.vjsout.push_back(jso);
|
||||
|
|
|
@ -34,7 +34,7 @@ typedef std::tuple<JSOutPoint, SproutNote, CAmount, SproutSpendingKey> MergeToAd
|
|||
typedef std::tuple<SaplingOutPoint, SaplingNote, CAmount, SaplingExpandedSpendingKey> MergeToAddressInputSaplingNote;
|
||||
|
||||
// A recipient is a tuple of address, memo (optional if zaddr)
|
||||
typedef std::tuple<std::string, std::string> MergeToAddressRecipient;
|
||||
typedef std::pair<libzcash::PaymentAddress, std::string> MergeToAddressRecipient;
|
||||
|
||||
// Package of info which is passed to perform_joinsplit methods.
|
||||
struct MergeToAddressJSInfo {
|
||||
|
@ -89,11 +89,11 @@ private:
|
|||
uint32_t consensusBranchId_;
|
||||
CAmount fee_;
|
||||
int mindepth_;
|
||||
MergeToAddressRecipient recipient_;
|
||||
bool isToTaddr_;
|
||||
bool isToZaddr_;
|
||||
CTxDestination toTaddr_;
|
||||
PaymentAddress toPaymentAddress_;
|
||||
std::string memo_;
|
||||
|
||||
Ed25519VerificationKey joinSplitPubKey_;
|
||||
Ed25519SigningKey joinSplitPrivKey_;
|
||||
|
|
|
@ -4487,20 +4487,32 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
|
|||
useAnySapling = true;
|
||||
isFromNonSprout = true;
|
||||
} else {
|
||||
CTxDestination taddr = keyIO.DecodeDestination(address);
|
||||
if (IsValidDestination(taddr)) {
|
||||
taddrs.insert(taddr);
|
||||
isFromNonSprout = true;
|
||||
} else {
|
||||
auto zaddr = keyIO.DecodePaymentAddress(address);
|
||||
if (zaddr.has_value()) {
|
||||
zaddrs.push_back(zaddr.value());
|
||||
if (std::holds_alternative<libzcash::SaplingPaymentAddress>(zaddr.value())) {
|
||||
auto addr = keyIO.DecodePaymentAddress(address);
|
||||
if (addr.has_value()) {
|
||||
std::visit(match {
|
||||
[&](const CKeyID& taddr) {
|
||||
taddrs.insert(taddr);
|
||||
isFromNonSprout = true;
|
||||
},
|
||||
[&](const CScriptID& taddr) {
|
||||
taddrs.insert(taddr);
|
||||
isFromNonSprout = true;
|
||||
},
|
||||
[&](const libzcash::SaplingPaymentAddress& zaddr) {
|
||||
zaddrs.push_back(zaddr);
|
||||
isFromNonSprout = true;
|
||||
},
|
||||
[&](const libzcash::SproutPaymentAddress& zaddr) {
|
||||
zaddrs.push_back(zaddr);
|
||||
},
|
||||
[&](libzcash::UnifiedAddress) {
|
||||
throw JSONRPCError(
|
||||
RPC_INVALID_PARAMETER,
|
||||
"Unified addresses are not supported in z_mergetoaddress");
|
||||
}
|
||||
} else {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Unknown address format: ") + address);
|
||||
}
|
||||
}, addr.value());
|
||||
} else {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Unknown address format: ") + address);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4522,12 +4534,12 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
|
|||
const bool canopyActive = Params().GetConsensus().NetworkUpgradeActive(nextBlockHeight, Consensus::UPGRADE_CANOPY);
|
||||
|
||||
// Validate the destination address
|
||||
auto destaddress = params[1].get_str();
|
||||
auto destStr = params[1].get_str();
|
||||
auto destaddress = keyIO.DecodePaymentAddress(destStr);
|
||||
bool isToTaddr = false;
|
||||
bool isToSproutZaddr = false;
|
||||
bool isToSaplingZaddr = false;
|
||||
auto paymentAddress = keyIO.DecodePaymentAddress(destaddress);
|
||||
if (paymentAddress.has_value()) {
|
||||
if (destaddress.has_value()) {
|
||||
std::visit(match {
|
||||
[&](CKeyID addr) {
|
||||
isToTaddr = true;
|
||||
|
@ -4546,11 +4558,15 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
|
|||
isToSproutZaddr = true;
|
||||
},
|
||||
[&](libzcash::UnifiedAddress) {
|
||||
// TODO UNIFIED
|
||||
throw JSONRPCError(
|
||||
RPC_INVALID_PARAMETER,
|
||||
"Invalid parameter, unified addresses are not yet supported.");
|
||||
}
|
||||
}, paymentAddress.value());
|
||||
}, destaddress.value());
|
||||
} else {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ") + destaddress );
|
||||
throw JSONRPCError(
|
||||
RPC_INVALID_PARAMETER,
|
||||
string("Invalid parameter, unknown address format: ") + destStr);
|
||||
}
|
||||
|
||||
if (canopyActive && isFromNonSprout && isToSproutZaddr) {
|
||||
|
@ -4600,7 +4616,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
|
|||
}
|
||||
}
|
||||
|
||||
MergeToAddressRecipient recipient(destaddress, memo);
|
||||
MergeToAddressRecipient recipient(destaddress.value(), memo);
|
||||
|
||||
// Prepare to get UTXOs and notes
|
||||
std::vector<MergeToAddressInputUTXO> utxoInputs;
|
||||
|
@ -4769,7 +4785,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
|
|||
// - We only have one from address
|
||||
// - It's equal to toaddress
|
||||
// - The address only contains a single UTXO or note
|
||||
if (setAddress.size() == 1 && setAddress.count(destaddress) && (numUtxos + numNotes) == 1) {
|
||||
if (setAddress.size() == 1 && setAddress.count(destStr) && (numUtxos + numNotes) == 1) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Destination address is also the only source address, and all its funds are already merged.");
|
||||
}
|
||||
|
||||
|
|
|
@ -1926,8 +1926,9 @@ BOOST_AUTO_TEST_CASE(rpc_z_mergetoaddress_parameters)
|
|||
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nHeight + 1);
|
||||
|
||||
// Test constructor of AsyncRPCOperation_mergetoaddress
|
||||
KeyIO keyIO(Params());
|
||||
MergeToAddressRecipient testnetzaddr(
|
||||
"ztjiDe569DPNbyTE6TSdJTaSDhoXEHLGvYoUnBU1wfVNU52TEyT6berYtySkd21njAeEoh8fFJUT42kua9r8EnhBaEKqCpP",
|
||||
keyIO.DecodePaymentAddress("ztjiDe569DPNbyTE6TSdJTaSDhoXEHLGvYoUnBU1wfVNU52TEyT6berYtySkd21njAeEoh8fFJUT42kua9r8EnhBaEKqCpP").value(),
|
||||
"testnet memo");
|
||||
|
||||
try {
|
||||
|
@ -1946,14 +1947,6 @@ BOOST_AUTO_TEST_CASE(rpc_z_mergetoaddress_parameters)
|
|||
|
||||
std::vector<MergeToAddressInputUTXO> inputs = { MergeToAddressInputUTXO{ COutPoint{uint256(), 0}, 0, CScript()} };
|
||||
|
||||
try {
|
||||
MergeToAddressRecipient badaddr("", "memo");
|
||||
std::shared_ptr<AsyncRPCOperation> operation(new AsyncRPCOperation_mergetoaddress(std::nullopt, mtx, inputs, {}, {}, badaddr, 1));
|
||||
BOOST_FAIL("Should have caused an error");
|
||||
} catch (const UniValue& objError) {
|
||||
BOOST_CHECK( find_error(objError, "Recipient parameter missing"));
|
||||
}
|
||||
|
||||
std::vector<MergeToAddressInputSproutNote> sproutNoteInputs =
|
||||
{MergeToAddressInputSproutNote{JSOutPoint(), SproutNote(), 0, SproutSpendingKey()}};
|
||||
std::vector<MergeToAddressInputSaplingNote> saplingNoteInputs =
|
||||
|
@ -1981,6 +1974,7 @@ BOOST_AUTO_TEST_CASE(rpc_z_mergetoaddress_internals)
|
|||
{
|
||||
SelectParams(CBaseChainParams::TESTNET);
|
||||
const Consensus::Params& consensusParams = Params().GetConsensus();
|
||||
KeyIO keyIO(Params());
|
||||
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
|
||||
|
@ -1994,10 +1988,9 @@ BOOST_AUTO_TEST_CASE(rpc_z_mergetoaddress_internals)
|
|||
|
||||
// Add keys manually
|
||||
BOOST_CHECK_NO_THROW(retValue = CallRPC("getnewaddress"));
|
||||
MergeToAddressRecipient taddr1(retValue.get_str(), "");
|
||||
MergeToAddressRecipient taddr1(keyIO.DecodePaymentAddress(retValue.get_str()).value(), "");
|
||||
auto pa = pwalletMain->GenerateNewSproutZKey();
|
||||
KeyIO keyIO(Params());
|
||||
MergeToAddressRecipient zaddr1(keyIO.EncodePaymentAddress(pa), "DEADBEEF");
|
||||
MergeToAddressRecipient zaddr1(pa, "DEADBEEF");
|
||||
|
||||
// Insufficient funds
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue