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