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.
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
))
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
)
51 std::vector
<valtype
> vSolutions
;
53 if (!Solver(scriptPubKey
, whichType
, vSolutions
)) {
54 if (keystore
.HaveWatchOnly(scriptPubKey
))
55 return ISMINE_WATCH_UNSOLVABLE
;
64 case TX_WITNESS_UNKNOWN
:
67 keyID
= CPubKey(vSolutions
[0]).GetID();
68 if (sigversion
!= SIGVERSION_BASE
&& vSolutions
[0].size() != 33) {
72 if (keystore
.HaveKey(keyID
))
73 return ISMINE_SPENDABLE
;
75 case TX_WITNESS_V0_KEYHASH
:
77 if (!keystore
.HaveCScript(CScriptID(CScript() << OP_0
<< vSolutions
[0]))) {
78 // We do not support bare witness outputs unless the P2SH version of it would be
79 // acceptable as well. This protects against matching before segwit activates.
80 // This also applies to the P2WSH case.
83 isminetype ret
= ::IsMine(keystore
, GetScriptForDestination(CKeyID(uint160(vSolutions
[0]))), isInvalid
, SIGVERSION_WITNESS_V0
);
84 if (ret
== ISMINE_SPENDABLE
|| ret
== ISMINE_WATCH_SOLVABLE
|| (ret
== ISMINE_NO
&& isInvalid
))
89 keyID
= CKeyID(uint160(vSolutions
[0]));
90 if (sigversion
!= SIGVERSION_BASE
) {
92 if (keystore
.GetPubKey(keyID
, pubkey
) && !pubkey
.IsCompressed()) {
97 if (keystore
.HaveKey(keyID
))
98 return ISMINE_SPENDABLE
;
102 CScriptID scriptID
= CScriptID(uint160(vSolutions
[0]));
104 if (keystore
.GetCScript(scriptID
, subscript
)) {
105 isminetype ret
= IsMine(keystore
, subscript
, isInvalid
);
106 if (ret
== ISMINE_SPENDABLE
|| ret
== ISMINE_WATCH_SOLVABLE
|| (ret
== ISMINE_NO
&& isInvalid
))
111 case TX_WITNESS_V0_SCRIPTHASH
:
113 if (!keystore
.HaveCScript(CScriptID(CScript() << OP_0
<< vSolutions
[0]))) {
117 CRIPEMD160().Write(&vSolutions
[0][0], vSolutions
[0].size()).Finalize(hash
.begin());
118 CScriptID scriptID
= CScriptID(hash
);
120 if (keystore
.GetCScript(scriptID
, subscript
)) {
121 isminetype ret
= IsMine(keystore
, subscript
, isInvalid
, SIGVERSION_WITNESS_V0
);
122 if (ret
== ISMINE_SPENDABLE
|| ret
== ISMINE_WATCH_SOLVABLE
|| (ret
== ISMINE_NO
&& isInvalid
))
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 std::vector
<valtype
> keys(vSolutions
.begin()+1, vSolutions
.begin()+vSolutions
.size()-1);
136 if (sigversion
!= SIGVERSION_BASE
) {
137 for (size_t i
= 0; i
< keys
.size(); i
++) {
138 if (keys
[i
].size() != 33) {
144 if (HaveKeys(keys
, keystore
) == keys
.size())
145 return ISMINE_SPENDABLE
;
150 if (keystore
.HaveWatchOnly(scriptPubKey
)) {
151 // TODO: This could be optimized some by doing some work after the above solver
153 return ProduceSignature(DummySignatureCreator(&keystore
), scriptPubKey
, sigs
) ? ISMINE_WATCH_SOLVABLE
: ISMINE_WATCH_UNSOLVABLE
;