1 // Copyright (c) 2018-2020 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 <script/descriptor.h>
6 #include <script/sign.h>
7 #include <script/standard.h>
8 #include <test/util/setup_common.h>
9 #include <util/strencodings.h>
10 
11 #include <boost/test/unit_test.hpp>
12 
13 #include <string>
14 #include <vector>
15 
16 namespace {
17 
CheckUnparsable(const std::string & prv,const std::string & pub,const std::string & expected_error)18 void CheckUnparsable(const std::string& prv, const std::string& pub, const std::string& expected_error)
19 {
20     FlatSigningProvider keys_priv, keys_pub;
21     std::string error;
22     auto parse_priv = Parse(prv, keys_priv, error);
23     auto parse_pub = Parse(pub, keys_pub, error);
24     BOOST_CHECK_MESSAGE(!parse_priv, prv);
25     BOOST_CHECK_MESSAGE(!parse_pub, pub);
26     BOOST_CHECK(error == expected_error);
27 }
28 
29 constexpr int DEFAULT = 0;
30 constexpr int RANGE = 1; // Expected to be ranged descriptor
31 constexpr int HARDENED = 2; // Derivation needs access to private keys
32 constexpr int UNSOLVABLE = 4; // This descriptor is not expected to be solvable
33 constexpr int SIGNABLE = 8; // We can sign with this descriptor (this is not true when actual BIP32 derivation is used, as that's not integrated in our signing code)
34 constexpr int DERIVE_HARDENED = 16; // The final derivation is hardened, i.e. ends with *' or *h
35 
36 /** Compare two descriptors. If only one of them has a checksum, the checksum is ignored. */
EqualDescriptor(std::string a,std::string b)37 bool EqualDescriptor(std::string a, std::string b)
38 {
39     bool a_check = (a.size() > 9 && a[a.size() - 9] == '#');
40     bool b_check = (b.size() > 9 && b[b.size() - 9] == '#');
41     if (a_check != b_check) {
42         if (a_check) a = a.substr(0, a.size() - 9);
43         if (b_check) b = b.substr(0, b.size() - 9);
44     }
45     return a == b;
46 }
47 
UseHInsteadOfApostrophe(const std::string & desc)48 std::string UseHInsteadOfApostrophe(const std::string& desc)
49 {
50     std::string ret = desc;
51     while (true) {
52         auto it = ret.find('\'');
53         if (it == std::string::npos) break;
54         ret[it] = 'h';
55     }
56 
57     // GetDescriptorChecksum returns "" if the checksum exists but is bad.
58     // Switching apostrophes with 'h' breaks the checksum if it exists - recalculate it and replace the broken one.
59     if (GetDescriptorChecksum(ret) == "") {
60         ret = ret.substr(0, desc.size() - 9);
61         ret += std::string("#") + GetDescriptorChecksum(ret);
62     }
63     return ret;
64 }
65 
66 const std::set<std::vector<uint32_t>> ONLY_EMPTY{{}};
67 
DoCheck(const std::string & prv,const std::string & pub,int flags,const std::vector<std::vector<std::string>> & scripts,const Optional<OutputType> & type,const std::set<std::vector<uint32_t>> & paths=ONLY_EMPTY,bool replace_apostrophe_with_h_in_prv=false,bool replace_apostrophe_with_h_in_pub=false)68 void DoCheck(const std::string& prv, const std::string& pub, int flags, const std::vector<std::vector<std::string>>& scripts, const Optional<OutputType>& type, const std::set<std::vector<uint32_t>>& paths = ONLY_EMPTY,
69     bool replace_apostrophe_with_h_in_prv=false, bool replace_apostrophe_with_h_in_pub=false)
70 {
71     FlatSigningProvider keys_priv, keys_pub;
72     std::set<std::vector<uint32_t>> left_paths = paths;
73     std::string error;
74 
75     std::unique_ptr<Descriptor> parse_priv;
76     std::unique_ptr<Descriptor> parse_pub;
77     // Check that parsing succeeds.
78     if (replace_apostrophe_with_h_in_prv) {
79         parse_priv = Parse(UseHInsteadOfApostrophe(prv), keys_priv, error);
80     } else {
81         parse_priv = Parse(prv, keys_priv, error);
82     }
83     if (replace_apostrophe_with_h_in_pub) {
84         parse_pub = Parse(UseHInsteadOfApostrophe(pub), keys_pub, error);
85     } else {
86         parse_pub = Parse(pub, keys_pub, error);
87     }
88 
89     BOOST_CHECK(parse_priv);
90     BOOST_CHECK(parse_pub);
91 
92     // Check that the correct OutputType is inferred
93     BOOST_CHECK(parse_priv->GetOutputType() == type);
94     BOOST_CHECK(parse_pub->GetOutputType() == type);
95 
96     // Check private keys are extracted from the private version but not the public one.
97     BOOST_CHECK(keys_priv.keys.size());
98     BOOST_CHECK(!keys_pub.keys.size());
99 
100     // Check that both versions serialize back to the public version.
101     std::string pub1 = parse_priv->ToString();
102     std::string pub2 = parse_pub->ToString();
103     BOOST_CHECK(EqualDescriptor(pub, pub1));
104     BOOST_CHECK(EqualDescriptor(pub, pub2));
105 
106     // Check that both can be serialized with private key back to the private version, but not without private key.
107     std::string prv1;
108     BOOST_CHECK(parse_priv->ToPrivateString(keys_priv, prv1));
109     BOOST_CHECK(EqualDescriptor(prv, prv1));
110     BOOST_CHECK(!parse_priv->ToPrivateString(keys_pub, prv1));
111     BOOST_CHECK(parse_pub->ToPrivateString(keys_priv, prv1));
112     BOOST_CHECK(EqualDescriptor(prv, prv1));
113     BOOST_CHECK(!parse_pub->ToPrivateString(keys_pub, prv1));
114 
115     // Check whether IsRange on both returns the expected result
116     BOOST_CHECK_EQUAL(parse_pub->IsRange(), (flags & RANGE) != 0);
117     BOOST_CHECK_EQUAL(parse_priv->IsRange(), (flags & RANGE) != 0);
118 
119     // * For ranged descriptors,  the `scripts` parameter is a list of expected result outputs, for subsequent
120     //   positions to evaluate the descriptors on (so the first element of `scripts` is for evaluating the
121     //   descriptor at 0; the second at 1; and so on). To verify this, we evaluate the descriptors once for
122     //   each element in `scripts`.
123     // * For non-ranged descriptors, we evaluate the descriptors at positions 0, 1, and 2, but expect the
124     //   same result in each case, namely the first element of `scripts`. Because of that, the size of
125     //   `scripts` must be one in that case.
126     if (!(flags & RANGE)) assert(scripts.size() == 1);
127     size_t max = (flags & RANGE) ? scripts.size() : 3;
128 
129     // Iterate over the position we'll evaluate the descriptors in.
130     for (size_t i = 0; i < max; ++i) {
131         // Call the expected result scripts `ref`.
132         const auto& ref = scripts[(flags & RANGE) ? i : 0];
133         // When t=0, evaluate the `prv` descriptor; when t=1, evaluate the `pub` descriptor.
134         for (int t = 0; t < 2; ++t) {
135             // When the descriptor is hardened, evaluate with access to the private keys inside.
136             const FlatSigningProvider& key_provider = (flags & HARDENED) ? keys_priv : keys_pub;
137 
138             // Evaluate the descriptor selected by `t` in position `i`.
139             FlatSigningProvider script_provider, script_provider_cached;
140             std::vector<CScript> spks, spks_cached;
141             DescriptorCache desc_cache;
142             BOOST_CHECK((t ? parse_priv : parse_pub)->Expand(i, key_provider, spks, script_provider, &desc_cache));
143 
144             // Compare the output with the expected result.
145             BOOST_CHECK_EQUAL(spks.size(), ref.size());
146 
147             // Try to expand again using cached data, and compare.
148             BOOST_CHECK(parse_pub->ExpandFromCache(i, desc_cache, spks_cached, script_provider_cached));
149             BOOST_CHECK(spks == spks_cached);
150             BOOST_CHECK(script_provider.pubkeys == script_provider_cached.pubkeys);
151             BOOST_CHECK(script_provider.scripts == script_provider_cached.scripts);
152             BOOST_CHECK(script_provider.origins == script_provider_cached.origins);
153 
154             // Check whether keys are in the cache
155             const auto& der_xpub_cache = desc_cache.GetCachedDerivedExtPubKeys();
156             const auto& parent_xpub_cache = desc_cache.GetCachedParentExtPubKeys();
157             if ((flags & RANGE) && !(flags & DERIVE_HARDENED)) {
158                 // For ranged, unhardened derivation, None of the keys in origins should appear in the cache but the cache should have parent keys
159                 // But we can derive one level from each of those parent keys and find them all
160                 BOOST_CHECK(der_xpub_cache.empty());
161                 BOOST_CHECK(parent_xpub_cache.size() > 0);
162                 std::set<CPubKey> pubkeys;
163                 for (const auto& xpub_pair : parent_xpub_cache) {
164                     const CExtPubKey& xpub = xpub_pair.second;
165                     CExtPubKey der;
166                     xpub.Derive(der, i);
167                     pubkeys.insert(der.pubkey);
168                 }
169                 for (const auto& origin_pair : script_provider_cached.origins) {
170                     const CPubKey& pk = origin_pair.second.first;
171                     BOOST_CHECK(pubkeys.count(pk) > 0);
172                 }
173             } else if (pub1.find("xpub") != std::string::npos) {
174                 // For ranged, hardened derivation, or not ranged, but has an xpub, all of the keys should appear in the cache
175                 BOOST_CHECK(der_xpub_cache.size() + parent_xpub_cache.size() == script_provider_cached.origins.size());
176                 // Get all of the derived pubkeys
177                 std::set<CPubKey> pubkeys;
178                 for (const auto& xpub_map_pair : der_xpub_cache) {
179                     for (const auto& xpub_pair : xpub_map_pair.second) {
180                         const CExtPubKey& xpub = xpub_pair.second;
181                         pubkeys.insert(xpub.pubkey);
182                     }
183                 }
184                 // Derive one level from all of the parents
185                 for (const auto& xpub_pair : parent_xpub_cache) {
186                     const CExtPubKey& xpub = xpub_pair.second;
187                     pubkeys.insert(xpub.pubkey);
188                     CExtPubKey der;
189                     xpub.Derive(der, i);
190                     pubkeys.insert(der.pubkey);
191                 }
192                 for (const auto& origin_pair : script_provider_cached.origins) {
193                     const CPubKey& pk = origin_pair.second.first;
194                     BOOST_CHECK(pubkeys.count(pk) > 0);
195                 }
196             } else {
197                 // No xpub, nothing should be cached
198                 BOOST_CHECK(der_xpub_cache.empty());
199                 BOOST_CHECK(parent_xpub_cache.empty());
200             }
201 
202             // Make sure we can expand using cached xpubs for unhardened derivation
203             if (!(flags & DERIVE_HARDENED)) {
204                 // Evaluate the descriptor at i + 1
205                 FlatSigningProvider script_provider1, script_provider_cached1;
206                 std::vector<CScript> spks1, spk1_from_cache;
207                 BOOST_CHECK((t ? parse_priv : parse_pub)->Expand(i + 1, key_provider, spks1, script_provider1, nullptr));
208 
209                 // Try again but use the cache from expanding i. That cache won't have the pubkeys for i + 1, but will have the parent xpub for derivation.
210                 BOOST_CHECK(parse_pub->ExpandFromCache(i + 1, desc_cache, spk1_from_cache, script_provider_cached1));
211                 BOOST_CHECK(spks1 == spk1_from_cache);
212                 BOOST_CHECK(script_provider1.pubkeys == script_provider_cached1.pubkeys);
213                 BOOST_CHECK(script_provider1.scripts == script_provider_cached1.scripts);
214                 BOOST_CHECK(script_provider1.origins == script_provider_cached1.origins);
215             }
216 
217             // For each of the produced scripts, verify solvability, and when possible, try to sign a transaction spending it.
218             for (size_t n = 0; n < spks.size(); ++n) {
219                 BOOST_CHECK_EQUAL(ref[n], HexStr(spks[n]));
220                 BOOST_CHECK_EQUAL(IsSolvable(Merge(key_provider, script_provider), spks[n]), (flags & UNSOLVABLE) == 0);
221 
222                 if (flags & SIGNABLE) {
223                     CMutableTransaction spend;
224                     spend.vin.resize(1);
225                     spend.vout.resize(1);
226                     BOOST_CHECK_MESSAGE(SignSignature(Merge(keys_priv, script_provider), spks[n], spend, 0, 1, SIGHASH_ALL), prv);
227                 }
228 
229                 /* Infer a descriptor from the generated script, and verify its solvability and that it roundtrips. */
230                 auto inferred = InferDescriptor(spks[n], script_provider);
231                 BOOST_CHECK_EQUAL(inferred->IsSolvable(), !(flags & UNSOLVABLE));
232                 std::vector<CScript> spks_inferred;
233                 FlatSigningProvider provider_inferred;
234                 BOOST_CHECK(inferred->Expand(0, provider_inferred, spks_inferred, provider_inferred));
235                 BOOST_CHECK_EQUAL(spks_inferred.size(), 1U);
236                 BOOST_CHECK(spks_inferred[0] == spks[n]);
237                 BOOST_CHECK_EQUAL(IsSolvable(provider_inferred, spks_inferred[0]), !(flags & UNSOLVABLE));
238                 BOOST_CHECK(provider_inferred.origins == script_provider.origins);
239             }
240 
241             // Test whether the observed key path is present in the 'paths' variable (which contains expected, unobserved paths),
242             // and then remove it from that set.
243             for (const auto& origin : script_provider.origins) {
244                 BOOST_CHECK_MESSAGE(paths.count(origin.second.second.path), "Unexpected key path: " + prv);
245                 left_paths.erase(origin.second.second.path);
246             }
247         }
248     }
249 
250     // Verify no expected paths remain that were not observed.
251     BOOST_CHECK_MESSAGE(left_paths.empty(), "Not all expected key paths found: " + prv);
252 }
253 
Check(const std::string & prv,const std::string & pub,int flags,const std::vector<std::vector<std::string>> & scripts,const Optional<OutputType> & type,const std::set<std::vector<uint32_t>> & paths=ONLY_EMPTY)254 void Check(const std::string& prv, const std::string& pub, int flags, const std::vector<std::vector<std::string>>& scripts, const Optional<OutputType>& type, const std::set<std::vector<uint32_t>>& paths = ONLY_EMPTY)
255 {
256     bool found_apostrophes_in_prv = false;
257     bool found_apostrophes_in_pub = false;
258 
259     // Do not replace apostrophes with 'h' in prv and pub
260     DoCheck(prv, pub, flags, scripts, type, paths);
261 
262     // Replace apostrophes with 'h' in prv but not in pub, if apostrophes are found in prv
263     if (prv.find('\'') != std::string::npos) {
264         found_apostrophes_in_prv = true;
265         DoCheck(prv, pub, flags, scripts, type, paths, /* replace_apostrophe_with_h_in_prv = */true, /*replace_apostrophe_with_h_in_pub = */false);
266     }
267 
268     // Replace apostrophes with 'h' in pub but not in prv, if apostrophes are found in pub
269     if (pub.find('\'') != std::string::npos) {
270         found_apostrophes_in_pub = true;
271         DoCheck(prv, pub, flags, scripts, type, paths, /* replace_apostrophe_with_h_in_prv = */false, /*replace_apostrophe_with_h_in_pub = */true);
272     }
273 
274     // Replace apostrophes with 'h' both in prv and in pub, if apostrophes are found in both
275     if (found_apostrophes_in_prv && found_apostrophes_in_pub) {
276         DoCheck(prv, pub, flags, scripts, type, paths, /* replace_apostrophe_with_h_in_prv = */true, /*replace_apostrophe_with_h_in_pub = */true);
277     }
278 }
279 
280 }
281 
BOOST_FIXTURE_TEST_SUITE(descriptor_tests,BasicTestingSetup)282 BOOST_FIXTURE_TEST_SUITE(descriptor_tests, BasicTestingSetup)
283 
284 BOOST_AUTO_TEST_CASE(descriptor_test)
285 {
286     // Basic single-key compressed
287     Check("combo(Tm16kMxfJWHubSbArk3eYn7sbqpQSNcEHUJARod7zvB975995Gai)", "combo(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"2103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bdac","76a9149a1c78a507689f6f54b847ad1cef1e614ee23f1e88ac","00149a1c78a507689f6f54b847ad1cef1e614ee23f1e","a91484ab21b1b2fd065d4504ff693d832434b6108d7b87"}}, nullopt);
288     Check("pk(Tm16kMxfJWHubSbArk3eYn7sbqpQSNcEHUJARod7zvB975995Gai)", "pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"2103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bdac"}}, nullopt);
289     Check("pkh([deadbeef/1/2'/3/4']Tm16kMxfJWHubSbArk3eYn7sbqpQSNcEHUJARod7zvB975995Gai)", "pkh([deadbeef/1/2'/3/4']03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"76a9149a1c78a507689f6f54b847ad1cef1e614ee23f1e88ac"}}, OutputType::LEGACY, {{1,0x80000002UL,3,0x80000004UL}});
290     Check("wpkh(Tm16kMxfJWHubSbArk3eYn7sbqpQSNcEHUJARod7zvB975995Gai)", "wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"00149a1c78a507689f6f54b847ad1cef1e614ee23f1e"}}, OutputType::BECH32);
291     Check("sh(wpkh(Tm16kMxfJWHubSbArk3eYn7sbqpQSNcEHUJARod7zvB975995Gai))", "sh(wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"a91484ab21b1b2fd065d4504ff693d832434b6108d7b87"}}, OutputType::P2SH_SEGWIT);
292     CheckUnparsable("sh(wpkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY2))", "sh(wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5))", "Pubkey '03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5' is invalid"); // Invalid pubkey
293     CheckUnparsable("pkh(deadbeef/1/2'/3/4']Tm16kMxfJWHubSbArk3eYn7sbqpQSNcEHUJARod7zvB975995Gai)", "pkh(deadbeef/1/2'/3/4']03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "Key origin start '[ character expected but not found, got 'd' instead"); // Missing start bracket in key origin
294     CheckUnparsable("pkh([deadbeef]/1/2'/3/4']Tm16kMxfJWHubSbArk3eYn7sbqpQSNcEHUJARod7zvB975995Gai)", "pkh([deadbeef]/1/2'/3/4']03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "Multiple ']' characters found for a single pubkey"); // Multiple end brackets in key origin
295 
296     // Basic single-key uncompressed
297     Check("combo(74dGoXaTMH9pG45a3fJNCH7YQJQRo5SeuDXd7ynLiDW2qYntR1H)", "combo(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235ac","76a914b5bd079c4d57cc7fc28ecf8213a6b791625b818388ac"}}, nullopt);
298     Check("pk(74dGoXaTMH9pG45a3fJNCH7YQJQRo5SeuDXd7ynLiDW2qYntR1H)", "pk(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235ac"}}, nullopt);
299     Check("pkh(74dGoXaTMH9pG45a3fJNCH7YQJQRo5SeuDXd7ynLiDW2qYntR1H)", "pkh(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"76a914b5bd079c4d57cc7fc28ecf8213a6b791625b818388ac"}}, OutputType::LEGACY);
300     CheckUnparsable("wpkh(74dGoXaTMH9pG45a3fJNCH7YQJQRo5SeuDXd7ynLiDW2qYntR1H)", "wpkh(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "Uncompressed keys are not allowed"); // No uncompressed keys in witness
301     CheckUnparsable("wsh(pk(74dGoXaTMH9pG45a3fJNCH7YQJQRo5SeuDXd7ynLiDW2qYntR1H))", "wsh(pk(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235))", "Uncompressed keys are not allowed"); // No uncompressed keys in witness
302     CheckUnparsable("sh(wpkh(74dGoXaTMH9pG45a3fJNCH7YQJQRo5SeuDXd7ynLiDW2qYntR1H))", "sh(wpkh(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235))", "Uncompressed keys are not allowed"); // No uncompressed keys in witness
303 
304     // Some unconventional single-key constructions
305     Check("sh(pk(Tm16kMxfJWHubSbArk3eYn7sbqpQSNcEHUJARod7zvB975995Gai))", "sh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"a9141857af51a5e516552b3086430fd8ce55f7c1a52487"}}, OutputType::LEGACY);
306     Check("sh(pkh(Tm16kMxfJWHubSbArk3eYn7sbqpQSNcEHUJARod7zvB975995Gai))", "sh(pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"a9141a31ad23bf49c247dd531a623c2ef57da3c400c587"}}, OutputType::LEGACY);
307     Check("wsh(pk(Tm16kMxfJWHubSbArk3eYn7sbqpQSNcEHUJARod7zvB975995Gai))", "wsh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"00202e271faa2325c199d25d22e1ead982e45b64eeb4f31e73dbdf41bd4b5fec23fa"}}, OutputType::BECH32);
308     Check("wsh(pkh(Tm16kMxfJWHubSbArk3eYn7sbqpQSNcEHUJARod7zvB975995Gai))", "wsh(pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"0020338e023079b91c58571b20e602d7805fb808c22473cbc391a41b1bd3a192e75b"}}, OutputType::BECH32);
309     Check("sh(wsh(pk(Tm16kMxfJWHubSbArk3eYn7sbqpQSNcEHUJARod7zvB975995Gai)))", "sh(wsh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))", SIGNABLE, {{"a91472d0c5a3bfad8c3e7bd5303a72b94240e80b6f1787"}}, OutputType::P2SH_SEGWIT);
310     Check("sh(wsh(pkh(Tm16kMxfJWHubSbArk3eYn7sbqpQSNcEHUJARod7zvB975995Gai)))", "sh(wsh(pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))", SIGNABLE, {{"a914b61b92e2ca21bac1e72a3ab859a742982bea960a87"}}, OutputType::P2SH_SEGWIT);
311 
312     // Versions with BIP32 derivations
313     Check("combo([01234567]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc)", "combo([01234567]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)", SIGNABLE, {{"2102d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0ac","76a91431a507b815593dfc51ffc7245ae7e5aee304246e88ac","001431a507b815593dfc51ffc7245ae7e5aee304246e","a9142aafb926eb247cb18240a7f4c07983ad1f37922687"}}, nullopt);
314     Check("pk(xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0)", "pk(xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0)", DEFAULT, {{"210379e45b3cf75f9c5f9befd8e9506fb962f6a9d185ac87001ec44a8d3df8d4a9e3ac"}}, nullopt, {{0}});
315     Check("pkh(xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0)", "pkh(xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0)", HARDENED, {{"76a914ebdc90806a9c4356c1c88e42216611e1cb4c1c1788ac"}}, OutputType::LEGACY, {{0xFFFFFFFFUL,0}});
316     Check("wpkh([ffffffff/13']xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*)", "wpkh([ffffffff/13']xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*)", RANGE, {{"0014326b2249e3a25d5dc60935f044ee835d090ba859"},{"0014af0bd98abc2f2cae66e36896a39ffe2d32984fb7"},{"00141fa798efd1cbf95cebf912c031b8a4a6e9fb9f27"}}, OutputType::BECH32, {{0x8000000DUL, 1, 2, 0}, {0x8000000DUL, 1, 2, 1}, {0x8000000DUL, 1, 2, 2}});
317     Check("sh(wpkh(xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "sh(wpkh(xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", RANGE | HARDENED | DERIVE_HARDENED, {{"a9149a4d9901d6af519b2a23d4a2f51650fcba87ce7b87"},{"a914bed59fc0024fae941d6e20a3b44a109ae740129287"},{"a9148483aa1116eb9c05c482a72bada4b1db24af654387"}}, OutputType::P2SH_SEGWIT, {{10, 20, 30, 40, 0x80000000UL}, {10, 20, 30, 40, 0x80000001UL}, {10, 20, 30, 40, 0x80000002UL}});
318     Check("combo(xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334/*)", "combo(xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV/*)", RANGE, {{"2102df12b7035bdac8e3bab862a3a83d06ea6b17b6753d52edecba9be46f5d09e076ac","76a914f90e3178ca25f2c808dc76624032d352fdbdfaf288ac","0014f90e3178ca25f2c808dc76624032d352fdbdfaf2","a91408f3ea8c68d4a7585bf9e8bda226723f70e445f087"},{"21032869a233c9adff9a994e4966e5b821fd5bac066da6c3112488dc52383b4a98ecac","76a914a8409d1b6dfb1ed2a3e8aa5e0ef2ff26b15b75b788ac","0014a8409d1b6dfb1ed2a3e8aa5e0ef2ff26b15b75b7","a91473e39884cb71ae4e5ac9739e9225026c99763e6687"}}, nullopt, {{0}, {1}});
319     CheckUnparsable("combo([012345678]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc)", "combo([012345678]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)", "Fingerprint is not 4 bytes (9 characters instead of 8 characters)"); // Too long key fingerprint
320     CheckUnparsable("pkh(xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483648)", "pkh(xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483648)", "Key path value 2147483648 is out of range"); // BIP 32 path element overflow
321     CheckUnparsable("pkh(xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/1aa)", "pkh(xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/1aa)", "Key path value '1aa' is not a valid uint32"); // Path is not valid uint
322 
323     // Multisig constructions
324     Check("multi(1,Tm16kMxfJWHubSbArk3eYn7sbqpQSNcEHUJARod7zvB975995Gai,74dGoXaTMH9pG45a3fJNCH7YQJQRo5SeuDXd7ynLiDW2qYntR1H)", "multi(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}}, nullopt);
325     Check("sortedmulti(1,Tm16kMxfJWHubSbArk3eYn7sbqpQSNcEHUJARod7zvB975995Gai,74dGoXaTMH9pG45a3fJNCH7YQJQRo5SeuDXd7ynLiDW2qYntR1H)", "sortedmulti(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}}, nullopt);
326     Check("sortedmulti(1,74dGoXaTMH9pG45a3fJNCH7YQJQRo5SeuDXd7ynLiDW2qYntR1H,Tm16kMxfJWHubSbArk3eYn7sbqpQSNcEHUJARod7zvB975995Gai)", "sortedmulti(1,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}}, nullopt);
327     Check("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))", DEFAULT, {{"a91445a9a622a8b0a1269944be477640eedc447bbd8487"}}, OutputType::LEGACY, {{0x8000006FUL,222},{0}});
328     Check("sortedmulti(2,xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc/*,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0/0/*)", "sortedmulti(2,xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/*,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0/0/*)", RANGE, {{"5221025d5fc65ebb8d44a5274b53bac21ff8307fec2334a32df05553459f8b1f7fe1b62102fbd47cc8034098f0e6a94c6aeee8528abf0a2153a5d8e46d325b7284c046784652ae"}, {"52210264fd4d1f5dea8ded94c61e9641309349b62f27fbffe807291f664e286bfbe6472103f4ece6dfccfa37b211eb3d0af4d0c61dba9ef698622dc17eecdf764beeb005a652ae"}, {"5221022ccabda84c30bad578b13c89eb3b9544ce149787e5b538175b1d1ba259cbb83321024d902e1a2fc7a8755ab5b694c575fce742c48d9ff192e63df5193e4c7afe1f9c52ae"}}, nullopt, {{0}, {1}, {2}, {0, 0, 0}, {0, 0, 1}, {0, 0, 2}});
329     Check("wsh(multi(2,xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", HARDENED | RANGE | DERIVE_HARDENED, {{"0020b92623201f3bb7c3771d45b2ad1d0351ea8fbf8cfe0a0e570264e1075fa1948f"},{"002036a08bbe4923af41cf4316817c93b8d37e2f635dd25cfff06bd50df6ae7ea203"},{"0020a96e7ab4607ca6b261bfe3245ffda9c746b28d3f59e83d34820ec0e2b36c139c"}}, OutputType::BECH32, {{0xFFFFFFFFUL,0}, {1,2,0}, {1,2,1}, {1,2,2}, {10, 20, 30, 40, 0x80000000UL}, {10, 20, 30, 40, 0x80000001UL}, {10, 20, 30, 40, 0x80000002UL}});
330     Check("sh(wsh(multi(16,TgwxiTwMtacZzZdzRNrqRErdkxZPUnnNPvkkqj9hkEUvV4pH8k3E,TdRAiVGyJQXhbAgJeniXc6oePv56bMuAKJreqU3J5NNxE2ZYt5jH,TexUH6T9mwc4YrcUF2d5f2Ew9RD33KDGJFtd1MJ62MvKcC3Dcrzt,TiLG72eEYyD6EedK3vJqrHvPiWUqPnUEJ4AryAXP7wSmPzCcPV6g,ThxY2f23t1PQQYDE5u4BLYRDhnoLS4Fssqz6J4qN7zcf3x44dAPQ,TeMz6qBED4vQ4VC2AGMRgw6JWnr7XaFJG1eKmL3pbWiDf91wRLuG,TmoR97zftkFokPCRBicvJxiaoB3bdAa66g36JcjrtwDaz9n5oEt8,TgPvCtzPLBkLDNX52jYPtmgggpDtnJbZzTUAajSpkbovp1yH2bgu,Tjw5CzY6N2aDALz2VV5WbEGU4Q6EWK18PdxjxGgYyaRDFwen6ajK,Tft5XRqQckBrPg1iFSHqrsy1B2MyEYvxXvdyvYVc89QKDqSPHFpC,Te2Thg4CaTCY5ofp83sVHbybU4EqDgBKtf8QLeY7o1raoc7bxcUR,TgMGKfS9FKwrJYwc66Wr5WDggSQYb5LTDPfLce5d4WsD1R3JHDfS,Tgqc5agiyCz6RUt2EoHd5FTu7oUS6KDBemfKd39EyzsCoMstzWRh,TfLKBnhqZ7BQjjqqN6sUjoqzNQewPMPAPagokKbS4TdrHUoepPAM,TgT1NYTiQR32zHiBn7KoW371w2Zq8fGkAUbSNFPa5BEPqDe4w9kz,Ti7P2FhktrUUzfVVN1NLCTKH3WR1FJdDYXcKbACMxePVj35nNbwk)))","sh(wsh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232)))", SIGNABLE, {{"a9147fc63e13dc25e8a95a3cee3d9a714ac3afd96f1e87"}}, OutputType::P2SH_SEGWIT);
331     CheckUnparsable("sh(multi(16,TgwxiTwMtacZzZdzRNrqRErdkxZPUnnNPvkkqj9hkEUvV4pH8k3E,TdRAiVGyJQXhbAgJeniXc6oePv56bMuAKJreqU3J5NNxE2ZYt5jH,TexUH6T9mwc4YrcUF2d5f2Ew9RD33KDGJFtd1MJ62MvKcC3Dcrzt,TiLG72eEYyD6EedK3vJqrHvPiWUqPnUEJ4AryAXP7wSmPzCcPV6g,ThxY2f23t1PQQYDE5u4BLYRDhnoLS4Fssqz6J4qN7zcf3x44dAPQ,TeMz6qBED4vQ4VC2AGMRgw6JWnr7XaFJG1eKmL3pbWiDf91wRLuG,TmoR97zftkFokPCRBicvJxiaoB3bdAa66g36JcjrtwDaz9n5oEt8,TgPvCtzPLBkLDNX52jYPtmgggpDtnJbZzTUAajSpkbovp1yH2bgu,Tjw5CzY6N2aDALz2VV5WbEGU4Q6EWK18PdxjxGgYyaRDFwen6ajK,Tft5XRqQckBrPg1iFSHqrsy1B2MyEYvxXvdyvYVc89QKDqSPHFpC,Te2Thg4CaTCY5ofp83sVHbybU4EqDgBKtf8QLeY7o1raoc7bxcUR,TgMGKfS9FKwrJYwc66Wr5WDggSQYb5LTDPfLce5d4WsD1R3JHDfS,Tgqc5agiyCz6RUt2EoHd5FTu7oUS6KDBemfKd39EyzsCoMstzWRh,TfLKBnhqZ7BQjjqqN6sUjoqzNQewPMPAPagokKbS4TdrHUoepPAM,TgT1NYTiQR32zHiBn7KoW371w2Zq8fGkAUbSNFPa5BEPqDe4w9kz,Ti7P2FhktrUUzfVVN1NLCTKH3WR1FJdDYXcKbACMxePVj35nNbwk))","sh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232))", "P2SH script is too large, 547 bytes is larger than 520 bytes"); // P2SH does not fit 16 compressed pubkeys in a redeemscript
332     CheckUnparsable("wsh(multi(2,[aaaaaaaa][aaaaaaaa]xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,[aaaaaaaa][aaaaaaaa]xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", "Multiple ']' characters found for a single pubkey"); // Double key origin descriptor
333     CheckUnparsable("wsh(multi(2,[aaaagaaa]xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,[aaagaaaa]xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", "Fingerprint 'aaagaaaa' is not hex"); // Non hex fingerprint
334     CheckUnparsable("wsh(multi(2,[aaaaaaaa],xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,[aaaaaaaa],xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", "No key provided"); // No public key with origin
335     CheckUnparsable("wsh(multi(2,[aaaaaaa]xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,[aaaaaaa]xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", "Fingerprint is not 4 bytes (7 characters instead of 8 characters)"); // Too short fingerprint
336     CheckUnparsable("wsh(multi(2,[aaaaaaaaa]xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,[aaaaaaaaa]xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", "Fingerprint is not 4 bytes (9 characters instead of 8 characters)"); // Too long fingerprint
337     CheckUnparsable("multi(a,Tm16kMxfJWHubSbArk3eYn7sbqpQSNcEHUJARod7zvB975995Gai,74dGoXaTMH9pG45a3fJNCH7YQJQRo5SeuDXd7ynLiDW2qYntR1H)", "multi(a,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "Multi threshold 'a' is not valid"); // Invalid threshold
338     CheckUnparsable("multi(0,Tm16kMxfJWHubSbArk3eYn7sbqpQSNcEHUJARod7zvB975995Gai,74dGoXaTMH9pG45a3fJNCH7YQJQRo5SeuDXd7ynLiDW2qYntR1H)", "multi(0,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "Multisig threshold cannot be 0, must be at least 1"); // Threshold of 0
339     CheckUnparsable("multi(3,Tm16kMxfJWHubSbArk3eYn7sbqpQSNcEHUJARod7zvB975995Gai,74dGoXaTMH9pG45a3fJNCH7YQJQRo5SeuDXd7ynLiDW2qYntR1H)", "multi(3,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "Multisig threshold cannot be larger than the number of keys; threshold is 3 but only 2 keys specified"); // Threshold larger than number of keys
340     CheckUnparsable("multi(3,TgwxiTwMtacZzZdzRNrqRErdkxZPUnnNPvkkqj9hkEUvV4pH8k3E,TdRAiVGyJQXhbAgJeniXc6oePv56bMuAKJreqU3J5NNxE2ZYt5jH,TexUH6T9mwc4YrcUF2d5f2Ew9RD33KDGJFtd1MJ62MvKcC3Dcrzt,TiLG72eEYyD6EedK3vJqrHvPiWUqPnUEJ4AryAXP7wSmPzCcPV6g)", "multi(3,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8)", "Cannot have 4 pubkeys in bare multisig; only at most 3 pubkeys"); // Threshold larger than number of keys
341     CheckUnparsable("sh(multi(16,TgwxiTwMtacZzZdzRNrqRErdkxZPUnnNPvkkqj9hkEUvV4pH8k3E,TdRAiVGyJQXhbAgJeniXc6oePv56bMuAKJreqU3J5NNxE2ZYt5jH,TexUH6T9mwc4YrcUF2d5f2Ew9RD33KDGJFtd1MJ62MvKcC3Dcrzt,TiLG72eEYyD6EedK3vJqrHvPiWUqPnUEJ4AryAXP7wSmPzCcPV6g,ThxY2f23t1PQQYDE5u4BLYRDhnoLS4Fssqz6J4qN7zcf3x44dAPQ,TeMz6qBED4vQ4VC2AGMRgw6JWnr7XaFJG1eKmL3pbWiDf91wRLuG,TmoR97zftkFokPCRBicvJxiaoB3bdAa66g36JcjrtwDaz9n5oEt8,TgPvCtzPLBkLDNX52jYPtmgggpDtnJbZzTUAajSpkbovp1yH2bgu,Tjw5CzY6N2aDALz2VV5WbEGU4Q6EWK18PdxjxGgYyaRDFwen6ajK,Tft5XRqQckBrPg1iFSHqrsy1B2MyEYvxXvdyvYVc89QKDqSPHFpC,Te2Thg4CaTCY5ofp83sVHbybU4EqDgBKtf8QLeY7o1raoc7bxcUR,TgMGKfS9FKwrJYwc66Wr5WDggSQYb5LTDPfLce5d4WsD1R3JHDfS,Tgqc5agiyCz6RUt2EoHd5FTu7oUS6KDBemfKd39EyzsCoMstzWRh,TfLKBnhqZ7BQjjqqN6sUjoqzNQewPMPAPagokKbS4TdrHUoepPAM,TgT1NYTiQR32zHiBn7KoW371w2Zq8fGkAUbSNFPa5BEPqDe4w9kz,Ti7P2FhktrUUzfVVN1NLCTKH3WR1FJdDYXcKbACMxePVj35nNbwk,Tm16kMxfJWHubSbArk3eYn7sbqpQSNcEHUJARod7zvB975995Gai))","sh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", "Cannot have 17 keys in multisig; must have between 1 and 16 keys, inclusive"); // Cannot have more than 16 keys in a multisig
342 
343     // Check for invalid nesting of structures
344     CheckUnparsable("sh(Tm16kMxfJWHubSbArk3eYn7sbqpQSNcEHUJARod7zvB975995Gai)", "sh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "A function is needed within P2SH"); // P2SH needs a script, not a key
345     CheckUnparsable("sh(combo(Tm16kMxfJWHubSbArk3eYn7sbqpQSNcEHUJARod7zvB975995Gai))", "sh(combo(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", "Cannot have combo in non-top level"); // Old must be top level
346     CheckUnparsable("wsh(Tm16kMxfJWHubSbArk3eYn7sbqpQSNcEHUJARod7zvB975995Gai)", "wsh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "A function is needed within P2WSH"); // P2WSH needs a script, not a key
347     CheckUnparsable("wsh(wpkh(Tm16kMxfJWHubSbArk3eYn7sbqpQSNcEHUJARod7zvB975995Gai))", "wsh(wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", "Cannot have wpkh within wsh"); // Cannot embed witness inside witness
348     CheckUnparsable("wsh(sh(pk(Tm16kMxfJWHubSbArk3eYn7sbqpQSNcEHUJARod7zvB975995Gai)))", "wsh(sh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))", "Cannot have sh in non-top level"); // Cannot embed P2SH inside P2WSH
349     CheckUnparsable("sh(sh(pk(Tm16kMxfJWHubSbArk3eYn7sbqpQSNcEHUJARod7zvB975995Gai)))", "sh(sh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))", "Cannot have sh in non-top level"); // Cannot embed P2SH inside P2SH
350     CheckUnparsable("wsh(wsh(pk(Tm16kMxfJWHubSbArk3eYn7sbqpQSNcEHUJARod7zvB975995Gai)))", "wsh(wsh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))", "Cannot have wsh within wsh"); // Cannot embed P2WSH inside P2WSH
351 
352     // Checksums
353     Check("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxfy", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5t", DEFAULT, {{"a91445a9a622a8b0a1269944be477640eedc447bbd8487"}}, OutputType::LEGACY, {{0x8000006FUL,222},{0}});
354     Check("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))", DEFAULT, {{"a91445a9a622a8b0a1269944be477640eedc447bbd8487"}}, OutputType::LEGACY, {{0x8000006FUL,222},{0}});
355     CheckUnparsable("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#", "Expected 8 character checksum, not 0 characters"); // Empty checksum
356     CheckUnparsable("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxfyq", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5tq", "Expected 8 character checksum, not 9 characters"); // Too long checksum
357     CheckUnparsable("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxf", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5", "Expected 8 character checksum, not 7 characters"); // Too short checksum
358     CheckUnparsable("sh(multi(3,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxfy", "sh(multi(3,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5t", "Provided checksum 'tjg09x5t' does not match computed checksum 'd4x0uxyv'"); // Error in payload
359     CheckUnparsable("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggssrxfy", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjq09x4t", "Provided checksum 'tjq09x4t' does not match computed checksum 'tjg09x5t'"); // Error in checksum
360     CheckUnparsable("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))##ggssrxfy", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))##tjq09x4t", "Multiple '#' symbols"); // Error in checksum
361 
362     // Addr and raw tests
363     CheckUnparsable("", "addr(asdf)", "Address is not valid"); // Invalid address
364     CheckUnparsable("", "raw(asdf)", "Raw script is not hex"); // Invalid script
365     CheckUnparsable("", "raw(Ü)#00000000", "Invalid characters in payload"); // Invalid chars
366 }
367 
368 BOOST_AUTO_TEST_SUITE_END()
369