aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml11
-rw-r--r--Makefile.am2
-rw-r--r--build_msvc/common.init.vcxproj2
-rw-r--r--src/Makefile.am4
-rw-r--r--src/Makefile.test.include3
-rw-r--r--src/interfaces/wallet.cpp2
-rw-r--r--src/interfaces/wallet.h4
-rw-r--r--src/qt/transactiondesc.cpp1
-rw-r--r--src/qt/transactionrecord.cpp1
-rw-r--r--src/rpc/misc.cpp4
-rw-r--r--src/rpc/util.cpp24
-rw-r--r--src/rpc/util.h3
-rw-r--r--src/test/script_p2sh_tests.cpp3
-rw-r--r--src/test/script_standard_tests.cpp361
-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/rpcwallet.cpp4
-rw-r--r--src/wallet/test/ismine_tests.cpp399
-rw-r--r--src/wallet/wallet.h2
-rw-r--r--src/wallet/wallettool.h2
-rwxr-xr-xtest/functional/feature_config_args.py10
-rwxr-xr-xtest/functional/rpc_createmultisig.py30
-rwxr-xr-xtest/lint/lint-circular-dependencies.sh1
23 files changed, 498 insertions, 402 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index 9104a0a3d1..ce17a223b1 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -2,15 +2,18 @@ task:
name: "FreeBsd 12.0 amd64 [GOAL: install] [no depends, only system libs]"
freebsd_instance:
image: freebsd-12-0-release-amd64
- ccache_cache:
- folder: "/tmp/ccache_dir"
+ cpu: 8
+ memory: 8G
+ timeout_in: 60m
env:
- MAKEJOBS: "-j3"
+ MAKEJOBS: "-j9"
CONFIGURE_OPTS: "--disable-dependency-tracking"
GOAL: "install"
CCACHE_SIZE: "200M"
CCACHE_COMPRESS: 1
CCACHE_DIR: "/tmp/ccache_dir"
+ ccache_cache:
+ folder: "/tmp/ccache_dir"
install_script:
- pkg install -y autoconf automake boost-libs git gmake libevent libtool openssl pkgconf python3 ccache
- ./contrib/install_db4.sh $(pwd)
@@ -23,4 +26,4 @@ task:
check_script:
- gmake check ${MAKEJOBS} VERBOSE=1
functional_test_script:
- - ./test/functional/test_runner.py --ci --combinedlogslen=1000 --quiet --failfast
+ - ./test/functional/test_runner.py --jobs 9 --ci --extended --exclude feature_dbcrash --combinedlogslen=1000 --quiet --failfast
diff --git a/Makefile.am b/Makefile.am
index ec0743c3fa..712f2a454d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -198,7 +198,7 @@ test_bitcoin_filtered.info: test_bitcoin.info
$(LCOV) -a $@ $(LCOV_OPTS) -o $@
functional_test.info: test_bitcoin_filtered.info
- -@TIMEOUT=15 test/functional/test_runner.py $(EXTENDED_FUNCTIONAL_TESTS)
+ @TIMEOUT=15 test/functional/test_runner.py $(EXTENDED_FUNCTIONAL_TESTS)
$(LCOV) -c $(LCOV_OPTS) -d $(abs_builddir)/src --t functional-tests -o $@
$(LCOV) -z $(LCOV_OPTS) -d $(abs_builddir)/src
diff --git a/build_msvc/common.init.vcxproj b/build_msvc/common.init.vcxproj
index 2b2afcdf13..8b6217e2b0 100644
--- a/build_msvc/common.init.vcxproj
+++ b/build_msvc/common.init.vcxproj
@@ -73,6 +73,7 @@
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -94,6 +95,7 @@
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
</ItemDefinitionGroup>
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/rpc/misc.cpp b/src/rpc/misc.cpp
index 2b29fd543b..7a1bdec7b9 100644
--- a/src/rpc/misc.cpp
+++ b/src/rpc/misc.cpp
@@ -122,9 +122,9 @@ static UniValue createmultisig(const JSONRPCRequest& request)
}
// Construct using pay-to-script-hash:
- const CScript inner = CreateMultisigRedeemscript(required, pubkeys);
CBasicKeyStore keystore;
- const CTxDestination dest = AddAndGetDestinationForScript(keystore, inner, output_type);
+ CScript inner;
+ const CTxDestination dest = AddAndGetMultisigDestination(required, pubkeys, output_type, keystore, inner);
UniValue result(UniValue::VOBJ);
result.pushKV("address", EncodeDestination(dest));
diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp
index 9cdb22001f..4642cf16b1 100644
--- a/src/rpc/util.cpp
+++ b/src/rpc/util.cpp
@@ -4,6 +4,7 @@
#include <key_io.h>
#include <keystore.h>
+#include <outputtype.h>
#include <rpc/util.h>
#include <tinyformat.h>
#include <util/strencodings.h>
@@ -150,8 +151,8 @@ CPubKey AddrToPubKey(CKeyStore* const keystore, const std::string& addr_in)
return vchPubKey;
}
-// Creates a multisig redeemscript from a given list of public keys and number required.
-CScript CreateMultisigRedeemscript(const int required, const std::vector<CPubKey>& pubkeys)
+// Creates a multisig address from a given list of public keys, number of signatures required, and the address type
+CTxDestination AddAndGetMultisigDestination(const int required, const std::vector<CPubKey>& pubkeys, OutputType type, CKeyStore& keystore, CScript& script_out)
{
// Gather public keys
if (required < 1) {
@@ -164,13 +165,24 @@ CScript CreateMultisigRedeemscript(const int required, const std::vector<CPubKey
throw JSONRPCError(RPC_INVALID_PARAMETER, "Number of keys involved in the multisignature address creation > 16\nReduce the number");
}
- CScript result = GetScriptForMultisig(required, pubkeys);
+ script_out = GetScriptForMultisig(required, pubkeys);
- if (result.size() > MAX_SCRIPT_ELEMENT_SIZE) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, (strprintf("redeemScript exceeds size limit: %d > %d", result.size(), MAX_SCRIPT_ELEMENT_SIZE)));
+ if (script_out.size() > MAX_SCRIPT_ELEMENT_SIZE) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, (strprintf("redeemScript exceeds size limit: %d > %d", script_out.size(), MAX_SCRIPT_ELEMENT_SIZE)));
}
- return result;
+ // Check if any keys are uncompressed. If so, the type is legacy
+ for (const CPubKey& pk : pubkeys) {
+ if (!pk.IsCompressed()) {
+ type = OutputType::LEGACY;
+ break;
+ }
+ }
+
+ // Make the address
+ CTxDestination dest = AddAndGetDestinationForScript(keystore, script_out, type);
+
+ return dest;
}
class DescribeAddressVisitor : public boost::static_visitor<UniValue>
diff --git a/src/rpc/util.h b/src/rpc/util.h
index e4fa8fc3d7..0eb2fef5c3 100644
--- a/src/rpc/util.h
+++ b/src/rpc/util.h
@@ -6,6 +6,7 @@
#define BITCOIN_RPC_UTIL_H
#include <node/transaction.h>
+#include <outputtype.h>
#include <pubkey.h>
#include <rpc/protocol.h>
#include <script/standard.h>
@@ -70,7 +71,7 @@ extern std::string HelpExampleRpc(const std::string& methodname, const std::stri
CPubKey HexToPubKey(const std::string& hex_in);
CPubKey AddrToPubKey(CKeyStore* const keystore, const std::string& addr_in);
-CScript CreateMultisigRedeemscript(const int required, const std::vector<CPubKey>& pubkeys);
+CTxDestination AddAndGetMultisigDestination(const int required, const std::vector<CPubKey>& pubkeys, OutputType type, CKeyStore& keystore, CScript& script_out);
UniValue DescribeAddress(const CTxDestination& dest);
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/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index cfa36ad40c..3232c65bca 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -1036,8 +1036,8 @@ static UniValue addmultisigaddress(const JSONRPCRequest& request)
}
// Construct using pay-to-script-hash:
- CScript inner = CreateMultisigRedeemscript(required, pubkeys);
- CTxDestination dest = AddAndGetDestinationForScript(*pwallet, inner, output_type);
+ CScript inner;
+ CTxDestination dest = AddAndGetMultisigDestination(required, pubkeys, output_type, *pwallet, inner);
pwallet->SetAddressBook(dest, label, "send");
UniValue result(UniValue::VOBJ);
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/functional/feature_config_args.py b/test/functional/feature_config_args.py
index 074a832594..f0d6bc21e6 100755
--- a/test/functional/feature_config_args.py
+++ b/test/functional/feature_config_args.py
@@ -21,6 +21,16 @@ class ConfArgsTest(BitcoinTestFramework):
with open(os.path.join(self.nodes[0].datadir, 'bitcoin.conf'), 'a', encoding='utf-8') as conf:
conf.write('includeconf={}\n'.format(inc_conf_file_path))
+ self.nodes[0].assert_start_raises_init_error(
+ expected_msg='Error parsing command line arguments: Invalid parameter -dash_cli',
+ extra_args=['-dash_cli=1'],
+ )
+ with open(inc_conf_file_path, 'w', encoding='utf-8') as conf:
+ conf.write('dash_conf=1\n')
+ with self.nodes[0].assert_debug_log(expected_msgs=['Ignoring unknown configuration value dash_conf']):
+ self.start_node(0)
+ self.stop_node(0)
+
with open(inc_conf_file_path, 'w', encoding='utf-8') as conf:
conf.write('-dash=1\n')
self.nodes[0].assert_start_raises_init_error(expected_msg='Error reading configuration file: parse error on line 1: -dash=1, options in configuration file must be specified without leading -')
diff --git a/test/functional/rpc_createmultisig.py b/test/functional/rpc_createmultisig.py
index 7abcd71bb8..58010f7c2e 100755
--- a/test/functional/rpc_createmultisig.py
+++ b/test/functional/rpc_createmultisig.py
@@ -7,9 +7,13 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_raises_rpc_error,
+ assert_equal,
)
-import decimal
+from test_framework.key import ECPubKey
+import binascii
+import decimal
+import itertools
class RpcCreateMultiSigTest(BitcoinTestFramework):
def set_test_params(self):
@@ -44,6 +48,30 @@ class RpcCreateMultiSigTest(BitcoinTestFramework):
self.checkbalances()
+ # Test mixed compressed and uncompressed pubkeys
+ self.log.info('Mixed compressed and uncompressed multisigs are not allowed')
+ pk0 = node0.getaddressinfo(node0.getnewaddress())['pubkey']
+ pk1 = node1.getaddressinfo(node1.getnewaddress())['pubkey']
+ pk2 = node2.getaddressinfo(node2.getnewaddress())['pubkey']
+
+ # decompress pk2
+ pk_obj = ECPubKey()
+ pk_obj.set(binascii.unhexlify(pk2))
+ pk_obj.compressed = False
+ pk2 = binascii.hexlify(pk_obj.get_bytes()).decode()
+
+ # Check all permutations of keys because order matters apparently
+ for keys in itertools.permutations([pk0, pk1, pk2]):
+ # Results should be the same as this legacy one
+ legacy_addr = node0.createmultisig(2, keys, 'legacy')['address']
+ assert_equal(legacy_addr, node0.addmultisigaddress(2, keys, '', 'legacy')['address'])
+
+ # Generate addresses with the segwit types. These should all make legacy addresses
+ assert_equal(legacy_addr, node0.createmultisig(2, keys, 'bech32')['address'])
+ assert_equal(legacy_addr, node0.createmultisig(2, keys, 'p2sh-segwit')['address'])
+ assert_equal(legacy_addr, node0.addmultisigaddress(2, keys, '', 'bech32')['address'])
+ assert_equal(legacy_addr, node0.addmultisigaddress(2, keys, '', 'p2sh-segwit')['address'])
+
def check_addmultisigaddress_errors(self):
self.log.info('Check that addmultisigaddress fails when the private keys are missing')
addresses = [self.nodes[1].getnewaddress(address_type='legacy') for _ in range(2)]
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