Changeset View
Changeset View
Standalone View
Standalone View
src/test/descriptor_tests.cpp
Show First 20 Lines • Show All 82 Lines • ▼ Show 20 Lines | void Check(const std::string &prv, const std::string &pub, int flags, | ||||
BOOST_CHECK(parse_pub->ToPrivateString(keys_priv, prv1)); | BOOST_CHECK(parse_pub->ToPrivateString(keys_priv, prv1)); | ||||
BOOST_CHECK_EQUAL(prv, prv1); | BOOST_CHECK_EQUAL(prv, prv1); | ||||
BOOST_CHECK(!parse_pub->ToPrivateString(keys_pub, prv1)); | BOOST_CHECK(!parse_pub->ToPrivateString(keys_pub, prv1)); | ||||
// Check whether IsRange on both returns the expected result | // Check whether IsRange on both returns the expected result | ||||
BOOST_CHECK_EQUAL(parse_pub->IsRange(), (flags & RANGE) != 0); | BOOST_CHECK_EQUAL(parse_pub->IsRange(), (flags & RANGE) != 0); | ||||
BOOST_CHECK_EQUAL(parse_priv->IsRange(), (flags & RANGE) != 0); | BOOST_CHECK_EQUAL(parse_priv->IsRange(), (flags & RANGE) != 0); | ||||
// Is not ranged descriptor, only a single result is expected. | // * For ranged descriptors, the `scripts` parameter is a list of expected | ||||
// result outputs, for subsequent | |||||
// positions to evaluate the descriptors on (so the first element of | |||||
// `scripts` is for evaluating the descriptor at 0; the second at 1; and | |||||
// so on). To verify this, we evaluate the descriptors once for each | |||||
// element in `scripts`. | |||||
// * For non-ranged descriptors, we evaluate the descriptors at positions 0, | |||||
// 1, and 2, but expect the | |||||
// same result in each case, namely the first element of `scripts`. | |||||
// Because of that, the size of `scripts` must be one in that case. | |||||
if (!(flags & RANGE)) { | if (!(flags & RANGE)) { | ||||
assert(scripts.size() == 1); | assert(scripts.size() == 1); | ||||
} | } | ||||
size_t max = (flags & RANGE) ? scripts.size() : 3; | size_t max = (flags & RANGE) ? scripts.size() : 3; | ||||
// Iterate over the position we'll evaluate the descriptors in. | |||||
for (size_t i = 0; i < max; ++i) { | for (size_t i = 0; i < max; ++i) { | ||||
// Call the expected result scripts `ref`. | |||||
const auto &ref = scripts[(flags & RANGE) ? i : 0]; | const auto &ref = scripts[(flags & RANGE) ? i : 0]; | ||||
// When t=0, evaluate the `prv` descriptor; when t=1, evaluate the `pub` | |||||
// descriptor. | |||||
for (int t = 0; t < 2; ++t) { | for (int t = 0; t < 2; ++t) { | ||||
// When the descriptor is hardened, evaluate with access to the | |||||
// private keys inside. | |||||
const FlatSigningProvider &key_provider = | const FlatSigningProvider &key_provider = | ||||
(flags & HARDENED) ? keys_priv : keys_pub; | (flags & HARDENED) ? keys_priv : keys_pub; | ||||
// Evaluate the descriptor selected by `t` in poisition `i`. | |||||
FlatSigningProvider script_provider, script_provider_cached; | FlatSigningProvider script_provider, script_provider_cached; | ||||
std::vector<CScript> spks, spks_cached; | std::vector<CScript> spks, spks_cached; | ||||
std::vector<uint8_t> cache; | std::vector<uint8_t> cache; | ||||
BOOST_CHECK( | BOOST_CHECK( | ||||
(t ? parse_priv : parse_pub) | (t ? parse_priv : parse_pub) | ||||
->Expand(i, key_provider, spks, script_provider, &cache)); | ->Expand(i, key_provider, spks, script_provider, &cache)); | ||||
// Compare the output with the expected result. | |||||
BOOST_CHECK_EQUAL(spks.size(), ref.size()); | |||||
// Try to expand again using cached data, and compare. | // Try to expand again using cached data, and compare. | ||||
BOOST_CHECK(parse_pub->ExpandFromCache(i, cache, spks_cached, | BOOST_CHECK(parse_pub->ExpandFromCache(i, cache, spks_cached, | ||||
script_provider_cached)); | script_provider_cached)); | ||||
BOOST_CHECK(spks == spks_cached); | BOOST_CHECK(spks == spks_cached); | ||||
BOOST_CHECK(script_provider.pubkeys == | BOOST_CHECK(script_provider.pubkeys == | ||||
script_provider_cached.pubkeys); | script_provider_cached.pubkeys); | ||||
BOOST_CHECK(script_provider.scripts == | BOOST_CHECK(script_provider.scripts == | ||||
script_provider_cached.scripts); | script_provider_cached.scripts); | ||||
BOOST_CHECK(script_provider.origins == | BOOST_CHECK(script_provider.origins == | ||||
script_provider_cached.origins); | script_provider_cached.origins); | ||||
BOOST_CHECK_EQUAL(spks.size(), ref.size()); | // For each of the produced scripts, verify solvability, and when | ||||
// possible, try to sign a transaction spending it. | |||||
for (size_t n = 0; n < spks.size(); ++n) { | for (size_t n = 0; n < spks.size(); ++n) { | ||||
BOOST_CHECK_EQUAL(ref[n], | BOOST_CHECK_EQUAL(ref[n], | ||||
HexStr(spks[n].begin(), spks[n].end())); | HexStr(spks[n].begin(), spks[n].end())); | ||||
BOOST_CHECK_EQUAL( | BOOST_CHECK_EQUAL( | ||||
IsSolvable(Merge(key_provider, script_provider), spks[n]), | IsSolvable(Merge(key_provider, script_provider), spks[n]), | ||||
(flags & UNSOLVABLE) == 0); | (flags & UNSOLVABLE) == 0); | ||||
if (flags & SIGNABLE) { | if (flags & SIGNABLE) { | ||||
Show All 30 Lines | for (size_t i = 0; i < max; ++i) { | ||||
// remove it from that set. | // remove it from that set. | ||||
for (const auto &origin : script_provider.origins) { | for (const auto &origin : script_provider.origins) { | ||||
BOOST_CHECK_MESSAGE(paths.count(origin.second.path), | BOOST_CHECK_MESSAGE(paths.count(origin.second.path), | ||||
"Unexpected key path: " + prv); | "Unexpected key path: " + prv); | ||||
left_paths.erase(origin.second.path); | left_paths.erase(origin.second.path); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
// Verify no expected paths remain that were not observed. | // Verify no expected paths remain that were not observed. | ||||
BOOST_CHECK_MESSAGE(left_paths.empty(), | BOOST_CHECK_MESSAGE(left_paths.empty(), | ||||
"Not all expected key paths found: " + prv); | "Not all expected key paths found: " + prv); | ||||
} | } | ||||
} // namespace | } // namespace | ||||
BOOST_FIXTURE_TEST_SUITE(descriptor_tests, BasicTestingSetup) | BOOST_FIXTURE_TEST_SUITE(descriptor_tests, BasicTestingSetup) | ||||
▲ Show 20 Lines • Show All 194 Lines • Show Last 20 Lines |