Major updates integration from all upstreams
This commit is contained in:
@@ -8,12 +8,13 @@
|
||||
#include "asyncrpcqueue.h"
|
||||
#include "core_io.h"
|
||||
#include "init.h"
|
||||
#include "key_io.h"
|
||||
#include "main.h"
|
||||
#include "miner.h"
|
||||
#include "net.h"
|
||||
#include "netbase.h"
|
||||
#include "rpcprotocol.h"
|
||||
#include "rpcserver.h"
|
||||
#include "rpc/protocol.h"
|
||||
#include "rpc/server.h"
|
||||
#include "script/interpreter.h"
|
||||
#include "sodium.h"
|
||||
#include "timedata.h"
|
||||
@@ -73,19 +74,19 @@ AsyncRPCOperation_mergetoaddress::AsyncRPCOperation_mergetoaddress(
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Recipient parameter missing");
|
||||
}
|
||||
|
||||
toTaddr_ = CBitcoinAddress(std::get<0>(recipient));
|
||||
isToTaddr_ = toTaddr_.IsValid();
|
||||
toTaddr_ = DecodeDestination(std::get<0>(recipient));
|
||||
isToTaddr_ = IsValidDestination(toTaddr_);
|
||||
isToZaddr_ = false;
|
||||
|
||||
if (!isToTaddr_) {
|
||||
CZCPaymentAddress address(std::get<0>(recipient));
|
||||
try {
|
||||
PaymentAddress addr = address.Get();
|
||||
|
||||
auto address = DecodePaymentAddress(std::get<0>(recipient));
|
||||
if (IsValidPaymentAddress(address)) {
|
||||
isToZaddr_ = true;
|
||||
toPaymentAddress_ = addr;
|
||||
} catch (const std::runtime_error& e) {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("runtime error: ") + e.what());
|
||||
// TODO: Add Sapling support. For now, ensure we can later convert freely.
|
||||
assert(boost::get<libzcash::SproutPaymentAddress>(&address) != nullptr);
|
||||
toPaymentAddress_ = address;
|
||||
} else {
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid recipient address");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,6 +208,12 @@ bool AsyncRPCOperation_mergetoaddress::main_impl()
|
||||
|
||||
// Check mempooltxinputlimit to avoid creating a transaction which the local mempool rejects
|
||||
size_t limit = (size_t)GetArg("-mempooltxinputlimit", 0);
|
||||
{
|
||||
LOCK(cs_main);
|
||||
if (NetworkUpgradeActive(chainActive.Height() + 1, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER)) {
|
||||
limit = 0;
|
||||
}
|
||||
}
|
||||
if (limit > 0 && numInputs > limit) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR,
|
||||
strprintf("Number of transparent inputs %d is greater than mempooltxinputlimit of %d",
|
||||
@@ -240,7 +247,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl()
|
||||
rawTx.vin.push_back(in);
|
||||
}
|
||||
if (isToTaddr_) {
|
||||
CScript scriptPubKey = GetScriptForDestination(toTaddr_.Get());
|
||||
CScript scriptPubKey = GetScriptForDestination(toTaddr_);
|
||||
CTxOut out(sendAmount, scriptPubKey);
|
||||
rawTx.vout.push_back(out);
|
||||
}
|
||||
@@ -302,7 +309,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl()
|
||||
info.vpub_old = sendAmount;
|
||||
info.vpub_new = 0;
|
||||
|
||||
JSOutput jso = JSOutput(toPaymentAddress_, sendAmount);
|
||||
JSOutput jso = JSOutput(boost::get<libzcash::SproutPaymentAddress>(toPaymentAddress_), sendAmount);
|
||||
if (hexMemo.size() > 0) {
|
||||
jso.memo = get_memo_from_hex_string(hexMemo);
|
||||
}
|
||||
@@ -321,6 +328,8 @@ bool AsyncRPCOperation_mergetoaddress::main_impl()
|
||||
// Copy zinputs to more flexible containers
|
||||
std::deque<MergeToAddressInputNote> zInputsDeque;
|
||||
for (auto o : noteInputs_) {
|
||||
// TODO: Add Sapling support. For now, ensure we can later convert freely.
|
||||
assert(boost::get<libzcash::SproutSpendingKey>(&std::get<3>(o)) != nullptr);
|
||||
zInputsDeque.push_back(o);
|
||||
}
|
||||
|
||||
@@ -333,8 +342,8 @@ bool AsyncRPCOperation_mergetoaddress::main_impl()
|
||||
JSOutPoint jso = std::get<0>(t);
|
||||
std::vector<JSOutPoint> vOutPoints = {jso};
|
||||
uint256 inputAnchor;
|
||||
std::vector<boost::optional<ZCIncrementalWitness>> vInputWitnesses;
|
||||
pwalletMain->GetNoteWitnesses(vOutPoints, vInputWitnesses, inputAnchor);
|
||||
std::vector<boost::optional<SproutWitness>> vInputWitnesses;
|
||||
pwalletMain->GetSproutNoteWitnesses(vOutPoints, vInputWitnesses, inputAnchor);
|
||||
jsopWitnessAnchorMap[jso.ToString()] = MergeToAddressWitnessAnchorData{vInputWitnesses[0], inputAnchor};
|
||||
}
|
||||
}
|
||||
@@ -360,8 +369,8 @@ bool AsyncRPCOperation_mergetoaddress::main_impl()
|
||||
|
||||
// At this point, we are guaranteed to have at least one input note.
|
||||
// Use address of first input note as the temporary change address.
|
||||
SpendingKey changeKey = std::get<3>(zInputsDeque.front());
|
||||
PaymentAddress changeAddress = changeKey.address();
|
||||
SproutSpendingKey changeKey = boost::get<libzcash::SproutSpendingKey>(std::get<3>(zInputsDeque.front()));
|
||||
SproutPaymentAddress changeAddress = changeKey.address();
|
||||
|
||||
CAmount vpubOldTarget = 0;
|
||||
CAmount vpubNewTarget = 0;
|
||||
@@ -376,7 +385,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl()
|
||||
}
|
||||
|
||||
// Keep track of treestate within this transaction
|
||||
boost::unordered_map<uint256, ZCIncrementalMerkleTree, CCoinsKeyHasher> intermediates;
|
||||
boost::unordered_map<uint256, SproutMerkleTree, CCoinsKeyHasher> intermediates;
|
||||
std::vector<uint256> previousCommitments;
|
||||
|
||||
while (!vpubNewProcessed) {
|
||||
@@ -397,7 +406,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl()
|
||||
|
||||
CAmount jsInputValue = 0;
|
||||
uint256 jsAnchor;
|
||||
std::vector<boost::optional<ZCIncrementalWitness>> witnesses;
|
||||
std::vector<boost::optional<SproutWitness>> witnesses;
|
||||
|
||||
JSDescription prevJoinSplit;
|
||||
|
||||
@@ -419,16 +428,16 @@ bool AsyncRPCOperation_mergetoaddress::main_impl()
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
|
||||
// Update tree state with previous joinsplit
|
||||
ZCIncrementalMerkleTree tree;
|
||||
SproutMerkleTree tree;
|
||||
auto it = intermediates.find(prevJoinSplit.anchor);
|
||||
if (it != intermediates.end()) {
|
||||
tree = it->second;
|
||||
} else if (!pcoinsTip->GetAnchorAt(prevJoinSplit.anchor, tree)) {
|
||||
} else if (!pcoinsTip->GetSproutAnchorAt(prevJoinSplit.anchor, tree)) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Could not find previous JoinSplit anchor");
|
||||
}
|
||||
|
||||
assert(changeOutputIndex != -1);
|
||||
boost::optional<ZCIncrementalWitness> changeWitness;
|
||||
boost::optional<SproutWitness> changeWitness;
|
||||
int n = 0;
|
||||
for (const uint256& commitment : prevJoinSplit.commitments) {
|
||||
tree.append(commitment);
|
||||
@@ -449,22 +458,22 @@ bool AsyncRPCOperation_mergetoaddress::main_impl()
|
||||
ZCNoteDecryption decryptor(changeKey.receiving_key());
|
||||
auto hSig = prevJoinSplit.h_sig(*pzcashParams, tx_.joinSplitPubKey);
|
||||
try {
|
||||
NotePlaintext plaintext = NotePlaintext::decrypt(
|
||||
SproutNotePlaintext plaintext = SproutNotePlaintext::decrypt(
|
||||
decryptor,
|
||||
prevJoinSplit.ciphertexts[changeOutputIndex],
|
||||
prevJoinSplit.ephemeralKey,
|
||||
hSig,
|
||||
(unsigned char)changeOutputIndex);
|
||||
|
||||
Note note = plaintext.note(changeAddress);
|
||||
SproutNote note = plaintext.note(changeAddress);
|
||||
info.notes.push_back(note);
|
||||
info.zkeys.push_back(changeKey);
|
||||
|
||||
jsInputValue += plaintext.value;
|
||||
jsInputValue += plaintext.value();
|
||||
|
||||
LogPrint("zrpcunsafe", "%s: spending change (amount=%s)\n",
|
||||
getId(),
|
||||
FormatMoney(plaintext.value));
|
||||
FormatMoney(plaintext.value()));
|
||||
|
||||
} catch (const std::exception& e) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, strprintf("Error decrypting output note of previous JoinSplit: %s", e.what()));
|
||||
@@ -475,18 +484,18 @@ bool AsyncRPCOperation_mergetoaddress::main_impl()
|
||||
//
|
||||
// Consume spendable non-change notes
|
||||
//
|
||||
std::vector<Note> vInputNotes;
|
||||
std::vector<SpendingKey> vInputZKeys;
|
||||
std::vector<SproutNote> vInputNotes;
|
||||
std::vector<SproutSpendingKey> vInputZKeys;
|
||||
std::vector<JSOutPoint> vOutPoints;
|
||||
std::vector<boost::optional<ZCIncrementalWitness>> vInputWitnesses;
|
||||
std::vector<boost::optional<SproutWitness>> vInputWitnesses;
|
||||
uint256 inputAnchor;
|
||||
int numInputsNeeded = (jsChange > 0) ? 1 : 0;
|
||||
while (numInputsNeeded++ < ZC_NUM_JS_INPUTS && zInputsDeque.size() > 0) {
|
||||
MergeToAddressInputNote t = zInputsDeque.front();
|
||||
JSOutPoint jso = std::get<0>(t);
|
||||
Note note = std::get<1>(t);
|
||||
SproutNote note = std::get<1>(t);
|
||||
CAmount noteFunds = std::get<2>(t);
|
||||
SpendingKey zkey = std::get<3>(t);
|
||||
SproutSpendingKey zkey = boost::get<libzcash::SproutSpendingKey>(std::get<3>(t));
|
||||
zInputsDeque.pop_front();
|
||||
|
||||
MergeToAddressWitnessAnchorData wad = jsopWitnessAnchorMap[jso.ToString()];
|
||||
@@ -535,7 +544,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl()
|
||||
if (!optionalWitness) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Witness for note commitment is null");
|
||||
}
|
||||
ZCIncrementalWitness w = *optionalWitness; // could use .get();
|
||||
SproutWitness w = *optionalWitness; // could use .get();
|
||||
if (jsChange > 0) {
|
||||
for (const uint256& commitment : previousCommitments) {
|
||||
w.append(commitment);
|
||||
@@ -585,7 +594,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl()
|
||||
// If this is the final output, set the target and memo
|
||||
if (isToZaddr_ && vpubNewProcessed) {
|
||||
outputType = "target";
|
||||
jso.addr = toPaymentAddress_;
|
||||
jso.addr = boost::get<libzcash::SproutPaymentAddress>(toPaymentAddress_);
|
||||
if (!hexMemo.empty()) {
|
||||
jso.memo = get_memo_from_hex_string(hexMemo);
|
||||
}
|
||||
@@ -614,6 +623,9 @@ bool AsyncRPCOperation_mergetoaddress::main_impl()
|
||||
}
|
||||
|
||||
|
||||
extern UniValue signrawtransaction(const UniValue& params, bool fHelp);
|
||||
extern UniValue sendrawtransaction(const UniValue& params, bool fHelp);
|
||||
|
||||
/**
|
||||
* Sign and send a raw transaction.
|
||||
* Raw transaction as hex string should be in object field "rawtxn"
|
||||
@@ -683,11 +695,11 @@ void AsyncRPCOperation_mergetoaddress::sign_send_raw_transaction(UniValue obj)
|
||||
|
||||
UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit(MergeToAddressJSInfo& info)
|
||||
{
|
||||
std::vector<boost::optional<ZCIncrementalWitness>> witnesses;
|
||||
std::vector<boost::optional<SproutWitness>> witnesses;
|
||||
uint256 anchor;
|
||||
{
|
||||
LOCK(cs_main);
|
||||
anchor = pcoinsTip->GetBestAnchor(); // As there are no inputs, ask the wallet for the best anchor
|
||||
anchor = pcoinsTip->GetBestAnchor(SPROUT); // As there are no inputs, ask the wallet for the best anchor
|
||||
}
|
||||
return perform_joinsplit(info, witnesses, anchor);
|
||||
}
|
||||
@@ -695,18 +707,18 @@ UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit(MergeToAddressJSInf
|
||||
|
||||
UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit(MergeToAddressJSInfo& info, std::vector<JSOutPoint>& outPoints)
|
||||
{
|
||||
std::vector<boost::optional<ZCIncrementalWitness>> witnesses;
|
||||
std::vector<boost::optional<SproutWitness>> witnesses;
|
||||
uint256 anchor;
|
||||
{
|
||||
LOCK(cs_main);
|
||||
pwalletMain->GetNoteWitnesses(outPoints, witnesses, anchor);
|
||||
pwalletMain->GetSproutNoteWitnesses(outPoints, witnesses, anchor);
|
||||
}
|
||||
return perform_joinsplit(info, witnesses, anchor);
|
||||
}
|
||||
|
||||
UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit(
|
||||
MergeToAddressJSInfo& info,
|
||||
std::vector<boost::optional<ZCIncrementalWitness>> witnesses,
|
||||
std::vector<boost::optional<SproutWitness>> witnesses,
|
||||
uint256 anchor)
|
||||
{
|
||||
if (anchor.IsNull()) {
|
||||
@@ -747,24 +759,19 @@ UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit(
|
||||
getId(),
|
||||
tx_.vjoinsplit.size(),
|
||||
FormatMoney(info.vpub_old), FormatMoney(info.vpub_new),
|
||||
FormatMoney(info.vjsin[0].note.value), FormatMoney(info.vjsin[1].note.value),
|
||||
FormatMoney(info.vjsin[0].note.value()), FormatMoney(info.vjsin[1].note.value()),
|
||||
FormatMoney(info.vjsout[0].value), FormatMoney(info.vjsout[1].value));
|
||||
|
||||
// Generate the proof, this can take over a minute.
|
||||
boost::array<libzcash::JSInput, ZC_NUM_JS_INPUTS> inputs{info.vjsin[0], info.vjsin[1]};
|
||||
boost::array<libzcash::JSOutput, ZC_NUM_JS_OUTPUTS> outputs{info.vjsout[0], info.vjsout[1]};
|
||||
#ifdef __LP64__
|
||||
boost::array<uint64_t, ZC_NUM_JS_INPUTS> inputMap;
|
||||
boost::array<uint64_t, ZC_NUM_JS_OUTPUTS> outputMap;
|
||||
#else
|
||||
boost::array<size_t, ZC_NUM_JS_INPUTS> inputMap;
|
||||
boost::array<size_t, ZC_NUM_JS_OUTPUTS> outputMap;
|
||||
#endif
|
||||
|
||||
std::array<libzcash::JSInput, ZC_NUM_JS_INPUTS> inputs{info.vjsin[0], info.vjsin[1]};
|
||||
std::array<libzcash::JSOutput, ZC_NUM_JS_OUTPUTS> outputs{info.vjsout[0], info.vjsout[1]};
|
||||
std::array<size_t, ZC_NUM_JS_INPUTS> inputMap;
|
||||
std::array<size_t, ZC_NUM_JS_OUTPUTS> outputMap;
|
||||
|
||||
uint256 esk; // payment disclosure - secret
|
||||
|
||||
JSDescription jsdesc = JSDescription::Randomized(
|
||||
mtx.fOverwintered && (mtx.nVersion >= SAPLING_TX_VERSION),
|
||||
*pzcashParams,
|
||||
joinSplitPubKey_,
|
||||
anchor,
|
||||
@@ -834,10 +841,10 @@ UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit(
|
||||
UniValue arrInputMap(UniValue::VARR);
|
||||
UniValue arrOutputMap(UniValue::VARR);
|
||||
for (size_t i = 0; i < ZC_NUM_JS_INPUTS; i++) {
|
||||
arrInputMap.push_back(inputMap[i]);
|
||||
arrInputMap.push_back(static_cast<uint64_t>(inputMap[i]));
|
||||
}
|
||||
for (size_t i = 0; i < ZC_NUM_JS_OUTPUTS; i++) {
|
||||
arrOutputMap.push_back(outputMap[i]);
|
||||
arrOutputMap.push_back(static_cast<uint64_t>(outputMap[i]));
|
||||
}
|
||||
|
||||
|
||||
@@ -853,12 +860,11 @@ UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit(
|
||||
// placeholder for txid will be filled in later when tx has been finalized and signed.
|
||||
PaymentDisclosureKey pdKey = {placeholder, js_index, mapped_index};
|
||||
JSOutput output = outputs[mapped_index];
|
||||
libzcash::PaymentAddress zaddr = output.addr; // randomized output
|
||||
libzcash::SproutPaymentAddress zaddr = output.addr; // randomized output
|
||||
PaymentDisclosureInfo pdInfo = {PAYMENT_DISCLOSURE_VERSION_EXPERIMENTAL, esk, joinSplitPrivKey, zaddr};
|
||||
paymentDisclosureData_.push_back(PaymentDisclosureKeyInfo(pdKey, pdInfo));
|
||||
|
||||
CZCPaymentAddress address(zaddr);
|
||||
LogPrint("paymentdisclosure", "%s: Payment Disclosure: js=%d, n=%d, zaddr=%s\n", getId(), js_index, int(mapped_index), address.ToString());
|
||||
LogPrint("paymentdisclosure", "%s: Payment Disclosure: js=%d, n=%d, zaddr=%s\n", getId(), js_index, int(mapped_index), EncodePaymentAddress(zaddr));
|
||||
}
|
||||
// !!! Payment disclosure END
|
||||
|
||||
@@ -871,9 +877,9 @@ UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit(
|
||||
return obj;
|
||||
}
|
||||
|
||||
boost::array<unsigned char, ZC_MEMO_SIZE> AsyncRPCOperation_mergetoaddress::get_memo_from_hex_string(std::string s)
|
||||
std::array<unsigned char, ZC_MEMO_SIZE> AsyncRPCOperation_mergetoaddress::get_memo_from_hex_string(std::string s)
|
||||
{
|
||||
boost::array<unsigned char, ZC_MEMO_SIZE> memo = {{0x00}};
|
||||
std::array<unsigned char, ZC_MEMO_SIZE> memo = {{0x00}};
|
||||
|
||||
std::vector<unsigned char> rawMemo = ParseHex(s.c_str());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user