@@ -588,7 +588,7 @@ struct Node {
588588 }
589589
590590 template <typename CTx>
591- bool ToString (const CTx& ctx, std::string& ret ) const {
591+ std::optional<std::string> ToString (const CTx& ctx) const {
592592 // To construct the std::string representation for a Miniscript object, we use
593593 // the TreeEvalMaybe algorithm. The State is a boolean: whether the parent node is a
594594 // wrapper. If so, non-wrapper expressions must be prefixed with a ":".
@@ -612,15 +612,15 @@ struct Node {
612612 case Fragment::WRAP_C:
613613 if (node.subs [0 ]->fragment == Fragment::PK_K) {
614614 // pk(K) is syntactic sugar for c:pk_k(K)
615- std::string key_str;
616- if (!ctx. ToString (node. subs [ 0 ]-> keys [ 0 ], key_str) ) return {};
617- return std::move (ret) + " pk(" + std::move (key_str) + " )" ;
615+ auto key_str = ctx. ToString (node. subs [ 0 ]-> keys [ 0 ]) ;
616+ if (!key_str) return {};
617+ return std::move (ret) + " pk(" + std::move (* key_str) + " )" ;
618618 }
619619 if (node.subs [0 ]->fragment == Fragment::PK_H) {
620620 // pkh(K) is syntactic sugar for c:pk_h(K)
621- std::string key_str;
622- if (!ctx. ToString (node. subs [ 0 ]-> keys [ 0 ], key_str) ) return {};
623- return std::move (ret) + " pkh(" + std::move (key_str) + " )" ;
621+ auto key_str = ctx. ToString (node. subs [ 0 ]-> keys [ 0 ]) ;
622+ if (!key_str) return {};
623+ return std::move (ret) + " pkh(" + std::move (* key_str) + " )" ;
624624 }
625625 return " c" + std::move (subs[0 ]);
626626 case Fragment::WRAP_D: return " d" + std::move (subs[0 ]);
@@ -639,14 +639,14 @@ struct Node {
639639 }
640640 switch (node.fragment ) {
641641 case Fragment::PK_K: {
642- std::string key_str;
643- if (!ctx. ToString (node. keys [ 0 ], key_str) ) return {};
644- return std::move (ret) + " pk_k(" + std::move (key_str) + " )" ;
642+ auto key_str = ctx. ToString (node. keys [ 0 ]) ;
643+ if (!key_str) return {};
644+ return std::move (ret) + " pk_k(" + std::move (* key_str) + " )" ;
645645 }
646646 case Fragment::PK_H: {
647- std::string key_str;
648- if (!ctx. ToString (node. keys [ 0 ], key_str) ) return {};
649- return std::move (ret) + " pk_h(" + std::move (key_str) + " )" ;
647+ auto key_str = ctx. ToString (node. keys [ 0 ]) ;
648+ if (!key_str) return {};
649+ return std::move (ret) + " pk_h(" + std::move (* key_str) + " )" ;
650650 }
651651 case Fragment::AFTER: return std::move (ret) + " after(" + ::ToString (node.k ) + " )" ;
652652 case Fragment::OLDER: return std::move (ret) + " older(" + ::ToString (node.k ) + " )" ;
@@ -669,9 +669,9 @@ struct Node {
669669 case Fragment::MULTI: {
670670 auto str = std::move (ret) + " multi(" + ::ToString (node.k );
671671 for (const auto & key : node.keys ) {
672- std::string key_str;
673- if (!ctx. ToString (key, key_str) ) return {};
674- str += " ," + std::move (key_str);
672+ auto key_str = ctx. ToString (key) ;
673+ if (!key_str) return {};
674+ str += " ," + std::move (* key_str);
675675 }
676676 return std::move (str) + " )" ;
677677 }
@@ -687,9 +687,7 @@ struct Node {
687687 return " " ; // Should never be reached.
688688 };
689689
690- auto res = TreeEvalMaybe<std::string>(false , downfn, upfn);
691- if (res.has_value ()) ret = std::move (*res);
692- return res.has_value ();
690+ return TreeEvalMaybe<std::string>(false , downfn, upfn);
693691 }
694692
695693 internal::Ops CalcOps () const {
@@ -1181,11 +1179,11 @@ int FindNextChar(Span<const char> in, const char m);
11811179template <typename Key, typename Ctx>
11821180std::optional<std::pair<Key, int >> ParseKeyEnd (Span<const char > in, const Ctx& ctx)
11831181{
1184- Key key;
11851182 int key_size = FindNextChar (in, ' )' );
11861183 if (key_size < 1 ) return {};
1187- if (!ctx.FromString (in.begin (), in.begin () + key_size, key)) return {};
1188- return {{std::move (key), key_size}};
1184+ auto key = ctx.FromString (in.begin (), in.begin () + key_size);
1185+ if (!key) return {};
1186+ return {{std::move (*key), key_size}};
11891187}
11901188
11911189/* * Parse a hex string ending at the end of the fragment's text representation. */
@@ -1356,12 +1354,12 @@ inline NodeRef<Key> Parse(Span<const char> in, const Ctx& ctx)
13561354 // Get keys
13571355 std::vector<Key> keys;
13581356 while (next_comma != -1 ) {
1359- Key key;
13601357 next_comma = FindNextChar (in, ' ,' );
13611358 int key_length = (next_comma == -1 ) ? FindNextChar (in, ' )' ) : next_comma;
13621359 if (key_length < 1 ) return {};
1363- if (!ctx.FromString (in.begin (), in.begin () + key_length, key)) return {};
1364- keys.push_back (std::move (key));
1360+ auto key = ctx.FromString (in.begin (), in.begin () + key_length);
1361+ if (!key) return {};
1362+ keys.push_back (std::move (*key));
13651363 in = in.subspan (key_length + 1 );
13661364 }
13671365 if (keys.size () < 1 || keys.size () > 20 ) return {};
@@ -1532,10 +1530,10 @@ inline NodeRef<Key> Parse(Span<const char> in, const Ctx& ctx)
15321530 * and OP_EQUALVERIFY are decomposed into OP_CHECKSIG, OP_CHECKMULTISIG, OP_EQUAL
15331531 * respectively, plus OP_VERIFY.
15341532 */
1535- bool DecomposeScript ( const CScript& script, std::vector<std::pair<opcodetype, std::vector<unsigned char >>>& out );
1533+ std::optional<std:: vector<std::pair<opcodetype, std::vector<unsigned char >>>> DecomposeScript ( const CScript& script );
15361534
15371535/* * Determine whether the passed pair (created by DecomposeScript) is pushing a number. */
1538- bool ParseScriptNumber (const std::pair<opcodetype, std::vector<unsigned char >>& in, int64_t & k );
1536+ std::optional< int64_t > ParseScriptNumber (const std::pair<opcodetype, std::vector<unsigned char >>& in);
15391537
15401538enum class DecodeContext {
15411539 /* * A single expression of type B, K, or V. Specifically, this can't be an
@@ -1642,34 +1640,35 @@ inline NodeRef<Key> DecodeScript(I& in, I last, const Ctx& ctx)
16421640 }
16431641 // Public keys
16441642 if (in[0 ].second .size () == 33 ) {
1645- Key key;
1646- if (!ctx. FromPKBytes (in[ 0 ]. second . begin (), in[ 0 ]. second . end (), key) ) return {};
1643+ auto key = ctx. FromPKBytes (in[ 0 ]. second . begin (), in[ 0 ]. second . end ()) ;
1644+ if (!key) return {};
16471645 ++in;
1648- constructed.push_back (MakeNodeRef<Key>(Fragment::PK_K, Vector (std::move (key))));
1646+ constructed.push_back (MakeNodeRef<Key>(Fragment::PK_K, Vector (std::move (* key))));
16491647 break ;
16501648 }
16511649 if (last - in >= 5 && in[0 ].first == OP_VERIFY && in[1 ].first == OP_EQUAL && in[3 ].first == OP_HASH160 && in[4 ].first == OP_DUP && in[2 ].second .size () == 20 ) {
1652- Key key;
1653- if (!ctx. FromPKHBytes (in[ 2 ]. second . begin (), in[ 2 ]. second . end (), key) ) return {};
1650+ auto key = ctx. FromPKHBytes (in[ 2 ]. second . begin (), in[ 2 ]. second . end ()) ;
1651+ if (!key) return {};
16541652 in += 5 ;
1655- constructed.push_back (MakeNodeRef<Key>(Fragment::PK_H, Vector (std::move (key))));
1653+ constructed.push_back (MakeNodeRef<Key>(Fragment::PK_H, Vector (std::move (* key))));
16561654 break ;
16571655 }
16581656 // Time locks
1659- if (last - in >= 2 && in[0 ].first == OP_CHECKSEQUENCEVERIFY && ParseScriptNumber (in[1 ], k)) {
1657+ std::optional<int64_t > num;
1658+ if (last - in >= 2 && in[0 ].first == OP_CHECKSEQUENCEVERIFY && (num = ParseScriptNumber (in[1 ]))) {
16601659 in += 2 ;
1661- if (k < 1 || k > 0x7FFFFFFFL ) return {};
1662- constructed.push_back (MakeNodeRef<Key>(Fragment::OLDER, k ));
1660+ if (*num < 1 || *num > 0x7FFFFFFFL ) return {};
1661+ constructed.push_back (MakeNodeRef<Key>(Fragment::OLDER, *num ));
16631662 break ;
16641663 }
1665- if (last - in >= 2 && in[0 ].first == OP_CHECKLOCKTIMEVERIFY && ParseScriptNumber (in[1 ], k )) {
1664+ if (last - in >= 2 && in[0 ].first == OP_CHECKLOCKTIMEVERIFY && (num = ParseScriptNumber (in[1 ]) )) {
16661665 in += 2 ;
1667- if (k < 1 || k > 0x7FFFFFFFL ) return {};
1668- constructed.push_back (MakeNodeRef<Key>(Fragment::AFTER, k ));
1666+ if (num < 1 || num > 0x7FFFFFFFL ) return {};
1667+ constructed.push_back (MakeNodeRef<Key>(Fragment::AFTER, *num ));
16691668 break ;
16701669 }
16711670 // Hashes
1672- if (last - in >= 7 && in[0 ].first == OP_EQUAL && in[3 ].first == OP_VERIFY && in[4 ].first == OP_EQUAL && ParseScriptNumber (in[5 ], k) && k == 32 && in[6 ].first == OP_SIZE) {
1671+ if (last - in >= 7 && in[0 ].first == OP_EQUAL && in[3 ].first == OP_VERIFY && in[4 ].first == OP_EQUAL && (num = ParseScriptNumber (in[5 ])) && num == 32 && in[6 ].first == OP_SIZE) {
16731672 if (in[2 ].first == OP_SHA256 && in[1 ].second .size () == 32 ) {
16741673 constructed.push_back (MakeNodeRef<Key>(Fragment::SHA256, in[1 ].second ));
16751674 in += 7 ;
@@ -1695,10 +1694,10 @@ inline NodeRef<Key> DecodeScript(I& in, I last, const Ctx& ctx)
16951694 if (last - in < 3 + n) return {};
16961695 if (n < 1 || n > 20 ) return {};
16971696 for (int i = 0 ; i < n; ++i) {
1698- Key key;
16991697 if (in[2 + i].second .size () != 33 ) return {};
1700- if (!ctx.FromPKBytes (in[2 + i].second .begin (), in[2 + i].second .end (), key)) return {};
1701- keys.push_back (std::move (key));
1698+ auto key = ctx.FromPKBytes (in[2 + i].second .begin (), in[2 + i].second .end ());
1699+ if (!key) return {};
1700+ keys.push_back (std::move (*key));
17021701 }
17031702 if (!ParseScriptNumber (in[2 + n], k)) return {};
17041703 if (k < 1 || k > n) return {};
@@ -1970,12 +1969,12 @@ inline NodeRef<typename Ctx::Key> FromString(const std::string& str, const Ctx&
19701969template <typename Ctx>
19711970inline NodeRef<typename Ctx::Key> FromScript (const CScript& script, const Ctx& ctx) {
19721971 using namespace internal ;
1973- std::vector<std::pair<opcodetype, std::vector< unsigned char >>> decomposed ;
1974- if (!DecomposeScript (script, decomposed) ) return {};
1975- auto it = decomposed. begin ();
1976- auto ret = DecodeScript<typename Ctx::Key>(it, decomposed. end (), ctx);
1972+ auto decomposed = DecomposeScript (script) ;
1973+ if (!decomposed) return {};
1974+ auto it = decomposed-> begin ();
1975+ auto ret = DecodeScript<typename Ctx::Key>(it, decomposed-> end (), ctx);
19771976 if (!ret) return {};
1978- if (it != decomposed. end ()) return {};
1977+ if (it != decomposed-> end ()) return {};
19791978 return ret;
19801979}
19811980
0 commit comments