From cca9cfe7c866d0e786228c93c4cc38f77a176f4b Mon Sep 17 00:00:00 2001 From: David Burkett Date: Tue, 5 Apr 2022 01:39:02 -0400 Subject: [PATCH] * Adding mweb_wtx_info to WalletTxToJSON * Better handling of conflicting wallet tx data during rescan * Fix create tx dialog for txs using subtract fee from amount * Safer MWEB block undo logic --- src/libmw/src/node/CoinsViewCache.cpp | 8 +++---- src/mweb/mweb_transact.cpp | 4 ++++ src/qt/walletmodeltransaction.cpp | 29 +++++++++++++----------- src/wallet/rpcwallet.cpp | 20 +++++++++++++++++ src/wallet/wallet.cpp | 32 +++++++++++++++++++-------- src/wallet/wallet.h | 1 + 6 files changed, 68 insertions(+), 26 deletions(-) diff --git a/src/libmw/src/node/CoinsViewCache.cpp b/src/libmw/src/node/CoinsViewCache.cpp index fb222b8867..43bbd652d8 100644 --- a/src/libmw/src/node/CoinsViewCache.cpp +++ b/src/libmw/src/node/CoinsViewCache.cpp @@ -96,16 +96,16 @@ void CoinsViewCache::UndoBlock(const mw::BlockUndo::CPtr& pUndo) { assert(pUndo != nullptr); - for (const mw::Hash& coinToRemove : pUndo->GetCoinsAdded()) { - m_pUpdates->SpendUTXO(coinToRemove); - } - std::vector leavesToAdd; for (const UTXO& coinToAdd : pUndo->GetCoinsSpent()) { leavesToAdd.push_back(coinToAdd.GetLeafIndex()); m_pUpdates->AddUTXO(std::make_shared(coinToAdd)); } + for (const mw::Hash& coinToRemove : pUndo->GetCoinsAdded()) { + m_pUpdates->SpendUTXO(coinToRemove); + } + auto pHeader = pUndo->GetPreviousHeader(); if (pHeader == nullptr) { m_pLeafSet->Rewind(0, {}); diff --git a/src/mweb/mweb_transact.cpp b/src/mweb/mweb_transact.cpp index 2ebcf85fee..f7c3dd534b 100644 --- a/src/mweb/mweb_transact.cpp +++ b/src/mweb/mweb_transact.cpp @@ -140,6 +140,10 @@ void Transact::AddMWEBTx(InProcessTx& new_tx) m_wallet.GetMWWallet()->SaveToWallet(output_coins); } + // TxBuilder::BuildTx only builds partial coins. + // We still need to rewind them to populate any remaining fields, like address index. + m_wallet.GetMWWallet()->RewindOutputs(CTransaction(new_tx.tx)); + // Update pegin output auto pegins = new_tx.tx.mweb_tx.GetPegIns(); if (!pegins.empty()) { diff --git a/src/qt/walletmodeltransaction.cpp b/src/qt/walletmodeltransaction.cpp index 3608b84cdd..6ac86d2e9c 100644 --- a/src/qt/walletmodeltransaction.cpp +++ b/src/qt/walletmodeltransaction.cpp @@ -44,24 +44,27 @@ void WalletModelTransaction::setTransactionFee(const CAmount& newFee) void WalletModelTransaction::reassignAmounts(interfaces::Wallet& wallet, int nChangePosRet) { std::vector outputs = wtx->GetOutputs(); + std::vector pegouts = wtx->mweb_tx.GetPegOuts(); - if (nChangePosRet == -1) { - for (size_t i = 0; i < outputs.size(); i++) { - if (wallet.isChange(outputs[i])) { - nChangePosRet = i; - break; - } - } - } - - int i = 0; + size_t i = 0; for (QList::iterator it = recipients.begin(); it != recipients.end(); ++it) { SendCoinsRecipient& rcp = (*it); { - if (i == nChangePosRet) - i++; - rcp.amount = wallet.getValue(outputs[i]); + while (i < outputs.size()) { + if (wallet.isChange(outputs[i]) || (!outputs[i].IsMWEB() && outputs[i].GetScriptPubKey().IsMWEBPegin())) { + i++; + } else { + break; + } + } + + if (i < outputs.size()) { + rcp.amount = wallet.getValue(outputs[i]); + } else if (pegouts.size() > (i - outputs.size())) { + rcp.amount = pegouts[i - outputs.size()].GetAmount(); + } + i++; } } diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index f48520e514..ca5e3e32ef 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -171,6 +171,26 @@ static void WalletTxToJSON(interfaces::Chain& chain, const CWalletTx& wtx, UniVa entry.pushKV("walletconflicts", conflicts); entry.pushKV("time", wtx.GetTxTime()); entry.pushKV("timereceived", (int64_t)wtx.nTimeReceived); + + if (wtx.mweb_wtx_info) { + UniValue partial_mweb(UniValue::VOBJ); + + if (wtx.mweb_wtx_info->received_coin) { + UniValue received_entry(UniValue::VOBJ); + const mw::Coin& received = *wtx.mweb_wtx_info->received_coin; + received_entry.pushKV("output_id", received.output_id.ToHex()); + received_entry.pushKV("amount", received.amount); + partial_mweb.pushKV("received", received_entry); + } + + if (wtx.mweb_wtx_info->spent_input) { + UniValue spent_entry(UniValue::VOBJ); + spent_entry.pushKV("output_id", wtx.mweb_wtx_info->spent_input->ToHex()); + partial_mweb.pushKV("spent", spent_entry); + } + + entry.pushKV("partial_mweb", partial_mweb); + } // Add opt-in RBF status std::string rbfStatus = "no"; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 21267cd7e3..26208b21b9 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -927,17 +927,14 @@ CWalletTx* CWallet::AddToWallet(CTransactionRef tx, const boost::optionalIsNull() && !tx->IsNull()) { + wtx.SetTx(tx); + wtx.mweb_wtx_info = mweb_wtx_info; + fUpdated = true; + } } //// debug print @@ -995,7 +999,7 @@ bool CWallet::LoadToWallet(const uint256& hash, const UpdateWalletTxFn& fill_wtx uint256 wtx_hash = wtx_tmp.GetHash(); if (mapWallet.count(wtx_hash) > 0 && wtx_tmp.tx->IsNull()) { - LogPrintf("%s already exists\n", wtx_hash.ToString()); + WalletLogPrintf("%s already exists\n", wtx_hash.ToString()); return true; } @@ -2086,7 +2090,12 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc for (const Kernel& kernel : block.mweb_block.m_block->GetKernels()) { const CWalletTx* wtx = FindWalletTxByKernelId(kernel.GetKernelID()); if (wtx) { - SyncTransaction(wtx->tx, wtx->mweb_wtx_info, {CWalletTx::Status::CONFIRMED, block_height, block_hash, wtx->m_confirm.nIndex}, fUpdate); + SyncTransaction( + wtx->tx, + wtx->mweb_wtx_info, + {CWalletTx::Status::CONFIRMED, block_height, block_hash, wtx->m_confirm.nIndex}, + fUpdate + ); } } @@ -2095,7 +2104,12 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc if (mweb_wallet->RewindOutput(output, mweb_coin)) { const CWalletTx* wtx = FindWalletTx(mweb_coin.output_id); if (wtx) { - SyncTransaction(wtx->tx, wtx->mweb_wtx_info, {CWalletTx::Status::CONFIRMED, block_height, block_hash, wtx->m_confirm.nIndex}, fUpdate); + SyncTransaction( + wtx->tx, + wtx->mweb_wtx_info, + {CWalletTx::Status::CONFIRMED, block_height, block_hash, wtx->m_confirm.nIndex}, + fUpdate + ); } else { AddToWallet( MakeTransactionRef(), @@ -2117,7 +2131,7 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc SyncTransaction( tx_iter->second.tx, tx_iter->second.mweb_wtx_info, - {CWalletTx::Status::CONFIRMED, block_height, block_hash, 0}, + {CWalletTx::Status::CONFIRMED, block_height, block_hash, tx_iter->second.m_confirm.nIndex}, fUpdate ); } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index c3e1dba411..d02a8b3caf 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -394,6 +394,7 @@ public: uint256 hashBlock; int nIndex; Confirmation(Status s = UNCONFIRMED, int b = 0, uint256 h = uint256(), int i = 0) : status(s), block_height(b), hashBlock(h), nIndex(i) {} + bool operator!=(const Confirmation& c) const { return status != c.status || block_height != c.block_height || hashBlock != c.hashBlock || nIndex != c.nIndex; } }; Confirmation m_confirm;