feat: track shielded send txids via z_viewtransaction
Extract txids from completed z_sendmany operations and store in send_txids_ so pure shielded sends are discoverable. The network thread includes them in the enrichment set, calls z_viewtransaction, caches results in viewtx_cache_, and removes them from send_txids_.
This commit is contained in:
15
src/app.cpp
15
src/app.cpp
@@ -564,13 +564,26 @@ void App::update()
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return [this, done, anySuccess]() {
|
// Extract txids from successful operations so shielded
|
||||||
|
// sends are discoverable by z_viewtransaction.
|
||||||
|
std::vector<std::string> successTxids;
|
||||||
|
for (const auto& op : result) {
|
||||||
|
if (op.value("status", "") == "success"
|
||||||
|
&& op.contains("result") && op["result"].contains("txid")) {
|
||||||
|
successTxids.push_back(op["result"]["txid"].get<std::string>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [this, done, anySuccess,
|
||||||
|
successTxids = std::move(successTxids)]() {
|
||||||
for (const auto& id : done) {
|
for (const auto& id : done) {
|
||||||
pending_opids_.erase(
|
pending_opids_.erase(
|
||||||
std::remove(pending_opids_.begin(), pending_opids_.end(), id),
|
std::remove(pending_opids_.begin(), pending_opids_.end(), id),
|
||||||
pending_opids_.end());
|
pending_opids_.end());
|
||||||
}
|
}
|
||||||
if (anySuccess) {
|
if (anySuccess) {
|
||||||
|
for (const auto& txid : successTxids) {
|
||||||
|
send_txids_.insert(txid);
|
||||||
|
}
|
||||||
// Transaction confirmed by daemon — force immediate data refresh
|
// Transaction confirmed by daemon — force immediate data refresh
|
||||||
transactions_dirty_ = true;
|
transactions_dirty_ = true;
|
||||||
addresses_dirty_ = true;
|
addresses_dirty_ = true;
|
||||||
|
|||||||
@@ -494,6 +494,12 @@ private:
|
|||||||
float opid_poll_timer_ = 0.0f;
|
float opid_poll_timer_ = 0.0f;
|
||||||
static constexpr float OPID_POLL_INTERVAL = 2.0f;
|
static constexpr float OPID_POLL_INTERVAL = 2.0f;
|
||||||
|
|
||||||
|
// Txids from completed z_sendmany operations.
|
||||||
|
// Ensures shielded sends are discoverable by z_viewtransaction
|
||||||
|
// even when they don't appear in listtransactions or
|
||||||
|
// z_listreceivedbyaddress.
|
||||||
|
std::unordered_set<std::string> send_txids_;
|
||||||
|
|
||||||
// First-run wizard state
|
// First-run wizard state
|
||||||
WizardPhase wizard_phase_ = WizardPhase::None;
|
WizardPhase wizard_phase_ = WizardPhase::None;
|
||||||
std::unique_ptr<util::Bootstrap> bootstrap_;
|
std::unique_ptr<util::Bootstrap> bootstrap_;
|
||||||
|
|||||||
@@ -437,6 +437,9 @@ void App::refreshData()
|
|||||||
// Snapshot viewtx cache for the worker thread
|
// Snapshot viewtx cache for the worker thread
|
||||||
auto viewtxCacheSnap = viewtx_cache_;
|
auto viewtxCacheSnap = viewtx_cache_;
|
||||||
|
|
||||||
|
// Snapshot send txids so the worker can include them in enrichment
|
||||||
|
auto sendTxidsSnap = send_txids_;
|
||||||
|
|
||||||
// Single consolidated worker task — all RPC calls happen back-to-back
|
// Single consolidated worker task — all RPC calls happen back-to-back
|
||||||
// on a single thread with no inter-task queue overhead.
|
// on a single thread with no inter-task queue overhead.
|
||||||
worker_->post([this, doAddresses, doPeers, doEncrypt, doTransactions,
|
worker_->post([this, doAddresses, doPeers, doEncrypt, doTransactions,
|
||||||
@@ -444,7 +447,8 @@ void App::refreshData()
|
|||||||
fullyEnriched = std::move(fullyEnriched),
|
fullyEnriched = std::move(fullyEnriched),
|
||||||
cachedConfirmedTxns = std::move(cachedConfirmedTxns),
|
cachedConfirmedTxns = std::move(cachedConfirmedTxns),
|
||||||
cachedConfirmedIds = std::move(cachedConfirmedIds),
|
cachedConfirmedIds = std::move(cachedConfirmedIds),
|
||||||
viewtxCacheSnap = std::move(viewtxCacheSnap)]() -> rpc::RPCWorker::MainCb {
|
viewtxCacheSnap = std::move(viewtxCacheSnap),
|
||||||
|
sendTxidsSnap = std::move(sendTxidsSnap)]() -> rpc::RPCWorker::MainCb {
|
||||||
// ================================================================
|
// ================================================================
|
||||||
// Phase 1: Balance + blockchain info
|
// Phase 1: Balance + blockchain info
|
||||||
// ================================================================
|
// ================================================================
|
||||||
@@ -596,6 +600,13 @@ void App::refreshData()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Include txids from completed z_sendmany operations so that
|
||||||
|
// pure shielded sends (which don't appear in listtransactions
|
||||||
|
// or z_listreceivedbyaddress) are discoverable.
|
||||||
|
for (const auto& txid : sendTxidsSnap) {
|
||||||
|
knownTxids.insert(txid);
|
||||||
|
}
|
||||||
|
|
||||||
// Phase 3c: detect shielded sends via z_viewtransaction
|
// Phase 3c: detect shielded sends via z_viewtransaction
|
||||||
// Check the in-memory viewtx cache first; only make RPC calls
|
// Check the in-memory viewtx cache first; only make RPC calls
|
||||||
// for txids we haven't seen before.
|
// for txids we haven't seen before.
|
||||||
@@ -858,6 +869,8 @@ void App::refreshData()
|
|||||||
// Merge new z_viewtransaction results into the persistent cache
|
// Merge new z_viewtransaction results into the persistent cache
|
||||||
for (auto& [txid, entry] : newViewTxEntries) {
|
for (auto& [txid, entry] : newViewTxEntries) {
|
||||||
viewtx_cache_[txid] = std::move(entry);
|
viewtx_cache_[txid] = std::move(entry);
|
||||||
|
// Once cached, no need to keep in send_txids_
|
||||||
|
send_txids_.erase(txid);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rebuild confirmed transaction cache: txns with >= 10
|
// Rebuild confirmed transaction cache: txns with >= 10
|
||||||
|
|||||||
Reference in New Issue
Block a user