1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2014 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or https://www.opensource.org/licenses/mit-license.php .
6 #include "wallet_ismine.h"
10 #include "script/script.h"
11 #include "script/standard.h"
13 #include "pbaas/identity.h"
14 #include "cc/CCinclude.h"
16 #include <boost/foreach.hpp>
20 typedef vector<unsigned char> valtype;
22 unsigned int HaveKeys(const vector<valtype>& pubkeys, const CKeyStore& keystore)
24 unsigned int nResult = 0;
25 BOOST_FOREACH(const valtype& pubkey, pubkeys)
27 CKeyID keyID = CPubKey(pubkey).GetID();
28 if (keystore.HaveKey(keyID))
34 isminetype IsMine(const CKeyStore &keystore, const CTxDestination& dest)
36 CScript script = GetScriptForDestination(dest);
37 return IsMine(keystore, script);
40 isminetype IsMine(const CKeyStore &keystore, const CScript& _scriptPubKey, uint32_t height)
42 vector<valtype> vSolutions;
44 CScript scriptPubKey = _scriptPubKey;
46 if (scriptPubKey.IsCheckLockTimeVerify())
48 uint8_t pushOp = scriptPubKey[0];
49 uint32_t scriptStart = pushOp + 3;
51 // continue with post CLTV script
52 scriptPubKey = CScript(scriptPubKey.size() > scriptStart ? scriptPubKey.begin() + scriptStart : scriptPubKey.end(), scriptPubKey.end());
56 if (scriptPubKey.IsPayToCryptoCondition(p) && p.IsValid())
58 std::vector<CTxDestination> dests;
61 bool canSpend = false;
63 if (ExtractDestinations(scriptPubKey, whichType, dests, minSigs, &keystore, &canSign, &canSpend, height))
67 return ISMINE_SPENDABLE;
71 return ISMINE_WATCH_ONLY;
83 else if (!Solver(scriptPubKey, whichType, vSolutions))
85 if (keystore.HaveWatchOnly(scriptPubKey))
86 return ISMINE_WATCH_ONLY;
96 case TX_CRYPTOCONDITION:
98 // for now, default is that the first value returned will be the target address, subsequent values will be
99 // pubkeys. if we have the first in our wallet, we consider it spendable for now
100 if (vSolutions[0].size() == 33)
102 keyID = CPubKey(vSolutions[0]).GetID();
104 else if (vSolutions[0].size() == 20)
106 keyID = CKeyID(uint160(vSolutions[0]));
108 if (!keyID.IsNull() && keystore.HaveKey(keyID))
110 return ISMINE_SPENDABLE;
115 keyID = CPubKey(vSolutions[0]).GetID();
116 if (keystore.HaveKey(keyID))
117 return ISMINE_SPENDABLE;
120 keyID = CKeyID(uint160(vSolutions[0]));
121 if (keystore.HaveKey(keyID))
122 return ISMINE_SPENDABLE;
126 CScriptID scriptID = CScriptID(uint160(vSolutions[0]));
128 if (keystore.GetCScript(scriptID, subscript)) {
129 isminetype ret = IsMine(keystore, subscript);
130 if (ret == ISMINE_SPENDABLE)
137 // Only consider transactions "mine" if we own ALL the
138 // keys involved. Multi-signature transactions that are
139 // partially owned (somebody else has a key that can spend
140 // them) enable spend-out-from-under-you attacks, especially
141 // in shared-wallet situations.
142 vector<valtype> keys(vSolutions.begin()+1, vSolutions.begin()+vSolutions.size()-1);
143 if (HaveKeys(keys, keystore) == keys.size())
144 return ISMINE_SPENDABLE;
149 if (keystore.HaveWatchOnly(scriptPubKey))
150 return ISMINE_WATCH_ONLY;