Merge #15986: Add checksum to getdescriptorinfo

26d3fad109 Add unmodified-but-with-checksum to getdescriptorinfo (Pieter Wuille)
104b3a5069 Factor out checksum checking from descriptor parsing (Pieter Wuille)

Pull request description:

ACKs for top commit:
  achow101:
    Code Review ACK 26d3fad109
  meshcollider:
    re-Code Review ACK 26d3fad109
  Sjors:
    ACK 26d3fad109

Tree-SHA512: b7a7f89b64a184927d6f9a0c183a087609983f0c5d5593f78e12db4714e930a4af655db9da4b0c407ea2e24d3b926cef6e1f2a15de502d0d1290a6e046826b99
This commit is contained in:
MeshCollider
2019-08-17 09:23:36 +12:00
4 changed files with 42 additions and 13 deletions

View File

@@ -914,27 +914,42 @@ std::unique_ptr<DescriptorImpl> InferScript(const CScript& script, ParseScriptCo
} // namespace
/** Check a descriptor checksum, and update desc to be the checksum-less part. */
bool CheckChecksum(Span<const char>& sp, bool require_checksum, std::string* out_checksum = nullptr)
{
auto check_split = Split(sp, '#');
if (check_split.size() > 2) return false; // Multiple '#' symbols
if (check_split.size() == 1 && require_checksum) return false; // Missing checksum
if (check_split.size() == 2) {
if (check_split[1].size() != 8) return false; // Unexpected length for checksum
}
auto checksum = DescriptorChecksum(check_split[0]);
if (checksum.empty()) return false; // Invalid characters in payload
if (check_split.size() == 2) {
if (!std::equal(checksum.begin(), checksum.end(), check_split[1].begin())) return false; // Checksum mismatch
}
if (out_checksum) *out_checksum = std::move(checksum);
sp = check_split[0];
return true;
}
std::unique_ptr<Descriptor> Parse(const std::string& descriptor, FlatSigningProvider& out, bool require_checksum)
{
Span<const char> sp(descriptor.data(), descriptor.size());
// Checksum checks
auto check_split = Split(sp, '#');
if (check_split.size() > 2) return nullptr; // Multiple '#' symbols
if (check_split.size() == 1 && require_checksum) return nullptr; // Missing checksum
if (check_split.size() == 2) {
if (check_split[1].size() != 8) return nullptr; // Unexpected length for checksum
auto checksum = DescriptorChecksum(check_split[0]);
if (checksum.empty()) return nullptr; // Invalid characters in payload
if (!std::equal(checksum.begin(), checksum.end(), check_split[1].begin())) return nullptr; // Checksum mismatch
}
sp = check_split[0];
if (!CheckChecksum(sp, require_checksum)) return nullptr;
auto ret = ParseScript(sp, ParseScriptContext::TOP, out);
if (sp.size() == 0 && ret) return std::unique_ptr<Descriptor>(std::move(ret));
return nullptr;
}
std::string GetDescriptorChecksum(const std::string& descriptor)
{
std::string ret;
Span<const char> sp(descriptor.data(), descriptor.size());
if (!CheckChecksum(sp, false, &ret)) return "";
return ret;
}
std::unique_ptr<Descriptor> InferDescriptor(const CScript& script, const SigningProvider& provider)
{
return InferScript(script, ParseScriptContext::TOP, provider);