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:
@@ -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.");
|
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_utxos();
|
lock_utxos();
|
||||||
// Lock shielded input notes
|
|
||||||
lock_notes();
|
|
||||||
LogPrint("zrpc", "%s: z_sendmany input notes locked\n", getId());
|
|
||||||
|
|
||||||
CAmount t_inputs_total = 0;
|
CAmount t_inputs_total = 0;
|
||||||
for (SendManyInputUTXO & t : t_inputs_) {
|
for (SendManyInputUTXO & t : t_inputs_) {
|
||||||
@@ -412,7 +406,14 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
|||||||
std::vector<SaplingOutPoint> ops;
|
std::vector<SaplingOutPoint> ops;
|
||||||
std::vector<SaplingNote> notes;
|
std::vector<SaplingNote> notes;
|
||||||
CAmount sum = 0;
|
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);
|
ops.push_back(t.op);
|
||||||
notes.push_back(t.note);
|
notes.push_back(t.note);
|
||||||
sum += t.note.value();
|
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
|
// Fetch Sapling anchor and witnesses
|
||||||
//LogPrintf("%s: Gathering anchors and witnesses\n", __FUNCTION__);
|
//LogPrintf("%s: Gathering anchors and witnesses\n", __FUNCTION__);
|
||||||
uint256 anchor;
|
uint256 anchor;
|
||||||
@@ -665,9 +669,10 @@ bool AsyncRPCOperation_sendmany::find_unspent_notes() {
|
|||||||
pwalletMain->GetFilteredNotes(saplingEntries, fromaddress_, mindepth_);
|
pwalletMain->GetFilteredNotes(saplingEntries, fromaddress_, mindepth_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// store sapling inputs so we can correctly lock and unlock them
|
|
||||||
for (auto entry : saplingEntries) {
|
for (auto entry : saplingEntries) {
|
||||||
z_sapling_inputs_.push_back(entry);
|
z_sapling_inputs_.push_back(entry);
|
||||||
|
|
||||||
std::string data(entry.memo.begin(), entry.memo.end());
|
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",
|
LogPrint("zrpcunsafe", "%s: found unspent Sapling note (txid=%s, vShieldedSpend=%d, amount=%s, memo=%s)\n",
|
||||||
getId(),
|
getId(),
|
||||||
@@ -805,17 +810,17 @@ void AsyncRPCOperation_sendmany::unlock_utxos() {
|
|||||||
// Lock input notes
|
// Lock input notes
|
||||||
void AsyncRPCOperation_sendmany::lock_notes() {
|
void AsyncRPCOperation_sendmany::lock_notes() {
|
||||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||||
fprintf(stderr,"%s: found %lu notes to lock\n", __func__, z_sapling_inputs_.size() );
|
fprintf(stderr,"%s: found %lu notes to lock\n", __func__, saplingNoteInputs_.size() );
|
||||||
for (auto note : z_sapling_inputs_) {
|
for (auto note : saplingNoteInputs_) {
|
||||||
pwalletMain->LockNote(note.op);
|
pwalletMain->LockNote(std::get<0>(note));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unlock input notes
|
// Unlock input notes
|
||||||
void AsyncRPCOperation_sendmany::unlock_notes() {
|
void AsyncRPCOperation_sendmany::unlock_notes() {
|
||||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||||
fprintf(stderr,"%s: found %lu notes to unlock\n", __func__, z_sapling_inputs_.size() );
|
fprintf(stderr,"%s: found %lu notes to unlock\n", __func__, saplingNoteInputs_.size() );
|
||||||
for (auto note : z_sapling_inputs_) {
|
for (auto note : saplingNoteInputs_) {
|
||||||
pwalletMain->UnlockNote(note.op);
|
pwalletMain->UnlockNote(std::get<0>(note));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,9 @@ typedef std::tuple<std::string, CAmount, std::string> SendManyRecipient;
|
|||||||
// Input UTXO is a tuple (quadruple) of txid, vout, amount, coinbase)
|
// Input UTXO is a tuple (quadruple) of txid, vout, amount, coinbase)
|
||||||
typedef std::tuple<uint256, int, CAmount, bool, CTxDestination> SendManyInputUTXO;
|
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 {
|
class AsyncRPCOperation_sendmany : public AsyncRPCOperation {
|
||||||
public:
|
public:
|
||||||
AsyncRPCOperation_sendmany(
|
AsyncRPCOperation_sendmany(
|
||||||
@@ -93,6 +96,7 @@ private:
|
|||||||
std::vector<SendManyRecipient> z_outputs_;
|
std::vector<SendManyRecipient> z_outputs_;
|
||||||
std::vector<SendManyInputUTXO> t_inputs_;
|
std::vector<SendManyInputUTXO> t_inputs_;
|
||||||
std::vector<SaplingNoteEntry> z_sapling_inputs_;
|
std::vector<SaplingNoteEntry> z_sapling_inputs_;
|
||||||
|
std::vector<SendManyInputSaplingNote> saplingNoteInputs_;
|
||||||
|
|
||||||
TransactionBuilder builder_;
|
TransactionBuilder builder_;
|
||||||
CTransaction tx_;
|
CTransaction tx_;
|
||||||
|
|||||||
Reference in New Issue
Block a user