PIVX Core  5.6.99
P2P Digital Currency
saplingscriptpubkeyman.cpp
Go to the documentation of this file.
1 // Copyright (c) 2016-2020 The ZCash developers
2 // Copyright (c) 2021 The PIVX Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or https://www.opensource.org/licenses/mit-license.php.
5 
7 
8 #include "chain.h" // for CBlockIndex
10 #include "consensus/params.h"
11 #include "primitives/block.h"
13 #include "uint256.h"
14 #include "validation.h" // for ReadBlockFromDisk()
15 #include "wallet/wallet.h"
16 #include <algorithm>
17 #include <map>
18 #include <string>
19 #include <vector>
20 
21 void SaplingScriptPubKeyMan::AddToSaplingSpends(const uint256& nullifier, const uint256& wtxid)
22 {
24  mapTxSaplingNullifiers.emplace(nullifier, wtxid);
25 
26  std::pair<TxNullifiers::iterator, TxNullifiers::iterator> range;
27  range = mapTxSaplingNullifiers.equal_range(nullifier);
28  wallet->SyncMetaDataN(range);
29 }
30 
32 {
33  for (auto& i : mapSaplingNullifiersToNotes) {
34  SaplingOutPoint iOp = i.second;
35  if (iOp == op) {
36  return IsSaplingSpent(i.first);
37  }
38  }
39  return false;
40 }
41 
42 bool SaplingScriptPubKeyMan::IsSaplingSpent(const uint256& nullifier) const {
43  LOCK(wallet->cs_wallet); // future: move to AssertLockHeld()
44  std::pair<TxNullifiers::const_iterator, TxNullifiers::const_iterator> range;
45  range = mapTxSaplingNullifiers.equal_range(nullifier);
46 
47  for (TxNullifiers::const_iterator it = range.first; it != range.second; ++it) {
48  const uint256& wtxid = it->second;
49  std::map<uint256, CWalletTx>::const_iterator mit = wallet->mapWallet.find(wtxid);
50  if (mit != wallet->mapWallet.end() && mit->second.GetDepthInMainChain() >= 0) {
51  return true; // Spent
52  }
53  }
54  return false;
55 }
56 
59 
60  for (const auto& tx : pblock->vtx) {
61  auto it = wallet->mapWallet.find(tx->GetHash());
62  if (it != wallet->mapWallet.end()) {
64  }
65  }
66 }
67 
68 // Updates noteData and mapSaplingNullifiersToNotes directly
70 {
72  nd.nullifier = nullifier;
73  if (nullifier) mapSaplingNullifiersToNotes[*nullifier] = op;
74 }
75 
81 
82  for (mapSaplingNoteData_t::value_type &item : wtx.mapSaplingNoteData) {
83  const SaplingOutPoint& op = item.first;
84  SaplingNoteData& nd = item.second;
85 
86  if (nd.witnesses.empty() || !nd.IsMyNote()) {
87  // If there are no witnesses, erase the nullifier and associated mapping.
88  if (nd.nullifier) {
89  mapSaplingNullifiersToNotes.erase(item.second.nullifier.get());
90  }
91  nd.nullifier = nullopt;
92  } else {
93  const libzcash::SaplingIncomingViewingKey& ivk = *(nd.ivk);
94  uint64_t position = nd.witnesses.front().position();
95  auto extfvk = wallet->mapSaplingFullViewingKeys.at(ivk);
96  OutputDescription output = wtx.tx->sapData->vShieldedOutput[op.n];
97  auto optPlaintext = libzcash::SaplingNotePlaintext::decrypt(output.encCiphertext, ivk, output.ephemeralKey, output.cmu);
98  if (!optPlaintext) {
99  // An item in mapSaplingNoteData must have already been successfully decrypted,
100  // otherwise the item would not exist in the first place.
101  assert(false);
102  }
103  auto optNote = optPlaintext.get().note(ivk);
104  if (!optNote) {
105  assert(false);
106  }
107  auto optNullifier = optNote.get().nullifier(extfvk.fvk, position);
108  if (!optNullifier) {
109  // This should not happen. If it does, maybe the position has been corrupted or miscalculated?
110  assert(false);
111  }
112  UpdateSaplingNullifierNoteMap(nd, op, optNullifier.get());
113  }
114  }
115 }
116 
121 {
122  {
124  for (const mapSaplingNoteData_t::value_type& item : wtx.mapSaplingNoteData) {
125  if (item.second.nullifier) {
126  mapSaplingNullifiersToNotes[*item.second.nullifier] = item.first;
127  }
128  }
129  }
130 }
131 
132 template<typename NoteDataMap>
133 void CopyPreviousWitnesses(NoteDataMap& noteDataMap, int indexHeight, int64_t nWitnessCacheSize)
134 {
135  for (auto& item : noteDataMap) {
136  auto* nd = &(item.second);
137  // skip externally sent notes
138  if (!nd->IsMyNote()) continue;
139  // Only increment witnesses that are behind the current height
140  if (nd->witnessHeight < indexHeight) {
141  // Check the validity of the cache
142  // The only time a note witnessed above the current height
143  // would be invalid here is during a reindex when blocks
144  // have been decremented, and we are incrementing the blocks
145  // immediately after.
146  assert(nWitnessCacheSize >= (int64_t) nd->witnesses.size());
147  // Witnesses being incremented should always be either -1
148  // (never incremented or decremented) or one below indexHeight
149  assert((nd->witnessHeight == -1) || (nd->witnessHeight == indexHeight - 1));
150  // Copy the witness for the previous block if we have one
151  if (nd->witnesses.size() > 0) {
152  nd->witnesses.push_front(nd->witnesses.front());
153  }
154  if (nd->witnesses.size() > WITNESS_CACHE_SIZE) {
155  nd->witnesses.pop_back();
156  }
157  }
158  }
159 }
160 
161 void AppendNoteCommitment(SaplingNoteData* nd, int indexHeight, int64_t nWitnessCacheSize, const uint256& note_commitment)
162 {
163  // skip externally sent notes
164  if (!nd->IsMyNote()) return;
165  // No empty witnesses can reach here. Before any append, the note must be already witnessed.
166  if (nd->witnessHeight < indexHeight && nd->witnesses.size() > 0) {
167  // Check the validity of the cache
168  // See comment in CopyPreviousWitnesses about validity.
169  assert(nWitnessCacheSize >= (int64_t) nd->witnesses.size());
170  nd->witnesses.front().append(note_commitment);
171  }
172 }
173 
174 template<typename Witness>
176  int indexHeight,
177  int64_t nWitnessCacheSize,
178  const Witness& witness)
179 {
180  assert(nd);
181  // skip externally sent and already witnessed notes
182  if (!nd->IsMyNote() || nd->witnessHeight >= indexHeight) return;
183  if (!nd->witnesses.empty()) {
184  // We think this can happen because we write out the
185  // witness cache state after every block increment or
186  // decrement, but the block index itself is written in
187  // batches. So if the node crashes in between these two
188  // operations, it is possible for IncrementNoteWitnesses
189  // to be called again on previously-cached blocks. This
190  // doesn't affect existing cached notes because of the
191  // NoteData::witnessHeight checks. See #1378 for details.
192  LogPrintf("Inconsistent witness cache state found\n- Cache size: %d\n- Top (height %d): %s\n- New (height %d): %s\n",
193  nd->witnesses.size(), nd->witnessHeight,
194  nd->witnesses.front().root().GetHex(),
195  indexHeight,
196  witness.root().GetHex());
197  nd->witnesses.clear();
198  }
199  nd->witnesses.push_front(witness);
200  // Set height to one less than pindex so it gets incremented
201  nd->witnessHeight = indexHeight - 1;
202  // Check the validity of the cache
203  assert(nWitnessCacheSize >= (int64_t) nd->witnesses.size());
204 }
205 
206 template <typename NoteDataMap>
207 void UpdateWitnessHeights(NoteDataMap& noteDataMap, int indexHeight, int64_t nWitnessCacheSize)
208 {
209  for (auto& item : noteDataMap) {
210  auto* nd = &(item.second);
211  // skip externally sent notes
212  if (!nd->IsMyNote()) continue;
213  if (nd->witnessHeight < indexHeight) {
214  nd->witnessHeight = indexHeight;
215  // Check the validity of the cache
216  // See comment in CopyPreviousWitnesses about validity.
217  assert(nWitnessCacheSize >= (int64_t) nd->witnesses.size());
218  }
219  }
220 }
221 
222 bool SaplingScriptPubKeyMan::BuildWitnessChain(const CBlockIndex* pTargetBlock, const Consensus::Params& params, std::string& errorStr)
223 {
224  // If V5 is not enforced building the witness cache is useless
226  return true;
227  }
228 
230  // Target is the last block we want to invalidate
231  rollbackTargetHeight = pTargetBlock->nHeight;
232  cachedWitnessMap.clear();
233 
234  // Find the oldest sapling note
235  int minHeight = INT_MAX;
236  for (auto& it : wallet->mapWallet) {
237  CWalletTx& wtx = it.second;
238  if (wtx.mapSaplingNoteData.empty()) continue;
239  // Skip abandoned and conflicted txs for which the block_height is not defined (more precisely it it set to 0 by default)
240  if (wtx.m_confirm.status != CWalletTx::CONFIRMED) continue;
241  minHeight = std::min(wtx.m_confirm.block_height, minHeight);
242  }
243 
244  // Read blocks from the disk from chaintip to the minimum found height
245  std::vector<CBlock> cblocks;
246  const CBlockIndex* pIndex = GetChainTip();
247  int currentHeight = GetChainTip()->nHeight;
248  while (currentHeight >= minHeight) {
249  CBlock cblock;
250  ReadBlockFromDisk(cblock, pIndex);
251  cblocks.insert(cblocks.begin(), cblock);
252  pIndex = pIndex->pprev;
253  currentHeight = pIndex->nHeight;
254  }
255 
256  SaplingMerkleTree initialSaplingTree = SaplingMerkleTree();
257  // Load the SaplingMerkleTree for the block before the oldest note (if the hash is zero then continue with an empty merkle tree)
258  if (!(pIndex->hashFinalSaplingRoot == UINT256_ZERO) && !pcoinsTip->GetSaplingAnchorAt(pIndex->hashFinalSaplingRoot, initialSaplingTree)) {
259  errorStr = "Cannot fetch the sapling anchor!";
260  return false;
261  }
262  // Finally build the witness cache for each sapling note of your wallet
263  int height = minHeight;
264  for (CBlock& block : cblocks) {
265  // Finally build the witness cache for each sapling note
266  std::vector<uint256> noteCommitments;
267  std::vector<SaplingNoteData*> inBlockArrivingNotes;
268  for (const auto& tx : block.vtx) {
269  const auto& hash = tx->GetHash();
270  auto it = wallet->mapWallet.find(hash);
271  bool txIsOurs = it != wallet->mapWallet.end();
272 
273  if (!tx->IsShieldedTx()) continue;
274  for (uint32_t i = 0; i < tx->sapData->vShieldedOutput.size(); i++) {
275  const auto& cmu = tx->sapData->vShieldedOutput[i].cmu;
276  noteCommitments.emplace_back(cmu);
277  for (auto& item : inBlockArrivingNotes) {
278  item->witnesses.front().append(cmu);
279  }
280  initialSaplingTree.append(cmu);
281  if (txIsOurs) {
282  CWalletTx* wtx = &it->second;
283  auto ndIt = wtx->mapSaplingNoteData.find({hash, i});
284  if (ndIt != wtx->mapSaplingNoteData.end()) {
285  SaplingNoteData* nd = &ndIt->second;
286  nd->witnesses.push_front(initialSaplingTree.witness());
287  inBlockArrivingNotes.emplace_back(nd);
288  }
289  }
290  }
291  }
292  for (auto& it2 : cachedWitnessMap) {
293  // Don't duplicate if the block is too old
294  if (height >= rollbackTargetHeight) {
295  it2.second.emplace_front(it2.second.front());
296  }
297  for (auto& noteComm : noteCommitments) {
298  it2.second.front().append(noteComm);
299  }
300  }
301  for (auto nd : inBlockArrivingNotes) {
302  if (nd->nullifier) {
303  std::list<SaplingWitness> witnesses;
304  witnesses.push_front(nd->witnesses.front());
305  cachedWitnessMap.emplace(*(nd->nullifier), witnesses);
306  }
307  }
308  height++;
309  }
310  return true;
311 }
312 
314  const CBlock* pblock,
315  SaplingMerkleTree& saplingTreeRes)
316 {
318  int chainHeight = pindex->nHeight;
319 
320  // Set the update cache flag.
321  int64_t prevWitCacheSize = nWitnessCacheSize;
322  if (nWitnessCacheSize < WITNESS_CACHE_SIZE) {
323  nWitnessCacheSize += 1;
325  }
326 
327  // 1) Loop over the block txs and gather the note commitments ordered.
328  // If the wtx is from this wallet, witness it and append the following block note commitments on top.
329  std::vector<uint256> noteCommitments;
330  std::vector<std::pair<CWalletTx*, SaplingNoteData*>> inBlockArrivingNotes;
331  for (const auto& tx : pblock->vtx) {
332  if (!tx->IsShieldedTx()) continue;
333 
334  const auto& hash = tx->GetHash();
335  auto it = wallet->mapWallet.find(hash);
336  bool txIsOurs = it != wallet->mapWallet.end();
337 
338  for (uint32_t i = 0; i < tx->sapData->vShieldedOutput.size(); i++) {
339  const auto& cmu = tx->sapData->vShieldedOutput[i].cmu;
340  noteCommitments.emplace_back(cmu);
341 
342  // Append note commitment to the in-block wallet's notes.
343  // This is processed here because we already looked for the wtx on
344  // the WitnessNoteIfMine call and only need to append the follow-up block notes,
345  // not every block note (check below).
346  for (auto& item : inBlockArrivingNotes) {
347  ::AppendNoteCommitment(item.second, chainHeight, nWitnessCacheSize, cmu);
348  }
349 
350  // If tx is from this wallet, try to witness the note for the first time (if exists).
351  // And add it to the in-block arriving txs.
352  saplingTreeRes.append(cmu);
353  if (txIsOurs) {
354  CWalletTx* wtx = &it->second;
355  auto ndIt = wtx->mapSaplingNoteData.find({hash, i});
356  if (ndIt != wtx->mapSaplingNoteData.end()) {
357  SaplingNoteData* nd = &ndIt->second;
358  ::WitnessNoteIfMine(nd, chainHeight, nWitnessCacheSize, saplingTreeRes.witness());
359  inBlockArrivingNotes.emplace_back(std::make_pair(wtx, nd));
360  }
361  }
362  }
363  }
364 
365  // 2) Mark already sync wtx, so we don't process them again.
366  for (auto& item : inBlockArrivingNotes) {
367  ::UpdateWitnessHeights(item.first->mapSaplingNoteData, chainHeight, nWitnessCacheSize);
368  }
369 
370  // 3) Loop over the shield txs in the wallet's map (excluding the wtx arriving in this block) and for each tx:
371  // a) Copy the previous witness.
372  // b) Append all new notes commitments
373  // c) Update witness last processed height
374  for (auto& it : wallet->mapWallet) {
375  CWalletTx& wtx = it.second;
376  if (!wtx.mapSaplingNoteData.empty()) {
377  // Create copy of the previous witness (verifying pre-arriving block witness cache size)
378  ::CopyPreviousWitnesses(wtx.mapSaplingNoteData, chainHeight, prevWitCacheSize);
379 
380  // Append new notes commitments.
381  for (auto& noteComm : noteCommitments) {
382  for (auto& item : wtx.mapSaplingNoteData) {
383  AppendNoteCommitment(&(item.second), chainHeight, nWitnessCacheSize, noteComm);
384  }
385  }
386 
387  // Set last processed height.
389  }
390  }
391 
392  // For performance reasons, we write out the witness cache in
393  // CWallet::SetBestChain() (which also ensures that overall consistency
394  // of the wallet.dat is maintained).
395 }
396 /*
397  * Clear and eventually reset each witness of noteDataMap with the corresponding front-value of cachedWitnessMap, indexHeight is the blockHeight being invalidated
398  */
399 void ResetNoteWitnesses(std::map<SaplingOutPoint, SaplingNoteData>& noteDataMap, std::map<uint256, std::list<SaplingWitness>>& cachedWitnessMap, int indexHeight)
400 {
401  // For each note that you own:
402  for (auto& item : noteDataMap) {
403  auto& nd = (item.second);
404  // skip externally sent notes
405  if (!nd.IsMyNote()) continue;
406  // Clear the cache
407  nd.witnesses.clear();
408  // The withnessHeight must be EITHER -1 or equal to the block indexHeight
409  // The case in which indexHeight > witnessHeight is due to conflicted notes, which are irrelevant
410  // TODO: Allow invalidating blocks only if there are not conflicted txs?
411  if (nd.witnessHeight <= indexHeight) {
412  assert((nd.witnessHeight == -1) || (nd.witnessHeight == indexHeight));
413  }
414  // Decrease the witnessHeight
415  nd.witnessHeight = indexHeight - 1;
416  if (nd.nullifier && cachedWitnessMap.at(*nd.nullifier).size() > 0) {
417  // Update the witness value with the cached one
418  nd.witnesses.push_front(cachedWitnessMap.at(*nd.nullifier).front());
419  cachedWitnessMap.at(*nd.nullifier).pop_front();
420  }
421  }
422 }
423 
424 
425 template<typename NoteDataMap>
426 void DecrementNoteWitnesses(NoteDataMap& noteDataMap, int indexHeight, int64_t nWitnessCacheSize)
427 {
428  for (auto& item : noteDataMap) {
429  auto* nd = &(item.second);
430  // skip externally sent notes
431  if (!nd->IsMyNote()) continue;
432  // Only decrement witnesses that are not above the current height
433  if (nd->witnessHeight <= indexHeight) {
434  // Check the validity of the cache
435  // See comment below (this would be invalid if there were a
436  // prior decrement).
437  assert(nWitnessCacheSize >= (int64_t) nd->witnesses.size());
438  // Witnesses being decremented should always be either -1
439  // (never incremented or decremented) or equal to the height
440  // of the block being removed (indexHeight)
441  assert((nd->witnessHeight == -1) || (nd->witnessHeight == indexHeight));
442  if (nd->witnesses.size() > 0) {
443  nd->witnesses.pop_front();
444  }
445  // indexHeight is the height of the block being removed, so
446  // the new witness cache height is one below it.
447  nd->witnessHeight = indexHeight - 1;
448  }
449  // Check the validity of the cache
450  // Technically if there are notes witnessed above the current
451  // height, their cache will now be invalid (relative to the new
452  // value of nWitnessCacheSize). However, this would only occur
453  // during a reindex, and by the time the reindex reaches the tip
454  // of the chain again, the existing witness caches will be valid
455  // again.
456  // We don't set nWitnessCacheSize to zero at the start of the
457  // reindex because the on-disk blocks had already resulted in a
458  // chain that didn't trigger the assertion below.
459  if (nd->witnessHeight < indexHeight) {
460  // Subtract 1 to compare to what nWitnessCacheSize will be after
461  // decrementing.
462  assert((nWitnessCacheSize - 1) >= (int64_t) nd->witnesses.size());
463  }
464  }
465 }
466 
468 {
469  assert(pindex);
471  int nChainHeight = pindex->nHeight;
472  // if the targetHeight is different from -1 we have a cache to use
473  if (rollbackTargetHeight != -1) {
474  for (std::pair<const uint256, CWalletTx>& wtxItem : wallet->mapWallet) {
475  if (!wtxItem.second.mapSaplingNoteData.empty()) {
476  // For each sapling note that you own reset the current witness with the cached one
477  ResetNoteWitnesses(wtxItem.second.mapSaplingNoteData, cachedWitnessMap, nChainHeight);
478  }
479  }
480  nWitnessCacheSize = 1;
482  // If we reached the target height empty the cache and reset the target height to -1
483  // Remember that the targetHeight is indeed the last block we want to invalidate
484  if (rollbackTargetHeight == pindex->nHeight) {
485  cachedWitnessMap.clear();
487  }
488  return;
489  }
490 
491  for (std::pair<const uint256, CWalletTx>& wtxItem : wallet->mapWallet) {
492  ::DecrementNoteWitnesses(wtxItem.second.mapSaplingNoteData, nChainHeight, nWitnessCacheSize);
493  }
494  nWitnessCacheSize -= 1;
496  // TODO: If nWitnessCache is zero, we need to regenerate the caches (#1302)
497  if (Params().IsRegTestNet()) { // throw an error in regtest to be able to catch it from the sapling_wallet_tests.cpp unit test.
498  if (nWitnessCacheSize <= 0) throw std::runtime_error("nWitnessCacheSize > 0");
499  } else assert(nWitnessCacheSize > 0);
500 
501  // For performance reasons, we write out the witness cache in
502  // CWallet::SetBestChain() (which also ensures that overall consistency
503  // of the wallet.dat is maintained).
504 }
505 
514 std::pair<mapSaplingNoteData_t, SaplingIncomingViewingKeyMap> SaplingScriptPubKeyMan::FindMySaplingNotes(const CTransaction &tx) const
515 {
516  // First check that this tx is a Shielded tx.
517  if (!tx.IsShieldedTx()) {
518  return {};
519  }
520 
522  const uint256& hash = tx.GetHash();
523 
524  mapSaplingNoteData_t noteData;
525  SaplingIncomingViewingKeyMap viewingKeysToAdd;
526 
527  // Protocol Spec: 4.19 Block Chain Scanning (Sapling)
528  for (uint32_t i = 0; i < tx.sapData->vShieldedOutput.size(); ++i) {
529  const OutputDescription output = tx.sapData->vShieldedOutput[i];
530  for (auto it = wallet->mapSaplingFullViewingKeys.begin(); it != wallet->mapSaplingFullViewingKeys.end(); ++it) {
531  libzcash::SaplingIncomingViewingKey ivk = it->first;
532  auto result = libzcash::SaplingNotePlaintext::decrypt(output.encCiphertext, ivk, output.ephemeralKey, output.cmu);
533  if (!result) {
534  continue;
535  }
536 
537  // Check if we already have it.
538  Optional<libzcash::SaplingPaymentAddress> address = ivk.address(result.get().d);
539  if (address && wallet->mapSaplingIncomingViewingKeys.count(address.get()) == 0) {
540  viewingKeysToAdd[address.get()] = ivk;
541  }
542  // We don't cache the nullifier here as computing it requires knowledge of the note position
543  // in the commitment tree, which can only be determined when the transaction has been mined.
544  SaplingOutPoint op {hash, i};
545  SaplingNoteData nd;
546  nd.ivk = ivk;
547  nd.amount = result->value();
548  nd.address = address;
549  const auto& memo = result->memo();
550  // don't save empty memo (starting with 0xF6)
551  if (memo[0] < 0xF6) {
552  nd.memo = memo;
553  }
554  noteData.insert(std::make_pair(op, nd));
555  break;
556  }
557  }
558 
559  return std::make_pair(noteData, viewingKeysToAdd);
560 }
561 
562 std::vector<libzcash::SaplingPaymentAddress> SaplingScriptPubKeyMan::FindMySaplingAddresses(const CTransaction& tx) const
563 {
565  std::vector<libzcash::SaplingPaymentAddress> ret;
566  if (!tx.sapData) return ret;
567 
568  // Protocol Spec: 4.19 Block Chain Scanning (Sapling)
569  for (const OutputDescription& output : tx.sapData->vShieldedOutput) {
570  for (auto it = wallet->mapSaplingFullViewingKeys.begin(); it != wallet->mapSaplingFullViewingKeys.end(); ++it) {
571  libzcash::SaplingIncomingViewingKey ivk = it->first;
572  auto result = libzcash::SaplingNotePlaintext::decrypt(output.encCiphertext, ivk, output.ephemeralKey, output.cmu);
573  if (!result) {
574  continue;
575  }
576  Optional<libzcash::SaplingPaymentAddress> address = ivk.address(result.get().d);
577  if (address && wallet->mapSaplingIncomingViewingKeys.count(address.get()) != 0) {
578  ret.emplace_back(address.get());
579  }
580  }
581  }
582  return ret;
583 }
584 
585 void SaplingScriptPubKeyMan::GetNotes(const std::vector<SaplingOutPoint>& saplingOutpoints,
586  std::vector<SaplingNoteEntry>& saplingEntriesRet) const
587 {
588  for (const auto& outpoint : saplingOutpoints) {
589  const auto* wtx = wallet->GetWalletTx(outpoint.hash);
590  if (!wtx) throw std::runtime_error("No transaction available for hash " + outpoint.hash.GetHex());
591  const int depth = WITH_LOCK(wallet->cs_wallet, return wtx->GetDepthInMainChain(); );
592  const auto& it = wtx->mapSaplingNoteData.find(outpoint);
593  if (it != wtx->mapSaplingNoteData.end()) {
594  const SaplingOutPoint& op = it->first;
595  const SaplingNoteData& nd = it->second;
596 
597  // skip sent notes
598  if (!nd.IsMyNote()) continue;
599 
600  // recover plaintext and address
601  auto optNotePtAndAddress = wtx->DecryptSaplingNote(op);
602  assert(static_cast<bool>(optNotePtAndAddress));
603 
604  const libzcash::SaplingIncomingViewingKey& ivk = *(nd.ivk);
605  const libzcash::SaplingNotePlaintext& notePt = optNotePtAndAddress->first;
606  const libzcash::SaplingPaymentAddress& pa = optNotePtAndAddress->second;
607  auto note = notePt.note(ivk).get();
608 
609  saplingEntriesRet.emplace_back(op, pa, note, notePt.memo(), depth);
610  }
611  }
612 }
613 
619  std::vector<SaplingNoteEntry>& saplingEntries,
621  int minDepth,
622  bool ignoreSpent,
623  bool requireSpendingKey,
624  bool ignoreLocked) const
625 {
626  std::set<libzcash::PaymentAddress> filterAddresses;
627 
628  if (address && IsValidPaymentAddress(*address)) {
629  filterAddresses.insert(*address);
630  }
631 
632  GetFilteredNotes(saplingEntries, filterAddresses, minDepth, INT_MAX, ignoreSpent, requireSpendingKey, ignoreLocked);
633 }
634 
641  std::vector<SaplingNoteEntry>& saplingEntries,
642  std::set<libzcash::PaymentAddress>& filterAddresses,
643  int minDepth,
644  int maxDepth,
645  bool ignoreSpent,
646  bool requireSpendingKey,
647  bool ignoreLocked) const
648 {
650 
651  for (auto& p : wallet->mapWallet) {
652  const CWalletTx& wtx = p.second;
653 
654  // Filter coinbase/coinstakes transactions that don't have Sapling outputs
655  if ((wtx.IsCoinBase() || wtx.IsCoinStake()) && wtx.mapSaplingNoteData.empty()) {
656  continue;
657  }
658 
659  // Filter the transactions before checking for notes
660  const int depth = wtx.GetDepthInMainChain();
661  if (!IsFinalTx(wtx.tx, wallet->GetLastBlockHeight() + 1, GetAdjustedTime()) ||
662  depth < minDepth || depth > maxDepth) {
663  continue;
664  }
665 
666  for (const auto& it : wtx.mapSaplingNoteData) {
667  const SaplingOutPoint& op = it.first;
668  const SaplingNoteData& nd = it.second;
669  // skip sent notes
670  if (!nd.IsMyNote()) continue;
671 
672  // recover plaintext and address
673  auto optNotePtAndAddress = wtx.DecryptSaplingNote(op);
674  assert(static_cast<bool>(optNotePtAndAddress));
675 
676  const libzcash::SaplingIncomingViewingKey& ivk = *(nd.ivk);
677  const libzcash::SaplingNotePlaintext& notePt = optNotePtAndAddress->first;
678  const libzcash::SaplingPaymentAddress& pa = optNotePtAndAddress->second;
679  auto note = notePt.note(ivk).get();
680 
681  // skip notes which belong to a different payment address in the wallet
682  if (!(filterAddresses.empty() || filterAddresses.count(pa))) {
683  continue;
684  }
685 
686  if (ignoreSpent && nd.nullifier && IsSaplingSpent(*nd.nullifier)) {
687  continue;
688  }
689 
690  // skip notes which cannot be spent
691  if (requireSpendingKey && !HaveSpendingKeyForPaymentAddress(pa)) {
692  continue;
693  }
694 
695  // skip locked notes.
696  if (ignoreLocked && wallet->IsLockedNote(op)) {
697  continue;
698  }
699 
700  saplingEntries.emplace_back(op, pa, note, notePt.memo(), depth);
701  }
702  }
703 }
704 
705 /* Return list of available notes and locked notes grouped by sapling address. */
706 std::map<libzcash::SaplingPaymentAddress, std::vector<SaplingNoteEntry>> SaplingScriptPubKeyMan::ListNotes() const
707 {
708  std::vector<SaplingNoteEntry> notes;
710  GetFilteredNotes(notes, dummy, 1, true, true, false);
711 
712  std::map<libzcash::SaplingPaymentAddress, std::vector<SaplingNoteEntry>> result;
713  for (const auto& note : notes) {
714  result[note.address].emplace_back(std::move(note));
715  }
716  return result;
717 }
718 
721 {
722  const CWalletTx* wtx = wallet->GetWalletTx(txHash);
723  if (!wtx) return nullopt;
724  return GetAddressFromInputIfPossible(wtx, index);
725 }
726 
729 {
730  if (!wtx->tx->sapData || wtx->tx->sapData->vShieldedSpend.empty()) return nullopt;
731 
732  SpendDescription spendDesc = wtx->tx->sapData->vShieldedSpend.at(index);
733  if (!IsSaplingNullifierFromMe(spendDesc.nullifier)) return nullopt;
734 
735  // Knowing that the spent note is from us, we can get the address from
736  const SaplingOutPoint& outPoint = mapSaplingNullifiersToNotes.at(spendDesc.nullifier);
737  const CWalletTx& txPrev = wallet->mapWallet.at(outPoint.hash);
738  return txPrev.mapSaplingNoteData.at(outPoint).address;
739 }
740 
742 {
744  auto it = mapSaplingNullifiersToNotes.find(nullifier);
745  return it != mapSaplingNullifiersToNotes.end() && wallet->mapWallet.count(it->second.hash);
746 }
747 
748 std::set<std::pair<libzcash::PaymentAddress, uint256>> SaplingScriptPubKeyMan::GetNullifiersForAddresses(
749  const std::set<libzcash::PaymentAddress> & addresses) const
750 {
752  std::set<std::pair<libzcash::PaymentAddress, uint256>> nullifierSet;
753  // Sapling ivk -> list of addrs map
754  // (There may be more than one diversified address for a given ivk.)
755  std::map<libzcash::SaplingIncomingViewingKey, std::vector<libzcash::SaplingPaymentAddress>> ivkMap;
756  for (const auto& addr : addresses) {
757  auto saplingAddr = boost::get<libzcash::SaplingPaymentAddress>(&addr);
758  if (saplingAddr != nullptr) {
760  if (wallet->GetSaplingIncomingViewingKey(*saplingAddr, ivk))
761  ivkMap[ivk].push_back(*saplingAddr);
762  }
763  }
764  for (const auto& txPair : wallet->mapWallet) {
765  for (const auto & noteDataPair : txPair.second.mapSaplingNoteData) {
766  const auto& noteData = noteDataPair.second;
767 
768  // Skip sent notes
769  if (!noteData.IsMyNote()) continue;
770  const libzcash::SaplingIncomingViewingKey& ivk = *(noteData.ivk);
771 
772  const auto& nullifier = noteData.nullifier;
773  if (nullifier && ivkMap.count(ivk)) {
774  for (const auto & addr : ivkMap[ivk]) {
775  nullifierSet.insert(std::make_pair(addr, nullifier.get()));
776  }
777  }
778  }
779  }
780  return nullifierSet;
781 }
782 
784 {
785  auto it = tx.mapSaplingNoteData.find(op);
786  if (it == tx.mapSaplingNoteData.end()) {
787  return nullopt;
788  }
789  return it->second.address;
790 }
791 
793 {
794  auto it = tx.mapSaplingNoteData.find(op);
795  if (it == tx.mapSaplingNoteData.end()) {
796  return 0;
797  }
798  return it->second.amount ? *(it->second.amount) : 0;
799 }
800 
802 {
803  auto it = tx.mapSaplingNoteData.find(op);
804  if (it == tx.mapSaplingNoteData.end() || !static_cast<bool>(it->second.memo))
805  return nullopt;
806  auto& memo = *(it->second.memo);
807  auto end = FindFirstNonZero(memo.rbegin(), memo.rend());
808  if (memo[0] <= 0xf4) {
809  std::string memoStr(memo.begin(), end.base());
810  if (IsValidUTF8(memoStr)) return memoStr;
811  }
812  // non UTF-8 memo. Return as hex encoded raw memo.
813  return HexStr(std::vector<unsigned char>(memo.begin(), end.base()));
814 }
815 
816 Optional<std::pair<
820 {
821  const uint256& txId = tx.GetHash();
822  assert(txId == op.hash);
823  // Try to recover it with the ovks (either the common one, if t->shield tx, or the ones from the spends)
824  std::set<uint256> ovks;
825  // Get the common OVK for recovering t->shield outputs.
826  // If not already databased, a new one will be generated from the HD seed (this throws an error if the
827  // wallet is currently locked). As the ovk is created when the wallet is unlocked for sending a t->shield
828  // tx for the first time, a failure to decode can happen only if this note was sent (from a t-addr)
829  // using this wallet.dat on another computer (and never sent t->shield txes from this computer).
830  if (!tx.tx->vin.empty()) {
831  try {
832  ovks.emplace(getCommonOVK());
833  } catch (...) {
834  LogPrintf("WARNING: No CommonOVK found. Some notes might not be correctly recovered. " /* Continued */
835  "Unlock the wallet and call 'viewshieldtransaction %s' to fix.\n", txId.ToString());
836  }
837  } else {
838  for (const auto& spend : tx.tx->sapData->vShieldedSpend) {
839  const auto& it = mapSaplingNullifiersToNotes.find(spend.nullifier);
840  if (it != mapSaplingNullifiersToNotes.end()) {
841  const SaplingOutPoint& prevOut = it->second;
842  const CWalletTx* txPrev = wallet->GetWalletTx(prevOut.hash);
843  if (!txPrev) continue;
844  const auto& itPrev = txPrev->mapSaplingNoteData.find(prevOut);
845  if (itPrev != txPrev->mapSaplingNoteData.end()) {
846  const SaplingNoteData& noteData = itPrev->second;
847  if (!noteData.IsMyNote()) continue;
849  if (wallet->GetSaplingFullViewingKey(*(noteData.ivk), extfvk)) {
850  ovks.emplace(extfvk.fvk.ovk);
851  }
852  }
853  }
854  }
855  }
856  return tx.RecoverSaplingNote(op, ovks);
857 }
858 
860 {
861  auto ndIt = wtx.mapSaplingNoteData.find(op);
862  if (ndIt != wtx.mapSaplingNoteData.end() && ndIt->second.IsMyNote()) {
863  const auto addr = ndIt->second.address;
864  return (static_cast<bool>(addr) && HaveSpendingKeyForPaymentAddress(*addr)) ?
866  }
867  return ISMINE_NO;
868 }
869 
870 CAmount SaplingScriptPubKeyMan::GetCredit(const CWalletTx& tx, const isminefilter& filter, const bool fUnspent) const
871 {
872  // If we are not filtering shield data, return
873  if (!(filter & ISMINE_WATCH_ONLY_SHIELDED || filter & ISMINE_SPENDABLE_SHIELDED)) {
874  return 0;
875  }
876 
877  if (!tx.tx->IsShieldedTx() || tx.tx->sapData->vShieldedOutput.empty()) {
878  return 0;
879  }
880  CAmount nCredit = 0;
881  for (int i = 0; i < (int) tx.tx->sapData->vShieldedOutput.size(); ++i) {
882  SaplingOutPoint op(tx.GetHash(), i);
883  if (tx.mapSaplingNoteData.find(op) == tx.mapSaplingNoteData.end()) {
884  continue;
885  }
886  // Obtain the noteData and check if the nullifier has being spent or not
887  SaplingNoteData noteData = tx.mapSaplingNoteData.at(op);
888 
889  // Skip externally sent notes
890  if (!noteData.IsMyNote()) continue;
891 
892  // The nullifier could be null if the wallet was locked when the noteData was created.
893  if (noteData.nullifier &&
894  (fUnspent && IsSaplingSpent(*noteData.nullifier))) {
895  continue; // only unspent
896  }
897  // If we are filtering watch only or we have spend authority add the amount
898  if ((filter & ISMINE_WATCH_ONLY_SHIELDED) || (noteData.address && HaveSpendingKeyForPaymentAddress(*noteData.address))) {
899  nCredit += noteData.amount ? *noteData.amount : 0;
900  }
901  }
902  return nCredit;
903 }
904 
906 {
907  // If we are not filtering shield data, return
908  if (!(filter & ISMINE_WATCH_ONLY_SHIELDED || filter & ISMINE_SPENDABLE_SHIELDED)) {
909  return 0;
910  }
911 
912  if (!tx.IsShieldedTx() || tx.sapData->vShieldedSpend.empty()) {
913  return 0;
914  }
915  CAmount nDebit = 0;
916  for (const SpendDescription& spend : tx.sapData->vShieldedSpend) {
917  const auto &it = mapSaplingNullifiersToNotes.find(spend.nullifier);
918  if (it != mapSaplingNullifiersToNotes.end()) {
919  // If we have the spend nullifier, it means that this input is ours.
920  // The transaction (and decrypted note data) has been added to the wallet.
921  const SaplingOutPoint& op = it->second;
922  auto wit = wallet->mapWallet.find(op.hash);
923  assert(wit != wallet->mapWallet.end());
924  const auto& wtx = wit->second;
925  auto nit = wtx.mapSaplingNoteData.find(op);
926  assert(nit != wtx.mapSaplingNoteData.end());
927  const auto& nd = nit->second;
928  assert(nd.IsMyNote());
929  assert(static_cast<bool>(nd.amount));
930  // If we are filtering watch only or we have spend authority add the amount
931  if ((filter & ISMINE_WATCH_ONLY_SHIELDED) || (nd.address && HaveSpendingKeyForPaymentAddress(*nd.address))) {
932  nDebit += *(nd.amount);
933  }
934  if (!Params().GetConsensus().MoneyRange(nDebit))
935  throw std::runtime_error("SaplingScriptPubKeyMan::GetDebit() : value out of range");
936  }
937  }
938  return nDebit;
939 }
940 
942 {
943  if (!wtx.tx->IsShieldedTx() || wtx.tx->sapData->vShieldedOutput.empty()) {
944  return 0;
945  }
946  const uint256& txHash = wtx.GetHash();
947  CAmount nChange = 0;
948  SaplingOutPoint op{txHash, 0};
949  for (uint32_t pos = 0; pos < (uint32_t) wtx.tx->sapData->vShieldedOutput.size(); ++pos) {
950  op.n = pos;
951  auto it = wtx.mapSaplingNoteData.find(op);
952  if (it == wtx.mapSaplingNoteData.end()) continue;
953  const auto& nd = it->second;
954  if (!nd.IsMyNote() || !static_cast<bool>(nd.address) || !static_cast<bool>(nd.amount)) continue;
955  if (IsNoteSaplingChange(op, *(nd.address))) {
956  nChange += *(nd.amount);
957  if (!Params().GetConsensus().MoneyRange(nChange))
958  throw std::runtime_error("GetShieldedChange() : value out of range");
959  }
960  }
961  return nChange;
962 }
963 
965 {
967  std::set<libzcash::PaymentAddress> shieldedAddresses = {address};
968  std::set<std::pair<libzcash::PaymentAddress, uint256>> nullifierSet = GetNullifiersForAddresses(shieldedAddresses);
969  return IsNoteSaplingChange(nullifierSet, address, op);
970 }
971 
972 bool SaplingScriptPubKeyMan::IsNoteSaplingChange(const std::set<std::pair<libzcash::PaymentAddress, uint256>> & nullifierSet,
973  const libzcash::PaymentAddress & address,
974  const SaplingOutPoint & op) const
975 {
976  // A Note is marked as "change" if the address that received it
977  // also spent Notes in the same transaction. This will catch,
978  // for instance:
979  // - Change created by spending fractions of Notes (because
980  // shieldsendmany sends change to the originating shielded address).
981  // - Notes sent from one address to itself.
982  const auto& tx = wallet->mapWallet.at(op.hash);
983  if (tx.tx->sapData) {
984  for (const SpendDescription& spend : tx.tx->sapData->vShieldedSpend) {
985  if (nullifierSet.count(std::make_pair(address, spend.nullifier))) {
986  return true;
987  }
988  }
989  }
990  return false;
991 }
992 
993 void SaplingScriptPubKeyMan::GetSaplingNoteWitnesses(const std::vector<SaplingOutPoint>& notes,
994  std::vector<Optional<SaplingWitness>>& witnesses,
995  uint256& final_anchor) const
996 {
998  witnesses.resize(notes.size());
1000  int i = 0;
1001  for (SaplingOutPoint note : notes) {
1002  auto it = wallet->mapWallet.find(note.hash);
1003  if (it != wallet->mapWallet.end()) {
1004  auto nit = it->second.mapSaplingNoteData.find(note);
1005  if (nit != it->second.mapSaplingNoteData.end() &&
1006  nit->second.witnesses.size() > 0) {
1007  witnesses[i] = nit->second.witnesses.front();
1008  if (!rt) {
1009  rt = witnesses[i]->root();
1010  } else {
1011  assert(*rt == witnesses[i]->root());
1012  }
1013  }
1014  }
1015  i++;
1016  }
1017  // All returned witnesses have the same anchor
1018  if (rt) {
1019  final_anchor = *rt;
1020  }
1021 }
1022 
1024 {
1025  bool unchangedSaplingFlag = (wtxIn.mapSaplingNoteData.empty() || wtxIn.mapSaplingNoteData == wtx.mapSaplingNoteData);
1026  if (!unchangedSaplingFlag) {
1027  auto tmp = wtxIn.mapSaplingNoteData;
1028  // Ensure we keep any cached witnesses we may already have
1029 
1030  for (const std::pair <SaplingOutPoint, SaplingNoteData> nd : wtx.mapSaplingNoteData) {
1031  if (tmp.count(nd.first) && nd.second.witnesses.size() > 0) {
1032  tmp.at(nd.first).witnesses.assign(
1033  nd.second.witnesses.cbegin(), nd.second.witnesses.cend());
1034  }
1035  tmp.at(nd.first).witnessHeight = nd.second.witnessHeight;
1036  }
1037 
1038  // Now copy over the updated note data
1039  wtx.mapSaplingNoteData = tmp;
1040  }
1041 
1042  return !unchangedSaplingFlag;
1043 }
1044 
1046 {
1047  LOCK(wallet->cs_wallet);
1048  for (std::pair<const uint256, CWalletTx>& wtxItem : wallet->mapWallet) {
1049  for (mapSaplingNoteData_t::value_type& item : wtxItem.second.mapSaplingNoteData) {
1050  item.second.witnesses.clear();
1051  item.second.witnessHeight = -1;
1052  }
1053  }
1054  nWitnessCacheSize = 0;
1055  nWitnessCacheNeedsUpdate = true;
1056 }
1057 
1059 {
1061  if (wallet->GetSaplingExtendedSpendingKey(addr, extsk)) {
1062  return extsk;
1063  } else {
1064  return nullopt;
1065  }
1066 }
1067 
1069  const libzcash::SaplingPaymentAddress &addr) const
1070 {
1073 
1074  if (wallet->GetSaplingIncomingViewingKey(addr, ivk) &&
1075  wallet->GetSaplingFullViewingKey(ivk, extfvk))
1076  {
1077  return extfvk;
1078  } else {
1079  return nullopt;
1080  }
1081 }
1082 
1084 // Generate a new Sapling spending key and return its public payment address
1086 {
1087  LOCK(wallet->cs_wallet); // mapSaplingZKeyMetadata
1088 
1089  // Try to get the seed
1090  CKey seedKey;
1091  if (!wallet->GetKey(hdChain.GetID(), seedKey))
1092  throw std::runtime_error(std::string(__func__) + ": HD seed not found");
1093 
1094  HDSeed seed(seedKey.GetPrivKey());
1096 
1097  // We use a fixed keypath scheme of m/32'/coin_type'/account'
1098  // Derive m/32'
1099  auto m_32h = m.Derive(32 | ZIP32_HARDENED_KEY_LIMIT);
1100  // Derive m/32'/coin_type'
1101  auto m_32h_cth = m_32h.Derive(119 | ZIP32_HARDENED_KEY_LIMIT);
1102 
1103  // Derive account key at next index, skip keys already known to the wallet
1105  do {
1107  hdChain.nExternalChainCounter++; // Increment childkey index
1108  } while (wallet->HaveSaplingSpendingKey(xsk.ToXFVK()));
1109 
1110  // Update the chain model in the database
1112  throw std::runtime_error(std::string(__func__) + ": Writing HD chain model failed");
1113 
1114  // Create new metadata
1115  int64_t nCreationTime = GetTime();
1116  auto ivk = xsk.expsk.full_viewing_key().in_viewing_key();
1117  CKeyMetadata metadata(nCreationTime);
1118  metadata.key_origin.path.push_back(32 | BIP32_HARDENED_KEY_LIMIT);
1119  metadata.key_origin.path.push_back(119 | BIP32_HARDENED_KEY_LIMIT);
1120  metadata.key_origin.path.push_back(hdChain.nExternalChainCounter | BIP32_HARDENED_KEY_LIMIT);
1121  metadata.hd_seed_id = hdChain.GetID();
1122  mapSaplingZKeyMetadata[ivk] = metadata;
1123 
1124  if (!AddSaplingZKey(xsk)) {
1125  throw std::runtime_error(std::string(__func__) + ": AddSaplingZKey failed");
1126  }
1127  // return default sapling payment address.
1128  return xsk.DefaultAddress();
1129 }
1130 
1132 {
1133  auto it = mapSaplingZKeyMetadata.find(ivk);
1134  return it != mapSaplingZKeyMetadata.end() ? it->second.nCreateTime : 0;
1135 }
1136 
1137 void SaplingScriptPubKeyMan::GetConflicts(const CWalletTx& wtx, std::set<uint256>& result) const
1138 {
1140  std::pair<TxNullifiers::const_iterator, TxNullifiers::const_iterator> range_o;
1141 
1142  if (wtx.tx->IsShieldedTx()) {
1143  for (const SpendDescription& spend : wtx.tx->sapData->vShieldedSpend) {
1144  const uint256& nullifier = spend.nullifier;
1145  if (mapTxSaplingNullifiers.count(nullifier) <= 1) {
1146  continue; // No conflict if zero or one spends
1147  }
1148  range_o = mapTxSaplingNullifiers.equal_range(nullifier);
1149  for (TxNullifiers::const_iterator it = range_o.first; it != range_o.second; ++it) {
1150  result.insert(it->second);
1151  }
1152  }
1153  }
1154 }
1155 
1157  if (wallet->HaveSaplingSpendingKey(extfvk)) {
1158  return SpendingKeyExists;
1159  } else if (wallet->HaveSaplingFullViewingKey(extfvk.fvk.in_viewing_key())) {
1160  return KeyAlreadyExists;
1161  } else if (wallet->AddSaplingFullViewingKey(extfvk)) {
1162  return KeyAdded;
1163  } else {
1164  return KeyNotAdded;
1165  }
1166 }
1167 
1169  const Consensus::Params &params,
1171  int64_t nTime)
1172 {
1173  auto extfvk = sk.ToXFVK();
1174  auto ivk = extfvk.fvk.in_viewing_key();
1175  {
1176  //LogPrint(BCLog::SAPLING, "Importing shielded addr %s...\n", KeyIO::EncodePaymentAddress(sk.DefaultAddress()));
1177  // Don't throw error in case a key is already there
1178  if (wallet->HaveSaplingSpendingKey(extfvk)) {
1179  return KeyAlreadyExists;
1180  } else {
1181  if (!wallet-> AddSaplingZKey(sk)) {
1182  return KeyNotAdded;
1183  }
1184 
1185  int64_t nTimeToSet;
1186  // Sapling addresses can't have been used in transactions prior to activation.
1188  nTimeToSet = nTime;
1189  } else {
1190  // TODO: Update epoch before release v5.
1191  // 154051200 seconds from epoch is Friday, 26 October 2018 00:00:00 GMT - definitely before Sapling activates
1192  nTimeToSet = std::max((int64_t) 154051200, nTime);
1193  }
1194 
1195  mapSaplingZKeyMetadata[ivk] = CKeyMetadata(nTimeToSet);
1196  return KeyAdded;
1197  }
1198  }
1199 }
1200 
1201 // Add spending key to keystore
1204 {
1205  AssertLockHeld(wallet->cs_wallet); // mapSaplingZKeyMetadata
1206 
1207  if (!IsEnabled()) {
1208  return error("%s: Sapling spkm not enabled", __func__ );
1209  }
1210 
1211  if (!AddSaplingSpendingKey(sk)) {
1212  return false;
1213  }
1214 
1215  if (!wallet->IsCrypted()) {
1216  auto ivk = sk.expsk.full_viewing_key().in_viewing_key();
1218  }
1219 
1220  return true;
1221 }
1222 
1225 {
1226  {
1228  if (!wallet->IsCrypted()) {
1229  return wallet->AddSaplingSpendingKey(sk); // keystore
1230  }
1231 
1232  if (wallet->IsLocked()) {
1233  return false;
1234  }
1235 
1236  std::vector<unsigned char> vchCryptedSecret;
1237  CSecureDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
1238  ss << sk;
1239  CKeyingMaterial vchSecret(ss.begin(), ss.end());
1240  auto extfvk = sk.ToXFVK();
1241  if (!EncryptSecret(wallet->GetEncryptionKey(), vchSecret, extfvk.fvk.GetFingerprint(), vchCryptedSecret)) {
1242  return false;
1243  }
1244 
1245  if (!AddCryptedSaplingSpendingKeyDB(extfvk, vchCryptedSecret)) {
1246  return false;
1247  }
1248  }
1249  return true;
1250 }
1251 
1252 // Add payment address -> incoming viewing key map entry
1255  const libzcash::SaplingPaymentAddress &addr)
1256 {
1257  AssertLockHeld(wallet->cs_wallet); // mapSaplingZKeyMetadata
1258 
1259  if (!wallet->AddSaplingIncomingViewingKey(ivk, addr)) {
1260  return false;
1261  }
1262 
1263  if (!wallet->IsCrypted()) {
1265  }
1266 
1267  return true;
1268 }
1269 
1271 {
1272  AssertLockHeld(wallet->cs_wallet); // mapSaplingSpendingKeys
1273 
1274  for (SaplingSpendingKeyMap::value_type& mSaplingSpendingKey : wallet->mapSaplingSpendingKeys) {
1275  const libzcash::SaplingExtendedSpendingKey &sk = mSaplingSpendingKey.second;
1276  CSecureDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
1277  ss << sk;
1278  CKeyingMaterial vchSecret(ss.begin(), ss.end());
1279  auto extfvk = sk.ToXFVK();
1280  std::vector<unsigned char> vchCryptedSecret;
1281  if (!EncryptSecret(vMasterKeyIn, vchSecret, extfvk.fvk.GetFingerprint(), vchCryptedSecret)) {
1282  return false;
1283  }
1284  if (!AddCryptedSaplingSpendingKeyDB(extfvk, vchCryptedSecret)) {
1285  return false;
1286  }
1287  }
1288  wallet->mapSaplingSpendingKeys.clear();
1289  return true;
1290 }
1291 
1293  const std::vector<unsigned char> &vchCryptedSecret)
1294 {
1295  if (!wallet->AddCryptedSaplingSpendingKey(extfvk, vchCryptedSecret))
1296  return false;
1297  {
1298  LOCK(wallet->cs_wallet);
1299  if (wallet->encrypted_batch) {
1301  vchCryptedSecret,
1303  } else {
1305  vchCryptedSecret,
1307  }
1308  }
1309  return false;
1310 }
1311 
1313 {
1316 
1317  return wallet->GetSaplingIncomingViewingKey(zaddr, ivk) &&
1318  wallet->GetSaplingFullViewingKey(ivk, extfvk) &&
1319  wallet->HaveSaplingSpendingKey(extfvk);
1320 }
1321 
1323 {
1325 
1326  // If we have a SaplingExtendedSpendingKey in the wallet, then we will
1327  // also have the corresponding SaplingExtendedFullViewingKey.
1328  return wallet->GetSaplingIncomingViewingKey(zaddr, ivk) &&
1330 }
1331 
1333 
1336  const std::vector<unsigned char> &vchCryptedSecret)
1337 {
1338  return wallet->AddCryptedSaplingSpendingKey(extfvk, vchCryptedSecret);
1339 }
1340 
1342 {
1343  AssertLockHeld(wallet->cs_wallet); // mapSaplingZKeyMetadata
1344  mapSaplingZKeyMetadata[ivk] = meta;
1345  return true;
1346 }
1347 
1349 {
1350  return wallet->AddSaplingSpendingKey(key);
1351 }
1352 
1354  const libzcash::SaplingPaymentAddress &addr,
1356 {
1357  return wallet->AddSaplingIncomingViewingKey(ivk, addr);
1358 }
1359 
1361 
1362 bool SaplingScriptPubKeyMan::SetupGeneration(const CKeyID& keyID, bool force, bool memonly)
1363 {
1364  SetHDSeed(keyID, force, memonly);
1365  return true;
1366 }
1367 
1368 void SaplingScriptPubKeyMan::SetHDSeed(const CPubKey& seed, bool force, bool memonly)
1369 {
1370  SetHDSeed(seed.GetID(), force, memonly);
1371 }
1372 
1373 void SaplingScriptPubKeyMan::SetHDSeed(const CKeyID& keyID, bool force, bool memonly)
1374 {
1375  if (!hdChain.IsNull() && !force)
1376  throw std::runtime_error(std::string(__func__) + ": sapling trying to set a hd seed on an already created chain");
1377 
1378  LOCK(wallet->cs_wallet);
1379  // store the keyid (hash160) together with
1380  // the child index counter in the database
1381  // as a hdChain object
1382  CHDChain newHdChain(HDChain::ChainCounterType::Sapling);
1383  if (!newHdChain.SetSeed(keyID) ) {
1384  throw std::runtime_error(std::string(__func__) + ": set sapling hd seed failed");
1385  }
1386 
1387  SetHDChain(newHdChain, memonly);
1388 
1389  // Update the commonOVK to recover t->shield notes
1392  throw std::runtime_error(std::string(__func__) + ": writing sapling commonOVK failed");
1393  }
1394 }
1395 
1397 {
1398  LOCK(wallet->cs_wallet);
1399  if (chain.chainType != HDChain::ChainCounterType::Sapling)
1400  throw std::runtime_error(std::string(__func__) + ": trying to store an invalid chain type");
1401 
1402  if (!memonly && !WalletBatch(wallet->GetDBHandle()).WriteHDChain(chain))
1403  throw std::runtime_error(std::string(__func__) + ": writing sapling chain failed");
1404 
1405  hdChain = chain;
1406 
1407  // Sanity check
1408  if (!wallet->HaveKey(hdChain.GetID()))
1409  throw std::runtime_error(std::string(__func__) + ": Not found sapling seed in wallet");
1410 }
1411 
1413 {
1414  // If already loaded, return it
1415  if (commonOVK) return *commonOVK;
1416 
1417  // Else, look for it in the database
1418  uint256 ovk;
1420  commonOVK = std::move(ovk);
1421  return *commonOVK;
1422  }
1423 
1424  // Otherwise create one. This throws if the wallet is encrypted.
1425  // So we should always call this after unlocking the wallet during a spend
1426  // from a transparent address, or when changing/setting the HD seed.
1429  throw std::runtime_error("Unable to write sapling Common OVK to database");
1430  }
1431  return *commonOVK;
1432 }
1433 
1435 {
1436  // Sending from a t-address, which we don't have an ovk for. Instead,
1437  // generate a common one from the HD seed. This ensures the data is
1438  // recoverable, while keeping it logically separate from the ZIP 32
1439  // Sapling key hierarchy, which the user might not be using.
1440  CKey key;
1441  if (!wallet->GetKey(GetHDChain().GetID(), key)) {
1442  throw std::runtime_error("HD seed not found, wallet must be un-locked");
1443  }
1444  HDSeed seed{key.GetPrivKey()};
1445  return ovkForShieldingFromTaddr(seed);
1446 }
bool IsValidPaymentAddress(const libzcash::PaymentAddress &zaddr)
Check whether a PaymentAddress is not an InvalidEncoding.
Definition: address.cpp:92
int64_t CAmount
Amount in PIV (Can be negative)
Definition: amount.h:13
const CChainParams & Params()
Return the currently selected parameters.
uint256 hash
Definition: transaction.h:35
uint32_t n
Definition: transaction.h:36
const_iterator end() const
Definition: streams.h:163
const_iterator begin() const
Definition: streams.h:161
SaplingSpendingKeyMap mapSaplingSpendingKeys
Definition: keystore.h:109
virtual bool GetSaplingFullViewingKey(const libzcash::SaplingIncomingViewingKey &ivk, libzcash::SaplingExtendedFullViewingKey &extfvkOut) const
Definition: keystore.cpp:215
virtual bool HaveSaplingFullViewingKey(const libzcash::SaplingIncomingViewingKey &ivk) const
Definition: keystore.cpp:194
virtual bool AddSaplingIncomingViewingKey(const libzcash::SaplingIncomingViewingKey &ivk, const libzcash::SaplingPaymentAddress &addr)
Sapling incoming viewing keys.
Definition: keystore.cpp:177
SaplingIncomingViewingKeyMap mapSaplingIncomingViewingKeys
Definition: keystore.h:111
virtual bool GetSaplingIncomingViewingKey(const libzcash::SaplingPaymentAddress &addr, libzcash::SaplingIncomingViewingKey &ivkOut) const
Definition: keystore.cpp:228
virtual bool AddSaplingFullViewingKey(const libzcash::SaplingExtendedFullViewingKey &extfvk)
Support for Sapling full viewing keys.
Definition: keystore.cpp:164
SaplingFullViewingKeyMap mapSaplingFullViewingKeys
Definition: keystore.h:110
bool AddSaplingSpendingKey(const libzcash::SaplingExtendedSpendingKey &sk)
Sapling.
Definition: keystore.cpp:148
bool GetSaplingExtendedSpendingKey(const libzcash::SaplingPaymentAddress &addr, libzcash::SaplingExtendedSpendingKey &extskOut) const
Definition: keystore.cpp:240
Definition: block.h:80
std::vector< CTransactionRef > vtx
Definition: block.h:83
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: chain.h:139
CBlockIndex * pprev
pointer to the index of the predecessor of this block
Definition: chain.h:145
uint256 hashFinalSaplingRoot
Definition: chain.h:195
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: chain.h:151
int Height() const
Return the maximal height in the chain.
Definition: chain.h:450
const Consensus::Params & GetConsensus() const
Definition: chainparams.h:72
bool GetKey(const CKeyID &address, CKey &keyOut) const override
Definition: crypter.cpp:199
bool HaveSaplingSpendingKey(const libzcash::SaplingExtendedFullViewingKey &extfvk) const override
bool IsLocked() const
Definition: crypter.cpp:148
bool HaveKey(const CKeyID &address) const override
Check whether a key corresponding to a given address is present in the store.
Definition: crypter.cpp:179
virtual bool AddCryptedSaplingSpendingKey(const libzcash::SaplingExtendedFullViewingKey &extfvk, const std::vector< unsigned char > &vchCryptedSecret)
Sapling.
bool IsCrypted() const
Definition: crypter.h:154
bool SetSeed(const CKeyID &seedId)
Definition: hdchain.cpp:28
bool IsNull() const
Definition: hdchain.cpp:23
CKeyID GetID() const
Definition: hdchain.h:52
uint8_t chainType
Definition: hdchain.h:38
uint32_t nExternalChainCounter
Definition: hdchain.h:34
An encapsulated private key.
Definition: key.h:30
CPrivKey GetPrivKey() const
Convert the private key to a CPrivKey (serialized secp256k1 private key data).
Definition: key.cpp:173
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:21
KeyOriginInfo key_origin
Definition: walletdb.h:71
CKeyID hd_seed_id
Definition: walletdb.h:70
RecursiveMutex cs_KeyStore
Definition: keystore.h:26
An encapsulated public key.
Definition: pubkey.h:44
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:167
The basic transaction that is broadcasted on the network and contained in blocks.
Definition: transaction.h:244
bool IsShieldedTx() const
Definition: transaction.h:319
const uint256 & GetHash() const
Definition: transaction.h:301
Optional< SaplingTxData > sapData
Definition: transaction.h:275
WalletBatch * encrypted_batch
Definition: wallet.h:724
std::map< uint256, CWalletTx > mapWallet
Definition: wallet.h:766
RecursiveMutex cs_wallet
Definition: wallet.h:720
int GetLastBlockHeight() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get last block processed height.
Definition: wallet.h:689
WalletDatabase & GetDBHandle() const
Definition: wallet.h:752
A transaction with a bunch of additional info that only the owner cares about.
Definition: wallet.h:325
@ CONFIRMED
Definition: wallet.h:376
CTransactionRef tx
Definition: wallet.h:364
Optional< std::pair< libzcash::SaplingNotePlaintext, libzcash::SaplingPaymentAddress > > RecoverSaplingNote(const SaplingOutPoint &op, const std::set< uint256 > &ovks) const
Definition: wallet.cpp:4894
int GetDepthInMainChain() const NO_THREAD_SAFETY_ANALYSIS
Return depth of transaction in blockchain: <0 : conflicts with a transaction this deep in the blockch...
Definition: wallet.cpp:4477
bool IsCoinStake() const
Definition: wallet.h:563
Confirmation m_confirm
Definition: wallet.h:394
Optional< std::pair< libzcash::SaplingNotePlaintext, libzcash::SaplingPaymentAddress > > DecryptSaplingNote(const SaplingOutPoint &op) const
Definition: wallet.cpp:4866
mapSaplingNoteData_t mapSaplingNoteData
Definition: wallet.h:336
const uint256 & GetHash() const
Definition: wallet.h:561
bool IsCoinBase() const
Definition: wallet.h:562
Definition: zip32.h:20
A shielded output to a transaction.
uint256 cmu
The u-coordinate of the note commitment for the output note.
libzcash::SaplingEncCiphertext encCiphertext
A ciphertext component for the encrypted output note.
uint256 ephemeralKey
A Jubjub public key.
Optional< CAmount > amount
Cached note amount.
Optional< uint256 > nullifier
Cached note nullifier.
std::list< SaplingWitness > witnesses
Optional< std::array< unsigned char, ZC_MEMO_SIZE > > memo
Cached note memo (only for non-empty memo) It will be loaded the first time that the note is decrypte...
Optional< libzcash::SaplingIncomingViewingKey > ivk
int witnessHeight
Block height corresponding to the most current witness.
Optional< libzcash::SaplingPaymentAddress > address
Cached shielded address It will be loaded the first time that the note is decrypted (when the tx is a...
An outpoint - a combination of a transaction hash and an index n into its sapling output description ...
Definition: transaction.h:82
std::map< libzcash::SaplingIncomingViewingKey, CKeyMetadata > mapSaplingZKeyMetadata
bool BuildWitnessChain(const CBlockIndex *pTargetBlock, const Consensus::Params &params, std::string &errorStr)
Build the old witness chain.
bool LoadSaplingZKey(const libzcash::SaplingExtendedSpendingKey &key)
Adds spending key to the store, without saving it to disk (used by LoadWallet)
bool UpdatedNoteData(const CWalletTx &wtxIn, CWalletTx &wtx)
Update note data if is needed.
bool IsNoteSaplingChange(const std::set< std::pair< libzcash::PaymentAddress, uint256 >> &nullifierSet, const libzcash::PaymentAddress &address, const SaplingOutPoint &entry) const
Optional< std::string > GetOutPointMemo(const CWalletTx &tx, const SaplingOutPoint &op) const
Return the memo value of a specific outpoint of wallet transaction.
int64_t GetKeyCreationTime(const libzcash::SaplingIncomingViewingKey &ivk)
bool IsSaplingSpent(const SaplingOutPoint &op) const
bool IsSaplingNullifierFromMe(const uint256 &nullifier) const
Whether the nullifier is from this wallet.
Optional< libzcash::SaplingExtendedFullViewingKey > GetViewingKeyForPaymentAddress(const libzcash::SaplingPaymentAddress &addr) const
Return the full viewing key for the shielded address.
bool HaveSpendingKeyForPaymentAddress(const libzcash::SaplingPaymentAddress &zaddr) const
Returns true if the wallet contains the spending key.
std::vector< libzcash::SaplingPaymentAddress > FindMySaplingAddresses(const CTransaction &tx) const
Find all of the addresses in the given tx that have been sent to a SaplingPaymentAddress in this wall...
bool AddCryptedSaplingSpendingKeyDB(const libzcash::SaplingExtendedFullViewingKey &extfvk, const std::vector< unsigned char > &vchCryptedSecret)
void AddToSaplingSpends(const uint256 &nullifier, const uint256 &wtxid)
Keep track of the used nullifier.
std::map< libzcash::SaplingPaymentAddress, std::vector< SaplingNoteEntry > > ListNotes() const
Optional< libzcash::SaplingExtendedSpendingKey > GetSpendingKeyForPaymentAddress(const libzcash::SaplingPaymentAddress &addr) const
Return the spending key for the payment address (nullopt if the wallet has no spending key for such a...
bool AddSaplingSpendingKey(const libzcash::SaplingExtendedSpendingKey &sk)
void IncrementNoteWitnesses(const CBlockIndex *pindex, const CBlock *pblock, SaplingMerkleTree &saplingTree)
pindex is the new tip being connected.
void UpdateSaplingNullifierNoteMap(SaplingNoteData &nd, const SaplingOutPoint &op, const Optional< uint256 > &nullifier)
Update mapSaplingNullifiersToNotes, and NoteData of a specific outpoint, directly with nullifier prov...
CAmount GetCredit(const CWalletTx &tx, const isminefilter &filter, const bool fUnspent=false) const
Return the shielded credit of the tx.
bool SetupGeneration(const CKeyID &keyID, bool force=false, bool memonly=false)
Set and initialize the Sapling HD chain.
const CHDChain & GetHDChain() const
void UpdateNullifierNoteMapWithTx(const CWalletTx &wtx)
Update mapSaplingNullifiersToNotes with the cached nullifiers in this tx.
Optional< std::pair< libzcash::SaplingNotePlaintext, libzcash::SaplingPaymentAddress > > TryToRecoverNote(const CWalletTx &tx, const SaplingOutPoint &op)
Try to recover the note using the wallet's ovks (mostly used when the outpoint is a debit)
bool LoadCryptedSaplingZKey(const libzcash::SaplingExtendedFullViewingKey &extfvk, const std::vector< unsigned char > &vchCryptedSecret)
Adds an encrypted spending key to the store, without saving it to disk (used by LoadWallet)
isminetype IsMine(const CWalletTx &wtx, const SaplingOutPoint &op) const
Return true if the wallet can decrypt & spend the shielded output.
bool LoadSaplingZKeyMetadata(const libzcash::SaplingIncomingViewingKey &ivk, const CKeyMetadata &meta)
Load spending key metadata (used by LoadWallet)
Optional< libzcash::SaplingPaymentAddress > GetOutPointAddress(const CWalletTx &tx, const SaplingOutPoint &op) const
Return the shielded address of a specific outpoint of wallet transaction.
std::map< uint256, SaplingOutPoint > mapSaplingNullifiersToNotes
The reverse mapping of nullifiers to notes.
bool LoadSaplingPaymentAddress(const libzcash::SaplingPaymentAddress &addr, const libzcash::SaplingIncomingViewingKey &ivk)
Adds a Sapling payment address -> incoming viewing key map entry, without saving it to disk (used by ...
KeyAddResult AddViewingKeyToWallet(const libzcash::SaplingExtendedFullViewingKey &extfvk) const
bool AddSaplingIncomingViewingKey(const libzcash::SaplingIncomingViewingKey &ivk, const libzcash::SaplingPaymentAddress &addr)
bool PaymentAddressBelongsToWallet(const libzcash::SaplingPaymentAddress &zaddr) const
Returns true if the wallet contains the spending and viewing key for the shielded address.
CAmount GetOutPointValue(const CWalletTx &tx, const SaplingOutPoint &op) const
Return the shielded value of a specific outpoint of wallet transaction.
std::map< uint256, std::list< SaplingWitness > > cachedWitnessMap
void GetNotes(const std::vector< SaplingOutPoint > &saplingOutpoints, std::vector< SaplingNoteEntry > &saplingEntriesRet) const
Find notes for the outpoints.
Optional< libzcash::SaplingPaymentAddress > GetAddressFromInputIfPossible(const CWalletTx *wtx, int index) const
Return the address from where the shielded spend is taking the funds from (if possible)
bool AddSaplingZKey(const libzcash::SaplingExtendedSpendingKey &key)
Adds Sapling spending key to the store, and saves it to disk.
std::pair< mapSaplingNoteData_t, SaplingIncomingViewingKeyMap > FindMySaplingNotes(const CTransaction &tx) const
Finds all output notes in the given tx that have been sent to a SaplingPaymentAddress in this wallet.
void GetSaplingNoteWitnesses(const std::vector< SaplingOutPoint > &notes, std::vector< Optional< SaplingWitness >> &witnesses, uint256 &final_anchor) const
Return all of the witnesses for the input notes.
void DecrementNoteWitnesses(const CBlockIndex *pindex)
pindex is the old tip being disconnected.
libzcash::SaplingPaymentAddress GenerateNewSaplingZKey()
Generates new Sapling key.
std::set< std::pair< libzcash::PaymentAddress, uint256 > > GetNullifiersForAddresses(const std::set< libzcash::PaymentAddress > &addresses) const
void SetHDSeed(const CPubKey &key, bool force=false, bool memonly=false)
Optional< uint256 > commonOVK
void UpdateSaplingNullifierNoteMapWithTx(CWalletTx &wtx)
Update mapSaplingNullifiersToNotes, computing the nullifier from a cached witness if necessary.
bool EncryptSaplingKeys(CKeyingMaterial &vMasterKeyIn)
void GetFilteredNotes(std::vector< SaplingNoteEntry > &saplingEntries, Optional< libzcash::SaplingPaymentAddress > &address, int minDepth=1, bool ignoreSpent=true, bool requireSpendingKey=true, bool ignoreLocked=true) const
Find notes in the wallet filtered by payment address, min depth and ability to spend and if the notes...
void SetHDChain(CHDChain &chain, bool memonly)
CAmount GetDebit(const CTransaction &tx, const isminefilter &filter) const
Return the shielded debit of the tx.
void UpdateSaplingNullifierNoteMapForBlock(const CBlock *pblock)
Iterate over transactions in a block and update the cached Sapling nullifiers for transactions which ...
void ClearNoteWitnessCache()
Clear every notesData from every wallet tx and reset the witness cache size.
void GetConflicts(const CWalletTx &wtx, std::set< uint256 > &result) const
CAmount GetShieldedChange(const CWalletTx &wtx) const
Return the shielded change of the tx.
KeyAddResult AddSpendingKeyToWallet(const Consensus::Params &params, const libzcash::SaplingExtendedSpendingKey &sk, int64_t nTime)
A shielded input to a transaction.
uint256 nullifier
The nullifier of the input note.
Access to the wallet database.
Definition: walletdb.h:112
bool WriteSaplingPaymentAddress(const libzcash::SaplingPaymentAddress &addr, const libzcash::SaplingIncomingViewingKey &ivk)
Definition: walletdb.cpp:148
bool WriteCryptedSaplingZKey(const libzcash::SaplingExtendedFullViewingKey &extfvk, const std::vector< unsigned char > &vchCryptedSecret, const CKeyMetadata &keyMeta)
Definition: walletdb.cpp:154
bool ReadSaplingCommonOVK(uint256 &ovkRet)
Definition: walletdb.cpp:181
bool WriteHDChain(const CHDChain &chain)
write the hdchain model (external/internal chain child index counter)
Definition: walletdb.cpp:275
bool WriteSaplingCommonOVK(const uint256 &ovk)
Common output viewing key, used when shielding transparent funds.
Definition: walletdb.cpp:176
bool WriteSaplingZKey(const libzcash::SaplingIncomingViewingKey &ivk, const libzcash::SaplingExtendedSpendingKey &key, const CKeyMetadata &keyMeta)
Write extended spending key to wallet database, where the key is the incoming viewing key.
Definition: walletdb.cpp:137
std::string ToString() const
Definition: uint256.cpp:65
const std::array< unsigned char, ZC_MEMO_SIZE > & memo() const
Definition: note.h:66
IncrementalWitness< Depth, Hash > witness() const
SaplingFullViewingKey full_viewing_key() const
Definition: address.cpp:29
SaplingIncomingViewingKey in_viewing_key() const
Definition: address.cpp:45
Optional< SaplingPaymentAddress > address(diversifier_t d) const
Definition: address.cpp:73
Optional< SaplingNote > note(const SaplingIncomingViewingKey &ivk) const
Definition: note.cpp:80
static Optional< SaplingNotePlaintext > decrypt(const SaplingEncCiphertext &ciphertext, const uint256 &ivk, const uint256 &epk, const uint256 &cmu)
Definition: note.cpp:115
Sapling functions.
Definition: address.h:30
256-bit opaque blob.
Definition: uint256.h:138
bool EncryptSecret(const CKeyingMaterial &vMasterKey, const CKeyingMaterial &vchPlaintext, const uint256 &nIV, std::vector< unsigned char > &vchCiphertext)
Definition: crypter.cpp:104
std::vector< unsigned char, secure_allocator< unsigned char > > CKeyingMaterial
Definition: crypter.h:63
bool IsLockedNote(const SaplingOutPoint &op) const
Definition: wallet.cpp:3992
const CKeyingMaterial & GetEncryptionKey() const
Definition: wallet.cpp:691
const CWalletTx * GetWalletTx(const uint256 &hash) const
Definition: wallet.cpp:166
void SyncMetaDataN(std::pair< TxSpendMap< uint256 >::iterator, TxSpendMap< uint256 >::iterator > range)
Definition: wallet.cpp:646
libzcash::IncrementalMerkleTree< SAPLING_INCREMENTAL_MERKLE_TREE_DEPTH, libzcash::PedersenHash > SaplingMerkleTree
isminetype
IsMine() return codes.
Definition: ismine.h:19
@ ISMINE_SPENDABLE_SHIELDED
Indicates that we have the spending key of a shielded spend/output.
Definition: ismine.h:30
@ ISMINE_WATCH_ONLY_SHIELDED
Indicates that we don't have the spending key of a shielded spend/output.
Definition: ismine.h:28
@ ISMINE_NO
Definition: ismine.h:20
uint8_t isminefilter
used for bitflags of isminetype
Definition: ismine.h:39
std::map< libzcash::SaplingPaymentAddress, libzcash::SaplingIncomingViewingKey > SaplingIncomingViewingKeyMap
Definition: keystore.h:94
@ LOCK
Definition: lockunlock.h:16
@ UPGRADE_V5_0
Definition: params.h:36
boost::variant< InvalidEncoding, SaplingPaymentAddress > PaymentAddress
Definition: address.h:127
RecursiveMutex cs_main
Global state.
Definition: validation.cpp:80
boost::optional< T > Optional
Substitute for C++17 std::optional.
Definition: optional.h:12
void CopyPreviousWitnesses(NoteDataMap &noteDataMap, int indexHeight, int64_t nWitnessCacheSize)
void UpdateWitnessHeights(NoteDataMap &noteDataMap, int indexHeight, int64_t nWitnessCacheSize)
void DecrementNoteWitnesses(NoteDataMap &noteDataMap, int indexHeight, int64_t nWitnessCacheSize)
void ResetNoteWitnesses(std::map< SaplingOutPoint, SaplingNoteData > &noteDataMap, std::map< uint256, std::list< SaplingWitness >> &cachedWitnessMap, int indexHeight)
void AppendNoteCommitment(SaplingNoteData *nd, int indexHeight, int64_t nWitnessCacheSize, const uint256 &note_commitment)
void WitnessNoteIfMine(SaplingNoteData *nd, int indexHeight, int64_t nWitnessCacheSize, const Witness &witness)
@ KeyAlreadyExists
@ SpendingKeyExists
std::map< SaplingOutPoint, SaplingNoteData > mapSaplingNoteData_t
@ SER_NETWORK
Definition: serialize.h:174
static constexpr int ALWAYS_ACTIVE
Special value for nActivationHeight indicating that the upgrade is always active.
Definition: params.h:67
int nActivationHeight
Height of the first block for which the new consensus rules will be active.
Definition: params.h:56
Parameters that influence chain consensus.
Definition: params.h:171
NetworkUpgrade vUpgrades[MAX_NETWORK_UPGRADES]
Definition: params.h:213
bool MoneyRange(const CAmount &nValue) const
Definition: params.h:217
bool NetworkUpgradeActive(int nHeight, Consensus::UpgradeIndex idx) const
Returns true if the given network upgrade is active as of the given block height.
Definition: params.cpp:12
std::vector< uint32_t > path
Definition: keyorigin.h:14
libzcash::SaplingFullViewingKey fvk
Definition: zip32.h:56
libzcash::SaplingExpandedSpendingKey expsk
Definition: zip32.h:92
libzcash::SaplingPaymentAddress DefaultAddress() const
Definition: zip32.cpp:162
SaplingExtendedSpendingKey Derive(uint32_t i) const
Definition: zip32.cpp:132
static SaplingExtendedSpendingKey Master(const HDSeed &seed)
Definition: zip32.cpp:117
SaplingExtendedFullViewingKey ToXFVK() const
Definition: zip32.cpp:150
#define LOCK2(cs1, cs2)
Definition: sync.h:221
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition: sync.h:247
#define AssertLockHeld(cs)
Definition: sync.h:75
bool error(const char *fmt, const Args &... args)
Definition: system.h:77
int64_t GetAdjustedTime()
Definition: timedata.cpp:36
bool IsFinalTx(const CTransactionRef &tx, int nBlockHeight, int64_t nBlockTime)
Check if transaction is final and can be included in a block with the specified height and time.
Definition: tx_verify.cpp:12
const uint256 UINT256_ZERO
constant uint256 instances
Definition: uint256.h:175
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
bool IsValidUTF8(const std::string &str)
Checks for valid 4-byte UTF-8 encoding in a string.
T FindFirstNonZero(T itbegin, T itend)
int64_t GetTime()
DEPRECATED Use either GetSystemTimeInSeconds (not mockable) or GetTime<T> (mockable)
Definition: utiltime.cpp:27
std::unique_ptr< CCoinsViewCache > pcoinsTip
Global variable that points to the active CCoinsView (protected by cs_main)
Definition: validation.cpp:206
bool ReadBlockFromDisk(CBlock &block, const FlatFilePos &pos)
Definition: validation.cpp:758
CBlockIndex * GetChainTip()
Return a reliable pointer (in mapBlockIndex) to the chain's tip index.
Definition: validation.cpp:194
CChain chainActive
The currently-connected chain of blocks (protected by cs_main).
Definition: validation.cpp:84
uint256 ovkForShieldingFromTaddr(HDSeed &seed)
Definition: zip32.cpp:38
const uint32_t ZIP32_HARDENED_KEY_LIMIT
Definition: zip32.h:16