Add caching and updating of Sapling note nullifier.
This commit is contained in:
@@ -474,8 +474,10 @@ void CWallet::ChainTip(const CBlockIndex *pindex,
|
||||
{
|
||||
if (added) {
|
||||
IncrementNoteWitnesses(pindex, pblock, sproutTree, saplingTree);
|
||||
UpdateSaplingNullifierNoteMapForBlock(pblock);
|
||||
} else {
|
||||
DecrementNoteWitnesses(pindex);
|
||||
UpdateSaplingNullifierNoteMapForBlock(pblock);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1169,6 +1171,10 @@ bool CWallet::UpdateNullifierNoteMap()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Sapling. This method is only called from RPC walletpassphrase, which is currently unsupported
|
||||
// as RPC encryptwallet is hidden behind two flags: -developerencryptwallet -experimentalfeatures
|
||||
|
||||
UpdateNullifierNoteMapWithTx(wtxItem.second);
|
||||
}
|
||||
}
|
||||
@@ -1176,7 +1182,8 @@ bool CWallet::UpdateNullifierNoteMap()
|
||||
}
|
||||
|
||||
/**
|
||||
* Update mapSproutNullifiersToNotes with the cached nullifiers in this tx.
|
||||
* Update mapSproutNullifiersToNotes and mapSaplingNullifiersToNotes
|
||||
* with the cached nullifiers in this tx.
|
||||
*/
|
||||
void CWallet::UpdateNullifierNoteMapWithTx(const CWalletTx& wtx)
|
||||
{
|
||||
@@ -1187,6 +1194,71 @@ void CWallet::UpdateNullifierNoteMapWithTx(const CWalletTx& wtx)
|
||||
mapSproutNullifiersToNotes[*item.second.nullifier] = item.first;
|
||||
}
|
||||
}
|
||||
|
||||
for (const mapSaplingNoteData_t::value_type& item : wtx.mapSaplingNoteData) {
|
||||
if (item.second.nullifier) {
|
||||
mapSaplingNullifiersToNotes[*item.second.nullifier] = item.first;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update mapSaplingNullifiersToNotes, computing the nullifier from a cached witness if necessary.
|
||||
*/
|
||||
void CWallet::UpdateSaplingNullifierNoteMapWithTx(CWalletTx& wtx) {
|
||||
LOCK(cs_wallet);
|
||||
|
||||
for (mapSaplingNoteData_t::value_type &item : wtx.mapSaplingNoteData) {
|
||||
SaplingOutPoint op = item.first;
|
||||
SaplingNoteData nd = item.second;
|
||||
|
||||
if (nd.witnesses.size() == 0) {
|
||||
// If there are no witnesses, erase the nullifier and associated mapping.
|
||||
if (item.second.nullifier) {
|
||||
mapSaplingNullifiersToNotes.erase(item.second.nullifier.get());
|
||||
}
|
||||
item.second.nullifier = boost::none;
|
||||
}
|
||||
else if (nd.witnesses.size() > 0) {
|
||||
uint64_t position = nd.witnesses.front().position();
|
||||
SaplingFullViewingKey fvk = mapSaplingFullViewingKeys.at(nd.ivk);
|
||||
OutputDescription output = wtx.vShieldedOutput[op.n];
|
||||
auto optPlaintext = SaplingNotePlaintext::decrypt(output.encCiphertext, nd.ivk, output.ephemeralKey, output.cm);
|
||||
if (!optPlaintext) {
|
||||
// An item in mapSaplingNoteData must have already been successfully decrypted,
|
||||
// otherwise the item would not exist in the first place.
|
||||
assert(false);
|
||||
}
|
||||
auto optNote = optPlaintext.get().note(nd.ivk);
|
||||
if (!optNote) {
|
||||
assert(false);
|
||||
}
|
||||
auto optNullifier = optNote.get().nullifier(fvk, position);
|
||||
if (!optNullifier) {
|
||||
// This should not happen. If it does, maybe the position has been corrupted or miscalculated?
|
||||
assert(false);
|
||||
}
|
||||
uint256 nullifier = optNullifier.get();
|
||||
mapSaplingNullifiersToNotes[nullifier] = op;
|
||||
item.second.nullifier = nullifier;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate over transactions in a block and update the cached Sapling nullifiers
|
||||
* for transactions which belong to the wallet.
|
||||
*/
|
||||
void CWallet::UpdateSaplingNullifierNoteMapForBlock(const CBlock *pblock) {
|
||||
LOCK(cs_wallet);
|
||||
|
||||
for (const CTransaction& tx : pblock->vtx) {
|
||||
auto hash = tx.GetHash();
|
||||
bool txIsOurs = mapWallet.count(hash);
|
||||
if (txIsOurs) {
|
||||
UpdateSaplingNullifierNoteMapWithTx(mapWallet[hash]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user