PIVX Core  5.6.99
P2P Digital Currency
saplingscriptpubkeyman.h
Go to the documentation of this file.
1 // Copyright (c) 2020-2021 The PIVX Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #ifndef PIVX_SAPLING_SAPLINGSCRIPTPUBKEYMAN_H
6 #define PIVX_SAPLING_SAPLINGSCRIPTPUBKEYMAN_H
7 
8 #include "consensus/consensus.h"
10 #include "sapling/note.h"
11 #include "uint256.h"
12 #include "wallet/hdchain.h"
13 #include "wallet/scriptpubkeyman.h"
14 #include "wallet/wallet.h"
15 #include "wallet/walletdb.h"
16 #include <map>
17 
19 // Should be large enough that we can expect not to reorg beyond our cache
20 // unless there is some exceptional network disruption.
21 static const unsigned int WITNESS_CACHE_SIZE = DEFAULT_MAX_REORG_DEPTH + 1;
22 
23 class CBlock;
24 class CBlockIndex;
25 
28 {
29  explicit SaplingNoteEntry(const SaplingOutPoint& _op,
31  const libzcash::SaplingNote& _note,
32  const std::array<unsigned char, ZC_MEMO_SIZE>& _memo,
33  const int _conf) :
34  op(_op), address(_addr), note(_note), memo(_memo),
35  confirmations(_conf) { }
39  std::array<unsigned char, ZC_MEMO_SIZE> memo;
41 };
42 
44 {
45 public:
46 
48  explicit SaplingNoteData(const libzcash::SaplingIncomingViewingKey& _ivk) : ivk {_ivk}, nullifier() { }
50 
51  /* witnesses/ivk: only for own (received) outputs */
52  std::list<SaplingWitness> witnesses;
53 
55  inline bool IsMyNote() const { return ivk != nullopt; }
56 
62 
68 
74 
84  int witnessHeight{-1};
85 
99 
101  {
102  int nVersion = s.GetVersion();
103  if (!(s.GetType() & SER_GETHASH)) {
104  READWRITE(nVersion);
105  }
106  READWRITE(obj.ivk);
107  READWRITE(obj.nullifier);
108  READWRITE(obj.witnesses);
109  READWRITE(obj.witnessHeight);
110  READWRITE(obj.amount);
111  READWRITE(obj.address);
112  READWRITE(obj.memo);
113  }
114 
115  friend bool operator==(const SaplingNoteData& a, const SaplingNoteData& b) {
116  return (a.ivk == b.ivk &&
117  a.nullifier == b.nullifier &&
118  a.witnessHeight == b.witnessHeight &&
119  a.amount == b.amount &&
120  a.address == b.address &&
121  a.memo == b.memo);
122  }
123 
124  friend bool operator!=(const SaplingNoteData& a, const SaplingNoteData& b) {
125  return !(a == b);
126  }
127 };
128 
134 };
135 
136 typedef std::map<SaplingOutPoint, SaplingNoteData> mapSaplingNoteData_t;
137 
138 /*
139  * Sapling keys manager
140  * A class implementing SaplingScriptPubKeyMan manages all sapling keys and Notes used in a wallet.
141  * It is responsible for the decryption of notes and caching metadata.
142  * A SaplingScriptPubKeyMan will be able to give out notes to be used, as well as marking
143  * when a note has been used. It also handles when and how to store a sapling OutputDescription
144  * and its related keys, including encryption.
145  * A ScriptPubKeyMan will also update notes witnesses, and keep track of nullifiers.
146  */
148 
149 public:
150  explicit SaplingScriptPubKeyMan(CWallet *parent) : wallet(parent) {}
151 
153 
157  void AddToSaplingSpends(const uint256& nullifier, const uint256& wtxid);
158  bool IsSaplingSpent(const SaplingOutPoint& op) const;
159  bool IsSaplingSpent(const uint256& nullifier) const;
160 
164  bool BuildWitnessChain(const CBlockIndex* pTargetBlock, const Consensus::Params& params, std::string& errorStr);
165 
169  void IncrementNoteWitnesses(const CBlockIndex* pindex,
170  const CBlock* pblock,
171  SaplingMerkleTree& saplingTree);
175  void DecrementNoteWitnesses(const CBlockIndex* pindex);
176 
181  void UpdateNullifierNoteMapWithTx(const CWalletTx& wtx);
182 
188 
194 
199  void UpdateSaplingNullifierNoteMapForBlock(const CBlock* pblock);
200 
204  bool SetupGeneration(const CKeyID& keyID, bool force = false, bool memonly = false);
205  bool IsEnabled() const { return !hdChain.IsNull(); };
206 
207  /* Set the current HD seed (will reset the chain child index counters)
208  Sets the seed's version based on the current wallet version (so the
209  caller must ensure the current wallet version is correct before calling
210  this function). */
211  void SetHDSeed(const CPubKey& key, bool force = false, bool memonly = false);
212  void SetHDSeed(const CKeyID& keyID, bool force = false, bool memonly = false);
213 
214  /* Set the HD chain model (chain child index counters) */
215  void SetHDChain(CHDChain& chain, bool memonly);
216  const CHDChain& GetHDChain() const { return hdChain; }
217 
218  /* Get cached sapling commonOVK
219  * If nullopt, read it from the database, and save it.
220  * If not found in the database, create a new one from the HD seed (throw
221  * if the wallet is locked), write it to database, and save it.
222  */
224  void setCommonOVK(const uint256& ovk) { commonOVK = ovk; }
225 
226  /* Encrypt Sapling keys */
227  bool EncryptSaplingKeys(CKeyingMaterial& vMasterKeyIn);
228 
229  void GetConflicts(const CWalletTx& wtx, std::set<uint256>& result) const;
230 
231  // Get the ivk creation time (we are only using the ivk's default address)
233 
234  // Add full viewing key if it's not already in the wallet
236 
237  // Add spending key if it's not already in the wallet
239  const Consensus::Params &params,
241  int64_t nTime);
242 
249  const libzcash::SaplingPaymentAddress &addr);
252  const std::vector<unsigned char> &vchCryptedSecret);
257 
264  const std::vector<unsigned char> &vchCryptedSecret);
271 
274  const libzcash::SaplingPaymentAddress &addr) const;
275 
278 
281  std::pair<mapSaplingNoteData_t, SaplingIncomingViewingKeyMap> FindMySaplingNotes(const CTransaction& tx) const;
282 
284  std::vector<libzcash::SaplingPaymentAddress> FindMySaplingAddresses(const CTransaction& tx) const;
285 
287  void GetNotes(const std::vector<SaplingOutPoint>& saplingOutpoints,
288  std::vector<SaplingNoteEntry>& saplingEntriesRet) const;
289 
290  /* Find notes filtered by payment address, min depth, ability to spend and if they are locked */
291  void GetFilteredNotes(std::vector<SaplingNoteEntry>& saplingEntries,
293  int minDepth = 1,
294  bool ignoreSpent = true,
295  bool requireSpendingKey = true,
296  bool ignoreLocked = true) const;
297 
298  /* Find notes filtered by payment addresses, min depth, max depth, if they are spent,
299  if a spending key is required, and if they are locked */
300  void GetFilteredNotes(std::vector<SaplingNoteEntry>& saplingEntries,
301  std::set<libzcash::PaymentAddress>& filterAddresses,
302  int minDepth=1,
303  int maxDepth=INT_MAX,
304  bool ignoreSpent=true,
305  bool requireSpendingKey=true,
306  bool ignoreLocked=true) const;
307 
308  /* Return list of available notes grouped by sapling address. */
309  std::map<libzcash::SaplingPaymentAddress, std::vector<SaplingNoteEntry>> ListNotes() const;
310 
314 
316  bool IsSaplingNullifierFromMe(const uint256& nullifier) const;
317 
320  const std::vector<SaplingOutPoint>& notes,
321  std::vector<Optional<SaplingWitness>>& witnesses,
322  uint256& final_anchor) const;
323 
324  std::set<std::pair<libzcash::PaymentAddress, uint256>> GetNullifiersForAddresses(const std::set<libzcash::PaymentAddress> & addresses) const;
325  bool IsNoteSaplingChange(const std::set<std::pair<libzcash::PaymentAddress, uint256>>& nullifierSet, const libzcash::PaymentAddress& address, const SaplingOutPoint& entry) const;
326 
328  Optional<std::pair<
331 
333  isminetype IsMine(const CWalletTx& wtx, const SaplingOutPoint& op) const;
337  CAmount GetOutPointValue(const CWalletTx& tx, const SaplingOutPoint& op) const;
341  CAmount GetCredit(const CWalletTx& tx, const isminefilter& filter, const bool fUnspent = false) const;
343  CAmount GetDebit(const CTransaction& tx, const isminefilter& filter) const;
345  CAmount GetShieldedChange(const CWalletTx& wtx) const;
346 
349 
351  bool UpdatedNoteData(const CWalletTx& wtxIn, CWalletTx& wtx);
352 
354  void ClearNoteWitnessCache();
355 
356  // Sapling metadata
357  std::map<libzcash::SaplingIncomingViewingKey, CKeyMetadata> mapSaplingZKeyMetadata;
358 
359  /*
360  * Size of the incremental witness cache for the notes in our wallet.
361  * This will always be greater than or equal to the size of the largest
362  * incremental witness cache in any transaction in mapWallet.
363  */
364  int64_t nWitnessCacheSize{0};
366 
416  std::map<uint256, SaplingOutPoint> mapSaplingNullifiersToNotes;
417 
418 private:
419  /* Map hash nullifiers, list Sapling Witness*/
420  std::map<uint256, std::list<SaplingWitness>> cachedWitnessMap;
422  /* Parent wallet */
423  CWallet* wallet{nullptr};
424  /* the HD chain data model (external/internal chain counters) */
426  /* cached common OVK for sapling spends from t addresses */
429 
430 
435  typedef std::multimap<uint256, uint256> TxNullifiers;
437 };
438 
439 #endif // PIVX_SAPLING_SAPLINGSCRIPTPUBKEYMAN_H
int64_t CAmount
Amount in PIV (Can be negative)
Definition: amount.h:13
Definition: block.h:80
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: chain.h:139
bool IsNull() const
Definition: hdchain.cpp:23
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:21
An encapsulated public key.
Definition: pubkey.h:44
The basic transaction that is broadcasted on the network and contained in blocks.
Definition: transaction.h:244
A CWallet is an extension of a keystore, which also maintains a set of transactions and balances,...
Definition: wallet.h:577
A transaction with a bunch of additional info that only the owner cares about.
Definition: wallet.h:325
SaplingNoteData(const libzcash::SaplingIncomingViewingKey &_ivk)
Optional< CAmount > amount
Cached note amount.
SERIALIZE_METHODS(SaplingNoteData, obj)
Optional< uint256 > nullifier
Cached note nullifier.
friend bool operator==(const SaplingNoteData &a, const SaplingNoteData &b)
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
friend bool operator!=(const SaplingNoteData &a, const SaplingNoteData &b)
int witnessHeight
Block height corresponding to the most current witness.
SaplingNoteData(const libzcash::SaplingIncomingViewingKey &_ivk, const uint256 &n)
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)
SaplingScriptPubKeyMan(CWallet *parent)
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)
std::multimap< uint256, uint256 > TxNullifiers
Used to keep track of spent Notes, and detect and report conflicts (double-spends).
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.
void setCommonOVK(const uint256 &ovk)
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)
Sapling functions.
Definition: address.h:30
256-bit opaque blob.
Definition: uint256.h:138
std::vector< unsigned char, secure_allocator< unsigned char > > CKeyingMaterial
Definition: crypter.h:63
isminetype
IsMine() return codes.
Definition: ismine.h:19
uint8_t isminefilter
used for bitflags of isminetype
Definition: ismine.h:39
boost::variant< InvalidEncoding, SaplingPaymentAddress > PaymentAddress
Definition: address.h:127
boost::optional< T > Optional
Substitute for C++17 std::optional.
Definition: optional.h:12
@ KeyAlreadyExists
@ SpendingKeyExists
std::map< SaplingOutPoint, SaplingNoteData > mapSaplingNoteData_t
@ SER_GETHASH
Definition: serialize.h:176
#define READWRITE(...)
Definition: serialize.h:183
Parameters that influence chain consensus.
Definition: params.h:171
Sapling note, its location in a transaction, and number of confirmations.
SaplingOutPoint op
SaplingNoteEntry(const SaplingOutPoint &_op, const libzcash::SaplingPaymentAddress &_addr, const libzcash::SaplingNote &_note, const std::array< unsigned char, ZC_MEMO_SIZE > &_memo, const int _conf)
int confirmations
libzcash::SaplingPaymentAddress address
std::array< unsigned char, ZC_MEMO_SIZE > memo
libzcash::SaplingNote note