Raven Core  3.0.0
P2P Digital Currency
ismine.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2016 The Bitcoin Core developers
3 // Copyright (c) 2017-2019 The Raven Core developers
4 // Distributed under the MIT software license, see the accompanying
5 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
6 
7 #include <util.h>
8 #include "ismine.h"
9 
10 #include "key.h"
11 #include "keystore.h"
12 #include "script/script.h"
13 #include "script/standard.h"
14 #include "script/sign.h"
15 #include "validation.h"
16 
17 
18 typedef std::vector<unsigned char> valtype;
19 
20 unsigned int HaveKeys(const std::vector<valtype>& pubkeys, const CKeyStore& keystore)
21 {
22  unsigned int nResult = 0;
23  for (const valtype& pubkey : pubkeys)
24  {
25  CKeyID keyID = CPubKey(pubkey).GetID();
26  if (keystore.HaveKey(keyID))
27  ++nResult;
28  }
29  return nResult;
30 }
31 
32 isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey, SigVersion sigversion)
33 {
34  bool isInvalid = false;
35  return IsMine(keystore, scriptPubKey, isInvalid, sigversion);
36 }
37 
38 isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest, SigVersion sigversion)
39 {
40  bool isInvalid = false;
41  return IsMine(keystore, dest, isInvalid, sigversion);
42 }
43 
44 isminetype IsMine(const CKeyStore &keystore, const CTxDestination& dest, bool& isInvalid, SigVersion sigversion)
45 {
46  CScript script = GetScriptForDestination(dest);
47  return IsMine(keystore, script, isInvalid, sigversion);
48 }
49 
50 isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey, bool& isInvalid, SigVersion sigversion)
51 {
52  isInvalid = false;
53 
54  std::vector<valtype> vSolutions;
55  txnouttype whichType;
56  if (!Solver(scriptPubKey, whichType, vSolutions)) {
57  if (keystore.HaveWatchOnly(scriptPubKey))
59  return ISMINE_NO;
60  }
61  CKeyID keyID;
62  switch (whichType) {
63  case TX_NONSTANDARD:
64  case TX_NULL_DATA:
65  break;
67  break;
68  case TX_PUBKEY:
69  keyID = CPubKey(vSolutions[0]).GetID();
70  if (sigversion != SIGVERSION_BASE && vSolutions[0].size() != 33) {
71  isInvalid = true;
72  return ISMINE_NO;
73  }
74  if (keystore.HaveKey(keyID))
75  return ISMINE_SPENDABLE;
76  break;
77  case TX_WITNESS_V0_KEYHASH: {
78  if (!keystore.HaveCScript(CScriptID(CScript() << OP_0 << vSolutions[0]))) {
79  // We do not support bare witness outputs unless the P2SH version of it would be
80  // acceptable as well. This protects against matching before segwit activates.
81  // This also applies to the P2WSH case.
82  break;
83  }
84  isminetype ret = ::IsMine(keystore, GetScriptForDestination(CKeyID(uint160(vSolutions[0]))), isInvalid,
86  if (ret == ISMINE_SPENDABLE || ret == ISMINE_WATCH_SOLVABLE || (ret == ISMINE_NO && isInvalid))
87  return ret;
88  break;
89  }
90  case TX_PUBKEYHASH:
91  keyID = CKeyID(uint160(vSolutions[0]));
92  if (sigversion != SIGVERSION_BASE) {
93  CPubKey pubkey;
94  if (keystore.GetPubKey(keyID, pubkey) && !pubkey.IsCompressed()) {
95  isInvalid = true;
96  return ISMINE_NO;
97  }
98  }
99  if (keystore.HaveKey(keyID))
100  return ISMINE_SPENDABLE;
101  break;
102  case TX_SCRIPTHASH: {
103  CScriptID scriptID = CScriptID(uint160(vSolutions[0]));
104  CScript subscript;
105  if (keystore.GetCScript(scriptID, subscript)) {
106  isminetype ret = IsMine(keystore, subscript, isInvalid);
107  if (ret == ISMINE_SPENDABLE || ret == ISMINE_WATCH_SOLVABLE || (ret == ISMINE_NO && isInvalid))
108  return ret;
109  }
110  break;
111  }
113  if (!keystore.HaveCScript(CScriptID(CScript() << OP_0 << vSolutions[0]))) {
114  break;
115  }
116  uint160 hash;
117  CRIPEMD160().Write(&vSolutions[0][0], vSolutions[0].size()).Finalize(hash.begin());
118  CScriptID scriptID = CScriptID(hash);
119  CScript subscript;
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))
123  return ret;
124  }
125  break;
126  }
127 
128  case TX_MULTISIG: {
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  }
148  case TX_NEW_ASSET: {
149  if (!AreAssetsDeployed())
150  return ISMINE_NO;
151  keyID = CKeyID(uint160(vSolutions[0]));
152  if (sigversion != SIGVERSION_BASE) {
153  CPubKey pubkey;
154  if (keystore.GetPubKey(keyID, pubkey) && !pubkey.IsCompressed()) {
155  isInvalid = true;
156  return ISMINE_NO;
157  }
158  }
159  if (keystore.HaveKey(keyID))
160  return ISMINE_SPENDABLE;
161  break;
162 
163  }
164 
165  case TX_TRANSFER_ASSET: {
166  if (!AreAssetsDeployed())
167  return ISMINE_NO;
168  keyID = CKeyID(uint160(vSolutions[0]));
169  if (sigversion != SIGVERSION_BASE) {
170  CPubKey pubkey;
171  if (keystore.GetPubKey(keyID, pubkey) && !pubkey.IsCompressed()) {
172  isInvalid = true;
173  return ISMINE_NO;
174  }
175  }
176  if (keystore.HaveKey(keyID))
177  return ISMINE_SPENDABLE;
178  break;
179  }
180 
181  case TX_REISSUE_ASSET: {
182  if (!AreAssetsDeployed())
183  return ISMINE_NO;
184  keyID = CKeyID(uint160(vSolutions[0]));
185  if (sigversion != SIGVERSION_BASE) {
186  CPubKey pubkey;
187  if (keystore.GetPubKey(keyID, pubkey) && !pubkey.IsCompressed()) {
188  isInvalid = true;
189  return ISMINE_NO;
190  }
191  }
192  if (keystore.HaveKey(keyID))
193  return ISMINE_SPENDABLE;
194  break;
195  }
197  }
198 
199  if (keystore.HaveWatchOnly(scriptPubKey)) {
200  // TODO: This could be optimized some by doing some work after the above solver
201  SignatureData sigs;
202  return ProduceSignature(DummySignatureCreator(&keystore), scriptPubKey, sigs) ? ISMINE_WATCH_SOLVABLE : ISMINE_WATCH_UNSOLVABLE;
203  }
204  return ISMINE_NO;
205 }
boost::variant< CNoDestination, CKeyID, CScriptID > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:89
unspendable OP_RETURN script that carries data
Definition: standard.h:65
std::vector< unsigned char > valtype
Definition: ismine.cpp:18
isminetype IsMine(const CKeyStore &keystore, const CScript &scriptPubKey, SigVersion sigversion)
Definition: ismine.cpp:32
unsigned char * begin()
Definition: uint256.h:57
bool ProduceSignature(const BaseSignatureCreator &creator, const CScript &fromPubKey, SignatureData &sigdata)
Produce a script signature using a generic signature creator.
Definition: sign.cpp:179
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:143
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:22
unsigned int HaveKeys(const std::vector< valtype > &pubkeys, const CKeyStore &keystore)
Definition: ismine.cpp:20
bool AreAssetsDeployed()
RVN START.
isminetype
IsMine() return codes.
Definition: ismine.h:18
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:40
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Raven scriptPubKey for the given CTxDestination.
Definition: standard.cpp:347
virtual bool GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const =0
bool Solver(const CScript &scriptPubKey, txnouttype &typeRet, std::vector< std::vector< unsigned char > > &vSolutionsRet)
Parse a scriptPubKey and identify script type for standard scripts.
Definition: standard.cpp:47
CRIPEMD160 & Write(const unsigned char *data, size_t len)
Definition: ripemd160.cpp:248
virtual bool HaveWatchOnly(const CScript &dest) const =0
txnouttype
Definition: standard.h:57
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:396
A virtual base class for key stores.
Definition: keystore.h:19
RVN START.
Definition: standard.h:69
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:30
160-bit opaque blob.
Definition: uint256.h:112
std::vector< unsigned char > valtype
Definition: interpreter.cpp:16
A reference to a CScript: the Hash160 of its serialization (see script.h)
Definition: standard.h:23
Indicates that we know how to create a scriptSig that would solve this if we were given the appropria...
Definition: ismine.h:24
void Finalize(unsigned char hash[OUTPUT_SIZE])
Definition: ripemd160.cpp:274
Definition: script.h:54
unspendable OP_RAVEN_ASSET script that carries data
Definition: standard.h:72
virtual bool GetCScript(const CScriptID &hash, CScript &redeemScriptOut) const =0
A hasher class for RIPEMD-160.
Definition: ripemd160.h:13
A signature creator that just produces 72-byte empty signatures.
Definition: sign.h:56
SigVersion
Definition: interpreter.h:125
bool IsCompressed() const
Check whether this is a compressed public key.
Definition: pubkey.h:168