You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ismine.cpp 5.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. // Copyright (c) 2009-2010 Satoshi Nakamoto
  2. // Copyright (c) 2009-2016 The Starwels developers
  3. // Distributed under the MIT software license, see the accompanying
  4. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  5. #include "ismine.h"
  6. #include "key.h"
  7. #include "keystore.h"
  8. #include "script/script.h"
  9. #include "script/standard.h"
  10. #include "script/sign.h"
  11. typedef std::vector<unsigned char> valtype;
  12. unsigned int HaveKeys(const std::vector<valtype>& pubkeys, const CKeyStore& keystore)
  13. {
  14. unsigned int nResult = 0;
  15. for (const valtype& pubkey : pubkeys)
  16. {
  17. CKeyID keyID = CPubKey(pubkey).GetID();
  18. if (keystore.HaveKey(keyID))
  19. ++nResult;
  20. }
  21. return nResult;
  22. }
  23. isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey, SigVersion sigversion)
  24. {
  25. bool isInvalid = false;
  26. return IsMine(keystore, scriptPubKey, isInvalid, sigversion);
  27. }
  28. isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest, SigVersion sigversion)
  29. {
  30. bool isInvalid = false;
  31. return IsMine(keystore, dest, isInvalid, sigversion);
  32. }
  33. isminetype IsMine(const CKeyStore &keystore, const CTxDestination& dest, bool& isInvalid, SigVersion sigversion)
  34. {
  35. CScript script = GetScriptForDestination(dest);
  36. return IsMine(keystore, script, isInvalid, sigversion);
  37. }
  38. isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey, bool& isInvalid, SigVersion sigversion)
  39. {
  40. isInvalid = false;
  41. std::vector<valtype> vSolutions;
  42. txnouttype whichType;
  43. if (!Solver(scriptPubKey, whichType, vSolutions)) {
  44. if (keystore.HaveWatchOnly(scriptPubKey))
  45. return ISMINE_WATCH_UNSOLVABLE;
  46. return ISMINE_NO;
  47. }
  48. CKeyID keyID;
  49. switch (whichType)
  50. {
  51. case TX_NONSTANDARD:
  52. case TX_NULL_DATA:
  53. break;
  54. case TX_PUBKEY:
  55. keyID = CPubKey(vSolutions[0]).GetID();
  56. if (sigversion != SIGVERSION_BASE && vSolutions[0].size() != 33) {
  57. isInvalid = true;
  58. return ISMINE_NO;
  59. }
  60. if (keystore.HaveKey(keyID))
  61. return ISMINE_SPENDABLE;
  62. break;
  63. case TX_WITNESS_V0_KEYHASH:
  64. {
  65. if (!keystore.HaveCScript(CScriptID(CScript() << OP_0 << vSolutions[0]))) {
  66. // We do not support bare witness outputs unless the P2SH version of it would be
  67. // acceptable as well. This protects against matching before segwit activates.
  68. // This also applies to the P2WSH case.
  69. break;
  70. }
  71. isminetype ret = ::IsMine(keystore, GetScriptForDestination(CKeyID(uint160(vSolutions[0]))), isInvalid, SIGVERSION_WITNESS_V0);
  72. if (ret == ISMINE_SPENDABLE || ret == ISMINE_WATCH_SOLVABLE || (ret == ISMINE_NO && isInvalid))
  73. return ret;
  74. break;
  75. }
  76. case TX_PUBKEYHASH:
  77. keyID = CKeyID(uint160(vSolutions[0]));
  78. if (sigversion != SIGVERSION_BASE) {
  79. CPubKey pubkey;
  80. if (keystore.GetPubKey(keyID, pubkey) && !pubkey.IsCompressed()) {
  81. isInvalid = true;
  82. return ISMINE_NO;
  83. }
  84. }
  85. if (keystore.HaveKey(keyID))
  86. return ISMINE_SPENDABLE;
  87. break;
  88. case TX_SCRIPTHASH:
  89. {
  90. CScriptID scriptID = CScriptID(uint160(vSolutions[0]));
  91. CScript subscript;
  92. if (keystore.GetCScript(scriptID, subscript)) {
  93. isminetype ret = IsMine(keystore, subscript, isInvalid);
  94. if (ret == ISMINE_SPENDABLE || ret == ISMINE_WATCH_SOLVABLE || (ret == ISMINE_NO && isInvalid))
  95. return ret;
  96. }
  97. break;
  98. }
  99. case TX_WITNESS_V0_SCRIPTHASH:
  100. {
  101. if (!keystore.HaveCScript(CScriptID(CScript() << OP_0 << vSolutions[0]))) {
  102. break;
  103. }
  104. uint160 hash;
  105. CRIPEMD160().Write(&vSolutions[0][0], vSolutions[0].size()).Finalize(hash.begin());
  106. CScriptID scriptID = CScriptID(hash);
  107. CScript subscript;
  108. if (keystore.GetCScript(scriptID, subscript)) {
  109. isminetype ret = IsMine(keystore, subscript, isInvalid, SIGVERSION_WITNESS_V0);
  110. if (ret == ISMINE_SPENDABLE || ret == ISMINE_WATCH_SOLVABLE || (ret == ISMINE_NO && isInvalid))
  111. return ret;
  112. }
  113. break;
  114. }
  115. case TX_MULTISIG:
  116. {
  117. // Only consider transactions "mine" if we own ALL the
  118. // keys involved. Multi-signature transactions that are
  119. // partially owned (somebody else has a key that can spend
  120. // them) enable spend-out-from-under-you attacks, especially
  121. // in shared-wallet situations.
  122. std::vector<valtype> keys(vSolutions.begin()+1, vSolutions.begin()+vSolutions.size()-1);
  123. if (sigversion != SIGVERSION_BASE) {
  124. for (size_t i = 0; i < keys.size(); i++) {
  125. if (keys[i].size() != 33) {
  126. isInvalid = true;
  127. return ISMINE_NO;
  128. }
  129. }
  130. }
  131. if (HaveKeys(keys, keystore) == keys.size())
  132. return ISMINE_SPENDABLE;
  133. break;
  134. }
  135. }
  136. if (keystore.HaveWatchOnly(scriptPubKey)) {
  137. // TODO: This could be optimized some by doing some work after the above solver
  138. SignatureData sigs;
  139. return ProduceSignature(DummySignatureCreator(&keystore), scriptPubKey, sigs) ? ISMINE_WATCH_SOLVABLE : ISMINE_WATCH_UNSOLVABLE;
  140. }
  141. return ISMINE_NO;
  142. }