Fabcoin Core  0.16.2
P2P Digital Currency
ismine.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2017 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 "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 
15 typedef std::vector<unsigned char> valtype;
16 
17 unsigned int HaveKeys(const std::vector<valtype>& pubkeys, const CKeyStore& keystore)
18 {
19  unsigned int nResult = 0;
20  for (const valtype& pubkey : pubkeys)
21  {
22  CKeyID keyID = CPubKey(pubkey).GetID();
23  if (keystore.HaveKey(keyID))
24  ++nResult;
25  }
26  return nResult;
27 }
28 
29 isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey, SigVersion sigversion)
30 {
31  bool isInvalid = false;
32  return IsMine(keystore, scriptPubKey, isInvalid, sigversion);
33 }
34 
35 isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest, SigVersion sigversion)
36 {
37  bool isInvalid = false;
38  return IsMine(keystore, dest, isInvalid, sigversion);
39 }
40 
41 isminetype IsMine(const CKeyStore &keystore, const CTxDestination& dest, bool& isInvalid, SigVersion sigversion)
42 {
43  CScript script = GetScriptForDestination(dest);
44  return IsMine(keystore, script, isInvalid, sigversion);
45 }
46 
47 isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey, bool& isInvalid, SigVersion sigversion)
48 {
49  isInvalid = false;
50 
51  std::vector<valtype> vSolutions;
52  txnouttype whichType;
53  if (!Solver(scriptPubKey, whichType, vSolutions)) {
54  if (keystore.HaveWatchOnly(scriptPubKey))
56  return ISMINE_NO;
57  }
58 
59  CKeyID keyID;
60  switch (whichType)
61  {
62  case TX_NONSTANDARD:
63  case TX_NULL_DATA:
64  break;
65  case TX_PUBKEY:
66  keyID = CPubKey(vSolutions[0]).GetID();
67  if (sigversion != SIGVERSION_BASE && vSolutions[0].size() != 33) {
68  isInvalid = true;
69  return ISMINE_NO;
70  }
71  if (keystore.HaveKey(keyID))
72  return ISMINE_SPENDABLE;
73  break;
75  {
76  if (!keystore.HaveCScript(CScriptID(CScript() << OP_0 << vSolutions[0]))) {
77  // We do not support bare witness outputs unless the P2SH version of it would be
78  // acceptable as well. This protects against matching before segwit activates.
79  // This also applies to the P2WSH case.
80  break;
81  }
82  isminetype ret = ::IsMine(keystore, GetScriptForDestination(CKeyID(uint160(vSolutions[0]))), isInvalid, SIGVERSION_WITNESS_V0);
83  if (ret == ISMINE_SPENDABLE || ret == ISMINE_WATCH_SOLVABLE || (ret == ISMINE_NO && isInvalid))
84  return ret;
85  break;
86  }
87  case TX_PUBKEYHASH:
88  keyID = CKeyID(uint160(vSolutions[0]));
89  if (sigversion != SIGVERSION_BASE) {
90  CPubKey pubkey;
91  if (keystore.GetPubKey(keyID, pubkey) && !pubkey.IsCompressed()) {
92  isInvalid = true;
93  return ISMINE_NO;
94  }
95  }
96  if (keystore.HaveKey(keyID))
97  return ISMINE_SPENDABLE;
98  break;
99  case TX_SCRIPTHASH:
100  {
101  CScriptID scriptID = CScriptID(uint160(vSolutions[0]));
102  CScript subscript;
103  if (keystore.GetCScript(scriptID, subscript)) {
104  isminetype ret = IsMine(keystore, subscript, isInvalid);
105  if (ret == ISMINE_SPENDABLE || ret == ISMINE_WATCH_SOLVABLE || (ret == ISMINE_NO && isInvalid))
106  return ret;
107  }
108  break;
109  }
111  {
112  if (!keystore.HaveCScript(CScriptID(CScript() << OP_0 << vSolutions[0]))) {
113  break;
114  }
115  uint160 hash;
116  CRIPEMD160().Write(&vSolutions[0][0], vSolutions[0].size()).Finalize(hash.begin());
117  CScriptID scriptID = CScriptID(hash);
118  CScript subscript;
119  if (keystore.GetCScript(scriptID, subscript)) {
120  isminetype ret = IsMine(keystore, subscript, isInvalid, SIGVERSION_WITNESS_V0);
121  if (ret == ISMINE_SPENDABLE || ret == ISMINE_WATCH_SOLVABLE || (ret == ISMINE_NO && isInvalid))
122  return ret;
123  }
124  break;
125  }
126 
127  case TX_MULTISIG:
128  {
129  // Only consider transactions "mine" if we own ALL the
130  // keys involved. Multi-signature transactions that are
131  // partially owned (somebody else has a key that can spend
132  // them) enable spend-out-from-under-you attacks, especially
133  // in shared-wallet situations.
134  std::vector<valtype> keys(vSolutions.begin()+1, vSolutions.begin()+vSolutions.size()-1);
135  if (sigversion != SIGVERSION_BASE) {
136  for (size_t i = 0; i < keys.size(); i++) {
137  if (keys[i].size() != 33) {
138  isInvalid = true;
139  return ISMINE_NO;
140  }
141  }
142  }
143  if (HaveKeys(keys, keystore) == keys.size())
144  return ISMINE_SPENDABLE;
145  break;
146  }
147  default:
148  break;
149  }
150 
151  if (keystore.HaveWatchOnly(scriptPubKey)) {
152  // TODO: This could be optimized some by doing some work after the above solver
153  SignatureData sigs;
154  return ProduceSignature(DummySignatureCreator(&keystore), scriptPubKey, sigs) ? ISMINE_WATCH_SOLVABLE : ISMINE_WATCH_UNSOLVABLE;
155  }
156  return ISMINE_NO;
157 }
boost::variant< CNoDestination, CKeyID, CScriptID > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:79
bool Solver(const CScript &scriptPubKey, txnouttype &typeRet, std::vector< std::vector< unsigned char > > &vSolutionsRet, bool contractConsensus)
Return public keys or hashes from scriptPubKey, for &#39;standard&#39; transaction types. ...
Definition: standard.cpp:46
std::vector< unsigned char > valtype
Definition: ismine.cpp:15
isminetype IsMine(const CKeyStore &keystore, const CScript &scriptPubKey, SigVersion sigversion)
Definition: ismine.cpp:29
unsigned char * begin()
Definition: uint256.h:65
bool ProduceSignature(const BaseSignatureCreator &creator, const CScript &fromPubKey, SignatureData &sigdata)
Produce a script signature using a generic signature creator.
Definition: sign.cpp:141
virtual bool HaveCScript(const CScriptID &hash) const =0
Indicates that we don&#39;t know how to create a scriptSig that would solve this if we were given the app...
Definition: ismine.h:21
unsigned int HaveKeys(const std::vector< valtype > &pubkeys, const CKeyStore &keystore)
Definition: ismine.cpp:17
isminetype
IsMine() return codes.
Definition: ismine.h:17
virtual bool HaveKey(const CKeyID &address) const =0
Check whether a key corresponding to a given address is present in the store.
An encapsulated public key.
Definition: pubkey.h:39
CScript GetScriptForDestination(const CTxDestination &dest)
Definition: standard.cpp:370
virtual bool GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const =0
CRIPEMD160 & Write(const unsigned char *data, size_t len)
Definition: ripemd160.cpp:247
bool IsCompressed() const
Check whether this is a compressed public key.
Definition: pubkey.h:171
virtual bool HaveWatchOnly(const CScript &dest) const =0
txnouttype
Definition: standard.h:51
uint8_t const size_t const size
Definition: sha3.h:20
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:417
A virtual base class for key stores.
Definition: keystore.h:18
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:29
160-bit opaque blob.
Definition: uint256.h:120
A reference to a CScript: the Hash160 of its serialization (see script.h)
Definition: standard.h:28
std::vector< unsigned char > valtype
Definition: fascstate.h:17
Indicates that we know how to create a scriptSig that would solve this if we were given the appropria...
Definition: ismine.h:23
void Finalize(unsigned char hash[OUTPUT_SIZE])
Definition: ripemd160.cpp:273
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:146
Definition: script.h:51
virtual bool GetCScript(const CScriptID &hash, CScript &redeemScriptOut) const =0
A hasher class for RIPEMD-160.
Definition: ripemd160.h:12
A signature creator that just produces 72-byte empty signatures.
Definition: sign.h:56
SigVersion
Definition: interpreter.h:124