handshake-org / hsd

Handshake Daemon & Full Node
Other
1.94k stars 281 forks source link

rpc abortrescan #727

Open pinheadmz opened 2 years ago

pinheadmz commented 2 years ago

bitcoin core has this call available. I think this will be useful especially since there are some cases where rescan can fail, but the blockchain continues to feed wallet rescan blocks (resulting in "error rescan block too high") until the ENTIRE chain has played out.

Stops current wallet rescan triggered by an RPC call, e.g. by an importprivkey call.
Note: Use "getwalletinfo" to query the scanning progress.

Result:
true|false    (boolean) Whether the abort was successful

Examples:

Import a private key
> bitcoin-cli importprivkey "mykey"

Abort the running wallet rescan
> bitcoin-cli abortrescan
rithvikvibhu commented 2 years ago

If a rescan is aborted midway, what's the state (height, etc.) of the node and wallet? What happens to the now-unconfirmed txs in the wallet?

pinheadmz commented 2 years ago

@rithvikvibhu you can see more about this in this old bcoin issue: https://github.com/bcoin-org/bcoin/issues/842

Rescan can fail for a lot of reasons. On the wallet side when rescan fails, wallet is stuck at some old state. Its height is old and its TX state is wrong (lots of TXs may be marked as pending instead of confirmed). The idea in this issue actually does not change that.

What makes recovering from this state extra hard is that, once wallet asks chain for a rescan, CHAIN DOES NOT STOP until it reaches the tip. So if wallet has already crashed or refused a rescan block for whatever reason, the user can't do anything about it until chainDB.scan() is concluded:

https://github.com/handshake-org/hsd/blob/a53f87755e449d45704f7b037e7e61f342122c94/lib/blockchain/chaindb.js#L1492

What i'm proposing here is adding a node rpc abortrescan that sets a flags chainDB.abortRescan = true and that flag is checked inside this while loop. Once the chain scan is aborted, yes wallet will still be in a crappy state but at least then the user can try something else: either another rescan command from a different height, or simply wait for a new block to be added to the chain (which will trigger wallet to scan again but this time it should funish)