1 // Copyright (c) 2009-2010 Satoshi Nakamoto 2 // Copyright (c) 2009-2020 The Bitcoin Core developers 3 // Distributed under the MIT software license, see the accompanying 4 // file COPYING or http://www.opensource.org/licenses/mit-license.php. 5 6 #ifndef BITCOIN_SCRIPT_SIGNINGPROVIDER_H 7 #define BITCOIN_SCRIPT_SIGNINGPROVIDER_H 8 9 #include <key.h> 10 #include <pubkey.h> 11 #include <script/script.h> 12 #include <script/standard.h> 13 #include <sync.h> 14 15 struct KeyOriginInfo; 16 17 /** An interface to be implemented by keystores that support signing. */ 18 class SigningProvider 19 { 20 public: ~SigningProvider()21 virtual ~SigningProvider() {} GetCScript(const CScriptID & scriptid,CScript & script)22 virtual bool GetCScript(const CScriptID &scriptid, CScript& script) const { return false; } HaveCScript(const CScriptID & scriptid)23 virtual bool HaveCScript(const CScriptID &scriptid) const { return false; } GetPubKey(const CKeyID & address,CPubKey & pubkey)24 virtual bool GetPubKey(const CKeyID &address, CPubKey& pubkey) const { return false; } GetKey(const CKeyID & address,CKey & key)25 virtual bool GetKey(const CKeyID &address, CKey& key) const { return false; } HaveKey(const CKeyID & address)26 virtual bool HaveKey(const CKeyID &address) const { return false; } GetKeyOrigin(const CKeyID & keyid,KeyOriginInfo & info)27 virtual bool GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const { return false; } GetTaprootSpendData(const XOnlyPubKey & output_key,TaprootSpendData & spenddata)28 virtual bool GetTaprootSpendData(const XOnlyPubKey& output_key, TaprootSpendData& spenddata) const { return false; } 29 }; 30 31 extern const SigningProvider& DUMMY_SIGNING_PROVIDER; 32 33 class HidingSigningProvider : public SigningProvider 34 { 35 private: 36 const bool m_hide_secret; 37 const bool m_hide_origin; 38 const SigningProvider* m_provider; 39 40 public: HidingSigningProvider(const SigningProvider * provider,bool hide_secret,bool hide_origin)41 HidingSigningProvider(const SigningProvider* provider, bool hide_secret, bool hide_origin) : m_hide_secret(hide_secret), m_hide_origin(hide_origin), m_provider(provider) {} 42 bool GetCScript(const CScriptID& scriptid, CScript& script) const override; 43 bool GetPubKey(const CKeyID& keyid, CPubKey& pubkey) const override; 44 bool GetKey(const CKeyID& keyid, CKey& key) const override; 45 bool GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const override; 46 bool GetTaprootSpendData(const XOnlyPubKey& output_key, TaprootSpendData& spenddata) const override; 47 }; 48 49 struct FlatSigningProvider final : public SigningProvider 50 { 51 std::map<CScriptID, CScript> scripts; 52 std::map<CKeyID, CPubKey> pubkeys; 53 std::map<CKeyID, std::pair<CPubKey, KeyOriginInfo>> origins; 54 std::map<CKeyID, CKey> keys; 55 std::map<XOnlyPubKey, TaprootSpendData> tr_spenddata; /** Map from output key to spend data. */ 56 57 bool GetCScript(const CScriptID& scriptid, CScript& script) const override; 58 bool GetPubKey(const CKeyID& keyid, CPubKey& pubkey) const override; 59 bool GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const override; 60 bool GetKey(const CKeyID& keyid, CKey& key) const override; 61 bool GetTaprootSpendData(const XOnlyPubKey& output_key, TaprootSpendData& spenddata) const override; 62 }; 63 64 FlatSigningProvider Merge(const FlatSigningProvider& a, const FlatSigningProvider& b); 65 66 /** Fillable signing provider that keeps keys in an address->secret map */ 67 class FillableSigningProvider : public SigningProvider 68 { 69 protected: 70 using KeyMap = std::map<CKeyID, CKey>; 71 using ScriptMap = std::map<CScriptID, CScript>; 72 73 /** 74 * Map of key id to unencrypted private keys known by the signing provider. 75 * Map may be empty if the provider has another source of keys, like an 76 * encrypted store. 77 */ 78 KeyMap mapKeys GUARDED_BY(cs_KeyStore); 79 80 /** 81 * Map of script id to scripts known by the signing provider. 82 * 83 * This map originally just held P2SH redeemScripts, and was used by wallet 84 * code to look up script ids referenced in "OP_HASH160 <script id> 85 * OP_EQUAL" P2SH outputs. Later in 605e8473a7d it was extended to hold 86 * P2WSH witnessScripts as well, and used to look up nested scripts 87 * referenced in "OP_0 <script hash>" P2WSH outputs. Later in commits 88 * f4691ab3a9d and 248f3a76a82, it was extended once again to hold segwit 89 * "OP_0 <key or script hash>" scriptPubKeys, in order to give the wallet a 90 * way to distinguish between segwit outputs that it generated addresses for 91 * and wanted to receive payments from, and segwit outputs that it never 92 * generated addresses for, but it could spend just because of having keys. 93 * (Before segwit activation it was also important to not treat segwit 94 * outputs to arbitrary wallet keys as payments, because these could be 95 * spent by anyone without even needing to sign with the keys.) 96 * 97 * Some of the scripts stored in mapScripts are memory-only and 98 * intentionally not saved to disk. Specifically, scripts added by 99 * ImplicitlyLearnRelatedKeyScripts(pubkey) calls are not written to disk so 100 * future wallet code can have flexibility to be more selective about what 101 * transaction outputs it recognizes as payments, instead of having to treat 102 * all outputs spending to keys it knows as payments. By contrast, 103 * mapScripts entries added by AddCScript(script), 104 * LearnRelatedScripts(pubkey, type), and LearnAllRelatedScripts(pubkey) 105 * calls are saved because they are all intentionally used to receive 106 * payments. 107 * 108 * The FillableSigningProvider::mapScripts script map should not be confused 109 * with LegacyScriptPubKeyMan::setWatchOnly script set. The two collections 110 * can hold the same scripts, but they serve different purposes. The 111 * setWatchOnly script set is intended to expand the set of outputs the 112 * wallet considers payments. Every output with a script it contains is 113 * considered to belong to the wallet, regardless of whether the script is 114 * solvable or signable. By contrast, the scripts in mapScripts are only 115 * used for solving, and to restrict which outputs are considered payments 116 * by the wallet. An output with a script in mapScripts, unlike 117 * setWatchOnly, is not automatically considered to belong to the wallet if 118 * it can't be solved and signed for. 119 */ 120 ScriptMap mapScripts GUARDED_BY(cs_KeyStore); 121 122 void ImplicitlyLearnRelatedKeyScripts(const CPubKey& pubkey) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore); 123 124 public: 125 mutable RecursiveMutex cs_KeyStore; 126 127 virtual bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey); AddKey(const CKey & key)128 virtual bool AddKey(const CKey &key) { return AddKeyPubKey(key, key.GetPubKey()); } 129 virtual bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const override; 130 virtual bool HaveKey(const CKeyID &address) const override; 131 virtual std::set<CKeyID> GetKeys() const; 132 virtual bool GetKey(const CKeyID &address, CKey &keyOut) const override; 133 virtual bool AddCScript(const CScript& redeemScript); 134 virtual bool HaveCScript(const CScriptID &hash) const override; 135 virtual std::set<CScriptID> GetCScripts() const; 136 virtual bool GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const override; 137 }; 138 139 /** Return the CKeyID of the key involved in a script (if there is a unique one). */ 140 CKeyID GetKeyForDestination(const SigningProvider& store, const CTxDestination& dest); 141 142 #endif // BITCOIN_SCRIPT_SIGNINGPROVIDER_H 143