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 4677 : isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest) 30 : { 31 4677 : CScript script = GetScriptForDestination(dest); 32 4677 : return IsMine(keystore, script); 33 : } 34 : 35 1307 : isminetype IsMine(const CKeyStore& keystore, const libzcash::SaplingPaymentAddress& pa) 36 : { 37 1307 : libzcash::SaplingIncomingViewingKey ivk; 38 1307 : libzcash::SaplingExtendedFullViewingKey exfvk; 39 2614 : if (keystore.GetSaplingIncomingViewingKey(pa, ivk) && 40 2614 : keystore.GetSaplingFullViewingKey(ivk, exfvk) && 41 1307 : 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 4318 : explicit CWDestinationVisitor(const CKeyStore& _keystore) : keystore(_keystore) {} 58 : 59 3011 : isminetype operator()(const CTxDestination& dest) const { 60 3011 : return ::IsMine(keystore, dest); 61 : } 62 : 63 1307 : isminetype operator()(const libzcash::SaplingPaymentAddress& pa) const { 64 1307 : return ::IsMine(keystore, pa); 65 : } 66 : }; 67 : } 68 : 69 4318 : isminetype IsMine(const CKeyStore& keystore, const CWDestination& dest) 70 : { 71 4318 : return boost::apply_visitor(CWDestinationVisitor(keystore), dest); 72 : } 73 : 74 6247427 : isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey) 75 : { 76 12494814 : std::vector<valtype> vSolutions; 77 6247427 : txnouttype whichType; 78 6247427 : if(!Solver(scriptPubKey, whichType, vSolutions)) { 79 327559 : if(keystore.HaveWatchOnly(scriptPubKey)) { 80 : return ISMINE_WATCH_ONLY; 81 : } 82 : 83 327559 : return ISMINE_NO; 84 : } 85 : 86 5919863 : CKeyID keyID; 87 5919863 : switch (whichType) { 88 : case TX_NONSTANDARD: 89 : case TX_NULL_DATA: 90 : break; 91 10727 : case TX_PUBKEY: 92 10727 : keyID = CPubKey(vSolutions[0]).GetID(); 93 10727 : if(keystore.HaveKey(keyID)) 94 : return ISMINE_SPENDABLE; 95 : break; 96 5807583 : case TX_PUBKEYHASH: 97 5807583 : case TX_EXCHANGEADDR: 98 5807583 : keyID = CKeyID(uint160(vSolutions[0])); 99 5807583 : if(keystore.HaveKey(keyID)) 100 : return ISMINE_SPENDABLE; 101 : break; 102 85122 : case TX_SCRIPTHASH: { 103 85122 : CScriptID scriptID = CScriptID(uint160(vSolutions[0])); 104 85122 : CScript subscript; 105 85122 : if(keystore.GetCScript(scriptID, subscript)) { 106 368 : isminetype ret = IsMine(keystore, subscript); 107 368 : if(ret != ISMINE_NO) 108 710 : return ret; 109 : } 110 84775 : 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 583160 : if (keystore.HaveWatchOnly(scriptPubKey)) { 143 620 : return ISMINE_WATCH_ONLY; 144 : } 145 : 146 : return ISMINE_NO; 147 : }