ismine_tests.cpp
1 // Copyright (c) 2017-present The Bitcoin Core developers 2 // Distributed under the MIT software license, see the accompanying 3 // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 5 #include <key.h> 6 #include <key_io.h> 7 #include <node/context.h> 8 #include <script/script.h> 9 #include <script/solver.h> 10 #include <script/signingprovider.h> 11 #include <test/util/setup_common.h> 12 #include <wallet/types.h> 13 #include <wallet/wallet.h> 14 #include <wallet/test/util.h> 15 16 #include <boost/test/unit_test.hpp> 17 18 using namespace util::hex_literals; 19 20 namespace wallet { 21 BOOST_FIXTURE_TEST_SUITE(ismine_tests, BasicTestingSetup) 22 23 BOOST_AUTO_TEST_CASE(ismine_standard) 24 { 25 CKey keys[2]; 26 CPubKey pubkeys[2]; 27 for (int i = 0; i < 2; i++) { 28 keys[i].MakeNewKey(true); 29 pubkeys[i] = keys[i].GetPubKey(); 30 } 31 32 CKey uncompressedKey = GenerateRandomKey(/*compressed=*/false); 33 CPubKey uncompressedPubkey = uncompressedKey.GetPubKey(); 34 std::unique_ptr<interfaces::Chain>& chain = m_node.chain; 35 36 CScript scriptPubKey; 37 bool result; 38 39 // P2PK compressed - Descriptor 40 { 41 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase()); 42 std::string desc_str = "pk(" + EncodeSecret(keys[0]) + ")"; 43 44 auto spk_manager = CreateDescriptor(keystore, desc_str, true); 45 46 scriptPubKey = GetScriptForRawPubKey(pubkeys[0]); 47 result = spk_manager->IsMine(scriptPubKey); 48 BOOST_CHECK(result); 49 } 50 51 // P2PK uncompressed - Descriptor 52 { 53 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase()); 54 std::string desc_str = "pk(" + EncodeSecret(uncompressedKey) + ")"; 55 56 auto spk_manager = CreateDescriptor(keystore, desc_str, true); 57 58 scriptPubKey = GetScriptForRawPubKey(uncompressedPubkey); 59 result = spk_manager->IsMine(scriptPubKey); 60 BOOST_CHECK(result); 61 } 62 63 // P2PKH compressed - Descriptor 64 { 65 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase()); 66 std::string desc_str = "pkh(" + EncodeSecret(keys[0]) + ")"; 67 68 auto spk_manager = CreateDescriptor(keystore, desc_str, true); 69 70 scriptPubKey = GetScriptForDestination(PKHash(pubkeys[0])); 71 result = spk_manager->IsMine(scriptPubKey); 72 BOOST_CHECK(result); 73 } 74 75 // P2PKH uncompressed - Descriptor 76 { 77 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase()); 78 std::string desc_str = "pkh(" + EncodeSecret(uncompressedKey) + ")"; 79 80 auto spk_manager = CreateDescriptor(keystore, desc_str, true); 81 82 scriptPubKey = GetScriptForDestination(PKHash(uncompressedPubkey)); 83 result = spk_manager->IsMine(scriptPubKey); 84 BOOST_CHECK(result); 85 } 86 87 // P2SH - Descriptor 88 { 89 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase()); 90 std::string desc_str = "sh(pkh(" + EncodeSecret(keys[0]) + "))"; 91 92 auto spk_manager = CreateDescriptor(keystore, desc_str, true); 93 94 CScript redeemScript = GetScriptForDestination(PKHash(pubkeys[0])); 95 scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript)); 96 result = spk_manager->IsMine(scriptPubKey); 97 BOOST_CHECK(result); 98 } 99 100 // (P2PKH inside) P2SH inside P2SH (invalid) - Descriptor 101 { 102 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase()); 103 std::string desc_str = "sh(sh(" + EncodeSecret(keys[0]) + "))"; 104 105 auto spk_manager = CreateDescriptor(keystore, desc_str, false); 106 BOOST_CHECK_EQUAL(spk_manager, nullptr); 107 } 108 109 // (P2PKH inside) P2SH inside P2WSH (invalid) - Descriptor 110 { 111 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase()); 112 std::string desc_str = "wsh(sh(" + EncodeSecret(keys[0]) + "))"; 113 114 auto spk_manager = CreateDescriptor(keystore, desc_str, false); 115 BOOST_CHECK_EQUAL(spk_manager, nullptr); 116 } 117 118 // P2WPKH inside P2WSH (invalid) - Descriptor 119 { 120 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase()); 121 std::string desc_str = "wsh(wpkh(" + EncodeSecret(keys[0]) + "))"; 122 123 auto spk_manager = CreateDescriptor(keystore, desc_str, false); 124 BOOST_CHECK_EQUAL(spk_manager, nullptr); 125 } 126 127 // (P2PKH inside) P2WSH inside P2WSH (invalid) - Descriptor 128 { 129 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase()); 130 std::string desc_str = "wsh(wsh(" + EncodeSecret(keys[0]) + "))"; 131 132 auto spk_manager = CreateDescriptor(keystore, desc_str, false); 133 BOOST_CHECK_EQUAL(spk_manager, nullptr); 134 } 135 136 // P2WPKH compressed - Descriptor 137 { 138 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase()); 139 std::string desc_str = "wpkh(" + EncodeSecret(keys[0]) + ")"; 140 141 auto spk_manager = CreateDescriptor(keystore, desc_str, true); 142 143 scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0])); 144 result = spk_manager->IsMine(scriptPubKey); 145 BOOST_CHECK(result); 146 } 147 148 // P2WPKH uncompressed (invalid) - Descriptor 149 { 150 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase()); 151 std::string desc_str = "wpkh(" + EncodeSecret(uncompressedKey) + ")"; 152 153 auto spk_manager = CreateDescriptor(keystore, desc_str, false); 154 BOOST_CHECK_EQUAL(spk_manager, nullptr); 155 } 156 157 // scriptPubKey multisig - Descriptor 158 { 159 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase()); 160 std::string desc_str = "multi(2," + EncodeSecret(uncompressedKey) + "," + EncodeSecret(keys[1]) + ")"; 161 162 auto spk_manager = CreateDescriptor(keystore, desc_str, true); 163 164 scriptPubKey = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]}); 165 result = spk_manager->IsMine(scriptPubKey); 166 BOOST_CHECK(result); 167 } 168 169 // P2SH multisig - Descriptor 170 { 171 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase()); 172 173 std::string desc_str = "sh(multi(2," + EncodeSecret(uncompressedKey) + "," + EncodeSecret(keys[1]) + "))"; 174 175 auto spk_manager = CreateDescriptor(keystore, desc_str, true); 176 177 CScript redeemScript = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]}); 178 scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript)); 179 result = spk_manager->IsMine(scriptPubKey); 180 BOOST_CHECK(result); 181 } 182 183 // P2WSH multisig with compressed keys - Descriptor 184 { 185 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase()); 186 187 std::string desc_str = "wsh(multi(2," + EncodeSecret(keys[0]) + "," + EncodeSecret(keys[1]) + "))"; 188 189 auto spk_manager = CreateDescriptor(keystore, desc_str, true); 190 191 CScript redeemScript = GetScriptForMultisig(2, {pubkeys[0], pubkeys[1]}); 192 scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(redeemScript)); 193 result = spk_manager->IsMine(scriptPubKey); 194 BOOST_CHECK(result); 195 } 196 197 // P2WSH multisig with uncompressed key (invalid) - Descriptor 198 { 199 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase()); 200 201 std::string desc_str = "wsh(multi(2," + EncodeSecret(uncompressedKey) + "," + EncodeSecret(keys[1]) + "))"; 202 203 auto spk_manager = CreateDescriptor(keystore, desc_str, false); 204 BOOST_CHECK_EQUAL(spk_manager, nullptr); 205 } 206 207 // P2WSH multisig wrapped in P2SH - Descriptor 208 { 209 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase()); 210 211 std::string desc_str = "sh(wsh(multi(2," + EncodeSecret(keys[0]) + "," + EncodeSecret(keys[1]) + ")))"; 212 213 auto spk_manager = CreateDescriptor(keystore, desc_str, true); 214 215 CScript witnessScript = GetScriptForMultisig(2, {pubkeys[0], pubkeys[1]}); 216 CScript redeemScript = GetScriptForDestination(WitnessV0ScriptHash(witnessScript)); 217 scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript)); 218 result = spk_manager->IsMine(scriptPubKey); 219 BOOST_CHECK(result); 220 } 221 222 // Combo - Descriptor 223 { 224 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase()); 225 226 std::string desc_str = "combo(" + EncodeSecret(keys[0]) + ")"; 227 228 auto spk_manager = CreateDescriptor(keystore, desc_str, true); 229 230 // Test P2PK 231 result = spk_manager->IsMine(GetScriptForRawPubKey(pubkeys[0])); 232 BOOST_CHECK(result); 233 234 // Test P2PKH 235 result = spk_manager->IsMine(GetScriptForDestination(PKHash(pubkeys[0]))); 236 BOOST_CHECK(result); 237 238 // Test P2SH (combo descriptor does not describe P2SH) 239 CScript redeemScript = GetScriptForDestination(PKHash(pubkeys[0])); 240 scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript)); 241 result = spk_manager->IsMine(scriptPubKey); 242 BOOST_CHECK(!result); 243 244 // Test P2WPKH 245 scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0])); 246 result = spk_manager->IsMine(scriptPubKey); 247 BOOST_CHECK(result); 248 249 // P2SH-P2WPKH output 250 redeemScript = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0])); 251 scriptPubKey = GetScriptForDestination(ScriptHash(redeemScript)); 252 result = spk_manager->IsMine(scriptPubKey); 253 BOOST_CHECK(result); 254 255 // Test P2TR (combo descriptor does not describe P2TR) 256 XOnlyPubKey xpk(pubkeys[0]); 257 Assert(xpk.IsFullyValid()); 258 TaprootBuilder builder; 259 builder.Finalize(xpk); 260 WitnessV1Taproot output = builder.GetOutput(); 261 scriptPubKey = GetScriptForDestination(output); 262 result = spk_manager->IsMine(scriptPubKey); 263 BOOST_CHECK(!result); 264 } 265 266 // Taproot - Descriptor 267 { 268 CWallet keystore(chain.get(), "", CreateMockableWalletDatabase()); 269 270 std::string desc_str = "tr(" + EncodeSecret(keys[0]) + ")"; 271 272 auto spk_manager = CreateDescriptor(keystore, desc_str, true); 273 274 XOnlyPubKey xpk(pubkeys[0]); 275 Assert(xpk.IsFullyValid()); 276 TaprootBuilder builder; 277 builder.Finalize(xpk); 278 WitnessV1Taproot output = builder.GetOutput(); 279 scriptPubKey = GetScriptForDestination(output); 280 result = spk_manager->IsMine(scriptPubKey); 281 BOOST_CHECK(result); 282 } 283 } 284 285 BOOST_AUTO_TEST_SUITE_END() 286 } // namespace wallet