/tmp/bitcoin/src/script/signingprovider.h
Line | Count | Source |
1 | | // Copyright (c) 2009-2010 Satoshi Nakamoto |
2 | | // Copyright (c) 2009-present 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 <addresstype.h> |
10 | | #include <attributes.h> |
11 | | #include <key.h> |
12 | | #include <pubkey.h> |
13 | | #include <script/keyorigin.h> |
14 | | #include <script/script.h> |
15 | | #include <sync.h> |
16 | | #include <uint256.h> |
17 | | |
18 | | #include <compare> |
19 | | #include <cstdint> |
20 | | #include <functional> |
21 | | #include <map> |
22 | | #include <memory> |
23 | | #include <optional> |
24 | | #include <set> |
25 | | #include <span> |
26 | | #include <tuple> |
27 | | #include <utility> |
28 | | #include <vector> |
29 | | |
30 | | class MuSig2SecNonce; |
31 | | |
32 | | struct ShortestVectorFirstComparator |
33 | | { |
34 | | bool operator()(const std::vector<unsigned char>& a, const std::vector<unsigned char>& b) const |
35 | 9.98k | { |
36 | 9.98k | if (a.size() < b.size()) return true; |
37 | 7.05k | if (a.size() > b.size()) return false; |
38 | 5.65k | return a < b; |
39 | 7.05k | } |
40 | | }; |
41 | | |
42 | | struct TaprootSpendData |
43 | | { |
44 | | /** The BIP341 internal key. */ |
45 | | XOnlyPubKey internal_key; |
46 | | /** The Merkle root of the script tree (0 if no scripts). */ |
47 | | uint256 merkle_root; |
48 | | /** Map from (script, leaf_version) to (sets of) control blocks. |
49 | | * More than one control block for a given script is only possible if it |
50 | | * appears in multiple branches of the tree. We keep them all so that |
51 | | * inference can reconstruct the full tree. Within each set, the control |
52 | | * blocks are sorted by size, so that the signing logic can easily |
53 | | * prefer the cheapest one. */ |
54 | | std::map<std::pair<std::vector<unsigned char>, int>, std::set<std::vector<unsigned char>, ShortestVectorFirstComparator>> scripts; |
55 | | /** Merge other TaprootSpendData (for the same scriptPubKey) into this. */ |
56 | | void Merge(TaprootSpendData other); |
57 | | }; |
58 | | |
59 | | /** Utility class to construct Taproot outputs from internal key and script tree. */ |
60 | | class TaprootBuilder |
61 | | { |
62 | | private: |
63 | | /** Information about a tracked leaf in the Merkle tree. */ |
64 | | struct LeafInfo |
65 | | { |
66 | | std::vector<unsigned char> script; //!< The script. |
67 | | int leaf_version; //!< The leaf version for that script. |
68 | | std::vector<uint256> merkle_branch; //!< The hashing partners above this leaf. |
69 | | }; |
70 | | |
71 | | /** Information associated with a node in the Merkle tree. */ |
72 | | struct NodeInfo |
73 | | { |
74 | | /** Merkle hash of this node. */ |
75 | | uint256 hash; |
76 | | /** Tracked leaves underneath this node (either from the node itself, or its children). |
77 | | * The merkle_branch field of each is the partners to get to *this* node. */ |
78 | | std::vector<LeafInfo> leaves; |
79 | | }; |
80 | | /** Whether the builder is in a valid state so far. */ |
81 | | bool m_valid = true; |
82 | | |
83 | | /** The current state of the builder. |
84 | | * |
85 | | * For each level in the tree, one NodeInfo object may be present. m_branch[0] |
86 | | * is information about the root; further values are for deeper subtrees being |
87 | | * explored. |
88 | | * |
89 | | * For every right branch taken to reach the position we're currently |
90 | | * working in, there will be a (non-nullopt) entry in m_branch corresponding |
91 | | * to the left branch at that level. |
92 | | * |
93 | | * For example, imagine this tree: - N0 - |
94 | | * / \ |
95 | | * N1 N2 |
96 | | * / \ / \ |
97 | | * A B C N3 |
98 | | * / \ |
99 | | * D E |
100 | | * |
101 | | * Initially, m_branch is empty. After processing leaf A, it would become |
102 | | * {nullopt, nullopt, A}. When processing leaf B, an entry at level 2 already |
103 | | * exists, and it would thus be combined with it to produce a level 1 one, |
104 | | * resulting in {nullopt, N1}. Adding C and D takes us to {nullopt, N1, C} |
105 | | * and {nullopt, N1, C, D} respectively. When E is processed, it is combined |
106 | | * with D, and then C, and then N1, to produce the root, resulting in {N0}. |
107 | | * |
108 | | * This structure allows processing with just O(log n) overhead if the leaves |
109 | | * are computed on the fly. |
110 | | * |
111 | | * As an invariant, there can never be nullopt entries at the end. There can |
112 | | * also not be more than 128 entries (as that would mean more than 128 levels |
113 | | * in the tree). The depth of newly added entries will always be at least |
114 | | * equal to the current size of m_branch (otherwise it does not correspond |
115 | | * to a depth-first traversal of a tree). m_branch is only empty if no entries |
116 | | * have ever be processed. m_branch having length 1 corresponds to being done. |
117 | | */ |
118 | | std::vector<std::optional<NodeInfo>> m_branch; |
119 | | |
120 | | XOnlyPubKey m_internal_key; //!< The internal key, set when finalizing. |
121 | | XOnlyPubKey m_output_key; //!< The output key, computed when finalizing. |
122 | | bool m_parity; //!< The tweak parity, computed when finalizing. |
123 | | |
124 | | /** Combine information about a parent Merkle tree node from its child nodes. */ |
125 | | static NodeInfo Combine(NodeInfo&& a, NodeInfo&& b); |
126 | | /** Insert information about a node at a certain depth, and propagate information up. */ |
127 | | void Insert(NodeInfo&& node, int depth); |
128 | | |
129 | | public: |
130 | | /** Add a new script at a certain depth in the tree. Add() operations must be called |
131 | | * in depth-first traversal order of binary tree. If track is true, it will be included in |
132 | | * the GetSpendData() output. */ |
133 | | TaprootBuilder& Add(int depth, std::span<const unsigned char> script, int leaf_version, bool track = true); |
134 | | /** Like Add(), but for a Merkle node with a given hash to the tree. */ |
135 | | TaprootBuilder& AddOmitted(int depth, const uint256& hash); |
136 | | /** Finalize the construction. Can only be called when IsComplete() is true. |
137 | | internal_key.IsFullyValid() must be true. */ |
138 | | TaprootBuilder& Finalize(const XOnlyPubKey& internal_key); |
139 | | |
140 | | /** Return true if so far all input was valid. */ |
141 | 41.1k | bool IsValid() const { return m_valid; } |
142 | | /** Return whether there were either no leaves, or the leaves form a Huffman tree. */ |
143 | 293k | bool IsComplete() const { return m_valid && (m_branch.size() == 0 || (m_branch.size() == 1 && m_branch[0].has_value())); } |
144 | | /** Compute scriptPubKey (after Finalize()). */ |
145 | | WitnessV1Taproot GetOutput(); |
146 | | /** Check if a list of depths is legal (will lead to IsComplete()). */ |
147 | | static bool ValidDepths(const std::vector<int>& depths); |
148 | | /** Compute spending data (after Finalize()). */ |
149 | | TaprootSpendData GetSpendData() const; |
150 | | /** Returns a vector of tuples representing the depth, leaf version, and script */ |
151 | | std::vector<std::tuple<uint8_t, uint8_t, std::vector<unsigned char>>> GetTreeTuples() const; |
152 | | /** Returns true if there are any tapscripts */ |
153 | 283 | bool HasScripts() const { return !m_branch.empty(); } |
154 | | |
155 | 0 | bool operator==(const TaprootBuilder& other) const { return GetTreeTuples() == other.GetTreeTuples(); } |
156 | | }; |
157 | | |
158 | | /** Given a TaprootSpendData and the output key, reconstruct its script tree. |
159 | | * |
160 | | * If the output doesn't match the spenddata, or if the data in spenddata is incomplete, |
161 | | * std::nullopt is returned. Otherwise, a vector of (depth, script, leaf_ver) tuples is |
162 | | * returned, corresponding to a depth-first traversal of the script tree. |
163 | | */ |
164 | | std::optional<std::vector<std::tuple<int, std::vector<unsigned char>, int>>> InferTaprootTree(const TaprootSpendData& spenddata, const XOnlyPubKey& output); |
165 | | |
166 | | /** An interface to be implemented by keystores that support signing. */ |
167 | | class SigningProvider |
168 | | { |
169 | | public: |
170 | 2.20M | virtual ~SigningProvider() = default; |
171 | 649 | virtual bool GetCScript(const CScriptID &scriptid, CScript& script) const { return false; } |
172 | 0 | virtual bool HaveCScript(const CScriptID &scriptid) const { return false; } |
173 | 2.01k | virtual bool GetPubKey(const CKeyID &address, CPubKey& pubkey) const { return false; } |
174 | 21.4k | virtual bool GetKey(const CKeyID &address, CKey& key) const { return false; } |
175 | 0 | virtual bool HaveKey(const CKeyID &address) const { return false; } |
176 | 55.5k | virtual bool GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const { return false; } |
177 | 14.1k | virtual bool GetTaprootSpendData(const XOnlyPubKey& output_key, TaprootSpendData& spenddata) const { return false; } |
178 | 331 | virtual bool GetTaprootBuilder(const XOnlyPubKey& output_key, TaprootBuilder& builder) const { return false; } |
179 | 0 | virtual std::vector<CPubKey> GetMuSig2ParticipantPubkeys(const CPubKey& pubkey) const { return {}; } |
180 | 331 | virtual std::map<CPubKey, std::vector<CPubKey>> GetAllMuSig2ParticipantPubkeys() const {return {}; } |
181 | 0 | virtual void SetMuSig2SecNonce(const uint256& id, MuSig2SecNonce&& nonce) const {} |
182 | 0 | virtual std::optional<std::reference_wrapper<MuSig2SecNonce>> GetMuSig2SecNonce(const uint256& session_id) const { return std::nullopt; } |
183 | 0 | virtual void DeleteMuSig2Session(const uint256& session_id) const {} |
184 | | |
185 | | bool GetKeyByXOnly(const XOnlyPubKey& pubkey, CKey& key) const |
186 | 154k | { |
187 | 308k | for (const auto& id : pubkey.GetKeyIDs()) { |
188 | 308k | if (GetKey(id, key)) return true; |
189 | 308k | } |
190 | 153k | return false; |
191 | 154k | } |
192 | | |
193 | | bool GetPubKeyByXOnly(const XOnlyPubKey& pubkey, CPubKey& out) const |
194 | 53 | { |
195 | 80 | for (const auto& id : pubkey.GetKeyIDs()) { |
196 | 80 | if (GetPubKey(id, out)) return true; |
197 | 80 | } |
198 | 0 | return false; |
199 | 53 | } |
200 | | |
201 | | bool GetKeyOriginByXOnly(const XOnlyPubKey& pubkey, KeyOriginInfo& info) const |
202 | 239k | { |
203 | 319k | for (const auto& id : pubkey.GetKeyIDs()) { |
204 | 319k | if (GetKeyOrigin(id, info)) return true; |
205 | 319k | } |
206 | 74.8k | return false; |
207 | 239k | } |
208 | | }; |
209 | | |
210 | | extern const SigningProvider& DUMMY_SIGNING_PROVIDER; |
211 | | |
212 | | class HidingSigningProvider : public SigningProvider |
213 | | { |
214 | | private: |
215 | | const bool m_hide_secret; |
216 | | const bool m_hide_origin; |
217 | | const SigningProvider* m_provider; |
218 | | |
219 | | public: |
220 | 25.6k | HidingSigningProvider(const SigningProvider* provider, bool hide_secret, bool hide_origin) : m_hide_secret(hide_secret), m_hide_origin(hide_origin), m_provider(provider) {} |
221 | | bool GetCScript(const CScriptID& scriptid, CScript& script) const override; |
222 | | bool GetPubKey(const CKeyID& keyid, CPubKey& pubkey) const override; |
223 | | bool GetKey(const CKeyID& keyid, CKey& key) const override; |
224 | | bool GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const override; |
225 | | bool GetTaprootSpendData(const XOnlyPubKey& output_key, TaprootSpendData& spenddata) const override; |
226 | | bool GetTaprootBuilder(const XOnlyPubKey& output_key, TaprootBuilder& builder) const override; |
227 | | std::vector<CPubKey> GetMuSig2ParticipantPubkeys(const CPubKey& pubkey) const override; |
228 | | std::map<CPubKey, std::vector<CPubKey>> GetAllMuSig2ParticipantPubkeys() const override; |
229 | | void SetMuSig2SecNonce(const uint256& id, MuSig2SecNonce&& nonce) const override; |
230 | | std::optional<std::reference_wrapper<MuSig2SecNonce>> GetMuSig2SecNonce(const uint256& session_id) const override; |
231 | | void DeleteMuSig2Session(const uint256& session_id) const override; |
232 | | }; |
233 | | |
234 | | struct FlatSigningProvider final : public SigningProvider |
235 | | { |
236 | | std::map<CScriptID, CScript> scripts; |
237 | | std::map<CKeyID, CPubKey> pubkeys; |
238 | | std::map<CKeyID, std::pair<CPubKey, KeyOriginInfo>> origins; |
239 | | std::map<CKeyID, CKey> keys; |
240 | | std::map<XOnlyPubKey, TaprootBuilder> tr_trees; /** Map from output key to Taproot tree (which can then make the TaprootSpendData */ |
241 | | std::map<CPubKey, std::vector<CPubKey>> aggregate_pubkeys; /** MuSig2 aggregate pubkeys */ |
242 | | std::map<uint256, MuSig2SecNonce>* musig2_secnonces{nullptr}; |
243 | | |
244 | | bool GetCScript(const CScriptID& scriptid, CScript& script) const override; |
245 | | bool GetPubKey(const CKeyID& keyid, CPubKey& pubkey) const override; |
246 | | bool GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const override; |
247 | | bool HaveKey(const CKeyID &keyid) const override; |
248 | | bool GetKey(const CKeyID& keyid, CKey& key) const override; |
249 | | bool GetTaprootSpendData(const XOnlyPubKey& output_key, TaprootSpendData& spenddata) const override; |
250 | | bool GetTaprootBuilder(const XOnlyPubKey& output_key, TaprootBuilder& builder) const override; |
251 | | std::vector<CPubKey> GetMuSig2ParticipantPubkeys(const CPubKey& pubkey) const override; |
252 | | std::map<CPubKey, std::vector<CPubKey>> GetAllMuSig2ParticipantPubkeys() const override; |
253 | | void SetMuSig2SecNonce(const uint256& id, MuSig2SecNonce&& nonce) const override; |
254 | | std::optional<std::reference_wrapper<MuSig2SecNonce>> GetMuSig2SecNonce(const uint256& session_id) const override; |
255 | | void DeleteMuSig2Session(const uint256& session_id) const override; |
256 | | |
257 | | FlatSigningProvider& Merge(FlatSigningProvider&& b) LIFETIMEBOUND; |
258 | | }; |
259 | | |
260 | | /** Fillable signing provider that keeps keys in an address->secret map */ |
261 | | class FillableSigningProvider : public SigningProvider |
262 | | { |
263 | | protected: |
264 | | using KeyMap = std::map<CKeyID, CKey>; |
265 | | using ScriptMap = std::map<CScriptID, CScript>; |
266 | | |
267 | | /** |
268 | | * Map of key id to unencrypted private keys known by the signing provider. |
269 | | * Map may be empty if the provider has another source of keys, like an |
270 | | * encrypted store. |
271 | | */ |
272 | | KeyMap mapKeys GUARDED_BY(cs_KeyStore); |
273 | | |
274 | | /** |
275 | | * Map of script id to scripts known by the signing provider. |
276 | | * |
277 | | * This map originally just held P2SH redeemScripts, and was used by wallet |
278 | | * code to look up script ids referenced in "OP_HASH160 <script id> |
279 | | * OP_EQUAL" P2SH outputs. Later in 605e8473a7d it was extended to hold |
280 | | * P2WSH witnessScripts as well, and used to look up nested scripts |
281 | | * referenced in "OP_0 <script hash>" P2WSH outputs. Later in commits |
282 | | * f4691ab3a9d and 248f3a76a82, it was extended once again to hold segwit |
283 | | * "OP_0 <key or script hash>" scriptPubKeys, in order to give the wallet a |
284 | | * way to distinguish between segwit outputs that it generated addresses for |
285 | | * and wanted to receive payments from, and segwit outputs that it never |
286 | | * generated addresses for, but it could spend just because of having keys. |
287 | | * (Before segwit activation it was also important to not treat segwit |
288 | | * outputs to arbitrary wallet keys as payments, because these could be |
289 | | * spent by anyone without even needing to sign with the keys.) |
290 | | * |
291 | | * Some of the scripts stored in mapScripts are memory-only and |
292 | | * intentionally not saved to disk. Specifically, scripts added by |
293 | | * ImplicitlyLearnRelatedKeyScripts(pubkey) calls are not written to disk so |
294 | | * future wallet code can have flexibility to be more selective about what |
295 | | * transaction outputs it recognizes as payments, instead of having to treat |
296 | | * all outputs spending to keys it knows as payments. By contrast, |
297 | | * mapScripts entries added by AddCScript(script), |
298 | | * LearnRelatedScripts(pubkey, type), and LearnAllRelatedScripts(pubkey) |
299 | | * calls are saved because they are all intentionally used to receive |
300 | | * payments. |
301 | | * |
302 | | * The FillableSigningProvider::mapScripts script map should not be confused |
303 | | * with the wallet::LegacyDataSPKM::setWatchOnly script set. The two collections |
304 | | * can hold the same scripts, but they serve different purposes. The |
305 | | * setWatchOnly script set is intended to expand the set of outputs the |
306 | | * wallet considers payments. Every output with a script it contains is |
307 | | * considered to belong to the wallet, regardless of whether the script is |
308 | | * solvable or signable. By contrast, the scripts in mapScripts are only |
309 | | * used for solving, and to restrict which outputs are considered payments |
310 | | * by the wallet. An output with a script in mapScripts, unlike |
311 | | * setWatchOnly, is not automatically considered to belong to the wallet if |
312 | | * it can't be solved and signed for. |
313 | | */ |
314 | | ScriptMap mapScripts GUARDED_BY(cs_KeyStore); |
315 | | |
316 | | void ImplicitlyLearnRelatedKeyScripts(const CPubKey& pubkey) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore); |
317 | | |
318 | | public: |
319 | | mutable RecursiveMutex cs_KeyStore; |
320 | | |
321 | | virtual bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey); |
322 | 174 | virtual bool AddKey(const CKey &key) { return AddKeyPubKey(key, key.GetPubKey()); } |
323 | | virtual bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const override; |
324 | | virtual bool HaveKey(const CKeyID &address) const override; |
325 | | virtual std::set<CKeyID> GetKeys() const; |
326 | | virtual bool GetKey(const CKeyID &address, CKey &keyOut) const override; |
327 | | virtual bool AddCScript(const CScript& redeemScript); |
328 | | virtual bool HaveCScript(const CScriptID &hash) const override; |
329 | | virtual std::set<CScriptID> GetCScripts() const; |
330 | | virtual bool GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const override; |
331 | | }; |
332 | | |
333 | | /** Return the CKeyID of the key involved in a script (if there is a unique one). */ |
334 | | CKeyID GetKeyForDestination(const SigningProvider& store, const CTxDestination& dest); |
335 | | |
336 | | /** A signing provider to be used to interface with multiple signing providers at once. */ |
337 | | class MultiSigningProvider: public SigningProvider { |
338 | | std::vector<std::unique_ptr<SigningProvider>> m_providers; |
339 | | |
340 | | public: |
341 | | void AddProvider(std::unique_ptr<SigningProvider> provider); |
342 | | |
343 | | bool GetCScript(const CScriptID& scriptid, CScript& script) const override; |
344 | | bool GetPubKey(const CKeyID& keyid, CPubKey& pubkey) const override; |
345 | | bool GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const override; |
346 | | bool GetKey(const CKeyID& keyid, CKey& key) const override; |
347 | | bool GetTaprootSpendData(const XOnlyPubKey& output_key, TaprootSpendData& spenddata) const override; |
348 | | bool GetTaprootBuilder(const XOnlyPubKey& output_key, TaprootBuilder& builder) const override; |
349 | | }; |
350 | | |
351 | | #endif // BITCOIN_SCRIPT_SIGNINGPROVIDER_H |