aboutsummaryrefslogtreecommitdiff
path: root/src/script
diff options
context:
space:
mode:
authorMarcoFalke <falke.marco@gmail.com>2019-10-10 12:32:57 -0400
committerMarcoFalke <falke.marco@gmail.com>2019-10-10 12:33:03 -0400
commitbefdef8aee899dcf7e40aa5ea4bc1b0256381cdc (patch)
tree565b2ab040d7ba97fcdbe79c2411911919f43e81 /src/script
parent59f0687fea26a19bfb90a3f55c67ed4aa895bbbd (diff)
parentbb36372b8f2bd675313ae8553ceb61f28c2c1afd (diff)
downloadbitcoin-befdef8aee899dcf7e40aa5ea4bc1b0256381cdc.tar.xz
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')
-rw-r--r--src/script/descriptor.cpp66
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";