Line data Source code
1 : // Copyright (c) 2009-2010 Satoshi Nakamoto 2 : // Copyright (c) 2009-2014 The Bitcoin developers 3 : // Copyright (c) 2016-2021 The PIVX Core developers 4 : // Distributed under the MIT software license, see the accompanying 5 : // file COPYING or http://www.opensource.org/licenses/mit-license.php. 6 : 7 : #include "ismine.h" 8 : 9 : #include "keystore.h" 10 : #include "script/script.h" 11 : #include "script/sign.h" 12 : #include "util/system.h" 13 : 14 : 15 : 16 : typedef std::vector<unsigned char> valtype; 17 : 18 370 : unsigned int HaveKeys(const std::vector<valtype>& pubkeys, const CKeyStore& keystore) 19 : { 20 370 : unsigned int nResult = 0; 21 1593 : for (const valtype& pubkey : pubkeys) { 22 1223 : CKeyID keyID = CPubKey(pubkey).GetID(); 23 1223 : if(keystore.HaveKey(keyID)) 24 607 : ++nResult; 25 : } 26 370 : return nResult; 27 : } 28 : 29 3319 : isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest) 30 : { 31 3319 : CScript script = GetScriptForDestination(dest); 32 3319 : return IsMine(keystore, script); 33 : } 34 : 35 1310 : isminetype IsMine(const CKeyStore& keystore, const libzcash::SaplingPaymentAddress& pa) 36 : { 37 1310 : libzcash::SaplingIncomingViewingKey ivk; 38 1310 : libzcash::SaplingExtendedFullViewingKey exfvk; 39 2620 : if (keystore.GetSaplingIncomingViewingKey(pa, ivk) && 40 2620 : keystore.GetSaplingFullViewingKey(ivk, exfvk) && 41 1310 : keystore.HaveSaplingSpendingKey(exfvk)) { 42 : return ISMINE_SPENDABLE_SHIELDED; 43 0 : } else if (!ivk.IsNull()) { 44 : return ISMINE_WATCH_ONLY_SHIELDED; 45 : } else { 46 0 : return ISMINE_NO; 47 : } 48 : } 49 : 50 : namespace 51 : { 52 : class CWDestinationVisitor : public boost::static_visitor<isminetype> 53 : { 54 : private: 55 : const CKeyStore& keystore; 56 : public: 57 3157 : explicit CWDestinationVisitor(const CKeyStore& _keystore) : keystore(_keystore) {} 58 : 59 1847 : isminetype operator()(const CTxDestination& dest) const { 60 1847 : return ::IsMine(keystore, dest); 61 : } 62 : 63 1310 : isminetype operator()(const libzcash::SaplingPaymentAddress& pa) const { 64 1310 : return ::IsMine(keystore, pa); 65 : } 66 : }; 67 : } 68 : 69 3157 : isminetype IsMine(const CKeyStore& keystore, const CWDestination& dest) 70 : { 71 3157 : return boost::apply_visitor(CWDestinationVisitor(keystore), dest); 72 : } 73 : 74 1110338 : isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey) 75 : { 76 2220676 : std::vector<valtype> vSolutions; 77 1110338 : txnouttype whichType; 78 1110338 : if(!Solver(scriptPubKey, whichType, vSolutions)) { 79 275639 : if(keystore.HaveWatchOnly(scriptPubKey)) { 80 : return ISMINE_WATCH_ONLY; 81 : } 82 : 83 275639 : return ISMINE_NO; 84 : } 85 : 86 834698 : CKeyID keyID; 87 834698 : switch (whichType) { 88 : case TX_NONSTANDARD: 89 : case TX_NULL_DATA: 90 : break; 91 10677 : case TX_PUBKEY: 92 10677 : keyID = CPubKey(vSolutions[0]).GetID(); 93 10677 : if(keystore.HaveKey(keyID)) 94 : return ISMINE_SPENDABLE; 95 : break; 96 734546 : case TX_PUBKEYHASH: 97 734546 : case TX_EXCHANGEADDR: 98 734546 : keyID = CKeyID(uint160(vSolutions[0])); 99 734546 : if(keystore.HaveKey(keyID)) 100 : return ISMINE_SPENDABLE; 101 : break; 102 87078 : case TX_SCRIPTHASH: { 103 87078 : CScriptID scriptID = CScriptID(uint160(vSolutions[0])); 104 87078 : CScript subscript; 105 87078 : if(keystore.GetCScript(scriptID, subscript)) { 106 368 : isminetype ret = IsMine(keystore, subscript); 107 368 : if(ret != ISMINE_NO) 108 710 : return ret; 109 : } 110 86731 : break; 111 : } 112 1914 : case TX_COLDSTAKE: { 113 1914 : CKeyID stakeKeyID = CKeyID(uint160(vSolutions[0])); 114 1914 : bool stakeKeyIsMine = keystore.HaveKey(stakeKeyID); 115 1914 : CKeyID ownerKeyID = CKeyID(uint160(vSolutions[1])); 116 1914 : bool spendKeyIsMine = keystore.HaveKey(ownerKeyID); 117 : 118 1914 : if (spendKeyIsMine) { 119 : // If the wallet has both keys, ISMINE_SPENDABLE_DELEGATED 120 : // takes precedence over ISMINE_COLD 121 1826 : return ISMINE_SPENDABLE_DELEGATED; 122 806 : } else if (stakeKeyIsMine) { 123 : return ISMINE_COLD; 124 : } else { 125 : // todo: Include watch only.. 126 : } 127 88 : break; 128 : } 129 370 : case TX_MULTISIG: { 130 : // Only consider transactions "mine" if we own ALL the 131 : // keys involved. multi-signature transactions that are 132 : // partially owned (somebody else has a key that can spend 133 : // them) enable spend-out-from-under-you attacks, especially 134 : // in shared-wallet situations. 135 370 : std::vector<valtype> keys(vSolutions.begin() + 1, vSolutions.begin() + vSolutions.size() - 1); 136 370 : if(HaveKeys(keys, keystore) == keys.size()) 137 87 : return ISMINE_SPENDABLE; 138 283 : break; 139 : } 140 : } 141 : 142 534078 : if (keystore.HaveWatchOnly(scriptPubKey)) { 143 620 : return ISMINE_WATCH_ONLY; 144 : } 145 : 146 : return ISMINE_NO; 147 : }