Line data Source code
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 http://www.opensource.org/licenses/mit-license.php.
5 :
6 : #include "wallet_ismine.h"
7 :
8 : #include "key.h"
9 : #include "keystore.h"
10 : #include "script/script.h"
11 : #include "script/standard.h"
12 : #include "script/sign.h"
13 :
14 : #include <boost/foreach.hpp>
15 :
16 : using namespace std;
17 :
18 : typedef vector<unsigned char> valtype;
19 :
20 81 : unsigned int HaveKeys(const vector<valtype>& pubkeys, const CKeyStore& keystore)
21 : {
22 81 : unsigned int nResult = 0;
23 1565 : BOOST_FOREACH(const valtype& pubkey, pubkeys)
24 : {
25 232 : CKeyID keyID = CPubKey(pubkey).GetID();
26 232 : if (keystore.HaveKey(keyID))
27 211 : ++nResult;
28 : }
29 81 : return nResult;
30 : }
31 :
32 477 : isminetype IsMine(const CKeyStore &keystore, const CTxDestination& dest)
33 : {
34 477 : CScript script = GetScriptForDestination(dest);
35 954 : return IsMine(keystore, script);
36 : }
37 :
38 34540 : isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey)
39 : {
40 : vector<valtype> vSolutions;
41 : txnouttype whichType;
42 34540 : if (!Solver(scriptPubKey, whichType, vSolutions)) {
43 253 : if (keystore.HaveWatchOnly(scriptPubKey))
44 : return ISMINE_WATCH_UNSOLVABLE;
45 253 : return ISMINE_NO;
46 : }
47 :
48 : CKeyID keyID;
49 34287 : switch (whichType)
50 : {
51 : case TX_NONSTANDARD:
52 : case TX_NULL_DATA:
53 : break;
54 : case TX_PUBKEY:
55 38090 : keyID = CPubKey(vSolutions[0]).GetID();
56 19045 : if (keystore.HaveKey(keyID))
57 : return ISMINE_SPENDABLE;
58 : break;
59 : case TX_PUBKEYHASH:
60 29496 : keyID = CKeyID(uint160(vSolutions[0]));
61 14748 : if (keystore.HaveKey(keyID))
62 : return ISMINE_SPENDABLE;
63 : break;
64 : case TX_SCRIPTHASH:
65 : {
66 826 : CScriptID scriptID = CScriptID(uint160(vSolutions[0]));
67 : CScript subscript;
68 413 : if (keystore.GetCScript(scriptID, subscript)) {
69 80 : isminetype ret = IsMine(keystore, subscript);
70 80 : if (ret == ISMINE_SPENDABLE)
71 67 : return ret;
72 : }
73 : break;
74 : }
75 : case TX_MULTISIG:
76 : {
77 : // Only consider transactions "mine" if we own ALL the
78 : // keys involved. Multi-signature transactions that are
79 : // partially owned (somebody else has a key that can spend
80 : // them) enable spend-out-from-under-you attacks, especially
81 : // in shared-wallet situations.
82 567 : vector<valtype> keys(vSolutions.begin()+1, vSolutions.begin()+vSolutions.size()-1);
83 162 : if (HaveKeys(keys, keystore) == keys.size())
84 64 : return ISMINE_SPENDABLE;
85 17 : break;
86 : }
87 : }
88 :
89 17653 : if (keystore.HaveWatchOnly(scriptPubKey)) {
90 : // TODO: This could be optimized some by doing some work after the above solver
91 : CScript scriptSig;
92 36 : return ProduceSignature(DummySignatureCreator(&keystore), scriptPubKey, scriptSig) ? ISMINE_WATCH_SOLVABLE : ISMINE_WATCH_UNSOLVABLE;
93 : }
94 34540 : return ISMINE_NO;
95 288 : }
|