perf(chat): sends re-read by origin, chat scans under the scan budget
A z_sendmany submit set off a burst of wallet scans before anything had changed. Ops now re-read the wallet when they finish, by who started them: the user's sends and dialog ops get a re-read plus one forced balance once none of their ops is pending; client auto-shield re-reads unforced; chat messages and splits refresh only the chat note view. A pending send no longer forces scans, and chat txids no longer enter the tracked-send set. Chat ingest skips stored messages before decrypting and caches undecryptable ones per identity. The inbox scan runs when getwalletinfo's txcount changed (a cheap probe, at most 2% duty) or a cost-scaled safety net is due; the note-buffer scan runs on need. Both are admitted by the scan budget, on a steady clock. The chat payer comes from a per-address view of verified notes, with debits re-applied across in-flight scans; splits are sized to one payer and only when they can refill the buffer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -311,6 +311,16 @@ public:
|
||||
bool anySuccess = false;
|
||||
};
|
||||
|
||||
// Who started a tracked async operation, i.e. what its completion re-reads (App::markWalletMutated).
|
||||
// Absent from the App's origin map = User.
|
||||
enum class OperationOrigin : std::uint8_t { User, Auto, Chat };
|
||||
struct OperationBatchPlan {
|
||||
bool userSucceeded = false; // >= 1 User op succeeded: re-read the wallet, force the balance
|
||||
bool autoSucceeded = false; // >= 1 Auto op (client auto-shield) succeeded: re-read, unforced
|
||||
bool walletTerminal = false; // >= 1 non-chat op finished (any outcome) or went stale
|
||||
bool chatTerminal = false; // >= 1 chat op finished or went stale: refresh the chat note view
|
||||
};
|
||||
|
||||
struct TransactionCacheUpdate {
|
||||
TransactionViewCache& viewTxCache;
|
||||
std::unordered_set<std::string>& sendTxids;
|
||||
@@ -435,6 +445,12 @@ public:
|
||||
// retained. Built explicitly, because a one-element braced list of a json ({ids}) collapses to the
|
||||
// inner array, which the daemon rejects ("JSON value is not an array as expected").
|
||||
static std::optional<nlohmann::json> buildOperationFilterParams(const std::vector<std::string>& opids);
|
||||
// Classify a poll's terminal ops by origin (absent from the map = User).
|
||||
static OperationBatchPlan planOperationBatch(const OperationStatusPollResult& parsed,
|
||||
const std::unordered_map<std::string, OperationOrigin>& origins);
|
||||
// Any pending id is a User op (absent from the map = User).
|
||||
static bool anyUserOperationPending(const std::vector<std::string>& pendingOpids,
|
||||
const std::unordered_map<std::string, OperationOrigin>& origins);
|
||||
|
||||
struct DaemonRescanScan {
|
||||
bool foundRescan = false;
|
||||
|
||||
Reference in New Issue
Block a user