From 2155e913d3ec69a13470feba08ca77172b73eb6c Mon Sep 17 00:00:00 2001 From: Ava Chow Date: Mon, 16 Jun 2025 15:03:00 -0700 Subject: [PATCH] wallet: Make CWalletTx "from" and "message" member variables Instead of storing "from" and "message" inside of mapValue, store these explicitly as members of CWalletTx. --- src/interfaces/wallet.h | 2 ++ src/qt/transactiondesc.cpp | 13 ++++++------- src/qt/transactionrecord.cpp | 2 +- src/wallet/interfaces.cpp | 2 ++ src/wallet/transaction.h | 23 +++++++++++++++++------ src/wallet/wallet.cpp | 2 ++ 6 files changed, 30 insertions(+), 14 deletions(-) diff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h index 4d965ec5a98..7f36692c427 100644 --- a/src/interfaces/wallet.h +++ b/src/interfaces/wallet.h @@ -391,6 +391,8 @@ struct WalletTx CAmount debit; CAmount change; int64_t time; + std::optional from; // Deprecated + std::optional message; // Deprecated std::map value_map; bool is_coinbase; diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 79c1911549c..d16e280883f 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -123,11 +123,9 @@ QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wall if (wtx.is_coinbase) { strHTML += "" + tr("Source") + ": " + tr("Generated") + "
"; - } - else if (wtx.value_map.contains("from") && !wtx.value_map["from"].empty()) - { + } else if (wtx.from) { // Online transaction - strHTML += "" + tr("From") + ": " + GUIUtil::HtmlEscape(wtx.value_map["from"]) + "
"; + strHTML += "" + tr("From") + ": " + GUIUtil::HtmlEscape(*wtx.from) + "
"; } else { @@ -273,9 +271,10 @@ QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wall // // Message // - if (wtx.value_map.contains("message") && !wtx.value_map["message"].empty()) - strHTML += "
" + tr("Message") + ":
" + GUIUtil::HtmlEscape(wtx.value_map["message"], true) + "
"; - if (wtx.value_map.contains("comment") && !wtx.value_map["comment"].empty()) + if (wtx.message) { + strHTML += "
" + tr("Message") + ":
" + GUIUtil::HtmlEscape(*wtx.message, true) + "
"; + } + if (wtx.value_map.count("comment") && !wtx.value_map["comment"].empty()) strHTML += "
" + tr("Comment") + ":
" + GUIUtil::HtmlEscape(wtx.value_map["comment"], true) + "
"; strHTML += "" + tr("Transaction ID") + ": " + rec->getTxHash() + "
"; diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index 1143bc35610..a06736bb3bd 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -112,7 +112,7 @@ QList TransactionRecord::decomposeTransaction(const interface { // Received by IP connection (deprecated features), or a multisignature or other non-simple transaction sub.type = TransactionRecord::RecvFromOther; - sub.address = mapValue["from"]; + sub.address = wtx.from.value_or(""); } if (wtx.is_coinbase) { diff --git a/src/wallet/interfaces.cpp b/src/wallet/interfaces.cpp index 800e52a4851..49271648a3e 100644 --- a/src/wallet/interfaces.cpp +++ b/src/wallet/interfaces.cpp @@ -79,6 +79,8 @@ WalletTx MakeWalletTx(CWallet& wallet, const CWalletTx& wtx) result.debit = CachedTxGetDebit(wallet, wtx, /*avoid_reuse=*/true); result.change = CachedTxGetChange(wallet, wtx); result.time = wtx.GetTxTime(); + result.from = wtx.m_from; + result.message = wtx.m_message; result.value_map = wtx.mapValue; result.is_coinbase = wtx.IsCoinBase(); return result; diff --git a/src/wallet/transaction.h b/src/wallet/transaction.h index 29baf6695a0..32236aaf638 100644 --- a/src/wallet/transaction.h +++ b/src/wallet/transaction.h @@ -194,6 +194,11 @@ public: class CWalletTx { public: + // "from" and "message" are obsolete fields that could be set in + // the UI prior to 2011 (removed in commit 4d9b223) + // These fields are kept to avoid losing metadata. + std::optional m_from; + std::optional m_message; /** * Key/value map with information about the transaction. * @@ -206,8 +211,6 @@ public: * bumpfee on transaction created by bumpfee * "replaced_by_txid" - txid (as HexStr) of transaction created by * bumpfee on transaction replaced by bumpfee - * "from", "message" - obsolete fields that could be set in UI prior to - * 2011 (removed in commit 4d9b223) * * The following keys are serialized in the wallet database, but shouldn't * be read or written through the map (they will be temporarily added and @@ -218,6 +221,8 @@ public: * "timesmart" - serialized nTimeSmart value * "spent" - serialized vfSpent value that existed prior to * 2014 (removed in commit 93a18a3) + * "from", "message" - obsolete fields that could be set in UI prior to + * 2011 (removed in commit 4d9b223) */ mapValue_t mapValue; std::vector > vOrderForm; @@ -285,6 +290,8 @@ public: void Serialize(Stream& s) const { mapValue_t mapValueCopy = mapValue; + if (m_from) mapValueCopy["from"] = *m_from; + if (m_message) mapValueCopy["message"] = *m_message; mapValueCopy["fromaccount"] = ""; if (nOrderPos != -1) { @@ -318,15 +325,19 @@ public: m_state = TxStateInterpretSerialized({serialized_block_hash, serializedIndex}); - const auto it_op = mapValue.find("n"); - nOrderPos = (it_op != mapValue.end()) ? LocaleIndependentAtoi(it_op->second) : -1; - const auto it_ts = mapValue.find("timesmart"); - nTimeSmart = (it_ts != mapValue.end()) ? static_cast(LocaleIndependentAtoi(it_ts->second)) : 0; + for (const auto& [key, value] : mapValue) { + if (key == "n") nOrderPos = LocaleIndependentAtoi(value); + else if (key == "timesmart") nTimeSmart = LocaleIndependentAtoi(value); + else if (key == "from") m_from = value; + else if (key == "message") m_message = value; + } mapValue.erase("fromaccount"); mapValue.erase("spent"); mapValue.erase("n"); mapValue.erase("timesmart"); + mapValue.erase("from"); + mapValue.erase("message"); } void SetTx(CTransactionRef arg) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 5f529a52b2c..b9980428fdd 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -742,6 +742,8 @@ void CWallet::SyncMetaData(std::pair ran if (copyFrom == copyTo) continue; assert(copyFrom && "Oldest wallet transaction in range assumed to have been found."); if (!copyFrom->IsEquivalentTo(*copyTo)) continue; + copyTo->m_from = copyFrom->m_from; + copyTo->m_message = copyFrom->m_message; copyTo->mapValue = copyFrom->mapValue; copyTo->vOrderForm = copyFrom->vOrderForm; // nTimeReceived not copied on purpose