]>
Commit | Line | Data |
---|---|---|
b2120e22 | 1 | // Copyright (c) 2009-2010 Satoshi Nakamoto |
f914f1a7 | 2 | // Copyright (c) 2009-2014 The Bitcoin Core developers |
5b40d886 | 3 | // Distributed under the MIT software license, see the accompanying |
3a25a2b9 | 4 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. |
093303a8 | 5 | |
a21df620 PK |
6 | #ifndef BITCOIN_WALLET_WALLET_H |
7 | #define BITCOIN_WALLET_WALLET_H | |
e8ef3da7 | 8 | |
eda37330 | 9 | #include "amount.h" |
be74c80d | 10 | #include "coins.h" |
e8ef3da7 | 11 | #include "key.h" |
2a45a494 | 12 | #include "keystore.h" |
57e6ecda | 13 | #include "main.h" |
26c16d9d JT |
14 | #include "primitives/block.h" |
15 | #include "primitives/transaction.h" | |
8a893c94 | 16 | #include "tinyformat.h" |
ab1b288f | 17 | #include "ui_interface.h" |
82c2d97c | 18 | #include "util.h" |
8a893c94 | 19 | #include "utilstrencodings.h" |
26c16d9d | 20 | #include "validationinterface.h" |
a354a59f | 21 | #include "wallet/crypter.h" |
50c72f23 JS |
22 | #include "wallet/wallet_ismine.h" |
23 | #include "wallet/walletdb.h" | |
34aca1b0 | 24 | #include "wallet/rpcwallet.h" |
c1c45943 S |
25 | #include "zcash/Address.hpp" |
26 | #include "base58.h" | |
51ed9ec9 BD |
27 | |
28 | #include <algorithm> | |
29 | #include <map> | |
30 | #include <set> | |
31 | #include <stdexcept> | |
32 | #include <stdint.h> | |
33 | #include <string> | |
34 | #include <utility> | |
35 | #include <vector> | |
e8ef3da7 | 36 | |
5b40d886 MF |
37 | /** |
38 | * Settings | |
39 | */ | |
c6cb21d1 | 40 | extern CFeeRate payTxFee; |
aa279d61 | 41 | extern CAmount maxTxFee; |
b33d1f5e | 42 | extern unsigned int nTxConfirmTarget; |
1bbca249 | 43 | extern bool bSpendZeroConfChange; |
0ed9675b | 44 | extern bool fSendFreeTransactions; |
ed3e5e46 | 45 | extern bool fPayAtLeastCustomFee; |
cd7fa8bb | 46 | |
5b40d886 | 47 | //! -paytxfee default |
a372168e | 48 | static const CAmount DEFAULT_TRANSACTION_FEE = 0; |
5b40d886 | 49 | //! -paytxfee will warn if called with a higher fee than this amount (in satoshis) per KB |
a372168e | 50 | static const CAmount nHighTransactionFeeWarning = 0.01 * COIN; |
aa279d61 GM |
51 | //! -maxtxfee default |
52 | static const CAmount DEFAULT_TRANSACTION_MAXFEE = 0.1 * COIN; | |
77ed59df | 53 | //! -txconfirmtarget default |
2457dc43 | 54 | static const unsigned int DEFAULT_TX_CONFIRM_TARGET = 2; |
aa279d61 GM |
55 | //! -maxtxfee will warn if called with a higher fee than this amount (in satoshis) |
56 | static const CAmount nHighTransactionMaxFeeWarning = 100 * nHighTransactionFeeWarning; | |
5b40d886 | 57 | //! Largest (in bytes) free transaction we're willing to create |
b33d1f5e | 58 | static const unsigned int MAX_FREE_TRANSACTION_CREATE_SIZE = 1000; |
be74c80d | 59 | //! Size of witness cache |
32a103aa JG |
60 | // Should be large enough that we can expect not to reorg beyond our cache |
61 | // unless there is some exceptional network disruption. | |
57e6ecda | 62 | static const unsigned int WITNESS_CACHE_SIZE = MAX_REORG_LENGTH + 1; |
ffeb4736 | 63 | |
8a893c94 | 64 | class CBlockIndex; |
0689f46c | 65 | class CCoinControl; |
9b0369c7 | 66 | class COutput; |
51ed9ec9 BD |
67 | class CReserveKey; |
68 | class CScript; | |
8a893c94 | 69 | class CTxMemPool; |
51ed9ec9 | 70 | class CWalletTx; |
e8ef3da7 | 71 | |
6b8de05d | 72 | /** (client) version numbers for particular wallet features */ |
439e1497 PW |
73 | enum WalletFeature |
74 | { | |
75 | FEATURE_BASE = 10500, // the earliest version new wallets supports (only useful for getinfo's clientversion output) | |
76 | ||
77 | FEATURE_WALLETCRYPT = 40000, // wallet encryption | |
78 | FEATURE_COMPRPUBKEY = 60000, // compressed public keys | |
79 | ||
80 | FEATURE_LATEST = 60000 | |
81 | }; | |
82 | ||
ed6d0b5f PW |
83 | |
84 | /** A key pool entry */ | |
85 | class CKeyPool | |
86 | { | |
87 | public: | |
51ed9ec9 | 88 | int64_t nTime; |
fd61d6f5 | 89 | CPubKey vchPubKey; |
ed6d0b5f | 90 | |
af8297c0 WL |
91 | CKeyPool(); |
92 | CKeyPool(const CPubKey& vchPubKeyIn); | |
ed6d0b5f | 93 | |
3f6540ad | 94 | ADD_SERIALIZE_METHODS; |
3d796f89 | 95 | |
84881f8c | 96 | template <typename Stream, typename Operation> |
242f1421 PW |
97 | inline void SerializationOp(Stream& s, Operation ser_action) { |
98 | int nVersion = s.GetVersion(); | |
99 | if (!(s.GetType() & SER_GETHASH)) | |
ed6d0b5f PW |
100 | READWRITE(nVersion); |
101 | READWRITE(nTime); | |
102 | READWRITE(vchPubKey); | |
3d796f89 | 103 | } |
ed6d0b5f PW |
104 | }; |
105 | ||
61885513 GA |
106 | /** Address book data */ |
107 | class CAddressBookData | |
108 | { | |
109 | public: | |
110 | std::string name; | |
a41d5fe0 | 111 | std::string purpose; |
61885513 GA |
112 | |
113 | CAddressBookData() | |
114 | { | |
a41d5fe0 | 115 | purpose = "unknown"; |
61885513 | 116 | } |
b10e1470 WL |
117 | |
118 | typedef std::map<std::string, std::string> StringMap; | |
119 | StringMap destdata; | |
61885513 GA |
120 | }; |
121 | ||
292623ad CL |
122 | struct CRecipient |
123 | { | |
124 | CScript scriptPubKey; | |
125 | CAmount nAmount; | |
126 | bool fSubtractFeeFromAmount; | |
127 | }; | |
3447cf87 CF |
128 | |
129 | typedef std::map<std::string, std::string> mapValue_t; | |
130 | ||
131 | ||
132 | static void ReadOrderPos(int64_t& nOrderPos, mapValue_t& mapValue) | |
133 | { | |
134 | if (!mapValue.count("n")) | |
135 | { | |
136 | nOrderPos = -1; // TODO: calculate elsewhere | |
137 | return; | |
138 | } | |
139 | nOrderPos = atoi64(mapValue["n"].c_str()); | |
140 | } | |
141 | ||
142 | ||
143 | static void WriteOrderPos(const int64_t& nOrderPos, mapValue_t& mapValue) | |
144 | { | |
145 | if (nOrderPos == -1) | |
146 | return; | |
147 | mapValue["n"] = i64tostr(nOrderPos); | |
148 | } | |
149 | ||
150 | struct COutputEntry | |
151 | { | |
152 | CTxDestination destination; | |
153 | CAmount amount; | |
154 | int vout; | |
155 | }; | |
156 | ||
c938fb1f | 157 | /** A note outpoint */ |
02e67455 JG |
158 | class JSOutPoint |
159 | { | |
160 | public: | |
161 | // Transaction hash | |
162 | uint256 hash; | |
163 | // Index into CTransaction.vjoinsplit | |
6c7930f6 | 164 | uint64_t js; |
02e67455 JG |
165 | // Index into JSDescription fields of length ZC_NUM_JS_OUTPUTS |
166 | uint8_t n; | |
167 | ||
168 | JSOutPoint() { SetNull(); } | |
daed9ba7 | 169 | JSOutPoint(uint256 h, uint64_t js, uint8_t n) : hash {h}, js {js}, n {n} { } |
02e67455 JG |
170 | |
171 | ADD_SERIALIZE_METHODS; | |
172 | ||
173 | template <typename Stream, typename Operation> | |
68a1a592 | 174 | inline void SerializationOp(Stream& s, Operation ser_action) { |
02e67455 JG |
175 | READWRITE(hash); |
176 | READWRITE(js); | |
177 | READWRITE(n); | |
178 | } | |
179 | ||
180 | void SetNull() { hash.SetNull(); } | |
181 | bool IsNull() const { return hash.IsNull(); } | |
182 | ||
183 | friend bool operator<(const JSOutPoint& a, const JSOutPoint& b) { | |
184 | return (a.hash < b.hash || | |
185 | (a.hash == b.hash && a.js < b.js) || | |
186 | (a.hash == b.hash && a.js == b.js && a.n < b.n)); | |
187 | } | |
188 | ||
189 | friend bool operator==(const JSOutPoint& a, const JSOutPoint& b) { | |
190 | return (a.hash == b.hash && a.js == b.js && a.n == b.n); | |
191 | } | |
192 | ||
193 | friend bool operator!=(const JSOutPoint& a, const JSOutPoint& b) { | |
194 | return !(a == b); | |
195 | } | |
196 | ||
197 | std::string ToString() const; | |
198 | }; | |
199 | ||
005f3ad1 | 200 | class SproutNoteData |
02e67455 JG |
201 | { |
202 | public: | |
e5eab182 | 203 | libzcash::SproutPaymentAddress address; |
02e67455 | 204 | |
1a62587e JG |
205 | /** |
206 | * Cached note nullifier. May not be set if the wallet was not unlocked when | |
005f3ad1 | 207 | * this was SproutNoteData was created. If not set, we always assume that the |
1a62587e JG |
208 | * note has not been spent. |
209 | * | |
210 | * It's okay to cache the nullifier in the wallet, because we are storing | |
211 | * the spending key there too, which could be used to derive this. | |
ddea44a2 JG |
212 | * If the wallet is encrypted, this means that someone with access to the |
213 | * locked wallet cannot spend notes, but can connect received notes to the | |
214 | * transactions they are spent in. This is the same security semantics as | |
215 | * for transparent addresses. | |
1a62587e JG |
216 | */ |
217 | boost::optional<uint256> nullifier; | |
02e67455 | 218 | |
be74c80d JG |
219 | /** |
220 | * Cached incremental witnesses for spendable Notes. | |
221 | * Beginning of the list is the most recent witness. | |
222 | */ | |
8ea8ef98 | 223 | std::list<SproutWitness> witnesses; |
be74c80d | 224 | |
ccfd8aae JG |
225 | /** |
226 | * Block height corresponding to the most current witness. | |
227 | * | |
57faf44e | 228 | * When we first create a SproutNoteData in CWallet::FindMySproutNotes, this is set to |
ccfd8aae JG |
229 | * -1 as a placeholder. The next time CWallet::ChainTip is called, we can |
230 | * determine what height the witness cache for this note is valid for (even | |
231 | * if no witnesses were cached), and so can set the correct value in | |
232 | * CWallet::IncrementNoteWitnesses and CWallet::DecrementNoteWitnesses. | |
233 | */ | |
b6961fc1 JG |
234 | int witnessHeight; |
235 | ||
005f3ad1 EOW |
236 | SproutNoteData() : address(), nullifier(), witnessHeight {-1} { } |
237 | SproutNoteData(libzcash::SproutPaymentAddress a) : | |
b6961fc1 | 238 | address {a}, nullifier(), witnessHeight {-1} { } |
005f3ad1 | 239 | SproutNoteData(libzcash::SproutPaymentAddress a, uint256 n) : |
b6961fc1 | 240 | address {a}, nullifier {n}, witnessHeight {-1} { } |
02e67455 JG |
241 | |
242 | ADD_SERIALIZE_METHODS; | |
243 | ||
244 | template <typename Stream, typename Operation> | |
68a1a592 | 245 | inline void SerializationOp(Stream& s, Operation ser_action) { |
02e67455 JG |
246 | READWRITE(address); |
247 | READWRITE(nullifier); | |
5abaca1a | 248 | READWRITE(witnesses); |
b6961fc1 | 249 | READWRITE(witnessHeight); |
02e67455 JG |
250 | } |
251 | ||
005f3ad1 | 252 | friend bool operator<(const SproutNoteData& a, const SproutNoteData& b) { |
02e67455 JG |
253 | return (a.address < b.address || |
254 | (a.address == b.address && a.nullifier < b.nullifier)); | |
255 | } | |
256 | ||
005f3ad1 | 257 | friend bool operator==(const SproutNoteData& a, const SproutNoteData& b) { |
02e67455 JG |
258 | return (a.address == b.address && a.nullifier == b.nullifier); |
259 | } | |
260 | ||
005f3ad1 | 261 | friend bool operator!=(const SproutNoteData& a, const SproutNoteData& b) { |
02e67455 JG |
262 | return !(a == b); |
263 | } | |
264 | }; | |
265 | ||
be43b746 EOW |
266 | class SaplingNoteData |
267 | { | |
268 | public: | |
45de2eda EOW |
269 | /** |
270 | * We initialize the hight to -1 for the same reason as we do in SproutNoteData. | |
271 | * See the comment in that class for a full description. | |
272 | */ | |
273 | SaplingNoteData() : witnessHeight {-1} { } | |
274 | ||
8ea8ef98 | 275 | std::list<SaplingWitness> witnesses; |
be43b746 EOW |
276 | int witnessHeight; |
277 | }; | |
278 | ||
005f3ad1 | 279 | typedef std::map<JSOutPoint, SproutNoteData> mapSproutNoteData_t; |
be43b746 | 280 | typedef std::map<SaplingOutPoint, SaplingNoteData> mapSaplingNoteData_t; |
02e67455 | 281 | |
cb0d208f | 282 | /** Decrypted note and its location in a transaction. */ |
5020a936 | 283 | struct CSproutNotePlaintextEntry |
a5ac2e25 S |
284 | { |
285 | JSOutPoint jsop; | |
e5eab182 | 286 | libzcash::SproutPaymentAddress address; |
5020a936 | 287 | libzcash::SproutNotePlaintext plaintext; |
a5ac2e25 S |
288 | }; |
289 | ||
d72c19a6 | 290 | /** Decrypted note, location in a transaction, and confirmation height. */ |
5020a936 | 291 | struct CUnspentSproutNotePlaintextEntry { |
d72c19a6 | 292 | JSOutPoint jsop; |
e5eab182 | 293 | libzcash::SproutPaymentAddress address; |
5020a936 | 294 | libzcash::SproutNotePlaintext plaintext; |
d72c19a6 S |
295 | int nHeight; |
296 | }; | |
a5ac2e25 | 297 | |
3447cf87 CF |
298 | /** A transaction with a merkle branch linking it to the block chain. */ |
299 | class CMerkleTx : public CTransaction | |
e8ef3da7 WL |
300 | { |
301 | private: | |
3447cf87 | 302 | int GetDepthInMainChainINTERNAL(const CBlockIndex* &pindexRet) const; |
e8ef3da7 | 303 | |
3447cf87 CF |
304 | public: |
305 | uint256 hashBlock; | |
306 | std::vector<uint256> vMerkleBranch; | |
307 | int nIndex; | |
e8ef3da7 | 308 | |
3447cf87 CF |
309 | // memory only |
310 | mutable bool fMerkleVerified; | |
0b807a41 | 311 | |
439e1497 | 312 | |
3447cf87 CF |
313 | CMerkleTx() |
314 | { | |
315 | Init(); | |
316 | } | |
203d1ae6 | 317 | |
3447cf87 CF |
318 | CMerkleTx(const CTransaction& txIn) : CTransaction(txIn) |
319 | { | |
320 | Init(); | |
321 | } | |
93a18a36 | 322 | |
3447cf87 CF |
323 | void Init() |
324 | { | |
325 | hashBlock = uint256(); | |
326 | nIndex = -1; | |
327 | fMerkleVerified = false; | |
328 | } | |
731b89b8 | 329 | |
3447cf87 CF |
330 | ADD_SERIALIZE_METHODS; |
331 | ||
332 | template <typename Stream, typename Operation> | |
242f1421 | 333 | inline void SerializationOp(Stream& s, Operation ser_action) { |
3447cf87 | 334 | READWRITE(*(CTransaction*)this); |
3447cf87 CF |
335 | READWRITE(hashBlock); |
336 | READWRITE(vMerkleBranch); | |
337 | READWRITE(nIndex); | |
338 | } | |
339 | ||
340 | int SetMerkleBranch(const CBlock& block); | |
341 | ||
342 | ||
343 | /** | |
344 | * Return depth of transaction in blockchain: | |
345 | * -1 : not in blockchain, and not in memory pool (conflicted transaction) | |
346 | * 0 : in memory pool, waiting to be included in a block | |
347 | * >=1 : this many blocks deep in the main chain | |
5b40d886 | 348 | */ |
3447cf87 CF |
349 | int GetDepthInMainChain(const CBlockIndex* &pindexRet) const; |
350 | int GetDepthInMainChain() const { const CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet); } | |
351 | bool IsInMainChain() const { const CBlockIndex *pindexRet; return GetDepthInMainChainINTERNAL(pindexRet) > 0; } | |
352 | int GetBlocksToMaturity() const; | |
353 | bool AcceptToMemoryPool(bool fLimitFree=true, bool fRejectAbsurdFee=true); | |
354 | }; | |
6cc4a62c | 355 | |
3447cf87 CF |
356 | /** |
357 | * A transaction with a bunch of additional info that only the owner cares about. | |
358 | * It includes any unrecorded transactions needed to link it back to the block chain. | |
359 | */ | |
360 | class CWalletTx : public CMerkleTx | |
361 | { | |
362 | private: | |
363 | const CWallet* pwallet; | |
e8ef3da7 | 364 | |
3447cf87 CF |
365 | public: |
366 | mapValue_t mapValue; | |
005f3ad1 | 367 | mapSproutNoteData_t mapSproutNoteData; |
be43b746 | 368 | mapSaplingNoteData_t mapSaplingNoteData; |
3447cf87 CF |
369 | std::vector<std::pair<std::string, std::string> > vOrderForm; |
370 | unsigned int fTimeReceivedIsTxTime; | |
371 | unsigned int nTimeReceived; //! time received by this node | |
372 | unsigned int nTimeSmart; | |
373 | char fFromMe; | |
374 | std::string strFromAccount; | |
375 | int64_t nOrderPos; //! position in ordered transaction list | |
0b807a41 | 376 | |
3447cf87 CF |
377 | // memory only |
378 | mutable bool fDebitCached; | |
379 | mutable bool fCreditCached; | |
380 | mutable bool fImmatureCreditCached; | |
381 | mutable bool fAvailableCreditCached; | |
382 | mutable bool fWatchDebitCached; | |
383 | mutable bool fWatchCreditCached; | |
384 | mutable bool fImmatureWatchCreditCached; | |
385 | mutable bool fAvailableWatchCreditCached; | |
386 | mutable bool fChangeCached; | |
387 | mutable CAmount nDebitCached; | |
388 | mutable CAmount nCreditCached; | |
389 | mutable CAmount nImmatureCreditCached; | |
390 | mutable CAmount nAvailableCreditCached; | |
391 | mutable CAmount nWatchDebitCached; | |
392 | mutable CAmount nWatchCreditCached; | |
393 | mutable CAmount nImmatureWatchCreditCached; | |
394 | mutable CAmount nAvailableWatchCreditCached; | |
395 | mutable CAmount nChangeCached; | |
4e87d341 | 396 | |
3447cf87 | 397 | CWalletTx() |
e8ef3da7 | 398 | { |
3447cf87 | 399 | Init(NULL); |
e8ef3da7 | 400 | } |
870da77d | 401 | |
3447cf87 | 402 | CWalletTx(const CWallet* pwalletIn) |
e8ef3da7 | 403 | { |
3447cf87 CF |
404 | Init(pwalletIn); |
405 | } | |
d04fd3e2 | 406 | |
3447cf87 CF |
407 | CWalletTx(const CWallet* pwalletIn, const CMerkleTx& txIn) : CMerkleTx(txIn) |
408 | { | |
409 | Init(pwalletIn); | |
d04fd3e2 | 410 | } |
870da77d | 411 | |
3447cf87 | 412 | CWalletTx(const CWallet* pwalletIn, const CTransaction& txIn) : CMerkleTx(txIn) |
870da77d | 413 | { |
3447cf87 | 414 | Init(pwalletIn); |
870da77d PK |
415 | } |
416 | ||
3447cf87 | 417 | void Init(const CWallet* pwalletIn) |
d04fd3e2 | 418 | { |
3447cf87 CF |
419 | pwallet = pwalletIn; |
420 | mapValue.clear(); | |
005f3ad1 | 421 | mapSproutNoteData.clear(); |
be43b746 | 422 | mapSaplingNoteData.clear(); |
3447cf87 CF |
423 | vOrderForm.clear(); |
424 | fTimeReceivedIsTxTime = false; | |
425 | nTimeReceived = 0; | |
426 | nTimeSmart = 0; | |
427 | fFromMe = false; | |
428 | strFromAccount.clear(); | |
429 | fDebitCached = false; | |
430 | fCreditCached = false; | |
431 | fImmatureCreditCached = false; | |
432 | fAvailableCreditCached = false; | |
433 | fWatchDebitCached = false; | |
434 | fWatchCreditCached = false; | |
435 | fImmatureWatchCreditCached = false; | |
436 | fAvailableWatchCreditCached = false; | |
437 | fChangeCached = false; | |
438 | nDebitCached = 0; | |
439 | nCreditCached = 0; | |
440 | nImmatureCreditCached = 0; | |
441 | nAvailableCreditCached = 0; | |
442 | nWatchDebitCached = 0; | |
443 | nWatchCreditCached = 0; | |
444 | nAvailableWatchCreditCached = 0; | |
445 | nImmatureWatchCreditCached = 0; | |
446 | nChangeCached = 0; | |
447 | nOrderPos = -1; | |
e8ef3da7 WL |
448 | } |
449 | ||
3447cf87 | 450 | ADD_SERIALIZE_METHODS; |
731b89b8 | 451 | |
3447cf87 | 452 | template <typename Stream, typename Operation> |
242f1421 | 453 | inline void SerializationOp(Stream& s, Operation ser_action) { |
3447cf87 CF |
454 | if (ser_action.ForRead()) |
455 | Init(NULL); | |
456 | char fSpent = false; | |
e8ef3da7 | 457 | |
3447cf87 CF |
458 | if (!ser_action.ForRead()) |
459 | { | |
460 | mapValue["fromaccount"] = strFromAccount; | |
e8ef3da7 | 461 | |
3447cf87 | 462 | WriteOrderPos(nOrderPos, mapValue); |
e8ef3da7 | 463 | |
3447cf87 CF |
464 | if (nTimeSmart) |
465 | mapValue["timesmart"] = strprintf("%u", nTimeSmart); | |
466 | } | |
fdbb537d | 467 | |
3447cf87 CF |
468 | READWRITE(*(CMerkleTx*)this); |
469 | std::vector<CMerkleTx> vUnused; //! Used to be vtxPrev | |
470 | READWRITE(vUnused); | |
471 | READWRITE(mapValue); | |
005f3ad1 | 472 | READWRITE(mapSproutNoteData); |
3447cf87 CF |
473 | READWRITE(vOrderForm); |
474 | READWRITE(fTimeReceivedIsTxTime); | |
475 | READWRITE(nTimeReceived); | |
476 | READWRITE(fFromMe); | |
477 | READWRITE(fSpent); | |
be43b746 EOW |
478 | // TODO: |
479 | //READWRITE(mapSaplingNoteData); | |
3869fb89 | 480 | |
3447cf87 CF |
481 | if (ser_action.ForRead()) |
482 | { | |
483 | strFromAccount = mapValue["fromaccount"]; | |
93a18a36 | 484 | |
3447cf87 | 485 | ReadOrderPos(nOrderPos, mapValue); |
439e1497 | 486 | |
3447cf87 CF |
487 | nTimeSmart = mapValue.count("timesmart") ? (unsigned int)atoi64(mapValue["timesmart"]) : 0; |
488 | } | |
95691680 | 489 | |
3447cf87 CF |
490 | mapValue.erase("fromaccount"); |
491 | mapValue.erase("version"); | |
492 | mapValue.erase("spent"); | |
493 | mapValue.erase("n"); | |
494 | mapValue.erase("timesmart"); | |
495 | } | |
93a18a36 | 496 | |
3447cf87 CF |
497 | //! make sure balances are recalculated |
498 | void MarkDirty() | |
499 | { | |
500 | fCreditCached = false; | |
501 | fAvailableCreditCached = false; | |
502 | fWatchDebitCached = false; | |
503 | fWatchCreditCached = false; | |
504 | fAvailableWatchCreditCached = false; | |
505 | fImmatureWatchCreditCached = false; | |
506 | fDebitCached = false; | |
507 | fChangeCached = false; | |
508 | } | |
509 | ||
510 | void BindWallet(CWallet *pwalletIn) | |
511 | { | |
512 | pwallet = pwalletIn; | |
513 | MarkDirty(); | |
514 | } | |
c3a7307a | 515 | |
8e8279e7 | 516 | void SetSproutNoteData(mapSproutNoteData_t ¬eData); |
e6b0a8b9 | 517 | void SetSaplingNoteData(mapSaplingNoteData_t ¬eData); |
3447cf87 CF |
518 | |
519 | //! filter decides which addresses will count towards the debit | |
520 | CAmount GetDebit(const isminefilter& filter) const; | |
521 | CAmount GetCredit(const isminefilter& filter) const; | |
522 | CAmount GetImmatureCredit(bool fUseCache=true) const; | |
523 | CAmount GetAvailableCredit(bool fUseCache=true) const; | |
524 | CAmount GetImmatureWatchOnlyCredit(const bool& fUseCache=true) const; | |
525 | CAmount GetAvailableWatchOnlyCredit(const bool& fUseCache=true) const; | |
526 | CAmount GetChange() const; | |
527 | ||
528 | void GetAmounts(std::list<COutputEntry>& listReceived, | |
529 | std::list<COutputEntry>& listSent, CAmount& nFee, std::string& strSentAccount, const isminefilter& filter) const; | |
530 | ||
531 | void GetAccountAmounts(const std::string& strAccount, CAmount& nReceived, | |
532 | CAmount& nSent, CAmount& nFee, const isminefilter& filter) const; | |
533 | ||
534 | bool IsFromMe(const isminefilter& filter) const | |
535 | { | |
536 | return (GetDebit(filter) > 0); | |
537 | } | |
538 | ||
539 | bool IsTrusted() const; | |
540 | ||
541 | bool WriteToDisk(CWalletDB *pwalletdb); | |
542 | ||
543 | int64_t GetTxTime() const; | |
544 | int GetRequestCount() const; | |
545 | ||
0f5954c4 | 546 | bool RelayWalletTransaction(); |
3447cf87 CF |
547 | |
548 | std::set<uint256> GetConflicts() const; | |
549 | }; | |
550 | ||
551 | ||
552 | ||
553 | ||
554 | class COutput | |
555 | { | |
556 | public: | |
557 | const CWalletTx *tx; | |
558 | int i; | |
559 | int nDepth; | |
560 | bool fSpendable; | |
561 | ||
562 | COutput(const CWalletTx *txIn, int iIn, int nDepthIn, bool fSpendableIn) | |
563 | { | |
564 | tx = txIn; i = iIn; nDepth = nDepthIn; fSpendable = fSpendableIn; | |
565 | } | |
566 | ||
567 | std::string ToString() const; | |
568 | }; | |
569 | ||
570 | ||
571 | ||
572 | ||
573 | /** Private key that includes an expiration date in case it never gets used. */ | |
574 | class CWalletKey | |
575 | { | |
576 | public: | |
577 | CPrivKey vchPrivKey; | |
578 | int64_t nTimeCreated; | |
579 | int64_t nTimeExpires; | |
580 | std::string strComment; | |
581 | //! todo: add something to note what created it (user, getnewaddress, change) | |
582 | //! maybe should have a map<string, string> property map | |
583 | ||
584 | CWalletKey(int64_t nExpires=0); | |
585 | ||
586 | ADD_SERIALIZE_METHODS; | |
587 | ||
588 | template <typename Stream, typename Operation> | |
242f1421 PW |
589 | inline void SerializationOp(Stream& s, Operation ser_action) { |
590 | int nVersion = s.GetVersion(); | |
591 | if (!(s.GetType() & SER_GETHASH)) | |
3447cf87 CF |
592 | READWRITE(nVersion); |
593 | READWRITE(vchPrivKey); | |
594 | READWRITE(nTimeCreated); | |
595 | READWRITE(nTimeExpires); | |
596 | READWRITE(LIMITED_STRING(strComment, 65536)); | |
597 | } | |
598 | }; | |
599 | ||
4bfe8a74 CF |
600 | /** |
601 | * Internal transfers. | |
602 | * Database key is acentry<account><counter>. | |
603 | */ | |
604 | class CAccountingEntry | |
605 | { | |
606 | public: | |
607 | std::string strAccount; | |
608 | CAmount nCreditDebit; | |
609 | int64_t nTime; | |
610 | std::string strOtherAccount; | |
611 | std::string strComment; | |
612 | mapValue_t mapValue; | |
613 | int64_t nOrderPos; //! position in ordered transaction list | |
614 | uint64_t nEntryNo; | |
615 | ||
616 | CAccountingEntry() | |
617 | { | |
618 | SetNull(); | |
619 | } | |
620 | ||
621 | void SetNull() | |
622 | { | |
623 | nCreditDebit = 0; | |
624 | nTime = 0; | |
625 | strAccount.clear(); | |
626 | strOtherAccount.clear(); | |
627 | strComment.clear(); | |
628 | nOrderPos = -1; | |
629 | nEntryNo = 0; | |
630 | } | |
631 | ||
632 | ADD_SERIALIZE_METHODS; | |
633 | ||
634 | template <typename Stream, typename Operation> | |
242f1421 PW |
635 | inline void SerializationOp(Stream& s, Operation ser_action) { |
636 | int nVersion = s.GetVersion(); | |
637 | if (!(s.GetType() & SER_GETHASH)) | |
4bfe8a74 CF |
638 | READWRITE(nVersion); |
639 | //! Note: strAccount is serialized as part of the key, not here. | |
640 | READWRITE(nCreditDebit); | |
641 | READWRITE(nTime); | |
642 | READWRITE(LIMITED_STRING(strOtherAccount, 65536)); | |
643 | ||
644 | if (!ser_action.ForRead()) | |
645 | { | |
646 | WriteOrderPos(nOrderPos, mapValue); | |
647 | ||
648 | if (!(mapValue.empty() && _ssExtra.empty())) | |
649 | { | |
242f1421 | 650 | CDataStream ss(s.GetType(), s.GetVersion()); |
4bfe8a74 CF |
651 | ss.insert(ss.begin(), '\0'); |
652 | ss << mapValue; | |
653 | ss.insert(ss.end(), _ssExtra.begin(), _ssExtra.end()); | |
654 | strComment.append(ss.str()); | |
655 | } | |
656 | } | |
657 | ||
658 | READWRITE(LIMITED_STRING(strComment, 65536)); | |
659 | ||
660 | size_t nSepPos = strComment.find("\0", 0, 1); | |
661 | if (ser_action.ForRead()) | |
662 | { | |
663 | mapValue.clear(); | |
664 | if (std::string::npos != nSepPos) | |
665 | { | |
242f1421 | 666 | CDataStream ss(std::vector<char>(strComment.begin() + nSepPos + 1, strComment.end()), s.GetType(), s.GetVersion()); |
4bfe8a74 CF |
667 | ss >> mapValue; |
668 | _ssExtra = std::vector<char>(ss.begin(), ss.end()); | |
669 | } | |
670 | ReadOrderPos(nOrderPos, mapValue); | |
671 | } | |
672 | if (std::string::npos != nSepPos) | |
673 | strComment.erase(nSepPos); | |
674 | ||
675 | mapValue.erase("n"); | |
676 | } | |
677 | ||
678 | private: | |
679 | std::vector<char> _ssExtra; | |
680 | }; | |
3447cf87 CF |
681 | |
682 | ||
683 | /** | |
684 | * A CWallet is an extension of a keystore, which also maintains a set of transactions and balances, | |
685 | * and provides the ability to create new transactions. | |
686 | */ | |
687 | class CWallet : public CCryptoKeyStore, public CValidationInterface | |
688 | { | |
689 | private: | |
2b1cda3b | 690 | bool SelectCoins(const CAmount& nTargetValue, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet, bool& fOnlyCoinbaseCoinsRet, bool& fNeedCoinbaseCoinsRet, const CCoinControl *coinControl = NULL) const; |
3447cf87 CF |
691 | |
692 | CWalletDB *pwalletdbEncryption; | |
693 | ||
694 | //! the current wallet version: clients below this version are not able to load the wallet | |
695 | int nWalletVersion; | |
696 | ||
697 | //! the maximum wallet format version: memory-only variable that specifies to what version this wallet may be upgraded | |
698 | int nWalletMaxVersion; | |
699 | ||
700 | int64_t nNextResend; | |
701 | int64_t nLastResend; | |
6f252627 | 702 | bool fBroadcastTransactions; |
3447cf87 | 703 | |
0f106047 JG |
704 | template <class T> |
705 | using TxSpendMap = std::multimap<T, uint256>; | |
3447cf87 CF |
706 | /** |
707 | * Used to keep track of spent outpoints, and | |
708 | * detect and report conflicts (double-spends or | |
709 | * mutated transactions where the mutant gets mined). | |
710 | */ | |
0f106047 | 711 | typedef TxSpendMap<COutPoint> TxSpends; |
3447cf87 | 712 | TxSpends mapTxSpends; |
0f106047 JG |
713 | /** |
714 | * Used to keep track of spent Notes, and | |
715 | * detect and report conflicts (double-spends). | |
716 | */ | |
717 | typedef TxSpendMap<uint256> TxNullifiers; | |
718 | TxNullifiers mapTxNullifiers; | |
719 | ||
3447cf87 | 720 | void AddToSpends(const COutPoint& outpoint, const uint256& wtxid); |
0f106047 | 721 | void AddToSpends(const uint256& nullifier, const uint256& wtxid); |
3447cf87 CF |
722 | void AddToSpends(const uint256& wtxid); |
723 | ||
be74c80d JG |
724 | public: |
725 | /* | |
4086e5ce JG |
726 | * Size of the incremental witness cache for the notes in our wallet. |
727 | * This will always be greater than or equal to the size of the largest | |
728 | * incremental witness cache in any transaction in mapWallet. | |
be74c80d | 729 | */ |
4086e5ce | 730 | int64_t nWitnessCacheSize; |
be74c80d | 731 | |
76b22658 JG |
732 | void ClearNoteWitnessCache(); |
733 | ||
be74c80d | 734 | protected: |
ccfd8aae JG |
735 | /** |
736 | * pindex is the new tip being connected. | |
737 | */ | |
be74c80d JG |
738 | void IncrementNoteWitnesses(const CBlockIndex* pindex, |
739 | const CBlock* pblock, | |
4fc309f0 EOW |
740 | SproutMerkleTree& sproutTree, |
741 | SaplingMerkleTree& saplingTree); | |
ccfd8aae JG |
742 | /** |
743 | * pindex is the old tip being disconnected. | |
744 | */ | |
40ef121e | 745 | void DecrementNoteWitnesses(const CBlockIndex* pindex); |
82c2d97c JG |
746 | |
747 | template <typename WalletDB> | |
03f83b9b | 748 | void SetBestChainINTERNAL(WalletDB& walletdb, const CBlockLocator& loc) { |
82c2d97c JG |
749 | if (!walletdb.TxnBegin()) { |
750 | // This needs to be done atomically, so don't do it at all | |
03f83b9b | 751 | LogPrintf("SetBestChain(): Couldn't start atomic write\n"); |
82c2d97c JG |
752 | return; |
753 | } | |
754 | try { | |
755 | for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) { | |
756 | if (!walletdb.WriteTx(wtxItem.first, wtxItem.second)) { | |
03f83b9b | 757 | LogPrintf("SetBestChain(): Failed to write CWalletTx, aborting atomic write\n"); |
82c2d97c JG |
758 | walletdb.TxnAbort(); |
759 | return; | |
760 | } | |
761 | } | |
762 | if (!walletdb.WriteWitnessCacheSize(nWitnessCacheSize)) { | |
03f83b9b JG |
763 | LogPrintf("SetBestChain(): Failed to write nWitnessCacheSize, aborting atomic write\n"); |
764 | walletdb.TxnAbort(); | |
765 | return; | |
766 | } | |
767 | if (!walletdb.WriteBestBlock(loc)) { | |
768 | LogPrintf("SetBestChain(): Failed to write best block, aborting atomic write\n"); | |
82c2d97c JG |
769 | walletdb.TxnAbort(); |
770 | return; | |
771 | } | |
772 | } catch (const std::exception &exc) { | |
773 | // Unexpected failure | |
03f83b9b | 774 | LogPrintf("SetBestChain(): Unexpected error during atomic write:\n"); |
82c2d97c JG |
775 | LogPrintf("%s\n", exc.what()); |
776 | walletdb.TxnAbort(); | |
777 | return; | |
778 | } | |
779 | if (!walletdb.TxnCommit()) { | |
780 | // Couldn't commit all to db, but in-memory state is fine | |
03f83b9b | 781 | LogPrintf("SetBestChain(): Couldn't commit atomic write\n"); |
82c2d97c JG |
782 | return; |
783 | } | |
784 | } | |
be74c80d JG |
785 | |
786 | private: | |
0f106047 JG |
787 | template <class T> |
788 | void SyncMetaData(std::pair<typename TxSpendMap<T>::iterator, typename TxSpendMap<T>::iterator>); | |
3447cf87 | 789 | |
ac1c9435 JG |
790 | protected: |
791 | bool UpdatedNoteData(const CWalletTx& wtxIn, CWalletTx& wtx); | |
792 | void MarkAffectedTransactionsDirty(const CTransaction& tx); | |
793 | ||
3447cf87 CF |
794 | public: |
795 | /* | |
796 | * Main wallet lock. | |
797 | * This lock protects all the fields added by CWallet | |
798 | * except for: | |
799 | * fFileBacked (immutable after instantiation) | |
800 | * strWalletFile (immutable after instantiation) | |
801 | */ | |
802 | mutable CCriticalSection cs_wallet; | |
803 | ||
804 | bool fFileBacked; | |
805 | std::string strWalletFile; | |
806 | ||
807 | std::set<int64_t> setKeyPool; | |
808 | std::map<CKeyID, CKeyMetadata> mapKeyMetadata; | |
e5eab182 | 809 | std::map<libzcash::SproutPaymentAddress, CKeyMetadata> mapZKeyMetadata; |
efb7662d | 810 | std::map<libzcash::SaplingPaymentAddress, CKeyMetadata> mapSaplingZKeyMetadata; |
3447cf87 CF |
811 | |
812 | typedef std::map<unsigned int, CMasterKey> MasterKeyMap; | |
813 | MasterKeyMap mapMasterKeys; | |
814 | unsigned int nMasterKeyMaxID; | |
815 | ||
816 | CWallet() | |
817 | { | |
818 | SetNull(); | |
819 | } | |
820 | ||
db954a65 | 821 | CWallet(const std::string& strWalletFileIn) |
3447cf87 CF |
822 | { |
823 | SetNull(); | |
824 | ||
825 | strWalletFile = strWalletFileIn; | |
826 | fFileBacked = true; | |
827 | } | |
828 | ||
829 | ~CWallet() | |
830 | { | |
831 | delete pwalletdbEncryption; | |
832 | pwalletdbEncryption = NULL; | |
833 | } | |
834 | ||
835 | void SetNull() | |
836 | { | |
837 | nWalletVersion = FEATURE_BASE; | |
838 | nWalletMaxVersion = FEATURE_BASE; | |
839 | fFileBacked = false; | |
840 | nMasterKeyMaxID = 0; | |
841 | pwalletdbEncryption = NULL; | |
842 | nOrderPosNext = 0; | |
843 | nNextResend = 0; | |
844 | nLastResend = 0; | |
845 | nTimeFirstKey = 0; | |
6f252627 | 846 | fBroadcastTransactions = false; |
f7d78fdd | 847 | nWitnessCacheSize = 0; |
3447cf87 CF |
848 | } |
849 | ||
1a62587e JG |
850 | /** |
851 | * The reverse mapping of nullifiers to notes. | |
852 | * | |
853 | * The mapping cannot be updated while an encrypted wallet is locked, | |
854 | * because we need the SpendingKey to create the nullifier (#1502). This has | |
855 | * several implications for transactions added to the wallet while locked: | |
856 | * | |
857 | * - Parent transactions can't be marked dirty when a child transaction that | |
858 | * spends their output notes is updated. | |
859 | * | |
860 | * - We currently don't cache any note values, so this is not a problem, | |
861 | * yet. | |
862 | * | |
863 | * - GetFilteredNotes can't filter out spent notes. | |
864 | * | |
005f3ad1 | 865 | * - Per the comment in SproutNoteData, we assume that if we don't have a |
1a62587e JG |
866 | * cached nullifier, the note is not spent. |
867 | * | |
868 | * Another more problematic implication is that the wallet can fail to | |
869 | * detect transactions on the blockchain that spend our notes. There are two | |
870 | * possible cases in which this could happen: | |
871 | * | |
872 | * - We receive a note when the wallet is locked, and then spend it using a | |
873 | * different wallet client. | |
874 | * | |
875 | * - We spend from a PaymentAddress we control, then we export the | |
876 | * SpendingKey and import it into a new wallet, and reindex/rescan to find | |
877 | * the old transactions. | |
878 | * | |
879 | * The wallet will only miss "pure" spends - transactions that are only | |
880 | * linked to us by the fact that they contain notes we spent. If it also | |
881 | * sends notes to us, or interacts with our transparent addresses, we will | |
882 | * detect the transaction and add it to the wallet (again without caching | |
883 | * nullifiers for new notes). As by default JoinSplits send change back to | |
884 | * the origin PaymentAddress, the wallet should rarely miss transactions. | |
885 | * | |
886 | * To work around these issues, whenever the wallet is unlocked, we scan all | |
887 | * cached notes, and cache any missing nullifiers. Since the wallet must be | |
888 | * unlocked in order to spend notes, this means that GetFilteredNotes will | |
889 | * always behave correctly within that context (and any other uses will give | |
890 | * correct responses afterwards), for the transactions that the wallet was | |
891 | * able to detect. Any missing transactions can be rediscovered by: | |
892 | * | |
893 | * - Unlocking the wallet (to fill all nullifier caches). | |
894 | * | |
895 | * - Restarting the node with -reindex (which operates on a locked wallet | |
896 | * but with the now-cached nullifiers). | |
1a62587e | 897 | */ |
ad20f214 | 898 | std::map<uint256, JSOutPoint> mapNullifiersToNotes; |
1a62587e | 899 | |
3447cf87 CF |
900 | std::map<uint256, CWalletTx> mapWallet; |
901 | ||
902 | int64_t nOrderPosNext; | |
903 | std::map<uint256, int> mapRequestCount; | |
904 | ||
905 | std::map<CTxDestination, CAddressBookData> mapAddressBook; | |
906 | ||
907 | CPubKey vchDefaultKey; | |
908 | ||
909 | std::set<COutPoint> setLockedCoins; | |
4e6400bc | 910 | std::set<JSOutPoint> setLockedNotes; |
3447cf87 CF |
911 | |
912 | int64_t nTimeFirstKey; | |
913 | ||
914 | const CWalletTx* GetWalletTx(const uint256& hash) const; | |
915 | ||
916 | //! check whether we are allowed to upgrade (or already support) to the named feature | |
917 | bool CanSupportFeature(enum WalletFeature wf) { AssertLockHeld(cs_wallet); return nWalletMaxVersion >= wf; } | |
918 | ||
2b1cda3b | 919 | void AvailableCoins(std::vector<COutput>& vCoins, bool fOnlyConfirmed=true, const CCoinControl *coinControl = NULL, bool fIncludeZeroValue=false, bool fIncludeCoinBase=true) const; |
3447cf87 CF |
920 | bool SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, std::vector<COutput> vCoins, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet) const; |
921 | ||
922 | bool IsSpent(const uint256& hash, unsigned int n) const; | |
0f106047 | 923 | bool IsSpent(const uint256& nullifier) const; |
3447cf87 CF |
924 | |
925 | bool IsLockedCoin(uint256 hash, unsigned int n) const; | |
fdbb537d JG |
926 | void LockCoin(COutPoint& output); |
927 | void UnlockCoin(COutPoint& output); | |
928 | void UnlockAllCoins(); | |
929 | void ListLockedCoins(std::vector<COutPoint>& vOutpts); | |
9b0369c7 | 930 | |
4e6400bc | 931 | |
e935beb8 JG |
932 | bool IsLockedNote(const JSOutPoint& outpt) const; |
933 | void LockNote(const JSOutPoint& output); | |
934 | void UnlockNote(const JSOutPoint& output); | |
4e6400bc BM |
935 | void UnlockAllNotes(); |
936 | std::vector<JSOutPoint> ListLockedNotes(); | |
937 | ||
938 | ||
5b40d886 MF |
939 | /** |
940 | * keystore implementation | |
941 | * Generate a new key | |
942 | */ | |
fd61d6f5 | 943 | CPubKey GenerateNewKey(); |
5b40d886 | 944 | //! Adds a key to the store, and saves it to disk. |
4addb2c0 | 945 | bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey); |
5b40d886 | 946 | //! Adds a key to the store, without saving it to disk (used by LoadWallet) |
dfa23b94 | 947 | bool LoadKey(const CKey& key, const CPubKey &pubkey) { return CCryptoKeyStore::AddKeyPubKey(key, pubkey); } |
5b40d886 | 948 | //! Load metadata (used by LoadWallet) |
4addb2c0 | 949 | bool LoadKeyMetadata(const CPubKey &pubkey, const CKeyMetadata &metadata); |
d825e6a3 | 950 | |
95691680 | 951 | bool LoadMinVersion(int nVersion) { AssertLockHeld(cs_wallet); nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; } |
0b807a41 | 952 | |
5b40d886 | 953 | //! Adds an encrypted key to the store, and saves it to disk. |
4addb2c0 | 954 | bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret); |
5b40d886 | 955 | //! Adds an encrypted key to the store, without saving it to disk (used by LoadWallet) |
2f15e86a | 956 | bool LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret); |
922e8e29 | 957 | bool AddCScript(const CScript& redeemScript); |
18116b06 | 958 | bool LoadCScript(const CScript& redeemScript); |
4e87d341 | 959 | |
5b40d886 | 960 | //! Adds a destination data tuple to the store, and saves it to disk |
b10e1470 | 961 | bool AddDestData(const CTxDestination &dest, const std::string &key, const std::string &value); |
5b40d886 | 962 | //! Erases a destination data tuple in the store and on disk |
b10e1470 | 963 | bool EraseDestData(const CTxDestination &dest, const std::string &key); |
5b40d886 | 964 | //! Adds a destination data tuple to the store, without saving it to disk |
b10e1470 | 965 | bool LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value); |
5b40d886 | 966 | //! Look up a destination data tuple in the store, return true if found false otherwise |
b10e1470 WL |
967 | bool GetDestData(const CTxDestination &dest, const std::string &key, std::string *value) const; |
968 | ||
5b40d886 | 969 | //! Adds a watch-only address to the store, and saves it to disk. |
d5087d1b | 970 | bool AddWatchOnly(const CScript &dest); |
ccca27a7 | 971 | bool RemoveWatchOnly(const CScript &dest); |
5b40d886 | 972 | //! Adds a watch-only address to the store, without saving it to disk (used by LoadWallet) |
d5087d1b | 973 | bool LoadWatchOnly(const CScript &dest); |
c8988460 | 974 | |
94f778bd DN |
975 | bool Unlock(const SecureString& strWalletPassphrase); |
976 | bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase); | |
977 | bool EncryptWallet(const SecureString& strWalletPassphrase); | |
acd65016 | 978 | |
51ed9ec9 | 979 | void GetKeyBirthTimes(std::map<CKeyID, int64_t> &mapKeyBirth) const; |
434e4273 | 980 | |
c1c45943 S |
981 | /** |
982 | * ZKeys | |
983 | */ | |
984 | //! Generates a new zaddr | |
80ed13d5 | 985 | libzcash::PaymentAddress GenerateNewZKey(); |
c1c45943 | 986 | //! Adds spending key to the store, and saves it to disk |
e5eab182 | 987 | bool AddZKey(const libzcash::SproutSpendingKey &key); |
c1c45943 | 988 | //! Adds spending key to the store, without saving it to disk (used by LoadWallet) |
e5eab182 | 989 | bool LoadZKey(const libzcash::SproutSpendingKey &key); |
c1c45943 | 990 | //! Load spending key metadata (used by LoadWallet) |
e5eab182 | 991 | bool LoadZKeyMetadata(const libzcash::SproutPaymentAddress &addr, const CKeyMetadata &meta); |
73699cea | 992 | //! Adds an encrypted spending key to the store, without saving it to disk (used by LoadWallet) |
e5eab182 | 993 | bool LoadCryptedZKey(const libzcash::SproutPaymentAddress &addr, const libzcash::ReceivingKey &rk, const std::vector<unsigned char> &vchCryptedSecret); |
73699cea | 994 | //! Adds an encrypted spending key to the store, and saves it to disk (virtual method, declared in crypter.h) |
25d5e80c JG |
995 | bool AddCryptedSproutSpendingKey( |
996 | const libzcash::SproutPaymentAddress &address, | |
997 | const libzcash::ReceivingKey &rk, | |
998 | const std::vector<unsigned char> &vchCryptedSecret); | |
c1c45943 | 999 | |
4c775177 JG |
1000 | //! Adds a Sprout viewing key to the store, and saves it to disk. |
1001 | bool AddSproutViewingKey(const libzcash::SproutViewingKey &vk); | |
1002 | bool RemoveSproutViewingKey(const libzcash::SproutViewingKey &vk); | |
1003 | //! Adds a Sprout viewing key to the store, without saving it to disk (used by LoadWallet) | |
1004 | bool LoadSproutViewingKey(const libzcash::SproutViewingKey &dest); | |
bc6344b3 | 1005 | |
efb7662d JG |
1006 | /** |
1007 | * Sapling ZKeys | |
1008 | */ | |
1009 | //! Generates new Sapling key | |
1010 | libzcash::SaplingPaymentAddress GenerateNewSaplingZKey(); | |
1011 | //! Adds Sapling spending key to the store, and saves it to disk | |
5175a7f0 JG |
1012 | bool AddSaplingZKey( |
1013 | const libzcash::SaplingSpendingKey &key, | |
1014 | const boost::optional<libzcash::SaplingPaymentAddress> &defaultAddr = boost::none); | |
1015 | bool AddCryptedSaplingSpendingKey( | |
1016 | const libzcash::SaplingFullViewingKey &fvk, | |
1017 | const std::vector<unsigned char> &vchCryptedSecret, | |
1018 | const boost::optional<libzcash::SaplingPaymentAddress> &defaultAddr = boost::none); | |
167cd333 | 1019 | |
5b40d886 MF |
1020 | /** |
1021 | * Increment the next transaction order id | |
1022 | * @return next transaction order id | |
da7b8c12 | 1023 | */ |
51ed9ec9 | 1024 | int64_t IncOrderPosNext(CWalletDB *pwalletdb = NULL); |
da7b8c12 | 1025 | |
c3f95ef1 | 1026 | typedef std::pair<CWalletTx*, CAccountingEntry*> TxPair; |
51ed9ec9 | 1027 | typedef std::multimap<int64_t, TxPair > TxItems; |
ddb709e9 | 1028 | |
5b40d886 MF |
1029 | /** |
1030 | * Get the wallet's activity log | |
1031 | * @return multimap of ordered transactions and accounting entries | |
1032 | * @warning Returned pointers are *only* valid within the scope of passed acentries | |
ddb709e9 LD |
1033 | */ |
1034 | TxItems OrderedTxItems(std::list<CAccountingEntry>& acentries, std::string strAccount = ""); | |
c3f95ef1 | 1035 | |
95d888a6 | 1036 | void MarkDirty(); |
1a62587e | 1037 | bool UpdateNullifierNoteMap(); |
6e263a5f | 1038 | void UpdateNullifierNoteMapWithTx(const CWalletTx& wtx); |
44bc988e | 1039 | bool AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletDB* pwalletdb); |
d38da59b PW |
1040 | void SyncTransaction(const CTransaction& tx, const CBlock* pblock); |
1041 | bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate); | |
00588c3f | 1042 | void EraseFromWallet(const uint256 &hash); |
4bc00dc1 | 1043 | void WitnessNoteCommitment( |
2dc35992 | 1044 | std::vector<uint256> commitments, |
8ea8ef98 | 1045 | std::vector<boost::optional<SproutWitness>>& witnesses, |
2dc35992 | 1046 | uint256 &final_anchor); |
e8ef3da7 WL |
1047 | int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false); |
1048 | void ReacceptWalletTransactions(); | |
0f5954c4 GA |
1049 | void ResendWalletTransactions(int64_t nBestBlockTime); |
1050 | std::vector<uint256> ResendWalletTransactionsBefore(int64_t nTime); | |
a372168e MF |
1051 | CAmount GetBalance() const; |
1052 | CAmount GetUnconfirmedBalance() const; | |
1053 | CAmount GetImmatureBalance() const; | |
1054 | CAmount GetWatchOnlyBalance() const; | |
1055 | CAmount GetUnconfirmedWatchOnlyBalance() const; | |
1056 | CAmount GetImmatureWatchOnlyBalance() const; | |
aa30f655 MC |
1057 | bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosRet, std::string& strFailReason); |
1058 | bool CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosRet, | |
1059 | std::string& strFailReason, const CCoinControl *coinControl = NULL, bool sign = true); | |
e8ef3da7 | 1060 | bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey); |
e8ef3da7 | 1061 | |
13fc83c7 | 1062 | static CFeeRate minTxFee; |
a372168e | 1063 | static CAmount GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool); |
b33d1f5e | 1064 | |
37971fcc | 1065 | bool NewKeyPool(); |
13dd2d09 | 1066 | bool TopUpKeyPool(unsigned int kpSize = 0); |
51ed9ec9 BD |
1067 | void ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool); |
1068 | void KeepKey(int64_t nIndex); | |
1069 | void ReturnKey(int64_t nIndex); | |
71ac5052 | 1070 | bool GetKeyFromPool(CPubKey &key); |
51ed9ec9 | 1071 | int64_t GetOldestKeyPoolTime(); |
434e4273 | 1072 | void GetAllReserveKeys(std::set<CKeyID>& setAddress) const; |
e8ef3da7 | 1073 | |
b1093efa | 1074 | std::set< std::set<CTxDestination> > GetAddressGroupings(); |
a372168e | 1075 | std::map<CTxDestination, CAmount> GetAddressBalances(); |
22dfd735 | 1076 | |
db954a65 | 1077 | std::set<CTxDestination> GetAccountAddresses(const std::string& strAccount) const; |
3624356e | 1078 | |
618206c7 | 1079 | boost::optional<uint256> GetSproutNoteNullifier( |
1a62587e | 1080 | const JSDescription& jsdesc, |
e5eab182 | 1081 | const libzcash::SproutPaymentAddress& address, |
1a62587e JG |
1082 | const ZCNoteDecryption& dec, |
1083 | const uint256& hSig, | |
1084 | uint8_t n) const; | |
57faf44e | 1085 | mapSproutNoteData_t FindMySproutNotes(const CTransaction& tx) const; |
1551db87 | 1086 | bool IsFromMe(const uint256& nullifier) const; |
8e8279e7 | 1087 | void GetSproutNoteWitnesses( |
be74c80d | 1088 | std::vector<JSOutPoint> notes, |
8ea8ef98 | 1089 | std::vector<boost::optional<SproutWitness>>& witnesses, |
be74c80d | 1090 | uint256 &final_anchor); |
e6b0a8b9 EOW |
1091 | void GetSaplingNoteWitnesses( |
1092 | std::vector<SaplingOutPoint> notes, | |
8ea8ef98 | 1093 | std::vector<boost::optional<SaplingWitness>>& witnesses, |
e6b0a8b9 | 1094 | uint256 &final_anchor); |
02e67455 | 1095 | |
c8988460 | 1096 | isminetype IsMine(const CTxIn& txin) const; |
a372168e | 1097 | CAmount GetDebit(const CTxIn& txin, const isminefilter& filter) const; |
eca0b1ea JT |
1098 | isminetype IsMine(const CTxOut& txout) const; |
1099 | CAmount GetCredit(const CTxOut& txout, const isminefilter& filter) const; | |
3447cf87 | 1100 | bool IsChange(const CTxOut& txout) const; |
eca0b1ea JT |
1101 | CAmount GetChange(const CTxOut& txout) const; |
1102 | bool IsMine(const CTransaction& tx) const; | |
3447cf87 | 1103 | /** should probably be renamed to IsRelevantToMe */ |
eca0b1ea JT |
1104 | bool IsFromMe(const CTransaction& tx) const; |
1105 | CAmount GetDebit(const CTransaction& tx, const isminefilter& filter) const; | |
1106 | CAmount GetCredit(const CTransaction& tx, const isminefilter& filter) const; | |
1107 | CAmount GetChange(const CTransaction& tx) const; | |
4fc309f0 | 1108 | void ChainTip(const CBlockIndex *pindex, const CBlock *pblock, SproutMerkleTree sproutTree, SaplingMerkleTree saplingTree, bool added); |
d85758f5 | 1109 | /** Saves witness caches and best block locator to disk. */ |
3447cf87 | 1110 | void SetBestChain(const CBlockLocator& loc); |
0646f749 EOW |
1111 | std::set<std::pair<libzcash::PaymentAddress, uint256>> GetNullifiersForAddresses(const std::set<libzcash::PaymentAddress> & addresses); |
1112 | bool IsNoteChange(const std::set<std::pair<libzcash::PaymentAddress, uint256>> & nullifierSet, const libzcash::PaymentAddress & address, const JSOutPoint & entry); | |
e8ef3da7 | 1113 | |
3447cf87 CF |
1114 | DBErrors LoadWallet(bool& fFirstRunRet); |
1115 | DBErrors ZapWalletTx(std::vector<CWalletTx>& vWtx); | |
e8ef3da7 | 1116 | |
3447cf87 | 1117 | bool SetAddressBook(const CTxDestination& address, const std::string& strName, const std::string& purpose); |
9c7722b7 | 1118 | |
3447cf87 | 1119 | bool DelAddressBook(const CTxDestination& address); |
c3f95ef1 | 1120 | |
3447cf87 | 1121 | void UpdatedTransaction(const uint256 &hashTx); |
e8ef3da7 | 1122 | |
3447cf87 | 1123 | void Inventory(const uint256 &hash) |
e8ef3da7 | 1124 | { |
3447cf87 CF |
1125 | { |
1126 | LOCK(cs_wallet); | |
1127 | std::map<uint256, int>::iterator mi = mapRequestCount.find(hash); | |
1128 | if (mi != mapRequestCount.end()) | |
1129 | (*mi).second++; | |
1130 | } | |
e8ef3da7 WL |
1131 | } |
1132 | ||
3447cf87 | 1133 | unsigned int GetKeyPoolSize() |
4c6e2295 | 1134 | { |
3447cf87 CF |
1135 | AssertLockHeld(cs_wallet); // setKeyPool |
1136 | return setKeyPool.size(); | |
4c6e2295 PW |
1137 | } |
1138 | ||
3447cf87 | 1139 | bool SetDefaultKey(const CPubKey &vchPubKey); |
e8ef3da7 | 1140 | |
3447cf87 CF |
1141 | //! signify that a particular wallet feature is now used. this may change nWalletVersion and nWalletMaxVersion if those are lower |
1142 | bool SetMinVersion(enum WalletFeature, CWalletDB* pwalletdbIn = NULL, bool fExplicit = false); | |
e8ef3da7 | 1143 | |
3447cf87 CF |
1144 | //! change which version we're allowed to upgrade to (note that this does not immediately imply upgrading to that format) |
1145 | bool SetMaxVersion(int nVersion); | |
e8ef3da7 | 1146 | |
3447cf87 CF |
1147 | //! get the current wallet format (the oldest client version guaranteed to understand this wallet) |
1148 | int GetVersion() { LOCK(cs_wallet); return nWalletVersion; } | |
e8ef3da7 | 1149 | |
3447cf87 CF |
1150 | //! Get wallet transactions that conflict with given transaction (spend same outputs) |
1151 | std::set<uint256> GetConflicts(const uint256& txid) const; | |
e8ef3da7 | 1152 | |
2bb1c877 JS |
1153 | //! Flush wallet (bitdb flush) |
1154 | void Flush(bool shutdown=false); | |
1155 | ||
1156 | //! Verify the wallet database and perform salvage if required | |
341e2385 | 1157 | static bool Verify(const std::string& walletFile, std::string& warningString, std::string& errorString); |
2bb1c877 | 1158 | |
3447cf87 CF |
1159 | /** |
1160 | * Address book entry changed. | |
1161 | * @note called with lock cs_wallet held. | |
1162 | */ | |
1163 | boost::signals2::signal<void (CWallet *wallet, const CTxDestination | |
1164 | &address, const std::string &label, bool isMine, | |
1165 | const std::string &purpose, | |
1166 | ChangeType status)> NotifyAddressBookChanged; | |
e8ef3da7 | 1167 | |
3447cf87 CF |
1168 | /** |
1169 | * Wallet transaction added, removed or updated. | |
1170 | * @note called with lock cs_wallet held. | |
1171 | */ | |
1172 | boost::signals2::signal<void (CWallet *wallet, const uint256 &hashTx, | |
1173 | ChangeType status)> NotifyTransactionChanged; | |
e8ef3da7 | 1174 | |
3447cf87 CF |
1175 | /** Show progress e.g. for rescan */ |
1176 | boost::signals2::signal<void (const std::string &title, int nProgress)> ShowProgress; | |
731b89b8 | 1177 | |
3447cf87 CF |
1178 | /** Watch-only address added */ |
1179 | boost::signals2::signal<void (bool fHaveWatchOnly)> NotifyWatchonlyChanged; | |
6f252627 WL |
1180 | |
1181 | /** Inquire whether this wallet broadcasts transactions. */ | |
1182 | bool GetBroadcastTransactions() const { return fBroadcastTransactions; } | |
1183 | /** Set whether this wallet broadcasts transactions. */ | |
1184 | void SetBroadcastTransactions(bool broadcast) { fBroadcastTransactions = broadcast; } | |
a5ac2e25 | 1185 | |
03812fef | 1186 | /* Find notes filtered by payment address, min depth, ability to spend */ |
5020a936 | 1187 | void GetFilteredNotes(std::vector<CSproutNotePlaintextEntry> & outEntries, |
9a2b8ae5 JG |
1188 | std::string address, |
1189 | int minDepth=1, | |
1190 | bool ignoreSpent=true, | |
bdbe8e85 JG |
1191 | bool ignoreUnspendable=true); |
1192 | ||
1193 | /* Find notes filtered by payment addresses, min depth, ability to spend */ | |
5020a936 | 1194 | void GetFilteredNotes(std::vector<CSproutNotePlaintextEntry>& outEntries, |
bdbe8e85 JG |
1195 | std::set<libzcash::PaymentAddress>& filterAddresses, |
1196 | int minDepth=1, | |
1197 | bool ignoreSpent=true, | |
9a2b8ae5 | 1198 | bool ignoreUnspendable=true); |
a5ac2e25 | 1199 | |
d72c19a6 | 1200 | /* Find unspent notes filtered by payment address, min depth and max depth */ |
5020a936 | 1201 | void GetUnspentFilteredNotes(std::vector<CUnspentSproutNotePlaintextEntry>& outEntries, |
d72c19a6 S |
1202 | std::set<libzcash::PaymentAddress>& filterAddresses, |
1203 | int minDepth=1, | |
1204 | int maxDepth=INT_MAX, | |
1205 | bool requireSpendingKey=true); | |
e8ef3da7 WL |
1206 | }; |
1207 | ||
3447cf87 CF |
1208 | /** A key allocated from the key pool. */ |
1209 | class CReserveKey | |
9b0369c7 | 1210 | { |
3447cf87 CF |
1211 | protected: |
1212 | CWallet* pwallet; | |
1213 | int64_t nIndex; | |
1214 | CPubKey vchPubKey; | |
9b0369c7 | 1215 | public: |
3447cf87 | 1216 | CReserveKey(CWallet* pwalletIn) |
9b0369c7 | 1217 | { |
3447cf87 CF |
1218 | nIndex = -1; |
1219 | pwallet = pwalletIn; | |
9b0369c7 CM |
1220 | } |
1221 | ||
3447cf87 CF |
1222 | ~CReserveKey() |
1223 | { | |
1224 | ReturnKey(); | |
3d796f89 | 1225 | } |
e8ef3da7 | 1226 | |
3447cf87 | 1227 | void ReturnKey(); |
8e8b6d70 | 1228 | virtual bool GetReservedKey(CPubKey &pubkey); |
3447cf87 CF |
1229 | void KeepKey(); |
1230 | }; | |
e8ef3da7 WL |
1231 | |
1232 | ||
5b40d886 MF |
1233 | /** |
1234 | * Account information. | |
6b8de05d PW |
1235 | * Stored in wallet with key "acc"+string account name. |
1236 | */ | |
e8ef3da7 WL |
1237 | class CAccount |
1238 | { | |
1239 | public: | |
fd61d6f5 | 1240 | CPubKey vchPubKey; |
e8ef3da7 WL |
1241 | |
1242 | CAccount() | |
1243 | { | |
1244 | SetNull(); | |
1245 | } | |
1246 | ||
1247 | void SetNull() | |
1248 | { | |
fd61d6f5 | 1249 | vchPubKey = CPubKey(); |
e8ef3da7 WL |
1250 | } |
1251 | ||
3f6540ad | 1252 | ADD_SERIALIZE_METHODS; |
3d796f89 | 1253 | |
84881f8c | 1254 | template <typename Stream, typename Operation> |
242f1421 PW |
1255 | inline void SerializationOp(Stream& s, Operation ser_action) { |
1256 | int nVersion = s.GetVersion(); | |
1257 | if (!(s.GetType() & SER_GETHASH)) | |
e8ef3da7 WL |
1258 | READWRITE(nVersion); |
1259 | READWRITE(vchPubKey); | |
3d796f89 | 1260 | } |
e8ef3da7 WL |
1261 | }; |
1262 | ||
a21df620 | 1263 | #endif // BITCOIN_WALLET_WALLET_H |