Keep a list of notes we are spending and must lock which is different from the list of all notes we might spend

This commit is contained in:
Duke
2025-05-31 11:50:38 -04:00
parent b5db300aed
commit 007f2b31af
2 changed files with 23 additions and 14 deletions

View File

@@ -234,14 +234,8 @@ bool AsyncRPCOperation_sendmany::main_impl() {
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Insufficient funds, no unspent notes found for zaddr from address.");
}
// Now that find_unspent_notes() has run, we now know which
// notes need to be locked
// Lock UTXOs
lock_utxos();
// Lock shielded input notes
lock_notes();
LogPrint("zrpc", "%s: z_sendmany input notes locked\n", getId());
CAmount t_inputs_total = 0;
for (SendManyInputUTXO & t : t_inputs_) {
@@ -412,7 +406,14 @@ bool AsyncRPCOperation_sendmany::main_impl() {
std::vector<SaplingOutPoint> ops;
std::vector<SaplingNote> notes;
CAmount sum = 0;
for (auto t : z_sapling_inputs_) {
//NOTE: z_sapling_inputs_ is a list of all potential notes to spend
// saplingNoteInputs_ is a list of notes we will actually spend
// and need to lock. It is a subset of z_sapling_inputs_
for (const auto t : z_sapling_inputs_) {
// keep track of notes to lock later on in lock_notes()
saplingNoteInputs_.emplace_back(t.op, t.note, t.note.value() );
ops.push_back(t.op);
notes.push_back(t.note);
sum += t.note.value();
@@ -421,6 +422,9 @@ bool AsyncRPCOperation_sendmany::main_impl() {
}
}
// Lock shielded input notes (zins) stored in saplingNoteInputs
lock_notes();
// Fetch Sapling anchor and witnesses
//LogPrintf("%s: Gathering anchors and witnesses\n", __FUNCTION__);
uint256 anchor;
@@ -665,9 +669,10 @@ bool AsyncRPCOperation_sendmany::find_unspent_notes() {
pwalletMain->GetFilteredNotes(saplingEntries, fromaddress_, mindepth_);
}
// store sapling inputs so we can correctly lock and unlock them
for (auto entry : saplingEntries) {
z_sapling_inputs_.push_back(entry);
std::string data(entry.memo.begin(), entry.memo.end());
LogPrint("zrpcunsafe", "%s: found unspent Sapling note (txid=%s, vShieldedSpend=%d, amount=%s, memo=%s)\n",
getId(),
@@ -805,17 +810,17 @@ void AsyncRPCOperation_sendmany::unlock_utxos() {
// Lock input notes
void AsyncRPCOperation_sendmany::lock_notes() {
LOCK2(cs_main, pwalletMain->cs_wallet);
fprintf(stderr,"%s: found %lu notes to lock\n", __func__, z_sapling_inputs_.size() );
for (auto note : z_sapling_inputs_) {
pwalletMain->LockNote(note.op);
fprintf(stderr,"%s: found %lu notes to lock\n", __func__, saplingNoteInputs_.size() );
for (auto note : saplingNoteInputs_) {
pwalletMain->LockNote(std::get<0>(note));
}
}
// Unlock input notes
void AsyncRPCOperation_sendmany::unlock_notes() {
LOCK2(cs_main, pwalletMain->cs_wallet);
fprintf(stderr,"%s: found %lu notes to unlock\n", __func__, z_sapling_inputs_.size() );
for (auto note : z_sapling_inputs_) {
pwalletMain->UnlockNote(note.op);
fprintf(stderr,"%s: found %lu notes to unlock\n", __func__, saplingNoteInputs_.size() );
for (auto note : saplingNoteInputs_) {
pwalletMain->UnlockNote(std::get<0>(note));
}
}

View File

@@ -45,6 +45,9 @@ typedef std::tuple<std::string, CAmount, std::string> SendManyRecipient;
// Input UTXO is a tuple (quadruple) of txid, vout, amount, coinbase)
typedef std::tuple<uint256, int, CAmount, bool, CTxDestination> SendManyInputUTXO;
// Input note is a tuple of output, note, amount
typedef std::tuple<SaplingOutPoint, SaplingNote, CAmount> SendManyInputSaplingNote;
class AsyncRPCOperation_sendmany : public AsyncRPCOperation {
public:
AsyncRPCOperation_sendmany(
@@ -93,6 +96,7 @@ private:
std::vector<SendManyRecipient> z_outputs_;
std::vector<SendManyInputUTXO> t_inputs_;
std::vector<SaplingNoteEntry> z_sapling_inputs_;
std::vector<SendManyInputSaplingNote> saplingNoteInputs_;
TransactionBuilder builder_;
CTransaction tx_;