Remove duplicate destination decoding
[bitcoinplatinum.git] / src / script / ismine.cpp
blob0a39619734cfeaa12d3b69829ecf3c66f805355d
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2016 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.
6 #include "ismine.h"
8 #include "key.h"
9 #include "keystore.h"
10 #include "script/script.h"
11 #include "script/standard.h"
12 #include "script/sign.h"
15 typedef std::vector<unsigned char> valtype;
17 unsigned int HaveKeys(const std::vector<valtype>& pubkeys, const CKeyStore& keystore)
19 unsigned int nResult = 0;
20 for (const valtype& pubkey : pubkeys)
22 CKeyID keyID = CPubKey(pubkey).GetID();
23 if (keystore.HaveKey(keyID))
24 ++nResult;
26 return nResult;
29 isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey, SigVersion sigversion)
31 bool isInvalid = false;
32 return IsMine(keystore, scriptPubKey, isInvalid, sigversion);
35 isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest, SigVersion sigversion)
37 bool isInvalid = false;
38 return IsMine(keystore, dest, isInvalid, sigversion);
41 isminetype IsMine(const CKeyStore &keystore, const CTxDestination& dest, bool& isInvalid, SigVersion sigversion)
43 CScript script = GetScriptForDestination(dest);
44 return IsMine(keystore, script, isInvalid, sigversion);
47 isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey, bool& isInvalid, SigVersion sigversion)
49 std::vector<valtype> vSolutions;
50 txnouttype whichType;
51 if (!Solver(scriptPubKey, whichType, vSolutions)) {
52 if (keystore.HaveWatchOnly(scriptPubKey))
53 return ISMINE_WATCH_UNSOLVABLE;
54 return ISMINE_NO;
57 CKeyID keyID;
58 switch (whichType)
60 case TX_NONSTANDARD:
61 case TX_NULL_DATA:
62 break;
63 case TX_PUBKEY:
64 keyID = CPubKey(vSolutions[0]).GetID();
65 if (sigversion != SIGVERSION_BASE && vSolutions[0].size() != 33) {
66 isInvalid = true;
67 return ISMINE_NO;
69 if (keystore.HaveKey(keyID))
70 return ISMINE_SPENDABLE;
71 break;
72 case TX_WITNESS_V0_KEYHASH:
74 if (!keystore.HaveCScript(CScriptID(CScript() << OP_0 << vSolutions[0]))) {
75 // We do not support bare witness outputs unless the P2SH version of it would be
76 // acceptable as well. This protects against matching before segwit activates.
77 // This also applies to the P2WSH case.
78 break;
80 isminetype ret = ::IsMine(keystore, GetScriptForDestination(CKeyID(uint160(vSolutions[0]))), isInvalid, SIGVERSION_WITNESS_V0);
81 if (ret == ISMINE_SPENDABLE || ret == ISMINE_WATCH_SOLVABLE || (ret == ISMINE_NO && isInvalid))
82 return ret;
83 break;
85 case TX_PUBKEYHASH:
86 keyID = CKeyID(uint160(vSolutions[0]));
87 if (sigversion != SIGVERSION_BASE) {
88 CPubKey pubkey;
89 if (keystore.GetPubKey(keyID, pubkey) && !pubkey.IsCompressed()) {
90 isInvalid = true;
91 return ISMINE_NO;
94 if (keystore.HaveKey(keyID))
95 return ISMINE_SPENDABLE;
96 break;
97 case TX_SCRIPTHASH:
99 CScriptID scriptID = CScriptID(uint160(vSolutions[0]));
100 CScript subscript;
101 if (keystore.GetCScript(scriptID, subscript)) {
102 isminetype ret = IsMine(keystore, subscript, isInvalid);
103 if (ret == ISMINE_SPENDABLE || ret == ISMINE_WATCH_SOLVABLE || (ret == ISMINE_NO && isInvalid))
104 return ret;
106 break;
108 case TX_WITNESS_V0_SCRIPTHASH:
110 if (!keystore.HaveCScript(CScriptID(CScript() << OP_0 << vSolutions[0]))) {
111 break;
113 uint160 hash;
114 CRIPEMD160().Write(&vSolutions[0][0], vSolutions[0].size()).Finalize(hash.begin());
115 CScriptID scriptID = CScriptID(hash);
116 CScript subscript;
117 if (keystore.GetCScript(scriptID, subscript)) {
118 isminetype ret = IsMine(keystore, subscript, isInvalid, SIGVERSION_WITNESS_V0);
119 if (ret == ISMINE_SPENDABLE || ret == ISMINE_WATCH_SOLVABLE || (ret == ISMINE_NO && isInvalid))
120 return ret;
122 break;
125 case TX_MULTISIG:
127 // Only consider transactions "mine" if we own ALL the
128 // keys involved. Multi-signature transactions that are
129 // partially owned (somebody else has a key that can spend
130 // them) enable spend-out-from-under-you attacks, especially
131 // in shared-wallet situations.
132 std::vector<valtype> keys(vSolutions.begin()+1, vSolutions.begin()+vSolutions.size()-1);
133 if (sigversion != SIGVERSION_BASE) {
134 for (size_t i = 0; i < keys.size(); i++) {
135 if (keys[i].size() != 33) {
136 isInvalid = true;
137 return ISMINE_NO;
141 if (HaveKeys(keys, keystore) == keys.size())
142 return ISMINE_SPENDABLE;
143 break;
147 if (keystore.HaveWatchOnly(scriptPubKey)) {
148 // TODO: This could be optimized some by doing some work after the above solver
149 SignatureData sigs;
150 return ProduceSignature(DummySignatureCreator(&keystore), scriptPubKey, sigs) ? ISMINE_WATCH_SOLVABLE : ISMINE_WATCH_UNSOLVABLE;
152 return ISMINE_NO;