Skip to content

Commit 230d43f

Browse files
committed
Abstract out some of the descriptor Span-parsing helpers
1 parent 796b713 commit 230d43f

File tree

4 files changed

+107
-57
lines changed

4 files changed

+107
-57
lines changed

src/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ BITCOIN_CORE_H = \
208208
util/bytevectorhash.h \
209209
util/error.h \
210210
util/fees.h \
211+
util/spanparsing.h \
211212
util/system.h \
212213
util/memory.h \
213214
util/moneystr.h \
@@ -503,6 +504,7 @@ libbitcoin_util_a_SOURCES = \
503504
util/moneystr.cpp \
504505
util/rbf.cpp \
505506
util/threadnames.cpp \
507+
util/spanparsing.cpp \
506508
util/strencodings.cpp \
507509
util/string.cpp \
508510
util/time.cpp \

src/script/descriptor.cpp

Lines changed: 9 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#include <span.h>
1313
#include <util/bip32.h>
14+
#include <util/spanparsing.h>
1415
#include <util/system.h>
1516
#include <util/strencodings.h>
1617

@@ -632,63 +633,6 @@ enum class ParseScriptContext {
632633
P2WSH,
633634
};
634635

635-
/** Parse a constant. If successful, sp is updated to skip the constant and return true. */
636-
bool Const(const std::string& str, Span<const char>& sp)
637-
{
638-
if ((size_t)sp.size() >= str.size() && std::equal(str.begin(), str.end(), sp.begin())) {
639-
sp = sp.subspan(str.size());
640-
return true;
641-
}
642-
return false;
643-
}
644-
645-
/** Parse a function call. If successful, sp is updated to be the function's argument(s). */
646-
bool Func(const std::string& str, Span<const char>& sp)
647-
{
648-
if ((size_t)sp.size() >= str.size() + 2 && sp[str.size()] == '(' && sp[sp.size() - 1] == ')' && std::equal(str.begin(), str.end(), sp.begin())) {
649-
sp = sp.subspan(str.size() + 1, sp.size() - str.size() - 2);
650-
return true;
651-
}
652-
return false;
653-
}
654-
655-
/** Return the expression that sp begins with, and update sp to skip it. */
656-
Span<const char> Expr(Span<const char>& sp)
657-
{
658-
int level = 0;
659-
auto it = sp.begin();
660-
while (it != sp.end()) {
661-
if (*it == '(') {
662-
++level;
663-
} else if (level && *it == ')') {
664-
--level;
665-
} else if (level == 0 && (*it == ')' || *it == ',')) {
666-
break;
667-
}
668-
++it;
669-
}
670-
Span<const char> ret = sp.first(it - sp.begin());
671-
sp = sp.subspan(it - sp.begin());
672-
return ret;
673-
}
674-
675-
/** Split a string on every instance of sep, returning a vector. */
676-
std::vector<Span<const char>> Split(const Span<const char>& sp, char sep)
677-
{
678-
std::vector<Span<const char>> ret;
679-
auto it = sp.begin();
680-
auto start = it;
681-
while (it != sp.end()) {
682-
if (*it == sep) {
683-
ret.emplace_back(start, it);
684-
start = it + 1;
685-
}
686-
++it;
687-
}
688-
ret.emplace_back(start, it);
689-
return ret;
690-
}
691-
692636
/** Parse a key path, being passed a split list of elements (the first element is ignored). */
693637
NODISCARD bool ParseKeyPath(const std::vector<Span<const char>>& split, KeyPath& out, std::string& error)
694638
{
@@ -715,6 +659,8 @@ NODISCARD bool ParseKeyPath(const std::vector<Span<const char>>& split, KeyPath&
715659
/** Parse a public key that excludes origin information. */
716660
std::unique_ptr<PubkeyProvider> ParsePubkeyInner(const Span<const char>& sp, bool permit_uncompressed, FlatSigningProvider& out, std::string& error)
717661
{
662+
using namespace spanparsing;
663+
718664
auto split = Split(sp, '/');
719665
std::string str(split[0].begin(), split[0].end());
720666
if (str.size() == 0) {
@@ -774,6 +720,8 @@ std::unique_ptr<PubkeyProvider> ParsePubkeyInner(const Span<const char>& sp, boo
774720
/** Parse a public key including origin information (if enabled). */
775721
std::unique_ptr<PubkeyProvider> ParsePubkey(const Span<const char>& sp, bool permit_uncompressed, FlatSigningProvider& out, std::string& error)
776722
{
723+
using namespace spanparsing;
724+
777725
auto origin_split = Split(sp, ']');
778726
if (origin_split.size() > 2) {
779727
error = "Multiple ']' characters found for a single pubkey";
@@ -808,6 +756,8 @@ std::unique_ptr<PubkeyProvider> ParsePubkey(const Span<const char>& sp, bool per
808756
/** Parse a script in a particular context. */
809757
std::unique_ptr<DescriptorImpl> ParseScript(Span<const char>& sp, ParseScriptContext ctx, FlatSigningProvider& out, std::string& error)
810758
{
759+
using namespace spanparsing;
760+
811761
auto expr = Expr(sp);
812762
if (Func("pk", expr)) {
813763
auto pubkey = ParsePubkey(expr, ctx != ParseScriptContext::P2WSH, out, error);
@@ -1003,6 +953,8 @@ std::unique_ptr<DescriptorImpl> InferScript(const CScript& script, ParseScriptCo
1003953
/** Check a descriptor checksum, and update desc to be the checksum-less part. */
1004954
bool CheckChecksum(Span<const char>& sp, bool require_checksum, std::string& error, std::string* out_checksum = nullptr)
1005955
{
956+
using namespace spanparsing;
957+
1006958
auto check_split = Split(sp, '#');
1007959
if (check_split.size() > 2) {
1008960
error = "Multiple '#' symbols";

src/util/spanparsing.cpp

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// Copyright (c) 2018 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 <util/spanparsing.h>
6+
7+
#include <span.h>
8+
9+
#include <string>
10+
#include <vector>
11+
12+
namespace spanparsing {
13+
14+
bool Const(const std::string& str, Span<const char>& sp)
15+
{
16+
if ((size_t)sp.size() >= str.size() && std::equal(str.begin(), str.end(), sp.begin())) {
17+
sp = sp.subspan(str.size());
18+
return true;
19+
}
20+
return false;
21+
}
22+
23+
bool Func(const std::string& str, Span<const char>& sp)
24+
{
25+
if ((size_t)sp.size() >= str.size() + 2 && sp[str.size()] == '(' && sp[sp.size() - 1] == ')' && std::equal(str.begin(), str.end(), sp.begin())) {
26+
sp = sp.subspan(str.size() + 1, sp.size() - str.size() - 2);
27+
return true;
28+
}
29+
return false;
30+
}
31+
32+
Span<const char> Expr(Span<const char>& sp)
33+
{
34+
int level = 0;
35+
auto it = sp.begin();
36+
while (it != sp.end()) {
37+
if (*it == '(') {
38+
++level;
39+
} else if (level && *it == ')') {
40+
--level;
41+
} else if (level == 0 && (*it == ')' || *it == ',')) {
42+
break;
43+
}
44+
++it;
45+
}
46+
Span<const char> ret = sp.first(it - sp.begin());
47+
sp = sp.subspan(it - sp.begin());
48+
return ret;
49+
}
50+
51+
std::vector<Span<const char>> Split(const Span<const char>& sp, char sep)
52+
{
53+
std::vector<Span<const char>> ret;
54+
auto it = sp.begin();
55+
auto start = it;
56+
while (it != sp.end()) {
57+
if (*it == sep) {
58+
ret.emplace_back(start, it);
59+
start = it + 1;
60+
}
61+
++it;
62+
}
63+
ret.emplace_back(start, it);
64+
return ret;
65+
}
66+
67+
} // namespace spanparsing

src/util/spanparsing.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright (c) 2018 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+
#ifndef BITCOIN_UTIL_SPANPARSING_H
6+
#define BITCOIN_UTIL_SPANPARSING_H
7+
8+
#include <span.h>
9+
10+
#include <string>
11+
#include <vector>
12+
13+
namespace spanparsing {
14+
15+
/** Parse a constant. If successful, sp is updated to skip the constant and return true. */
16+
bool Const(const std::string& str, Span<const char>& sp);
17+
18+
/** Parse a function call. If successful, sp is updated to be the function's argument(s). */
19+
bool Func(const std::string& str, Span<const char>& sp);
20+
21+
/** Return the expression that sp begins with, and update sp to skip it. */
22+
Span<const char> Expr(Span<const char>& sp);
23+
24+
/** Split a string on every instance of sep, returning a vector. */
25+
std::vector<Span<const char>> Split(const Span<const char>& sp, char sep);
26+
27+
} // namespace spanparsing
28+
29+
#endif // BITCOIN_UTIL_SPANPARSING_H

0 commit comments

Comments
 (0)