- Make sure the server sends a complete response when the client
includes the "Connection: close" header.
- Make sure the server terminates in `m_strand` to avoid
concurrent socket closure and ops processing.
If a tx is marked as failed (because it never shows up in the
daemon's pool), its key images get reset back to unspent so they
can be used in future txs.
If the tx re-enters the daemon's pool (e.g. it's removed from the
pool and then relayed back), then the wallet incorrectly maintains
that the tx's key images are unspent.
This change ensures the wallet re-marks the tx's key images as
spent if the tx re-appears in the node's pool.
Without this commit:
1) read height from DB
2) add block to chain in separate thread
3) read chain for block id's and request them from peer
4) ERR in handle_response_chain_entry, peer's first block is the
one that was added to the chain, which has block idx=height from
step 1.
This commit reads the chain for height and highest block id's
in one go while holding the m_blockchain_lock to avoid the race.
Otherwise we can end up double counting txs towards the weight,
which can over-state the pool weight. E.g. relay tx to node in
stem phase, add its weight to pool weight, then receive tx
from another node, then bump the pool weight again. That double
counts the tx towards the pool weight.
If the weight exceeds the max, the node will "prune" txs from the
pool. Thus, over-counting is probably a cause of, but perhaps
not the only cause of:
https://github.com/seraphis-migration/monero/issues/148
A reorg can end up causing an output's position in the chain to
move. Since the wallet doesn't update the RingDB on reorg, it
may refer to the output's stale position in the chain.
This seems a reasonable solution rather than introducing complex
logic to update the stale ring member's value on rerog, since
RingDB can be deprecated with FCMP++.
- Make sure to mark identified spends in the pool as spends. The
wallet might not know these have been spent if it wasn't the wallet
that relayed the tx to the daemon, or the wallet was cleared via
rescan_bc.
- Make sure to add spends to m_unconfirmed_txs if not present.
- Make sure to process the entire pool again if refreshing for
the first time. The wallet fetches pool and blocks at the same
time. The wallet scans blocks first, then pool. If the wallet
identifies received outputs in the chain, then it may have spent
those received outputs in the pool. So we make sure to re-process
the entire pool again after scanning the chain for the first time.
- Multisig wallets that know about spent key images can now detect
spend txs in the pool. Update tests for that.
Since current behavior on release is to ban clients with too
high a height included in the request, it seems reasonably
justified to modify that behavior to instead return a successful
response that includes the chain height and top block hash.
Behavior before: when start_height > chain tip, response fails
Behavior after: when req.high_height_ok is true && req.start_height
> chain tip, server rerturns a successful response that includes
chain height
- When background syncing, the wallet wipes the spend key
from memory and processes all new transactions. The wallet saves
all receives, spends, and "plausible" spends of receives the
wallet does not know key images for.
- When background sync disabled, the wallet processes all
background synced txs and then clears the background sync cache.
- Adding "plausible" spends to the background sync cache ensures
that the wallet does not need to query the daemon to see if any
received outputs were spent while background sync was enabled.
This would harm privacy especially for users of 3rd party daemons.
- To enable the feature in the CLI wallet, the user can set
background-sync to reuse-wallet-password or
custom-background-password and the wallet automatically syncs in
the background when the wallet locks, then processes all
background synced txs when the wallet is unlocked.
- The custom-background-password option enables the user to
open a distinct background wallet that only has a view key saved
and can be opened/closed/synced separately from the main wallet.
When the main wallet opens, it processes the background wallet's
cache.
- To enable the feature in the RPC wallet, there is a new
`/setup_background_sync` endpoint.
- HW, multsig and view-only wallets cannot background sync.
Looks like the logic from #8882 was accidentally removed in #8861
(regressing to the behavior noted in the #8882 description).
This commit brings that logic back.
- Detach & re-process txs >= lowest scan height
- ensures that if a user calls scan_tx(tx1) after scanning tx2,
the wallet correctly processes tx1 and tx2
- if a user provides a tx with a height higher than the wallet's
last scanned height, the wallet will scan starting from that tx's
height
- scan_tx requires trusted daemon iff need to re-process existing
txs: in addition to querying a daemon for txids, if a user
provides a txid of a tx with height *lower* than any *already*
scanned txs in the wallet, then the wallet will also query the
daemon for all the *higher* txs as well. This is likely
unexpected behavior to a caller, and so to protect a caller from
revealing txid's to an untrusted daemon in an unexpected way,
require the daemon be trusted.
Ensures both transfers and sweeps use a fee that's calculated
from the tx's weight. Using different logic could theoretically
enable distinguishability between the two types of txs. We don't
want that.
- `/getblocks.bin` respects the `RESTRICTED_TX_COUNT` (=100) when
returning pool txs via a restricted RPC daemon.
- A restricted RPC daemon includes a max of `RESTRICTED_TX_COUNT` txs
in the `added_pool_txs` field, and returns any remaining pool hashes
in the `remaining_added_pool_txids` field. The client then requests
the remaining txs via `/gettransactions` in chunks.
- `/gettransactions` no longer does expensive no-ops for ALL pool txs
if the client requests a subset of pool txs. Instead it searches for
the txs the client explicitly requests.
- Reset `m_pool_info_query_time` when a user:
(1) rescans the chain (so the wallet re-requests the whole pool)
(2) changes the daemon their wallets points to (a new daemon would
have a different view of the pool)
- `/getblocks.bin` respects the `req.prune` field when returning
pool txs.
- Pool extension fields in response to `/getblocks.bin` are optional
with default 0'd values.
- spend secret key is no longer the sum of multisig key shares;
no need to check that is the case upon restore.
- restoring a multisig wallet from multisig info means that the
wallet must have already completed all setup rounds. Upon restore,
set the number of rounds completed accordingly.
Implements view tags as proposed by @UkoeHB in MRL issue
https://github.com/monero-project/research-lab/issues/73
At tx construction, the sender adds a 1-byte view tag to each
output. The view tag is derived from the sender-receiver
shared secret. When scanning for outputs, the receiver can
check the view tag for a match, in order to reduce scanning
time. When the view tag does not match, the wallet avoids the
more expensive EC operations when deriving the output public
key using the shared secret.