diff options
author | MarcoFalke <falke.marco@gmail.com> | 2019-10-10 12:32:57 -0400 |
---|---|---|
committer | MarcoFalke <falke.marco@gmail.com> | 2019-10-10 12:33:03 -0400 |
commit | befdef8aee899dcf7e40aa5ea4bc1b0256381cdc (patch) | |
tree | 565b2ab040d7ba97fcdbe79c2411911919f43e81 /src/script/descriptor.cpp | |
parent | 59f0687fea26a19bfb90a3f55c67ed4aa895bbbd (diff) | |
parent | bb36372b8f2bd675313ae8553ceb61f28c2c1afd (diff) |
Merge #16887: Abstract out some of the descriptor Span-parsing helpers
bb36372b8f2bd675313ae8553ceb61f28c2c1afd test: add unit tests for Span-parsing helpers (Sebastian Falbesoner)
5e69aeec3f2a0fafd5e591b7222716f00145761d Add documenting comments to spanparsing.h (Pieter Wuille)
230d43fdbc41b356700b0d8a6984d69e00279ade Abstract out some of the descriptor Span-parsing helpers (Pieter Wuille)
Pull request description:
As suggested here: https://github.com/bitcoin/bitcoin/pull/16800#issuecomment-531605482.
This moves the Span parsing functions out of the descriptor module, making them more easily usable for other parsers (in particular, in preparation for miniscript parsing).
ACKs for top commit:
MarcoFalke:
ACK bb36372b8f2bd675313ae8553ceb61f28c2c1afd
Tree-SHA512: b5c5c11a9bc3f0a1c2c4cfa22755654ecfb8d4b69da0dc1fb9f04e1556dc0f6ffd87ad153600963279ac465d587d7971b53d240ced802d12693682411ac73deb
Diffstat (limited to 'src/script/descriptor.cpp')
-rw-r--r-- | src/script/descriptor.cpp | 66 |
1 files changed, 9 insertions, 57 deletions
diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp index b223349eb1..ed1bd4cda9 100644 --- a/src/script/descriptor.cpp +++ b/src/script/descriptor.cpp @@ -11,6 +11,7 @@ #include <span.h> #include <util/bip32.h> +#include <util/spanparsing.h> #include <util/system.h> #include <util/strencodings.h> @@ -640,63 +641,6 @@ enum class ParseScriptContext { P2WSH, }; -/** Parse a constant. If successful, sp is updated to skip the constant and return true. */ -bool Const(const std::string& str, Span<const char>& sp) -{ - if ((size_t)sp.size() >= str.size() && std::equal(str.begin(), str.end(), sp.begin())) { - sp = sp.subspan(str.size()); - return true; - } - return false; -} - -/** Parse a function call. If successful, sp is updated to be the function's argument(s). */ -bool Func(const std::string& str, Span<const char>& sp) -{ - if ((size_t)sp.size() >= str.size() + 2 && sp[str.size()] == '(' && sp[sp.size() - 1] == ')' && std::equal(str.begin(), str.end(), sp.begin())) { - sp = sp.subspan(str.size() + 1, sp.size() - str.size() - 2); - return true; - } - return false; -} - -/** Return the expression that sp begins with, and update sp to skip it. */ -Span<const char> Expr(Span<const char>& sp) -{ - int level = 0; - auto it = sp.begin(); - while (it != sp.end()) { - if (*it == '(') { - ++level; - } else if (level && *it == ')') { - --level; - } else if (level == 0 && (*it == ')' || *it == ',')) { - break; - } - ++it; - } - Span<const char> ret = sp.first(it - sp.begin()); - sp = sp.subspan(it - sp.begin()); - return ret; -} - -/** Split a string on every instance of sep, returning a vector. */ -std::vector<Span<const char>> Split(const Span<const char>& sp, char sep) -{ - std::vector<Span<const char>> ret; - auto it = sp.begin(); - auto start = it; - while (it != sp.end()) { - if (*it == sep) { - ret.emplace_back(start, it); - start = it + 1; - } - ++it; - } - ret.emplace_back(start, it); - return ret; -} - /** Parse a key path, being passed a split list of elements (the first element is ignored). */ NODISCARD bool ParseKeyPath(const std::vector<Span<const char>>& split, KeyPath& out, std::string& error) { @@ -723,6 +667,8 @@ NODISCARD bool ParseKeyPath(const std::vector<Span<const char>>& split, KeyPath& /** Parse a public key that excludes origin information. */ std::unique_ptr<PubkeyProvider> ParsePubkeyInner(const Span<const char>& sp, bool permit_uncompressed, FlatSigningProvider& out, std::string& error) { + using namespace spanparsing; + auto split = Split(sp, '/'); std::string str(split[0].begin(), split[0].end()); if (str.size() == 0) { @@ -782,6 +728,8 @@ std::unique_ptr<PubkeyProvider> ParsePubkeyInner(const Span<const char>& sp, boo /** Parse a public key including origin information (if enabled). */ std::unique_ptr<PubkeyProvider> ParsePubkey(const Span<const char>& sp, bool permit_uncompressed, FlatSigningProvider& out, std::string& error) { + using namespace spanparsing; + auto origin_split = Split(sp, ']'); if (origin_split.size() > 2) { error = "Multiple ']' characters found for a single pubkey"; @@ -816,6 +764,8 @@ std::unique_ptr<PubkeyProvider> ParsePubkey(const Span<const char>& sp, bool per /** Parse a script in a particular context. */ std::unique_ptr<DescriptorImpl> ParseScript(Span<const char>& sp, ParseScriptContext ctx, FlatSigningProvider& out, std::string& error) { + using namespace spanparsing; + auto expr = Expr(sp); bool sorted_multi = false; if (Func("pk", expr)) { @@ -1012,6 +962,8 @@ std::unique_ptr<DescriptorImpl> InferScript(const CScript& script, ParseScriptCo /** Check a descriptor checksum, and update desc to be the checksum-less part. */ bool CheckChecksum(Span<const char>& sp, bool require_checksum, std::string& error, std::string* out_checksum = nullptr) { + using namespace spanparsing; + auto check_split = Split(sp, '#'); if (check_split.size() > 2) { error = "Multiple '#' symbols"; |