Bitcoin Core  0.19.99
P2P Digital Currency
scriptpubkeyman.h
Go to the documentation of this file.
1 // Copyright (c) 2019-2020 The Bitcoin 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 BITCOIN_WALLET_SCRIPTPUBKEYMAN_H
6 #define BITCOIN_WALLET_SCRIPTPUBKEYMAN_H
7 
9 #include <script/standard.h>
10 #include <wallet/crypter.h>
11 #include <wallet/ismine.h>
12 #include <wallet/walletdb.h>
13 #include <wallet/walletutil.h>
14 
15 #include <boost/signals2/signal.hpp>
16 
17 enum class OutputType;
18 
19 // Wallet storage things that ScriptPubKeyMans need in order to be able to store things to the wallet database.
20 // It provides access to things that are part of the entire wallet and not specific to a ScriptPubKeyMan such as
21 // wallet flags, wallet version, encryption keys, encryption status, and the database itself. This allows a
22 // ScriptPubKeyMan to have callbacks into CWallet without causing a circular dependency.
23 // WalletStorage should be the same for all ScriptPubKeyMans of a wallet.
25 {
26 public:
27  virtual ~WalletStorage() = default;
28  virtual const std::string GetDisplayName() const = 0;
29  virtual WalletDatabase& GetDatabase() = 0;
30  virtual bool IsWalletFlagSet(uint64_t) const = 0;
31  virtual void UnsetBlankWalletFlag(WalletBatch&) = 0;
32  virtual bool CanSupportFeature(enum WalletFeature) const = 0;
33  virtual void SetMinVersion(enum WalletFeature, WalletBatch* = nullptr, bool = false) = 0;
34  virtual const CKeyingMaterial& GetEncryptionKey() const = 0;
35  virtual bool HasEncryptionKeys() const = 0;
36  virtual bool IsLocked() const = 0;
37 };
38 
40 static const unsigned int DEFAULT_KEYPOOL_SIZE = 1000;
41 
42 std::vector<CKeyID> GetAffectedKeys(const CScript& spk, const SigningProvider& provider);
43 
93 class CKeyPool
94 {
95 public:
97  int64_t nTime;
101  bool fInternal;
104 
105  CKeyPool();
106  CKeyPool(const CPubKey& vchPubKeyIn, bool internalIn);
107 
109 
110  template <typename Stream, typename Operation>
111  inline void SerializationOp(Stream& s, Operation ser_action) {
112  int nVersion = s.GetVersion();
113  if (!(s.GetType() & SER_GETHASH))
114  READWRITE(nVersion);
115  READWRITE(nTime);
116  READWRITE(vchPubKey);
117  if (ser_action.ForRead()) {
118  try {
119  READWRITE(fInternal);
120  }
121  catch (std::ios_base::failure&) {
122  /* flag as external address if we can't read the internal boolean
123  (this will be the case for any wallet before the HD chain split version) */
124  fInternal = false;
125  }
126  try {
127  READWRITE(m_pre_split);
128  }
129  catch (std::ios_base::failure&) {
130  /* flag as postsplit address if we can't read the m_pre_split boolean
131  (this will be the case for any wallet that upgrades to HD chain split)*/
132  m_pre_split = false;
133  }
134  }
135  else {
136  READWRITE(fInternal);
137  READWRITE(m_pre_split);
138  }
139  }
140 };
141 
142 /*
143  * A class implementing ScriptPubKeyMan manages some (or all) scriptPubKeys used in a wallet.
144  * It contains the scripts and keys related to the scriptPubKeys it manages.
145  * A ScriptPubKeyMan will be able to give out scriptPubKeys to be used, as well as marking
146  * when a scriptPubKey has been used. It also handles when and how to store a scriptPubKey
147  * and its related scripts and keys, including encryption.
148  */
150 {
151 protected:
153 
154 public:
155  ScriptPubKeyMan(WalletStorage& storage) : m_storage(storage) {}
156  virtual ~ScriptPubKeyMan() {};
157  virtual bool GetNewDestination(const OutputType type, CTxDestination& dest, std::string& error) { return false; }
158  virtual isminetype IsMine(const CScript& script) const { return ISMINE_NO; }
159 
161  virtual bool CheckDecryptionKey(const CKeyingMaterial& master_key, bool accept_no_keys = false) { return false; }
162  virtual bool Encrypt(const CKeyingMaterial& master_key, WalletBatch* batch) { return false; }
163 
164  virtual bool GetReservedDestination(const OutputType type, bool internal, CTxDestination& address, int64_t& index, CKeyPool& keypool) { return false; }
165  virtual void KeepDestination(int64_t index, const OutputType& type) {}
166  virtual void ReturnDestination(int64_t index, bool internal, const CTxDestination& addr) {}
167 
172  virtual bool TopUp(unsigned int size = 0) { return false; }
173 
175  virtual void MarkUnusedAddresses(const CScript& script) {}
176 
181  virtual bool SetupGeneration(bool force = false) { return false; }
182 
183  /* Returns true if HD is enabled */
184  virtual bool IsHDEnabled() const { return false; }
185 
186  /* Returns true if the wallet can give out new addresses. This means it has keys in the keypool or can generate new keys */
187  virtual bool CanGetAddresses(bool internal = false) { return false; }
188 
190  virtual bool Upgrade(int prev_version, std::string& error) { return false; }
191 
192  virtual bool HavePrivateKeys() const { return false; }
193 
195  virtual void RewriteDB() {}
196 
197  virtual int64_t GetOldestKeyPoolTime() { return GetTime(); }
198 
199  virtual size_t KeypoolCountExternalKeys() { return 0; }
200  virtual unsigned int GetKeyPoolSize() const { return 0; }
201 
202  virtual int64_t GetTimeFirstKey() const { return 0; }
203 
204  virtual const CKeyMetadata* GetMetadata(const CTxDestination& dest) const { return nullptr; }
205 
206  virtual std::unique_ptr<SigningProvider> GetSigningProvider(const CScript& script) const { return nullptr; }
207 
211  virtual bool CanProvide(const CScript& script, SignatureData& sigdata) { return false; }
212 
213  virtual uint256 GetID() const { return uint256(); }
214 
216  template<typename... Params>
217  void WalletLogPrintf(std::string fmt, Params... parameters) const {
218  LogPrintf(("%s " + fmt).c_str(), m_storage.GetDisplayName(), parameters...);
219  };
220 
222  boost::signals2::signal<void (bool fHaveWatchOnly)> NotifyWatchonlyChanged;
223 
225  boost::signals2::signal<void ()> NotifyCanGetAddressesChanged;
226 };
227 
229 {
230 private:
232  bool fDecryptionThoroughlyChecked = false;
233 
234  using WatchOnlySet = std::set<CScript>;
235  using WatchKeyMap = std::map<CKeyID, CPubKey>;
236 
237  WalletBatch *encrypted_batch GUARDED_BY(cs_KeyStore) = nullptr;
238 
239  using CryptedKeyMap = std::map<CKeyID, std::pair<CPubKey, std::vector<unsigned char>>>;
240 
241  CryptedKeyMap mapCryptedKeys GUARDED_BY(cs_KeyStore);
242  WatchOnlySet setWatchOnly GUARDED_BY(cs_KeyStore);
243  WatchKeyMap mapWatchKeys GUARDED_BY(cs_KeyStore);
244 
245  int64_t nTimeFirstKey GUARDED_BY(cs_KeyStore) = 0;
246 
247  bool AddKeyPubKeyInner(const CKey& key, const CPubKey &pubkey);
248  bool AddCryptedKeyInner(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
249 
259  bool AddWatchOnly(const CScript& dest) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
260  bool AddWatchOnlyWithDB(WalletBatch &batch, const CScript& dest) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
261  bool AddWatchOnlyInMem(const CScript &dest);
263  bool AddWatchOnlyWithDB(WalletBatch &batch, const CScript& dest, int64_t create_time) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
264 
266  bool AddKeyPubKeyWithDB(WalletBatch &batch,const CKey& key, const CPubKey &pubkey) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
267 
268  void AddKeypoolPubkeyWithDB(const CPubKey& pubkey, const bool internal, WalletBatch& batch);
269 
271  bool AddCScriptWithDB(WalletBatch& batch, const CScript& script);
272 
274  bool AddKeyOriginWithDB(WalletBatch& batch, const CPubKey& pubkey, const KeyOriginInfo& info);
275 
276  /* the HD chain data model (external chain counters) */
278 
279  /* HD derive new child key (on internal or external chain) */
280  void DeriveNewChildKey(WalletBatch& batch, CKeyMetadata& metadata, CKey& secret, bool internal = false) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
281 
282  std::set<int64_t> setInternalKeyPool GUARDED_BY(cs_KeyStore);
283  std::set<int64_t> setExternalKeyPool GUARDED_BY(cs_KeyStore);
284  std::set<int64_t> set_pre_split_keypool GUARDED_BY(cs_KeyStore);
285  int64_t m_max_keypool_index GUARDED_BY(cs_KeyStore) = 0;
286  std::map<CKeyID, int64_t> m_pool_key_to_index;
287  // Tracks keypool indexes to CKeyIDs of keys that have been taken out of the keypool but may be returned to it
288  std::map<int64_t, CKeyID> m_index_to_reserved_key;
289 
291  bool GetKeyFromPool(CPubKey &key, const OutputType type, bool internal = false);
292 
307  bool ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRequestedInternal);
308 
309 public:
311 
312  bool GetNewDestination(const OutputType type, CTxDestination& dest, std::string& error) override;
313  isminetype IsMine(const CScript& script) const override;
314 
315  bool CheckDecryptionKey(const CKeyingMaterial& master_key, bool accept_no_keys = false) override;
316  bool Encrypt(const CKeyingMaterial& master_key, WalletBatch* batch) override;
317 
318  bool GetReservedDestination(const OutputType type, bool internal, CTxDestination& address, int64_t& index, CKeyPool& keypool) override;
319  void KeepDestination(int64_t index, const OutputType& type) override;
320  void ReturnDestination(int64_t index, bool internal, const CTxDestination&) override;
321 
322  bool TopUp(unsigned int size = 0) override;
323 
324  void MarkUnusedAddresses(const CScript& script) override;
325 
327  void UpgradeKeyMetadata();
328 
329  bool IsHDEnabled() const override;
330 
331  bool SetupGeneration(bool force = false) override;
332 
333  bool Upgrade(int prev_version, std::string& error) override;
334 
335  bool HavePrivateKeys() const override;
336 
337  void RewriteDB() override;
338 
339  int64_t GetOldestKeyPoolTime() override;
340  size_t KeypoolCountExternalKeys() override;
341  unsigned int GetKeyPoolSize() const override;
342 
343  int64_t GetTimeFirstKey() const override;
344 
345  const CKeyMetadata* GetMetadata(const CTxDestination& dest) const override;
346 
347  bool CanGetAddresses(bool internal = false) override;
348 
349  std::unique_ptr<SigningProvider> GetSigningProvider(const CScript& script) const override;
350 
351  bool CanProvide(const CScript& script, SignatureData& sigdata) override;
352 
353  uint256 GetID() const override;
354 
355  // Map from Key ID to key metadata.
356  std::map<CKeyID, CKeyMetadata> mapKeyMetadata GUARDED_BY(cs_KeyStore);
357 
358  // Map from Script ID to key metadata (for watch-only keys).
359  std::map<CScriptID, CKeyMetadata> m_script_metadata GUARDED_BY(cs_KeyStore);
360 
362  bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey) override;
364  bool LoadKey(const CKey& key, const CPubKey &pubkey);
366  bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
368  bool LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
369  void UpdateTimeFirstKey(int64_t nCreateTime) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
371  bool LoadCScript(const CScript& redeemScript);
373  void LoadKeyMetadata(const CKeyID& keyID, const CKeyMetadata &metadata);
374  void LoadScriptMetadata(const CScriptID& script_id, const CKeyMetadata &metadata);
376  CPubKey GenerateNewKey(WalletBatch& batch, bool internal = false) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
377 
378  /* Set the HD chain model (chain child index counters) */
379  void SetHDChain(const CHDChain& chain, bool memonly);
380  const CHDChain& GetHDChain() const { return hdChain; }
381 
383  bool LoadWatchOnly(const CScript &dest);
385  bool HaveWatchOnly(const CScript &dest) const;
387  bool HaveWatchOnly() const;
389  bool RemoveWatchOnly(const CScript &dest);
390  bool AddWatchOnly(const CScript& dest, int64_t nCreateTime) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
391 
393  bool GetWatchPubKey(const CKeyID &address, CPubKey &pubkey_out) const;
394 
395  /* SigningProvider overrides */
396  bool HaveKey(const CKeyID &address) const override;
397  bool GetKey(const CKeyID &address, CKey& keyOut) const override;
398  bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const override;
399  bool AddCScript(const CScript& redeemScript) override;
400  bool GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const override;
401 
403  void LoadKeyPool(int64_t nIndex, const CKeyPool &keypool);
404  bool NewKeyPool();
405  void MarkPreSplitKeys() EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
406 
407  bool ImportScripts(const std::set<CScript> scripts, int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
408  bool ImportPrivKeys(const std::map<CKeyID, CKey>& privkey_map, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
409  bool ImportPubKeys(const std::vector<CKeyID>& ordered_pubkeys, const std::map<CKeyID, CPubKey>& pubkey_map, const std::map<CKeyID, std::pair<CPubKey, KeyOriginInfo>>& key_origins, const bool add_keypool, const bool internal, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
410  bool ImportScriptPubKeys(const std::set<CScript>& script_pub_keys, const bool have_solving_data, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
411 
412  /* Returns true if the wallet can generate new keys */
413  bool CanGenerateKeys();
414 
415  /* Generates a new HD seed (will not be activated) */
416  CPubKey GenerateNewSeed();
417 
418  /* Derives a new HD seed (will not be activated) */
419  CPubKey DeriveNewSeed(const CKey& key);
420 
421  /* Set the current HD seed (will reset the chain child index counters)
422  Sets the seed's version based on the current wallet version (so the
423  caller must ensure the current wallet version is correct before calling
424  this function). */
425  void SetHDSeed(const CPubKey& key);
426 
433  void LearnRelatedScripts(const CPubKey& key, OutputType);
434 
439  void LearnAllRelatedScripts(const CPubKey& key);
440 
444  void MarkReserveKeysAsUsed(int64_t keypool_id) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore);
445  const std::map<CKeyID, int64_t>& GetAllReserveKeys() const { return m_pool_key_to_index; }
446 
447  std::set<CKeyID> GetKeys() const override;
448 };
449 
452 {
453 private:
455 public:
456  LegacySigningProvider(const LegacyScriptPubKeyMan& spk_man) : m_spk_man(spk_man) {}
457 
458  bool GetCScript(const CScriptID &scriptid, CScript& script) const override { return m_spk_man.GetCScript(scriptid, script); }
459  bool HaveCScript(const CScriptID &scriptid) const override { return m_spk_man.HaveCScript(scriptid); }
460  bool GetPubKey(const CKeyID &address, CPubKey& pubkey) const override { return m_spk_man.GetPubKey(address, pubkey); }
461  bool GetKey(const CKeyID &address, CKey& key) const override { return m_spk_man.GetKey(address, key); }
462  bool HaveKey(const CKeyID &address) const override { return m_spk_man.HaveKey(address); }
463  bool GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const override { return m_spk_man.GetKeyOrigin(keyid, info); }
464 };
465 
466 #endif // BITCOIN_WALLET_SCRIPTPUBKEYMAN_H
const LegacyScriptPubKeyMan & m_spk_man
virtual const CKeyingMaterial & GetEncryptionKey() const =0
bool GetCScript(const CScriptID &scriptid, CScript &script) const override
bool GetKeyOrigin(const CKeyID &keyid, KeyOriginInfo &info) const override
virtual void UnsetBlankWalletFlag(WalletBatch &)=0
virtual bool GetCScript(const CScriptID &hash, CScript &redeemScriptOut) const override
bool GetKeyOrigin(const CKeyID &keyid, KeyOriginInfo &info) const override
virtual const std::string GetDisplayName() const =0
virtual ~ScriptPubKeyMan()
bool GetPubKey(const CKeyID &address, CPubKey &pubkey) const override
bool HaveKey(const SigningProvider &wallet, const CKey &key)
Checks if a CKey is in the given CWallet compressed or otherwise.
Definition: rpcwallet.cpp:71
std::set< CScript > WatchOnlySet
An instance of this class represents one database.
Definition: db.h:111
std::vector< unsigned char, secure_allocator< unsigned char > > CKeyingMaterial
Definition: crypter.h:67
boost::signals2::signal< void()> NotifyCanGetAddressesChanged
Keypool has new keys.
virtual void RewriteDB()
The action to do when the DB needs rewrite.
static void LogPrintf(const char *fmt, const Args &... args)
Definition: logging.h:163
virtual std::unique_ptr< SigningProvider > GetSigningProvider(const CScript &script) const
virtual size_t KeypoolCountExternalKeys()
bool GetKey(const CKeyID &address, CKey &key) const override
bool HaveKey(const CKeyID &address) const override
virtual WalletDatabase & GetDatabase()=0
virtual const CKeyMetadata * GetMetadata(const CTxDestination &dest) const
std::map< CKeyID, std::pair< CPubKey, std::vector< unsigned char > >> CryptedKeyMap
boost::signals2::signal< void(bool fHaveWatchOnly)> NotifyWatchonlyChanged
Watch-only address added.
virtual bool IsWalletFlagSet(uint64_t) const =0
virtual int64_t GetTimeFirstKey() const
OutputType
Definition: outputtype.h:17
virtual bool Upgrade(int prev_version, std::string &error)
Upgrades the wallet to the specified version.
WalletFeature
(client) version numbers for particular wallet features
Definition: walletutil.h:13
const std::map< CKeyID, int64_t > & GetAllReserveKeys() const
virtual unsigned int GetKeyPoolSize() const
Access to the wallet database.
Definition: walletdb.h:175
void WalletLogPrintf(std::string fmt, Params... parameters) const
Prepends the wallet name in logging output to ease debugging in multi-wallet use cases.
virtual void KeepDestination(int64_t index, const OutputType &type)
virtual bool CanProvide(const CScript &script, SignatureData &sigdata)
Whether this ScriptPubKeyMan can provide a SigningProvider (via GetSigningProvider) that...
int64_t nTime
The time at which the key was generated. Set in AddKeypoolPubKeyWithDB.
virtual uint256 GetID() const
ScriptPubKeyMan(WalletStorage &storage)
virtual ~WalletStorage()=default
static const unsigned int DEFAULT_KEYPOOL_SIZE
Default for -keypool.
virtual bool IsHDEnabled() const
An encapsulated public key.
Definition: pubkey.h:30
std::map< CKeyID, CPubKey > WatchKeyMap
Fillable signing provider that keeps keys in an address->secret map.
virtual void MarkUnusedAddresses(const CScript &script)
Mark unused addresses as being used.
virtual bool CanGetAddresses(bool internal=false)
Wraps a LegacyScriptPubKeyMan so that it can be returned in a new unique_ptr.
LegacySigningProvider(const LegacyScriptPubKeyMan &spk_man)
virtual bool CheckDecryptionKey(const CKeyingMaterial &master_key, bool accept_no_keys=false)
Check that the given decryption key is valid for this ScriptPubKeyMan, i.e. it decrypts all of the ke...
bool m_pre_split
Whether this key was generated for a keypool before the wallet was upgraded to HD-split.
bool GetKey(const CKeyID &address, CKey &keyOut) const override
virtual int64_t GetOldestKeyPoolTime()
isminetype
IsMine() return codes.
Definition: ismine.h:18
virtual bool HavePrivateKeys() const
virtual bool IsLocked() const =0
virtual void ReturnDestination(int64_t index, bool internal, const CTxDestination &addr)
256-bit opaque blob.
Definition: uint256.h:120
CPubKey vchPubKey
The public key.
virtual bool CanSupportFeature(enum WalletFeature) const =0
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:51
An interface to be implemented by keystores that support signing.
virtual bool TopUp(unsigned int size=0)
Fills internal address pool.
const CChainParams & Params()
Return the currently selected parameters.
bool HaveKey(const CKeyID &address) const override
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:390
static bool GetPubKey(const SigningProvider &provider, const SignatureData &sigdata, const CKeyID &address, CPubKey &pubkey)
Definition: sign.cpp:52
bool HaveCScript(const CScriptID &scriptid) const override
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:20
virtual bool Encrypt(const CKeyingMaterial &master_key, WalletBatch *batch)
virtual bool HaveCScript(const CScriptID &hash) const override
virtual isminetype IsMine(const CScript &script) const
#define GUARDED_BY(x)
Definition: threadsafety.h:38
A reference to a CScript: the Hash160 of its serialization (see script.h)
Definition: standard.h:21
void SerializationOp(Stream &s, Operation ser_action)
virtual bool HasEncryptionKeys() const =0
An encapsulated private key.
Definition: key.h:27
virtual bool GetReservedDestination(const OutputType type, bool internal, CTxDestination &address, int64_t &index, CKeyPool &keypool)
WalletStorage & m_storage
boost::variant< CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessUnknown > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:143
virtual bool GetNewDestination(const OutputType type, CTxDestination &dest, std::string &error)
#define READWRITE(...)
Definition: serialize.h:186
int64_t GetTime()
Return system time (or mocked time, if set)
Definition: time.cpp:20
virtual bool SetupGeneration(bool force=false)
Sets up the key generation stuff, i.e.
virtual void SetMinVersion(enum WalletFeature, WalletBatch *=nullptr, bool=false)=0
bool GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const override
bool error(const char *fmt, const Args &... args)
Definition: system.h:49
bool fInternal
Whether this keypool entry is in the internal keypool (for change outputs)
std::vector< CKeyID > GetAffectedKeys(const CScript &spk, const SigningProvider &provider)
A key from a CWallet&#39;s keypool.