Browse Source

Resolves Sapling nullifier persistence issue when importing a key.

During a rescan, a CWalletTx was persisted to disk before it had its
note data set.  This meant that upon restart, the CWalletTx would
potentially be missing its nullifiers causing the wallet's balance
to include notes which had already been spent.

The resolution is to ensure that after a rescan, a CWalletTx is
persisted after it has had its nullifiers set correctly.

Co-authored-by: Eirik Ogilvie-Wigley <eirik@z.cash>
pull/4/head
Simon 6 years ago
parent
commit
cd10562c73
  1. 20
      src/wallet/wallet.cpp

20
src/wallet/wallet.cpp

@ -2398,6 +2398,9 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
const CChainParams& chainParams = Params();
CBlockIndex* pindex = pindexStart;
std::vector<uint256> myTxHashes;
{
LOCK2(cs_main, cs_wallet);
@ -2418,8 +2421,10 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
ReadBlockFromDisk(block, pindex);
BOOST_FOREACH(CTransaction& tx, block.vtx)
{
if (AddToWalletIfInvolvingMe(tx, &block, fUpdate))
if (AddToWalletIfInvolvingMe(tx, &block, fUpdate)) {
myTxHashes.push_back(tx.GetHash());
ret++;
}
}
SproutMerkleTree sproutTree;
@ -2441,6 +2446,19 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
LogPrintf("Still rescanning. At block %d. Progress=%f\n", pindex->nHeight, Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), pindex));
}
}
// After rescanning, persist Sapling note data that might have changed, e.g. nullifiers.
// Do not flush the wallet here for performance reasons.
CWalletDB walletdb(strWalletFile, "r+", false);
for (auto hash : myTxHashes) {
CWalletTx wtx = mapWallet[hash];
if (!wtx.mapSaplingNoteData.empty()) {
if (!wtx.WriteToDisk(&walletdb)) {
LogPrintf("Rescanning... WriteToDisk failed to update Sapling note data for: %s\n", hash.ToString());
}
}
}
ShowProgress(_("Rescanning..."), 100); // hide progress dialog in GUI
}
return ret;

Loading…
Cancel
Save