diff options
author | MeshCollider <dobsonsa68@gmail.com> | 2019-06-21 19:58:18 +1200 |
---|---|---|
committer | MeshCollider <dobsonsa68@gmail.com> | 2019-06-21 19:59:48 +1200 |
commit | fd333e15a5454ea7be85702b5eefb3edca1da794 (patch) | |
tree | 307679d1ed8bcff6ab29e4c3363c1b8b5e4d2eae | |
parent | 303ec103bacf2c9498d567210dd77c1305bddf81 (diff) | |
parent | e61de6306fd89fe9aae90253062e7b1b20343f8a (diff) | |
download | bitcoin-fd333e15a5454ea7be85702b5eefb3edca1da794.tar.xz |
Merge #16226: Move ismine to the wallet module
e61de6306fd89fe9aae90253062e7b1b20343f8a Change ismine to take a CWallet instead of CKeyStore (Andrew Chow)
7c611e20007bf5face34d33dffa26c8db67e29ec Move ismine to wallet module (Andrew Chow)
Pull request description:
`IsMine` isn't used outside of the wallet except for the tests. It also doesn't make sense to be outside of the wallet. This PR moves `IsMine` into the wallet module and for it to take a `CWallet` instead of `CKeyStore`. The test that used `IsMine` is also moved to the wallet tests.
This is first [prerequisites](https://github.com/bitcoin-core/bitcoin-devwiki/wiki/Wallet-Class-Structure-Changes#ismine) for the wallet structure changes.
ACKs for commit e61de6:
MarcoFalke:
re-ACK e61de6306f (only change is rebase with git auto-merge)
meshcollider:
Very light code review ACK https://github.com/bitcoin/bitcoin/pull/16226/commits/e61de6306fd89fe9aae90253062e7b1b20343f8a
Tree-SHA512: 1cb4ad12652aef7922ab7460c6d413e8b9d1855dca78c0a286ae49d5c0765bc7996c55f262c742001d434eb9bd4215dc2cc7aae1b371ee1a82d46b32c17e6341
-rw-r--r-- | src/Makefile.am | 4 | ||||
-rw-r--r-- | src/Makefile.test.include | 3 | ||||
-rw-r--r-- | src/interfaces/wallet.cpp | 2 | ||||
-rw-r--r-- | src/interfaces/wallet.h | 4 | ||||
-rw-r--r-- | src/qt/transactiondesc.cpp | 1 | ||||
-rw-r--r-- | src/qt/transactionrecord.cpp | 1 | ||||
-rw-r--r-- | src/test/script_p2sh_tests.cpp | 3 | ||||
-rw-r--r-- | src/test/script_standard_tests.cpp | 361 | ||||
-rw-r--r-- | src/wallet/ismine.cpp (renamed from src/script/ismine.cpp) | 13 | ||||
-rw-r--r-- | src/wallet/ismine.h (renamed from src/script/ismine.h) | 14 | ||||
-rw-r--r-- | src/wallet/test/ismine_tests.cpp | 399 | ||||
-rw-r--r-- | src/wallet/wallet.h | 2 | ||||
-rw-r--r-- | src/wallet/wallettool.h | 2 | ||||
-rwxr-xr-x | test/lint/lint-circular-dependencies.sh | 1 |
14 files changed, 425 insertions, 385 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index ec3d81b76f..39e8d3d689 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -181,7 +181,6 @@ BITCOIN_CORE_H = \ rpc/util.h \ scheduler.h \ script/descriptor.h \ - script/ismine.h \ script/sigcache.h \ script/sign.h \ script/standard.h \ @@ -223,6 +222,7 @@ BITCOIN_CORE_H = \ wallet/db.h \ wallet/feebumper.h \ wallet/fees.h \ + wallet/ismine.h \ wallet/load.h \ wallet/psbtwallet.h \ wallet/rpcwallet.h \ @@ -328,6 +328,7 @@ libbitcoin_wallet_a_SOURCES = \ wallet/db.cpp \ wallet/feebumper.cpp \ wallet/fees.cpp \ + wallet/ismine.cpp \ wallet/load.cpp \ wallet/psbtwallet.cpp \ wallet/rpcdump.cpp \ @@ -458,7 +459,6 @@ libbitcoin_common_a_SOURCES = \ rpc/util.cpp \ scheduler.cpp \ script/descriptor.cpp \ - script/ismine.cpp \ script/sign.cpp \ script/standard.cpp \ versionbitsinfo.cpp \ diff --git a/src/Makefile.test.include b/src/Makefile.test.include index c9c029818e..d3fe138133 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -167,7 +167,8 @@ BITCOIN_TESTS += \ wallet/test/wallet_tests.cpp \ wallet/test/wallet_crypto_tests.cpp \ wallet/test/coinselector_tests.cpp \ - wallet/test/init_tests.cpp + wallet/test/init_tests.cpp \ + wallet/test/ismine_tests.cpp BITCOIN_TEST_SUITE += \ wallet/test/wallet_test_fixture.cpp \ diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp index 240670cbe7..34c982e1e6 100644 --- a/src/interfaces/wallet.cpp +++ b/src/interfaces/wallet.cpp @@ -11,7 +11,6 @@ #include <policy/feerate.h> #include <policy/fees.h> #include <primitives/transaction.h> -#include <script/ismine.h> #include <script/standard.h> #include <support/allocators/secure.h> #include <sync.h> @@ -20,6 +19,7 @@ #include <util/system.h> #include <wallet/feebumper.h> #include <wallet/fees.h> +#include <wallet/ismine.h> #include <wallet/rpcwallet.h> #include <wallet/load.h> #include <wallet/wallet.h> diff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h index 7096f54047..9c9b29a813 100644 --- a/src/interfaces/wallet.h +++ b/src/interfaces/wallet.h @@ -7,7 +7,6 @@ #include <amount.h> // For CAmount #include <pubkey.h> // For CKeyID and CScriptID (definitions needed in CTxDestination instantiation) -#include <script/ismine.h> // For isminefilter, isminetype #include <script/standard.h> // For CTxDestination #include <support/allocators/secure.h> // For SecureString #include <ui_interface.h> // For ChangeType @@ -25,7 +24,10 @@ class CCoinControl; class CFeeRate; class CKey; class CWallet; +enum isminetype : unsigned int; enum class FeeReason; +typedef uint8_t isminefilter; + enum class OutputType; struct CRecipient; diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index aabe9dfb58..ebe7925368 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -21,6 +21,7 @@ #include <timedata.h> #include <util/system.h> #include <policy/policy.h> +#include <wallet/ismine.h> #include <stdint.h> #include <string> diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index 7d6d84aa7b..9de90759fa 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -7,6 +7,7 @@ #include <chain.h> #include <interfaces/wallet.h> #include <key_io.h> +#include <wallet/ismine.h> #include <stdint.h> diff --git a/src/test/script_p2sh_tests.cpp b/src/test/script_p2sh_tests.cpp index aa9c98c173..735b67c06e 100644 --- a/src/test/script_p2sh_tests.cpp +++ b/src/test/script_p2sh_tests.cpp @@ -11,7 +11,6 @@ #include <script/script_error.h> #include <policy/settings.h> #include <script/sign.h> -#include <script/ismine.h> #include <test/setup_common.h> #include <vector> @@ -98,7 +97,6 @@ BOOST_AUTO_TEST_CASE(sign) txTo[i].vin[0].prevout.n = i; txTo[i].vin[0].prevout.hash = txFrom.GetHash(); txTo[i].vout[0].nValue = 1; - BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i)); } for (int i = 0; i < 8; i++) { @@ -195,7 +193,6 @@ BOOST_AUTO_TEST_CASE(set) txTo[i].vin[0].prevout.hash = txFrom.GetHash(); txTo[i].vout[0].nValue = 1*CENT; txTo[i].vout[0].scriptPubKey = inner[i]; - BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i)); } for (int i = 0; i < 4; i++) { diff --git a/src/test/script_standard_tests.cpp b/src/test/script_standard_tests.cpp index 9f50083335..195283f89f 100644 --- a/src/test/script_standard_tests.cpp +++ b/src/test/script_standard_tests.cpp @@ -4,7 +4,6 @@ #include <key.h> #include <keystore.h> -#include <script/ismine.h> #include <script/script.h> #include <script/script_error.h> #include <script/standard.h> @@ -372,364 +371,4 @@ BOOST_AUTO_TEST_CASE(script_standard_GetScriptFor_) BOOST_CHECK(result == expected); } -BOOST_AUTO_TEST_CASE(script_standard_IsMine) -{ - CKey keys[2]; - CPubKey pubkeys[2]; - for (int i = 0; i < 2; i++) { - keys[i].MakeNewKey(true); - pubkeys[i] = keys[i].GetPubKey(); - } - - CKey uncompressedKey; - uncompressedKey.MakeNewKey(false); - CPubKey uncompressedPubkey = uncompressedKey.GetPubKey(); - - CScript scriptPubKey; - isminetype result; - - // P2PK compressed - { - CBasicKeyStore keystore; - scriptPubKey = GetScriptForRawPubKey(pubkeys[0]); - - // Keystore does not have key - result = IsMine(keystore, scriptPubKey); - BOOST_CHECK_EQUAL(result, ISMINE_NO); - - // Keystore has key - BOOST_CHECK(keystore.AddKey(keys[0])); - result = IsMine(keystore, scriptPubKey); - BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE); - } - - // P2PK uncompressed - { - CBasicKeyStore keystore; - scriptPubKey = GetScriptForRawPubKey(uncompressedPubkey); - - // Keystore does not have key - result = IsMine(keystore, scriptPubKey); - BOOST_CHECK_EQUAL(result, ISMINE_NO); - - // Keystore has key - BOOST_CHECK(keystore.AddKey(uncompressedKey)); - result = IsMine(keystore, scriptPubKey); - BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE); - } - - // P2PKH compressed - { - CBasicKeyStore keystore; - scriptPubKey = GetScriptForDestination(PKHash(pubkeys[0])); - - // Keystore does not have key - result = IsMine(keystore, scriptPubKey); - BOOST_CHECK_EQUAL(result, ISMINE_NO); - - // Keystore has key - BOOST_CHECK(keystore.AddKey(keys[0])); - result = IsMine(keystore, scriptPubKey); - BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE); - } - - // P2PKH uncompressed - { - CBasicKeyStore keystore; - scriptPubKey = GetScriptForDestination(PKHash(uncompressedPubkey)); - - // Keystore does not have key - result = IsMine(keystore, scriptPubKey); - BOOST_CHECK_EQUAL(result, ISMINE_NO); - - // Keystore has key - BOOST_CHECK(keystore.AddKey(uncompressedKey)); - result = IsMine(keystore, scriptPubKey); - BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE); - } - - // P2SH - { - CBasicKeyStore keystore; - - CScript redeemScript = GetScriptForDestination(PKHash(pubkeys[0])); - scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript)); - - // Keystore does not have redeemScript or key - result = IsMine(keystore, scriptPubKey); - BOOST_CHECK_EQUAL(result, ISMINE_NO); - - // Keystore has redeemScript but no key - BOOST_CHECK(keystore.AddCScript(redeemScript)); - result = IsMine(keystore, scriptPubKey); - BOOST_CHECK_EQUAL(result, ISMINE_NO); - - // Keystore has redeemScript and key - BOOST_CHECK(keystore.AddKey(keys[0])); - result = IsMine(keystore, scriptPubKey); - BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE); - } - - // (P2PKH inside) P2SH inside P2SH (invalid) - { - CBasicKeyStore keystore; - - CScript redeemscript_inner = GetScriptForDestination(PKHash(pubkeys[0])); - CScript redeemscript = GetScriptForDestination(ScriptHash(redeemscript_inner)); - scriptPubKey = GetScriptForDestination(ScriptHash(redeemscript)); - - BOOST_CHECK(keystore.AddCScript(redeemscript)); - BOOST_CHECK(keystore.AddCScript(redeemscript_inner)); - BOOST_CHECK(keystore.AddCScript(scriptPubKey)); - BOOST_CHECK(keystore.AddKey(keys[0])); - result = IsMine(keystore, scriptPubKey); - BOOST_CHECK_EQUAL(result, ISMINE_NO); - } - - // (P2PKH inside) P2SH inside P2WSH (invalid) - { - CBasicKeyStore keystore; - - CScript redeemscript = GetScriptForDestination(PKHash(pubkeys[0])); - CScript witnessscript = GetScriptForDestination(ScriptHash(redeemscript)); - scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessscript)); - - BOOST_CHECK(keystore.AddCScript(witnessscript)); - BOOST_CHECK(keystore.AddCScript(redeemscript)); - BOOST_CHECK(keystore.AddCScript(scriptPubKey)); - BOOST_CHECK(keystore.AddKey(keys[0])); - result = IsMine(keystore, scriptPubKey); - BOOST_CHECK_EQUAL(result, ISMINE_NO); - } - - // P2WPKH inside P2WSH (invalid) - { - CBasicKeyStore keystore; - - CScript witnessscript = GetScriptForDestination(WitnessV0KeyHash(PKHash(pubkeys[0]))); - scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessscript)); - - BOOST_CHECK(keystore.AddCScript(witnessscript)); - BOOST_CHECK(keystore.AddCScript(scriptPubKey)); - BOOST_CHECK(keystore.AddKey(keys[0])); - result = IsMine(keystore, scriptPubKey); - BOOST_CHECK_EQUAL(result, ISMINE_NO); - } - - // (P2PKH inside) P2WSH inside P2WSH (invalid) - { - CBasicKeyStore keystore; - - CScript witnessscript_inner = GetScriptForDestination(PKHash(pubkeys[0])); - CScript witnessscript = GetScriptForDestination(WitnessV0ScriptHash(witnessscript_inner)); - scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessscript)); - - BOOST_CHECK(keystore.AddCScript(witnessscript_inner)); - BOOST_CHECK(keystore.AddCScript(witnessscript)); - BOOST_CHECK(keystore.AddCScript(scriptPubKey)); - BOOST_CHECK(keystore.AddKey(keys[0])); - result = IsMine(keystore, scriptPubKey); - BOOST_CHECK_EQUAL(result, ISMINE_NO); - } - - // P2WPKH compressed - { - CBasicKeyStore keystore; - BOOST_CHECK(keystore.AddKey(keys[0])); - - scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(PKHash(pubkeys[0]))); - - // Keystore implicitly has key and P2SH redeemScript - BOOST_CHECK(keystore.AddCScript(scriptPubKey)); - result = IsMine(keystore, scriptPubKey); - BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE); - } - - // P2WPKH uncompressed - { - CBasicKeyStore keystore; - BOOST_CHECK(keystore.AddKey(uncompressedKey)); - - scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(PKHash(uncompressedPubkey))); - - // Keystore has key, but no P2SH redeemScript - result = IsMine(keystore, scriptPubKey); - BOOST_CHECK_EQUAL(result, ISMINE_NO); - - // Keystore has key and P2SH redeemScript - BOOST_CHECK(keystore.AddCScript(scriptPubKey)); - result = IsMine(keystore, scriptPubKey); - BOOST_CHECK_EQUAL(result, ISMINE_NO); - } - - // scriptPubKey multisig - { - CBasicKeyStore keystore; - - scriptPubKey = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]}); - - // Keystore does not have any keys - result = IsMine(keystore, scriptPubKey); - BOOST_CHECK_EQUAL(result, ISMINE_NO); - - // Keystore has 1/2 keys - BOOST_CHECK(keystore.AddKey(uncompressedKey)); - - result = IsMine(keystore, scriptPubKey); - BOOST_CHECK_EQUAL(result, ISMINE_NO); - - // Keystore has 2/2 keys - BOOST_CHECK(keystore.AddKey(keys[1])); - - result = IsMine(keystore, scriptPubKey); - BOOST_CHECK_EQUAL(result, ISMINE_NO); - - // Keystore has 2/2 keys and the script - BOOST_CHECK(keystore.AddCScript(scriptPubKey)); - - result = IsMine(keystore, scriptPubKey); - BOOST_CHECK_EQUAL(result, ISMINE_NO); - } - - // P2SH multisig - { - CBasicKeyStore keystore; - BOOST_CHECK(keystore.AddKey(uncompressedKey)); - BOOST_CHECK(keystore.AddKey(keys[1])); - - CScript redeemScript = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]}); - scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript)); - - // Keystore has no redeemScript - result = IsMine(keystore, scriptPubKey); - BOOST_CHECK_EQUAL(result, ISMINE_NO); - - // Keystore has redeemScript - BOOST_CHECK(keystore.AddCScript(redeemScript)); - result = IsMine(keystore, scriptPubKey); - BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE); - } - - // P2WSH multisig with compressed keys - { - CBasicKeyStore keystore; - BOOST_CHECK(keystore.AddKey(keys[0])); - BOOST_CHECK(keystore.AddKey(keys[1])); - - CScript witnessScript = GetScriptForMultisig(2, {pubkeys[0], pubkeys[1]}); - scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessScript)); - - // Keystore has keys, but no witnessScript or P2SH redeemScript - result = IsMine(keystore, scriptPubKey); - BOOST_CHECK_EQUAL(result, ISMINE_NO); - - // Keystore has keys and witnessScript, but no P2SH redeemScript - BOOST_CHECK(keystore.AddCScript(witnessScript)); - result = IsMine(keystore, scriptPubKey); - BOOST_CHECK_EQUAL(result, ISMINE_NO); - - // Keystore has keys, witnessScript, P2SH redeemScript - BOOST_CHECK(keystore.AddCScript(scriptPubKey)); - result = IsMine(keystore, scriptPubKey); - BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE); - } - - // P2WSH multisig with uncompressed key - { - CBasicKeyStore keystore; - BOOST_CHECK(keystore.AddKey(uncompressedKey)); - BOOST_CHECK(keystore.AddKey(keys[1])); - - CScript witnessScript = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]}); - scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessScript)); - - // Keystore has keys, but no witnessScript or P2SH redeemScript - result = IsMine(keystore, scriptPubKey); - BOOST_CHECK_EQUAL(result, ISMINE_NO); - - // Keystore has keys and witnessScript, but no P2SH redeemScript - BOOST_CHECK(keystore.AddCScript(witnessScript)); - result = IsMine(keystore, scriptPubKey); - BOOST_CHECK_EQUAL(result, ISMINE_NO); - - // Keystore has keys, witnessScript, P2SH redeemScript - BOOST_CHECK(keystore.AddCScript(scriptPubKey)); - result = IsMine(keystore, scriptPubKey); - BOOST_CHECK_EQUAL(result, ISMINE_NO); - } - - // P2WSH multisig wrapped in P2SH - { - CBasicKeyStore keystore; - - CScript witnessScript = GetScriptForMultisig(2, {pubkeys[0], pubkeys[1]}); - CScript redeemScript = GetScriptForDestination(WitnessV0ScriptHash(witnessScript)); - scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript)); - - // Keystore has no witnessScript, P2SH redeemScript, or keys - result = IsMine(keystore, scriptPubKey); - BOOST_CHECK_EQUAL(result, ISMINE_NO); - - // Keystore has witnessScript and P2SH redeemScript, but no keys - BOOST_CHECK(keystore.AddCScript(redeemScript)); - BOOST_CHECK(keystore.AddCScript(witnessScript)); - result = IsMine(keystore, scriptPubKey); - BOOST_CHECK_EQUAL(result, ISMINE_NO); - - // Keystore has keys, witnessScript, P2SH redeemScript - BOOST_CHECK(keystore.AddKey(keys[0])); - BOOST_CHECK(keystore.AddKey(keys[1])); - result = IsMine(keystore, scriptPubKey); - BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE); - } - - // OP_RETURN - { - CBasicKeyStore keystore; - BOOST_CHECK(keystore.AddKey(keys[0])); - - scriptPubKey.clear(); - scriptPubKey << OP_RETURN << ToByteVector(pubkeys[0]); - - result = IsMine(keystore, scriptPubKey); - BOOST_CHECK_EQUAL(result, ISMINE_NO); - } - - // witness unspendable - { - CBasicKeyStore keystore; - BOOST_CHECK(keystore.AddKey(keys[0])); - - scriptPubKey.clear(); - scriptPubKey << OP_0 << ToByteVector(ParseHex("aabb")); - - result = IsMine(keystore, scriptPubKey); - BOOST_CHECK_EQUAL(result, ISMINE_NO); - } - - // witness unknown - { - CBasicKeyStore keystore; - BOOST_CHECK(keystore.AddKey(keys[0])); - - scriptPubKey.clear(); - scriptPubKey << OP_16 << ToByteVector(ParseHex("aabb")); - - result = IsMine(keystore, scriptPubKey); - BOOST_CHECK_EQUAL(result, ISMINE_NO); - } - - // Nonstandard - { - CBasicKeyStore keystore; - BOOST_CHECK(keystore.AddKey(keys[0])); - - scriptPubKey.clear(); - scriptPubKey << OP_9 << OP_ADD << OP_11 << OP_EQUAL; - - result = IsMine(keystore, scriptPubKey); - BOOST_CHECK_EQUAL(result, ISMINE_NO); - } -} - BOOST_AUTO_TEST_SUITE_END() diff --git a/src/script/ismine.cpp b/src/wallet/ismine.cpp index 75fc2e84f1..6138d4ae44 100644 --- a/src/script/ismine.cpp +++ b/src/wallet/ismine.cpp @@ -3,13 +3,12 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <script/ismine.h> +#include <wallet/ismine.h> #include <key.h> -#include <keystore.h> #include <script/script.h> #include <script/sign.h> - +#include <wallet/wallet.h> typedef std::vector<unsigned char> valtype; @@ -46,7 +45,7 @@ bool PermitsUncompressed(IsMineSigVersion sigversion) return sigversion == IsMineSigVersion::TOP || sigversion == IsMineSigVersion::P2SH; } -bool HaveKeys(const std::vector<valtype>& pubkeys, const CKeyStore& keystore) +bool HaveKeys(const std::vector<valtype>& pubkeys, const CWallet& keystore) { for (const valtype& pubkey : pubkeys) { CKeyID keyID = CPubKey(pubkey).GetID(); @@ -55,7 +54,7 @@ bool HaveKeys(const std::vector<valtype>& pubkeys, const CKeyStore& keystore) return true; } -IsMineResult IsMineInner(const CKeyStore& keystore, const CScript& scriptPubKey, IsMineSigVersion sigversion) +IsMineResult IsMineInner(const CWallet& keystore, const CScript& scriptPubKey, IsMineSigVersion sigversion) { IsMineResult ret = IsMineResult::NO; @@ -172,7 +171,7 @@ IsMineResult IsMineInner(const CKeyStore& keystore, const CScript& scriptPubKey, } // namespace -isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey) +isminetype IsMine(const CWallet& keystore, const CScript& scriptPubKey) { switch (IsMineInner(keystore, scriptPubKey, IsMineSigVersion::TOP)) { case IsMineResult::INVALID: @@ -186,7 +185,7 @@ isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey) assert(false); } -isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest) +isminetype IsMine(const CWallet& keystore, const CTxDestination& dest) { CScript script = GetScriptForDestination(dest); return IsMine(keystore, script); diff --git a/src/script/ismine.h b/src/wallet/ismine.h index da3da7e324..41555fcb93 100644 --- a/src/script/ismine.h +++ b/src/wallet/ismine.h @@ -3,19 +3,19 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifndef BITCOIN_SCRIPT_ISMINE_H -#define BITCOIN_SCRIPT_ISMINE_H +#ifndef BITCOIN_WALLET_ISMINE_H +#define BITCOIN_WALLET_ISMINE_H #include <script/standard.h> #include <stdint.h> #include <bitset> -class CKeyStore; +class CWallet; class CScript; /** IsMine() return codes */ -enum isminetype +enum isminetype : unsigned int { ISMINE_NO = 0, ISMINE_WATCH_ONLY = 1 << 0, @@ -28,8 +28,8 @@ enum isminetype /** used for bitflags of isminetype */ typedef uint8_t isminefilter; -isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey); -isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest); +isminetype IsMine(const CWallet& wallet, const CScript& scriptPubKey); +isminetype IsMine(const CWallet& wallet, const CTxDestination& dest); /** * Cachable amount subdivided into watchonly and spendable parts. @@ -50,4 +50,4 @@ struct CachableAmount } }; -#endif // BITCOIN_SCRIPT_ISMINE_H +#endif // BITCOIN_WALLET_ISMINE_H diff --git a/src/wallet/test/ismine_tests.cpp b/src/wallet/test/ismine_tests.cpp new file mode 100644 index 0000000000..0cae055676 --- /dev/null +++ b/src/wallet/test/ismine_tests.cpp @@ -0,0 +1,399 @@ +// Copyright (c) 2017-2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <key.h> +#include <script/script.h> +#include <script/script_error.h> +#include <script/standard.h> +#include <test/setup_common.h> +#include <wallet/ismine.h> +#include <wallet/wallet.h> + +#include <boost/test/unit_test.hpp> + + +BOOST_FIXTURE_TEST_SUITE(ismine_tests, BasicTestingSetup) + +BOOST_AUTO_TEST_CASE(ismine_standard) +{ + CKey keys[2]; + CPubKey pubkeys[2]; + for (int i = 0; i < 2; i++) { + keys[i].MakeNewKey(true); + pubkeys[i] = keys[i].GetPubKey(); + } + + CKey uncompressedKey; + uncompressedKey.MakeNewKey(false); + CPubKey uncompressedPubkey = uncompressedKey.GetPubKey(); + std::unique_ptr<interfaces::Chain> chain = interfaces::MakeChain(); + + CScript scriptPubKey; + isminetype result; + + // P2PK compressed + { + CWallet keystore(chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); + LOCK(keystore.cs_wallet); + scriptPubKey = GetScriptForRawPubKey(pubkeys[0]); + + // Keystore does not have key + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_NO); + + // Keystore has key + BOOST_CHECK(keystore.AddKey(keys[0])); + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE); + } + + // P2PK uncompressed + { + CWallet keystore(chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); + LOCK(keystore.cs_wallet); + scriptPubKey = GetScriptForRawPubKey(uncompressedPubkey); + + // Keystore does not have key + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_NO); + + // Keystore has key + BOOST_CHECK(keystore.AddKey(uncompressedKey)); + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE); + } + + // P2PKH compressed + { + CWallet keystore(chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); + LOCK(keystore.cs_wallet); + scriptPubKey = GetScriptForDestination(PKHash(pubkeys[0])); + + // Keystore does not have key + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_NO); + + // Keystore has key + BOOST_CHECK(keystore.AddKey(keys[0])); + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE); + } + + // P2PKH uncompressed + { + CWallet keystore(chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); + LOCK(keystore.cs_wallet); + scriptPubKey = GetScriptForDestination(PKHash(uncompressedPubkey)); + + // Keystore does not have key + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_NO); + + // Keystore has key + BOOST_CHECK(keystore.AddKey(uncompressedKey)); + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE); + } + + // P2SH + { + CWallet keystore(chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); + LOCK(keystore.cs_wallet); + + CScript redeemScript = GetScriptForDestination(PKHash(pubkeys[0])); + scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript)); + + // Keystore does not have redeemScript or key + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_NO); + + // Keystore has redeemScript but no key + BOOST_CHECK(keystore.AddCScript(redeemScript)); + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_NO); + + // Keystore has redeemScript and key + BOOST_CHECK(keystore.AddKey(keys[0])); + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE); + } + + // (P2PKH inside) P2SH inside P2SH (invalid) + { + CWallet keystore(chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); + LOCK(keystore.cs_wallet); + + CScript redeemscript_inner = GetScriptForDestination(PKHash(pubkeys[0])); + CScript redeemscript = GetScriptForDestination(ScriptHash(redeemscript_inner)); + scriptPubKey = GetScriptForDestination(ScriptHash(redeemscript)); + + BOOST_CHECK(keystore.AddCScript(redeemscript)); + BOOST_CHECK(keystore.AddCScript(redeemscript_inner)); + BOOST_CHECK(keystore.AddCScript(scriptPubKey)); + BOOST_CHECK(keystore.AddKey(keys[0])); + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_NO); + } + + // (P2PKH inside) P2SH inside P2WSH (invalid) + { + CWallet keystore(chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); + LOCK(keystore.cs_wallet); + + CScript redeemscript = GetScriptForDestination(PKHash(pubkeys[0])); + CScript witnessscript = GetScriptForDestination(ScriptHash(redeemscript)); + scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessscript)); + + BOOST_CHECK(keystore.AddCScript(witnessscript)); + BOOST_CHECK(keystore.AddCScript(redeemscript)); + BOOST_CHECK(keystore.AddCScript(scriptPubKey)); + BOOST_CHECK(keystore.AddKey(keys[0])); + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_NO); + } + + // P2WPKH inside P2WSH (invalid) + { + CWallet keystore(chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); + LOCK(keystore.cs_wallet); + + CScript witnessscript = GetScriptForDestination(WitnessV0KeyHash(PKHash(pubkeys[0]))); + scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessscript)); + + BOOST_CHECK(keystore.AddCScript(witnessscript)); + BOOST_CHECK(keystore.AddCScript(scriptPubKey)); + BOOST_CHECK(keystore.AddKey(keys[0])); + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_NO); + } + + // (P2PKH inside) P2WSH inside P2WSH (invalid) + { + CWallet keystore(chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); + LOCK(keystore.cs_wallet); + + CScript witnessscript_inner = GetScriptForDestination(PKHash(pubkeys[0])); + CScript witnessscript = GetScriptForDestination(WitnessV0ScriptHash(witnessscript_inner)); + scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessscript)); + + BOOST_CHECK(keystore.AddCScript(witnessscript_inner)); + BOOST_CHECK(keystore.AddCScript(witnessscript)); + BOOST_CHECK(keystore.AddCScript(scriptPubKey)); + BOOST_CHECK(keystore.AddKey(keys[0])); + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_NO); + } + + // P2WPKH compressed + { + CWallet keystore(chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); + LOCK(keystore.cs_wallet); + BOOST_CHECK(keystore.AddKey(keys[0])); + + scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(PKHash(pubkeys[0]))); + + // Keystore implicitly has key and P2SH redeemScript + BOOST_CHECK(keystore.AddCScript(scriptPubKey)); + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE); + } + + // P2WPKH uncompressed + { + CWallet keystore(chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); + LOCK(keystore.cs_wallet); + BOOST_CHECK(keystore.AddKey(uncompressedKey)); + + scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(PKHash(uncompressedPubkey))); + + // Keystore has key, but no P2SH redeemScript + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_NO); + + // Keystore has key and P2SH redeemScript + BOOST_CHECK(keystore.AddCScript(scriptPubKey)); + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_NO); + } + + // scriptPubKey multisig + { + CWallet keystore(chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); + LOCK(keystore.cs_wallet); + + scriptPubKey = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]}); + + // Keystore does not have any keys + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_NO); + + // Keystore has 1/2 keys + BOOST_CHECK(keystore.AddKey(uncompressedKey)); + + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_NO); + + // Keystore has 2/2 keys + BOOST_CHECK(keystore.AddKey(keys[1])); + + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_NO); + + // Keystore has 2/2 keys and the script + BOOST_CHECK(keystore.AddCScript(scriptPubKey)); + + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_NO); + } + + // P2SH multisig + { + CWallet keystore(chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); + LOCK(keystore.cs_wallet); + BOOST_CHECK(keystore.AddKey(uncompressedKey)); + BOOST_CHECK(keystore.AddKey(keys[1])); + + CScript redeemScript = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]}); + scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript)); + + // Keystore has no redeemScript + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_NO); + + // Keystore has redeemScript + BOOST_CHECK(keystore.AddCScript(redeemScript)); + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE); + } + + // P2WSH multisig with compressed keys + { + CWallet keystore(chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); + LOCK(keystore.cs_wallet); + BOOST_CHECK(keystore.AddKey(keys[0])); + BOOST_CHECK(keystore.AddKey(keys[1])); + + CScript witnessScript = GetScriptForMultisig(2, {pubkeys[0], pubkeys[1]}); + scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessScript)); + + // Keystore has keys, but no witnessScript or P2SH redeemScript + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_NO); + + // Keystore has keys and witnessScript, but no P2SH redeemScript + BOOST_CHECK(keystore.AddCScript(witnessScript)); + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_NO); + + // Keystore has keys, witnessScript, P2SH redeemScript + BOOST_CHECK(keystore.AddCScript(scriptPubKey)); + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE); + } + + // P2WSH multisig with uncompressed key + { + CWallet keystore(chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); + LOCK(keystore.cs_wallet); + BOOST_CHECK(keystore.AddKey(uncompressedKey)); + BOOST_CHECK(keystore.AddKey(keys[1])); + + CScript witnessScript = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]}); + scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessScript)); + + // Keystore has keys, but no witnessScript or P2SH redeemScript + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_NO); + + // Keystore has keys and witnessScript, but no P2SH redeemScript + BOOST_CHECK(keystore.AddCScript(witnessScript)); + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_NO); + + // Keystore has keys, witnessScript, P2SH redeemScript + BOOST_CHECK(keystore.AddCScript(scriptPubKey)); + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_NO); + } + + // P2WSH multisig wrapped in P2SH + { + CWallet keystore(chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); + LOCK(keystore.cs_wallet); + + CScript witnessScript = GetScriptForMultisig(2, {pubkeys[0], pubkeys[1]}); + CScript redeemScript = GetScriptForDestination(WitnessV0ScriptHash(witnessScript)); + scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript)); + + // Keystore has no witnessScript, P2SH redeemScript, or keys + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_NO); + + // Keystore has witnessScript and P2SH redeemScript, but no keys + BOOST_CHECK(keystore.AddCScript(redeemScript)); + BOOST_CHECK(keystore.AddCScript(witnessScript)); + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_NO); + + // Keystore has keys, witnessScript, P2SH redeemScript + BOOST_CHECK(keystore.AddKey(keys[0])); + BOOST_CHECK(keystore.AddKey(keys[1])); + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE); + } + + // OP_RETURN + { + CWallet keystore(chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); + LOCK(keystore.cs_wallet); + BOOST_CHECK(keystore.AddKey(keys[0])); + + scriptPubKey.clear(); + scriptPubKey << OP_RETURN << ToByteVector(pubkeys[0]); + + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_NO); + } + + // witness unspendable + { + CWallet keystore(chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); + LOCK(keystore.cs_wallet); + BOOST_CHECK(keystore.AddKey(keys[0])); + + scriptPubKey.clear(); + scriptPubKey << OP_0 << ToByteVector(ParseHex("aabb")); + + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_NO); + } + + // witness unknown + { + CWallet keystore(chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); + LOCK(keystore.cs_wallet); + BOOST_CHECK(keystore.AddKey(keys[0])); + + scriptPubKey.clear(); + scriptPubKey << OP_16 << ToByteVector(ParseHex("aabb")); + + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_NO); + } + + // Nonstandard + { + CWallet keystore(chain.get(), WalletLocation(), WalletDatabase::CreateDummy()); + LOCK(keystore.cs_wallet); + BOOST_CHECK(keystore.AddKey(keys[0])); + + scriptPubKey.clear(); + scriptPubKey << OP_9 << OP_ADD << OP_11 << OP_EQUAL; + + result = IsMine(keystore, scriptPubKey); + BOOST_CHECK_EQUAL(result, ISMINE_NO); + } +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index c2d1102c33..7b5465c219 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -11,7 +11,6 @@ #include <interfaces/handler.h> #include <outputtype.h> #include <policy/feerate.h> -#include <script/ismine.h> #include <script/sign.h> #include <streams.h> #include <tinyformat.h> @@ -21,6 +20,7 @@ #include <validationinterface.h> #include <wallet/coinselection.h> #include <wallet/crypter.h> +#include <wallet/ismine.h> #include <wallet/walletdb.h> #include <wallet/walletutil.h> diff --git a/src/wallet/wallettool.h b/src/wallet/wallettool.h index da848a747b..7ee2505631 100644 --- a/src/wallet/wallettool.h +++ b/src/wallet/wallettool.h @@ -5,7 +5,7 @@ #ifndef BITCOIN_WALLET_WALLETTOOL_H #define BITCOIN_WALLET_WALLETTOOL_H -#include <script/ismine.h> +#include <wallet/ismine.h> #include <wallet/wallet.h> namespace WalletTool { diff --git a/test/lint/lint-circular-dependencies.sh b/test/lint/lint-circular-dependencies.sh index 2701015c79..70cc16337e 100755 --- a/test/lint/lint-circular-dependencies.sh +++ b/test/lint/lint-circular-dependencies.sh @@ -30,6 +30,7 @@ EXPECTED_CIRCULAR_DEPENDENCIES=( "policy/fees -> txmempool -> validation -> policy/fees" "qt/guiutil -> qt/walletmodel -> qt/optionsmodel -> qt/guiutil" "txmempool -> validation -> validationinterface -> txmempool" + "wallet/ismine -> wallet/wallet -> wallet/ismine" ) EXIT_CODE=0 |